From 6c45c7e94634c340019d12615b7eae8f3c0f49b3 Mon Sep 17 00:00:00 2001 From: BobTheBob9 Date: Wed, 4 Jan 2023 14:21:29 +0000 Subject: commit all changes for merge --- NorthstarDLL/NorthstarDLL.vcxproj | 2 + NorthstarDLL/NorthstarDLL.vcxproj.filters | 6 + NorthstarDLL/bansystem.cpp | 2 +- NorthstarDLL/bots.cpp | 184 ++++++++++++++++++++++++++++++ NorthstarDLL/bots.h | 26 +++++ NorthstarDLL/r2engine.h | 1 + NorthstarDLL/r2server.h | 2 + NorthstarDLL/serverauthentication.cpp | 13 ++- 8 files changed, 231 insertions(+), 5 deletions(-) create mode 100644 NorthstarDLL/bots.cpp create mode 100644 NorthstarDLL/bots.h diff --git a/NorthstarDLL/NorthstarDLL.vcxproj b/NorthstarDLL/NorthstarDLL.vcxproj index 5e329f1f..7961ddf4 100644 --- a/NorthstarDLL/NorthstarDLL.vcxproj +++ b/NorthstarDLL/NorthstarDLL.vcxproj @@ -120,6 +120,7 @@ + @@ -569,6 +570,7 @@ + diff --git a/NorthstarDLL/NorthstarDLL.vcxproj.filters b/NorthstarDLL/NorthstarDLL.vcxproj.filters index 14f8c265..4f5ccbc5 100644 --- a/NorthstarDLL/NorthstarDLL.vcxproj.filters +++ b/NorthstarDLL/NorthstarDLL.vcxproj.filters @@ -1503,6 +1503,9 @@ Header Files\Squirrel + + Header Files\Server + @@ -1733,6 +1736,9 @@ Source Files\Client + + Source Files\Server + diff --git a/NorthstarDLL/bansystem.cpp b/NorthstarDLL/bansystem.cpp index 25c0e6bf..5ba24cf1 100644 --- a/NorthstarDLL/bansystem.cpp +++ b/NorthstarDLL/bansystem.cpp @@ -188,7 +188,7 @@ void ConCommand_ban(const CCommand& args) { R2::CBaseClient* player = &R2::g_pClientArray[i]; - if (!strcmp(player->m_Name, args.Arg(1)) || !strcmp(player->m_UID, args.Arg(1))) + if (player->m_Signon >= R2::eSignonState::CONNECTED && !strcmp(player->m_Name, args.Arg(1)) || !strcmp(player->m_UID, args.Arg(1))) { g_pBanSystem->BanUID(strtoull(player->m_UID, nullptr, 10)); R2::CBaseClient__Disconnect(player, 1, "Banned from server"); diff --git a/NorthstarDLL/bots.cpp b/NorthstarDLL/bots.cpp new file mode 100644 index 00000000..f8a37d26 --- /dev/null +++ b/NorthstarDLL/bots.cpp @@ -0,0 +1,184 @@ +#include "pch.h" +#include "bots.h" + +#include "concommand.h" +#include "r2engine.h" +#include "r2server.h" +#include "playlist.h" +#include "maxplayers.h" +#include "serverauthentication.h" + +AUTOHOOK_INIT() + +ServerBotManager* g_pBots; + +void* pServer; +R2::CBaseClient* (*__fastcall CBaseServer__CreateFakeClient)( + void* self, const char* pName, const char* pUnk, const char* pDesiredPlaylist, int nDesiredTeam); + +void* pServerGameClients; +void (*__fastcall ServerGameClients__ClientFullyConnect)(void* self, uint16_t edict, bool bRestore); + +void (*__fastcall CBasePlayer__RunNullCommand)(R2::CBasePlayer* self); + +const std::vector BOT_NAMES = { + // normal titanfall names + "Jack", + "Cooper", + "BT-7274", + "FS-1041", + "Blisk", + "Marv", + "Marvin", + "Barker", + "Gates", + "Marder", + "Sarah", + "Briggs", + "Viper", + "Ash", + "Richter", + "Slone", + "Tai", + "Lastimosa", + "Davis", + "Droz", + "Bear", + "MacAllan", + "Bish", + "Spyglass", + + // tf1 training/campaign npc names + "Rakowski", + "Alavi", + "Riggs", + "Bracken", + "Hainey", + "Vaughan", + "Dunnam", + "Riggins", + "Messerly", + "Heppe", + "Keating", + "Blanton", + "Emslie", + "Flagg", + "Hofner", + + // deepcut references lol + "Iron", + "Starseeker", + "Hollow", + "Preacher", + + // contributors/cool people + "BobTheBot", + "GeckoEidechsBot", + "TaskiBot", + "RoyalBot", + "EmmaB(ot)", // ok this one is shit to be honest but it's a hard name to put bot into + "bot0358", + // how the fuck do i turn amos into a bot name oh my god + "Botmos", + "Botscuit", + "Botty_RaVen", +}; + +// this is the root func from what usercmd running is called from +AUTOHOOK(SomeRunUsercmdFunc, server.dll + 0x483A50, +void, __fastcall, (char a1)) +{ + g_pBots->SimulatePlayers(); + SomeRunUsercmdFunc(a1); +} + +void ConCommand_bot_add(const CCommand& arg) +{ + if (arg.ArgC() == 1) + g_pBots->AddBot(); + else if (arg.ArgC() == 2) + g_pBots->AddBot(arg.Arg(1)); + else if (arg.ArgC() == 2) + g_pBots->AddBot(arg.Arg(1), std::stoi(arg.Arg(2))); +} + +ServerBotManager::ServerBotManager() +{ + //m_Cvar_bot_teams = new ConVar("") +} + + +// add a new bot player +void ServerBotManager::AddBot(const char* pName, int iTeam) +{ + if (!*pName) + pName = BOT_NAMES[rand() % BOT_NAMES.size()]; + + if (iTeam == -1) + { + // pick team that needs players + // oops i cant be bothered just do imc for now + iTeam = 2; + } + + const R2::CBaseClient* pPlayer = CBaseServer__CreateFakeClient(pServer, pName, "", "", iTeam); + ServerGameClients__ClientFullyConnect(pServerGameClients, pPlayer->edict, false); // this is normally done on eSignonState::FULL, but bots don't properly call it + + spdlog::info("Created bot {}", pPlayer->m_Name); +} + + +// add bots at the start of a game +void ServerBotManager::StartMatch() +{ + int nNumBots = Cvar_bot_quota->GetInt() - g_pServerAuthentication->m_PlayerAuthenticationData.size(); + for (int i = nNumBots; i > 0; i--) + AddBot(); +} + +// setup bot after it connects +void ServerBotManager::SetupPlayer(R2::CBaseClient* pPlayer) +{ + strncpy_s(pPlayer->m_ClanTag, Cvar_bot_clantag->GetString(), 15); +} + +// every server frame, run bot usercmds +void ServerBotManager::SimulatePlayers() +{ + for (int i = 0; i < R2::GetMaxPlayers(); i++) + { + R2::CBaseClient* pClient = &R2::g_pClientArray[i]; + if (pClient->m_Signon == R2::eSignonState::FULL && pClient->m_bFakePlayer) + { + // todo: if we ever want actual moving bots, this would be where we'd nav, build usercmd, etc + CBasePlayer__RunNullCommand(R2::UTIL_PlayerByIndex(i + 1)); + } + } +} + +ON_DLL_LOAD_RELIESON("engine.dll", Bots, (ConVar, ConCommand), (CModule module)) +{ + g_pBots = new ServerBotManager; + g_pBots->Cvar_bot_quota = new ConVar("bot_quota", "0", FCVAR_GAMEDLL, "Minimum number of players when filling game with bots"); + g_pBots->Cvar_bot_clantag = new ConVar("bot_clantag", "BOT", FCVAR_GAMEDLL, "Clantag to give bots"); + + pServer = module.Offset(0x12A53D40).As(); + pServerGameClients = module.Offset(0x13F0AAA8).As(); + + CBaseServer__CreateFakeClient = + module.Offset(0x114C60).As(); + + RegisterConCommand( + "bot_add", + ConCommand_bot_add, + "Add a bot, by default name and team are automatically chosen, they can be specified (bot_add name team)", + FCVAR_GAMEDLL); +} + +ON_DLL_LOAD("server.dll", ServerBots, (CModule module)) +{ + AUTOHOOK_DISPATCH_MODULE(server.dll) + + ServerGameClients__ClientFullyConnect = module.Offset(0x153B70).As(); + CBasePlayer__RunNullCommand = module.Offset(0x5A9FD0).As(); +} diff --git a/NorthstarDLL/bots.h b/NorthstarDLL/bots.h new file mode 100644 index 00000000..5973983a --- /dev/null +++ b/NorthstarDLL/bots.h @@ -0,0 +1,26 @@ +#pragma once +#include "convar.h" +#include "r2engine.h" + +class ServerBotManager +{ + + public: + ConVar* Cvar_bot_quota; + ConVar* Cvar_bot_teams; + + ConVar* Cvar_bot_clantag; + + public: + ServerBotManager(); + + void AddBot(const char* pName = "", int iTeam = -1); + + // events we react to + void StartMatch(); + void SetupPlayer(R2::CBaseClient* pPlayer); + void SimulatePlayers(); + +}; + +extern ServerBotManager* g_pBots; diff --git a/NorthstarDLL/r2engine.h b/NorthstarDLL/r2engine.h index 1b1fc081..c816ec86 100644 --- a/NorthstarDLL/r2engine.h +++ b/NorthstarDLL/r2engine.h @@ -175,6 +175,7 @@ namespace R2 OFFSET_STRUCT(CBaseClient) { STRUCT_SIZE(0x2D728) + FIELD(0x14, uint16_t edict) FIELD(0x16, char m_Name[64]) FIELD(0x258, KeyValues* m_ConVars) FIELD(0x2A0, eSignonState m_Signon) diff --git a/NorthstarDLL/r2server.h b/NorthstarDLL/r2server.h index aadfdefe..5d69f53e 100644 --- a/NorthstarDLL/r2server.h +++ b/NorthstarDLL/r2server.h @@ -15,6 +15,8 @@ namespace R2 STRUCT_SIZE(0x1D02); FIELD(0x58, uint32_t m_nPlayerIndex) + FIELD(0x5E4, int m_nTeam) + FIELD(0x1C90, bool m_hasBadReputation) FIELD(0x1C91, char m_communityName[64]) FIELD(0x1CD1, char m_communityClanTag[16]) diff --git a/NorthstarDLL/serverauthentication.cpp b/NorthstarDLL/serverauthentication.cpp index 73b714ab..53892623 100644 --- a/NorthstarDLL/serverauthentication.cpp +++ b/NorthstarDLL/serverauthentication.cpp @@ -15,6 +15,7 @@ #include "r2engine.h" #include "r2client.h" #include "r2server.h" +#include "bots.h" #include "httplib.h" @@ -188,10 +189,6 @@ bool ServerAuthenticationManager::CheckAuthentication(R2::CBaseClient* pPlayer, void ServerAuthenticationManager::AuthenticatePlayer(R2::CBaseClient* pPlayer, uint64_t iUid, char* pAuthToken) { - // for bot players, generate a new uid - if (pPlayer->m_bFakePlayer) - iUid = 0; // is this a good way of doing things :clueless: - std::string sUid = std::to_string(iUid); // copy uuid @@ -316,7 +313,12 @@ bool,, (R2::CBaseClient* self, char* pName, void* pNetChannel, char bFakePlayer, pAuthenticationFailure = "Authentication Failed."; } else // need to copy name for bots still + { + // generate uid and token for bot + iNextPlayerUid = 0; + pNextPlayerToken = (char*)""; strncpy_s(pVerifiedName, pName, 63); + } if (pAuthenticationFailure) { @@ -333,6 +335,9 @@ bool,, (R2::CBaseClient* self, char* pName, void* pNetChannel, char bFakePlayer, // we already know this player's authentication data is legit, actually write it to them now g_pServerAuthentication->AuthenticatePlayer(self, iNextPlayerUid, pNextPlayerToken); + if (bFakePlayer) + g_pBots->SetupPlayer(self); + g_pServerAuthentication->AddPlayer(self, pNextPlayerToken); g_pServerLimits->AddPlayer(self); -- cgit v1.2.3