Merge branch 'develop'
This commit is contained in:
commit
04b8a1e156
288
Jenkinsfile
vendored
Normal file
288
Jenkinsfile
vendored
Normal file
@ -0,0 +1,288 @@
|
||||
#!groovy
|
||||
|
||||
/*
|
||||
This is our new pipeline script to do all of the building in, of and around IW4x.
|
||||
|
||||
Here's what it is supposed to do:
|
||||
|
||||
- Make sure Modern Warfare 2 is installed (CI should provide the folder like a custom tool)
|
||||
- Check out code from iw4x-data
|
||||
- Build the IW4x client library (this code repository)
|
||||
- Use iw4x.exe from the iw4x-data repository in order to build the zone files in iw4x-data
|
||||
- Package the IW4x client with the newly built data files
|
||||
|
||||
At this point it is done building everything, however afterwards we want the build server to
|
||||
also push the newly built files to an update repository, depending on the branch we're on.
|
||||
|
||||
- For "develop", release to the "iw4x-dev" branch on the repository server.
|
||||
- For "master", release to the "iw4x" branch on the repository server.
|
||||
|
||||
I'm looking into how the logic of pipelining works in detail before deciding on whether to
|
||||
throw in the IW4x Updater and the IW4x Node binaries in as well or not.
|
||||
*/
|
||||
|
||||
/*
|
||||
Note that this is just a rewrite of the jobs as they are currently set up on the production
|
||||
Jenkins server. This will allow every developer to tinker around with how the build process
|
||||
is set up. For those who want to play around with this, here's a bit of information:
|
||||
|
||||
- This is a Groovy script. Essentially Java but with less bullshit (like brackets and verbose writing).
|
||||
- This gets directly translated into a Jenkins pipeline.
|
||||
- If you have no idea how to handle scripts, get your hands off this file.
|
||||
- If you do not use Jenkins, get your hands off this file.
|
||||
- If you fuck this script up, I will kill you.
|
||||
*/
|
||||
|
||||
import groovy.transform.Field
|
||||
|
||||
@Field def configurations = [
|
||||
"Debug": [
|
||||
WorkspaceID: "build@debug",
|
||||
StashName: "iw4x-debug",
|
||||
MSBuildConfiguration: "Debug",
|
||||
PremakeArgs: "",
|
||||
Archive: true,
|
||||
],
|
||||
"Release": [
|
||||
WorkspaceID: "build@release",
|
||||
StashName: "iw4x-release",
|
||||
MSBuildConfiguration: "Release",
|
||||
PremakeArgs: "",
|
||||
Archive: true,
|
||||
],
|
||||
"Release with unit tests": [
|
||||
WorkspaceID: "build@release+unittests",
|
||||
StashName: "iw4x-release-unittests",
|
||||
MSBuildConfiguration: "Release",
|
||||
PremakeArgs: "--force-unit-tests",
|
||||
Archive: false,
|
||||
],
|
||||
].collect {k, v -> [k, v]}
|
||||
|
||||
@Field def testing = [
|
||||
"Debug": [
|
||||
WorkspaceID: "testing@debug",
|
||||
StashName: "iw4x-debug",
|
||||
],
|
||||
"Release": [
|
||||
WorkspaceID: "testing@release",
|
||||
StashName: "iw4x-release-unittests",
|
||||
],
|
||||
].collect {k, v -> [k, v]}
|
||||
|
||||
def jobWorkspace(id, f) {
|
||||
ws("workspace/${env.JOB_NAME}@$id", f)
|
||||
}
|
||||
|
||||
def useShippedPremake(f) {
|
||||
def premakeHome = "${pwd()}\\tools"
|
||||
|
||||
withEnv(["PATH+=${premakeHome}"], f)
|
||||
}
|
||||
|
||||
def getIW4xExecutable() {
|
||||
step([
|
||||
$class: 'CopyArtifact',
|
||||
filter: '*',
|
||||
fingerprintArtifacts: true,
|
||||
projectName: 'iw4x/iw4x-executable/master',
|
||||
selector: [
|
||||
$class: 'TriggeredBuildSelector',
|
||||
allowUpstreamDependencies: false,
|
||||
fallbackToLastSuccessful: true,
|
||||
upstreamFilterStrategy: 'UseGlobalSetting'
|
||||
]
|
||||
])
|
||||
}
|
||||
|
||||
// This will build the IW4x client.
|
||||
// We need a Windows Server with Visual Studio 2015, Premake5 and Git on it.
|
||||
def doBuild(cfg) {
|
||||
node("windows") {
|
||||
jobWorkspace(cfg.WorkspaceID) {
|
||||
checkout scm
|
||||
|
||||
useShippedPremake {
|
||||
def outputDir = pwd()
|
||||
def msbuild = tool "Microsoft.NET MSBuild 14.0"
|
||||
bat "premake5 vs2015 ${cfg.PremakeArgs}"
|
||||
bat "\"${msbuild}\" build\\iw4x.sln \"/p:OutDir=$outputDir\\\\\" \"/p:Configuration=${cfg.MSBuildConfiguration}\""
|
||||
}
|
||||
|
||||
stash name: "${cfg.StashName}", includes: "*.dll,*.pdb"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This will run the unit tests for IW4x.
|
||||
// We need a Windows Server with MW2 on it.
|
||||
def doUnitTests(name) {
|
||||
mw2dir = tool "Modern Warfare 2"
|
||||
|
||||
unstash "$name"
|
||||
|
||||
// Get installed localization for correct zonefiles directory junction
|
||||
def localization = readFile("$mw2dir/localization.txt").split("\r?\n")[0]
|
||||
|
||||
try {
|
||||
timeout(time: 180, unit: "MINUTES") {
|
||||
// Set up environment
|
||||
if (isUnix()) {
|
||||
sh """
|
||||
mkdir -p zone
|
||||
for f in main zone/dlc \"zone/$localization\"; do
|
||||
ln -sfv \"$mw2dir/\$f\" \"\$f\"
|
||||
done
|
||||
for f in \"$mw2dir\"/*.dll \"$mw2dir\"/*.txt \"$mw2dir\"/*.bmp; do
|
||||
ln -sfv \"\$f\" \"\$(basename \"\$f\")\"
|
||||
done
|
||||
"""
|
||||
} else {
|
||||
bat """
|
||||
mklink /J \"main\" \"$mw2dir\\main\"
|
||||
mkdir \"zone\"
|
||||
mklink /J \"zone\\dlc\" \"$mw2dir\\zone\\dlc\"
|
||||
mklink /J \"zone\\$localization\" \"$mw2dir\\zone\\$localization\"
|
||||
copy /y \"$mw2dir\\*.dll\"
|
||||
copy /y \"$mw2dir\\*.txt\"
|
||||
copy /y \"$mw2dir\\*.bmp\"
|
||||
"""
|
||||
}
|
||||
|
||||
// Run tests
|
||||
getIW4xExecutable()
|
||||
if (isUnix()) {
|
||||
sh "wine-wrapper iw4x.exe -tests"
|
||||
} else {
|
||||
bat "iw4x.exe -tests"
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
// In all cases make sure to at least remove the directory junctions!
|
||||
if (!isUnix()) {
|
||||
bat """
|
||||
rmdir \"main\"
|
||||
rmdir \"zone\\dlc\"
|
||||
rmdir \"zone\\$localization\"
|
||||
"""
|
||||
}
|
||||
deleteDir()
|
||||
}
|
||||
}
|
||||
|
||||
// Job properties
|
||||
properties([
|
||||
[$class: "GitLabConnectionProperty", gitLabConnection: "sr0"]
|
||||
])
|
||||
|
||||
gitlabBuilds(builds: ["Checkout & Versioning", "Build", "Testing", "Archiving"]) {
|
||||
// First though let's give this build a proper name
|
||||
stage("Checkout & Versioning") {
|
||||
gitlabCommitStatus("Checkout & Versioning") {
|
||||
node("windows") {
|
||||
jobWorkspace("versioning") {
|
||||
checkout scm
|
||||
|
||||
useShippedPremake {
|
||||
def version = bat(returnStdout: true, script: '@premake5 version').split("\r?\n")[1]
|
||||
|
||||
currentBuild.setDisplayName "$version (#${env.BUILD_NUMBER})"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// For each available configuration generate a normal build and a unit test build.
|
||||
stage("Build") {
|
||||
gitlabCommitStatus("Build") {
|
||||
def executions = [:]
|
||||
for (int i = 0; i < configurations.size(); i++) {
|
||||
def entry = configurations[i]
|
||||
|
||||
def configName = entry[0]
|
||||
def config = entry[1]
|
||||
|
||||
executions[configName] = {
|
||||
node("windows") {
|
||||
jobWorkspace(config.WorkspaceID) {
|
||||
doBuild(config)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
parallel executions
|
||||
}
|
||||
}
|
||||
|
||||
// Run unit tests on each configuration.
|
||||
stage("Testing") {
|
||||
gitlabCommitStatus("Testing") {
|
||||
executions = [:]
|
||||
for (int i = 0; i < testing.size(); i++) {
|
||||
def entry = testing.get(i)
|
||||
|
||||
def testName = entry[0]
|
||||
def test = entry[1]
|
||||
|
||||
executions["$testName on Windows"] = {
|
||||
node("windows") {
|
||||
jobWorkspace(test.WorkspaceID) {
|
||||
doUnitTests(test.StashName)
|
||||
}
|
||||
}
|
||||
}
|
||||
executions["$testName on Linux"] = {
|
||||
node("docker && linux && amd64") {
|
||||
try {
|
||||
def image = null
|
||||
dir("src") {
|
||||
checkout scm
|
||||
image = docker.build("github.com/IW4x/iw4x-client-testing-wine32", "--rm --force-rm -f jenkins/wine32.Dockerfile jenkins")
|
||||
deleteDir()
|
||||
}
|
||||
image.inside {
|
||||
doUnitTests(test.StashName)
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (isUnix()) {
|
||||
manager.buildUnstable()
|
||||
manager.addWarningBadge "$testName unit test failed on Linux"
|
||||
} else {
|
||||
throw e
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
parallel executions
|
||||
}
|
||||
}
|
||||
|
||||
// Collect all the binaries and give each configuration its own subfolder
|
||||
stage("Archiving") {
|
||||
gitlabCommitStatus("Archiving") {
|
||||
node("windows") { // any node will do
|
||||
jobWorkspace("archiving") {
|
||||
try {
|
||||
for (int i = 0; i < configurations.size(); i++) {
|
||||
def entry = configurations[i]
|
||||
|
||||
def configName = entry[0]
|
||||
def config = entry[1]
|
||||
|
||||
if (config.Archive) {
|
||||
dir(configName) {
|
||||
unstash config.StashName
|
||||
}
|
||||
}
|
||||
}
|
||||
archiveArtifacts artifacts: "**/*.dll,**/*.pdb", fingerprint: true
|
||||
} finally {
|
||||
deleteDir()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
17
README.md
17
README.md
@ -1,5 +1,5 @@
|
||||
|
||||
# IW4x: Client
|
||||
# IW4x: Client
|
||||
|
||||
## How to compile
|
||||
|
||||
@ -8,5 +8,16 @@
|
||||
|
||||
## Premake arguments
|
||||
|
||||
- `--copy-to=PATH` - Optional, copy the DLL to a custom folder after build, define the path here if wanted.
|
||||
- `--no-new-structure` - Do not use new virtual path structure (separating headers and source files).
|
||||
| Argument | Description |
|
||||
| ------------- | ------------- |
|
||||
| `--copy-to=PATH` | Optional, copy the DLL to a custom folder after build, define the path here if wanted. |
|
||||
| `--copy-pdb` | Copy debug information for binaries as well to the path given via --copy-to. |
|
||||
| `--ac-debug-detections` | Log anticheat detections. |
|
||||
| `--ac-debug-load-library` | Log libraries that get loaded. |
|
||||
| `--force-unit-tests` | Always compile unit tests. |
|
||||
| `--force-exception-handler` | Install custom unhandled exception handler even for Debug builds. |
|
||||
| `--force-minidump-upload` | Upload minidumps even for Debug builds. |
|
||||
| `--disable-bitmessage` | Disable use of BitMessage completely. |
|
||||
| `--disable-node-log` | Disable debugging messages for Nodes in Debug builds. |
|
||||
| `--disable-base128` | Disable base128 encoding for minidumps. |
|
||||
| `--no-new-structure` | Do not use new virtual path structure (separating headers and source files). |
|
||||
|
@ -18,7 +18,7 @@ exit /B 1
|
||||
:build
|
||||
call generate.bat
|
||||
set PLATFORM=Win32
|
||||
set CONFIGURATION=ReleaseStatic
|
||||
set CONFIGURATION=Release
|
||||
msbuild /nologo /m /v:m %* build\iw4x.sln
|
||||
endlocal
|
||||
exit /B %ERRORLEVEL%
|
||||
|
2
deps/fmt
vendored
2
deps/fmt
vendored
@ -1 +1 @@
|
||||
Subproject commit 0d25f6fcbbf0a867b939a5501965ee4462b21ee6
|
||||
Subproject commit 1fb0586b065c4202e976528a6bdc6384dc56dc04
|
2
deps/mongoose
vendored
2
deps/mongoose
vendored
@ -1 +1 @@
|
||||
Subproject commit 2a541175b56a1aeecd2dc8474f981923ef580af6
|
||||
Subproject commit ffa981d1728163f8b3d0961c127ef924d68ef84c
|
2
deps/protobuf
vendored
2
deps/protobuf
vendored
@ -1 +1 @@
|
||||
Subproject commit 14e74f6a21f2726d25e0e679c59d569f6bc8fe8e
|
||||
Subproject commit c44ca26fe89ed8a81d3ee475a2ccc1797141dbce
|
37
jenkins/wine32.Dockerfile
Normal file
37
jenkins/wine32.Dockerfile
Normal file
@ -0,0 +1,37 @@
|
||||
# Requires a decent modern Docker version (v1.10.x at least ideally)
|
||||
|
||||
# Use semi-official Arch Linux image with fixed versioning
|
||||
FROM pritunl/archlinux:2016-09-10
|
||||
|
||||
# Environment variables
|
||||
ENV WINEPREFIX /wine32
|
||||
ENV WINEARCH win32
|
||||
ENV WINEDEBUG -all
|
||||
|
||||
# Install Wine (32-bit)
|
||||
RUN \
|
||||
echo -e "#!/bin/sh\nwine \$@\nretval=\$?\ntail --pid=\$(pidof wineserver 2>/dev/null||echo 0) -f /dev/null\nexit \$retval" > /usr/local/bin/wine-wrapper &&\
|
||||
chmod +x /usr/local/bin/wine-wrapper &&\
|
||||
\
|
||||
(\
|
||||
echo '' &&\
|
||||
echo '[multilib]' &&\
|
||||
echo 'Include = /etc/pacman.d/mirrorlist'\
|
||||
) >> /etc/pacman.conf &&\
|
||||
pacman -Sy --noconfirm wine wget xorg-server-xvfb &&\
|
||||
\
|
||||
wine-wrapper wineboot.exe -i &&\
|
||||
wget -Ovcredist_x86.exe https://download.microsoft.com/download/d/d/9/dd9a82d0-52ef-40db-8dab-795376989c03/vcredist_x86.exe &&\
|
||||
xvfb-run sh -c 'wine-wrapper vcredist_x86.exe /q' &&\
|
||||
rm vcredist_x86.exe &&\
|
||||
\
|
||||
pacman -Rs --noconfirm xorg-server-xvfb wget &&\
|
||||
\
|
||||
find /. -name "*~" -type f -delete &&\
|
||||
rm -rf /tmp/* /var/tmp/* /usr/share/man/* /usr/share/info/* /usr/share/doc/* &&\
|
||||
pacman -Scc --noconfirm &&\
|
||||
paccache -rk0 &&\
|
||||
pacman-optimize &&\
|
||||
rm -rf /var/lib/pacman/sync/*
|
||||
|
||||
USER 0
|
@ -46,7 +46,7 @@ function zlib.project()
|
||||
warnings "Off"
|
||||
|
||||
kind "SharedLib"
|
||||
configuration "*Static"
|
||||
--configuration "*Static"
|
||||
defines { "_LIB" }
|
||||
removedefines { "_USRDLL", "_DLL", "ZLIB_DLL" }
|
||||
kind "StaticLib"
|
||||
|
25
premake5.lua
25
premake5.lua
@ -13,17 +13,17 @@ function cstrquote(value)
|
||||
return result
|
||||
end
|
||||
|
||||
-- Converts tags in "vX.X.X" format to X,X,X.
|
||||
-- In the case where the format does not work fall back to old 4,2,REVISION.
|
||||
function vertonum(value, vernumber)
|
||||
-- Converts tags in "vX.X.X" format to an array of numbers {X,X,X}.
|
||||
-- In the case where the format does not work fall back to old {4,2,REVISION}.
|
||||
function vertonumarr(value, vernumber)
|
||||
vernum = {}
|
||||
for num in string.gmatch(value, "%d+") do
|
||||
table.insert(vernum, num)
|
||||
table.insert(vernum, tonumber(num))
|
||||
end
|
||||
if #vernum < 3 then
|
||||
return "4,2," .. vernumber
|
||||
return {4,2,tonumber(vernumber)}
|
||||
end
|
||||
return vernum[1] .. "," .. vernum[2] .. "," .. vernum[3]
|
||||
return vernum
|
||||
end
|
||||
|
||||
-- Option to allow copying the DLL file to a custom folder after build
|
||||
@ -80,7 +80,7 @@ newoption {
|
||||
|
||||
newoption {
|
||||
trigger = "disable-base128",
|
||||
description = "Disable debugging messages for Nodes in Debug builds."
|
||||
description = "Disable base128 encoding for minidumps."
|
||||
}
|
||||
|
||||
newaction {
|
||||
@ -116,7 +116,7 @@ newaction {
|
||||
if revDirty then revDirty = 1 else revDirty = 0 end
|
||||
proc:close()
|
||||
|
||||
-- get current tag name (aka milestone for now)
|
||||
-- get current tag name
|
||||
proc = assert(io.popen("git describe --tags --abbrev=0"))
|
||||
local tagName = assert(proc:read('*l'))
|
||||
|
||||
@ -153,11 +153,11 @@ newaction {
|
||||
versionHeader:write("#define REVISION " .. revNumber .. "\n")
|
||||
versionHeader:write("\n")
|
||||
versionHeader:write("// Version transformed for RC files\n")
|
||||
versionHeader:write("#define VERSION_RC " .. vertonum(tagName, revNumber) .. "\n")
|
||||
versionHeader:write("#define VERSION_RC " .. table.concat(vertonumarr(tagName, revNumber), ",") .. "\n")
|
||||
versionHeader:write("\n")
|
||||
versionHeader:write("// Alias definitions\n")
|
||||
versionHeader:write("#define VERSION GIT_DESCRIBE\n")
|
||||
versionHeader:write("#define SHORTVERSION GIT_TAG\n")
|
||||
versionHeader:write("#define SHORTVERSION " .. cstrquote(table.concat(vertonumarr(tagName, revNumber), ".")) .. "\n")
|
||||
versionHeader:close()
|
||||
local versionHeader = assert(io.open(wks.location .. "/src/version.hpp", "w"))
|
||||
versionHeader:write("/*\n")
|
||||
@ -260,7 +260,8 @@ workspace "iw4x"
|
||||
location "./build"
|
||||
objdir "%{wks.location}/obj"
|
||||
targetdir "%{wks.location}/bin/%{cfg.buildcfg}"
|
||||
configurations { "Debug", "DebugStatic", "Release", "ReleaseStatic" }
|
||||
--configurations { "Debug", "DebugStatic", "Release", "ReleaseStatic" }
|
||||
configurations { "Debug", "Release" }
|
||||
architecture "x32"
|
||||
platforms "x86"
|
||||
|
||||
@ -280,7 +281,7 @@ workspace "iw4x"
|
||||
flags { "MultiProcessorCompile", "Symbols", "No64BitChecks" }
|
||||
optimize "Debug"
|
||||
|
||||
configuration "*Static"
|
||||
--configuration "*Static"
|
||||
flags { "StaticRuntime" }
|
||||
|
||||
project "iw4x"
|
||||
|
@ -28,6 +28,7 @@ namespace Components
|
||||
Loader::Register(new Menus());
|
||||
Loader::Register(new Toast());
|
||||
Loader::Register(new Party());
|
||||
Loader::Register(new Zones());
|
||||
Loader::Register(new Colors());
|
||||
Loader::Register(new D3D9Ex());
|
||||
Loader::Register(new Logger());
|
||||
@ -56,6 +57,7 @@ namespace Components
|
||||
Loader::Register(new BitMessage());
|
||||
#endif
|
||||
Loader::Register(new FileSystem());
|
||||
Loader::Register(new ModelSurfs());
|
||||
Loader::Register(new PlayerName());
|
||||
Loader::Register(new QuickPatch());
|
||||
Loader::Register(new ServerInfo());
|
||||
@ -78,7 +80,10 @@ namespace Components
|
||||
for (auto component : Loader::Components)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
Logger::Print("Unregistering component: %s\n", component->GetName());
|
||||
if(!Loader::PerformingUnitTests())
|
||||
{
|
||||
Logger::Print("Unregistering component: %s\n", component->GetName());
|
||||
}
|
||||
#endif
|
||||
delete component;
|
||||
}
|
||||
@ -94,7 +99,7 @@ namespace Components
|
||||
|
||||
for (auto component : Loader::Components)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
#if defined(DEBUG) || defined(FORCE_UNIT_TESTS)
|
||||
Logger::Print("Testing '%s'...\n", component->GetName());
|
||||
#endif
|
||||
auto startTime = std::chrono::high_resolution_clock::now();
|
||||
@ -121,7 +126,10 @@ namespace Components
|
||||
if (component)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
Logger::Print("Component registered: %s\n", component->GetName());
|
||||
if(!Loader::PerformingUnitTests())
|
||||
{
|
||||
Logger::Print("Component registered: %s\n", component->GetName());
|
||||
}
|
||||
#endif
|
||||
Loader::Components.push_back(component);
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ namespace Components
|
||||
Component() {};
|
||||
virtual ~Component() {};
|
||||
|
||||
#ifdef DEBUG
|
||||
#if defined(DEBUG) || defined(FORCE_UNIT_TESTS)
|
||||
virtual const char* GetName() { return "Unknown"; };
|
||||
#endif
|
||||
|
||||
@ -39,6 +39,7 @@ namespace Components
|
||||
#include "Modules\Flags.hpp"
|
||||
#include "Modules\Menus.hpp"
|
||||
#include "Modules\Toast.hpp"
|
||||
#include "Modules\Zones.hpp"
|
||||
#include "Modules\Colors.hpp"
|
||||
#include "Modules\D3D9Ex.hpp"
|
||||
#include "Modules\Script.hpp"
|
||||
@ -69,6 +70,7 @@ namespace Components
|
||||
#include "Modules\Singleton.hpp"
|
||||
#include "Modules\BitMessage.hpp"
|
||||
#include "Modules\FileSystem.hpp"
|
||||
#include "Modules\ModelSurfs.hpp"
|
||||
#include "Modules\PlayerName.hpp"
|
||||
#include "Modules\QuickPatch.hpp"
|
||||
#include "Modules\ServerInfo.hpp"
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
namespace Components
|
||||
{
|
||||
int AntiCheat::LastCheck = 0;
|
||||
int AntiCheat::LastCheck;
|
||||
std::string AntiCheat::Hash;
|
||||
Utils::Hook AntiCheat::LoadLibHook[4];
|
||||
unsigned long AntiCheat::Flags = NO_FLAG;
|
||||
@ -92,7 +92,15 @@ namespace Components
|
||||
MessageBoxA(0, "Check the log for more information!", "AntiCheat triggered", MB_ICONERROR);
|
||||
ExitProcess(0xFFFFFFFF);
|
||||
#else
|
||||
Utils::Hook::Set<BYTE>(0x41BA2C, 0xEB);
|
||||
static std::thread triggerThread;
|
||||
if (!triggerThread.joinable())
|
||||
{
|
||||
triggerThread = std::thread([] ()
|
||||
{
|
||||
std::this_thread::sleep_for(43s);
|
||||
Utils::Hook::Set<BYTE>(0x41BA2C, 0xEB);
|
||||
});
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
@ -112,8 +120,7 @@ namespace Components
|
||||
Logger::Print(Utils::String::VA("AntiCheat: Callee assertion failed: %X %s", reinterpret_cast<uint32_t>(callee), buffer));
|
||||
#endif
|
||||
|
||||
//AntiCheat::CrashClient();
|
||||
AntiCheat::Hash.append("\0", 1);
|
||||
AntiCheat::CrashClient();
|
||||
}
|
||||
}
|
||||
|
||||
@ -161,8 +168,10 @@ namespace Components
|
||||
{
|
||||
static int lastCheck = Game::Sys_Milliseconds();
|
||||
|
||||
if ((Game::Sys_Milliseconds() - lastCheck) > 1000 * 70)
|
||||
if ((Game::Sys_Milliseconds() - lastCheck) > 1000 * 20)
|
||||
{
|
||||
lastCheck = Game::Sys_Milliseconds();
|
||||
|
||||
if (HANDLE h = OpenProcess(PROCESS_VM_READ, TRUE, GetCurrentProcessId()))
|
||||
{
|
||||
#ifdef DEBUG_DETECTIONS
|
||||
@ -170,7 +179,7 @@ namespace Components
|
||||
#endif
|
||||
|
||||
CloseHandle(h);
|
||||
AntiCheat::Hash.append("\0", 1);
|
||||
AntiCheat::CrashClient();
|
||||
}
|
||||
}
|
||||
|
||||
@ -182,7 +191,7 @@ namespace Components
|
||||
{
|
||||
static int lastCheck = Game::Sys_Milliseconds();
|
||||
|
||||
if ((Game::Sys_Milliseconds() - lastCheck) > 1000 * 180)
|
||||
if ((Game::Sys_Milliseconds() - lastCheck) > 1000 * 30)
|
||||
{
|
||||
lastCheck = Game::Sys_Milliseconds();
|
||||
|
||||
@ -208,10 +217,8 @@ namespace Components
|
||||
if (lastCheck) count = 0;
|
||||
else ++count;
|
||||
|
||||
if (milliseconds < 1000 * 40) return;
|
||||
|
||||
// If there was no check within the last 120 seconds, crash!
|
||||
if ((lastCheck && (milliseconds - lastCheck) > 1000 * 120) || count > 1)
|
||||
if ((milliseconds > 1000 * 25) && ((lastCheck && (milliseconds - lastCheck) > 1000 * 40) || count > 1))
|
||||
{
|
||||
#ifdef DEBUG_DETECTIONS
|
||||
Logger::Print("AntiCheat: Integrity check failed");
|
||||
@ -254,7 +261,7 @@ namespace Components
|
||||
void AntiCheat::Frame()
|
||||
{
|
||||
// Perform check only every 30 seconds
|
||||
if (AntiCheat::LastCheck && (Game::Sys_Milliseconds() - AntiCheat::LastCheck) < 1000 * 30) return;
|
||||
if (AntiCheat::LastCheck && (Game::Sys_Milliseconds() - AntiCheat::LastCheck) < 1000 * 10) return;
|
||||
AntiCheat::LastCheck = Game::Sys_Milliseconds();
|
||||
|
||||
AntiCheat::PerformCheck();
|
||||
@ -627,6 +634,9 @@ namespace Components
|
||||
|
||||
AntiCheat::AntiCheat()
|
||||
{
|
||||
AntiCheat::Flags = NO_FLAG;
|
||||
AntiCheat::LastCheck = 0;
|
||||
|
||||
AntiCheat::EmptyHash();
|
||||
|
||||
#ifdef DEBUG
|
||||
|
@ -11,7 +11,7 @@ namespace Components
|
||||
AntiCheat();
|
||||
~AntiCheat();
|
||||
|
||||
#ifdef DEBUG
|
||||
#if defined(DEBUG) || defined(FORCE_UNIT_TESTS)
|
||||
const char* GetName() { return "AntiCheat"; };
|
||||
#endif
|
||||
|
||||
|
@ -20,7 +20,7 @@ namespace Components
|
||||
AssetHandler();
|
||||
~AssetHandler();
|
||||
|
||||
#ifdef DEBUG
|
||||
#if defined(DEBUG) || defined(FORCE_UNIT_TESTS)
|
||||
const char* GetName() { return "AssetHandler"; };
|
||||
#endif
|
||||
|
||||
|
@ -34,8 +34,10 @@ namespace Assets
|
||||
return;
|
||||
}
|
||||
|
||||
const Game::GfxImageFileHeader* iwiHeader = reinterpret_cast<const Game::GfxImageFileHeader*>(iwi.GetBuffer().data());
|
||||
auto iwiBuffer = iwi.GetBuffer();
|
||||
|
||||
const Game::GfxImageFileHeader* iwiHeader = reinterpret_cast<const Game::GfxImageFileHeader*>(iwiBuffer.data());
|
||||
|
||||
image->mapType = 3;
|
||||
image->dataLen1 = iwiHeader->fileSizeForPicmip[0] - 32;
|
||||
image->dataLen2 = iwiHeader->fileSizeForPicmip[0] - 32;
|
||||
|
@ -6,7 +6,7 @@ namespace Assets
|
||||
{
|
||||
Game::MaterialTechniqueSet* asset = header.materialTechset;
|
||||
|
||||
for (int i = 0; i < ARR_SIZE(Game::MaterialTechniqueSet::techniques); ++i)
|
||||
for (int i = 0; i < ARRAYSIZE(Game::MaterialTechniqueSet::techniques); ++i)
|
||||
{
|
||||
Game::MaterialTechnique* technique = asset->techniques[i];
|
||||
|
||||
@ -52,9 +52,9 @@ namespace Assets
|
||||
}
|
||||
|
||||
// Save_MaterialTechniquePtrArray
|
||||
static_assert(ARR_SIZE(Game::MaterialTechniqueSet::techniques) == 48, "Techniques array invalid!");
|
||||
static_assert(ARRAYSIZE(Game::MaterialTechniqueSet::techniques) == 48, "Techniques array invalid!");
|
||||
|
||||
for (int i = 0; i < ARR_SIZE(Game::MaterialTechniqueSet::techniques); ++i)
|
||||
for (int i = 0; i < ARRAYSIZE(Game::MaterialTechniqueSet::techniques); ++i)
|
||||
{
|
||||
Game::MaterialTechnique* technique = asset->techniques[i];
|
||||
|
||||
|
@ -6,7 +6,7 @@ namespace Components
|
||||
Auth();
|
||||
~Auth();
|
||||
|
||||
#ifdef DEBUG
|
||||
#if defined(DEBUG) || defined(FORCE_UNIT_TESTS)
|
||||
const char* GetName() { return "Auth"; };
|
||||
#endif
|
||||
|
||||
|
@ -8,7 +8,7 @@ namespace Components
|
||||
Bans();
|
||||
~Bans();
|
||||
|
||||
#ifdef DEBUG
|
||||
#if defined(DEBUG) || defined(FORCE_UNIT_TESTS)
|
||||
const char* GetName() { return "Bans"; };
|
||||
#endif
|
||||
|
||||
|
@ -13,11 +13,9 @@ namespace Components
|
||||
BitMessage::BitMessage()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
Logger::Print("Initializing BitMessage...\n");
|
||||
Logger::Print("Initializing BitMessage...\n");
|
||||
#endif // DEBUG
|
||||
|
||||
|
||||
|
||||
BitMessage::BMClient = new BitMRC(BITMESSAGE_OBJECT_STORAGE_FILENAME, BITMESSAGE_KEYS_FILENAME);
|
||||
BitMessage::BMClient->init();
|
||||
BitMessage::BMClient->defaultTTL = 1 * 60 * 60; // 1 hour
|
||||
@ -36,7 +34,7 @@ Logger::Print("Initializing BitMessage...\n");
|
||||
BitMessage::BMClient->start();
|
||||
|
||||
#ifdef DEBUG
|
||||
Command::Add("bm_send", [](Command::Params params)
|
||||
Command::Add("bm_send", [](Command::Params params)
|
||||
{
|
||||
if (params.Length() < 3) return;
|
||||
|
||||
@ -70,7 +68,7 @@ Logger::Print("Initializing BitMessage...\n");
|
||||
Logger::Print("Broadcast done.\n");
|
||||
});
|
||||
|
||||
Command::Add("bm_check_messages", [](Command::Params)
|
||||
Command::Add("bm_check_messages", [](Command::Params)
|
||||
{
|
||||
while (BitMessage::BMClient->new_messages.size() > 0)
|
||||
{
|
||||
@ -79,7 +77,7 @@ Logger::Print("Initializing BitMessage...\n");
|
||||
}
|
||||
});
|
||||
|
||||
Command::Add("bm_check_connections", [](Command::Params)
|
||||
Command::Add("bm_check_connections", [](Command::Params)
|
||||
{
|
||||
std::shared_lock<std::shared_timed_mutex> mlock(BitMessage::BMClient->mutex_nodes);
|
||||
|
||||
@ -104,7 +102,7 @@ Logger::Print("Initializing BitMessage...\n");
|
||||
mlock.unlock();
|
||||
});
|
||||
|
||||
Command::Add("bm_check_privatekey", [](Command::Params)
|
||||
Command::Add("bm_check_privatekey", [](Command::Params)
|
||||
{
|
||||
std::shared_lock<std::shared_timed_mutex> mlock(BitMessage::BMClient->mutex_priv);
|
||||
|
||||
@ -123,7 +121,7 @@ Logger::Print("Initializing BitMessage...\n");
|
||||
mlock.unlock();
|
||||
});
|
||||
|
||||
Command::Add("bm_check_publickey", [](Command::Params)
|
||||
Command::Add("bm_check_publickey", [](Command::Params)
|
||||
{
|
||||
std::shared_lock<std::shared_timed_mutex> mlock(BitMessage::BMClient->mutex_pub);
|
||||
|
||||
@ -140,12 +138,12 @@ Logger::Print("Initializing BitMessage...\n");
|
||||
mlock.unlock();
|
||||
});
|
||||
|
||||
Command::Add("bm_save", [](Command::Params)
|
||||
Command::Add("bm_save", [](Command::Params)
|
||||
{
|
||||
BitMessage::Save();
|
||||
});
|
||||
|
||||
Command::Add("bm_address_public", [](Command::Params params)
|
||||
Command::Add("bm_address_public", [](Command::Params params)
|
||||
{
|
||||
if (params.Length() < 2) return;
|
||||
|
||||
@ -165,7 +163,7 @@ Logger::Print("Initializing BitMessage...\n");
|
||||
}
|
||||
});
|
||||
|
||||
Command::Add("bm_address_broadcast", [](Command::Params params)
|
||||
Command::Add("bm_address_broadcast", [](Command::Params params)
|
||||
{
|
||||
if (params.Length() < 2) return;
|
||||
|
||||
|
@ -13,7 +13,7 @@ namespace Components
|
||||
BitMessage();
|
||||
~BitMessage();
|
||||
|
||||
#ifdef DEBUG
|
||||
#if defined(DEBUG) || defined(FORCE_UNIT_TESTS)
|
||||
const char* GetName() { return "BitMessage"; };
|
||||
#endif
|
||||
|
||||
|
@ -6,7 +6,7 @@ namespace Components
|
||||
Colors();
|
||||
~Colors();
|
||||
|
||||
#ifdef DEBUG
|
||||
#if defined(DEBUG) || defined(FORCE_UNIT_TESTS)
|
||||
const char* GetName() { return "Colors"; };
|
||||
#endif
|
||||
|
||||
|
@ -26,7 +26,7 @@ namespace Components
|
||||
Command();
|
||||
~Command();
|
||||
|
||||
#ifdef DEBUG
|
||||
#if defined(DEBUG) || defined(FORCE_UNIT_TESTS)
|
||||
const char* GetName() { return "Command"; };
|
||||
#endif
|
||||
|
||||
|
@ -5,7 +5,7 @@ namespace Components
|
||||
public:
|
||||
ConnectProtocol();
|
||||
|
||||
#ifdef DEBUG
|
||||
#if defined(DEBUG) || defined(FORCE_UNIT_TESTS)
|
||||
const char* GetName() { return "ConnectProtocol"; };
|
||||
#endif
|
||||
|
||||
|
@ -9,7 +9,7 @@ namespace Components
|
||||
Console();
|
||||
~Console();
|
||||
|
||||
#ifdef DEBUG
|
||||
#if defined(DEBUG) || defined(FORCE_UNIT_TESTS)
|
||||
const char* GetName() { return "Console"; };
|
||||
#endif
|
||||
|
||||
|
@ -5,7 +5,7 @@ namespace Components
|
||||
public:
|
||||
D3D9Ex();
|
||||
|
||||
#ifdef DEBUG
|
||||
#if defined(DEBUG) || defined(FORCE_UNIT_TESTS)
|
||||
const char* GetName() { return "D3D9Ex"; };
|
||||
#endif
|
||||
|
||||
|
@ -8,7 +8,7 @@ namespace Components
|
||||
Dedicated();
|
||||
~Dedicated();
|
||||
|
||||
#ifdef DEBUG
|
||||
#if defined(DEBUG) || defined(FORCE_UNIT_TESTS)
|
||||
const char* GetName() { return "Dedicated"; };
|
||||
#endif
|
||||
|
||||
|
@ -6,7 +6,7 @@ namespace Components
|
||||
Discovery();
|
||||
~Discovery();
|
||||
|
||||
#ifdef DEBUG
|
||||
#if defined(DEBUG) || defined(FORCE_UNIT_TESTS)
|
||||
const char* GetName() { return "Discovery"; };
|
||||
#endif
|
||||
|
||||
|
@ -522,7 +522,7 @@ namespace Components
|
||||
|
||||
if (file.Exists())
|
||||
{
|
||||
std::string& buffer = file.GetBuffer();
|
||||
std::string buffer = file.GetBuffer();
|
||||
|
||||
mg_printf(nc,
|
||||
"HTTP/1.1 200 OK\r\n"
|
||||
|
@ -6,7 +6,7 @@ namespace Components
|
||||
Download();
|
||||
~Download();
|
||||
|
||||
#ifdef DEBUG
|
||||
#if defined(DEBUG) || defined(FORCE_UNIT_TESTS)
|
||||
const char* GetName() { return "Download"; };
|
||||
#endif
|
||||
|
||||
|
@ -42,7 +42,7 @@ namespace Components
|
||||
Dvar();
|
||||
~Dvar();
|
||||
|
||||
#ifdef DEBUG
|
||||
#if defined(DEBUG) || defined(FORCE_UNIT_TESTS)
|
||||
const char* GetName() { return "Dvar"; };
|
||||
#endif
|
||||
|
||||
|
@ -8,7 +8,7 @@ namespace Components
|
||||
Exception();
|
||||
~Exception();
|
||||
|
||||
#ifdef DEBUG
|
||||
#if defined(DEBUG) || defined(FORCE_UNIT_TESTS)
|
||||
const char* GetName() { return "Exception"; };
|
||||
#endif
|
||||
static LPTOP_LEVEL_EXCEPTION_FILTER Hook();
|
||||
|
@ -147,11 +147,13 @@ namespace Components
|
||||
{
|
||||
Game::DB_ReadXFileUncompressed(version, size);
|
||||
|
||||
// Allow loading out custom version
|
||||
// Allow loading of custom version
|
||||
if (*version == XFILE_VERSION_IW4X)
|
||||
{
|
||||
*version = XFILE_VERSION;
|
||||
}
|
||||
|
||||
Zones::InstallPatches(*version);
|
||||
}
|
||||
|
||||
FastFiles::FastFiles()
|
||||
|
@ -6,7 +6,7 @@ namespace Components
|
||||
FastFiles();
|
||||
~FastFiles();
|
||||
|
||||
#ifdef DEBUG
|
||||
#if defined(DEBUG) || defined(FORCE_UNIT_TESTS)
|
||||
const char* GetName() { return "FastFiles"; };
|
||||
#endif
|
||||
|
||||
|
@ -2,24 +2,64 @@
|
||||
|
||||
namespace Components
|
||||
{
|
||||
void FileSystem::File::Read()
|
||||
FileSystem::File::File(std::string file) : Name(file), Handle(0)
|
||||
{
|
||||
this->Size = Game::FS_FOpenFileRead(this->Name.data(), &this->Handle, 0);
|
||||
}
|
||||
|
||||
FileSystem::File::~File()
|
||||
{
|
||||
char* buffer = nullptr;
|
||||
int size = Game::FS_ReadFile(this->FilePath.data(), &buffer);
|
||||
|
||||
this->Buffer.clear();
|
||||
|
||||
if (size < 0)
|
||||
if (this->Exists())
|
||||
{
|
||||
if (buffer)
|
||||
{
|
||||
Game::FS_FreeFile(buffer);
|
||||
}
|
||||
Game::FS_FCloseFile(this->Handle);
|
||||
}
|
||||
else
|
||||
}
|
||||
|
||||
bool FileSystem::File::Exists()
|
||||
{
|
||||
return (this->Size > 0);
|
||||
}
|
||||
|
||||
std::string FileSystem::File::GetName()
|
||||
{
|
||||
return this->Name;
|
||||
}
|
||||
|
||||
std::string FileSystem::File::GetBuffer()
|
||||
{
|
||||
Utils::Memory::Allocator allocator;
|
||||
if (!this->Exists()) return std::string();
|
||||
|
||||
int position = Game::FS_FTell(this->Handle);
|
||||
this->Seek(0, FS_SEEK_SET);
|
||||
|
||||
char* buffer = allocator.AllocateArray<char>(this->Size);
|
||||
if (!FileSystem::File::Read(buffer, this->Size))
|
||||
{
|
||||
this->Buffer.append(buffer, size);
|
||||
Game::FS_FreeFile(buffer);
|
||||
this->Seek(position, FS_SEEK_SET);
|
||||
return std::string();
|
||||
}
|
||||
|
||||
this->Seek(position, FS_SEEK_SET);
|
||||
|
||||
return std::string(buffer, this->Size);
|
||||
}
|
||||
|
||||
bool FileSystem::File::Read(void* buffer, size_t size)
|
||||
{
|
||||
if (!this->Exists() || static_cast<size_t>(this->Size) < size || Game::FS_Read(buffer, size, this->Handle) != static_cast<int>(size))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void FileSystem::File::Seek(int offset, int origin)
|
||||
{
|
||||
if (this->Exists())
|
||||
{
|
||||
Game::FS_Seek(this->Handle, offset, origin);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7,18 +7,20 @@ namespace Components
|
||||
class File
|
||||
{
|
||||
public:
|
||||
File() {};
|
||||
File(std::string file) : FilePath(file) { this->Read(); };
|
||||
File() : Size(-1), Name(), Handle(0) {};
|
||||
File(std::string file);
|
||||
~File();
|
||||
|
||||
bool Exists() { return !this->Buffer.empty(); };
|
||||
std::string GetName() { return this->FilePath; };
|
||||
std::string& GetBuffer() { return this->Buffer; };
|
||||
bool Exists();
|
||||
std::string GetName();
|
||||
std::string GetBuffer();
|
||||
bool Read(void* buffer, size_t size);
|
||||
void Seek(int offset, int origin);
|
||||
|
||||
private:
|
||||
std::string FilePath;
|
||||
std::string Buffer;
|
||||
|
||||
void Read();
|
||||
int Handle;
|
||||
int Size;
|
||||
std::string Name;
|
||||
};
|
||||
|
||||
class FileWriter
|
||||
@ -39,7 +41,7 @@ namespace Components
|
||||
|
||||
FileSystem();
|
||||
|
||||
#ifdef DEBUG
|
||||
#if defined(DEBUG) || defined(FORCE_UNIT_TESTS)
|
||||
const char* GetName() { return "FileSystem"; };
|
||||
#endif
|
||||
|
||||
|
@ -6,7 +6,7 @@ namespace Components
|
||||
Flags();
|
||||
~Flags();
|
||||
|
||||
#ifdef DEBUG
|
||||
#if defined(DEBUG) || defined(FORCE_UNIT_TESTS)
|
||||
const char* GetName() { return "Flags"; };
|
||||
#endif
|
||||
|
||||
|
@ -63,7 +63,7 @@ namespace Components
|
||||
IPCPipe();
|
||||
~IPCPipe();
|
||||
|
||||
#ifdef DEBUG
|
||||
#if defined(DEBUG) || defined(FORCE_UNIT_TESTS)
|
||||
const char* GetName() { return "IPCPipe"; };
|
||||
#endif
|
||||
|
||||
|
@ -8,7 +8,7 @@ namespace Components
|
||||
public:
|
||||
Lean();
|
||||
|
||||
#ifdef DEBUG
|
||||
#if defined(DEBUG) || defined(FORCE_UNIT_TESTS)
|
||||
const char* GetName() { return "Lean"; };
|
||||
#endif
|
||||
|
||||
|
@ -6,7 +6,7 @@ namespace Components
|
||||
Localization();
|
||||
~Localization();
|
||||
|
||||
#ifdef DEBUG
|
||||
#if defined(DEBUG) || defined(FORCE_UNIT_TESTS)
|
||||
const char* GetName() { return "Localization"; };
|
||||
#endif
|
||||
|
||||
|
@ -12,6 +12,11 @@ namespace Components
|
||||
return (IsWindow(*reinterpret_cast<HWND*>(0x64A3288)) != FALSE || (Dedicated::IsEnabled() && !Flags::HasFlag("console")));
|
||||
}
|
||||
|
||||
void Logger::PrintStub(int channel, const char* message, ...)
|
||||
{
|
||||
return Logger::MessagePrint(channel, Logger::Format(&message));
|
||||
}
|
||||
|
||||
void Logger::Print(const char* message, ...)
|
||||
{
|
||||
return Logger::MessagePrint(0, Logger::Format(&message));
|
||||
@ -176,6 +181,11 @@ namespace Components
|
||||
Utils::Hook(0x4B0218, Logger::GameLogStub, HOOK_CALL).Install()->Quick();
|
||||
Utils::Hook(Game::Com_PrintMessage, Logger::PrintMessageStub, HOOK_JUMP).Install()->Quick();
|
||||
|
||||
if (Loader::PerformingUnitTests())
|
||||
{
|
||||
Utils::Hook(Game::Com_Printf, Logger::PrintStub, HOOK_JUMP).Install()->Quick();
|
||||
}
|
||||
|
||||
Dvar::OnInit([] ()
|
||||
{
|
||||
Command::AddSV("log_add", [] (Command::Params params)
|
||||
|
@ -6,7 +6,7 @@ namespace Components
|
||||
Logger();
|
||||
~Logger();
|
||||
|
||||
#ifdef DEBUG
|
||||
#if defined(DEBUG) || defined(FORCE_UNIT_TESTS)
|
||||
const char* GetName() { return "Logger"; };
|
||||
#endif
|
||||
|
||||
@ -19,6 +19,8 @@ namespace Components
|
||||
static void SoftError(const char* message, ...);
|
||||
static bool IsConsoleReady();
|
||||
|
||||
static void PrintStub(int channel, const char* message, ...);
|
||||
|
||||
static void PipeOutput(void(*callback)(std::string));
|
||||
|
||||
private:
|
||||
|
@ -6,7 +6,7 @@ namespace Components
|
||||
Maps();
|
||||
~Maps();
|
||||
|
||||
#ifdef DEBUG
|
||||
#if defined(DEBUG) || defined(FORCE_UNIT_TESTS)
|
||||
const char* GetName() { return "Maps"; };
|
||||
#endif
|
||||
|
||||
|
@ -6,7 +6,7 @@ namespace Components
|
||||
Materials();
|
||||
~Materials();
|
||||
|
||||
#ifdef DEBUG
|
||||
#if defined(DEBUG) || defined(FORCE_UNIT_TESTS)
|
||||
const char* GetName() { return "Materials"; };
|
||||
#endif
|
||||
|
||||
|
@ -25,7 +25,7 @@ namespace Components
|
||||
return i;
|
||||
}
|
||||
|
||||
Game::script_t* Menus::LoadMenuScript(std::string name, std::string& buffer)
|
||||
Game::script_t* Menus::LoadMenuScript(std::string name, std::string buffer)
|
||||
{
|
||||
Game::script_t* script = Game::Script_Alloc(sizeof(Game::script_t) + 1 + buffer.length());
|
||||
|
||||
@ -52,7 +52,7 @@ namespace Components
|
||||
return script;
|
||||
}
|
||||
|
||||
int Menus::LoadMenuSource(std::string name, std::string& buffer)
|
||||
int Menus::LoadMenuSource(std::string name, std::string buffer)
|
||||
{
|
||||
int handle = Menus::ReserveSourceHandle();
|
||||
if (!Menus::IsValidSourceHandle(handle)) return 0; // No free source slot!
|
||||
|
@ -9,7 +9,7 @@ namespace Components
|
||||
Menus();
|
||||
~Menus();
|
||||
|
||||
#ifdef DEBUG
|
||||
#if defined(DEBUG) || defined(FORCE_UNIT_TESTS)
|
||||
const char* GetName() { return "Menus"; };
|
||||
#endif
|
||||
|
||||
@ -30,8 +30,8 @@ namespace Components
|
||||
static std::vector<Game::menuDef_t*> LoadMenu(Game::menuDef_t* menudef);
|
||||
static std::vector<Game::menuDef_t*> LoadMenu(std::string file);
|
||||
|
||||
static Game::script_t* LoadMenuScript(std::string name, std::string& buffer);
|
||||
static int LoadMenuSource(std::string name, std::string& buffer);
|
||||
static Game::script_t* LoadMenuScript(std::string name, std::string buffer);
|
||||
static int LoadMenuSource(std::string name, std::string buffer);
|
||||
|
||||
static int ReserveSourceHandle();
|
||||
static bool IsValidSourceHandle(int handle);
|
||||
|
@ -157,6 +157,7 @@ namespace Components
|
||||
MinidumpUpload::MinidumpUpload()
|
||||
{
|
||||
#if !defined(DEBUG) || defined(FORCE_MINIDUMP_UPLOAD)
|
||||
if (Loader::PerformingUnitTests() || ZoneBuilder::IsEnabled()) return;
|
||||
this->uploadThread = std::thread([&]() { this->UploadQueuedMinidumps(); });
|
||||
#endif
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ namespace Components
|
||||
class MinidumpUpload : public Component
|
||||
{
|
||||
public:
|
||||
#ifdef DEBUG
|
||||
#if defined(DEBUG) || defined(FORCE_UNIT_TESTS)
|
||||
const char* GetName() { return "MinidumpUpload"; };
|
||||
#endif
|
||||
MinidumpUpload();
|
||||
|
@ -6,7 +6,7 @@ namespace Components
|
||||
ModList();
|
||||
~ModList();
|
||||
|
||||
#ifdef DEBUG
|
||||
#if defined(DEBUG) || defined(FORCE_UNIT_TESTS)
|
||||
const char* GetName() { return "ModList"; };
|
||||
#endif
|
||||
|
||||
|
308
src/Components/Modules/ModelSurfs.cpp
Normal file
308
src/Components/Modules/ModelSurfs.cpp
Normal file
@ -0,0 +1,308 @@
|
||||
#include "STDInclude.hpp"
|
||||
|
||||
namespace Components
|
||||
{
|
||||
std::map<void*, IUnknown*> ModelSurfs::BufferMap;
|
||||
std::map<void*, Game::CModelAllocData*> ModelSurfs::AllocMap;
|
||||
|
||||
IUnknown* ModelSurfs::GetBuffer(void* buffer)
|
||||
{
|
||||
return ModelSurfs::BufferMap[buffer];
|
||||
}
|
||||
|
||||
void ModelSurfs::SetBuffer(char /*streamHandle*/, void* buffer, IUnknown** bufferOut, int* offsetOut)
|
||||
{
|
||||
*offsetOut = 0;
|
||||
*bufferOut = ModelSurfs::BufferMap[buffer];
|
||||
}
|
||||
|
||||
void ModelSurfs::CreateBuffers(Game::XModelSurfs* surfs)
|
||||
{
|
||||
for (int i = 0; i < surfs->numSurfaces; ++i)
|
||||
{
|
||||
Game::XSurface* surface = &surfs->surfaces[i];
|
||||
if (surface->streamHandle == 0xFF)
|
||||
{
|
||||
IDirect3DVertexBuffer9* vertexBuffer;
|
||||
IDirect3DIndexBuffer9* indexBuffer;
|
||||
|
||||
Game::Load_VertexBuffer(surface->vertexBuffer, &vertexBuffer, surface->numVertices * 32);
|
||||
Game::Load_IndexBuffer(surface->indexBuffer, &indexBuffer, surface->numPrimitives * 3);
|
||||
|
||||
ModelSurfs::BufferMap[surface->vertexBuffer] = vertexBuffer;
|
||||
ModelSurfs::BufferMap[surface->indexBuffer] = indexBuffer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Game::XModelSurfs* ModelSurfs::LoadXModelSurfaces(std::string name)
|
||||
{
|
||||
Utils::Memory::Allocator allocator;
|
||||
FileSystem::File model(fmt::sprintf("models/%s", name.data()));
|
||||
|
||||
if (!model.Exists())
|
||||
{
|
||||
Logger::Error("Loading model %s failed!", name.data());
|
||||
}
|
||||
|
||||
Game::CModelHeader header;
|
||||
if (!model.Read(&header, sizeof header))
|
||||
{
|
||||
Logger::Error("Reading header for model %s failed!", name.data());
|
||||
}
|
||||
|
||||
if (header.version != 1)
|
||||
{
|
||||
Logger::Error("Model %s has an invalid version %d (should be 1)!", name.data(), header.version);
|
||||
}
|
||||
|
||||
// Allocate section buffers
|
||||
header.sectionHeader[Game::SECTION_MAIN].buffer = Utils::Memory::Allocate(header.sectionHeader[Game::SECTION_MAIN].size);
|
||||
header.sectionHeader[Game::SECTION_INDEX].buffer = Utils::Memory::AllocateAlign(header.sectionHeader[Game::SECTION_INDEX].size, 16);
|
||||
header.sectionHeader[Game::SECTION_VERTEX].buffer = Utils::Memory::AllocateAlign(header.sectionHeader[Game::SECTION_VERTEX].size, 16);
|
||||
header.sectionHeader[Game::SECTION_FIXUP].buffer = allocator.AllocateArray<char>(header.sectionHeader[Game::SECTION_FIXUP].size);
|
||||
|
||||
// Load section data
|
||||
for (int i = 0; i < ARRAY_SIZE(header.sectionHeader); ++i)
|
||||
{
|
||||
model.Seek(header.sectionHeader[i].offset, FS_SEEK_SET);
|
||||
if (!model.Read(header.sectionHeader[i].buffer, header.sectionHeader[i].size))
|
||||
{
|
||||
Logger::Error("Reading section %d for model %s failed!", i, name.data());
|
||||
}
|
||||
}
|
||||
|
||||
// Fixup sections
|
||||
unsigned int* fixups = reinterpret_cast<unsigned int*>(header.sectionHeader[Game::SECTION_FIXUP].buffer);
|
||||
for (int i = 0; i < 3; ++i)
|
||||
{
|
||||
Game::CModelSectionHeader* section = &header.sectionHeader[i];
|
||||
for (int j = section->fixupStart; j < section->fixupStart + section->fixupCount; ++j)
|
||||
{
|
||||
unsigned int fixup = fixups[i];
|
||||
*reinterpret_cast<DWORD*>(reinterpret_cast<char*>(section->buffer) + (fixup >> 3)) += reinterpret_cast<DWORD>(header.sectionHeader[fixup & 3].buffer);
|
||||
}
|
||||
}
|
||||
|
||||
// Store allocation data (not sure if this is correct)
|
||||
Game::CModelAllocData* allocationData = Utils::Memory::AllocateArray<Game::CModelAllocData>();
|
||||
allocationData->mainArray = header.sectionHeader[Game::SECTION_MAIN].buffer;
|
||||
allocationData->indexBuffer = header.sectionHeader[Game::SECTION_INDEX].buffer;
|
||||
allocationData->vertexBuffer = header.sectionHeader[Game::SECTION_VERTEX].buffer;
|
||||
|
||||
ModelSurfs::AllocMap[allocationData->vertexBuffer] = allocationData;
|
||||
*reinterpret_cast<void**>(reinterpret_cast<char*>(allocationData->mainArray) + 44) = allocationData;
|
||||
|
||||
Assert_Size(Game::XSurface, 64);
|
||||
Game::XModelSurfs* modelSurfs = reinterpret_cast<Game::XModelSurfs*>(allocationData->mainArray);
|
||||
Game::XSurface* tempSurfaces = allocator.AllocateArray<Game::XSurface>(modelSurfs->numSurfaces);
|
||||
char* surfaceData = reinterpret_cast<char*>(modelSurfs->surfaces);
|
||||
|
||||
for (int i = 0; i < modelSurfs->numSurfaces; ++i)
|
||||
{
|
||||
memcpy(&tempSurfaces[i], surfaceData + (i * 84), 12);
|
||||
memcpy(&tempSurfaces[i].indexBuffer, surfaceData + (i * 84) + 16, 20);
|
||||
memcpy(&tempSurfaces[i].numCT, surfaceData + (i * 84) + 40, 8);
|
||||
memcpy(&tempSurfaces[i].pad5, surfaceData + (i * 84) + 52, 24);
|
||||
tempSurfaces[i].streamHandle = 0xFF; // Fake handle for buffer interception
|
||||
}
|
||||
|
||||
memcpy(surfaceData, tempSurfaces, 64 * modelSurfs->numSurfaces);
|
||||
|
||||
ModelSurfs::CreateBuffers(modelSurfs);
|
||||
|
||||
return modelSurfs;
|
||||
}
|
||||
|
||||
bool ModelSurfs::LoadSurfaces(Game::XModel* model)
|
||||
{
|
||||
if (!model) return false;
|
||||
bool changed = false;
|
||||
|
||||
short surfCount = 0;
|
||||
|
||||
for (char i = 0; i < model->numLods; ++i)
|
||||
{
|
||||
Game::XModelSurfs* surfs = model->lods[i].surfaces;
|
||||
|
||||
if (!surfs->surfaces)
|
||||
{
|
||||
Game::XModelSurfs* newSurfs = ModelSurfs::LoadXModelSurfaces(surfs->name);
|
||||
|
||||
surfs->surfaces = newSurfs->surfaces;
|
||||
surfs->numSurfaces = newSurfs->numSurfaces;
|
||||
|
||||
model->lods[i].surfaces = newSurfs;
|
||||
memcpy(model->lods[i].pad3, newSurfs->pad, 24);
|
||||
|
||||
short numSurfs = static_cast<short>(newSurfs->numSurfaces);
|
||||
model->lods[i].someCount = numSurfs;
|
||||
model->lods[i].someTotalCount = surfCount;
|
||||
surfCount += numSurfs;
|
||||
}
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
void ModelSurfs::ReleaseModelSurf(Game::XAssetHeader header)
|
||||
{
|
||||
for (int i = 0; i < header.surfaces->numSurfaces && header.surfaces->surfaces; ++i)
|
||||
{
|
||||
Game::XSurface* surface = &header.surfaces->surfaces[i];
|
||||
if (surface->streamHandle == 0xFF)
|
||||
{
|
||||
auto buffer = ModelSurfs::BufferMap.find(surface->indexBuffer);
|
||||
if (buffer != ModelSurfs::BufferMap.end())
|
||||
{
|
||||
buffer->second->Release();
|
||||
ModelSurfs::BufferMap.erase(buffer);
|
||||
}
|
||||
|
||||
buffer = ModelSurfs::BufferMap.find(surface->vertexBuffer);
|
||||
if (buffer != ModelSurfs::BufferMap.end())
|
||||
{
|
||||
buffer->second->Release();
|
||||
ModelSurfs::BufferMap.erase(buffer);
|
||||
}
|
||||
|
||||
auto allocData = ModelSurfs::AllocMap.find(surface->vertexBuffer);
|
||||
if (allocData != ModelSurfs::AllocMap.end())
|
||||
{
|
||||
Utils::Memory::Free(allocData->second->indexBuffer);
|
||||
Utils::Memory::Free(allocData->second->vertexBuffer);
|
||||
Utils::Memory::Free(allocData->second->mainArray);
|
||||
Utils::Memory::Free(allocData->second);
|
||||
|
||||
ModelSurfs::AllocMap.erase(allocData);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ModelSurfs::BeginRecover()
|
||||
{
|
||||
for (auto& buffer : ModelSurfs::BufferMap)
|
||||
{
|
||||
buffer.second->Release();
|
||||
}
|
||||
|
||||
ModelSurfs::BufferMap.clear();
|
||||
}
|
||||
|
||||
void ModelSurfs::EndRecover()
|
||||
{
|
||||
Game::DB_EnumXAssets_Internal(Game::XAssetType::ASSET_TYPE_XMODELSURFS, [] (Game::XAssetHeader header, void* /*userdata*/)
|
||||
{
|
||||
ModelSurfs::CreateBuffers(header.surfaces);
|
||||
}, nullptr, false);
|
||||
}
|
||||
|
||||
void ModelSurfs::XModelSurfsFixup(Game::XModel* model)
|
||||
{
|
||||
if (!ModelSurfs::LoadSurfaces(model))
|
||||
{
|
||||
Game::DB_XModelSurfsFixup(model);
|
||||
}
|
||||
}
|
||||
|
||||
__declspec(naked) void ModelSurfs::GetIndexBufferStub()
|
||||
{
|
||||
__asm
|
||||
{
|
||||
mov eax, [esp + 4h]
|
||||
cmp al, 0FFh
|
||||
|
||||
jne returnSafe
|
||||
|
||||
jmp ModelSurfs::SetBuffer
|
||||
|
||||
returnSafe:
|
||||
movzx eax, [esp + 4h]
|
||||
mov edx, 4B4DE5h
|
||||
jmp edx
|
||||
}
|
||||
}
|
||||
|
||||
__declspec(naked) void ModelSurfs::GetIndexBufferStub2()
|
||||
{
|
||||
__asm
|
||||
{
|
||||
mov eax, [esp + 4h]
|
||||
cmp al, 0FFh
|
||||
|
||||
jne returnSafe
|
||||
|
||||
mov eax, [edi + 0Ch]
|
||||
push eax
|
||||
call ModelSurfs::GetBuffer
|
||||
add esp, 4h
|
||||
retn
|
||||
|
||||
returnSafe:
|
||||
mov eax, 4FDC20h
|
||||
jmp eax
|
||||
}
|
||||
}
|
||||
|
||||
__declspec(naked) void ModelSurfs::GetIndexBaseStub()
|
||||
{
|
||||
__asm
|
||||
{
|
||||
mov eax, [esp + 4h]
|
||||
cmp al, 0FFh
|
||||
|
||||
jne returnSafe
|
||||
|
||||
xor eax, eax
|
||||
retn
|
||||
|
||||
returnSafe:
|
||||
mov eax, 48C5F0h
|
||||
jmp eax
|
||||
}
|
||||
}
|
||||
|
||||
__declspec(naked) void ModelSurfs::GetVertexBufferStub()
|
||||
{
|
||||
__asm
|
||||
{
|
||||
mov eax, [esp + 4h]
|
||||
cmp al, 0FFh
|
||||
|
||||
jne returnSafe
|
||||
|
||||
jmp ModelSurfs::SetBuffer
|
||||
|
||||
returnSafe:
|
||||
movzx eax, [esp + 4h]
|
||||
mov edx, 5BC055h
|
||||
jmp edx
|
||||
}
|
||||
}
|
||||
|
||||
ModelSurfs::ModelSurfs()
|
||||
{
|
||||
ModelSurfs::BufferMap.clear();
|
||||
|
||||
// Install release handler
|
||||
Game::DB_ReleaseXAssetHandlers[Game::XAssetType::ASSET_TYPE_XMODELSURFS] = ModelSurfs::ReleaseModelSurf;
|
||||
|
||||
// Install device recovery handlers
|
||||
Renderer::OnDeviceRecoveryBegin(ModelSurfs::BeginRecover);
|
||||
Renderer::OnDeviceRecoveryEnd(ModelSurfs::EndRecover);
|
||||
|
||||
// Install hooks
|
||||
Utils::Hook(0x47A6BD, ModelSurfs::XModelSurfsFixup, HOOK_CALL).Install()->Quick();
|
||||
Utils::Hook(0x558F12, ModelSurfs::GetIndexBaseStub, HOOK_CALL).Install()->Quick();
|
||||
Utils::Hook(0x5BC050, ModelSurfs::GetIndexBufferStub, HOOK_JUMP).Install()->Quick();
|
||||
Utils::Hook(0x558E70, ModelSurfs::GetIndexBufferStub2, HOOK_CALL).Install()->Quick();
|
||||
Utils::Hook(0x5BC050, ModelSurfs::GetVertexBufferStub, HOOK_JUMP).Install()->Quick();
|
||||
}
|
||||
|
||||
ModelSurfs::~ModelSurfs()
|
||||
{
|
||||
assert(ModelSurfs::BufferMap.empty());
|
||||
assert(ModelSurfs::AllocMap.empty());
|
||||
}
|
||||
}
|
35
src/Components/Modules/ModelSurfs.hpp
Normal file
35
src/Components/Modules/ModelSurfs.hpp
Normal file
@ -0,0 +1,35 @@
|
||||
namespace Components
|
||||
{
|
||||
class ModelSurfs : public Component
|
||||
{
|
||||
public:
|
||||
ModelSurfs();
|
||||
~ModelSurfs();
|
||||
|
||||
#if defined(DEBUG) || defined(FORCE_UNIT_TESTS)
|
||||
const char* GetName() { return "ModelSurfs"; };
|
||||
#endif
|
||||
|
||||
private:
|
||||
static std::map<void*, IUnknown*> BufferMap;
|
||||
static std::map<void*, Game::CModelAllocData*> AllocMap;
|
||||
|
||||
static void ReleaseModelSurf(Game::XAssetHeader header);
|
||||
|
||||
static void BeginRecover();
|
||||
static void EndRecover();
|
||||
|
||||
static IUnknown* GetBuffer(void* buffer);
|
||||
static void SetBuffer(char streamHandle, void* buffer, IUnknown** bufferOut, int* offsetOut);
|
||||
|
||||
static void CreateBuffers(Game::XModelSurfs* surfs);
|
||||
static Game::XModelSurfs* LoadXModelSurfaces(std::string name);
|
||||
static bool LoadSurfaces(Game::XModel* model);
|
||||
static void XModelSurfsFixup(Game::XModel* model);
|
||||
|
||||
static void GetIndexBaseStub();
|
||||
static void GetIndexBufferStub();
|
||||
static void GetIndexBufferStub2();
|
||||
static void GetVertexBufferStub();
|
||||
};
|
||||
}
|
@ -6,7 +6,7 @@ namespace Components
|
||||
MusicalTalent();
|
||||
~MusicalTalent();
|
||||
|
||||
#ifdef DEBUG
|
||||
#if defined(DEBUG) || defined(FORCE_UNIT_TESTS)
|
||||
const char* GetName() { return "MusicalTalent"; };
|
||||
#endif
|
||||
|
||||
|
@ -56,7 +56,7 @@ namespace Components
|
||||
Network();
|
||||
~Network();
|
||||
|
||||
#ifdef DEBUG
|
||||
#if defined(DEBUG) || defined(FORCE_UNIT_TESTS)
|
||||
const char* GetName() { return "Network"; };
|
||||
#endif
|
||||
|
||||
|
@ -6,7 +6,7 @@ namespace Components
|
||||
News();
|
||||
~News();
|
||||
|
||||
#ifdef DEBUG
|
||||
#if defined(DEBUG) || defined(FORCE_UNIT_TESTS)
|
||||
const char* GetName() { return "News"; };
|
||||
#endif
|
||||
|
||||
|
@ -2,6 +2,8 @@
|
||||
|
||||
namespace Components
|
||||
{
|
||||
std::mutex Node::NodeMutex;
|
||||
std::mutex Node::SessionMutex;
|
||||
Utils::Cryptography::ECC::Key Node::SignatureKey;
|
||||
std::vector<Node::NodeEntry> Node::Nodes;
|
||||
std::vector<Node::ClientSession> Node::Sessions;
|
||||
@ -45,6 +47,7 @@ namespace Components
|
||||
// However, defining another proto message due to this would be redundant.
|
||||
//list.set_is_dedi(Dedicated::IsDedicated());
|
||||
|
||||
std::lock_guard<std::mutex> _(Node::NodeMutex);
|
||||
for (auto node : Node::Nodes)
|
||||
{
|
||||
if (node.state == Node::STATE_VALID && node.registered)
|
||||
@ -88,6 +91,7 @@ namespace Components
|
||||
unsigned int Node::GetValidNodeCount()
|
||||
{
|
||||
unsigned int count = 0;
|
||||
std::lock_guard<std::mutex> _(Node::NodeMutex);
|
||||
|
||||
for (auto node : Node::Nodes)
|
||||
{
|
||||
@ -108,6 +112,7 @@ namespace Components
|
||||
if (!address.IsValid() || address.IsLocal() || address.IsSelf()) return;
|
||||
#endif
|
||||
|
||||
std::lock_guard<std::mutex> _(Node::NodeMutex);
|
||||
Node::NodeEntry* existingEntry = Node::FindNode(address);
|
||||
if (existingEntry)
|
||||
{
|
||||
@ -142,7 +147,9 @@ namespace Components
|
||||
list.set_protocol(PROTOCOL);
|
||||
list.set_version(NODE_VERSION);
|
||||
|
||||
for (auto node : Node::Nodes)
|
||||
std::lock_guard<std::mutex> _(Node::NodeMutex);
|
||||
|
||||
for (auto& node : Node::Nodes)
|
||||
{
|
||||
if (node.state == Node::STATE_VALID && node.registered)
|
||||
{
|
||||
@ -163,6 +170,7 @@ namespace Components
|
||||
|
||||
void Node::DeleteInvalidSessions()
|
||||
{
|
||||
std::lock_guard<std::mutex> _(Node::SessionMutex);
|
||||
for (auto i = Node::Sessions.begin(); i != Node::Sessions.end();)
|
||||
{
|
||||
if (i->lastTime <= 0 || (Game::Sys_Milliseconds() - i->lastTime) > SESSION_TIMEOUT)
|
||||
@ -178,6 +186,7 @@ namespace Components
|
||||
|
||||
void Node::DeleteInvalidNodes()
|
||||
{
|
||||
std::lock_guard<std::mutex> _(Node::NodeMutex);
|
||||
std::vector<Node::NodeEntry> cleanNodes;
|
||||
|
||||
for (auto node : Node::Nodes)
|
||||
@ -204,6 +213,7 @@ namespace Components
|
||||
|
||||
void Node::SyncNodeList()
|
||||
{
|
||||
std::lock_guard<std::mutex> _(Node::NodeMutex);
|
||||
for (auto& node : Node::Nodes)
|
||||
{
|
||||
if (node.state == Node::STATE_VALID && node.registered)
|
||||
@ -254,62 +264,65 @@ namespace Components
|
||||
int registerCount = 0;
|
||||
int listQueryCount = 0;
|
||||
|
||||
for (auto &node : Node::Nodes)
|
||||
{
|
||||
// TODO: Decide how to handle nodes that were already registered, but timed out re-registering.
|
||||
if (node.state == STATE_NEGOTIATING && (Game::Sys_Milliseconds() - node.lastTime) > (NODE_QUERY_TIMEOUT))
|
||||
std::lock_guard<std::mutex> _(Node::NodeMutex);
|
||||
for (auto &node : Node::Nodes)
|
||||
{
|
||||
node.registered = false; // Definitely unregister here!
|
||||
node.state = Node::STATE_INVALID;
|
||||
node.lastHeard = Game::Sys_Milliseconds();
|
||||
node.lastTime = Game::Sys_Milliseconds();
|
||||
// TODO: Decide how to handle nodes that were already registered, but timed out re-registering.
|
||||
if (node.state == STATE_NEGOTIATING && (Game::Sys_Milliseconds() - node.lastTime) > (NODE_QUERY_TIMEOUT))
|
||||
{
|
||||
node.registered = false; // Definitely unregister here!
|
||||
node.state = Node::STATE_INVALID;
|
||||
node.lastHeard = Game::Sys_Milliseconds();
|
||||
node.lastTime = Game::Sys_Milliseconds();
|
||||
|
||||
#if defined(DEBUG) && !defined(DISABLE_NODE_LOG)
|
||||
Logger::Print("Node negotiation timed out. Invalidating %s\n", node.address.GetCString());
|
||||
Logger::Print("Node negotiation timed out. Invalidating %s\n", node.address.GetCString());
|
||||
#endif
|
||||
}
|
||||
|
||||
if (registerCount < NODE_FRAME_QUERY_LIMIT)
|
||||
{
|
||||
// Register when unregistered and in UNKNOWN state (I doubt it's possible to be unregistered and in VALID state)
|
||||
if (!node.registered && (node.state != Node::STATE_NEGOTIATING && node.state != Node::STATE_INVALID))
|
||||
{
|
||||
++registerCount;
|
||||
node.state = Node::STATE_NEGOTIATING;
|
||||
Node::PerformRegistration(node.address);
|
||||
}
|
||||
// Requery invalid nodes within the NODE_QUERY_INTERVAL
|
||||
// This is required, as a node might crash, which causes it to be invalid.
|
||||
// If it's restarted though, we wouldn't query it again.
|
||||
|
||||
// But wouldn't it send a registration request to us?
|
||||
// Not sure if the code below is necessary...
|
||||
// Well, it might be possible that this node doesn't know use anymore. Anyways, just keep that code here...
|
||||
|
||||
// Nvm, this is required for clients, as nodes don't send registration requests to clients.
|
||||
else if (node.state == STATE_INVALID && (Game::Sys_Milliseconds() - node.lastTime) > NODE_QUERY_INTERVAL)
|
||||
if (registerCount < NODE_FRAME_QUERY_LIMIT)
|
||||
{
|
||||
++registerCount;
|
||||
Node::PerformRegistration(node.address);
|
||||
}
|
||||
}
|
||||
|
||||
if (listQueryCount < NODE_FRAME_QUERY_LIMIT)
|
||||
{
|
||||
if (node.registered && node.state == Node::STATE_VALID && (!node.lastListQuery || (Game::Sys_Milliseconds() - node.lastListQuery) > NODE_QUERY_INTERVAL))
|
||||
{
|
||||
++listQueryCount;
|
||||
node.state = Node::STATE_NEGOTIATING;
|
||||
node.lastTime = Game::Sys_Milliseconds();
|
||||
node.lastListQuery = Game::Sys_Milliseconds();
|
||||
|
||||
if (Dedicated::IsEnabled())
|
||||
// Register when unregistered and in UNKNOWN state (I doubt it's possible to be unregistered and in VALID state)
|
||||
if (!node.registered && (node.state != Node::STATE_NEGOTIATING && node.state != Node::STATE_INVALID))
|
||||
{
|
||||
Network::SendCommand(node.address, "nodeListRequest");
|
||||
++registerCount;
|
||||
node.state = Node::STATE_NEGOTIATING;
|
||||
Node::PerformRegistration(node.address);
|
||||
}
|
||||
else
|
||||
// Requery invalid nodes within the NODE_QUERY_INTERVAL
|
||||
// This is required, as a node might crash, which causes it to be invalid.
|
||||
// If it's restarted though, we wouldn't query it again.
|
||||
|
||||
// But wouldn't it send a registration request to us?
|
||||
// Not sure if the code below is necessary...
|
||||
// Well, it might be possible that this node doesn't know use anymore. Anyways, just keep that code here...
|
||||
|
||||
// Nvm, this is required for clients, as nodes don't send registration requests to clients.
|
||||
else if (node.state == STATE_INVALID && (Game::Sys_Milliseconds() - node.lastTime) > NODE_QUERY_INTERVAL)
|
||||
{
|
||||
Network::SendCommand(node.address, "sessionRequest");
|
||||
++registerCount;
|
||||
Node::PerformRegistration(node.address);
|
||||
}
|
||||
}
|
||||
|
||||
if (listQueryCount < NODE_FRAME_QUERY_LIMIT)
|
||||
{
|
||||
if (node.registered && node.state == Node::STATE_VALID && (!node.lastListQuery || (Game::Sys_Milliseconds() - node.lastListQuery) > NODE_QUERY_INTERVAL))
|
||||
{
|
||||
++listQueryCount;
|
||||
node.state = Node::STATE_NEGOTIATING;
|
||||
node.lastTime = Game::Sys_Milliseconds();
|
||||
node.lastListQuery = Game::Sys_Milliseconds();
|
||||
|
||||
if (Dedicated::IsEnabled())
|
||||
{
|
||||
Network::SendCommand(node.address, "nodeListRequest");
|
||||
}
|
||||
else
|
||||
{
|
||||
Network::SendCommand(node.address, "sessionRequest");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -374,6 +387,7 @@ namespace Components
|
||||
packet.set_challenge(challenge);
|
||||
packet.set_signature(Utils::Cryptography::ECC::SignMessage(Node::SignatureKey, challenge));
|
||||
|
||||
std::lock_guard<std::mutex> _(Node::NodeMutex);
|
||||
for (auto node : Node::Nodes)
|
||||
{
|
||||
Network::SendCommand(node.address, "nodeDeregister", packet.SerializeAsString());
|
||||
@ -386,16 +400,16 @@ namespace Components
|
||||
{
|
||||
if (Dvar::Var("sv_lanOnly").Get<bool>()) return;
|
||||
|
||||
Node::NodeEntry* entry = Node::FindNode(address);
|
||||
|
||||
// Create a new entry, if we don't already know it
|
||||
if (!entry)
|
||||
if (!Node::FindNode(address))
|
||||
{
|
||||
Node::AddNode(address);
|
||||
entry = Node::FindNode(address);
|
||||
if (!entry) return;
|
||||
if (!Node::FindNode(address)) return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> _(Node::NodeMutex);
|
||||
Node::NodeEntry* entry = Node::FindNode(address);
|
||||
|
||||
#if defined(DEBUG) && !defined(DISABLE_NODE_LOG)
|
||||
Logger::Print("Received registration request from %s\n", address.GetCString());
|
||||
#endif
|
||||
@ -434,6 +448,7 @@ namespace Components
|
||||
{
|
||||
if (Dvar::Var("sv_lanOnly").Get<bool>()) return;
|
||||
|
||||
std::lock_guard<std::mutex> _(Node::NodeMutex);
|
||||
Node::NodeEntry* entry = Node::FindNode(address);
|
||||
if (!entry || entry->state != Node::STATE_NEGOTIATING) return;
|
||||
|
||||
@ -485,6 +500,7 @@ namespace Components
|
||||
if (Dvar::Var("sv_lanOnly").Get<bool>()) return;
|
||||
|
||||
// Ignore requests from nodes we don't know
|
||||
std::lock_guard<std::mutex> _(Node::NodeMutex);
|
||||
Node::NodeEntry* entry = Node::FindNode(address);
|
||||
if (!entry || entry->state != Node::STATE_NEGOTIATING) return;
|
||||
|
||||
@ -527,21 +543,26 @@ namespace Components
|
||||
|
||||
// Check if this is a registered node
|
||||
bool allowed = false;
|
||||
Node::NodeEntry* entry = Node::FindNode(address);
|
||||
if (entry && entry->registered)
|
||||
{
|
||||
entry->lastTime = Game::Sys_Milliseconds();
|
||||
allowed = true;
|
||||
}
|
||||
|
||||
// Check if there is any open session
|
||||
if (!allowed)
|
||||
{
|
||||
Node::ClientSession* session = Node::FindSession(address);
|
||||
if (session)
|
||||
std::lock_guard<std::mutex> _(Node::NodeMutex);
|
||||
Node::NodeEntry* entry = Node::FindNode(address);
|
||||
if (entry && entry->registered)
|
||||
{
|
||||
session->lastTime = Game::Sys_Milliseconds();
|
||||
allowed = session->valid;
|
||||
entry->lastTime = Game::Sys_Milliseconds();
|
||||
allowed = true;
|
||||
}
|
||||
|
||||
// Check if there is any open session
|
||||
if (!allowed)
|
||||
{
|
||||
std::lock_guard<std::mutex> __(Node::SessionMutex);
|
||||
Node::ClientSession* session = Node::FindSession(address);
|
||||
if (session)
|
||||
{
|
||||
session->lastTime = Game::Sys_Milliseconds();
|
||||
allowed = session->valid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -563,6 +584,7 @@ namespace Components
|
||||
{
|
||||
if (Dvar::Var("sv_lanOnly").Get<bool>()) return;
|
||||
|
||||
std::lock_guard<std::mutex> _(Node::NodeMutex);
|
||||
Node::NodeEntry* entry = Node::FindNode(address);
|
||||
if (!entry || !entry->registered) return;
|
||||
|
||||
@ -598,6 +620,7 @@ namespace Components
|
||||
if (Dvar::Var("sv_lanOnly").Get<bool>()) return;
|
||||
|
||||
// Search an active session, if we haven't found one, register a template
|
||||
std::lock_guard<std::mutex> _(Node::SessionMutex);
|
||||
if (!Node::FindSession(address))
|
||||
{
|
||||
Node::ClientSession templateSession;
|
||||
@ -626,6 +649,7 @@ namespace Components
|
||||
if (Dvar::Var("sv_lanOnly").Get<bool>()) return;
|
||||
|
||||
// Return if we don't have a session for this address
|
||||
std::lock_guard<std::mutex> _(Node::SessionMutex);
|
||||
Node::ClientSession* session = Node::FindSession(address);
|
||||
if (!session || session->valid) return;
|
||||
|
||||
@ -650,6 +674,7 @@ namespace Components
|
||||
{
|
||||
Network::Handle("sessionInitialize", [] (Network::Address address, std::string data)
|
||||
{
|
||||
std::lock_guard<std::mutex> _(Node::NodeMutex);
|
||||
Node::NodeEntry* entry = Node::FindNode(address);
|
||||
if (!entry) return;
|
||||
|
||||
@ -663,12 +688,15 @@ namespace Components
|
||||
|
||||
Network::Handle("sessionAcknowledge", [] (Network::Address address, std::string data)
|
||||
{
|
||||
Node::NodeEntry* entry = Node::FindNode(address);
|
||||
if (!entry) return;
|
||||
{
|
||||
std::lock_guard<std::mutex> _(Node::NodeMutex);
|
||||
Node::NodeEntry* entry = Node::FindNode(address);
|
||||
if (!entry) return;
|
||||
|
||||
entry->state = Node::STATE_VALID;
|
||||
entry->registered = true;
|
||||
entry->lastTime = Game::Sys_Milliseconds();
|
||||
entry->state = Node::STATE_VALID;
|
||||
entry->registered = true;
|
||||
entry->lastTime = Game::Sys_Milliseconds();
|
||||
}
|
||||
|
||||
#if defined(DEBUG) && !defined(DISABLE_NODE_LOG)
|
||||
Logger::Print("Session acknowledged by %s, synchronizing node list...\n", address.GetCString());
|
||||
@ -690,6 +718,7 @@ namespace Components
|
||||
return;
|
||||
}
|
||||
|
||||
Node::NodeMutex.lock();
|
||||
Node::NodeEntry* entry = Node::FindNode(address);
|
||||
if (entry)
|
||||
{
|
||||
@ -705,11 +734,21 @@ namespace Components
|
||||
entry->state = Node::STATE_VALID;
|
||||
entry->lastTime = Game::Sys_Milliseconds();
|
||||
|
||||
// Block old versions
|
||||
// if (entry->version < NODE_VERSION)
|
||||
// {
|
||||
// entry->state = Node::STATE_INVALID;
|
||||
// Node::NodeMutex.unlock();
|
||||
// return;
|
||||
// }
|
||||
|
||||
if (!Dedicated::IsEnabled() && entry->isDedi && ServerList::IsOnlineList() && entry->protocol == PROTOCOL)
|
||||
{
|
||||
ServerList::InsertRequest(entry->address, true);
|
||||
}
|
||||
|
||||
Node::NodeMutex.unlock();
|
||||
|
||||
for (int i = 0; i < list.address_size(); ++i)
|
||||
{
|
||||
Network::Address _addr(list.address(i));
|
||||
@ -730,11 +769,17 @@ namespace Components
|
||||
Node::AddNode(_addr);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Node::NodeMutex.unlock();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Node::NodeMutex.unlock();
|
||||
//Node::AddNode(address);
|
||||
|
||||
std::lock_guard<std::mutex> _(Node::SessionMutex);
|
||||
Node::ClientSession* session = Node::FindSession(address);
|
||||
if (session && session->valid)
|
||||
{
|
||||
@ -754,6 +799,7 @@ namespace Components
|
||||
{
|
||||
if (Dedicated::IsEnabled())
|
||||
{
|
||||
Node::NodeMutex.lock();
|
||||
Node::NodeEntry* entry = Node::FindNode(address);
|
||||
if (entry)
|
||||
{
|
||||
@ -761,9 +807,12 @@ namespace Components
|
||||
entry->lastTime = Game::Sys_Milliseconds();
|
||||
entry->registered = false;
|
||||
entry->state = Node::STATE_UNKNOWN;
|
||||
Node::NodeMutex.unlock();
|
||||
}
|
||||
else
|
||||
{
|
||||
Node::NodeMutex.unlock();
|
||||
|
||||
// Add as new entry to perform registration
|
||||
Node::AddNode(address);
|
||||
}
|
||||
@ -774,6 +823,7 @@ namespace Components
|
||||
{
|
||||
Logger::Print("Nodes: %d (%d)\n", Node::Nodes.size(), Node::GetValidNodeCount());
|
||||
|
||||
std::lock_guard<std::mutex> _(Node::NodeMutex);
|
||||
for (auto node : Node::Nodes)
|
||||
{
|
||||
Logger::Print("%s\t(%s)\n", node.address.GetCString(), Node::GetStateName(node.state));
|
||||
@ -787,6 +837,7 @@ namespace Components
|
||||
Network::Address address(params[1]);
|
||||
Node::AddNode(address);
|
||||
|
||||
std::lock_guard<std::mutex> _(Node::NodeMutex);
|
||||
Node::NodeEntry* entry = Node::FindNode(address);
|
||||
if (entry)
|
||||
{
|
||||
@ -799,6 +850,7 @@ namespace Components
|
||||
{
|
||||
Logger::Print("Re-Synchronizing nodes...\n");
|
||||
|
||||
std::lock_guard<std::mutex> _(Node::NodeMutex);
|
||||
for (auto& node : Node::Nodes)
|
||||
{
|
||||
node.state = Node::STATE_UNKNOWN;
|
||||
@ -817,6 +869,8 @@ namespace Components
|
||||
Node::SignatureKey.Free();
|
||||
|
||||
Node::StoreNodes(true);
|
||||
std::lock_guard<std::mutex> _(Node::NodeMutex);
|
||||
std::lock_guard<std::mutex> __(Node::SessionMutex);
|
||||
Node::Nodes.clear();
|
||||
Node::Sessions.clear();
|
||||
}
|
||||
@ -831,7 +885,7 @@ namespace Components
|
||||
printf("ECDSA key seems invalid!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
printf("Success\n");
|
||||
printf("Testing 10 valid signatures...");
|
||||
|
||||
@ -885,45 +939,6 @@ namespace Components
|
||||
}
|
||||
|
||||
printf("Success\n");
|
||||
|
||||
uint32_t randIntCount = 4'000'000;
|
||||
printf("Generating %d random integers...", randIntCount);
|
||||
|
||||
auto startTime = std::chrono::high_resolution_clock::now();
|
||||
|
||||
for (uint32_t i = 0; i < randIntCount; ++i)
|
||||
{
|
||||
Utils::Cryptography::Rand::GenerateInt();
|
||||
}
|
||||
|
||||
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - startTime).count();
|
||||
Logger::Print("took %llims\n", duration);
|
||||
|
||||
printf("Testing ZLib compression...");
|
||||
|
||||
std::string test = fmt::sprintf("%c", Utils::Cryptography::Rand::GenerateInt());
|
||||
|
||||
for (int i = 0; i < 21; ++i)
|
||||
{
|
||||
std::string compressed = Utils::Compression::ZLib::Compress(test);
|
||||
std::string decompressed = Utils::Compression::ZLib::Decompress(compressed);
|
||||
|
||||
if (test != decompressed)
|
||||
{
|
||||
printf("Error\n");
|
||||
printf("Compressing %d bytes and decompressing failed!\n", test.size());
|
||||
return false;
|
||||
}
|
||||
|
||||
auto size = test.size();
|
||||
for (unsigned int j = 0; j < size; ++j)
|
||||
{
|
||||
test.append(fmt::sprintf("%c", Utils::Cryptography::Rand::GenerateInt()));
|
||||
}
|
||||
}
|
||||
|
||||
printf("Success\n");
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,7 @@
|
||||
#define NODE_STORE_INTERVAL 1000 * 60* 1 // Store nodes every minute
|
||||
#define SESSION_TIMEOUT 1000 * 10 // 10 seconds session timeout
|
||||
|
||||
#define NODE_VERSION 1
|
||||
#define NODE_VERSION 2
|
||||
|
||||
namespace Components
|
||||
{
|
||||
@ -17,7 +17,7 @@ namespace Components
|
||||
Node();
|
||||
~Node();
|
||||
|
||||
#ifdef DEBUG
|
||||
#if defined(DEBUG) || defined(FORCE_UNIT_TESTS)
|
||||
const char* GetName() { return "Node"; };
|
||||
#endif
|
||||
|
||||
@ -69,6 +69,8 @@ namespace Components
|
||||
|
||||
static Utils::Cryptography::ECC::Key SignatureKey;
|
||||
|
||||
static std::mutex NodeMutex;
|
||||
static std::mutex SessionMutex;
|
||||
static std::vector<NodeEntry> Nodes;
|
||||
static std::vector<ClientSession> Sessions;
|
||||
|
||||
|
@ -6,7 +6,7 @@ namespace Components
|
||||
Party();
|
||||
~Party();
|
||||
|
||||
#ifdef DEBUG
|
||||
#if defined(DEBUG) || defined(FORCE_UNIT_TESTS)
|
||||
const char* GetName() { return "Party"; };
|
||||
#endif
|
||||
|
||||
|
@ -6,7 +6,7 @@ namespace Components
|
||||
PlayerName();
|
||||
~PlayerName();
|
||||
|
||||
#ifdef DEBUG
|
||||
#if defined(DEBUG) || defined(FORCE_UNIT_TESTS)
|
||||
const char* GetName() { return "PlayerName"; };
|
||||
#endif
|
||||
|
||||
|
@ -8,7 +8,7 @@ namespace Components
|
||||
Playlist();
|
||||
~Playlist();
|
||||
|
||||
#ifdef DEBUG
|
||||
#if defined(DEBUG) || defined(FORCE_UNIT_TESTS)
|
||||
const char* GetName() { return "Playlist"; };
|
||||
#endif
|
||||
|
||||
|
@ -424,4 +424,46 @@ namespace Components
|
||||
{
|
||||
QuickPatch::ShutdownSignal.clear();
|
||||
}
|
||||
|
||||
bool QuickPatch::UnitTest()
|
||||
{
|
||||
uint32_t randIntCount = 4'000'000;
|
||||
printf("Generating %d random integers...", randIntCount);
|
||||
|
||||
auto startTime = std::chrono::high_resolution_clock::now();
|
||||
|
||||
for (uint32_t i = 0; i < randIntCount; ++i)
|
||||
{
|
||||
Utils::Cryptography::Rand::GenerateInt();
|
||||
}
|
||||
|
||||
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - startTime).count();
|
||||
Logger::Print("took %llims\n", duration);
|
||||
|
||||
printf("Testing ZLib compression...");
|
||||
|
||||
std::string test = fmt::sprintf("%c", Utils::Cryptography::Rand::GenerateInt());
|
||||
|
||||
for (int i = 0; i < 21; ++i)
|
||||
{
|
||||
std::string compressed = Utils::Compression::ZLib::Compress(test);
|
||||
std::string decompressed = Utils::Compression::ZLib::Decompress(compressed);
|
||||
|
||||
if (test != decompressed)
|
||||
{
|
||||
printf("Error\n");
|
||||
printf("Compressing %d bytes and decompressing failed!\n", test.size());
|
||||
return false;
|
||||
}
|
||||
|
||||
auto size = test.size();
|
||||
for (unsigned int j = 0; j < size; ++j)
|
||||
{
|
||||
test.append(fmt::sprintf("%c", Utils::Cryptography::Rand::GenerateInt()));
|
||||
}
|
||||
}
|
||||
|
||||
printf("Success\n");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -8,10 +8,12 @@ namespace Components
|
||||
QuickPatch();
|
||||
~QuickPatch();
|
||||
|
||||
#ifdef DEBUG
|
||||
#if defined(DEBUG) || defined(FORCE_UNIT_TESTS)
|
||||
const char* GetName() { return "QuickPatch"; };
|
||||
#endif
|
||||
|
||||
bool UnitTest();
|
||||
|
||||
static void UnlockStats();
|
||||
static void OnShutdown(Callback* callback);
|
||||
|
||||
|
@ -6,7 +6,7 @@ namespace Components
|
||||
RCon();
|
||||
~RCon();
|
||||
|
||||
#ifdef DEBUG
|
||||
#if defined(DEBUG) || defined(FORCE_UNIT_TESTS)
|
||||
const char* GetName() { return "RCon"; };
|
||||
#endif
|
||||
|
||||
|
@ -5,7 +5,7 @@ namespace Components
|
||||
public:
|
||||
RawFiles();
|
||||
|
||||
#ifdef DEBUG
|
||||
#if defined(DEBUG) || defined(FORCE_UNIT_TESTS)
|
||||
const char* GetName() { return "RawFiles"; };
|
||||
#endif
|
||||
|
||||
|
@ -7,6 +7,9 @@ namespace Components
|
||||
wink::signal<wink::slot<Renderer::Callback>> Renderer::FrameOnceSignal;
|
||||
wink::signal<wink::slot<Renderer::BackendCallback>> Renderer::BackendFrameSignal;
|
||||
|
||||
wink::signal<wink::slot<Renderer::Callback>> Renderer::EndRecoverDeviceSignal;
|
||||
wink::signal<wink::slot<Renderer::Callback>> Renderer::BeginRecoverDeviceSignal;
|
||||
|
||||
__declspec(naked) void Renderer::FrameStub()
|
||||
{
|
||||
__asm
|
||||
@ -62,6 +65,16 @@ namespace Components
|
||||
Renderer::BackendFrameSignal.connect(callback);
|
||||
}
|
||||
|
||||
void Renderer::OnDeviceRecoveryEnd(Renderer::Callback* callback)
|
||||
{
|
||||
Renderer::EndRecoverDeviceSignal.connect(callback);
|
||||
}
|
||||
|
||||
void Renderer::OnDeviceRecoveryBegin(Renderer::Callback* callback)
|
||||
{
|
||||
Renderer::BeginRecoverDeviceSignal.connect(callback);
|
||||
}
|
||||
|
||||
int Renderer::Width()
|
||||
{
|
||||
return Utils::Hook::Get<int>(0x66E1C68);
|
||||
@ -106,6 +119,18 @@ namespace Components
|
||||
Renderer::DrawFrameHook.Initialize(0x5ACB99, Renderer::FrameStub, HOOK_CALL)->Install();
|
||||
|
||||
Utils::Hook(0x536A80, Renderer::BackendFrameStub, HOOK_JUMP).Install()->Quick();
|
||||
|
||||
Utils::Hook(0x508298, [] ()
|
||||
{
|
||||
Game::DB_BeginRecoverLostDevice();
|
||||
Renderer::BeginRecoverDeviceSignal();
|
||||
}, HOOK_CALL).Install()->Quick();
|
||||
|
||||
Utils::Hook(0x508355, [] ()
|
||||
{
|
||||
Renderer::EndRecoverDeviceSignal();
|
||||
Game::DB_EndRecoverLostDevice();
|
||||
}, HOOK_CALL).Install()->Quick();
|
||||
}
|
||||
|
||||
Renderer::~Renderer()
|
||||
@ -114,5 +139,8 @@ namespace Components
|
||||
Renderer::BackendFrameSignal.clear();
|
||||
Renderer::FrameOnceSignal.clear();
|
||||
Renderer::FrameSignal.clear();
|
||||
|
||||
Renderer::EndRecoverDeviceSignal.clear();
|
||||
Renderer::BeginRecoverDeviceSignal.clear();
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ namespace Components
|
||||
Renderer();
|
||||
~Renderer();
|
||||
|
||||
#ifdef DEBUG
|
||||
#if defined(DEBUG) || defined(FORCE_UNIT_TESTS)
|
||||
const char* GetName() { return "Renderer"; };
|
||||
#endif
|
||||
|
||||
@ -20,6 +20,9 @@ namespace Components
|
||||
static void OnFrame(Callback* callback);
|
||||
static void OnBackendFrame(BackendCallback* callback);
|
||||
|
||||
static void OnDeviceRecoveryEnd(Callback* callback);
|
||||
static void OnDeviceRecoveryBegin(Callback* callback);
|
||||
|
||||
private:
|
||||
static void FrameStub();
|
||||
static void FrameHandler();
|
||||
@ -29,6 +32,10 @@ namespace Components
|
||||
|
||||
static wink::signal<wink::slot<Callback>> FrameSignal;
|
||||
static wink::signal<wink::slot<Callback>> FrameOnceSignal;
|
||||
|
||||
static wink::signal<wink::slot<Callback>> EndRecoverDeviceSignal;
|
||||
static wink::signal<wink::slot<Callback>> BeginRecoverDeviceSignal;
|
||||
|
||||
static wink::signal<wink::slot<BackendCallback>> BackendFrameSignal;
|
||||
static Utils::Hook DrawFrameHook;
|
||||
};
|
||||
|
@ -6,7 +6,7 @@ namespace Components
|
||||
Script();
|
||||
~Script();
|
||||
|
||||
#ifdef DEBUG
|
||||
#if defined(DEBUG) || defined(FORCE_UNIT_TESTS)
|
||||
const char* GetName() { return "Script"; };
|
||||
#endif
|
||||
|
||||
|
@ -6,7 +6,7 @@ namespace Components
|
||||
ServerInfo();
|
||||
~ServerInfo();
|
||||
|
||||
#ifdef DEBUG
|
||||
#if defined(DEBUG) || defined(FORCE_UNIT_TESTS)
|
||||
const char* GetName() { return "ServerInfo"; };
|
||||
#endif
|
||||
|
||||
|
@ -27,7 +27,7 @@ namespace Components
|
||||
ServerList();
|
||||
~ServerList();
|
||||
|
||||
#ifdef DEBUG
|
||||
#if defined(DEBUG) || defined(FORCE_UNIT_TESTS)
|
||||
const char* GetName() { return "ServerList"; };
|
||||
#endif
|
||||
|
||||
|
@ -19,7 +19,7 @@ namespace Components
|
||||
|
||||
Console::FreeNativeConsole();
|
||||
|
||||
if (Dedicated::IsEnabled() || ZoneBuilder::IsEnabled()) return;
|
||||
if (Loader::PerformingUnitTests() || Dedicated::IsEnabled() || ZoneBuilder::IsEnabled()) return;
|
||||
|
||||
Singleton::FirstInstance = (CreateMutexA(NULL, FALSE, "iw4x_mutex") && GetLastError() != ERROR_ALREADY_EXISTS);
|
||||
|
||||
|
@ -5,7 +5,7 @@ namespace Components
|
||||
public:
|
||||
Singleton();
|
||||
|
||||
#ifdef DEBUG
|
||||
#if defined(DEBUG) || defined(FORCE_UNIT_TESTS)
|
||||
const char* GetName() { return "Singleton"; };
|
||||
#endif
|
||||
|
||||
|
@ -6,7 +6,7 @@ namespace Components
|
||||
StringTable();
|
||||
~StringTable();
|
||||
|
||||
#ifdef DEBUG
|
||||
#if defined(DEBUG) || defined(FORCE_UNIT_TESTS)
|
||||
const char* GetName() { return "StringTable"; };
|
||||
#endif
|
||||
|
||||
|
@ -24,7 +24,7 @@ namespace Components
|
||||
StructuredData();
|
||||
~StructuredData();
|
||||
|
||||
#ifdef DEBUG
|
||||
#if defined(DEBUG) || defined(FORCE_UNIT_TESTS)
|
||||
const char* GetName() { return "StructuredData"; };
|
||||
#endif
|
||||
|
||||
|
@ -5,7 +5,7 @@ namespace Components
|
||||
public:
|
||||
Theatre();
|
||||
|
||||
#ifdef DEBUG
|
||||
#if defined(DEBUG) || defined(FORCE_UNIT_TESTS)
|
||||
const char* GetName() { return "Theatre"; };
|
||||
#endif
|
||||
|
||||
|
@ -6,7 +6,7 @@ namespace Components
|
||||
Toast();
|
||||
~Toast();
|
||||
|
||||
#ifdef DEBUG
|
||||
#if defined(DEBUG) || defined(FORCE_UNIT_TESTS)
|
||||
const char* GetName() { return "Toast"; };
|
||||
#endif
|
||||
|
||||
|
@ -17,7 +17,7 @@ namespace Components
|
||||
UIFeeder();
|
||||
~UIFeeder();
|
||||
|
||||
#ifdef DEBUG
|
||||
#if defined(DEBUG) || defined(FORCE_UNIT_TESTS)
|
||||
const char* GetName() { return "UIFeeder"; };
|
||||
#endif
|
||||
|
||||
|
@ -6,7 +6,7 @@ namespace Components
|
||||
UIScript();
|
||||
~UIScript();
|
||||
|
||||
#ifdef DEBUG
|
||||
#if defined(DEBUG) || defined(FORCE_UNIT_TESTS)
|
||||
const char* GetName() { return "UIScript"; };
|
||||
#endif
|
||||
|
||||
|
@ -5,7 +5,7 @@ namespace Components
|
||||
public:
|
||||
Weapon();
|
||||
|
||||
#ifdef DEBUG
|
||||
#if defined(DEBUG) || defined(FORCE_UNIT_TESTS)
|
||||
const char* GetName() { return "Weapon"; };
|
||||
#endif
|
||||
|
||||
|
@ -5,7 +5,7 @@ namespace Components
|
||||
public:
|
||||
Window();
|
||||
|
||||
#ifdef DEBUG
|
||||
#if defined(DEBUG) || defined(FORCE_UNIT_TESTS)
|
||||
const char* GetName() { return "Window"; };
|
||||
#endif
|
||||
|
||||
|
@ -73,7 +73,7 @@ namespace Components
|
||||
|
||||
ZoneBuilder();
|
||||
|
||||
#ifdef DEBUG
|
||||
#if defined(DEBUG) || defined(FORCE_UNIT_TESTS)
|
||||
const char* GetName() { return "ZoneBuilder"; };
|
||||
#endif
|
||||
|
||||
|
21
src/Components/Modules/Zones.cpp
Normal file
21
src/Components/Modules/Zones.cpp
Normal file
@ -0,0 +1,21 @@
|
||||
#include "STDInclude.hpp"
|
||||
|
||||
namespace Components
|
||||
{
|
||||
int Zones::ZoneVersion;
|
||||
|
||||
void Zones::InstallPatches(int version)
|
||||
{
|
||||
Zones::ZoneVersion = version;
|
||||
}
|
||||
|
||||
Zones::Zones()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Zones::~Zones()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
18
src/Components/Modules/Zones.hpp
Normal file
18
src/Components/Modules/Zones.hpp
Normal file
@ -0,0 +1,18 @@
|
||||
namespace Components
|
||||
{
|
||||
class Zones : public Component
|
||||
{
|
||||
public:
|
||||
Zones();
|
||||
~Zones();
|
||||
|
||||
#if defined(DEBUG) || defined(FORCE_UNIT_TESTS)
|
||||
const char* GetName() { return "Zones"; };
|
||||
#endif
|
||||
|
||||
static void InstallPatches(int version);
|
||||
|
||||
private:
|
||||
static int ZoneVersion;
|
||||
};
|
||||
}
|
@ -22,6 +22,7 @@ namespace Game
|
||||
Cmd_AddCommand_t Cmd_AddCommand = (Cmd_AddCommand_t)0x470090;
|
||||
Cmd_AddServerCommand_t Cmd_AddServerCommand = (Cmd_AddServerCommand_t)0x4DCE00;
|
||||
Cmd_ExecuteSingleCommand_t Cmd_ExecuteSingleCommand = (Cmd_ExecuteSingleCommand_t)0x609540;
|
||||
Com_ClientPacketEvent_t Com_ClientPacketEvent = (Com_ClientPacketEvent_t)0x49F0B0;
|
||||
|
||||
Com_Error_t Com_Error = (Com_Error_t)0x4B22D0;
|
||||
Com_Printf_t Com_Printf = (Com_Printf_t)0x402500;
|
||||
@ -31,6 +32,8 @@ namespace Game
|
||||
Con_DrawMiniConsole_t Con_DrawMiniConsole = (Con_DrawMiniConsole_t)0x464F30;
|
||||
Con_DrawSolidConsole_t Con_DrawSolidConsole = (Con_DrawSolidConsole_t)0x5A5040;
|
||||
|
||||
DB_BeginRecoverLostDevice_t DB_BeginRecoverLostDevice = (DB_BeginRecoverLostDevice_t)0x4BFF90;
|
||||
DB_EndRecoverLostDevice_t DB_EndRecoverLostDevice = (DB_EndRecoverLostDevice_t)0x46B660;
|
||||
DB_EnumXAssets_t DB_EnumXAssets = (DB_EnumXAssets_t)0x4B76D0;
|
||||
DB_EnumXAssets_Internal_t DB_EnumXAssets_Internal = (DB_EnumXAssets_Internal_t)0x5BB0A0;
|
||||
DB_FindXAssetHeader_t DB_FindXAssetHeader = (DB_FindXAssetHeader_t)0x407930;
|
||||
@ -40,6 +43,8 @@ namespace Game
|
||||
DB_IsXAssetDefault_t DB_IsXAssetDefault = (DB_IsXAssetDefault_t)0x48E6A0;
|
||||
DB_LoadXAssets_t DB_LoadXAssets = (DB_LoadXAssets_t)0x4E5930;
|
||||
DB_ReadXFileUncompressed_t DB_ReadXFileUncompressed = (DB_ReadXFileUncompressed_t)0x4705E0;
|
||||
DB_ReleaseXAssetHandler_t* DB_ReleaseXAssetHandlers = (DB_ReleaseXAssetHandler_t*)0x799AB8;
|
||||
DB_XModelSurfsFixup_t DB_XModelSurfsFixup = (DB_XModelSurfsFixup_t)0x5BAC50;
|
||||
|
||||
Dvar_RegisterBool_t Dvar_RegisterBool = (Dvar_RegisterBool_t)0x4CE1A0;
|
||||
Dvar_RegisterFloat_t Dvar_RegisterFloat = (Dvar_RegisterFloat_t)0x648440;
|
||||
@ -88,6 +93,8 @@ namespace Game
|
||||
Image_LoadFromFileWithReader_t Image_LoadFromFileWithReader = (Image_LoadFromFileWithReader_t)0x53ABF0;
|
||||
Image_Release_t Image_Release = (Image_Release_t)0x51F010;
|
||||
|
||||
LargeLocalInit_t LargeLocalInit = (LargeLocalInit_t)0x4A62A0;
|
||||
|
||||
Menus_CloseAll_t Menus_CloseAll = (Menus_CloseAll_t)0x4BA5B0;
|
||||
Menus_OpenByName_t Menus_OpenByName = (Menus_OpenByName_t)0x4CCE60;
|
||||
Menus_FindByName_t Menus_FindByName = (Menus_FindByName_t)0x487240;
|
||||
@ -111,6 +118,7 @@ namespace Game
|
||||
|
||||
NET_AdrToString_t NET_AdrToString = (NET_AdrToString_t)0x469880;
|
||||
NET_CompareAdr_t NET_CompareAdr = (NET_CompareAdr_t)0x4D0AA0;
|
||||
NET_Init_t NET_Init = (NET_Init_t)0x491860;
|
||||
NET_IsLocalAddress_t NET_IsLocalAddress = (NET_IsLocalAddress_t)0x402BD0;
|
||||
NET_StringToAdr_t NET_StringToAdr = (NET_StringToAdr_t)0x409010;
|
||||
NET_OutOfBandPrint_t NET_OutOfBandPrint = (NET_OutOfBandPrint_t)0x4AEF00;
|
||||
@ -131,6 +139,7 @@ namespace Game
|
||||
PartyHost_GetMemberName_t PartyHost_GetMemberName = (PartyHost_GetMemberName_t)0x44BE90;
|
||||
|
||||
R_AddCmdDrawStretchPic_t R_AddCmdDrawStretchPic = (R_AddCmdDrawStretchPic_t)0x509770;
|
||||
R_AllocStaticIndexBuffer_t R_AllocStaticIndexBuffer = (R_AllocStaticIndexBuffer_t)0x51E7A0;
|
||||
R_Cinematic_StartPlayback_Now_t R_Cinematic_StartPlayback_Now = (R_Cinematic_StartPlayback_Now_t)0x51C5B0;
|
||||
R_RegisterFont_t R_RegisterFont = (R_RegisterFont_t)0x505670;
|
||||
R_AddCmdDrawText_t R_AddCmdDrawText = (R_AddCmdDrawText_t)0x509D80;
|
||||
@ -461,4 +470,38 @@ namespace Game
|
||||
pop esi
|
||||
}
|
||||
}
|
||||
|
||||
void Load_IndexBuffer(void* data, IDirect3DIndexBuffer9** storeHere, int count)
|
||||
{
|
||||
if (Components::Dvar::Var("r_loadForRenderer").Get<bool>())
|
||||
{
|
||||
void* buffer = R_AllocStaticIndexBuffer(storeHere, 2 * count);
|
||||
memcpy(buffer, data, 2 * count);
|
||||
|
||||
if (storeHere && *storeHere)
|
||||
{
|
||||
(*storeHere)->Unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Load_VertexBuffer(void* data, IDirect3DVertexBuffer9** where, int len)
|
||||
{
|
||||
__asm
|
||||
{
|
||||
push edi
|
||||
push ebx
|
||||
|
||||
mov eax, len
|
||||
mov edi, where
|
||||
push data
|
||||
|
||||
mov ebx, 5112C0h
|
||||
call ebx
|
||||
add esp, 4
|
||||
|
||||
pop ebx
|
||||
pop edi
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -45,6 +45,9 @@ namespace Game
|
||||
typedef void(__cdecl * Cmd_ExecuteSingleCommand_t)(int localClientNum, int controllerIndex, const char* cmd);
|
||||
extern Cmd_ExecuteSingleCommand_t Cmd_ExecuteSingleCommand;
|
||||
|
||||
typedef void(__cdecl * Com_ClientPacketEvent_t)();
|
||||
extern Com_ClientPacketEvent_t Com_ClientPacketEvent;
|
||||
|
||||
typedef void(__cdecl * Com_Error_t)(int type, char* message, ...);
|
||||
extern Com_Error_t Com_Error;
|
||||
|
||||
@ -63,6 +66,12 @@ namespace Game
|
||||
typedef void (__cdecl * Con_DrawSolidConsole_t)();
|
||||
extern Con_DrawSolidConsole_t Con_DrawSolidConsole;
|
||||
|
||||
typedef void(__cdecl * DB_BeginRecoverLostDevice_t)();
|
||||
extern DB_BeginRecoverLostDevice_t DB_BeginRecoverLostDevice;
|
||||
|
||||
typedef void(__cdecl * DB_EndRecoverLostDevice_t)();
|
||||
extern DB_EndRecoverLostDevice_t DB_EndRecoverLostDevice;
|
||||
|
||||
typedef void(__cdecl * DB_EnumXAssets_t)(XAssetType type, void(*)(XAssetHeader, void *), void* userdata, bool overrides);
|
||||
extern DB_EnumXAssets_t DB_EnumXAssets;
|
||||
|
||||
@ -90,6 +99,12 @@ namespace Game
|
||||
typedef void(__cdecl * DB_ReadXFileUncompressed_t)(void* buffer, int size);
|
||||
extern DB_ReadXFileUncompressed_t DB_ReadXFileUncompressed;
|
||||
|
||||
typedef void(__cdecl * DB_ReleaseXAssetHandler_t)(XAssetHeader header);
|
||||
extern DB_ReleaseXAssetHandler_t* DB_ReleaseXAssetHandlers;
|
||||
|
||||
typedef void(__cdecl * DB_XModelSurfsFixup_t)(XModel* model);
|
||||
extern DB_XModelSurfsFixup_t DB_XModelSurfsFixup;
|
||||
|
||||
typedef dvar_t* (__cdecl * Dvar_RegisterBool_t)(const char* name, bool default, int flags, const char* description);
|
||||
extern Dvar_RegisterBool_t Dvar_RegisterBool;
|
||||
|
||||
@ -206,6 +221,9 @@ namespace Game
|
||||
typedef void(__cdecl * Image_Release_t)(GfxImage* image);
|
||||
extern Image_Release_t Image_Release;
|
||||
|
||||
typedef void(__cdecl * LargeLocalInit_t)();
|
||||
extern LargeLocalInit_t LargeLocalInit;
|
||||
|
||||
typedef void(__cdecl * Menus_CloseAll_t)(UiContext *dc);
|
||||
extern Menus_CloseAll_t Menus_CloseAll;
|
||||
|
||||
@ -266,6 +284,9 @@ namespace Game
|
||||
typedef bool(__cdecl * NET_CompareAdr_t)(netadr_t a, netadr_t b);
|
||||
extern NET_CompareAdr_t NET_CompareAdr;
|
||||
|
||||
typedef void(__cdecl * NET_Init_t)();
|
||||
extern NET_Init_t NET_Init;
|
||||
|
||||
typedef bool(__cdecl * NET_IsLocalAddress_t)(netadr_t adr);
|
||||
extern NET_IsLocalAddress_t NET_IsLocalAddress;
|
||||
|
||||
@ -317,6 +338,9 @@ namespace Game
|
||||
typedef void(_cdecl * R_AddCmdDrawStretchPic_t)(float x, float y, float w, float h, float xScale, float yScale, float xay, float yay, const float *color, Game::Material* material);
|
||||
extern R_AddCmdDrawStretchPic_t R_AddCmdDrawStretchPic;
|
||||
|
||||
typedef void* (__cdecl * R_AllocStaticIndexBuffer_t)(IDirect3DIndexBuffer9** store, int length);
|
||||
extern R_AllocStaticIndexBuffer_t R_AllocStaticIndexBuffer;
|
||||
|
||||
typedef bool(__cdecl * R_Cinematic_StartPlayback_Now_t)();
|
||||
extern R_Cinematic_StartPlayback_Now_t R_Cinematic_StartPlayback_Now;
|
||||
|
||||
@ -518,4 +542,7 @@ namespace Game
|
||||
|
||||
void IN_KeyUp(kbutton_t* button);
|
||||
void IN_KeyDown(kbutton_t* button);
|
||||
|
||||
void Load_IndexBuffer(void* data, IDirect3DIndexBuffer9** storeHere, int count);
|
||||
void Load_VertexBuffer(void* data, IDirect3DVertexBuffer9** where, int len);
|
||||
}
|
||||
|
@ -818,6 +818,10 @@ namespace Game
|
||||
menuDef_t **menus;
|
||||
};
|
||||
|
||||
#define FS_SEEK_CUR 0
|
||||
#define FS_SEEK_END 1
|
||||
#define FS_SEEK_SET 2
|
||||
|
||||
enum FsListBehavior_e
|
||||
{
|
||||
FS_LIST_PURE_ONLY = 0x0,
|
||||
@ -1394,7 +1398,10 @@ namespace Game
|
||||
|
||||
struct XModelLodInfo
|
||||
{
|
||||
char pad[4]; // +0
|
||||
// I'm not sure if this is correct
|
||||
short someCount;
|
||||
short someTotalCount;
|
||||
|
||||
short numSurfs; // +4
|
||||
short pad2;// +6
|
||||
XModelSurfs* surfaces; // +8
|
||||
@ -1525,6 +1532,39 @@ namespace Game
|
||||
PhysCollmap* physCollmap;
|
||||
}; // total size 304
|
||||
|
||||
//static_assert(offsetof(XModel, lods) <= 70, "");
|
||||
|
||||
struct CModelAllocData
|
||||
{
|
||||
void* mainArray;
|
||||
void* vertexBuffer;
|
||||
void* indexBuffer;
|
||||
};
|
||||
|
||||
struct CModelSectionHeader
|
||||
{
|
||||
int size;
|
||||
int offset;
|
||||
int fixupStart;
|
||||
int fixupCount;
|
||||
void* buffer;
|
||||
};
|
||||
|
||||
enum CModelSection
|
||||
{
|
||||
SECTION_MAIN = 0,
|
||||
SECTION_INDEX = 1,
|
||||
SECTION_VERTEX = 2,
|
||||
SECTION_FIXUP = 3,
|
||||
};
|
||||
|
||||
struct CModelHeader
|
||||
{
|
||||
int version;
|
||||
unsigned int signature;
|
||||
CModelSectionHeader sectionHeader[4];
|
||||
};
|
||||
|
||||
struct DSkelPartBits
|
||||
{
|
||||
int anim[4];
|
||||
|
@ -2,13 +2,15 @@
|
||||
|
||||
// Rename sections
|
||||
#ifndef DEBUG
|
||||
#pragma comment(linker, "/merge:.text=.fucker")
|
||||
#pragma comment(linker, "/merge:.data=.bastard")
|
||||
#pragma comment(linker, "/merge:.rdata=.faggot")
|
||||
#pragma comment(linker, "/merge:.tls=.asshole")
|
||||
#pragma comment(linker, "/merge:.gfids=.idiot")
|
||||
#pragma comment(linker, "/merge:.text=.UPX0")
|
||||
#pragma comment(linker, "/merge:.data=.UPX1")
|
||||
#pragma comment(linker, "/merge:.rdata=.UPX2")
|
||||
#pragma comment(linker, "/merge:.tls=.UPX3")
|
||||
#pragma comment(linker, "/merge:.gfids=.UPX4")
|
||||
#endif
|
||||
|
||||
#pragma comment(linker,"\"/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
|
||||
|
||||
// Do necessary assertions here
|
||||
// Some compilers treat them differently which causes a size mismatch
|
||||
|
||||
|
@ -91,6 +91,7 @@
|
||||
#include "Utils\Memory.hpp"
|
||||
#include "Utils\String.hpp"
|
||||
#include "Utils\Hooking.hpp"
|
||||
#include "Utils\Library.hpp"
|
||||
#include "Utils\InfoString.hpp"
|
||||
#include "Utils\Compression.hpp"
|
||||
#include "Utils\Cryptography.hpp"
|
||||
|
@ -2,8 +2,8 @@
|
||||
|
||||
namespace Steam
|
||||
{
|
||||
HMODULE Proxy::Client = nullptr;
|
||||
HMODULE Proxy::Overlay = nullptr;
|
||||
::Utils::Library Proxy::Client;
|
||||
::Utils::Library Proxy::Overlay;
|
||||
|
||||
bool Proxy::Inititalize()
|
||||
{
|
||||
@ -12,20 +12,16 @@ namespace Steam
|
||||
|
||||
SetDllDirectoryA(Proxy::GetSteamDirectory().data());
|
||||
|
||||
Proxy::Client = LoadLibraryA(STEAMCLIENT_LIB);
|
||||
Proxy::Overlay = LoadLibraryA(GAMEOVERLAY_LIB);
|
||||
Proxy::Client = ::Utils::Library(STEAMCLIENT_LIB, false);
|
||||
Proxy::Overlay = ::Utils::Library(GAMEOVERLAY_LIB, false);
|
||||
|
||||
return (Proxy::Client && Proxy::Overlay);
|
||||
return (Proxy::Client.Valid() && Proxy::Overlay.Valid());
|
||||
}
|
||||
|
||||
void Proxy::Uninititalize()
|
||||
{
|
||||
// Freeing libraries causes crashes
|
||||
//if (Proxy::Client) FreeLibrary(Proxy::Client);
|
||||
Proxy::Client = nullptr;
|
||||
|
||||
//if (Proxy::Overlay) FreeLibrary(Proxy::Overlay);
|
||||
Proxy::Overlay = nullptr;
|
||||
Proxy::Client = ::Utils::Library();
|
||||
Proxy::Overlay = ::Utils::Library();
|
||||
}
|
||||
|
||||
std::string Proxy::GetSteamDirectory()
|
||||
@ -46,27 +42,17 @@ namespace Steam
|
||||
|
||||
void Proxy::SetOverlayNotificationPosition(uint32_t eNotificationPosition)
|
||||
{
|
||||
if (Proxy::Overlay)
|
||||
if (Proxy::Overlay.Valid())
|
||||
{
|
||||
FARPROC SetNotificationPositionFn = GetProcAddress(Proxy::Overlay, "SetNotificationPosition");
|
||||
|
||||
if (SetNotificationPositionFn)
|
||||
{
|
||||
::Utils::Hook::Call<void(uint32_t)>(SetNotificationPositionFn)(eNotificationPosition);
|
||||
}
|
||||
Proxy::Overlay.Get<void(uint32_t)>("SetNotificationPosition")(eNotificationPosition);
|
||||
}
|
||||
}
|
||||
|
||||
bool Proxy::IsOverlayEnabled()
|
||||
{
|
||||
if (Proxy::Overlay)
|
||||
if (Proxy::Overlay.Valid())
|
||||
{
|
||||
FARPROC IsOverlayEnabledFn = GetProcAddress(Proxy::Overlay, "IsOverlayEnabled");
|
||||
|
||||
if (IsOverlayEnabledFn)
|
||||
{
|
||||
return ::Utils::Hook::Call<bool()>(IsOverlayEnabledFn)();
|
||||
}
|
||||
return Proxy::Overlay.Get<bool()>("IsOverlayEnabled")();
|
||||
}
|
||||
|
||||
return false;
|
||||
@ -74,14 +60,9 @@ namespace Steam
|
||||
|
||||
bool Proxy::BOverlayNeedsPresent()
|
||||
{
|
||||
if (Proxy::Overlay)
|
||||
if (Proxy::Overlay.Valid())
|
||||
{
|
||||
FARPROC BOverlayNeedsPresentFn = GetProcAddress(Proxy::Overlay, "BOverlayNeedsPresent");
|
||||
|
||||
if (BOverlayNeedsPresentFn)
|
||||
{
|
||||
return ::Utils::Hook::Call<bool()>(BOverlayNeedsPresentFn)();
|
||||
}
|
||||
return Proxy::Overlay.Get<bool()>("BOverlayNeedsPresent")();
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -22,8 +22,8 @@ namespace Steam
|
||||
static bool BOverlayNeedsPresent();
|
||||
|
||||
private:
|
||||
static HMODULE Client;
|
||||
static HMODULE Overlay;
|
||||
static ::Utils::Library Client;
|
||||
static ::Utils::Library Overlay;
|
||||
|
||||
static std::string GetSteamDirectory();
|
||||
};
|
||||
|
@ -1,5 +1,3 @@
|
||||
#define ARR_SIZE(x) (sizeof(x) / sizeof(x[0]))
|
||||
|
||||
namespace Utils
|
||||
{
|
||||
class InfoString
|
||||
|
29
src/Utils/Library.cpp
Normal file
29
src/Utils/Library.cpp
Normal file
@ -0,0 +1,29 @@
|
||||
#include "STDInclude.hpp"
|
||||
|
||||
namespace Utils
|
||||
{
|
||||
Library::Library(std::string buffer, bool freeOnDestroy) : FreeOnDestroy(freeOnDestroy), Module(nullptr)
|
||||
{
|
||||
this->Module = LoadLibraryExA(buffer.data(), NULL, 0);
|
||||
}
|
||||
|
||||
Library::~Library()
|
||||
{
|
||||
if (this->FreeOnDestroy && this->Valid())
|
||||
{
|
||||
FreeLibrary(this->GetModule());
|
||||
}
|
||||
|
||||
this->Module = nullptr;
|
||||
}
|
||||
|
||||
bool Library::Valid()
|
||||
{
|
||||
return (this->GetModule() != nullptr);
|
||||
}
|
||||
|
||||
HMODULE Library::GetModule()
|
||||
{
|
||||
return this->Module;
|
||||
}
|
||||
}
|
28
src/Utils/Library.hpp
Normal file
28
src/Utils/Library.hpp
Normal file
@ -0,0 +1,28 @@
|
||||
namespace Utils
|
||||
{
|
||||
class Library
|
||||
{
|
||||
public:
|
||||
Library() : Module(nullptr), FreeOnDestroy(false) {};
|
||||
Library(std::string buffer, bool freeOnDestroy = true);
|
||||
~Library();
|
||||
|
||||
bool Valid();
|
||||
HMODULE GetModule();
|
||||
|
||||
template <typename T>
|
||||
std::function<T> Get(std::string process)
|
||||
{
|
||||
if (!this->Valid())
|
||||
{
|
||||
throw new std::runtime_error("Library not loaded!");
|
||||
}
|
||||
|
||||
return reinterpret_cast<T*>(GetProcAddress(this->GetModule(), process.data()));
|
||||
}
|
||||
|
||||
private:
|
||||
HMODULE Module;
|
||||
bool FreeOnDestroy;
|
||||
};
|
||||
}
|
@ -2,17 +2,17 @@
|
||||
|
||||
namespace Utils
|
||||
{
|
||||
void* Memory::AllocateAlign(size_t length, size_t alignment)
|
||||
{
|
||||
void* data = _aligned_malloc(length, alignment);
|
||||
assert(data != nullptr);
|
||||
return data;
|
||||
}
|
||||
|
||||
void* Memory::Allocate(size_t length)
|
||||
{
|
||||
void* data = new char[length];
|
||||
|
||||
void* data = calloc(length, 1);
|
||||
assert(data != nullptr);
|
||||
|
||||
if (data)
|
||||
{
|
||||
ZeroMemory(data, length);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
@ -27,7 +27,7 @@ namespace Utils
|
||||
{
|
||||
if (data)
|
||||
{
|
||||
delete[] data;
|
||||
free(data);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -92,6 +92,7 @@ namespace Utils
|
||||
std::map<void*, FreeCallback> RefMemory;
|
||||
};
|
||||
|
||||
static void* AllocateAlign(size_t length, size_t alignment);
|
||||
static void* Allocate(size_t length);
|
||||
template <typename T> static T* Allocate()
|
||||
{
|
||||
|
@ -12,7 +12,7 @@ namespace Utils
|
||||
class Reader
|
||||
{
|
||||
public:
|
||||
Reader(Utils::Memory::Allocator* allocator, std::string& buffer) : Buffer(buffer), Allocator(allocator), Position(0) {}
|
||||
Reader(Utils::Memory::Allocator* allocator, std::string buffer) : Buffer(buffer), Allocator(allocator), Position(0) {}
|
||||
|
||||
std::string ReadString();
|
||||
const char* ReadCString();
|
||||
|
BIN
tools/protoc.exe
BIN
tools/protoc.exe
Binary file not shown.
Loading…
Reference in New Issue
Block a user