Logfile + scripting

This commit is contained in:
Federico Cecchetto 2022-05-24 21:55:53 +02:00
parent a1d2252f6c
commit a88f117c6e
9 changed files with 83 additions and 134 deletions

View File

@ -6,6 +6,7 @@
#include "game_console.hpp"
#include "fastfiles.hpp"
#include "scheduler.hpp"
#include "logfile.hpp"
#include "game/game.hpp"
#include "game/dvars.hpp"
@ -40,6 +41,11 @@ namespace command
void client_command(const int client_num)
{
if (!logfile::client_command_stub(client_num))
{
return;
}
params_sv params = {};
const auto command = utils::string::to_lower(params[0]);

View File

@ -270,7 +270,15 @@ namespace console
void post_unpack() override
{
ShowWindow(GetConsoleWindow(), SW_SHOW);
if (game::environment::is_dedi())
{
ShowWindow(GetConsoleWindow(), SW_HIDE);
}
else
{
ShowWindow(GetConsoleWindow(), SW_SHOW);
}
SetConsoleTitle("H1-Mod");
con.kill_event = CreateEvent(NULL, TRUE, FALSE, NULL);

View File

@ -12,36 +12,6 @@
namespace filesystem
{
namespace
{
bool custom_path_registered = false;
std::string get_binary_directory()
{
const auto dir = game_module::get_host_module().get_folder();
return utils::string::replace(dir, "/", "\\");
}
void register_custom_path_stub(const char* path, const char* dir)
{
if (!custom_path_registered)
{
custom_path_registered = true;
const auto launcher_dir = get_binary_directory();
game::FS_AddLocalizedGameDirectory(launcher_dir.data(), "data");
}
game::FS_AddLocalizedGameDirectory(path, dir);
}
void fs_startup_stub(const char* gamename)
{
custom_path_registered = false;
game::FS_Startup(gamename);
}
}
file::file(std::string name)
: name_(std::move(name))
{
@ -110,19 +80,6 @@ namespace filesystem
public:
void post_unpack() override
{
// Set fs_basegame
dvars::override::register_string("fs_basegame", "h1-mod", game::DVAR_FLAG_WRITE);
utils::hook::call(SELECT_VALUE(0x1403B76E2, 0x1404ED3E2), fs_startup_stub);
if (game::environment::is_mp())
{
utils::hook::call(0x1404ED823, fs_startup_stub);
}
utils::hook::call(SELECT_VALUE(0x1403B8D31, 0x1404EE3D0), register_custom_path_stub);
utils::hook::call(SELECT_VALUE(0x1403B8D51, 0x1404EE3F0), register_custom_path_stub);
utils::hook::call(SELECT_VALUE(0x1403B8D90, 0x1404EE42F), register_custom_path_stub);
get_search_paths().insert(".");
get_search_paths().insert("h1-mod");
get_search_paths().insert("data");
@ -130,4 +87,4 @@ namespace filesystem
};
}
//REGISTER_COMPONENT(filesystem::component)
REGISTER_COMPONENT(filesystem::component)

View File

@ -2,15 +2,10 @@
#include "loader/component_loader.hpp"
#include "scheduler.hpp"
#include "game/scripting/entity.hpp"
#include "game/scripting/execution.hpp"
#include "game/scripting/lua/value_conversion.hpp"
#include "game/scripting/lua/error.hpp"
#include "logfile.hpp"
#include <utils/hook.hpp>
#include "logfile.hpp"
namespace logfile
{
std::unordered_map<const char*, sol::protected_function> vm_execute_hooks;
@ -20,6 +15,9 @@ namespace logfile
utils::hook::detour scr_player_killed_hook;
utils::hook::detour scr_player_damage_hook;
utils::hook::detour client_command_hook;
utils::hook::detour g_shutdown_game_hook;
std::vector<sol::protected_function> player_killed_callbacks;
std::vector<sol::protected_function> player_damage_callbacks;
@ -147,51 +145,6 @@ namespace logfile
meansOfDeath, weapon, isAlternate, vPoint, vDir, hitLoc, timeOffset);
}
void client_command_stub(const int clientNum)
{
auto self = &game::mp::g_entities[clientNum];
char cmd[1024] = {0};
game::SV_Cmd_ArgvBuffer(0, cmd, 1024);
if (cmd == "say"s || cmd == "say_team"s)
{
auto hidden = false;
std::string message(game::ConcatArgs(1));
hidden = message[1] == '/';
message.erase(0, hidden ? 2 : 1);
scheduler::once([cmd, message, self]()
{
const scripting::entity level{*game::levelEntityId};
const scripting::entity player{game::Scr_GetEntityId(self->s.entityNum, 0)};
scripting::notify(level, cmd, {player, message});
scripting::notify(player, cmd, {message});
}, scheduler::pipeline::server);
if (hidden)
{
return;
}
}
// ClientCommand
return utils::hook::invoke<void>(0x4132E0_b, clientNum);
}
void g_shutdown_game_stub(const int freeScripts)
{
{
const scripting::entity level{*game::levelEntityId};
scripting::notify(level, "shutdownGame_called", {1});
}
// G_ShutdownGame
return utils::hook::invoke<void>(0x422F30_b, freeScripts);
}
unsigned int local_id_to_entity(unsigned int local_id)
{
const auto variable = game::scr_VarGlob->objectVariableValue[local_id];
@ -291,27 +244,55 @@ namespace logfile
hook_enabled = false;
}
bool client_command_stub(const int client_num)
{
auto self = &game::mp::g_entities[client_num];
char cmd[1024] = {0};
game::SV_Cmd_ArgvBuffer(0, cmd, 1024);
if (cmd == "say"s || cmd == "say_team"s)
{
auto hidden = false;
std::string message(game::ConcatArgs(1));
hidden = message[1] == '/';
message.erase(0, hidden ? 2 : 1);
scheduler::once([cmd, message, self, hidden]()
{
const scripting::entity level{*game::levelEntityId};
const scripting::entity player{game::Scr_GetEntityId(self->s.entityNum, 0)};
scripting::notify(level, cmd, {player, message, hidden});
scripting::notify(player, cmd, {message, hidden});
}, scheduler::pipeline::server);
if (hidden)
{
return false;
}
}
return true;
}
class component final : public component_interface
{
public:
void post_unpack() override
{
utils::hook::jump(SELECT_VALUE(0x0, 0x444645_b), utils::hook::assemble(vm_execute_stub), true);
utils::hook::jump(SELECT_VALUE(0x0, 0x5111A5_b), utils::hook::assemble(vm_execute_stub), true);
if (game::environment::is_sp())
{
return;
}
utils::hook::call(0x54EB46_b, client_command_stub);
scr_player_damage_hook.create(0x1CE780_b, scr_player_damage_stub);
scr_player_killed_hook.create(0x1CEA60_b, scr_player_killed_stub);
utils::hook::call(0x5520E0_b, g_shutdown_game_stub);
utils::hook::call(0x5525E1_b, g_shutdown_game_stub);
}
};
}
//REGISTER_COMPONENT(logfile::component)
REGISTER_COMPONENT(logfile::component)

View File

@ -1,5 +1,10 @@
#pragma once
#include "game/scripting/entity.hpp"
#include "game/scripting/execution.hpp"
#include "game/scripting/lua/value_conversion.hpp"
#include "game/scripting/lua/error.hpp"
namespace logfile
{
extern std::unordered_map<const char*, sol::protected_function> vm_execute_hooks;
@ -10,4 +15,6 @@ namespace logfile
void enable_vm_execute_hook();
void disable_vm_execute_hook();
bool client_command_stub(const int client_num);
}

View File

@ -94,6 +94,7 @@ namespace scripting
script_function_table.clear();
}
scripting::notify(*game::levelEntityId, "shutdownGame_called", {1});
lua::engine::stop();
return g_shutdown_game_hook.invoke<void>(free_scripts);
}
@ -159,26 +160,6 @@ namespace scripting
scripting::token_map[str] = result;
return result;
}
game::XAssetHeader db_find_xasset_header_stub(game::XAssetType type, const char* name, int allow_create_default)
{
const auto result = db_find_xasset_header_hook.invoke<game::XAssetHeader>(type, name, allow_create_default);
if (!g_dump_scripts->current.enabled || type != game::XAssetType::ASSET_TYPE_SCRIPTFILE)
{
return result;
}
std::string buffer;
buffer.append(result.scriptfile->name, strlen(result.scriptfile->name) + 1);
buffer.append(reinterpret_cast<char*>(&result.scriptfile->compressedLen), 4);
buffer.append(reinterpret_cast<char*>(&result.scriptfile->len), 4);
buffer.append(reinterpret_cast<char*>(&result.scriptfile->bytecodeLen), 4);
buffer.append(result.scriptfile->buffer, result.scriptfile->compressedLen);
buffer.append(result.scriptfile->bytecode, result.scriptfile->bytecodeLen);
utils::io::write_file(utils::string::va("gsc_dump/%s.gscbin", name), buffer);
return result;
}
}
class component final : public component_interface
@ -205,9 +186,6 @@ namespace scripting
g_shutdown_game_hook.create(SELECT_VALUE(0x0, 0x422F30_b), g_shutdown_game_stub);
db_find_xasset_header_hook.create(game::DB_FindXAssetHeader, db_find_xasset_header_stub);
g_dump_scripts = dvars::register_bool("g_dumpScripts", false, game::DVAR_FLAG_NONE, "Dump GSC scripts");
scheduler::loop([]()
{
lua::engine::run_frame();
@ -216,4 +194,4 @@ namespace scripting
};
}
//REGISTER_COMPONENT(scripting::component)
REGISTER_COMPONENT(scripting::component)

View File

@ -12,6 +12,7 @@
#include "game_module.hpp"
#include "fps.hpp"
#include "server_list.hpp"
#include "filesystem.hpp"
#include "game/ui_scripting/execution.hpp"
#include "game/scripting/execution.hpp"
@ -223,8 +224,19 @@ namespace ui_scripting
load_script("lui_common", lui_common);
load_scripts("h1-mod/ui_scripts/");
load_scripts("data/ui_scripts/");
for (const auto& path : filesystem::get_search_paths())
{
load_scripts(path + "/ui_scripts/");
if (game::environment::is_sp())
{
load_scripts(path + "/ui_scripts/sp/");
}
else
{
load_scripts(path + "/ui_scripts/mp/");
}
}
}
void try_start()

View File

@ -59,10 +59,10 @@ namespace scripting
script_function get_function_by_index(const unsigned index)
{
static const auto function_table = SELECT_VALUE(0x14B1D1B90, 0xAC85070_b);
static const auto function_table = SELECT_VALUE(0x14B1D1B90, 0xAC83820_b);
static const auto method_table = SELECT_VALUE(0x14B1D33A0, 0xAC85070_b);
if (index < 0x301)
if (index < 0x30A)
{
return reinterpret_cast<script_function*>(function_table)[index - 1];
}

View File

@ -74,7 +74,7 @@ namespace game
float w, float min, float max, unsigned int flags)> Dvar_RegisterVec4{0x0, 0x183010};
WEAK symbol<long long(const char* qpath, char** buffer)> FS_ReadFile{0x0, 0x1EC690};
WEAK symbol<void(void* buffer)> FS_FreeFile{0x0, 0x0};
WEAK symbol<void(void* buffer)> FS_FreeFile{0x0, 0x59E2F0};
WEAK symbol<void(const char* gameName)> FS_Startup{0x0, 0x0};
WEAK symbol<void(const char* path, const char* dir)> FS_AddLocalizedGameDirectory{0x0, 0x1878F0};
@ -204,8 +204,8 @@ namespace game
WEAK symbol<const char*(const char* string)> UI_SafeTranslateString{0x0, 0x4E8BC0};
WEAK symbol<void*(jmp_buf* Buf, int Value)> longjmp{0x0, 0x0};
WEAK symbol<int(jmp_buf* Buf)> _setjmp{0x0, 0x0};
WEAK symbol<void*(jmp_buf* Buf, int Value)> longjmp{0x0, 0x826710};
WEAK symbol<int(jmp_buf* Buf)> _setjmp{0x0, 0x8A3190};
/***************************************************************
* Variables