General Refactoring

* [General] Clean up a few things
This commit is contained in:
Edo 2022-06-04 22:16:55 +02:00 committed by GitHub
parent 558bf09338
commit 27f78edb29
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 152 additions and 94 deletions

View File

@ -19,7 +19,7 @@ The format is based on [Keep a Changelog v0.3.0](http://keepachangelog.com/en/0.
- Knife charge is fixed for controller players (#259)
- Fixed internet, local and favorites filters (#260)
- `sv_lanOnly` Dvar now prevents the server from sending heatbeats to master if set to true (#246)
- `sv_lanOnly` Dvar now prevents the server from sending heartbeats to master if set to true (#246)
### Known issue

View File

@ -6,6 +6,8 @@ namespace Components
Dvar::Var Dedicated::SVRandomMapRotation;
Dvar::Var Dedicated::SVLanOnly;
Dvar::Var Dedicated::SVDontRotate;
Dvar::Var Dedicated::COMLogFilter;
bool Dedicated::IsEnabled()
{
@ -35,7 +37,7 @@ namespace Components
std::memcpy(reinterpret_cast<void*>(0x66E1CB0), &fastfiles, sizeof(fastfiles));
Game::R_LoadGraphicsAssets();
if (Dvar::Var("com_logFilter").get<bool>())
if (COMLogFilter.get<bool>())
{
Utils::Hook::Nop(0x647466, 5); // 'dvar set' lines
Utils::Hook::Nop(0x5DF4F2, 5); // 'sending splash open' lines
@ -129,21 +131,22 @@ namespace Components
const auto tokens = Utils::String::Split(rotation, ' ');
std::vector<std::pair<std::string, std::string>> mapRotationPair;
for (auto i = 0u; i < (tokens.size() - 1); i += 2)
for (std::size_t i = 0; i < (tokens.size() - 1); i += 2)
{
if (i + 1 >= tokens.size()) break;
const auto& key = tokens[i];
const auto& value = tokens[i + 1];
mapRotationPair.push_back(std::make_pair(key, value));
mapRotationPair.emplace_back(std::make_pair(key, value));
}
const auto seed = Utils::Cryptography::Rand::GenerateInt();
std::shuffle(std::begin(mapRotationPair), std::end(mapRotationPair), std::default_random_engine(seed));
std::shuffle(mapRotationPair.begin(), mapRotationPair.end(), std::default_random_engine(seed));
// Rebuild map rotation using the randomized key/values
rotation.clear();
for (auto j = 0u; j < mapRotationPair.size(); j++)
for (std::size_t j = 0; j < mapRotationPair.size(); j++)
{
const auto& pair = mapRotationPair[j];
rotation.append(pair.first);
@ -151,33 +154,79 @@ namespace Components
rotation.append(pair.second);
if (j != mapRotationPair.size() - 1)
rotation.append(" ");
rotation.append(" "); // No space on last element
}
Dvar::Var("sv_mapRotationCurrent").set(rotation);
}
void Dedicated::ApplyMapRotation()
{
auto rotation = Dvar::Var("sv_mapRotationCurrent").get<std::string>();
const auto tokens = Utils::String::Split(rotation, ' ');
for (std::size_t i = 0; i < (tokens.size() - 1); i += 2)
{
if (i + 1 >= tokens.size())
{
Dvar::Var("sv_mapRotationCurrent").set("");
Command::Execute("map_rotate", true);
return;
}
const auto& key = tokens[i];
const auto& value = tokens[i + 1];
if (key == "map")
{
// Rebuild map rotation string
rotation.clear();
for (std::size_t j = (i + 2); j < tokens.size(); ++j)
{
if (j != (i + 2)) rotation += " ";
rotation += tokens[j];
}
Dvar::Var("sv_mapRotationCurrent").set(rotation);
Logger::Print(Game::conChannel_t::CON_CHANNEL_SERVER,"Loading new map: %s\n", value.data());
Command::Execute(Utils::String::VA("map %s", value.data()), true);
break;
}
if (key == "gametype")
{
Logger::Print(Game::conChannel_t::CON_CHANNEL_SERVER, "Applying new gametype: %s\n", value.data());
Dvar::Var("g_gametype").set(value);
}
else
{
Logger::Print(Game::conChannel_t::CON_CHANNEL_SERVER, "Unsupported maprotation key '%s'!\n", key.data());
}
}
}
void Dedicated::MapRotate()
{
if (!Dedicated::IsEnabled() && Dvar::Var("sv_dontrotate").get<bool>())
if (!Dedicated::IsEnabled() && Dedicated::SVDontRotate.get<bool>())
{
Dvar::Var("sv_dontrotate").set(false);
Dedicated::SVDontRotate.set(false);
return;
}
if (Dvar::Var("party_enable").get<bool>() && Dvar::Var("party_host").get<bool>())
{
Logger::Print("Not performing map rotation as we are hosting a party!\n");
Logger::Print(Game::conChannel_t::CON_CHANNEL_SERVER, "Not performing map rotation as we are hosting a party!\n");
return;
}
Logger::Print("Rotating map...\n");
Logger::Print(Game::conChannel_t::CON_CHANNEL_SERVER, "Rotating map...\n");
const auto mapRotation = Dvar::Var("sv_mapRotation").get<std::string>();
// if nothing, just restart
if (mapRotation.empty())
{
Logger::Print("No rotation defined, restarting map.\n");
Logger::Print(Game::conChannel_t::CON_CHANNEL_SERVER, "No rotation defined, restarting map.\n");
if (!Dvar::Var("sv_cheats").get<bool>())
{
@ -194,11 +243,11 @@ namespace Components
// First, check if the string contains nothing
if (Dvar::Var("sv_mapRotationCurrent").get<std::string>().empty())
{
Logger::Print("Current map rotation has finished, reloading...\n");
Logger::Print(Game::conChannel_t::CON_CHANNEL_SERVER, "Current map rotation has finished, reloading...\n");
if (Dedicated::SVRandomMapRotation.get<bool>())
{
Logger::Print("Randomizing map rotation\n");
Logger::Print(Game::conChannel_t::CON_CHANNEL_SERVER, "Randomizing map rotation\n");
Dedicated::RandomizeMapRotation();
}
else
@ -207,48 +256,7 @@ namespace Components
}
}
auto rotation = Dvar::Var("sv_mapRotationCurrent").get<std::string>();
auto tokens = Utils::String::Split(rotation, ' ');
for (unsigned int i = 0; i < (tokens.size() - 1); i += 2)
{
if (i + 1 >= tokens.size())
{
Dvar::Var("sv_mapRotationCurrent").set("");
Command::Execute("map_rotate", true);
return;
}
std::string key = tokens[i];
std::string value = tokens[i + 1];
if (key == "map")
{
// Rebuild map rotation string
rotation.clear();
for (unsigned int j = (i + 2); j < tokens.size(); ++j)
{
if (j != (i + 2)) rotation += " ";
rotation += tokens[j];
}
Dvar::Var("sv_mapRotationCurrent").set(rotation);
Logger::Print("Loading new map: %s\n", value.data());
Command::Execute(Utils::String::VA("map %s", value.data()), true);
break;
}
else if (key == "gametype")
{
Logger::Print("Applying new gametype: %s\n", value.data());
Dvar::Var("g_gametype").set(value);
}
else
{
Logger::Print("Unsupported maprotation key '%s', motherfucker!\n", key.data());
}
}
Dedicated::ApplyMapRotation();
}
void Dedicated::Heartbeat()
@ -264,7 +272,7 @@ namespace Components
Network::Address master(Utils::String::VA("%s:%u", masterServerName, masterPort));
Logger::Print("Sending heartbeat to master: %s:%u\n", masterServerName, masterPort);
Logger::Print(Game::conChannel_t::CON_CHANNEL_SERVER, "Sending heartbeat to master: %s:%u\n", masterServerName, masterPort);
Network::SendCommand(master, "heartbeat", "IW4");
}
@ -290,8 +298,13 @@ namespace Components
{
// Map rotation
Utils::Hook::Set(0x4152E8, Dedicated::MapRotate);
Dvar::Register<bool>("sv_dontrotate", false, Game::dvar_flag::DVAR_CHEAT, "");
Dvar::Register<bool>("com_logFilter", true, Game::dvar_flag::DVAR_LATCH, "Removes ~95% of unneeded lines from the log");
Dvar::OnInit([]
{
Dedicated::SVDontRotate = Dvar::Register<bool>("sv_dontRotate", false,
Game::dvar_flag::DVAR_NONE, "");
Dedicated::COMLogFilter = Dvar::Register<bool>("com_logFilter", true,
Game::dvar_flag::DVAR_LATCH, "Removes ~95% of unneeded lines from the log");
});
if (Dedicated::IsEnabled() || ZoneBuilder::IsEnabled())
{

View File

@ -9,6 +9,8 @@ namespace Components
static SteamID PlayerGuids[18][2];
static Dvar::Var SVLanOnly;
static Dvar::Var SVDontRotate;
static Dvar::Var COMLogFilter;
static bool IsEnabled();
@ -18,6 +20,7 @@ namespace Components
static Dvar::Var SVRandomMapRotation;
static void RandomizeMapRotation();
static void ApplyMapRotation();
static void MapRotate();
static void InitDedicatedServer();

View File

@ -45,13 +45,29 @@ namespace Components
if (params.size() >= 4)
{
const auto* dvarName = params[3];
const auto* dvar = Game::Dvar_FindVar(dvarName);
if (Command::Find(dvarName) ||
(dvar != nullptr && dvar->flags & (Game::DVAR_WRITEPROTECTED | Game::DVAR_CHEAT | Game::DVAR_READONLY)))
const auto* name = params.get(3);
// If it's a command don't execute it
if (Command::Find(name) != nullptr)
{
Logger::Print(0, "CL_SelectStringTableEntryInDvar_f: illegal parameter\n");
Logger::Print(0, "CL_SelectStringTableEntryInDvar_f: parameter is a command\n");
return;
}
const auto* dvar = Game::Dvar_FindVar(name);
if (dvar == nullptr)
{
// If it's not a dvar let it continue
Game::CL_SelectStringTableEntryInDvar_f();
return;
}
constexpr auto disallowedFlags = (Game::DVAR_CHEAT | Game::DVAR_WRITEPROTECTED
| Game::DVAR_READONLY | Game::DVAR_EXTERNAL | Game::DVAR_LATCH);
// If it's a dvar check that it does not have disallowed flags
if ((dvar->flags & disallowedFlags) != 0)
{
Logger::Print(0, "CL_SelectStringTableEntryInDvar_f: parameter is a protected dvar\n");
return;
}
}

View File

@ -45,7 +45,7 @@ namespace Components
if (Game::Scr_GetNumParam() >= 3u)
{
duration = static_cast<int>(Game::Scr_GetFloat(2) * 1000.0);
duration = static_cast<int>(Game::Scr_GetFloat(2) * 1000.0f);
}
int delay = 0;
@ -70,16 +70,16 @@ namespace Components
// set snapshot num to 1 behind (T6 does this, why shouldn't we?)
for (int i = 0; i < *Game::svs_clientCount; ++i)
{
Game::svs_clients[i].snapNum = *reinterpret_cast<DWORD*>(0x31D9384) - 1;
Game::svs_clients[i].snapNum = *Game::svs_time - 1;
}
}
void SlowMotion::DrawConnectionInterruptedStub(int /*a1*/)
{
// if (!*reinterpret_cast<bool*>(0x1AD8ED0) && !*reinterpret_cast<bool*>(0x1AD8EEC) && !*reinterpret_cast<int*>(0x1AD78F8))
// {
// Utils::Hook::Call<void(int)>(0x454A70)(a1);
// }
// if (!*reinterpret_cast<bool*>(0x1AD8ED0) && !*reinterpret_cast<bool*>(0x1AD8EEC) && !*reinterpret_cast<int*>(0x1AD78F8))
// {
// Utils::Hook::Call<void(int)>(0x454A70)(a1);
// }
}
SlowMotion::SlowMotion()

View File

@ -39,7 +39,7 @@ namespace Main
popad
push 6BAA2Fh // Continue init routine
push 6CA062h // ___security_init_cookie
push 6CA062h // __security_init_cookie
retn
}
}

View File

@ -514,7 +514,7 @@ namespace Game
FxEffectDef*** varFxEffectDefHandle = reinterpret_cast<FxEffectDef***>(0x112ACC0);
PhysCollmap*** varPhysCollmapPtr = reinterpret_cast<PhysCollmap***>(0x112B440);
PhysPreset*** varPhysPresetPtr = reinterpret_cast<PhysPreset***>(0x112B378);
Game::MaterialPass** varMaterialPass = reinterpret_cast<Game::MaterialPass**>(0x112A960);
MaterialPass** varMaterialPass = reinterpret_cast<MaterialPass**>(0x112A960);
snd_alias_list_t*** varsnd_alias_list_name = reinterpret_cast<snd_alias_list_t***>(0x112AF38);
FxElemField* s_elemFields = reinterpret_cast<FxElemField*>(0x73B848);
@ -577,6 +577,8 @@ namespace Game
int* g_waitingForKey = reinterpret_cast<int*>(0x63A50FC);
unsigned long* _tls_index = reinterpret_cast<unsigned long*>(0x66D94A8);
void Sys_LockRead(FastCriticalSection* critSect)
{
InterlockedIncrement(&critSect->readCount);

View File

@ -1194,6 +1194,8 @@ namespace Game
extern int* g_waitingForKey;
extern unsigned long* _tls_index;
void Sys_LockRead(FastCriticalSection* critSect);
void Sys_UnlockRead(FastCriticalSection* critSect);

View File

@ -135,24 +135,24 @@ namespace Game
enum dvar_flag : unsigned __int16
{
DVAR_NONE = 0x0, // No flags
DVAR_ARCHIVE = 0x1, // Set to cause it to be saved to config_mp.cfg of the client
DVAR_LATCH = 0x2, // Will only change when C code next does a Dvar_Get(), so it can't be changed
DVAR_NONE = 0, // No flags
DVAR_ARCHIVE = 1 << 0, // Set to cause it to be saved to config_mp.cfg of the client
DVAR_LATCH = 1 << 1, // Will only change when C code next does a Dvar_Get(), so it can't be changed
// without proper initialization. Modified will be set, even though the value hasn't changed yet
DVAR_CHEAT = 0x4, // Can not be changed if cheats are disabled
DVAR_CODINFO = 0x8, // On change, this is sent to all clients (if you are host)
DVAR_SCRIPTINFO = 0x10,
DVAR_UNKNOWN20 = 0x20,
DVAR_CHANGEABLE_RESET = 0x40,
DVAR_UNKNOWN80 = 0x80,
DVAR_EXTERNAL = 0x100, // Created by a set command
DVAR_USERINFO = 0x200, // Sent to server on connect or change
DVAR_SERVERINFO = 0x400, // Sent in response to front end requests
DVAR_WRITEPROTECTED = 0x800,
DVAR_SYSTEMINFO = 0x1000, // Will be duplicated on all clients
DVAR_READONLY = 0x2000, // Read only (same as DVAR_WRITEPROTECTED?)
DVAR_SAVED = 0x4000,
DVAR_AUTOEXEC = 0x8000,
DVAR_CHEAT = 1 << 2, // Can not be changed if cheats are disabled
DVAR_CODINFO = 1 << 3, // On change, this is sent to all clients (if you are host)
DVAR_SCRIPTINFO = 1 << 4,
DVAR_UNKNOWN20 = 1 << 5,
DVAR_CHANGEABLE_RESET = 1 << 6,
DVAR_UNKNOWN80 = 1 << 7,
DVAR_EXTERNAL = 1 << 8, // Created by a set command
DVAR_USERINFO = 1 << 9, // Sent to server on connect or change
DVAR_SERVERINFO = 1 << 10, // Sent in response to front end requests
DVAR_WRITEPROTECTED = 1 << 11,
DVAR_SYSTEMINFO = 1 << 12, // Will be duplicated on all clients
DVAR_READONLY = 1 << 13, // Read only (same as DVAR_WRITEPROTECTED?)
DVAR_SAVED = 1 << 14,
DVAR_AUTOEXEC = 1 << 15, // isLoadingAutoExecGlobalFlag is always false so it should be never set by the game
};
enum ImageCategory : char
@ -234,6 +234,13 @@ namespace Game
CS_ACTIVE = 0x5,
} clientstate_t;
enum serverState_t
{
SS_DEAD = 0x0,
SS_LOADING = 0x1,
SS_GAME = 0x2,
};
enum errorParm_t
{
ERR_FATAL = 0x0,
@ -1620,7 +1627,6 @@ namespace Game
int groundEntityNum;
int loopSound;
int surfType;
union
{
int brushModel;
@ -1629,7 +1635,6 @@ namespace Game
int xmodel;
int primaryLight;
} index;
int clientNum;
int iHeadIcon;
int iHeadIconTeam;
@ -1641,8 +1646,23 @@ namespace Game
unsigned __int16 weapon;
int legsAnim;
int torsoAnim;
int un1;
int un2;
union
{
int eventParm2;
int hintString;
int fxId;
int helicopterStage;
} un1;
union
{
int hintType;
struct
{
unsigned __int16 vehicleXModel;
char weaponModel;
} __s1;
int actorFlags;
} un2;
clientLinkInfo_t clientLinkInfo;
unsigned int partBits[6];
int clientMask[1];
@ -2152,6 +2172,8 @@ namespace Game
cLeaf_t leaf;
};
static_assert(sizeof(cmodel_t) == 0x44);
struct TriggerModel
{
int contents;