Implement the stuff B3 needs.

This commit is contained in:
momo5502 2016-03-04 14:48:31 +01:00
parent 69db2c0734
commit 3b8e47fecc
7 changed files with 242 additions and 6 deletions

View File

@ -4,6 +4,7 @@ namespace Components
{ {
std::vector<Game::cmd_function_t*> Command::Functions; std::vector<Game::cmd_function_t*> Command::Functions;
std::map<std::string, wink::slot<Command::Callback>> Command::FunctionMap; std::map<std::string, wink::slot<Command::Callback>> Command::FunctionMap;
std::map<std::string, wink::slot<Command::Callback>> Command::FunctionMapSV;
char* Command::Params::operator[](size_t index) char* Command::Params::operator[](size_t index)
{ {
@ -12,12 +13,26 @@ namespace Components
return ""; return "";
} }
return Game::cmd_argv[this->CommandId][index]; if (this->IsSV)
{
return Game::cmd_argv_sv[this->CommandId][index];
}
else
{
return Game::cmd_argv[this->CommandId][index];
}
} }
size_t Command::Params::Length() size_t Command::Params::Length()
{ {
return Game::cmd_argc[this->CommandId]; if (this->IsSV)
{
return Game::cmd_argc_sv[this->CommandId];
}
else
{
return Game::cmd_argc[this->CommandId];
}
} }
std::string Command::Params::Join(size_t startIndex) std::string Command::Params::Join(size_t startIndex)
@ -39,6 +54,28 @@ namespace Components
Game::Cmd_AddCommand(name, Command::MainCallback, Command::Allocate(), 0); Game::Cmd_AddCommand(name, Command::MainCallback, Command::Allocate(), 0);
} }
void Command::AddSV(const char* name, Command::Callback* callback)
{
Command::FunctionMapSV[Utils::StrToLower(name)] = callback;
Game::Cmd_AddServerCommand(name, Command::MainCallbackSV, Command::Allocate());
// If the main command is registered as Cbuf_AddServerText, the command will be redirected to the SV handler
Command::AddRaw(name, Game::Cbuf_AddServerText);
}
void Command::AddRaw(const char* name, void(*callback)())
{
Game::Cmd_AddCommand(name, callback, Command::Allocate(), 0);
}
void Command::AddRawSV(const char* name, void(*callback)())
{
Game::Cmd_AddServerCommand(name, callback, Command::Allocate());
// If the main command is registered as Cbuf_AddServerText, the command will be redirected to the SV handler
Command::AddRaw(name, Game::Cbuf_AddServerText);
}
void Command::Execute(std::string command, bool sync) void Command::Execute(std::string command, bool sync)
{ {
command.append("\n"); // Make sure it's terminated command.append("\n"); // Make sure it's terminated
@ -63,7 +100,7 @@ namespace Components
void Command::MainCallback() void Command::MainCallback()
{ {
Command::Params params(*Game::cmd_id); Command::Params params(false, *Game::cmd_id);
std::string command = Utils::StrToLower(params[0]); std::string command = Utils::StrToLower(params[0]);
@ -73,6 +110,18 @@ namespace Components
} }
} }
void Command::MainCallbackSV()
{
Command::Params params(true, *Game::cmd_id_sv);
std::string command = Utils::StrToLower(params[0]);
if (Command::FunctionMapSV.find(command) != Command::FunctionMapSV.end())
{
Command::FunctionMapSV[command](params);
}
}
Command::Command() Command::Command()
{ {
// TODO: Add commands here? // TODO: Add commands here?
@ -86,5 +135,7 @@ namespace Components
} }
Command::Functions.clear(); Command::Functions.clear();
Command::FunctionMap.clear();
Command::FunctionMapSV.clear();
} }
} }

View File

@ -6,9 +6,9 @@ namespace Components
class Params class Params
{ {
public: public:
Params(DWORD id) : CommandId(id) {}; Params(bool sv, DWORD id) : CommandId(id), IsSV(sv) {};
Params(const Params &obj) { this->CommandId = obj.CommandId; }; Params(const Params &obj) : CommandId(obj.CommandId), IsSV(obj.IsSV) {};
Params() : Params(*Game::cmd_id) {}; Params() : Params(false, *Game::cmd_id) {};
char* operator[](size_t index); char* operator[](size_t index);
size_t Length(); size_t Length();
@ -16,6 +16,7 @@ namespace Components
std::string Join(size_t startIndex); std::string Join(size_t startIndex);
private: private:
bool IsSV;
DWORD CommandId; DWORD CommandId;
}; };
@ -26,12 +27,17 @@ namespace Components
const char* GetName() { return "Command"; }; const char* GetName() { return "Command"; };
static void Add(const char* name, Callback* callback); static void Add(const char* name, Callback* callback);
static void AddSV(const char* name, Callback* callback);
static void AddRaw(const char* name, void(*callback)());
static void AddRawSV(const char* name, void(*callback)());
static void Execute(std::string command, bool sync = true); static void Execute(std::string command, bool sync = true);
private: private:
static Game::cmd_function_t* Allocate(); static Game::cmd_function_t* Allocate();
static std::vector<Game::cmd_function_t*> Functions; static std::vector<Game::cmd_function_t*> Functions;
static std::map<std::string, wink::slot<Callback>> FunctionMap; static std::map<std::string, wink::slot<Callback>> FunctionMap;
static std::map<std::string, wink::slot<Callback>> FunctionMapSV;
static void MainCallback(); static void MainCallback();
static void MainCallbackSV();
}; };
} }

View File

@ -5,6 +5,8 @@ namespace Components
wink::signal<wink::slot<Dedicated::Callback>> Dedicated::FrameSignal; wink::signal<wink::slot<Dedicated::Callback>> Dedicated::FrameSignal;
wink::signal<wink::slot<Dedicated::Callback>> Dedicated::FrameOnceSignal; wink::signal<wink::slot<Dedicated::Callback>> Dedicated::FrameOnceSignal;
bool Dedicated::SendChat;
bool Dedicated::IsDedicated() bool Dedicated::IsDedicated()
{ {
return Flags::HasFlag("dedicated"); return Flags::HasFlag("dedicated");
@ -58,6 +60,62 @@ namespace Components
} }
} }
const char* Dedicated::EvaluateSay(char* text)
{
Dedicated::SendChat = true;
if (text[1] == '/')
{
Dedicated::SendChat = false;
text[1] = text[0];
++text;
}
return text;
}
void __declspec(naked) Dedicated::PreSayStub()
{
__asm
{
mov eax, [esp + 100h + 10h]
push eax
call EvaluateSay
add esp, 4h
mov [esp + 100h + 10h], eax
jmp Colors::CleanStrStub
}
}
void __declspec(naked) Dedicated::PostSayStub()
{
__asm
{
// eax is used by the callee
push eax
xor eax, eax
mov al, Dedicated::SendChat
test al, al
jnz return
// Don't send the chat
pop eax
retn
return:
pop eax
// Jump to the target
push 5DF620h
retn
}
}
void Dedicated::MapRotate() void Dedicated::MapRotate()
{ {
if (!Dedicated::IsDedicated() && Dvar::Var("sv_dontrotate").Get<bool>()) if (!Dedicated::IsDedicated() && Dvar::Var("sv_dontrotate").Get<bool>())
@ -228,6 +286,11 @@ namespace Components
// Dedicated frame handler // Dedicated frame handler
Utils::Hook(0x4B0F81, Dedicated::FrameStub, HOOK_CALL).Install()->Quick(); Utils::Hook(0x4B0F81, Dedicated::FrameStub, HOOK_CALL).Install()->Quick();
// Intercept chat sending
Utils::Hook(0x4D000B, Dedicated::PreSayStub, HOOK_CALL).Install()->Quick();
Utils::Hook(0x4D00D4, Dedicated::PostSayStub, HOOK_CALL).Install()->Quick();
Utils::Hook(0x4D0110, Dedicated::PostSayStub, HOOK_CALL).Install()->Quick();
if (!ZoneBuilder::IsEnabled()) if (!ZoneBuilder::IsEnabled())
{ {
// Post initialization point // Post initialization point
@ -248,6 +311,93 @@ namespace Components
}); });
#endif #endif
} }
Dvar::OnInit([] ()
{
Dvar::Register<const char*>("sv_sayName", "^7Console", Game::dvar_flag::DVAR_FLAG_NONE, "The name to pose as for 'say' commands");
// Say command
Command::AddSV("say", [] (Command::Params params)
{
if (params.Length() < 2) return;
std::string message = params.Join(1);
std::string name = Dvar::Var("sv_sayName").Get<std::string>();
if (!name.empty())
{
Game::SV_GameSendServerCommand(-1, 0, Utils::VA("%c \"%s: %s\"", 104, name.data(), message.data()));
Game::Com_Printf(15, "%s: %s\n", name.data(), message.data());
}
else
{
Game::SV_GameSendServerCommand(-1, 0, Utils::VA("%c \"Console: %s\"", 104, message.data()));
Game::Com_Printf(15, "Console: %s\n", message.data());
}
});
// Tell command
Command::AddSV("tell", [] (Command::Params params)
{
if (params.Length() < 3) return;
int client = atoi(params[1]);
std::string message = params.Join(2);
std::string name = Dvar::Var("sv_sayName").Get<std::string>();
if (!name.empty())
{
Game::SV_GameSendServerCommand(client, 0, Utils::VA("%c \"%s: %s\"", 104, name.data(), message.data()));
Game::Com_Printf(15, "%s -> %i: %s\n", name.data(), client, message.data());
}
else
{
Game::SV_GameSendServerCommand(client, 0, Utils::VA("%c \"Console: %s\"", 104, message.data()));
Game::Com_Printf(15, "Console -> %i: %s\n", client, message.data());
}
});
// Sayraw command
Command::AddSV("sayraw", [] (Command::Params params)
{
if (params.Length() < 2) return;
std::string message = params.Join(1);
Game::SV_GameSendServerCommand(-1, 0, Utils::VA("%c \"%s\"", 104, message.data()));
Game::Com_Printf(15, "Raw: %s\n", message.data());
});
// Tellraw command
Command::AddSV("tellraw", [] (Command::Params params)
{
if (params.Length() < 3) return;
int client = atoi(params[1]);
std::string message = params.Join(2);
Game::SV_GameSendServerCommand(client, 0, Utils::VA("%c \"%s\"", 104, message.data()));
Game::Com_Printf(15, "Raw -> %i: %s\n", client, message.data());
});
// ! command
Command::AddSV("!", [] (Command::Params params)
{
if (params.Length() != 2) return;
int client = -1;
if (std::string(params[1]) != "all")
{
client = atoi(params[1]);
if (client >= *reinterpret_cast<int*>(0x31D938C))
{
Game::Com_Printf(0, "Invalid player.\n");
return;
}
}
Game::SV_GameSendServerCommand(client, 0, Utils::VA("%c \"\"", 106));
});
});
} }
} }

View File

@ -20,11 +20,18 @@ namespace Components
static wink::signal<wink::slot<Callback>> FrameSignal; static wink::signal<wink::slot<Callback>> FrameSignal;
static wink::signal<wink::slot<Callback>> FrameOnceSignal; static wink::signal<wink::slot<Callback>> FrameOnceSignal;
static bool SendChat;
static void MapRotate(); static void MapRotate();
static void FrameStub(); static void FrameStub();
static void InitDedicatedServer(); static void InitDedicatedServer();
static void PostInitialization(); static void PostInitialization();
static void PostInitializationStub(); static void PostInitializationStub();
static const char* EvaluateSay(char* text);
static void PreSayStub();
static void PostSayStub();
}; };
} }

View File

@ -88,6 +88,8 @@ namespace Components
Utils::Hook::Set<void*>(0x4D90B7, Maps::WorldMP); Utils::Hook::Set<void*>(0x4D90B7, Maps::WorldMP);
} }
AntiCheat::EmptyHash();
_snprintf(buffer, size, format, mapname); _snprintf(buffer, size, format, mapname);
} }

View File

@ -5,6 +5,7 @@ namespace Game
// C-Style casts are fine here, that's where we're doing our dirty stuff anyways... // C-Style casts are fine here, that's where we're doing our dirty stuff anyways...
BG_LoadWeaponDef_LoadObj_t BG_LoadWeaponDef_LoadObj = (BG_LoadWeaponDef_LoadObj_t)0x57B5F0; BG_LoadWeaponDef_LoadObj_t BG_LoadWeaponDef_LoadObj = (BG_LoadWeaponDef_LoadObj_t)0x57B5F0;
Cbuf_AddServerText_t Cbuf_AddServerText = (Cbuf_AddServerText_t)0x4BB9B0;
Cbuf_AddText_t Cbuf_AddText = (Cbuf_AddText_t)0x404B20; Cbuf_AddText_t Cbuf_AddText = (Cbuf_AddText_t)0x404B20;
CL_GetClientName_t CL_GetClientName = (CL_GetClientName_t)0x4563D0; CL_GetClientName_t CL_GetClientName = (CL_GetClientName_t)0x4563D0;
@ -12,6 +13,7 @@ namespace Game
CL_ConnectFromParty_t CL_ConnectFromParty = (CL_ConnectFromParty_t)0x433D30; CL_ConnectFromParty_t CL_ConnectFromParty = (CL_ConnectFromParty_t)0x433D30;
Cmd_AddCommand_t Cmd_AddCommand = (Cmd_AddCommand_t)0x470090; Cmd_AddCommand_t Cmd_AddCommand = (Cmd_AddCommand_t)0x470090;
Cmd_AddServerCommand_t Cmd_AddServerCommand = (Cmd_AddServerCommand_t)0x4DCE00;
Cmd_ExecuteSingleCommand_t Cmd_ExecuteSingleCommand = (Cmd_ExecuteSingleCommand_t)0x609540; Cmd_ExecuteSingleCommand_t Cmd_ExecuteSingleCommand = (Cmd_ExecuteSingleCommand_t)0x609540;
Com_Error_t Com_Error = (Com_Error_t)0x4B22D0; Com_Error_t Com_Error = (Com_Error_t)0x4B22D0;
@ -130,6 +132,7 @@ namespace Game
Steam_JoinLobby_t Steam_JoinLobby = (Steam_JoinLobby_t)0x49CF70; Steam_JoinLobby_t Steam_JoinLobby = (Steam_JoinLobby_t)0x49CF70;
SV_GameClientNum_Score_t SV_GameClientNum_Score = (SV_GameClientNum_Score_t)0x469AC0; SV_GameClientNum_Score_t SV_GameClientNum_Score = (SV_GameClientNum_Score_t)0x469AC0;
SV_GameSendServerCommand_t SV_GameSendServerCommand = (SV_GameSendServerCommand_t)0x4BC3A0;
Sys_IsMainThread_t Sys_IsMainThread = (Sys_IsMainThread_t)0x4C37D0; Sys_IsMainThread_t Sys_IsMainThread = (Sys_IsMainThread_t)0x4C37D0;
Sys_SendPacket_t Sys_SendPacket = (Sys_SendPacket_t)0x60FDC0; Sys_SendPacket_t Sys_SendPacket = (Sys_SendPacket_t)0x60FDC0;
@ -147,6 +150,10 @@ namespace Game
DWORD* cmd_argc = (DWORD*)0x1AAC614; DWORD* cmd_argc = (DWORD*)0x1AAC614;
char*** cmd_argv = (char***)0x1AAC634; char*** cmd_argv = (char***)0x1AAC634;
DWORD* cmd_id_sv = (DWORD*)0x1ACF8A0;
DWORD* cmd_argc_sv = (DWORD*)0x1ACF8E4;
char*** cmd_argv_sv = (char***)0x1ACF904;
source_t **sourceFiles = (source_t **)0x7C4A98; source_t **sourceFiles = (source_t **)0x7C4A98;
keywordHash_t **menuParseKeywordHash = (keywordHash_t **)0x63AE928; keywordHash_t **menuParseKeywordHash = (keywordHash_t **)0x63AE928;

View File

@ -3,6 +3,9 @@ namespace Game
typedef void*(__cdecl * BG_LoadWeaponDef_LoadObj_t)(const char* filename); typedef void*(__cdecl * BG_LoadWeaponDef_LoadObj_t)(const char* filename);
extern BG_LoadWeaponDef_LoadObj_t BG_LoadWeaponDef_LoadObj; extern BG_LoadWeaponDef_LoadObj_t BG_LoadWeaponDef_LoadObj;
typedef void(__cdecl * Cbuf_AddServerText_t)();
extern Cbuf_AddServerText_t Cbuf_AddServerText;
typedef void(__cdecl * Cbuf_AddText_t)(int localClientNum, const char *text); typedef void(__cdecl * Cbuf_AddText_t)(int localClientNum, const char *text);
extern Cbuf_AddText_t Cbuf_AddText; extern Cbuf_AddText_t Cbuf_AddText;
@ -18,6 +21,9 @@ namespace Game
typedef void(__cdecl * Cmd_AddCommand_t)(const char* name, void(*callback), cmd_function_t* data, char); typedef void(__cdecl * Cmd_AddCommand_t)(const char* name, void(*callback), cmd_function_t* data, char);
extern Cmd_AddCommand_t Cmd_AddCommand; extern Cmd_AddCommand_t Cmd_AddCommand;
typedef void(__cdecl * Cmd_AddServerCommand_t)(const char* name, void(*callback), cmd_function_t* data);
extern Cmd_AddServerCommand_t Cmd_AddServerCommand;
typedef void(__cdecl * Cmd_ExecuteSingleCommand_t)(int controller, int a2, const char* cmd); typedef void(__cdecl * Cmd_ExecuteSingleCommand_t)(int controller, int a2, const char* cmd);
extern Cmd_ExecuteSingleCommand_t Cmd_ExecuteSingleCommand; extern Cmd_ExecuteSingleCommand_t Cmd_ExecuteSingleCommand;
@ -302,6 +308,9 @@ namespace Game
typedef int(__cdecl* SV_GameClientNum_Score_t)(int clientID); typedef int(__cdecl* SV_GameClientNum_Score_t)(int clientID);
extern SV_GameClientNum_Score_t SV_GameClientNum_Score; extern SV_GameClientNum_Score_t SV_GameClientNum_Score;
typedef void(__cdecl * SV_GameSendServerCommand_t)(int clientNum, /*svscmd_type*/int type, const char* text);
extern SV_GameSendServerCommand_t SV_GameSendServerCommand;
typedef bool(__cdecl * Sys_IsMainThread_t)(); typedef bool(__cdecl * Sys_IsMainThread_t)();
extern Sys_IsMainThread_t Sys_IsMainThread; extern Sys_IsMainThread_t Sys_IsMainThread;
@ -327,6 +336,10 @@ namespace Game
extern DWORD* cmd_argc; extern DWORD* cmd_argc;
extern char*** cmd_argv; extern char*** cmd_argv;
extern DWORD* cmd_id_sv;
extern DWORD* cmd_argc_sv;
extern char*** cmd_argv_sv;
extern int* svs_numclients; extern int* svs_numclients;
extern client_t* svs_clients; extern client_t* svs_clients;