Merge pull request #680 from catornot/bob-pr-fix
Resolves the merge conflicts for #408
This commit is contained in:
commit
880d489803
|
@ -3,6 +3,7 @@ Standard: Cpp11
|
|||
IndentWidth: 4
|
||||
TabWidth: 4
|
||||
UseCRLF: false
|
||||
AccessModifierOffset: -4
|
||||
AlignTrailingComments: false
|
||||
AllowAllConstructorInitializersOnNextLine: false
|
||||
AllowAllParametersOfDeclarationOnNextLine: true
|
||||
|
@ -34,3 +35,5 @@ IndentExternBlock: Indent
|
|||
PointerAlignment: Left
|
||||
SortIncludes: false
|
||||
NamespaceIndentation: All
|
||||
PackConstructorInitializers: NextLine
|
||||
BreakConstructorInitializersBeforeComma: true
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"format": {
|
||||
"line_width": 120,
|
||||
"tab_size": 4,
|
||||
"use_tabchars": false,
|
||||
"fractional_tab_policy": "use-space",
|
||||
"max_subgroups_hwrap": 2,
|
||||
"max_pargs_hwrap": 2,
|
||||
"max_rows_cmdline": 2,
|
||||
"separate_ctrl_name_with_space": false,
|
||||
"separate_fn_name_with_space": false,
|
||||
"dangle_parens": true,
|
||||
"dangle_align": "child",
|
||||
"min_prefix_chars": 4,
|
||||
"max_prefix_chars": 10,
|
||||
"max_lines_hwrap": 2,
|
||||
"line_ending": "unix",
|
||||
"command_case": "canonical",
|
||||
"keyword_case": "unchanged",
|
||||
"always_wrap": [],
|
||||
"enable_sort": true,
|
||||
"autosort": false,
|
||||
"require_valid_layout": false,
|
||||
"layout_passes": {}
|
||||
}
|
||||
}
|
|
@ -20,10 +20,10 @@ jobs:
|
|||
- name: Setup resource file version
|
||||
shell: bash
|
||||
run: |
|
||||
sed -i 's/DEV/${{ env.NORTHSTAR_VERSION }}/g' NorthstarLauncher/resources.rc
|
||||
sed -i 's/DEV/${{ env.NORTHSTAR_VERSION }}/g' NorthstarDLL/resources.rc
|
||||
sed -i 's/DEV/${{ env.NORTHSTAR_VERSION }}/g' primedev/primelauncher/resources.rc
|
||||
sed -i 's/DEV/${{ env.NORTHSTAR_VERSION }}/g' primedev/resources.rc
|
||||
FILEVERSION=$(echo ${{ env.NORTHSTAR_VERSION }} | tr '.' ',' | sed -E 's/-rc[0-9]+//' | tr -d '[:alpha:]')
|
||||
sed -i "s/0,0,0,1/${FILEVERSION}/g" NorthstarDLL/ns_version.h
|
||||
sed -i "s/0,0,0,1/${FILEVERSION}/g" primedev/ns_version.h
|
||||
- name: Build
|
||||
run: cmake --build .
|
||||
- name: Extract Short Commit Hash
|
||||
|
@ -41,10 +41,20 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: DoozyX/clang-format-lint-action@v0.13
|
||||
- uses: DoozyX/clang-format-lint-action@v0.16.2
|
||||
with:
|
||||
source: 'NorthstarDLL NorthstarLauncher'
|
||||
exclude: 'NorthstarDLL/include loader_launcher_proxy loader_wsock32_proxy'
|
||||
source: 'primedev'
|
||||
exclude: 'primedev/include primedev/thirdparty primedev/wsockproxy'
|
||||
extensions: 'h,cpp'
|
||||
clangFormatVersion: 13
|
||||
clangFormatVersion: 16
|
||||
style: file
|
||||
|
||||
format-check-cmake-files:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: puneetmatharu/cmake-format-lint-action@v1.0.4
|
||||
with:
|
||||
args: "--in-place"
|
||||
- run: |
|
||||
git diff --exit-code
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
name: Merge Conflict Auto Label
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
schedule:
|
||||
- cron: "10 21 * * *"
|
||||
|
||||
jobs:
|
||||
triage:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: mschilde/auto-label-merge-conflicts@master
|
||||
with:
|
||||
CONFLICT_LABEL_NAME: "merge conflicts"
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
MAX_RETRIES: 5
|
||||
WAIT_MS: 5000
|
|
@ -25,10 +25,10 @@ jobs:
|
|||
- name: Setup resource file version
|
||||
shell: bash
|
||||
run: |
|
||||
sed -i 's/DEV/${{ env.NORTHSTAR_VERSION }}/g' NorthstarLauncher/resources.rc
|
||||
sed -i 's/DEV/${{ env.NORTHSTAR_VERSION }}/g' NorthstarDLL/resources.rc
|
||||
sed -i 's/DEV/${{ env.NORTHSTAR_VERSION }}/g' primedev/primelauncher/resources.rc
|
||||
sed -i 's/DEV/${{ env.NORTHSTAR_VERSION }}/g' primedev/resources.rc
|
||||
FILEVERSION=$(echo ${{ env.NORTHSTAR_VERSION }} | tr '.' ',' | sed -E 's/-rc[0-9]+//' | tr -d '[:alpha:]')
|
||||
sed -i "s/0,0,0,1/${FILEVERSION}/g" NorthstarDLL/ns_version.h
|
||||
sed -i "s/0,0,0,1/${FILEVERSION}/g" primedev/ns_version.h
|
||||
- name: Build
|
||||
run: cmake --build .
|
||||
- name: Upload launcher build as artifact
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
[submodule "thirdparty/libcurl"]
|
||||
path = thirdparty/libcurl
|
||||
path = primedev/thirdparty/libcurl
|
||||
url = https://github.com/curl/curl
|
||||
ignore = untracked
|
||||
[submodule "thirdparty/minhook"]
|
||||
path = thirdparty/minhook
|
||||
path = primedev/thirdparty/minhook
|
||||
url = https://github.com/TsudaKageyu/minhook
|
||||
ignore = untracked
|
||||
[submodule "thirdparty/minizip"]
|
||||
path = thirdparty/minizip
|
||||
path = primedev/thirdparty/minizip
|
||||
url = https://github.com/zlib-ng/minizip-ng.git
|
||||
|
|
|
@ -1,10 +1,18 @@
|
|||
cmake_minimum_required(VERSION 3.15)
|
||||
|
||||
project(Northstar CXX ASM_MASM)
|
||||
project(
|
||||
Northstar
|
||||
CXX
|
||||
ASM_MASM
|
||||
)
|
||||
|
||||
if(NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE "Release" CACHE STRING
|
||||
"Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel." FORCE)
|
||||
set(CMAKE_BUILD_TYPE
|
||||
"Release"
|
||||
CACHE STRING
|
||||
"Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel."
|
||||
FORCE
|
||||
)
|
||||
endif()
|
||||
|
||||
# Language specs
|
||||
|
@ -15,19 +23,22 @@ set(CMAKE_VS_PLATFORM_TOOLSET v143)
|
|||
|
||||
# This determines the real binary root directory
|
||||
set(NS_BINARY_DIR ${CMAKE_BINARY_DIR}/game)
|
||||
# NOTE [Fifty]: Visual studio deems Build root with the value "${projectDir}"
|
||||
# in CMakeSettings.json as invalid and defaults to using a temporary dir
|
||||
# somewhere in %USER%/CMakeBuilds. To combat this we set it to "${projectDir}/build"
|
||||
# and then link binaries in ${CMAKE_BINARY_DIR}/game. This means you can copy your
|
||||
# game into ${CMAKE_BINARY_DIR}/game without it being cluttered up by cmake files.
|
||||
# NOTE [Fifty]: Visual studio deems Build root with the value "${projectDir}" in CMakeSettings.json as invalid and
|
||||
# defaults to using a temporary dir somewhere in %USER%/CMakeBuilds. To combat this we set it to "${projectDir}/build"
|
||||
# and then link binaries in ${CMAKE_BINARY_DIR}/game. This means you can copy your game into ${CMAKE_BINARY_DIR}/game
|
||||
# without it being cluttered up by cmake files.
|
||||
|
||||
message(STATUS "NS: Building to ${NS_BINARY_DIR}")
|
||||
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||
list(
|
||||
APPEND
|
||||
CMAKE_MODULE_PATH
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/primedev/cmake"
|
||||
)
|
||||
include(utils)
|
||||
|
||||
include_directories(primedev)
|
||||
include_directories(primedev/thirdparty)
|
||||
|
||||
# Targets
|
||||
add_subdirectory(loader_wsock32_proxy)
|
||||
add_subdirectory(NorthstarDLL)
|
||||
add_subdirectory(NorthstarLauncher)
|
||||
add_subdirectory(primedev)
|
||||
|
|
|
@ -1,188 +0,0 @@
|
|||
# NorthstarDLL
|
||||
|
||||
find_package(minhook REQUIRED)
|
||||
find_package(libcurl REQUIRED)
|
||||
find_package(minizip REQUIRED)
|
||||
|
||||
add_library(NorthstarDLL SHARED
|
||||
"resources.rc"
|
||||
"client/audio.cpp"
|
||||
"client/audio.h"
|
||||
"client/chatcommand.cpp"
|
||||
"client/clientauthhooks.cpp"
|
||||
"client/clientruihooks.cpp"
|
||||
"client/clientvideooverrides.cpp"
|
||||
"client/debugoverlay.cpp"
|
||||
"client/demofixes.cpp"
|
||||
"client/diskvmtfixes.cpp"
|
||||
"client/languagehooks.cpp"
|
||||
"client/latencyflex.cpp"
|
||||
"client/localchatwriter.cpp"
|
||||
"client/localchatwriter.h"
|
||||
"client/modlocalisation.cpp"
|
||||
"client/r2client.cpp"
|
||||
"client/r2client.h"
|
||||
"client/rejectconnectionfixes.cpp"
|
||||
"config/profile.cpp"
|
||||
"config/profile.h"
|
||||
"core/convar/concommand.cpp"
|
||||
"core/convar/concommand.h"
|
||||
"core/convar/convar.cpp"
|
||||
"core/convar/convar.h"
|
||||
"core/convar/cvar.cpp"
|
||||
"core/convar/cvar.h"
|
||||
"core/filesystem/filesystem.cpp"
|
||||
"core/filesystem/filesystem.h"
|
||||
"core/filesystem/rpakfilesystem.cpp"
|
||||
"core/filesystem/rpakfilesystem.h"
|
||||
"core/math/bitbuf.h"
|
||||
"core/math/bits.cpp"
|
||||
"core/math/bits.h"
|
||||
"core/math/color.cpp"
|
||||
"core/math/color.h"
|
||||
"core/math/vector.h"
|
||||
"core/hooks.cpp"
|
||||
"core/hooks.h"
|
||||
"core/macros.h"
|
||||
"core/memalloc.cpp"
|
||||
"core/memalloc.h"
|
||||
"core/memory.cpp"
|
||||
"core/memory.h"
|
||||
"core/sourceinterface.cpp"
|
||||
"core/sourceinterface.h"
|
||||
"core/structs.h"
|
||||
"core/tier0.cpp"
|
||||
"core/tier0.h"
|
||||
"dedicated/dedicated.cpp"
|
||||
"dedicated/dedicated.h"
|
||||
"dedicated/dedicatedlogtoclient.cpp"
|
||||
"dedicated/dedicatedlogtoclient.h"
|
||||
"dedicated/dedicatedmaterialsystem.cpp"
|
||||
"engine/host.cpp"
|
||||
"engine/hoststate.cpp"
|
||||
"engine/hoststate.h"
|
||||
"engine/r2engine.cpp"
|
||||
"engine/r2engine.h"
|
||||
"engine/runframe.cpp"
|
||||
"logging/crashhandler.cpp"
|
||||
"logging/crashhandler.h"
|
||||
"logging/logging.cpp"
|
||||
"logging/logging.h"
|
||||
"logging/loghooks.cpp"
|
||||
"logging/loghooks.h"
|
||||
"logging/sourceconsole.cpp"
|
||||
"logging/sourceconsole.h"
|
||||
"masterserver/masterserver.cpp"
|
||||
"masterserver/masterserver.h"
|
||||
"mods/autodownload/moddownloader.h"
|
||||
"mods/autodownload/moddownloader.cpp"
|
||||
"mods/compiled/kb_act.cpp"
|
||||
"mods/compiled/modkeyvalues.cpp"
|
||||
"mods/compiled/modpdef.cpp"
|
||||
"mods/compiled/modscriptsrson.cpp"
|
||||
"mods/modmanager.cpp"
|
||||
"mods/modmanager.h"
|
||||
"mods/modsavefiles.cpp"
|
||||
"mods/modsavefiles.h"
|
||||
"plugins/plugin_abi.h"
|
||||
"plugins/pluginbackend.cpp"
|
||||
"plugins/pluginbackend.h"
|
||||
"plugins/plugins.cpp"
|
||||
"plugins/plugins.h"
|
||||
"scripts/client/clientchathooks.cpp"
|
||||
"scripts/client/cursorposition.cpp"
|
||||
"scripts/client/scriptbrowserhooks.cpp"
|
||||
"scripts/client/scriptmainmenupromos.cpp"
|
||||
"scripts/client/scriptmodmenu.cpp"
|
||||
"scripts/client/scriptoriginauth.cpp"
|
||||
"scripts/client/scriptserverbrowser.cpp"
|
||||
"scripts/client/scriptservertoclientstringcommand.cpp"
|
||||
"scripts/server/miscserverfixes.cpp"
|
||||
"scripts/server/miscserverscript.cpp"
|
||||
"scripts/server/scriptuserinfo.cpp"
|
||||
"scripts/scriptdatatables.cpp"
|
||||
"scripts/scripthttprequesthandler.cpp"
|
||||
"scripts/scripthttprequesthandler.h"
|
||||
"scripts/scriptjson.cpp"
|
||||
"scripts/scriptjson.h"
|
||||
"scripts/scriptutility.cpp"
|
||||
"server/auth/bansystem.cpp"
|
||||
"server/auth/bansystem.h"
|
||||
"server/auth/serverauthentication.cpp"
|
||||
"server/auth/serverauthentication.h"
|
||||
"server/alltalk.cpp"
|
||||
"server/buildainfile.cpp"
|
||||
"server/r2server.cpp"
|
||||
"server/r2server.h"
|
||||
"server/serverchathooks.cpp"
|
||||
"server/serverchathooks.h"
|
||||
"server/servernethooks.cpp"
|
||||
"server/serverpresence.cpp"
|
||||
"server/serverpresence.h"
|
||||
"shared/exploit_fixes/exploitfixes.cpp"
|
||||
"shared/exploit_fixes/exploitfixes_lzss.cpp"
|
||||
"shared/exploit_fixes/exploitfixes_utf8parser.cpp"
|
||||
"shared/exploit_fixes/ns_limits.cpp"
|
||||
"shared/exploit_fixes/ns_limits.h"
|
||||
"shared/keyvalues.cpp"
|
||||
"shared/keyvalues.h"
|
||||
"shared/maxplayers.cpp"
|
||||
"shared/maxplayers.h"
|
||||
"shared/misccommands.cpp"
|
||||
"shared/misccommands.h"
|
||||
"shared/playlist.cpp"
|
||||
"shared/playlist.h"
|
||||
"squirrel/squirrel.cpp"
|
||||
"squirrel/squirrel.h"
|
||||
"squirrel/squirrelautobind.cpp"
|
||||
"squirrel/squirrelautobind.h"
|
||||
"squirrel/squirrelclasstypes.h"
|
||||
"squirrel/squirreldatatypes.h"
|
||||
"util/printcommands.cpp"
|
||||
"util/printcommands.h"
|
||||
"util/printmaps.cpp"
|
||||
"util/printmaps.h"
|
||||
"util/utils.cpp"
|
||||
"util/utils.h"
|
||||
"util/version.cpp"
|
||||
"util/version.h"
|
||||
"util/wininfo.cpp"
|
||||
"util/wininfo.h"
|
||||
"audio_asm.asm"
|
||||
"dllmain.cpp"
|
||||
"dllmain.h"
|
||||
"ns_version.h"
|
||||
)
|
||||
|
||||
target_link_libraries(NorthstarDLL PRIVATE
|
||||
minhook
|
||||
libcurl
|
||||
minizip
|
||||
WS2_32.lib
|
||||
Crypt32.lib
|
||||
Cryptui.lib
|
||||
dbghelp.lib
|
||||
Wldap32.lib
|
||||
Normaliz.lib
|
||||
Bcrypt.lib
|
||||
version.lib
|
||||
)
|
||||
|
||||
target_include_directories(NorthstarDLL PRIVATE
|
||||
${CMAKE_SOURCE_DIR}/NorthstarDLL
|
||||
${CMAKE_SOURCE_DIR}/thirdparty
|
||||
)
|
||||
|
||||
target_precompile_headers(NorthstarDLL PRIVATE pch.h)
|
||||
|
||||
target_compile_definitions(NorthstarDLL PRIVATE
|
||||
UNICODE
|
||||
_UNICODE
|
||||
CURL_STATICLIB
|
||||
)
|
||||
|
||||
set_target_properties(NorthstarDLL PROPERTIES
|
||||
RUNTIME_OUTPUT_DIRECTORY ${NS_BINARY_DIR}
|
||||
OUTPUT_NAME Northstar
|
||||
LINK_FLAGS "/MANIFEST:NO /DEBUG"
|
||||
)
|
|
@ -1,8 +0,0 @@
|
|||
public Audio_GetParentEvent
|
||||
|
||||
.code
|
||||
Audio_GetParentEvent proc
|
||||
mov rax, r12
|
||||
ret
|
||||
Audio_GetParentEvent endp
|
||||
end
|
|
@ -1,11 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
// use the R2 namespace for game funcs
|
||||
namespace R2
|
||||
{
|
||||
extern char* g_pLocalPlayerUserID;
|
||||
extern char* g_pLocalPlayerOriginToken;
|
||||
|
||||
typedef void* (*GetBaseLocalClientType)();
|
||||
extern GetBaseLocalClientType GetBaseLocalClient;
|
||||
} // namespace R2
|
|
@ -1,47 +0,0 @@
|
|||
#include <cmath>
|
||||
|
||||
#pragma once
|
||||
|
||||
union Vector3
|
||||
{
|
||||
struct
|
||||
{
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
};
|
||||
|
||||
float raw[3];
|
||||
|
||||
void MakeValid()
|
||||
{
|
||||
for (auto& fl : raw)
|
||||
if (std::isnan(fl))
|
||||
fl = 0;
|
||||
}
|
||||
|
||||
// todo: more operators maybe
|
||||
bool operator==(const Vector3& other)
|
||||
{
|
||||
return x == other.x && y == other.y && z == other.z;
|
||||
}
|
||||
};
|
||||
|
||||
union QAngle
|
||||
{
|
||||
struct
|
||||
{
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
float w;
|
||||
};
|
||||
|
||||
float raw[4];
|
||||
|
||||
// todo: more operators maybe
|
||||
bool operator==(const QAngle& other)
|
||||
{
|
||||
return x == other.x && y == other.y && z == other.z && w == other.w;
|
||||
}
|
||||
};
|
|
@ -1,347 +0,0 @@
|
|||
#include "memory.h"
|
||||
|
||||
CMemoryAddress::CMemoryAddress() : m_nAddress(0) {}
|
||||
CMemoryAddress::CMemoryAddress(const uintptr_t nAddress) : m_nAddress(nAddress) {}
|
||||
CMemoryAddress::CMemoryAddress(const void* pAddress) : m_nAddress(reinterpret_cast<uintptr_t>(pAddress)) {}
|
||||
|
||||
// operators
|
||||
CMemoryAddress::operator uintptr_t() const
|
||||
{
|
||||
return m_nAddress;
|
||||
}
|
||||
|
||||
CMemoryAddress::operator void*() const
|
||||
{
|
||||
return reinterpret_cast<void*>(m_nAddress);
|
||||
}
|
||||
|
||||
CMemoryAddress::operator bool() const
|
||||
{
|
||||
return m_nAddress != 0;
|
||||
}
|
||||
|
||||
bool CMemoryAddress::operator==(const CMemoryAddress& other) const
|
||||
{
|
||||
return m_nAddress == other.m_nAddress;
|
||||
}
|
||||
|
||||
bool CMemoryAddress::operator!=(const CMemoryAddress& other) const
|
||||
{
|
||||
return m_nAddress != other.m_nAddress;
|
||||
}
|
||||
|
||||
bool CMemoryAddress::operator==(const uintptr_t& addr) const
|
||||
{
|
||||
return m_nAddress == addr;
|
||||
}
|
||||
|
||||
bool CMemoryAddress::operator!=(const uintptr_t& addr) const
|
||||
{
|
||||
return m_nAddress != addr;
|
||||
}
|
||||
|
||||
CMemoryAddress CMemoryAddress::operator+(const CMemoryAddress& other) const
|
||||
{
|
||||
return Offset(other.m_nAddress);
|
||||
}
|
||||
|
||||
CMemoryAddress CMemoryAddress::operator-(const CMemoryAddress& other) const
|
||||
{
|
||||
return CMemoryAddress(m_nAddress - other.m_nAddress);
|
||||
}
|
||||
|
||||
CMemoryAddress CMemoryAddress::operator+(const uintptr_t& addr) const
|
||||
{
|
||||
return Offset(addr);
|
||||
}
|
||||
|
||||
CMemoryAddress CMemoryAddress::operator-(const uintptr_t& addr) const
|
||||
{
|
||||
return CMemoryAddress(m_nAddress - addr);
|
||||
}
|
||||
|
||||
CMemoryAddress CMemoryAddress::operator*() const
|
||||
{
|
||||
return Deref();
|
||||
}
|
||||
|
||||
// traversal
|
||||
CMemoryAddress CMemoryAddress::Offset(const uintptr_t nOffset) const
|
||||
{
|
||||
return CMemoryAddress(m_nAddress + nOffset);
|
||||
}
|
||||
|
||||
CMemoryAddress CMemoryAddress::Deref(const int nNumDerefs) const
|
||||
{
|
||||
uintptr_t ret = m_nAddress;
|
||||
for (int i = 0; i < nNumDerefs; i++)
|
||||
ret = *reinterpret_cast<uintptr_t*>(ret);
|
||||
|
||||
return CMemoryAddress(ret);
|
||||
}
|
||||
|
||||
// patching
|
||||
void CMemoryAddress::Patch(const uint8_t* pBytes, const size_t nSize)
|
||||
{
|
||||
if (nSize)
|
||||
WriteProcessMemory(GetCurrentProcess(), reinterpret_cast<LPVOID>(m_nAddress), pBytes, nSize, NULL);
|
||||
}
|
||||
|
||||
void CMemoryAddress::Patch(const std::initializer_list<uint8_t> bytes)
|
||||
{
|
||||
uint8_t* pBytes = new uint8_t[bytes.size()];
|
||||
|
||||
int i = 0;
|
||||
for (const uint8_t& byte : bytes)
|
||||
pBytes[i++] = byte;
|
||||
|
||||
Patch(pBytes, bytes.size());
|
||||
delete[] pBytes;
|
||||
}
|
||||
|
||||
inline std::vector<uint8_t> HexBytesToString(const char* pHexString)
|
||||
{
|
||||
std::vector<uint8_t> ret;
|
||||
|
||||
int size = strlen(pHexString);
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
// If this is a space character, ignore it
|
||||
if (isspace(pHexString[i]))
|
||||
continue;
|
||||
|
||||
if (i < size - 1)
|
||||
{
|
||||
BYTE result = 0;
|
||||
for (int j = 0; j < 2; j++)
|
||||
{
|
||||
int val = 0;
|
||||
char c = *(pHexString + i + j);
|
||||
if (c >= 'a')
|
||||
{
|
||||
val = c - 'a' + 0xA;
|
||||
}
|
||||
else if (c >= 'A')
|
||||
{
|
||||
val = c - 'A' + 0xA;
|
||||
}
|
||||
else if (isdigit(c))
|
||||
{
|
||||
val = c - '0';
|
||||
}
|
||||
else
|
||||
{
|
||||
assert_msg(false, "Failed to parse invalid hex string.");
|
||||
val = -1;
|
||||
}
|
||||
|
||||
result += (j == 0) ? val * 16 : val;
|
||||
}
|
||||
ret.push_back(result);
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void CMemoryAddress::Patch(const char* pBytes)
|
||||
{
|
||||
std::vector<uint8_t> vBytes = HexBytesToString(pBytes);
|
||||
Patch(vBytes.data(), vBytes.size());
|
||||
}
|
||||
|
||||
void CMemoryAddress::NOP(const size_t nSize)
|
||||
{
|
||||
uint8_t* pBytes = new uint8_t[nSize];
|
||||
|
||||
memset(pBytes, 0x90, nSize);
|
||||
Patch(pBytes, nSize);
|
||||
|
||||
delete[] pBytes;
|
||||
}
|
||||
|
||||
bool CMemoryAddress::IsMemoryReadable(const size_t nSize)
|
||||
{
|
||||
static SYSTEM_INFO sysInfo;
|
||||
if (!sysInfo.dwPageSize)
|
||||
GetSystemInfo(&sysInfo);
|
||||
|
||||
MEMORY_BASIC_INFORMATION memInfo;
|
||||
if (!VirtualQuery(reinterpret_cast<LPCVOID>(m_nAddress), &memInfo, sizeof(memInfo)))
|
||||
return false;
|
||||
|
||||
return memInfo.RegionSize >= nSize && memInfo.State & MEM_COMMIT && !(memInfo.Protect & PAGE_NOACCESS);
|
||||
}
|
||||
|
||||
CModule::CModule(const HMODULE pModule)
|
||||
{
|
||||
MODULEINFO mInfo {0};
|
||||
|
||||
if (pModule && pModule != INVALID_HANDLE_VALUE)
|
||||
GetModuleInformation(GetCurrentProcess(), pModule, &mInfo, sizeof(MODULEINFO));
|
||||
|
||||
m_nModuleSize = static_cast<size_t>(mInfo.SizeOfImage);
|
||||
m_pModuleBase = reinterpret_cast<uintptr_t>(mInfo.lpBaseOfDll);
|
||||
m_nAddress = m_pModuleBase;
|
||||
|
||||
if (!m_nModuleSize || !m_pModuleBase)
|
||||
return;
|
||||
|
||||
m_pDOSHeader = reinterpret_cast<IMAGE_DOS_HEADER*>(m_pModuleBase);
|
||||
m_pNTHeaders = reinterpret_cast<IMAGE_NT_HEADERS64*>(m_pModuleBase + m_pDOSHeader->e_lfanew);
|
||||
|
||||
const IMAGE_SECTION_HEADER* hSection = IMAGE_FIRST_SECTION(m_pNTHeaders); // Get first image section.
|
||||
|
||||
for (WORD i = 0; i < m_pNTHeaders->FileHeader.NumberOfSections; i++) // Loop through the sections.
|
||||
{
|
||||
const IMAGE_SECTION_HEADER& hCurrentSection = hSection[i]; // Get current section.
|
||||
|
||||
ModuleSections_t moduleSection = ModuleSections_t(
|
||||
std::string(reinterpret_cast<const char*>(hCurrentSection.Name)),
|
||||
static_cast<uintptr_t>(m_pModuleBase + hCurrentSection.VirtualAddress),
|
||||
hCurrentSection.SizeOfRawData);
|
||||
|
||||
if (!strcmp((const char*)hCurrentSection.Name, ".text"))
|
||||
m_ExecutableCode = moduleSection;
|
||||
else if (!strcmp((const char*)hCurrentSection.Name, ".pdata"))
|
||||
m_ExceptionTable = moduleSection;
|
||||
else if (!strcmp((const char*)hCurrentSection.Name, ".data"))
|
||||
m_RunTimeData = moduleSection;
|
||||
else if (!strcmp((const char*)hCurrentSection.Name, ".rdata"))
|
||||
m_ReadOnlyData = moduleSection;
|
||||
|
||||
m_vModuleSections.push_back(moduleSection); // Push back a struct with the section data.
|
||||
}
|
||||
}
|
||||
|
||||
CModule::CModule(const char* pModuleName) : CModule(GetModuleHandleA(pModuleName)) {}
|
||||
|
||||
CMemoryAddress CModule::GetExport(const char* pExportName)
|
||||
{
|
||||
return CMemoryAddress(reinterpret_cast<uintptr_t>(GetProcAddress(reinterpret_cast<HMODULE>(m_nAddress), pExportName)));
|
||||
}
|
||||
|
||||
CMemoryAddress CModule::FindPattern(const uint8_t* pPattern, const char* pMask)
|
||||
{
|
||||
if (!m_ExecutableCode.IsSectionValid())
|
||||
return CMemoryAddress();
|
||||
|
||||
uint64_t nBase = static_cast<uint64_t>(m_ExecutableCode.m_pSectionBase);
|
||||
uint64_t nSize = static_cast<uint64_t>(m_ExecutableCode.m_nSectionSize);
|
||||
|
||||
const uint8_t* pData = reinterpret_cast<uint8_t*>(nBase);
|
||||
const uint8_t* pEnd = pData + static_cast<uint32_t>(nSize) - strlen(pMask);
|
||||
|
||||
int nMasks[64]; // 64*16 = enough masks for 1024 bytes.
|
||||
int iNumMasks = static_cast<int>(ceil(static_cast<float>(strlen(pMask)) / 16.f));
|
||||
|
||||
memset(nMasks, '\0', iNumMasks * sizeof(int));
|
||||
for (intptr_t i = 0; i < iNumMasks; ++i)
|
||||
{
|
||||
for (intptr_t j = strnlen(pMask + i * 16, 16) - 1; j >= 0; --j)
|
||||
{
|
||||
if (pMask[i * 16 + j] == 'x')
|
||||
{
|
||||
_bittestandset(reinterpret_cast<LONG*>(&nMasks[i]), j);
|
||||
}
|
||||
}
|
||||
}
|
||||
__m128i xmm1 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(pPattern));
|
||||
__m128i xmm2, xmm3, msks;
|
||||
for (; pData != pEnd; _mm_prefetch(reinterpret_cast<const char*>(++pData + 64), _MM_HINT_NTA))
|
||||
{
|
||||
if (pPattern[0] == pData[0])
|
||||
{
|
||||
xmm2 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(pData));
|
||||
msks = _mm_cmpeq_epi8(xmm1, xmm2);
|
||||
if ((_mm_movemask_epi8(msks) & nMasks[0]) == nMasks[0])
|
||||
{
|
||||
for (uintptr_t i = 1; i < static_cast<uintptr_t>(iNumMasks); ++i)
|
||||
{
|
||||
xmm2 = _mm_loadu_si128(reinterpret_cast<const __m128i*>((pData + i * 16)));
|
||||
xmm3 = _mm_loadu_si128(reinterpret_cast<const __m128i*>((pPattern + i * 16)));
|
||||
msks = _mm_cmpeq_epi8(xmm2, xmm3);
|
||||
if ((_mm_movemask_epi8(msks) & nMasks[i]) == nMasks[i])
|
||||
{
|
||||
if ((i + 1) == iNumMasks)
|
||||
{
|
||||
return CMemoryAddress(const_cast<uint8_t*>(pData));
|
||||
}
|
||||
}
|
||||
else
|
||||
goto CONTINUE;
|
||||
}
|
||||
|
||||
return CMemoryAddress((&*(const_cast<uint8_t*>(pData))));
|
||||
}
|
||||
}
|
||||
|
||||
CONTINUE:;
|
||||
}
|
||||
|
||||
return CMemoryAddress();
|
||||
}
|
||||
|
||||
inline std::pair<std::vector<uint8_t>, std::string> MaskedBytesFromPattern(const char* pPatternString)
|
||||
{
|
||||
std::vector<uint8_t> vRet;
|
||||
std::string sMask;
|
||||
|
||||
int size = strlen(pPatternString);
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
// If this is a space character, ignore it
|
||||
if (isspace(pPatternString[i]))
|
||||
continue;
|
||||
|
||||
if (pPatternString[i] == '?')
|
||||
{
|
||||
// Add a wildcard
|
||||
vRet.push_back(0);
|
||||
sMask.append("?");
|
||||
}
|
||||
else if (i < size - 1)
|
||||
{
|
||||
BYTE result = 0;
|
||||
for (int j = 0; j < 2; j++)
|
||||
{
|
||||
int val = 0;
|
||||
char c = *(pPatternString + i + j);
|
||||
if (c >= 'a')
|
||||
{
|
||||
val = c - 'a' + 0xA;
|
||||
}
|
||||
else if (c >= 'A')
|
||||
{
|
||||
val = c - 'A' + 0xA;
|
||||
}
|
||||
else if (isdigit(c))
|
||||
{
|
||||
val = c - '0';
|
||||
}
|
||||
else
|
||||
{
|
||||
assert_msg(false, "Failed to parse invalid pattern string.");
|
||||
val = -1;
|
||||
}
|
||||
|
||||
result += (j == 0) ? val * 16 : val;
|
||||
}
|
||||
|
||||
vRet.push_back(result);
|
||||
sMask.append("x");
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
return std::make_pair(vRet, sMask);
|
||||
}
|
||||
|
||||
CMemoryAddress CModule::FindPattern(const char* pPattern)
|
||||
{
|
||||
const auto pattern = MaskedBytesFromPattern(pPattern);
|
||||
return FindPattern(pattern.first.data(), pattern.second.c_str());
|
||||
}
|
|
@ -1,90 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
class CMemoryAddress
|
||||
{
|
||||
public:
|
||||
uintptr_t m_nAddress;
|
||||
|
||||
public:
|
||||
CMemoryAddress();
|
||||
CMemoryAddress(const uintptr_t nAddress);
|
||||
CMemoryAddress(const void* pAddress);
|
||||
|
||||
// operators
|
||||
operator uintptr_t() const;
|
||||
operator void*() const;
|
||||
operator bool() const;
|
||||
|
||||
bool operator==(const CMemoryAddress& other) const;
|
||||
bool operator!=(const CMemoryAddress& other) const;
|
||||
bool operator==(const uintptr_t& addr) const;
|
||||
bool operator!=(const uintptr_t& addr) const;
|
||||
|
||||
CMemoryAddress operator+(const CMemoryAddress& other) const;
|
||||
CMemoryAddress operator-(const CMemoryAddress& other) const;
|
||||
CMemoryAddress operator+(const uintptr_t& other) const;
|
||||
CMemoryAddress operator-(const uintptr_t& other) const;
|
||||
CMemoryAddress operator*() const;
|
||||
|
||||
template <typename T> T RCast()
|
||||
{
|
||||
return reinterpret_cast<T>(m_nAddress);
|
||||
}
|
||||
|
||||
// traversal
|
||||
CMemoryAddress Offset(const uintptr_t nOffset) const;
|
||||
CMemoryAddress Deref(const int nNumDerefs = 1) const;
|
||||
|
||||
// patching
|
||||
void Patch(const uint8_t* pBytes, const size_t nSize);
|
||||
void Patch(const std::initializer_list<uint8_t> bytes);
|
||||
void Patch(const char* pBytes);
|
||||
void NOP(const size_t nSize);
|
||||
|
||||
bool IsMemoryReadable(const size_t nSize);
|
||||
};
|
||||
|
||||
// based on https://github.com/Mauler125/r5sdk/blob/master/r5dev/public/include/module.h
|
||||
class CModule : public CMemoryAddress
|
||||
{
|
||||
public:
|
||||
struct ModuleSections_t
|
||||
{
|
||||
ModuleSections_t(void) = default;
|
||||
ModuleSections_t(const std::string& svSectionName, uintptr_t pSectionBase, size_t nSectionSize)
|
||||
: m_svSectionName(svSectionName), m_pSectionBase(pSectionBase), m_nSectionSize(nSectionSize)
|
||||
{
|
||||
}
|
||||
|
||||
bool IsSectionValid(void) const
|
||||
{
|
||||
return m_nSectionSize != 0;
|
||||
}
|
||||
|
||||
std::string m_svSectionName; // Name of section.
|
||||
uintptr_t m_pSectionBase {}; // Start address of section.
|
||||
size_t m_nSectionSize {}; // Size of section.
|
||||
};
|
||||
|
||||
ModuleSections_t m_ExecutableCode;
|
||||
ModuleSections_t m_ExceptionTable;
|
||||
ModuleSections_t m_RunTimeData;
|
||||
ModuleSections_t m_ReadOnlyData;
|
||||
|
||||
private:
|
||||
std::string m_svModuleName;
|
||||
uintptr_t m_pModuleBase {};
|
||||
DWORD m_nModuleSize {};
|
||||
IMAGE_NT_HEADERS64* m_pNTHeaders = nullptr;
|
||||
IMAGE_DOS_HEADER* m_pDOSHeader = nullptr;
|
||||
std::vector<ModuleSections_t> m_vModuleSections;
|
||||
|
||||
public:
|
||||
CModule() = delete; // no default, we need a module name
|
||||
CModule(const HMODULE pModule);
|
||||
CModule(const char* pModuleName);
|
||||
|
||||
CMemoryAddress GetExport(const char* pExportName);
|
||||
CMemoryAddress FindPattern(const uint8_t* pPattern, const char* pMask);
|
||||
CMemoryAddress FindPattern(const char* pPattern);
|
||||
};
|
|
@ -1,77 +0,0 @@
|
|||
#pragma once
|
||||
//clang-format off
|
||||
// About this file:
|
||||
// This file contains several macros used to define reversed structs
|
||||
// The reason we use these macros is to make it easier to update existing structs
|
||||
// when new fields are reversed
|
||||
// This means we dont have to manually add padding, and recalculate when updating
|
||||
|
||||
// Technical note:
|
||||
// While functionally, these structs act like a regular struct, they are actually
|
||||
// defined as unions with anonymous structs in them.
|
||||
// This means that each field is essentially an offset into a union.
|
||||
// We acknowledge that this goes against C++'s active-member guideline for unions
|
||||
// However, this is not such a big deal here as these structs will not be constructed
|
||||
|
||||
// Usage:
|
||||
// To use these macros, define a struct like so:
|
||||
/*
|
||||
OFFSET_STRUCT(Name)
|
||||
{
|
||||
STRUCT_SIZE(0x100) // Total in-memory struct size
|
||||
FIELD(0x0, int field) // offset, signature
|
||||
}
|
||||
*/
|
||||
|
||||
#define OFFSET_STRUCT(name) union name
|
||||
#define STRUCT_SIZE(size) char __size[size];
|
||||
#define STRUCT_FIELD_OFFSET(offset, signature) \
|
||||
struct \
|
||||
{ \
|
||||
char CONCAT2(pad, __LINE__)[offset]; \
|
||||
signature; \
|
||||
};
|
||||
|
||||
// Special case for a 0-offset field
|
||||
#define STRUCT_FIELD_NOOFFSET(offset, signature) signature;
|
||||
|
||||
// Just puts two tokens next to each other, but
|
||||
// allows us to force the preprocessor to do another pass
|
||||
#define FX(f, x) f x
|
||||
|
||||
// Macro used to detect if the given offset is 0 or not
|
||||
#define TEST_0 ,
|
||||
// MSVC does no preprocessing of integer literals.
|
||||
// On other compilers `0x0` gets processed into `0`
|
||||
#define TEST_0x0 ,
|
||||
|
||||
// Concats the first and third argument and drops everything else
|
||||
// Used with preprocessor expansion in later passes to move the third argument to the fourth and change the value
|
||||
#define ZERO_P_I(a, b, c, ...) a##c
|
||||
|
||||
// We use FX to prepare to use ZERO_P_I.
|
||||
// The right block contains 3 arguments:
|
||||
// NIF_
|
||||
// CONCAT2(TEST_, offset)
|
||||
// 1
|
||||
//
|
||||
// If offset is not 0 (or 0x0) the preprocessor replaces
|
||||
// it with nothing and the third argument stays 1
|
||||
//
|
||||
// If the offset is 0, TEST_0 expands to , and 1 becomes the fourth argument
|
||||
//
|
||||
// With those arguments we call ZERO_P_I and the first and third arugment get concat.
|
||||
// We either end up with:
|
||||
// NIF_ (if offset is 0) or
|
||||
// NIF_1 (if offset is not 0)
|
||||
#define IF_ZERO(m) FX(ZERO_P_I, (NIF_, CONCAT2(TEST_, m), 1))
|
||||
|
||||
// These macros are used to branch after we processed if the offset is zero or not
|
||||
#define NIF_(t, ...) t
|
||||
#define NIF_1(t, ...) __VA_ARGS__
|
||||
|
||||
// FIELD(S), generates an anonymous struct when a non 0 offset is given, otherwise just a signature
|
||||
#define FIELD(offset, signature) IF_ZERO(offset)(STRUCT_FIELD_NOOFFSET, STRUCT_FIELD_OFFSET)(offset, signature)
|
||||
#define FIELDS FIELD
|
||||
|
||||
//clang-format on
|
|
@ -1,36 +0,0 @@
|
|||
#include "tier0.h"
|
||||
|
||||
// use the Tier0 namespace for tier0 funcs
|
||||
namespace Tier0
|
||||
{
|
||||
IMemAlloc* g_pMemAllocSingleton = nullptr;
|
||||
|
||||
ErrorType Error;
|
||||
CommandLineType CommandLine;
|
||||
Plat_FloatTimeType Plat_FloatTime;
|
||||
ThreadInServerFrameThreadType ThreadInServerFrameThread;
|
||||
} // namespace Tier0
|
||||
|
||||
typedef Tier0::IMemAlloc* (*CreateGlobalMemAllocType)();
|
||||
CreateGlobalMemAllocType CreateGlobalMemAlloc;
|
||||
|
||||
// needs to be a seperate function, since memalloc.cpp calls it
|
||||
void TryCreateGlobalMemAlloc()
|
||||
{
|
||||
// init memalloc stuff
|
||||
CreateGlobalMemAlloc =
|
||||
reinterpret_cast<CreateGlobalMemAllocType>(GetProcAddress(GetModuleHandleA("tier0.dll"), "CreateGlobalMemAlloc"));
|
||||
Tier0::g_pMemAllocSingleton = CreateGlobalMemAlloc(); // if it already exists, this returns the preexisting IMemAlloc instance
|
||||
}
|
||||
|
||||
ON_DLL_LOAD("tier0.dll", Tier0GameFuncs, (CModule module))
|
||||
{
|
||||
// shouldn't be necessary, but do this just in case
|
||||
TryCreateGlobalMemAlloc();
|
||||
|
||||
// setup tier0 funcs
|
||||
Tier0::Error = module.GetExport("Error").RCast<Tier0::ErrorType>();
|
||||
Tier0::CommandLine = module.GetExport("CommandLine").RCast<Tier0::CommandLineType>();
|
||||
Tier0::Plat_FloatTime = module.GetExport("Plat_FloatTime").RCast<Tier0::Plat_FloatTimeType>();
|
||||
Tier0::ThreadInServerFrameThread = module.GetExport("ThreadInServerFrameThread").RCast<Tier0::ThreadInServerFrameThreadType>();
|
||||
}
|
|
@ -1,68 +0,0 @@
|
|||
#pragma once
|
||||
namespace Tier0
|
||||
{
|
||||
class IMemAlloc
|
||||
{
|
||||
public:
|
||||
struct VTable
|
||||
{
|
||||
void* unknown[1]; // alloc debug
|
||||
void* (*Alloc)(IMemAlloc* memAlloc, size_t nSize);
|
||||
void* unknown2[1]; // realloc debug
|
||||
void* (*Realloc)(IMemAlloc* memAlloc, void* pMem, size_t nSize);
|
||||
void* unknown3[1]; // free #1
|
||||
void (*Free)(IMemAlloc* memAlloc, void* pMem);
|
||||
void* unknown4[2]; // nullsubs, maybe CrtSetDbgFlag
|
||||
size_t (*GetSize)(IMemAlloc* memAlloc, void* pMem);
|
||||
void* unknown5[9]; // they all do literally nothing
|
||||
void (*DumpStats)(IMemAlloc* memAlloc);
|
||||
void (*DumpStatsFileBase)(IMemAlloc* memAlloc, const char* pchFileBase);
|
||||
void* unknown6[4];
|
||||
int (*heapchk)(IMemAlloc* memAlloc);
|
||||
};
|
||||
|
||||
VTable* m_vtable;
|
||||
};
|
||||
|
||||
class CCommandLine
|
||||
{
|
||||
public:
|
||||
// based on the defs in the 2013 source sdk, but for some reason has an extra function (may be another CreateCmdLine overload?)
|
||||
// these seem to line up with what they should be though
|
||||
virtual void CreateCmdLine(const char* commandline) = 0;
|
||||
virtual void CreateCmdLine(int argc, char** argv) = 0;
|
||||
virtual void unknown() = 0;
|
||||
virtual const char* GetCmdLine(void) const = 0;
|
||||
|
||||
virtual const char* CheckParm(const char* psz, const char** ppszValue = 0) const = 0;
|
||||
virtual void RemoveParm() const = 0;
|
||||
virtual void AppendParm(const char* pszParm, const char* pszValues) = 0;
|
||||
|
||||
virtual const char* ParmValue(const char* psz, const char* pDefaultVal = 0) const = 0;
|
||||
virtual int ParmValue(const char* psz, int nDefaultVal) const = 0;
|
||||
virtual float ParmValue(const char* psz, float flDefaultVal) const = 0;
|
||||
|
||||
virtual int ParmCount() const = 0;
|
||||
virtual int FindParm(const char* psz) const = 0;
|
||||
virtual const char* GetParm(int nIndex) const = 0;
|
||||
virtual void SetParm(int nIndex, char const* pParm) = 0;
|
||||
|
||||
// virtual const char** GetParms() const {}
|
||||
};
|
||||
|
||||
extern IMemAlloc* g_pMemAllocSingleton;
|
||||
|
||||
typedef void (*ErrorType)(const char* fmt, ...);
|
||||
extern ErrorType Error;
|
||||
|
||||
typedef CCommandLine* (*CommandLineType)();
|
||||
extern CommandLineType CommandLine;
|
||||
|
||||
typedef double (*Plat_FloatTimeType)();
|
||||
extern Plat_FloatTimeType Plat_FloatTime;
|
||||
|
||||
typedef bool (*ThreadInServerFrameThreadType)();
|
||||
extern ThreadInServerFrameThreadType ThreadInServerFrameThread;
|
||||
} // namespace Tier0
|
||||
|
||||
void TryCreateGlobalMemAlloc();
|
|
@ -1,3 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
extern "C" __declspec(dllexport) bool InitialiseNorthstar();
|
|
@ -1,45 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
// use the R2 namespace for game funxcs
|
||||
namespace R2
|
||||
{
|
||||
enum class HostState_t
|
||||
{
|
||||
HS_NEW_GAME = 0,
|
||||
HS_LOAD_GAME,
|
||||
HS_CHANGE_LEVEL_SP,
|
||||
HS_CHANGE_LEVEL_MP,
|
||||
HS_RUN,
|
||||
HS_GAME_SHUTDOWN,
|
||||
HS_SHUTDOWN,
|
||||
HS_RESTART,
|
||||
};
|
||||
|
||||
struct CHostState
|
||||
{
|
||||
public:
|
||||
HostState_t m_iCurrentState;
|
||||
HostState_t m_iNextState;
|
||||
|
||||
float m_vecLocation[3];
|
||||
float m_angLocation[3];
|
||||
|
||||
char m_levelName[32];
|
||||
char m_mapGroupName[32];
|
||||
char m_landmarkName[32];
|
||||
char m_saveName[32];
|
||||
float m_flShortFrameTime; // run a few one-tick frames to avoid large timesteps while loading assets
|
||||
|
||||
bool m_activeGame;
|
||||
bool m_bRememberLocation;
|
||||
bool m_bBackgroundLevel;
|
||||
bool m_bWaitingForConnection;
|
||||
bool m_bLetToolsOverrideLoadGameEnts; // During a load game, this tells Foundry to override ents that are selected in Hammer.
|
||||
bool m_bSplitScreenConnect;
|
||||
bool m_bGameHasShutDownAndFlushedMemory; // This is false once we load a map into memory, and set to true once the map is unloaded
|
||||
// and all memory flushed
|
||||
bool m_bWorkshopMapDownloadPending;
|
||||
};
|
||||
|
||||
extern CHostState* g_pHostState;
|
||||
} // namespace R2
|
|
@ -1,264 +0,0 @@
|
|||
#pragma once
|
||||
#include "shared/keyvalues.h"
|
||||
|
||||
// use the R2 namespace for game funcs
|
||||
namespace R2
|
||||
{
|
||||
// Cbuf
|
||||
enum class ECommandTarget_t
|
||||
{
|
||||
CBUF_FIRST_PLAYER = 0,
|
||||
CBUF_LAST_PLAYER = 1, // MAX_SPLITSCREEN_CLIENTS - 1, MAX_SPLITSCREEN_CLIENTS = 2
|
||||
CBUF_SERVER = CBUF_LAST_PLAYER + 1,
|
||||
|
||||
CBUF_COUNT,
|
||||
};
|
||||
|
||||
enum class cmd_source_t
|
||||
{
|
||||
// Added to the console buffer by gameplay code. Generally unrestricted.
|
||||
kCommandSrcCode,
|
||||
|
||||
// Sent from code via engine->ClientCmd, which is restricted to commands visible
|
||||
// via FCVAR_GAMEDLL_FOR_REMOTE_CLIENTS.
|
||||
kCommandSrcClientCmd,
|
||||
|
||||
// Typed in at the console or via a user key-bind. Generally unrestricted, although
|
||||
// the client will throttle commands sent to the server this way to 16 per second.
|
||||
kCommandSrcUserInput,
|
||||
|
||||
// Came in over a net connection as a clc_stringcmd
|
||||
// host_client will be valid during this state.
|
||||
//
|
||||
// Restricted to FCVAR_GAMEDLL commands (but not convars) and special non-ConCommand
|
||||
// server commands hardcoded into gameplay code (e.g. "joingame")
|
||||
kCommandSrcNetClient,
|
||||
|
||||
// Received from the server as the client
|
||||
//
|
||||
// Restricted to commands with FCVAR_SERVER_CAN_EXECUTE
|
||||
kCommandSrcNetServer,
|
||||
|
||||
// Being played back from a demo file
|
||||
//
|
||||
// Not currently restricted by convar flag, but some commands manually ignore calls
|
||||
// from this source. FIXME: Should be heavily restricted as demo commands can come
|
||||
// from untrusted sources.
|
||||
kCommandSrcDemoFile,
|
||||
|
||||
// Invalid value used when cleared
|
||||
kCommandSrcInvalid = -1
|
||||
};
|
||||
|
||||
typedef ECommandTarget_t (*Cbuf_GetCurrentPlayerType)();
|
||||
extern Cbuf_GetCurrentPlayerType Cbuf_GetCurrentPlayer;
|
||||
|
||||
typedef void (*Cbuf_AddTextType)(ECommandTarget_t eTarget, const char* text, cmd_source_t source);
|
||||
extern Cbuf_AddTextType Cbuf_AddText;
|
||||
|
||||
typedef void (*Cbuf_ExecuteType)();
|
||||
extern Cbuf_ExecuteType Cbuf_Execute;
|
||||
|
||||
extern bool (*CCommand__Tokenize)(CCommand& self, const char* pCommandString, R2::cmd_source_t commandSource);
|
||||
|
||||
// CEngine
|
||||
|
||||
enum EngineQuitState
|
||||
{
|
||||
QUIT_NOTQUITTING = 0,
|
||||
QUIT_TODESKTOP,
|
||||
QUIT_RESTART
|
||||
};
|
||||
|
||||
enum class EngineState_t
|
||||
{
|
||||
DLL_INACTIVE = 0, // no dll
|
||||
DLL_ACTIVE, // engine is focused
|
||||
DLL_CLOSE, // closing down dll
|
||||
DLL_RESTART, // engine is shutting down but will restart right away
|
||||
DLL_PAUSED, // engine is paused, can become active from this state
|
||||
};
|
||||
|
||||
class CEngine
|
||||
{
|
||||
public:
|
||||
virtual void unknown() = 0; // unsure if this is where
|
||||
virtual bool Load(bool dedicated, const char* baseDir) = 0;
|
||||
virtual void Unload() = 0;
|
||||
virtual void SetNextState(EngineState_t iNextState) = 0;
|
||||
virtual EngineState_t GetState() = 0;
|
||||
virtual void Frame() = 0;
|
||||
virtual double GetFrameTime() = 0;
|
||||
virtual float GetCurTime() = 0;
|
||||
|
||||
EngineQuitState m_nQuitting;
|
||||
EngineState_t m_nDllState;
|
||||
EngineState_t m_nNextDllState;
|
||||
double m_flCurrentTime;
|
||||
float m_flFrameTime;
|
||||
double m_flPreviousTime;
|
||||
float m_flFilteredTime;
|
||||
float m_flMinFrameTime; // Expected duration of a frame, or zero if it is unlimited.
|
||||
};
|
||||
|
||||
extern CEngine* g_pEngine;
|
||||
|
||||
extern void (*CBaseClient__Disconnect)(void* self, uint32_t unknownButAlways1, const char* reason, ...);
|
||||
|
||||
#pragma once
|
||||
typedef enum
|
||||
{
|
||||
NA_NULL = 0,
|
||||
NA_LOOPBACK,
|
||||
NA_IP,
|
||||
} netadrtype_t;
|
||||
|
||||
#pragma pack(push, 1)
|
||||
typedef struct netadr_s
|
||||
{
|
||||
netadrtype_t type;
|
||||
unsigned char ip[16]; // IPv6
|
||||
// IPv4's 127.0.0.1 is [::ffff:127.0.0.1], that is:
|
||||
// 00 00 00 00 00 00 00 00 00 00 FF FF 7F 00 00 01
|
||||
unsigned short port;
|
||||
} netadr_t;
|
||||
#pragma pack(pop)
|
||||
|
||||
#pragma pack(push, 1)
|
||||
typedef struct netpacket_s
|
||||
{
|
||||
netadr_t adr; // sender address
|
||||
// int source; // received source
|
||||
char unk[10];
|
||||
double received_time;
|
||||
unsigned char* data; // pointer to raw packet data
|
||||
void* message; // easy bitbuf data access // 'inpacket.message' etc etc (pointer)
|
||||
char unk2[16];
|
||||
int size;
|
||||
|
||||
// bf_read message; // easy bitbuf data access // 'inpacket.message' etc etc (pointer)
|
||||
// int size; // size in bytes
|
||||
// int wiresize; // size in bytes before decompression
|
||||
// bool stream; // was send as stream
|
||||
// struct netpacket_s* pNext; // for internal use, should be NULL in public
|
||||
} netpacket_t;
|
||||
#pragma pack(pop)
|
||||
|
||||
// #56169 $DB69 PData size
|
||||
// #512 $200 Trailing data
|
||||
// #100 $64 Safety buffer
|
||||
const int PERSISTENCE_MAX_SIZE = 0xDDCD;
|
||||
|
||||
// note: NOT_READY and READY are the only entries we have here that are defined by the vanilla game
|
||||
// entries after this are custom and used to determine the source of persistence, e.g. whether it is local or remote
|
||||
enum class ePersistenceReady : char
|
||||
{
|
||||
NOT_READY,
|
||||
READY = 3,
|
||||
READY_INSECURE = 3,
|
||||
READY_REMOTE
|
||||
};
|
||||
|
||||
enum class eSignonState : int
|
||||
{
|
||||
NONE = 0, // no state yet; about to connect
|
||||
CHALLENGE = 1, // client challenging server; all OOB packets
|
||||
CONNECTED = 2, // client is connected to server; netchans ready
|
||||
NEW = 3, // just got serverinfo and string tables
|
||||
PRESPAWN = 4, // received signon buffers
|
||||
GETTINGDATA = 5, // respawn-defined signonstate, assumedly this is for persistence
|
||||
SPAWN = 6, // ready to receive entity packets
|
||||
FIRSTSNAP = 7, // another respawn-defined one
|
||||
FULL = 8, // we are fully connected; first non-delta packet received
|
||||
CHANGELEVEL = 9, // server is changing level; please wait
|
||||
};
|
||||
|
||||
// clang-format off
|
||||
OFFSET_STRUCT(CBaseClient)
|
||||
{
|
||||
STRUCT_SIZE(0x2D728)
|
||||
FIELD(0x16, char m_Name[64])
|
||||
FIELD(0x258, KeyValues* m_ConVars)
|
||||
FIELD(0x2A0, eSignonState m_Signon)
|
||||
FIELD(0x358, char m_ClanTag[16])
|
||||
FIELD(0x484, bool m_bFakePlayer)
|
||||
FIELD(0x4A0, ePersistenceReady m_iPersistenceReady)
|
||||
FIELD(0x4FA, char m_PersistenceBuffer[PERSISTENCE_MAX_SIZE])
|
||||
FIELD(0xF500, char m_UID[32])
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
extern CBaseClient* g_pClientArray;
|
||||
|
||||
enum server_state_t
|
||||
{
|
||||
ss_dead = 0, // Dead
|
||||
ss_loading, // Spawning
|
||||
ss_active, // Running
|
||||
ss_paused, // Running, but paused
|
||||
};
|
||||
|
||||
extern server_state_t* g_pServerState;
|
||||
|
||||
extern char* g_pModName;
|
||||
|
||||
// clang-format off
|
||||
OFFSET_STRUCT(CGlobalVars)
|
||||
{
|
||||
FIELD(0x0,
|
||||
// Absolute time (per frame still - Use Plat_FloatTime() for a high precision real time
|
||||
// perf clock, but not that it doesn't obey host_timescale/host_framerate)
|
||||
double m_flRealTime);
|
||||
|
||||
FIELDS(0x8,
|
||||
// Absolute frame counter - continues to increase even if game is paused
|
||||
int m_nFrameCount;
|
||||
|
||||
// Non-paused frametime
|
||||
float m_flAbsoluteFrameTime;
|
||||
|
||||
// Current time
|
||||
//
|
||||
// On the client, this (along with tickcount) takes a different meaning based on what
|
||||
// piece of code you're in:
|
||||
//
|
||||
// - While receiving network packets (like in PreDataUpdate/PostDataUpdate and proxies),
|
||||
// this is set to the SERVER TICKCOUNT for that packet. There is no interval between
|
||||
// the server ticks.
|
||||
// [server_current_Tick * tick_interval]
|
||||
//
|
||||
// - While rendering, this is the exact client clock
|
||||
// [client_current_tick * tick_interval + interpolation_amount]
|
||||
//
|
||||
// - During prediction, this is based on the client's current tick:
|
||||
// [client_current_tick * tick_interval]
|
||||
float m_flCurTime;
|
||||
)
|
||||
|
||||
FIELDS(0x30,
|
||||
// Time spent on last server or client frame (has nothing to do with think intervals)
|
||||
float m_flFrameTime;
|
||||
|
||||
// current maxplayers setting
|
||||
int m_nMaxClients;
|
||||
)
|
||||
|
||||
FIELDS(0x3C,
|
||||
// Simulation ticks - does not increase when game is paused
|
||||
uint32_t m_nTickCount; // this is weird and doesn't seem to increase once per frame?
|
||||
|
||||
// Simulation tick interval
|
||||
float m_flTickInterval;
|
||||
)
|
||||
|
||||
FIELDS(0x60,
|
||||
const char* m_pMapName;
|
||||
int m_nMapVersion;
|
||||
)
|
||||
|
||||
//FIELD(0x98, double m_flRealTime); // again?
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
extern CGlobalVars* g_pGlobals;
|
||||
} // namespace R2
|
|
@ -1,151 +0,0 @@
|
|||
#pragma once
|
||||
#include "squirrel/squirrelclasstypes.h"
|
||||
|
||||
#define ABI_VERSION 3
|
||||
|
||||
enum PluginLoadDLL
|
||||
{
|
||||
ENGINE = 0,
|
||||
CLIENT,
|
||||
SERVER
|
||||
};
|
||||
|
||||
enum ObjectType
|
||||
{
|
||||
CONCOMMANDS = 0,
|
||||
CONVAR = 1,
|
||||
};
|
||||
|
||||
struct SquirrelFunctions
|
||||
{
|
||||
RegisterSquirrelFuncType RegisterSquirrelFunc;
|
||||
sq_defconstType __sq_defconst;
|
||||
|
||||
sq_compilebufferType __sq_compilebuffer;
|
||||
sq_callType __sq_call;
|
||||
sq_raiseerrorType __sq_raiseerror;
|
||||
sq_compilefileType __sq_compilefile;
|
||||
|
||||
sq_newarrayType __sq_newarray;
|
||||
sq_arrayappendType __sq_arrayappend;
|
||||
|
||||
sq_newtableType __sq_newtable;
|
||||
sq_newslotType __sq_newslot;
|
||||
|
||||
sq_pushroottableType __sq_pushroottable;
|
||||
sq_pushstringType __sq_pushstring;
|
||||
sq_pushintegerType __sq_pushinteger;
|
||||
sq_pushfloatType __sq_pushfloat;
|
||||
sq_pushboolType __sq_pushbool;
|
||||
sq_pushassetType __sq_pushasset;
|
||||
sq_pushvectorType __sq_pushvector;
|
||||
sq_pushobjectType __sq_pushobject;
|
||||
|
||||
sq_getstringType __sq_getstring;
|
||||
sq_getintegerType __sq_getinteger;
|
||||
sq_getfloatType __sq_getfloat;
|
||||
sq_getboolType __sq_getbool;
|
||||
sq_getType __sq_get;
|
||||
sq_getassetType __sq_getasset;
|
||||
sq_getuserdataType __sq_getuserdata;
|
||||
sq_getvectorType __sq_getvector;
|
||||
sq_getthisentityType __sq_getthisentity;
|
||||
sq_getobjectType __sq_getobject;
|
||||
|
||||
sq_stackinfosType __sq_stackinfos;
|
||||
|
||||
sq_createuserdataType __sq_createuserdata;
|
||||
sq_setuserdatatypeidType __sq_setuserdatatypeid;
|
||||
sq_getfunctionType __sq_getfunction;
|
||||
|
||||
sq_schedule_call_externalType __sq_schedule_call_external;
|
||||
|
||||
sq_getentityfrominstanceType __sq_getentityfrominstance;
|
||||
sq_GetEntityConstantType __sq_GetEntityConstant_CBaseEntity;
|
||||
|
||||
sq_pushnewstructinstanceType __sq_pushnewstructinstance;
|
||||
sq_sealstructslotType __sq_sealstructslot;
|
||||
};
|
||||
|
||||
struct MessageSource
|
||||
{
|
||||
const char* file;
|
||||
const char* func;
|
||||
int line;
|
||||
};
|
||||
|
||||
// This is a modified version of spdlog::details::log_msg
|
||||
// This is so that we can make it cross DLL boundaries
|
||||
struct LogMsg
|
||||
{
|
||||
int level;
|
||||
uint64_t timestamp;
|
||||
const char* msg;
|
||||
MessageSource source;
|
||||
int pluginHandle;
|
||||
};
|
||||
|
||||
extern "C"
|
||||
{
|
||||
typedef void (*loggerfunc_t)(LogMsg* msg);
|
||||
typedef void (*PLUGIN_RELAY_INVITE_TYPE)(const char* invite);
|
||||
typedef void* (*CreateObjectFunc)(ObjectType type);
|
||||
|
||||
typedef void (*PluginFnCommandCallback_t)(void* command);
|
||||
typedef void (*PluginConCommandConstructorType)(
|
||||
void* newCommand, const char* name, PluginFnCommandCallback_t callback, const char* helpString, int flags, void* parent);
|
||||
typedef void (*PluginConVarRegisterType)(
|
||||
void* pConVar,
|
||||
const char* pszName,
|
||||
const char* pszDefaultValue,
|
||||
int nFlags,
|
||||
const char* pszHelpString,
|
||||
bool bMin,
|
||||
float fMin,
|
||||
bool bMax,
|
||||
float fMax,
|
||||
void* pCallback);
|
||||
typedef void (*PluginConVarMallocType)(void* pConVarMaloc, int a2, int a3);
|
||||
}
|
||||
|
||||
struct PluginNorthstarData
|
||||
{
|
||||
const char* version;
|
||||
HMODULE northstarModule;
|
||||
int pluginHandle;
|
||||
};
|
||||
|
||||
struct PluginInitFuncs
|
||||
{
|
||||
loggerfunc_t logger;
|
||||
PLUGIN_RELAY_INVITE_TYPE relayInviteFunc;
|
||||
CreateObjectFunc createObject;
|
||||
};
|
||||
|
||||
struct PluginEngineData
|
||||
{
|
||||
PluginConCommandConstructorType ConCommandConstructor;
|
||||
PluginConVarMallocType conVarMalloc;
|
||||
PluginConVarRegisterType conVarRegister;
|
||||
void* ConVar_Vtable;
|
||||
void* IConVar_Vtable;
|
||||
void* g_pCVar;
|
||||
};
|
||||
|
||||
/// <summary> Async communication within the plugin system
|
||||
/// Due to the asynchronous nature of plugins, combined with the limitations of multi-compiler support
|
||||
/// and the custom memory allocator used by r2, is it difficult to safely get data across DLL boundaries
|
||||
/// from Northstar to plugin unless Northstar can own that memory.
|
||||
/// This means that plugins should manage their own memory and can only receive data from northstar using one of the functions below.
|
||||
/// These should be exports of the plugin DLL. If they are not exported, they will not be called.
|
||||
/// Note that it is not required to have these exports if you do not use them.
|
||||
/// </summary>
|
||||
|
||||
// Northstar -> Plugin
|
||||
typedef void (*PLUGIN_INIT_TYPE)(PluginInitFuncs* funcs, PluginNorthstarData* data);
|
||||
typedef void (*PLUGIN_INIT_SQVM_TYPE)(SquirrelFunctions* funcs);
|
||||
typedef void (*PLUGIN_INFORM_SQVM_CREATED_TYPE)(ScriptContext context, CSquirrelVM* sqvm);
|
||||
typedef void (*PLUGIN_INFORM_SQVM_DESTROYED_TYPE)(ScriptContext context);
|
||||
|
||||
typedef void (*PLUGIN_INFORM_DLL_LOAD_TYPE)(const char* dll, PluginEngineData* data, void* dllPtr);
|
||||
typedef void (*PLUGIN_RUNFRAME)();
|
|
@ -1,50 +0,0 @@
|
|||
#include "pluginbackend.h"
|
||||
#include "plugin_abi.h"
|
||||
#include "server/serverpresence.h"
|
||||
#include "masterserver/masterserver.h"
|
||||
#include "squirrel/squirrel.h"
|
||||
#include "plugins.h"
|
||||
|
||||
#include "core/convar/concommand.h"
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
#define EXPORT extern "C" __declspec(dllexport)
|
||||
|
||||
AUTOHOOK_INIT()
|
||||
|
||||
PluginCommunicationHandler* g_pPluginCommunicationhandler;
|
||||
|
||||
static PluginDataRequest storedRequest {PluginDataRequestType::END, (PluginRespondDataCallable) nullptr};
|
||||
|
||||
void PluginCommunicationHandler::RunFrame()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(requestMutex);
|
||||
if (!requestQueue.empty())
|
||||
{
|
||||
storedRequest = requestQueue.front();
|
||||
switch (storedRequest.type)
|
||||
{
|
||||
default:
|
||||
spdlog::error("{} was called with invalid request type '{}'", __FUNCTION__, static_cast<int>(storedRequest.type));
|
||||
}
|
||||
requestQueue.pop();
|
||||
}
|
||||
}
|
||||
|
||||
void PluginCommunicationHandler::PushRequest(PluginDataRequestType type, PluginRespondDataCallable func)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(requestMutex);
|
||||
requestQueue.push(PluginDataRequest {type, func});
|
||||
}
|
||||
|
||||
void InformPluginsDLLLoad(fs::path dllPath, void* address)
|
||||
{
|
||||
std::string dllName = dllPath.filename().string();
|
||||
|
||||
void* data = NULL;
|
||||
if (strncmp(dllName.c_str(), "engine.dll", 10) == 0)
|
||||
data = &g_pPluginCommunicationhandler->m_sEngineData;
|
||||
|
||||
g_pPluginManager->InformDLLLoad(dllName.c_str(), data, address);
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
#pragma once
|
||||
#include "plugin_abi.h"
|
||||
|
||||
#include <queue>
|
||||
#include <mutex>
|
||||
|
||||
enum PluginDataRequestType
|
||||
{
|
||||
END = 0,
|
||||
};
|
||||
|
||||
union PluginRespondDataCallable
|
||||
{
|
||||
// Empty for now
|
||||
void* UNUSED;
|
||||
};
|
||||
|
||||
class PluginDataRequest
|
||||
{
|
||||
public:
|
||||
PluginDataRequestType type;
|
||||
PluginRespondDataCallable func;
|
||||
PluginDataRequest(PluginDataRequestType type, PluginRespondDataCallable func) : type(type), func(func) {}
|
||||
};
|
||||
|
||||
class PluginCommunicationHandler
|
||||
{
|
||||
public:
|
||||
void RunFrame();
|
||||
void PushRequest(PluginDataRequestType type, PluginRespondDataCallable func);
|
||||
|
||||
public:
|
||||
std::queue<PluginDataRequest> requestQueue = {};
|
||||
std::mutex requestMutex;
|
||||
|
||||
PluginEngineData m_sEngineData {};
|
||||
};
|
||||
|
||||
void InformPluginsDLLLoad(fs::path dllPath, void* address);
|
||||
extern PluginCommunicationHandler* g_pPluginCommunicationhandler;
|
|
@ -1,321 +0,0 @@
|
|||
#include "plugins.h"
|
||||
#include "config/profile.h"
|
||||
|
||||
#include "squirrel/squirrel.h"
|
||||
#include "plugins.h"
|
||||
#include "masterserver/masterserver.h"
|
||||
#include "core/convar/convar.h"
|
||||
#include "server/serverpresence.h"
|
||||
#include <optional>
|
||||
#include <regex>
|
||||
|
||||
#include "util/version.h"
|
||||
#include "pluginbackend.h"
|
||||
#include "util/wininfo.h"
|
||||
#include "logging/logging.h"
|
||||
#include "dedicated/dedicated.h"
|
||||
|
||||
PluginManager* g_pPluginManager;
|
||||
|
||||
void freeLibrary(HMODULE hLib)
|
||||
{
|
||||
if (!FreeLibrary(hLib))
|
||||
{
|
||||
spdlog::error("There was an error while trying to free library");
|
||||
}
|
||||
}
|
||||
|
||||
EXPORT void PLUGIN_LOG(LogMsg* msg)
|
||||
{
|
||||
spdlog::source_loc src {};
|
||||
src.filename = msg->source.file;
|
||||
src.funcname = msg->source.func;
|
||||
src.line = msg->source.line;
|
||||
auto&& logger = g_pPluginManager->m_vLoadedPlugins[msg->pluginHandle].logger;
|
||||
logger->log(src, (spdlog::level::level_enum)msg->level, msg->msg);
|
||||
}
|
||||
|
||||
EXPORT void* CreateObject(ObjectType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case ObjectType::CONVAR:
|
||||
return (void*)new ConVar;
|
||||
case ObjectType::CONCOMMANDS:
|
||||
return (void*)new ConCommand;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<Plugin> PluginManager::LoadPlugin(fs::path path, PluginInitFuncs* funcs, PluginNorthstarData* data)
|
||||
{
|
||||
|
||||
Plugin plugin {};
|
||||
|
||||
std::string pathstring = path.string();
|
||||
std::wstring wpath = path.wstring();
|
||||
|
||||
LPCWSTR wpptr = wpath.c_str();
|
||||
HMODULE datafile = LoadLibraryExW(wpptr, 0, LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_IMAGE_RESOURCE); // Load the DLL as a data file
|
||||
if (datafile == NULL)
|
||||
{
|
||||
NS::log::PLUGINSYS->info("Failed to load library '{}': ", std::system_category().message(GetLastError()));
|
||||
return std::nullopt;
|
||||
}
|
||||
HRSRC manifestResource = FindResourceW(datafile, MAKEINTRESOURCEW(IDR_RCDATA1), RT_RCDATA);
|
||||
|
||||
if (manifestResource == NULL)
|
||||
{
|
||||
NS::log::PLUGINSYS->info("Could not find manifest for library '{}'", pathstring);
|
||||
freeLibrary(datafile);
|
||||
return std::nullopt;
|
||||
}
|
||||
HGLOBAL myResourceData = LoadResource(datafile, manifestResource);
|
||||
if (myResourceData == NULL)
|
||||
{
|
||||
NS::log::PLUGINSYS->error("Failed to load manifest from library '{}'", pathstring);
|
||||
freeLibrary(datafile);
|
||||
return std::nullopt;
|
||||
}
|
||||
int manifestSize = SizeofResource(datafile, manifestResource);
|
||||
std::string manifest = std::string((const char*)LockResource(myResourceData), 0, manifestSize);
|
||||
freeLibrary(datafile);
|
||||
|
||||
rapidjson_document manifestJSON;
|
||||
manifestJSON.Parse(manifest.c_str());
|
||||
|
||||
if (manifestJSON.HasParseError())
|
||||
{
|
||||
NS::log::PLUGINSYS->error("Manifest for '{}' was invalid", pathstring);
|
||||
return std::nullopt;
|
||||
}
|
||||
if (!manifestJSON.HasMember("name"))
|
||||
{
|
||||
NS::log::PLUGINSYS->error("'{}' is missing a name in its manifest", pathstring);
|
||||
return std::nullopt;
|
||||
}
|
||||
if (!manifestJSON.HasMember("displayname"))
|
||||
{
|
||||
NS::log::PLUGINSYS->error("'{}' is missing a displayname in its manifest", pathstring);
|
||||
return std::nullopt;
|
||||
}
|
||||
if (!manifestJSON.HasMember("description"))
|
||||
{
|
||||
NS::log::PLUGINSYS->error("'{}' is missing a description in its manifest", pathstring);
|
||||
return std::nullopt;
|
||||
}
|
||||
if (!manifestJSON.HasMember("api_version"))
|
||||
{
|
||||
NS::log::PLUGINSYS->error("'{}' is missing a api_version in its manifest", pathstring);
|
||||
return std::nullopt;
|
||||
}
|
||||
if (!manifestJSON.HasMember("version"))
|
||||
{
|
||||
NS::log::PLUGINSYS->error("'{}' is missing a version in its manifest", pathstring);
|
||||
return std::nullopt;
|
||||
}
|
||||
if (!manifestJSON.HasMember("run_on_server"))
|
||||
{
|
||||
NS::log::PLUGINSYS->error("'{}' is missing 'run_on_server' in its manifest", pathstring);
|
||||
return std::nullopt;
|
||||
}
|
||||
if (!manifestJSON.HasMember("run_on_client"))
|
||||
{
|
||||
NS::log::PLUGINSYS->error("'{}' is missing 'run_on_client' in its manifest", pathstring);
|
||||
return std::nullopt;
|
||||
}
|
||||
auto test = manifestJSON["api_version"].GetString();
|
||||
if (strcmp(manifestJSON["api_version"].GetString(), std::to_string(ABI_VERSION).c_str()))
|
||||
{
|
||||
NS::log::PLUGINSYS->error(
|
||||
"'{}' has an incompatible API version number in its manifest. Current ABI version is '{}'", pathstring, ABI_VERSION);
|
||||
return std::nullopt;
|
||||
}
|
||||
// Passed all checks, going to actually load it now
|
||||
|
||||
HMODULE pluginLib = LoadLibraryW(wpptr); // Load the DLL as a data file
|
||||
if (pluginLib == NULL)
|
||||
{
|
||||
NS::log::PLUGINSYS->info("Failed to load library '{}': ", std::system_category().message(GetLastError()));
|
||||
return std::nullopt;
|
||||
}
|
||||
plugin.init = (PLUGIN_INIT_TYPE)GetProcAddress(pluginLib, "PLUGIN_INIT");
|
||||
if (plugin.init == NULL)
|
||||
{
|
||||
NS::log::PLUGINSYS->info("Library '{}' has no function 'PLUGIN_INIT'", pathstring);
|
||||
return std::nullopt;
|
||||
}
|
||||
NS::log::PLUGINSYS->info("Succesfully loaded {}", pathstring);
|
||||
|
||||
plugin.name = manifestJSON["name"].GetString();
|
||||
plugin.displayName = manifestJSON["displayname"].GetString();
|
||||
plugin.description = manifestJSON["description"].GetString();
|
||||
plugin.api_version = manifestJSON["api_version"].GetString();
|
||||
plugin.version = manifestJSON["version"].GetString();
|
||||
|
||||
plugin.run_on_client = manifestJSON["run_on_client"].GetBool();
|
||||
plugin.run_on_server = manifestJSON["run_on_server"].GetBool();
|
||||
|
||||
if (!plugin.run_on_server && IsDedicatedServer())
|
||||
return std::nullopt;
|
||||
|
||||
if (manifestJSON.HasMember("dependencyName"))
|
||||
{
|
||||
plugin.dependencyName = manifestJSON["dependencyName"].GetString();
|
||||
}
|
||||
else
|
||||
{
|
||||
plugin.dependencyName = plugin.name;
|
||||
}
|
||||
|
||||
plugin.init_sqvm_client = (PLUGIN_INIT_SQVM_TYPE)GetProcAddress(pluginLib, "PLUGIN_INIT_SQVM_CLIENT");
|
||||
plugin.init_sqvm_server = (PLUGIN_INIT_SQVM_TYPE)GetProcAddress(pluginLib, "PLUGIN_INIT_SQVM_SERVER");
|
||||
plugin.inform_sqvm_created = (PLUGIN_INFORM_SQVM_CREATED_TYPE)GetProcAddress(pluginLib, "PLUGIN_INFORM_SQVM_CREATED");
|
||||
plugin.inform_sqvm_destroyed = (PLUGIN_INFORM_SQVM_DESTROYED_TYPE)GetProcAddress(pluginLib, "PLUGIN_INFORM_SQVM_DESTROYED");
|
||||
|
||||
plugin.inform_dll_load = (PLUGIN_INFORM_DLL_LOAD_TYPE)GetProcAddress(pluginLib, "PLUGIN_INFORM_DLL_LOAD");
|
||||
|
||||
plugin.run_frame = (PLUGIN_RUNFRAME)GetProcAddress(pluginLib, "PLUGIN_RUNFRAME");
|
||||
|
||||
plugin.handle = m_vLoadedPlugins.size();
|
||||
plugin.logger = std::make_shared<ColoredLogger>(plugin.displayName.c_str(), NS::Colors::PLUGIN);
|
||||
RegisterLogger(plugin.logger);
|
||||
NS::log::PLUGINSYS->info("Loading plugin {} version {}", plugin.displayName, plugin.version);
|
||||
m_vLoadedPlugins.push_back(plugin);
|
||||
|
||||
plugin.init(funcs, data);
|
||||
|
||||
return plugin;
|
||||
}
|
||||
|
||||
inline void FindPlugins(fs::path pluginPath, std::vector<fs::path>& paths)
|
||||
{
|
||||
// ensure dirs exist
|
||||
if (!fs::exists(pluginPath) || !fs::is_directory(pluginPath))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (const fs::directory_entry& entry : fs::recursive_directory_iterator(pluginPath))
|
||||
{
|
||||
if (fs::is_regular_file(entry) && entry.path().extension() == ".dll")
|
||||
paths.emplace_back(entry.path());
|
||||
}
|
||||
}
|
||||
|
||||
bool PluginManager::LoadPlugins()
|
||||
{
|
||||
if (strstr(GetCommandLineA(), "-noplugins") != NULL)
|
||||
{
|
||||
NS::log::PLUGINSYS->warn("-noplugins detected; skipping loading plugins");
|
||||
return false;
|
||||
}
|
||||
|
||||
fs::create_directories(GetThunderstoreModFolderPath());
|
||||
|
||||
std::vector<fs::path> paths;
|
||||
|
||||
pluginPath = GetNorthstarPrefix() + "\\plugins";
|
||||
|
||||
PluginNorthstarData data {};
|
||||
std::string ns_version {version};
|
||||
|
||||
PluginInitFuncs funcs {};
|
||||
funcs.logger = PLUGIN_LOG;
|
||||
funcs.relayInviteFunc = nullptr;
|
||||
funcs.createObject = CreateObject;
|
||||
|
||||
data.version = ns_version.c_str();
|
||||
data.northstarModule = g_NorthstarModule;
|
||||
|
||||
FindPlugins(pluginPath, paths);
|
||||
|
||||
// Special case for Thunderstore mods dir
|
||||
std::filesystem::directory_iterator thunderstoreModsDir = fs::directory_iterator(GetThunderstoreModFolderPath());
|
||||
// Set up regex for `AUTHOR-MOD-VERSION` pattern
|
||||
std::regex pattern(R"(.*\\([a-zA-Z0-9_]+)-([a-zA-Z0-9_]+)-(\d+\.\d+\.\d+))");
|
||||
for (fs::directory_entry dir : thunderstoreModsDir)
|
||||
{
|
||||
fs::path pluginsDir = dir.path() / "plugins";
|
||||
// Use regex to match `AUTHOR-MOD-VERSION` pattern
|
||||
if (!std::regex_match(dir.path().string(), pattern))
|
||||
{
|
||||
spdlog::warn("The following directory did not match 'AUTHOR-MOD-VERSION': {}", dir.path().string());
|
||||
continue; // skip loading package that doesn't match
|
||||
}
|
||||
FindPlugins(pluginsDir, paths);
|
||||
}
|
||||
|
||||
if (paths.empty())
|
||||
{
|
||||
NS::log::PLUGINSYS->warn("Could not find any plugins. Skipped loading plugins");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (fs::path path : paths)
|
||||
{
|
||||
if (LoadPlugin(path, &funcs, &data))
|
||||
data.pluginHandle += 1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void PluginManager::InformSQVMLoad(ScriptContext context, SquirrelFunctions* s)
|
||||
{
|
||||
for (auto plugin : m_vLoadedPlugins)
|
||||
{
|
||||
if (context == ScriptContext::CLIENT && plugin.init_sqvm_client != NULL)
|
||||
{
|
||||
plugin.init_sqvm_client(s);
|
||||
}
|
||||
else if (context == ScriptContext::SERVER && plugin.init_sqvm_server != NULL)
|
||||
{
|
||||
plugin.init_sqvm_server(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PluginManager::InformSQVMCreated(ScriptContext context, CSquirrelVM* sqvm)
|
||||
{
|
||||
for (auto plugin : m_vLoadedPlugins)
|
||||
{
|
||||
if (plugin.inform_sqvm_created != NULL)
|
||||
{
|
||||
plugin.inform_sqvm_created(context, sqvm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PluginManager::InformSQVMDestroyed(ScriptContext context)
|
||||
{
|
||||
for (auto plugin : m_vLoadedPlugins)
|
||||
{
|
||||
if (plugin.inform_sqvm_destroyed != NULL)
|
||||
{
|
||||
plugin.inform_sqvm_destroyed(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PluginManager::InformDLLLoad(const char* dll, void* data, void* dllPtr)
|
||||
{
|
||||
for (auto plugin : m_vLoadedPlugins)
|
||||
{
|
||||
if (plugin.inform_dll_load != NULL)
|
||||
{
|
||||
plugin.inform_dll_load(dll, (PluginEngineData*)data, dllPtr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PluginManager::RunFrame()
|
||||
{
|
||||
for (auto plugin : m_vLoadedPlugins)
|
||||
{
|
||||
if (plugin.run_frame != NULL)
|
||||
{
|
||||
plugin.run_frame();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,59 +0,0 @@
|
|||
#pragma once
|
||||
#include "plugin_abi.h"
|
||||
|
||||
const int IDR_RCDATA1 = 101;
|
||||
|
||||
class Plugin
|
||||
{
|
||||
public:
|
||||
std::string name;
|
||||
std::string displayName;
|
||||
std::string dependencyName;
|
||||
std::string description;
|
||||
|
||||
std::string api_version;
|
||||
std::string version;
|
||||
|
||||
// For now this is just implemented as the index into the plugins array
|
||||
// Maybe a bit shit but it works
|
||||
int handle;
|
||||
|
||||
std::shared_ptr<ColoredLogger> logger;
|
||||
|
||||
bool run_on_client = false;
|
||||
bool run_on_server = false;
|
||||
|
||||
public:
|
||||
PLUGIN_INIT_TYPE init;
|
||||
PLUGIN_INIT_SQVM_TYPE init_sqvm_client;
|
||||
PLUGIN_INIT_SQVM_TYPE init_sqvm_server;
|
||||
PLUGIN_INFORM_SQVM_CREATED_TYPE inform_sqvm_created;
|
||||
PLUGIN_INFORM_SQVM_DESTROYED_TYPE inform_sqvm_destroyed;
|
||||
|
||||
PLUGIN_INFORM_DLL_LOAD_TYPE inform_dll_load;
|
||||
|
||||
PLUGIN_RUNFRAME run_frame;
|
||||
};
|
||||
|
||||
class PluginManager
|
||||
{
|
||||
public:
|
||||
std::vector<Plugin> m_vLoadedPlugins;
|
||||
|
||||
public:
|
||||
bool LoadPlugins();
|
||||
std::optional<Plugin> LoadPlugin(fs::path path, PluginInitFuncs* funcs, PluginNorthstarData* data);
|
||||
|
||||
void InformSQVMLoad(ScriptContext context, SquirrelFunctions* s);
|
||||
void InformSQVMCreated(ScriptContext context, CSquirrelVM* sqvm);
|
||||
void InformSQVMDestroyed(ScriptContext context);
|
||||
|
||||
void InformDLLLoad(const char* dll, void* data, void* dllPtr);
|
||||
|
||||
void RunFrame();
|
||||
|
||||
private:
|
||||
std::string pluginPath;
|
||||
};
|
||||
|
||||
extern PluginManager* g_pPluginManager;
|
|
@ -1,110 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "core/math/vector.h"
|
||||
|
||||
// use the R2 namespace for game funcs
|
||||
namespace R2
|
||||
{
|
||||
// server entity stuff
|
||||
class CBaseEntity;
|
||||
extern CBaseEntity* (*Server_GetEntityByIndex)(int index);
|
||||
|
||||
// clang-format off
|
||||
OFFSET_STRUCT(CBasePlayer)
|
||||
{
|
||||
FIELD(0x58, uint32_t m_nPlayerIndex)
|
||||
|
||||
FIELD(0x23E8, bool m_grappleActive)
|
||||
FIELD(0x1D08, uint32_t m_platformUserId)
|
||||
FIELD(0x1D10, int32_t m_classModsActive)
|
||||
FIELD(0x1D8C, int32_t m_posClassModsActive)
|
||||
FIELD(0x1DCC, bool m_passives)
|
||||
FIELD(0x4948, int32_t m_selectedOffhand)
|
||||
FIELD(0x1358, int32_t m_selectedOffhandPendingHybridAction)
|
||||
FIELD(0x1E88, int32_t m_playerFlags)
|
||||
FIELD(0x26A8, int32_t m_lastUCmdSimulationTicks)
|
||||
FIELD(0x26AC, float m_lastUCmdSimulationRemainderTime)
|
||||
FIELD(0x1F04, int32_t m_remoteTurret)
|
||||
FIELD(0x414, int32_t m_hGroundEntity)
|
||||
FIELD(0x13B8, int32_t m_titanSoul)
|
||||
FIELD(0x2054, int32_t m_petTitan)
|
||||
FIELD(0x4D4, int32_t m_iHealth)
|
||||
FIELD(0x4D0, int32_t m_iMaxHealth)
|
||||
FIELD(0x4F1, int32_t m_lifeState)
|
||||
FIELD(0x50C, float m_flMaxspeed)
|
||||
FIELD(0x298, int32_t m_fFlags)
|
||||
FIELD(0x1F64, int32_t m_iObserverMode)
|
||||
FIELD(0x1F6C, int32_t m_hObserverTarget)
|
||||
FIELD(0x2098, int32_t m_hViewModel)
|
||||
FIELD(0x27E4, int32_t m_ubEFNointerpParity)
|
||||
FIELD(0x1FA4, int32_t m_activeBurnCardIndex)
|
||||
FIELD(0x1B68, int32_t m_hColorCorrectionCtrl)
|
||||
FIELD(0x19E0, int32_t m_PlayerFog__m_hCtrl)
|
||||
FIELD(0x26BC, bool m_bShouldDrawPlayerWhileUsingViewEntity)
|
||||
FIELD(0x2848, char m_title[32])
|
||||
FIELD(0x2964, bool m_useCredit)
|
||||
FIELD(0x1F40, float m_damageImpulseNoDecelEndTime)
|
||||
FIELD(0x1E8C, bool m_hasMic)
|
||||
FIELD(0x1E8D, bool m_inPartyChat)
|
||||
FIELD(0x1E90, float m_playerMoveSpeedScale)
|
||||
FIELD(0x1F58, float m_flDeathTime)
|
||||
FIELD(0x25A8, bool m_iSpawnParity)
|
||||
FIELD(0x102284, Vector3 m_upDir)
|
||||
FIELD(0x259C, float m_lastDodgeTime)
|
||||
FIELD(0x22E0, bool m_wallHanging)
|
||||
FIELD(0x22EC, int32_t m_traversalType)
|
||||
FIELD(0x22F0, int32_t m_traversalState)
|
||||
FIELD(0x2328, Vector3 m_traversalRefPos)
|
||||
FIELD(0x231C, Vector3 m_traversalForwardDir)
|
||||
FIELD(0x2354, float m_traversalYawDelta)
|
||||
FIELD(0x2358, int32_t m_traversalYawPoseParameter)
|
||||
FIELD(0x2050, int32_t m_grappleHook)
|
||||
FIELD(0x27C0, int32_t m_autoSprintForced)
|
||||
FIELD(0x27C4, bool m_fIsSprinting)
|
||||
FIELD(0x27CC, float m_sprintStartedTime)
|
||||
FIELD(0x27D0, float m_sprintStartedFrac)
|
||||
FIELD(0x27D4, float m_sprintEndedTime)
|
||||
FIELD(0x27D8, float m_sprintEndedFrac)
|
||||
FIELD(0x27DC, float m_stickySprintStartTime)
|
||||
FIELD(0x2998, float m_smartAmmoPreviousHighestLockOnMeFractionValue)
|
||||
FIELD(0x23FC, int32_t m_activeZipline)
|
||||
FIELD(0x2400, bool m_ziplineReverse)
|
||||
FIELD(0x2410, int32_t m_ziplineState)
|
||||
FIELD(0x2250, int32_t m_duckState)
|
||||
FIELD(0x2254, Vector3 m_StandHullMin)
|
||||
FIELD(0x2260, Vector3 m_StandHullMax)
|
||||
FIELD(0x226C, Vector3 m_DuckHullMin)
|
||||
FIELD(0x2278, Vector3 m_DuckHullMax)
|
||||
FIELD(0x205C, int32_t m_xp)
|
||||
FIELD(0x2060, int32_t m_generation)
|
||||
FIELD(0x2064, int32_t m_rank)
|
||||
FIELD(0x2068, int32_t m_serverForceIncreasePlayerListGenerationParity)
|
||||
FIELD(0x206C, bool m_isPlayingRanked)
|
||||
FIELD(0x2070, float m_skill_mu)
|
||||
FIELD(0x1E80, int32_t m_titanSoulBeingRodeoed)
|
||||
FIELD(0x1E84, int32_t m_entitySyncingWithMe)
|
||||
FIELD(0x2078, float m_nextTitanRespawnAvailable)
|
||||
FIELD(0x1C90, bool m_hasBadReputation)
|
||||
FIELD(0x1C91, char m_communityName[64])
|
||||
FIELD(0x1CD1, char m_communityClanTag[16])
|
||||
FIELD(0x1CE1, char m_factionName[16])
|
||||
FIELD(0x1CF1, char m_hardwareIcon[16])
|
||||
FIELD(0x1D01, bool m_happyHourActive)
|
||||
FIELD(0x1EF4, int32_t m_gestureAutoKillBitfield)
|
||||
FIELD(0x2EA8, int32_t m_pilotClassIndex)
|
||||
FIELD(0x100490, Vector3 m_vecAbsOrigin)
|
||||
FIELD(0x25BE, bool m_isPerformingBoostAction)
|
||||
FIELD(0x240C, bool m_ziplineValid3pWeaponLayerAnim)
|
||||
FIELD(0x345C, int32_t m_playerScriptNetDataGlobal)
|
||||
FIELD(0x1598, int32_t m_bZooming)
|
||||
FIELD(0x1599, bool m_zoomToggleOn)
|
||||
FIELD(0x159C, float m_zoomBaseFrac)
|
||||
FIELD(0x15A0, float m_zoomBaseTime)
|
||||
FIELD(0x15A4, float m_zoomFullStartTime)
|
||||
FIELD(0xA04, int32_t m_camoIndex)
|
||||
FIELD(0xA08, int32_t m_decalIndex)
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
extern CBasePlayer*(__fastcall* UTIL_PlayerByIndex)(int playerIndex);
|
||||
} // namespace R2
|
|
@ -1,7 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
// should we use R2 for this? not sure
|
||||
namespace R2 // use R2 namespace for game funcs
|
||||
{
|
||||
int GetMaxPlayers();
|
||||
} // namespace R2
|
|
@ -1,6 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
namespace NS::Utils
|
||||
{
|
||||
void RemoveAsciiControlSequences(char* str, bool allow_color_codes);
|
||||
}
|
|
@ -1,33 +0,0 @@
|
|||
# NorthstarLauncher
|
||||
|
||||
add_executable(NorthstarLauncher
|
||||
"main.cpp"
|
||||
"resources.rc"
|
||||
)
|
||||
|
||||
target_compile_definitions(NorthstarLauncher PRIVATE
|
||||
UNICODE
|
||||
_UNICODE
|
||||
)
|
||||
|
||||
target_link_libraries(NorthstarLauncher PRIVATE
|
||||
shlwapi.lib
|
||||
kernel32.lib
|
||||
user32.lib
|
||||
gdi32.lib
|
||||
winspool.lib
|
||||
comdlg32.lib
|
||||
advapi32.lib
|
||||
shell32.lib
|
||||
ole32.lib
|
||||
oleaut32.lib
|
||||
uuid.lib
|
||||
odbc32.lib
|
||||
odbccp32.lib
|
||||
WS2_32.lib
|
||||
)
|
||||
|
||||
set_target_properties(NorthstarLauncher PROPERTIES
|
||||
RUNTIME_OUTPUT_DIRECTORY ${NS_BINARY_DIR}
|
||||
LINK_FLAGS "/MANIFEST:NO /DEBUG /STACK:8000000"
|
||||
)
|
|
@ -9,4 +9,4 @@ Check [BUILD.md](BUILD.md) for instructions on how to compile, you can also down
|
|||
|
||||
## Format
|
||||
|
||||
This project uses [clang-format](https://clang.llvm.org/docs/ClangFormat.html), make sure you run `clang-format -i --style=file NorthstarLauncher/*.cpp NorthstarLauncher/*.h NorthstarDLL/*.cpp NorthstarDLL/*.h` when opening a Pull Request. Check the tool's website for instructions on how to integrate it with your IDE.
|
||||
This project uses [clang-format](https://clang.llvm.org/docs/ClangFormat.html), make sure you run `clang-format -i --style=file --exclude=primedev/include primedev/*.cpp primedev/*.h` when opening a Pull Request. Check the tool's website for instructions on how to integrate it with your IDE.
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
|
||||
|
||||
if (NOT libcurl_FOUND)
|
||||
check_init_submodule(${PROJECT_SOURCE_DIR}/thirdparty/libcurl)
|
||||
|
||||
set(BUILD_SHARED_LIBS OFF CACHE BOOL "Build shared libraries")
|
||||
set(BUILD_CURL_EXE OFF CACHE BOOL "Build curl EXE")
|
||||
set(HTTP_ONLY ON CACHE BOOL "Only build HTTP and HTTPS")
|
||||
set(CURL_ENABLE_SSL ON CACHE BOOL "Enable SSL support")
|
||||
set(CURL_USE_OPENSSL OFF CACHE BOOL "Disable OpenSSL")
|
||||
set(CURL_USE_LIBSSH2 OFF CACHE BOOL "Disable libSSH2")
|
||||
set(CURL_USE_SCHANNEL ON CACHE BOOL "Enable Secure Channel")
|
||||
set(CURL_CA_BUNDLE "none" CACHE STRING "Disable CA Bundle")
|
||||
set(CURL_CA_PATH "none" CACHE STRING "Disable CA Path")
|
||||
|
||||
add_subdirectory(${PROJECT_SOURCE_DIR}/thirdparty/libcurl libcurl)
|
||||
set(libcurl_FOUND 1 PARENT_SCOPE)
|
||||
endif()
|
|
@ -1,8 +0,0 @@
|
|||
|
||||
if(NOT minhook_FOUND)
|
||||
check_init_submodule(${PROJECT_SOURCE_DIR}/thirdparty/minhook)
|
||||
|
||||
add_subdirectory(${PROJECT_SOURCE_DIR}/thirdparty/minhook minhook)
|
||||
set(minhook_FOUND 1 PARENT_SCOPE)
|
||||
endif()
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
|
||||
if(NOT minizip_FOUND)
|
||||
check_init_submodule(${PROJECT_SOURCE_DIR}/thirdparty/minizip)
|
||||
|
||||
set(MZ_LZMA OFF CACHE BOOL "Disable LZMA & XZ compression")
|
||||
|
||||
add_subdirectory(${PROJECT_SOURCE_DIR}/thirdparty/minizip minizip)
|
||||
set(minizip_FOUND 1 PARENT_SCOPE)
|
||||
endif()
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
|
||||
if(NOT spdlog_FOUND)
|
||||
check_init_submodule(${PROJECT_SOURCE_DIR}/thirdparty/spdlog)
|
||||
|
||||
add_subdirectory(${PROJECT_SOURCE_DIR}/thirdparty/spdlog spdlog)
|
||||
set(spdlog_FOUND 1 PARENT_SCOPE)
|
||||
endif()
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
|
||||
# Check if a dependency exist before trying to init git submodules
|
||||
function(check_init_submodule path)
|
||||
file(GLOB DIR_CONTENT "${path}/*")
|
||||
list(LENGTH DIR_CONTENT CONTENT_COUNT)
|
||||
if (CONTENT_COUNT EQUAL 0)
|
||||
if (NOT EXISTS "${PROJECT_SOURCE_DIR}/.git")
|
||||
message(FATAL_ERROR "Failed to find third party dependency in '${path}'")
|
||||
endif()
|
||||
|
||||
find_package(Git QUIET)
|
||||
if (NOT Git_FOUND)
|
||||
message(FATAL_ERROR "Failed to find Git, third party dependency could not be setup at `${path}")
|
||||
endif()
|
||||
|
||||
message(STATUS "Setting up dependencies as git submodules")
|
||||
execute_process(COMMAND ${GIT_EXECUTABLE} submodule update --init --recursive
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
RESULT_VARIABLE GIT_SUBMOD_RESULT)
|
||||
|
||||
if(NOT GIT_SUBMOD_RESULT EQUAL "0")
|
||||
message(FATAL_ERROR "Initializing Git submodules failed with ${GIT_SUBMOD_RESULT}")
|
||||
endif()
|
||||
endif()
|
||||
endfunction()
|
|
@ -1,45 +0,0 @@
|
|||
# loader_wsock32_proxy
|
||||
|
||||
find_package(minhook REQUIRED)
|
||||
|
||||
add_library(loader_wsock32_proxy SHARED
|
||||
"dllmain.cpp"
|
||||
"loader.cpp"
|
||||
"loader.h"
|
||||
"wsock32.asm"
|
||||
"wsock32.def"
|
||||
)
|
||||
|
||||
target_link_libraries(loader_wsock32_proxy PRIVATE
|
||||
minhook
|
||||
mswsock.lib
|
||||
ws2_32.lib
|
||||
ShLwApi.lib
|
||||
imagehlp.lib
|
||||
dbghelp.lib
|
||||
kernel32.lib
|
||||
user32.lib
|
||||
gdi32.lib
|
||||
winspool.lib
|
||||
comdlg32.lib
|
||||
advapi32.lib
|
||||
shell32.lib
|
||||
ole32.lib
|
||||
oleaut32.lib
|
||||
uuid.lib
|
||||
odbc32.lib
|
||||
odbccp32.lib
|
||||
)
|
||||
|
||||
target_precompile_headers(loader_wsock32_proxy PRIVATE pch.h)
|
||||
|
||||
target_compile_definitions(loader_wsock32_proxy PRIVATE
|
||||
UNICODE
|
||||
_UNICODE
|
||||
)
|
||||
|
||||
set_target_properties(loader_wsock32_proxy PROPERTIES
|
||||
RUNTIME_OUTPUT_DIRECTORY ${NS_BINARY_DIR}/bin/x64_retail
|
||||
OUTPUT_NAME wsock32
|
||||
LINK_FLAGS "/MANIFEST:NO /DEBUG"
|
||||
)
|
|
@ -1,182 +0,0 @@
|
|||
#include "loader.h"
|
||||
|
||||
#include <shlwapi.h>
|
||||
#include <filesystem>
|
||||
|
||||
HINSTANCE hLThis = 0;
|
||||
FARPROC p[857];
|
||||
HINSTANCE hL = 0;
|
||||
|
||||
bool GetExePathWide(wchar_t* dest, DWORD destSize)
|
||||
{
|
||||
if (!dest)
|
||||
return NULL;
|
||||
if (destSize < MAX_PATH)
|
||||
return NULL;
|
||||
|
||||
DWORD length = GetModuleFileNameW(NULL, dest, destSize);
|
||||
return length && PathRemoveFileSpecW(dest);
|
||||
}
|
||||
|
||||
wchar_t exePath[4096];
|
||||
wchar_t buffer1[8192];
|
||||
wchar_t buffer2[12288];
|
||||
|
||||
BOOL WINAPI DllMain(HINSTANCE hInst, DWORD reason, LPVOID)
|
||||
{
|
||||
if (reason == DLL_PROCESS_ATTACH)
|
||||
{
|
||||
hLThis = hInst;
|
||||
|
||||
if (!GetExePathWide(exePath, 4096))
|
||||
{
|
||||
MessageBoxA(
|
||||
GetForegroundWindow(),
|
||||
"Failed getting game directory.\nThe game cannot continue and has to exit.",
|
||||
"Northstar Wsock32 Proxy Error",
|
||||
0);
|
||||
return true;
|
||||
}
|
||||
|
||||
SetCurrentDirectoryW(exePath);
|
||||
|
||||
if (!ProvisionNorthstar()) // does not call InitialiseNorthstar yet, will do it on LauncherMain hook
|
||||
return true;
|
||||
|
||||
// copy the original library for system to our local directory, with changed name so that we can load it
|
||||
swprintf_s(buffer1, L"%s\\bin\\x64_retail\\wsock32.org.dll", exePath);
|
||||
GetSystemDirectoryW(buffer2, 4096);
|
||||
swprintf_s(buffer2, L"%s\\wsock32.dll", buffer2);
|
||||
try
|
||||
{
|
||||
std::filesystem::copy_file(buffer2, buffer1);
|
||||
}
|
||||
catch (const std::exception& e1)
|
||||
{
|
||||
if (!std::filesystem::exists(buffer1))
|
||||
{
|
||||
// fallback by copying to temp dir...
|
||||
// because apparently games installed by EA Desktop app don't have write permissions in their directories
|
||||
auto temp_dir = std::filesystem::temp_directory_path() / L"wsock32.org.dll";
|
||||
try
|
||||
{
|
||||
std::filesystem::copy_file(buffer2, temp_dir);
|
||||
}
|
||||
catch (const std::exception& e2)
|
||||
{
|
||||
if (!std::filesystem::exists(temp_dir))
|
||||
{
|
||||
swprintf_s(
|
||||
buffer2,
|
||||
L"Failed copying wsock32.dll from system32 to \"%s\"\n\n%S\n\nFurthermore, we failed copying wsock32.dll into "
|
||||
L"temporary directory at \"%s\"\n\n%S",
|
||||
buffer1,
|
||||
e1.what(),
|
||||
temp_dir.c_str(),
|
||||
e2.what());
|
||||
MessageBoxW(GetForegroundWindow(), buffer2, L"Northstar Wsock32 Proxy Error", 0);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
swprintf_s(buffer1, L"%s", temp_dir.c_str());
|
||||
}
|
||||
}
|
||||
hL = LoadLibraryExW(buffer1, 0, LOAD_WITH_ALTERED_SEARCH_PATH);
|
||||
if (!hL)
|
||||
{
|
||||
LibraryLoadError(GetLastError(), L"wsock32.org.dll", buffer1);
|
||||
return false;
|
||||
}
|
||||
|
||||
// load the functions to proxy
|
||||
// it's only some of them, because in case of wsock32 most of the functions can actually be natively redirected
|
||||
// (see wsock32.def and https://source.winehq.org/WineAPI/wsock32.html)
|
||||
p[1] = GetProcAddress(hL, "EnumProtocolsA");
|
||||
p[2] = GetProcAddress(hL, "EnumProtocolsW");
|
||||
p[4] = GetProcAddress(hL, "GetAddressByNameA");
|
||||
p[5] = GetProcAddress(hL, "GetAddressByNameW");
|
||||
p[17] = GetProcAddress(hL, "WEP");
|
||||
p[30] = GetProcAddress(hL, "WSARecvEx");
|
||||
p[36] = GetProcAddress(hL, "__WSAFDIsSet");
|
||||
p[45] = GetProcAddress(hL, "getnetbyname");
|
||||
p[52] = GetProcAddress(hL, "getsockopt");
|
||||
p[56] = GetProcAddress(hL, "inet_network");
|
||||
p[67] = GetProcAddress(hL, "s_perror");
|
||||
p[72] = GetProcAddress(hL, "setsockopt");
|
||||
}
|
||||
|
||||
if (reason == DLL_PROCESS_DETACH)
|
||||
{
|
||||
FreeLibrary(hL);
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
{
|
||||
FARPROC PA = NULL;
|
||||
int RunASM();
|
||||
|
||||
void PROXY_EnumProtocolsA()
|
||||
{
|
||||
PA = p[1];
|
||||
RunASM();
|
||||
}
|
||||
void PROXY_EnumProtocolsW()
|
||||
{
|
||||
PA = p[2];
|
||||
RunASM();
|
||||
}
|
||||
void PROXY_GetAddressByNameA()
|
||||
{
|
||||
PA = p[4];
|
||||
RunASM();
|
||||
}
|
||||
void PROXY_GetAddressByNameW()
|
||||
{
|
||||
PA = p[5];
|
||||
RunASM();
|
||||
}
|
||||
void PROXY_WEP()
|
||||
{
|
||||
PA = p[17];
|
||||
RunASM();
|
||||
}
|
||||
void PROXY_WSARecvEx()
|
||||
{
|
||||
PA = p[30];
|
||||
RunASM();
|
||||
}
|
||||
void PROXY___WSAFDIsSet()
|
||||
{
|
||||
PA = p[36];
|
||||
RunASM();
|
||||
}
|
||||
void PROXY_getnetbyname()
|
||||
{
|
||||
PA = p[45];
|
||||
RunASM();
|
||||
}
|
||||
void PROXY_getsockopt()
|
||||
{
|
||||
PA = p[52];
|
||||
RunASM();
|
||||
}
|
||||
void PROXY_inet_network()
|
||||
{
|
||||
PA = p[56];
|
||||
RunASM();
|
||||
}
|
||||
void PROXY_s_perror()
|
||||
{
|
||||
PA = p[67];
|
||||
RunASM();
|
||||
}
|
||||
void PROXY_setsockopt()
|
||||
{
|
||||
PA = p[72];
|
||||
RunASM();
|
||||
}
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
.data
|
||||
extern PA : qword
|
||||
.code
|
||||
RunASM proc
|
||||
jmp qword ptr [PA]
|
||||
RunASM endp
|
||||
end
|
|
@ -0,0 +1,3 @@
|
|||
include(Northstar.cmake)
|
||||
include(Launcher.cmake)
|
||||
add_subdirectory(wsockproxy)
|
|
@ -0,0 +1,28 @@
|
|||
# NorthstarLauncher
|
||||
|
||||
add_executable(NorthstarLauncher "primelauncher/main.cpp" "primelauncher/resources.rc")
|
||||
|
||||
target_compile_definitions(NorthstarLauncher PRIVATE UNICODE _UNICODE)
|
||||
|
||||
target_link_libraries(
|
||||
NorthstarLauncher
|
||||
PRIVATE shlwapi.lib
|
||||
kernel32.lib
|
||||
user32.lib
|
||||
gdi32.lib
|
||||
winspool.lib
|
||||
comdlg32.lib
|
||||
advapi32.lib
|
||||
shell32.lib
|
||||
ole32.lib
|
||||
oleaut32.lib
|
||||
uuid.lib
|
||||
odbc32.lib
|
||||
odbccp32.lib
|
||||
WS2_32.lib
|
||||
)
|
||||
|
||||
set_target_properties(
|
||||
NorthstarLauncher PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${NS_BINARY_DIR} LINK_FLAGS
|
||||
"/MANIFEST:NO /DEBUG /STACK:8000000"
|
||||
)
|
|
@ -0,0 +1,203 @@
|
|||
# NorthstarDLL
|
||||
|
||||
find_package(minhook REQUIRED)
|
||||
find_package(libcurl REQUIRED)
|
||||
find_package(minizip REQUIRED)
|
||||
find_package(silver-bun REQUIRED)
|
||||
|
||||
add_library(
|
||||
NorthstarDLL SHARED
|
||||
"resources.rc"
|
||||
"client/audio.cpp"
|
||||
"client/audio.h"
|
||||
"client/chatcommand.cpp"
|
||||
"client/clientauthhooks.cpp"
|
||||
"client/clientruihooks.cpp"
|
||||
"client/clientvideooverrides.cpp"
|
||||
"client/debugoverlay.cpp"
|
||||
"client/demofixes.cpp"
|
||||
"client/diskvmtfixes.cpp"
|
||||
"client/entity_client_tools.cpp"
|
||||
"client/languagehooks.cpp"
|
||||
"client/latencyflex.cpp"
|
||||
"client/localchatwriter.cpp"
|
||||
"client/localchatwriter.h"
|
||||
"client/modlocalisation.cpp"
|
||||
"client/r2client.cpp"
|
||||
"client/r2client.h"
|
||||
"client/rejectconnectionfixes.cpp"
|
||||
"config/profile.cpp"
|
||||
"config/profile.h"
|
||||
"core/convar/concommand.cpp"
|
||||
"core/convar/concommand.h"
|
||||
"core/convar/convar.cpp"
|
||||
"core/convar/convar.h"
|
||||
"core/convar/cvar.cpp"
|
||||
"core/convar/cvar.h"
|
||||
"core/filesystem/filesystem.cpp"
|
||||
"core/filesystem/filesystem.h"
|
||||
"core/filesystem/rpakfilesystem.cpp"
|
||||
"core/filesystem/rpakfilesystem.h"
|
||||
"core/math/bitbuf.h"
|
||||
"core/math/bits.cpp"
|
||||
"core/math/bits.h"
|
||||
"core/math/color.cpp"
|
||||
"core/math/color.h"
|
||||
"core/math/math_pfns.h"
|
||||
"core/math/vector.h"
|
||||
"core/math/vplane.h"
|
||||
"core/hooks.cpp"
|
||||
"core/hooks.h"
|
||||
"core/macros.h"
|
||||
"core/memalloc.cpp"
|
||||
"core/memalloc.h"
|
||||
"core/sourceinterface.cpp"
|
||||
"core/sourceinterface.h"
|
||||
"core/tier0.cpp"
|
||||
"core/tier0.h"
|
||||
"core/tier1.cpp"
|
||||
"core/tier1.h"
|
||||
"dedicated/dedicated.cpp"
|
||||
"dedicated/dedicated.h"
|
||||
"dedicated/dedicatedlogtoclient.cpp"
|
||||
"dedicated/dedicatedlogtoclient.h"
|
||||
"dedicated/dedicatedmaterialsystem.cpp"
|
||||
"engine/host.cpp"
|
||||
"engine/hoststate.cpp"
|
||||
"engine/hoststate.h"
|
||||
"engine/r2engine.cpp"
|
||||
"engine/r2engine.h"
|
||||
"engine/runframe.cpp"
|
||||
"logging/crashhandler.cpp"
|
||||
"logging/crashhandler.h"
|
||||
"logging/logging.cpp"
|
||||
"logging/logging.h"
|
||||
"logging/loghooks.cpp"
|
||||
"logging/loghooks.h"
|
||||
"logging/sourceconsole.cpp"
|
||||
"logging/sourceconsole.h"
|
||||
"masterserver/masterserver.cpp"
|
||||
"masterserver/masterserver.h"
|
||||
"mods/autodownload/moddownloader.h"
|
||||
"mods/autodownload/moddownloader.cpp"
|
||||
"mods/compiled/kb_act.cpp"
|
||||
"mods/compiled/modkeyvalues.cpp"
|
||||
"mods/compiled/modpdef.cpp"
|
||||
"mods/compiled/modscriptsrson.cpp"
|
||||
"mods/modmanager.cpp"
|
||||
"mods/modmanager.h"
|
||||
"mods/modsavefiles.cpp"
|
||||
"mods/modsavefiles.h"
|
||||
"plugins/interfaces/interface.h"
|
||||
"plugins/interfaces/interface.cpp"
|
||||
"plugins/interfaces/sys/ISys.h"
|
||||
"plugins/interfaces/sys/ISys.cpp"
|
||||
"plugins/interfaces/IPluginId.h"
|
||||
"plugins/interfaces/IPluginCallbacks.h"
|
||||
"plugins/plugins.cpp"
|
||||
"plugins/plugins.h"
|
||||
"plugins/pluginmanager.h"
|
||||
"plugins/pluginmanager.cpp"
|
||||
"scripts/client/clientchathooks.cpp"
|
||||
"scripts/client/cursorposition.cpp"
|
||||
"scripts/client/scriptbrowserhooks.cpp"
|
||||
"scripts/client/scriptmainmenupromos.cpp"
|
||||
"scripts/client/scriptmodmenu.cpp"
|
||||
"scripts/client/scriptoriginauth.cpp"
|
||||
"scripts/client/scriptserverbrowser.cpp"
|
||||
"scripts/client/scriptservertoclientstringcommand.cpp"
|
||||
"scripts/server/miscserverfixes.cpp"
|
||||
"scripts/server/miscserverscript.cpp"
|
||||
"scripts/server/scriptuserinfo.cpp"
|
||||
"scripts/scriptdatatables.cpp"
|
||||
"scripts/scripthttprequesthandler.cpp"
|
||||
"scripts/scripthttprequesthandler.h"
|
||||
"scripts/scriptjson.cpp"
|
||||
"scripts/scriptjson.h"
|
||||
"scripts/scriptutility.cpp"
|
||||
"server/auth/bansystem.cpp"
|
||||
"server/auth/bansystem.h"
|
||||
"server/auth/serverauthentication.cpp"
|
||||
"server/auth/serverauthentication.h"
|
||||
"server/alltalk.cpp"
|
||||
"server/ai_helper.cpp"
|
||||
"server/ai_helper.h"
|
||||
"server/ai_navmesh.cpp"
|
||||
"server/ai_navmesh.h"
|
||||
"server/buildainfile.cpp"
|
||||
"server/r2server.cpp"
|
||||
"server/r2server.h"
|
||||
"server/serverchathooks.cpp"
|
||||
"server/serverchathooks.h"
|
||||
"server/servernethooks.cpp"
|
||||
"server/serverpresence.cpp"
|
||||
"server/serverpresence.h"
|
||||
"shared/exploit_fixes/exploitfixes.cpp"
|
||||
"shared/exploit_fixes/exploitfixes_lzss.cpp"
|
||||
"shared/exploit_fixes/exploitfixes_utf8parser.cpp"
|
||||
"shared/exploit_fixes/ns_limits.cpp"
|
||||
"shared/exploit_fixes/ns_limits.h"
|
||||
"shared/keyvalues.cpp"
|
||||
"shared/keyvalues.h"
|
||||
"shared/maxplayers.cpp"
|
||||
"shared/maxplayers.h"
|
||||
"shared/misccommands.cpp"
|
||||
"shared/misccommands.h"
|
||||
"shared/playlist.cpp"
|
||||
"shared/playlist.h"
|
||||
"squirrel/squirrel.cpp"
|
||||
"squirrel/squirrel.h"
|
||||
"squirrel/squirrelautobind.cpp"
|
||||
"squirrel/squirrelautobind.h"
|
||||
"squirrel/squirrelclasstypes.h"
|
||||
"squirrel/squirreldatatypes.h"
|
||||
"util/printcommands.cpp"
|
||||
"util/printcommands.h"
|
||||
"util/printmaps.cpp"
|
||||
"util/printmaps.h"
|
||||
"util/utils.cpp"
|
||||
"util/utils.h"
|
||||
"util/version.cpp"
|
||||
"util/version.h"
|
||||
"util/wininfo.cpp"
|
||||
"util/wininfo.h"
|
||||
"dllmain.cpp"
|
||||
"ns_version.h"
|
||||
"Northstar.def"
|
||||
)
|
||||
|
||||
target_link_libraries(
|
||||
NorthstarDLL
|
||||
PRIVATE minhook
|
||||
libcurl
|
||||
minizip
|
||||
silver-bun
|
||||
WS2_32.lib
|
||||
Crypt32.lib
|
||||
Cryptui.lib
|
||||
dbghelp.lib
|
||||
Wldap32.lib
|
||||
Normaliz.lib
|
||||
Bcrypt.lib
|
||||
version.lib
|
||||
)
|
||||
|
||||
target_precompile_headers(
|
||||
NorthstarDLL
|
||||
PRIVATE
|
||||
pch.h
|
||||
)
|
||||
|
||||
target_compile_definitions(
|
||||
NorthstarDLL
|
||||
PRIVATE UNICODE
|
||||
_UNICODE
|
||||
CURL_STATICLIB
|
||||
)
|
||||
|
||||
set_target_properties(
|
||||
NorthstarDLL
|
||||
PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${NS_BINARY_DIR}
|
||||
OUTPUT_NAME Northstar
|
||||
LINK_FLAGS "/MANIFEST:NO /DEBUG"
|
||||
)
|
|
@ -0,0 +1,4 @@
|
|||
LIBRARY dedicated
|
||||
|
||||
EXPORTS
|
||||
InitialiseNorthstar @1
|
|
@ -10,11 +10,7 @@
|
|||
|
||||
AUTOHOOK_INIT()
|
||||
|
||||
extern "C"
|
||||
{
|
||||
// should be called only in LoadSampleMetadata_Hook
|
||||
extern void* __fastcall Audio_GetParentEvent();
|
||||
}
|
||||
static const char* pszAudioEventName;
|
||||
|
||||
ConVar* Cvar_mileslog_enable;
|
||||
ConVar* Cvar_ns_print_played_sounds;
|
||||
|
@ -366,32 +362,16 @@ bool ShouldPlayAudioEvent(const char* eventName, const std::shared_ptr<EventOver
|
|||
return true; // good to go
|
||||
}
|
||||
|
||||
// forward declare
|
||||
bool __declspec(noinline) __fastcall LoadSampleMetadata_Internal(
|
||||
uintptr_t parentEvent, void* sample, void* audioBuffer, unsigned int audioBufferLength, int audioType);
|
||||
|
||||
// DO NOT TOUCH THIS FUNCTION
|
||||
// The actual logic of it in a separate function (forcefully not inlined) to preserve the r12 register, which holds the event pointer.
|
||||
// clang-format off
|
||||
AUTOHOOK(LoadSampleMetadata, mileswin64.dll + 0xF110,
|
||||
bool, __fastcall, (void* sample, void* audioBuffer, unsigned int audioBufferLength, int audioType))
|
||||
// clang-format on
|
||||
{
|
||||
uintptr_t parentEvent = (uintptr_t)Audio_GetParentEvent();
|
||||
|
||||
// Raw source, used for voice data only
|
||||
if (audioType == 0)
|
||||
return LoadSampleMetadata(sample, audioBuffer, audioBufferLength, audioType);
|
||||
|
||||
return LoadSampleMetadata_Internal(parentEvent, sample, audioBuffer, audioBufferLength, audioType);
|
||||
}
|
||||
|
||||
// DO NOT INLINE THIS FUNCTION
|
||||
// See comment below.
|
||||
bool __declspec(noinline) __fastcall LoadSampleMetadata_Internal(
|
||||
uintptr_t parentEvent, void* sample, void* audioBuffer, unsigned int audioBufferLength, int audioType)
|
||||
{
|
||||
char* eventName = (char*)parentEvent + 0x110;
|
||||
const char* eventName = pszAudioEventName;
|
||||
|
||||
if (Cvar_ns_print_played_sounds->GetInt() > 0)
|
||||
spdlog::info("[AUDIO] Playing event {}", eventName);
|
||||
|
@ -465,7 +445,7 @@ bool __declspec(noinline) __fastcall LoadSampleMetadata_Internal(
|
|||
else
|
||||
{
|
||||
data = dat->second.get();
|
||||
dataLength = dat->first;
|
||||
dataLength = (unsigned int)dat->first;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -490,6 +470,15 @@ bool __declspec(noinline) __fastcall LoadSampleMetadata_Internal(
|
|||
return res;
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
AUTOHOOK(sub_1800294C0, mileswin64.dll + 0x294C0,
|
||||
void*, __fastcall, (void* a1, void* a2))
|
||||
// clang-format on
|
||||
{
|
||||
pszAudioEventName = reinterpret_cast<const char*>((*((__int64*)a2 + 6)));
|
||||
return sub_1800294C0(a1, a2);
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
AUTOHOOK(MilesLog, client.dll + 0x57DAD0,
|
||||
void, __fastcall, (int level, const char* string))
|
|
@ -14,11 +14,11 @@ enum class AudioSelectionStrategy
|
|||
|
||||
class EventOverrideData
|
||||
{
|
||||
public:
|
||||
public:
|
||||
EventOverrideData(const std::string&, const fs::path&);
|
||||
EventOverrideData();
|
||||
|
||||
public:
|
||||
public:
|
||||
bool LoadedSuccessfully = false;
|
||||
|
||||
std::vector<std::string> EventIds = {};
|
||||
|
@ -34,7 +34,7 @@ class EventOverrideData
|
|||
|
||||
class CustomAudioManager
|
||||
{
|
||||
public:
|
||||
public:
|
||||
bool TryLoadAudioOverride(const fs::path&);
|
||||
void ClearAudioOverrides();
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
#include "toolframework/itoolentity.h"
|
||||
|
||||
inline IClientTools* g_pClientTools = nullptr;
|
|
@ -1,6 +1,7 @@
|
|||
#include "masterserver/masterserver.h"
|
||||
#include "core/convar/convar.h"
|
||||
#include "client/r2client.h"
|
||||
#include "core/vanilla.h"
|
||||
|
||||
AUTOHOOK_INIT()
|
||||
|
||||
|
@ -16,6 +17,14 @@ AUTOHOOK(AuthWithStryder, engine.dll + 0x1843A0,
|
|||
void, __fastcall, (void* a1))
|
||||
// clang-format on
|
||||
{
|
||||
// don't attempt to do Atlas auth if we are in vanilla compatibility mode
|
||||
// this prevents users from joining untrustworthy servers (unless they use a concommand or something)
|
||||
if (g_pVanillaCompatibility->GetVanillaCompatibility())
|
||||
{
|
||||
AuthWithStryder(a1);
|
||||
return;
|
||||
}
|
||||
|
||||
// game will call this forever, until it gets a valid auth key
|
||||
// so, we need to manually invalidate our key until we're authed with northstar, then we'll allow game to auth with stryder
|
||||
if (!g_pMasterServerManager->m_bOriginAuthWithMasterServerDone && Cvar_ns_has_agreed_to_send_token->GetInt() != DISAGREED_TO_SEND_TOKEN)
|
||||
|
@ -23,10 +32,10 @@ void, __fastcall, (void* a1))
|
|||
// if player has agreed to send token and we aren't already authing, try to auth
|
||||
if (Cvar_ns_has_agreed_to_send_token->GetInt() == AGREED_TO_SEND_TOKEN &&
|
||||
!g_pMasterServerManager->m_bOriginAuthWithMasterServerInProgress)
|
||||
g_pMasterServerManager->AuthenticateOriginWithMasterServer(R2::g_pLocalPlayerUserID, R2::g_pLocalPlayerOriginToken);
|
||||
g_pMasterServerManager->AuthenticateOriginWithMasterServer(g_pLocalPlayerUserID, g_pLocalPlayerOriginToken);
|
||||
|
||||
// invalidate key so auth will fail
|
||||
*R2::g_pLocalPlayerOriginToken = 0;
|
||||
*g_pLocalPlayerOriginToken = 0;
|
||||
}
|
||||
|
||||
AuthWithStryder(a1);
|
||||
|
@ -39,7 +48,7 @@ AUTOHOOK(Auth3PToken, engine.dll + 0x183760,
|
|||
char*, __fastcall, ())
|
||||
// clang-format on
|
||||
{
|
||||
if (g_pMasterServerManager->m_sOwnClientAuthToken[0])
|
||||
if (!g_pVanillaCompatibility->GetVanillaCompatibility() && g_pMasterServerManager->m_sOwnClientAuthToken[0])
|
||||
{
|
||||
memset(p3PToken, 0x0, 1024);
|
||||
strcpy(p3PToken, "Protocol 3: Protect the Pilot");
|
|
@ -1,6 +1,9 @@
|
|||
#include "debugoverlay.h"
|
||||
|
||||
#include "dedicated/dedicated.h"
|
||||
#include "core/convar/cvar.h"
|
||||
#include "core/math/vector.h"
|
||||
#include "server/ai_helper.h"
|
||||
|
||||
AUTOHOOK_INIT()
|
||||
|
||||
|
@ -122,48 +125,13 @@ struct OverlaySphere_t : public OverlayBase_t
|
|||
bool m_bWireframe;
|
||||
};
|
||||
|
||||
typedef bool (*OverlayBase_t__IsDeadType)(OverlayBase_t* a1);
|
||||
static OverlayBase_t__IsDeadType OverlayBase_t__IsDead;
|
||||
typedef void (*OverlayBase_t__DestroyOverlayType)(OverlayBase_t* a1);
|
||||
static OverlayBase_t__DestroyOverlayType OverlayBase_t__DestroyOverlay;
|
||||
static bool (*OverlayBase_t__IsDead)(OverlayBase_t* a1);
|
||||
static void (*OverlayBase_t__DestroyOverlay)(OverlayBase_t* a1);
|
||||
|
||||
static ConVar* Cvar_enable_debug_overlays;
|
||||
|
||||
LPCRITICAL_SECTION s_OverlayMutex;
|
||||
|
||||
// Render Line
|
||||
typedef void (*RenderLineType)(const Vector3& v1, const Vector3& v2, Color c, bool bZBuffer);
|
||||
static RenderLineType RenderLine;
|
||||
|
||||
// Render box
|
||||
typedef void (*RenderBoxType)(
|
||||
const Vector3& vOrigin, const QAngle& angles, const Vector3& vMins, const Vector3& vMaxs, Color c, bool bZBuffer, bool bInsideOut);
|
||||
static RenderBoxType RenderBox;
|
||||
|
||||
// Render wireframe box
|
||||
static RenderBoxType RenderWireframeBox;
|
||||
|
||||
// Render swept box
|
||||
typedef void (*RenderWireframeSweptBoxType)(
|
||||
const Vector3& vStart, const Vector3& vEnd, const QAngle& angles, const Vector3& vMins, const Vector3& vMaxs, Color c, bool bZBuffer);
|
||||
RenderWireframeSweptBoxType RenderWireframeSweptBox;
|
||||
|
||||
// Render Triangle
|
||||
typedef void (*RenderTriangleType)(const Vector3& p1, const Vector3& p2, const Vector3& p3, Color c, bool bZBuffer);
|
||||
static RenderTriangleType RenderTriangle;
|
||||
|
||||
// Render Axis
|
||||
typedef void (*RenderAxisType)(const Vector3& vOrigin, float flScale, bool bZBuffer);
|
||||
static RenderAxisType RenderAxis;
|
||||
|
||||
// I dont know
|
||||
typedef void (*RenderUnknownType)(const Vector3& vUnk, float flUnk, bool bUnk);
|
||||
static RenderUnknownType RenderUnknown;
|
||||
|
||||
// Render Sphere
|
||||
typedef void (*RenderSphereType)(const Vector3& vCenter, float flRadius, int nTheta, int nPhi, Color c, bool bZBuffer);
|
||||
static RenderSphereType RenderSphere;
|
||||
|
||||
OverlayBase_t** s_pOverlays;
|
||||
|
||||
int* g_nRenderTickCount;
|
||||
|
@ -306,7 +274,10 @@ void, __fastcall, (bool bRender))
|
|||
|
||||
if (bShouldDraw && bRender && (Cvar_enable_debug_overlays->GetBool() || pCurrOverlay->m_Type == OVERLAY_SMARTAMMO))
|
||||
{
|
||||
DrawOverlay(pCurrOverlay);
|
||||
// call the new function, not the original
|
||||
// note: if there is a beter way to call the hooked version of an
|
||||
// autohook func then that would be better than this
|
||||
__autohookfuncDrawOverlay(pCurrOverlay);
|
||||
}
|
||||
|
||||
pPrevOverlay = pCurrOverlay;
|
||||
|
@ -314,6 +285,11 @@ void, __fastcall, (bool bRender))
|
|||
}
|
||||
}
|
||||
|
||||
if (bRender && Cvar_enable_debug_overlays->GetBool())
|
||||
{
|
||||
g_pAIHelper->DrawNavmeshPolys();
|
||||
}
|
||||
|
||||
LeaveCriticalSection(s_OverlayMutex);
|
||||
}
|
||||
|
||||
|
@ -321,17 +297,17 @@ ON_DLL_LOAD_CLIENT_RELIESON("engine.dll", DebugOverlay, ConVar, (CModule module)
|
|||
{
|
||||
AUTOHOOK_DISPATCH()
|
||||
|
||||
OverlayBase_t__IsDead = module.Offset(0xACAC0).RCast<OverlayBase_t__IsDeadType>();
|
||||
OverlayBase_t__DestroyOverlay = module.Offset(0xAB680).RCast<OverlayBase_t__DestroyOverlayType>();
|
||||
OverlayBase_t__IsDead = module.Offset(0xACAC0).RCast<decltype(OverlayBase_t__IsDead)>();
|
||||
OverlayBase_t__DestroyOverlay = module.Offset(0xAB680).RCast<decltype(OverlayBase_t__DestroyOverlay)>();
|
||||
|
||||
RenderLine = module.Offset(0x192A70).RCast<RenderLineType>();
|
||||
RenderBox = module.Offset(0x192520).RCast<RenderBoxType>();
|
||||
RenderWireframeBox = module.Offset(0x193DA0).RCast<RenderBoxType>();
|
||||
RenderWireframeSweptBox = module.Offset(0x1945A0).RCast<RenderWireframeSweptBoxType>();
|
||||
RenderTriangle = module.Offset(0x193940).RCast<RenderTriangleType>();
|
||||
RenderAxis = module.Offset(0x1924D0).RCast<RenderAxisType>();
|
||||
RenderSphere = module.Offset(0x194170).RCast<RenderSphereType>();
|
||||
RenderUnknown = module.Offset(0x1924E0).RCast<RenderUnknownType>();
|
||||
RenderLine = module.Offset(0x192A70).RCast<decltype(RenderLine)>();
|
||||
RenderBox = module.Offset(0x192520).RCast<decltype(RenderBox)>();
|
||||
RenderWireframeBox = module.Offset(0x193DA0).RCast<decltype(RenderWireframeBox)>();
|
||||
RenderWireframeSweptBox = module.Offset(0x1945A0).RCast<decltype(RenderWireframeSweptBox)>();
|
||||
RenderTriangle = module.Offset(0x193940).RCast<decltype(RenderTriangle)>();
|
||||
RenderAxis = module.Offset(0x1924D0).RCast<decltype(RenderAxis)>();
|
||||
RenderSphere = module.Offset(0x194170).RCast<decltype(RenderSphere)>();
|
||||
RenderUnknown = module.Offset(0x1924E0).RCast<decltype(RenderUnknown)>();
|
||||
|
||||
s_OverlayMutex = module.Offset(0x10DB0A38).RCast<LPCRITICAL_SECTION>();
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
#pragma once
|
||||
|
||||
// Render Line
|
||||
inline void (*RenderLine)(const Vector3& v1, const Vector3& v2, Color c, bool bZBuffer);
|
||||
|
||||
// Render box
|
||||
inline void (*RenderBox)(
|
||||
const Vector3& vOrigin, const QAngle& angles, const Vector3& vMins, const Vector3& vMaxs, Color c, bool bZBuffer, bool bInsideOut);
|
||||
|
||||
// Render wireframe box
|
||||
inline void (*RenderWireframeBox)(
|
||||
const Vector3& vOrigin, const QAngle& angles, const Vector3& vMins, const Vector3& vMaxs, Color c, bool bZBuffer, bool bInsideOut);
|
||||
|
||||
// Render swept box
|
||||
inline void (*RenderWireframeSweptBox)(
|
||||
const Vector3& vStart, const Vector3& vEnd, const QAngle& angles, const Vector3& vMins, const Vector3& vMaxs, Color c, bool bZBuffer);
|
||||
|
||||
// Render Triangle
|
||||
inline void (*RenderTriangle)(const Vector3& p1, const Vector3& p2, const Vector3& p3, Color c, bool bZBuffer);
|
||||
|
||||
// Render Axis
|
||||
inline void (*RenderAxis)(const Vector3& vOrigin, float flScale, bool bZBuffer);
|
||||
|
||||
// I dont know
|
||||
inline void (*RenderUnknown)(const Vector3& vUnk, float flUnk, bool bUnk);
|
||||
|
||||
// Render Sphere
|
||||
inline void (*RenderSphere)(const Vector3& vCenter, float flRadius, int nTheta, int nPhi, Color c, bool bZBuffer);
|
|
@ -11,15 +11,15 @@ ON_DLL_LOAD_CLIENT_RELIESON("client.dll", ClientDemoFixes, ConVar, (CModule modu
|
|||
{
|
||||
// change default values of demo cvars to enable them by default, but not autorecord
|
||||
// this is before Host_Init, the setvalue calls here will get overwritten by custom cfgs/launch options
|
||||
ConVar* Cvar_demo_enableDemos = R2::g_pCVar->FindVar("demo_enabledemos");
|
||||
ConVar* Cvar_demo_enableDemos = g_pCVar->FindVar("demo_enabledemos");
|
||||
Cvar_demo_enableDemos->m_pszDefaultValue = "1";
|
||||
Cvar_demo_enableDemos->SetValue(true);
|
||||
|
||||
ConVar* Cvar_demo_writeLocalFile = R2::g_pCVar->FindVar("demo_writeLocalFile");
|
||||
ConVar* Cvar_demo_writeLocalFile = g_pCVar->FindVar("demo_writeLocalFile");
|
||||
Cvar_demo_writeLocalFile->m_pszDefaultValue = "1";
|
||||
Cvar_demo_writeLocalFile->SetValue(true);
|
||||
|
||||
ConVar* Cvar_demo_autoRecord = R2::g_pCVar->FindVar("demo_autoRecord");
|
||||
ConVar* Cvar_demo_autoRecord = g_pCVar->FindVar("demo_autoRecord");
|
||||
Cvar_demo_autoRecord->m_pszDefaultValue = "0";
|
||||
Cvar_demo_autoRecord->SetValue(false);
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
#include "toolframework/itoolentity.h"
|
||||
#include "client/cdll_client_int.h"
|
||||
#include "core/tier1.h"
|
||||
|
||||
class CClientTools : public IClientTools
|
||||
{
|
||||
public:
|
||||
};
|
||||
|
||||
ON_DLL_LOAD("client.dll", ClientClientTools, (CModule module))
|
||||
{
|
||||
g_pClientTools = Sys_GetFactoryPtr("client.dll", "VCLIENTTOOLS001").RCast<IClientTools*>();
|
||||
}
|
|
@ -57,7 +57,7 @@ char*, __fastcall, ())
|
|||
bool& canOriginDictateLang = *(bool*)((char*)tier0Handle + 0xA9A90);
|
||||
|
||||
const char* forcedLanguage;
|
||||
if (Tier0::CommandLine()->CheckParm("-language", &forcedLanguage))
|
||||
if (CommandLine()->CheckParm("-language", &forcedLanguage))
|
||||
{
|
||||
if (!CheckLangAudioExists((char*)forcedLanguage))
|
||||
{
|
|
@ -4,13 +4,13 @@ class vgui_BaseRichText_vtable;
|
|||
|
||||
class vgui_BaseRichText
|
||||
{
|
||||
public:
|
||||
public:
|
||||
vgui_BaseRichText_vtable* vtable;
|
||||
};
|
||||
|
||||
class vgui_BaseRichText_vtable
|
||||
{
|
||||
public:
|
||||
public:
|
||||
char unknown1[1880];
|
||||
|
||||
void(__fastcall* InsertChar)(vgui_BaseRichText* self, wchar_t ch);
|
||||
|
@ -49,7 +49,7 @@ class vgui_BaseRichText_vtable
|
|||
|
||||
class CGameSettings
|
||||
{
|
||||
public:
|
||||
public:
|
||||
char unknown1[92];
|
||||
int isChatEnabled;
|
||||
};
|
||||
|
@ -58,7 +58,7 @@ class CGameSettings
|
|||
// have their value at the same offset
|
||||
class CGameFloatVar
|
||||
{
|
||||
public:
|
||||
public:
|
||||
char unknown1[88];
|
||||
float value;
|
||||
};
|
||||
|
@ -101,7 +101,7 @@ Color lightColors[8] = {
|
|||
|
||||
class AnsiEscapeParser
|
||||
{
|
||||
public:
|
||||
public:
|
||||
explicit AnsiEscapeParser(LocalChatWriter* writer) : m_writer(writer) {}
|
||||
|
||||
void HandleVal(unsigned long val)
|
||||
|
@ -129,7 +129,7 @@ class AnsiEscapeParser
|
|||
}
|
||||
}
|
||||
|
||||
private:
|
||||
private:
|
||||
enum class Next
|
||||
{
|
||||
ControlType,
|
|
@ -5,7 +5,7 @@ class vgui_BaseRichText;
|
|||
|
||||
class CHudChat
|
||||
{
|
||||
public:
|
||||
public:
|
||||
static CHudChat** allHuds;
|
||||
|
||||
char unknown1[720];
|
||||
|
@ -29,7 +29,7 @@ class CHudChat
|
|||
|
||||
class LocalChatWriter
|
||||
{
|
||||
public:
|
||||
public:
|
||||
enum Context
|
||||
{
|
||||
NetworkContext = 0,
|
||||
|
@ -56,7 +56,7 @@ class LocalChatWriter
|
|||
void InsertColorChange(Color color);
|
||||
void InsertSwatchColorChange(SwatchColor color);
|
||||
|
||||
private:
|
||||
private:
|
||||
Context m_context;
|
||||
|
||||
const char* ApplyAnsiEscape(const char* escape);
|
|
@ -1,14 +1,8 @@
|
|||
#include "r2client.h"
|
||||
|
||||
using namespace R2;
|
||||
|
||||
// use the R2 namespace for game funcs
|
||||
namespace R2
|
||||
{
|
||||
char* g_pLocalPlayerUserID;
|
||||
char* g_pLocalPlayerOriginToken;
|
||||
GetBaseLocalClientType GetBaseLocalClient;
|
||||
} // namespace R2
|
||||
char* g_pLocalPlayerUserID;
|
||||
char* g_pLocalPlayerOriginToken;
|
||||
GetBaseLocalClientType GetBaseLocalClient;
|
||||
|
||||
ON_DLL_LOAD("engine.dll", R2EngineClient, (CModule module))
|
||||
{
|
|
@ -0,0 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
extern char* g_pLocalPlayerUserID;
|
||||
extern char* g_pLocalPlayerOriginToken;
|
||||
|
||||
typedef void* (*GetBaseLocalClientType)();
|
||||
extern GetBaseLocalClientType GetBaseLocalClient;
|
|
@ -22,7 +22,7 @@ void,, (bool a1, const char* fmt, ...))
|
|||
// not doing this gets our client in a pretty weird state so we need to shut it down manually here
|
||||
|
||||
// don't call Cbuf_Execute because we don't need this called immediately
|
||||
R2::Cbuf_AddText(R2::Cbuf_GetCurrentPlayer(), "disconnect", R2::cmd_source_t::kCommandSrcCode);
|
||||
Cbuf_AddText(Cbuf_GetCurrentPlayer(), "disconnect", cmd_source_t::kCommandSrcCode);
|
||||
}
|
||||
|
||||
return COM_ExplainDisconnection(a1, "%s", buf);
|
|
@ -0,0 +1,46 @@
|
|||
if(NOT libcurl_FOUND)
|
||||
check_init_submodule(${PROJECT_SOURCE_DIR}/primedev/thirdparty/libcurl)
|
||||
|
||||
set(BUILD_SHARED_LIBS
|
||||
OFF
|
||||
CACHE BOOL "Build shared libraries"
|
||||
)
|
||||
set(BUILD_CURL_EXE
|
||||
OFF
|
||||
CACHE BOOL "Build curl EXE"
|
||||
)
|
||||
set(HTTP_ONLY
|
||||
ON
|
||||
CACHE BOOL "Only build HTTP and HTTPS"
|
||||
)
|
||||
set(CURL_ENABLE_SSL
|
||||
ON
|
||||
CACHE BOOL "Enable SSL support"
|
||||
)
|
||||
set(CURL_USE_OPENSSL
|
||||
OFF
|
||||
CACHE BOOL "Disable OpenSSL"
|
||||
)
|
||||
set(CURL_USE_LIBSSH2
|
||||
OFF
|
||||
CACHE BOOL "Disable libSSH2"
|
||||
)
|
||||
set(CURL_USE_SCHANNEL
|
||||
ON
|
||||
CACHE BOOL "Enable Secure Channel"
|
||||
)
|
||||
set(CURL_CA_BUNDLE
|
||||
"none"
|
||||
CACHE STRING "Disable CA Bundle"
|
||||
)
|
||||
set(CURL_CA_PATH
|
||||
"none"
|
||||
CACHE STRING "Disable CA Path"
|
||||
)
|
||||
|
||||
add_subdirectory(${PROJECT_SOURCE_DIR}/primedev/thirdparty/libcurl libcurl)
|
||||
set(libcurl_FOUND
|
||||
1
|
||||
PARENT_SCOPE
|
||||
)
|
||||
endif()
|
|
@ -0,0 +1,6 @@
|
|||
if(NOT minhook_FOUND)
|
||||
check_init_submodule(${PROJECT_SOURCE_DIR}/primedev/thirdparty/minhook)
|
||||
|
||||
add_subdirectory(${PROJECT_SOURCE_DIR}/primedev/thirdparty/minhook minhook)
|
||||
set(minhook_FOUND 1)
|
||||
endif()
|
|
@ -0,0 +1,43 @@
|
|||
if(NOT minizip_FOUND)
|
||||
|
||||
# zlib 1.3.1 had a cmake change that broke stuff, so this branch on our fork reverts that one commit :)
|
||||
set(ZLIB_TAG "fix-things")
|
||||
set(ZLIB_REPOSITORY "https://github.com/R2Northstar/zlib")
|
||||
|
||||
check_init_submodule(${PROJECT_SOURCE_DIR}/primedev/thirdparty/minizip)
|
||||
|
||||
set(MZ_ZLIB
|
||||
ON
|
||||
CACHE BOOL "Enable ZLIB compression, needed for DEFLATE"
|
||||
)
|
||||
set(MZ_BZIP2
|
||||
OFF
|
||||
CACHE BOOL "Disable BZIP2 compression"
|
||||
)
|
||||
set(MZ_LZMA
|
||||
OFF
|
||||
CACHE BOOL "Disable LZMA & XZ compression"
|
||||
)
|
||||
set(MZ_PKCRYPT
|
||||
OFF
|
||||
CACHE BOOL "Disable PKWARE traditional encryption"
|
||||
)
|
||||
set(MZ_WZAES
|
||||
OFF
|
||||
CACHE BOOL "Disable WinZIP AES encryption"
|
||||
)
|
||||
set(MZ_ZSTD
|
||||
OFF
|
||||
CACHE BOOL "Disable ZSTD compression"
|
||||
)
|
||||
set(MZ_SIGNING
|
||||
OFF
|
||||
CACHE BOOL "Disable zip signing support"
|
||||
)
|
||||
|
||||
add_subdirectory(${PROJECT_SOURCE_DIR}/primedev/thirdparty/minizip minizip)
|
||||
set(minizip_FOUND
|
||||
1
|
||||
PARENT_SCOPE
|
||||
)
|
||||
endif()
|
|
@ -0,0 +1,9 @@
|
|||
if(NOT silver-bun_FOUND)
|
||||
check_init_submodule(${PROJECT_SOURCE_DIR}/primedev/thirdparty/silver-bun)
|
||||
|
||||
add_subdirectory(${PROJECT_SOURCE_DIR}/primedev/thirdparty/silver-bun silver-bun)
|
||||
set(silver-bun_FOUND
|
||||
1
|
||||
PARENT_SCOPE
|
||||
)
|
||||
endif()
|
|
@ -0,0 +1,6 @@
|
|||
if(NOT spdlog_FOUND)
|
||||
check_init_submodule(${PROJECT_SOURCE_DIR}/primedev/thirdparty/spdlog)
|
||||
|
||||
add_subdirectory(${PROJECT_SOURCE_DIR}/primedev/thirdparty/spdlog spdlog)
|
||||
set(spdlog_FOUND 1)
|
||||
endif()
|
|
@ -0,0 +1,44 @@
|
|||
# Check if a dependency exist before trying to init git submodules
|
||||
function(check_init_submodule path)
|
||||
file(
|
||||
GLOB
|
||||
DIR_CONTENT
|
||||
"${path}/*"
|
||||
)
|
||||
list(
|
||||
LENGTH
|
||||
DIR_CONTENT
|
||||
CONTENT_COUNT
|
||||
)
|
||||
if(CONTENT_COUNT
|
||||
EQUAL
|
||||
0
|
||||
)
|
||||
if(NOT
|
||||
EXISTS
|
||||
"${PROJECT_SOURCE_DIR}/.git"
|
||||
)
|
||||
message(FATAL_ERROR "Failed to find third party dependency in '${path}'")
|
||||
endif()
|
||||
|
||||
find_package(Git QUIET)
|
||||
if(NOT Git_FOUND)
|
||||
message(FATAL_ERROR "Failed to find Git, third party dependency could not be setup at `${path}")
|
||||
endif()
|
||||
|
||||
message(STATUS "Setting up dependencies as git submodules")
|
||||
execute_process(
|
||||
COMMAND ${GIT_EXECUTABLE} submodule update --init --recursive
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
RESULT_VARIABLE GIT_SUBMOD_RESULT
|
||||
)
|
||||
|
||||
if(NOT
|
||||
GIT_SUBMOD_RESULT
|
||||
EQUAL
|
||||
"0"
|
||||
)
|
||||
message(FATAL_ERROR "Initializing Git submodules failed with ${GIT_SUBMOD_RESULT}")
|
||||
endif()
|
||||
endif()
|
||||
endfunction()
|
|
@ -15,15 +15,15 @@ void InitialiseNorthstarPrefix()
|
|||
std::string cla = std::string(clachar);
|
||||
if (strncmp(cla.substr(9, 1).c_str(), "\"", 1))
|
||||
{
|
||||
int space = cla.find(" ");
|
||||
size_t space = cla.find(" ");
|
||||
std::string dirname = cla.substr(9, space - 9);
|
||||
NORTHSTAR_FOLDER_PREFIX = dirname;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string quote = "\"";
|
||||
int quote1 = cla.find(quote);
|
||||
int quote2 = (cla.substr(quote1 + 1)).find(quote);
|
||||
size_t quote1 = cla.find(quote);
|
||||
size_t quote2 = (cla.substr(quote1 + 1)).find(quote);
|
||||
std::string dirname = cla.substr(quote1 + 1, quote2);
|
||||
NORTHSTAR_FOLDER_PREFIX = dirname;
|
||||
}
|
|
@ -2,9 +2,6 @@
|
|||
#include "shared/misccommands.h"
|
||||
#include "engine/r2engine.h"
|
||||
|
||||
#include "plugins/pluginbackend.h"
|
||||
#include "plugins/plugin_abi.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -145,13 +142,11 @@ void RegisterConCommand(
|
|||
ConCommand* newCommand = new ConCommand;
|
||||
ConCommandConstructor(newCommand, name, callback, helpString, flags, nullptr);
|
||||
newCommand->m_pCompletionCallback = completionCallback;
|
||||
newCommand->m_nCallbackFlags |= 0x3; // seems to be correct?; derived from client.dll + 0x737267
|
||||
}
|
||||
|
||||
ON_DLL_LOAD("engine.dll", ConCommand, (CModule module))
|
||||
{
|
||||
ConCommandConstructor = module.Offset(0x415F60).RCast<ConCommandConstructorType>();
|
||||
AddMiscConCommands();
|
||||
|
||||
g_pPluginCommunicationhandler->m_sEngineData.ConCommandConstructor =
|
||||
reinterpret_cast<PluginConCommandConstructorType>(ConCommandConstructor);
|
||||
}
|
|
@ -4,7 +4,7 @@
|
|||
class ConCommandBase;
|
||||
class IConCommandBaseAccessor
|
||||
{
|
||||
public:
|
||||
public:
|
||||
// Flags is a combination of FCVAR flags in cvar.h.
|
||||
// hOut is filled in with a handle to the variable.
|
||||
virtual bool RegisterConCommandBase(ConCommandBase* pVar) = 0;
|
||||
|
@ -12,7 +12,7 @@ class IConCommandBaseAccessor
|
|||
|
||||
class CCommand
|
||||
{
|
||||
public:
|
||||
public:
|
||||
CCommand() = delete;
|
||||
|
||||
int64_t ArgC() const;
|
||||
|
@ -24,7 +24,7 @@ class CCommand
|
|||
|
||||
static int MaxCommandLength();
|
||||
|
||||
private:
|
||||
private:
|
||||
enum
|
||||
{
|
||||
COMMAND_MAX_ARGC = 64,
|
||||
|
@ -88,7 +88,7 @@ typedef int (*FnCommandCompletionCallback)(const char* partial, char commands[CO
|
|||
// From r5reloaded
|
||||
class ConCommandBase
|
||||
{
|
||||
public:
|
||||
public:
|
||||
bool HasFlags(int nFlags);
|
||||
void AddFlags(int nFlags);
|
||||
void RemoveFlags(int nFlags);
|
||||
|
@ -120,7 +120,7 @@ class ConCommand : public ConCommandBase
|
|||
{
|
||||
friend class CCVar;
|
||||
|
||||
public:
|
||||
public:
|
||||
ConCommand(void) {}; // !TODO: Rebuild engine constructor in SDK instead.
|
||||
ConCommand(const char* szName, const char* szHelpString, int nFlags, void* pCallback, void* pCommandCompletionCallback);
|
||||
void Init(void);
|
|
@ -3,9 +3,6 @@
|
|||
#include "convar.h"
|
||||
#include "core/sourceinterface.h"
|
||||
|
||||
#include "plugins/pluginbackend.h"
|
||||
#include "plugins/plugin_abi.h"
|
||||
|
||||
#include <float.h>
|
||||
|
||||
typedef void (*ConVarRegisterType)(
|
||||
|
@ -38,14 +35,8 @@ ON_DLL_LOAD("engine.dll", ConVar, (CModule module))
|
|||
g_pConVar_Vtable = module.Offset(0x67FD28);
|
||||
g_pIConVar_Vtable = module.Offset(0x67FDC8);
|
||||
|
||||
R2::g_pCVarInterface = new SourceInterface<CCvar>("vstdlib.dll", "VEngineCvar007");
|
||||
R2::g_pCVar = *R2::g_pCVarInterface;
|
||||
|
||||
g_pPluginCommunicationhandler->m_sEngineData.conVarMalloc = reinterpret_cast<PluginConVarMallocType>(conVarMalloc);
|
||||
g_pPluginCommunicationhandler->m_sEngineData.conVarRegister = reinterpret_cast<PluginConVarRegisterType>(conVarRegister);
|
||||
g_pPluginCommunicationhandler->m_sEngineData.ConVar_Vtable = reinterpret_cast<void*>(g_pConVar_Vtable);
|
||||
g_pPluginCommunicationhandler->m_sEngineData.IConVar_Vtable = reinterpret_cast<void*>(g_pIConVar_Vtable);
|
||||
g_pPluginCommunicationhandler->m_sEngineData.g_pCVar = reinterpret_cast<void*>(R2::g_pCVar);
|
||||
g_pCVarInterface = new SourceInterface<CCvar>("vstdlib.dll", "VEngineCvar007");
|
||||
g_pCVar = *g_pCVarInterface;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -372,6 +363,7 @@ void ConVar::SetValue(Color clValue)
|
|||
//-----------------------------------------------------------------------------
|
||||
void ConVar::ChangeStringValue(const char* pszTempVal, float flOldValue)
|
||||
{
|
||||
NOTE_UNUSED(flOldValue);
|
||||
assert(!(m_ConCommandBase.m_nFlags & FCVAR_NEVER_AS_STRING));
|
||||
|
||||
char* pszOldValue = (char*)_malloca(m_Value.m_iStringLength);
|
||||
|
@ -382,7 +374,7 @@ void ConVar::ChangeStringValue(const char* pszTempVal, float flOldValue)
|
|||
|
||||
if (pszTempVal)
|
||||
{
|
||||
int len = strlen(pszTempVal) + 1;
|
||||
size_t len = strlen(pszTempVal) + 1;
|
||||
|
||||
if (len > m_Value.m_iStringLength)
|
||||
{
|
|
@ -124,7 +124,7 @@ typedef void (*FnChangeCallback_t)(ConVar* var, const char* pOldValue, float flO
|
|||
//-----------------------------------------------------------------------------
|
||||
class ConVar
|
||||
{
|
||||
public:
|
||||
public:
|
||||
ConVar(void) {};
|
||||
ConVar(const char* pszName, const char* pszDefaultValue, int nFlags, const char* pszHelpString);
|
||||
ConVar(
|
|
@ -22,9 +22,5 @@ std::unordered_map<std::string, ConCommandBase*> CCvar::DumpToMap()
|
|||
return allConVars;
|
||||
}
|
||||
|
||||
// use the R2 namespace for game funcs
|
||||
namespace R2
|
||||
{
|
||||
SourceInterface<CCvar>* g_pCVarInterface;
|
||||
CCvar* g_pCVar;
|
||||
} // namespace R2
|
||||
SourceInterface<CCvar>* g_pCVarInterface;
|
||||
CCvar* g_pCVar;
|
|
@ -13,7 +13,7 @@ class ConVar;
|
|||
//-----------------------------------------------------------------------------
|
||||
class CCVarIteratorInternal // Fully reversed table, just look at the virtual function table and rename the function.
|
||||
{
|
||||
public:
|
||||
public:
|
||||
virtual void SetFirst(void) = 0; // 0
|
||||
virtual void Next(void) = 0; // 1
|
||||
virtual bool IsValid(void) = 0; // 2
|
||||
|
@ -25,7 +25,7 @@ class CCVarIteratorInternal // Fully reversed table, just look at the virtual fu
|
|||
//-----------------------------------------------------------------------------
|
||||
class CCvar
|
||||
{
|
||||
public:
|
||||
public:
|
||||
M_VMETHOD(ConCommandBase*, FindCommandBase, 14, (const char* pszCommandName), (this, pszCommandName));
|
||||
M_VMETHOD(ConVar*, FindVar, 16, (const char* pszVarName), (this, pszVarName));
|
||||
M_VMETHOD(ConCommand*, FindCommand, 18, (const char* pszCommandName), (this, pszCommandName));
|
||||
|
@ -34,9 +34,5 @@ class CCvar
|
|||
std::unordered_map<std::string, ConCommandBase*> DumpToMap();
|
||||
};
|
||||
|
||||
// use the R2 namespace for game funcs
|
||||
namespace R2
|
||||
{
|
||||
extern SourceInterface<CCvar>* g_pCVarInterface;
|
||||
extern CCvar* g_pCVar;
|
||||
} // namespace R2
|
||||
extern SourceInterface<CCvar>* g_pCVarInterface;
|
||||
extern CCvar* g_pCVar;
|
|
@ -7,48 +7,42 @@
|
|||
|
||||
AUTOHOOK_INIT()
|
||||
|
||||
using namespace R2;
|
||||
|
||||
bool bReadingOriginalFile = false;
|
||||
std::string sCurrentModPath;
|
||||
|
||||
ConVar* Cvar_ns_fs_log_reads;
|
||||
|
||||
// use the R2 namespace for game funcs
|
||||
namespace R2
|
||||
SourceInterface<IFileSystem>* g_pFilesystem;
|
||||
|
||||
std::string ReadVPKFile(const char* path)
|
||||
{
|
||||
SourceInterface<IFileSystem>* g_pFilesystem;
|
||||
// read scripts.rson file, todo: check if this can be overwritten
|
||||
FileHandle_t fileHandle = (*g_pFilesystem)->m_vtable2->Open(&(*g_pFilesystem)->m_vtable2, path, "rb", "GAME", 0);
|
||||
|
||||
std::string ReadVPKFile(const char* path)
|
||||
std::stringstream fileStream;
|
||||
int bytesRead = 0;
|
||||
char data[4096];
|
||||
do
|
||||
{
|
||||
// read scripts.rson file, todo: check if this can be overwritten
|
||||
FileHandle_t fileHandle = (*g_pFilesystem)->m_vtable2->Open(&(*g_pFilesystem)->m_vtable2, path, "rb", "GAME", 0);
|
||||
bytesRead = (*g_pFilesystem)->m_vtable2->Read(&(*g_pFilesystem)->m_vtable2, data, (int)std::size(data), fileHandle);
|
||||
fileStream.write(data, bytesRead);
|
||||
} while (bytesRead == std::size(data));
|
||||
|
||||
std::stringstream fileStream;
|
||||
int bytesRead = 0;
|
||||
char data[4096];
|
||||
do
|
||||
{
|
||||
bytesRead = (*g_pFilesystem)->m_vtable2->Read(&(*g_pFilesystem)->m_vtable2, data, (int)std::size(data), fileHandle);
|
||||
fileStream.write(data, bytesRead);
|
||||
} while (bytesRead == std::size(data));
|
||||
(*g_pFilesystem)->m_vtable2->Close(*g_pFilesystem, fileHandle);
|
||||
|
||||
(*g_pFilesystem)->m_vtable2->Close(*g_pFilesystem, fileHandle);
|
||||
return fileStream.str();
|
||||
}
|
||||
|
||||
return fileStream.str();
|
||||
}
|
||||
std::string ReadVPKOriginalFile(const char* path)
|
||||
{
|
||||
// todo: should probably set search path to be g_pModName here also
|
||||
|
||||
std::string ReadVPKOriginalFile(const char* path)
|
||||
{
|
||||
// todo: should probably set search path to be g_pModName here also
|
||||
bReadingOriginalFile = true;
|
||||
std::string ret = ReadVPKFile(path);
|
||||
bReadingOriginalFile = false;
|
||||
|
||||
bReadingOriginalFile = true;
|
||||
std::string ret = ReadVPKFile(path);
|
||||
bReadingOriginalFile = false;
|
||||
|
||||
return ret;
|
||||
}
|
||||
} // namespace R2
|
||||
return ret;
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
HOOK(AddSearchPathHook, AddSearchPath,
|
||||
|
@ -175,7 +169,7 @@ ON_DLL_LOAD("filesystem_stdio.dll", Filesystem, (CModule module))
|
|||
{
|
||||
AUTOHOOK_DISPATCH()
|
||||
|
||||
R2::g_pFilesystem = new SourceInterface<IFileSystem>("filesystem_stdio.dll", "VFileSystem017");
|
||||
g_pFilesystem = new SourceInterface<IFileSystem>("filesystem_stdio.dll", "VFileSystem017");
|
||||
|
||||
AddSearchPathHook.Dispatch((LPVOID)(*g_pFilesystem)->m_vtable->AddSearchPath);
|
||||
ReadFromCacheHook.Dispatch((LPVOID)(*g_pFilesystem)->m_vtable->ReadFromCache);
|
|
@ -4,21 +4,6 @@
|
|||
// taken from ttf2sdk
|
||||
typedef void* FileHandle_t;
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
// clang-format off
|
||||
OFFSET_STRUCT(VPKFileEntry)
|
||||
{
|
||||
STRUCT_SIZE(0x44);
|
||||
FIELDS(0x0,
|
||||
char* directory;
|
||||
char* filename;
|
||||
char* extension;
|
||||
)
|
||||
};
|
||||
// clang-format on
|
||||
#pragma pack(pop)
|
||||
|
||||
struct VPKData;
|
||||
|
||||
enum SearchPathAdd_t
|
||||
|
@ -29,14 +14,14 @@ enum SearchPathAdd_t
|
|||
|
||||
class CSearchPath
|
||||
{
|
||||
public:
|
||||
public:
|
||||
unsigned char unknown[0x18];
|
||||
const char* debugPath;
|
||||
};
|
||||
|
||||
class IFileSystem
|
||||
{
|
||||
public:
|
||||
public:
|
||||
struct VTable
|
||||
{
|
||||
void* unknown[10];
|
||||
|
@ -63,11 +48,7 @@ class IFileSystem
|
|||
VTable2* m_vtable2;
|
||||
};
|
||||
|
||||
// use the R2 namespace for game funcs
|
||||
namespace R2
|
||||
{
|
||||
extern SourceInterface<IFileSystem>* g_pFilesystem;
|
||||
extern SourceInterface<IFileSystem>* g_pFilesystem;
|
||||
|
||||
std::string ReadVPKFile(const char* path);
|
||||
std::string ReadVPKOriginalFile(const char* path);
|
||||
} // namespace R2
|
||||
std::string ReadVPKFile(const char* path);
|
||||
std::string ReadVPKOriginalFile(const char* path);
|
|
@ -209,8 +209,8 @@ int, __fastcall, (char* pPath, void* unknownSingleton, int flags, void* pCallbac
|
|||
// dedicated only needs common, common_mp, common_sp, and sp_<map> rpaks
|
||||
// sp_<map> rpaks contain tutorial ghost data
|
||||
// sucks to have to load the entire rpak for that but sp was never meant to be done on dedi
|
||||
if (IsDedicatedServer() && (Tier0::CommandLine()->CheckParm("-nopakdedi") ||
|
||||
strncmp(&originalPath[0], "common", 6) && strncmp(&originalPath[0], "sp_", 3)))
|
||||
if (IsDedicatedServer() &&
|
||||
(CommandLine()->CheckParm("-nopakdedi") || strncmp(&originalPath[0], "common", 6) && strncmp(&originalPath[0], "sp_", 3)))
|
||||
{
|
||||
if (bNeedToFreePakName)
|
||||
delete[] pPath;
|
|
@ -17,11 +17,11 @@ struct LoadedPak
|
|||
|
||||
class PakLoadManager
|
||||
{
|
||||
private:
|
||||
private:
|
||||
std::map<int, LoadedPak> m_vLoadedPaks {};
|
||||
std::unordered_map<size_t, int> m_HashToPakHandle {};
|
||||
|
||||
public:
|
||||
public:
|
||||
int LoadPakAsync(const char* pPath, const ePakLoadSource nLoadSource);
|
||||
void UnloadPak(const int nPakHandle);
|
||||
void UnloadMapPaks();
|
|
@ -1,5 +1,5 @@
|
|||
#include "dedicated/dedicated.h"
|
||||
#include "plugins/pluginbackend.h"
|
||||
#include "plugins/pluginmanager.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <wchar.h>
|
||||
|
@ -10,6 +10,8 @@
|
|||
#include <filesystem>
|
||||
#include <Psapi.h>
|
||||
|
||||
#define XINPUT1_3_DLL "XInput1_3.dll"
|
||||
|
||||
AUTOHOOK_INIT()
|
||||
|
||||
// called from the ON_DLL_LOAD macros
|
||||
|
@ -75,7 +77,7 @@ void __fileAutohook::Dispatch()
|
|||
|
||||
void __fileAutohook::DispatchForModule(const char* pModuleName)
|
||||
{
|
||||
const int iModuleNameLen = strlen(pModuleName);
|
||||
const size_t iModuleNameLen = strlen(pModuleName);
|
||||
|
||||
for (__autohook* hook : hooks)
|
||||
if ((hook->iAddressResolutionMode == __autohook::OFFSET_STRING && !strncmp(pModuleName, hook->pAddrString, iModuleNameLen)) ||
|
||||
|
@ -85,14 +87,14 @@ void __fileAutohook::DispatchForModule(const char* pModuleName)
|
|||
|
||||
ManualHook::ManualHook(const char* funcName, LPVOID func) : pHookFunc(func), ppOrigFunc(nullptr)
|
||||
{
|
||||
const int iFuncNameStrlen = strlen(funcName);
|
||||
const size_t iFuncNameStrlen = strlen(funcName);
|
||||
pFuncName = new char[iFuncNameStrlen];
|
||||
memcpy(pFuncName, funcName, iFuncNameStrlen);
|
||||
}
|
||||
|
||||
ManualHook::ManualHook(const char* funcName, LPVOID* orig, LPVOID func) : pHookFunc(func), ppOrigFunc(orig)
|
||||
{
|
||||
const int iFuncNameStrlen = strlen(funcName);
|
||||
const size_t iFuncNameStrlen = strlen(funcName);
|
||||
pFuncName = new char[iFuncNameStrlen];
|
||||
memcpy(pFuncName, funcName, iFuncNameStrlen);
|
||||
}
|
||||
|
@ -139,7 +141,7 @@ uintptr_t ParseDLLOffsetString(const char* pAddrString)
|
|||
uintptr_t iOffset = 0;
|
||||
|
||||
int iOffsetBegin = iDllNameEnd;
|
||||
int iOffsetEnd = strlen(pAddrString);
|
||||
size_t iOffsetEnd = strlen(pAddrString);
|
||||
|
||||
// seek until we hit the start of the number offset
|
||||
for (; !(pAddrString[iOffsetBegin] >= '0' && pAddrString[iOffsetBegin] <= '9') && pAddrString[iOffsetBegin]; iOffsetBegin++)
|
||||
|
@ -393,8 +395,11 @@ HMODULE, WINAPI, (LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags))
|
|||
{
|
||||
HMODULE moduleAddress;
|
||||
|
||||
LPCSTR lpLibFileNameEnd = lpLibFileName + strlen(lpLibFileName);
|
||||
LPCSTR lpLibName = lpLibFileNameEnd - strlen(XINPUT1_3_DLL);
|
||||
|
||||
// replace xinput dll with one that has ASLR
|
||||
if (!strncmp(lpLibFileName, "XInput1_3.dll", 14))
|
||||
if (lpLibFileName <= lpLibName && !strncmp(lpLibName, XINPUT1_3_DLL, strlen(XINPUT1_3_DLL) + 1))
|
||||
{
|
||||
moduleAddress = _LoadLibraryExA("XInput9_1_0.dll", hFile, dwFlags);
|
||||
|
||||
|
@ -412,7 +417,7 @@ HMODULE, WINAPI, (LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags))
|
|||
if (moduleAddress)
|
||||
{
|
||||
CallLoadLibraryACallbacks(lpLibFileName, moduleAddress);
|
||||
InformPluginsDLLLoad(fs::path(lpLibFileName), moduleAddress);
|
||||
g_pPluginManager->InformDllLoad(moduleAddress, fs::path(lpLibFileName));
|
||||
}
|
||||
|
||||
return moduleAddress;
|
||||
|
@ -454,7 +459,7 @@ HMODULE, WINAPI, (LPCWSTR lpLibFileName))
|
|||
if (moduleAddress)
|
||||
{
|
||||
CallLoadLibraryWCallbacks(lpLibFileName, moduleAddress);
|
||||
InformPluginsDLLLoad(fs::path(lpLibFileName), moduleAddress);
|
||||
g_pPluginManager->InformDllLoad(moduleAddress, fs::path(lpLibFileName));
|
||||
}
|
||||
|
||||
return moduleAddress;
|
|
@ -1,5 +1,4 @@
|
|||
#pragma once
|
||||
#include "memory.h"
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
@ -25,7 +24,7 @@ enum class eDllLoadCallbackSide
|
|||
|
||||
class __dllLoadCallback
|
||||
{
|
||||
public:
|
||||
public:
|
||||
__dllLoadCallback() = delete;
|
||||
__dllLoadCallback(
|
||||
eDllLoadCallbackSide side,
|
||||
|
@ -67,7 +66,7 @@ class __autovar;
|
|||
|
||||
class __fileAutohook
|
||||
{
|
||||
public:
|
||||
public:
|
||||
std::vector<__autohook*> hooks;
|
||||
std::vector<__autovar*> vars;
|
||||
|
||||
|
@ -91,7 +90,7 @@ uintptr_t ParseDLLOffsetString(const char* pAddrString);
|
|||
|
||||
class __autohook
|
||||
{
|
||||
public:
|
||||
public:
|
||||
enum AddressResolutionMode
|
||||
{
|
||||
OFFSET_STRING, // we're using a string that of the format dllname.dll + offset
|
||||
|
@ -111,7 +110,7 @@ class __autohook
|
|||
char* pModuleName; // for PROCADDRESS
|
||||
char* pProcName; // for PROCADDRESS
|
||||
|
||||
public:
|
||||
public:
|
||||
__autohook() = delete;
|
||||
|
||||
__autohook(__fileAutohook* autohook, const char* funcName, LPVOID absoluteAddress, LPVOID* orig, LPVOID func)
|
||||
|
@ -119,7 +118,7 @@ class __autohook
|
|||
{
|
||||
iAddressResolutionMode = ABSOLUTE_ADDR;
|
||||
|
||||
const int iFuncNameStrlen = strlen(funcName) + 1;
|
||||
const size_t iFuncNameStrlen = strlen(funcName) + 1;
|
||||
pFuncName = new char[iFuncNameStrlen];
|
||||
memcpy(pFuncName, funcName, iFuncNameStrlen);
|
||||
|
||||
|
@ -131,11 +130,11 @@ class __autohook
|
|||
{
|
||||
iAddressResolutionMode = OFFSET_STRING;
|
||||
|
||||
const int iFuncNameStrlen = strlen(funcName) + 1;
|
||||
const size_t iFuncNameStrlen = strlen(funcName) + 1;
|
||||
pFuncName = new char[iFuncNameStrlen];
|
||||
memcpy(pFuncName, funcName, iFuncNameStrlen);
|
||||
|
||||
const int iAddrStrlen = strlen(addrString) + 1;
|
||||
const size_t iAddrStrlen = strlen(addrString) + 1;
|
||||
pAddrString = new char[iAddrStrlen];
|
||||
memcpy(pAddrString, addrString, iAddrStrlen);
|
||||
|
||||
|
@ -147,15 +146,15 @@ class __autohook
|
|||
{
|
||||
iAddressResolutionMode = PROCADDRESS;
|
||||
|
||||
const int iFuncNameStrlen = strlen(funcName) + 1;
|
||||
const size_t iFuncNameStrlen = strlen(funcName) + 1;
|
||||
pFuncName = new char[iFuncNameStrlen];
|
||||
memcpy(pFuncName, funcName, iFuncNameStrlen);
|
||||
|
||||
const int iModuleNameStrlen = strlen(moduleName) + 1;
|
||||
const size_t iModuleNameStrlen = strlen(moduleName) + 1;
|
||||
pModuleName = new char[iModuleNameStrlen];
|
||||
memcpy(pModuleName, moduleName, iModuleNameStrlen);
|
||||
|
||||
const int iProcNameStrlen = strlen(procName) + 1;
|
||||
const size_t iProcNameStrlen = strlen(procName) + 1;
|
||||
pProcName = new char[iProcNameStrlen];
|
||||
memcpy(pProcName, procName, iProcNameStrlen);
|
||||
|
||||
|
@ -250,13 +249,13 @@ class __autohook
|
|||
|
||||
class ManualHook
|
||||
{
|
||||
public:
|
||||
public:
|
||||
char* pFuncName;
|
||||
|
||||
LPVOID pHookFunc;
|
||||
LPVOID* ppOrigFunc;
|
||||
|
||||
public:
|
||||
public:
|
||||
ManualHook() = delete;
|
||||
ManualHook(const char* funcName, LPVOID func);
|
||||
ManualHook(const char* funcName, LPVOID* orig, LPVOID func);
|
||||
|
@ -284,16 +283,16 @@ void MakeHook(LPVOID pTarget, LPVOID pDetour, void* ppOriginal, const char* pFun
|
|||
|
||||
class __autovar
|
||||
{
|
||||
public:
|
||||
public:
|
||||
char* m_pAddrString;
|
||||
void** m_pTarget;
|
||||
|
||||
public:
|
||||
public:
|
||||
__autovar(__fileAutohook* pAutohook, const char* pAddrString, void** pTarget)
|
||||
{
|
||||
m_pTarget = pTarget;
|
||||
|
||||
const int iAddrStrlen = strlen(pAddrString) + 1;
|
||||
const size_t iAddrStrlen = strlen(pAddrString) + 1;
|
||||
m_pAddrString = new char[iAddrStrlen];
|
||||
memcpy(m_pAddrString, pAddrString, iAddrStrlen);
|
||||
|
|
@ -89,13 +89,13 @@ enum EBitCoordType
|
|||
|
||||
class BitBufferBase
|
||||
{
|
||||
protected:
|
||||
protected:
|
||||
INLINE void SetName(const char* name)
|
||||
{
|
||||
m_BufferName = name;
|
||||
}
|
||||
|
||||
public:
|
||||
public:
|
||||
INLINE bool IsOverflowed()
|
||||
{
|
||||
return m_Overflow;
|
||||
|
@ -110,16 +110,16 @@ class BitBufferBase
|
|||
return m_BufferName;
|
||||
}
|
||||
|
||||
private:
|
||||
private:
|
||||
const char* m_BufferName = "";
|
||||
|
||||
protected:
|
||||
protected:
|
||||
u8 m_Overflow = false;
|
||||
};
|
||||
|
||||
class BFRead : public BitBufferBase
|
||||
{
|
||||
public:
|
||||
public:
|
||||
BFRead() = default;
|
||||
|
||||
INLINE BFRead(uptr data, size_t byteLength, size_t startPos = 0, const char* bufferName = 0)
|
||||
|
@ -130,7 +130,7 @@ class BFRead : public BitBufferBase
|
|||
SetName(bufferName);
|
||||
}
|
||||
|
||||
public:
|
||||
public:
|
||||
INLINE void StartReading(uptr data, size_t byteLength, size_t startPos = 0)
|
||||
{
|
||||
m_Data = reinterpret_cast<u32 const*>(data);
|
||||
|
@ -630,7 +630,7 @@ class BFRead : public BitBufferBase
|
|||
// at the head to make reading and detecting the end efficient.
|
||||
int nHead = m_DataBytes & 3;
|
||||
|
||||
int posBytes = startPos / 8;
|
||||
size_t posBytes = startPos / 8;
|
||||
if ((m_DataBytes < 4) || (nHead && (posBytes < nHead)))
|
||||
{
|
||||
// partial first dword
|
||||
|
@ -652,7 +652,7 @@ class BFRead : public BitBufferBase
|
|||
}
|
||||
else
|
||||
{
|
||||
int adjustedPos = startPos - (nHead << 3);
|
||||
size_t adjustedPos = startPos - (nHead << 3);
|
||||
|
||||
m_DataIn = reinterpret_cast<u32 const*>(reinterpret_cast<u8 const*>(m_Data) + ((adjustedPos / 32) << 2) + nHead);
|
||||
|
||||
|
@ -706,7 +706,7 @@ class BFRead : public BitBufferBase
|
|||
return GetNumBitsLeft() >> 3;
|
||||
}
|
||||
|
||||
private:
|
||||
private:
|
||||
size_t m_DataBits; // 0x0010
|
||||
size_t m_DataBytes; // 0x0018
|
||||
|
||||
|
@ -720,7 +720,7 @@ class BFRead : public BitBufferBase
|
|||
|
||||
class BFWrite : public BitBufferBase
|
||||
{
|
||||
public:
|
||||
public:
|
||||
BFWrite() = default;
|
||||
|
||||
INLINE BFWrite(uptr data, size_t byteLength, const char* bufferName = 0)
|
||||
|
@ -731,7 +731,7 @@ class BFWrite : public BitBufferBase
|
|||
SetName(bufferName);
|
||||
}
|
||||
|
||||
public:
|
||||
public:
|
||||
INLINE void StartWriting(uptr data, size_t byteLength)
|
||||
{
|
||||
m_Data = reinterpret_cast<u32*>(data);
|
||||
|
@ -1131,7 +1131,7 @@ class BFWrite : public BitBufferBase
|
|||
WriteBitVec3Coord(tmp);
|
||||
}*/
|
||||
|
||||
private:
|
||||
private:
|
||||
size_t m_DataBits = 0;
|
||||
size_t m_DataBytes = 0;
|
||||
|
|
@ -57,7 +57,7 @@ struct SourceColor
|
|||
//-----------------------------------------------------------------------------
|
||||
class Color
|
||||
{
|
||||
public:
|
||||
public:
|
||||
Color(int r, int g, int b, int a = 255)
|
||||
{
|
||||
_color[0] = (unsigned char)r;
|
||||
|
@ -169,7 +169,7 @@ class Color
|
|||
return SourceColor(_color[0], _color[1], _color[2], _color[3]);
|
||||
}
|
||||
|
||||
private:
|
||||
private:
|
||||
unsigned char _color[4];
|
||||
};
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
inline float FastSqrt(float x)
|
||||
{
|
||||
__m128 root = _mm_sqrt_ss(_mm_load_ss(&x));
|
||||
return *(reinterpret_cast<float*>(&root));
|
||||
}
|
|
@ -0,0 +1,331 @@
|
|||
#pragma once
|
||||
|
||||
#include "bits.h"
|
||||
#include "math_pfns.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#define DEG2RAD(a) (a) * (3.14159265358979323846f / 180.0f)
|
||||
#define RAD2DEG(a) (a) * (180.0f / 3.14159265358979323846f)
|
||||
|
||||
class Vector3
|
||||
{
|
||||
public:
|
||||
float x, y, z;
|
||||
|
||||
Vector3(float _x, float _y, float _z) : x(_x), y(_y), z(_z) {}
|
||||
Vector3(float _f) : x(_f), y(_f), z(_f) {}
|
||||
Vector3() : x(0.0f), y(0.0f), z(0.0f) {}
|
||||
|
||||
inline bool IsValid()
|
||||
{
|
||||
return IsFinite(x) && IsFinite(y) && IsFinite(z);
|
||||
}
|
||||
|
||||
inline void Init(float fX = 0.0f, float fY = 0.0f, float fZ = 0.0f)
|
||||
{
|
||||
x = fX;
|
||||
y = fY;
|
||||
z = fZ;
|
||||
}
|
||||
|
||||
inline float Length()
|
||||
{
|
||||
return FastSqrt(x * x + y * y + z * z);
|
||||
}
|
||||
|
||||
inline float DistTo(const Vector3& vOther)
|
||||
{
|
||||
Vector3 vDelta;
|
||||
vDelta.x = vOther.x - x;
|
||||
vDelta.y = vOther.y - y;
|
||||
vDelta.z = vOther.z - z;
|
||||
|
||||
return vDelta.Length();
|
||||
}
|
||||
|
||||
float Dot(const Vector3& vOther) const
|
||||
{
|
||||
return x * vOther.x + y * vOther.y + z * vOther.z;
|
||||
}
|
||||
|
||||
// Cross product between two vectors.
|
||||
Vector3 Cross(const Vector3& vOther) const;
|
||||
|
||||
void Normalize();
|
||||
|
||||
bool operator==(const Vector3& v) const;
|
||||
bool operator!=(const Vector3& v) const;
|
||||
|
||||
FORCEINLINE Vector3& operator+=(const Vector3& v);
|
||||
FORCEINLINE Vector3& operator-=(const Vector3& v);
|
||||
FORCEINLINE Vector3& operator*=(const Vector3& v);
|
||||
FORCEINLINE Vector3& operator*=(float s);
|
||||
FORCEINLINE Vector3& operator/=(const Vector3& v);
|
||||
FORCEINLINE Vector3& operator/=(float s);
|
||||
FORCEINLINE Vector3& operator+=(float fl); ///< broadcast add
|
||||
FORCEINLINE Vector3& operator-=(float fl);
|
||||
|
||||
// arithmetic operations
|
||||
Vector3 operator-(void) const;
|
||||
|
||||
Vector3 operator+(const Vector3& v) const;
|
||||
Vector3 operator-(const Vector3& v) const;
|
||||
Vector3 operator*(const Vector3& v) const;
|
||||
Vector3 operator/(const Vector3& v) const;
|
||||
Vector3 operator*(float fl) const;
|
||||
Vector3 operator/(float fl) const;
|
||||
};
|
||||
|
||||
FORCEINLINE void VectorAdd(const Vector3& a, const Vector3& b, Vector3& result);
|
||||
FORCEINLINE void VectorSubtract(const Vector3& a, const Vector3& b, Vector3& result);
|
||||
FORCEINLINE void VectorMultiply(const Vector3& a, float b, Vector3& result);
|
||||
FORCEINLINE void VectorMultiply(const Vector3& a, const Vector3& b, Vector3& result);
|
||||
FORCEINLINE void VectorDivide(const Vector3& a, float b, Vector3& result);
|
||||
FORCEINLINE void VectorDivide(const Vector3& a, const Vector3& b, Vector3& result);
|
||||
|
||||
inline bool Vector3::operator==(const Vector3& src) const
|
||||
{
|
||||
return (src.x == x) && (src.y == y) && (src.z == z);
|
||||
}
|
||||
|
||||
inline bool Vector3::operator!=(const Vector3& src) const
|
||||
{
|
||||
return (src.x != x) || (src.y != y) || (src.z != z);
|
||||
}
|
||||
|
||||
FORCEINLINE Vector3& Vector3::operator+=(const Vector3& v)
|
||||
{
|
||||
x += v.x;
|
||||
y += v.y;
|
||||
z += v.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
FORCEINLINE Vector3& Vector3::operator-=(const Vector3& v)
|
||||
{
|
||||
x -= v.x;
|
||||
y -= v.y;
|
||||
z -= v.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
FORCEINLINE Vector3& Vector3::operator*=(float fl)
|
||||
{
|
||||
x *= fl;
|
||||
y *= fl;
|
||||
z *= fl;
|
||||
return *this;
|
||||
}
|
||||
|
||||
FORCEINLINE Vector3& Vector3::operator*=(const Vector3& v)
|
||||
{
|
||||
x *= v.x;
|
||||
y *= v.y;
|
||||
z *= v.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// this ought to be an opcode.
|
||||
FORCEINLINE Vector3& Vector3::operator+=(float fl)
|
||||
{
|
||||
x += fl;
|
||||
y += fl;
|
||||
z += fl;
|
||||
return *this;
|
||||
}
|
||||
|
||||
FORCEINLINE Vector3& Vector3::operator-=(float fl)
|
||||
{
|
||||
x -= fl;
|
||||
y -= fl;
|
||||
z -= fl;
|
||||
return *this;
|
||||
}
|
||||
|
||||
FORCEINLINE Vector3& Vector3::operator/=(float fl)
|
||||
{
|
||||
float oofl = 1.0f / fl;
|
||||
x *= oofl;
|
||||
y *= oofl;
|
||||
z *= oofl;
|
||||
return *this;
|
||||
}
|
||||
|
||||
FORCEINLINE Vector3& Vector3::operator/=(const Vector3& v)
|
||||
{
|
||||
x /= v.x;
|
||||
y /= v.y;
|
||||
z /= v.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Vector3 Vector3::operator-(void) const
|
||||
{
|
||||
return Vector3(-x, -y, -z);
|
||||
}
|
||||
|
||||
inline Vector3 Vector3::operator+(const Vector3& v) const
|
||||
{
|
||||
Vector3 res;
|
||||
VectorAdd(*this, v, res);
|
||||
return res;
|
||||
}
|
||||
|
||||
inline Vector3 Vector3::operator-(const Vector3& v) const
|
||||
{
|
||||
Vector3 res;
|
||||
VectorSubtract(*this, v, res);
|
||||
return res;
|
||||
}
|
||||
|
||||
inline Vector3 Vector3::operator*(float fl) const
|
||||
{
|
||||
Vector3 res;
|
||||
VectorMultiply(*this, fl, res);
|
||||
return res;
|
||||
}
|
||||
|
||||
inline Vector3 Vector3::operator*(const Vector3& v) const
|
||||
{
|
||||
Vector3 res;
|
||||
VectorMultiply(*this, v, res);
|
||||
return res;
|
||||
}
|
||||
|
||||
inline Vector3 Vector3::operator/(float fl) const
|
||||
{
|
||||
Vector3 res;
|
||||
VectorDivide(*this, fl, res);
|
||||
return res;
|
||||
}
|
||||
|
||||
inline Vector3 Vector3::operator/(const Vector3& v) const
|
||||
{
|
||||
Vector3 res;
|
||||
VectorDivide(*this, v, res);
|
||||
return res;
|
||||
}
|
||||
|
||||
inline Vector3 operator*(float fl, const Vector3& v)
|
||||
{
|
||||
return v * fl;
|
||||
}
|
||||
|
||||
inline Vector3 Vector3::Cross(const Vector3& vOther) const
|
||||
{
|
||||
return Vector3(y * vOther.z - z * vOther.y, z * vOther.x - x * vOther.z, x * vOther.y - y * vOther.x);
|
||||
}
|
||||
|
||||
inline void Vector3::Normalize()
|
||||
{
|
||||
float fLen = Length();
|
||||
x /= fLen;
|
||||
y /= fLen;
|
||||
z /= fLen;
|
||||
}
|
||||
|
||||
inline Vector3 StringToVector(char* pString)
|
||||
{
|
||||
Vector3 vRet;
|
||||
|
||||
int length = 0;
|
||||
while (pString[length])
|
||||
{
|
||||
if ((pString[length] == '<') || (pString[length] == '>'))
|
||||
pString[length] = '\0';
|
||||
length++;
|
||||
}
|
||||
|
||||
int startOfFloat = 1;
|
||||
int currentIndex = 1;
|
||||
|
||||
while (pString[currentIndex] && (pString[currentIndex] != ','))
|
||||
currentIndex++;
|
||||
pString[currentIndex] = '\0';
|
||||
vRet.x = std::stof(&pString[startOfFloat]);
|
||||
startOfFloat = ++currentIndex;
|
||||
|
||||
while (pString[currentIndex] && (pString[currentIndex] != ','))
|
||||
currentIndex++;
|
||||
pString[currentIndex] = '\0';
|
||||
vRet.y = std::stof(&pString[startOfFloat]);
|
||||
startOfFloat = ++currentIndex;
|
||||
|
||||
while (pString[currentIndex] && (pString[currentIndex] != ','))
|
||||
currentIndex++;
|
||||
pString[currentIndex] = '\0';
|
||||
vRet.z = std::stof(&pString[startOfFloat]);
|
||||
startOfFloat = ++currentIndex;
|
||||
|
||||
return vRet;
|
||||
}
|
||||
|
||||
FORCEINLINE void VectorAdd(const Vector3& a, const Vector3& b, Vector3& c)
|
||||
{
|
||||
c.x = a.x + b.x;
|
||||
c.y = a.y + b.y;
|
||||
c.z = a.z + b.z;
|
||||
}
|
||||
|
||||
FORCEINLINE void VectorSubtract(const Vector3& a, const Vector3& b, Vector3& c)
|
||||
{
|
||||
c.x = a.x - b.x;
|
||||
c.y = a.y - b.y;
|
||||
c.z = a.z - b.z;
|
||||
}
|
||||
|
||||
FORCEINLINE void VectorMultiply(const Vector3& a, float b, Vector3& c)
|
||||
{
|
||||
c.x = a.x * b;
|
||||
c.y = a.y * b;
|
||||
c.z = a.z * b;
|
||||
}
|
||||
|
||||
FORCEINLINE void VectorMultiply(const Vector3& a, const Vector3& b, Vector3& c)
|
||||
{
|
||||
c.x = a.x * b.x;
|
||||
c.y = a.y * b.y;
|
||||
c.z = a.z * b.z;
|
||||
}
|
||||
|
||||
FORCEINLINE void VectorDivide(const Vector3& a, float b, Vector3& c)
|
||||
{
|
||||
float oob = 1.0f / b;
|
||||
c.x = a.x * oob;
|
||||
c.y = a.y * oob;
|
||||
c.z = a.z * oob;
|
||||
}
|
||||
|
||||
FORCEINLINE void VectorDivide(const Vector3& a, const Vector3& b, Vector3& c)
|
||||
{
|
||||
c.x = a.x / b.x;
|
||||
c.y = a.y / b.y;
|
||||
c.z = a.z / b.z;
|
||||
}
|
||||
|
||||
class QAngle
|
||||
{
|
||||
public:
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
|
||||
QAngle(float _x, float _y, float _z) : x(_x), y(_y), z(_z) {}
|
||||
QAngle(float _f) : x(_f), y(_f), z(_f) {}
|
||||
QAngle() : x(0.0f), y(0.0f), z(0.0f) {}
|
||||
|
||||
Vector3 GetNormal() const;
|
||||
|
||||
// todo: more operators maybe
|
||||
bool operator==(const QAngle& other)
|
||||
{
|
||||
return x == other.x && y == other.y && z == other.z;
|
||||
}
|
||||
};
|
||||
|
||||
inline Vector3 QAngle::GetNormal() const
|
||||
{
|
||||
Vector3 ret(cos(DEG2RAD(y)), sin(DEG2RAD(y)), -sin(DEG2RAD(x)));
|
||||
return ret;
|
||||
}
|
|
@ -0,0 +1,106 @@
|
|||
#pragma once
|
||||
|
||||
typedef int SideType;
|
||||
|
||||
// Used to represent sides of things like planes.
|
||||
#define SIDE_FRONT 0
|
||||
#define SIDE_BACK 1
|
||||
#define SIDE_ON 2
|
||||
|
||||
#define VP_EPSILON 0.01f
|
||||
|
||||
class VPlane
|
||||
{
|
||||
public:
|
||||
VPlane();
|
||||
VPlane(const Vector3& vNormal, float dist);
|
||||
VPlane(const Vector3& vPoint, const QAngle& ang);
|
||||
|
||||
void Init(const Vector3& vNormal, float dist);
|
||||
|
||||
// Return the distance from the point to the plane.
|
||||
float DistTo(const Vector3& vVec) const;
|
||||
|
||||
// Copy.
|
||||
VPlane& operator=(const VPlane& thePlane);
|
||||
|
||||
// Returns SIDE_ON, SIDE_FRONT, or SIDE_BACK.
|
||||
// The epsilon for SIDE_ON can be passed in.
|
||||
SideType GetPointSide(const Vector3& vPoint, float sideEpsilon = VP_EPSILON) const;
|
||||
|
||||
// Returns SIDE_FRONT or SIDE_BACK.
|
||||
SideType GetPointSideExact(const Vector3& vPoint) const;
|
||||
|
||||
// Get a point on the plane (normal*dist).
|
||||
Vector3 GetPointOnPlane() const;
|
||||
|
||||
// Snap the specified point to the plane (along the plane's normal).
|
||||
Vector3 SnapPointToPlane(const Vector3& vPoint) const;
|
||||
|
||||
public:
|
||||
Vector3 m_Normal;
|
||||
float m_Dist;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Inlines.
|
||||
//-----------------------------------------------------------------------------
|
||||
inline VPlane::VPlane() {}
|
||||
|
||||
inline VPlane::VPlane(const Vector3& vNormal, float dist)
|
||||
{
|
||||
m_Normal = vNormal;
|
||||
m_Dist = dist;
|
||||
}
|
||||
|
||||
inline VPlane::VPlane(const Vector3& vPoint, const QAngle& ang)
|
||||
{
|
||||
m_Normal = ang.GetNormal();
|
||||
m_Dist = vPoint.x * m_Normal.x + vPoint.y * m_Normal.y + vPoint.z * m_Normal.z;
|
||||
}
|
||||
|
||||
inline void VPlane::Init(const Vector3& vNormal, float dist)
|
||||
{
|
||||
m_Normal = vNormal;
|
||||
m_Dist = dist;
|
||||
}
|
||||
|
||||
inline float VPlane::DistTo(const Vector3& vVec) const
|
||||
{
|
||||
return vVec.Dot(m_Normal) - m_Dist;
|
||||
}
|
||||
|
||||
inline VPlane& VPlane::operator=(const VPlane& thePlane)
|
||||
{
|
||||
m_Normal = thePlane.m_Normal;
|
||||
m_Dist = thePlane.m_Dist;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Vector3 VPlane::GetPointOnPlane() const
|
||||
{
|
||||
return m_Normal * m_Dist;
|
||||
}
|
||||
|
||||
inline Vector3 VPlane::SnapPointToPlane(const Vector3& vPoint) const
|
||||
{
|
||||
return vPoint - m_Normal * DistTo(vPoint);
|
||||
}
|
||||
|
||||
inline SideType VPlane::GetPointSide(const Vector3& vPoint, float sideEpsilon) const
|
||||
{
|
||||
float fDist;
|
||||
|
||||
fDist = DistTo(vPoint);
|
||||
if (fDist >= sideEpsilon)
|
||||
return SIDE_FRONT;
|
||||
else if (fDist <= -sideEpsilon)
|
||||
return SIDE_BACK;
|
||||
else
|
||||
return SIDE_ON;
|
||||
}
|
||||
|
||||
inline SideType VPlane::GetPointSideExact(const Vector3& vPoint) const
|
||||
{
|
||||
return DistTo(vPoint) > 0.0f ? SIDE_FRONT : SIDE_BACK;
|
||||
}
|
|
@ -1,8 +1,6 @@
|
|||
#include "core/memalloc.h"
|
||||
#include "core/tier0.h"
|
||||
|
||||
using namespace Tier0;
|
||||
|
||||
// TODO: rename to malloc and free after removing statically compiled .libs
|
||||
|
||||
extern "C" void* _malloc_base(size_t n)
|
|
@ -1,7 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "rapidjson/document.h"
|
||||
//#include "include/rapidjson/allocators.h"
|
||||
// #include "include/rapidjson/allocators.h"
|
||||
|
||||
extern "C" void* _malloc_base(size_t size);
|
||||
extern "C" void* _calloc_base(size_t const count, size_t const size);
|
||||
|
@ -17,7 +17,7 @@ void operator delete(void* p) noexcept;
|
|||
|
||||
class SourceAllocator
|
||||
{
|
||||
public:
|
||||
public:
|
||||
static const bool kNeedFree = true;
|
||||
void* Malloc(size_t size)
|
||||
{
|
|
@ -1,15 +1,22 @@
|
|||
#pragma once
|
||||
#include <string>
|
||||
|
||||
// interface return status
|
||||
enum class InterfaceStatus : int
|
||||
{
|
||||
IFACE_OK = 0,
|
||||
IFACE_FAILED,
|
||||
};
|
||||
|
||||
// literally just copied from ttf2sdk definition
|
||||
typedef void* (*CreateInterfaceFn)(const char* pName, int* pReturnCode);
|
||||
|
||||
template <typename T> class SourceInterface
|
||||
{
|
||||
private:
|
||||
private:
|
||||
T* m_interface;
|
||||
|
||||
public:
|
||||
public:
|
||||
SourceInterface(const std::string& moduleName, const std::string& interfaceName)
|
||||
{
|
||||
HMODULE handle = GetModuleHandleA(moduleName.c_str());
|
|
@ -0,0 +1,30 @@
|
|||
#include "tier0.h"
|
||||
|
||||
IMemAlloc* g_pMemAllocSingleton = nullptr;
|
||||
|
||||
CommandLineType CommandLine;
|
||||
Plat_FloatTimeType Plat_FloatTime;
|
||||
ThreadInServerFrameThreadType ThreadInServerFrameThread;
|
||||
|
||||
typedef IMemAlloc* (*CreateGlobalMemAllocType)();
|
||||
CreateGlobalMemAllocType CreateGlobalMemAlloc;
|
||||
|
||||
// needs to be a seperate function, since memalloc.cpp calls it
|
||||
void TryCreateGlobalMemAlloc()
|
||||
{
|
||||
// init memalloc stuff
|
||||
CreateGlobalMemAlloc =
|
||||
reinterpret_cast<CreateGlobalMemAllocType>(GetProcAddress(GetModuleHandleA("tier0.dll"), "CreateGlobalMemAlloc"));
|
||||
g_pMemAllocSingleton = CreateGlobalMemAlloc(); // if it already exists, this returns the preexisting IMemAlloc instance
|
||||
}
|
||||
|
||||
ON_DLL_LOAD("tier0.dll", Tier0GameFuncs, (CModule module))
|
||||
{
|
||||
// shouldn't be necessary, but do this just in case
|
||||
TryCreateGlobalMemAlloc();
|
||||
|
||||
// setup tier0 funcs
|
||||
CommandLine = module.GetExportedFunction("CommandLine").RCast<CommandLineType>();
|
||||
Plat_FloatTime = module.GetExportedFunction("Plat_FloatTime").RCast<Plat_FloatTimeType>();
|
||||
ThreadInServerFrameThread = module.GetExportedFunction("ThreadInServerFrameThread").RCast<ThreadInServerFrameThreadType>();
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
#pragma once
|
||||
|
||||
class IMemAlloc
|
||||
{
|
||||
public:
|
||||
struct VTable
|
||||
{
|
||||
void* unknown[1]; // alloc debug
|
||||
void* (*Alloc)(IMemAlloc* memAlloc, size_t nSize);
|
||||
void* unknown2[1]; // realloc debug
|
||||
void* (*Realloc)(IMemAlloc* memAlloc, void* pMem, size_t nSize);
|
||||
void* unknown3[1]; // free #1
|
||||
void (*Free)(IMemAlloc* memAlloc, void* pMem);
|
||||
void* unknown4[2]; // nullsubs, maybe CrtSetDbgFlag
|
||||
size_t (*GetSize)(IMemAlloc* memAlloc, void* pMem);
|
||||
void* unknown5[9]; // they all do literally nothing
|
||||
void (*DumpStats)(IMemAlloc* memAlloc);
|
||||
void (*DumpStatsFileBase)(IMemAlloc* memAlloc, const char* pchFileBase);
|
||||
void* unknown6[4];
|
||||
int (*heapchk)(IMemAlloc* memAlloc);
|
||||
};
|
||||
|
||||
VTable* m_vtable;
|
||||
};
|
||||
|
||||
class CCommandLine
|
||||
{
|
||||
public:
|
||||
// based on the defs in the 2013 source sdk, but for some reason has an extra function (may be another CreateCmdLine overload?)
|
||||
// these seem to line up with what they should be though
|
||||
virtual void CreateCmdLine(const char* commandline) = 0;
|
||||
virtual void CreateCmdLine(int argc, char** argv) = 0;
|
||||
virtual void unknown() = 0;
|
||||
virtual const char* GetCmdLine(void) const = 0;
|
||||
|
||||
virtual const char* CheckParm(const char* psz, const char** ppszValue = 0) const = 0;
|
||||
virtual void RemoveParm() const = 0;
|
||||
virtual void AppendParm(const char* pszParm, const char* pszValues) = 0;
|
||||
|
||||
virtual const char* ParmValue(const char* psz, const char* pDefaultVal = 0) const = 0;
|
||||
virtual int ParmValue(const char* psz, int nDefaultVal) const = 0;
|
||||
virtual float ParmValue(const char* psz, float flDefaultVal) const = 0;
|
||||
|
||||
virtual int ParmCount() const = 0;
|
||||
virtual int FindParm(const char* psz) const = 0;
|
||||
virtual const char* GetParm(int nIndex) const = 0;
|
||||
virtual void SetParm(int nIndex, char const* pParm) = 0;
|
||||
|
||||
// virtual const char** GetParms() const {}
|
||||
};
|
||||
|
||||
extern IMemAlloc* g_pMemAllocSingleton;
|
||||
|
||||
typedef CCommandLine* (*CommandLineType)();
|
||||
extern CommandLineType CommandLine;
|
||||
|
||||
typedef double (*Plat_FloatTimeType)();
|
||||
extern Plat_FloatTimeType Plat_FloatTime;
|
||||
|
||||
typedef bool (*ThreadInServerFrameThreadType)();
|
||||
extern ThreadInServerFrameThreadType ThreadInServerFrameThread;
|
||||
|
||||
void TryCreateGlobalMemAlloc();
|
|
@ -0,0 +1,19 @@
|
|||
#include "tier1.h"
|
||||
|
||||
// Note: this file is tier1/interface.cpp in primedev, but given that tier0 is yet to be split
|
||||
// I am following the existing "pattern" and putting this here
|
||||
|
||||
CMemory Sys_GetFactoryPtr(const std::string& svModuleName, const std::string& svFactoryName)
|
||||
{
|
||||
HMODULE hModule = GetModuleHandleA(svModuleName.c_str());
|
||||
|
||||
if (!hModule)
|
||||
{
|
||||
spdlog::error("Failed to get module handle of '{}'!", svModuleName.c_str());
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
CreateInterfaceFn fnCreateInterface = reinterpret_cast<CreateInterfaceFn>(GetProcAddress(hModule, CREATEINTERFACE_PROCNAME));
|
||||
|
||||
return fnCreateInterface(svFactoryName.c_str(), NULL);
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
#pragma once
|
||||
|
||||
// Note: this file is tier1/interface.h in primedev, but given that tier0 is yet to be split
|
||||
// I am following the existing "pattern" and putting this here
|
||||
|
||||
#include "memory.h"
|
||||
|
||||
#define CREATEINTERFACE_PROCNAME "CreateInterface"
|
||||
|
||||
typedef void* (*CreateInterfaceFn)(const char* pName, int* pReturnCode);
|
||||
|
||||
CMemory Sys_GetFactoryPtr(const std::string& svModuleName, const std::string& svFact);
|
|
@ -0,0 +1,29 @@
|
|||
#pragma once
|
||||
|
||||
/// Determines if we are in vanilla-compatibility mode.
|
||||
/// In this mode we shouldn't auth with Atlas, which prevents users from joining a
|
||||
/// non-trusted server. This means that we can unrestrict client/server commands
|
||||
/// as well as various other small changes for compatibility
|
||||
class VanillaCompatibility
|
||||
{
|
||||
public:
|
||||
void SetVanillaCompatibility(bool isVanilla)
|
||||
{
|
||||
static bool bInitialised = false;
|
||||
if (bInitialised)
|
||||
return;
|
||||
|
||||
bInitialised = true;
|
||||
m_bIsVanillaCompatible = isVanilla;
|
||||
}
|
||||
|
||||
bool GetVanillaCompatibility()
|
||||
{
|
||||
return m_bIsVanillaCompatible;
|
||||
}
|
||||
|
||||
private:
|
||||
bool m_bIsVanillaCompatible = false;
|
||||
};
|
||||
|
||||
inline VanillaCompatibility* g_pVanillaCompatibility;
|
|
@ -10,8 +10,6 @@
|
|||
|
||||
AUTOHOOK_INIT()
|
||||
|
||||
using namespace R2;
|
||||
|
||||
bool IsDedicatedServer()
|
||||
{
|
||||
static bool result = strstr(GetCommandLineA(), "-dedicated");
|
||||
|
@ -37,21 +35,24 @@ struct CDedicatedExports
|
|||
|
||||
void Sys_Printf(CDedicatedExports* dedicated, const char* msg)
|
||||
{
|
||||
NOTE_UNUSED(dedicated);
|
||||
spdlog::info("[DEDICATED SERVER] {}", msg);
|
||||
}
|
||||
|
||||
void RunServer(CDedicatedExports* dedicated)
|
||||
{
|
||||
NOTE_UNUSED(dedicated);
|
||||
|
||||
spdlog::info("CDedicatedExports::RunServer(): starting");
|
||||
spdlog::info(Tier0::CommandLine()->GetCmdLine());
|
||||
spdlog::info(CommandLine()->GetCmdLine());
|
||||
|
||||
// initialise engine
|
||||
g_pEngine->Frame();
|
||||
|
||||
// add +map if no map loading command is present
|
||||
// don't manually execute this from cbuf as users may have it in their startup args anyway, easier just to run from stuffcmds if present
|
||||
if (!Tier0::CommandLine()->CheckParm("+map") && !Tier0::CommandLine()->CheckParm("+launchplaylist"))
|
||||
Tier0::CommandLine()->AppendParm("+map", g_pCVar->FindVar("match_defaultMap")->GetString());
|
||||
if (!CommandLine()->CheckParm("+map") && !CommandLine()->CheckParm("+launchplaylist"))
|
||||
CommandLine()->AppendParm("+map", g_pCVar->FindVar("match_defaultMap")->GetString());
|
||||
|
||||
// re-run commandline
|
||||
Cbuf_AddText(Cbuf_GetCurrentPlayer(), "stuffcmds", cmd_source_t::kCommandSrcCode);
|
||||
|
@ -61,11 +62,11 @@ void RunServer(CDedicatedExports* dedicated)
|
|||
double frameTitle = 0;
|
||||
while (g_pEngine->m_nQuitting == EngineQuitState::QUIT_NOTQUITTING)
|
||||
{
|
||||
double frameStart = Tier0::Plat_FloatTime();
|
||||
double frameStart = Plat_FloatTime();
|
||||
g_pEngine->Frame();
|
||||
|
||||
std::this_thread::sleep_for(
|
||||
std::chrono::duration<double, std::ratio<1>>(g_pGlobals->m_flTickInterval - fmin(Tier0::Plat_FloatTime() - frameStart, 0.25)));
|
||||
std::chrono::duration<double, std::ratio<1>>(g_pGlobals->m_flTickInterval - fmin(Plat_FloatTime() - frameStart, 0.25)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -88,6 +89,8 @@ class DedicatedConsoleServerPresence : public ServerPresenceReporter
|
|||
HANDLE consoleInputThreadHandle = NULL;
|
||||
DWORD WINAPI ConsoleInputThread(PVOID pThreadParameter)
|
||||
{
|
||||
NOTE_UNUSED(pThreadParameter);
|
||||
|
||||
while (!g_pEngine || !g_pHostState || g_pHostState->m_iCurrentState != HostState_t::HS_RUN)
|
||||
Sleep(1000);
|
||||
|
||||
|
@ -137,7 +140,7 @@ ON_DLL_LOAD_DEDI_RELIESON("engine.dll", DedicatedServer, ServerPresence, (CModul
|
|||
{
|
||||
// CModAppSystemGroup::Create
|
||||
// force the engine into dedicated mode by changing the first comparison to IsServerOnly to an assignment
|
||||
CMemoryAddress base = module.Offset(0x1C4EBD);
|
||||
CMemory base = module.Offset(0x1C4EBD);
|
||||
|
||||
// cmp => mov
|
||||
base.Offset(1).Patch("C6 87");
|
||||
|
@ -215,13 +218,13 @@ ON_DLL_LOAD_DEDI_RELIESON("engine.dll", DedicatedServer, ServerPresence, (CModul
|
|||
// make sure it still gets registered
|
||||
|
||||
// add cmdline args that are good for dedi
|
||||
Tier0::CommandLine()->AppendParm("-nomenuvid", 0);
|
||||
Tier0::CommandLine()->AppendParm("-nosound", 0);
|
||||
Tier0::CommandLine()->AppendParm("-windowed", 0);
|
||||
Tier0::CommandLine()->AppendParm("-nomessagebox", 0);
|
||||
Tier0::CommandLine()->AppendParm("+host_preload_shaders", "0");
|
||||
Tier0::CommandLine()->AppendParm("+net_usesocketsforloopback", "1");
|
||||
Tier0::CommandLine()->AppendParm("+community_frame_run", "0");
|
||||
CommandLine()->AppendParm("-nomenuvid", 0);
|
||||
CommandLine()->AppendParm("-nosound", 0);
|
||||
CommandLine()->AppendParm("-windowed", 0);
|
||||
CommandLine()->AppendParm("-nomessagebox", 0);
|
||||
CommandLine()->AppendParm("+host_preload_shaders", "0");
|
||||
CommandLine()->AppendParm("+net_usesocketsforloopback", "1");
|
||||
CommandLine()->AppendParm("+community_frame_run", "0");
|
||||
|
||||
// use presence reporter for console title
|
||||
DedicatedConsoleServerPresence* presenceReporter = new DedicatedConsoleServerPresence;
|
||||
|
@ -231,7 +234,7 @@ ON_DLL_LOAD_DEDI_RELIESON("engine.dll", DedicatedServer, ServerPresence, (CModul
|
|||
RegisterCustomSink(std::make_shared<DedicatedServerLogToClientSink>());
|
||||
|
||||
// Disable Quick Edit mode to reduce chance of user unintentionally hanging their server by selecting something.
|
||||
if (!Tier0::CommandLine()->CheckParm("-bringbackquickedit"))
|
||||
if (!CommandLine()->CheckParm("-bringbackquickedit"))
|
||||
{
|
||||
HANDLE stdIn = GetStdHandle(STD_INPUT_HANDLE);
|
||||
DWORD mode = 0;
|
||||
|
@ -253,7 +256,7 @@ ON_DLL_LOAD_DEDI_RELIESON("engine.dll", DedicatedServer, ServerPresence, (CModul
|
|||
spdlog::info("Quick Edit enabled by user request");
|
||||
|
||||
// create console input thread
|
||||
if (!Tier0::CommandLine()->CheckParm("-noconsoleinput"))
|
||||
if (!CommandLine()->CheckParm("-noconsoleinput"))
|
||||
consoleInputThreadHandle = CreateThread(0, 0, ConsoleInputThread, 0, 0, NULL);
|
||||
else
|
||||
spdlog::info("Console input disabled by user request");
|
||||
|
@ -264,7 +267,7 @@ ON_DLL_LOAD_DEDI("tier0.dll", DedicatedServerOrigin, (CModule module))
|
|||
// disable origin on dedicated
|
||||
// for any big ea lawyers, this can't be used to play the game without origin, game will throw a fit if you try to do anything without
|
||||
// an origin id as a client for dedi it's fine though, game doesn't care if origin is disabled as long as there's only a server
|
||||
module.GetExport("Tier0_InitOrigin").Patch("C3");
|
||||
module.GetExportedFunction("Tier0_InitOrigin").Patch("C3");
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
|
@ -288,7 +291,7 @@ ON_DLL_LOAD_DEDI("server.dll", DedicatedServerGameDLL, (CModule module))
|
|||
{
|
||||
AUTOHOOK_DISPATCH_MODULE(server.dll)
|
||||
|
||||
if (Tier0::CommandLine()->CheckParm("-nopakdedi"))
|
||||
if (CommandLine()->CheckParm("-nopakdedi"))
|
||||
{
|
||||
module.Offset(0x6BA350).Patch("C3"); // dont load skins.rson from rpak if we don't have rpaks, as loading it will cause a crash
|
||||
module.Offset(0x6BA300).Patch(
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue