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"]
|
[submodule "deps/mongoose"]
|
||||||
path = deps/mongoose
|
path = deps/mongoose
|
||||||
url = https://github.com/cesanta/mongoose.git
|
url = https://github.com/cesanta/mongoose.git
|
||||||
branch = master
|
branch = dev
|
||||||
[submodule "deps/protobuf"]
|
[submodule "deps/protobuf"]
|
||||||
path = deps/protobuf
|
path = deps/protobuf
|
||||||
url = https://github.com/google/protobuf.git
|
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
|
### Added
|
||||||
|
|
||||||
|
- Show friend avatars when they play IW4x (request)
|
||||||
|
- Cod4 style fast download for usermaps
|
||||||
- Display a toast when an update is available.
|
- Display a toast when an update is available.
|
||||||
- Use the hourglass cursor while loading assets (with the native cursor feature).
|
- 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).
|
- 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
|
### 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 lags and frame drops caused by server sorting.
|
||||||
- Fix demos on custom maps.
|
- Fix demos on custom maps.
|
||||||
|
|
||||||
|
4
Jenkinsfile
vendored
4
Jenkinsfile
vendored
@ -104,8 +104,8 @@ def doBuild(cfg) {
|
|||||||
|
|
||||||
useShippedPremake {
|
useShippedPremake {
|
||||||
def outputDir = pwd()
|
def outputDir = pwd()
|
||||||
def msbuild = tool "Microsoft.NET MSBuild 14.0"
|
def msbuild = tool "Microsoft.NET MSBuild 15.0"
|
||||||
bat "premake5 vs2015 ${cfg.PremakeArgs}"
|
bat "premake5 vs2017 ${cfg.PremakeArgs}"
|
||||||
bat "\"${msbuild}\" build\\iw4x.sln \"/p:OutDir=$outputDir\\\\\" \"/p:Configuration=${cfg.MSBuildConfiguration}\""
|
bat "\"${msbuild}\" build\\iw4x.sln \"/p:OutDir=$outputDir\\\\\" \"/p:Configuration=${cfg.MSBuildConfiguration}\""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
## How to compile
|
## 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.)
|
- Build via solution file in `build\iw4x.sln`. (You can use the `build.bat` script to do it quick and easy.)
|
||||||
|
|
||||||
## Premake arguments
|
## Premake arguments
|
||||||
|
@ -2,16 +2,16 @@
|
|||||||
|
|
||||||
cd %~dp0
|
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
|
msbuild /version >NUL 2>NUL
|
||||||
if errorlevel 0 goto:build
|
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
|
msbuild /version >NUL 2>NUL
|
||||||
if errorlevel 0 goto:build
|
if errorlevel 0 goto:build
|
||||||
|
|
||||||
echo Couldn't find any MSBuild to build this project.
|
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
|
endlocal
|
||||||
exit /B 1
|
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 off
|
||||||
echo Updating submodules...
|
echo Updating submodules...
|
||||||
git submodule update --init --recursive
|
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"),
|
path.join(libtommath.settings.source, "*.c"),
|
||||||
}
|
}
|
||||||
|
|
||||||
-- dependencies
|
|
||||||
libtommath.import()
|
|
||||||
|
|
||||||
-- not our code, ignore POSIX usage warnings for now
|
-- not our code, ignore POSIX usage warnings for now
|
||||||
warnings "Off"
|
warnings "Off"
|
||||||
|
|
||||||
|
@ -40,6 +40,5 @@ function udis86.project()
|
|||||||
-- not our code, ignore POSIX usage warnings for now
|
-- not our code, ignore POSIX usage warnings for now
|
||||||
warnings "Off"
|
warnings "Off"
|
||||||
|
|
||||||
kind "SharedLib"
|
|
||||||
kind "StaticLib"
|
kind "StaticLib"
|
||||||
end
|
end
|
@ -235,14 +235,12 @@ workspace "iw4x"
|
|||||||
location "./build"
|
location "./build"
|
||||||
objdir "%{wks.location}/obj"
|
objdir "%{wks.location}/obj"
|
||||||
targetdir "%{wks.location}/bin/%{cfg.buildcfg}"
|
targetdir "%{wks.location}/bin/%{cfg.buildcfg}"
|
||||||
|
buildlog "%{wks.location}/obj/%{cfg.architecture}/%{cfg.buildcfg}/%{prj.name}/%{prj.name}.log"
|
||||||
configurations { "Debug", "Release" }
|
configurations { "Debug", "Release" }
|
||||||
architecture "x32"
|
architecture "x32"
|
||||||
platforms "x86"
|
platforms "x86"
|
||||||
exceptionhandling ("SEH")
|
exceptionhandling ("SEH")
|
||||||
|
|
||||||
-- VS 2015 toolset only
|
|
||||||
toolset "msc-140"
|
|
||||||
|
|
||||||
flags { "StaticRuntime" }
|
flags { "StaticRuntime" }
|
||||||
|
|
||||||
configuration "windows"
|
configuration "windows"
|
||||||
@ -266,7 +264,6 @@ workspace "iw4x"
|
|||||||
project "iw4x"
|
project "iw4x"
|
||||||
kind "SharedLib"
|
kind "SharedLib"
|
||||||
language "C++"
|
language "C++"
|
||||||
flags { "C++14" }
|
|
||||||
files {
|
files {
|
||||||
"./src/**.rc",
|
"./src/**.rc",
|
||||||
"./src/**.hpp",
|
"./src/**.hpp",
|
||||||
@ -376,7 +373,8 @@ workspace "iw4x"
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Specific configurations
|
-- Specific configurations
|
||||||
flags { "UndefinedIdentifiers", "ExtraWarnings" }
|
flags { "UndefinedIdentifiers" }
|
||||||
|
warnings "Extra"
|
||||||
|
|
||||||
if symbols ~= nil then
|
if symbols ~= nil then
|
||||||
symbols "On"
|
symbols "On"
|
||||||
|
@ -61,7 +61,7 @@ namespace Components
|
|||||||
Loader::Register(new Monitor());
|
Loader::Register(new Monitor());
|
||||||
Loader::Register(new Network());
|
Loader::Register(new Network());
|
||||||
Loader::Register(new Theatre());
|
Loader::Register(new Theatre());
|
||||||
//Loader::Register(new Clantags());
|
//Loader::Register(new ClanTags());
|
||||||
Loader::Register(new Download());
|
Loader::Register(new Download());
|
||||||
Loader::Register(new Playlist());
|
Loader::Register(new Playlist());
|
||||||
Loader::Register(new RawFiles());
|
Loader::Register(new RawFiles());
|
||||||
@ -93,7 +93,7 @@ namespace Components
|
|||||||
Loader::Register(new ZoneBuilder());
|
Loader::Register(new ZoneBuilder());
|
||||||
Loader::Register(new AssetHandler());
|
Loader::Register(new AssetHandler());
|
||||||
Loader::Register(new Localization());
|
Loader::Register(new Localization());
|
||||||
Loader::Register(new MusicalTalent());
|
//Loader::Register(new MusicalTalent());
|
||||||
Loader::Register(new ServerCommands());
|
Loader::Register(new ServerCommands());
|
||||||
Loader::Register(new StructuredData());
|
Loader::Register(new StructuredData());
|
||||||
Loader::Register(new ConnectProtocol());
|
Loader::Register(new ConnectProtocol());
|
||||||
|
@ -92,7 +92,7 @@ namespace Components
|
|||||||
#include "Modules/Logger.hpp"
|
#include "Modules/Logger.hpp"
|
||||||
#include "Modules/Friends.hpp"
|
#include "Modules/Friends.hpp"
|
||||||
#include "Modules/IPCPipe.hpp"
|
#include "Modules/IPCPipe.hpp"
|
||||||
#include "Modules/Clantags.hpp"
|
#include "Modules/ClanTags.hpp"
|
||||||
#include "Modules/Download.hpp"
|
#include "Modules/Download.hpp"
|
||||||
#include "Modules/Playlist.hpp"
|
#include "Modules/Playlist.hpp"
|
||||||
#include "Modules/RawFiles.hpp"
|
#include "Modules/RawFiles.hpp"
|
||||||
|
@ -102,8 +102,8 @@ namespace Components
|
|||||||
#ifdef DEBUG_LOAD_LIBRARY
|
#ifdef DEBUG_LOAD_LIBRARY
|
||||||
AntiCheat::LoadLibHook[0].initialize(loadLibA, LoadLibaryAStub, HOOK_JUMP);
|
AntiCheat::LoadLibHook[0].initialize(loadLibA, LoadLibaryAStub, HOOK_JUMP);
|
||||||
AntiCheat::LoadLibHook[1].initialize(loadLibW, LoadLibaryWStub, HOOK_JUMP);
|
AntiCheat::LoadLibHook[1].initialize(loadLibW, LoadLibaryWStub, HOOK_JUMP);
|
||||||
AntiCheat::LoadLibHook[2].initialize(loadLibExA, LoadLibaryAStub, HOOK_JUMP);
|
AntiCheat::LoadLibHook[2].initialize(loadLibExA, LoadLibaryExAStub, HOOK_JUMP);
|
||||||
AntiCheat::LoadLibHook[3].initialize(loadLibExW, LoadLibaryWStub, HOOK_JUMP);
|
AntiCheat::LoadLibHook[3].initialize(loadLibExW, LoadLibaryExWStub, HOOK_JUMP);
|
||||||
#else
|
#else
|
||||||
static uint8_t loadLibStub[] = { 0x33, 0xC0, 0xC2, 0x04, 0x00 }; // xor eax, eax; retn 04h
|
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
|
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
|
static uint8_t ldrLoadDll[] = { 0xB3, 0x9B, 0x8D, 0xB3, 0x90, 0x9E, 0x9B, 0xBB, 0x93, 0x93 }; // LdrLoadDll
|
||||||
|
|
||||||
HMODULE ntdll = Utils::GetNTDLL();
|
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
|
// Patch LdrpLoadDll
|
||||||
Utils::Hook::Signature::Container container;
|
Utils::Hook::Signature::Container container;
|
||||||
@ -133,7 +133,7 @@ namespace Components
|
|||||||
|
|
||||||
Utils::Hook::Signature signature(ntdll, Utils::GetModuleSize(ntdll));
|
Utils::Hook::Signature signature(ntdll, Utils::GetModuleSize(ntdll));
|
||||||
signature.add(container);
|
signature.add(container);
|
||||||
signature.process();
|
//signature.process();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AntiCheat::ReadIntegrityCheck()
|
void AntiCheat::ReadIntegrityCheck()
|
||||||
@ -229,10 +229,10 @@ namespace Components
|
|||||||
AntiCheat::Flags |= AntiCheat::IntergrityFlag::MEMORY_SCAN;
|
AntiCheat::Flags |= AntiCheat::IntergrityFlag::MEMORY_SCAN;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AntiCheat::QuickCodeScanner_1()
|
void AntiCheat::QuickCodeScanner1()
|
||||||
{
|
{
|
||||||
static Utils::Time::Interval interval;
|
static Utils::Time::Interval interval;
|
||||||
static Utils::Value<std::string> hashVal;
|
static std::optional<std::string> hashVal;
|
||||||
|
|
||||||
if (!interval.elapsed(11s)) return;
|
if (!interval.elapsed(11s)) return;
|
||||||
interval.update();
|
interval.update();
|
||||||
@ -243,30 +243,30 @@ namespace Components
|
|||||||
uint8_t* textBase = reinterpret_cast<uint8_t*>(0x400FFF);
|
uint8_t* textBase = reinterpret_cast<uint8_t*>(0x400FFF);
|
||||||
std::string hash = Utils::Cryptography::SHA256::Compute(textBase + 1, textSize + 1, false);
|
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
|
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::Time::Interval interval;
|
||||||
static Utils::Value<std::string> hashVal;
|
static std::optional<std::string> hashVal;
|
||||||
|
|
||||||
if (!interval.elapsed(12s)) return;
|
if (!interval.elapsed(12s)) return;
|
||||||
interval.update();
|
interval.update();
|
||||||
|
|
||||||
// Hash .text segment
|
// Hash .text segment
|
||||||
std::string hash = Utils::Cryptography::SHA1::Compute(reinterpret_cast<uint8_t*>(0x401000), 0x2D6000, false);
|
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
|
Utils::Hook::Set<BYTE>(0x40797C, 0x90); // Crash
|
||||||
}
|
}
|
||||||
|
|
||||||
hashVal.set(hash);
|
hashVal.emplace(hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_LOAD_LIBRARY
|
#ifdef DEBUG_LOAD_LIBRARY
|
||||||
|
@ -31,8 +31,8 @@ namespace Components
|
|||||||
|
|
||||||
static void VerifyThreadIntegrity();
|
static void VerifyThreadIntegrity();
|
||||||
|
|
||||||
static void QuickCodeScanner_1();
|
static void QuickCodeScanner1();
|
||||||
static void QuickCodeScanner_2();
|
static void QuickCodeScanner2();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum IntergrityFlag
|
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
|
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()
|
AssetHandler::AssetHandler()
|
||||||
{
|
{
|
||||||
|
this->reallocateEntryPool();
|
||||||
|
|
||||||
Dvar::Register<bool>("r_noVoid", false, Game::DVAR_FLAG_SAVED, "Disable void model (red fx)");
|
Dvar::Register<bool>("r_noVoid", false, Game::DVAR_FLAG_SAVED, "Disable void model (red fx)");
|
||||||
|
|
||||||
AssetHandler::ClearTemporaryAssets();
|
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
|
// Register asset interfaces
|
||||||
if (ZoneBuilder::IsEnabled())
|
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::IFont_s());
|
||||||
AssetHandler::RegisterInterface(new Assets::IXModel());
|
AssetHandler::RegisterInterface(new Assets::IXModel());
|
||||||
AssetHandler::RegisterInterface(new Assets::IFxWorld());
|
AssetHandler::RegisterInterface(new Assets::IFxWorld());
|
||||||
|
@ -70,6 +70,8 @@ namespace Components
|
|||||||
static void SetBypassState(bool value);
|
static void SetBypassState(bool value);
|
||||||
|
|
||||||
static void MissingAssetError(int severity, const char* format, const char* type, const char* name);
|
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!
|
// TODO: Allow loading assets from raw!
|
||||||
if (Game::s_elemFields[i].handler(&session, element)) break;
|
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);
|
UIFeeder::Add(62.0f, Changelog::GetChangelogCount, Changelog::GetChangelogText, Changelog::SelectChangelog);
|
||||||
|
|
||||||
#if !defined(DEBUG) && !defined(DISABLE_ANTICHEAT)
|
#if !defined(DEBUG) && !defined(DISABLE_ANTICHEAT)
|
||||||
Scheduler::OnFrame(AntiCheat::QuickCodeScanner_1);
|
Scheduler::OnFrame(AntiCheat::QuickCodeScanner1);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,20 +2,20 @@
|
|||||||
|
|
||||||
namespace Components
|
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++)
|
for (int i = 0; i < 18; i++)
|
||||||
{
|
{
|
||||||
const char* clantag = Game::Info_ValueForKey(infoString, std::to_string(i).data());
|
const char* clantag = Game::Info_ValueForKey(infoString, std::to_string(i).data());
|
||||||
|
|
||||||
if (clantag) Clantags::Tags[i] = clantag;
|
if (clantag) ClanTags::Tags[i] = clantag;
|
||||||
else Clantags::Tags[i].clear();
|
else ClanTags::Tags[i].clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Clantags::SendClantagsToClients()
|
void ClanTags::SendClantagsToClients()
|
||||||
{
|
{
|
||||||
std::string list;
|
std::string list;
|
||||||
|
|
||||||
@ -35,18 +35,18 @@ namespace Components
|
|||||||
Game::SV_GameSendServerCommand(-1, 0, command.data());
|
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 0
|
||||||
if (Clantags::Tags[clientnum].empty()) return playername;
|
if (ClanTags::Tags[clientnum].empty()) return playername;
|
||||||
return Utils::String::VA("[%s] %s", Clantags::Tags[clientnum].data(), playername);
|
return Utils::String::VA("[%s] %s", ClanTags::Tags[clientnum].data(), playername);
|
||||||
#else
|
#else
|
||||||
return playername;
|
return playername;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
__declspec(naked) void Clantags::DrawPlayerNameOnScoreboard()
|
__declspec(naked) void ClanTags::DrawPlayerNameOnScoreboard()
|
||||||
{
|
{
|
||||||
__asm
|
__asm
|
||||||
{
|
{
|
||||||
@ -56,7 +56,7 @@ namespace Components
|
|||||||
push edi
|
push edi
|
||||||
push [ebp]
|
push [ebp]
|
||||||
|
|
||||||
call Clantags::GetUserClantag
|
call ClanTags::GetUserClantag
|
||||||
add esp, 8
|
add esp, 8
|
||||||
|
|
||||||
mov [esp + 20h], eax
|
mov [esp + 20h], eax
|
||||||
@ -70,7 +70,7 @@ namespace Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Clantags::Clantags()
|
ClanTags::ClanTags()
|
||||||
{
|
{
|
||||||
// Create clantag dvar
|
// Create clantag dvar
|
||||||
Dvar::OnInit([]()
|
Dvar::OnInit([]()
|
||||||
@ -85,7 +85,7 @@ namespace Components
|
|||||||
{
|
{
|
||||||
if (params->length() == 3)
|
if (params->length() == 3)
|
||||||
{
|
{
|
||||||
Clantags::ParseClantags(params->get(2));
|
ClanTags::ParseClantags(params->get(2));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -93,20 +93,20 @@ namespace Components
|
|||||||
return false;
|
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
|
// 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
|
namespace Components
|
||||||
{
|
{
|
||||||
class Clantags : public Component
|
class ClanTags : public Component
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static void ParseClantags(const char * infoString);
|
static void ParseClantags(const char * infoString);
|
||||||
static void SendClantagsToClients();
|
static void SendClantagsToClients();
|
||||||
static const char* GetUserClantag(std::uint32_t clientnum, const char * playername);
|
static const char* GetUserClantag(std::uint32_t clientnum, const char * playername);
|
||||||
|
|
||||||
Clantags();
|
ClanTags();
|
||||||
~Clantags();
|
~ClanTags();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static std::string Clantags::Tags[18];
|
static std::string ClanTags::Tags[18];
|
||||||
|
|
||||||
static void DrawPlayerNameOnScoreboard();
|
static void DrawPlayerNameOnScoreboard();
|
||||||
|
|
||||||
|
@ -86,6 +86,20 @@ namespace Components
|
|||||||
return std::string(buffer);
|
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()
|
__declspec(naked) void Colors::ClientUserinfoChanged()
|
||||||
{
|
{
|
||||||
__asm
|
__asm
|
||||||
@ -97,7 +111,7 @@ namespace Components
|
|||||||
push ecx // name
|
push ecx // name
|
||||||
push edx // buffer
|
push edx // buffer
|
||||||
|
|
||||||
call strncpy
|
call Colors::UserInfoCopy
|
||||||
|
|
||||||
add esp, 0Ch
|
add esp, 0Ch
|
||||||
retn
|
retn
|
||||||
@ -109,7 +123,7 @@ namespace Components
|
|||||||
Game::CL_GetClientName(localClientNum, index, buf, size);
|
Game::CL_GetClientName(localClientNum, index, buf, size);
|
||||||
|
|
||||||
// Append clantag to username & remove the colors
|
// 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;
|
return buf;
|
||||||
}
|
}
|
||||||
@ -227,6 +241,7 @@ namespace Components
|
|||||||
// Register dvar
|
// Register dvar
|
||||||
Colors::NewColors = Dvar::Register<bool>("cg_newColors", true, Game::dvar_flag::DVAR_FLAG_SAVED, "Use Warfare² color code style.");
|
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.");
|
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
|
// Add our colors
|
||||||
Colors::Add(0, 0, 0); // 0 - Black
|
Colors::Add(0, 0, 0); // 0 - Black
|
||||||
|
@ -25,6 +25,8 @@ namespace Components
|
|||||||
|
|
||||||
static DWORD HsvToRgb(HsvColor hsv);
|
static DWORD HsvToRgb(HsvColor hsv);
|
||||||
|
|
||||||
|
static void UserInfoCopy(char* buffer, const char* name, size_t size);
|
||||||
|
|
||||||
static void ClientUserinfoChanged();
|
static void ClientUserinfoChanged();
|
||||||
static char* GetClientName(int localClientNum, int index, char *buf, size_t size);
|
static char* GetClientName(int localClientNum, int index, char *buf, size_t size);
|
||||||
static void PatchColorLimit(char limit);
|
static void PatchColorLimit(char limit);
|
||||||
|
@ -491,7 +491,7 @@ namespace Components
|
|||||||
|
|
||||||
void Console::FreeNativeConsole()
|
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();
|
FreeConsole();
|
||||||
}
|
}
|
||||||
@ -643,7 +643,7 @@ namespace Components
|
|||||||
Utils::Hook(0x43D570, Console::Error, HOOK_JUMP).install()->quick();
|
Utils::Hook(0x43D570, Console::Error, HOOK_JUMP).install()->quick();
|
||||||
Utils::Hook(0x4859A5, Console::Input, HOOK_CALL).install()->quick();
|
Utils::Hook(0x4859A5, Console::Input, HOOK_CALL).install()->quick();
|
||||||
}
|
}
|
||||||
else
|
else if(!Loader::PerformingUnitTests())
|
||||||
{
|
{
|
||||||
FreeConsole();
|
FreeConsole();
|
||||||
}
|
}
|
||||||
|
@ -8,14 +8,14 @@ namespace Components
|
|||||||
|
|
||||||
bool Dedicated::IsEnabled()
|
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()
|
void Dedicated::InitDedicatedServer()
|
||||||
|
@ -11,12 +11,12 @@ namespace Components
|
|||||||
|
|
||||||
#pragma region Client
|
#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;
|
if (Download::CLDownload.running) return;
|
||||||
|
|
||||||
@ -29,6 +29,18 @@ namespace Components
|
|||||||
|
|
||||||
Command::Execute("openmenu mod_download_popmenu", false);
|
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.running = true;
|
||||||
Download::CLDownload.isMap = map;
|
Download::CLDownload.isMap = map;
|
||||||
Download::CLDownload.mod = mod;
|
Download::CLDownload.mod = mod;
|
||||||
@ -37,6 +49,7 @@ namespace Components
|
|||||||
Download::CLDownload.lastTimeStamp = 0;
|
Download::CLDownload.lastTimeStamp = 0;
|
||||||
Download::CLDownload.downBytes = 0;
|
Download::CLDownload.downBytes = 0;
|
||||||
Download::CLDownload.timeStampBytes = 0;
|
Download::CLDownload.timeStampBytes = 0;
|
||||||
|
Download::CLDownload.isPrivate = needPassword;
|
||||||
Download::CLDownload.target = Party::Target();
|
Download::CLDownload.target = Party::Target();
|
||||||
Download::CLDownload.thread = std::thread(Download::ModDownloader, &Download::CLDownload);
|
Download::CLDownload.thread = std::thread(Download::ModDownloader, &Download::CLDownload);
|
||||||
}
|
}
|
||||||
@ -216,7 +229,8 @@ namespace Components
|
|||||||
}
|
}
|
||||||
else
|
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;
|
Download::FileDownload fDownload;
|
||||||
@ -258,7 +272,9 @@ namespace Components
|
|||||||
|
|
||||||
std::string host = "http://" + download->target.getString();
|
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 (list.empty())
|
||||||
{
|
{
|
||||||
if (download->terminateThread) return;
|
if (download->terminateThread) return;
|
||||||
@ -386,6 +402,31 @@ namespace Components
|
|||||||
return nullptr;
|
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)
|
void Download::Forbid(mg_connection *nc)
|
||||||
{
|
{
|
||||||
mg_printf(nc, "HTTP/1.1 403 Forbidden\r\n"
|
mg_printf(nc, "HTTP/1.1 403 Forbidden\r\n"
|
||||||
@ -397,11 +438,13 @@ namespace Components
|
|||||||
nc->flags |= MG_F_SEND_AND_CLOSE;
|
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
|
// Only handle http requests
|
||||||
if (ev != MG_EV_HTTP_REQUEST) return;
|
if (ev != MG_EV_HTTP_REQUEST) return;
|
||||||
|
|
||||||
|
if (!Download::VerifyPassword(nc, reinterpret_cast<http_message*>(ev_data))) return;
|
||||||
|
|
||||||
static std::string mapnamePre;
|
static std::string mapnamePre;
|
||||||
static json11::Json jsonList;
|
static json11::Json jsonList;
|
||||||
|
|
||||||
@ -448,11 +491,13 @@ namespace Components
|
|||||||
nc->flags |= MG_F_SEND_AND_CLOSE;
|
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
|
// Only handle http requests
|
||||||
if (ev != MG_EV_HTTP_REQUEST) return;
|
if (ev != MG_EV_HTTP_REQUEST) return;
|
||||||
|
|
||||||
|
if (!Download::VerifyPassword(nc, reinterpret_cast<http_message*>(ev_data))) return;
|
||||||
|
|
||||||
// if (!Download::IsClient(nc))
|
// if (!Download::IsClient(nc))
|
||||||
// {
|
// {
|
||||||
// Download::Forbid(nc);
|
// Download::Forbid(nc);
|
||||||
@ -512,6 +557,8 @@ namespace Components
|
|||||||
|
|
||||||
http_message* message = reinterpret_cast<http_message*>(ev_data);
|
http_message* message = reinterpret_cast<http_message*>(ev_data);
|
||||||
|
|
||||||
|
//if (!Download::VerifyPassword(nc, message)) return;
|
||||||
|
|
||||||
// if (!Download::IsClient(nc))
|
// if (!Download::IsClient(nc))
|
||||||
// {
|
// {
|
||||||
// Download::Forbid(nc);
|
// Download::Forbid(nc);
|
||||||
@ -597,7 +644,7 @@ namespace Components
|
|||||||
// Only handle http requests
|
// Only handle http requests
|
||||||
if (ev != MG_EV_HTTP_REQUEST) return;
|
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();
|
Utils::InfoString status = ServerInfo::GetInfo();
|
||||||
|
|
||||||
|
@ -11,8 +11,8 @@ namespace Components
|
|||||||
|
|
||||||
void preDestroy() override;
|
void preDestroy() override;
|
||||||
|
|
||||||
static void InitiateClientDownload(std::string mod, bool map = false);
|
static void InitiateClientDownload(std::string mod, bool needPassword, bool map = false);
|
||||||
static void InitiateMapDownload(std::string map);
|
static void InitiateMapDownload(std::string map, bool needPassword);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class ClientDownload
|
class ClientDownload
|
||||||
@ -25,8 +25,10 @@ namespace Components
|
|||||||
bool valid;
|
bool valid;
|
||||||
bool terminateThread;
|
bool terminateThread;
|
||||||
bool isMap;
|
bool isMap;
|
||||||
|
bool isPrivate;
|
||||||
mg_mgr mgr;
|
mg_mgr mgr;
|
||||||
Network::Address target;
|
Network::Address target;
|
||||||
|
std::string hashedPassword;
|
||||||
std::string mod;
|
std::string mod;
|
||||||
std::thread thread;
|
std::thread thread;
|
||||||
|
|
||||||
@ -209,6 +211,8 @@ namespace Components
|
|||||||
static std::thread ServerThread;
|
static std::thread ServerThread;
|
||||||
static bool Terminate;
|
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 EventHandler(mg_connection *nc, int ev, void *ev_data);
|
||||||
static void ListHandler(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);
|
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);
|
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)
|
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;
|
*reinterpret_cast<unsigned __int64*>(header) = XFILE_MAGIC_UNSIGNED;
|
||||||
}
|
}
|
||||||
|
@ -164,7 +164,7 @@ namespace Components
|
|||||||
{
|
{
|
||||||
std::vector<int> ids;
|
std::vector<int> ids;
|
||||||
|
|
||||||
auto addId = [&](int id)
|
const auto addId = [&](int id)
|
||||||
{
|
{
|
||||||
if (std::find(ids.begin(), ids.end(), id) == ids.end())
|
if (std::find(ids.begin(), ids.end(), id) == ids.end())
|
||||||
{
|
{
|
||||||
@ -186,8 +186,7 @@ namespace Components
|
|||||||
{
|
{
|
||||||
std::lock_guard<std::recursive_mutex> _(Friends::Mutex);
|
std::lock_guard<std::recursive_mutex> _(Friends::Mutex);
|
||||||
|
|
||||||
char* mod = "IW4x";
|
const unsigned int modId = *reinterpret_cast<unsigned int*>("IW4x") | 0x80000000;
|
||||||
unsigned int modId = *reinterpret_cast<unsigned int*>(mod) | 0x80000000;
|
|
||||||
|
|
||||||
// Split up the list
|
// Split up the list
|
||||||
for (auto entry : Friends::FriendsList)
|
for (auto entry : Friends::FriendsList)
|
||||||
@ -283,15 +282,15 @@ namespace Components
|
|||||||
|
|
||||||
void Friends::UpdateRank()
|
void Friends::UpdateRank()
|
||||||
{
|
{
|
||||||
static Utils::Value<int> levelVal;
|
static std::optional<int> levelVal;
|
||||||
|
|
||||||
int experience = Game::Live_GetXp(0);
|
int experience = Game::Live_GetXp(0);
|
||||||
int prestige = Game::Live_GetPrestige(0);
|
int prestige = Game::Live_GetPrestige(0);
|
||||||
int level = (experience & 0xFFFFFF) | ((prestige & 0xFF) << 24);
|
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_experience", Utils::String::VA("%d", experience));
|
||||||
Friends::SetPresence("iw4x_prestige", Utils::String::VA("%d", prestige));
|
Friends::SetPresence("iw4x_prestige", Utils::String::VA("%d", prestige));
|
||||||
|
@ -9,7 +9,6 @@ namespace Components
|
|||||||
|
|
||||||
bool Maps::SPMap;
|
bool Maps::SPMap;
|
||||||
std::vector<Maps::DLC> Maps::DlcPacks;
|
std::vector<Maps::DLC> Maps::DlcPacks;
|
||||||
std::vector<Game::XAssetEntry> Maps::EntryPool;
|
|
||||||
|
|
||||||
const char* Maps::UserMapFiles[4] =
|
const char* Maps::UserMapFiles[4] =
|
||||||
{
|
{
|
||||||
@ -713,59 +712,7 @@ namespace Components
|
|||||||
|
|
||||||
Game::XAssetEntry* Maps::GetAssetEntryPool()
|
Game::XAssetEntry* Maps::GetAssetEntryPool()
|
||||||
{
|
{
|
||||||
if(Maps::EntryPool.empty())
|
return *reinterpret_cast<Game::XAssetEntry**>(0x48E6F4);
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// dlcIsTrue serves as a check if the map is a custom map and if it's missing
|
// 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
|
// Load usermap arena file
|
||||||
Utils::Hook(0x630A88, Maps::LoadArenaFileStub, HOOK_CALL).install()->quick();
|
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
|
// Dependencies
|
||||||
//Maps::AddDependency("oilrig", "mp_subbase");
|
//Maps::AddDependency("oilrig", "mp_subbase");
|
||||||
//Maps::AddDependency("gulag", "mp_subbase");
|
//Maps::AddDependency("gulag", "mp_subbase");
|
||||||
@ -1113,7 +1042,5 @@ namespace Components
|
|||||||
Maps::DependencyList.clear();
|
Maps::DependencyList.clear();
|
||||||
Maps::CurrentMainZone.clear();
|
Maps::CurrentMainZone.clear();
|
||||||
Maps::CurrentDependencies.clear();
|
Maps::CurrentDependencies.clear();
|
||||||
|
|
||||||
Maps::EntryPool.clear();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -78,7 +78,6 @@ namespace Components
|
|||||||
static bool SPMap;
|
static bool SPMap;
|
||||||
static UserMapContainer UserMap;
|
static UserMapContainer UserMap;
|
||||||
static std::vector<DLC> DlcPacks;
|
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::pair<std::string, std::string>> DependencyList;
|
||||||
static std::vector<std::string> CurrentDependencies;
|
static std::vector<std::string> CurrentDependencies;
|
||||||
@ -123,7 +122,5 @@ namespace Components
|
|||||||
static Game::dvar_t* GetSpecularDvar();
|
static Game::dvar_t* GetSpecularDvar();
|
||||||
static void SetSpecularStub1();
|
static void SetSpecularStub1();
|
||||||
static void SetSpecularStub2();
|
static void SetSpecularStub2();
|
||||||
|
|
||||||
void reallocateEntryPool();
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -767,7 +767,7 @@ namespace Components
|
|||||||
});
|
});
|
||||||
|
|
||||||
#if !defined(DEBUG) && !defined(DISABLE_ANTICHEAT)
|
#if !defined(DEBUG) && !defined(DISABLE_ANTICHEAT)
|
||||||
Scheduler::OnFrame(AntiCheat::QuickCodeScanner_2);
|
Scheduler::OnFrame(AntiCheat::QuickCodeScanner2);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Command::Add("mp_QuickMessage", [](Command::Params*)
|
Command::Add("mp_QuickMessage", [](Command::Params*)
|
||||||
|
@ -7,14 +7,14 @@ namespace Components
|
|||||||
{
|
{
|
||||||
bool Monitor::IsEnabled()
|
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*/)
|
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;
|
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)];
|
aliases->head->soundFile->data.stream.name = MusicalTalent::SoundAliasList[Utils::String::ToLower(filename)];
|
||||||
}
|
}
|
||||||
|
@ -430,15 +430,19 @@ namespace Components
|
|||||||
{
|
{
|
||||||
Party::ConnectError("Invalid map or gametype.");
|
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")))
|
else if (isUsermap && usermapHash != Maps::GetUsermapHash(info.get("mapname")))
|
||||||
{
|
{
|
||||||
Command::Execute("closemenu popup_reconnectingtoparty");
|
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")))
|
else if (!info.get("fs_game").empty() && Utils::String::ToLower(mod) != Utils::String::ToLower(info.get("fs_game")))
|
||||||
{
|
{
|
||||||
Command::Execute("closemenu popup_reconnectingtoparty");
|
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())
|
else if (!Dvar::Var("fs_game").get<std::string>().empty() && info.get("fs_game").empty())
|
||||||
{
|
{
|
||||||
@ -462,7 +466,7 @@ namespace Components
|
|||||||
// Send playlist request
|
// Send playlist request
|
||||||
Party::Container.requestTime = Game::Sys_Milliseconds();
|
Party::Container.requestTime = Game::Sys_Milliseconds();
|
||||||
Party::Container.awaitingPlaylist = true;
|
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
|
// This is not a safe method
|
||||||
// TODO: Fix actual error!
|
// TODO: Fix actual error!
|
||||||
|
@ -45,6 +45,16 @@ namespace Components
|
|||||||
|
|
||||||
void Playlist::PlaylistRequest(Network::Address address, std::string data)
|
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");
|
Logger::Print("Received playlist request, sending currently stored buffer.\n");
|
||||||
|
|
||||||
std::string compressedList = Utils::Compression::ZLib::Compress(Playlist::CurrentPlaylistBuffer);
|
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)
|
void Playlist::MapNameCopy(char *dest, const char *src, int destsize)
|
||||||
{
|
{
|
||||||
Utils::Hook::Call<void(char*, const char*, int)>(0x4D6F80)(dest, src, 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("getPlaylist", PlaylistRequest);
|
||||||
Network::Handle("playlistResponse", PlaylistReponse);
|
Network::Handle("playlistResponse", PlaylistReponse);
|
||||||
|
Network::Handle("playlistInvalidPassword", PlaylistInvalidPassword);
|
||||||
}
|
}
|
||||||
|
|
||||||
Playlist::~Playlist()
|
Playlist::~Playlist()
|
||||||
|
@ -22,6 +22,7 @@ namespace Components
|
|||||||
|
|
||||||
static void PlaylistRequest(Network::Address address, std::string data);
|
static void PlaylistRequest(Network::Address address, std::string data);
|
||||||
static void PlaylistReponse(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 MapNameCopy(char *dest, const char *src, int destsize);
|
||||||
static void SetMapName(const char* cvar, const char* value);
|
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");
|
printf("Success\n");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -746,8 +746,7 @@ namespace Components
|
|||||||
do
|
do
|
||||||
{
|
{
|
||||||
entry = reinterpret_cast<ServerList::MasterEntry*>(const_cast<char*>(data.data()) + offset++);
|
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)
|
for (int i = 0; !entry[i].IsEndToken() && entry[i].HasSeparator(); ++i)
|
||||||
{
|
{
|
||||||
|
@ -37,5 +37,4 @@ namespace Components
|
|||||||
{
|
{
|
||||||
StartupMessages::MessageList.push_back(message);
|
StartupMessages::MessageList.push_back(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -70,6 +70,7 @@ namespace Components
|
|||||||
|
|
||||||
// ToDo: Allow playerdata changes in setPlayerData UI script.
|
// ToDo: Allow playerdata changes in setPlayerData UI script.
|
||||||
}
|
}
|
||||||
|
|
||||||
Stats::~Stats()
|
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* 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::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 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 };
|
Game::vec4_t borderColor = { 1.0f, 1.0f, 1.0f, 0.2f };
|
||||||
|
|
||||||
height /= 5;
|
height /= 5;
|
||||||
|
@ -506,7 +506,7 @@ namespace Components
|
|||||||
// Add branding asset
|
// Add branding asset
|
||||||
void ZoneBuilder::Zone::addBranding()
|
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 };
|
this->branding = { this->zoneName.data(), static_cast<int>(strlen(data)), 0, data };
|
||||||
|
|
||||||
if (this->findAsset(Game::XAssetType::ASSET_TYPE_RAWFILE, this->branding.name) != -1)
|
if (this->findAsset(Game::XAssetType::ASSET_TYPE_RAWFILE, this->branding.name) != -1)
|
||||||
@ -664,14 +664,14 @@ namespace Components
|
|||||||
|
|
||||||
bool ZoneBuilder::IsEnabled()
|
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)
|
void ZoneBuilder::BeginAssetTrace(std::string zone)
|
||||||
@ -1034,17 +1034,6 @@ namespace Components
|
|||||||
// Don't read stats
|
// Don't read stats
|
||||||
Utils::Hook(0x4875E1, 0x487717, HOOK_JUMP).install()->quick();
|
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
|
// patch g_copyInfo because we're using so many more assets than originally intended
|
||||||
int newLimit = 0x2000;
|
int newLimit = 0x2000;
|
||||||
int* g_copyInfo_new = Utils::Memory::GetAllocator()->allocateArray<int>(newLimit);
|
int* g_copyInfo_new = Utils::Memory::GetAllocator()->allocateArray<int>(newLimit);
|
||||||
|
@ -222,14 +222,12 @@ namespace Game
|
|||||||
const void *initial_ptr;
|
const void *initial_ptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* 526 */
|
|
||||||
struct MssSound
|
struct MssSound
|
||||||
{
|
{
|
||||||
_AILSOUNDINFO info;
|
_AILSOUNDINFO info;
|
||||||
char *data;
|
char *data;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* 527 */
|
|
||||||
struct LoadedSound
|
struct LoadedSound
|
||||||
{
|
{
|
||||||
const char *name;
|
const char *name;
|
||||||
@ -242,7 +240,7 @@ namespace Game
|
|||||||
StreamedSound stream;
|
StreamedSound stream;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SoundFile // 0xC
|
struct SoundFile
|
||||||
{
|
{
|
||||||
snd_alias_type_t type;
|
snd_alias_type_t type;
|
||||||
bool exists;
|
bool exists;
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
#ifndef RC_INVOKED
|
#ifndef RC_INVOKED
|
||||||
|
|
||||||
|
#define _HAS_CXX17 1
|
||||||
#define VC_EXTRALEAN
|
#define VC_EXTRALEAN
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
|
||||||
@ -33,12 +34,12 @@
|
|||||||
#include <regex>
|
#include <regex>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <future>
|
#include <future>
|
||||||
#include <queue>
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
|
||||||
// Experimental C++17 features
|
// Experimental C++17 features
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
|
|
||||||
|
@ -6,12 +6,12 @@ namespace Steam
|
|||||||
{
|
{
|
||||||
unsigned int Utils::GetSecondsSinceAppActive()
|
unsigned int Utils::GetSecondsSinceAppActive()
|
||||||
{
|
{
|
||||||
return 0;
|
return Game::Sys_Milliseconds() / 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int Utils::GetSecondsSinceComputerActive()
|
unsigned int Utils::GetSecondsSinceComputerActive()
|
||||||
{
|
{
|
||||||
return 0;
|
return timeGetTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
int Utils::GetConnectedUniverse()
|
int Utils::GetConnectedUniverse()
|
||||||
@ -21,25 +21,28 @@ namespace Steam
|
|||||||
|
|
||||||
unsigned int Utils::GetServerRealTime()
|
unsigned int Utils::GetServerRealTime()
|
||||||
{
|
{
|
||||||
static ::Utils::Value<unsigned int> timeDelta;
|
static std::optional<unsigned int> timeDelta;
|
||||||
|
if(!timeDelta.has_value())
|
||||||
if(!timeDelta.isValid())
|
|
||||||
{
|
{
|
||||||
unsigned int steamTime = static_cast<unsigned int>(time(nullptr));
|
unsigned int steamTime = static_cast<unsigned int>(time(nullptr));
|
||||||
|
|
||||||
if(Steam::Proxy::SteamUtils)
|
if(Steam::Proxy::SteamUtils)
|
||||||
{
|
{
|
||||||
steamTime = Steam::Proxy::SteamUtils->GetServerRealTime();
|
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()
|
const char* Utils::GetIPCountry()
|
||||||
{
|
{
|
||||||
|
if (Steam::Proxy::SteamUtils)
|
||||||
|
{
|
||||||
|
return Steam::Proxy::SteamUtils->GetIPCountry();
|
||||||
|
}
|
||||||
|
|
||||||
return "US";
|
return "US";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,6 +63,11 @@ namespace Steam
|
|||||||
|
|
||||||
unsigned char Utils::GetCurrentBatteryPower()
|
unsigned char Utils::GetCurrentBatteryPower()
|
||||||
{
|
{
|
||||||
|
if (Steam::Proxy::SteamUtils)
|
||||||
|
{
|
||||||
|
return Steam::Proxy::SteamUtils->GetCurrentBatteryPower();
|
||||||
|
}
|
||||||
|
|
||||||
return 255;
|
return 255;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,10 +48,8 @@ namespace Utils
|
|||||||
{
|
{
|
||||||
ECC::Key key;
|
ECC::Key key;
|
||||||
|
|
||||||
register_prng(&sprng_desc);
|
|
||||||
|
|
||||||
ltc_mp = ltm_desc;
|
ltc_mp = ltm_desc;
|
||||||
|
register_prng(&sprng_desc);
|
||||||
ecc_make_key(nullptr, find_prng("sprng"), bits / 8, key.getKeyPtr());
|
ecc_make_key(nullptr, find_prng("sprng"), bits / 8, key.getKeyPtr());
|
||||||
|
|
||||||
return key;
|
return key;
|
||||||
@ -64,10 +62,8 @@ namespace Utils
|
|||||||
uint8_t buffer[512];
|
uint8_t buffer[512];
|
||||||
DWORD length = sizeof(buffer);
|
DWORD length = sizeof(buffer);
|
||||||
|
|
||||||
register_prng(&sprng_desc);
|
|
||||||
|
|
||||||
ltc_mp = ltm_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());
|
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);
|
return std::string(reinterpret_cast<char*>(buffer), length);
|
||||||
|
@ -113,14 +113,20 @@ namespace Utils
|
|||||||
// trim from start
|
// trim from start
|
||||||
std::string <rim(std::string &s)
|
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;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
// trim from end
|
// trim from end
|
||||||
std::string &RTrim(std::string &s)
|
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;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,33 +112,4 @@ namespace Utils
|
|||||||
private:
|
private:
|
||||||
std::vector<Slot<T>> slots;
|
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