Merge branch 'feature/vs2017' into 'develop'
[Merge] feature/vs2017 -> develop
This commit is contained in:
commit
e75c662687
2
.gitmodules
vendored
2
.gitmodules
vendored
@ -21,7 +21,7 @@
|
||||
[submodule "deps/mongoose"]
|
||||
path = deps/mongoose
|
||||
url = https://github.com/cesanta/mongoose.git
|
||||
branch = master
|
||||
branch = dev
|
||||
[submodule "deps/protobuf"]
|
||||
path = deps/protobuf
|
||||
url = https://github.com/google/protobuf.git
|
||||
|
@ -8,6 +8,8 @@ The format is based on [Keep a Changelog v0.3.0](http://keepachangelog.com/en/0.
|
||||
|
||||
### Added
|
||||
|
||||
- Show friend avatars when they play IW4x (request)
|
||||
- Cod4 style fast download for usermaps
|
||||
- Display a toast when an update is available.
|
||||
- Use the hourglass cursor while loading assets (with the native cursor feature).
|
||||
- Show bots in parenthesis after the number of players in the serverlist (request).
|
||||
@ -18,6 +20,9 @@ The format is based on [Keep a Changelog v0.3.0](http://keepachangelog.com/en/0.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix lags and frame drops caused by server sorting
|
||||
- Fix demos on custom maps
|
||||
- Can no longer join a lobby with an incorrect password
|
||||
- Fix lags and frame drops caused by server sorting.
|
||||
- Fix demos on custom maps.
|
||||
|
||||
|
4
Jenkinsfile
vendored
4
Jenkinsfile
vendored
@ -104,8 +104,8 @@ def doBuild(cfg) {
|
||||
|
||||
useShippedPremake {
|
||||
def outputDir = pwd()
|
||||
def msbuild = tool "Microsoft.NET MSBuild 14.0"
|
||||
bat "premake5 vs2015 ${cfg.PremakeArgs}"
|
||||
def msbuild = tool "Microsoft.NET MSBuild 15.0"
|
||||
bat "premake5 vs2017 ${cfg.PremakeArgs}"
|
||||
bat "\"${msbuild}\" build\\iw4x.sln \"/p:OutDir=$outputDir\\\\\" \"/p:Configuration=${cfg.MSBuildConfiguration}\""
|
||||
}
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
||||
|
||||
## How to compile
|
||||
|
||||
- Run `premake5 vs2015` or use the delivered `generate.bat`.
|
||||
- Run `premake5 vs2017` or use the delivered `generate.bat`.
|
||||
- Build via solution file in `build\iw4x.sln`. (You can use the `build.bat` script to do it quick and easy.)
|
||||
|
||||
## Premake arguments
|
||||
|
@ -2,16 +2,16 @@
|
||||
|
||||
cd %~dp0
|
||||
|
||||
if exist "%VS140COMNTOOLS%\vsvars32.bat" call "%VS140COMNTOOLS%\vsvars32.bat"
|
||||
if exist "%PROGRAMFILES(x86)%\Microsoft Visual Studio\2017\Enterprise\Common7\Tools\VsMSBuildCmd.bat" call "%PROGRAMFILES(x86)%\Microsoft Visual Studio\2017\Enterprise\Common7\Tools\VsMSBuildCmd.bat"
|
||||
msbuild /version >NUL 2>NUL
|
||||
if errorlevel 0 goto:build
|
||||
|
||||
if exist "%PROGRAMFILES(x86)%\msbuild\14.0\Bin\msbuild.exe" path %PROGRAMFILES(x86)%\msbuild\14.0\Bin;%PATH%
|
||||
if exist "%PROGRAMFILES(x86)%\Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0\Bin\msbuild.exe" path %PROGRAMFILES(x86)%\Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0\Bin;%PATH%
|
||||
msbuild /version >NUL 2>NUL
|
||||
if errorlevel 0 goto:build
|
||||
|
||||
echo Couldn't find any MSBuild to build this project.
|
||||
echo Make sure you have Visual C++ Build Tools 2015 or Visual Studio 2015 installed.
|
||||
echo Make sure you have Visual C++ Build Tools 2017 or Visual Studio 2017 installed.
|
||||
endlocal
|
||||
exit /B 1
|
||||
|
||||
|
2
deps/json11
vendored
2
deps/json11
vendored
@ -1 +1 @@
|
||||
Subproject commit ed35a09c043c376969dde9a3293824e1c11aa1f1
|
||||
Subproject commit ec4e45219af1d7cde3d58b49ed762376fccf1ace
|
2
deps/libtomcrypt
vendored
2
deps/libtomcrypt
vendored
@ -1 +1 @@
|
||||
Subproject commit bda493d770259300f48a79a5a8686c83c62b60e0
|
||||
Subproject commit 6f852936723daa03157efdebfcf0bea711fa17e8
|
2
deps/mongoose
vendored
2
deps/mongoose
vendored
@ -1 +1 @@
|
||||
Subproject commit 7c0493071f182b890f4e01ece84ab2523858cc76
|
||||
Subproject commit fb3a5a7d905978b5b1ce26ad3100294ee669dda1
|
2
deps/protobuf
vendored
2
deps/protobuf
vendored
@ -1 +1 @@
|
||||
Subproject commit c722c3d29440de4b33bed3e4d908cabe38a1196f
|
||||
Subproject commit 703cd8e11c8d34283d4c8bf869c61866e8211c9d
|
@ -1,4 +1,4 @@
|
||||
@echo off
|
||||
echo Updating submodules...
|
||||
git submodule update --init --recursive
|
||||
tools\premake5 %* vs2015
|
||||
tools\premake5 %* vs2017
|
@ -1,83 +0,0 @@
|
||||
boost = {
|
||||
settings = nil,
|
||||
}
|
||||
|
||||
function boost.setup(settings)
|
||||
if not settings.source then error("Missing source.") end
|
||||
|
||||
boost.settings = settings
|
||||
end
|
||||
|
||||
function boost.import()
|
||||
if not boost.settings then error("Run boost.setup first") end
|
||||
|
||||
--links { "boost" }
|
||||
boost.includes()
|
||||
end
|
||||
|
||||
function boost.includes()
|
||||
if not boost.settings then error("Run boost.setup first") end
|
||||
|
||||
submodules = {
|
||||
"mpl",
|
||||
"core",
|
||||
"move",
|
||||
"tuple",
|
||||
"assert",
|
||||
"predef",
|
||||
"config",
|
||||
"detail",
|
||||
"winapi",
|
||||
"integer",
|
||||
"utility",
|
||||
"iterator",
|
||||
"container",
|
||||
"unordered",
|
||||
"date_time",
|
||||
"smart_ptr",
|
||||
"intrusive",
|
||||
"functional",
|
||||
"type_traits",
|
||||
"interprocess",
|
||||
"preprocessor",
|
||||
"static_assert",
|
||||
"throw_exception",
|
||||
}
|
||||
|
||||
for i, submodule in ipairs(submodules) do
|
||||
includedirs { path.join(boost.settings.source, string.format("%s/include", submodule)) }
|
||||
end
|
||||
|
||||
includedirs { boost.settings.source }
|
||||
end
|
||||
|
||||
function boost.project()
|
||||
if not boost.settings then error("Run boost.setup first") end
|
||||
|
||||
--[[
|
||||
project "boost"
|
||||
language "C++"
|
||||
|
||||
includedirs
|
||||
{
|
||||
boost.settings.source,
|
||||
}
|
||||
|
||||
files
|
||||
{
|
||||
path.join(boost.settings.source, "*.cpp"),
|
||||
path.join(boost.settings.source, "*.hpp"),
|
||||
}
|
||||
removefiles
|
||||
{
|
||||
path.join(boost.settings.source, "test*"),
|
||||
}
|
||||
|
||||
-- not our code, ignore POSIX usage warnings for now
|
||||
warnings "Off"
|
||||
|
||||
defines { "_LIB" }
|
||||
removedefines { "_USRDLL", "_DLL" }
|
||||
kind "StaticLib"
|
||||
]]
|
||||
end
|
@ -36,9 +36,6 @@ function libtommath.project()
|
||||
path.join(libtommath.settings.source, "*.c"),
|
||||
}
|
||||
|
||||
-- dependencies
|
||||
libtommath.import()
|
||||
|
||||
-- not our code, ignore POSIX usage warnings for now
|
||||
warnings "Off"
|
||||
|
||||
|
@ -40,6 +40,5 @@ function udis86.project()
|
||||
-- not our code, ignore POSIX usage warnings for now
|
||||
warnings "Off"
|
||||
|
||||
kind "SharedLib"
|
||||
kind "StaticLib"
|
||||
end
|
@ -235,14 +235,12 @@ workspace "iw4x"
|
||||
location "./build"
|
||||
objdir "%{wks.location}/obj"
|
||||
targetdir "%{wks.location}/bin/%{cfg.buildcfg}"
|
||||
buildlog "%{wks.location}/obj/%{cfg.architecture}/%{cfg.buildcfg}/%{prj.name}/%{prj.name}.log"
|
||||
configurations { "Debug", "Release" }
|
||||
architecture "x32"
|
||||
platforms "x86"
|
||||
exceptionhandling ("SEH")
|
||||
|
||||
-- VS 2015 toolset only
|
||||
toolset "msc-140"
|
||||
|
||||
flags { "StaticRuntime" }
|
||||
|
||||
configuration "windows"
|
||||
@ -266,7 +264,6 @@ workspace "iw4x"
|
||||
project "iw4x"
|
||||
kind "SharedLib"
|
||||
language "C++"
|
||||
flags { "C++14" }
|
||||
files {
|
||||
"./src/**.rc",
|
||||
"./src/**.hpp",
|
||||
@ -376,7 +373,8 @@ workspace "iw4x"
|
||||
end
|
||||
|
||||
-- Specific configurations
|
||||
flags { "UndefinedIdentifiers", "ExtraWarnings" }
|
||||
flags { "UndefinedIdentifiers" }
|
||||
warnings "Extra"
|
||||
|
||||
if symbols ~= nil then
|
||||
symbols "On"
|
||||
|
@ -61,7 +61,7 @@ namespace Components
|
||||
Loader::Register(new Monitor());
|
||||
Loader::Register(new Network());
|
||||
Loader::Register(new Theatre());
|
||||
//Loader::Register(new Clantags());
|
||||
//Loader::Register(new ClanTags());
|
||||
Loader::Register(new Download());
|
||||
Loader::Register(new Playlist());
|
||||
Loader::Register(new RawFiles());
|
||||
@ -93,7 +93,7 @@ namespace Components
|
||||
Loader::Register(new ZoneBuilder());
|
||||
Loader::Register(new AssetHandler());
|
||||
Loader::Register(new Localization());
|
||||
Loader::Register(new MusicalTalent());
|
||||
//Loader::Register(new MusicalTalent());
|
||||
Loader::Register(new ServerCommands());
|
||||
Loader::Register(new StructuredData());
|
||||
Loader::Register(new ConnectProtocol());
|
||||
|
@ -92,7 +92,7 @@ namespace Components
|
||||
#include "Modules/Logger.hpp"
|
||||
#include "Modules/Friends.hpp"
|
||||
#include "Modules/IPCPipe.hpp"
|
||||
#include "Modules/Clantags.hpp"
|
||||
#include "Modules/ClanTags.hpp"
|
||||
#include "Modules/Download.hpp"
|
||||
#include "Modules/Playlist.hpp"
|
||||
#include "Modules/RawFiles.hpp"
|
||||
|
@ -102,8 +102,8 @@ namespace Components
|
||||
#ifdef DEBUG_LOAD_LIBRARY
|
||||
AntiCheat::LoadLibHook[0].initialize(loadLibA, LoadLibaryAStub, HOOK_JUMP);
|
||||
AntiCheat::LoadLibHook[1].initialize(loadLibW, LoadLibaryWStub, HOOK_JUMP);
|
||||
AntiCheat::LoadLibHook[2].initialize(loadLibExA, LoadLibaryAStub, HOOK_JUMP);
|
||||
AntiCheat::LoadLibHook[3].initialize(loadLibExW, LoadLibaryWStub, HOOK_JUMP);
|
||||
AntiCheat::LoadLibHook[2].initialize(loadLibExA, LoadLibaryExAStub, HOOK_JUMP);
|
||||
AntiCheat::LoadLibHook[3].initialize(loadLibExW, LoadLibaryExWStub, HOOK_JUMP);
|
||||
#else
|
||||
static uint8_t loadLibStub[] = { 0x33, 0xC0, 0xC2, 0x04, 0x00 }; // xor eax, eax; retn 04h
|
||||
static uint8_t loadLibExStub[] = { 0x33, 0xC0, 0xC2, 0x0C, 0x00 }; // xor eax, eax; retn 0Ch
|
||||
@ -119,7 +119,7 @@ namespace Components
|
||||
static uint8_t ldrLoadDll[] = { 0xB3, 0x9B, 0x8D, 0xB3, 0x90, 0x9E, 0x9B, 0xBB, 0x93, 0x93 }; // LdrLoadDll
|
||||
|
||||
HMODULE ntdll = Utils::GetNTDLL();
|
||||
AntiCheat::LoadLibHook[4].initialize(GetProcAddress(ntdll, Utils::String::XOR(std::string(reinterpret_cast<char*>(ldrLoadDll), sizeof ldrLoadDll), -1).data()), ldrLoadDllStub, HOOK_JUMP);
|
||||
//AntiCheat::LoadLibHook[4].initialize(GetProcAddress(ntdll, Utils::String::XOR(std::string(reinterpret_cast<char*>(ldrLoadDll), sizeof ldrLoadDll), -1).data()), ldrLoadDllStub, HOOK_JUMP);
|
||||
|
||||
// Patch LdrpLoadDll
|
||||
Utils::Hook::Signature::Container container;
|
||||
@ -133,7 +133,7 @@ namespace Components
|
||||
|
||||
Utils::Hook::Signature signature(ntdll, Utils::GetModuleSize(ntdll));
|
||||
signature.add(container);
|
||||
signature.process();
|
||||
//signature.process();
|
||||
}
|
||||
|
||||
void AntiCheat::ReadIntegrityCheck()
|
||||
@ -229,10 +229,10 @@ namespace Components
|
||||
AntiCheat::Flags |= AntiCheat::IntergrityFlag::MEMORY_SCAN;
|
||||
}
|
||||
|
||||
void AntiCheat::QuickCodeScanner_1()
|
||||
void AntiCheat::QuickCodeScanner1()
|
||||
{
|
||||
static Utils::Time::Interval interval;
|
||||
static Utils::Value<std::string> hashVal;
|
||||
static std::optional<std::string> hashVal;
|
||||
|
||||
if (!interval.elapsed(11s)) return;
|
||||
interval.update();
|
||||
@ -243,30 +243,30 @@ namespace Components
|
||||
uint8_t* textBase = reinterpret_cast<uint8_t*>(0x400FFF);
|
||||
std::string hash = Utils::Cryptography::SHA256::Compute(textBase + 1, textSize + 1, false);
|
||||
|
||||
if (hashVal.isValid() && hash != hashVal.get())
|
||||
if (hashVal.has_value() && hash != hashVal.value())
|
||||
{
|
||||
Utils::Hook::Set<BYTE>(0x42A667, 0x90); // Crash
|
||||
}
|
||||
|
||||
hashVal.set(hash);
|
||||
hashVal.emplace(hash);
|
||||
}
|
||||
|
||||
void AntiCheat::QuickCodeScanner_2()
|
||||
void AntiCheat::QuickCodeScanner2()
|
||||
{
|
||||
static Utils::Time::Interval interval;
|
||||
static Utils::Value<std::string> hashVal;
|
||||
static std::optional<std::string> hashVal;
|
||||
|
||||
if (!interval.elapsed(12s)) return;
|
||||
interval.update();
|
||||
|
||||
// Hash .text segment
|
||||
std::string hash = Utils::Cryptography::SHA1::Compute(reinterpret_cast<uint8_t*>(0x401000), 0x2D6000, false);
|
||||
if (hashVal.isValid() && hash != hashVal.get())
|
||||
if (hashVal.has_value() && hash != hashVal.value())
|
||||
{
|
||||
Utils::Hook::Set<BYTE>(0x40797C, 0x90); // Crash
|
||||
}
|
||||
|
||||
hashVal.set(hash);
|
||||
hashVal.emplace(hash);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_LOAD_LIBRARY
|
||||
|
@ -31,8 +31,8 @@ namespace Components
|
||||
|
||||
static void VerifyThreadIntegrity();
|
||||
|
||||
static void QuickCodeScanner_1();
|
||||
static void QuickCodeScanner_2();
|
||||
static void QuickCodeScanner1();
|
||||
static void QuickCodeScanner2();
|
||||
|
||||
private:
|
||||
enum IntergrityFlag
|
||||
|
@ -407,8 +407,57 @@ namespace Components
|
||||
Utils::Hook::Call<void(int, const char*, const char*, const char*)>(0x4F8C70)(severity, format, type, name); // Print error
|
||||
}
|
||||
|
||||
void AssetHandler::reallocateEntryPool()
|
||||
{
|
||||
AssertSize(Game::XAssetEntry, 16);
|
||||
|
||||
size_t size = (ZoneBuilder::IsEnabled() ? 1183968 : 789312);
|
||||
Game::XAssetEntry* entryPool = Utils::Memory::GetAllocator()->allocateArray<Game::XAssetEntry>(size);
|
||||
|
||||
// Apply new size
|
||||
Utils::Hook::Set<DWORD>(0x5BAEB0, size);
|
||||
|
||||
// Apply new pool
|
||||
DWORD patches[] =
|
||||
{
|
||||
0x48E6F4,
|
||||
0x4C67E4,
|
||||
0x4C8584,
|
||||
0x5BAEA8,
|
||||
0x5BB0C4,
|
||||
0x5BB0F5,
|
||||
0x5BB1D4,
|
||||
0x5BB235,
|
||||
0x5BB278,
|
||||
0x5BB34C,
|
||||
0x5BB484,
|
||||
0x5BB570,
|
||||
0x5BB6B7,
|
||||
0x5BB844,
|
||||
0x5BB98D,
|
||||
0x5BBA66,
|
||||
0x5BBB8D,
|
||||
0x5BBCB1,
|
||||
0x5BBD9B,
|
||||
0x5BBE4C,
|
||||
0x5BBF14,
|
||||
0x5BBF54,
|
||||
0x5BBFB8
|
||||
};
|
||||
|
||||
for (int i = 0; i < ARRAYSIZE(patches); ++i)
|
||||
{
|
||||
Utils::Hook::Set<Game::XAssetEntry*>(patches[i], entryPool);
|
||||
}
|
||||
|
||||
Utils::Hook::Set<Game::XAssetEntry*>(0x5BAE91, entryPool + 1);
|
||||
Utils::Hook::Set<Game::XAssetEntry*>(0x5BAEA2, entryPool + 1);
|
||||
}
|
||||
|
||||
AssetHandler::AssetHandler()
|
||||
{
|
||||
this->reallocateEntryPool();
|
||||
|
||||
Dvar::Register<bool>("r_noVoid", false, Game::DVAR_FLAG_SAVED, "Disable void model (red fx)");
|
||||
|
||||
AssetHandler::ClearTemporaryAssets();
|
||||
@ -450,9 +499,31 @@ namespace Components
|
||||
}
|
||||
});
|
||||
|
||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_GAMEWORLD_SP, 1);
|
||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_IMAGE, ZoneBuilder::IsEnabled() ? 14336 : 7168);
|
||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_LOADED_SOUND, 2700);
|
||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_FX, 1200);
|
||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_LOCALIZE_ENTRY, 14000);
|
||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_XANIMPARTS, 8192);
|
||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_XMODEL, 5125);
|
||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_PHYSPRESET, 128);
|
||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_PIXELSHADER, ZoneBuilder::IsEnabled() ? 0x4000 : 10000);
|
||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_VERTEXSHADER, ZoneBuilder::IsEnabled() ? 0x2000 : 3072);
|
||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_MATERIAL, 8192);
|
||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_VERTEXDECL, ZoneBuilder::IsEnabled() ? 0x400 : 196);
|
||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_WEAPON, WEAPON_LIMIT);
|
||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_STRINGTABLE, 800);
|
||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_IMPACT_FX, 8);
|
||||
|
||||
// Register asset interfaces
|
||||
if (ZoneBuilder::IsEnabled())
|
||||
{
|
||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_MAP_ENTS, 10);
|
||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_XMODELSURFS, 8192);
|
||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_TECHNIQUE_SET, 0x2000);
|
||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_FONT, 32);
|
||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_RAWFILE, 2048);
|
||||
|
||||
AssetHandler::RegisterInterface(new Assets::IFont_s());
|
||||
AssetHandler::RegisterInterface(new Assets::IXModel());
|
||||
AssetHandler::RegisterInterface(new Assets::IFxWorld());
|
||||
|
@ -70,6 +70,8 @@ namespace Components
|
||||
static void SetBypassState(bool value);
|
||||
|
||||
static void MissingAssetError(int severity, const char* format, const char* type, const char* name);
|
||||
|
||||
void reallocateEntryPool();
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -255,7 +255,7 @@ namespace Assets
|
||||
{
|
||||
// TODO: Allow loading assets from raw!
|
||||
if (Game::s_elemFields[i].handler(&session, element)) break;
|
||||
Components::Logger::Error("Failed to parse element %s!\n", newValue);
|
||||
Components::Logger::Error("Failed to parse element %s!\n", newValue.data());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -57,7 +57,7 @@ namespace Components
|
||||
UIFeeder::Add(62.0f, Changelog::GetChangelogCount, Changelog::GetChangelogText, Changelog::SelectChangelog);
|
||||
|
||||
#if !defined(DEBUG) && !defined(DISABLE_ANTICHEAT)
|
||||
Scheduler::OnFrame(AntiCheat::QuickCodeScanner_1);
|
||||
Scheduler::OnFrame(AntiCheat::QuickCodeScanner1);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -2,20 +2,20 @@
|
||||
|
||||
namespace Components
|
||||
{
|
||||
std::string Clantags::Tags[18];
|
||||
std::string ClanTags::Tags[18];
|
||||
|
||||
void Clantags::ParseClantags(const char* infoString)
|
||||
void ClanTags::ParseClantags(const char* infoString)
|
||||
{
|
||||
for (int i = 0; i < 18; i++)
|
||||
{
|
||||
const char* clantag = Game::Info_ValueForKey(infoString, std::to_string(i).data());
|
||||
|
||||
if (clantag) Clantags::Tags[i] = clantag;
|
||||
else Clantags::Tags[i].clear();
|
||||
if (clantag) ClanTags::Tags[i] = clantag;
|
||||
else ClanTags::Tags[i].clear();
|
||||
}
|
||||
}
|
||||
|
||||
void Clantags::SendClantagsToClients()
|
||||
void ClanTags::SendClantagsToClients()
|
||||
{
|
||||
std::string list;
|
||||
|
||||
@ -35,18 +35,18 @@ namespace Components
|
||||
Game::SV_GameSendServerCommand(-1, 0, command.data());
|
||||
}
|
||||
|
||||
const char* Clantags::GetUserClantag(std::uint32_t /*clientnum*/, const char* playername)
|
||||
const char* ClanTags::GetUserClantag(std::uint32_t /*clientnum*/, const char* playername)
|
||||
{
|
||||
#if 0
|
||||
if (Clantags::Tags[clientnum].empty()) return playername;
|
||||
return Utils::String::VA("[%s] %s", Clantags::Tags[clientnum].data(), playername);
|
||||
if (ClanTags::Tags[clientnum].empty()) return playername;
|
||||
return Utils::String::VA("[%s] %s", ClanTags::Tags[clientnum].data(), playername);
|
||||
#else
|
||||
return playername;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
__declspec(naked) void Clantags::DrawPlayerNameOnScoreboard()
|
||||
__declspec(naked) void ClanTags::DrawPlayerNameOnScoreboard()
|
||||
{
|
||||
__asm
|
||||
{
|
||||
@ -56,7 +56,7 @@ namespace Components
|
||||
push edi
|
||||
push [ebp]
|
||||
|
||||
call Clantags::GetUserClantag
|
||||
call ClanTags::GetUserClantag
|
||||
add esp, 8
|
||||
|
||||
mov [esp + 20h], eax
|
||||
@ -70,7 +70,7 @@ namespace Components
|
||||
}
|
||||
}
|
||||
|
||||
Clantags::Clantags()
|
||||
ClanTags::ClanTags()
|
||||
{
|
||||
// Create clantag dvar
|
||||
Dvar::OnInit([]()
|
||||
@ -85,7 +85,7 @@ namespace Components
|
||||
{
|
||||
if (params->length() == 3)
|
||||
{
|
||||
Clantags::ParseClantags(params->get(2));
|
||||
ClanTags::ParseClantags(params->get(2));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -93,20 +93,20 @@ namespace Components
|
||||
return false;
|
||||
});
|
||||
|
||||
for (int i = 0; i < ARRAYSIZE(Clantags::Tags); ++i)
|
||||
for (int i = 0; i < ARRAYSIZE(ClanTags::Tags); ++i)
|
||||
{
|
||||
Clantags::Tags[i].clear();
|
||||
ClanTags::Tags[i].clear();
|
||||
}
|
||||
|
||||
// Draw clantag before playername
|
||||
Utils::Hook(0x591242, Clantags::DrawPlayerNameOnScoreboard).install()->quick();
|
||||
Utils::Hook(0x591242, ClanTags::DrawPlayerNameOnScoreboard).install()->quick();
|
||||
}
|
||||
|
||||
Clantags::~Clantags()
|
||||
ClanTags::~ClanTags()
|
||||
{
|
||||
for (int i = 0; i < ARRAYSIZE(Clantags::Tags); ++i)
|
||||
for (int i = 0; i < ARRAYSIZE(ClanTags::Tags); ++i)
|
||||
{
|
||||
Clantags::Tags[i].clear();
|
||||
ClanTags::Tags[i].clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,18 +2,18 @@
|
||||
|
||||
namespace Components
|
||||
{
|
||||
class Clantags : public Component
|
||||
class ClanTags : public Component
|
||||
{
|
||||
public:
|
||||
static void ParseClantags(const char * infoString);
|
||||
static void SendClantagsToClients();
|
||||
static const char* GetUserClantag(std::uint32_t clientnum, const char * playername);
|
||||
|
||||
Clantags();
|
||||
~Clantags();
|
||||
ClanTags();
|
||||
~ClanTags();
|
||||
|
||||
private:
|
||||
static std::string Clantags::Tags[18];
|
||||
static std::string ClanTags::Tags[18];
|
||||
|
||||
static void DrawPlayerNameOnScoreboard();
|
||||
|
||||
|
@ -86,6 +86,20 @@ namespace Components
|
||||
return std::string(buffer);
|
||||
}
|
||||
|
||||
void Colors::UserInfoCopy(char* buffer, const char* name, size_t size)
|
||||
{
|
||||
Utils::Memory::Allocator allocator;
|
||||
|
||||
if (!Dvar::Var("sv_allowColoredNames").get<bool>())
|
||||
{
|
||||
Colors::Strip(name, buffer, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
strncpy_s(buffer, size, name, size);
|
||||
}
|
||||
}
|
||||
|
||||
__declspec(naked) void Colors::ClientUserinfoChanged()
|
||||
{
|
||||
__asm
|
||||
@ -97,7 +111,7 @@ namespace Components
|
||||
push ecx // name
|
||||
push edx // buffer
|
||||
|
||||
call strncpy
|
||||
call Colors::UserInfoCopy
|
||||
|
||||
add esp, 0Ch
|
||||
retn
|
||||
@ -109,7 +123,7 @@ namespace Components
|
||||
Game::CL_GetClientName(localClientNum, index, buf, size);
|
||||
|
||||
// Append clantag to username & remove the colors
|
||||
strncpy_s(buf, size, Colors::Strip(Clantags::GetUserClantag(index, buf)).data(), size);
|
||||
strncpy_s(buf, size, Colors::Strip(ClanTags::GetUserClantag(index, buf)).data(), size);
|
||||
|
||||
return buf;
|
||||
}
|
||||
@ -227,6 +241,7 @@ namespace Components
|
||||
// Register dvar
|
||||
Colors::NewColors = Dvar::Register<bool>("cg_newColors", true, Game::dvar_flag::DVAR_FLAG_SAVED, "Use Warfare² color code style.");
|
||||
Game::Dvar_RegisterColor("sv_customTextColor", 1, 0.7f, 0, 1, Game::dvar_flag::DVAR_FLAG_REPLICATED, "Color for the extended color code.");
|
||||
Dvar::Register<bool>("sv_allowColoredNames", true, Game::dvar_flag::DVAR_FLAG_NONE, "Allow colored names on the server");
|
||||
|
||||
// Add our colors
|
||||
Colors::Add(0, 0, 0); // 0 - Black
|
||||
|
@ -25,6 +25,8 @@ namespace Components
|
||||
|
||||
static DWORD HsvToRgb(HsvColor hsv);
|
||||
|
||||
static void UserInfoCopy(char* buffer, const char* name, size_t size);
|
||||
|
||||
static void ClientUserinfoChanged();
|
||||
static char* GetClientName(int localClientNum, int index, char *buf, size_t size);
|
||||
static void PatchColorLimit(char limit);
|
||||
|
@ -491,7 +491,7 @@ namespace Components
|
||||
|
||||
void Console::FreeNativeConsole()
|
||||
{
|
||||
if (!Monitor::IsEnabled() && !Flags::HasFlag("stdout") && (!Dedicated::IsEnabled() || Flags::HasFlag("console")))
|
||||
if (!Monitor::IsEnabled() && !Flags::HasFlag("stdout") && (!Dedicated::IsEnabled() || Flags::HasFlag("console")) && !Loader::PerformingUnitTests())
|
||||
{
|
||||
FreeConsole();
|
||||
}
|
||||
@ -643,7 +643,7 @@ namespace Components
|
||||
Utils::Hook(0x43D570, Console::Error, HOOK_JUMP).install()->quick();
|
||||
Utils::Hook(0x4859A5, Console::Input, HOOK_CALL).install()->quick();
|
||||
}
|
||||
else
|
||||
else if(!Loader::PerformingUnitTests())
|
||||
{
|
||||
FreeConsole();
|
||||
}
|
||||
|
@ -8,14 +8,14 @@ namespace Components
|
||||
|
||||
bool Dedicated::IsEnabled()
|
||||
{
|
||||
static Utils::Value<bool> flag;
|
||||
static std::optional<bool> flag;
|
||||
|
||||
if (!flag.isValid())
|
||||
if (!flag.has_value())
|
||||
{
|
||||
flag.set(Flags::HasFlag("dedicated"));
|
||||
flag.emplace(Flags::HasFlag("dedicated"));
|
||||
}
|
||||
|
||||
return flag.get();
|
||||
return flag.value();
|
||||
}
|
||||
|
||||
void Dedicated::InitDedicatedServer()
|
||||
|
@ -11,12 +11,12 @@ namespace Components
|
||||
|
||||
#pragma region Client
|
||||
|
||||
void Download::InitiateMapDownload(std::string map)
|
||||
void Download::InitiateMapDownload(std::string map, bool needPassword)
|
||||
{
|
||||
Download::InitiateClientDownload(map, true);
|
||||
Download::InitiateClientDownload(map, needPassword, true);
|
||||
}
|
||||
|
||||
void Download::InitiateClientDownload(std::string mod, bool map)
|
||||
void Download::InitiateClientDownload(std::string mod, bool needPassword, bool map)
|
||||
{
|
||||
if (Download::CLDownload.running) return;
|
||||
|
||||
@ -29,6 +29,18 @@ namespace Components
|
||||
|
||||
Command::Execute("openmenu mod_download_popmenu", false);
|
||||
|
||||
if (needPassword)
|
||||
{
|
||||
std::string pass = Dvar::Var("password").get<std::string>();
|
||||
if (!pass.length())
|
||||
{
|
||||
// shouldn't ever happen but this is safe
|
||||
Party::ConnectError("A password is required to connect to this server!");
|
||||
return;
|
||||
}
|
||||
Download::CLDownload.hashedPassword = Utils::Cryptography::SHA256::Compute(pass);
|
||||
}
|
||||
|
||||
Download::CLDownload.running = true;
|
||||
Download::CLDownload.isMap = map;
|
||||
Download::CLDownload.mod = mod;
|
||||
@ -37,6 +49,7 @@ namespace Components
|
||||
Download::CLDownload.lastTimeStamp = 0;
|
||||
Download::CLDownload.downBytes = 0;
|
||||
Download::CLDownload.timeStampBytes = 0;
|
||||
Download::CLDownload.isPrivate = needPassword;
|
||||
Download::CLDownload.target = Party::Target();
|
||||
Download::CLDownload.thread = std::thread(Download::ModDownloader, &Download::CLDownload);
|
||||
}
|
||||
@ -216,7 +229,8 @@ namespace Components
|
||||
}
|
||||
else
|
||||
{
|
||||
url = host + "/file/" + (download->isMap ? "map/" : "") + file.name;
|
||||
url = host + "/file/" + (download->isMap ? "map/" : "") + file.name
|
||||
+ (download->isPrivate ? ("?password=" + download->hashedPassword) : "");
|
||||
}
|
||||
|
||||
Download::FileDownload fDownload;
|
||||
@ -258,7 +272,9 @@ namespace Components
|
||||
|
||||
std::string host = "http://" + download->target.getString();
|
||||
|
||||
std::string list = Utils::WebIO("IW4x", host + (download->isMap ? "/map" : "/list")).setTimeout(5000)->get();
|
||||
std::string listUrl = host + (download->isMap ? "/map" : "/list") + (download->isPrivate ? ("?password=" + download->hashedPassword) : "");
|
||||
|
||||
std::string list = Utils::WebIO("IW4x", listUrl).setTimeout(5000)->get();
|
||||
if (list.empty())
|
||||
{
|
||||
if (download->terminateThread) return;
|
||||
@ -386,6 +402,31 @@ namespace Components
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool Download::VerifyPassword(mg_connection *nc, http_message* message)
|
||||
{
|
||||
std::string g_password = Dvar::Var("g_password").get<std::string>();
|
||||
|
||||
if (!g_password.size()) return true;
|
||||
|
||||
// sha256 hashes are 64 chars long but we're gonna be safe here
|
||||
char buffer[128] = { 0 };
|
||||
int passLen = mg_get_http_var(&message->query_string, "password", buffer, sizeof buffer);
|
||||
|
||||
if (passLen <= 0 || std::string(buffer, passLen) != g_password)//Utils::Cryptography::SHA256::Compute(g_password))
|
||||
{
|
||||
mg_printf(nc, ("HTTP/1.1 403 Forbidden\r\n"s +
|
||||
"Content-Type: text/html\r\n"s +
|
||||
"Connection: close\r\n"s +
|
||||
"\r\n"s +
|
||||
((passLen == 0) ? "Password Required"s : "Invalid Password"s)).c_str());
|
||||
|
||||
nc->flags |= MG_F_SEND_AND_CLOSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Download::Forbid(mg_connection *nc)
|
||||
{
|
||||
mg_printf(nc, "HTTP/1.1 403 Forbidden\r\n"
|
||||
@ -397,11 +438,13 @@ namespace Components
|
||||
nc->flags |= MG_F_SEND_AND_CLOSE;
|
||||
}
|
||||
|
||||
void Download::MapHandler(mg_connection *nc, int ev, void* /*ev_data*/)
|
||||
void Download::MapHandler(mg_connection *nc, int ev, void* ev_data)
|
||||
{
|
||||
// Only handle http requests
|
||||
if (ev != MG_EV_HTTP_REQUEST) return;
|
||||
|
||||
if (!Download::VerifyPassword(nc, reinterpret_cast<http_message*>(ev_data))) return;
|
||||
|
||||
static std::string mapnamePre;
|
||||
static json11::Json jsonList;
|
||||
|
||||
@ -448,11 +491,13 @@ namespace Components
|
||||
nc->flags |= MG_F_SEND_AND_CLOSE;
|
||||
}
|
||||
|
||||
void Download::ListHandler(mg_connection* nc, int ev, void* /*ev_data*/)
|
||||
void Download::ListHandler(mg_connection* nc, int ev, void* ev_data)
|
||||
{
|
||||
// Only handle http requests
|
||||
if (ev != MG_EV_HTTP_REQUEST) return;
|
||||
|
||||
if (!Download::VerifyPassword(nc, reinterpret_cast<http_message*>(ev_data))) return;
|
||||
|
||||
// if (!Download::IsClient(nc))
|
||||
// {
|
||||
// Download::Forbid(nc);
|
||||
@ -512,6 +557,8 @@ namespace Components
|
||||
|
||||
http_message* message = reinterpret_cast<http_message*>(ev_data);
|
||||
|
||||
//if (!Download::VerifyPassword(nc, message)) return;
|
||||
|
||||
// if (!Download::IsClient(nc))
|
||||
// {
|
||||
// Download::Forbid(nc);
|
||||
@ -597,7 +644,7 @@ namespace Components
|
||||
// Only handle http requests
|
||||
if (ev != MG_EV_HTTP_REQUEST) return;
|
||||
|
||||
//http_message* message = reinterpret_cast<http_message*>(ev_data);
|
||||
//if (!Download::VerifyPassword(nc, reinterpret_cast<http_message*>(ev_data))) return;
|
||||
|
||||
Utils::InfoString status = ServerInfo::GetInfo();
|
||||
|
||||
|
@ -11,8 +11,8 @@ namespace Components
|
||||
|
||||
void preDestroy() override;
|
||||
|
||||
static void InitiateClientDownload(std::string mod, bool map = false);
|
||||
static void InitiateMapDownload(std::string map);
|
||||
static void InitiateClientDownload(std::string mod, bool needPassword, bool map = false);
|
||||
static void InitiateMapDownload(std::string map, bool needPassword);
|
||||
|
||||
private:
|
||||
class ClientDownload
|
||||
@ -25,8 +25,10 @@ namespace Components
|
||||
bool valid;
|
||||
bool terminateThread;
|
||||
bool isMap;
|
||||
bool isPrivate;
|
||||
mg_mgr mgr;
|
||||
Network::Address target;
|
||||
std::string hashedPassword;
|
||||
std::string mod;
|
||||
std::thread thread;
|
||||
|
||||
@ -209,6 +211,8 @@ namespace Components
|
||||
static std::thread ServerThread;
|
||||
static bool Terminate;
|
||||
|
||||
static bool VerifyPassword(mg_connection *nc, http_message* message);
|
||||
|
||||
static void EventHandler(mg_connection *nc, int ev, void *ev_data);
|
||||
static void ListHandler(mg_connection *nc, int ev, void *ev_data);
|
||||
static void MapHandler(mg_connection *nc, int ev, void *ev_data);
|
||||
|
@ -345,12 +345,10 @@ namespace Components
|
||||
{
|
||||
Logger::Error("The fastfile you are trying to load is outdated (%d, expected %d)", header[1], XFILE_VERSION_IW4X);
|
||||
}
|
||||
#ifdef DEBUG
|
||||
else if (header[1] > XFILE_VERSION_IW4X)
|
||||
{
|
||||
Logger::Error("You are loading a fastfile that is too new (%d, expected %d), how's that possible?", header[1], XFILE_VERSION_IW4X);
|
||||
Logger::Error("You are loading a fastfile that is too new (%d, expected %d), update your game", header[1], XFILE_VERSION_IW4X);
|
||||
}
|
||||
#endif
|
||||
|
||||
*reinterpret_cast<unsigned __int64*>(header) = XFILE_MAGIC_UNSIGNED;
|
||||
}
|
||||
|
@ -164,7 +164,7 @@ namespace Components
|
||||
{
|
||||
std::vector<int> ids;
|
||||
|
||||
auto addId = [&](int id)
|
||||
const auto addId = [&](int id)
|
||||
{
|
||||
if (std::find(ids.begin(), ids.end(), id) == ids.end())
|
||||
{
|
||||
@ -186,8 +186,7 @@ namespace Components
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> _(Friends::Mutex);
|
||||
|
||||
char* mod = "IW4x";
|
||||
unsigned int modId = *reinterpret_cast<unsigned int*>(mod) | 0x80000000;
|
||||
const unsigned int modId = *reinterpret_cast<unsigned int*>("IW4x") | 0x80000000;
|
||||
|
||||
// Split up the list
|
||||
for (auto entry : Friends::FriendsList)
|
||||
@ -283,15 +282,15 @@ namespace Components
|
||||
|
||||
void Friends::UpdateRank()
|
||||
{
|
||||
static Utils::Value<int> levelVal;
|
||||
static std::optional<int> levelVal;
|
||||
|
||||
int experience = Game::Live_GetXp(0);
|
||||
int prestige = Game::Live_GetPrestige(0);
|
||||
int level = (experience & 0xFFFFFF) | ((prestige & 0xFF) << 24);
|
||||
|
||||
if(!levelVal.isValid() || levelVal.get() != level)
|
||||
if (!levelVal.has_value() || levelVal.value() != level)
|
||||
{
|
||||
levelVal.set(level);
|
||||
levelVal.emplace(level);
|
||||
|
||||
Friends::SetPresence("iw4x_experience", Utils::String::VA("%d", experience));
|
||||
Friends::SetPresence("iw4x_prestige", Utils::String::VA("%d", prestige));
|
||||
|
@ -9,7 +9,6 @@ namespace Components
|
||||
|
||||
bool Maps::SPMap;
|
||||
std::vector<Maps::DLC> Maps::DlcPacks;
|
||||
std::vector<Game::XAssetEntry> Maps::EntryPool;
|
||||
|
||||
const char* Maps::UserMapFiles[4] =
|
||||
{
|
||||
@ -713,59 +712,7 @@ namespace Components
|
||||
|
||||
Game::XAssetEntry* Maps::GetAssetEntryPool()
|
||||
{
|
||||
if(Maps::EntryPool.empty())
|
||||
{
|
||||
return reinterpret_cast<Game::XAssetEntry*>(0x134CAD8);
|
||||
}
|
||||
|
||||
return Maps::EntryPool.data();
|
||||
}
|
||||
|
||||
void Maps::reallocateEntryPool()
|
||||
{
|
||||
AssertSize(Game::XAssetEntry, 16);
|
||||
|
||||
Maps::EntryPool.clear();
|
||||
|
||||
if (ZoneBuilder::IsEnabled())
|
||||
{
|
||||
Maps::EntryPool.resize(1183968);
|
||||
}
|
||||
else
|
||||
{
|
||||
Maps::EntryPool.resize(789312);
|
||||
}
|
||||
|
||||
// Apply new size
|
||||
Utils::Hook::Set<DWORD>(0x5BAEB0, Maps::EntryPool.size());
|
||||
|
||||
// Apply new pool
|
||||
Utils::Hook::Set<Game::XAssetEntry*>(0x48E6F4, Maps::EntryPool.data());
|
||||
Utils::Hook::Set<Game::XAssetEntry*>(0x4C67E4, Maps::EntryPool.data());
|
||||
Utils::Hook::Set<Game::XAssetEntry*>(0x4C8584, Maps::EntryPool.data());
|
||||
Utils::Hook::Set<Game::XAssetEntry*>(0x5BAEA8, Maps::EntryPool.data());
|
||||
Utils::Hook::Set<Game::XAssetEntry*>(0x5BB0C4, Maps::EntryPool.data());
|
||||
Utils::Hook::Set<Game::XAssetEntry*>(0x5BB0F5, Maps::EntryPool.data());
|
||||
Utils::Hook::Set<Game::XAssetEntry*>(0x5BB1D4, Maps::EntryPool.data());
|
||||
Utils::Hook::Set<Game::XAssetEntry*>(0x5BB235, Maps::EntryPool.data());
|
||||
Utils::Hook::Set<Game::XAssetEntry*>(0x5BB278, Maps::EntryPool.data());
|
||||
Utils::Hook::Set<Game::XAssetEntry*>(0x5BB34C, Maps::EntryPool.data());
|
||||
Utils::Hook::Set<Game::XAssetEntry*>(0x5BB484, Maps::EntryPool.data());
|
||||
Utils::Hook::Set<Game::XAssetEntry*>(0x5BB570, Maps::EntryPool.data());
|
||||
Utils::Hook::Set<Game::XAssetEntry*>(0x5BB6B7, Maps::EntryPool.data());
|
||||
Utils::Hook::Set<Game::XAssetEntry*>(0x5BB844, Maps::EntryPool.data());
|
||||
Utils::Hook::Set<Game::XAssetEntry*>(0x5BB98D, Maps::EntryPool.data());
|
||||
Utils::Hook::Set<Game::XAssetEntry*>(0x5BBA66, Maps::EntryPool.data());
|
||||
Utils::Hook::Set<Game::XAssetEntry*>(0x5BBB8D, Maps::EntryPool.data());
|
||||
Utils::Hook::Set<Game::XAssetEntry*>(0x5BBCB1, Maps::EntryPool.data());
|
||||
Utils::Hook::Set<Game::XAssetEntry*>(0x5BBD9B, Maps::EntryPool.data());
|
||||
Utils::Hook::Set<Game::XAssetEntry*>(0x5BBE4C, Maps::EntryPool.data());
|
||||
Utils::Hook::Set<Game::XAssetEntry*>(0x5BBF14, Maps::EntryPool.data());
|
||||
Utils::Hook::Set<Game::XAssetEntry*>(0x5BBF54, Maps::EntryPool.data());
|
||||
Utils::Hook::Set<Game::XAssetEntry*>(0x5BBFB8, Maps::EntryPool.data());
|
||||
|
||||
Utils::Hook::Set<Game::XAssetEntry*>(0x5BAE91, Maps::EntryPool.data() + 1);
|
||||
Utils::Hook::Set<Game::XAssetEntry*>(0x5BAEA2, Maps::EntryPool.data() + 1);
|
||||
return *reinterpret_cast<Game::XAssetEntry**>(0x48E6F4);
|
||||
}
|
||||
|
||||
// dlcIsTrue serves as a check if the map is a custom map and if it's missing
|
||||
@ -1022,24 +969,6 @@ namespace Components
|
||||
// Load usermap arena file
|
||||
Utils::Hook(0x630A88, Maps::LoadArenaFileStub, HOOK_CALL).install()->quick();
|
||||
|
||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_GAMEWORLD_SP, 1);
|
||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_IMAGE, 7168);
|
||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_LOADED_SOUND, 2700);
|
||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_FX, 1200);
|
||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_LOCALIZE_ENTRY, 14000);
|
||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_XANIMPARTS, 8192);
|
||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_XMODEL, 5125);
|
||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_PHYSPRESET, 128);
|
||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_PIXELSHADER, 10000);
|
||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_VERTEXSHADER, 3072);
|
||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_MATERIAL, 8192);
|
||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_VERTEXDECL, 196);
|
||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_WEAPON, WEAPON_LIMIT);
|
||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_STRINGTABLE, 800);
|
||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_IMPACT_FX, 8);
|
||||
|
||||
this->reallocateEntryPool();
|
||||
|
||||
// Dependencies
|
||||
//Maps::AddDependency("oilrig", "mp_subbase");
|
||||
//Maps::AddDependency("gulag", "mp_subbase");
|
||||
@ -1113,7 +1042,5 @@ namespace Components
|
||||
Maps::DependencyList.clear();
|
||||
Maps::CurrentMainZone.clear();
|
||||
Maps::CurrentDependencies.clear();
|
||||
|
||||
Maps::EntryPool.clear();
|
||||
}
|
||||
}
|
||||
|
@ -78,7 +78,6 @@ namespace Components
|
||||
static bool SPMap;
|
||||
static UserMapContainer UserMap;
|
||||
static std::vector<DLC> DlcPacks;
|
||||
static std::vector<Game::XAssetEntry> EntryPool;
|
||||
|
||||
static std::vector<std::pair<std::string, std::string>> DependencyList;
|
||||
static std::vector<std::string> CurrentDependencies;
|
||||
@ -123,7 +122,5 @@ namespace Components
|
||||
static Game::dvar_t* GetSpecularDvar();
|
||||
static void SetSpecularStub1();
|
||||
static void SetSpecularStub2();
|
||||
|
||||
void reallocateEntryPool();
|
||||
};
|
||||
}
|
||||
|
@ -767,7 +767,7 @@ namespace Components
|
||||
});
|
||||
|
||||
#if !defined(DEBUG) && !defined(DISABLE_ANTICHEAT)
|
||||
Scheduler::OnFrame(AntiCheat::QuickCodeScanner_2);
|
||||
Scheduler::OnFrame(AntiCheat::QuickCodeScanner2);
|
||||
#endif
|
||||
|
||||
Command::Add("mp_QuickMessage", [](Command::Params*)
|
||||
|
@ -7,14 +7,14 @@ namespace Components
|
||||
{
|
||||
bool Monitor::IsEnabled()
|
||||
{
|
||||
static Utils::Value<bool> flag;
|
||||
static std::optional<bool> flag;
|
||||
|
||||
if (!flag.isValid())
|
||||
if (!flag.has_value())
|
||||
{
|
||||
flag.set(Flags::HasFlag("monitor"));
|
||||
flag.emplace(Flags::HasFlag("monitor"));
|
||||
}
|
||||
|
||||
return flag.get();
|
||||
return flag.value();
|
||||
}
|
||||
|
||||
int __stdcall Monitor::EntryPoint(HINSTANCE /*hInstance*/, HINSTANCE /*hPrevInstance*/, LPSTR /*lpCmdLine*/, int /*nShowCmd*/)
|
||||
|
@ -17,9 +17,9 @@ namespace Components
|
||||
{
|
||||
Game::snd_alias_list_t* aliases = Game::DB_FindXAssetHeader(type, filename.data()).sound;
|
||||
|
||||
if (aliases)
|
||||
if (aliases && aliases->count > 0 && aliases->head && aliases->head->soundFile)
|
||||
{
|
||||
if (aliases->head->soundFile->type == 2)
|
||||
if (aliases->head->soundFile->type == Game::snd_alias_type_t::SAT_STREAMED)
|
||||
{
|
||||
aliases->head->soundFile->data.stream.name = MusicalTalent::SoundAliasList[Utils::String::ToLower(filename)];
|
||||
}
|
||||
|
@ -430,15 +430,19 @@ namespace Components
|
||||
{
|
||||
Party::ConnectError("Invalid map or gametype.");
|
||||
}
|
||||
else if (Party::Container.info.get("isPrivate") == "1"s && !Dvar::Var("password").get<std::string>().length())
|
||||
{
|
||||
Party::ConnectError("A password is required to join this server! Set it at the bottom of the serverlist.");
|
||||
}
|
||||
else if (isUsermap && usermapHash != Maps::GetUsermapHash(info.get("mapname")))
|
||||
{
|
||||
Command::Execute("closemenu popup_reconnectingtoparty");
|
||||
Download::InitiateMapDownload(info.get("mapname"));
|
||||
Download::InitiateMapDownload(info.get("mapname"), info.get("isPrivate") == "1");
|
||||
}
|
||||
else if (!info.get("fs_game").empty() && Utils::String::ToLower(mod) != Utils::String::ToLower(info.get("fs_game")))
|
||||
{
|
||||
Command::Execute("closemenu popup_reconnectingtoparty");
|
||||
Download::InitiateClientDownload(info.get("fs_game"));
|
||||
Download::InitiateClientDownload(info.get("fs_game"), info.get("isPrivate") == "1"s);
|
||||
}
|
||||
else if (!Dvar::Var("fs_game").get<std::string>().empty() && info.get("fs_game").empty())
|
||||
{
|
||||
@ -462,7 +466,7 @@ namespace Components
|
||||
// Send playlist request
|
||||
Party::Container.requestTime = Game::Sys_Milliseconds();
|
||||
Party::Container.awaitingPlaylist = true;
|
||||
Network::SendCommand(Party::Container.target, "getplaylist");
|
||||
Network::SendCommand(Party::Container.target, "getplaylist", Dvar::Var("password").get<std::string>());
|
||||
|
||||
// This is not a safe method
|
||||
// TODO: Fix actual error!
|
||||
|
@ -45,6 +45,16 @@ namespace Components
|
||||
|
||||
void Playlist::PlaylistRequest(Network::Address address, std::string data)
|
||||
{
|
||||
std::string password = Dvar::Var("g_password").get<std::string>();
|
||||
if (password.length())
|
||||
{
|
||||
if (password != data)
|
||||
{
|
||||
Network::SendCommand(address, "playlistInvalidPassword");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Logger::Print("Received playlist request, sending currently stored buffer.\n");
|
||||
|
||||
std::string compressedList = Utils::Compression::ZLib::Compress(Playlist::CurrentPlaylistBuffer);
|
||||
@ -104,6 +114,11 @@ namespace Components
|
||||
}
|
||||
}
|
||||
|
||||
void Playlist::PlaylistInvalidPassword(Network::Address /*address*/, std::string /*data*/)
|
||||
{
|
||||
Party::PlaylistError("Error: Invalid Password for Party.");
|
||||
}
|
||||
|
||||
void Playlist::MapNameCopy(char *dest, const char *src, int destsize)
|
||||
{
|
||||
Utils::Hook::Call<void(char*, const char*, int)>(0x4D6F80)(dest, src, destsize);
|
||||
@ -173,6 +188,7 @@ namespace Components
|
||||
|
||||
Network::Handle("getPlaylist", PlaylistRequest);
|
||||
Network::Handle("playlistResponse", PlaylistReponse);
|
||||
Network::Handle("playlistInvalidPassword", PlaylistInvalidPassword);
|
||||
}
|
||||
|
||||
Playlist::~Playlist()
|
||||
|
@ -22,6 +22,7 @@ namespace Components
|
||||
|
||||
static void PlaylistRequest(Network::Address address, std::string data);
|
||||
static void PlaylistReponse(Network::Address address, std::string data);
|
||||
static void PlaylistInvalidPassword(Network::Address address, std::string data);
|
||||
|
||||
static void MapNameCopy(char *dest, const char *src, int destsize);
|
||||
static void SetMapName(const char* cvar, const char* value);
|
||||
|
@ -735,6 +735,21 @@ namespace Components
|
||||
}
|
||||
}
|
||||
|
||||
printf("Success\n");
|
||||
|
||||
printf("Testing trimming...");
|
||||
std::string trim1 = " 1 ";
|
||||
std::string trim2 = " 1";
|
||||
std::string trim3 = "1 ";
|
||||
|
||||
Utils::String::Trim(trim1);
|
||||
Utils::String::LTrim(trim2);
|
||||
Utils::String::RTrim(trim3);
|
||||
|
||||
if (trim1 != "1") return false;
|
||||
if (trim2 != "1") return false;
|
||||
if (trim3 != "1") return false;
|
||||
|
||||
printf("Success\n");
|
||||
return true;
|
||||
}
|
||||
|
@ -746,8 +746,7 @@ namespace Components
|
||||
do
|
||||
{
|
||||
entry = reinterpret_cast<ServerList::MasterEntry*>(const_cast<char*>(data.data()) + offset++);
|
||||
}
|
||||
while (!entry->HasSeparator() && !entry->IsEndToken());
|
||||
} while (!entry->HasSeparator() && !entry->IsEndToken());
|
||||
|
||||
for (int i = 0; !entry[i].IsEndToken() && entry[i].HasSeparator(); ++i)
|
||||
{
|
||||
|
@ -37,5 +37,4 @@ namespace Components
|
||||
{
|
||||
StartupMessages::MessageList.push_back(message);
|
||||
}
|
||||
|
||||
}
|
@ -70,6 +70,7 @@ namespace Components
|
||||
|
||||
// ToDo: Allow playerdata changes in setPlayerData UI script.
|
||||
}
|
||||
|
||||
Stats::~Stats()
|
||||
{
|
||||
|
||||
|
@ -55,7 +55,7 @@ namespace Components
|
||||
Game::Font* font = Game::DB_FindXAssetHeader(Game::XAssetType::ASSET_TYPE_FONT, "fonts/objectiveFont").font; if (!font) return;
|
||||
Game::Font* descfont = Game::DB_FindXAssetHeader(Game::XAssetType::ASSET_TYPE_FONT, "fonts/normalFont").font; if (!descfont) return;
|
||||
Game::vec4_t wColor = { 1.0f, 1.0f, 1.0f, 1.0f };
|
||||
Game::vec4_t bgColor = { 0.0f, 0.0f, 0.0f, 0.5f };
|
||||
Game::vec4_t bgColor = { 0.0f, 0.0f, 0.0f, 0.8f };
|
||||
Game::vec4_t borderColor = { 1.0f, 1.0f, 1.0f, 0.2f };
|
||||
|
||||
height /= 5;
|
||||
|
@ -506,7 +506,7 @@ namespace Components
|
||||
// Add branding asset
|
||||
void ZoneBuilder::Zone::addBranding()
|
||||
{
|
||||
char* data = "FastFile built using IW4x ZoneTool!";
|
||||
char* data = "FastFile built using the IW4x ZoneBuilder!";
|
||||
this->branding = { this->zoneName.data(), static_cast<int>(strlen(data)), 0, data };
|
||||
|
||||
if (this->findAsset(Game::XAssetType::ASSET_TYPE_RAWFILE, this->branding.name) != -1)
|
||||
@ -664,14 +664,14 @@ namespace Components
|
||||
|
||||
bool ZoneBuilder::IsEnabled()
|
||||
{
|
||||
static Utils::Value<bool> flag;
|
||||
static std::optional<bool> flag;
|
||||
|
||||
if (!flag.isValid())
|
||||
if (!flag.has_value())
|
||||
{
|
||||
flag.set(Flags::HasFlag("zonebuilder"));
|
||||
flag.emplace(Flags::HasFlag("zonebuilder"));
|
||||
}
|
||||
|
||||
return (flag.get() && !Dedicated::IsEnabled());
|
||||
return (flag.value() && !Dedicated::IsEnabled());
|
||||
}
|
||||
|
||||
void ZoneBuilder::BeginAssetTrace(std::string zone)
|
||||
@ -1034,17 +1034,6 @@ namespace Components
|
||||
// Don't read stats
|
||||
Utils::Hook(0x4875E1, 0x487717, HOOK_JUMP).install()->quick();
|
||||
|
||||
// Increase asset pools
|
||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_MAP_ENTS, 10);
|
||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_XMODELSURFS, 8192);
|
||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_IMAGE, 14336);
|
||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_TECHNIQUE_SET, 0x2000);
|
||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_PIXELSHADER, 0x4000);
|
||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_VERTEXSHADER, 0x2000);
|
||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_VERTEXDECL, 0x400);
|
||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_FONT, 32);
|
||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_RAWFILE, 2048);
|
||||
|
||||
// patch g_copyInfo because we're using so many more assets than originally intended
|
||||
int newLimit = 0x2000;
|
||||
int* g_copyInfo_new = Utils::Memory::GetAllocator()->allocateArray<int>(newLimit);
|
||||
|
@ -222,14 +222,12 @@ namespace Game
|
||||
const void *initial_ptr;
|
||||
};
|
||||
|
||||
/* 526 */
|
||||
struct MssSound
|
||||
{
|
||||
_AILSOUNDINFO info;
|
||||
char *data;
|
||||
};
|
||||
|
||||
/* 527 */
|
||||
struct LoadedSound
|
||||
{
|
||||
const char *name;
|
||||
@ -242,7 +240,7 @@ namespace Game
|
||||
StreamedSound stream;
|
||||
};
|
||||
|
||||
struct SoundFile // 0xC
|
||||
struct SoundFile
|
||||
{
|
||||
snd_alias_type_t type;
|
||||
bool exists;
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
#ifndef RC_INVOKED
|
||||
|
||||
#define _HAS_CXX17 1
|
||||
#define VC_EXTRALEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
|
||||
@ -33,12 +34,12 @@
|
||||
#include <regex>
|
||||
#include <thread>
|
||||
#include <future>
|
||||
#include <queue>
|
||||
#include <unordered_map>
|
||||
#include <queue>
|
||||
|
||||
// Experimental C++17 features
|
||||
#include <filesystem>
|
||||
#include <optional>
|
||||
|
||||
#pragma warning(pop)
|
||||
|
||||
|
@ -6,12 +6,12 @@ namespace Steam
|
||||
{
|
||||
unsigned int Utils::GetSecondsSinceAppActive()
|
||||
{
|
||||
return 0;
|
||||
return Game::Sys_Milliseconds() / 1000;
|
||||
}
|
||||
|
||||
unsigned int Utils::GetSecondsSinceComputerActive()
|
||||
{
|
||||
return 0;
|
||||
return timeGetTime();
|
||||
}
|
||||
|
||||
int Utils::GetConnectedUniverse()
|
||||
@ -21,25 +21,28 @@ namespace Steam
|
||||
|
||||
unsigned int Utils::GetServerRealTime()
|
||||
{
|
||||
static ::Utils::Value<unsigned int> timeDelta;
|
||||
|
||||
if(!timeDelta.isValid())
|
||||
static std::optional<unsigned int> timeDelta;
|
||||
if(!timeDelta.has_value())
|
||||
{
|
||||
unsigned int steamTime = static_cast<unsigned int>(time(nullptr));
|
||||
|
||||
if(Steam::Proxy::SteamUtils)
|
||||
{
|
||||
steamTime = Steam::Proxy::SteamUtils->GetServerRealTime();
|
||||
}
|
||||
|
||||
timeDelta.set(steamTime - (Game::Sys_Milliseconds() / 1000));
|
||||
timeDelta.emplace(steamTime - (Game::Sys_Milliseconds() / 1000));
|
||||
}
|
||||
|
||||
return timeDelta.get() + (Game::Sys_Milliseconds() / 1000);
|
||||
return timeDelta.value() + (Game::Sys_Milliseconds() / 1000);
|
||||
}
|
||||
|
||||
const char* Utils::GetIPCountry()
|
||||
{
|
||||
if (Steam::Proxy::SteamUtils)
|
||||
{
|
||||
return Steam::Proxy::SteamUtils->GetIPCountry();
|
||||
}
|
||||
|
||||
return "US";
|
||||
}
|
||||
|
||||
@ -60,6 +63,11 @@ namespace Steam
|
||||
|
||||
unsigned char Utils::GetCurrentBatteryPower()
|
||||
{
|
||||
if (Steam::Proxy::SteamUtils)
|
||||
{
|
||||
return Steam::Proxy::SteamUtils->GetCurrentBatteryPower();
|
||||
}
|
||||
|
||||
return 255;
|
||||
}
|
||||
|
||||
|
@ -48,10 +48,8 @@ namespace Utils
|
||||
{
|
||||
ECC::Key key;
|
||||
|
||||
register_prng(&sprng_desc);
|
||||
|
||||
ltc_mp = ltm_desc;
|
||||
|
||||
register_prng(&sprng_desc);
|
||||
ecc_make_key(nullptr, find_prng("sprng"), bits / 8, key.getKeyPtr());
|
||||
|
||||
return key;
|
||||
@ -64,10 +62,8 @@ namespace Utils
|
||||
uint8_t buffer[512];
|
||||
DWORD length = sizeof(buffer);
|
||||
|
||||
register_prng(&sprng_desc);
|
||||
|
||||
ltc_mp = ltm_desc;
|
||||
|
||||
register_prng(&sprng_desc);
|
||||
ecc_sign_hash(reinterpret_cast<const uint8_t*>(message.data()), message.size(), buffer, &length, nullptr, find_prng("sprng"), key.getKeyPtr());
|
||||
|
||||
return std::string(reinterpret_cast<char*>(buffer), length);
|
||||
|
@ -113,14 +113,20 @@ namespace Utils
|
||||
// trim from start
|
||||
std::string <rim(std::string &s)
|
||||
{
|
||||
s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun<int, int>(IsSpace))));
|
||||
s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](int val)
|
||||
{
|
||||
return !IsSpace(val);
|
||||
}));
|
||||
return s;
|
||||
}
|
||||
|
||||
// trim from end
|
||||
std::string &RTrim(std::string &s)
|
||||
{
|
||||
s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun<int, int>(IsSpace))).base(), s.end());
|
||||
s.erase(std::find_if(s.rbegin(), s.rend(), [](int val)
|
||||
{
|
||||
return !IsSpace(val);
|
||||
}).base(), s.end());
|
||||
return s;
|
||||
}
|
||||
|
||||
|
@ -112,33 +112,4 @@ namespace Utils
|
||||
private:
|
||||
std::vector<Slot<T>> slots;
|
||||
};
|
||||
|
||||
// TODO: Replace with std::optional, once C++17 is fully available!
|
||||
template <typename T>
|
||||
class Value
|
||||
{
|
||||
public:
|
||||
Value() : hasValue(false) {}
|
||||
Value(T _value) { this->set(_value); }
|
||||
|
||||
void set(T _value)
|
||||
{
|
||||
this->value = _value;
|
||||
this->hasValue = true;
|
||||
}
|
||||
|
||||
bool isValid()
|
||||
{
|
||||
return this->hasValue;
|
||||
}
|
||||
|
||||
T get()
|
||||
{
|
||||
return this->value;
|
||||
}
|
||||
|
||||
private:
|
||||
bool hasValue;
|
||||
T value;
|
||||
};
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user