[Events] Group game events callbacks in one module (#306)

This commit is contained in:
Edo 2022-06-13 20:16:57 +02:00 committed by GitHub
parent e754e9d56a
commit 0a852c6431
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 119 additions and 84 deletions

3
.github/CODEOWNERS vendored Normal file
View File

@ -0,0 +1,3 @@
# SPDX-License-Identifier: GPL-3.0
* @XLabsProject/Developers

View File

@ -112,6 +112,7 @@ namespace Components
Loader::Register(new MapRotation()); Loader::Register(new MapRotation());
Loader::Register(new Ceg()); Loader::Register(new Ceg());
Loader::Register(new UserInfo()); Loader::Register(new UserInfo());
Loader::Register(new Events());
Loader::Pregame = false; Loader::Pregame = false;
} }

View File

@ -143,3 +143,4 @@ namespace Components
#include "Modules/MapRotation.hpp" #include "Modules/MapRotation.hpp"
#include "Modules/Ceg.hpp" #include "Modules/Ceg.hpp"
#include "Modules/UserInfo.hpp" #include "Modules/UserInfo.hpp"
#include "Modules/Events.hpp"

View File

@ -309,21 +309,6 @@ namespace Components
} }
} }
/*
* Should be called when a client drops from the server
* but not "between levels" (Quake-III-Arena)
*/
void Bots::ClientDisconnect_Hk(const int clientNum)
{
g_botai[clientNum].active = false;
// Clear the overrides for UserInfo
UserInfo::ClearClientOverrides(clientNum);
// Call original function
Utils::Hook::Call<void(int)>(0x4AA430)(clientNum);
}
Bots::Bots() Bots::Bots()
{ {
AssertOffset(Game::client_s, bIsTestClient, 0x41AF0); AssertOffset(Game::client_s, bIsTestClient, 0x41AF0);
@ -340,7 +325,10 @@ namespace Components
Utils::Hook(0x441B80, Bots::G_SelectWeaponIndex_Hk, HOOK_JUMP).install()->quick(); Utils::Hook(0x441B80, Bots::G_SelectWeaponIndex_Hk, HOOK_JUMP).install()->quick();
// Reset BotMovementInfo.active when client is dropped // Reset BotMovementInfo.active when client is dropped
Utils::Hook(0x625235, Bots::ClientDisconnect_Hk, HOOK_CALL).install()->quick(); Events::OnClientDisconnect([](const int clientNum)
{
g_botai[clientNum].active = false;
});
// Zero the bot command array // Zero the bot command array
for (auto i = 0u; i < std::extent_v<decltype(g_botai)>; i++) for (auto i = 0u; i < std::extent_v<decltype(g_botai)>; i++)
@ -393,9 +381,9 @@ namespace Components
Bots::AddMethods(); Bots::AddMethods();
// In case a loaded mod didn't call "BotStop" before the VM shutdown // In case a loaded mod didn't call "BotStop" before the VM shutdown
Script::OnVMShutdown([] Events::OnVMShutdown([]
{ {
for (auto i = 0u; i < std::extent_v<decltype(g_botai)>; i++) for (std::size_t i = 0; i < std::extent_v<decltype(g_botai)>; i++)
{ {
g_botai[i].active = false; g_botai[i].active = false;
} }

View File

@ -22,7 +22,5 @@ namespace Components
static void G_SelectWeaponIndex(int clientNum, int iWeaponIndex); static void G_SelectWeaponIndex(int clientNum, int iWeaponIndex);
static void G_SelectWeaponIndex_Hk(); static void G_SelectWeaponIndex_Hk();
static void ClientDisconnect_Hk(int clientNum);
}; };
} }

View File

@ -961,7 +961,7 @@ namespace Components
}, Scheduler::Pipeline::MAIN); }, Scheduler::Pipeline::MAIN);
Script::OnVMShutdown([]() Events::OnVMShutdown([]()
{ {
Download::ScriptDownloads.clear(); Download::ScriptDownloads.clear();
}); });

View File

@ -377,6 +377,9 @@ namespace Components
// If the game closed abruptly, the dvars would not have been restored // If the game closed abruptly, the dvars would not have been restored
Scheduler::Once(Dvar::ResetDvarsValue, Scheduler::Pipeline::MAIN); Scheduler::Once(Dvar::ResetDvarsValue, Scheduler::Pipeline::MAIN);
// Reset archive dvars when client leaves a server
Events::OnSteamDisconnect(Dvar::ResetDvarsValue);
} }
Dvar::~Dvar() Dvar::~Dvar()

View File

@ -0,0 +1,58 @@
#include <STDInclude.hpp>
namespace Components
{
Utils::Signal<Events::ClientCallback> Events::ClientDisconnectSignal;
Utils::Signal<Events::Callback> Events::SteamDisconnectSignal;
Utils::Signal<Events::Callback> Events::ShutdownSystemSignal;
void Events::OnClientDisconnect(const Utils::Slot<ClientCallback>& callback)
{
ClientDisconnectSignal.connect(callback);
}
void Events::OnSteamDisconnect(const Utils::Slot<Callback>& callback)
{
SteamDisconnectSignal.connect(callback);
}
void Events::OnVMShutdown(const Utils::Slot<Callback>& callback)
{
ShutdownSystemSignal.connect(callback);
}
/*
* Should be called when a client drops from the server
* but not "between levels" (Quake-III-Arena)
*/
void Events::ClientDisconnect_Hk(const int clientNum)
{
ClientDisconnectSignal(clientNum);
Utils::Hook::Call<void(int)>(0x4AA430)(clientNum); // ClientDisconnect
}
void Events::SteamDisconnect_Hk()
{
SteamDisconnectSignal();
Utils::Hook::Call<void()>(0x467CC0)(); // LiveSteam_Client_SteamDisconnect
}
void Events::Scr_ShutdownSystem_Hk(unsigned char sys)
{
ShutdownSystemSignal();
Utils::Hook::Call<void(unsigned char)>(0x421EE0)(sys); // Scr_ShutdownSystem
}
Events::Events()
{
Utils::Hook(0x625235, ClientDisconnect_Hk, HOOK_CALL).install()->quick(); // SV_FreeClient
Utils::Hook(0x403582, SteamDisconnect_Hk, HOOK_CALL).install()->quick(); // CL_Disconnect
Utils::Hook(0x47548B, Scr_ShutdownSystem_Hk, HOOK_CALL).install()->quick(); // G_LoadGame
Utils::Hook(0x4D06BA, Scr_ShutdownSystem_Hk, HOOK_CALL).install()->quick(); // G_ShutdownGame
}
}

View File

@ -0,0 +1,30 @@
#pragma once
namespace Components
{
class Events : public Component
{
public:
typedef void(ClientCallback)(int clientNum);
typedef void(Callback)();
Events();
// Server side
static void OnClientDisconnect(const Utils::Slot<ClientCallback>& callback);
// Client side
static void OnSteamDisconnect(const Utils::Slot<Callback>& callback);
static void OnVMShutdown(const Utils::Slot<Callback>& callback);
private:
static Utils::Signal<ClientCallback> ClientDisconnectSignal;
static Utils::Signal<Callback> SteamDisconnectSignal;
static Utils::Signal<Callback> ShutdownSystemSignal;
static void ClientDisconnect_Hk(int clientNum);
static void SteamDisconnect_Hk();
static void Scr_ShutdownSystem_Hk(unsigned char sys);
};
}

View File

@ -457,22 +457,6 @@ namespace Components
Friends::CurrentFriend = index; Friends::CurrentFriend = index;
} }
__declspec(naked) void Friends::DisconnectStub()
{
__asm
{
pushad
call Friends::ClearServer
call Dvar::ResetDvarsValue
popad
push 467CC0h
retn
}
}
void Friends::AddFriend(SteamID user) void Friends::AddFriend(SteamID user)
{ {
if (Steam::Proxy::ClientFriends && Steam::Proxy::SteamFriends) if (Steam::Proxy::ClientFriends && Steam::Proxy::SteamFriends)
@ -622,7 +606,8 @@ namespace Components
}); });
// Update state when connecting/disconnecting // Update state when connecting/disconnecting
Utils::Hook(0x403582, Friends::DisconnectStub, HOOK_CALL).install()->quick(); Events::OnSteamDisconnect(Friends::ClearServer);
Utils::Hook(0x4CD023, Friends::SetServer, HOOK_JUMP).install()->quick(); Utils::Hook(0x4CD023, Friends::SetServer, HOOK_JUMP).install()->quick();
// Show blue icons on the minimap // Show blue icons on the minimap

View File

@ -77,7 +77,6 @@ namespace Components
static std::recursive_mutex Mutex; static std::recursive_mutex Mutex;
static std::vector<Friend> FriendsList; static std::vector<Friend> FriendsList;
static void DisconnectStub();
static void ClearServer(); static void ClearServer();
static void SetServer(); static void SetServer();

View File

@ -14,8 +14,6 @@ namespace Components
const char* Script::ReplacedPos = nullptr; const char* Script::ReplacedPos = nullptr;
int Script::LastFrameTime = -1; int Script::LastFrameTime = -1;
Utils::Signal<Script::Callback> Script::VMShutdownSignal;
void Script::FunctionError() void Script::FunctionError()
{ {
const auto* funcName = Game::SL_ConvertToString(Script::FunctionName); const auto* funcName = Game::SL_ConvertToString(Script::FunctionName);
@ -411,20 +409,6 @@ namespace Components
} }
} }
void Script::OnVMShutdown(Utils::Slot<Script::Callback> callback)
{
Script::ScriptBaseProgramNum.clear();
Script::VMShutdownSignal.connect(std::move(callback));
}
void Script::ScrShutdownSystemStub(unsigned char sys)
{
Script::VMShutdownSignal();
// Scr_ShutdownSystem
Utils::Hook::Call<void(unsigned char)>(0x421EE0)(sys);
}
unsigned int Script::SetExpFogStub() unsigned int Script::SetExpFogStub()
{ {
if (Game::Scr_GetNumParam() == 6u) if (Game::Scr_GetNumParam() == 6u)
@ -715,9 +699,6 @@ namespace Components
Utils::Hook(0x61E92E, Script::VMExecuteInternalStub, HOOK_JUMP).install()->quick(); Utils::Hook(0x61E92E, Script::VMExecuteInternalStub, HOOK_JUMP).install()->quick();
Utils::Hook::Nop(0x61E933, 1); Utils::Hook::Nop(0x61E933, 1);
Utils::Hook(0x47548B, Script::ScrShutdownSystemStub, HOOK_CALL).install()->quick(); // G_LoadGame
Utils::Hook(0x4D06BA, Script::ScrShutdownSystemStub, HOOK_CALL).install()->quick(); // G_ShutdownGame
Scheduler::Loop([]() Scheduler::Loop([]()
{ {
if (!Game::SV_Loaded()) if (!Game::SV_Loaded())
@ -753,14 +734,9 @@ namespace Components
Script::AddFunctions(); Script::AddFunctions();
Script::OnVMShutdown([] Events::OnVMShutdown([]
{ {
Script::ReplacedFunctions.clear(); Script::ReplacedFunctions.clear();
}); });
} }
Script::~Script()
{
Script::VMShutdownSignal.clear();
}
} }

View File

@ -7,17 +7,12 @@ namespace Components
{ {
public: public:
Script(); Script();
~Script();
typedef void(Callback)();
static int LoadScriptAndLabel(const std::string& script, const std::string& label); static int LoadScriptAndLabel(const std::string& script, const std::string& label);
static void AddFunction(const char* name, Game::BuiltinFunction func, int type = 0); static void AddFunction(const char* name, Game::BuiltinFunction func, int type = 0);
static void AddMethod(const char* name, Game::BuiltinMethod func, int type = 0); static void AddMethod(const char* name, Game::BuiltinMethod func, int type = 0);
static void OnVMShutdown(Utils::Slot<Script::Callback> callback);
static Game::client_t* GetClient(const Game::gentity_t* gentity); static Game::client_t* GetClient(const Game::gentity_t* gentity);
private: private:
@ -33,8 +28,6 @@ namespace Components
static const char* ReplacedPos; static const char* ReplacedPos;
static int LastFrameTime; static int LastFrameTime;
static Utils::Signal<Script::Callback> VMShutdownSignal;
static void CompileError(unsigned int offset, const char* message, ...); static void CompileError(unsigned int offset, const char* message, ...);
static void PrintSourcePos(const char* filename, unsigned int offset); static void PrintSourcePos(const char* filename, unsigned int offset);
@ -54,7 +47,6 @@ namespace Components
static Game::BuiltinFunction BuiltIn_GetFunctionStub(const char** pName, int* type); static Game::BuiltinFunction BuiltIn_GetFunctionStub(const char** pName, int* type);
static Game::BuiltinMethod BuiltIn_GetMethod(const char** pName, int* type); static Game::BuiltinMethod BuiltIn_GetMethod(const char** pName, int* type);
static void ScrShutdownSystemStub(unsigned char sys);
static void StoreScriptBaseProgramNumStub(); static void StoreScriptBaseProgramNumStub();
static void StoreScriptBaseProgramNum(); static void StoreScriptBaseProgramNum();
static void Scr_PrintPrevCodePosStub(); static void Scr_PrintPrevCodePosStub();

View File

@ -31,9 +31,9 @@ namespace Components
strncpy_s(buffer, bufferSize, userInfo.data(), _TRUNCATE); strncpy_s(buffer, bufferSize, userInfo.data(), _TRUNCATE);
} }
void UserInfo::ClearClientOverrides(const int client) void UserInfo::ClearClientOverrides(const int clientNum)
{ {
UserInfoOverrides[client].clear(); UserInfoOverrides[clientNum].clear();
} }
void UserInfo::ClearAllOverrides() void UserInfo::ClearAllOverrides()
@ -75,9 +75,15 @@ namespace Components
AddScriptMethods(); AddScriptMethods();
Script::OnVMShutdown([] Events::OnVMShutdown([]
{ {
ClearAllOverrides(); ClearAllOverrides();
}); });
Events::OnClientDisconnect([](const int clientNum)
{
// Clear the overrides for UserInfo
ClearClientOverrides(clientNum);
});
} }
} }

View File

@ -7,7 +7,7 @@ namespace Components
public: public:
UserInfo(); UserInfo();
static void ClearClientOverrides(int client); static void ClearClientOverrides(int clientNum);
static void ClearAllOverrides(); static void ClearAllOverrides();
private: private:

View File

@ -69,12 +69,7 @@ namespace Utils
class Signal class Signal
{ {
public: public:
Signal() Signal() = default;
{
std::lock_guard<std::recursive_mutex> _(this->mutex);
this->slots.clear();
}
Signal(Signal& obj) : Signal() Signal(Signal& obj) : Signal()
{ {
@ -84,13 +79,13 @@ namespace Utils
Utils::Merge(&this->slots, obj.getSlots()); Utils::Merge(&this->slots, obj.getSlots());
} }
void connect(Slot<T> slot) void connect(const Slot<T> slot)
{ {
std::lock_guard<std::recursive_mutex> _(this->mutex); std::lock_guard<std::recursive_mutex> _(this->mutex);
if (slot) if (slot)
{ {
this->slots.push_back(slot); this->slots.emplace_back(slot);
} }
} }