Merge remote-tracking branch 'upstream/main' into MSVCCompilerFlags

This commit is contained in:
jadebenn 2024-04-08 22:30:35 -05:00
commit c4adcee8e8
33 changed files with 1947 additions and 830 deletions

View File

@ -156,8 +156,11 @@ namespace GeneralUtils {
* @returns An std::optional containing the desired value if it is equivalent to the string * @returns An std::optional containing the desired value if it is equivalent to the string
*/ */
template <Numeric T> template <Numeric T>
[[nodiscard]] std::optional<T> TryParse(const std::string_view str) { [[nodiscard]] std::optional<T> TryParse(std::string_view str) {
numeric_parse_t<T> result; numeric_parse_t<T> result;
if (!str.empty()) {
while (std::isspace(str.front())) str.remove_prefix(1);
}
const char* const strEnd = str.data() + str.size(); const char* const strEnd = str.data() + str.size();
const auto [parseEnd, ec] = std::from_chars(str.data(), strEnd, result); const auto [parseEnd, ec] = std::from_chars(str.data(), strEnd, result);
@ -181,8 +184,12 @@ namespace GeneralUtils {
* @returns An std::optional containing the desired value if it is equivalent to the string * @returns An std::optional containing the desired value if it is equivalent to the string
*/ */
template <std::floating_point T> template <std::floating_point T>
[[nodiscard]] std::optional<T> TryParse(const std::string_view str) noexcept [[nodiscard]] std::optional<T> TryParse(std::string_view str) noexcept
try { try {
if (!str.empty()) {
while (std::isspace(str.front())) str.remove_prefix(1);
}
size_t parseNum; size_t parseNum;
const T result = details::_parse<T>(str, parseNum); const T result = details::_parse<T>(str, parseNum);
const bool isParsed = str.length() == parseNum; const bool isParsed = str.length() == parseNum;

View File

@ -790,9 +790,10 @@ enum class eGameMessageType : uint16_t {
GET_MISSION_TYPE_STATES = 853, GET_MISSION_TYPE_STATES = 853,
GET_TIME_PLAYED = 854, GET_TIME_PLAYED = 854,
SET_MISSION_VIEWED = 855, SET_MISSION_VIEWED = 855,
SLASH_COMMAND_TEXT_FEEDBACK = 856, HKX_VEHICLE_LOADED = 856,
HANDLE_SLASH_COMMAND_KORE_DEBUGGER = 857, SLASH_COMMAND_TEXT_FEEDBACK = 857,
BROADCAST_TEXT_TO_CHATBOX = 858, BROADCAST_TEXT_TO_CHATBOX = 858,
HANDLE_SLASH_COMMAND_KORE_DEBUGGER = 859,
OPEN_PROPERTY_MANAGEMENT = 860, OPEN_PROPERTY_MANAGEMENT = 860,
OPEN_PROPERTY_VENDOR = 861, OPEN_PROPERTY_VENDOR = 861,
VOTE_ON_PROPERTY = 862, VOTE_ON_PROPERTY = 862,

View File

@ -27,12 +27,9 @@ Character::Character(uint32_t id, User* parentUser) {
m_ID = id; m_ID = id;
m_ParentUser = parentUser; m_ParentUser = parentUser;
m_OurEntity = nullptr; m_OurEntity = nullptr;
m_Doc = nullptr;
} }
Character::~Character() { Character::~Character() {
if (m_Doc) delete m_Doc;
m_Doc = nullptr;
m_OurEntity = nullptr; m_OurEntity = nullptr;
m_ParentUser = nullptr; m_ParentUser = nullptr;
} }
@ -55,8 +52,6 @@ void Character::UpdateInfoFromDatabase() {
m_ZoneInstanceID = 0; //These values don't really matter, these are only used on the char select screen and seem unused. m_ZoneInstanceID = 0; //These values don't really matter, these are only used on the char select screen and seem unused.
m_ZoneCloneID = 0; m_ZoneCloneID = 0;
m_Doc = nullptr;
//Quickly and dirtly parse the xmlData to get the info we need: //Quickly and dirtly parse the xmlData to get the info we need:
DoQuickXMLDataParse(); DoQuickXMLDataParse();
@ -70,18 +65,13 @@ void Character::UpdateInfoFromDatabase() {
} }
void Character::UpdateFromDatabase() { void Character::UpdateFromDatabase() {
if (m_Doc) delete m_Doc;
UpdateInfoFromDatabase(); UpdateInfoFromDatabase();
} }
void Character::DoQuickXMLDataParse() { void Character::DoQuickXMLDataParse() {
if (m_XMLData.size() == 0) return; if (m_XMLData.size() == 0) return;
delete m_Doc; if (m_Doc.Parse(m_XMLData.c_str(), m_XMLData.size()) == 0) {
m_Doc = new tinyxml2::XMLDocument();
if (!m_Doc) return;
if (m_Doc->Parse(m_XMLData.c_str(), m_XMLData.size()) == 0) {
LOG("Loaded xmlData for character %s (%i)!", m_Name.c_str(), m_ID); LOG("Loaded xmlData for character %s (%i)!", m_Name.c_str(), m_ID);
} else { } else {
LOG("Failed to load xmlData!"); LOG("Failed to load xmlData!");
@ -89,7 +79,7 @@ void Character::DoQuickXMLDataParse() {
return; return;
} }
tinyxml2::XMLElement* mf = m_Doc->FirstChildElement("obj")->FirstChildElement("mf"); tinyxml2::XMLElement* mf = m_Doc.FirstChildElement("obj")->FirstChildElement("mf");
if (!mf) { if (!mf) {
LOG("Failed to find mf tag!"); LOG("Failed to find mf tag!");
return; return;
@ -108,7 +98,7 @@ void Character::DoQuickXMLDataParse() {
mf->QueryAttribute("ess", &m_Eyes); mf->QueryAttribute("ess", &m_Eyes);
mf->QueryAttribute("ms", &m_Mouth); mf->QueryAttribute("ms", &m_Mouth);
tinyxml2::XMLElement* inv = m_Doc->FirstChildElement("obj")->FirstChildElement("inv"); tinyxml2::XMLElement* inv = m_Doc.FirstChildElement("obj")->FirstChildElement("inv");
if (!inv) { if (!inv) {
LOG("Char has no inv!"); LOG("Char has no inv!");
return; return;
@ -141,7 +131,7 @@ void Character::DoQuickXMLDataParse() {
} }
tinyxml2::XMLElement* character = m_Doc->FirstChildElement("obj")->FirstChildElement("char"); tinyxml2::XMLElement* character = m_Doc.FirstChildElement("obj")->FirstChildElement("char");
if (character) { if (character) {
character->QueryAttribute("cc", &m_Coins); character->QueryAttribute("cc", &m_Coins);
int32_t gm_level = 0; int32_t gm_level = 0;
@ -205,7 +195,7 @@ void Character::DoQuickXMLDataParse() {
character->QueryAttribute("lzrw", &m_OriginalRotation.w); character->QueryAttribute("lzrw", &m_OriginalRotation.w);
} }
auto* flags = m_Doc->FirstChildElement("obj")->FirstChildElement("flag"); auto* flags = m_Doc.FirstChildElement("obj")->FirstChildElement("flag");
if (flags) { if (flags) {
auto* currentChild = flags->FirstChildElement(); auto* currentChild = flags->FirstChildElement();
while (currentChild) { while (currentChild) {
@ -239,12 +229,10 @@ void Character::SetBuildMode(bool buildMode) {
} }
void Character::SaveXMLToDatabase() { void Character::SaveXMLToDatabase() {
if (!m_Doc) return;
//For metrics, we'll record the time it took to save: //For metrics, we'll record the time it took to save:
auto start = std::chrono::system_clock::now(); auto start = std::chrono::system_clock::now();
tinyxml2::XMLElement* character = m_Doc->FirstChildElement("obj")->FirstChildElement("char"); tinyxml2::XMLElement* character = m_Doc.FirstChildElement("obj")->FirstChildElement("char");
if (character) { if (character) {
character->SetAttribute("gm", static_cast<uint32_t>(m_GMLevel)); character->SetAttribute("gm", static_cast<uint32_t>(m_GMLevel));
character->SetAttribute("cc", m_Coins); character->SetAttribute("cc", m_Coins);
@ -266,11 +254,11 @@ void Character::SaveXMLToDatabase() {
} }
auto emotes = character->FirstChildElement("ue"); auto emotes = character->FirstChildElement("ue");
if (!emotes) emotes = m_Doc->NewElement("ue"); if (!emotes) emotes = m_Doc.NewElement("ue");
emotes->DeleteChildren(); emotes->DeleteChildren();
for (int emoteID : m_UnlockedEmotes) { for (int emoteID : m_UnlockedEmotes) {
auto emote = m_Doc->NewElement("e"); auto emote = m_Doc.NewElement("e");
emote->SetAttribute("id", emoteID); emote->SetAttribute("id", emoteID);
emotes->LinkEndChild(emote); emotes->LinkEndChild(emote);
@ -280,15 +268,15 @@ void Character::SaveXMLToDatabase() {
} }
//Export our flags: //Export our flags:
auto* flags = m_Doc->FirstChildElement("obj")->FirstChildElement("flag"); auto* flags = m_Doc.FirstChildElement("obj")->FirstChildElement("flag");
if (!flags) { if (!flags) {
flags = m_Doc->NewElement("flag"); //Create a flags tag if we don't have one flags = m_Doc.NewElement("flag"); //Create a flags tag if we don't have one
m_Doc->FirstChildElement("obj")->LinkEndChild(flags); //Link it to the obj tag so we can find next time m_Doc.FirstChildElement("obj")->LinkEndChild(flags); //Link it to the obj tag so we can find next time
} }
flags->DeleteChildren(); //Clear it if we have anything, so that we can fill it up again without dupes flags->DeleteChildren(); //Clear it if we have anything, so that we can fill it up again without dupes
for (std::pair<uint32_t, uint64_t> flag : m_PlayerFlags) { for (std::pair<uint32_t, uint64_t> flag : m_PlayerFlags) {
auto* f = m_Doc->NewElement("f"); auto* f = m_Doc.NewElement("f");
f->SetAttribute("id", flag.first); f->SetAttribute("id", flag.first);
//Because of the joy that is tinyxml2, it doesn't offer a function to set a uint64 as an attribute. //Because of the joy that is tinyxml2, it doesn't offer a function to set a uint64 as an attribute.
@ -301,7 +289,7 @@ void Character::SaveXMLToDatabase() {
// Prevents the news feed from showing up on world transfers // Prevents the news feed from showing up on world transfers
if (GetPlayerFlag(ePlayerFlag::IS_NEWS_SCREEN_VISIBLE)) { if (GetPlayerFlag(ePlayerFlag::IS_NEWS_SCREEN_VISIBLE)) {
auto* s = m_Doc->NewElement("s"); auto* s = m_Doc.NewElement("s");
s->SetAttribute("si", ePlayerFlag::IS_NEWS_SCREEN_VISIBLE); s->SetAttribute("si", ePlayerFlag::IS_NEWS_SCREEN_VISIBLE);
flags->LinkEndChild(s); flags->LinkEndChild(s);
} }
@ -326,7 +314,7 @@ void Character::SaveXMLToDatabase() {
void Character::SetIsNewLogin() { void Character::SetIsNewLogin() {
// If we dont have a flag element, then we cannot have a s element as a child of flag. // If we dont have a flag element, then we cannot have a s element as a child of flag.
auto* flags = m_Doc->FirstChildElement("obj")->FirstChildElement("flag"); auto* flags = m_Doc.FirstChildElement("obj")->FirstChildElement("flag");
if (!flags) return; if (!flags) return;
auto* currentChild = flags->FirstChildElement(); auto* currentChild = flags->FirstChildElement();
@ -344,7 +332,7 @@ void Character::SetIsNewLogin() {
void Character::WriteToDatabase() { void Character::WriteToDatabase() {
//Dump our xml into m_XMLData: //Dump our xml into m_XMLData:
tinyxml2::XMLPrinter printer(0, true, 0); tinyxml2::XMLPrinter printer(0, true, 0);
m_Doc->Print(&printer); m_Doc.Print(&printer);
//Finally, save to db: //Finally, save to db:
Database::Get()->UpdateCharacterXml(m_ID, printer.CStr()); Database::Get()->UpdateCharacterXml(m_ID, printer.CStr());
@ -421,15 +409,15 @@ void Character::SetRetroactiveFlags() {
void Character::SaveXmlRespawnCheckpoints() { void Character::SaveXmlRespawnCheckpoints() {
//Export our respawn points: //Export our respawn points:
auto* points = m_Doc->FirstChildElement("obj")->FirstChildElement("res"); auto* points = m_Doc.FirstChildElement("obj")->FirstChildElement("res");
if (!points) { if (!points) {
points = m_Doc->NewElement("res"); points = m_Doc.NewElement("res");
m_Doc->FirstChildElement("obj")->LinkEndChild(points); m_Doc.FirstChildElement("obj")->LinkEndChild(points);
} }
points->DeleteChildren(); points->DeleteChildren();
for (const auto& point : m_WorldRespawnCheckpoints) { for (const auto& point : m_WorldRespawnCheckpoints) {
auto* r = m_Doc->NewElement("r"); auto* r = m_Doc.NewElement("r");
r->SetAttribute("w", point.first); r->SetAttribute("w", point.first);
r->SetAttribute("x", point.second.x); r->SetAttribute("x", point.second.x);
@ -443,7 +431,7 @@ void Character::SaveXmlRespawnCheckpoints() {
void Character::LoadXmlRespawnCheckpoints() { void Character::LoadXmlRespawnCheckpoints() {
m_WorldRespawnCheckpoints.clear(); m_WorldRespawnCheckpoints.clear();
auto* points = m_Doc->FirstChildElement("obj")->FirstChildElement("res"); auto* points = m_Doc.FirstChildElement("obj")->FirstChildElement("res");
if (!points) { if (!points) {
return; return;
} }

View File

@ -37,7 +37,7 @@ public:
void LoadXmlRespawnCheckpoints(); void LoadXmlRespawnCheckpoints();
const std::string& GetXMLData() const { return m_XMLData; } const std::string& GetXMLData() const { return m_XMLData; }
tinyxml2::XMLDocument* GetXMLDoc() const { return m_Doc; } const tinyxml2::XMLDocument& GetXMLDoc() const { return m_Doc; }
/** /**
* Out of abundance of safety and clarity of what this saves, this is its own function. * Out of abundance of safety and clarity of what this saves, this is its own function.
@ -623,7 +623,7 @@ private:
/** /**
* The character XML belonging to this character * The character XML belonging to this character
*/ */
tinyxml2::XMLDocument* m_Doc; tinyxml2::XMLDocument m_Doc;
/** /**
* Title of an announcement this character made (reserved for GMs) * Title of an announcement this character made (reserved for GMs)

View File

@ -476,8 +476,7 @@ void Entity::Initialize() {
} }
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::INVENTORY) > 0 || m_Character) { if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::INVENTORY) > 0 || m_Character) {
auto* xmlDoc = m_Character ? m_Character->GetXMLDoc() : nullptr; AddComponent<InventoryComponent>();
AddComponent<InventoryComponent>(xmlDoc);
} }
// if this component exists, then we initialize it. it's value is always 0 // if this component exists, then we initialize it. it's value is always 0
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::MULTI_ZONE_ENTRANCE, -1) != -1) { if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::MULTI_ZONE_ENTRANCE, -1) != -1) {
@ -1244,7 +1243,7 @@ void Entity::WriteComponents(RakNet::BitStream& outBitStream, eReplicaPacketType
outBitStream.Write0(); outBitStream.Write0();
} }
void Entity::UpdateXMLDoc(tinyxml2::XMLDocument* doc) { void Entity::UpdateXMLDoc(tinyxml2::XMLDocument& doc) {
//This function should only ever be called from within Character, meaning doc should always exist when this is called. //This function should only ever be called from within Character, meaning doc should always exist when this is called.
//Naturally, we don't include any non-player components in this update function. //Naturally, we don't include any non-player components in this update function.
@ -1635,10 +1634,8 @@ void Entity::PickupItem(const LWOOBJID& objectID) {
CDObjectSkillsTable* skillsTable = CDClientManager::GetTable<CDObjectSkillsTable>(); CDObjectSkillsTable* skillsTable = CDClientManager::GetTable<CDObjectSkillsTable>();
std::vector<CDObjectSkills> skills = skillsTable->Query([=](CDObjectSkills entry) {return (entry.objectTemplate == p.second.lot); }); std::vector<CDObjectSkills> skills = skillsTable->Query([=](CDObjectSkills entry) {return (entry.objectTemplate == p.second.lot); });
for (CDObjectSkills skill : skills) { for (CDObjectSkills skill : skills) {
CDSkillBehaviorTable* skillBehTable = CDClientManager::GetTable<CDSkillBehaviorTable>();
auto* skillComponent = GetComponent<SkillComponent>(); auto* skillComponent = GetComponent<SkillComponent>();
if (skillComponent) skillComponent->CastSkill(skill.skillID, GetObjectID(), GetObjectID()); if (skillComponent) skillComponent->CastSkill(skill.skillID, GetObjectID(), GetObjectID(), skill.castOnType, NiQuaternion(0, 0, 0, 0));
auto* missionComponent = GetComponent<MissionComponent>(); auto* missionComponent = GetComponent<MissionComponent>();

View File

@ -174,7 +174,7 @@ public:
void WriteBaseReplicaData(RakNet::BitStream& outBitStream, eReplicaPacketType packetType); void WriteBaseReplicaData(RakNet::BitStream& outBitStream, eReplicaPacketType packetType);
void WriteComponents(RakNet::BitStream& outBitStream, eReplicaPacketType packetType); void WriteComponents(RakNet::BitStream& outBitStream, eReplicaPacketType packetType);
void UpdateXMLDoc(tinyxml2::XMLDocument* doc); void UpdateXMLDoc(tinyxml2::XMLDocument& doc);
void Update(float deltaTime); void Update(float deltaTime);
// Events // Events

View File

@ -326,9 +326,9 @@ Entity* BuffComponent::GetParent() const {
return m_Parent; return m_Parent;
} }
void BuffComponent::LoadFromXml(tinyxml2::XMLDocument* doc) { void BuffComponent::LoadFromXml(const tinyxml2::XMLDocument& doc) {
// Load buffs // Load buffs
auto* dest = doc->FirstChildElement("obj")->FirstChildElement("dest"); auto* dest = doc.FirstChildElement("obj")->FirstChildElement("dest");
// Make sure we have a clean buff element. // Make sure we have a clean buff element.
auto* buffElement = dest->FirstChildElement("buff"); auto* buffElement = dest->FirstChildElement("buff");
@ -386,15 +386,15 @@ void BuffComponent::LoadFromXml(tinyxml2::XMLDocument* doc) {
} }
} }
void BuffComponent::UpdateXml(tinyxml2::XMLDocument* doc) { void BuffComponent::UpdateXml(tinyxml2::XMLDocument& doc) {
// Save buffs // Save buffs
auto* dest = doc->FirstChildElement("obj")->FirstChildElement("dest"); auto* dest = doc.FirstChildElement("obj")->FirstChildElement("dest");
// Make sure we have a clean buff element. // Make sure we have a clean buff element.
auto* buffElement = dest->FirstChildElement("buff"); auto* buffElement = dest->FirstChildElement("buff");
if (buffElement == nullptr) { if (buffElement == nullptr) {
buffElement = doc->NewElement("buff"); buffElement = doc.NewElement("buff");
dest->LinkEndChild(buffElement); dest->LinkEndChild(buffElement);
} else { } else {
@ -402,7 +402,7 @@ void BuffComponent::UpdateXml(tinyxml2::XMLDocument* doc) {
} }
for (const auto& [id, buff] : m_Buffs) { for (const auto& [id, buff] : m_Buffs) {
auto* buffEntry = doc->NewElement("b"); auto* buffEntry = doc.NewElement("b");
// TODO: change this if to if (buff.cancelOnZone || buff.cancelOnLogout) handling at some point. No current way to differentiate between zone transfer and logout. // TODO: change this if to if (buff.cancelOnZone || buff.cancelOnLogout) handling at some point. No current way to differentiate between zone transfer and logout.
if (buff.cancelOnZone) continue; if (buff.cancelOnZone) continue;

View File

@ -57,9 +57,9 @@ public:
Entity* GetParent() const; Entity* GetParent() const;
void LoadFromXml(tinyxml2::XMLDocument* doc) override; void LoadFromXml(const tinyxml2::XMLDocument& doc) override;
void UpdateXml(tinyxml2::XMLDocument* doc) override; void UpdateXml(tinyxml2::XMLDocument& doc) override;
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override; void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;

View File

@ -186,9 +186,9 @@ void CharacterComponent::SetGMLevel(eGameMasterLevel gmlevel) {
m_GMLevel = gmlevel; m_GMLevel = gmlevel;
} }
void CharacterComponent::LoadFromXml(tinyxml2::XMLDocument* doc) { void CharacterComponent::LoadFromXml(const tinyxml2::XMLDocument& doc) {
tinyxml2::XMLElement* character = doc->FirstChildElement("obj")->FirstChildElement("char"); auto* character = doc.FirstChildElement("obj")->FirstChildElement("char");
if (!character) { if (!character) {
LOG("Failed to find char tag while loading XML!"); LOG("Failed to find char tag while loading XML!");
return; return;
@ -299,8 +299,8 @@ void CharacterComponent::LoadFromXml(tinyxml2::XMLDocument* doc) {
} }
} }
void CharacterComponent::UpdateXml(tinyxml2::XMLDocument* doc) { void CharacterComponent::UpdateXml(tinyxml2::XMLDocument& doc) {
tinyxml2::XMLElement* minifig = doc->FirstChildElement("obj")->FirstChildElement("mf"); tinyxml2::XMLElement* minifig = doc.FirstChildElement("obj")->FirstChildElement("mf");
if (!minifig) { if (!minifig) {
LOG("Failed to find mf tag while updating XML!"); LOG("Failed to find mf tag while updating XML!");
return; return;
@ -320,7 +320,7 @@ void CharacterComponent::UpdateXml(tinyxml2::XMLDocument* doc) {
// done with minifig // done with minifig
tinyxml2::XMLElement* character = doc->FirstChildElement("obj")->FirstChildElement("char"); tinyxml2::XMLElement* character = doc.FirstChildElement("obj")->FirstChildElement("char");
if (!character) { if (!character) {
LOG("Failed to find char tag while updating XML!"); LOG("Failed to find char tag while updating XML!");
return; return;
@ -338,11 +338,11 @@ void CharacterComponent::UpdateXml(tinyxml2::XMLDocument* doc) {
// Set the zone statistics of the form <zs><s/> ... <s/></zs> // Set the zone statistics of the form <zs><s/> ... <s/></zs>
auto zoneStatistics = character->FirstChildElement("zs"); auto zoneStatistics = character->FirstChildElement("zs");
if (!zoneStatistics) zoneStatistics = doc->NewElement("zs"); if (!zoneStatistics) zoneStatistics = doc.NewElement("zs");
zoneStatistics->DeleteChildren(); zoneStatistics->DeleteChildren();
for (auto pair : m_ZoneStatistics) { for (auto pair : m_ZoneStatistics) {
auto zoneStatistic = doc->NewElement("s"); auto zoneStatistic = doc.NewElement("s");
zoneStatistic->SetAttribute("map", pair.first); zoneStatistic->SetAttribute("map", pair.first);
zoneStatistic->SetAttribute("ac", pair.second.m_AchievementsCollected); zoneStatistic->SetAttribute("ac", pair.second.m_AchievementsCollected);

View File

@ -70,8 +70,8 @@ public:
CharacterComponent(Entity* parent, Character* character, const SystemAddress& systemAddress); CharacterComponent(Entity* parent, Character* character, const SystemAddress& systemAddress);
~CharacterComponent() override; ~CharacterComponent() override;
void LoadFromXml(tinyxml2::XMLDocument* doc) override; void LoadFromXml(const tinyxml2::XMLDocument& doc) override;
void UpdateXml(tinyxml2::XMLDocument* doc) override; void UpdateXml(tinyxml2::XMLDocument& doc) override;
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override; void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;

View File

@ -21,11 +21,11 @@ void Component::OnUse(Entity* originator) {
} }
void Component::UpdateXml(tinyxml2::XMLDocument* doc) { void Component::UpdateXml(tinyxml2::XMLDocument& doc) {
} }
void Component::LoadFromXml(tinyxml2::XMLDocument* doc) { void Component::LoadFromXml(const tinyxml2::XMLDocument& doc) {
} }

View File

@ -34,13 +34,13 @@ public:
* Save data from this componennt to character XML * Save data from this componennt to character XML
* @param doc the document to write data to * @param doc the document to write data to
*/ */
virtual void UpdateXml(tinyxml2::XMLDocument* doc); virtual void UpdateXml(tinyxml2::XMLDocument& doc);
/** /**
* Load base data for this component from character XML * Load base data for this component from character XML
* @param doc the document to read data from * @param doc the document to read data from
*/ */
virtual void LoadFromXml(tinyxml2::XMLDocument* doc); virtual void LoadFromXml(const tinyxml2::XMLDocument& doc);
virtual void Serialize(RakNet::BitStream& outBitStream, bool isConstruction); virtual void Serialize(RakNet::BitStream& outBitStream, bool isConstruction);

View File

@ -158,8 +158,8 @@ void ControllablePhysicsComponent::Serialize(RakNet::BitStream& outBitStream, bo
} }
} }
void ControllablePhysicsComponent::LoadFromXml(tinyxml2::XMLDocument* doc) { void ControllablePhysicsComponent::LoadFromXml(const tinyxml2::XMLDocument& doc) {
tinyxml2::XMLElement* character = doc->FirstChildElement("obj")->FirstChildElement("char"); auto* character = doc.FirstChildElement("obj")->FirstChildElement("char");
if (!character) { if (!character) {
LOG("Failed to find char tag!"); LOG("Failed to find char tag!");
return; return;
@ -178,8 +178,8 @@ void ControllablePhysicsComponent::LoadFromXml(tinyxml2::XMLDocument* doc) {
m_DirtyPosition = true; m_DirtyPosition = true;
} }
void ControllablePhysicsComponent::UpdateXml(tinyxml2::XMLDocument* doc) { void ControllablePhysicsComponent::UpdateXml(tinyxml2::XMLDocument& doc) {
tinyxml2::XMLElement* character = doc->FirstChildElement("obj")->FirstChildElement("char"); tinyxml2::XMLElement* character = doc.FirstChildElement("obj")->FirstChildElement("char");
if (!character) { if (!character) {
LOG("Failed to find char tag while updating XML!"); LOG("Failed to find char tag while updating XML!");
return; return;

View File

@ -28,8 +28,8 @@ public:
void Update(float deltaTime) override; void Update(float deltaTime) override;
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override; void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;
void LoadFromXml(tinyxml2::XMLDocument* doc) override; void LoadFromXml(const tinyxml2::XMLDocument& doc) override;
void UpdateXml(tinyxml2::XMLDocument* doc) override; void UpdateXml(tinyxml2::XMLDocument& doc) override;
/** /**
* Sets the position of this entity, also ensures this update is serialized next tick. * Sets the position of this entity, also ensures this update is serialized next tick.

View File

@ -185,8 +185,8 @@ void DestroyableComponent::Update(float deltaTime) {
m_DamageCooldownTimer -= deltaTime; m_DamageCooldownTimer -= deltaTime;
} }
void DestroyableComponent::LoadFromXml(tinyxml2::XMLDocument* doc) { void DestroyableComponent::LoadFromXml(const tinyxml2::XMLDocument& doc) {
tinyxml2::XMLElement* dest = doc->FirstChildElement("obj")->FirstChildElement("dest"); auto* dest = doc.FirstChildElement("obj")->FirstChildElement("dest");
if (!dest) { if (!dest) {
LOG("Failed to find dest tag!"); LOG("Failed to find dest tag!");
return; return;
@ -207,8 +207,8 @@ void DestroyableComponent::LoadFromXml(tinyxml2::XMLDocument* doc) {
m_DirtyHealth = true; m_DirtyHealth = true;
} }
void DestroyableComponent::UpdateXml(tinyxml2::XMLDocument* doc) { void DestroyableComponent::UpdateXml(tinyxml2::XMLDocument& doc) {
tinyxml2::XMLElement* dest = doc->FirstChildElement("obj")->FirstChildElement("dest"); tinyxml2::XMLElement* dest = doc.FirstChildElement("obj")->FirstChildElement("dest");
if (!dest) { if (!dest) {
LOG("Failed to find dest tag!"); LOG("Failed to find dest tag!");
return; return;

View File

@ -26,8 +26,8 @@ public:
void Update(float deltaTime) override; void Update(float deltaTime) override;
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override; void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;
void LoadFromXml(tinyxml2::XMLDocument* doc) override; void LoadFromXml(const tinyxml2::XMLDocument& doc) override;
void UpdateXml(tinyxml2::XMLDocument* doc) override; void UpdateXml(tinyxml2::XMLDocument& doc) override;
/** /**
* Initializes the component using a different LOT * Initializes the component using a different LOT

View File

@ -38,7 +38,7 @@
#include "CDObjectSkillsTable.h" #include "CDObjectSkillsTable.h"
#include "CDSkillBehaviorTable.h" #include "CDSkillBehaviorTable.h"
InventoryComponent::InventoryComponent(Entity* parent, tinyxml2::XMLDocument* document) : Component(parent) { InventoryComponent::InventoryComponent(Entity* parent) : Component(parent) {
this->m_Dirty = true; this->m_Dirty = true;
this->m_Equipped = {}; this->m_Equipped = {};
this->m_Pushed = {}; this->m_Pushed = {};
@ -48,7 +48,8 @@ InventoryComponent::InventoryComponent(Entity* parent, tinyxml2::XMLDocument* do
const auto lot = parent->GetLOT(); const auto lot = parent->GetLOT();
if (lot == 1) { if (lot == 1) {
LoadXml(document); auto* character = m_Parent->GetCharacter();
if (character) LoadXml(character->GetXMLDoc());
CheckProxyIntegrity(); CheckProxyIntegrity();
@ -472,10 +473,10 @@ bool InventoryComponent::HasSpaceForLoot(const std::unordered_map<LOT, int32_t>&
return true; return true;
} }
void InventoryComponent::LoadXml(tinyxml2::XMLDocument* document) { void InventoryComponent::LoadXml(const tinyxml2::XMLDocument& document) {
LoadPetXml(document); LoadPetXml(document);
auto* inventoryElement = document->FirstChildElement("obj")->FirstChildElement("inv"); auto* inventoryElement = document.FirstChildElement("obj")->FirstChildElement("inv");
if (inventoryElement == nullptr) { if (inventoryElement == nullptr) {
LOG("Failed to find 'inv' xml element!"); LOG("Failed to find 'inv' xml element!");
@ -594,10 +595,10 @@ void InventoryComponent::LoadXml(tinyxml2::XMLDocument* document) {
} }
} }
void InventoryComponent::UpdateXml(tinyxml2::XMLDocument* document) { void InventoryComponent::UpdateXml(tinyxml2::XMLDocument& document) {
UpdatePetXml(document); UpdatePetXml(document);
auto* inventoryElement = document->FirstChildElement("obj")->FirstChildElement("inv"); auto* inventoryElement = document.FirstChildElement("obj")->FirstChildElement("inv");
if (inventoryElement == nullptr) { if (inventoryElement == nullptr) {
LOG("Failed to find 'inv' xml element!"); LOG("Failed to find 'inv' xml element!");
@ -631,7 +632,7 @@ void InventoryComponent::UpdateXml(tinyxml2::XMLDocument* document) {
bags->DeleteChildren(); bags->DeleteChildren();
for (const auto* inventory : inventoriesToSave) { for (const auto* inventory : inventoriesToSave) {
auto* bag = document->NewElement("b"); auto* bag = document.NewElement("b");
bag->SetAttribute("t", inventory->GetType()); bag->SetAttribute("t", inventory->GetType());
bag->SetAttribute("m", static_cast<unsigned int>(inventory->GetSize())); bag->SetAttribute("m", static_cast<unsigned int>(inventory->GetSize()));
@ -654,14 +655,14 @@ void InventoryComponent::UpdateXml(tinyxml2::XMLDocument* document) {
continue; continue;
} }
auto* bagElement = document->NewElement("in"); auto* bagElement = document.NewElement("in");
bagElement->SetAttribute("t", inventory->GetType()); bagElement->SetAttribute("t", inventory->GetType());
for (const auto& pair : inventory->GetItems()) { for (const auto& pair : inventory->GetItems()) {
auto* item = pair.second; auto* item = pair.second;
auto* itemElement = document->NewElement("i"); auto* itemElement = document.NewElement("i");
itemElement->SetAttribute("l", item->GetLot()); itemElement->SetAttribute("l", item->GetLot());
itemElement->SetAttribute("id", item->GetId()); itemElement->SetAttribute("id", item->GetId());
@ -680,7 +681,7 @@ void InventoryComponent::UpdateXml(tinyxml2::XMLDocument* document) {
continue; continue;
} }
auto* extraInfo = document->NewElement("x"); auto* extraInfo = document.NewElement("x");
extraInfo->SetAttribute("ma", data->GetString(false).c_str()); extraInfo->SetAttribute("ma", data->GetString(false).c_str());
@ -1542,8 +1543,8 @@ void InventoryComponent::PurgeProxies(Item* item) {
} }
} }
void InventoryComponent::LoadPetXml(tinyxml2::XMLDocument* document) { void InventoryComponent::LoadPetXml(const tinyxml2::XMLDocument& document) {
auto* petInventoryElement = document->FirstChildElement("obj")->FirstChildElement("pet"); auto* petInventoryElement = document.FirstChildElement("obj")->FirstChildElement("pet");
if (petInventoryElement == nullptr) { if (petInventoryElement == nullptr) {
m_Pets.clear(); m_Pets.clear();
@ -1574,19 +1575,19 @@ void InventoryComponent::LoadPetXml(tinyxml2::XMLDocument* document) {
} }
} }
void InventoryComponent::UpdatePetXml(tinyxml2::XMLDocument* document) { void InventoryComponent::UpdatePetXml(tinyxml2::XMLDocument& document) {
auto* petInventoryElement = document->FirstChildElement("obj")->FirstChildElement("pet"); auto* petInventoryElement = document.FirstChildElement("obj")->FirstChildElement("pet");
if (petInventoryElement == nullptr) { if (petInventoryElement == nullptr) {
petInventoryElement = document->NewElement("pet"); petInventoryElement = document.NewElement("pet");
document->FirstChildElement("obj")->LinkEndChild(petInventoryElement); document.FirstChildElement("obj")->LinkEndChild(petInventoryElement);
} }
petInventoryElement->DeleteChildren(); petInventoryElement->DeleteChildren();
for (const auto& pet : m_Pets) { for (const auto& pet : m_Pets) {
auto* petElement = document->NewElement("p"); auto* petElement = document.NewElement("p");
petElement->SetAttribute("id", pet.first); petElement->SetAttribute("id", pet.first);
petElement->SetAttribute("l", pet.second.lot); petElement->SetAttribute("l", pet.second.lot);

View File

@ -38,12 +38,12 @@ enum class eItemType : int32_t;
class InventoryComponent final : public Component { class InventoryComponent final : public Component {
public: public:
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::INVENTORY; static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::INVENTORY;
explicit InventoryComponent(Entity* parent, tinyxml2::XMLDocument* document = nullptr); InventoryComponent(Entity* parent);
void Update(float deltaTime) override; void Update(float deltaTime) override;
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override; void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;
void LoadXml(tinyxml2::XMLDocument* document); void LoadXml(const tinyxml2::XMLDocument& document);
void UpdateXml(tinyxml2::XMLDocument* document) override; void UpdateXml(tinyxml2::XMLDocument& document) override;
/** /**
* Returns an inventory of the specified type, if it exists * Returns an inventory of the specified type, if it exists
@ -470,13 +470,13 @@ private:
* Saves all the pet information stored in inventory items to the database * Saves all the pet information stored in inventory items to the database
* @param document the xml doc to save to * @param document the xml doc to save to
*/ */
void LoadPetXml(tinyxml2::XMLDocument* document); void LoadPetXml(const tinyxml2::XMLDocument& document);
/** /**
* Loads all the pet information from an xml doc into items * Loads all the pet information from an xml doc into items
* @param document the xml doc to load from * @param document the xml doc to load from
*/ */
void UpdatePetXml(tinyxml2::XMLDocument* document); void UpdatePetXml(tinyxml2::XMLDocument& document);
}; };
#endif #endif

View File

@ -13,8 +13,8 @@ LevelProgressionComponent::LevelProgressionComponent(Entity* parent) : Component
m_CharacterVersion = eCharacterVersion::LIVE; m_CharacterVersion = eCharacterVersion::LIVE;
} }
void LevelProgressionComponent::UpdateXml(tinyxml2::XMLDocument* doc) { void LevelProgressionComponent::UpdateXml(tinyxml2::XMLDocument& doc) {
tinyxml2::XMLElement* level = doc->FirstChildElement("obj")->FirstChildElement("lvl"); tinyxml2::XMLElement* level = doc.FirstChildElement("obj")->FirstChildElement("lvl");
if (!level) { if (!level) {
LOG("Failed to find lvl tag while updating XML!"); LOG("Failed to find lvl tag while updating XML!");
return; return;
@ -24,8 +24,8 @@ void LevelProgressionComponent::UpdateXml(tinyxml2::XMLDocument* doc) {
level->SetAttribute("cv", static_cast<uint32_t>(m_CharacterVersion)); level->SetAttribute("cv", static_cast<uint32_t>(m_CharacterVersion));
} }
void LevelProgressionComponent::LoadFromXml(tinyxml2::XMLDocument* doc) { void LevelProgressionComponent::LoadFromXml(const tinyxml2::XMLDocument& doc) {
tinyxml2::XMLElement* level = doc->FirstChildElement("obj")->FirstChildElement("lvl"); auto* level = doc.FirstChildElement("obj")->FirstChildElement("lvl");
if (!level) { if (!level) {
LOG("Failed to find lvl tag while loading XML!"); LOG("Failed to find lvl tag while loading XML!");
return; return;

View File

@ -27,13 +27,13 @@ public:
* Save data from this componennt to character XML * Save data from this componennt to character XML
* @param doc the document to write data to * @param doc the document to write data to
*/ */
void UpdateXml(tinyxml2::XMLDocument* doc) override; void UpdateXml(tinyxml2::XMLDocument& doc) override;
/** /**
* Load base data for this component from character XML * Load base data for this component from character XML
* @param doc the document to read data from * @param doc the document to read data from
*/ */
void LoadFromXml(tinyxml2::XMLDocument* doc) override; void LoadFromXml(const tinyxml2::XMLDocument& doc) override;
/** /**
* Gets the current level of the entity * Gets the current level of the entity

View File

@ -504,10 +504,8 @@ bool MissionComponent::RequiresItem(const LOT lot) {
} }
void MissionComponent::LoadFromXml(tinyxml2::XMLDocument* doc) { void MissionComponent::LoadFromXml(const tinyxml2::XMLDocument& doc) {
if (doc == nullptr) return; auto* mis = doc.FirstChildElement("obj")->FirstChildElement("mis");
auto* mis = doc->FirstChildElement("obj")->FirstChildElement("mis");
if (mis == nullptr) return; if (mis == nullptr) return;
@ -523,7 +521,7 @@ void MissionComponent::LoadFromXml(tinyxml2::XMLDocument* doc) {
auto* mission = new Mission(this, missionId); auto* mission = new Mission(this, missionId);
mission->LoadFromXml(doneM); mission->LoadFromXml(*doneM);
doneM = doneM->NextSiblingElement(); doneM = doneM->NextSiblingElement();
@ -540,7 +538,7 @@ void MissionComponent::LoadFromXml(tinyxml2::XMLDocument* doc) {
auto* mission = new Mission(this, missionId); auto* mission = new Mission(this, missionId);
mission->LoadFromXml(currentM); mission->LoadFromXml(*currentM);
if (currentM->QueryAttribute("o", &missionOrder) == tinyxml2::XML_SUCCESS && mission->IsMission()) { if (currentM->QueryAttribute("o", &missionOrder) == tinyxml2::XML_SUCCESS && mission->IsMission()) {
mission->SetUniqueMissionOrderID(missionOrder); mission->SetUniqueMissionOrderID(missionOrder);
@ -554,25 +552,23 @@ void MissionComponent::LoadFromXml(tinyxml2::XMLDocument* doc) {
} }
void MissionComponent::UpdateXml(tinyxml2::XMLDocument* doc) { void MissionComponent::UpdateXml(tinyxml2::XMLDocument& doc) {
if (doc == nullptr) return;
auto shouldInsertMis = false; auto shouldInsertMis = false;
auto* obj = doc->FirstChildElement("obj"); auto* obj = doc.FirstChildElement("obj");
auto* mis = obj->FirstChildElement("mis"); auto* mis = obj->FirstChildElement("mis");
if (mis == nullptr) { if (mis == nullptr) {
mis = doc->NewElement("mis"); mis = doc.NewElement("mis");
shouldInsertMis = true; shouldInsertMis = true;
} }
mis->DeleteChildren(); mis->DeleteChildren();
auto* done = doc->NewElement("done"); auto* done = doc.NewElement("done");
auto* cur = doc->NewElement("cur"); auto* cur = doc.NewElement("cur");
for (const auto& pair : m_Missions) { for (const auto& pair : m_Missions) {
auto* mission = pair.second; auto* mission = pair.second;
@ -580,10 +576,10 @@ void MissionComponent::UpdateXml(tinyxml2::XMLDocument* doc) {
if (mission) { if (mission) {
const auto complete = mission->IsComplete(); const auto complete = mission->IsComplete();
auto* m = doc->NewElement("m"); auto* m = doc.NewElement("m");
if (complete) { if (complete) {
mission->UpdateXml(m); mission->UpdateXml(*m);
done->LinkEndChild(m); done->LinkEndChild(m);
@ -591,7 +587,7 @@ void MissionComponent::UpdateXml(tinyxml2::XMLDocument* doc) {
} }
if (mission->IsMission()) m->SetAttribute("o", mission->GetUniqueMissionOrderID()); if (mission->IsMission()) m->SetAttribute("o", mission->GetUniqueMissionOrderID());
mission->UpdateXml(m); mission->UpdateXml(*m);
cur->LinkEndChild(m); cur->LinkEndChild(m);
} }

View File

@ -31,8 +31,8 @@ public:
explicit MissionComponent(Entity* parent); explicit MissionComponent(Entity* parent);
~MissionComponent() override; ~MissionComponent() override;
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate, unsigned int& flags); void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate, unsigned int& flags);
void LoadFromXml(tinyxml2::XMLDocument* doc) override; void LoadFromXml(const tinyxml2::XMLDocument& doc) override;
void UpdateXml(tinyxml2::XMLDocument* doc) override; void UpdateXml(tinyxml2::XMLDocument& doc) override;
/** /**
* Returns all the missions for this entity, mapped by mission ID * Returns all the missions for this entity, mapped by mission ID

View File

@ -227,7 +227,7 @@ void SkillComponent::RegisterCalculatedProjectile(const LWOOBJID projectileId, B
this->m_managedProjectiles.push_back(entry); this->m_managedProjectiles.push_back(entry);
} }
bool SkillComponent::CastSkill(const uint32_t skillId, LWOOBJID target, const LWOOBJID optionalOriginatorID) { bool SkillComponent::CastSkill(const uint32_t skillId, LWOOBJID target, const LWOOBJID optionalOriginatorID, const int32_t castType, const NiQuaternion rotationOverride) {
uint32_t behaviorId = -1; uint32_t behaviorId = -1;
// try to find it via the cache // try to find it via the cache
const auto& pair = m_skillBehaviorCache.find(skillId); const auto& pair = m_skillBehaviorCache.find(skillId);
@ -247,11 +247,19 @@ bool SkillComponent::CastSkill(const uint32_t skillId, LWOOBJID target, const LW
return false; return false;
} }
return CalculateBehavior(skillId, behaviorId, target, false, false, optionalOriginatorID).success; return CalculateBehavior(skillId, behaviorId, target, false, false, optionalOriginatorID, castType, rotationOverride).success;
} }
SkillExecutionResult SkillComponent::CalculateBehavior(const uint32_t skillId, const uint32_t behaviorId, const LWOOBJID target, const bool ignoreTarget, const bool clientInitalized, const LWOOBJID originatorOverride) { SkillExecutionResult SkillComponent::CalculateBehavior(
const uint32_t skillId,
const uint32_t behaviorId,
const LWOOBJID target,
const bool ignoreTarget,
const bool clientInitalized,
const LWOOBJID originatorOverride,
const int32_t castType,
const NiQuaternion rotationOverride) {
RakNet::BitStream bitStream{}; RakNet::BitStream bitStream{};
auto* behavior = Behavior::CreateBehavior(behaviorId); auto* behavior = Behavior::CreateBehavior(behaviorId);
@ -283,7 +291,7 @@ SkillExecutionResult SkillComponent::CalculateBehavior(const uint32_t skillId, c
// Echo start skill // Echo start skill
EchoStartSkill start; EchoStartSkill start;
start.iCastType = 0; start.iCastType = castType;
start.skillID = skillId; start.skillID = skillId;
start.uiSkillHandle = context->skillUId; start.uiSkillHandle = context->skillUId;
start.optionalOriginatorID = context->originator; start.optionalOriginatorID = context->originator;
@ -294,6 +302,10 @@ SkillExecutionResult SkillComponent::CalculateBehavior(const uint32_t skillId, c
if (originator != nullptr) { if (originator != nullptr) {
start.originatorRot = originator->GetRotation(); start.originatorRot = originator->GetRotation();
} }
if (rotationOverride != NiQuaternionConstant::IDENTITY) {
start.originatorRot = rotationOverride;
}
//start.optionalTargetID = target; //start.optionalTargetID = target;
start.sBitStream.assign(reinterpret_cast<char*>(bitStream.GetData()), bitStream.GetNumberOfBytesUsed()); start.sBitStream.assign(reinterpret_cast<char*>(bitStream.GetData()), bitStream.GetNumberOfBytesUsed());

View File

@ -127,7 +127,7 @@ public:
* @param optionalOriginatorID change the originator of the skill * @param optionalOriginatorID change the originator of the skill
* @return if the case succeeded * @return if the case succeeded
*/ */
bool CastSkill(const uint32_t skillId, LWOOBJID target = LWOOBJID_EMPTY, const LWOOBJID optionalOriginatorID = LWOOBJID_EMPTY); bool CastSkill(const uint32_t skillId, LWOOBJID target = LWOOBJID_EMPTY, const LWOOBJID optionalOriginatorID = LWOOBJID_EMPTY, const int32_t castType = 0, const NiQuaternion rotationOverride = NiQuaternionConstant::IDENTITY);
/** /**
* Initializes a server-side skill calculation. * Initializes a server-side skill calculation.
@ -139,7 +139,7 @@ public:
* @param originatorOverride an override for the originator of the skill calculation * @param originatorOverride an override for the originator of the skill calculation
* @return the result of the skill calculation * @return the result of the skill calculation
*/ */
SkillExecutionResult CalculateBehavior(uint32_t skillId, uint32_t behaviorId, LWOOBJID target, bool ignoreTarget = false, bool clientInitalized = false, LWOOBJID originatorOverride = LWOOBJID_EMPTY); SkillExecutionResult CalculateBehavior(uint32_t skillId, uint32_t behaviorId, LWOOBJID target, bool ignoreTarget = false, bool clientInitalized = false, LWOOBJID originatorOverride = LWOOBJID_EMPTY, const int32_t castType = 0, const NiQuaternion rotationOverride = NiQuaternionConstant::IDENTITY);
/** /**
* Register a server-side projectile. * Register a server-side projectile.

View File

@ -6197,3 +6197,15 @@ void GameMessages::HandleCancelDonationOnPlayer(RakNet::BitStream& inStream, Ent
if (!characterComponent) return; if (!characterComponent) return;
characterComponent->SetCurrentInteracting(LWOOBJID_EMPTY); characterComponent->SetCurrentInteracting(LWOOBJID_EMPTY);
} }
void GameMessages::SendSlashCommandFeedbackText(Entity* entity, std::u16string text) {
CBITSTREAM;
CMSGHEADER;
bitStream.Write(entity->GetObjectID());
bitStream.Write(eGameMessageType::SLASH_COMMAND_TEXT_FEEDBACK);
bitStream.Write<uint32_t>(text.size());
bitStream.Write(text);
auto sysAddr = entity->GetSystemAddress();
SEND_PACKET;
}

View File

@ -664,6 +664,8 @@ namespace GameMessages {
void HandleRemoveDonationItem(RakNet::BitStream& inStream, Entity* entity, const SystemAddress& sysAddr); void HandleRemoveDonationItem(RakNet::BitStream& inStream, Entity* entity, const SystemAddress& sysAddr);
void HandleConfirmDonationOnPlayer(RakNet::BitStream& inStream, Entity* entity); void HandleConfirmDonationOnPlayer(RakNet::BitStream& inStream, Entity* entity);
void HandleCancelDonationOnPlayer(RakNet::BitStream& inStream, Entity* entity); void HandleCancelDonationOnPlayer(RakNet::BitStream& inStream, Entity* entity);
void SendSlashCommandFeedbackText(Entity* entity, std::u16string text);
}; };
#endif // GAMEMESSAGES_H #endif // GAMEMESSAGES_H

View File

@ -65,24 +65,24 @@ Mission::Mission(MissionComponent* missionComponent, const uint32_t missionId) {
} }
} }
void Mission::LoadFromXml(tinyxml2::XMLElement* element) { void Mission::LoadFromXml(const tinyxml2::XMLElement& element) {
// Start custom XML // Start custom XML
if (element->Attribute("state") != nullptr) { if (element.Attribute("state") != nullptr) {
m_State = static_cast<eMissionState>(std::stoul(element->Attribute("state"))); m_State = static_cast<eMissionState>(std::stoul(element.Attribute("state")));
} }
// End custom XML // End custom XML
if (element->Attribute("cct") != nullptr) { if (element.Attribute("cct") != nullptr) {
m_Completions = std::stoul(element->Attribute("cct")); m_Completions = std::stoul(element.Attribute("cct"));
m_Timestamp = std::stoul(element->Attribute("cts")); m_Timestamp = std::stoul(element.Attribute("cts"));
if (IsComplete()) { if (IsComplete()) {
return; return;
} }
} }
auto* task = element->FirstChildElement(); auto* task = element.FirstChildElement();
auto index = 0U; auto index = 0U;
@ -132,19 +132,19 @@ void Mission::LoadFromXml(tinyxml2::XMLElement* element) {
} }
} }
void Mission::UpdateXml(tinyxml2::XMLElement* element) { void Mission::UpdateXml(tinyxml2::XMLElement& element) {
// Start custom XML // Start custom XML
element->SetAttribute("state", static_cast<unsigned int>(m_State)); element.SetAttribute("state", static_cast<unsigned int>(m_State));
// End custom XML // End custom XML
element->DeleteChildren(); element.DeleteChildren();
element->SetAttribute("id", static_cast<unsigned int>(info.id)); element.SetAttribute("id", static_cast<unsigned int>(info.id));
if (m_Completions > 0) { if (m_Completions > 0) {
element->SetAttribute("cct", static_cast<unsigned int>(m_Completions)); element.SetAttribute("cct", static_cast<unsigned int>(m_Completions));
element->SetAttribute("cts", static_cast<unsigned int>(m_Timestamp)); element.SetAttribute("cts", static_cast<unsigned int>(m_Timestamp));
if (IsComplete()) { if (IsComplete()) {
return; return;
@ -155,27 +155,27 @@ void Mission::UpdateXml(tinyxml2::XMLElement* element) {
if (task->GetType() == eMissionTaskType::COLLECTION || if (task->GetType() == eMissionTaskType::COLLECTION ||
task->GetType() == eMissionTaskType::VISIT_PROPERTY) { task->GetType() == eMissionTaskType::VISIT_PROPERTY) {
auto* child = element->GetDocument()->NewElement("sv"); auto* child = element.GetDocument()->NewElement("sv");
child->SetAttribute("v", static_cast<unsigned int>(task->GetProgress())); child->SetAttribute("v", static_cast<unsigned int>(task->GetProgress()));
element->LinkEndChild(child); element.LinkEndChild(child);
for (auto unique : task->GetUnique()) { for (auto unique : task->GetUnique()) {
auto* uniqueElement = element->GetDocument()->NewElement("sv"); auto* uniqueElement = element.GetDocument()->NewElement("sv");
uniqueElement->SetAttribute("v", static_cast<unsigned int>(unique)); uniqueElement->SetAttribute("v", static_cast<unsigned int>(unique));
element->LinkEndChild(uniqueElement); element.LinkEndChild(uniqueElement);
} }
break; break;
} }
auto* child = element->GetDocument()->NewElement("sv"); auto* child = element.GetDocument()->NewElement("sv");
child->SetAttribute("v", static_cast<unsigned int>(task->GetProgress())); child->SetAttribute("v", static_cast<unsigned int>(task->GetProgress()));
element->LinkEndChild(child); element.LinkEndChild(child);
} }
} }

View File

@ -28,8 +28,8 @@ public:
Mission(MissionComponent* missionComponent, uint32_t missionId); Mission(MissionComponent* missionComponent, uint32_t missionId);
~Mission(); ~Mission();
void LoadFromXml(tinyxml2::XMLElement* element); void LoadFromXml(const tinyxml2::XMLElement& element);
void UpdateXml(tinyxml2::XMLElement* element); void UpdateXml(tinyxml2::XMLElement& element);
/** /**
* Returns the ID of this mission * Returns the ID of this mission

View File

@ -29,15 +29,14 @@ const BrickList& BrickDatabase::GetBricks(const LxfmlPath& lxfmlPath) {
return emptyCache; return emptyCache;
} }
auto* doc = new tinyxml2::XMLDocument(); tinyxml2::XMLDocument doc;
if (doc->Parse(data.str().c_str(), data.str().size()) != 0) { if (doc.Parse(data.str().c_str(), data.str().size()) != 0) {
delete doc;
return emptyCache; return emptyCache;
} }
BrickList parts; BrickList parts;
auto* lxfml = doc->FirstChildElement("LXFML"); auto* lxfml = doc.FirstChildElement("LXFML");
auto* bricks = lxfml->FirstChildElement("Bricks"); auto* bricks = lxfml->FirstChildElement("Bricks");
std::string searchTerm = "Brick"; std::string searchTerm = "Brick";
@ -86,7 +85,5 @@ const BrickList& BrickDatabase::GetBricks(const LxfmlPath& lxfmlPath) {
m_Cache[lxfmlPath] = parts; m_Cache[lxfmlPath] = parts;
delete doc;
return m_Cache[lxfmlPath]; return m_Cache[lxfmlPath];
} }

File diff suppressed because it is too large Load Diff

View File

@ -7,13 +7,128 @@
#define SLASHCOMMANDHANDLER_H #define SLASHCOMMANDHANDLER_H
#include "RakNetTypes.h" #include "RakNetTypes.h"
#include "eGameMasterLevel.h"
#include <string> #include <string>
class Entity; class Entity;
namespace SlashCommandHandler { struct Command {
void HandleChatCommand(const std::u16string& command, Entity* entity, const SystemAddress& sysAddr); std::string help;
void SendAnnouncement(const std::string& title, const std::string& message); std::string info;
std::vector<std::string> aliases;
std::function<void(Entity*, const SystemAddress&,const std::string)> handle;
eGameMasterLevel requiredLevel = eGameMasterLevel::OPERATOR;
}; };
namespace SlashCommandHandler {
void Startup();
void HandleChatCommand(const std::u16string& command, Entity* entity, const SystemAddress& sysAddr);
void SendAnnouncement(const std::string& title, const std::string& message);
void RegisterCommand(Command info);
};
namespace DEVGMCommands {
void SetGMLevel(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void ToggleNameplate(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void ToggleSkipCinematics(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void Kill(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void Metrics(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void Announce(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void SetAnnTitle(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void SetAnnMsg(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void ShutdownUniverse(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void SetMinifig(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void TestMap(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void ReportProxPhys(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void SpawnPhysicsVerts(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void Teleport(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void ActivateSpawner(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void AddMission(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void Boost(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void Unboost(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void Buff(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void BuffMe(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void BuffMed(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void ClearFlag(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void CompleteMission(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void CreatePrivate(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void DebugUi(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void Dismount(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void ReloadConfig(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void ForceSave(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void Freecam(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void FreeMoney(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void GetNavmeshHeight(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void GiveUScore(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void GmAddItem(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void Inspect(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void ListSpawns(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void LocRow(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void Lookup(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void PlayAnimation(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void PlayEffect(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void PlayLvlFx(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void PlayRebuildFx(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void Pos(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void RefillStats(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void Reforge(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void ResetMission(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void Rot(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void RunMacro(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void SetControlScheme(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void SetCurrency(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void SetFlag(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void SetInventorySize(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void SetUiState(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void Spawn(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void SpawnGroup(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void SpeedBoost(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void StartCelebration(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void StopEffect(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void Toggle(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void TpAll(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void TriggerSpawner(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void UnlockEmote(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void SetLevel(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void SetSkillSlot(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void SetFaction(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void AddFaction(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void GetFactions(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void SetRewardCode(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void Crash(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void RollLoot(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void CastSkill(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void DeleteInven(Entity* entity, const SystemAddress& sysAddr, const std::string args);
}
namespace GMZeroCommands {
void Help(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void Credits(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void Info(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void Die(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void Ping(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void Pvp(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void RequestMailCount(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void Who(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void FixStats(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void Join(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void LeaveZone(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void Resurrect(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void InstanceInfo(Entity* entity, const SystemAddress& sysAddr, const std::string args);
}
namespace GMGreaterThanZeroCommands {
void Kick(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void MailItem(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void Ban(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void ApproveProperty(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void Mute(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void Fly(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void AttackImmune(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void GmImmune(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void GmInvis(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void SetName(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void Title(Entity* entity, const SystemAddress& sysAddr, const std::string args);
}
#endif // SLASHCOMMANDHANDLER_H #endif // SLASHCOMMANDHANDLER_H

View File

@ -79,6 +79,7 @@
#include "PositionUpdate.h" #include "PositionUpdate.h"
#include "PlayerManager.h" #include "PlayerManager.h"
#include "eLoginResponse.h" #include "eLoginResponse.h"
#include "SlashCommandHandler.h"
namespace Game { namespace Game {
Logger* logger = nullptr; Logger* logger = nullptr;
@ -313,6 +314,9 @@ int main(int argc, char** argv) {
uint32_t sqlPingTime = 10 * 60 * currentFramerate; // 10 minutes in frames uint32_t sqlPingTime = 10 * 60 * currentFramerate; // 10 minutes in frames
uint32_t emptyShutdownTime = (cloneID == 0 ? 30 : 5) * 60 * currentFramerate; // 30 minutes for main worlds, 5 for all others. uint32_t emptyShutdownTime = (cloneID == 0 ? 30 : 5) * 60 * currentFramerate; // 30 minutes for main worlds, 5 for all others.
// Register slash commands
SlashCommandHandler::Startup();
Game::logger->Flush(); // once immediately before the main loop Game::logger->Flush(); // once immediately before the main loop
while (true) { while (true) {
Metrics::StartMeasurement(MetricVariable::Frame); Metrics::StartMeasurement(MetricVariable::Frame);

View File

@ -121,7 +121,7 @@ TEST(MagicEnumTest, eGameMessageTypeTest) {
namespace { namespace {
template <typename T> template <typename T>
void AssertEnumArraySorted(const T& eArray) { void AssertEnumArraySorted(const T& eArray) {
for (int i = 0; i < eArray->size(); ++i) { for (int i = 0; i < eArray->size() - 1; ++i) {
const auto entryCurr = eArray->at(i).first; const auto entryCurr = eArray->at(i).first;
LOG_EARRAY(eArray, i, entryCurr); LOG_EARRAY(eArray, i, entryCurr);
const auto entryNext = eArray->at(++i).first; const auto entryNext = eArray->at(++i).first;