├── .clang-format
├── .dockerignore
├── .editorconfig
├── .github
└── workflows
│ ├── linux.yml
│ └── windows.yml
├── .gitignore
├── .gitmodules
├── .idea
└── .gitignore
├── .vscode
├── c_cpp_properties.json
└── launch.json
├── BuildInfo.h.in
├── CyberpunkMP.code-workspace
├── Dockerfile
├── LICENSE.md
├── MakeVSLatestProjects.cmd
├── README.md
├── code
├── assets
│ ├── Archives
│ │ ├── .gitignore
│ │ ├── CyberpunkMP.cpmodproj
│ │ ├── layout.xml
│ │ ├── packed
│ │ │ └── archive
│ │ │ │ └── pc
│ │ │ │ └── mod
│ │ │ │ └── CyberpunkMP.archive
│ │ ├── source
│ │ │ └── archive
│ │ │ │ ├── base
│ │ │ │ └── gameplay
│ │ │ │ │ └── gui
│ │ │ │ │ └── prototype_hud.inkhud
│ │ │ │ ├── mods
│ │ │ │ └── cyberpunkmp
│ │ │ │ │ ├── default_male.ccstate
│ │ │ │ │ ├── minimap_mappin.inkwidget
│ │ │ │ │ ├── minimap_mappin_player.inkwidget
│ │ │ │ │ ├── multiplayer_ui.inkanim
│ │ │ │ │ ├── multiplayer_ui.inkwidget
│ │ │ │ │ ├── muppet.ent
│ │ │ │ │ ├── player_ma_fpp.ent
│ │ │ │ │ ├── player_ma_tpp.ent
│ │ │ │ │ ├── player_ma_tpp_cutscene.ent
│ │ │ │ │ ├── player_wa_fpp.ent
│ │ │ │ │ ├── player_wa_tpp_cutscene.ent
│ │ │ │ │ ├── workspot_anim.ent
│ │ │ │ │ └── workspot_base.workspot
│ │ │ │ └── multi
│ │ │ │ └── gameplay
│ │ │ │ └── gui
│ │ │ │ └── widgets
│ │ │ │ └── minimap
│ │ │ │ └── minimap_pingsystem_mapping.inkwidget
│ │ └── xmake.lua
│ ├── CET
│ │ └── init.lua
│ ├── Inputs
│ │ ├── CyberpunkMP.xml
│ │ └── xmake.lua
│ ├── Tweaks
│ │ ├── CyberpunkMP.tweak
│ │ └── xmake.lua
│ ├── redscript
│ │ ├── Common.reds
│ │ ├── CyberpunkMP.reds
│ │ ├── DeathMenu.reds
│ │ ├── Ink
│ │ │ ├── ChatController.reds
│ │ │ ├── ChatHotkeyController.reds
│ │ │ ├── ChatMessageController.reds
│ │ │ ├── DeliveryListController.reds
│ │ │ ├── DeliveryListItemController.reds
│ │ │ ├── EmoteSelector.reds
│ │ │ ├── EmoteSelectorItem.reds
│ │ │ ├── JobListController.reds
│ │ │ ├── JobListItemController.reds
│ │ │ ├── MultiplayerGameController.reds
│ │ │ ├── ServerListController.reds
│ │ │ └── ServerListItemController.reds
│ │ ├── PhoneHotkeyController.reds
│ │ ├── Plugins
│ │ │ ├── Delivery.reds
│ │ │ ├── Emotes.reds
│ │ │ ├── Jobs.reds
│ │ │ ├── Mappins.reds
│ │ │ └── Taxi.reds
│ │ ├── Rpc.reds
│ │ ├── World
│ │ │ ├── AppearanceSystem.reds
│ │ │ ├── ChatSystem.reds
│ │ │ ├── InterpolationSystem.reds
│ │ │ ├── NetworkWorldSystem.reds
│ │ │ └── VehicleSystem.reds
│ │ ├── helpers.reds
│ │ └── xmake.lua
│ └── xmake.lua
├── client
│ ├── App
│ │ ├── Application.cpp
│ │ ├── Application.h
│ │ ├── ChatMessageEvent.cpp
│ │ ├── ChatMessageEvent.h
│ │ ├── Components
│ │ │ ├── AttachedComponent.h
│ │ │ ├── EntityComponent.h
│ │ │ ├── InterpolationComponent.h
│ │ │ ├── PlayerComponent.h
│ │ │ └── SpawningComponent.h
│ │ ├── Debugging
│ │ │ ├── DebugService.cpp
│ │ │ └── DebugService.h
│ │ ├── Extensions
│ │ │ └── inkTextInputWidget.cpp
│ │ ├── Network
│ │ │ ├── NetworkService.cpp
│ │ │ ├── NetworkService.h
│ │ │ └── Rpc
│ │ │ │ ├── RpcCsharp.cpp
│ │ │ │ ├── RpcCsharp.h
│ │ │ │ ├── RpcGenerator.cpp
│ │ │ │ ├── RpcGenerator.h
│ │ │ │ ├── RpcPack.cpp
│ │ │ │ ├── RpcPack.h
│ │ │ │ ├── RpcService.cpp
│ │ │ │ ├── RpcService.h
│ │ │ │ ├── RpcValidator.cpp
│ │ │ │ └── RpcValidator.h
│ │ ├── Rendering
│ │ │ ├── ImGuiService.cpp
│ │ │ ├── ImGuiService.h
│ │ │ ├── dx12.cpp
│ │ │ ├── dx12.h
│ │ │ ├── imgui_user_config.cpp
│ │ │ ├── imgui_user_config.h
│ │ │ ├── win32.cpp
│ │ │ └── win32.h
│ │ ├── Settings.cpp
│ │ ├── Settings.h
│ │ ├── Threading
│ │ │ ├── ThreadService.cpp
│ │ │ └── ThreadService.h
│ │ └── World
│ │ │ ├── AppearanceSystem.cpp
│ │ │ ├── AppearanceSystem.h
│ │ │ ├── ChatSystem.cpp
│ │ │ ├── ChatSystem.h
│ │ │ ├── InterpolationSystem.cpp
│ │ │ ├── InterpolationSystem.h
│ │ │ ├── NetworkWorldSystem.cpp
│ │ │ ├── NetworkWorldSystem.h
│ │ │ ├── RpcDefinition.cpp
│ │ │ ├── RpcDefinition.h
│ │ │ ├── VehicleSystem.cpp
│ │ │ └── VehicleSystem.h
│ ├── Core
│ │ ├── Container
│ │ │ ├── Container.hpp
│ │ │ └── Registry.hpp
│ │ ├── Facades
│ │ │ ├── Container.hpp
│ │ │ ├── Hook.hpp
│ │ │ ├── Log.hpp
│ │ │ ├── Runtime.cpp
│ │ │ └── Runtime.hpp
│ │ ├── Foundation
│ │ │ ├── Application.cpp
│ │ │ ├── Application.hpp
│ │ │ ├── Feature.hpp
│ │ │ ├── LocaleProvider.hpp
│ │ │ ├── RuntimeProvider.cpp
│ │ │ └── RuntimeProvider.hpp
│ │ ├── Hooking
│ │ │ ├── Detail.hpp
│ │ │ ├── HookingAgent.cpp
│ │ │ ├── HookingAgent.hpp
│ │ │ ├── HookingDriver.cpp
│ │ │ └── HookingDriver.hpp
│ │ ├── Logging
│ │ │ ├── LoggingAgent.cpp
│ │ │ ├── LoggingAgent.hpp
│ │ │ ├── LoggingDriver.cpp
│ │ │ └── LoggingDriver.hpp
│ │ ├── Raw.hpp
│ │ ├── Rendering
│ │ │ ├── RenderingAgent.cpp
│ │ │ ├── RenderingAgent.hpp
│ │ │ ├── RenderingDriver.cpp
│ │ │ └── RenderingDriver.hpp
│ │ ├── Runtime
│ │ │ ├── HostImage.cpp
│ │ │ ├── HostImage.hpp
│ │ │ ├── ModuleImage.cpp
│ │ │ ├── ModuleImage.hpp
│ │ │ ├── OwnerMutex.cpp
│ │ │ └── OwnerMutex.hpp
│ │ ├── Stl.hpp
│ │ └── Win.hpp
│ ├── Game
│ │ ├── Animation
│ │ │ ├── AnimationData.h
│ │ │ ├── AnimationDriver.cpp
│ │ │ ├── AnimationDriver.h
│ │ │ ├── Base.h
│ │ │ ├── MultiMovementController.cpp
│ │ │ ├── MultiMovementController.h
│ │ │ └── States
│ │ │ │ ├── Base.cpp
│ │ │ │ ├── Base.h
│ │ │ │ ├── Idling.cpp
│ │ │ │ ├── Idling.h
│ │ │ │ ├── Spawning.cpp
│ │ │ │ ├── Spawning.h
│ │ │ │ ├── Sprinting.cpp
│ │ │ │ ├── Sprinting.h
│ │ │ │ ├── Walking.cpp
│ │ │ │ └── Walking.h
│ │ ├── CharacterCustomizationSystem.h
│ │ ├── DelaySystem.h
│ │ ├── Entity.h
│ │ ├── MappinSystem.h
│ │ ├── MorphTargetManagerComponent.h
│ │ ├── Movement.h
│ │ ├── PlayerSystem.h
│ │ ├── Puppet.h
│ │ ├── Rendering.h
│ │ ├── ScriptValidation.cpp
│ │ ├── ScriptValidation.h
│ │ ├── Utils.cpp
│ │ └── Utils.h
│ ├── Main.cpp
│ ├── Red
│ │ ├── Alias.hpp
│ │ ├── Engine.hpp
│ │ ├── Engine
│ │ │ ├── Framework.hpp
│ │ │ ├── LogChannel.hpp
│ │ │ ├── Macros
│ │ │ │ └── Framework.hpp
│ │ │ └── Mappings.hpp
│ │ ├── Specializations.hpp
│ │ ├── TypeInfo.hpp
│ │ ├── TypeInfo
│ │ │ ├── Common.hpp
│ │ │ ├── Construction.hpp
│ │ │ ├── Definition.hpp
│ │ │ ├── Invocation.hpp
│ │ │ ├── Macros
│ │ │ │ ├── Definition.hpp
│ │ │ │ └── Resolving.hpp
│ │ │ ├── Mappings.hpp
│ │ │ ├── Parameters.hpp
│ │ │ ├── Registrar.hpp
│ │ │ └── Resolving.hpp
│ │ ├── Utils.hpp
│ │ └── Utils
│ │ │ ├── Handles.hpp
│ │ │ ├── JobQueues.hpp
│ │ │ └── Resources.hpp
│ ├── Support
│ │ ├── MinHook
│ │ │ ├── MinHookProvider.cpp
│ │ │ └── MinHookProvider.hpp
│ │ ├── RED4ext
│ │ │ ├── RED4extProvider.cpp
│ │ │ └── RED4extProvider.hpp
│ │ ├── RedLib
│ │ │ ├── RedLibProvider.cpp
│ │ │ └── RedLibProvider.hpp
│ │ ├── Renderer
│ │ │ ├── RenderingProvider.cpp
│ │ │ └── RenderingProvider.hpp
│ │ └── Spdlog
│ │ │ ├── SpdlogProvider.cpp
│ │ │ └── SpdlogProvider.hpp
│ ├── stdafx.h
│ └── xmake.lua
├── common
│ ├── CommonPCH.h
│ ├── Core
│ │ ├── Allocator.cpp
│ │ ├── Allocator.h
│ │ ├── AllocatorSymbolOverride.h
│ │ ├── BoundedAllocator.cpp
│ │ ├── BoundedAllocator.h
│ │ ├── Buffer.cpp
│ │ ├── Buffer.h
│ │ ├── Filesystem.cpp
│ │ ├── Filesystem.h
│ │ ├── Hash.cpp
│ │ ├── Hash.h
│ │ ├── Initializer.h
│ │ ├── Lockable.h
│ │ ├── Locked.h
│ │ ├── Memory.h
│ │ ├── Meta.h
│ │ ├── MimallocAllocator.cpp
│ │ ├── MimallocAllocator.h
│ │ ├── Outcome.h
│ │ ├── Platform.h
│ │ ├── ScratchAllocator.cpp
│ │ ├── ScratchAllocator.h
│ │ ├── Serialization.cpp
│ │ ├── Serialization.h
│ │ ├── Signal.h
│ │ ├── StackAllocator.h
│ │ ├── StandardAllocator.cpp
│ │ ├── StandardAllocator.h
│ │ ├── Stl.h
│ │ ├── StlAllocator.h
│ │ ├── TaskQueue.cpp
│ │ ├── TaskQueue.h
│ │ ├── TrackAllocator.h
│ │ ├── ViewBuffer.cpp
│ │ └── ViewBuffer.h
│ ├── Math
│ │ ├── Hash.h
│ │ ├── Math.cpp
│ │ ├── Math.h
│ │ ├── Spline.h
│ │ ├── Vector2.h
│ │ └── Vector3.h
│ ├── Network
│ │ ├── Client.cpp
│ │ ├── Client.h
│ │ ├── Packet.cpp
│ │ ├── Packet.h
│ │ ├── Server.cpp
│ │ ├── Server.h
│ │ ├── SteamInterface.cpp
│ │ ├── SteamInterface.h
│ │ ├── SynchronizedClock.cpp
│ │ └── SynchronizedClock.h
│ ├── Reverse
│ │ ├── App.cpp
│ │ ├── App.h
│ │ ├── AutoPtr.cpp
│ │ ├── AutoPtr.h
│ │ ├── AutoPtrManager.cpp
│ │ ├── AutoPtrManager.h
│ │ ├── Debug.cpp
│ │ ├── Debug.h
│ │ ├── Entry.cpp
│ │ ├── Entry.h
│ │ ├── FunctionHook.cpp
│ │ ├── FunctionHook.h
│ │ ├── JitAssembly.h
│ │ ├── Memory.h
│ │ ├── MemoryVP.h
│ │ ├── Memory_Win.inl
│ │ ├── Pattern.cpp
│ │ ├── Pattern.h
│ │ └── ThisCall.h
│ ├── System
│ │ ├── Log.cpp
│ │ ├── Log.h
│ │ ├── Path.cpp
│ │ └── Path.h
│ ├── Tests
│ │ └── main.cpp
│ └── xmake.lua
├── launcher
│ ├── .env
│ ├── .gitignore
│ ├── README.md
│ ├── electron
│ │ ├── .gitignore
│ │ ├── app.js
│ │ ├── package.json
│ │ ├── pnpm-lock.yaml
│ │ └── preload.mjs
│ ├── index.html
│ ├── package.json
│ ├── pnpm-lock.yaml
│ ├── postcss.config.cjs
│ ├── public
│ │ └── vite.svg
│ ├── src
│ │ ├── App.tsx
│ │ ├── assets
│ │ │ └── react.svg
│ │ ├── components
│ │ │ ├── ModDownloadPanel.tsx
│ │ │ ├── Owadview.tsx
│ │ │ ├── WindowFrame.tsx
│ │ │ ├── dialogs
│ │ │ │ └── AddServerDialog.tsx
│ │ │ └── servers
│ │ │ │ ├── HeadRow.tsx
│ │ │ │ ├── ServerList.tsx
│ │ │ │ └── ServerRow.tsx
│ │ ├── data
│ │ │ ├── ModData.ts
│ │ │ └── ServerData.ts
│ │ ├── index.css
│ │ ├── main.tsx
│ │ ├── react-app-env.d.ts
│ │ └── vite-env.d.ts
│ ├── tailwind.config.cjs
│ ├── tsconfig.json
│ ├── tsconfig.node.json
│ ├── vite.config.mjs
│ └── xmake.lua
├── loader
│ └── xmake.lua
├── netpack
│ ├── ErrorHandler.cpp
│ ├── ErrorHandler.h
│ ├── Indent.cpp
│ ├── Indent.h
│ ├── NetPackPCH.h
│ ├── cpp
│ │ ├── helpers.cc
│ │ ├── helpers.h
│ │ ├── names.h
│ │ └── options.h
│ ├── main.cpp
│ └── xmake.lua
├── protocol
│ ├── Protocol.cpp
│ ├── ProtocolPCH.h
│ ├── client.proto
│ ├── common.proto
│ ├── server.proto
│ └── xmake.lua
└── server
│ ├── admin
│ ├── .gitignore
│ ├── README.md
│ ├── eslint.config.js
│ ├── globals.d.ts
│ ├── index.html
│ ├── package.json
│ ├── pnpm-lock.yaml
│ ├── src
│ │ ├── App.tsx
│ │ ├── Clients
│ │ │ └── WebApiClient.ts
│ │ ├── Components
│ │ │ ├── Drawer
│ │ │ │ ├── Drawer.tsx
│ │ │ │ └── DrawerItem.tsx
│ │ │ ├── Toast
│ │ │ │ └── ToastProvider.tsx
│ │ │ └── Toolbar
│ │ │ │ ├── ThemeSwitch.tsx
│ │ │ │ └── Toolbar.tsx
│ │ ├── Data
│ │ │ ├── PluginData.ts
│ │ │ └── ToastData.ts
│ │ ├── Pages
│ │ │ ├── About
│ │ │ │ └── About.tsx
│ │ │ ├── Dashboard
│ │ │ │ ├── Dashboard.tsx
│ │ │ │ └── WidgetGrid.tsx
│ │ │ ├── Plugins
│ │ │ │ └── Plugins.tsx
│ │ │ └── Settings
│ │ │ │ └── Settings.tsx
│ │ ├── Stores
│ │ │ ├── AppStore.ts
│ │ │ ├── PluginStore.ts
│ │ │ ├── StorageStore.ts
│ │ │ └── ToastStore.ts
│ │ ├── Theme.ts
│ │ ├── index.css
│ │ ├── main.tsx
│ │ └── vite-env.d.ts
│ ├── tsconfig.app.json
│ ├── tsconfig.json
│ ├── tsconfig.node.json
│ ├── vite.config.ts
│ ├── watcher.js
│ └── xmake.lua
│ ├── loader
│ ├── .gitignore
│ ├── EnvironmentHelper.cs
│ ├── Extensions
│ │ └── EmbedIO.cs
│ ├── FileSystemHelper.cs
│ ├── Game
│ │ ├── PlayerManager.cs
│ │ ├── Timer.cs
│ │ └── World.cs
│ ├── Program.cs
│ ├── Server.Loader.csproj
│ ├── Server.cs
│ ├── Systems
│ │ ├── Plugins.cs
│ │ ├── Rpc.cs
│ │ ├── Statistics.cs
│ │ └── WebApi.cs
│ └── xmake.lua
│ ├── native
│ ├── Components
│ │ ├── AppearanceComponent.h
│ │ ├── AttachmentComponent.cpp
│ │ ├── AttachmentComponent.h
│ │ ├── CellComponent.h
│ │ ├── CharacterComponent.h
│ │ ├── InterpolationComponent.h
│ │ ├── LevelTag.h
│ │ ├── MovementComponent.cpp
│ │ ├── MovementComponent.h
│ │ ├── PlayerComponent.cpp
│ │ ├── PlayerComponent.h
│ │ ├── VehicleComponent.cpp
│ │ └── VehicleComponent.h
│ ├── Config.cpp
│ ├── Config.h
│ ├── Game
│ │ ├── GridCell.cpp
│ │ ├── GridCell.h
│ │ ├── Level.cpp
│ │ ├── Level.h
│ │ ├── World.cpp
│ │ └── World.h
│ ├── GameServer.cpp
│ ├── GameServer.h
│ ├── PlayerManager.cpp
│ ├── PlayerManager.h
│ ├── Scripting
│ │ ├── AttachmentComponentScriptInstance.cpp
│ │ ├── AttachmentComponentScriptInstance.h
│ │ ├── BufferScriptInstance.cpp
│ │ ├── BufferScriptInstance.h
│ │ ├── ConfigScriptInstance.cpp
│ │ ├── IAttachmentComponent.h
│ │ ├── IBuffer.h
│ │ ├── IConfig.h
│ │ ├── ILogger.h
│ │ ├── IMovementComponent.h
│ │ ├── IPlayer.h
│ │ ├── IPlayerManager.h
│ │ ├── IRpc.h
│ │ ├── IWorld.h
│ │ ├── LoggerScriptInstance.cpp
│ │ ├── LoggerScriptInstance.h
│ │ ├── MovementComponentScriptInstance.cpp
│ │ ├── MovementComponentScriptInstance.h
│ │ ├── PlayerManagerScriptInstance.cpp
│ │ ├── PlayerManagerScriptInstance.h
│ │ ├── PlayerScriptInstance.cpp
│ │ ├── PlayerScriptInstance.h
│ │ ├── RpcScriptInstance.cpp
│ │ ├── RpcScriptInstance.h
│ │ ├── ScriptingBase.h
│ │ ├── ServerAPI.cpp
│ │ ├── ServerAPI.h
│ │ ├── WorldScriptInstance.cpp
│ │ └── WorldScriptInstance.h
│ ├── ServerPCH.h
│ ├── Systems
│ │ ├── ChatSystem.cpp
│ │ ├── ChatSystem.h
│ │ ├── ServerListSystem.cpp
│ │ └── ServerListSystem.h
│ └── xmake.lua
│ ├── scripting
│ ├── CyberpunkSdk
│ │ ├── .gitignore
│ │ ├── AssemblyInfo.cs
│ │ ├── CyberpunkSdk.csproj
│ │ ├── Game
│ │ │ ├── Components
│ │ │ │ ├── AttachmentComponent.cs
│ │ │ │ └── MovementComponent.cs
│ │ │ ├── Player.cs
│ │ │ ├── PlayerManager.cs
│ │ │ ├── Timer.cs
│ │ │ └── World.cs
│ │ ├── Server.cs
│ │ ├── Systems
│ │ │ ├── Logger.cs
│ │ │ └── Rpc.cs
│ │ ├── Types
│ │ │ ├── CName.cs
│ │ │ ├── GameTime.cs
│ │ │ └── TweakDBID.cs
│ │ ├── Utils
│ │ │ └── CRC32.cs
│ │ └── WebApi.cs
│ ├── EmoteSystem
│ │ ├── .gitignore
│ │ ├── Admin
│ │ │ ├── .gitignore
│ │ │ ├── index.ts
│ │ │ ├── package.json
│ │ │ ├── pnpm-lock.yaml
│ │ │ ├── src
│ │ │ │ └── widget.tsx
│ │ │ ├── tsconfig.json
│ │ │ └── vite.config.js
│ │ ├── Client
│ │ │ └── Plugins.EmoteClient.cs
│ │ ├── EmoteSystem.csproj
│ │ ├── Plugin.cs
│ │ ├── RedTypes.cs
│ │ ├── Server
│ │ │ └── Plugins.EmoteServer.cs
│ │ ├── ServerImpl.cs
│ │ └── WebApi.cs
│ ├── JobSystem
│ │ ├── .gitignore
│ │ ├── Client
│ │ │ ├── Plugins.DeliveryClient.cs
│ │ │ ├── Plugins.JobsClient.cs
│ │ │ ├── Plugins.TaxiDriverClient.cs
│ │ │ └── Plugins.TaxiRiderClient.cs
│ │ ├── DeliveryDriver.cs
│ │ ├── Job.cs
│ │ ├── JobManager.cs
│ │ ├── JobSystem.csproj
│ │ ├── JobSystem.csproj.user
│ │ ├── Plugin.cs
│ │ ├── Police.cs
│ │ ├── Properties
│ │ │ └── PublishProfiles
│ │ │ │ └── FolderProfile.pubxml
│ │ ├── RedTypes.cs
│ │ ├── Server
│ │ │ ├── Plugins.DeliveryServer.cs
│ │ │ ├── Plugins.JobsServer.cs
│ │ │ └── Plugins.TaxiServer.cs
│ │ └── Taxi.cs
│ ├── SdkGenerator
│ │ ├── .gitignore
│ │ ├── Program.cs
│ │ └── SdkGenerator.csproj
│ ├── VehicleSystem
│ │ ├── .gitignore
│ │ ├── Plugin.cs
│ │ ├── Server
│ │ │ └── Plugins.EmoteServer.cs
│ │ ├── ServerImpl.cs
│ │ └── VehicleSystem.csproj
│ ├── scripting.sln
│ └── xmake.lua
│ └── xmake.lua
├── log.reds
├── tools
├── InkWidgetCustomClass.1sc
├── VftableCounter.py
├── codegen
│ └── xmake.lua
└── csharp
│ └── xmake.lua
├── vendor
├── httplib.h
└── xmake.lua
├── xmake-requires.lock
└── xmake.lua
/.clang-format:
--------------------------------------------------------------------------------
1 | ---
2 | BasedOnStyle: LLVM
3 | AccessModifierOffset: -4
4 | AlignAfterOpenBracket: AlwaysBreak
5 | AlignEscapedNewlines: Left
6 | AlignOperands: true
7 | AllowShortCaseLabelsOnASingleLine: true
8 | AllowShortFunctionsOnASingleLine: InlineOnly
9 | AllowShortLambdasOnASingleLine: Inline
10 | BraceWrapping:
11 | AfterCaseLabel: true
12 | IndentBraces: true
13 | BreakBeforeBraces: Allman
14 | BreakConstructorInitializers: BeforeComma
15 | ColumnLimit: 180
16 | IndentWidth: 4
17 | PenaltyBreakFirstLessLess: 180
18 | PointerAlignment: Left
19 | SortIncludes: Never
20 | SpaceBeforeParensOptions:
21 | AfterControlStatements: false
--------------------------------------------------------------------------------
/.dockerignore:
--------------------------------------------------------------------------------
1 | .github/
2 | .vscode/
3 | .xmake/
4 | build/
5 | bin/
6 | obj/
7 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*.{cpp,hpp}]
4 | charset = utf-8
5 | end_of_line = lf
6 | insert_final_newline = true
7 | indent_size = 4
8 | indent_style = space
9 | trim_trailing_whitespace = true
10 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Tools / IDEs
2 | vs20*/
3 | vsxmake*/
4 | .vs/
5 | .idea
6 | compile_commands.json
7 | code/scripting/CyberpunkSdk/CyberpunkSdk.csproj.user
8 | code/scripting/JobSystem/Properties/PublishProfiles/FolderProfile.pubxml.user
9 |
10 | # Dependencies
11 | .xmake/*
12 | package/*
13 | .cache/*
14 | node_modules
15 |
16 | # Generated
17 | **.netpack.gen.cpp
18 | **.netpack.gen.h
19 |
20 | # Builds
21 | build/*
22 | out/*
23 | dist
24 | distrib/*
25 |
26 | # Miscellaneous
27 | code/client/Archives/CyberpunkMP.zip
28 | Cyberpunk2077.exe*
29 | imgui.ini
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "vendor/RED4ext.SDK"]
2 | path = vendor/RED4ext.SDK
3 | url = https://github.com/tiltedphoques/RED4ext.SDK.git
4 | [submodule "vendor/ArchiveXL"]
5 | path = vendor/ArchiveXL
6 | url = https://github.com/psiberx/cp2077-archive-xl.git
7 | [submodule "vendor/TweakXL"]
8 | path = vendor/TweakXL
9 | url = https://github.com/psiberx/cp2077-tweak-xl.git
10 | [submodule "vendor/Codeware"]
11 | path = vendor/Codeware
12 | url = https://github.com/psiberx/cp2077-codeware.git
13 |
--------------------------------------------------------------------------------
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 | # Rider ignored files
5 | /modules.xml
6 | /.idea.CyberpunkMP.iml
7 | /contentModel.xml
8 | /projectSettingsUpdater.xml
9 | # Editor-based HTTP Client requests
10 | /httpRequests/
11 | # Datasource local storage ignored files
12 | /dataSources/
13 | /dataSources.local.xml
14 |
--------------------------------------------------------------------------------
/.vscode/c_cpp_properties.json:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "myIncludePath": [
4 | "${workspaceFolder}/code",
5 | "${workspaceFolder}/vendor"
6 | ]
7 | },
8 | "configurations": [
9 | {
10 | "name": "Win32",
11 | "compilerPath": "C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\VC\\Tools\\MSVC\\14.38.33130\\bin\\HostX64\\x64\\cl.exe",
12 | "intelliSenseMode": "windows-msvc-x64",
13 | "compileCommands": ".vscode/compile_commands.json",
14 | "includePath": [
15 | "${myIncludePath}"
16 | ],
17 | "defines": [
18 | "_WINDOWS"
19 | ],
20 | "cStandard": "c17",
21 | "cppStandard": "c++20",
22 | "browse": {
23 | "path": [
24 | "${myIncludePath}",
25 | "${workspaceFolder}"
26 | ]
27 | }
28 | }
29 | ],
30 | "version": 4
31 | }
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | "configurations": [
3 | {
4 | "name": "XMake Debug",
5 | "type": "xmake",
6 | "request": "launch",
7 | "target": "Client"
8 | }
9 | ]
10 | }
--------------------------------------------------------------------------------
/BuildInfo.h.in:
--------------------------------------------------------------------------------
1 | #pragma once
2 | // This file was autogenerated by xmake
3 | #define BUILD_BRANCH "${GIT_BRANCH}"
4 | #define BUILD_COMMIT "${GIT_COMMIT}"
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM mcr.microsoft.com/dotnet/sdk:8.0.404-bookworm-slim-amd64 AS build
2 | WORKDIR /app
3 | ENV XMAKE_ROOT y
4 |
5 | RUN echo 'deb http://deb.debian.org/debian bookworm-backports main' >> /etc/apt/sources.list
6 | RUN apt update \
7 | && apt install -y xmake g++ \
8 | && apt clean
9 |
10 | COPY . .
11 |
12 | RUN --mount=type=cache,target=/root/.xmake xmake -y
13 |
14 | # RELEASE STAGE
15 | FROM mcr.microsoft.com/dotnet/runtime:8.0.11-bookworm-slim-amd64 AS release
16 | WORKDIR /app
17 |
18 | COPY --from=build /app/build/linux/x86_64/release/ /app/
19 |
20 |
21 | EXPOSE 11778
22 | CMD [ "/app/Server.Loader" ]
23 |
--------------------------------------------------------------------------------
/MakeVSLatestProjects.cmd:
--------------------------------------------------------------------------------
1 | @echo off
2 |
3 | xmake project -k vsxmake
--------------------------------------------------------------------------------
/code/assets/Archives/.gitignore:
--------------------------------------------------------------------------------
1 | *.zip
--------------------------------------------------------------------------------
/code/assets/Archives/CyberpunkMP.cpmodproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | CyberpunkMP
4 | CyberpunkMP
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/code/assets/Archives/packed/archive/pc/mod/CyberpunkMP.archive:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tiltedphoques/CyberpunkMP/0ccb0cfa78222cc463ea937e0c8271060f9afd2a/code/assets/Archives/packed/archive/pc/mod/CyberpunkMP.archive
--------------------------------------------------------------------------------
/code/assets/Archives/source/archive/base/gameplay/gui/prototype_hud.inkhud:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tiltedphoques/CyberpunkMP/0ccb0cfa78222cc463ea937e0c8271060f9afd2a/code/assets/Archives/source/archive/base/gameplay/gui/prototype_hud.inkhud
--------------------------------------------------------------------------------
/code/assets/Archives/source/archive/mods/cyberpunkmp/default_male.ccstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tiltedphoques/CyberpunkMP/0ccb0cfa78222cc463ea937e0c8271060f9afd2a/code/assets/Archives/source/archive/mods/cyberpunkmp/default_male.ccstate
--------------------------------------------------------------------------------
/code/assets/Archives/source/archive/mods/cyberpunkmp/minimap_mappin.inkwidget:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tiltedphoques/CyberpunkMP/0ccb0cfa78222cc463ea937e0c8271060f9afd2a/code/assets/Archives/source/archive/mods/cyberpunkmp/minimap_mappin.inkwidget
--------------------------------------------------------------------------------
/code/assets/Archives/source/archive/mods/cyberpunkmp/minimap_mappin_player.inkwidget:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tiltedphoques/CyberpunkMP/0ccb0cfa78222cc463ea937e0c8271060f9afd2a/code/assets/Archives/source/archive/mods/cyberpunkmp/minimap_mappin_player.inkwidget
--------------------------------------------------------------------------------
/code/assets/Archives/source/archive/mods/cyberpunkmp/multiplayer_ui.inkanim:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tiltedphoques/CyberpunkMP/0ccb0cfa78222cc463ea937e0c8271060f9afd2a/code/assets/Archives/source/archive/mods/cyberpunkmp/multiplayer_ui.inkanim
--------------------------------------------------------------------------------
/code/assets/Archives/source/archive/mods/cyberpunkmp/multiplayer_ui.inkwidget:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tiltedphoques/CyberpunkMP/0ccb0cfa78222cc463ea937e0c8271060f9afd2a/code/assets/Archives/source/archive/mods/cyberpunkmp/multiplayer_ui.inkwidget
--------------------------------------------------------------------------------
/code/assets/Archives/source/archive/mods/cyberpunkmp/muppet.ent:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tiltedphoques/CyberpunkMP/0ccb0cfa78222cc463ea937e0c8271060f9afd2a/code/assets/Archives/source/archive/mods/cyberpunkmp/muppet.ent
--------------------------------------------------------------------------------
/code/assets/Archives/source/archive/mods/cyberpunkmp/player_ma_fpp.ent:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tiltedphoques/CyberpunkMP/0ccb0cfa78222cc463ea937e0c8271060f9afd2a/code/assets/Archives/source/archive/mods/cyberpunkmp/player_ma_fpp.ent
--------------------------------------------------------------------------------
/code/assets/Archives/source/archive/mods/cyberpunkmp/player_ma_tpp.ent:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tiltedphoques/CyberpunkMP/0ccb0cfa78222cc463ea937e0c8271060f9afd2a/code/assets/Archives/source/archive/mods/cyberpunkmp/player_ma_tpp.ent
--------------------------------------------------------------------------------
/code/assets/Archives/source/archive/mods/cyberpunkmp/player_ma_tpp_cutscene.ent:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tiltedphoques/CyberpunkMP/0ccb0cfa78222cc463ea937e0c8271060f9afd2a/code/assets/Archives/source/archive/mods/cyberpunkmp/player_ma_tpp_cutscene.ent
--------------------------------------------------------------------------------
/code/assets/Archives/source/archive/mods/cyberpunkmp/player_wa_fpp.ent:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tiltedphoques/CyberpunkMP/0ccb0cfa78222cc463ea937e0c8271060f9afd2a/code/assets/Archives/source/archive/mods/cyberpunkmp/player_wa_fpp.ent
--------------------------------------------------------------------------------
/code/assets/Archives/source/archive/mods/cyberpunkmp/player_wa_tpp_cutscene.ent:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tiltedphoques/CyberpunkMP/0ccb0cfa78222cc463ea937e0c8271060f9afd2a/code/assets/Archives/source/archive/mods/cyberpunkmp/player_wa_tpp_cutscene.ent
--------------------------------------------------------------------------------
/code/assets/Archives/source/archive/mods/cyberpunkmp/workspot_anim.ent:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tiltedphoques/CyberpunkMP/0ccb0cfa78222cc463ea937e0c8271060f9afd2a/code/assets/Archives/source/archive/mods/cyberpunkmp/workspot_anim.ent
--------------------------------------------------------------------------------
/code/assets/Archives/source/archive/mods/cyberpunkmp/workspot_base.workspot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tiltedphoques/CyberpunkMP/0ccb0cfa78222cc463ea937e0c8271060f9afd2a/code/assets/Archives/source/archive/mods/cyberpunkmp/workspot_base.workspot
--------------------------------------------------------------------------------
/code/assets/Archives/source/archive/multi/gameplay/gui/widgets/minimap/minimap_pingsystem_mapping.inkwidget:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tiltedphoques/CyberpunkMP/0ccb0cfa78222cc463ea937e0c8271060f9afd2a/code/assets/Archives/source/archive/multi/gameplay/gui/widgets/minimap/minimap_pingsystem_mapping.inkwidget
--------------------------------------------------------------------------------
/code/assets/Archives/xmake.lua:
--------------------------------------------------------------------------------
1 | rule("archive")
2 | set_extensions(".archive")
3 | -- on_build_file(function (target, sourcefile, opt)
4 | -- os.cp(sourcefile, path.join(target:targetdir(), path.basename(sourcefile) .. ".archive"))
5 | -- end)
6 | on_install(function (target)
7 | print("on_install")
8 | for _, sourcebatch in pairs(target:sourcebatches()) do
9 | local sourcekind = sourcebatch.rulename
10 | if sourcekind == "archive" then
11 | for _, sourcefile in ipairs(sourcebatch.sourcefiles) do
12 | os.cp(sourcefile, path.join(target:installdir("launcher"), "mod", "assets", "Archives", path.basename(sourcefile) .. ".archive"))
13 | end
14 | end
15 | end
16 | end)
17 |
18 | target("Archives")
19 | if is_mode("debug") then
20 | add_defines("TP_ARCHIVES_LOCATION=\"../../../../code/assets/Archives/packed/archive/pc/mod/\"", {public = true})
21 | else
22 | add_defines("TP_ARCHIVES_LOCATION=\"assets/Archives\"", {public = true})
23 | end
24 | set_kind("headeronly")
25 | set_group("Assets")
26 | add_rules("archive")
27 | add_files("packed/archive/pc/mod/CyberpunkMP.archive")
--------------------------------------------------------------------------------
/code/assets/Inputs/xmake.lua:
--------------------------------------------------------------------------------
1 | rule("input")
2 | set_extensions(".xml")
3 | on_install(function (target)
4 | for _, sourcebatch in pairs(target:sourcebatches()) do
5 | local sourcekind = sourcebatch.rulename
6 | if sourcekind == "input" then
7 | for _, sourcefile in ipairs(sourcebatch.sourcefiles) do
8 | os.cp(sourcefile, path.join(target:installdir("launcher"), "mod", "assets", "Inputs", path.basename(sourcefile) .. ".xml"))
9 | end
10 | end
11 | end
12 | end)
13 |
14 | target("Inputs")
15 | if is_mode("debug") then
16 | add_defines("TP_INPUTS_LOCATION=\"../../../../code/assets/Inputs/CyberpunkMP.xml\"", {public = true})
17 | else
18 | add_defines("TP_INPUTS_LOCATION=\"assets/Inputs/CyberpunkMP.xml\"", {public = true})
19 | end
20 | set_kind("headeronly")
21 | set_group("Assets")
22 | add_rules("input")
23 | add_files("CyberpunkMP.xml")
--------------------------------------------------------------------------------
/code/assets/Tweaks/xmake.lua:
--------------------------------------------------------------------------------
1 | rule("tweak")
2 | set_extensions(".tweak")
3 |
4 | on_install(function (target)
5 | for _, sourcebatch in pairs(target:sourcebatches()) do
6 | local sourcekind = sourcebatch.rulename
7 | if sourcekind == "tweak" then
8 | for _, sourcefile in ipairs(sourcebatch.sourcefiles) do
9 | os.cp(sourcefile, path.join(target:installdir("launcher"), "mod", "assets", "Tweaks", path.basename(sourcefile) .. ".tweak"))
10 | end
11 | end
12 | end
13 | end)
14 |
15 | target("Tweaks")
16 | if is_mode("debug") then
17 | add_defines("TP_TWEAKS_LOCATION=\"../../../../code/assets/Tweaks/\"", {public = true})
18 | else
19 | add_defines("TP_TWEAKS_LOCATION=\"assets/Tweaks/\"", {public = true})
20 | end
21 | set_kind("headeronly")
22 | set_group("Assets")
23 | add_rules("tweak")
24 | add_files("**.tweak")
--------------------------------------------------------------------------------
/code/assets/redscript/DeathMenu.reds:
--------------------------------------------------------------------------------
1 | // @wrapMethod(DeathMenuGameController)
2 | // protected cb func OnInitialize() -> Bool {
3 | // wrappedMethod();
4 | // this.SpawnFromExternal(this.GetRootCompoundWidget(), r"mods\\cyberpunkmp\\multiplayer_ui.inkwidget", n"chat");
5 | // }
6 |
7 | @wrapMethod(DeathMenuGameController)
8 | protected cb func OnInitialize() -> Bool {
9 | wrappedMethod();
10 | this.AsyncSpawnFromExternal(inkWidgetRef.Get(this.m_buttonHintsManagerRef), r"mods\\cyberpunkmp\\multiplayer_ui.inkwidget", n"chat", this, n"OnChatSpawn");
11 | }
12 |
13 | @addMethod(DeathMenuGameController)
14 | protected cb func OnChatSpawn(widget: ref, userData: ref) -> Bool {
15 | widget.SetAnchorPoint(1.0, 1.0);
16 | // this.GetRootCompoundWidget().ReorderChild(widget, 0);
17 | }
--------------------------------------------------------------------------------
/code/assets/redscript/PhoneHotkeyController.reds:
--------------------------------------------------------------------------------
1 | @addField(PhoneHotkeyController)
2 | private let m_isMultiplayerUIOpenBBId: ref;
3 |
4 | @wrapMethod(PhoneHotkeyController)
5 | protected func Initialize() -> Bool {
6 | let og = wrappedMethod();
7 | this.m_isMultiplayerUIOpenBBId = this.GetUIBlackboard().RegisterListenerBool(GetAllBlackboardDefs().UIGameData.UIMultiplayerContextRequest, this, n"OnUIMultiplayerIsShown");
8 | return og;
9 | }
10 |
11 | @wrapMethod(PhoneHotkeyController)
12 | protected func Uninitialize() -> Void {
13 | wrappedMethod();
14 | this.GetUIBlackboard().UnregisterListenerBool(GetAllBlackboardDefs().UIGameData.UIMultiplayerContextRequest, this.m_isMultiplayerUIOpenBBId);
15 | }
16 |
17 | @addMethod(PhoneHotkeyController)
18 | private final func OnUIMultiplayerIsShown(value: Bool) -> Void {
19 | this.ToggleVisibility(!value, false);
20 | }
--------------------------------------------------------------------------------
/code/assets/redscript/Plugins/Emotes.reds:
--------------------------------------------------------------------------------
1 | module CyberpunkMP.Plugins
2 |
3 | import CyberpunkMP.*
4 | import CyberpunkMP.World.*
5 |
6 | public native class EmoteServer extends ServerRpc {
7 | public static native func TriggerEmote(name: String) -> Void;
8 | }
9 |
10 | public class EmoteClient extends ClientRpc {
11 | public func TriggerEmote(serverId: Uint64, name: String) -> Void{
12 | let entityId = GameInstance.GetNetworkWorldSystem().GetEntityIdByServerId(serverId);
13 | GameInstance.GetNetworkWorldSystem().GetAppearanceSystem().HandleEmote(entityId, name);
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/code/assets/redscript/Plugins/Jobs.reds:
--------------------------------------------------------------------------------
1 | module CyberpunkMP.Plugins
2 |
3 | import CyberpunkMP.*
4 | import CyberpunkMP.World.*
5 |
6 | public class JobEntry {
7 | let id: Uint32;
8 | let name: String;
9 | let description: String;
10 | let reward: Uint32;
11 | }
12 |
13 | public struct JobInfo {
14 | let id: Uint32;
15 | let name: String;
16 | let description: String;
17 | let reward: Uint32;
18 | }
19 |
20 | public native class JobsServer extends ServerRpc {
21 | public static native func SelectJob(job: CName) -> Void;
22 | public static native func QuitJob() -> Void;
23 | }
24 |
25 | public class JobsClient extends ClientRpc {
26 |
27 | public func SetActiveJob(job: CName) -> Void {
28 | LogChannel(n"DEBUG", s"[JobsClient] SetActiveJob");
29 |
30 | // Set the current active job of the player
31 | if (Equals(job, n"Delivery Driver")) {
32 | // Enable the delivery UI
33 | DeliveryServer.LoadDeliveries();
34 | } else if (Equals(job, n"Taxi Driver")) {
35 | TaxiServer.LoadJobs();
36 | }
37 | // Handle "None" here
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/code/assets/redscript/Rpc.reds:
--------------------------------------------------------------------------------
1 | module CyberpunkMP
2 |
3 | public native class ClientRpc extends IScriptable {
4 | }
5 |
6 | public native class ServerRpc extends IScriptable {
7 | }
8 |
--------------------------------------------------------------------------------
/code/assets/redscript/World/ChatSystem.reds:
--------------------------------------------------------------------------------
1 | module CyberpunkMP.World
2 |
3 | import Codeware.*
4 | import CyberpunkMP.*
5 |
6 | public native class ChatSystem extends IScriptable {
7 | public native func Send(message: String);
8 | public native func GetUsername() -> String;
9 |
10 | public func HandleChatMessage(author: String, message: String) {
11 | let evt: ref;
12 | evt.author = author;
13 | evt.message = message;
14 |
15 | LogChannel(n"DEBUG", s"[ChatSystem] HandleChatMessage: " + message);
16 | let uiSystem = GameInstance.GetUISystem(GetGameInstance());
17 | uiSystem.QueueEvent(evt);
18 | }
19 | // private final func OnConnectToServer(request: ref) -> Void {
20 | // this.m_Blackboard.SetBool(GetAllBlackboardDefs().UI_ComDevice.ContactsActive, open, true);
21 | // }
22 | }
23 |
--------------------------------------------------------------------------------
/code/assets/redscript/World/InterpolationSystem.reds:
--------------------------------------------------------------------------------
1 | module CyberpunkMP.World
2 |
3 | public native class InterpolationSystem extends IScriptable {
4 |
5 | }
--------------------------------------------------------------------------------
/code/assets/redscript/helpers.reds:
--------------------------------------------------------------------------------
1 | native func Log(const text: script_ref) -> Void
2 | native func LogWarning(const text: script_ref) -> Void
3 | native func LogError(const text: script_ref) -> Void
4 |
5 | // output goes to CET window
6 | native func LogChannel(channel: CName, const text: script_ref)
7 | native func LogChannelWarning(channel: CName, const text: script_ref) -> Void
8 | native func LogChannelError(channel: CName, const text: script_ref) -> Void
9 |
10 | native func FTLog(const value: script_ref) -> Void
11 | native func FTLogWarning(const value: script_ref) -> Void
12 | native func FTLogError(const value: script_ref) -> Void
13 |
14 | native func Trace() -> Void
15 | native func TraceToString() -> String
--------------------------------------------------------------------------------
/code/assets/redscript/xmake.lua:
--------------------------------------------------------------------------------
1 | rule("redscript")
2 | set_extensions(".reds")
3 | -- on_build_file(function (target, sourcefile, opt)
4 | -- -- not sure how to not hard-code the relative directory
5 | -- os.cp(sourcefile, path.join(target:targetdir() .. "/redscript", path.relative(sourcefile, "code/redscript")))
6 | -- end)
7 | on_install(function (target)
8 | for _, sourcebatch in pairs(target:sourcebatches()) do
9 | local sourcekind = sourcebatch.rulename
10 | if sourcekind == "redscript" then
11 | for _, sourcefile in ipairs(sourcebatch.sourcefiles) do
12 | os.cp(sourcefile, path.join(target:installdir("launcher"), "mod", "assets", "redscript", path.relative(sourcefile, "code/redscript/assets")))
13 | end
14 | end
15 | end
16 | end)
17 |
18 | target("redscript")
19 | if is_mode("debug") then
20 | add_defines("TP_REDSCRIPT_LOCATION=\"../../../../code/assets/redscript\"", {public = true})
21 | else
22 | add_defines("TP_REDSCRIPT_LOCATION=\"assets/redscript\"", {public = true})
23 | end
24 | set_kind("headeronly")
25 | set_group("Assets")
26 | add_rules("redscript")
27 | add_files("**.reds")
--------------------------------------------------------------------------------
/code/assets/xmake.lua:
--------------------------------------------------------------------------------
1 | includes("Archives", "Inputs", "Tweaks", "redscript")
--------------------------------------------------------------------------------
/code/client/App/Application.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "Core/Foundation/Application.hpp"
4 | #include
5 |
6 |
7 | namespace App
8 | {
9 | struct Application : Core::Application
10 | {
11 | explicit Application(RED4ext::PluginHandle aPlugin, const RED4ext::Sdk* aSdk = nullptr);
12 |
13 | protected:
14 |
15 | void OnStarted() override;
16 | void OnStopped() override;
17 | };
18 |
19 | extern UniquePtr GApplication;
20 | }
21 |
22 |
23 |
--------------------------------------------------------------------------------
/code/client/App/ChatMessageEvent.cpp:
--------------------------------------------------------------------------------
1 | #include "ChatMessageEvent.h"
--------------------------------------------------------------------------------
/code/client/App/ChatMessageEvent.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include "Red/TypeInfo/Macros/Definition.hpp"
6 |
7 | struct ChatMessageUIEvent : RED4ext::red::Event
8 | {
9 | RED4ext::CString author;
10 | RED4ext::CString message;
11 |
12 | RTTI_IMPL_TYPEINFO(ChatMessageUIEvent);
13 | RTTI_IMPL_ALLOCATOR();
14 | };
15 |
16 | RTTI_DEFINE_CLASS(ChatMessageUIEvent, {
17 | RTTI_PARENT(RED4ext::red::Event);
18 | // auto pType = Red::GetClass("String");
19 | // type->props.PushBack(Red::CProperty::Create(pType, "author", nullptr, static_cast(0x40)));
20 | // type->props.PushBack(Red::CProperty::Create(pType, "message", nullptr, static_cast(0x60)));
21 | RTTI_PROPERTY(author);
22 | RTTI_PROPERTY(message);
23 | });
--------------------------------------------------------------------------------
/code/client/App/Components/AttachedComponent.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | struct AttachedComponent
4 | {
5 | //flecs::entity Parent;
6 | };
--------------------------------------------------------------------------------
/code/client/App/Components/EntityComponent.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "Game/Animation/MultiMovementController.h"
3 |
4 | struct EntityComponent
5 | {
6 | Red::EntityID Id;
7 | bool IsVehicle{false};
8 | MultiMovementController* Controller{nullptr};
9 | };
10 |
--------------------------------------------------------------------------------
/code/client/App/Components/InterpolationComponent.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | struct InterpolationComponent
4 | {
5 | struct Timepoint
6 | {
7 | glm::vec3 Position{};
8 | glm::vec3 Rotation{};
9 | float Velocity{0.f};
10 | uint64_t Tick{0};
11 | };
12 |
13 | List TimePoints{};
14 | Timepoint PreviousFrame{};
15 | };
--------------------------------------------------------------------------------
/code/client/App/Components/PlayerComponent.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | struct PlayerComponent
4 | {
5 | };
--------------------------------------------------------------------------------
/code/client/App/Components/SpawningComponent.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | struct MultiMovementController;
4 | struct SpawningComponent
5 | {
6 | Red::EntityID Id;
7 | MultiMovementController* Controller{nullptr};
8 | };
--------------------------------------------------------------------------------
/code/client/App/Debugging/DebugService.cpp:
--------------------------------------------------------------------------------
1 |
2 | #include "DebugService.h"
3 | #include
4 |
5 | namespace App
6 | {
7 | DebugService::DebugService()
8 | {
9 | }
10 |
11 | DebugService::~DebugService()
12 | {
13 | }
14 |
15 | void DebugService::OnBootstrap()
16 | {
17 | }
18 |
19 | void DebugService::Draw()
20 | {
21 | if (ImGui::BeginMainMenuBar())
22 | {
23 | if (ImGui::BeginMenu("Test"))
24 | {
25 | if (ImGui::Button("Connect"))
26 | {
27 | Core::Container::Get()->Connect("127.0.0.1:11778");
28 |
29 | /*auto handle = Red::GetGameSystem();
30 | Red::EntityID id;
31 | Red::ScriptGameInstance game;
32 | Red::CallVirtual(handle, "CreatePuppet", id, game);*/
33 | }
34 | ImGui::EndMenu();
35 | }
36 | ImGui::EndMainMenuBar();
37 | }
38 |
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/code/client/App/Debugging/DebugService.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "Core/Foundation/Feature.hpp"
4 | #include "Core/Logging/LoggingAgent.hpp"
5 |
6 | namespace App
7 | {
8 | struct DebugService : Core::Feature, Core::LoggingAgent
9 | {
10 | DebugService();
11 | ~DebugService() override;
12 |
13 | void OnBootstrap() override;
14 |
15 | void Draw();
16 | };
17 | } // namespace App
18 |
--------------------------------------------------------------------------------
/code/client/App/Extensions/inkTextInputWidget.cpp:
--------------------------------------------------------------------------------
1 | #include "Core/Stl.hpp"
2 | #include
3 |
4 | struct TextInputExtension : RED4ext::ink::TextInputWidget
5 | {
6 | void MoveCaret(int32_t position) { this->caretPosition = position; }
7 | };
8 |
9 | RTTI_EXPAND_CLASS(RED4ext::ink::TextInputWidget, { RTTI_METHOD_FQN(TextInputExtension::MoveCaret); });
--------------------------------------------------------------------------------
/code/client/App/Network/Rpc/RpcCsharp.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
--------------------------------------------------------------------------------
/code/client/App/Network/Rpc/RpcGenerator.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | struct BaseArgumentPack;
4 |
5 | namespace Game
6 | {
7 | struct ScriptFunction;
8 | struct ScriptClass;
9 | }
10 |
11 | struct RpcMock
12 | {
13 | };
14 |
15 | struct RpcContext
16 | {
17 | struct Arg
18 | {
19 | UniquePtr pack;
20 | };
21 |
22 | Vector args;
23 | Red::CName klass;
24 | Red::CName function;
25 | };
26 |
27 | struct RpcHandler
28 | {
29 | RpcContext context;
30 | Red::CClassFunction* function;
31 | };
32 |
33 | struct RpcGenerator
34 | {
35 | using Descriptor = Red::ClassDescriptorDefaultImpl;
36 |
37 | static void GenerateHandlers();
38 | static void DumpCsharp();
39 | static void CreateFunction(Descriptor* desc, const Game::ScriptClass* klass, Game::ScriptFunction* func);
40 | static const Vector& GetFunctions() { return s_functions; }
41 | static RpcHandler* GetRpcHandler(uint64_t klass, uint64_t func);
42 |
43 | private:
44 |
45 | static inline Vector s_functions;
46 | };
47 |
48 |
--------------------------------------------------------------------------------
/code/client/App/Network/Rpc/RpcPack.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | struct BaseArgumentPack
4 | {
5 | BaseArgumentPack(Red::CBaseRTTIType* type)
6 | : m_pRtti(type)
7 | {
8 | }
9 |
10 | virtual ~BaseArgumentPack() {}
11 |
12 | virtual void Read(void* pDest, Buffer::Reader& aReader) = 0;
13 | virtual void Write(void* pSrc, Buffer::Writer& aWriter) = 0;
14 |
15 | Red::CBaseRTTIType* m_pRtti;
16 | };
17 |
18 | UniquePtr MakePack(Red::CBaseRTTIType* type);
--------------------------------------------------------------------------------
/code/client/App/Network/Rpc/RpcService.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "Core/Foundation/Feature.hpp"
3 | #include "Core/Hooking/HookingAgent.hpp"
4 |
5 | struct RpcId
6 | {
7 | uint64_t Klass;
8 | uint64_t Function;
9 |
10 | bool operator==(const RpcId& acRhs) const { return Klass == acRhs.Klass && Function == acRhs.Function; }
11 | };
12 |
13 | struct RpcHandler;
14 | struct CachedRpcHandler
15 | {
16 | RpcId Id;
17 | RpcHandler* Handler;
18 | };
19 |
20 | template <> struct std::hash
21 | {
22 | std::size_t operator()(const RpcId& s) const noexcept { return s.Klass ^ (s.Function << 1); }
23 | };
24 |
25 | struct RpcService : Core::Feature, Core::HookingAgent
26 | {
27 | RpcService(RED4ext::PluginHandle aPlugin, const RED4ext::Sdk* aSdk);
28 | ~RpcService() override;
29 |
30 | void OnInitialize() override;
31 | void OnShutdown() override;
32 |
33 | std::optional GetRpcId(uint64_t aKlass, uint64_t aFunction) const;
34 |
35 | protected:
36 |
37 | static bool PrepareRpc(RED4ext::CGameApplication* aApp);
38 |
39 | void HandleRpc(const PacketEvent& aMessage);
40 | void HandleRpcDefinitions(const PacketEvent& aMessage);
41 | bool Call(const server::RpcCall& aMessage) const;
42 |
43 | private:
44 |
45 | Map m_serverRpcs;
46 | Vector m_clientRpcs;
47 | };
48 |
--------------------------------------------------------------------------------
/code/client/App/Network/Rpc/RpcValidator.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "Core/Hooking/HookingAgent.hpp"
3 |
4 | struct RpcValidator : Core::HookingAgent
5 | {
6 | static void InternalValidate();
7 |
8 | static void Attach();
9 | };
10 |
--------------------------------------------------------------------------------
/code/client/App/Rendering/imgui_user_config.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | #include "Core/Facades/Log.hpp"
4 |
5 | // NOTE: imgui_user_config.h is included by imgui.h which is included with precompiled header, so no need to include it
6 | // here once more
7 |
8 | // global definition "Enable ImGui Assertions Logging"
9 | bool g_ImGuiAssertionsEnabled{false};
10 |
11 | #ifdef NDEBUG
12 | // inline _wassert decl for NDEBUG as it is not emitted inside assert.h header in this case
13 | extern "C" _ACRTIMP void __cdecl _wassert(char const* _Message, char const* _File, unsigned _Line);
14 | #endif
15 |
16 | // runtime assertions which can be enabled/disabled inside CET options, always logged into main log file when they
17 | // happen
18 | void ImGuiAssert(char const* acpMessage, char const* acpFile, unsigned aLine)
19 | {
20 | // TODO - make this log to log of the one who caused assertion instead of default log!
21 | Core::Log::Error("ImGui assertion failed in file \"{}\" at line {}! Expression ({}) evaluates to false!", acpFile, aLine, acpMessage);
22 | }
23 |
--------------------------------------------------------------------------------
/code/client/App/Rendering/imgui_user_config.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | // global declaration "Enable ImGui Assertions"
4 | extern bool g_ImGuiAssertionsEnabled;
5 |
6 | // runtime assertions which can be enabled/disabled inside CET options
7 | void ImGuiAssert(wchar_t const* acpMessage, wchar_t const* acpFile, unsigned aLine);
8 |
9 | // custom assertion function macro for ImGui
10 | #define IM_ASSERT(expression) (void)((g_ImGuiAssertionsEnabled && ((!!(expression)) || (ImGuiAssert(#expression, __FILE__, (unsigned)(__LINE__)), 0))))
--------------------------------------------------------------------------------
/code/client/App/Settings.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | namespace fs = std::filesystem;
4 |
5 | struct Settings
6 | {
7 | static Settings& Get()
8 | {
9 | static Settings instance;
10 | return instance;
11 | }
12 | static bool IsDisabled()
13 | {
14 | return !Get().enabled;
15 | }
16 | static void Load();
17 |
18 | fs::path exePath{};
19 | fs::path gamePath{};
20 | String Version{};
21 | String ip = "127.0.0.1";
22 | uint16_t port = 11778;
23 | Vector mods = {};
24 | bool enabled = false;
25 | bool RpcOnly = false;
26 | fs::path RpcPath{};
27 |
28 | private:
29 | Settings() = default;
30 | };
--------------------------------------------------------------------------------
/code/client/App/Threading/ThreadService.cpp:
--------------------------------------------------------------------------------
1 | #include "ThreadService.h"
2 |
3 | void ThreadService::RunInMainThread(std::function aFunc)
4 | {
5 | auto pService = Core::Container::Get();
6 | pService->m_queue.Add(aFunc);
7 | }
8 |
9 | void ThreadService::OnGameUpdate(RED4ext::CGameApplication* apApp)
10 | {
11 | m_queue.Drain();
12 | }
13 |
--------------------------------------------------------------------------------
/code/client/App/Threading/ThreadService.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "Core/Foundation/Feature.hpp"
4 | #include
5 |
6 | struct ThreadService final
7 | : Core::Feature
8 | {
9 | static void RunInMainThread(std::function aFunc);
10 |
11 | protected:
12 |
13 | void OnGameUpdate(RED4ext::CGameApplication* apApp) override;
14 |
15 | private:
16 |
17 | TaskQueue m_queue;
18 | };
19 |
--------------------------------------------------------------------------------
/code/client/App/World/AppearanceSystem.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "Core/Stl.hpp"
4 | #include "Core/Hooking/HookingAgent.hpp"
5 | #include "RED4ext/Scripting/Natives/Generated/Vector4.hpp"
6 | #include "RED4ext/Scripting/Natives/Generated/Quaternion.hpp"
7 | #include "Network/Client.h"
8 |
9 |
10 | struct AppearanceSystem : RED4ext::IScriptable
11 | {
12 | RTTI_IMPL_TYPEINFO(AppearanceSystem);
13 | RTTI_IMPL_ALLOCATOR();
14 |
15 | AppearanceSystem();
16 |
17 | void OnInitialize(const RED4ext::JobHandle& aJob);
18 |
19 | Red::DynArray GetEntityItems(Red::EntityID &);
20 | void AddEntity(const Red::EntityID entityID, const Red::DynArray& items, const Vector ccstate);
21 | Vector GetPlayerItems(Red::Handle player);
22 | bool ApplyAppearance(Red::Handle object);
23 |
24 | void OnWorldAttached(RED4ext::world::RuntimeScene* aScene);
25 | void OnBeforeWorldDetach(RED4ext::world::RuntimeScene* aScene);
26 |
27 | private:
28 | Core::Map> m_playerEquipment;
29 | Core::Map> m_playerCcstate;
30 | };
31 |
32 | RTTI_DEFINE_CLASS(AppearanceSystem, {
33 | RTTI_ALIAS("CyberpunkMP.World.AppearanceSystem");
34 | RTTI_METHOD(GetEntityItems);
35 | RTTI_METHOD(ApplyAppearance);
36 | });
--------------------------------------------------------------------------------
/code/client/App/World/ChatSystem.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "Core/Stl.hpp"
4 |
5 | struct ChatSystem : RED4ext::IScriptable
6 | {
7 | RTTI_IMPL_TYPEINFO(ChatSystem);
8 | RTTI_IMPL_ALLOCATOR();
9 |
10 | void Update(uint64_t aTick);
11 |
12 | void OnInitialize(const RED4ext::JobHandle& aJob);
13 | void OnWorldAttached(RED4ext::world::RuntimeScene* aScene);
14 | void OnAfterWorldDetach();
15 |
16 | void Send(const Red::CString& aMessage);
17 | RED4ext::CString GetUsername();
18 |
19 | protected:
20 |
21 |
22 | void HandleChatMessage(const PacketEvent& aMessage);
23 |
24 | private:
25 | bool m_ready{false};
26 | Vector m_messages;
27 | };
28 |
29 | RTTI_DEFINE_CLASS(ChatSystem, {
30 | RTTI_ALIAS("CyberpunkMP.World.ChatSystem");
31 | RTTI_METHOD(Send);
32 | RTTI_METHOD(GetUsername);
33 | });
--------------------------------------------------------------------------------
/code/client/App/World/InterpolationSystem.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "Core/Hooking/HookingAgent.hpp"
4 | #include "RED4ext/Scripting/Natives/gameIEntityStubSystem.hpp"
5 |
6 |
7 | struct InterpolationSystem : RED4ext::IScriptable, Core::HookingAgent
8 | {
9 | RTTI_IMPL_TYPEINFO(InterpolationSystem)
10 | RTTI_IMPL_ALLOCATOR();
11 |
12 | void OnInitialize(const RED4ext::JobHandle& aJob);
13 | void OnWorldAttached(RED4ext::world::RuntimeScene* aScene);
14 | void OnAfterWorldDetach();
15 |
16 | void OnConnected();
17 | void OnDisconnected();
18 |
19 | protected:
20 |
21 | void HandleNotifyEntityMove(const PacketEvent& aMessage);
22 |
23 | private:
24 | bool m_ready{false};
25 | flecs::system m_interpolator;
26 | flecs::observer m_entityObserver;
27 | };
28 |
29 | RTTI_DEFINE_CLASS(InterpolationSystem, {
30 | RTTI_ALIAS("CyberpunkMP.World.InterpolationSystem");
31 | });
--------------------------------------------------------------------------------
/code/client/App/World/RpcDefinition.cpp:
--------------------------------------------------------------------------------
1 | #include "RpcDefinition.h"
2 |
--------------------------------------------------------------------------------
/code/client/App/World/RpcDefinition.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | struct ClientRpc : RED4ext::IScriptable
4 | {
5 | RTTI_IMPL_TYPEINFO(ClientRpc);
6 | RTTI_IMPL_ALLOCATOR();
7 | };
8 |
9 | struct ServerRpc : RED4ext::IScriptable
10 | {
11 | RTTI_IMPL_TYPEINFO(ServerRpc);
12 | RTTI_IMPL_ALLOCATOR();
13 | };
14 |
15 | RTTI_DEFINE_CLASS(ClientRpc, { RTTI_ALIAS("CyberpunkMP.ClientRpc"); });
16 | RTTI_DEFINE_CLASS(ServerRpc, { RTTI_ALIAS("CyberpunkMP.ServerRpc"); });
--------------------------------------------------------------------------------
/code/client/Core/Container/Container.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "Core/Stl.hpp"
4 |
5 | namespace Core
6 | {
7 | class Container
8 | {
9 | public:
10 | template
11 | inline static void Set(const Core::SharedPtr& aInstance)
12 | {
13 | Resolver::Assign(aInstance);
14 | }
15 |
16 | template
17 | inline static Core::SharedPtr Get()
18 | {
19 | return Resolver::Retrieve().lock();
20 | }
21 |
22 | template
23 | inline static bool Has()
24 | {
25 | return !Resolver::Retrieve().expired();
26 | }
27 |
28 | template
29 | inline static void Reset()
30 | {
31 | Resolver::Reset();
32 | }
33 |
34 | private:
35 | template
36 | struct Resolver
37 | {
38 | inline static void Assign(const Core::SharedPtr& aInstance)
39 | {
40 | s_instance = aInstance;
41 | }
42 |
43 | inline static Core::WeakPtr& Retrieve()
44 | {
45 | return s_instance;
46 | }
47 |
48 | inline static void Reset()
49 | {
50 | s_instance = {};
51 | }
52 |
53 | inline static Core::WeakPtr s_instance;
54 | };
55 | };
56 | }
57 |
--------------------------------------------------------------------------------
/code/client/Core/Facades/Container.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "Core/Container/Container.hpp"
4 |
5 | namespace Core
6 | {
7 | template
8 | inline Core::SharedPtr Resolve()
9 | {
10 | return Container::Get();
11 | }
12 |
13 | template
14 | inline bool Resolvable()
15 | {
16 | return Container::Get();
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/code/client/Core/Facades/Runtime.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "Core/Runtime/HostImage.hpp"
4 | #include "Core/Runtime/ModuleImage.hpp"
5 |
6 | namespace Core::Runtime
7 | {
8 | void Initialize(const Core::HostImage& aHost, const Core::ModuleImage& aModule);
9 |
10 | [[nodiscard]] uintptr_t GetImageBase();
11 | [[nodiscard]] std::filesystem::path GetImagePath();
12 | [[nodiscard]] std::filesystem::path GetRootDir();
13 | [[nodiscard]] std::filesystem::path GetModulePath();
14 | [[nodiscard]] std::filesystem::path GetModuleDir();
15 | [[nodiscard]] std::string GetModuleName();
16 | [[nodiscard]] bool IsASI();
17 | [[nodiscard]] bool IsASI(HMODULE aHandle);
18 | [[nodiscard]] bool IsEXE(std::wstring_view aName);
19 | }
20 |
--------------------------------------------------------------------------------
/code/client/Core/Foundation/LocaleProvider.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "Core/Foundation/Feature.hpp"
4 |
5 | namespace Core
6 | {
7 | class LocaleProvider : public Feature
8 | {
9 | public:
10 | LocaleProvider(const char* aLocale = "en_US.UTF-8")
11 | {
12 | std::setlocale(LC_ALL, aLocale);
13 | }
14 | };
15 | }
16 |
--------------------------------------------------------------------------------
/code/client/Core/Foundation/RuntimeProvider.cpp:
--------------------------------------------------------------------------------
1 | #include "RuntimeProvider.hpp"
2 | #include "Core/Facades/Runtime.hpp"
3 |
4 | Core::RuntimeProvider::RuntimeProvider(HMODULE aHandle) noexcept
5 | : m_handle(aHandle)
6 | , m_basePathDepth(0)
7 | {
8 | }
9 |
10 | void Core::RuntimeProvider::OnInitialize()
11 | {
12 | Runtime::Initialize(HostImage(m_basePathDepth), ModuleImage(m_handle));
13 | }
14 |
--------------------------------------------------------------------------------
/code/client/Core/Foundation/RuntimeProvider.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "Core/Foundation/Feature.hpp"
4 | #include "Core/Win.hpp"
5 |
6 | namespace Core
7 | {
8 | class RuntimeProvider : public Feature
9 | {
10 | public:
11 | explicit RuntimeProvider(HMODULE aHandle) noexcept;
12 |
13 | auto SetBaseImagePathDepth(int aDepth) noexcept
14 | {
15 | m_basePathDepth = aDepth;
16 | return Defer(this);
17 | }
18 |
19 | protected:
20 | void OnInitialize() override;
21 |
22 | HMODULE m_handle;
23 | int m_basePathDepth;
24 | };
25 | }
26 |
--------------------------------------------------------------------------------
/code/client/Core/Hooking/HookingAgent.cpp:
--------------------------------------------------------------------------------
1 | #include "HookingAgent.hpp"
2 |
3 | #include
4 |
5 | namespace
6 | {
7 | Core::HookingDriver* s_driver;
8 | }
9 |
10 | void Core::HookingAgent::SetHookingDriver(Core::HookingDriver& aDriver)
11 | {
12 | s_driver = &aDriver;
13 | }
14 |
15 | Core::HookingDriver& Core::HookingAgent::GetHookingDriver()
16 | {
17 | assert(s_driver);
18 | return *s_driver;
19 | }
20 |
--------------------------------------------------------------------------------
/code/client/Core/Hooking/HookingDriver.cpp:
--------------------------------------------------------------------------------
1 | #include "HookingDriver.hpp"
2 | #include "HookingAgent.hpp"
3 |
4 | #include
5 |
6 | namespace
7 | {
8 | Core::HookingDriver* s_default;
9 | }
10 |
11 | void Core::HookingDriver::SetDefault(Core::HookingDriver& aDriver)
12 | {
13 | s_default = &aDriver;
14 |
15 | HookingAgent::SetHookingDriver(aDriver);
16 | }
17 |
18 | Core::HookingDriver& Core::HookingDriver::GetDefault()
19 | {
20 | assert(s_default);
21 | return *s_default;
22 | }
23 |
--------------------------------------------------------------------------------
/code/client/Core/Hooking/HookingDriver.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | namespace Core
4 | {
5 | class HookingDriver
6 | {
7 | public:
8 | virtual bool HookAttach(uintptr_t aAddress, void* aCallback) = 0;
9 | virtual bool HookAttach(uintptr_t aAddress, void* aCallback, void** aOriginal) = 0;
10 | virtual bool HookDetach(uintptr_t aAddress) = 0;
11 | virtual void Enqueue(std::function aFunc) = 0;
12 |
13 | static void SetDefault(HookingDriver& aDriver);
14 | static HookingDriver& GetDefault();
15 | };
16 | }
17 |
--------------------------------------------------------------------------------
/code/client/Core/Logging/LoggingAgent.cpp:
--------------------------------------------------------------------------------
1 | #include "LoggingAgent.hpp"
2 |
3 | #include
4 |
5 | namespace
6 | {
7 | Core::LoggingDriver* s_driver;
8 | }
9 |
10 | void Core::LoggingAgent::SetDriver(Core::LoggingDriver& aDriver)
11 | {
12 | s_driver = &aDriver;
13 | }
14 |
15 | Core::LoggingDriver& Core::LoggingAgent::GetLoggingDriver()
16 | {
17 | assert(s_driver);
18 | return *s_driver;
19 | }
20 |
21 | void Core::LoggingAgent::LogFlush()
22 | {
23 | s_driver->LogFlush();
24 | }
25 |
--------------------------------------------------------------------------------
/code/client/Core/Logging/LoggingDriver.cpp:
--------------------------------------------------------------------------------
1 | #include "LoggingDriver.hpp"
2 | #include "LoggingAgent.hpp"
3 |
4 | #include
5 |
6 | namespace
7 | {
8 | Core::LoggingDriver* s_default;
9 | }
10 |
11 | void Core::LoggingDriver::SetDefault(LoggingDriver& aDriver)
12 | {
13 | s_default = &aDriver;
14 |
15 | LoggingAgent::SetDriver(aDriver);
16 | }
17 |
18 | Core::LoggingDriver& Core::LoggingDriver::GetDefault()
19 | {
20 | assert(s_default);
21 | return *s_default;
22 | }
23 |
--------------------------------------------------------------------------------
/code/client/Core/Rendering/RenderingAgent.cpp:
--------------------------------------------------------------------------------
1 | #include "RenderingAgent.hpp"
2 |
3 | #include
4 |
5 | namespace
6 | {
7 | Core::RenderingDriver* s_driver;
8 | }
9 |
10 | Microsoft::WRL::ComPtr Core::RenderingAgent::GetSwapChain()
11 | {
12 | return GetRenderingDriver().GetSwapChain();
13 | }
14 |
15 | Microsoft::WRL::ComPtr Core::RenderingAgent::GetCommandQueue()
16 | {
17 | return GetRenderingDriver().GetCommandQueue();
18 | }
19 |
20 | HWND Core::RenderingAgent::GetWindow()
21 | {
22 | return GetRenderingDriver().GetWindow();
23 | }
24 |
25 | void Core::RenderingAgent::SetDriver(RenderingDriver& aDriver)
26 | {
27 | s_driver = &aDriver;
28 | }
29 |
30 | Core::RenderingDriver& Core::RenderingAgent::GetRenderingDriver()
31 | {
32 | assert(s_driver);
33 | return *s_driver;
34 | }
35 |
36 | Core::RenderingAgent::RenderingAgent()
37 | {
38 | GetRenderingDriver().Register(this);
39 | }
40 |
41 | Core::RenderingAgent::~RenderingAgent()
42 | {
43 | GetRenderingDriver().UnRegister(this);
44 | }
45 |
46 |
--------------------------------------------------------------------------------
/code/client/Core/Rendering/RenderingAgent.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "RenderingDriver.hpp"
4 |
5 | namespace Core
6 | {
7 | class RenderingAgent
8 | {
9 | protected:
10 | static RenderingDriver& GetRenderingDriver();
11 |
12 | RenderingAgent();
13 | virtual ~RenderingAgent();
14 |
15 | TP_NOCOPYMOVE(RenderingAgent);
16 |
17 | virtual void OnRenderInit() = 0;
18 | virtual void OnPresent() = 0;
19 | virtual void OnReset(bool aCompleteReset) = 0;
20 | virtual bool OnWindowProc(HWND ahWnd, UINT auMsg, WPARAM awParam, LPARAM alParam) { return false; }
21 |
22 | static Microsoft::WRL::ComPtr GetSwapChain();
23 | static Microsoft::WRL::ComPtr GetCommandQueue();
24 | static HWND GetWindow();
25 |
26 | friend RenderingDriver;
27 |
28 | private:
29 | friend RenderingDriver;
30 |
31 | static void SetDriver(RenderingDriver& aDriver);
32 | };
33 | }
34 |
--------------------------------------------------------------------------------
/code/client/Core/Rendering/RenderingDriver.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | namespace Core
4 | {
5 | class RenderingAgent;
6 |
7 | class RenderingDriver
8 | {
9 | public:
10 |
11 | static void SetDefault(RenderingDriver& aDriver);
12 | static RenderingDriver& GetDefault();
13 |
14 | Microsoft::WRL::ComPtr GetSwapChain() const;
15 | Microsoft::WRL::ComPtr GetCommandQueue() const;
16 | Microsoft::WRL::ComPtr GetCommandList() const;
17 | HWND GetWindow() const;
18 |
19 | void Register(RenderingAgent* aAgent);
20 | void UnRegister(RenderingAgent* aAgent);
21 |
22 | protected:
23 |
24 | void TriggerPresent() const;
25 | void TriggerReset(bool aCompleteReset = false) const;
26 | void TriggerRenderInit() const;
27 | bool TriggerWindowProc(HWND, UINT, WPARAM, LPARAM);
28 |
29 | Microsoft::WRL::ComPtr m_pdxgiSwapChain{};
30 | Microsoft::WRL::ComPtr m_pCommandQueue{};
31 | Microsoft::WRL::ComPtr m_pCommandList{};
32 | HWND m_window{nullptr};
33 |
34 | private:
35 |
36 | Vector m_agents;
37 | };
38 | }
39 |
--------------------------------------------------------------------------------
/code/client/Core/Runtime/HostImage.cpp:
--------------------------------------------------------------------------------
1 | #include "HostImage.hpp"
2 | #include "Core/Win.hpp"
3 |
4 | Core::HostImage::HostImage(int aExePathDepth)
5 | {
6 | const auto handle = GetModuleHandleW(nullptr);
7 |
8 | m_base = reinterpret_cast(handle);
9 |
10 | std::wstring filePath(MAX_PATH, '\0');
11 | filePath.resize(::GetModuleFileNameW(handle, filePath.data(), MAX_PATH));
12 |
13 | m_exe = filePath;
14 | m_root = m_exe.parent_path();
15 |
16 | while (--aExePathDepth >= 0)
17 | m_root = m_root.parent_path();
18 | }
19 |
20 | uintptr_t Core::HostImage::GetBase() const
21 | {
22 | return m_base;
23 | }
24 |
25 | std::filesystem::path Core::HostImage::GetPath() const
26 | {
27 | return m_exe;
28 | }
29 |
30 | std::string Core::HostImage::GetName() const
31 | {
32 | return m_exe.stem().string();
33 | }
34 |
35 | std::filesystem::path Core::HostImage::GetRootDir() const
36 | {
37 | return m_root;
38 | }
39 |
--------------------------------------------------------------------------------
/code/client/Core/Runtime/HostImage.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | namespace Core
4 | {
5 | class HostImage
6 | {
7 | public:
8 | explicit HostImage(int32_t aExePathDepth = 0);
9 | ~HostImage() = default;
10 |
11 | [[nodiscard]] uintptr_t GetBase() const;
12 | [[nodiscard]] std::filesystem::path GetPath() const;
13 | [[nodiscard]] std::string GetName() const;
14 | [[nodiscard]] std::filesystem::path GetRootDir() const;
15 |
16 | private:
17 | uintptr_t m_base;
18 | std::filesystem::path m_exe;
19 | std::filesystem::path m_root;
20 | };
21 | }
22 |
--------------------------------------------------------------------------------
/code/client/Core/Runtime/ModuleImage.cpp:
--------------------------------------------------------------------------------
1 | #include "ModuleImage.hpp"
2 |
3 | Core::ModuleImage::ModuleImage(HMODULE aHandle)
4 | {
5 | std::wstring filePath(MAX_PATH, '\0');
6 | filePath.resize(::GetModuleFileNameW(aHandle, filePath.data(), MAX_PATH));
7 |
8 | m_path = filePath;
9 | }
10 |
11 | std::filesystem::path Core::ModuleImage::GetPath() const
12 | {
13 | return m_path;
14 | }
15 |
16 | std::filesystem::path Core::ModuleImage::GetDir() const
17 | {
18 | return m_path.parent_path();
19 | }
20 |
21 | std::string Core::ModuleImage::GetName() const
22 | {
23 | return m_path.stem().string();
24 | }
25 |
26 | bool Core::ModuleImage::IsASI() const
27 | {
28 | return m_path.extension() == L".asi";
29 | }
30 |
--------------------------------------------------------------------------------
/code/client/Core/Runtime/ModuleImage.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "Core/Win.hpp"
4 |
5 | namespace Core
6 | {
7 | class ModuleImage
8 | {
9 | public:
10 | explicit ModuleImage(HMODULE aHandle);
11 | ~ModuleImage() = default;
12 |
13 | [[nodiscard]] std::filesystem::path GetPath() const;
14 | [[nodiscard]] std::filesystem::path GetDir() const;
15 | [[nodiscard]] std::string GetName() const;
16 | [[nodiscard]] bool IsASI() const;
17 |
18 | private:
19 | std::filesystem::path m_path;
20 | };
21 | }
22 |
--------------------------------------------------------------------------------
/code/client/Core/Runtime/OwnerMutex.cpp:
--------------------------------------------------------------------------------
1 | #include "OwnerMutex.hpp"
2 |
3 | Core::OwnerMutex::OwnerMutex(std::string_view aName)
4 | : m_aname(aName)
5 | , m_mutex(nullptr)
6 | {
7 | }
8 |
9 | Core::OwnerMutex::OwnerMutex(std::wstring_view aName)
10 | : m_wname(aName)
11 | , m_mutex(nullptr)
12 | {
13 | }
14 |
15 | Core::OwnerMutex::~OwnerMutex()
16 | {
17 | Release();
18 | }
19 |
20 | bool Core::OwnerMutex::Obtain()
21 | {
22 | const auto mutex = !m_wname.empty()
23 | ? CreateMutexW(NULL, TRUE, m_wname.data())
24 | : CreateMutexA(NULL, TRUE, m_aname.data());
25 |
26 | if (!mutex)
27 | return false;
28 |
29 | if (GetLastError() == ERROR_ALREADY_EXISTS)
30 | {
31 | ReleaseMutex(mutex);
32 | return false;
33 | }
34 |
35 | m_mutex = mutex;
36 |
37 | return true;
38 | }
39 |
40 | bool Core::OwnerMutex::Release()
41 | {
42 | if (!m_mutex)
43 | return false;
44 |
45 | ReleaseMutex(m_mutex);
46 | m_mutex = nullptr;
47 |
48 | return true;
49 | }
50 |
51 | bool Core::OwnerMutex::IsOwner()
52 | {
53 | return m_mutex;
54 | }
55 |
--------------------------------------------------------------------------------
/code/client/Core/Runtime/OwnerMutex.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "Core/Win.hpp"
4 |
5 | namespace Core
6 | {
7 | class OwnerMutex
8 | {
9 | public:
10 | explicit OwnerMutex(std::string_view aName);
11 | explicit OwnerMutex(std::wstring_view aName);
12 | ~OwnerMutex();
13 |
14 | bool Obtain();
15 | bool Release();
16 | bool IsOwner();
17 |
18 | private:
19 | std::string_view m_aname;
20 | std::wstring_view m_wname;
21 | HANDLE m_mutex;
22 | };
23 | }
24 |
--------------------------------------------------------------------------------
/code/client/Core/Win.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #ifndef WIN32_LEAN_AND_MEAN
4 | #define WIN32_LEAN_AND_MEAN
5 | #endif
6 | #ifndef NOMINMAX
7 | #define NOMINMAX
8 | #endif
9 |
10 | #include
11 | #include
12 |
--------------------------------------------------------------------------------
/code/client/Game/Animation/AnimationData.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "Base.h"
4 |
5 | struct AnimationData
6 | {
7 | Red::CName controller;
8 | bool debug = false;
9 | Locomotion_Style style{LS_Idle};
10 | MotionTableAction action{MTA_None};
11 | float path = 0.f;
12 | float slope = 0.f;
13 | float delta = 0.f;
14 | bool stairs = false;
15 | float ground = 0.f;
16 | float time = 0.f;
17 | float footScale = 1.f;
18 | float startAngle = 0.f;
19 | bool unk = false;
20 | float speed = 0.f;
21 | };
22 |
--------------------------------------------------------------------------------
/code/client/Game/Animation/AnimationDriver.cpp:
--------------------------------------------------------------------------------
1 | #include "AnimationDriver.h"
2 |
3 |
4 | AnimationDriver::~AnimationDriver()
5 | {
6 | Detach();
7 | }
8 |
9 | void AnimationDriver::Attach(Red::Entity* parent)
10 | {
11 | static Core::RawFunc<2624656810UL, decltype(&AnimationDriver::Attach)> attach;
12 | attach(this, parent);
13 | }
14 |
15 | void AnimationDriver::Detach()
16 | {
17 | static Core::RawFunc<2385973466UL, decltype(&AnimationDriver::Detach)> detach;
18 | detach(this);
19 | }
20 |
21 | void AnimationDriver::SendParameters(AnimationData& data)
22 | {
23 | static Core::RawFunc<2132808949UL, decltype(&AnimationDriver::SendParameters)> send;
24 | send(this, data);
25 | }
26 |
27 | float AnimationDriver::GetAnimLength(Red::CName name) const
28 | {
29 | static Core::RawFunc<3750304414UL, float (*)(Red::AnimationControllerComponent*, Red::CName)> get;
30 | if (const auto pComp = component.Lock())
31 | return get(pComp.GetPtr(), name);
32 | return 0.f;
33 | }
34 |
--------------------------------------------------------------------------------
/code/client/Game/Animation/AnimationDriver.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "RED4ext/Scripting/Natives/Generated/anim/AnimFeature_CrowdLocomotion.hpp"
4 | #include "RED4ext/Scripting/Natives/Generated/anim/AnimFeature_Locomotion.hpp"
5 | #include "RED4ext/Scripting/Natives/Generated/ent/AnimationControllerComponent.hpp"
6 |
7 | struct AnimationData;
8 |
9 | struct AnimationDriver
10 | {
11 | ~AnimationDriver();
12 |
13 | void Attach(Red::Entity* parent);
14 | void Detach();
15 |
16 | void SendParameters(AnimationData& data);
17 |
18 | float GetAnimLength(Red::CName name) const;
19 |
20 | Red::Handle locomotion;
21 | Red::Handle crowd;
22 | Red::WeakHandle component;
23 | };
24 |
--------------------------------------------------------------------------------
/code/client/Game/Animation/States/Base.cpp:
--------------------------------------------------------------------------------
1 | #include "Base.h"
2 |
3 | #include "Game/Animation/AnimationData.h"
4 |
5 | namespace States
6 | {
7 | void Base::GetAnimationData(AnimationData& aData) const
8 | {
9 | aData.action = MTA_None;
10 | aData.style = LS_Idle;
11 | }
12 |
13 | std::optional Base::Process(const Update& acEvent) noexcept
14 | {
15 | return std::nullopt;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/code/client/Game/Animation/States/Idling.cpp:
--------------------------------------------------------------------------------
1 | #include "Idling.h"
2 |
3 | #include "Sprinting.h"
4 | #include "Walking.h"
5 |
6 | namespace States
7 | {
8 | void Idling::Enter() noexcept
9 | {
10 | }
11 |
12 | std::optional Idling::Process(const Update& acEvent) noexcept
13 | {
14 | if (acEvent.Speed >= kRunSpeed)
15 | return Transit();
16 | if (acEvent.Speed >= kWalkSpeed)
17 | return Transit();
18 |
19 | return std::nullopt;
20 | }
21 | } // namespace States
22 |
--------------------------------------------------------------------------------
/code/client/Game/Animation/States/Idling.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "Base.h"
4 |
5 | namespace States
6 | {
7 | struct Idling : Base
8 | {
9 | Idling(MultiMovementController& aParent)
10 | : Base(aParent)
11 | {
12 | }
13 |
14 | ~Idling() override{}
15 | void Enter() noexcept override;
16 |
17 | std::optional Process(const Update& acEvent) noexcept override;
18 | };
19 | } // namespace States
20 |
--------------------------------------------------------------------------------
/code/client/Game/Animation/States/Spawning.cpp:
--------------------------------------------------------------------------------
1 | #include "Spawning.h"
2 | #include "Idling.h"
3 | #include "Sprinting.h"
4 | #include "Walking.h"
5 |
6 | namespace States
7 | {
8 | void Spawning::Enter() noexcept
9 | {
10 | }
11 |
12 | std::optional Spawning::Process(const Update& acEvent) noexcept
13 | {
14 | if (acEvent.Speed >= kRunSpeed)
15 | return Transit();
16 | if (acEvent.Speed >= kWalkSpeed)
17 | return Transit();
18 |
19 | return Transit();
20 | }
21 | } // namespace States
22 |
--------------------------------------------------------------------------------
/code/client/Game/Animation/States/Spawning.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "Base.h"
4 |
5 | namespace States
6 | {
7 | struct Spawning : Base
8 | {
9 | Spawning(MultiMovementController& aParent)
10 | : Base(aParent)
11 | {
12 | }
13 |
14 | ~Spawning() override{}
15 | void Enter() noexcept override;
16 |
17 | std::optional Process(const Update& acEvent) noexcept override;
18 | };
19 | } // namespace States
20 |
--------------------------------------------------------------------------------
/code/client/Game/Animation/States/Sprinting.cpp:
--------------------------------------------------------------------------------
1 | #include "Sprinting.h"
2 |
3 | #include "Idling.h"
4 | #include "Walking.h"
5 |
6 | #include "Game/Animation/AnimationData.h"
7 | #include "Game/Animation/MultiMovementController.h"
8 |
9 | namespace States
10 | {
11 | void Sprinting::Enter() noexcept
12 | {
13 | m_timer = 0.f;
14 | m_duration = m_parent.GetAnimLength("sprint_0");
15 | }
16 |
17 | void Sprinting::GetAnimationData(AnimationData& aData) const
18 | {
19 | aData.action = MTA_Move;
20 | aData.style = LS_Sprint;
21 | aData.time = m_timer;
22 | }
23 |
24 | std::optional Sprinting::Process(const Update& acEvent) noexcept
25 | {
26 | if (acEvent.Speed < kRunSpeed)
27 | {
28 | if (acEvent.Speed >= kWalkSpeed)
29 | return Transit();
30 | return Transit();
31 | }
32 |
33 | m_timer += acEvent.Delta;
34 | m_timer = std::fmodf(m_timer, m_duration);
35 |
36 | return std::nullopt;
37 | }
38 | } // namespace States
39 |
--------------------------------------------------------------------------------
/code/client/Game/Animation/States/Sprinting.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "Base.h"
4 |
5 | namespace States
6 | {
7 | struct Sprinting : Base
8 | {
9 | Sprinting(MultiMovementController& aParent)
10 | : Base(aParent)
11 | {
12 | }
13 |
14 | ~Sprinting() override{}
15 | void Enter() noexcept override;
16 |
17 | void GetAnimationData(AnimationData& aData) const override;
18 |
19 | std::optional Process(const Update& acEvent) noexcept override;
20 |
21 | private:
22 |
23 | float m_timer = 0.f;
24 | float m_duration = 0.f;
25 | };
26 | } // namespace States
27 |
--------------------------------------------------------------------------------
/code/client/Game/Animation/States/Walking.cpp:
--------------------------------------------------------------------------------
1 | #include "Walking.h"
2 |
3 | #include "Idling.h"
4 | #include "Sprinting.h"
5 |
6 | #include "Game/Animation/AnimationData.h"
7 | #include "Game/Animation/MultiMovementController.h"
8 |
9 | namespace States
10 | {
11 | void Walking::Enter() noexcept
12 | {
13 | m_timer = 0.f;
14 | m_duration = m_parent.GetAnimLength("walk_0");
15 | }
16 |
17 | void Walking::GetAnimationData(AnimationData& aData) const
18 | {
19 | aData.action = MTA_Move;
20 | aData.style = LS_Walk;
21 | aData.time = m_timer;
22 | }
23 |
24 | std::optional Walking::Process(const Update& acEvent) noexcept
25 | {
26 | if (acEvent.Speed >= kRunSpeed)
27 | return Transit();
28 | if (acEvent.Speed < kWalkSpeed)
29 | return Transit();
30 |
31 | m_timer += acEvent.Delta;
32 | m_timer = std::fmodf(m_timer, m_duration);
33 |
34 | return std::nullopt;
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/code/client/Game/Animation/States/Walking.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "Base.h"
4 |
5 | namespace States
6 | {
7 | struct Walking : Base
8 | {
9 | Walking(MultiMovementController& aParent)
10 | : Base(aParent)
11 | {
12 | }
13 |
14 | ~Walking() override {}
15 | void Enter() noexcept override;
16 | void GetAnimationData(AnimationData& aData) const override;
17 |
18 | std::optional Process(const Update& acEvent) noexcept override;
19 |
20 | private:
21 |
22 | float m_timer = 0.f;
23 | float m_duration = 0.f;
24 | };
25 | } // namespace States
26 |
--------------------------------------------------------------------------------
/code/client/Game/DelaySystem.h:
--------------------------------------------------------------------------------
1 | #include "RED4ext/Scripting/Natives/Generated/game/IDelaySystem.hpp"
2 |
3 | namespace Game
4 | {
5 | struct ExDelaySystem : Red::game::IDelaySystem
6 | {
7 | enum DelayFlag : uint32_t
8 | {
9 | NoFlag = 0,
10 | Flag1 = 1 << 0,
11 | Flag2 = 1 << 1,
12 | Flag3 = 1 << 2,
13 | Flag4 = 1 << 3
14 | };
15 |
16 | virtual void sub_1B0();
17 | virtual void sub_1B8();
18 | virtual void sub_1C0();
19 | virtual void AddFunction(const std::function& func, float delay, DelayFlag flag, int one, Red::CName name1, Red::CName name2);
20 |
21 | };
22 | }
--------------------------------------------------------------------------------
/code/client/Game/Entity.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | struct AnimationData;
6 |
7 | namespace Game
8 | {
9 | using EntityID = Core::OffsetPtr<0x48, Red::EntityID>;
10 | using EntityPtr = Core::OffsetPtr<0x90, Red::Entity*>;
11 |
12 | struct Controller
13 | {
14 | virtual RED4ext::Memory::PoolAI_Movement* GetMemoryPool();
15 | virtual ~Controller();
16 |
17 | uint32_t m_type = 0; // 4
18 | bool m_attached = false; // 8
19 | bool m_highPriotiry = false; // C
20 | Red::move::Component* MoveComponent; // 10
21 | Red::EntityID Id;
22 | };
23 |
24 | constexpr auto IdleController_SetAnimation = Core::RawFunc<
25 | /* hash = */ 2268141838UL,
26 | /* type = */ void (*)(Game::Controller*, AnimationData&)>();
27 |
28 | template
29 | Red::Handle FindComponent(Red::Entity* apEntity)
30 | {
31 | static auto pClass = Red::ResolveClass();
32 | if (pClass && apEntity)
33 | {
34 | for (auto& component : apEntity->componentsStorage.components)
35 | {
36 | if (component && component->GetType()->IsA(pClass))
37 | return Red::Cast(component);
38 | }
39 | }
40 |
41 | return {};
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/code/client/Game/MappinSystem.h:
--------------------------------------------------------------------------------
1 | #include "RED4ext/Scripting/Natives/Generated/game/mappins/IMappinSystem.hpp"
2 | #include "RED4ext/Scripting/Natives/Generated/game/mappins/MappinData.hpp"
3 | #include "RED4ext/Scripting/Natives/Generated/game/NewMappinID.hpp"
4 | #include "RED4ext/Scripting/Natives/Generated/game/mappins/MappinScriptData.hpp"
5 | #include "RED4ext/NativeTypes.hpp"
6 | #include "RED4ext/Scripting/Natives/Generated/Vector3.hpp"
7 |
8 | constexpr auto RegisterRemotePlayerMappin = Core::RawFunc<2624990479UL,
9 | Red::game::NewMappinID * (*)(Red::game::mappins::IMappinSystem *, Red::game::NewMappinID *, Red::game::mappins::MappinData const &, Red::WeakHandle *)>();
10 |
11 |
12 | constexpr auto RegisterMappin = Core::RawFunc<3577160229UL,
13 | Red::game::NewMappinID * (*)(Red::game::mappins::IMappinSystem *, Red::game::NewMappinID *, Red::game::mappins::MappinData const &, Red::Vector3 *)>();
14 |
--------------------------------------------------------------------------------
/code/client/Game/MorphTargetManagerComponent.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 |
6 | inline Red::DynArray * GetTargetWeightEntries(Red::ent::MorphTargetManagerComponent * self)
7 | {
8 | return reinterpret_cast *>((uintptr_t)self + 0x98);
9 | }
10 |
11 | constexpr auto SetTargetWeightWithNormalize = Core::RawFunc<633871992UL,
12 | void (*)(Red::ent::MorphTargetManagerComponent *, Red::CName targetName, Red::CName regionName, float amount, bool force)>();
13 |
14 | constexpr auto ResetWeights = Core::RawFunc<1054086242UL,
15 | void (*)(Red::ent::MorphTargetManagerComponent *)>();
16 |
17 |
--------------------------------------------------------------------------------
/code/client/Game/Movement.h:
--------------------------------------------------------------------------------
1 | #include "RED4ext/Scripting/Natives/Generated/game/Puppet.hpp"
2 | #include "RED4ext/SpinLock.hpp"
3 |
4 | struct MultiMovementController;
5 |
6 | namespace Game
7 | {
8 | struct StubMoveComponent
9 | {
10 | uint8_t pad[0xA8];
11 | MultiMovementController* pController;
12 | uint8_t padB8[0x128 - 0xB0];
13 | Red::SpinLock lock;
14 | };
15 | } // namespace Game
--------------------------------------------------------------------------------
/code/client/Game/PlayerSystem.h:
--------------------------------------------------------------------------------
1 | #include "RED4ext/Scripting/Natives/Generated/cp/PlayerSystem.hpp"
2 | #include "RED4ext/Scripting/Natives/Generated/game/Object.hpp"
3 |
4 | namespace Game
5 | {
6 | struct PlayerSystem : Red::PlayerSystem
7 | {
8 | virtual void sub_1B0(); // 1B0
9 | virtual void sub_1B8(); // 1B8
10 | virtual void sub_1C0(); // 1C0
11 | virtual void sub_1C8(); // 1C8
12 | virtual void sub_1D0(); // 1D0
13 | virtual void sub_1D8(); // 1D8
14 | virtual void GetLocalPlayerControlledGameObject(Red::Handle& aObject); // 1E0
15 | };
16 | }
--------------------------------------------------------------------------------
/code/client/Game/ScriptValidation.cpp:
--------------------------------------------------------------------------------
1 | #include "ScriptValidation.h"
2 |
--------------------------------------------------------------------------------
/code/client/Game/Utils.cpp:
--------------------------------------------------------------------------------
1 | #include "Utils.h"
2 |
3 | Red::WorldPosition Game::ToRed(const glm::vec3& acPosition)
4 | {
5 | Red::WorldPosition pos;
6 | pos.x = acPosition.x;
7 | pos.y = acPosition.y;
8 | pos.z = acPosition.z;
9 | return pos;
10 | }
11 |
12 | glm::vec3 Game::ToGlm(const Red::WorldPosition& acPosition)
13 | {
14 | glm::vec3 pos{acPosition.x, acPosition.y, acPosition.z};
15 | return pos;
16 | }
17 |
18 | Red::Quaternion Game::ToRed(const glm::quat& acOrientation)
19 | {
20 | return {acOrientation.x, acOrientation.y, acOrientation.z, acOrientation.w};
21 | }
22 |
23 | glm::quat Game::ToGlm(const Red::Quaternion& acOrientation)
24 | {
25 | return {acOrientation.r,
26 | acOrientation.i,
27 | acOrientation.j,
28 | acOrientation.k};
29 | }
--------------------------------------------------------------------------------
/code/client/Red/Alias.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | namespace Red
4 | {
5 | using namespace RED4ext;
6 | }
7 |
8 | namespace Red::Detail
9 | {
10 | using namespace RED4ext::Detail;
11 | }
12 |
--------------------------------------------------------------------------------
/code/client/Red/Engine.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "TypeInfo/Resolving.hpp"
4 |
5 | #include "Engine/Framework.hpp"
6 | #include "Engine/LogChannel.hpp"
7 |
8 | #include "Engine/Mappings.hpp"
9 |
--------------------------------------------------------------------------------
/code/client/Red/Engine/Framework.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "Macros/Framework.hpp"
4 |
5 | namespace Red
6 | {
7 | template
8 | struct RuntimeSystemMapping : public std::false_type {};
9 |
10 | namespace Detail
11 | {
12 | template
13 | concept HasRuntimeSystemMapping = RuntimeSystemMapping::value
14 | && RuntimeSystemMapping::offset >= 0
15 | && RuntimeSystemMapping::offset <= 64;
16 | }
17 |
18 | template
19 | requires std::is_base_of_v && std::is_base_of_v
20 | U* GetGameSystem()
21 | {
22 | static const auto s_type = GetType();
23 | auto& gameInstance = CGameEngine::Get()->framework->gameInstance;
24 | return reinterpret_cast(gameInstance->GetSystem(s_type));
25 | }
26 |
27 | template
28 | requires std::is_base_of_v && std::is_base_of_v && Detail::HasRuntimeSystemMapping
29 | U* GetRuntimeSystem()
30 | {
31 | constexpr auto systemOffset = RuntimeSystemMapping::offset * sizeof(Handle);
32 | const auto& runtimeSceneAddr = CGameEngine::Get()->framework->unk18;
33 | return reinterpret_cast*>(runtimeSceneAddr + systemOffset)->instance;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/code/client/Red/Engine/LogChannel.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | namespace Red::Log
4 | {
5 | inline void Channel(Red::CName aChannel, const std::string& aMessage)
6 | {
7 | static auto* s_rtti = CRTTISystem::Get();
8 | static auto* s_logFunc = s_rtti->GetFunction("LogChannel");
9 | static auto* s_stringType = s_rtti->GetType("String");
10 | static auto* s_stringRefType = s_rtti->GetType("script_ref:String");
11 | static auto* s_nameType = s_rtti->GetType("CName");
12 |
13 | CString message(aMessage.c_str());
14 | ScriptRef messageRef;
15 | messageRef.innerType = s_stringType;
16 | messageRef.hash = s_stringType->GetName();
17 | messageRef.ref = &message;
18 |
19 | StackArgs_t args;
20 | args.emplace_back(s_nameType, &aChannel);
21 | args.emplace_back(s_stringRefType, &messageRef);
22 |
23 | CStack stack(nullptr, args.data(), static_cast(args.size()), nullptr);
24 |
25 | s_logFunc->Execute(&stack);
26 | }
27 |
28 | template
29 | constexpr void Channel(CName aChannel, std::format_string aFormat, Args&&... aArgs)
30 | {
31 | Channel(aChannel, std::format(aFormat, std::forward(aArgs)...));
32 | }
33 |
34 | template
35 | constexpr void Debug(std::format_string aFormat, Args&&... aArgs)
36 | {
37 | Channel("DEBUG", std::format(aFormat, std::forward(aArgs)...));
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/code/client/Red/Engine/Macros/Framework.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #define RTTI_MAP_RUNTIME_SYSTEM(_type, _offset) \
4 | template<> \
5 | struct Red::RuntimeSystemMapping<_type> : public std::true_type \
6 | { \
7 | static constexpr auto offset = _offset; \
8 | };
9 |
--------------------------------------------------------------------------------
/code/client/Red/Specializations.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "TypeInfo/Resolving.hpp"
4 |
5 | template<>
6 | struct std::hash
7 | {
8 | std::size_t operator()(RED4ext::CName aKey) const
9 | {
10 | return aKey.hash;
11 | }
12 | };
13 |
14 | template<>
15 | struct std::hash
16 | {
17 | std::size_t operator()(RED4ext::TweakDBID aKey) const
18 | {
19 | return aKey.value;
20 | }
21 | };
22 |
23 | template<>
24 | struct std::hash
25 | {
26 | std::size_t operator()(RED4ext::ResourcePath aKey) const
27 | {
28 | return aKey.hash;
29 | }
30 | };
31 |
32 | template<>
33 | struct std::hash
34 | {
35 | std::size_t operator()(RED4ext::NodeRef aKey) const
36 | {
37 | return aKey.hash;
38 | }
39 | };
40 |
41 | template
42 | requires std::is_class_v && std::is_convertible_v && Red::Detail::HasGeneratedTypeName
43 | struct std::hash
44 | {
45 | std::size_t operator()(T aKey) const
46 | {
47 | return static_cast(aKey);
48 | }
49 | };
50 |
--------------------------------------------------------------------------------
/code/client/Red/TypeInfo.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "TypeInfo/Construction.hpp"
4 | #include "TypeInfo/Definition.hpp"
5 | #include "TypeInfo/Invocation.hpp"
6 | #include "TypeInfo/Registrar.hpp"
7 | #include "TypeInfo/Resolving.hpp"
8 |
9 | #include "TypeInfo/Mappings.hpp"
10 |
--------------------------------------------------------------------------------
/code/client/Red/TypeInfo/Construction.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "Resolving.hpp"
4 |
5 | namespace Red
6 | {
7 | template
8 | inline T* Construct()
9 | {
10 | auto type = GetType();
11 | auto instance = reinterpret_cast(type->GetAllocator()->AllocAligned(type->GetSize(),
12 | type->GetAlignment()).memory);
13 | type->Construct(instance);
14 | return instance;
15 | }
16 |
17 | template
18 | inline void Destruct(T* aInstance)
19 | {
20 | auto type = GetType();
21 | type->Destruct(aInstance);
22 | type->GetAllocator()->Free(aInstance);
23 | }
24 | }
25 |
26 | template
27 | requires std::is_abstract_v && Red::Detail::HasGeneratedTypeName
28 | struct RED4ext::Detail::AllocatorHook : std::true_type
29 | {
30 | inline static Memory::IAllocator* Get()
31 | {
32 | return Red::GetClass()->GetAllocator();
33 | }
34 | };
35 |
36 | template
37 | requires std::is_abstract_v && Red::Detail::HasGeneratedTypeName
38 | struct RED4ext::Detail::ConstructorHook : std::true_type
39 | {
40 | inline static void Apply(T* aInstance)
41 | {
42 | Red::GetClass()->ConstructCls(aInstance);
43 | }
44 | };
45 |
--------------------------------------------------------------------------------
/code/client/Red/TypeInfo/Mappings.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "Resolving.hpp"
4 |
5 | namespace Red
6 | {
7 | RTTI_MAP_TYPE_NAME(int8_t, "Int8");
8 | RTTI_MAP_TYPE_NAME(uint8_t, "Uint8");
9 | RTTI_MAP_TYPE_NAME(int16_t, "Int16");
10 | RTTI_MAP_TYPE_NAME(uint16_t, "Uint16");
11 | RTTI_MAP_TYPE_NAME(int32_t, "Int32");
12 | RTTI_MAP_TYPE_NAME(uint32_t, "Uint32");
13 | RTTI_MAP_TYPE_NAME(int64_t, "Int64");
14 | RTTI_MAP_TYPE_NAME(uint64_t, "Uint64");
15 | RTTI_MAP_TYPE_NAME(float, "Float");
16 | RTTI_MAP_TYPE_NAME(double, "Double");
17 | RTTI_MAP_TYPE_NAME(bool, "Bool");
18 | RTTI_MAP_TYPE_NAME(CString, "String");
19 | RTTI_MAP_TYPE_NAME(CName, "CName");
20 | RTTI_MAP_TYPE_NAME(TweakDBID, "TweakDBID");
21 | RTTI_MAP_TYPE_NAME(ItemID, "gameItemID");
22 | RTTI_MAP_TYPE_NAME(NodeRef, "NodeRef");
23 | RTTI_MAP_TYPE_NAME(Variant, "Variant");
24 |
25 | RTTI_MAP_TYPE_PREFIX(DynArray, "array:");
26 | RTTI_MAP_TYPE_PREFIX(Handle, "handle:");
27 | RTTI_MAP_TYPE_PREFIX(WeakHandle, "whandle:");
28 | RTTI_MAP_TYPE_PREFIX(ResourceReference, "rRef:");
29 | RTTI_MAP_TYPE_PREFIX(ResourceAsyncReference, "raRef:");
30 |
31 | RTTI_MAP_TYPE_NAME(char, "Uint8");
32 | }
33 |
--------------------------------------------------------------------------------
/code/client/Red/Utils.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "Utils/Handles.hpp"
4 | #include "Utils/JobQueues.hpp"
5 | #include "Utils/Resources.hpp"
6 |
--------------------------------------------------------------------------------
/code/client/Red/Utils/JobQueues.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | namespace Red
4 | {
5 | template
6 | inline void WaitForJob(JobHandle& aJob, const W& aTimeout)
7 | {
8 | std::mutex mutex;
9 | std::unique_lock lock(mutex);
10 | std::condition_variable cv;
11 |
12 | JobQueue queue;
13 | queue.Wait(aJob);
14 | queue.Dispatch([&lock, &cv]() {
15 | lock.release();
16 | cv.notify_all();
17 | });
18 |
19 | cv.wait_for(lock, aTimeout);
20 |
21 | if (lock.owns_lock())
22 | {
23 | cv.wait_for(lock, aTimeout);
24 | }
25 |
26 | if (!lock || !lock.owns_lock())
27 | {
28 | mutex.unlock();
29 | }
30 | }
31 |
32 | template
33 | inline void WaitForQueue(JobQueue& aQueue, const W& aTimeout)
34 | {
35 | WaitForJob(aQueue.unk10, aTimeout);
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/code/client/Support/MinHook/MinHookProvider.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "Core/TaskQueue.h"
4 | #include "Core/Foundation/Feature.hpp"
5 | #include "Core/Hooking/HookingDriver.hpp"
6 |
7 | namespace Support
8 | {
9 | class MinHookProvider
10 | : public Core::Feature
11 | , public Core::HookingDriver
12 | {
13 | public:
14 | MinHookProvider();
15 | ~MinHookProvider() override;
16 |
17 | bool HookAttach(uintptr_t aAddress, void* aCallback) override;
18 | bool HookAttach(uintptr_t aAddress, void* aCallback, void** aOriginal) override;
19 | bool HookDetach(uintptr_t aAddress) override;
20 | void Enqueue(std::function aFunc) override;
21 |
22 | void OnGameUpdate(RED4ext::CGameApplication* apApp) override;
23 |
24 | private:
25 |
26 | TaskQueue m_queue;
27 | };
28 | }
29 |
--------------------------------------------------------------------------------
/code/client/Support/RedLib/RedLibProvider.cpp:
--------------------------------------------------------------------------------
1 | #include "RedLibProvider.hpp"
2 | #include "Red/TypeInfo/Registrar.hpp"
3 |
4 | void Support::RedLibProvider::OnBootstrap()
5 | {
6 | Red::TypeInfoRegistrar::RegisterDiscovered();
7 | }
8 |
--------------------------------------------------------------------------------
/code/client/Support/RedLib/RedLibProvider.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "Core/Foundation/Feature.hpp"
4 |
5 | namespace Support
6 | {
7 | class RedLibProvider : public Core::Feature
8 | {
9 | void OnBootstrap() override;
10 | };
11 | }
12 |
--------------------------------------------------------------------------------
/code/client/Support/Spdlog/SpdlogProvider.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "Core/Foundation/Feature.hpp"
4 | #include "Core/Logging/LoggingDriver.hpp"
5 |
6 | namespace Support
7 | {
8 | class SpdlogProvider
9 | : public Core::Feature
10 | , public Core::LoggingDriver
11 | {
12 | public:
13 | void LogInfo(const std::string_view& aMessage) override;
14 | void LogWarning(const std::string_view& aMessage) override;
15 | void LogError(const std::string_view& aMessage) override;
16 | void LogDebug(const std::string_view& aMessage) override;
17 | void LogFlush() override;
18 |
19 | auto SetLogPath(const std::filesystem::path& aPath) noexcept
20 | {
21 | m_logPath = aPath;
22 | return Defer(this);
23 | }
24 |
25 | protected:
26 | void OnInitialize() override;
27 |
28 | std::filesystem::path m_logPath;
29 | };
30 | }
31 |
--------------------------------------------------------------------------------
/code/common/CommonPCH.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 |
6 | #include
7 | #include
8 | #include
9 |
10 | #include
11 |
12 | #ifdef WIN32
13 | #define EXTERN_DLL_EXPORT extern "C" __declspec(dllexport)
14 | #else
15 | #define EXTERN_DLL_EXPORT extern "C"
16 | #endif
--------------------------------------------------------------------------------
/code/common/Core/BoundedAllocator.cpp:
--------------------------------------------------------------------------------
1 | #include "BoundedAllocator.h"
2 |
3 |
4 | BoundedAllocator::BoundedAllocator(const size_t aMaximumAllocationSize) noexcept
5 | : m_availableMemory{ aMaximumAllocationSize }
6 | {
7 | }
8 |
9 | void* BoundedAllocator::Allocate(size_t aSize) noexcept
10 | {
11 | if (m_availableMemory >= aSize)
12 | {
13 | m_availableMemory -= aSize;
14 | return MimallocAllocator::Allocate(aSize);
15 | }
16 |
17 | return nullptr;
18 | }
19 |
20 | void BoundedAllocator::Free(void* apData) noexcept
21 | {
22 | m_availableMemory += Size(apData);
23 |
24 | MimallocAllocator::Free(apData);
25 | }
26 |
--------------------------------------------------------------------------------
/code/common/Core/BoundedAllocator.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "MimallocAllocator.h"
4 |
5 |
6 | struct BoundedAllocator : MimallocAllocator
7 | {
8 | BoundedAllocator(size_t aMaximumAllocationSize) noexcept;
9 | virtual ~BoundedAllocator() = default;
10 |
11 | TP_NOCOPYMOVE(BoundedAllocator);
12 |
13 | [[nodiscard]] void* Allocate(size_t aSize) noexcept override;
14 | void Free(void* apData) noexcept override;
15 |
16 | private:
17 |
18 | size_t m_availableMemory;
19 | };
20 |
21 |
--------------------------------------------------------------------------------
/code/common/Core/Filesystem.cpp:
--------------------------------------------------------------------------------
1 | #include "Filesystem.h"
2 | #include "Platform.h"
3 |
4 | #include
5 |
6 | #if TP_PLATFORM_WINDOWS
7 | #include
8 |
9 | EXTERN_C IMAGE_DOS_HEADER __ImageBase;
10 | #endif
11 |
12 |
13 | std::filesystem::path GetPath() noexcept
14 | {
15 | #if TP_PLATFORM_WINDOWS
16 | WCHAR dllPath[MAX_PATH] = { 0 };
17 | GetModuleFileNameW(reinterpret_cast(&__ImageBase), dllPath, std::size(dllPath));
18 |
19 | std::error_code ec;
20 | const auto currentPath = std::filesystem::path(dllPath).parent_path();
21 |
22 | return currentPath;
23 | #else
24 | return std::filesystem::current_path();
25 | #endif
26 | }
27 |
28 | String LoadFile(const std::filesystem::path& acPath) noexcept
29 | {
30 | std::ifstream file(acPath, std::ios::binary);
31 | file.seekg(0, std::ifstream::end);
32 | const size_t length = file.tellg();
33 | file.seekg(0, std::ifstream::beg);
34 |
35 | String content(length, '\0');
36 | file.read(content.data(), length);
37 |
38 | return content;
39 | }
40 |
41 | bool SaveFile(const std::filesystem::path& acPath, const String& acData) noexcept
42 | {
43 | std::ofstream out(acPath, std::ios::binary);
44 | if (!out.is_open())
45 | return false;
46 |
47 | out.write(acData.data(), acData.size());
48 |
49 | return true;
50 | }
51 |
52 |
--------------------------------------------------------------------------------
/code/common/Core/Filesystem.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include "Stl.h"
5 |
6 |
7 |
8 | std::filesystem::path GetPath() noexcept;
9 | String LoadFile(const std::filesystem::path& acPath) noexcept;
10 | bool SaveFile(const std::filesystem::path& acPath, const String& acData) noexcept;
11 |
--------------------------------------------------------------------------------
/code/common/Core/Hash.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 |
6 | namespace FHash
7 | {
8 | uint64_t Crc64(const unsigned char* acpData, std::size_t aLength);
9 | uint64_t FNV1a64(const char* aText, uint64_t aSeed = 0xCBF29CE484222325);
10 |
11 | template inline void Combine(std::size_t& seed, const T& v)
12 | {
13 | std::hash hasher;
14 | seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/code/common/Core/Locked.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "Lockable.h"
4 |
5 | template
6 | struct Locked
7 | {
8 | Locked(SharedPtr::Data> apData)
9 | : m_pData(std::move(apData))
10 | , m_handle(m_pData->Lock)
11 | {
12 | }
13 |
14 | operator typename Lockable::Ref() const
15 | {
16 | return { m_pData };
17 | }
18 |
19 | bool IsValid() const
20 | {
21 | return (bool)m_pData;
22 | }
23 |
24 | operator T& ()
25 | {
26 | return Get();
27 | }
28 |
29 | operator T&() const
30 | {
31 | return Get();
32 | }
33 |
34 | const T& Get() const noexcept
35 | {
36 | return m_pData->Value;
37 | }
38 |
39 | T& Get() noexcept
40 | {
41 | return m_pData->Value;
42 | }
43 |
44 | private:
45 | friend struct Lockable;
46 |
47 | SharedPtr::Data> m_pData;
48 | std::scoped_lock m_handle;
49 | };
50 |
51 |
--------------------------------------------------------------------------------
/code/common/Core/Memory.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
--------------------------------------------------------------------------------
/code/common/Core/MimallocAllocator.cpp:
--------------------------------------------------------------------------------
1 | #include "MimallocAllocator.h"
2 |
3 | #include
4 |
5 |
6 | void* MimallocAllocator::Allocate(const size_t aSize) noexcept
7 | {
8 | return mi_malloc(aSize);
9 | }
10 |
11 | void MimallocAllocator::Free(void* apData) noexcept
12 | {
13 | mi_free(apData);
14 | }
15 |
16 | size_t MimallocAllocator::Size(void* apData) noexcept
17 | {
18 | if (apData == nullptr) return 0;
19 |
20 | return mi_malloc_size(apData);
21 | }
22 |
23 | void* MimallocAllocator::AlignedAllocate(size_t aSize, size_t aAlignment) noexcept
24 | {
25 | return mi_malloc_aligned(aSize, aAlignment);
26 | }
27 |
28 | void MimallocAllocator::AlignedFree(void* apData) noexcept
29 | {
30 | mi_free(apData);
31 | }
32 |
33 |
--------------------------------------------------------------------------------
/code/common/Core/MimallocAllocator.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "Allocator.h"
4 |
5 | struct MimallocAllocator : Allocator
6 | {
7 | MimallocAllocator() noexcept = default;
8 | virtual ~MimallocAllocator() = default;
9 |
10 | TP_NOCOPYMOVE(MimallocAllocator);
11 |
12 | [[nodiscard]] void* Allocate(size_t aSize) noexcept override;
13 | void Free(void* apData) noexcept override;
14 | [[nodiscard]] size_t Size(void* apData) noexcept override;
15 |
16 | [[nodiscard]] static void* AlignedAllocate(size_t aSize, size_t aAlignment) noexcept;
17 | static void AlignedFree(void* apData) noexcept;
18 | };
19 |
20 |
--------------------------------------------------------------------------------
/code/common/Core/Platform.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | // Do mac someday ?
4 | #ifdef _WIN32
5 | #define TP_PLATFORM_WINDOWS 1
6 | #define TP_PLATFORM_LINUX 0
7 | #else
8 | #define TP_PLATFORM_WINDOWS 0
9 | #define TP_PLATFORM_LINUX 1
10 | #endif
11 |
12 | #if defined(_LP64) || defined(_WIN64)
13 | #define TP_PLATFORM_64 1
14 | #define TP_PLATFORM_32 0
15 | #else
16 | #define TP_PLATFORM_64 0
17 | #define TP_PLATFORM_32 1
18 | #endif
19 |
20 | #ifdef NDEBUG
21 | #define TP_RELEASE 1
22 | #define TP_DEBUG 0
23 | #else
24 | #define TP_RELEASE 0
25 | #define TP_DEBUG 1
26 | #endif
27 |
28 | consteval bool IsDebug()
29 | {
30 | return false;
31 | return TP_DEBUG;
32 | }
33 |
34 | #define TP_UNUSED(x) (void)x;
35 |
--------------------------------------------------------------------------------
/code/common/Core/ScratchAllocator.cpp:
--------------------------------------------------------------------------------
1 | #include "ScratchAllocator.h"
2 | #include "Platform.h"
3 | #include
4 |
5 |
6 | ScratchAllocator::ScratchAllocator(const size_t aSize) noexcept
7 | : m_size(aSize)
8 | , m_baseSize(aSize)
9 | {
10 | m_pBaseData = m_pData = GetDefault()->Allocate(aSize);
11 |
12 | if (m_pData == nullptr)
13 | {
14 | m_size = 0;
15 | }
16 | }
17 |
18 | ScratchAllocator::~ScratchAllocator()
19 | {
20 | GetDefault()->Free(m_pBaseData);
21 | }
22 |
23 | void* ScratchAllocator::Allocate(const size_t aSize) noexcept
24 | {
25 | if (std::align(alignof(std::max_align_t), aSize, m_pData, m_size))
26 | {
27 | const auto pResult = m_pData;
28 | m_pData = static_cast(m_pData) + aSize;
29 | m_size -= aSize;
30 | return pResult;
31 | }
32 |
33 | return nullptr;
34 | }
35 |
36 | void ScratchAllocator::Free(void* apData) noexcept
37 | {
38 | TP_UNUSED(apData);
39 | }
40 |
41 | size_t ScratchAllocator::Size(void* apData) noexcept
42 | {
43 | TP_UNUSED(apData);
44 | return m_size;
45 | }
46 |
47 | void ScratchAllocator::Reset() noexcept
48 | {
49 | m_size = m_baseSize;
50 | m_pData = m_pBaseData;
51 | }
52 |
53 |
--------------------------------------------------------------------------------
/code/common/Core/ScratchAllocator.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "Allocator.h"
4 |
5 |
6 | struct ScratchAllocator : Allocator
7 | {
8 | explicit ScratchAllocator(size_t aSize) noexcept;
9 | virtual ~ScratchAllocator();
10 |
11 | TP_NOCOPYMOVE(ScratchAllocator);
12 |
13 | [[nodiscard]] void* Allocate(size_t aSize) noexcept override;
14 | void Free(void* apData) noexcept override;
15 | [[nodiscard]] size_t Size(void* apData) noexcept override;
16 | void Reset() noexcept override;
17 |
18 | private:
19 |
20 | size_t m_size;
21 | size_t m_baseSize;
22 | void* m_pData;
23 | void* m_pBaseData;
24 | };
25 |
26 |
--------------------------------------------------------------------------------
/code/common/Core/StandardAllocator.cpp:
--------------------------------------------------------------------------------
1 | #include "StandardAllocator.h"
2 |
3 | #include
4 | #ifdef __APPLE__
5 | #include
6 | #else
7 | #include
8 | #endif
9 |
10 |
11 |
12 | void* StandardAllocator::Allocate(const size_t aSize) noexcept
13 | {
14 | return malloc(aSize);
15 | }
16 |
17 | void StandardAllocator::Free(void* apData) noexcept
18 | {
19 | free(apData);
20 | }
21 |
22 | size_t StandardAllocator::Size(void* apData) noexcept
23 | {
24 | if (apData == nullptr) return 0;
25 |
26 | #ifdef _WIN32
27 | return _msize(apData);
28 | #elif __linux__
29 | return malloc_usable_size(apData);
30 | #elif __APPLE__
31 | return malloc_size(apData);
32 | #else
33 | static_assert(false, "Not implemented");
34 | return 0;
35 | #endif
36 | }
37 |
--------------------------------------------------------------------------------
/code/common/Core/StandardAllocator.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "Allocator.h"
4 |
5 |
6 | struct StandardAllocator : Allocator
7 | {
8 | StandardAllocator() noexcept = default;
9 | virtual ~StandardAllocator() = default;
10 |
11 | TP_NOCOPYMOVE(StandardAllocator);
12 |
13 | [[nodiscard]] void* Allocate(size_t aSize) noexcept override;
14 | void Free(void* apData) noexcept override;
15 | [[nodiscard]] size_t Size(void* apData) noexcept override;
16 | };
17 |
18 |
--------------------------------------------------------------------------------
/code/common/Core/StlAllocator.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "Allocator.h"
4 | #include
5 |
6 |
7 | template
8 | struct StlAllocator
9 | {
10 | using value_type = T;
11 |
12 | StlAllocator()
13 | {
14 | m_pAllocator = Allocator::Get();
15 | }
16 |
17 | template
18 | constexpr StlAllocator(const StlAllocator& acRhs) noexcept
19 | {
20 | m_pAllocator = acRhs.m_pAllocator;
21 | }
22 |
23 | [[nodiscard]] T* allocate(std::size_t aSize)
24 | {
25 | if (aSize > std::size_t(-1) / sizeof(T))
26 | throw std::bad_alloc();
27 |
28 | if (auto p = static_cast(m_pAllocator->Allocate(aSize * sizeof(T))))
29 | return p;
30 |
31 | throw std::bad_alloc();
32 | }
33 | void deallocate(T* p, std::size_t) noexcept
34 | {
35 | m_pAllocator->Free(p);
36 | }
37 |
38 |
39 | Allocator* m_pAllocator;
40 | };
41 |
42 | template
43 | bool operator==(const StlAllocator&, const StlAllocator&) { return true; }
44 | template
45 | bool operator!=(const StlAllocator&, const StlAllocator&) { return false; }
46 |
--------------------------------------------------------------------------------
/code/common/Core/TaskQueue.cpp:
--------------------------------------------------------------------------------
1 | #include "TaskQueue.h"
2 |
3 |
4 |
5 | void TaskQueue::Add(std::function aFunction) noexcept
6 | {
7 | std::scoped_lock _{ m_mutex };
8 |
9 | UnsafeAdd(std::move(aFunction));
10 | }
11 |
12 | bool TaskQueue::Pop(std::function& aResultFunction) noexcept
13 | {
14 | std::scoped_lock _{ m_mutex };
15 |
16 | return UnsafePop(aResultFunction);
17 | }
18 |
19 | size_t TaskQueue::Drain() noexcept
20 | {
21 | size_t count = 0;
22 |
23 | std::scoped_lock _{ m_mutex };
24 |
25 | std::function func;
26 | while (UnsafePop(func))
27 | {
28 | func();
29 | ++count;
30 | }
31 |
32 | return count;
33 | }
34 |
35 | void TaskQueue::UnsafeAdd(std::function aFunction) noexcept
36 | {
37 | m_tasks.emplace(std::move(aFunction));
38 | }
39 |
40 | bool TaskQueue::UnsafePop(std::function& aResultFunction) noexcept
41 | {
42 | if (m_tasks.empty())
43 | return false;
44 |
45 | aResultFunction = std::move(m_tasks.front());
46 |
47 | m_tasks.pop();
48 |
49 | return true;
50 | }
51 |
52 | std::mutex& TaskQueue::Lock() noexcept
53 | {
54 | return m_mutex;
55 | }
56 |
57 |
--------------------------------------------------------------------------------
/code/common/Core/TaskQueue.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "Stl.h"
4 | #include
5 |
6 |
7 | // Thread safe task queue
8 | struct TaskQueue
9 | {
10 | void Add(std::function aFunction) noexcept;
11 | bool Pop(std::function& aResultFunction) noexcept;
12 | size_t Drain() noexcept;
13 |
14 | void UnsafeAdd(std::function aFunction) noexcept;
15 | bool UnsafePop(std::function& aResultFunction) noexcept;
16 |
17 | [[nodiscard]] std::mutex& Lock() noexcept;
18 |
19 | private:
20 |
21 | std::mutex m_mutex;
22 | Queue> m_tasks;
23 | };
24 |
25 |
--------------------------------------------------------------------------------
/code/common/Core/TrackAllocator.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "Allocator.hpp"
4 |
5 |
6 | {
7 | template
8 | struct TrackAllocator : Allocator
9 | {
10 | TrackAllocator() noexcept = default;
11 | virtual ~TrackAllocator() {}
12 |
13 | TP_NOCOPYMOVE(TrackAllocator);
14 |
15 | [[nodiscard]] void* Allocate(size_t aSize) noexcept override
16 | {
17 | void* pData = m_allocator.Allocate(aSize);
18 |
19 | if (pData)
20 | m_usedMemory += m_allocator.Size(pData);
21 |
22 | return pData;
23 | }
24 |
25 | void Free(void* apData) noexcept override
26 | {
27 | m_usedMemory -= m_allocator.Size(apData);
28 | }
29 |
30 | [[nodiscard]]size_t Size(void* apData) noexcept override
31 | {
32 | return m_allocator.Size(apData);
33 | }
34 |
35 | [[nodiscard]] size_t GetUsedMemory() const noexcept
36 | {
37 | return m_usedMemory;
38 | }
39 |
40 | private:
41 |
42 | T m_allocator;
43 | size_t m_usedMemory{ 0 };
44 | };
45 | }
46 |
--------------------------------------------------------------------------------
/code/common/Core/ViewBuffer.cpp:
--------------------------------------------------------------------------------
1 | #include "ViewBuffer.h"
2 |
3 |
4 | ViewBuffer::ViewBuffer(uint8_t* apData, size_t aSize) noexcept
5 | {
6 | m_pData = apData;
7 | m_size = aSize;
8 | }
9 |
10 | ViewBuffer::~ViewBuffer()
11 | {
12 | m_pData = nullptr;
13 | }
14 |
15 |
--------------------------------------------------------------------------------
/code/common/Core/ViewBuffer.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "Buffer.h"
4 |
5 |
6 | struct ViewBuffer : Buffer
7 | {
8 | explicit ViewBuffer(uint8_t* apData, size_t aSize) noexcept;
9 | virtual ~ViewBuffer();
10 | };
11 |
12 |
--------------------------------------------------------------------------------
/code/common/Math/Hash.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tiltedphoques/CyberpunkMP/0ccb0cfa78222cc463ea937e0c8271060f9afd2a/code/common/Math/Hash.h
--------------------------------------------------------------------------------
/code/common/Math/Math.cpp:
--------------------------------------------------------------------------------
1 | #include "Math.h"
2 | #include
3 |
4 |
5 | float Sigmoid(float x, float lambda, float k) noexcept
6 | {
7 | return 1.f / (1.f + expf(-x * lambda + k));
8 | }
9 |
10 | float SmoothStep(float delta) noexcept
11 | {
12 | return delta * delta * (3 - 2 * delta);
13 | }
14 |
15 | float DeltaAngle(float from, float to, bool useRadians) noexcept
16 | {
17 | const float halfCircle = useRadians ? float(Pi) : 180.f;
18 |
19 | if (fabs(from - to) >= halfCircle)
20 | {
21 | if (from < to)
22 | {
23 | return to - (from + halfCircle * 2);
24 | }
25 |
26 | return (to + halfCircle * 2) - from;
27 | }
28 |
29 | return to - from;
30 | }
31 |
32 | float Mod(float aValue, float aMax) noexcept
33 | {
34 | return fmod(aValue, aMax);
35 | }
36 |
37 | float Max(float aVal, float aMax) noexcept
38 | {
39 | return aVal < aMax ? aMax : aVal;
40 | }
41 |
42 | float Min(float aVal, float aMin) noexcept
43 | {
44 | return aVal > aMin ? aMin : aVal;
45 | }
46 |
47 | float Clamp(float aValue, float aMin, float aMax) noexcept
48 | {
49 | return Max(aMin, Min(aValue, aMax));
50 | }
51 |
52 | float Sqrt(float aValue) noexcept
53 | {
54 | return sqrt(aValue);
55 | }
56 |
57 | double Sqrt(double aValue) noexcept
58 | {
59 | return sqrt(aValue);
60 | }
61 |
62 |
--------------------------------------------------------------------------------
/code/common/Math/Math.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 |
4 | constexpr double Pi = 3.14159265358979323846;
5 |
6 | [[nodiscard]] float Sigmoid(float x, float lambda, float k) noexcept;
7 | [[nodiscard]] float SmoothStep(float delta) noexcept;
8 | [[nodiscard]] float DeltaAngle(float from, float to, bool useRadians) noexcept;
9 | [[nodiscard]] float Mod(float aValue, float aMax) noexcept;
10 | [[nodiscard]] float Max(float aVal, float aMax) noexcept;
11 | [[nodiscard]] float Min(float aVal, float aMin) noexcept;
12 | [[nodiscard]] float Clamp(float aValue, float aMin, float aMax) noexcept;
13 | [[nodiscard]] float Sqrt(float aValue) noexcept;
14 | [[nodiscard]] double Sqrt(double aValue) noexcept;
15 |
16 | template [[nodiscard]]
17 | T LerpDelta(const T& a, const T& b, float delta) noexcept
18 | {
19 | return (b - a) * delta;
20 | }
21 |
22 | // delta should be between 0.f & 1.f
23 | template [[nodiscard]]
24 | T Lerp(const T& a, const T& b, float delta) noexcept
25 | {
26 | return a + LerpDelta(a, b, delta);
27 | }
28 |
--------------------------------------------------------------------------------
/code/common/Math/Vector2.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | template
6 | struct Vector2 : glm::vec<2, T, glm::defaultp>
7 | {
8 | Vector2(T x, T y)
9 | : glm::vec<2, T, glm::defaultp>(x, y)
10 | {
11 | }
12 | };
13 |
14 | namespace std
15 | {
16 | template struct hash>
17 | {
18 | size_t operator()(const Vector2& aVector) const noexcept
19 | {
20 | size_t hash = 0;
21 | FHash::Combine(hash, aVector.x);
22 | FHash::Combine(hash, aVector.y);
23 | return hash;
24 | }
25 | };
26 | } // namespace std
--------------------------------------------------------------------------------
/code/common/Math/Vector3.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tiltedphoques/CyberpunkMP/0ccb0cfa78222cc463ea937e0c8271060f9afd2a/code/common/Math/Vector3.h
--------------------------------------------------------------------------------
/code/common/Network/Packet.cpp:
--------------------------------------------------------------------------------
1 | #include "Packet.h"
2 | #include "SteamInterface.h"
3 |
4 |
5 | Packet::Packet() noexcept
6 | : m_pData(nullptr)
7 | , m_size(0)
8 | {
9 | }
10 |
11 | Packet::Packet(const uint32_t aSize) noexcept
12 | : m_pData(nullptr)
13 | , m_size(aSize + 1)
14 | {
15 | m_pData = static_cast(GetAllocator()->Allocate(m_size));
16 | m_pData[0] = kPayload;
17 | }
18 |
19 | Packet::~Packet() noexcept
20 | {
21 | GetAllocator()->Free(m_pData);
22 | }
23 |
24 | char* Packet::GetData() const noexcept
25 | {
26 | return m_pData + 1;
27 | }
28 |
29 | uint32_t Packet::GetSize() const noexcept
30 | {
31 | return m_size - 1;
32 | }
33 |
34 | uint32_t Packet::GetTotalSize() const noexcept
35 | {
36 | return m_size;
37 | }
38 |
39 | bool Packet::IsValid() const noexcept
40 | {
41 | return m_pData != nullptr;
42 | }
43 |
44 | PacketView::PacketView(char* aPointer, uint32_t aSize)
45 | : Packet()
46 | {
47 | m_pData = aPointer;
48 | m_size = aSize;
49 |
50 | m_pData[0] = kPayload;
51 | }
52 |
53 | PacketView::~PacketView()
54 | {
55 | m_pData = nullptr;
56 | m_size = 0;
57 | }
58 |
59 |
--------------------------------------------------------------------------------
/code/common/Network/Packet.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "Core/Meta.h"
4 | #include "Core/Allocator.h"
5 |
6 |
7 | struct Packet
8 | {
9 | TP_ALLOCATOR;
10 |
11 | Packet() noexcept;
12 | Packet(uint32_t aSize) noexcept;
13 | virtual ~Packet() noexcept;
14 |
15 | TP_NOCOPYMOVE(Packet);
16 |
17 | // Get the start of the write buffer
18 | [[nodiscard]] char* GetData() const noexcept;
19 |
20 | // Get the writable data size, note that the actual packet size may differ from that
21 | [[nodiscard]] uint32_t GetSize() const noexcept;
22 |
23 | // Get the writable data size + protocol data size
24 | [[nodiscard]] uint32_t GetTotalSize() const noexcept;
25 |
26 | // Returns true if the packet has an associated buffer, usually used to check if the underlying allocator had enough space
27 | [[nodiscard]] bool IsValid() const noexcept;
28 |
29 | protected:
30 |
31 | friend struct Server;
32 | friend struct Client;
33 |
34 | char* m_pData;
35 | uint32_t m_size;
36 | };
37 |
38 | struct PacketView : Packet
39 | {
40 | PacketView(char* aPointer, uint32_t aSize);
41 | virtual ~PacketView();
42 | };
43 |
44 |
--------------------------------------------------------------------------------
/code/common/Network/SteamInterface.cpp:
--------------------------------------------------------------------------------
1 | #include "SteamInterface.h"
2 | #include "steam/steamnetworkingsockets.h"
3 |
4 | #include
5 |
6 |
7 | static std::atomic s_initCounter = 0;
8 |
9 | void SteamInterface::Acquire()
10 | {
11 | if (s_initCounter.fetch_add(1, std::memory_order_relaxed) == 0)
12 | {
13 | SteamDatagramErrMsg errorMessage;
14 | if (!GameNetworkingSockets_Init(nullptr, errorMessage))
15 | {
16 | // TODO: Error management
17 | }
18 | }
19 | }
20 |
21 | void SteamInterface::Release()
22 | {
23 | // This seems to conflict with the game's handles so disabling it
24 | if (s_initCounter.fetch_sub(1, std::memory_order_relaxed) == 1)
25 | {
26 | // GameNetworkingSockets_Kill();
27 | }
28 | }
29 |
30 |
--------------------------------------------------------------------------------
/code/common/Network/SteamInterface.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "steam/steamnetworkingsockets.h"
4 |
5 |
6 | enum EPacketFlags
7 | {
8 | kReliable,
9 | kUnreliable
10 | };
11 |
12 | enum EConnectOpcode : uint8_t
13 | {
14 | kPayload = 0,
15 | kServerTime = 1,
16 | kCompressedPayload = 2,
17 | kHandshake = 3
18 | };
19 |
20 | struct SteamInterface
21 | {
22 | static void Acquire();
23 | static void Release();
24 | };
25 |
26 | using ConnectionId = HSteamNetConnection;
27 |
28 |
--------------------------------------------------------------------------------
/code/common/Network/SynchronizedClock.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 |
6 | struct SynchronizedClock
7 | {
8 | SynchronizedClock() noexcept;
9 | [[nodiscard]] uint64_t GetCurrentTick() const noexcept;
10 | [[nodiscard]] bool IsSynchronized() const noexcept;
11 | void Synchronize(uint64_t aServerTick, uint32_t aPing) noexcept;
12 | void Reset() noexcept;
13 | void Update() noexcept;
14 |
15 | private:
16 |
17 | uint64_t m_lastServerTick;
18 | uint64_t m_simulatedTick;
19 | std::chrono::nanoseconds m_previousSimulatedTick;
20 | std::chrono::nanoseconds m_tickDelta;
21 | std::chrono::time_point m_lastSynchronizationTime{};
22 | };
23 |
24 |
--------------------------------------------------------------------------------
/code/common/Reverse/App.cpp:
--------------------------------------------------------------------------------
1 | #include "App.h"
2 | #include "Memory.h"
3 | #include
4 |
5 |
6 | App::App() noexcept
7 | : m_ready(false)
8 | {
9 | }
10 |
11 | App::~App() = default;
12 |
13 | void App::Start() noexcept
14 | {
15 | m_ready = true;
16 |
17 | BeginMain();
18 | }
19 |
20 | bool App::IsReady() const noexcept
21 | {
22 | return m_ready;
23 | }
24 |
--------------------------------------------------------------------------------
/code/common/Reverse/App.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | struct App
4 | {
5 | App() noexcept;
6 | virtual ~App();
7 |
8 | // Retrieve the program's main address, if null is returned the main function will not be hooked
9 | [[nodiscard]] virtual void* GetMainAddress() const = 0;
10 |
11 | // Called right before the program's main function is called
12 | virtual bool BeginMain() = 0;
13 |
14 | // Called after the program's main function exits
15 | virtual bool EndMain() = 0;
16 |
17 | // Called when the dll is attached, before anything else
18 | virtual bool Attach() = 0;
19 |
20 | // Called when the dll is detached
21 | virtual bool Detach() = 0;
22 |
23 | // Must be called once per frame
24 | virtual void Update() = 0;
25 |
26 | void Start() noexcept;
27 |
28 | // Functions that can be called by class users
29 | [[nodiscard]] bool IsReady() const noexcept;
30 |
31 |
32 | static App& GetInstance() noexcept;
33 |
34 | private:
35 |
36 | bool m_ready;
37 | };
38 |
39 |
--------------------------------------------------------------------------------
/code/common/Reverse/AutoPtr.cpp:
--------------------------------------------------------------------------------
1 | #include "AutoPtr.h"
2 | #include "AutoPtrManager.h"
3 |
4 | #include
5 |
6 |
7 | BasicAutoPtr::BasicAutoPtr(Pattern aPattern) noexcept
8 | {
9 | m_pPtr = AutoPtrManager::GetInstance().Find(std::move(aPattern));
10 |
11 | assert(m_pPtr != nullptr);
12 | }
13 |
14 | BasicAutoPtr::BasicAutoPtr(const uintptr_t aAddress) noexcept
15 | {
16 | m_pPtr = reinterpret_cast(aAddress + AutoPtrManager::GetInstance().GetBaseAddress());
17 | }
18 |
19 | void* BasicAutoPtr::GetPtr() const noexcept
20 | {
21 | return m_pPtr;
22 | }
23 |
24 |
--------------------------------------------------------------------------------
/code/common/Reverse/AutoPtr.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "Pattern.h"
4 |
5 |
6 | struct BasicAutoPtr
7 | {
8 | explicit BasicAutoPtr(Pattern aPattern) noexcept;
9 | explicit BasicAutoPtr(uintptr_t aAddress) noexcept;
10 |
11 | BasicAutoPtr() = delete;
12 | BasicAutoPtr(BasicAutoPtr&) = delete;
13 | BasicAutoPtr& operator=(BasicAutoPtr&) = delete;
14 |
15 | [[nodiscard]] void* GetPtr() const noexcept;
16 |
17 | private:
18 |
19 | void* m_pPtr;
20 | };
21 |
22 | template
23 | struct AutoPtr : BasicAutoPtr
24 | {
25 | explicit AutoPtr(Pattern aPattren) noexcept : BasicAutoPtr(std::move(aPattren)) {}
26 | explicit AutoPtr(const uintptr_t aAddress) noexcept : BasicAutoPtr(aAddress) {}
27 |
28 | AutoPtr() = delete;
29 | AutoPtr(AutoPtr&) = delete;
30 | AutoPtr& operator=(AutoPtr&) = delete;
31 |
32 | operator T* () const noexcept { return Get(); }
33 | T* operator->() const noexcept { return Get(); }
34 |
35 | T* Get() const noexcept { return static_cast(GetPtr()); }
36 | };
37 |
38 |
--------------------------------------------------------------------------------
/code/common/Reverse/AutoPtrManager.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include "Pattern.h"
5 |
6 |
7 | struct AutoPtrManager
8 | {
9 | TP_NOCOPYMOVE(AutoPtrManager);
10 |
11 | [[nodiscard]] uintptr_t GetBaseAddress() const noexcept;
12 | [[nodiscard]] void* Find(Pattern aPattern) const noexcept;
13 |
14 | static AutoPtrManager& GetInstance() noexcept
15 | {
16 | return s_instance;
17 | }
18 |
19 | private:
20 |
21 | AutoPtrManager() noexcept;
22 | ~AutoPtrManager() noexcept;
23 |
24 | uintptr_t m_baseAddress;
25 | uintptr_t m_textStartAddress;
26 | size_t m_textSize;
27 | uint64_t m_textHash;
28 |
29 | static AutoPtrManager s_instance;
30 | };
31 |
--------------------------------------------------------------------------------
/code/common/Reverse/Debug.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | struct Debug
4 | {
5 | static void WaitForDebugger() noexcept;
6 | static void CreateConsole() noexcept;
7 | static void OnAttach() noexcept;
8 | static void OnDetach() noexcept;
9 | };
10 |
11 |
--------------------------------------------------------------------------------
/code/common/Reverse/Entry.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 |
6 |
7 | struct App;
8 |
9 | namespace details
10 | {
11 | BOOL ReverseMain(HMODULE hModule, DWORD fdwReason, LPVOID lpReserved, const std::function()>& aAppFactory) noexcept;
12 | }
13 |
14 | template
15 | BOOL CreateReverseApp(HMODULE hModule, DWORD fdwReason, LPVOID lpReserved) noexcept
16 | {
17 | static_assert(std::is_base_of_v);
18 |
19 | return details::ReverseMain(hModule, fdwReason, lpReserved, []() { return std::make_unique(); });
20 | }
21 |
22 |
23 | #define DEFINE_DLL_ENTRY_INITIALIZER(className) \
24 | BOOL APIENTRY DllMain(HMODULE hModule, DWORD fdwReason, LPVOID lpReserved) \
25 | { \
26 | return TiltedPhoques::CreateReverseApp(hModule, fdwReason, lpReserved); \
27 | }
28 |
--------------------------------------------------------------------------------
/code/common/Reverse/JitAssembly.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #ifndef REVERSE_ALLOC_STUB
4 | #define REVERSE_ALLOC_STUB(x) malloc(x)
5 | #endif
6 |
7 | #include