diff --git a/src/framework/core/binarytree.cpp b/src/framework/core/binarytree.cpp index 7dc50abf..3ebfa452 100644 --- a/src/framework/core/binarytree.cpp +++ b/src/framework/core/binarytree.cpp @@ -93,3 +93,14 @@ uint64 BinaryTree::getU64() m_pos += 8; return v; } + +std::string BinaryTree::getString() +{ + uint16 len = getU16(); + if (len == 0 || len > 8192) + stdext::throw_exception("failed to get string from binary tree - invalid size read."); + + std::string ret((char *)&m_buffer[m_pos], len); + m_pos += len; + return ret; +} diff --git a/src/framework/core/filestream.cpp b/src/framework/core/filestream.cpp index 12216dde..0d286e14 100644 --- a/src/framework/core/filestream.cpp +++ b/src/framework/core/filestream.cpp @@ -254,7 +254,7 @@ BinaryTreePtr FileStream::getBinaryTree() if(byte == BINARYTREE_NODE_START) root->unserialize(asFileStream()); else - stdext::throw_exception(stdext::format("failed to read node start (getFirstNode): %d", byte)); + stdext::throw_exception(stdext::format("failed to read node start (getBinaryTree): %d", byte)); return root; } diff --git a/src/otclient/core/item.cpp b/src/otclient/core/item.cpp index dff466eb..df5799fb 100644 --- a/src/otclient/core/item.cpp +++ b/src/otclient/core/item.cpp @@ -31,6 +31,7 @@ #include #include #include +#include Item::Item() : m_id(0), @@ -203,7 +204,7 @@ bool Item::isValid() return g_things.isValidDatId(m_id, DatItemCategory); } -bool Item::unserializeAttr(FileStreamPtr fin) +bool Item::unserializeAttr(const BinaryTreePtr &fin) { uint8 attrType; while ((attrType = fin->getU8()) != 0) @@ -212,7 +213,7 @@ bool Item::unserializeAttr(FileStreamPtr fin) return true; } -void Item::readAttr(AttrTypes_t attrType, FileStreamPtr fin) +void Item::readAttr(AttrTypes_t attrType, const BinaryTreePtr &fin) { switch (attrType) { case ATTR_COUNT: @@ -269,3 +270,13 @@ void Item::readAttr(AttrTypes_t attrType, FileStreamPtr fin) break; } } + +bool Item::isMoveable() +{ + if (m_datType) + return !m_datType->isNotMoveable(); + + g_logger.warning(stdext::format( + "Invalid dat type for item %d", m_id)); + return false; +} diff --git a/src/otclient/core/item.h b/src/otclient/core/item.h index 9958d3ea..a66997dd 100644 --- a/src/otclient/core/item.h +++ b/src/otclient/core/item.h @@ -101,9 +101,10 @@ public: bool isItem() { return true; } // TODO: These should be abstract and declared in i.e containers, doors, etc. - bool unserializeAttr(FileStreamPtr fin); - bool unserializeItemNode(FileStreamPtr fin, uint8) { return unserializeAttr(fin); } - void readAttr(AttrTypes_t attrType, FileStreamPtr fin); + bool unserializeAttr(const BinaryTreePtr &fin); + bool unserializeItemNode(const BinaryTreePtr &fin) { return unserializeAttr(fin); } + void readAttr(AttrTypes_t attrType, const BinaryTreePtr &fin); + bool isMoveable(); private: uint16 m_id; diff --git a/src/otclient/core/map.cpp b/src/otclient/core/map.cpp index e16ac8e4..bcdb37ab 100644 --- a/src/otclient/core/map.cpp +++ b/src/otclient/core/map.cpp @@ -32,6 +32,7 @@ #include "mapview.h" #include #include +#include Map g_map; @@ -60,29 +61,31 @@ void Map::notificateTileUpdateToMapViews(const Position& pos) bool Map::loadOtbm(const std::string& fileName) { -#if 0 FileStreamPtr fin = g_resources.openFile(fileName); if (!fin) { g_logger.error(stdext::format("Unable to load map '%s'", fileName)); return false; } - if (!g_things.isOtbLoaded() || !g_things.isXmlLoaded()) { + if (!g_things.isOtbLoaded()/* || !g_things.isXmlLoaded()*/) { g_logger.error("OTB and XML are not loaded yet to load a map."); return false; } - uint32 type = 0; - uint8 root = 0; - root = fin->readNode(root, type); - - uint32 headerVersion = fin->getU32(); + assert(fin->getU32() == 0); + BinaryTreePtr root = fin->getBinaryTree(); + root->skip(1); // Not sure, what exactly that is... perhaps node type? + uint32 headerVersion = root->getU32(); + dump << headerVersion; if (!headerVersion || headerVersion > 3) { g_logger.error("Unknown OTBM version detected."); return false; } - uint32 headerMajorItems = fin->getU32(); + root->skip(1); // ?? + uint32 headerMajorItems = root->getU8(); + dump << headerMajorItems; + dump << "major: " << g_things.getOtbMajorVersion(); if (headerMajorItems < 3) { g_logger.error("This map needs to be upgraded."); return false; @@ -93,20 +96,24 @@ bool Map::loadOtbm(const std::string& fileName) return false; } - uint32_t headerMinorItems = fin->getU32(); + root->skip(1); /// ?? + uint32 headerMinorItems = root->getU8(); + dump << headerMinorItems; + dump << "minor: " << g_things.getOtbMinorVersion(); if (headerMinorItems > g_things.getOtbMinorVersion()) g_logger.warning("This map needs an updated OTB."); - uint8 node = fin->readNode(root, type); - if (type != OTBM_MAP_DATA) { + BinaryTreePtr node = root->getChildren()[0]; + if (node->getU8() != OTBM_MAP_DATA) { g_logger.error("Could not read data node."); return false; } std::string tmp; uint8 attribute; - while ((attribute = fin->getU8())) { - tmp = fin->getString(); + while (node->canRead()) { + attribute = node->getU8(); + tmp = node->getString(); switch (attribute) { case OTBM_ATTR_DESCRIPTION: if (!m_description.empty()) @@ -127,40 +134,41 @@ bool Map::loadOtbm(const std::string& fileName) } dump << m_description; + dump << m_houseFile; + dump << m_spawnFile; - uint8 nodeMapData; - do { - nodeMapData = fin->readNode(node, type); - - if (type == OTBM_TILE_AREA) { - uint16 baseX = fin->getU16(), baseY = fin->getU16(); - uint8 pz = fin->getU8(); - - uint8 nodeTile; - do { - nodeTile = fin->readNode(nodeMapData, type); + for (const BinaryTreePtr &nodeMapData : node->getChildren()) { + uint8 mapDataType = nodeMapData->getU8(); + dump << "mapData: " << (int)mapDataType; + if (mapDataType == OTBM_TILE_AREA) { + dump << "Tile: reading pos..."; + uint16 baseX = nodeMapData->getU16(), baseY = nodeMapData->getU16(); + uint8 pz = nodeMapData->getU8(); + for (const BinaryTreePtr &nodeTile : nodeMapData->getChildren()) { + uint8 type = nodeTile->getU8(); if (type == OTBM_TILE || type == OTBM_HOUSETILE) { TilePtr tile = 0; ItemPtr ground = 0; uint32 flags = 0; - uint16 px = baseX + fin->getU16(), py = fin->getU16(); + uint16 px = baseX + nodeTile->getU16(), py = baseY + nodeTile->getU16(); Position pos(px, py, pz); // TODO: Houses. if (type == OTBM_HOUSETILE) { - uint32 hId = fin->getU32(); + uint32 hId = nodeTile->getU32(); tile = createTile(pos); // TODO: add it to house. } uint8 tileAttr; - while ((tileAttr = fin->getU8())) { + while (nodeTile->canRead()) { + tileAttr = nodeTile->getU8(); switch (tileAttr) { case OTBM_ATTR_TILE_FLAGS: { - uint32 _flags = fin->getU32(); + uint32 _flags = nodeTile->getU32(); if ((_flags & TILESTATE_PROTECTIONZONE) == TILESTATE_PROTECTIONZONE) flags |= TILESTATE_PROTECTIONZONE; @@ -176,7 +184,7 @@ bool Map::loadOtbm(const std::string& fileName) flags |= TILESTATE_REFRESH; break; } case OTBM_ATTR_ITEM: { - ItemPtr item = Item::createFromOtb(fin->getU16()); + ItemPtr item = Item::createFromOtb(nodeTile->getU16()); if (!item) { g_logger.error(stdext::format("failed to create new item at tile pos %d, %d, %d", px, py, pz)); return false; @@ -198,22 +206,19 @@ bool Map::loadOtbm(const std::string& fileName) } } - uint8 nodeItem; - do { - nodeItem = fin->readNode(nodeTile, type); - - if (type == OTBM_ITEM) { - ItemPtr item = Item::createFromOtb(fin->getU16()); + for (const BinaryTreePtr &nodeItem : nodeTile->getChildren()) { + if (nodeItem->getU8() == OTBM_ITEM) { + ItemPtr item = Item::createFromOtb(nodeItem->getU16()); if (!item) { g_logger.error(stdext::format("failed to create new item at pos %d, %d, %d", px, py, pz)); return false; } - if (item->unserializeItemNode(fin, nodeItem)) { + if (item->unserializeItemNode(nodeItem)) { if (/* house && */item->isMoveable()) { g_logger.warning(stdext::format("Moveable item found in house: %d at pos %d %d %d", item->getId(), px, py, pz)); - item = 0; + item = nullptr; } else if (tile) { tile->addThing(item); } else if (item->isGround()) { @@ -232,7 +237,7 @@ bool Map::loadOtbm(const std::string& fileName) g_logger.error(stdext::format("Unknown item node type %d", type)); return false; } - } while (nodeItem); + } if (!tile) { tile = createTile(pos); @@ -244,42 +249,30 @@ bool Map::loadOtbm(const std::string& fileName) g_logger.error(stdext::format("Unknown tile node type %d", type)); return false; } - } while (nodeTile); - } else if (type == OTBM_TOWNS) { - uint8 nodeTown; - do { - nodeTown = fin->readNode(nodeMapData, type); + } + } else if (mapDataType == OTBM_TOWNS) { + for (const BinaryTreePtr &nodeTown : nodeMapData->getChildren()) { + if (nodeTown->getU8() == OTBM_TOWN) { + uint32 townId = nodeTown->getU32(); + std::string townName = nodeTown->getString(); - if (type == OTBM_TOWN) { - uint32 townId = fin->getU32(); - std::string townName = fin->getString(); - - Position townCoords(fin->getU16(), fin->getU16(), fin->getU8()); - } else { - g_logger.error(stdext::format("Unknown town node type %d", type)); + Position townCoords(nodeTown->getU16(), nodeTown->getU16(), nodeTown->getU8()); + } else return false; + } + } else if (mapDataType == OTBM_WAYPOINTS && headerVersion > 1) { + for (const BinaryTreePtr &nodeWaypoint : nodeMapData->getChildren()) { + if (nodeWaypoint->getU8() == OTBM_WAYPOINT) { + std::string name = nodeWaypoint->getString(); + Position waypointPos(nodeWaypoint->getU16(), nodeWaypoint->getU16(), nodeWaypoint->getU8()); } - } while (nodeTown); - } else if (type == OTBM_WAYPOINTS && headerVersion > 1) { - uint8 nodeWaypoint; - do { - nodeWaypoint = fin->readNode(nodeMapData, type); - - if (type == OTBM_WAYPOINT) { - std::string name = fin->getString(); - Position waypointPos(fin->getU16(), fin->getU16(), fin->getU8()); - } - } while (nodeWaypoint); - } else { - g_logger.error(stdext::format("Unknown map node %d", type)); + } + } else return false; - } - } while (nodeMapData); + } // TODO: Load house & spawns. return true; -#endif - return false; } bool Map::loadOtcm(const std::string& fileName) diff --git a/src/otclient/ui/uiprogressrect.cpp.autosave b/src/otclient/ui/uiprogressrect.cpp.autosave new file mode 100644 index 00000000..c74ff034 --- /dev/null +++ b/src/otclient/ui/uiprogressrect.cpp.autosave @@ -0,0 +1,98 @@ +/* + * 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 "uiprogressrect.h" +#include +#include +#include + +UIProgressRect::UIProgressRect() +{ + m_percent = 0; +} + +void UIProgressRect::drawSelf(Fw::DrawPane drawPane) +{ + if((drawPane & Fw::ForegroundPane) == 0) + return; + + g_painter->setColor(m_backgroundColor); + + // todo: check +1 to right/bottom + // todo: add smooth + Rect drawRect = getPaddingRect(); + + // 0% - 12.5% (12.5) + // triangle from top center, to top right (var x) + if(m_percent < 12.5) { + Point var = Point(std::max(m_percent - 0.0, 0.0) * (drawRect.right() - drawRect.horizontalCenter()) / 12.5, 0); + g_painter->drawFilledTriangle(drawRect.center(), drawRect.topRight() + Point(1,0), drawRect.topCenter() + var); + } + + // 12.5% - 37.5% (25) + // triangle from top right to bottom right (var y) + if(m_percent < 37.5) { + Point var = Point(0, std::max(m_percent - 12.5, 0.0) * (drawRect.bottom() - drawRect.top()) / 25.0); + g_painter->drawFilledTriangle(drawRect.center(), drawRect.bottomRight() + Point(1,1), drawRect.topRight() + var + Point(1,0)); + } + + // 37.5% - 62.5% (25) + // triangle from bottom right to bottom left (var x) + if(m_percent < 62.5) { + Point var = Point(std::max(m_percent - 37.5, 0.0) * (drawRect.right() - drawRect.left()) / 25.0, 0); + g_painter->drawFilledTriangle(drawRect.center(), drawRect.bottomLeft() + Point(0,1), drawRect.bottomRight() - var + Point(1,1)); + } + + // 62.5% - 87.5% (25) + // triangle from bottom left to top left + if(m_percent < 87.5) { + Point var = Point(0, std::max(m_percent - 62.5, 0.0) * (drawRect.bottom() - drawRect.top()) / 25.0); + g_painter->drawFilledTriangle(drawRect.center(), drawRect.topLeft(), drawRect.bottomLeft() - var + Point(0,1)); + } + + // 87.5% - 100% (12.5) + // triangle from top left to top center + if(m_percent < 100) { + Point var = Point(std::max(m_percent - 87.5, 0.0) * (drawRect.horizontalCenter() - drawRect.left()) / 12.5, 0); + g_painter->drawFilledTriangle(drawRect.center(), drawRect.topCenter(), drawRect.topLeft() + var); + } + + drawImage(m_rect); + drawBorder(m_rect); + drawIcon(m_rect); + drawText(m_rect); +} + +void UIProgressRect::setPercent(float percent) +{ + m_percent = std::max(std::min((double)percent, 100.0), 0.0); +} + +void UIProgressRect::onStyleApply(const std::string& styleName, const OTMLNodePtr& styleNode) +{ + UIWidget::onStyleApply(styleName, styleNode); + + for(const OTMLNodePtr& node : styleNode->children()) { + if(node->tag() == "percent") + setPercent(node->value()); + } +}