Compare commits

..

No commits in common. "main" and "v1.2.3" have entirely different histories.
main ... v1.2.3

43 changed files with 7690 additions and 818 deletions

View File

@ -1,7 +0,0 @@
version: 2
updates:
- package-ecosystem: gitsubmodule
directory: "/"
schedule:
interval: daily
open-pull-requests-limit: 10

View File

@ -1,45 +0,0 @@
name: Build
on:
push:
branches:
- "*"
pull_request:
branches:
- "*"
types: [opened, synchronize, reopened]
jobs:
build:
name: Build binaries
runs-on: windows-2022
strategy:
matrix:
configuration:
- Debug
- Release
steps:
- name: Check out files
uses: actions/checkout@v3
with:
submodules: true
fetch-depth: 0
lfs: false
- name: Add msbuild to PATH
uses: microsoft/setup-msbuild@v1.1.3
- name: Generate project files
run: tools/premake5 vs2022
- name: Set up problem matching
uses: ammaraskar/msvc-problem-matcher@master
- name: Build ${{matrix.configuration}} binaries
run: msbuild /m /v:minimal /p:Configuration=${{matrix.configuration}} /p:PlatformTarget=x86 build/iw5-gsc-utils.sln
- name: Upload ${{matrix.configuration}} binaries
uses: actions/upload-artifact@v3.1.0
with:
name: ${{matrix.configuration}} binaries
path: |
build/bin/${{matrix.configuration}}/iw5-gsc-utils.dll

13
.gitmodules vendored
View File

@ -4,13 +4,12 @@
[submodule "deps/GSL"] [submodule "deps/GSL"]
path = deps/GSL path = deps/GSL
url = https://github.com/microsoft/GSL.git url = https://github.com/microsoft/GSL.git
[submodule "deps/sol2"]
path = deps/sol2
url = https://github.com/ThePhD/sol2.git
[submodule "deps/lua"]
path = deps/lua
url = https://github.com/lua/lua.git
[submodule "deps/json"] [submodule "deps/json"]
path = deps/json path = deps/json
url = https://github.com/nlohmann/json.git url = https://github.com/nlohmann/json.git
branch = develop
[submodule "deps/gsc-tool"]
path = deps/gsc-tool
url = https://github.com/xensik/gsc-tool.git
[submodule "deps/zlib"]
path = deps/zlib
url = https://github.com/madler/zlib.git

2
deps/GSL vendored

@ -1 +1 @@
Subproject commit b39e7e4b0987859f5b19ff7686b149c916588658 Subproject commit c31a9ad5e8e99da8567237a7ba51a7d8f419e5bf

1
deps/gsc-tool vendored

@ -1 +0,0 @@
Subproject commit 0e6238a6ab8643df6404f7c0280242df2812f6c8

2
deps/json vendored

@ -1 +1 @@
Subproject commit 0457de21cffb298c22b629e538036bfeb96130b7 Subproject commit e10a3fac8a255433146e3f06a703dc110fc3c3da

2
deps/minhook vendored

@ -1 +1 @@
Subproject commit f5485b8454544c2f034c78f8f127c1d03dea3636 Subproject commit 423d1e45af2ed2719a5c31e990e935ef301ed9c3

View File

@ -1,62 +0,0 @@
gsc_tool = {
source = path.join(dependencies.basePath, "gsc-tool"),
}
function gsc_tool.import()
links { "xsk-gsc-iw5-pc", "xsk-gsc-utils" }
gsc_tool.includes()
end
function gsc_tool.includes()
includedirs {
path.join(gsc_tool.source, "include"),
}
end
function gsc_tool.project()
project "xsk-gsc-utils"
kind "StaticLib"
language "C++"
files {
path.join(gsc_tool.source, "include/xsk/utils/*.hpp"),
path.join(gsc_tool.source, "src/utils/*.cpp"),
}
includedirs {
path.join(gsc_tool.source, "include"),
}
zlib.includes()
project "xsk-gsc-iw5-pc"
kind "StaticLib"
language "C++"
filter "action:vs*"
buildoptions "/Zc:__cplusplus"
filter {}
files {
path.join(gsc_tool.source, "include/xsk/stdinc.hpp"),
path.join(gsc_tool.source, "include/xsk/gsc/engine/iw5_pc.hpp"),
path.join(gsc_tool.source, "src/gsc/engine/iw5_pc.cpp"),
path.join(gsc_tool.source, "src/gsc/engine/iw5_pc_code.cpp"),
path.join(gsc_tool.source, "src/gsc/engine/iw5_pc_func.cpp"),
path.join(gsc_tool.source, "src/gsc/engine/iw5_pc_meth.cpp"),
path.join(gsc_tool.source, "src/gsc/engine/iw5_pc_token.cpp"),
path.join(gsc_tool.source, "src/gsc/*.cpp"),
path.join(gsc_tool.source, "src/gsc/common/*.cpp"),
path.join(gsc_tool.source, "include/xsk/gsc/common/*.hpp"),
}
includedirs {
path.join(gsc_tool.source, "include"),
}
end
table.insert(dependencies, gsc_tool)

39
deps/premake/zlib.lua vendored
View File

@ -1,39 +0,0 @@
zlib = {
source = path.join(dependencies.basePath, "zlib"),
}
function zlib.import()
links { "zlib" }
zlib.includes()
end
function zlib.includes()
includedirs {
zlib.source
}
defines {
"ZLIB_CONST",
}
end
function zlib.project()
project "zlib"
language "C"
zlib.includes()
files {
path.join(zlib.source, "*.h"),
path.join(zlib.source, "*.c"),
}
defines {
"_CRT_SECURE_NO_DEPRECATE",
}
warnings "Off"
kind "StaticLib"
end
table.insert(dependencies, zlib)

1
deps/zlib vendored

@ -1 +0,0 @@
Subproject commit 5c42a230b7b468dff011f444161c0145b5efae59

View File

@ -1,3 +1,2 @@
@echo off @echo off
call git submodule update --init --recursive tools\windows\premake5.exe vs2019
tools\premake5.exe vs2022

View File

@ -36,35 +36,32 @@ workspace "iw5-gsc-utils"
targetdir "%{wks.location}/bin/%{cfg.buildcfg}" targetdir "%{wks.location}/bin/%{cfg.buildcfg}"
targetname "%{prj.name}" targetname "%{prj.name}"
configurations { "Debug", "Release", }
language "C++" language "C++"
cppdialect "C++20"
architecture "x86" architecture "x86"
buildoptions "/std:c++latest"
systemversion "latest" systemversion "latest"
symbols "On"
staticruntime "On"
editandcontinue "Off"
warnings "Extra"
characterset "ASCII"
flags flags
{ {
"NoIncrementalLink", "NoIncrementalLink",
"MultiProcessorCompile", "MultiProcessorCompile",
} }
configurations { "Debug", "Release", }
symbols "On"
filter "configurations:Release" configuration "Release"
optimize "Full" optimize "Full"
defines { "NDEBUG" } defines { "NDEBUG" }
filter {} configuration{}
filter "configurations:Debug" configuration "Debug"
optimize "Debug" optimize "Debug"
defines { "DEBUG", "_DEBUG" } defines { "DEBUG", "_DEBUG" }
filter {} configuration {}
startproject "iw5-gsc-utils" startproject "iw5-gsc-utils"

View File

@ -49,7 +49,6 @@ namespace command
if (i > index) result.append(" "); if (i > index) result.append(" ");
result.append(this->get(i)); result.append(this->get(i));
} }
return result; return result;
} }
@ -97,6 +96,7 @@ namespace command
public: public:
void post_unpack() override void post_unpack() override
{ {
} }
}; };
} }

View File

@ -21,13 +21,13 @@ namespace gsc
{ {
std::string method_name(unsigned int id) std::string method_name(unsigned int id)
{ {
const auto& map = (*game::plutonium::gsc_ctx)->meth_map(); const auto map = *game::plutonium::method_map_rev;
for (const auto& function : map) for (const auto& function : map)
{ {
if (function.second == id) if (function.second == id)
{ {
return function.first.data(); return function.first;
} }
} }
@ -36,13 +36,13 @@ namespace gsc
std::string function_name(unsigned int id) std::string function_name(unsigned int id)
{ {
const auto& map = (*game::plutonium::gsc_ctx)->func_map(); const auto map = *game::plutonium::function_map_rev;
for (const auto& function : map) for (const auto& function : map)
{ {
if (function.second == id) if (function.second == id)
{ {
return function.first.data(); return function.first;
} }
} }
@ -53,6 +53,8 @@ namespace gsc
{ {
std::vector<scripting::script_value> args; std::vector<scripting::script_value> args;
const auto top = game::scr_VmPub->top;
for (auto i = 0; i < game::scr_VmPub->outparamcount; i++) for (auto i = 0; i < game::scr_VmPub->outparamcount; i++)
{ {
const auto value = game::scr_VmPub->top[-i]; const auto value = game::scr_VmPub->top[-i];
@ -91,7 +93,7 @@ namespace gsc
{ {
if (id < 0x200) if (id < 0x200)
{ {
return reinterpret_cast<builtin_function*>(game::plutonium::function_table.get())[id](); return reinterpret_cast<builtin_function*>(0x20689DD8)[id]();
} }
try try
@ -117,7 +119,7 @@ namespace gsc
{ {
if (id < 0x8400) if (id < 0x8400)
{ {
return reinterpret_cast<builtin_method*>(game::plutonium::method_table.get())[id - 0x8000](ent); return reinterpret_cast<builtin_method*>(0x2068A5A8)[id - 0x8000](ent);
} }
try try
@ -192,7 +194,7 @@ namespace gsc
return scr_get_object_field_hook.invoke<void>(classnum, entnum, offset); return scr_get_object_field_hook.invoke<void>(classnum, entnum, offset);
} }
const auto& field = custom_fields[classnum][offset]; const auto field = custom_fields[classnum][offset];
try try
{ {
@ -217,7 +219,7 @@ namespace gsc
} }
const auto args = get_arguments(); const auto args = get_arguments();
const auto& field = custom_fields[classnum][offset]; const auto field = custom_fields[classnum][offset];
try try
{ {
@ -248,21 +250,10 @@ namespace gsc
{ {
void add(const std::string& name, const script_function& func) void add(const std::string& name, const script_function& func)
{ {
auto index = 0u; const auto index = function_map_start++;
auto& ctx = (*game::plutonium::gsc_ctx);
if (ctx->func_exists(name))
{
printf("[iw5-gsc-utils] Warning: function '%s' already defined\n", name.data());
index = ctx->func_id(name);
}
else
{
index = function_map_start++;
ctx->func_add(name, index);
}
functions.insert(std::make_pair(index, func)); functions[index] = func;
(*game::plutonium::function_map_rev)[name] = index;
} }
} }
@ -270,37 +261,29 @@ namespace gsc
{ {
void add(const std::string& name, const script_method& func) void add(const std::string& name, const script_method& func)
{ {
auto index = 0u; const auto index = method_map_start++;
auto& ctx = (*game::plutonium::gsc_ctx);
if (ctx->meth_exists(name)) methods[index] = func;
{ (*game::plutonium::method_map_rev)[name] = index;
printf("[iw5-gsc-utils] Warning: method '%s' already defined\n", name.data());
index = ctx->meth_id(name);
}
else
{
index = method_map_start++;
ctx->meth_add(name, index);
}
methods.insert(std::make_pair(index, func));
} }
} }
namespace field namespace field
{ {
void add(const classid classnum, const std::string& name, void add(classid classnum, const std::string& name,
const std::function<scripting::script_value(unsigned int entnum)>& getter, const std::function<scripting::script_value(unsigned int entnum)>& getter,
const std::function<void(unsigned int entnum, const scripting::script_value&)>& setter) const std::function<void(unsigned int entnum, const scripting::script_value&)>& setter)
{ {
const auto token_id = token_map_start++;
const auto offset = field_offset_start++; const auto offset = field_offset_start++;
custom_fields[classnum][offset] = {name, getter, setter};
post_load_callbacks.push_back([=]() custom_fields[classnum][offset] = {name, getter, setter};
(*game::plutonium::token_map_rev)[name] = token_id;
post_load_callbacks.push_back([classnum, name, token_id, offset]()
{ {
const auto name_str = game::SL_GetString(name.data(), 0); const auto name_str = game::SL_GetString(name.data(), 0);
game::Scr_AddClassField(classnum, name_str, game::SL_GetCanonicalString(name.data()), offset); game::Scr_AddClassField(classnum, name_str, token_id, offset);
}); });
} }
} }
@ -339,7 +322,7 @@ namespace gsc
scr_set_object_field_hook.create(0x52BCC0, scr_set_object_field_stub); scr_set_object_field_hook.create(0x52BCC0, scr_set_object_field_stub);
scr_post_load_scripts_hook.create(0x628B50, scr_post_load_scripts_stub); scr_post_load_scripts_hook.create(0x628B50, scr_post_load_scripts_stub);
field::add(classid::entity, "entityflags", field::add(classid::entity, "flags",
[](unsigned int entnum) -> scripting::script_value [](unsigned int entnum) -> scripting::script_value
{ {
const auto entity = &game::g_entities[entnum]; const auto entity = &game::g_entities[entnum];
@ -397,20 +380,6 @@ namespace gsc
return {}; return {};
}); });
function::add("dropallbots", [](const function_args&) -> scripting::script_value
{
for (auto i = 0; i < *game::svs_clientCount; i++)
{
if (game::svs_clients[i].header.state != game::CS_FREE
&& game::svs_clients[i].header.netchan.remoteAddress.type == game::NA_BOT)
{
game::SV_GameDropClient(i, "GAME_GET_TO_COVER");
}
}
return {};
});
method::add("tell", [](const game::scr_entref_t ent, const function_args& args) -> scripting::script_value method::add("tell", [](const game::scr_entref_t ent, const function_args& args) -> scripting::script_value
{ {
if (ent.classnum != 0) if (ent.classnum != 0)
@ -419,13 +388,8 @@ namespace gsc
} }
const auto client = ent.entnum; const auto client = ent.entnum;
if (game::g_entities[client].client == nullptr)
{
throw std::runtime_error("Not a player entity");
}
const auto message = args[0].as<std::string>(); const auto message = args[0].as<std::string>();
game::SV_GameSendServerCommand(client, 0, utils::string::va("%c \"%s\"", 84, message.data())); game::SV_GameSendServerCommand(client, 0, utils::string::va("%c \"%s\"", 84, message.data()));
return {}; return {};
@ -438,62 +402,22 @@ namespace gsc
throw std::runtime_error("Invalid entity"); throw std::runtime_error("Invalid entity");
} }
const auto client = ent.entnum; const auto num = ent.entnum;
if (game::g_entities[client].client == nullptr)
{
throw std::runtime_error("Not a player entity");
}
const auto toggle = args[0].as<int>(); const auto toggle = args[0].as<int>();
auto flags = game::g_entities[client].client->ps.perks[0];
game::g_entities[client].client->ps.perks[0] = toggle auto g_client = game::g_entities[num].client;
? flags | 0x4000u : flags & ~0x4000u; auto playerState = &g_client->ps;
auto flags = playerState->perks[0];
playerState->perks[0] = toggle
? flags | 0x4000u
: flags & ~0x4000u;
return {}; return {};
}); });
method::add("isbot", [](const game::scr_entref_t ent, const function_args&) -> scripting::script_value utils::hook::jump(0x56C8EB, call_builtin_stub);
{ utils::hook::jump(0x56CBDC, call_builtin_method_stub);
if (ent.classnum != 0)
{
throw std::runtime_error("Invalid entity");
}
const auto client = ent.entnum;
if (game::g_entities[client].client == nullptr)
{
throw std::runtime_error("Not a player entity");
}
return game::svs_clients[client].bIsTestClient;
});
method::add("arecontrolsfrozen", [](const game::scr_entref_t ent, const function_args&) -> scripting::script_value
{
if (ent.classnum != 0)
{
throw std::runtime_error("Invalid entity");
}
const auto client = ent.entnum;
if (game::g_entities[client].client == nullptr)
{
throw std::runtime_error("Not a player entity");
}
return {(game::g_entities[client].client->flags & 4) != 0};
});
// let other plugins read the pointers
post_load_callbacks.push_back([]()
{
utils::hook::jump(0x56C8EB, call_builtin_stub);
utils::hook::jump(0x56CBDC, call_builtin_method_stub);
});
} }
}; };
} }

View File

@ -1,6 +1,4 @@
#pragma once #pragma once
#include "game/scripting/array.hpp"
#include "game/scripting/execution.hpp"
namespace gsc namespace gsc
{ {
@ -48,7 +46,7 @@ namespace gsc
namespace field namespace field
{ {
void add(const classid classnum, const std::string& name, void add(classid classnum, const std::string& name,
const std::function<scripting::script_value(unsigned int entnum)>& getter, const std::function<scripting::script_value(unsigned int entnum)>& getter,
const std::function<void(unsigned int entnum, const scripting::script_value&)>& setter); const std::function<void(unsigned int entnum, const scripting::script_value&)>& setter);
} }

View File

@ -2,6 +2,12 @@
#include "loader/component_loader.hpp" #include "loader/component_loader.hpp"
#include "scheduler.hpp" #include "scheduler.hpp"
#include "game/scripting/event.hpp"
#include "game/scripting/execution.hpp"
#include "game/scripting/functions.hpp"
#include "game/scripting/array.hpp"
#include "gsc.hpp" #include "gsc.hpp"
#include "json.hpp" #include "json.hpp"
@ -179,4 +185,4 @@ namespace io
}; };
} }
REGISTER_COMPONENT(io::component) REGISTER_COMPONENT(io::component)

View File

@ -2,6 +2,12 @@
#include "loader/component_loader.hpp" #include "loader/component_loader.hpp"
#include "scheduler.hpp" #include "scheduler.hpp"
#include "game/scripting/event.hpp"
#include "game/scripting/execution.hpp"
#include "game/scripting/functions.hpp"
#include "game/scripting/array.hpp"
#include "gsc.hpp" #include "gsc.hpp"
#include "json.hpp" #include "json.hpp"
@ -194,4 +200,4 @@ namespace json
}; };
} }
REGISTER_COMPONENT(json::component) REGISTER_COMPONENT(json::component)

View File

@ -1,51 +1,35 @@
#include <stdinc.hpp> #include <stdinc.hpp>
#include "loader/component_loader.hpp" #include "loader/component_loader.hpp"
#include "scheduler.hpp" #include "scheduler.hpp"
#include "gsc.hpp"
#include "scripting.hpp" #include "game/scripting/entity.hpp"
#include "game/scripting/execution.hpp"
namespace notifies namespace notifies
{ {
namespace namespace
{ {
std::vector<scripting::function> say_callbacks;
utils::hook::detour client_command_hook; utils::hook::detour client_command_hook;
void client_command_stub(int clientNum) void client_command_stub(int clientNum)
{ {
char cmd[1024] = {0}; char cmd[1024] = { 0 };
const auto* entity = &game::g_entities[clientNum];
if (entity->client == nullptr)
{
return; // Client is not fully in game yet
}
game::SV_Cmd_ArgvBuffer(0, cmd, 1024); game::SV_Cmd_ArgvBuffer(0, cmd, 1024);
auto hidden = false;
if (cmd == "say"s || cmd == "say_team"s) if (cmd == "say"s || cmd == "say_team"s)
{ {
std::string message = game::ConcatArgs(1); std::string message = game::ConcatArgs(1);
message.erase(0, 1); message.erase(0, 1);
for (const auto& callback : say_callbacks) const scripting::entity level{*game::levelEntityId};
{ const auto player = scripting::call("getEntByNum", {clientNum}).as<scripting::entity>();
const auto entity_id = game::Scr_GetEntityId(clientNum, 0);
const auto result = callback(entity_id, {message, cmd == "say_team"s});
if (result.is<int>() && !hidden) scripting::notify(level, cmd, {player, message});
{ scripting::notify(player, cmd, {message});
hidden = result.as<int>() == 0;
}
}
} }
if (!hidden) return client_command_hook.invoke<void>(clientNum);
{
client_command_hook.invoke<void>(clientNum);
}
} }
} }
@ -55,20 +39,8 @@ namespace notifies
void post_unpack() override void post_unpack() override
{ {
client_command_hook.create(0x502CB0, client_command_stub); client_command_hook.create(0x502CB0, client_command_stub);
scripting::on_shutdown([]()
{
say_callbacks.clear();
});
gsc::function::add("onplayersay", [](const gsc::function_args& args) -> scripting::script_value
{
const auto function = args[0].as<scripting::function>();
say_callbacks.push_back(function);
return {};
});
} }
}; };
} }
REGISTER_COMPONENT(notifies::component) REGISTER_COMPONENT(notifies::component)

View File

@ -29,8 +29,6 @@ namespace scripting
std::string current_file; std::string current_file;
std::vector<std::function<void()>> shutdown_callbacks;
void vm_notify_stub(const unsigned int notify_list_owner_id, const unsigned int string_value, void vm_notify_stub(const unsigned int notify_list_owner_id, const unsigned int string_value,
game::VariableValue* top) game::VariableValue* top)
{ {
@ -79,12 +77,6 @@ namespace scripting
{ {
userinfo::clear_overrides(); userinfo::clear_overrides();
command::clear_script_commands(); command::clear_script_commands();
for (const auto& callback : shutdown_callbacks)
{
callback();
}
g_shutdown_game_hook.invoke<void>(free_scripts); g_shutdown_game_hook.invoke<void>(free_scripts);
} }
@ -95,7 +87,7 @@ namespace scripting
const auto file_id = atoi(filename); const auto file_id = atoi(filename);
if (file_id) if (file_id)
{ {
current_file = scripting::find_file(file_id); current_file = scripting::file_list[file_id];
} }
process_script_hook.invoke<void>(filename); process_script_hook.invoke<void>(filename);
@ -114,11 +106,6 @@ namespace scripting
} }
} }
void on_shutdown(const std::function<void()>& callback)
{
shutdown_callbacks.push_back(callback);
}
class component final : public component_interface class component final : public component_interface
{ {
public: public:
@ -136,4 +123,4 @@ namespace scripting
}; };
} }
REGISTER_COMPONENT(scripting::component) REGISTER_COMPONENT(scripting::component)

View File

@ -4,6 +4,4 @@ namespace scripting
{ {
extern std::unordered_map<int, std::unordered_map<std::string, int>> fields_table; extern std::unordered_map<int, std::unordered_map<std::string, int>> fields_table;
extern std::unordered_map<std::string, std::unordered_map<std::string, const char*>> script_function_table; extern std::unordered_map<std::string, std::unordered_map<std::string, const char*>> script_function_table;
void on_shutdown(const std::function<void()>& callback);
} }

View File

@ -1,106 +0,0 @@
#include <stdinc.hpp>
#include "signatures.hpp"
#include <utils/hook.hpp>
namespace signatures
{
size_t load_image_size()
{
MODULEINFO info{};
GetModuleInformation(GetCurrentProcess(),
GetModuleHandle("plutonium-bootstrapper-win32.exe"), &info, sizeof(MODULEINFO));
return info.SizeOfImage;
}
size_t get_image_size()
{
static const auto image_size = load_image_size();
return image_size;
}
void load_function_tables()
{
static const auto ptr = *reinterpret_cast<size_t*>(0x56CBDC + 0x1) + 0x56CBDC + 0x5;
static const auto function_table = *reinterpret_cast<size_t*>(0x56C8EB + 0x3);
static const auto method_table = *reinterpret_cast<size_t*>(ptr + 0xA);
game::plutonium::function_table.set(function_table);
game::plutonium::method_table.set(method_table);
}
size_t find_string_ptr(const std::string& string)
{
const char* string_ptr = nullptr;
std::string mask(string.size(), 'x');
const auto base = reinterpret_cast<size_t>(GetModuleHandle("plutonium-bootstrapper-win32.exe"));
utils::hook::signature signature(base, get_image_size() - base);
auto found = false;
signature.add({
string,
mask,
[&](char* address)
{
if (found)
{
return;
}
found = true;
string_ptr = address;
}
});
signature.process();
return reinterpret_cast<size_t>(string_ptr);
}
size_t find_string_ref(const std::string& string)
{
char bytes[4] = {0};
const auto string_ptr = find_string_ptr(string);
if (!string_ptr)
{
return 0;
}
std::memcpy(bytes, &string_ptr, sizeof(bytes));
return find_string_ptr({bytes, 4});
}
bool process_gsc_ctx()
{
const auto string_ref = find_string_ref("in call to builtin %s \"%s\"");
if (!string_ref)
{
return false;
}
const auto gsc_ctx_ptr = *reinterpret_cast<size_t*>(string_ref - 0xAD);
OutputDebugString(utils::string::va("gsc_ctx_ptr: %p\n", gsc_ctx_ptr));
game::plutonium::gsc_ctx.set(gsc_ctx_ptr);
return true;
}
bool process_printf()
{
const auto string_ref = find_string_ref("A critical exception occured!\n");
if (!string_ref)
{
return false;
}
const auto offset = *reinterpret_cast<size_t*>(string_ref + 5);
const auto printf_ptr = string_ref + 4 + 5 + offset;
OutputDebugString(utils::string::va("printf_ptr: %p\n", printf_ptr));
game::plutonium::printf.set(printf_ptr);
return true;
}
bool process()
{
load_function_tables();
return process_printf() && process_gsc_ctx();
}
}

View File

@ -1,6 +0,0 @@
#pragma once
namespace signatures
{
bool process();
}

View File

@ -1,46 +0,0 @@
#include <stdinc.hpp>
#include "loader/component_loader.hpp"
#include "gsc.hpp"
#include <utils/string.hpp>
namespace string
{
class component final : public component_interface
{
public:
void post_unpack() override
{
gsc::function::add("toupper", [](const gsc::function_args& args)
{
return utils::string::to_upper(args[0].as<std::string>());
});
gsc::function::add("getchar", [](const gsc::function_args& args)
{
auto index = 0;
if (args.size() > 1)
{
index = args[1].as<int>();
}
const auto string = args[0].as<std::string>();
if (index >= static_cast<int>(string.size()))
{
throw std::runtime_error("Char index out of bounds");
}
return static_cast<int>(string[index]);
});
gsc::function::add("chartostring", [](const gsc::function_args& args)
{
const auto char_ = static_cast<char>(args[0].as<int>());
return std::string(1, char_);
});
}
};
}
REGISTER_COMPONENT(string::component)

View File

@ -2,6 +2,12 @@
#include "loader/component_loader.hpp" #include "loader/component_loader.hpp"
#include "scheduler.hpp" #include "scheduler.hpp"
#include "game/scripting/event.hpp"
#include "game/scripting/execution.hpp"
#include "game/scripting/functions.hpp"
#include "game/scripting/array.hpp"
#include "gsc.hpp" #include "gsc.hpp"
namespace userinfo namespace userinfo
@ -13,17 +19,12 @@ namespace userinfo
{ {
utils::hook::detour sv_getuserinfo_hook; utils::hook::detour sv_getuserinfo_hook;
userinfo_map userinfo_to_map(std::string userinfo) userinfo_map userinfo_to_map(const std::string& userinfo)
{ {
userinfo_map map{}; userinfo_map map;
if (userinfo[0] == '\\')
{
userinfo = userinfo.substr(1);
}
const auto args = utils::string::split(userinfo, '\\'); const auto args = utils::string::split(userinfo, '\\');
for (size_t i = 0; !args.empty() && i < (args.size() - 1); i += 2)
for (auto i = 1; i < args.size() - 1; i += 2)
{ {
map[args[i]] = args[i + 1]; map[args[i]] = args[i + 1];
} }
@ -33,7 +34,7 @@ namespace userinfo
std::string map_to_userinfo(const userinfo_map& map) std::string map_to_userinfo(const userinfo_map& map)
{ {
std::string buffer{}; std::string buffer;
for (const auto& value : map) for (const auto& value : map)
{ {
@ -48,8 +49,9 @@ namespace userinfo
void sv_getuserinfo_stub(int index, char* buffer, int bufferSize) void sv_getuserinfo_stub(int index, char* buffer, int bufferSize)
{ {
sv_getuserinfo_hook.invoke<void>(index, buffer, bufferSize); char _buffer[1024];
auto map = userinfo_to_map(buffer); sv_getuserinfo_hook.invoke<void>(index, _buffer, 1024);
auto map = userinfo_to_map(_buffer);
if (userinfo_overrides.find(index) == userinfo_overrides.end()) if (userinfo_overrides.find(index) == userinfo_overrides.end())
{ {
@ -92,36 +94,28 @@ namespace userinfo
gsc::method::add("setname", [](const game::scr_entref_t ent, const gsc::function_args& args) -> scripting::script_value gsc::method::add("setname", [](const game::scr_entref_t ent, const gsc::function_args& args) -> scripting::script_value
{ {
if (ent.classnum != 0) const auto name = args[0].as<std::string>();
if (ent.classnum != 0 || ent.entnum > 17)
{ {
throw std::runtime_error("Invalid entity"); throw std::runtime_error("Invalid entity");
} }
if (game::g_entities[ent.entnum].client == nullptr)
{
throw std::runtime_error("Not a player entity");
}
const auto name = args[0].as<std::string>();
userinfo_overrides[ent.entnum]["name"] = name; userinfo_overrides[ent.entnum]["name"] = name;
game::ClientUserinfoChanged(ent.entnum); game::ClientUserinfoChanged(ent.entnum);
return {}; return {};
}); });
gsc::method::add("resetname", [](const game::scr_entref_t ent, const gsc::function_args&) -> scripting::script_value gsc::method::add("resetname", [](const game::scr_entref_t ent, const gsc::function_args& args) -> scripting::script_value
{ {
if (ent.classnum != 0) const auto name = args[0].as<std::string>();
if (ent.classnum != 0 || ent.entnum > 17)
{ {
throw std::runtime_error("Invalid entity"); throw std::runtime_error("Invalid entity");
} }
if (game::g_entities[ent.entnum].client == nullptr)
{
throw std::runtime_error("Not a player entity");
}
userinfo_overrides[ent.entnum].erase("name"); userinfo_overrides[ent.entnum].erase("name");
game::ClientUserinfoChanged(ent.entnum); game::ClientUserinfoChanged(ent.entnum);
@ -130,18 +124,13 @@ namespace userinfo
gsc::method::add("setclantag", [](const game::scr_entref_t ent, const gsc::function_args& args) -> scripting::script_value gsc::method::add("setclantag", [](const game::scr_entref_t ent, const gsc::function_args& args) -> scripting::script_value
{ {
if (ent.classnum != 0) const auto name = args[0].as<std::string>();
if (ent.classnum != 0 || ent.entnum > 17)
{ {
throw std::runtime_error("Invalid entity"); throw std::runtime_error("Invalid entity");
} }
if (game::g_entities[ent.entnum].client == nullptr)
{
throw std::runtime_error("Not a player entity");
}
const auto name = args[0].as<std::string>();
userinfo_overrides[ent.entnum]["clantag"] = name; userinfo_overrides[ent.entnum]["clantag"] = name;
userinfo_overrides[ent.entnum]["ec_TagText"] = name; userinfo_overrides[ent.entnum]["ec_TagText"] = name;
userinfo_overrides[ent.entnum]["ec_usingTag"] = "1"; userinfo_overrides[ent.entnum]["ec_usingTag"] = "1";
@ -150,18 +139,15 @@ namespace userinfo
return {}; return {};
}); });
gsc::method::add("resetclantag", [](const game::scr_entref_t ent, const gsc::function_args&) -> scripting::script_value gsc::method::add("resetclantag", [](const game::scr_entref_t ent, const gsc::function_args& args) -> scripting::script_value
{ {
if (ent.classnum != 0) const auto name = args[0].as<std::string>();
if (ent.classnum != 0 || ent.entnum > 17)
{ {
throw std::runtime_error("Invalid entity"); throw std::runtime_error("Invalid entity");
} }
if (game::g_entities[ent.entnum].client == nullptr)
{
throw std::runtime_error("Not a player entity");
}
userinfo_overrides[ent.entnum].erase("clantag"); userinfo_overrides[ent.entnum].erase("clantag");
userinfo_overrides[ent.entnum].erase("ec_TagText"); userinfo_overrides[ent.entnum].erase("ec_TagText");
userinfo_overrides[ent.entnum].erase("ec_usingTag"); userinfo_overrides[ent.entnum].erase("ec_usingTag");
@ -170,18 +156,13 @@ namespace userinfo
return {}; return {};
}); });
gsc::method::add("removeclantag", [](const game::scr_entref_t ent, const gsc::function_args&) -> scripting::script_value gsc::method::add("removeclantag", [](const game::scr_entref_t ent, const gsc::function_args& args) -> scripting::script_value
{ {
if (ent.classnum != 0) if (ent.classnum != 0 || ent.entnum > 17)
{ {
throw std::runtime_error("Invalid entity"); throw std::runtime_error("Invalid entity");
} }
if (game::g_entities[ent.entnum].client == nullptr)
{
throw std::runtime_error("Not a player entity");
}
userinfo_overrides[ent.entnum]["clantag"] = ""; userinfo_overrides[ent.entnum]["clantag"] = "";
userinfo_overrides[ent.entnum]["ec_TagText"] = ""; userinfo_overrides[ent.entnum]["ec_TagText"] = "";
userinfo_overrides[ent.entnum]["ec_usingTag"] = "0"; userinfo_overrides[ent.entnum]["ec_usingTag"] = "0";
@ -193,4 +174,4 @@ namespace userinfo
}; };
} }
REGISTER_COMPONENT(userinfo::component) REGISTER_COMPONENT(userinfo::component)

View File

@ -1,27 +1,20 @@
#include <stdinc.hpp> #include <stdinc.hpp>
#include "loader/component_loader.hpp" #include "loader/component_loader.hpp"
#include "component/signatures.hpp" BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
BOOL APIENTRY DllMain(HMODULE /*hModule*/, DWORD ul_reason_for_call, LPVOID /*lpReserved*/)
{ {
if (ul_reason_for_call == DLL_PROCESS_ATTACH) if (ul_reason_for_call == DLL_PROCESS_ATTACH)
{ {
if (!signatures::process()) const auto value = *reinterpret_cast<DWORD*>(0x20800000);
if (value != 0xB9C9566)
{ {
MessageBoxA(NULL, printf("\x1b[31m\n**************************************************************************************\n\n");
"This version of iw5-gsc-utils is outdated.\n" \ printf("This version of \x1b[33miw5-gsc-utils\x1b[31m is outdated.\n");
"Download the latest dll from here: https://github.com/fedddddd/iw5-gsc-utils/releases", printf("Download the latest dll from here:\x1b[34m https://github.com/fedddddd/iw5-gsc-utils/releases \x1b[31m\n");
"ERROR", MB_ICONERROR); printf("\n**************************************************************************************\n\n\x1b[37m");
return FALSE; return FALSE;
} }
if (game::plutonium::printf.get() != nullptr)
{
utils::hook::jump(reinterpret_cast<uintptr_t>(&printf), game::plutonium::printf);
}
component_loader::post_unpack(); component_loader::post_unpack();
} }

View File

@ -2,11 +2,5 @@
namespace game namespace game
{ {
void SV_GameDropClient(int clientNum, const char* reason)
{
if (clientNum >= 0 && clientNum < sv_maxclients->current.integer)
{
SV_DropClient(&svs_clients[clientNum], reason, true);
}
}
} }

View File

@ -16,11 +16,6 @@ namespace game
return dedi_; return dedi_;
} }
void set(const size_t dedi)
{
this->dedi_ = reinterpret_cast<T*>(dedi);
}
operator T* () const operator T* () const
{ {
return this->get(); return this->get();
@ -34,8 +29,6 @@ namespace game
private: private:
T* dedi_; T* dedi_;
}; };
void SV_GameDropClient(int clientNum, const char* reason);
} }
#include "symbols.hpp" #include "symbols.hpp"

View File

@ -60,11 +60,13 @@ namespace scripting
array::array() array::array()
{ {
this->id_ = make_array(); this->id_ = make_array();
this->add();
} }
array::array(std::vector<script_value> values) array::array(std::vector<script_value> values)
{ {
this->id_ = make_array(); this->id_ = make_array();
this->add();
for (const auto& value : values) for (const auto& value : values)
{ {
@ -75,6 +77,7 @@ namespace scripting
array::array(std::unordered_map<std::string, script_value> values) array::array(std::unordered_map<std::string, script_value> values)
{ {
this->id_ = make_array(); this->id_ = make_array();
this->add();
for (const auto& value : values) for (const auto& value : values)
{ {
@ -263,9 +266,11 @@ namespace scripting
} }
} }
void array::set(const std::string& key, const script_value& value_) const void array::set(const std::string& key, const script_value& _value) const
{ {
const auto value = value_.get_raw(); const auto value = _value.get_raw();
const auto string_value = game::SL_GetString(key.data(), 0);
const auto variable_id = this->get_value_id(key); const auto variable_id = this->get_value_id(key);
if (!variable_id) if (!variable_id)
@ -282,9 +287,9 @@ namespace scripting
variable->u.u = value.u; variable->u.u = value.u;
} }
void array::set(const unsigned int index, const script_value& value_) const void array::set(const unsigned int index, const script_value& _value) const
{ {
const auto value = value_.get_raw(); const auto value = _value.get_raw();
const auto variable_id = this->get_value_id(index); const auto variable_id = this->get_value_id(index);
if (!variable_id) if (!variable_id)

View File

@ -269,6 +269,8 @@ namespace scripting
{ {
return get_custom_field(entity, field); return get_custom_field(entity, field);
} }
return {};
} }
unsigned int make_array() unsigned int make_array()

File diff suppressed because it is too large Load Diff

View File

@ -7,20 +7,51 @@ namespace scripting
{ {
namespace namespace
{ {
int find_function_index(const std::string& name, [[maybe_unused]] const bool prefer_global) std::unordered_map<std::string, unsigned> lowercase_map(
const std::unordered_map<std::string, unsigned>& old_map)
{ {
const auto target = utils::string::to_lower(name); std::unordered_map<std::string, unsigned> new_map{};
auto const& first = (*game::plutonium::gsc_ctx)->func_map(); for (auto& entry : old_map)
auto const& second = (*game::plutonium::gsc_ctx)->meth_map();
if (const auto itr = first.find(name); itr != first.end())
{ {
return static_cast<int>(itr->second); new_map[utils::string::to_lower(entry.first)] = entry.second;
} }
if (const auto itr = second.find(name); itr != second.end()) return new_map;
}
const std::unordered_map<std::string, unsigned>& get_methods()
{
static auto methods = lowercase_map(method_map);
return methods;
}
const std::unordered_map<std::string, unsigned>& get_functions()
{
static auto function = lowercase_map(function_map);
return function;
}
int find_function_index(const std::string& name, const bool prefer_global)
{
const auto target = utils::string::to_lower(name);
const auto& primary_map = prefer_global
? get_functions()
: get_methods();
const auto& secondary_map = !prefer_global
? get_functions()
: get_methods();
auto function_entry = primary_map.find(target);
if (function_entry != primary_map.end())
{ {
return static_cast<int>(itr->second); return function_entry->second;
}
function_entry = secondary_map.find(target);
if (function_entry != secondary_map.end())
{
return function_entry->second;
} }
return -1; return -1;
@ -28,8 +59,8 @@ namespace scripting
script_function get_function_by_index(const unsigned index) script_function get_function_by_index(const unsigned index)
{ {
static const auto function_table = game::plutonium::function_table.get(); static const auto function_table = 0x20689DD8;
static const auto method_table = game::plutonium::method_table.get(); static const auto method_table = 0x2068A5A8;
if (index < 0x1C7) if (index < 0x1C7)
{ {
@ -42,26 +73,33 @@ namespace scripting
std::string find_token(unsigned int id) std::string find_token(unsigned int id)
{ {
return (*game::plutonium::gsc_ctx)->token_name(id); for (const auto& token : token_map)
} {
if (token.second == id)
{
return token.first;
}
}
std::string find_file(unsigned int id) return {};
{
return find_token(id);
} }
int find_token_id(const std::string& name) int find_token_id(const std::string& name)
{ {
return (*game::plutonium::gsc_ctx)->token_id(name); const auto result = token_map.find(name);
if (result != token_map.end())
{
return result->second;
}
return -1;
} }
script_function find_function(const std::string& name, const bool prefer_global) script_function find_function(const std::string& name, const bool prefer_global)
{ {
const auto index = find_function_index(name, prefer_global); const auto index = find_function_index(name, prefer_global);
if (index < 0) if (index < 0) return nullptr;
{
return nullptr;
}
return get_function_by_index(index); return get_function_by_index(index);
} }

View File

@ -3,10 +3,14 @@
namespace scripting namespace scripting
{ {
extern std::unordered_map<std::string, unsigned> method_map;
extern std::unordered_map<std::string, unsigned> function_map;
extern std::unordered_map<std::string, unsigned> token_map;
extern std::unordered_map<unsigned, std::string> file_list;
using script_function = void(*)(game::scr_entref_t); using script_function = void(*)(game::scr_entref_t);
script_function find_function(const std::string& name, const bool prefer_global); script_function find_function(const std::string& name, const bool prefer_global);
int find_token_id(const std::string& name); int find_token_id(const std::string& name);
std::string find_token(unsigned int id); std::string find_token(unsigned int id);
std::string find_file(unsigned int id);
} }

View File

@ -25,7 +25,7 @@ namespace scripting::safe_execution
bool call(const script_function function, const game::scr_entref_t& entref) bool call(const script_function function, const game::scr_entref_t& entref)
{ {
*game::g_script_error_level += 1; *game::g_script_error_level += 1;
if (game::_setjmp(&game::g_script_error[*game::g_script_error_level], 0, 0, 0)) if (game::_setjmp(&game::g_script_error[*game::g_script_error_level]))
{ {
*game::g_script_error_level -= 1; *game::g_script_error_level -= 1;
return false; return false;
@ -39,7 +39,7 @@ namespace scripting::safe_execution
bool set_entity_field(const game::scr_entref_t& entref, const int offset) bool set_entity_field(const game::scr_entref_t& entref, const int offset)
{ {
*game::g_script_error_level += 1; *game::g_script_error_level += 1;
if (game::_setjmp(&game::g_script_error[*game::g_script_error_level], 0, 0, 0)) if (game::_setjmp(&game::g_script_error[*game::g_script_error_level]))
{ {
*game::g_script_error_level -= 1; *game::g_script_error_level -= 1;
return false; return false;
@ -54,7 +54,7 @@ namespace scripting::safe_execution
bool get_entity_field(const game::scr_entref_t& entref, const int offset, game::VariableValue* value) bool get_entity_field(const game::scr_entref_t& entref, const int offset, game::VariableValue* value)
{ {
*game::g_script_error_level += 1; *game::g_script_error_level += 1;
if (game::_setjmp(&game::g_script_error[*game::g_script_error_level], 0, 0, 0)) if (game::_setjmp(&game::g_script_error[*game::g_script_error_level]))
{ {
value->type = game::SCRIPT_NONE; value->type = game::SCRIPT_NONE;
value->u.intValue = 0; value->u.intValue = 0;

View File

@ -82,11 +82,6 @@ namespace scripting
return "array"; return "array";
} }
if (info == typeid(function))
{
return "function";
}
if (info == typeid(vector)) if (info == typeid(vector))
{ {
return "vector"; return "vector";

View File

@ -26,35 +26,20 @@ namespace game
const char** argv[8]; const char** argv[8];
}; };
enum netsrc_t
{
NS_CLIENT1 = 0x0,
NS_CLIENT2 = 0x1,
NS_CLIENT3 = 0x2,
NS_CLIENT4 = 0x3,
NS_MAXCLIENTS = 0x4,
NS_SERVER = 0x4,
NS_PACKET = 0x5,
NS_INVALID_NETSRC = 0x6
};
struct msg_t struct msg_t
{ {
int overflowed; int overflowed;
int readOnly; int readOnly;
unsigned char* data; char* data;
unsigned char* splitData; char* splitData;
int maxsize; int maxsize;
int cursize; int cursize;
int splitSize; int splitSize;
int readcount; int readcount;
int bit; int bit;
int lastEntityRef; int lastEntityRef;
netsrc_t targetLocalNetID;
}; };
static_assert(sizeof(msg_t) == 0x2C);
struct XZoneInfo struct XZoneInfo
{ {
const char* name; const char* name;
@ -342,88 +327,4 @@ namespace game
int flags; int flags;
char __pad2[0xEC]; char __pad2[0xEC];
}; };
enum netadrtype_t
{
NA_BOT = 0x0,
NA_BAD = 0x1,
NA_LOOPBACK = 0x2,
NA_BROADCAST = 0x3,
NA_IP = 0x4
};
struct netadr_s
{
netadrtype_t type;
unsigned char ip[4];
unsigned __int16 port;
unsigned char ipx[10];
unsigned int addrHandleIndex;
};
static_assert(sizeof(netadr_s) == 24);
struct netchan_t
{
int outgoingSequence;
netsrc_t sock;
int dropped;
int incomingSequence;
netadr_s remoteAddress;
int qport;
int fragmentSequence;
int fragmentLength;
unsigned char* fragmentBuffer;
int fragmentBufferSize;
int unsentFragments;
int unsentFragmentStart;
int unsentLength;
unsigned char* unsentBuffer;
int unsentBufferSize;
unsigned char __pad0[0x5E0];
};
static_assert(sizeof(netchan_t) == 0x630);
enum clientState_t
{
CS_FREE = 0,
CS_ZOMBIE = 1,
CS_RECONNECTING = 2,
CS_CONNECTED = 3,
CS_CLIENTLOADING = 4,
CS_ACTIVE = 5
};
struct clientHeader_t
{
clientState_t state; // 0
int sendAsActive; // 4
int deltaMessage; // 8
int rateDealyed; // 12
int hasAckedBaselineData; // 16
int hugeSnapshotSent; // 20
netchan_t netchan; // 24
vec3_t predictedOrigin;
int predictedOriginServerTime;
int migrationState;
vec3_t predictedVehicleOrigin;
int predictedVehicleServerTime;
};
static_assert(sizeof(clientHeader_t) == 0x66C);
struct client_s
{
clientHeader_t header;
const char* dropReason;
char userinfo[1024];
char __pad0[0x41242];
unsigned __int16 scriptId; // 269490
int bIsTestClient; // 269492
int serverId; // 269496
char __pad1[0x369DC];
};
static_assert(sizeof(client_s) == 0x78698);
} }

View File

@ -57,13 +57,12 @@ namespace game
WEAK symbol<void(int clientNum, int type, const char* command)> SV_GameSendServerCommand{0x573220}; WEAK symbol<void(int clientNum, int type, const char* command)> SV_GameSendServerCommand{0x573220};
WEAK symbol<void(int arg, char* buffer, int bufferLength)> SV_Cmd_ArgvBuffer{0x5459F0}; WEAK symbol<void(int arg, char* buffer, int bufferLength)> SV_Cmd_ArgvBuffer{0x5459F0};
WEAK symbol<void(client_s* drop, const char* reason, bool tellThem)> SV_DropClient{0x570980};
WEAK symbol<void(unsigned int notifyListOwnerId, unsigned int stringValue, VariableValue* top)> VM_Notify{0x569720}; WEAK symbol<void(unsigned int notifyListOwnerId, unsigned int stringValue, VariableValue* top)> VM_Notify{0x569720};
WEAK symbol<unsigned int(unsigned int localId, const char* pos, unsigned int paramcount)> VM_Execute{0x56DFE0}; WEAK symbol<unsigned int(unsigned int localId, const char* pos, unsigned int paramcount)> VM_Execute{0x56DFE0};
WEAK symbol<void* (jmp_buf* Buf, int Value)> longjmp{0x7363BC}; WEAK symbol<void* (jmp_buf* Buf, int Value)> longjmp{0x7363BC};
WEAK symbol<int(jmp_buf* Buf, int a2, int a3, int a4)> _setjmp{0x734CF8}; WEAK symbol<int(jmp_buf* Buf)> _setjmp{0x734CF8};
// Variables // Variables
@ -80,15 +79,10 @@ namespace game
WEAK symbol<gentity_s> g_entities{0x1A66E28}; WEAK symbol<gentity_s> g_entities{0x1A66E28};
WEAK symbol<unsigned int> levelEntityId{0x208E1A4}; WEAK symbol<unsigned int> levelEntityId{0x208E1A4};
WEAK symbol<dvar_t> sv_maxclients{0x1BA0E4C};
WEAK symbol<int> svs_clientCount{0x4B5CF8C};
WEAK symbol<client_s> svs_clients{0x4B5CF90};
namespace plutonium namespace plutonium
{ {
WEAK symbol<std::unique_ptr<xsk::gsc::iw5_pc::context>> gsc_ctx{0}; WEAK symbol<std::unordered_map<std::string, std::uint16_t>> function_map_rev{0x20691228};
WEAK symbol<int(const char* fmt, ...)> printf{0}; WEAK symbol<std::unordered_map<std::string, std::uint16_t>> method_map_rev{0x20691248};
WEAK symbol<void*> function_table{0}; WEAK symbol<std::unordered_map<std::string, std::uint16_t>> token_map_rev{0x20691288};
WEAK symbol<void*> method_table{0};
} }
} }

View File

@ -8,8 +8,6 @@
#pragma warning(disable: 4996) #pragma warning(disable: 4996)
#pragma warning(disable: 26812) #pragma warning(disable: 26812)
#include <xsk/gsc/engine/iw5_pc.hpp>
#define DLL_EXPORT extern "C" __declspec(dllexport) #define DLL_EXPORT extern "C" __declspec(dllexport)
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#include <windows.h> #include <windows.h>
@ -30,7 +28,6 @@
#include <map> #include <map>
#include <csetjmp> #include <csetjmp>
#include <atlcomcli.h> #include <atlcomcli.h>
#include <Psapi.h>
#pragma comment(lib, "urlmon.lib") #pragma comment(lib, "urlmon.lib")
@ -39,7 +36,6 @@ using namespace std::literals;
#include <gsl/gsl> #include <gsl/gsl>
#include <MinHook.h> #include <MinHook.h>
#include "utils/memory.hpp" #include "utils/memory.hpp"
#include "utils/string.hpp" #include "utils/string.hpp"
#include "utils/hook.hpp" #include "utils/hook.hpp"
@ -49,4 +45,4 @@ using namespace std::literals;
#include "utils/http.hpp" #include "utils/http.hpp"
#include "game/structs.hpp" #include "game/structs.hpp"
#include "game/game.hpp" #include "game/game.hpp"

View File

@ -4,48 +4,6 @@
namespace utils::hook namespace utils::hook
{ {
// open-iw5
void signature::process()
{
if (this->signatures_.empty()) return;
const auto start = static_cast<char*>(this->start_);
const unsigned int sig_count = this->signatures_.size();
const auto containers = this->signatures_.data();
for (size_t i = 0; i < this->length_; ++i)
{
const auto address = start + i;
for (unsigned int k = 0; k < sig_count; ++k)
{
const auto container = &containers[k];
unsigned int j;
for (j = 0; j < static_cast<unsigned int>(container->mask.size()); ++j)
{
if (container->mask[j] != '?' && container->signature[j] != address[j])
{
break;
}
}
if (j == container->mask.size())
{
container->callback(address);
}
}
}
}
void signature::add(const container& container)
{
signatures_.push_back(container);
}
namespace namespace
{ {
[[maybe_unused]] class _ [[maybe_unused]] class _

View File

@ -4,37 +4,6 @@
namespace utils::hook namespace utils::hook
{ {
class signature final
{
public:
struct container final
{
std::string signature;
std::string mask;
std::function<void(char*)> callback;
};
signature(void* start, const size_t length) : start_(start), length_(length)
{
}
signature(const DWORD start, const size_t length) : signature(reinterpret_cast<void*>(start), length)
{
}
signature() : signature(0x400000, 0x800000)
{
}
void process();
void add(const container& container);
private:
void* start_;
size_t length_;
std::vector<container> signatures_;
};
class detour class detour
{ {
public: public:

View File

@ -1,14 +1,8 @@
#include <stdinc.hpp> #include <stdinc.hpp>
#include <fstream> #include <fstream>
#include "io.hpp"
namespace utils::io namespace utils::io
{ {
bool remove_file(const std::string& file)
{
return DeleteFileA(file.data()) == TRUE;
}
bool file_exists(const std::string& file) bool file_exists(const std::string& file)
{ {
return std::ifstream(file).good(); return std::ifstream(file).good();

View File

@ -6,7 +6,6 @@
namespace utils::io namespace utils::io
{ {
bool remove_file(const std::string& file);
bool file_exists(const std::string& file); bool file_exists(const std::string& file);
bool write_file(const std::string& file, const std::string& data, bool append = false); bool write_file(const std::string& file, const std::string& data, bool append = false);
bool read_file(const std::string& file, std::string* data); bool read_file(const std::string& file, std::string* data);

Binary file not shown.

BIN
tools/windows/premake5.exe Normal file

Binary file not shown.