[MapRotation] Allow people to circumvent 1024 dvar character limit
This commit is contained in:
parent
020201ab1f
commit
bf4ae7f116
@ -175,13 +175,13 @@ namespace Components
|
||||
|
||||
Logger::Print("Performing unit tests for components:\n");
|
||||
|
||||
for (auto component : Loader::Components)
|
||||
for (const auto component : Loader::Components)
|
||||
{
|
||||
#if defined(DEBUG) || defined(FORCE_UNIT_TESTS)
|
||||
Logger::Print("Testing '{}'...\n", component->getName());
|
||||
#if defined(FORCE_UNIT_TESTS)
|
||||
Logger::Debug("Testing '{}'...\n", component->getName());
|
||||
#endif
|
||||
auto startTime = std::chrono::high_resolution_clock::now();
|
||||
bool testRes = component->unitTest();
|
||||
auto testRes = component->unitTest();
|
||||
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - startTime).count();
|
||||
Logger::Print("Test done ({}ms): {}\n\n", duration, (testRes ? "Success" : "Error"));
|
||||
result &= testRes;
|
||||
|
@ -5,8 +5,8 @@ namespace Components
|
||||
class Component
|
||||
{
|
||||
public:
|
||||
Component() {}
|
||||
virtual ~Component() {}
|
||||
Component() = default;
|
||||
virtual ~Component() = default;
|
||||
|
||||
#if defined(DEBUG) || defined(FORCE_UNIT_TESTS)
|
||||
virtual std::string getName()
|
||||
|
@ -89,21 +89,21 @@ namespace Components
|
||||
std::vector<std::string> idVector;
|
||||
std::vector<std::string> ipVector;
|
||||
|
||||
for (auto& idEntry : list->idList)
|
||||
for (const auto& idEntry : list->idList)
|
||||
{
|
||||
idVector.push_back(Utils::String::VA("%llX", idEntry.bits));
|
||||
idVector.emplace_back(Utils::String::VA("%llX", idEntry.bits));
|
||||
}
|
||||
|
||||
for (auto& ipEntry : list->ipList)
|
||||
for (const auto& ipEntry : list->ipList)
|
||||
{
|
||||
ipVector.push_back(Utils::String::VA("%u.%u.%u.%u",
|
||||
ipVector.emplace_back(Utils::String::VA("%u.%u.%u.%u",
|
||||
ipEntry.bytes[0] & 0xFF,
|
||||
ipEntry.bytes[1] & 0xFF,
|
||||
ipEntry.bytes[2] & 0xFF,
|
||||
ipEntry.bytes[3] & 0xFF));
|
||||
}
|
||||
|
||||
json11::Json bans = json11::Json::object
|
||||
const json11::Json bans = json11::Json::object
|
||||
{
|
||||
{ "ip", ipVector },
|
||||
{ "id", idVector },
|
||||
|
@ -113,19 +113,19 @@ namespace Components
|
||||
|
||||
void Logger::Frame()
|
||||
{
|
||||
std::lock_guard<std::mutex> _(Logger::MessageMutex);
|
||||
std::unique_lock _(Logger::MessageMutex);
|
||||
|
||||
for (std::size_t i = 0; i < Logger::MessageQueue.size(); ++i)
|
||||
for (auto i = Logger::MessageQueue.begin(); i != Logger::MessageQueue.end();)
|
||||
{
|
||||
Game::Com_PrintMessage(Game::CON_CHANNEL_DONT_FILTER, Logger::MessageQueue[i].data(), 0);
|
||||
Game::Com_PrintMessage(Game::CON_CHANNEL_DONT_FILTER, i->data(), 0);
|
||||
|
||||
if (!Logger::IsConsoleReady())
|
||||
{
|
||||
OutputDebugStringA(Logger::MessageQueue[i].data());
|
||||
OutputDebugStringA(i->data());
|
||||
}
|
||||
}
|
||||
|
||||
Logger::MessageQueue.clear();
|
||||
i = Logger::MessageQueue.erase(i);
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::PipeOutput(void(*callback)(const std::string&))
|
||||
@ -203,9 +203,8 @@ namespace Components
|
||||
|
||||
void Logger::EnqueueMessage(const std::string& message)
|
||||
{
|
||||
Logger::MessageMutex.lock();
|
||||
std::unique_lock _(Logger::MessageMutex);
|
||||
Logger::MessageQueue.push_back(message);
|
||||
Logger::MessageMutex.unlock();
|
||||
}
|
||||
|
||||
void Logger::RedirectOSPath(const char* file, char* folder)
|
||||
@ -375,9 +374,9 @@ namespace Components
|
||||
Logger::LoggingAddresses[0].clear();
|
||||
Logger::LoggingAddresses[1].clear();
|
||||
|
||||
Logger::MessageMutex.lock();
|
||||
std::unique_lock lock(Logger::MessageMutex);
|
||||
Logger::MessageQueue.clear();
|
||||
Logger::MessageMutex.unlock();
|
||||
lock.unlock();
|
||||
|
||||
// Flush the console log
|
||||
if (const auto logfile = *reinterpret_cast<int*>(0x1AD8F28))
|
||||
|
@ -61,6 +61,33 @@ namespace Components
|
||||
}
|
||||
}
|
||||
|
||||
json11::Json MapRotation::RotationData::to_json() const
|
||||
{
|
||||
std::vector<std::string> mapVector;
|
||||
std::vector<std::string> gametypeVector;
|
||||
|
||||
for (const auto& [key, val] : this->rotationEntries_)
|
||||
{
|
||||
if (key == "map")
|
||||
{
|
||||
mapVector.emplace_back(val);
|
||||
}
|
||||
else if (key == "gametype")
|
||||
{
|
||||
gametypeVector.emplace_back(val);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
json11::Json mapRotationJson = json11::Json::object
|
||||
{
|
||||
{"maps", mapVector},
|
||||
{"gametypes", gametypeVector},
|
||||
};
|
||||
|
||||
return mapRotationJson;
|
||||
}
|
||||
|
||||
void MapRotation::LoadRotation(const std::string& data)
|
||||
{
|
||||
static auto loaded = false;
|
||||
@ -77,10 +104,10 @@ namespace Components
|
||||
}
|
||||
catch (const std::exception& ex)
|
||||
{
|
||||
Logger::Print(Game::CON_CHANNEL_SERVER, "%s: sv_mapRotation contains invalid data!\n", ex.what());
|
||||
Logger::Print(Game::CON_CHANNEL_SERVER, "{}: sv_mapRotation contains invalid data!\n", ex.what());
|
||||
}
|
||||
|
||||
Logger::Print(Game::CON_CHANNEL_SERVER, "DedicatedRotation size after parsing is '%u'\n", DedicatedRotation.getEntriesSize());
|
||||
Logger::DebugInfo("DedicatedRotation size after parsing is '{}'\n", DedicatedRotation.getEntriesSize());
|
||||
|
||||
// Shuffles values
|
||||
if (SVRandomMapRotation.get<bool>())
|
||||
@ -92,6 +119,31 @@ namespace Components
|
||||
loaded = true;
|
||||
}
|
||||
|
||||
void MapRotation::AddMapRotationCommands()
|
||||
{
|
||||
Command::Add("AddMap", [](Command::Params* params)
|
||||
{
|
||||
if (params->size() < 2)
|
||||
{
|
||||
Logger::Print("{} <map name> : add a map to the map rotation\n", params->get(0));
|
||||
return;
|
||||
}
|
||||
|
||||
DedicatedRotation.addEntry("map", params->get(1));
|
||||
});
|
||||
|
||||
Command::Add("AddGametype", [](Command::Params* params)
|
||||
{
|
||||
if (params->size() < 2)
|
||||
{
|
||||
Logger::Print("{} <gametype> : add a game mode to the map rotation\n", params->get(0));
|
||||
return;
|
||||
}
|
||||
|
||||
DedicatedRotation.addEntry("gametype", params->get(1));
|
||||
});
|
||||
}
|
||||
|
||||
bool MapRotation::ShouldRotate()
|
||||
{
|
||||
if (!Dedicated::IsEnabled() && SVDontRotate.get<bool>())
|
||||
@ -132,7 +184,7 @@ namespace Components
|
||||
|
||||
void MapRotation::ApplyMapRotation()
|
||||
{
|
||||
// Continue to apply gamemode until a map is found
|
||||
// Continue to apply gametype until a map is found
|
||||
auto foundMap = false;
|
||||
|
||||
std::size_t i = 0;
|
||||
@ -142,15 +194,15 @@ namespace Components
|
||||
|
||||
if (entry.first == "map")
|
||||
{
|
||||
Logger::Print("Loading new map: '%s'\n", entry.second.data());
|
||||
Logger::DebugInfo("Loading new map: '{}'\n", entry.second);
|
||||
Command::Execute(Utils::String::VA("map %s", entry.second.data()), true);
|
||||
|
||||
// Map was found so we exit the loop
|
||||
foundMap = true;
|
||||
}
|
||||
else if (entry.first == "gamemode")
|
||||
else if (entry.first == "gametype")
|
||||
{
|
||||
Logger::Print("Applying new gametype: '%s'\n", entry.second.data());
|
||||
Logger::DebugInfo("Applying new gametype: '{}'\n", entry.second);
|
||||
Dvar::Var("g_gametype").set(entry.second);
|
||||
}
|
||||
|
||||
@ -189,6 +241,7 @@ namespace Components
|
||||
|
||||
MapRotation::MapRotation()
|
||||
{
|
||||
AddMapRotationCommands();
|
||||
Utils::Hook::Set<void(*)()>(0x4152E8, SV_MapRotate_f);
|
||||
|
||||
SVRandomMapRotation = Dvar::Register<bool>("sv_randomMapRotation", false,
|
||||
@ -196,4 +249,38 @@ namespace Components
|
||||
SVDontRotate = Dvar::Register<bool>("sv_dontRotate", false,
|
||||
Game::dvar_flag::DVAR_NONE, "Do not perform map rotation");
|
||||
}
|
||||
|
||||
bool MapRotation::unitTest()
|
||||
{
|
||||
RotationData rotation;
|
||||
|
||||
Logger::DebugInfo("Testing map rotation parsing...");
|
||||
|
||||
const auto* normal = "map mp_highrise map mp_terminal map mp_firingrange map mp_trailerpark gametype dm map mp_shipment_long";
|
||||
|
||||
try
|
||||
{
|
||||
DedicatedRotation.parse(normal);
|
||||
}
|
||||
catch (const std::exception& ex)
|
||||
{
|
||||
Logger::PrintError(Game::CON_CHANNEL_ERROR, "{}: parsing of 'normal' failed", ex.what());
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto* mistake = "spdevmap mp_dome";
|
||||
auto success = false;
|
||||
|
||||
try
|
||||
{
|
||||
DedicatedRotation.parse(mistake);
|
||||
}
|
||||
catch (const std::exception& ex)
|
||||
{
|
||||
Logger::Debug("{}: parsing of 'normal' failed as expected", ex.what());
|
||||
success = true;
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,8 @@ namespace Components
|
||||
public:
|
||||
MapRotation();
|
||||
|
||||
bool unitTest() override;
|
||||
|
||||
private:
|
||||
struct ParseRotationError : public std::exception
|
||||
{
|
||||
@ -31,6 +33,9 @@ namespace Components
|
||||
|
||||
void parse(const std::string& data);
|
||||
|
||||
// Json11 Implicit constructor
|
||||
[[nodiscard]] json11::Json to_json() const;
|
||||
|
||||
private:
|
||||
std::vector<rotationEntry> rotationEntries_;
|
||||
|
||||
@ -49,6 +54,9 @@ namespace Components
|
||||
|
||||
static void LoadRotation(const std::string& data);
|
||||
|
||||
// Use these commands before SV_MapRotate_f is called
|
||||
static void AddMapRotationCommands();
|
||||
|
||||
static bool ShouldRotate();
|
||||
static void RestartCurrentMap();
|
||||
static void ApplyMapRotation();
|
||||
|
@ -731,9 +731,9 @@ namespace Components
|
||||
bool QuickPatch::unitTest()
|
||||
{
|
||||
uint32_t randIntCount = 4'000'000;
|
||||
printf("Generating %d random integers...", randIntCount);
|
||||
Logger::Debug("Generating %d random integers...", randIntCount);
|
||||
|
||||
auto startTime = std::chrono::high_resolution_clock::now();
|
||||
const auto startTime = std::chrono::high_resolution_clock::now();
|
||||
|
||||
for (uint32_t i = 0; i < randIntCount; ++i)
|
||||
{
|
||||
@ -741,9 +741,9 @@ namespace Components
|
||||
}
|
||||
|
||||
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - startTime).count();
|
||||
Logger::Print("took {}ms\n", duration);
|
||||
Logger::Debug("took {}ms\n", duration);
|
||||
|
||||
printf("Testing ZLib compression...");
|
||||
Logger::Debug("Testing ZLib compression...");
|
||||
|
||||
std::string test = Utils::String::VA("%c", Utils::Cryptography::Rand::GenerateInt());
|
||||
|
||||
@ -754,21 +754,20 @@ namespace Components
|
||||
|
||||
if (test != decompressed)
|
||||
{
|
||||
printf("Error\n");
|
||||
printf("Compressing %d bytes and decompressing failed!\n", test.size());
|
||||
Logger::PrintError(Game::CON_CHANNEL_ERROR, "Compressing {} bytes and decompressing failed!\n", test.size());
|
||||
return false;
|
||||
}
|
||||
|
||||
auto size = test.size();
|
||||
const auto size = test.size();
|
||||
for (unsigned int j = 0; j < size; ++j)
|
||||
{
|
||||
test.append(Utils::String::VA("%c", Utils::Cryptography::Rand::GenerateInt()));
|
||||
}
|
||||
}
|
||||
|
||||
printf("Success\n");
|
||||
Logger::Debug("Success");
|
||||
|
||||
printf("Testing trimming...");
|
||||
Logger::Debug("Testing trimming...");
|
||||
std::string trim1 = " 1 ";
|
||||
std::string trim2 = " 1";
|
||||
std::string trim3 = "1 ";
|
||||
@ -781,7 +780,7 @@ namespace Components
|
||||
if (trim2 != "1") return false;
|
||||
if (trim3 != "1") return false;
|
||||
|
||||
printf("Success\n");
|
||||
Logger::Debug("Success");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user