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