2023-11-20 19:26:52 +00:00
|
|
|
#include "ServerPreconditions.h"
|
2023-10-22 15:36:08 +00:00
|
|
|
|
|
|
|
#include "tinyxml2.h"
|
|
|
|
|
|
|
|
using namespace ServerPreconditions;
|
|
|
|
|
2023-11-20 19:26:52 +00:00
|
|
|
namespace {
|
|
|
|
std::unordered_map<LOT, std::vector<std::pair<bool, PreconditionExpression>>> m_Preconditions;
|
2023-10-22 15:36:08 +00:00
|
|
|
|
2023-11-20 19:26:52 +00:00
|
|
|
std::unordered_map<LWOOBJID, LWOOBJID> m_SoloActors;
|
2023-10-22 15:36:08 +00:00
|
|
|
|
2023-11-20 19:26:52 +00:00
|
|
|
std::unordered_map<LWOOBJID, std::unordered_set<LWOOBJID>> m_ExcludeForPlayer;
|
|
|
|
}
|
2023-10-22 15:36:08 +00:00
|
|
|
|
|
|
|
void ServerPreconditions::LoadPreconditions(std::string file) {
|
|
|
|
tinyxml2::XMLDocument doc;
|
|
|
|
doc.LoadFile(file.c_str());
|
|
|
|
|
|
|
|
tinyxml2::XMLElement* root = doc.FirstChildElement("Preconditions");
|
|
|
|
if (!root) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (tinyxml2::XMLElement* element = root->FirstChildElement("Entity"); element; element = element->NextSiblingElement("Entity")) {
|
|
|
|
LOT lot = element->UnsignedAttribute("lot");
|
|
|
|
std::vector<std::pair<bool, PreconditionExpression>> preconditions;
|
|
|
|
|
|
|
|
for (tinyxml2::XMLElement* precondition = element->FirstChildElement("Precondition"); precondition; precondition = precondition->NextSiblingElement("Precondition")) {
|
|
|
|
const auto condition = Preconditions::CreateExpression(precondition->GetText());
|
|
|
|
|
|
|
|
int64_t inverted;
|
|
|
|
|
|
|
|
if (precondition->QueryInt64Attribute("not", &inverted) == tinyxml2::XML_SUCCESS) {
|
|
|
|
preconditions.push_back(std::make_pair(inverted > 0, condition));
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
preconditions.push_back(std::make_pair(false, condition));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
m_Preconditions[lot] = preconditions;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ServerPreconditions::CheckPreconditions(Entity* target, Entity* entity) {
|
|
|
|
if (IsExcludedFor(entity->GetObjectID(), target->GetObjectID())) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (IsSoloActor(target->GetObjectID())) {
|
|
|
|
return IsActingFor(target->GetObjectID(), entity->GetObjectID());
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_Preconditions.find(target->GetLOT()) == m_Preconditions.end()) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (const auto& [inverse, precondition] : m_Preconditions[target->GetLOT()]) {
|
|
|
|
if (precondition.Check(entity) == inverse) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ServerPreconditions::IsSoloActor(LWOOBJID actor) {
|
|
|
|
return m_SoloActors.find(actor) != m_SoloActors.end();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ServerPreconditions::IsActingFor(LWOOBJID actor, LWOOBJID target) {
|
|
|
|
return m_SoloActors.find(actor) != m_SoloActors.end() && m_SoloActors[actor] == target;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ServerPreconditions::AddSoloActor(LWOOBJID actor, LWOOBJID target) {
|
|
|
|
m_SoloActors[actor] = target;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ServerPreconditions::RemoveSoloActor(LWOOBJID actor) {
|
|
|
|
m_SoloActors.erase(actor);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ServerPreconditions::AddExcludeFor(LWOOBJID player, LWOOBJID target) {
|
|
|
|
const auto& it = m_ExcludeForPlayer.find(player);
|
|
|
|
|
|
|
|
if (it == m_ExcludeForPlayer.end()) {
|
|
|
|
m_ExcludeForPlayer[player] = std::unordered_set<LWOOBJID>();
|
|
|
|
}
|
|
|
|
|
|
|
|
m_ExcludeForPlayer[player].insert(target);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ServerPreconditions::RemoveExcludeFor(LWOOBJID player, LWOOBJID target) {
|
|
|
|
const auto& it = m_ExcludeForPlayer.find(player);
|
|
|
|
|
|
|
|
if (it == m_ExcludeForPlayer.end()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_ExcludeForPlayer[player].erase(target);
|
|
|
|
|
|
|
|
if (m_ExcludeForPlayer[player].empty()) {
|
|
|
|
m_ExcludeForPlayer.erase(player);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ServerPreconditions::IsExcludedFor(LWOOBJID player, LWOOBJID target) {
|
|
|
|
const auto& it = m_ExcludeForPlayer.find(player);
|
|
|
|
|
|
|
|
if (it == m_ExcludeForPlayer.end()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return it->second.find(target) != it->second.end();
|
|
|
|
}
|