From 6b0d922dd9648ee7b7fcb00995c3c267cb7a32ff Mon Sep 17 00:00:00 2001 From: otfallen Date: Thu, 21 Jun 2012 04:39:40 +0200 Subject: [PATCH] missing files --- src/otclient/core/itemloader.cpp | 238 +++++++++++++++++++++++++++++++ src/otclient/core/itemloader.h | 119 ++++++++++++++++ 2 files changed, 357 insertions(+) create mode 100644 src/otclient/core/itemloader.cpp create mode 100644 src/otclient/core/itemloader.h diff --git a/src/otclient/core/itemloader.cpp b/src/otclient/core/itemloader.cpp new file mode 100644 index 00000000..bcff5f62 --- /dev/null +++ b/src/otclient/core/itemloader.cpp @@ -0,0 +1,238 @@ +/* + * Copyright (c) 2010-2012 OTClient + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "itemloader.h" +#include +#include +#define TIXML_USE_STL // use STL strings instead. +#include + +ItemLoader g_itemLoader; + +ItemLoader::~ItemLoader() +{ + m_items.clear(); +} + +ItemDataPtr ItemLoader::getType(uint16 id) const +{ + for (const ItemDataPtr &it : m_items) { + if (it->id == id) + return it; + } + + return nullptr; +} + +void ItemLoader::addType(uint16 id, ItemDataPtr type) +{ + if (getType(id)) + return; + + m_items.push_back(type); +} + +bool ItemLoader::loadOtb(const std::string &name) +{ + FileStreamPtr fin = g_resources.openFile(name); + if (!fin) { + g_logger.error(stdext::format("failed to open file '%s'", name)); + return false; + } + + fin->getU32(); // skip version + + uint32 type; + uint8 node = fin->readNode(node, type); + + fin->getU32(); // skip flags... + if (fin->getU8() == 0x01) { // version + fin->getU8(); // skip length. + dwMajorVersion = fin->getU32(); + dwMinorVersion = fin->getU32(); + dwBuildNumber = fin->getU32(); + } + + uint16 lastId = 99; + ItemDataPtr newItem; + + while ((node = fin->readNode(node, type))) { + if (!(newItem = ItemDataPtr(new ItemData))) { + g_logger.error("failed to read new item from OTB"); + return false; + } + + newItem->group = (ItemGroup)type; + fin->getU32(); // skip flags + + ItemAttrib attr; + while ((attr = (ItemAttrib)fin->getU8())) { + uint16 dsize = fin->getU16(); + switch (attr) { + case ServerId: { + if (dsize != sizeof(uint16)) { + g_logger.error("Invalid data size"); + return false; + } + + uint16 serverId = fin->getU16(); + if (serverId > 20000 && serverId < 20100) { + serverId -= 20000; + } else if (lastId > 99 && lastId != serverId - 1) { + static ItemDataPtr dummyItemType(new ItemData); + while (lastId != serverId - 1) { + dummyItemType->id = ++lastId; + addType(lastId, dummyItemType); + } + } + + newItem->id = serverId; + lastId = serverId; + break; + } case ClientId: { + newItem->clientId = fin->getU16(); + break; + } case Speed: { + fin->getU16(); // skip speed + break; + } case Light2: { + if (!fin->seek(dsize)) { + g_logger.error(stdext::format("fail to skip light block with size %d", dsize)); + return false; + } + } default: { + if (!fin->seek(dsize)) { + g_logger.error(stdext::format("fail to skip unknown data with size %d", dsize)); + return false; + } + } + } + } + + addType(newItem->id, newItem); + } + + return true; +} + +bool ItemLoader::loadXML(const std::string &name) +{ + TiXmlDocument doc(name.c_str()); + if (!doc.LoadFile()) { + g_logger.error(stdext::format("failed to load xml '%s'", name)); + return false; + } + + TiXmlElement* root = doc.FirstChildElement(); + if (!root) { + g_logger.error("invalid xml root"); + return false; + } + + if (root->ValueTStr() != "items") { + g_logger.error("invalid xml tag name, should be 'items'"); + return false; + } + + 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 = stdext::unsafe_cast(element->Attribute("id")); + uint16 idEx = 0; + if (!id) { + bool found = false; + // fallback into reading fromid and toid + uint16 fromid = stdext::unsafe_cast(element->Attribute("fromid")); + uint16 toid = stdext::unsafe_cast(element->Attribute("toid")); + ItemDataPtr iType; + for (int __id = fromid; __id < toid; ++__id) { + if (!(iType = getType(__id))) + continue; + + iType->name = name; + idEx = iType->id == fromid ? fromid : toid; + found = true; + } + + if (!found) + continue; + } + + ItemDataPtr iType = getType(id); + if (!iType) { + iType = ItemDataPtr(new ItemData); + iType->id = idEx ? idEx : id; + iType->name = name; + addType(iType->id, iType); + } + + iType->name = name; + + for (TiXmlElement *attr = element->FirstChildElement(); attr; attr = attr->NextSiblingElement()) { + if (attr->ValueTStr() != "attribute") + continue; + + std::string key = attr->Attribute("key"); + std::string value = attr->Attribute("value"); + if (key == "type") { + if (value == "magicfield") + iType->group = IsMagicField; + else if (value == "key") + iType->group = IsKey; + else if (value == "depot") + iType->isDepot = true; + else if (value == "teleport") + iType->group = IsTeleport; + else if (value == "bed") + iType->isBed = true; + else if (value == "door") + iType->group = IsDoor; + } else if (key == "name") { + iType->name = value; + } else if (key == "description") { + iType->description = value; + } else if (key == "weight") { + iType->weight = stdext::unsafe_cast(stdext::unsafe_cast(value) / 100.f); + } else if (key == "containerSize") { + int containerSize = stdext::unsafe_cast(value); + if (containerSize) + iType->containerSize = containerSize; + iType->group = IsContainer; + } else if (key == "writeable") { + if (!value.empty()) + iType->group = IsWritable; + } else if (key == "maxTextLen") { + iType->maxTextLength = stdext::unsafe_cast(value); + } else if (key == "charges") { + iType->charges = stdext::unsafe_cast(value); + } + } + } + + doc.Clear(); + return true; +} diff --git a/src/otclient/core/itemloader.h b/src/otclient/core/itemloader.h new file mode 100644 index 00000000..b29dd83c --- /dev/null +++ b/src/otclient/core/itemloader.h @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2010-2012 OTClient + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef OTBLOADER_H +#define OTBLOADER_H + +#include "declarations.h" + +enum ItemGroup { + IsGround, + IsContainer, + IsWeapon, + IsAmmunition, + IsArmor, + IsCharges, + IsTeleport, + IsMagicField, + IsWritable, + IsKey, + IsSplash, + IsFluid, + IsDoor, + InvalidGroup +}; + +enum ItemAttrib { + First = 0x10, + ServerId = First, + ClientId, + Name, /* deprecated */ + Desc, /*deprecated*/ + Speed, + Slot, /*deprecated*/ + MaxItems, /*deprecated*/ + Weight, /*deprecated*/ + Weapon, /*deprecated*/ + Amu, /*deprecated*/ + Armor, /*deprecated*/ + MagLevel, /*deprecated*/ + MagicField, /*deprecated*/ + Writable, /*deprecated*/ + RotateTo, /*deprecated*/ + Decay, /*deprecated*/ + SpriteHash, + MinimapColor, + Attr07, + Attr08, + Light, + + // 1-byte aligned + Decay2, /*deprecated*/ + Weapon2, /*deprecated*/ + Amu2, /*deprecated*/ + Armor2, /*deprecated*/ + Writable2, /*deprecated*/ + Light2, + TopOrder, + Wrtiable3 /*deprecated*/ +}; + +struct ItemData { + uint16 id; + uint16 clientId; + std::string name, description; + int containerSize; + ItemGroup group; + double weight; + + // xml stuff. + bool isDepot; + bool isBed; + uint32 maxTextLength; + uint32 charges; +}; + +class ItemLoader +{ +public: + uint32 dwMajorVersion; + uint32 dwMinorVersion; + uint32 dwBuildNumber; + + ItemLoader() : m_otbLoaded(false), m_xmlLoaded(false) { } + ~ItemLoader(); + + bool loadOtb(const std::string &name); + bool loadXML(const std::string &name); + + bool isLoaded() { return m_otbLoaded && m_xmlLoaded; } + ItemDataPtr getType(uint16 id) const; + void addType(uint16 id, ItemDataPtr type); + +private: + ItemDataList m_items; + bool m_otbLoaded, m_xmlLoaded; +}; + +extern ItemLoader g_itemLoader; + +#endif