From 0d746273a7c755e445a975e27957e95844336c6a Mon Sep 17 00:00:00 2001 From: HuiZhiYin <639821869@qq.com> Date: Thu, 7 May 2026 04:00:44 +0800 Subject: [PATCH 01/17] Block empty chat messages (#915) * Block empty chat messages --- primedev/scripts/client/clientchathooks.cpp | 11 +++++++++++ primedev/server/serverchathooks.cpp | 11 +++++++++++ 2 files changed, 22 insertions(+) diff --git a/primedev/scripts/client/clientchathooks.cpp b/primedev/scripts/client/clientchathooks.cpp index 310adf6a..bc6cc180 100644 --- a/primedev/scripts/client/clientchathooks.cpp +++ b/primedev/scripts/client/clientchathooks.cpp @@ -5,6 +5,7 @@ #include "client/localchatwriter.h" #include +#include static void(__fastcall* o_pCHudChat__AddGameLine)(void* self, const char* message, int inboxId, bool isTeam, bool isDead) = nullptr; static void __fastcall h_CHudChat__AddGameLine(void* self, const char* message, int inboxId, bool isTeam, bool isDead) @@ -12,6 +13,8 @@ static void __fastcall h_CHudChat__AddGameLine(void* self, const char* message, // This hook is called for each HUD, but we only want our logic to run once. if (self != *CHudChat::allHuds) return; + if (message == nullptr || message[0] == '\0') + return; int senderId = inboxId & CUSTOM_MESSAGE_INDEX_MASK; bool isAnonymous = senderId == 0; @@ -28,6 +31,14 @@ static void __fastcall h_CHudChat__AddGameLine(void* self, const char* message, RemoveAsciiControlSequences(const_cast(message), true); + { + const char* p = isCustom ? payload : message; + while (isspace((unsigned char)*p)) + p++; + if (*p == '\0') + return; + } + SQRESULT result = g_pSquirrel[ScriptContext::CLIENT]->Call( "CHudChat_ProcessMessageStartThread", static_cast(senderId) - 1, payload, isTeam, isDead, type); if (result == SQRESULT_ERROR) diff --git a/primedev/server/serverchathooks.cpp b/primedev/server/serverchathooks.cpp index 58e6dc03..7470559e 100644 --- a/primedev/server/serverchathooks.cpp +++ b/primedev/server/serverchathooks.cpp @@ -7,6 +7,7 @@ #include #include #include +#include class CServerGameDLL; @@ -36,8 +37,18 @@ static void(__fastcall* o_pCServerGameDLL__OnReceivedSayTextMessage)( static void __fastcall h_CServerGameDLL__OnReceivedSayTextMessage( CServerGameDLL* self, unsigned int senderPlayerId, const char* text, bool isTeam) { + if (text == nullptr) + return; RemoveAsciiControlSequences(const_cast(text), true); + if (text[0] == '\0') + return; + const char* p = text; + while (isspace((unsigned char)*p)) + p++; + if (*p == '\0') + return; + // MiniHook doesn't allow calling the base function outside of anywhere but the hook function. // To allow bypassing the hook, isSkippingHook can be set. if (bShouldCallSayTextHook) From 8d19272b65c539595eb787e264e7c7dab5ba1ee6 Mon Sep 17 00:00:00 2001 From: cat_or_not <41955154+catornot@users.noreply.github.com> Date: Wed, 6 May 2026 16:59:04 -0400 Subject: [PATCH 02/17] Pin clang version to 16 for formatting in the flake (#911) * Add older nixpkgs for clang-format-16 --- flake.lock | 17 +++++++++++++++++ flake.nix | 15 ++++++++++++--- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index aae179c9..a5c3155b 100644 --- a/flake.lock +++ b/flake.lock @@ -34,6 +34,22 @@ "type": "github" } }, + "nixpkgs-24-11": { + "locked": { + "lastModified": 1731603435, + "narHash": "sha256-CqCX4JG7UiHvkrBTpYC3wcEurvbtTADLbo3Ns2CEoL8=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "8b27c1239e5c421a2bbc2c65d52e4a6fbf2ff296", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "24.11", + "repo": "nixpkgs", + "type": "github" + } + }, "nixpkgs_2": { "locked": { "lastModified": 1770107345, @@ -54,6 +70,7 @@ "inputs": { "flake-utils": "flake-utils", "nixpkgs": "nixpkgs", + "nixpkgs-24-11": "nixpkgs-24-11", "treefmt-nix": "treefmt-nix" } }, diff --git a/flake.nix b/flake.nix index c67ff6ee..61711f8a 100644 --- a/flake.nix +++ b/flake.nix @@ -4,6 +4,8 @@ inputs = { nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + nixpkgs-24-11.url = "github:NixOS/nixpkgs/24.11"; # needed for clang-format-16 + flake-utils.url = "github:numtide/flake-utils"; treefmt-nix.url = "github:numtide/treefmt-nix"; @@ -15,6 +17,7 @@ { self, nixpkgs, + nixpkgs-24-11, flake-utils, treefmt-nix, }: @@ -135,14 +138,20 @@ # settings settings.formatter.clang-format = { - args = [ + package = nixpkgs-24-11.legacyPackages.${system}.llvmPackages_16.clang-tools; + command = "${nixpkgs-24-11.legacyPackages.${system}.llvmPackages_16.clang-tools}/bin/clang-format"; + options = [ "-i" "--style=file" ]; excludes = [ "primedev/include/**" - "primedev/*.cpp" - "primedev/*.h" + "primedev/thirdparty/**" + "primedev/wsockproxy/**" + "primedev/dllmain.cpp" + "primedev/ns_version.h" + "primedev/pch.h" + "primedev/resource1.h" ]; }; } From 64a7735c5722fd221c9894a63c6ec338ac6324fe Mon Sep 17 00:00:00 2001 From: Jack <66967891+ASpoonPlaysGames@users.noreply.github.com> Date: Wed, 6 May 2026 23:07:50 +0100 Subject: [PATCH 03/17] Don't include the various libcurl test build targets (#916) * Don't add all of the libcurl testing build targets --- CMakeSettings.json | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/CMakeSettings.json b/CMakeSettings.json index 2e46e711..d9611e71 100644 --- a/CMakeSettings.json +++ b/CMakeSettings.json @@ -9,7 +9,14 @@ "cmakeCommandArgs": "", "buildCommandArgs": "", "ctestCommandArgs": "", - "inheritEnvironments": [ "msvc_x64_x64" ] + "inheritEnvironments": [ "msvc_x64_x64" ], + "variables": [ + { + "name": "BUILD_TESTING", + "value": "False", + "type": "BOOL" + } + ] }, { "name": "x64-RelWithDebInfo", @@ -20,7 +27,14 @@ "installRoot": "${projectDir}\\out\\install\\${name}", "cmakeCommandArgs": "", "buildCommandArgs": "", - "ctestCommandArgs": "" + "ctestCommandArgs": "", + "variables": [ + { + "name": "BUILD_TESTING", + "value": "False", + "type": "BOOL" + } + ] }, { "name": "x64-Debug", @@ -32,7 +46,13 @@ "buildCommandArgs": "", "ctestCommandArgs": "", "inheritEnvironments": [ "msvc_x64_x64" ], - "variables": [] + "variables": [ + { + "name": "BUILD_TESTING", + "value": "False", + "type": "BOOL" + } + ] } ] -} \ No newline at end of file +} From 39d5570c7670e2bf7189ec0eb86db1e04ddc39d9 Mon Sep 17 00:00:00 2001 From: Allusive <154700875+AllusiveWheat@users.noreply.github.com> Date: Sat, 9 May 2026 17:30:55 -0700 Subject: [PATCH 04/17] Make pakLoadApi global (#918) * make pakLoadApi global * fmt --------- Co-authored-by: catornot <41955154+catornot@users.noreply.github.com> --- primedev/core/filesystem/rpakfilesystem.cpp | 41 -------------------- primedev/core/filesystem/rpakfilesystem.h | 43 +++++++++++++++++++++ 2 files changed, 43 insertions(+), 41 deletions(-) diff --git a/primedev/core/filesystem/rpakfilesystem.cpp b/primedev/core/filesystem/rpakfilesystem.cpp index f427f1f6..6bc06bfe 100644 --- a/primedev/core/filesystem/rpakfilesystem.cpp +++ b/primedev/core/filesystem/rpakfilesystem.cpp @@ -5,47 +5,6 @@ #include "util/utils.h" #include "rtech/pakfile.h" -#pragma pack(push, 1) -struct PakLoadFuncs -{ - void (*InitRpakSystem)(); - void (*AddAssetLoaderWithJobDetails)(/*assetTypeHeader*/ void*, uint32_t, int); - void (*AddAssetLoader)(/*assetTypeHeader*/ void*); - PakHandle (*LoadRpakFileAsync)(const char* pPath, void* allocator, int flags); - void (*LoadRpakFile)(const char*, __int64(__fastcall*)(), __int64, void(__cdecl*)()); - __int64 qword28; - void (*UnloadPak)(PakHandle iPakHandle, void* callback); - __int64 qword38; - __int64 qword40; - __int64 qword48; - __int64 qword50; - FARPROC (*GetDllCallback)(__int16 a1, const CHAR* a2); - __int64 (*GetAssetByHash)(__int64 hash); - __int64 (*GetAssetByName)(const char* a1); - __int64 qword70; - __int64 qword78; - __int64 qword80; - __int64 qword88; - __int64 qword90; - __int64 qword98; - __int64 qwordA0; - __int64 qwordA8; - __int64 qwordB0; - __int64 qwordBB; - void* (*OpenFile)(const char* pPath); - __int64 CloseFile; - __int64 qwordD0; - __int64 FileReadAsync; - __int64 ComplexFileReadAsync; - __int64 GetReadJobState; - __int64 WaitForFileReadJobComplete; - __int64 CancelFileReadJob; - __int64 CancelFileReadJobAsync; - __int64 qword108; -}; -static_assert(sizeof(PakLoadFuncs) == 0x110); -#pragma pack(pop) - PakLoadFuncs* g_pakLoadApi; PakLoadManager* g_pPakLoadManager; diff --git a/primedev/core/filesystem/rpakfilesystem.h b/primedev/core/filesystem/rpakfilesystem.h index 9c090807..a13013a1 100644 --- a/primedev/core/filesystem/rpakfilesystem.h +++ b/primedev/core/filesystem/rpakfilesystem.h @@ -3,6 +3,49 @@ #include #include "rtech/pakfile.h" +#pragma pack(push, 1) +struct PakLoadFuncs +{ + void (*InitRpakSystem)(); + void (*AddAssetLoaderWithJobDetails)(/*assetTypeHeader*/ void*, uint32_t, int); + void (*AddAssetLoader)(/*assetTypeHeader*/ void*); + PakHandle (*LoadRpakFileAsync)(const char* pPath, void* allocator, int flags); + void (*LoadRpakFile)(const char*, __int64(__fastcall*)(), __int64, void(__cdecl*)()); + __int64 qword28; + void (*UnloadPak)(PakHandle iPakHandle, void* callback); + __int64 qword38; + __int64 qword40; + __int64 qword48; + __int64 qword50; + FARPROC (*GetDllCallback)(__int16 a1, const CHAR* a2); + __int64 (*GetAssetByHash)(__int64 hash); + __int64 (*GetAssetByName)(const char* a1); + __int64 qword70; + __int64 qword78; + __int64 qword80; + __int64 qword88; + __int64 qword90; + __int64 qword98; + __int64 qwordA0; + __int64 qwordA8; + __int64 qwordB0; + __int64 qwordBB; + void* (*OpenFile)(const char* pPath); + __int64 CloseFile; + __int64 qwordD0; + __int64 FileReadAsync; + __int64 ComplexFileReadAsync; + __int64 GetReadJobState; + __int64 WaitForFileReadJobComplete; + __int64 CancelFileReadJob; + __int64 CancelFileReadJobAsync; + __int64 qword108; +}; +static_assert(sizeof(PakLoadFuncs) == 0x110); +#pragma pack(pop) + +extern PakLoadFuncs* g_pakLoadApi; + struct ModPak_t { std::string m_modName; From fad19af91972aaa841fe9950ec9e339bfdb29e0b Mon Sep 17 00:00:00 2001 From: FourthVolt <87427011+EM4Volts@users.noreply.github.com> Date: Mon, 18 May 2026 21:17:06 +0200 Subject: [PATCH 05/17] Various materialsystem things (#919) * various materialsystem things * Update nscustomdxbuffer.cpp formatter maybe * Update nscustomdxbuffer.cpp Buy minecraft * move comment move comment * Update nscustomdxbuffer.cpp * more slots slots go brrrt more slots slots go brrrt --- primedev/engine/gl_matsysiface.cpp | 48 +++-- primedev/materialsystem/cmaterialglue.h | 151 +++++++++++---- primedev/materialsystem/cshaderglue.h | 25 +++ primedev/materialsystem/nscustomdxbuffer.cpp | 186 ++++++++++++++++++- 4 files changed, 349 insertions(+), 61 deletions(-) diff --git a/primedev/engine/gl_matsysiface.cpp b/primedev/engine/gl_matsysiface.cpp index 075a56ac..6c88c38f 100644 --- a/primedev/engine/gl_matsysiface.cpp +++ b/primedev/engine/gl_matsysiface.cpp @@ -19,26 +19,46 @@ static void __fastcall h_CC_mat_crosshair_printmaterial_f(const CCommand& args) if (!pGlue) { - spdlog::info("|-- {} is NULL", szName); + spdlog::info("├ No reference material for {}", szName); return; } - spdlog::info("|-- Name: {}", szName); - spdlog::info("|-- GUID: {:#x}", pGlue->m_GUID); - spdlog::info("|-- Name: {}", pGlue->m_pszName); - spdlog::info("|-- Width : {}", pGlue->m_iWidth); - spdlog::info("|-- Height: {}", pGlue->m_iHeight); + spdlog::info("├ {}", szName); + spdlog::info("│├── GUID: {:#x}", pGlue->material.guid); + spdlog::info("│└── Name: {}", pGlue->material.name); }; - spdlog::info("|- GUID: {:#x}", pMat->m_GUID); - spdlog::info("|- Name: {}", pMat->m_pszName); - spdlog::info("|- Width : {}", pMat->m_iWidth); - spdlog::info("|- Height: {}", pMat->m_iHeight); + spdlog::info("────────────────────────────────────────────────────────────"); + spdlog::info("┌ Name: {}", pMat->material.name); + spdlog::info("├ GUID: {:#x}", pMat->material.guid); + spdlog::info("├ Width : {}", pMat->material.width); + spdlog::info("├ Height: {}", pMat->material.height); + spdlog::info("├ Shaderset: {}", pMat->material.shaderSet->inner.name); - fnPrintGlue(pMat->m_pDepthShadow, "DepthShadow"); - fnPrintGlue(pMat->m_pDepthPrepass, "DepthPrepass"); - fnPrintGlue(pMat->m_pDepthVSM, "DepthVSM"); - fnPrintGlue(pMat->m_pColPass, "ColPass"); + fnPrintGlue(pMat->material.DepthShadow_ref, "DepthShadow"); + fnPrintGlue(pMat->material.DepthPrepass_ref, "DepthPrepass"); + fnPrintGlue(pMat->material.DepthVSM_ref, "DepthVSM"); + fnPrintGlue(pMat->material.Colpass_ref, "Colpass"); + + if (pMat && pMat->material.shaderSet && pMat->material.shaderSet->inner.textureInputCount >= 1 && pMat->material.textureHandles) + { + spdlog::info("├ Textures"); + for (size_t slot = 0; slot < pMat->material.shaderSet->inner.textureInputCount + 1; ++slot) + { + RpakTextureHeader* currentTexture = pMat->material.textureHandles[slot]; + + if (currentTexture && currentTexture->name) + { + if (slot == pMat->material.shaderSet->inner.textureInputCount) + spdlog::info("│└[{}][{:#x}]{}", slot, currentTexture->guid, currentTexture->name); + else + spdlog::info("│├[{}][{:#x}]{}", slot, currentTexture->guid, currentTexture->name); + } + } + } + spdlog::info("├ Glueflags: {:#x}", pMat->material.flags); + spdlog::info("└ Glueflags2: {:#x}", pMat->material.flags2); + spdlog::info("────────────────────────────────────────────────────────────"); } ON_DLL_LOAD("engine.dll", GlMatSysIFace, (CModule module)) diff --git a/primedev/materialsystem/cmaterialglue.h b/primedev/materialsystem/cmaterialglue.h index 1738a91a..f57d6221 100644 --- a/primedev/materialsystem/cmaterialglue.h +++ b/primedev/materialsystem/cmaterialglue.h @@ -1,47 +1,124 @@ #pragma once #include "materialsystem/cshaderglue.h" +#include +class RpakTextureHeader // Expected size: 0x130 +{ +public: + uint64_t guid; + const char* name; + uint16_t width; + uint16_t height; + int16_t depth; + uint16_t dxgiFormat; + uint32_t dataSize; + uint8_t compressionType; + uint8_t optStreamedMipCount; + uint8_t arraySize; + uint8_t layerCount; + uint8_t mipFlags; + uint8_t permanentMipCount; + uint8_t streamedMipCount; + uint8_t unk[13]; + int64_t numPixels; + uint16_t unknownWord38; + uint8_t unknownByte3A; + uint8_t unknownByte3B; + uint32_t unknownDword3C; + uint32_t unknownDword40; + uint32_t unknownDword44; + float transform[16]; + uint64_t unknownQword88; + uint64_t unknownQword90; + uint32_t unknownArray98[16]; + uint32_t unknownArrayD8[16]; + ID3D11Resource* d3d11Resource; + ID3D11ShaderResourceView* shaderResourceView; + uint8_t unknownByte128; + uint8_t padding[7]; +}; + +struct CBufUberStatic // sizeof = 0xE0 +{ + float c_uv1RotScaleX[2]; // 0x00 + float c_uv1RotScaleY[2]; // 0x08 + float c_uv1Translate[2]; // 0x10 + float c_uv2RotScaleX[2]; // 0x18 + float c_uv2RotScaleY[2]; // 0x20 + float c_uv2Translate[2]; // 0x28 + float c_uv3RotScaleX[2]; // 0x30 + float c_uv3RotScaleY[2]; // 0x38 + float c_uv3Translate[2]; // 0x40 + float c_uvDistortionIntensity[2]; // 0x48 + float c_uvDistortion2Intensity[2]; // 0x50 + float c_fogColorFactor; // 0x58 + float c_layerBlendRamp; // 0x5C + float c_albedoTint[3]; // 0x60 + float c_opacity; // 0x6C + float c_useAlphaModulateSpecular; // 0x70 + float c_alphaEdgeFadeExponent; // 0x74 + float c_alphaEdgeFadeInner; // 0x78 + float c_alphaEdgeFadeOuter; // 0x7C + float c_useAlphaModulateEmissive; // 0x80 + float c_emissiveEdgeFadeExponent; // 0x84 + float c_emissiveEdgeFadeInner; // 0x88 + float c_emissiveEdgeFadeOuter; // 0x8C + float c_alphaDistanceFadeScale; // 0x90 + float c_alphaDistanceFadeBias; // 0x94 + float c_alphaTestReference; // 0x98 + float c_aspectRatioMulV; // 0x9C + float c_emissiveTint[3]; // 0xA0 + float c_shadowBias; // 0xAC + float c_tsaaDepthAlphaThreshold; // 0xB0 + float c_tsaaMotionAlphaThreshold; // 0xB4 + float c_tsaaMotionAlphaRamp; // 0xB8 + uint32_t c_tsaaResponsiveFlag; // 0xBC + float c_dofOpacityLuminanceScale; // 0xC0 + float c_glitchStrength; // 0xC4 + float c_padding[2]; // 0xC8 + float c_perfGloss; // 0xD0 + float c_perfSpecColor[3]; // 0xD4 +}; + +class CMaterialGlue; + +class CMaterialGlue_short +{ +public: + uint64_t guid; + const char* name; + uint64_t* surfaceProps[2]; + CMaterialGlue* DepthShadow_ref; + CMaterialGlue* DepthPrepass_ref; + CMaterialGlue* DepthVSM_ref; + CMaterialGlue* Colpass_ref; + uint8_t gap_50[64]; + ShaderGlue* shaderSet; + RpakTextureHeader** textureHandles; + RpakTextureHeader** streamingTextures; + int16_t streamingTextureCount; + uint8_t samplersIndices[4]; + int16_t unknown; + uint8_t gap_B0[12]; + uint16_t unknownWord[2]; + uint32_t flags; + uint32_t flags2; + uint16_t width; + uint16_t height; + uint8_t gap_CC[2]; + uint16_t word_CE; + void** pointer_D0; + CBufUberStatic* cbufUberStatic; + ID3D11Buffer* buffer; + uint32_t* atlasBufferIndices; + uint32_t dword_F0; + uint8_t gap_F4[12]; +}; class CMaterialGlue { public: void* m_pVFTable; char m_unk[8]; - - uint64_t m_GUID; - - const char* m_pszName; - const char* m_pszSurfaceProp; - const char* m_pszSurfaceProp2; - - CMaterialGlue* m_pDepthShadow; - CMaterialGlue* m_pDepthPrepass; - CMaterialGlue* m_pDepthVSM; - CMaterialGlue* m_pColPass; - - char gap_50[64]; - - CShaderGlue* m_pShaderGlue; - void** m_pTextureHandles; - void** m_pStreamingTextures; - int16_t m_iStreamingTextureCount; - uint8_t m_iSamplersIndices[4]; - int16_t m_iUnknown0; - char gap_B0[12]; - - int16_t aword_BC[2]; - int32_t flags2; - int32_t flags3; - int16_t m_iWidth; - int16_t m_iHeight; - int16_t m_iUnknown1; - int16_t m_iUnknown2; - - void** m_pUnkD3D11Ptr; - void* m_pD3D11Buffer; - void* qword_E0; - void* pointer_E8; - - int32_t dword_F0; - char gap_F4[12]; + CMaterialGlue_short material; }; diff --git a/primedev/materialsystem/cshaderglue.h b/primedev/materialsystem/cshaderglue.h index 8194f1fb..85653b7d 100644 --- a/primedev/materialsystem/cshaderglue.h +++ b/primedev/materialsystem/cshaderglue.h @@ -5,3 +5,28 @@ class CShaderGlue public: void* vftable; }; + +struct ShaderGlue_inner +{ + const char* name; + uint64_t flagsMaybe; + + uint16_t resourceBindingSlot; + uint16_t textureInputCount; + int16_t shadowSamplerCount; + uint16_t unkBindingSlot; + uint16_t unkBindingCount; + + uint8_t bytes_22[6]; + + uint64_t unk3[4]; + + void* vertexShader; + void* pixelShader; +}; + +struct ShaderGlue +{ + void* vtable; + ShaderGlue_inner inner; +}; diff --git a/primedev/materialsystem/nscustomdxbuffer.cpp b/primedev/materialsystem/nscustomdxbuffer.cpp index 56dbe1ea..7269124e 100644 --- a/primedev/materialsystem/nscustomdxbuffer.cpp +++ b/primedev/materialsystem/nscustomdxbuffer.cpp @@ -6,6 +6,8 @@ #include #include #include +#include "core/filesystem/rpakfilesystem.h" +#include "cmaterialglue.h" static ID3D11DeviceContext** DeviceContext; static ID3D11Device** D3D11Device_14E8DD0; @@ -15,6 +17,12 @@ struct Ns_Constant_Buffer float data[320]; }; +struct MaterialTextureMappings +{ + + std::array slots; +}; + AUTOHOOK_INIT() static Ns_Constant_Buffer NSCustomDXBuffer; @@ -22,15 +30,48 @@ static std::mutex NSCustomDXBufferMutex; // map to later on associate guid > buffer static std::map NSCustomBuffersPerMaterial = {}; +static std::map NSMaterialTextureSlotBindings = {}; +static std::unordered_set NSRegisteredCustomBufferMaterials = {}; +static std::unordered_set NSRegisteredTextureOverrides = {}; -AUTOHOOK(SUB_511D0, materialsystem_dx11.dll + 0x511D0, __int64, __fastcall, (__int64 a1, __int64 a2, __int64 a3, __int64 a4)) +AUTOHOOK(SUB_511D0, materialsystem_dx11.dll + 0x511D0, __int64, __fastcall, (__int64 a1, __int64 a2, __int64 a3, CMaterialGlue_short* a4)) { - int64_t subResult = SUB_511D0(a1, a2, a3, a4); + CMaterialGlue_short* internal_logic_material = a4; - uint32_t glueFlags = *(uint32_t*)((uint8_t*)a4 + 176); + int64_t subResult = SUB_511D0(a1, a2, a3, internal_logic_material); + + if (!DeviceContext || !D3D11Device_14E8DD0 || !*DeviceContext || !*D3D11Device_14E8DD0) + return subResult; + + // bind textures to slots if existing + if (NSMaterialTextureSlotBindings.contains(internal_logic_material->guid)) + { + + auto& mappings = NSMaterialTextureSlotBindings[internal_logic_material->guid]; + + for (size_t slot = 0; slot < mappings.slots.size(); ++slot) + { + uint64_t textureGUID = mappings.slots[slot]; + + if (textureGUID == 0) + continue; + + __int64 texturePointer = g_pakLoadApi->GetAssetByHash(textureGUID); + if (!texturePointer) + continue; + + RpakTextureHeader* TextureHeader = (RpakTextureHeader*)texturePointer; + ID3D11ShaderResourceView* TextureSRV = TextureHeader->shaderResourceView; + + if (!TextureSRV) + continue; + + (*DeviceContext)->PSSetShaderResources(slot, 1, &TextureSRV); + } + } // bind custom buffer when flag is 0x04089901 in rpak mat - if ((glueFlags & 0x04089901) == 0x04089901) + if (NSRegisteredCustomBufferMaterials.contains(internal_logic_material->guid)) { D3D11_BUFFER_DESC desc {}; @@ -62,7 +103,7 @@ AUTOHOOK(SUB_511D0, materialsystem_dx11.dll + 0x511D0, __int64, __fastcall, (__i std::lock_guard lock(NSCustomDXBufferMutex); - memcpy(pData, &NSCustomBuffersPerMaterial[*(uint64_t*)a4], sizeof(Ns_Constant_Buffer)); + memcpy(pData, &NSCustomBuffersPerMaterial[internal_logic_material->guid], sizeof(Ns_Constant_Buffer)); (*DeviceContext)->Unmap(resource, 0); (*DeviceContext)->PSSetConstantBuffers(4, 1, &resource); @@ -86,7 +127,73 @@ bool isValidMaterialGUID(const std::string& str) return true; } -template SQRESULT NSSetCustomDXBuffer(HSQUIRRELVM sqvm) +SQRESULT NSRegisterCustomDXBufferForGUID(HSQUIRRELVM sqvm) +{ + + auto rPakMaterialGUIDString = (g_pSquirrel[ScriptContext::CLIENT]->getstring(sqvm, 1)); + uint64_t rPakMaterialGUID = std::stoull(rPakMaterialGUIDString, nullptr, 16); + + __int64 AssetFromGUID = g_pakLoadApi->GetAssetByHash(rPakMaterialGUID); + + if (!AssetFromGUID) + { + g_pSquirrel[ScriptContext::CLIENT]->raiseerror( + sqvm, fmt::format("Asset with GUID {} Doesnt Exist", rPakMaterialGUIDString).c_str()); + return SQRESULT_ERROR; + } + + // we need to add 16 to the pointer, matglueshort is matglue without the first 16 bytes. GetAssetByHash returns a pointer to the full + auto* base = reinterpret_cast(AssetFromGUID); + auto* GUIDMaterialGlue_short = reinterpret_cast(base + 16); + + if (!NSRegisteredCustomBufferMaterials.contains(GUIDMaterialGlue_short->guid)) + { + NS::log::SCRIPT_CL->info("Registered GUID: {} to use the NSCustomDXBuffer system", GUIDMaterialGlue_short->guid); + + NSRegisteredCustomBufferMaterials.insert(GUIDMaterialGlue_short->guid); + } + else + { + NS::log::SCRIPT_CL->warn( + "Attempted to register GUID: {} to the NSCustomDXBuffer system, GUID was already registered", GUIDMaterialGlue_short->guid); + } + return SQRESULT_NULL; +} + +SQRESULT NSDeregisterCustomDXBufferForGUID(HSQUIRRELVM sqvm) +{ + + auto rPakMaterialGUIDString = (g_pSquirrel[ScriptContext::CLIENT]->getstring(sqvm, 1)); + uint64_t rPakMaterialGUID = std::stoull(rPakMaterialGUIDString, nullptr, 16); + + __int64 AssetFromGUID = g_pakLoadApi->GetAssetByHash(rPakMaterialGUID); + + if (!AssetFromGUID) + { + g_pSquirrel[ScriptContext::CLIENT]->raiseerror( + sqvm, fmt::format("Asset with GUID {} Doesnt Exist", rPakMaterialGUIDString).c_str()); + return SQRESULT_ERROR; + } + + // we need to add 16 to the pointer, matglueshort is matglue without the first 16 bytes. GetAssetByHash returns a pointer to the full + auto* base = reinterpret_cast(AssetFromGUID); + auto* GUIDMaterialGlue_short = reinterpret_cast(base + 16); + + if (NSRegisteredCustomBufferMaterials.contains(GUIDMaterialGlue_short->guid)) + { + NS::log::SCRIPT_CL->info("Deregistered GUID: {} from the NSCustomDXBuffer system", GUIDMaterialGlue_short->guid); + + NSRegisteredCustomBufferMaterials.erase(GUIDMaterialGlue_short->guid); + } + else + { + NS::log::SCRIPT_CL->warn( + "Attempted to deregister GUID: {} from the NSCustomDXBuffer system, GUID was not registered", GUIDMaterialGlue_short->guid); + } + return SQRESULT_NULL; +} + +SQRESULT NSUpdateCustomDXBufferForGUID(HSQUIRRELVM sqvm) { // get the guid as a string to later conv @@ -107,7 +214,7 @@ template SQRESULT NSSetCustomDXBuffer(HSQUIRRELVM sqvm) if (!isValidMaterialGUID(guidString)) { - g_pSquirrel[ScriptContext::SERVER]->raiseerror( + g_pSquirrel[ScriptContext::CLIENT]->raiseerror( sqvm, fmt::format("Malformed Material GUID", (NSCustomBufferDataArray->_usedSlots) * 4, sizeof(Ns_Constant_Buffer)).c_str()); return SQRESULT_ERROR; } @@ -118,7 +225,7 @@ template SQRESULT NSSetCustomDXBuffer(HSQUIRRELVM sqvm) if ((NSCustomBufferDataArray->_usedSlots) * 4 > sizeof(Ns_Constant_Buffer)) { - g_pSquirrel[ScriptContext::SERVER]->raiseerror( + g_pSquirrel[ScriptContext::CLIENT]->raiseerror( sqvm, fmt::format( "Size of Squirrel array exceeds NSCustomDXBuffer size\n\nSquirrel " @@ -136,16 +243,75 @@ template SQRESULT NSSetCustomDXBuffer(HSQUIRRELVM sqvm) return SQRESULT_NULL; } +SQRESULT NSBindTextureToMaterial(HSQUIRRELVM sqvm) +{ + + auto rPakMaterialGUIDString = (g_pSquirrel[ScriptContext::CLIENT]->getstring(sqvm, 1)); + auto rPakTextureGUIDString = (g_pSquirrel[ScriptContext::CLIENT]->getstring(sqvm, 2)); + auto rPakShaderSlotBindingInt = (g_pSquirrel[ScriptContext::CLIENT]->getinteger(sqvm, 3)); + + uint64_t rPakMaterialGUID = std::stoull(rPakMaterialGUIDString, nullptr, 16); + __int64 MatAssetFromGUID = g_pakLoadApi->GetAssetByHash(rPakMaterialGUID); + + if (rPakShaderSlotBindingInt > 60) + { + g_pSquirrel[ScriptContext::CLIENT]->raiseerror(sqvm, fmt::format("TextureOverrides only support 30 custom bindings").c_str()); + return SQRESULT_ERROR; + } + + if (!MatAssetFromGUID) + { + g_pSquirrel[ScriptContext::CLIENT]->raiseerror( + sqvm, fmt::format("Material with GUID {} Doesnt Exist", rPakMaterialGUIDString).c_str()); + return SQRESULT_ERROR; + } + + auto* base = reinterpret_cast(MatAssetFromGUID); + auto* GUIDMaterialGlue_short = reinterpret_cast(base + 16); + + if (!rPakTextureGUIDString == 0) + { + uint64_t rPakTextureGUID = std::stoull(rPakTextureGUIDString, nullptr, 16); + __int64 TexAssetFromGUID = g_pakLoadApi->GetAssetByHash(rPakTextureGUID); + + if (!TexAssetFromGUID) + { + g_pSquirrel[ScriptContext::CLIENT]->raiseerror( + sqvm, fmt::format("Texture with GUID {} Doesnt Exist", rPakTextureGUIDString).c_str()); + return SQRESULT_ERROR; + } + NSMaterialTextureSlotBindings[GUIDMaterialGlue_short->guid].slots[rPakShaderSlotBindingInt] = rPakTextureGUID; + } + else + NSMaterialTextureSlotBindings[GUIDMaterialGlue_short->guid].slots[rPakShaderSlotBindingInt] = 0; + + return SQRESULT_NULL; +} + ON_DLL_LOAD_CLIENT("materialsystem_dx11.dll", SUB_511D0, (CModule module)) { AUTOHOOK_DISPATCH_MODULE(materialsystem_dx11.dll) DeviceContext = module.Offset(0x14E8DD8).RCast(); D3D11Device_14E8DD0 = module.Offset(0x14E8DD0).RCast(); + g_pSquirrel[ScriptContext::CLIENT]->AddFuncRegistration( "void", - "NSSetCustomDXBuffer", + "NSUpdateCustomDXBufferForGUID", "string rPakMaterialGUID array NSCustomBufferPerMaterialData", "", - NSSetCustomDXBuffer); + NSUpdateCustomDXBufferForGUID); + + g_pSquirrel[ScriptContext::CLIENT]->AddFuncRegistration( + "void", "NSRegisterCustomDXBufferForGUID", "string rPakMaterialGUID", "", NSRegisterCustomDXBufferForGUID); + + g_pSquirrel[ScriptContext::CLIENT]->AddFuncRegistration( + "void", "NSDeregisterCustomDXBufferForGUID", "string rPakMaterialGUID", "", NSDeregisterCustomDXBufferForGUID); + + g_pSquirrel[ScriptContext::CLIENT]->AddFuncRegistration( + "void", + "NSBindTextureToMaterial", + "string rPakMaterialGUID string rPakTextureGUID int shaderBindingSlot", + "", + NSBindTextureToMaterial); } From 0075d671d1b07d0e9e5a4c2ac724a61c044e2646 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Raes?= Date: Sat, 23 May 2026 15:29:31 +0200 Subject: [PATCH 06/17] build(ci): use actions/checkout@v4 in release workflow --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 831b192e..120b57b6 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -15,7 +15,7 @@ jobs: runs-on: windows-2022 steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: submodules: 'true' - name: Setup msvc From 47f0fa43b6f822c7ce24d2ff0618205db2f559eb Mon Sep 17 00:00:00 2001 From: cat_or_not <41955154+catornot@users.noreply.github.com> Date: Mon, 1 Jun 2026 19:18:06 -0400 Subject: [PATCH 07/17] Cache nix builds on main (#921) * cache nix artifacts to cache server instead of uploading them * Revert "cache nix artifacts to cache server instead of uploading them" This reverts commit d9ffaeda9299b92f766ad82b86e0b5c67adf4aa6. * Revert "Revert "cache nix artifacts to cache server instead of uploading them"" This reverts commit 707b4165353901ca162a0ee7d216827757e3c337. * only run on main the motivation for this is to not completly fill my cache server instantly (which only has 15gb) * push the store path instead of the result path --- .github/workflows/ci.yml | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 56ae5eb6..72e9de55 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -96,17 +96,12 @@ jobs: - name: Build run: nix build - - name: Extract Short Commit Hash - id: extract - shell: bash - run: echo commit=$(git rev-parse --short HEAD) >> $GITHUB_OUTPUT - - - name: Upload Build Artifact - uses: actions/upload-artifact@v4 - with: - name: NorthstarLauncher-NIX-${{ steps.extract.outputs.commit }} - path: | - result/ + - name: Cache this Build + continue-on-error: true + if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }} + run: | + nix run nixpkgs#attic-client -- login northstar https://attic.catornot.net ${{ secrets.ATTIC_CACHE_TOKEN }} + nix run nixpkgs#attic-client -- push northstar $(nix build --print-out-paths) format-check-cmake-files: runs-on: ubuntu-latest From f05943806ff177766d0957a5434a9a188a48e26f Mon Sep 17 00:00:00 2001 From: Jack <66967891+ASpoonPlaysGames@users.noreply.github.com> Date: Tue, 2 Jun 2026 18:48:19 +0100 Subject: [PATCH 08/17] Fix `weapon_reparse` not invalidating compiled weapon files (#922) * fix weapon_reparse not invalidating compiled weapon files * remove unused include --- primedev/Northstar.cmake | 1 + primedev/shared/weapon_reparse.cpp | 37 ++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 primedev/shared/weapon_reparse.cpp diff --git a/primedev/Northstar.cmake b/primedev/Northstar.cmake index 508375c0..e7672067 100644 --- a/primedev/Northstar.cmake +++ b/primedev/Northstar.cmake @@ -152,6 +152,7 @@ add_library( "shared/misccommands.h" "shared/playlist.cpp" "shared/playlist.h" + "shared/weapon_reparse.cpp" "squirrel/squirrel.cpp" "squirrel/squirrel.h" "squirrel/squirrelautobind.cpp" diff --git a/primedev/shared/weapon_reparse.cpp b/primedev/shared/weapon_reparse.cpp new file mode 100644 index 00000000..ae1cb300 --- /dev/null +++ b/primedev/shared/weapon_reparse.cpp @@ -0,0 +1,37 @@ +#include "mods/modmanager.h" +#include +#include + +static void RemoveCompiledWeaponScripts() +{ + // avoid clearing literally everything, just weapons + auto& files = g_pModManager->m_CompiledFiles; + std::erase_if( + files, [](const std::string& val) { return val.starts_with("scripts/weapons/") || val.starts_with("scripts\\weapons\\"); }); +} + +static void(__fastcall* o_pConCommand_weapon_reparse_server)(const CCommand& arg) = nullptr; +static void __fastcall h_ConCommand_weapon_reparse_server(const CCommand& arg) +{ + RemoveCompiledWeaponScripts(); + o_pConCommand_weapon_reparse_server(arg); +} + +static void(__fastcall* o_pConCommand_weapon_reparse)(const CCommand& arg) = nullptr; +static void __fastcall h_ConCommand_weapon_reparse(const CCommand& arg) +{ + RemoveCompiledWeaponScripts(); + o_pConCommand_weapon_reparse(arg); +} + +ON_DLL_LOAD("server.dll", WeaponReparse_Server, (CModule module)) +{ + o_pConCommand_weapon_reparse_server = module.Offset(0x6D2B70).RCast(); + HookAttach(&(PVOID&)o_pConCommand_weapon_reparse_server, (PVOID)h_ConCommand_weapon_reparse_server); +} + +ON_DLL_LOAD("client.dll", WeaponReparse_Client, (CModule module)) +{ + o_pConCommand_weapon_reparse = module.Offset(0x3D4930).RCast(); + HookAttach(&(PVOID&)o_pConCommand_weapon_reparse, (PVOID)h_ConCommand_weapon_reparse); +} From 9430cef24007a9354b1eea6b53a6f3e148bf8edd Mon Sep 17 00:00:00 2001 From: Allusive <154700875+AllusiveWheat@users.noreply.github.com> Date: Tue, 2 Jun 2026 13:31:38 -0700 Subject: [PATCH 09/17] Allows for custom gamemode text for ffa rui (#924) * add the ability to replace the ffa text in for custom gamemodes * fmt * maybe make it work for clang * fmt * forgot this * more stuff * Delete clang-format.exe * give vars good names --- primedev/Northstar.cmake | 2 + primedev/rtech/rui.cpp | 175 +++++++++++++++++++++++++++++++++++++++ primedev/rtech/rui.h | 77 +++++++++++++++++ 3 files changed, 254 insertions(+) create mode 100644 primedev/rtech/rui.cpp create mode 100644 primedev/rtech/rui.h diff --git a/primedev/Northstar.cmake b/primedev/Northstar.cmake index e7672067..a9e09315 100644 --- a/primedev/Northstar.cmake +++ b/primedev/Northstar.cmake @@ -160,6 +160,8 @@ add_library( "squirrel/squirrelclasstypes.h" "rtech/pakfile.h" "rtech/pakfile.cpp" + "rtech/rui.h" + "rtech/rui.cpp" "util/printcommands.cpp" "util/printcommands.h" "util/printmaps.cpp" diff --git a/primedev/rtech/rui.cpp b/primedev/rtech/rui.cpp new file mode 100644 index 00000000..203738af --- /dev/null +++ b/primedev/rtech/rui.cpp @@ -0,0 +1,175 @@ +#include "rui.h" + +struct gamestate_info_ffa_struct +{ + BYTE gap0[68]; + float endTime; + const char* statusText; + float leftTeamScore; + float rightTeamScore; + DWORD maxTeamScore; + const char* factionImage; + const char* friendlyPlayerCardImage; + const char* enemyPlayerCardImage; + BYTE gap78[64]; + DWORD whiteAssetHandle; + DWORD playerCardImageAssetHandle; + // struct needs to be 8 byte aligned for these + uint64_t owordC0[2]; + uint64_t owordD0[2]; + uint64_t topColor[2]; + uint64_t bottomColor[2]; + const char* formattedTimeString; + const char* gameModeName; + DWORD otherPlayerCardAssetHandle; + DWORD leftFillAsset; + DWORD rightFillAsset; + float leftTeamScoreDiff; + float otherTeamScoreDiff; + DWORD factionImageHandle; + const char* scoreString; + const char* rightTeamScoreString; +}; + +using gamestate_info_ffa_t = void(__fastcall*)(RuiFunctions_t*, RuiGlobals*, RuiInstance*, gamestate_info_ffa_struct*); +gamestate_info_ffa_t o_gamestate_info_ffa = nullptr; + +void h_gamestate_info_ffa(RuiFunctions_t* funcs, RuiGlobals* globals, RuiInstance* inst, gamestate_info_ffa_struct* data) +{ + static __m128 xmmword_D3C20 = {25.866, 25.866f, 40.000f, 40.000f}; + static __m128 xmmword_D3C40 = {128.000f, 128.000f, 40.000f, 40.f}; + static __m128 xmmword_D3C50 = {200.000f, 200.000f, 40.000f, 40.000f}; + static __m128 xmmword_D4A00 = {1920.000f, 1920.000f, 1080.000f, 1080.000f}; + static __m128 xmmword_D40E0 = {2.000f, 2.000f, 84.000f, 84.000f}; + static __m128 xmmword_D3CE0 = {48.000f, 48.000f, 48.000f, 48.000f}; + + static __m128 enemyColor = {1.000f, 0.188f, 0.014f, 1.f}; + static __m128 friendlyColor = {0.095f, 0.309f, 0.708f, 1.f}; + + float endTime = data->endTime; + float timeLeft = endTime - globals->currentTime; + char* buffer = (char*)alloca(2048); + strcpy_s(buffer, 2048, data->statusText); + if (strcmp(buffer, "") == 0) + { + strcpy_s(buffer, 2048, "#PL_ffa"); + } + + if (timeLeft < 0.0f || endTime == -1.0e30f) + { + data->formattedTimeString = "--:--"; + } + else if (timeLeft > 30.0f) + { + data->formattedTimeString = funcs->printf(inst, "%i:%02i", (unsigned int)((int)timeLeft / 60), (unsigned int)((int)timeLeft % 60)); + } + else + { + data->formattedTimeString = funcs->printf(inst, "%05.2f", timeLeft); + } + + data->rightFillAsset = funcs->LoadAsset(inst, "rui/hud/gamestate/score_fill_right"); + assetHandle v9 = funcs->LoadAsset(inst, "rui/hud/gamestate/score_fill_right"); + bool teamScoreDiff = data->leftTeamScore < data->rightTeamScore; + data->leftFillAsset = v9; + + __m128 topColor, bottomColor; + const char* scoreString; + const char* v23; + float otherScore; + + if (teamScoreDiff) + { + assetHandle enemyPlayerCardImage_1 = funcs->LoadAsset(inst, data->enemyPlayerCardImage); + const char* friendlyPlayerCardImage = data->friendlyPlayerCardImage; + data->playerCardImageAssetHandle = enemyPlayerCardImage_1; + assetHandle v26 = funcs->LoadAsset(inst, friendlyPlayerCardImage); + data->otherPlayerCardAssetHandle = v26; + float v28 = static_cast(data->maxTeamScore); + if (v28 == 0.0f) + { + return (funcs->SetErrorWithReason)(inst, "content\\r2\\ui\\hud\\gamemode_ffa.rui (83,46): divide by zero.\n"); + } + + float rightTeamScore = data->rightTeamScore; + data->leftTeamScoreDiff = rightTeamScore / v28; + topColor = enemyColor; + bottomColor = friendlyColor; + float v30 = data->leftTeamScore / v28; + *(__m128*)data->topColor = topColor; + *(__m128*)data->bottomColor = bottomColor; + data->otherTeamScoreDiff = v30; + scoreString = funcs->printf(inst, "%.8g", rightTeamScore); + otherScore = data->leftTeamScore; + v23 = "%.8g"; + } + else + { + assetHandle v11 = funcs->LoadAsset(inst, data->friendlyPlayerCardImage); + const char* enemyPlayerCardImage = data->enemyPlayerCardImage; + data->playerCardImageAssetHandle = v11; + assetHandle enemyPlayerCardImageAssetHandle_2 = funcs->LoadAsset(inst, enemyPlayerCardImage); + data->otherPlayerCardAssetHandle = enemyPlayerCardImageAssetHandle_2; + float maxTeamScore_1 = static_cast(data->maxTeamScore); + if (maxTeamScore_1 == 0.0f) + { + return (funcs->SetErrorWithReason)(inst, "content\\r2\\ui\\hud\\gamemode_ffa.rui (83,46): divide by zero.\n"); + } + + float leftTeamScore_1 = data->leftTeamScore; + data->leftTeamScoreDiff = leftTeamScore_1 / maxTeamScore_1; + topColor = friendlyColor; + bottomColor = enemyColor; + float v20 = data->rightTeamScore / maxTeamScore_1; + *(__m128*)data->topColor = topColor; + *(__m128*)data->bottomColor = bottomColor; + data->otherTeamScoreDiff = v20; + scoreString = funcs->printf(inst, "%.8g", leftTeamScore_1); + otherScore = data->rightTeamScore; + v23 = "%.8g"; + } + + data->scoreString = scoreString; + const char* v31 = funcs->printf(inst, v23, otherScore); + *(__m128*)data->owordD0 = bottomColor; + *(__m128*)data->owordC0 = topColor; + data->rightTeamScoreString = v31; + data->whiteAssetHandle = funcs->LoadAsset(inst, "white"); + const char* factionImage = data->factionImage; + data->gameModeName = funcs->localize(inst, buffer); + data->factionImageHandle = funcs->LoadAsset(inst, factionImage); + + __m128* transformSizes = funcs->GetTransformSize(inst); + transformSizes[3] = (__m128)xmmword_D3C50; + funcs->executeTransform(inst, 1); + transformSizes[4] = (__m128)xmmword_D3C50; + funcs->executeTransform(inst, 2); + transformSizes[5] = (__m128)xmmword_D4A00; + transformSizes[6] = (__m128)xmmword_D40E0; + + __m128 v35; + v35 = _mm_set_ps(40.0f, 40.0f, 0.0f, 0.0f); + transformSizes[7] = (__m128)xmmword_D4A00; + transformSizes[9] = (__m128)xmmword_D3C20; + transformSizes[8] = (__m128)xmmword_D3C40; + transformSizes[10] = (__m128)xmmword_D3C20; + + v35 = (funcs->unknown_5)(inst, 3LL, 4LL); + transformSizes[11] = v35; + v35 = (funcs->unknown_5)(inst, 4LL, 5LL); + transformSizes[12] = v35; + transformSizes[13] = (funcs->GetTextSize)(inst, 42LL); + transformSizes[14] = (funcs->GetTextSize)(inst, 60LL); + transformSizes[15] = (funcs->GetTextSize)(inst, 78LL); + transformSizes[16] = (funcs->GetTextSize)(inst, 348LL); + transformSizes[17] = (funcs->GetTextSize)(inst, 366LL); + transformSizes[18] = xmmword_D3CE0; + + return (funcs->executeTransform)(inst, 0x9ELL); +} + +ON_DLL_LOAD("ui(11).dll", Rui, (CModule module)) +{ + o_gamestate_info_ffa = module.Offset(0x3E8E0).RCast(); + HookAttach(&(PVOID&)o_gamestate_info_ffa, (PVOID)h_gamestate_info_ffa); +} diff --git a/primedev/rtech/rui.h b/primedev/rtech/rui.h new file mode 100644 index 00000000..e1661191 --- /dev/null +++ b/primedev/rtech/rui.h @@ -0,0 +1,77 @@ +#pragma once + +#include +#include +#include +#include + +typedef unsigned int assetHandle; + +struct RuiGlobals +{ + BYTE gap_0[60]; + float localPlayerPos[3]; + BYTE gap_48[72]; + uint64_t qword_90; + float currentTime; + BYTE gap_9C[4]; + int dword_A0; + int isConsole; + int dword_A8; + int dword_AC; + int dword_B0; + int dword_B4; + float float_B8; + float float_BC; + float float_C0; + int dword_C4; + float float_C8; + float float_CC; + DWORD dword_D0; + DWORD dword_D4; + DWORD dword_D8; + DWORD dword_DC; + float float_E0; + DWORD dword_E4; +}; + +struct RuiInstance +{ + void* header; // original type RuiHeader + float canvasWidth; + float canvasHeight; + float canvasWidthRatio; + float canvasHeightRatio; + void* v1; // original type struct_v1 + __int64 createTimeStamp; + BYTE byte_28; + BYTE error; + BYTE gap_2A[14]; + void* pvoid_38; // original type ruiUnknown2 + char dataValues[1]; +}; + +struct RuiFunctions_t +{ + void(__fastcall* setNoRender)(RuiInstance* a1); + void(__fastcall* setError)(RuiInstance* a1); + void(__fastcall* SetErrorWithReason)(RuiInstance* a1, const char* a2); + __m128*(__fastcall* GetTransformSize)(RuiInstance* a1); + __m128(__fastcall* GetTextSize)(RuiInstance* a1, unsigned int a2); + __m128(__fastcall* unknown_5)(RuiInstance* a1, int a2, int a3); + void(__fastcall* executeTransform)(RuiInstance* a1, int a2); + const char* (*printf)(RuiInstance* a1, const char* format, ...); + const char* (*localize)(RuiInstance* a1, const char* format, ...); + const char*(__fastcall* toUpper)(RuiInstance* a1, const char* a2); + __m128(__fastcall* unknown_10)(__m128* a1); + __m128(__fastcall* unknown_11)(float a1); + float(__fastcall* randomFloat)(RuiInstance* a1); + __int64(__fastcall* unknown_13)(__int64 a1, __int64 a2, __m128* a3); + __m128(__fastcall* unknown_14)(__int64 a1); + int(__fastcall* LoadAsset)(RuiInstance* a1, const char* assetPath); + const char*(__fastcall* unknown_16)(RuiInstance* a1, int a2); + float(__fastcall* unknown_17)(RuiInstance* a1, __int64 a2, float a3); + __m128(__fastcall* unknown_18)(__int64 a1, __int64 a2, float a3); + __m128(__fastcall* unknown_19)(__int64 a1, __int64 a2, __int64 a3); + __m128(__fastcall* unknown_20)(__int64 a1, __int64 a2, __int64 a3); +}; From 48f35600771b1631aa7980642816e916cbb2213f Mon Sep 17 00:00:00 2001 From: HuiZhiYin <639821869@qq.com> Date: Fri, 3 Jul 2026 09:24:10 +0800 Subject: [PATCH 10/17] Add callback for client chat messages (#920) --- primedev/client/chatcommand.cpp | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/primedev/client/chatcommand.cpp b/primedev/client/chatcommand.cpp index 9cf34e43..0ef6652b 100644 --- a/primedev/client/chatcommand.cpp +++ b/primedev/client/chatcommand.cpp @@ -1,21 +1,42 @@ #include "core/convar/convar.h" #include "core/convar/concommand.h" #include "localchatwriter.h" +#include "squirrel/squirrel.h" // note: isIngameChat is an int64 because the whole register the arg is stored in needs to be 0'd out to work // if isIngameChat is false, we use network chat instead -void(__fastcall* ClientSayText)(void* a1, const char* message, uint64_t isIngameChat, bool isTeamChat); +static void(__fastcall* o_ClientSayText)(void* a1, const char* message, uint64_t isIngameChat, bool isTeamChat) = nullptr; + +static void __fastcall h_ClientSayText(void* a1, const char* message, uint64_t isIngameChat, bool isTeamChat) +{ + SQRESULT result = g_pSquirrel[ScriptContext::CLIENT]->Call("NS_PreSendMessage", message, (bool)isIngameChat, (bool)isTeamChat); + if (result == SQRESULT_ERROR) + { + o_ClientSayText(a1, message, isIngameChat, isTeamChat); + } +} + +ADD_SQFUNC("void", NSSendMessage, "string message, bool isIngame, bool isTeam", "", ScriptContext::CLIENT) +{ + const char* message = g_pSquirrel[ScriptContext::CLIENT]->getstring(sqvm, 1); + bool isIngame = g_pSquirrel[ScriptContext::CLIENT]->getbool(sqvm, 2); + bool isTeam = g_pSquirrel[ScriptContext::CLIENT]->getbool(sqvm, 3); + + o_ClientSayText(nullptr, message, isIngame, isTeam); + + return SQRESULT_NULL; +} void ConCommand_say(const CCommand& args) { if (args.ArgC() >= 2) - ClientSayText(nullptr, args.ArgS(), true, false); + o_ClientSayText(nullptr, args.ArgS(), true, false); } void ConCommand_say_team(const CCommand& args) { if (args.ArgC() >= 2) - ClientSayText(nullptr, args.ArgS(), true, true); + o_ClientSayText(nullptr, args.ArgS(), true, true); } void ConCommand_log(const CCommand& args) @@ -28,8 +49,9 @@ void ConCommand_log(const CCommand& args) ON_DLL_LOAD_CLIENT_RELIESON("engine.dll", ClientChatCommand, ConCommand, (CModule module)) { - ClientSayText = + o_ClientSayText = module.Offset(0x54780).RCast(); + HookAttach(&(PVOID&)o_ClientSayText, (PVOID)h_ClientSayText); RegisterConCommand("say", ConCommand_say, "Enters a message in public chat", FCVAR_CLIENTDLL); RegisterConCommand("say_team", ConCommand_say_team, "Enters a message in team chat", FCVAR_CLIENTDLL); RegisterConCommand("log", ConCommand_log, "Log a message to the local chat window", FCVAR_CLIENTDLL); From 329e8f667f43caffccb0b34ccbbe746494a46453 Mon Sep 17 00:00:00 2001 From: LightBlueCube <115393812+LightBlueCube@users.noreply.github.com> Date: Wed, 5 Aug 2026 11:38:03 +0800 Subject: [PATCH 11/17] -noshaderapi and -nowindow (#926) * -noshaderapi * fmt --------- Co-authored-by: catornot <41955154+catornot@users.noreply.github.com> --- primedev/dedicated/dedicated.cpp | 22 ++++++ .../dedicated/dedicatedmaterialsystem.cpp | 79 +++++++++++++++++++ primedev/primelauncher/main.cpp | 14 ++++ 3 files changed, 115 insertions(+) diff --git a/primedev/dedicated/dedicated.cpp b/primedev/dedicated/dedicated.cpp index 8b0604fc..1dfac971 100644 --- a/primedev/dedicated/dedicated.cpp +++ b/primedev/dedicated/dedicated.cpp @@ -150,6 +150,28 @@ ON_DLL_LOAD_DEDI_RELIESON("engine.dll", DedicatedServer, ServerPresence, (CModul // nop the call to it module.Offset(0x156A63).NOP(5); + if (CommandLine()->CheckParm("-noshaderapi")) + { + // Likely CL_ClearState: clears the client map/model state. + // Preserve all software-side cleanup, but skip the render-context reset and release because the null MaterialSystem has no context. + module.Offset(0x72B9A).NOP(9); + module.Offset(0x72BCE).NOP(6); + module.Offset(0x72BDC).Patch("C3 90 90 90"); + + // Called by Mod_LoadCubemapSamples to select the map cubemap or engine/defaultcubemap. + // Keep the texture reference and BSP model metadata, but skip BindLocalCubemap and the context release because the context is null. + module.Offset(0xC8404).NOP(9); + module.Offset(0xC8414).NOP(6); + module.Offset(0xC842E).Patch("C3 90 90 90"); + } + + if (CommandLine()->CheckParm("-nowindow")) + { + // CVideoMode_Common::CreateGameWindow: skip creating and binding the Win32 window and skip IMaterialSystem::SetMode. + // Resume at the software-side datatable and LCD screen effect RPak type registrations, then return success. + module.Offset(0x1CD0ED).Patch("E9 70 00 00 00"); + } + // runframeserver // nop some access violations module.Offset(0x159819).NOP(17); diff --git a/primedev/dedicated/dedicatedmaterialsystem.cpp b/primedev/dedicated/dedicatedmaterialsystem.cpp index f74cbfe3..b45ef89a 100644 --- a/primedev/dedicated/dedicatedmaterialsystem.cpp +++ b/primedev/dedicated/dedicatedmaterialsystem.cpp @@ -41,6 +41,85 @@ ON_DLL_LOAD_DEDI("materialsystem_dx11.dll", DedicatedServerMaterialSystem, (CMod o_pD3D11CreateDevice = module.Offset(0xD9A0E).RCast(); HookAttach(&(PVOID&)o_pD3D11CreateDevice, (PVOID)h_D3D11CreateDevice); + if (CommandLine()->CheckParm("-noshaderapi")) + { + // Initializes the texture/sampler cache, default bindings, and HBAO context. + // Keep the software-side resource tables, but skip their D3D-backed initialization. + module.Offset(0x29590).Patch("C3 90 90 90 90"); + + // Initializes the transient vertex/index streaming-buffer pools. + // Keep the surrounding ShaderAPI state initialization, but do not allocate or map D3D buffers. + module.Offset(0x19BE0).Patch("C3 90 90 90 90"); + + // Initializes GPU query pools and renderer-owned scratch textures/buffers. + // These resources have no software consumers on a dedicated server and require a D3D device. + module.Offset(0x2C000).Patch("C3 90 90 90 90"); + + // Initializes the shader-set global constant buffers and sampler-state table. + // Shader-set RPak registration remains active; only its global D3D resources are omitted. + module.Offset(0x505D0).Patch("C3 90 90 90 90"); + + // RPak "txtr" asset load callback. + // Parse and register the texture metadata, then skip D3D texture and shader-resource-view creation. + module.Offset(0x2B28).Patch("E9 5A 02 00 00"); + + // RPak "matl" asset constructor callback. + // Construct and register the CMaterialGlue asset without its D3D constant buffer. + module.Offset(0x50AD4).Patch("EB 48"); + + // RPak "shdr" asset load callback for pixel, vertex, geometry, and compute shaders. + // Keep the shader assets registered without creating their D3D shader objects. + module.Offset(0x2850).Patch("C3 90 90 90 90"); + + // These three functions create blend, depth-stencil, and rasterizer states respectively. + // Preserve the shader-set state caches while returning null D3D handles for these GPU-only objects. + module.Offset(0x33350).Patch("33 C0 C3 90 90 90 90 90 90"); + module.Offset(0x33430).Patch("33 C0 C3 90"); + module.Offset(0x33520).Patch("33 C0 C3 90"); + + // Decompresses dynamic .vcs bytecode and creates the requested D3D shader variants. + // Treat the bytecode as loaded successfully because no caller on the dedicated server consumes the D3D objects. + module.Offset(0x30D00).Patch("B8 01 00 00 00 C3 90"); + + // Maps and updates the two global shader-set constant buffers. + // Skip these uploads because the shader-set resource initializer deliberately leaves both buffers uncreated. + module.Offset(0x50BF0).Patch("C3 90 90"); + + // These three functions are the 1D, 2D, and 3D runtime texture hardware constructors. + // Keep the caller-created texture IDs and metadata without creating D3D textures or views. + module.Offset(0x274C0).Patch("C3 90 90 90 90"); + module.Offset(0x277C0).Patch("C3 90 90 90 90"); + module.Offset(0x28020).Patch("C3 90 90"); + + // Rebuilds and binds the GPU buffer containing lightmap-page data. + // Preserve the CPU lightmap tables maintained by its caller, but skip creation and binding of this GPU-only buffer. + module.Offset(0x22150).Patch("C3 90 90 90 90"); + + // Tests the active device feature level against D3D_FEATURE_LEVEL_10_0. + // Report the low-capability path without querying the null D3D device. + module.Offset(0x11E80).Patch("B0 01 C3 90"); + + // Likely the ShaderAPI/ShaderDevice SetMode path from Source SDK. + // Keep window/mode bookkeeping and interface setup, but skip swap-chain and device-resource initialization. + module.Offset(0x16CC5).Patch("E9 0C 01 00 00 90 90 90 90 90 90"); + + // Likely InitClientRenderTargets: creates the water, camera, shadow, and frame render targets. + // Dedicated servers do not need the named render-target set or its render-context bindings. + module.Offset(0x95EF0).Patch("C3 90 90 90 90"); + + // Likely CMaterialSystem::CreateStandardTextures: creates black, white, flat-normal, and debug textures. + // Leave this standard/debug texture set uninitialized on a null device; do not set its initialized flag or run shutdown releases. + module.Offset(0x594B0).Patch("C3 90 90"); + + // Likely the ShaderAPI state-cache shutdown/reset path. + // Skip its three hardware-state unbinds on the null ShaderAPI interface, then retain all CPU cache clearing and guarded releases. + module.Offset(0x33C3A).Patch("EB 3D 90 90 90 90 90"); + + // Shuts down the transient vertex/index streaming-buffer pools omitted above. + // None of its GPU resources or backing containers were constructed, so its unguarded releases must also be omitted. + module.Offset(0x1A1B0).Patch("C3 90 90 90 90"); + } + // CMaterialSystem::FindMaterial // make the game always use the error material module.Offset(0x5F0F1).Patch("E9 34 03 00"); diff --git a/primedev/primelauncher/main.cpp b/primedev/primelauncher/main.cpp index 96c96c04..54676faf 100644 --- a/primedev/primelauncher/main.cpp +++ b/primedev/primelauncher/main.cpp @@ -364,14 +364,28 @@ int main(int argc, char* argv[]) bool noOriginStartup = false; bool dedicated = false; bool nostubs = false; + bool noWindow = false; + bool noShaderApi = false; for (int i = 0; i < argc; i++) + { if (!strcmp(argv[i], "-noOriginStartup")) noOriginStartup = true; else if (!strcmp(argv[i], "-dedicated")) // also checked by Northstar.dll dedicated = true; else if (!strcmp(argv[i], "-nostubs")) nostubs = true; + else if (!strcmp(argv[i], "-nowindow")) + noWindow = true; + else if (!strcmp(argv[i], "-noshaderapi")) + noShaderApi = true; + } + + if (noWindow && (!dedicated || !noShaderApi)) + { + std::cerr << "[*] ERROR: -nowindow requires -dedicated and -noshaderapi" << std::endl; + return 1; + } if (!noOriginStartup && !dedicated) { From 4df8857814dd683147f1cc5fdae0b3b419a7f1cf Mon Sep 17 00:00:00 2001 From: pg9182 <96569817+pg9182@users.noreply.github.com> Date: Tue, 4 Aug 2026 23:49:49 -0400 Subject: [PATCH 12/17] Fix remove_server (#894) * Fix remove_server * me lazy --- primedev/masterserver/masterserver.cpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/primedev/masterserver/masterserver.cpp b/primedev/masterserver/masterserver.cpp index 3e423157..edd7befc 100644 --- a/primedev/masterserver/masterserver.cpp +++ b/primedev/masterserver/masterserver.cpp @@ -1062,11 +1062,14 @@ void MasterServerPresenceReporter::DestroyPresence(const ServerPresence* pServer return; } + auto url = + fmt::format("{}/server/remove_server?id={}", Cvar_ns_masterserver_hostname->GetString(), g_pMasterServerManager->m_sOwnServerId); + // Not bothering with better thread safety in this case since DestroyPresence() is called when the game is shutting down. *g_pMasterServerManager->m_sOwnServerId = 0; std::thread requestThread( - [this] + [this, url] { CURL* curl = curl_easy_init(); SetCommonHttpClientOptions(curl); @@ -1075,12 +1078,7 @@ void MasterServerPresenceReporter::DestroyPresence(const ServerPresence* pServer curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE"); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlWriteToStringBufferCallback); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer); - curl_easy_setopt( - curl, - CURLOPT_URL, - fmt::format( - "{}/server/remove_server?id={}", Cvar_ns_masterserver_hostname->GetString(), g_pMasterServerManager->m_sOwnServerId) - .c_str()); + curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); CURLcode result = curl_easy_perform(curl); curl_easy_cleanup(curl); From edbd89f636383cbac4f03e694965684cc325b6e0 Mon Sep 17 00:00:00 2001 From: cat_or_not <41955154+catornot@users.noreply.github.com> Date: Thu, 6 Aug 2026 03:18:04 -0400 Subject: [PATCH 13/17] Patch idlekick (#927) * patch idlekick * remove empty header --- primedev/Northstar.cmake | 1 + primedev/server/idlekick.cpp | 39 ++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 primedev/server/idlekick.cpp diff --git a/primedev/Northstar.cmake b/primedev/Northstar.cmake index a9e09315..01100776 100644 --- a/primedev/Northstar.cmake +++ b/primedev/Northstar.cmake @@ -139,6 +139,7 @@ add_library( "server/servernethooks.cpp" "server/serverpresence.cpp" "server/serverpresence.h" + "server/idlekick.cpp" "shared/exploit_fixes/exploitfixes.cpp" "shared/exploit_fixes/exploitfixes_lzss.cpp" "shared/exploit_fixes/exploitfixes_utf8parser.cpp" diff --git a/primedev/server/idlekick.cpp b/primedev/server/idlekick.cpp new file mode 100644 index 00000000..e4a6176f --- /dev/null +++ b/primedev/server/idlekick.cpp @@ -0,0 +1,39 @@ +#include "core/convar/convar.h" +#include "dedicated/dedicated.h" +#include "silver-bun/module.h" + +ConVar* Cvar_idleKickLocal_enable; + +ON_DLL_LOAD("server.dll", IdleKick, (CModule module)) +{ + // Jump over the check for match_useMatchmaking in the function that handles idling + module.Offset(0x157e68).Patch("EB 17 90 90 90 90 90 90 90 90"); + + // Skip the first player (local player) in the idle kick function + if (!IsDedicatedServer()) + CModule("server.dll").Offset(0x157ea6).Patch("BF 02"); + + Cvar_idleKickLocal_enable = new ConVar( + "idleKickLocal_enable", + "0", + FCVAR_GAMEDLL, + "Enables/disables whether the local player would get kicked or not; doesn't work on dedicated servers", + false, + 0, + false, + 0, + [](ConVar* cvar, const char* pOldValue, float flOldValue) + { + NOTE_UNUSED(cvar); + NOTE_UNUSED(pOldValue); + NOTE_UNUSED(flOldValue); + if (IsDedicatedServer()) + return; + + // Toggles if the first player would get skipped in the idle kick function + if (Cvar_idleKickLocal_enable->GetBool()) + CModule("server.dll").Offset(0x157ea6).Patch("BF 01"); + else + CModule("server.dll").Offset(0x157ea6).Patch("BF 02"); + }); +} From e85910e9ac81d065d366f0495c1affc37d54987d Mon Sep 17 00:00:00 2001 From: cat_or_not <41955154+catornot@users.noreply.github.com> Date: Sat, 8 Aug 2026 04:26:00 -0400 Subject: [PATCH 14/17] Move `core/convar/` to `tier1/` 2 (#928) --- primedev/Northstar.cmake | 12 ++++++------ primedev/client/audio.cpp | 2 +- primedev/client/chatcommand.cpp | 4 ++-- primedev/client/clientauthhooks.cpp | 2 +- primedev/client/clientruihooks.cpp | 2 +- primedev/client/debugoverlay.cpp | 2 +- primedev/client/demofixes.cpp | 2 +- primedev/client/latencyflex.cpp | 2 +- primedev/dedicated/dedicatedlogtoclient.h | 2 +- primedev/engine/host.cpp | 2 +- primedev/logging/logging.cpp | 4 ++-- primedev/logging/loghooks.cpp | 4 ++-- primedev/logging/sourceconsole.cpp | 4 ++-- primedev/masterserver/masterserver.cpp | 2 +- primedev/masterserver/masterserver.h | 2 +- primedev/mods/modmanager.cpp | 4 ++-- primedev/mods/modmanager.h | 2 +- primedev/plugins/pluginmanager.cpp | 2 +- .../client/scriptservertoclientstringcommand.cpp | 4 ++-- primedev/scripts/scriptdatatables.cpp | 2 +- primedev/server/alltalk.cpp | 2 +- primedev/server/auth/bansystem.cpp | 2 +- primedev/server/auth/serverauthentication.cpp | 6 +++--- primedev/server/auth/serverauthentication.h | 2 +- primedev/server/buildainfile.cpp | 2 +- primedev/server/idlekick.cpp | 2 +- primedev/server/servernethooks.cpp | 2 +- primedev/server/serverpresence.cpp | 2 +- primedev/server/serverpresence.h | 2 +- primedev/shared/exploit_fixes/exploitfixes.cpp | 2 +- primedev/shared/exploit_fixes/ns_limits.h | 2 +- primedev/shared/misccommands.cpp | 2 +- primedev/shared/playlist.cpp | 4 ++-- primedev/squirrel/squirrel.cpp | 2 +- .../{core/convar/concommand.cpp => tier1/cmd.cpp} | 2 +- primedev/{core/convar/concommand.h => tier1/cmd.h} | 0 primedev/{core/convar => tier1}/convar.cpp | 0 primedev/{core/convar => tier1}/convar.h | 2 +- primedev/{core/convar => tier1}/cvar.cpp | 2 +- primedev/{core/convar => tier1}/cvar.h | 0 primedev/util/printcommands.cpp | 6 +++--- primedev/util/printcommands.h | 2 +- primedev/util/printmaps.cpp | 4 ++-- 43 files changed, 57 insertions(+), 57 deletions(-) rename primedev/{core/convar/concommand.cpp => tier1/cmd.cpp} (99%) rename primedev/{core/convar/concommand.h => tier1/cmd.h} (100%) rename primedev/{core/convar => tier1}/convar.cpp (100%) rename primedev/{core/convar => tier1}/convar.h (99%) rename primedev/{core/convar => tier1}/cvar.cpp (96%) rename primedev/{core/convar => tier1}/cvar.h (100%) diff --git a/primedev/Northstar.cmake b/primedev/Northstar.cmake index 01100776..8163d89c 100644 --- a/primedev/Northstar.cmake +++ b/primedev/Northstar.cmake @@ -28,12 +28,12 @@ add_library( "client/rejectconnectionfixes.cpp" "config/profile.cpp" "config/profile.h" - "core/convar/concommand.cpp" - "core/convar/concommand.h" - "core/convar/convar.cpp" - "core/convar/convar.h" - "core/convar/cvar.cpp" - "core/convar/cvar.h" + "tier1/cmd.cpp" + "tier1/cmd.h" + "tier1/convar.cpp" + "tier1/convar.h" + "tier1/cvar.cpp" + "tier1/cvar.h" "core/filesystem/filesystem.cpp" "core/filesystem/filesystem.h" "core/filesystem/rpakfilesystem.cpp" diff --git a/primedev/client/audio.cpp b/primedev/client/audio.cpp index 8a491235..3c156fee 100644 --- a/primedev/client/audio.cpp +++ b/primedev/client/audio.cpp @@ -1,6 +1,6 @@ #include "audio.h" #include "dedicated/dedicated.h" -#include "core/convar/convar.h" +#include "tier1/convar.h" #include "rapidjson/error/en.h" #include diff --git a/primedev/client/chatcommand.cpp b/primedev/client/chatcommand.cpp index 0ef6652b..5824ffd8 100644 --- a/primedev/client/chatcommand.cpp +++ b/primedev/client/chatcommand.cpp @@ -1,5 +1,5 @@ -#include "core/convar/convar.h" -#include "core/convar/concommand.h" +#include "tier1/convar.h" +#include "tier1/cmd.h" #include "localchatwriter.h" #include "squirrel/squirrel.h" diff --git a/primedev/client/clientauthhooks.cpp b/primedev/client/clientauthhooks.cpp index ceb648a5..661d7f6d 100644 --- a/primedev/client/clientauthhooks.cpp +++ b/primedev/client/clientauthhooks.cpp @@ -1,5 +1,5 @@ #include "masterserver/masterserver.h" -#include "core/convar/convar.h" +#include "tier1/convar.h" #include "client/r2client.h" #include "core/vanilla.h" diff --git a/primedev/client/clientruihooks.cpp b/primedev/client/clientruihooks.cpp index e49e6f63..5c564edd 100644 --- a/primedev/client/clientruihooks.cpp +++ b/primedev/client/clientruihooks.cpp @@ -1,4 +1,4 @@ -#include "core/convar/convar.h" +#include "tier1/convar.h" ConVar* Cvar_rui_drawEnable; diff --git a/primedev/client/debugoverlay.cpp b/primedev/client/debugoverlay.cpp index 9cfc1612..cd02c52d 100644 --- a/primedev/client/debugoverlay.cpp +++ b/primedev/client/debugoverlay.cpp @@ -1,7 +1,7 @@ #include "debugoverlay.h" #include "dedicated/dedicated.h" -#include "core/convar/cvar.h" +#include "tier1/cvar.h" #include "core/math/vector.h" #include "server/ai_helper.h" diff --git a/primedev/client/demofixes.cpp b/primedev/client/demofixes.cpp index 344764ba..d9bbb1bf 100644 --- a/primedev/client/demofixes.cpp +++ b/primedev/client/demofixes.cpp @@ -1,4 +1,4 @@ -#include "core/convar/convar.h" +#include "tier1/convar.h" ON_DLL_LOAD_CLIENT("engine.dll", EngineDemoFixes, (CModule module)) { diff --git a/primedev/client/latencyflex.cpp b/primedev/client/latencyflex.cpp index be93fabd..70044d3d 100644 --- a/primedev/client/latencyflex.cpp +++ b/primedev/client/latencyflex.cpp @@ -1,4 +1,4 @@ -#include "core/convar/convar.h" +#include "tier1/convar.h" ConVar* Cvar_r_latencyflex; diff --git a/primedev/dedicated/dedicatedlogtoclient.h b/primedev/dedicated/dedicatedlogtoclient.h index 8775ea04..c1cad065 100644 --- a/primedev/dedicated/dedicatedlogtoclient.h +++ b/primedev/dedicated/dedicatedlogtoclient.h @@ -1,6 +1,6 @@ #pragma once #include "logging/logging.h" -#include "core/convar/convar.h" +#include "tier1/convar.h" class CBaseClient; diff --git a/primedev/engine/host.cpp b/primedev/engine/host.cpp index e414908b..9ce0790f 100644 --- a/primedev/engine/host.cpp +++ b/primedev/engine/host.cpp @@ -1,4 +1,4 @@ -#include "core/convar/convar.h" +#include "tier1/convar.h" #include "mods/modmanager.h" #include "util/printcommands.h" #include "util/printmaps.h" diff --git a/primedev/logging/logging.cpp b/primedev/logging/logging.cpp index 6fa76b11..0568822f 100644 --- a/primedev/logging/logging.cpp +++ b/primedev/logging/logging.cpp @@ -1,6 +1,6 @@ #include "logging.h" -#include "core/convar/convar.h" -#include "core/convar/concommand.h" +#include "tier1/convar.h" +#include "tier1/cmd.h" #include "config/profile.h" #include "core/tier0.h" #include "util/version.h" diff --git a/primedev/logging/loghooks.cpp b/primedev/logging/loghooks.cpp index 51b4c241..4567ef7b 100644 --- a/primedev/logging/loghooks.cpp +++ b/primedev/logging/loghooks.cpp @@ -1,7 +1,7 @@ #include "logging.h" #include "loghooks.h" -#include "core/convar/convar.h" -#include "core/convar/concommand.h" +#include "tier1/convar.h" +#include "tier1/cmd.h" #include "core/math/bitbuf.h" #include "config/profile.h" #include "core/tier0.h" diff --git a/primedev/logging/sourceconsole.cpp b/primedev/logging/sourceconsole.cpp index c9063d19..6d9cd0ad 100644 --- a/primedev/logging/sourceconsole.cpp +++ b/primedev/logging/sourceconsole.cpp @@ -1,7 +1,7 @@ -#include "core/convar/convar.h" +#include "tier1/convar.h" #include "sourceconsole.h" #include "core/tier1.h" -#include "core/convar/concommand.h" +#include "tier1/cmd.h" #include "util/printcommands.h" CGameConsole* g_pGameConsole; diff --git a/primedev/masterserver/masterserver.cpp b/primedev/masterserver/masterserver.cpp index edd7befc..9d46a267 100644 --- a/primedev/masterserver/masterserver.cpp +++ b/primedev/masterserver/masterserver.cpp @@ -1,5 +1,5 @@ #include "masterserver/masterserver.h" -#include "core/convar/concommand.h" +#include "tier1/cmd.h" #include "shared/playlist.h" #include "server/auth/serverauthentication.h" #include "core/tier0.h" diff --git a/primedev/masterserver/masterserver.h b/primedev/masterserver/masterserver.h index 570db619..b3921237 100644 --- a/primedev/masterserver/masterserver.h +++ b/primedev/masterserver/masterserver.h @@ -1,6 +1,6 @@ #pragma once -#include "core/convar/convar.h" +#include "tier1/convar.h" #include "server/serverpresence.h" #include #include diff --git a/primedev/mods/modmanager.cpp b/primedev/mods/modmanager.cpp index c674f6b2..8d53203d 100644 --- a/primedev/mods/modmanager.cpp +++ b/primedev/mods/modmanager.cpp @@ -1,6 +1,6 @@ #include "modmanager.h" -#include "core/convar/convar.h" -#include "core/convar/concommand.h" +#include "tier1/convar.h" +#include "tier1/cmd.h" #include "client/audio.h" #include "masterserver/masterserver.h" #include "core/filesystem/filesystem.h" diff --git a/primedev/mods/modmanager.h b/primedev/mods/modmanager.h index 61e87691..58e07cdb 100644 --- a/primedev/mods/modmanager.h +++ b/primedev/mods/modmanager.h @@ -1,5 +1,5 @@ #pragma once -#include "core/convar/convar.h" +#include "tier1/convar.h" #include "core/memalloc.h" #include "squirrel/squirrel.h" diff --git a/primedev/plugins/pluginmanager.cpp b/primedev/plugins/pluginmanager.cpp index 7992efe2..2bcde61e 100644 --- a/primedev/plugins/pluginmanager.cpp +++ b/primedev/plugins/pluginmanager.cpp @@ -4,7 +4,7 @@ #include #include "plugins.h" #include "config/profile.h" -#include "core/convar/concommand.h" +#include "tier1/cmd.h" namespace fs = std::filesystem; diff --git a/primedev/scripts/client/scriptservertoclientstringcommand.cpp b/primedev/scripts/client/scriptservertoclientstringcommand.cpp index 66472763..97a66626 100644 --- a/primedev/scripts/client/scriptservertoclientstringcommand.cpp +++ b/primedev/scripts/client/scriptservertoclientstringcommand.cpp @@ -1,6 +1,6 @@ #include "squirrel/squirrel.h" -#include "core/convar/convar.h" -#include "core/convar/concommand.h" +#include "tier1/convar.h" +#include "tier1/cmd.h" void ConCommand_ns_script_servertoclientstringcommand(const CCommand& arg) { diff --git a/primedev/scripts/scriptdatatables.cpp b/primedev/scripts/scriptdatatables.cpp index a680c223..e4d3d53e 100644 --- a/primedev/scripts/scriptdatatables.cpp +++ b/primedev/scripts/scriptdatatables.cpp @@ -1,6 +1,6 @@ #include "squirrel/squirrel.h" #include "core/filesystem/rpakfilesystem.h" -#include "core/convar/convar.h" +#include "tier1/convar.h" #include "dedicated/dedicated.h" #include "core/filesystem/filesystem.h" #include "core/math/vector.h" diff --git a/primedev/server/alltalk.cpp b/primedev/server/alltalk.cpp index 4eb5aef7..941c318f 100644 --- a/primedev/server/alltalk.cpp +++ b/primedev/server/alltalk.cpp @@ -1,4 +1,4 @@ -#include "core/convar/convar.h" +#include "tier1/convar.h" #include "engine/r2engine.h" size_t __fastcall ShouldAllowAlltalk() diff --git a/primedev/server/auth/bansystem.cpp b/primedev/server/auth/bansystem.cpp index a81432be..1c525653 100644 --- a/primedev/server/auth/bansystem.cpp +++ b/primedev/server/auth/bansystem.cpp @@ -1,6 +1,6 @@ #include "bansystem.h" #include "serverauthentication.h" -#include "core/convar/concommand.h" +#include "tier1/cmd.h" #include "server/r2server.h" #include "engine/r2engine.h" #include "client/r2client.h" diff --git a/primedev/server/auth/serverauthentication.cpp b/primedev/server/auth/serverauthentication.cpp index fae445a0..613ad720 100644 --- a/primedev/server/auth/serverauthentication.cpp +++ b/primedev/server/auth/serverauthentication.cpp @@ -1,12 +1,12 @@ #include "serverauthentication.h" #include "shared/exploit_fixes/ns_limits.h" -#include "core/convar/cvar.h" -#include "core/convar/convar.h" +#include "tier1/cvar.h" +#include "tier1/convar.h" #include "masterserver/masterserver.h" #include "server/serverpresence.h" #include "engine/hoststate.h" #include "bansystem.h" -#include "core/convar/concommand.h" +#include "tier1/cmd.h" #include "dedicated/dedicated.h" #include "config/profile.h" #include "core/tier0.h" diff --git a/primedev/server/auth/serverauthentication.h b/primedev/server/auth/serverauthentication.h index 996d20e1..6ac635ca 100644 --- a/primedev/server/auth/serverauthentication.h +++ b/primedev/server/auth/serverauthentication.h @@ -1,5 +1,5 @@ #pragma once -#include "core/convar/convar.h" +#include "tier1/convar.h" #include "engine/r2engine.h" #include #include diff --git a/primedev/server/buildainfile.cpp b/primedev/server/buildainfile.cpp index 456c84f0..54e53660 100644 --- a/primedev/server/buildainfile.cpp +++ b/primedev/server/buildainfile.cpp @@ -1,4 +1,4 @@ -#include "core/convar/convar.h" +#include "tier1/convar.h" #include "engine/hoststate.h" #include "engine/r2engine.h" diff --git a/primedev/server/idlekick.cpp b/primedev/server/idlekick.cpp index e4a6176f..d04184e0 100644 --- a/primedev/server/idlekick.cpp +++ b/primedev/server/idlekick.cpp @@ -1,4 +1,4 @@ -#include "core/convar/convar.h" +#include "tier1/convar.h" #include "dedicated/dedicated.h" #include "silver-bun/module.h" diff --git a/primedev/server/servernethooks.cpp b/primedev/server/servernethooks.cpp index 148b735f..7dfbf1c9 100644 --- a/primedev/server/servernethooks.cpp +++ b/primedev/server/servernethooks.cpp @@ -1,4 +1,4 @@ -#include "core/convar/convar.h" +#include "tier1/convar.h" #include "engine/r2engine.h" #include "shared/exploit_fixes/ns_limits.h" #include "masterserver/masterserver.h" diff --git a/primedev/server/serverpresence.cpp b/primedev/server/serverpresence.cpp index 099f6e64..142bcdf2 100644 --- a/primedev/server/serverpresence.cpp +++ b/primedev/server/serverpresence.cpp @@ -1,7 +1,7 @@ #include "serverpresence.h" #include "shared/playlist.h" #include "core/tier0.h" -#include "core/convar/convar.h" +#include "tier1/convar.h" #include diff --git a/primedev/server/serverpresence.h b/primedev/server/serverpresence.h index 07c6fb55..62254d69 100644 --- a/primedev/server/serverpresence.h +++ b/primedev/server/serverpresence.h @@ -1,5 +1,5 @@ #pragma once -#include "core/convar/convar.h" +#include "tier1/convar.h" struct ServerPresence { diff --git a/primedev/shared/exploit_fixes/exploitfixes.cpp b/primedev/shared/exploit_fixes/exploitfixes.cpp index 434ed44a..8f2ef32b 100644 --- a/primedev/shared/exploit_fixes/exploitfixes.cpp +++ b/primedev/shared/exploit_fixes/exploitfixes.cpp @@ -1,4 +1,4 @@ -#include "core/convar/cvar.h" +#include "tier1/cvar.h" #include "ns_limits.h" #include "dedicated/dedicated.h" #include "core/tier0.h" diff --git a/primedev/shared/exploit_fixes/ns_limits.h b/primedev/shared/exploit_fixes/ns_limits.h index 546fec6f..275e57c6 100644 --- a/primedev/shared/exploit_fixes/ns_limits.h +++ b/primedev/shared/exploit_fixes/ns_limits.h @@ -1,6 +1,6 @@ #pragma once #include "engine/r2engine.h" -#include "core/convar/convar.h" +#include "tier1/convar.h" #include struct PlayerLimitData diff --git a/primedev/shared/misccommands.cpp b/primedev/shared/misccommands.cpp index 7bfa86a8..7e2dc817 100644 --- a/primedev/shared/misccommands.cpp +++ b/primedev/shared/misccommands.cpp @@ -1,5 +1,5 @@ #include "misccommands.h" -#include "core/convar/concommand.h" +#include "tier1/cmd.h" #include "shared/playlist.h" #include "engine/r2engine.h" #include "client/r2client.h" diff --git a/primedev/shared/playlist.cpp b/primedev/shared/playlist.cpp index 619e6eca..2da31909 100644 --- a/primedev/shared/playlist.cpp +++ b/primedev/shared/playlist.cpp @@ -1,6 +1,6 @@ #include "playlist.h" -#include "core/convar/concommand.h" -#include "core/convar/convar.h" +#include "tier1/cmd.h" +#include "tier1/convar.h" #include "core/vanilla.h" #include "squirrel/squirrel.h" #include "engine/hoststate.h" diff --git a/primedev/squirrel/squirrel.cpp b/primedev/squirrel/squirrel.cpp index fa7b199b..e96a7550 100644 --- a/primedev/squirrel/squirrel.cpp +++ b/primedev/squirrel/squirrel.cpp @@ -1,7 +1,7 @@ #include "squirrel.h" #include "mods/modsavefiles.h" #include "logging/logging.h" -#include "core/convar/concommand.h" +#include "tier1/cmd.h" #include "mods/modmanager.h" #include "dedicated/dedicated.h" #include "engine/r2engine.h" diff --git a/primedev/core/convar/concommand.cpp b/primedev/tier1/cmd.cpp similarity index 99% rename from primedev/core/convar/concommand.cpp rename to primedev/tier1/cmd.cpp index 02c11ada..99f23fd3 100644 --- a/primedev/core/convar/concommand.cpp +++ b/primedev/tier1/cmd.cpp @@ -1,4 +1,4 @@ -#include "concommand.h" +#include "cmd.h" #include "shared/misccommands.h" #include "engine/r2engine.h" diff --git a/primedev/core/convar/concommand.h b/primedev/tier1/cmd.h similarity index 100% rename from primedev/core/convar/concommand.h rename to primedev/tier1/cmd.h diff --git a/primedev/core/convar/convar.cpp b/primedev/tier1/convar.cpp similarity index 100% rename from primedev/core/convar/convar.cpp rename to primedev/tier1/convar.cpp diff --git a/primedev/core/convar/convar.h b/primedev/tier1/convar.h similarity index 99% rename from primedev/core/convar/convar.h rename to primedev/tier1/convar.h index 33a50c1c..5a9b304c 100644 --- a/primedev/core/convar/convar.h +++ b/primedev/tier1/convar.h @@ -1,7 +1,7 @@ #pragma once #include "core/math/color.h" #include "cvar.h" -#include "concommand.h" +#include "cmd.h" // taken directly from iconvar.h diff --git a/primedev/core/convar/cvar.cpp b/primedev/tier1/cvar.cpp similarity index 96% rename from primedev/core/convar/cvar.cpp rename to primedev/tier1/cvar.cpp index 78da1ad2..cccd53af 100644 --- a/primedev/core/convar/cvar.cpp +++ b/primedev/tier1/cvar.cpp @@ -1,6 +1,6 @@ #include "cvar.h" #include "convar.h" -#include "concommand.h" +#include "cmd.h" //----------------------------------------------------------------------------- // Purpose: returns all ConVars diff --git a/primedev/core/convar/cvar.h b/primedev/tier1/cvar.h similarity index 100% rename from primedev/core/convar/cvar.h rename to primedev/tier1/cvar.h diff --git a/primedev/util/printcommands.cpp b/primedev/util/printcommands.cpp index 03ccce5e..b7d556b4 100644 --- a/primedev/util/printcommands.cpp +++ b/primedev/util/printcommands.cpp @@ -1,7 +1,7 @@ #include "printcommands.h" -#include "core/convar/cvar.h" -#include "core/convar/convar.h" -#include "core/convar/concommand.h" +#include "tier1/cvar.h" +#include "tier1/convar.h" +#include "tier1/cmd.h" void PrintCommandHelpDialogue(const ConCommandBase* command, const char* name) { diff --git a/primedev/util/printcommands.h b/primedev/util/printcommands.h index cb72e5cc..f7cd287f 100644 --- a/primedev/util/printcommands.h +++ b/primedev/util/printcommands.h @@ -1,5 +1,5 @@ #pragma once -#include "core/convar/concommand.h" +#include "tier1/cmd.h" void PrintCommandHelpDialogue(const ConCommandBase* command, const char* name); void TryPrintCvarHelpForCommand(const char* pCommand); diff --git a/primedev/util/printmaps.cpp b/primedev/util/printmaps.cpp index 07c33218..26cd0ccd 100644 --- a/primedev/util/printmaps.cpp +++ b/primedev/util/printmaps.cpp @@ -1,6 +1,6 @@ #include "printmaps.h" -#include "core/convar/convar.h" -#include "core/convar/concommand.h" +#include "tier1/convar.h" +#include "tier1/cmd.h" #include "mods/modmanager.h" #include "core/tier0.h" #include "engine/r2engine.h" From 0d0cf3e79f0fa0debf359ad453ec9d0cd1ba4262 Mon Sep 17 00:00:00 2001 From: cat_or_not <41955154+catornot@users.noreply.github.com> Date: Wed, 12 Aug 2026 22:09:18 -0400 Subject: [PATCH 15/17] fix version eval in flake (#929) --- flake.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index 61711f8a..738c4e8c 100644 --- a/flake.nix +++ b/flake.nix @@ -212,7 +212,7 @@ versionQuadruplet = "${versionAt 0},${versionAt 1},${versionAt 2},${ if isDev then "1" - else if builtins.length > 3 then + else if builtins.length versionSeq > 3 then versionAt 3 else "0" From 2c16ed3605c3a07037b9f974544f7ac294cb6aa5 Mon Sep 17 00:00:00 2001 From: cat_or_not <41955154+catornot@users.noreply.github.com> Date: Wed, 12 Aug 2026 22:30:00 -0400 Subject: [PATCH 16/17] Hardcode cardinals of all exports in wsock32 (#931) * fix version eval in flake * Move `core/convar/` to `tier1/` 2 (#928) * just hard code everything in wsock32 def --- primedev/wsockproxy/wsock32.def | 112 ++++++++++++++++---------------- 1 file changed, 56 insertions(+), 56 deletions(-) diff --git a/primedev/wsockproxy/wsock32.def b/primedev/wsockproxy/wsock32.def index 187b2959..b731dcad 100644 --- a/primedev/wsockproxy/wsock32.def +++ b/primedev/wsockproxy/wsock32.def @@ -1,77 +1,77 @@ LIBRARY wsock32 EXPORTS - AcceptEx=mswsock.AcceptEx - EnumProtocolsA=PROXY_EnumProtocolsA - EnumProtocolsW=PROXY_EnumProtocolsW - GetAcceptExSockaddrs=mswsock.GetAcceptExSockaddrs - GetAddressByNameA=PROXY_GetAddressByNameA - GetAddressByNameW=PROXY_GetAddressByNameW - GetNameByTypeA=ws2_32.GetNameByTypeA - GetNameByTypeW=ws2_32.GetNameByTypeW - GetServiceA=ws2_32.GetServiceA - GetServiceW=ws2_32.GetServiceW - GetTypeByNameA=ws2_32.GetTypeByNameA - GetTypeByNameW=ws2_32.GetTypeByNameW - MigrateWinsockConfiguration=ws2_32.MigrateWinsockConfiguration - NPLoadNameSpaces=ws2_32.NPLoadNameSpaces - SetServiceA=ws2_32.SetServiceA - SetServiceW=ws2_32.SetServiceW - TransmitFile=mswsock.TransmitFile - WEP=PROXY_WEP - WSAAsyncGetHostByAddr=ws2_32.WSAAsyncGetHostByAddr - WSAAsyncGetHostByName=ws2_32.WSAAsyncGetHostByName - WSAAsyncGetProtoByName=ws2_32.WSAAsyncGetProtoByName - WSAAsyncGetProtoByNumber=ws2_32.WSAAsyncGetProtoByNumber - WSAAsyncGetServByName=ws2_32.WSAAsyncGetServByName - WSAAsyncGetServByPort=ws2_32.WSAAsyncGetServByPort - WSAAsyncSelect=ws2_32.WSAAsyncSelect - WSACancelAsyncRequest=ws2_32.WSACancelAsyncRequest - WSACancelBlockingCall=ws2_32.WSACancelBlockingCall - WSACleanup=ws2_32.WSACleanup @116 - WSAGetLastError=ws2_32.WSAGetLastError @111 - WSAIsBlocking=ws2_32.WSAIsBlocking - WSARecvEx=PROXY_WSARecvEx - WSASetBlockingHook=ws2_32.WSASetBlockingHook - WSASetLastError=ws2_32.WSASetLastError @112 - WSAStartup=ws2_32.WSAStartup @115 - WSAUnhookBlockingHook=ws2_32.WSAUnhookBlockingHook - WSApSetPostRoutine=ws2_32.WSApSetPostRoutine - __WSAFDIsSet=PROXY___WSAFDIsSet @151 accept=ws2_32.accept @1 bind=ws2_32.bind @2 closesocket=ws2_32.closesocket @3 connect=ws2_32.connect @4 - dn_expand=ws2_32.dn_expand @1106 - gethostbyaddr=ws2_32.gethostbyaddr - gethostbyname=ws2_32.gethostbyname @52 - gethostname=ws2_32.gethostname @57 - getnetbyname=PROXY_getnetbyname @ 1101 getpeername=ws2_32.getpeername @5 - getprotobyname=ws2_32.getprotobyname - getprotobynumber=ws2_32.getprotobynumber - getservbyname=ws2_32.getservbyname - getservbyport=ws2_32.getservbyport getsockname=ws2_32.getsockname @6 getsockopt=PROXY_getsockopt @7 - htonl=ws2_32.htonl + AcceptEx=mswsock.AcceptEx @8 htons=ws2_32.htons @9 - inet_addr=ws2_32.inet_addr - inet_network=PROXY_inet_network - inet_ntoa=ws2_32.inet_ntoa + EnumProtocolsA=PROXY_EnumProtocolsA @10 + EnumProtocolsW=PROXY_EnumProtocolsW @11 ioctlsocket=ws2_32.ioctlsocket @12 listen=ws2_32.listen @13 - ntohl=ws2_32.ntohl + GetAcceptExSockaddrs=mswsock.GetAcceptExSockaddrs @14 ntohs=ws2_32.ntohs @15 - rcmd=ws2_32.rcmd recv=ws2_32.recv @16 recvfrom=ws2_32.recvfrom @17 - rexec=ws2_32.rexec - rresvport=ws2_32.rresvport - s_perror=PROXY_s_perror select=ws2_32.select @18 send=ws2_32.send @19 sendto=ws2_32.sendto @20 - sethostname=ws2_32.sethostname setsockopt=PROXY_setsockopt @21 shutdown=ws2_32.shutdown @22 socket=ws2_32.socket @23 + GetAddressByNameA=PROXY_GetAddressByNameA @24 + GetAddressByNameW=PROXY_GetAddressByNameW @25 + GetNameByTypeA=ws2_32.GetNameByTypeA @26 + GetNameByTypeW=ws2_32.GetNameByTypeW @27 + GetServiceA=ws2_32.GetServiceA @28 + GetServiceW=ws2_32.GetServiceW @29 + GetTypeByNameA=ws2_32.GetTypeByNameA @30 + GetTypeByNameW=ws2_32.GetTypeByNameW @31 + MigrateWinsockConfiguration=ws2_32.MigrateWinsockConfiguration @32 + NPLoadNameSpaces=ws2_32.NPLoadNameSpaces @33 + SetServiceA=ws2_32.SetServiceA @34 + SetServiceW=ws2_32.SetServiceW @35 + TransmitFile=mswsock.TransmitFile @36 + WEP=PROXY_WEP @37 + WSAAsyncGetHostByAddr=ws2_32.WSAAsyncGetHostByAddr @38 + WSAAsyncGetHostByName=ws2_32.WSAAsyncGetHostByName @39 + WSAAsyncGetProtoByName=ws2_32.WSAAsyncGetProtoByName @40 + WSAAsyncGetProtoByNumber=ws2_32.WSAAsyncGetProtoByNumber @41 + WSAAsyncGetServByName=ws2_32.WSAAsyncGetServByName @42 + WSAAsyncGetServByPort=ws2_32.WSAAsyncGetServByPort @43 + WSAAsyncSelect=ws2_32.WSAAsyncSelect @44 + WSACancelAsyncRequest=ws2_32.WSACancelAsyncRequest @45 + WSACancelBlockingCall=ws2_32.WSACancelBlockingCall @46 + WSAIsBlocking=ws2_32.WSAIsBlocking @47 + WSARecvEx=PROXY_WSARecvEx @48 + WSASetBlockingHook=ws2_32.WSASetBlockingHook @49 + WSAUnhookBlockingHook=ws2_32.WSAUnhookBlockingHook @50 + WSApSetPostRoutine=ws2_32.WSApSetPostRoutine @51 + gethostbyname=ws2_32.gethostbyname @52 + gethostbyaddr=ws2_32.gethostbyaddr @53 + getprotobyname=ws2_32.getprotobyname @54 + getprotobynumber=ws2_32.getprotobynumber @55 + getservbyname=ws2_32.getservbyname @56 + gethostname=ws2_32.gethostname @57 + getservbyport=ws2_32.getservbyport @58 + htonl=ws2_32.htonl @59 + inet_addr=ws2_32.inet_addr @60 + inet_network=PROXY_inet_network @61 + inet_ntoa=ws2_32.inet_ntoa @62 + ntohl=ws2_32.ntohl @63 + rcmd=ws2_32.rcmd @64 + rexec=ws2_32.rexec @65 + rresvport=ws2_32.rresvport @66 + s_perror=PROXY_s_perror @67 + sethostname=ws2_32.sethostname @68 + WSAGetLastError=ws2_32.WSAGetLastError @111 + WSASetLastError=ws2_32.WSASetLastError @112 + WSAStartup=ws2_32.WSAStartup @115 + WSACleanup=ws2_32.WSACleanup @116 + __WSAFDIsSet=PROXY___WSAFDIsSet @151 + getnetbyname=PROXY_getnetbyname @1101 + dn_expand=ws2_32.dn_expand @1106 From 9ddf557948f9fb681d91fc9fe4e1710fa6b11f2c Mon Sep 17 00:00:00 2001 From: Allusive <154700875+AllusiveWheat@users.noreply.github.com> Date: Thu, 20 Aug 2026 19:33:16 -0700 Subject: [PATCH 17/17] Default compile constants to 0 if not defined (#932) * default ifdef constants to 0 --------- Co-authored-by: Will <39478251+sonny-tel@users.noreply.github.com> Co-authored-by: Will <39478251+VITALISED@users.noreply.github.com> --- primedev/squirrel/squirrel.cpp | 50 ++++++++++++++++++- .../squirrel_re/squirrel/sqcompiler.h | 4 +- .../languages/squirrel_re/squirrel/sqstate.h | 4 +- 3 files changed, 55 insertions(+), 3 deletions(-) diff --git a/primedev/squirrel/squirrel.cpp b/primedev/squirrel/squirrel.cpp index e96a7550..dddcf2fa 100644 --- a/primedev/squirrel/squirrel.cpp +++ b/primedev/squirrel/squirrel.cpp @@ -20,7 +20,7 @@ AUTOHOOK_INIT() SquirrelManagerManager g_pSquirrel; - +thread_local SQCompiler* pIfDirectiveCompiler; std::shared_ptr getSquirrelLoggerByContext(ScriptContext context) { switch (context) @@ -326,9 +326,43 @@ bool IsUIVM(ScriptContext context, HSQUIRRELVM pSqvm) return ScriptContext(pSqvm->sharedState->cSquirrelVM->vmContext) == ScriptContext::UI; } +template std::int64_t (*SQCompiler_ParseDirective)(SQCompiler* pCompiler); +template std::int64_t __fastcall SQCompiler_ParseDirectiveHook(SQCompiler* pCompiler) +{ + SQCompiler* pPreviousCompiler = pIfDirectiveCompiler; + pIfDirectiveCompiler = pCompiler; + const std::int64_t result = SQCompiler_ParseDirective(pCompiler); + pIfDirectiveCompiler = pPreviousCompiler; + return result; +} + +template +bool (*SQCompiler_ResolveLocalOrConstant)(void* pFunctionState, SQObject* pIdentifier, SQObject* pValue, std::uintptr_t* pType); +template +bool __fastcall SQCompiler_ResolveLocalOrConstantHook(void* pFunctionState, SQObject* pIdentifier, SQObject* pValue, std::uintptr_t* pType) +{ + if (SQCompiler_ResolveLocalOrConstant(pFunctionState, pIdentifier, pValue, pType)) + return true; + // if we're not in a preprocessor directive, we don't want to resolve the identifier as a constant + if (!pIfDirectiveCompiler || pIfDirectiveCompiler->preprocessorDepth <= 0) + return false; + + // evaluate to 0 if we're doing directives because #if with a compile error is stupid + pValue->_Type = OT_INTEGER; + pValue->structNumber = 0; + pValue->_VAL.as64Integer = 0; + constexpr std::uint32_t typeHashMagic = 0x9E3779B9u - 0x61C88647u; + constexpr std::uint32_t typeHash = typeHashMagic * static_cast(OT_INTEGER); + constexpr std::size_t typeIndex = (typeHash / 0xF499u) & 0x3FFFu; + SQSharedState* pSharedState = pIfDirectiveCompiler->pSQVM->sharedState; + *pType = reinterpret_cast(&pSharedState->compilerTypeDescriptors[typeIndex]); + return true; +} + template void* (*sq_compiler_create)(HSQUIRRELVM sqvm, void* a2, void* a3, SQBool bShouldThrowError); template void* __fastcall sq_compiler_createHook(HSQUIRRELVM sqvm, void* a2, void* a3, SQBool bShouldThrowError) { + pIfDirectiveCompiler = nullptr; // store whether errors generated from this compile should be fatal if (IsUIVM(context, sqvm)) g_pSquirrel[ScriptContext::UI]->m_bFatalCompilationErrors = bShouldThrowError; @@ -789,6 +823,13 @@ ON_DLL_LOAD_RELIESON("client.dll", ClientSquirrel, ConCommand, (CModule module)) MAKEHOOK(module.Offset(0x8AD0), &sq_compiler_createHook, &sq_compiler_create); + MAKEHOOK( + module.Offset(0x58590), &SQCompiler_ParseDirectiveHook, &SQCompiler_ParseDirective); + MAKEHOOK( + module.Offset(0x65CB0), + &SQCompiler_ResolveLocalOrConstantHook, + &SQCompiler_ResolveLocalOrConstant); + MAKEHOOK(module.Offset(0x12B00), &SQPrintHook, &SQPrint); MAKEHOOK(module.Offset(0x12BA0), &SQPrintHook, &SQPrint); @@ -868,6 +909,13 @@ ON_DLL_LOAD_RELIESON("server.dll", ServerSquirrel, ConCommand, (CModule module)) MAKEHOOK(module.Offset(0x8AA0), &sq_compiler_createHook, &sq_compiler_create); + MAKEHOOK( + module.Offset(0x58530), &SQCompiler_ParseDirectiveHook, &SQCompiler_ParseDirective); + MAKEHOOK( + module.Offset(0x65C50), + &SQCompiler_ResolveLocalOrConstantHook, + &SQCompiler_ResolveLocalOrConstant); + MAKEHOOK(module.Offset(0x1FE90), &SQPrintHook, &SQPrint); MAKEHOOK(module.Offset(0x260E0), &CreateNewVMHook, &CreateNewVM); MAKEHOOK(module.Offset(0x26E20), &DestroyVMHook, &DestroyVM); diff --git a/primedev/vscript/languages/squirrel_re/squirrel/sqcompiler.h b/primedev/vscript/languages/squirrel_re/squirrel/sqcompiler.h index 5a54751c..1b50dc7d 100644 --- a/primedev/vscript/languages/squirrel_re/squirrel/sqcompiler.h +++ b/primedev/vscript/languages/squirrel_re/squirrel/sqcompiler.h @@ -14,7 +14,9 @@ struct SQCompiler int64_t qword98; BYTE gapA0[280]; bool bFatalError; - BYTE gap1B9[143]; + BYTE gap1B9[11]; + int preprocessorDepth; + BYTE gap1C8[128]; int64_t qword248; int64_t qword250; int64_t qword258; diff --git a/primedev/vscript/languages/squirrel_re/squirrel/sqstate.h b/primedev/vscript/languages/squirrel_re/squirrel/sqstate.h index d5282ac7..b226f2f3 100644 --- a/primedev/vscript/languages/squirrel_re/squirrel/sqstate.h +++ b/primedev/vscript/languages/squirrel_re/squirrel/sqstate.h @@ -58,7 +58,9 @@ struct SQSharedState SQTable* _entityTypesMaybe; SQObjectType unknownTable2Type; SQTable* unknownTable2; - unsigned char gap_41D8[64]; + unsigned char gap_41D8[16]; + SQObject* compilerTypeDescriptors; + unsigned char gap_41F0[40]; SQCompiler* pCompiler; SQObjectType _compilerKeywordsType; SQTable* _compilerKeywords;