[MapRotation]: Refactor (#916)
This commit is contained in:
parent
1f94353e1a
commit
9b1f49252e
@ -121,7 +121,7 @@ namespace Components
|
||||
return;
|
||||
}
|
||||
|
||||
command.append("\n"); // Make sure it's terminated
|
||||
command.push_back('\n'); // Make sure it's terminated
|
||||
|
||||
assert(command.size() < Game::MAX_CMD_LINE);
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include <STDInclude.hpp>
|
||||
#include "MapRotation.hpp"
|
||||
#include "Party.hpp"
|
||||
|
||||
namespace Components
|
||||
{
|
||||
@ -25,7 +26,7 @@ namespace Components
|
||||
|
||||
void MapRotation::RotationData::addEntry(const std::string& key, const std::string& value)
|
||||
{
|
||||
this->rotationEntries_.emplace_back(std::make_pair(key, value));
|
||||
this->rotationEntries_.emplace_back(key, value);
|
||||
}
|
||||
|
||||
std::size_t MapRotation::RotationData::getEntriesSize() const noexcept
|
||||
@ -36,7 +37,7 @@ namespace Components
|
||||
MapRotation::RotationData::rotationEntry& MapRotation::RotationData::getNextEntry()
|
||||
{
|
||||
const auto index = this->index_;
|
||||
++this->index_ %= this->rotationEntries_.size(); // Point index_ to the next entry
|
||||
++this->index_ %= this->rotationEntries_.size();
|
||||
return this->rotationEntries_.at(index);
|
||||
}
|
||||
|
||||
@ -45,6 +46,19 @@ namespace Components
|
||||
return this->rotationEntries_.at(this->index_);
|
||||
}
|
||||
|
||||
void MapRotation::RotationData::setHandler(const std::string& key, const rotationCallback& callback)
|
||||
{
|
||||
this->rotationHandlers_[key] = callback;
|
||||
}
|
||||
|
||||
void MapRotation::RotationData::callHandler(const rotationEntry& entry) const
|
||||
{
|
||||
if (const auto itr = this->rotationHandlers_.find(entry.first); itr != this->rotationHandlers_.end())
|
||||
{
|
||||
itr->second(entry.second);
|
||||
}
|
||||
}
|
||||
|
||||
void MapRotation::RotationData::parse(const std::string& data)
|
||||
{
|
||||
const auto tokens = Utils::String::Split(data, ' ');
|
||||
@ -54,14 +68,12 @@ namespace Components
|
||||
const auto& key = tokens[i];
|
||||
const auto& value = tokens[i + 1];
|
||||
|
||||
if (key == "map"s || key == "gametype"s)
|
||||
if (!this->containsHandler(key))
|
||||
{
|
||||
this->addEntry(key, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw MapRotationParseError();
|
||||
throw MapRotationParseError(std::format("Invalid key {}", key));
|
||||
}
|
||||
|
||||
this->addEntry(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
@ -78,6 +90,16 @@ namespace Components
|
||||
});
|
||||
}
|
||||
|
||||
bool MapRotation::RotationData::containsHandler(const std::string& key) const
|
||||
{
|
||||
return this->rotationHandlers_.contains(key);
|
||||
}
|
||||
|
||||
void MapRotation::RotationData::clear() noexcept
|
||||
{
|
||||
this->rotationEntries_.clear();
|
||||
}
|
||||
|
||||
nlohmann::json MapRotation::RotationData::to_json() const
|
||||
{
|
||||
std::vector<std::string> mapVector;
|
||||
@ -97,8 +119,8 @@ namespace Components
|
||||
|
||||
auto mapRotationJson = nlohmann::json
|
||||
{
|
||||
{"maps", mapVector},
|
||||
{"gametypes", gametypeVector},
|
||||
{ "maps", mapVector },
|
||||
{ "gametypes", gametypeVector },
|
||||
};
|
||||
|
||||
return mapRotationJson;
|
||||
@ -183,7 +205,7 @@ namespace Components
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Dvar::Var("party_enable").get<bool>() && Dvar::Var("party_host").get<bool>())
|
||||
if (Party::IsEnabled() && Dvar::Var("party_host").get<bool>())
|
||||
{
|
||||
Logger::Warning(Game::CON_CHANNEL_SERVER, "Not performing map rotation as we are hosting a party!\n");
|
||||
return false;
|
||||
@ -212,6 +234,13 @@ namespace Components
|
||||
Game::Dvar_SetStringByName("g_gametype", gametype.data());
|
||||
}
|
||||
|
||||
void MapRotation::ApplyExec(const std::string& name)
|
||||
{
|
||||
assert(!name.empty());
|
||||
Command::Execute(std::format("exec {}", name), false);
|
||||
Command::Execute(std::format("exec game_settings/{}", name), false);
|
||||
}
|
||||
|
||||
void MapRotation::RestartCurrentMap()
|
||||
{
|
||||
std::string svMapname = (*Game::sv_mapname)->current.string;
|
||||
@ -234,21 +263,15 @@ namespace Components
|
||||
while (i < rotation.getEntriesSize())
|
||||
{
|
||||
const auto& entry = rotation.getNextEntry();
|
||||
rotation.callHandler(entry);
|
||||
Logger::Print("MapRotation: applying key '{}' with value '{}'\n", entry.first, entry.second);
|
||||
|
||||
if (entry.first == "map"s)
|
||||
{
|
||||
Logger::Print("Loading new map: '{}'", entry.second);
|
||||
ApplyMap(entry.second);
|
||||
|
||||
// Map was found so we exit the loop
|
||||
break;
|
||||
}
|
||||
|
||||
if (entry.first == "gametype"s)
|
||||
{
|
||||
Logger::Print("Applying new gametype: '{}'", entry.second);
|
||||
ApplyGametype(entry.second);
|
||||
}
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
@ -374,13 +397,15 @@ namespace Components
|
||||
AddMapRotationCommands();
|
||||
Utils::Hook::Set<void(*)()>(0x4152E8, SV_MapRotate_f);
|
||||
|
||||
DedicatedRotation.setHandler("map", ApplyMap);
|
||||
DedicatedRotation.setHandler("gametype", ApplyGametype);
|
||||
DedicatedRotation.setHandler("exec", ApplyExec);
|
||||
|
||||
Events::OnDvarInit(RegisterMapRotationDvars);
|
||||
}
|
||||
|
||||
bool MapRotation::unitTest()
|
||||
{
|
||||
RotationData rotation;
|
||||
|
||||
Logger::Debug("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";
|
||||
@ -395,6 +420,8 @@ namespace Components
|
||||
return false;
|
||||
}
|
||||
|
||||
DedicatedRotation.clear();
|
||||
|
||||
const auto* mistake = "spdevmap mp_dome";
|
||||
auto success = false;
|
||||
|
||||
|
@ -14,9 +14,27 @@ namespace Components
|
||||
bool unitTest() override;
|
||||
|
||||
private:
|
||||
struct MapRotationParseError : public std::exception
|
||||
class MapRotationParseError : public std::runtime_error
|
||||
{
|
||||
[[nodiscard]] const char* what() const noexcept override { return "Map Rotation Parse Error"; }
|
||||
private:
|
||||
static std::string fmt(const std::string& message)
|
||||
{
|
||||
std::string error = "Map Rotation Parse Error";
|
||||
|
||||
if (!message.empty())
|
||||
{
|
||||
error.append(": ");
|
||||
error.append(message);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
public:
|
||||
MapRotationParseError(const std::string& message)
|
||||
: std::runtime_error(fmt(message))
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class RotationData
|
||||
@ -24,6 +42,8 @@ namespace Components
|
||||
public:
|
||||
using rotationEntry = std::pair<std::string, std::string>;
|
||||
|
||||
using rotationCallback = std::function<void(const std::string&)>;
|
||||
|
||||
RotationData();
|
||||
|
||||
void randomize();
|
||||
@ -36,15 +56,22 @@ namespace Components
|
||||
rotationEntry& getNextEntry();
|
||||
rotationEntry& peekNextEntry();
|
||||
|
||||
void setHandler(const std::string& key, const rotationCallback& callback);
|
||||
void callHandler(const rotationEntry& entry) const;
|
||||
|
||||
void parse(const std::string& data);
|
||||
|
||||
[[nodiscard]] bool empty() const noexcept;
|
||||
[[nodiscard]] bool contains(const std::string& key, const std::string& value) const;
|
||||
[[nodiscard]] bool containsHandler(const std::string& key) const;
|
||||
|
||||
void clear() noexcept;
|
||||
|
||||
[[nodiscard]] nlohmann::json to_json() const;
|
||||
|
||||
private:
|
||||
std::vector<rotationEntry> rotationEntries_;
|
||||
std::unordered_map<std::string, rotationCallback> rotationHandlers_;
|
||||
|
||||
std::size_t index_;
|
||||
};
|
||||
@ -67,6 +94,7 @@ namespace Components
|
||||
static bool ShouldRotate();
|
||||
static void ApplyMap(const std::string& map);
|
||||
static void ApplyGametype(const std::string& gametype);
|
||||
static void ApplyExec(const std::string& name);
|
||||
static void RestartCurrentMap();
|
||||
static void ApplyRotation(RotationData& rotation);
|
||||
static void ApplyMapRotationCurrent(const std::string& data);
|
||||
|
@ -316,11 +316,17 @@ namespace Components
|
||||
|
||||
void Maps::GetBSPName(char* buffer, size_t size, const char* format, const char* mapname)
|
||||
{
|
||||
if (!Utils::String::StartsWith(mapname, "mp_") && !Utils::String::StartsWith(mapname, "zm_"))
|
||||
if (!Utils::String::StartsWith(mapname, "mp_"))
|
||||
{
|
||||
format = "maps/%s.d3dbsp";
|
||||
}
|
||||
|
||||
// TODO: Remove this hack by using CoD4 version of the map
|
||||
if (std::strcmp(mapname, "mp_shipment") == 0)
|
||||
{
|
||||
mapname = "mp_shipment_long";
|
||||
}
|
||||
|
||||
_snprintf_s(buffer, size, _TRUNCATE, format, mapname);
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,7 @@ namespace Components
|
||||
{
|
||||
Utils::Signal<Network::CallbackRaw> Network::StartupSignal;
|
||||
// Packet interception
|
||||
std::unordered_map<std::string, Network::NetworkCallback> Network::CL_Callbacks;
|
||||
std::unordered_map<std::string, Network::networkCallback> Network::CL_Callbacks;
|
||||
|
||||
Network::Address::Address()
|
||||
{
|
||||
@ -283,7 +283,7 @@ namespace Components
|
||||
Utils::Hook::Call<void(Game::client_t*, Game::msg_t*)>(0x414D40)(client, msg);
|
||||
}
|
||||
|
||||
void Network::OnClientPacket(const std::string& command, const NetworkCallback& callback)
|
||||
void Network::OnClientPacket(const std::string& command, const networkCallback& callback)
|
||||
{
|
||||
CL_Callbacks[Utils::String::ToLower(command)] = callback;
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ namespace Components
|
||||
|
||||
typedef void(CallbackRaw)();
|
||||
|
||||
using NetworkCallback = std::function<void(Address&, const std::string&)>;
|
||||
using networkCallback = std::function<void(Address&, const std::string&)>;
|
||||
|
||||
Network();
|
||||
|
||||
@ -72,11 +72,11 @@ namespace Components
|
||||
static void BroadcastRange(unsigned int min, unsigned int max, const std::string& data);
|
||||
static void BroadcastAll(const std::string& data);
|
||||
|
||||
static void OnClientPacket(const std::string& command, const NetworkCallback& callback);
|
||||
static void OnClientPacket(const std::string& command, const networkCallback& callback);
|
||||
|
||||
private:
|
||||
static Utils::Signal<CallbackRaw> StartupSignal;
|
||||
static std::unordered_map<std::string, NetworkCallback> CL_Callbacks;
|
||||
static std::unordered_map<std::string, networkCallback> CL_Callbacks;
|
||||
|
||||
static void NetworkStart();
|
||||
static void NetworkStartStub();
|
||||
|
@ -14,7 +14,7 @@ namespace Components
|
||||
|
||||
Utils::Cryptography::ECC::Key Session::SignatureKey;
|
||||
|
||||
std::unordered_map<std::string, Network::NetworkCallback> Session::PacketHandlers;
|
||||
std::unordered_map<std::string, Network::networkCallback> Session::PacketHandlers;
|
||||
|
||||
std::queue<std::pair<Network::Address, std::string>> Session::SignatureQueue;
|
||||
|
||||
@ -61,7 +61,7 @@ namespace Components
|
||||
#endif
|
||||
}
|
||||
|
||||
void Session::Handle(const std::string& packet, const Network::NetworkCallback& callback)
|
||||
void Session::Handle(const std::string& packet, const Network::networkCallback& callback)
|
||||
{
|
||||
#ifdef DISABLE_SESSION
|
||||
Network::OnClientPacket(packet, callback);
|
||||
|
@ -35,7 +35,7 @@ namespace Components
|
||||
void preDestroy() override;
|
||||
|
||||
static void Send(const Network::Address& target, const std::string& command, const std::string& data = "");
|
||||
static void Handle(const std::string& packet, const Network::NetworkCallback& callback);
|
||||
static void Handle(const std::string& packet, const Network::networkCallback& callback);
|
||||
|
||||
private:
|
||||
static volatile bool Terminate;
|
||||
@ -46,7 +46,7 @@ namespace Components
|
||||
|
||||
static Utils::Cryptography::ECC::Key SignatureKey;
|
||||
|
||||
static std::unordered_map<std::string, Network::NetworkCallback> PacketHandlers;
|
||||
static std::unordered_map<std::string, Network::networkCallback> PacketHandlers;
|
||||
|
||||
static std::queue<std::pair<Network::Address, std::string>> SignatureQueue;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user