From 5015ced156d88578ae7df9ae714d0637acc54315 Mon Sep 17 00:00:00 2001 From: niczkx Date: Wed, 18 Jul 2012 13:46:58 +0200 Subject: [PATCH] update houses/monsters/items xml readers --- src/otclient/houses.cpp | 9 ++-- src/otclient/map.cpp | 25 +++++++---- src/otclient/monsters.cpp | 55 +++++++++++++---------- src/otclient/monsters.h | 2 + src/otclient/thingtypemanager.cpp | 73 +++++++++++++++++-------------- src/otclient/thingtypemanager.h | 1 + src/otclient/thingtypeotb.cpp | 25 ++++++----- src/otclient/thingtypeotb.h | 9 +--- 8 files changed, 110 insertions(+), 89 deletions(-) diff --git a/src/otclient/houses.cpp b/src/otclient/houses.cpp index b7226e5b..6bc181c9 100644 --- a/src/otclient/houses.cpp +++ b/src/otclient/houses.cpp @@ -22,6 +22,8 @@ #include "map.h" +#include + House::House(uint32 hId, const std::string &name, const Position &pos) : m_id(hId), m_name(name) { @@ -83,9 +85,10 @@ HousePtr Houses::getHouse(uint32 houseId) void Houses::load(const std::string& fileName) { - TiXmlDocument doc(fileName.c_str()); - if(!doc.LoadFile()) - stdext::throw_exception(stdext::format("failed to load '%s' (House XML)", fileName)); + TiXmlDocument doc; + doc.Parse(g_resources.loadFile(fileName).c_str()); + if(doc.Error()) + stdext::throw_exception(stdext::format("failed to load '%s': %s (House XML)", fileName, doc.ErrorDesc())); TiXmlElement *root = doc.FirstChildElement(); if(!root || root->ValueTStr() != "houses") diff --git a/src/otclient/map.cpp b/src/otclient/map.cpp index 2fd941ed..e235a0fa 100644 --- a/src/otclient/map.cpp +++ b/src/otclient/map.cpp @@ -376,33 +376,40 @@ void Map::loadSpawns(const std::string &fileName) if(!m_monsters.isLoaded()) stdext::throw_exception("cannot load spawns; monsters aren't loaded."); - TiXmlDocument doc(fileName); - if(!doc.LoadFile()) - stdext::throw_exception(stdext::format("cannot load spawns xml file '%s", fileName)); + TiXmlDocument doc; + doc.Parse(g_resources.loadFile(fileName).c_str()); + if(doc.Error()) + stdext::throw_exception(stdext::format("cannot load spawns xml file '%s: '%s'", fileName, doc.ErrorDesc())); TiXmlElement* root = doc.FirstChildElement(); if(!root || root->ValueStr() != "spawns") stdext::throw_exception("malformed spawns file"); for(TiXmlElement* node = root->FirstChildElement(); node; node = node->NextSiblingElement()) { - if (node->ValueTStr() != "spawn") + if(node->ValueTStr() != "spawn") stdext::throw_exception("invalid spawn node"); Position centerPos = node->readPos("center"); for(TiXmlElement* mType = node->FirstChildElement(); mType; mType = mType->NextSiblingElement()) { - if (mType->ValueStr() != "monster") - stdext::throw_exception("invalid spawn-subnode"); + if(mType->ValueStr() != "monster" && mType->ValueStr() != "npc") + stdext::throw_exception(stdext::format("invalid spawn-subnode %s", mType->ValueStr())); + if(mType->ValueStr() == "npc") // escape npc's for now... + continue; std::string mName = mType->Attribute("name"); - MonsterTypePtr m = m_monsters.getMonster(mName); + MonsterTypePtr m = getMonster(mName); if (!m) - stdext::throw_exception(stdext::format("unkown monster %s", mName)); + stdext::throw_exception(stdext::format("unkown monster '%s'", stdext::trim(stdext::tolower(mName)))); Point off = mType->readPoint(); Position mPos(centerPos.x + off.x, centerPos.y + off.y, centerPos.z); m->setPos(mPos); + m->setSpawnTime(mType->readType("spawntime")); } } + + doc.Clear(); + g_logger.debug("Loaded spawns"); } bool Map::loadOtcm(const std::string& fileName) @@ -1026,5 +1033,5 @@ std::tuple, Otc::PathFindResult> Map::findPath(const MonsterTypePtr Map::getMonster(const std::string& name) { - return m_monsters.getMonster(stdext::trim(stdext::tolower(name))); + return m_monsters.getMonster(name); } diff --git a/src/otclient/monsters.cpp b/src/otclient/monsters.cpp index ba62affc..a5daec64 100644 --- a/src/otclient/monsters.cpp +++ b/src/otclient/monsters.cpp @@ -24,20 +24,27 @@ #include "creature.h" #include +#include void Monsters::loadMonsters(const std::string& file) { - TiXmlDocument doc(file); - if(!doc.LoadFile()) - stdext::throw_exception(stdext::format("cannot open monsters file '%s'", file)); + TiXmlDocument doc; + doc.Parse(g_resources.loadFile(file).c_str()); + if(doc.Error()) + stdext::throw_exception(stdext::format("cannot open monsters file '%s': '%s'", file, doc.ErrorDesc())); TiXmlElement* root = doc.FirstChildElement(); if(!root || root->ValueStr() != "monsters") stdext::throw_exception("malformed monsters xml file"); - for(TiXmlElement* monster = root->FirstChildElement(); root; root = root->NextSiblingElement()) { - MonsterTypePtr newMonster(new MonsterType(monster->Attribute("name"))); - loadSingleMonster(file.substr(0, file.find_last_of('/')) + '/' + monster->Attribute("file"), newMonster); + for(TiXmlElement* monster = root->FirstChildElement(); monster; monster = monster->NextSiblingElement()) { + MonsterTypePtr newMonster(new MonsterType(stdext::trim(stdext::tolower(monster->Attribute("name"))))); + std::string fname = file.substr(0, file.find_last_of('/')) + '/' + monster->Attribute("file"); + + if(fname.substr(fname.length() - 4) != ".xml") + fname += ".xml"; + + loadSingleMonster(fname, newMonster); } doc.Clear(); @@ -49,9 +56,10 @@ void Monsters::loadSingleMonster(const std::string& file, const MonsterTypePtr& if (!m || std::find(m_monsters.begin(), m_monsters.end(), m) != m_monsters.end()) stdext::throw_exception("reloading monsters is not supported yet."); - TiXmlDocument doc(file); - if(!doc.LoadFile()) - stdext::throw_exception(stdext::format("cannot load single monster file '%s'", file)); + TiXmlDocument doc; + doc.Parse(g_resources.loadFile(file).c_str()); + if(doc.Error()) + stdext::throw_exception(stdext::format("cannot load single monster file '%s': '%s'", file, doc.ErrorDesc())); TiXmlElement* root = doc.FirstChildElement(); if(!root || root->ValueStr() != "monster") @@ -61,21 +69,20 @@ void Monsters::loadSingleMonster(const std::string& file, const MonsterTypePtr& if(attrib->ValueStr() == "look") { Outfit out; - int type = attrib->readType("type"); - if (type <= 0) + int type = 0; + if(!attrib->Attribute("type").empty()) + type = attrib->readType("type"); + else type = attrib->readType("typeex"); - if(type) { - out.setId(type); - { - out.setHead(attrib->readType(("head"))); - out.setBody(attrib->readType(("body"))); - out.setLegs(attrib->readType(("legs"))); - out.setFeet(attrib->readType(("feet"))); - out.setAddons(attrib->readType(("addons"))); - out.setMount(attrib->readType(("mount"))); - } - } else - stdext::throw_exception(stdext::format("invalid look type/typeex for monster %s", m->getName())); + out.setId(type); + { + out.setHead(attrib->readType(("head"))); + out.setBody(attrib->readType(("body"))); + out.setLegs(attrib->readType(("legs"))); + out.setFeet(attrib->readType(("feet"))); + out.setAddons(attrib->readType(("addons"))); + out.setMount(attrib->readType(("mount"))); + } m->setOutfit(out); } } @@ -86,7 +93,7 @@ void Monsters::loadSingleMonster(const std::string& file, const MonsterTypePtr& MonsterTypePtr Monsters::getMonster(const std::string& name) { auto it = std::find_if(m_monsters.begin(), m_monsters.end(), - [=] (const MonsterTypePtr& m) -> bool { return m->getName() == name; }); + [=] (const MonsterTypePtr& m) -> bool { return m->getName() == stdext::trim(stdext::tolower(name)); }); return it != m_monsters.end() ? *it : nullptr; } diff --git a/src/otclient/monsters.h b/src/otclient/monsters.h index f2bb88e8..2f27beba 100644 --- a/src/otclient/monsters.h +++ b/src/otclient/monsters.h @@ -37,6 +37,7 @@ public: void setPos(const Position& pos) { m_pos = pos; } void setName(const std::string& name) { m_name = name; } void setOutfit(const Outfit& o) { m_outfit = o; } + void setSpawnTime(int spawnTime) { m_spawnTime = spawnTime; } std::string getName() { return m_name; } Position getPos() { return m_pos; } @@ -46,6 +47,7 @@ private: Position m_pos; std::string m_name; Outfit m_outfit; + int m_spawnTime; }; class Monsters diff --git a/src/otclient/thingtypemanager.cpp b/src/otclient/thingtypemanager.cpp index c055d526..1b85ab55 100644 --- a/src/otclient/thingtypemanager.cpp +++ b/src/otclient/thingtypemanager.cpp @@ -124,56 +124,63 @@ void ThingTypeManager::loadOtb(const std::string& file) void ThingTypeManager::loadXml(const std::string& file) { - TiXmlDocument doc(file.c_str()); - if(!doc.LoadFile()) - stdext::throw_exception(stdext::format("failed to load xml '%s'", file)); + TiXmlDocument doc; + doc.Parse(g_resources.loadFile(file).c_str()); + if(doc.Error()) + stdext::throw_exception(stdext::format("failed to parse '%s': '%s'", file, doc.ErrorDesc())); TiXmlElement* root = doc.FirstChildElement(); if(!root || root->ValueTStr() != "items") stdext::throw_exception("invalid root tag name"); - ThingTypeOtbPtr otbType = nullptr; for (TiXmlElement *element = root->FirstChildElement(); element; element = element->NextSiblingElement()) { if(element->ValueTStr() != "item") continue; - std::string name = element->Attribute("id"); - if(name.empty()) - continue; + uint16 id = element->readType("id"); + if(id > 20000 && id < 20100) { + id -= 20000; + ThingTypeOtbPtr newType(new ThingTypeOtb); + newType->setServerId(id); + addOtbType(newType); + } - uint16 id = stdext::unsafe_cast(element->Attribute("id")); - if(!(otbType = getOtbType(id))) { - // try reading fromId toId - uint16 from = stdext::unsafe_cast(element->Attribute("fromId")); - uint16 to = stdext::unsafe_cast(element->Attribute("toid")); + if(id != 0) + parseItemType(id, element); + else { + uint16 fromId = element->readType("fromid"), toId = element->readType("toid"); + for(uint16 i = fromId; i < toId; ++i) + parseItemType(i, element); + } + } - for (uint16 __id = from; __id < to; ++__id) { - if(!(otbType = getOtbType(__id))) - continue; + doc.Clear(); + m_xmlLoaded = true; + g_logger.debug("items.xml read successfully."); +} - otbType->setHasRange(); - otbType->setFromServerId(from); - otbType->setToServerId(to); - break; - } +void ThingTypeManager::parseItemType(uint16 id, TiXmlElement* elem) +{ + uint16 serverId = id; + if(serverId > 20000 && id < 20100) { + serverId -= 20000; - // perform last check - if(!otbType) { - stdext::throw_exception(stdext::format("failed to find item with server id %d - tried reading fromid to id", - id)); - } - } + ThingTypeOtbPtr newType(new ThingTypeOtb); + newType->setServerId(serverId); + addOtbType(newType); + } - for (TiXmlElement *attr = element->FirstChildElement(); attr; attr = attr->NextSiblingElement()) { - if(attr->ValueTStr() != "attribute") - continue; + ThingTypeOtbPtr otbType = getOtbType(serverId); + otbType->setName(elem->Attribute("name")); + for(TiXmlElement* attrib = elem->FirstChildElement(); attrib; attrib = attrib->NextSiblingElement()) { + if(attrib->ValueStr() != "attribute") + break; - otbType->unserializeXML(attr); + if(attrib->Attribute("key") == "description") { + otbType->setDesc(attrib->Attribute("value")); + break; } } - - doc.Clear(); - m_xmlLoaded = true; } void ThingTypeManager::addOtbType(const ThingTypeOtbPtr& otbType) diff --git a/src/otclient/thingtypemanager.h b/src/otclient/thingtypemanager.h index 20f903bb..b0879661 100644 --- a/src/otclient/thingtypemanager.h +++ b/src/otclient/thingtypemanager.h @@ -38,6 +38,7 @@ public: bool loadDat(const std::string& file); void loadOtb(const std::string& file); void loadXml(const std::string& file); + void parseItemType(uint16 id, TiXmlElement *elem); void addOtbType(const ThingTypeOtbPtr& otbType); const ThingTypeOtbPtr& findOtbForClientId(uint16 id); diff --git a/src/otclient/thingtypeotb.cpp b/src/otclient/thingtypeotb.cpp index 80a6d915..977d7b61 100644 --- a/src/otclient/thingtypeotb.cpp +++ b/src/otclient/thingtypeotb.cpp @@ -21,6 +21,7 @@ */ +#include "thingtypemanager.h" #include "thingtypeotb.h" #include @@ -41,6 +42,7 @@ void ThingTypeOtb::unserialize(const BinaryTreePtr& node) node->getU32(); // flags + static uint16 lastId = 99; while(node->canRead()) { uint8 attr = node->getU8(); if(attr == 0 || attr == 0xFF) @@ -48,10 +50,20 @@ void ThingTypeOtb::unserialize(const BinaryTreePtr& node) uint16 len = node->getU16(); switch(attr) { - case OtbAttribServerId: + case OtbAttribServerId: { m_serverId = node->getU16(); + if(m_serverId > 20000 && m_serverId < 20100) { + m_serverId -= 20000; + } else if(lastId > 99 && lastId != m_serverId - 1) { + static ThingTypeOtbPtr dummyType(g_things.getNullOtbType()); + while(lastId != m_serverId - 1) { + dummyType->setServerId(++lastId); + g_things.addOtbType(dummyType); + } + } assert(len == 2); break; + } case OtbAttribClientId: m_clientId = node->getU16(); assert(len == 2); @@ -62,14 +74,3 @@ void ThingTypeOtb::unserialize(const BinaryTreePtr& node) } } } - -void ThingTypeOtb::unserializeXML(const TiXmlElement* elem) -{ - std::string key = elem->Attribute("key"); - std::string value = elem->Attribute("value"); - - if(key == "name") - setName(value); - else if(key == "description") - setDesc(value); -} diff --git a/src/otclient/thingtypeotb.h b/src/otclient/thingtypeotb.h index 3baec575..6e78c111 100644 --- a/src/otclient/thingtypeotb.h +++ b/src/otclient/thingtypeotb.h @@ -87,31 +87,24 @@ public: ThingTypeOtb(); void unserialize(const BinaryTreePtr& node); - void unserializeXML(const TiXmlElement* elem); uint16 getServerId() { return m_serverId; } uint16 getClientId() { return m_clientId; } OtbCategory getCategory() { return m_category; } bool isNull() { return m_null; } - bool hasRange() { return m_hasRange; } - void setHasRange() { m_hasRange = true; } - void setFromServerId(uint16 from) { m_fromId = from; } - void setToServerId(uint16 to) { m_toId = to; } + void setServerId(uint16 serverId) { m_serverId = serverId; } void setName(const std::string& name) { m_name = name; } void setDesc(const std::string& desc) { m_desc = desc; } private: uint16 m_serverId; uint16 m_clientId; - uint16 m_fromId, m_toId; std::string m_name, m_desc; OtbCategory m_category; Boolean m_null; - Boolean m_hasRange; }; #endif -