Serverinfo stuff.
This commit is contained in:
parent
497e223371
commit
323ab2bf41
@ -32,6 +32,7 @@ namespace Components
|
||||
Loader::Register(new Materials());
|
||||
Loader::Register(new FileSystem());
|
||||
Loader::Register(new QuickPatch());
|
||||
Loader::Register(new ServerInfo());
|
||||
Loader::Register(new ServerList());
|
||||
Loader::Register(new ZoneBuilder());
|
||||
Loader::Register(new AssetHandler());
|
||||
|
@ -45,6 +45,7 @@ namespace Components
|
||||
#include "Modules\Singleton.hpp"
|
||||
#include "Modules\FileSystem.hpp"
|
||||
#include "Modules\QuickPatch.hpp"
|
||||
#include "Modules\ServerInfo.hpp"
|
||||
#include "Modules\ServerList.hpp"
|
||||
#include "Modules\ZoneBuilder.hpp"
|
||||
#include "Modules\AssetHandler.hpp"
|
||||
|
251
src/Components/Modules/ServerInfo.cpp
Normal file
251
src/Components/Modules/ServerInfo.cpp
Normal file
@ -0,0 +1,251 @@
|
||||
#include "STDInclude.hpp"
|
||||
#include "..\..\Utils\Versioning.hpp"
|
||||
|
||||
namespace Components
|
||||
{
|
||||
ServerInfo::Container ServerInfo::PlayerContainer;
|
||||
|
||||
int ServerInfo::GetPlayerCount()
|
||||
{
|
||||
return ServerInfo::PlayerContainer.PlayerList.size();
|
||||
}
|
||||
|
||||
const char* ServerInfo::GetPlayerText(int index, int column)
|
||||
{
|
||||
if ((unsigned int)index < ServerInfo::PlayerContainer.PlayerList.size())
|
||||
{
|
||||
switch (column)
|
||||
{
|
||||
case 0:
|
||||
return Utils::VA("%d", index);
|
||||
|
||||
case 1:
|
||||
return ServerInfo::PlayerContainer.PlayerList[index].Name.data();
|
||||
|
||||
case 2:
|
||||
return Utils::VA("%d", ServerInfo::PlayerContainer.PlayerList[index].Score);
|
||||
|
||||
case 3:
|
||||
return Utils::VA("%d", ServerInfo::PlayerContainer.PlayerList[index].Ping);
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
void ServerInfo::SelectPlayer(int index)
|
||||
{
|
||||
ServerInfo::PlayerContainer.CurrentPlayer = index;
|
||||
}
|
||||
|
||||
void ServerInfo::ServerStatus()
|
||||
{
|
||||
ServerInfo::PlayerContainer.CurrentPlayer = 0;
|
||||
ServerInfo::PlayerContainer.PlayerList.clear();
|
||||
|
||||
ServerList::ServerInfo* info = ServerList::GetCurrentServer();
|
||||
|
||||
if(info)
|
||||
{
|
||||
Dvar::Var("uiSi_ServerName").Set(info->Hostname);
|
||||
Dvar::Var("uiSi_MaxClients").Set(info->Clients);
|
||||
Dvar::Var("uiSi_Version").Set(info->Shortversion);
|
||||
Dvar::Var("uiSi_isPrivate").Set(info->Password ? "@MENU_YES" : "@MENU_NO");
|
||||
Dvar::Var("uiSi_Hardcore").Set(info->Hardcore ? "@MENU_ENABLED" : "@MENU_DISABLED");
|
||||
Dvar::Var("uiSi_KillCam").Set("@MENU_NO");
|
||||
Dvar::Var("uiSi_ffType").Set("@MENU_DISABLED");
|
||||
Dvar::Var("uiSi_MapName").Set(info->Mapname);
|
||||
Dvar::Var("uiSi_MapNameLoc").Set(Game::UI_LocalizeMapName(info->Mapname.data()));
|
||||
Dvar::Var("uiSi_GameType").Set(Game::UI_LocalizeGameType(info->Gametype.data()));
|
||||
Dvar::Var("uiSi_ModName").Set("");
|
||||
|
||||
if (info->Mod.size() > 5)
|
||||
{
|
||||
Dvar::Var("uiSi_ModName").Set(info->Mod.data() + 5);
|
||||
}
|
||||
|
||||
ServerInfo::PlayerContainer.Target = info->Addr;
|
||||
Network::Send(ServerInfo::PlayerContainer.Target, "getstatus\n");
|
||||
}
|
||||
}
|
||||
|
||||
ServerInfo::ServerInfo()
|
||||
{
|
||||
ServerInfo::PlayerContainer.CurrentPlayer = 0;
|
||||
ServerInfo::PlayerContainer.PlayerList.clear();
|
||||
|
||||
// Ignore native getStatus implementation
|
||||
Utils::Hook::Nop(0x62654E, 6);
|
||||
|
||||
// Add uiscript
|
||||
UIScript::Add("ServerStatus", ServerInfo::ServerStatus);
|
||||
|
||||
// Add uifeeder
|
||||
UIFeeder::Add(13.0f, ServerInfo::GetPlayerCount, ServerInfo::GetPlayerText, ServerInfo::SelectPlayer);
|
||||
|
||||
Network::Handle("getStatus", [] (Network::Address address, std::string data)
|
||||
{
|
||||
bool isInLobby = false;
|
||||
int maxclientCount = *Game::svs_numclients;
|
||||
|
||||
if(!maxclientCount)
|
||||
{
|
||||
isInLobby = true;
|
||||
|
||||
//maxclientCount = Dvar::Var("sv_maxclients").Get<int>();
|
||||
maxclientCount = Game::Party_GetMaxPlayers(*Game::partyIngame);
|
||||
}
|
||||
|
||||
Utils::InfoString info(Game::Dvar_InfoString_Big(1024));
|
||||
info.Set("challenge", Utils::ParseChallenge(data));
|
||||
info.Set("gamename", "IW4");
|
||||
info.Set("sv_maxclients", Utils::VA("%i", maxclientCount));
|
||||
info.Set("protocol", Utils::VA("%i", PROTOCOL));
|
||||
info.Set("shortversion", VERSION_STR);
|
||||
info.Set("checksum", Utils::VA("%d", Game::Com_Milliseconds()));
|
||||
info.Set("mapname", Dvar::Var("mapname").Get<const char*>());
|
||||
info.Set("isPrivate", (Dvar::Var("g_password").Get<std::string>().size() ? "1" : "0"));
|
||||
|
||||
// Ensure mapname is set
|
||||
if (!info.Get("mapname").size())
|
||||
{
|
||||
info.Set("mapname", Dvar::Var("ui_mapname").Get<const char*>());
|
||||
}
|
||||
|
||||
// Set matchtype
|
||||
// 0 - No match, connecting not possible
|
||||
// 1 - Party, use Steam_JoinLobby to connect
|
||||
// 2 - Match, use CL_ConnectFromParty to connect
|
||||
|
||||
if (Dvar::Var("party_enable").Get<bool>() && Dvar::Var("party_host").Get<bool>()) // Party hosting
|
||||
{
|
||||
info.Set("matchtype", "1");
|
||||
}
|
||||
else if (Dvar::Var("sv_running").Get<bool>()) // Match hosting
|
||||
{
|
||||
info.Set("matchtype", "2");
|
||||
}
|
||||
else
|
||||
{
|
||||
info.Set("matchtype", "0");
|
||||
}
|
||||
|
||||
std::string playerList;
|
||||
|
||||
for (int i = 0; i < maxclientCount; i++) // Maybe choose 18 here?
|
||||
{
|
||||
int score = 0;
|
||||
int ping = 0;
|
||||
std::string name;
|
||||
|
||||
if (!isInLobby)
|
||||
{
|
||||
if (Game::svs_clients[i].state < 3) continue;
|
||||
|
||||
score = Game::SV_GameClientNum_Score(i);
|
||||
ping = Game::svs_clients[i].ping;
|
||||
name = Game::svs_clients[i].name;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Score and ping are irrelevant
|
||||
const char* namePtr = Game::PartyHost_GetMemberName((Game::PartyData_s*)0x1081C00, i);
|
||||
if (!namePtr || !namePtr[0]) continue;
|
||||
|
||||
name = namePtr;
|
||||
}
|
||||
|
||||
playerList.append(Utils::VA("%i %i \"%s\"\n", score, ping, name.data()));
|
||||
}
|
||||
|
||||
Network::Send(address, Utils::VA("statusResponse\n\\%s\n%s\n", info.Build().data(), playerList.data()));
|
||||
});
|
||||
|
||||
Network::Handle("statusResponse", [] (Network::Address address, std::string data)
|
||||
{
|
||||
if (ServerInfo::PlayerContainer.Target == address)
|
||||
{
|
||||
Utils::InfoString info(data.substr(0, data.find_first_of("\n")));
|
||||
|
||||
Dvar::Var("uiSi_ServerName").Set(info.Get("sv_hostname"));
|
||||
Dvar::Var("uiSi_MaxClients").Set(info.Get("sv_maxclients"));
|
||||
Dvar::Var("uiSi_Version").Set(info.Get("shortversion"));
|
||||
Dvar::Var("uiSi_isPrivate").Set(info.Get("isPrivate") == "0" ? "@MENU_NO" : "@MENU_YES");
|
||||
Dvar::Var("uiSi_Hardcore").Set(info.Get("g_hardcore") == "0" ? "@MENU_DISABLED" : "@MENU_ENABLED");
|
||||
Dvar::Var("uiSi_KillCam").Set(info.Get("scr_game_allowkillcam") == "0" ? "@MENU_NO" : "@MENU_YES");
|
||||
Dvar::Var("uiSi_MapName").Set(info.Get("mapname"));
|
||||
Dvar::Var("uiSi_MapNameLoc").Set(Game::UI_LocalizeMapName(info.Get("mapname").data()));
|
||||
Dvar::Var("uiSi_GameType").Set(Game::UI_LocalizeGameType(info.Get("g_gametype").data()));
|
||||
Dvar::Var("uiSi_ModName").Set("");
|
||||
|
||||
switch (atoi(info.Get("scr_team_fftype").data()))
|
||||
{
|
||||
default:
|
||||
Dvar::Var("uiSi_ffType").Set("@MENU_DISABLED");
|
||||
break;
|
||||
|
||||
case 1:
|
||||
Dvar::Var("uiSi_ffType").Set("@MENU_ENABLED");
|
||||
break;
|
||||
|
||||
case 2:
|
||||
Dvar::Var("uiSi_ffType").Set("@MPUI_RULES_REFLECT");
|
||||
break;
|
||||
|
||||
case 3:
|
||||
Dvar::Var("uiSi_ffType").Set("@MPUI_RULES_SHARED");
|
||||
break;
|
||||
}
|
||||
|
||||
if (info.Get("fs_game").size() > 5)
|
||||
{
|
||||
Dvar::Var("uiSi_ModName").Set(info.Get("fs_game").data() + 5);
|
||||
}
|
||||
|
||||
auto lines = Utils::Explode(data, '\n');
|
||||
|
||||
if (lines.size() <= 1) return;
|
||||
|
||||
for (unsigned int i = 1; i < lines.size(); i++)
|
||||
{
|
||||
ServerInfo::Container::Player player;
|
||||
|
||||
std::string currentData = lines[i];
|
||||
|
||||
if (currentData.size() < 3) continue;
|
||||
|
||||
// Insert score
|
||||
player.Score = atoi(currentData.substr(0, currentData.find_first_of(" ")).data());
|
||||
|
||||
// Remove score
|
||||
currentData = currentData.substr(currentData.find_first_of(" ") + 1);
|
||||
|
||||
// Insert ping
|
||||
player.Ping = atoi(currentData.substr(0, currentData.find_first_of(" ")).data());
|
||||
|
||||
// Remove ping
|
||||
currentData = currentData.substr(currentData.find_first_of(" ") + 1);
|
||||
|
||||
if (currentData[0] == '\"')
|
||||
{
|
||||
currentData = currentData.substr(1);
|
||||
}
|
||||
|
||||
if (currentData[currentData.size() - 1] == '\"')
|
||||
{
|
||||
currentData.pop_back();
|
||||
}
|
||||
|
||||
player.Name = currentData;
|
||||
|
||||
ServerInfo::PlayerContainer.PlayerList.push_back(player);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ServerInfo::~ServerInfo()
|
||||
{
|
||||
ServerInfo::PlayerContainer.PlayerList.clear();
|
||||
}
|
||||
}
|
33
src/Components/Modules/ServerInfo.hpp
Normal file
33
src/Components/Modules/ServerInfo.hpp
Normal file
@ -0,0 +1,33 @@
|
||||
namespace Components
|
||||
{
|
||||
class ServerInfo : public Component
|
||||
{
|
||||
public:
|
||||
ServerInfo();
|
||||
~ServerInfo();
|
||||
const char* GetName() { return "ServerInfo"; };
|
||||
|
||||
private:
|
||||
struct Container
|
||||
{
|
||||
struct Player
|
||||
{
|
||||
int Ping;
|
||||
int Score;
|
||||
std::string Name;
|
||||
};
|
||||
|
||||
int CurrentPlayer;
|
||||
std::vector<Player> PlayerList;
|
||||
Network::Address Target;
|
||||
};
|
||||
|
||||
static Container PlayerContainer;
|
||||
|
||||
static void ServerStatus();
|
||||
|
||||
static int GetPlayerCount();
|
||||
static const char* GetPlayerText(int index, int column);
|
||||
static void SelectPlayer(int index);
|
||||
};
|
||||
}
|
@ -303,6 +303,11 @@ namespace Components
|
||||
ServerList::RefreshContainer.Mutex.unlock();
|
||||
}
|
||||
|
||||
ServerList::ServerInfo* ServerList::GetCurrentServer()
|
||||
{
|
||||
return ServerList::GetServer(ServerList::CurrentServer);
|
||||
}
|
||||
|
||||
void ServerList::SortList()
|
||||
{
|
||||
qsort(ServerList::VisibleList.data(), ServerList::VisibleList.size(), sizeof(int), [] (const void* first, const void* second)
|
||||
|
@ -30,6 +30,8 @@ namespace Components
|
||||
static void InsertRequest(Network::Address address, bool acquireMutex = true);
|
||||
static void Insert(Network::Address address, Utils::InfoString info);
|
||||
|
||||
static ServerInfo* GetCurrentServer();
|
||||
|
||||
static bool IsFavouriteList();
|
||||
static bool IsOfflineList();
|
||||
static bool IsOnlineList();
|
||||
|
@ -34,6 +34,7 @@ namespace Game
|
||||
Dvar_RegisterColor_t Dvar_RegisterColor = (Dvar_RegisterColor_t)0x471500;
|
||||
|
||||
Dvar_FindVar_t Dvar_FindVar = (Dvar_FindVar_t)0x4D5390;
|
||||
Dvar_InfoString_Big_t Dvar_InfoString_Big = (Dvar_InfoString_Big_t)0x4D98A0;
|
||||
Dvar_SetCommand_t Dvar_SetCommand = (Dvar_SetCommand_t)0x4EE430;
|
||||
|
||||
Field_Clear_t Field_Clear = (Field_Clear_t)0x437EB0;
|
||||
@ -87,6 +88,7 @@ namespace Game
|
||||
Party_GetMaxPlayers_t Party_GetMaxPlayers = (Party_GetMaxPlayers_t)0x4F5D60;
|
||||
PartyHost_CountMembers_t PartyHost_CountMembers = (PartyHost_CountMembers_t)0x497330;
|
||||
PartyHost_GetMemberAddressBySlot_t PartyHost_GetMemberAddressBySlot = (PartyHost_GetMemberAddressBySlot_t)0x44E100;
|
||||
PartyHost_GetMemberName_t PartyHost_GetMemberName = (PartyHost_GetMemberName_t)0x44BE90;
|
||||
|
||||
Script_Alloc_t Script_Alloc = (Script_Alloc_t)0x422E70;
|
||||
Script_SetupTokens_t Script_SetupTokens = (Script_SetupTokens_t)0x4E6950;
|
||||
@ -98,6 +100,8 @@ namespace Game
|
||||
|
||||
Steam_JoinLobby_t Steam_JoinLobby = (Steam_JoinLobby_t)0x49CF70;
|
||||
|
||||
SV_GameClientNum_Score_t SV_GameClientNum_Score = (SV_GameClientNum_Score_t)0x469AC0;
|
||||
|
||||
Sys_IsMainThread_t Sys_IsMainThread = (Sys_IsMainThread_t)0x4C37D0;
|
||||
|
||||
UI_AddMenuList_t UI_AddMenuList = (UI_AddMenuList_t)0x4533C0;
|
||||
|
@ -78,6 +78,9 @@ namespace Game
|
||||
typedef dvar_t* (__cdecl * Dvar_FindVar_t)(const char *dvarName);
|
||||
extern Dvar_FindVar_t Dvar_FindVar;
|
||||
|
||||
typedef char* (__cdecl* Dvar_InfoString_Big_t)(int typeMask);
|
||||
extern Dvar_InfoString_Big_t Dvar_InfoString_Big;
|
||||
|
||||
typedef dvar_t* (__cdecl * Dvar_SetCommand_t)(const char* name, const char* value);
|
||||
extern Dvar_SetCommand_t Dvar_SetCommand;
|
||||
|
||||
@ -199,6 +202,9 @@ namespace Game
|
||||
typedef netadr_t *(__cdecl * PartyHost_GetMemberAddressBySlot_t)(int unk, void *party, const int slot);
|
||||
extern PartyHost_GetMemberAddressBySlot_t PartyHost_GetMemberAddressBySlot;
|
||||
|
||||
typedef const char *(__cdecl * PartyHost_GetMemberName_t)(PartyData_s* party, const int clientNum);
|
||||
extern PartyHost_GetMemberName_t PartyHost_GetMemberName;
|
||||
|
||||
typedef script_t* (__cdecl * Script_Alloc_t)(int length);
|
||||
extern Script_Alloc_t Script_Alloc;
|
||||
|
||||
@ -217,6 +223,9 @@ namespace Game
|
||||
typedef void(__cdecl * Steam_JoinLobby_t)(SteamID, char);
|
||||
extern Steam_JoinLobby_t Steam_JoinLobby;
|
||||
|
||||
typedef int(__cdecl* SV_GameClientNum_Score_t)(int clientID);
|
||||
extern SV_GameClientNum_Score_t SV_GameClientNum_Score;
|
||||
|
||||
typedef bool(__cdecl * Sys_IsMainThread_t)();
|
||||
extern Sys_IsMainThread_t Sys_IsMainThread;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user