[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 Ceg());
Loader::Register(new UserInfo());
Loader::Register(new Events());
Loader::Pregame = false;
}

View File

@ -143,3 +143,4 @@ namespace Components
#include "Modules/MapRotation.hpp"
#include "Modules/Ceg.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()
{
AssertOffset(Game::client_s, bIsTestClient, 0x41AF0);
@ -340,7 +325,10 @@ namespace Components
Utils::Hook(0x441B80, Bots::G_SelectWeaponIndex_Hk, HOOK_JUMP).install()->quick();
// 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
for (auto i = 0u; i < std::extent_v<decltype(g_botai)>; i++)
@ -393,9 +381,9 @@ namespace Components
Bots::AddMethods();
// 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;
}

View File

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

View File

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

View File

@ -377,6 +377,9 @@ namespace Components
// If the game closed abruptly, the dvars would not have been restored
Scheduler::Once(Dvar::ResetDvarsValue, Scheduler::Pipeline::MAIN);
// Reset archive dvars when client leaves a server
Events::OnSteamDisconnect(Dvar::ResetDvarsValue);
}
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;
}
__declspec(naked) void Friends::DisconnectStub()
{
__asm
{
pushad
call Friends::ClearServer
call Dvar::ResetDvarsValue
popad
push 467CC0h
retn
}
}
void Friends::AddFriend(SteamID user)
{
if (Steam::Proxy::ClientFriends && Steam::Proxy::SteamFriends)
@ -622,7 +606,8 @@ namespace Components
});
// 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();
// Show blue icons on the minimap

View File

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

View File

@ -14,8 +14,6 @@ namespace Components
const char* Script::ReplacedPos = nullptr;
int Script::LastFrameTime = -1;
Utils::Signal<Script::Callback> Script::VMShutdownSignal;
void Script::FunctionError()
{
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()
{
if (Game::Scr_GetNumParam() == 6u)
@ -715,9 +699,6 @@ namespace Components
Utils::Hook(0x61E92E, Script::VMExecuteInternalStub, HOOK_JUMP).install()->quick();
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([]()
{
if (!Game::SV_Loaded())
@ -753,14 +734,9 @@ namespace Components
Script::AddFunctions();
Script::OnVMShutdown([]
Events::OnVMShutdown([]
{
Script::ReplacedFunctions.clear();
});
}
Script::~Script()
{
Script::VMShutdownSignal.clear();
}
}

View File

@ -7,17 +7,12 @@ namespace Components
{
public:
Script();
~Script();
typedef void(Callback)();
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 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);
private:
@ -33,8 +28,6 @@ namespace Components
static const char* ReplacedPos;
static int LastFrameTime;
static Utils::Signal<Script::Callback> VMShutdownSignal;
static void CompileError(unsigned int offset, const char* message, ...);
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::BuiltinMethod BuiltIn_GetMethod(const char** pName, int* type);
static void ScrShutdownSystemStub(unsigned char sys);
static void StoreScriptBaseProgramNumStub();
static void StoreScriptBaseProgramNum();
static void Scr_PrintPrevCodePosStub();

View File

@ -31,9 +31,9 @@ namespace Components
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()
@ -75,9 +75,15 @@ namespace Components
AddScriptMethods();
Script::OnVMShutdown([]
Events::OnVMShutdown([]
{
ClearAllOverrides();
});
Events::OnClientDisconnect([](const int clientNum)
{
// Clear the overrides for UserInfo
ClearClientOverrides(clientNum);
});
}
}

View File

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

View File

@ -69,12 +69,7 @@ namespace Utils
class Signal
{
public:
Signal()
{
std::lock_guard<std::recursive_mutex> _(this->mutex);
this->slots.clear();
}
Signal() = default;
Signal(Signal& obj) : Signal()
{
@ -84,13 +79,13 @@ namespace Utils
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);
if (slot)
{
this->slots.push_back(slot);
this->slots.emplace_back(slot);
}
}