From 0af783b5cf89eb2c5b4fe187f0d1264b67eed267 Mon Sep 17 00:00:00 2001 From: niczkx Date: Sun, 19 Aug 2012 22:30:49 +0000 Subject: [PATCH] Fix OTBM saving --- src/framework/core/binarytree.cpp | 67 +++++++++++++++++ src/framework/core/binarytree.h | 23 ++++++ src/framework/core/declarations.h | 4 +- src/otclient/creature.h | 1 + src/otclient/item.cpp | 4 +- src/otclient/item.h | 3 +- src/otclient/mapio.cpp | 120 ++++++++++++++++-------------- src/otclient/position.h | 1 - src/otclient/tile.h | 1 + 9 files changed, 164 insertions(+), 60 deletions(-) diff --git a/src/framework/core/binarytree.cpp b/src/framework/core/binarytree.cpp index 1439ecac..dde520a3 100644 --- a/src/framework/core/binarytree.cpp +++ b/src/framework/core/binarytree.cpp @@ -181,3 +181,70 @@ Point BinaryTree::getPoint() ret.y = getU8(); return ret; } + +OutputBinaryTree::OutputBinaryTree(const FileStreamPtr& fin) + : m_fin(fin) +{ + startNode(0); +} + +void OutputBinaryTree::addU8(uint8 v) +{ + write(&v, 1); +} + +void OutputBinaryTree::addU16(uint16 v) +{ + uint8 data[2]; + stdext::writeLE16(data, v); + write(data, 2); +} + +void OutputBinaryTree::addU32(uint32 v) +{ + uint8 data[4]; + stdext::writeLE32(data, v); + write(data, 4); +} + +void OutputBinaryTree::addString(const std::string& v) +{ + if(v.size() > 0xFFFF) + stdext::throw_exception("too long string"); + + addU16(v.length()); + write((const uint8*)v.c_str(), v.length()); +} + +void OutputBinaryTree::addPos(const Position& pos) +{ + addU16(pos.x); + addU16(pos.y); + addU8(pos.z); +} + +void OutputBinaryTree::addPoint(const Point& point) +{ + addU8(point.x); + addU8(point.y); +} + +void OutputBinaryTree::startNode(uint8 node) +{ + m_fin->addU8(BINARYTREE_NODE_START); + addU8(node); +} + +void OutputBinaryTree::endNode() +{ + m_fin->addU8(BINARYTREE_NODE_END); +} + +void OutputBinaryTree::write(const uint8 *data, int size) +{ + for(int i=0;iaddU8(BINARYTREE_ESCAPE_CHAR); + m_fin->addU8(data[i]); + } +} diff --git a/src/framework/core/binarytree.h b/src/framework/core/binarytree.h index 65d68d20..19a42d15 100644 --- a/src/framework/core/binarytree.h +++ b/src/framework/core/binarytree.h @@ -66,4 +66,27 @@ private: uint m_startPos; }; +class OutputBinaryTree : public stdext::shared_object +{ +public: + OutputBinaryTree(const FileStreamPtr& finish); + + void addU8(uint8 v); + void addU16(uint16 v); + void addU32(uint32 v); + void addString(const std::string& v); + void addPos(const Position& pos); + void addPoint(const Point& point); + + void startNode(uint8 node); + void endNode(); + +private: + FileStreamPtr m_fin; + +protected: + void write(const uint8* data, int size); +}; + #endif + diff --git a/src/framework/core/declarations.h b/src/framework/core/declarations.h index c08699a7..65bf7e3e 100644 --- a/src/framework/core/declarations.h +++ b/src/framework/core/declarations.h @@ -32,14 +32,14 @@ class Event; class ScheduledEvent; class FileStream; class BinaryTree; -class BinaryWriteTree; +class OutputBinaryTree; typedef stdext::shared_object_ptr ModulePtr; typedef stdext::shared_object_ptr EventPtr; typedef stdext::shared_object_ptr ScheduledEventPtr; typedef stdext::shared_object_ptr FileStreamPtr; typedef stdext::shared_object_ptr BinaryTreePtr; -typedef stdext::shared_object_ptr BinaryWriteTreePtr; +typedef stdext::shared_object_ptr OutputBinaryTreePtr; typedef std::vector BinaryTreeVec; diff --git a/src/otclient/creature.h b/src/otclient/creature.h index 573c02f3..cfb93340 100644 --- a/src/otclient/creature.h +++ b/src/otclient/creature.h @@ -43,6 +43,7 @@ public: Creature(); + virtual void draw(const Point& dest, float scaleFactor, bool animate); void internalDrawOutfit(Point dest, float scaleFactor, bool animateWalk, bool animateIdle, Otc::Direction direction); diff --git a/src/otclient/item.cpp b/src/otclient/item.cpp index c05ce3eb..80dbf045 100644 --- a/src/otclient/item.cpp +++ b/src/otclient/item.cpp @@ -268,10 +268,10 @@ void Item::unserializeItem(const BinaryTreePtr &in) } } -void Item::serializeItem(const FileStreamPtr& out) +void Item::serializeItem(const OutputBinaryTreePtr& out) { out->startNode(OTBM_ITEM); - out->addU16(getId()); + out->addU16(getServerId()); out->addU8(ATTR_COUNT); out->addU8(getCount()); diff --git a/src/otclient/item.h b/src/otclient/item.h index ffe99499..1f86e1eb 100644 --- a/src/otclient/item.h +++ b/src/otclient/item.h @@ -93,12 +93,13 @@ public: int getSubType(); int getCount(); uint32 getId() { return m_id; } + uint16 getServerId() { return m_otbId; } bool isValid(); ItemPtr clone(); void unserializeItem(const BinaryTreePtr& in); - void serializeItem(const FileStreamPtr& out); + void serializeItem(const OutputBinaryTreePtr& out); void setDepotId(uint16 depotId) { m_attribs.set(ATTR_DEPOT_ID, depotId); } uint16 getDepotId() { return m_attribs.get(ATTR_DEPOT_ID); } diff --git a/src/otclient/mapio.cpp b/src/otclient/mapio.cpp index 84a444ad..36f126fe 100644 --- a/src/otclient/mapio.cpp +++ b/src/otclient/mapio.cpp @@ -144,7 +144,8 @@ void Map::loadOtbm(const std::string& fileName) break; } default: { - stdext::throw_exception(stdext::format("invalid tile attribute %d at pos %s", (int)tileAttr, stdext::to_string(pos))); + stdext::throw_exception(stdext::format("invalid tile attribute %d at pos %s", + (int)tileAttr, stdext::to_string(pos))); } } } @@ -266,114 +267,125 @@ void Map::saveOtbm(const std::string &fileName) #endif fin->addU32(0); // file version - fin->startNode(0); + OutputBinaryTreePtr root(new OutputBinaryTree(fin)); { - fin->addU32(version); + root->addU32(version); Size mapSize = getSize(); - fin->addU16(mapSize.width()); - fin->addU16(mapSize.height()); + root->addU16(mapSize.width()); + root->addU16(mapSize.height()); - fin->addU32(g_things.getOtbMajorVersion()); - fin->addU32(g_things.getOtbMinorVersion()); + root->addU32(g_things.getOtbMajorVersion()); + root->addU32(g_things.getOtbMinorVersion()); - fin->startNode(OTBM_MAP_DATA); + root->startNode(OTBM_MAP_DATA); { // own description. for(const auto& desc : getDescriptions()) { - fin->addU8(OTBM_ATTR_DESCRIPTION); - fin->addString(desc); + root->addU8(OTBM_ATTR_DESCRIPTION); + root->addString(desc); } // special one - fin->addU8(OTBM_ATTR_DESCRIPTION); - fin->addString(stdext::format("Saved with %s v%s", g_app.getName(), g_app.getVersion())); + root->addU8(OTBM_ATTR_DESCRIPTION); + root->addString(stdext::format("Saved with %s v%s", g_app.getName(), g_app.getVersion())); // spawn file. - fin->addU8(OTBM_ATTR_SPAWN_FILE); - fin->addString(spawnFile); + root->addU8(OTBM_ATTR_SPAWN_FILE); + root->addString(spawnFile); // house file. if(version > 1) { - fin->addU8(OTBM_ATTR_HOUSE_FILE); - fin->addString(houseFile); + root->addU8(OTBM_ATTR_HOUSE_FILE); + root->addString(houseFile); } - Position base(0, 0, 0); + int px = -1, py = -1, pz =-1; bool firstNode = true; for(uint8_t z = 0; z <= Otc::MAX_Z; ++z) { for(const auto& it : m_tileBlocks[z]) { const TileBlock& block = it.second; for(const TilePtr& tile : block.getTiles()) { - if(!tile) + if(!tile || tile->isEmpty()) continue; const Position& pos = tile->getPosition(); if(!pos.isValid()) continue; - if(pos.x < base.x || pos.x >= base.x + 255 - || pos.y < base.y || pos.y >= base.y + 255 - || pos.z != base.z) { + if(pos.x < px || pos.x >= px + 256 + || pos.y < py || pos.y >= py + 256 + || pos.z != pz) { if(!firstNode) - fin->endNode(); /// OTBM_TILE_AREA + root->endNode(); /// OTBM_TILE_AREA - fin->startNode(OTBM_TILE_AREA); firstNode = false; - fin->addPos(base = pos & 0xFF00); - } + root->startNode(OTBM_TILE_AREA); - uint32 flags = tile->getFlags(); + px = pos.x & 0xFF00; + py = pos.y & 0xFF00; + pz = pos.z; + root->addPos(Position(px, py, pz)); + } - fin->startNode((flags & TILESTATE_HOUSE) == TILESTATE_HOUSE ? OTBM_HOUSETILE : OTBM_TILE); - fin->addPoint(Point(pos.x, pos.y) & 0xFF); - if((flags & TILESTATE_HOUSE) == TILESTATE_HOUSE) - fin->addU32(tile->getHouseId()); + root->startNode(tile->isHouseTile() ? OTBM_HOUSETILE : OTBM_TILE); + root->addPoint(Point(pos.x, pos.y) & 0xFF); + if(tile->isHouseTile()) + root->addU32(tile->getHouseId()); - if(flags) { - fin->addU8(OTBM_ATTR_TILE_FLAGS); - fin->addU32(flags); + if(tile->getFlags()) { + root->addU8(OTBM_ATTR_TILE_FLAGS); + root->addU32(tile->getFlags()); } - for(const ItemPtr& item : tile->getItems()) { - if(item->isGround()) { - fin->addU8(OTBM_ATTR_ITEM); - fin->addU16(item->getId()); - continue; - } - - item->serializeItem(fin); + const auto& itemList = tile->getItems(); + const ItemPtr& ground = tile->getGround(); + if(ground) { + // Those types are called "complex" needs other stuff to be written. + // For containers, there is container items, for depot, depot it and so on. + if(!ground->isContainer() && !ground->isDepot() + && !ground->isDoor() && !ground->isTeleport()) { + root->addU8(OTBM_ATTR_ITEM); + root->addU16(ground->getServerId()); + } else + ground->serializeItem(root); } + for(const ItemPtr& item : itemList) + if(!item->isGround()) + item->serializeItem(root); - fin->endNode(); // OTBM_TILE + root->endNode(); // OTBM_TILE } } } if(!firstNode) - fin->endNode(); // OTBM_TILE_AREA + root->endNode(); // OTBM_TILE_AREA - fin->startNode(OTBM_TOWNS); + root->startNode(OTBM_TOWNS); for(const TownPtr& town : m_towns.getTowns()) { - fin->addU32(town->getId()); - fin->addString(town->getName()); - fin->addPos(town->getPos()); + root->addU32(town->getId()); + root->addString(town->getName()); + root->addPos(town->getPos()); } - fin->endNode(); + root->endNode(); if(version > 1) { - fin->startNode(OTBM_WAYPOINTS); + root->startNode(OTBM_WAYPOINTS); for(const auto& it : m_waypoints) { - fin->addString(it.second); - fin->addPos(it.first); + root->addString(it.second); + root->addPos(it.first); } - fin->endNode(); + root->endNode(); } } - fin->endNode(); // OTBM_MAP_DATA + root->endNode(); // OTBM_MAP_DATA } - fin->endNode(); // 0 (root) + root->endNode(); + + fin->flush(); + fin->close(); } void Map::loadSpawns(const std::string &fileName) diff --git a/src/otclient/position.h b/src/otclient/position.h index 4d140829..3c87e556 100644 --- a/src/otclient/position.h +++ b/src/otclient/position.h @@ -165,7 +165,6 @@ public: Position& operator-=(const Position& other) { x-=other.x; y-=other.y; z-=other.z; return *this; } // Point conversion(s) Position operator+(const Point& other) const { return Position(x + other.x, y + other.y, z); } - Position operator&(int a) const { return Position(x & a, y & a, z); } Position& operator+=(const Point& other) { x += other.x; y += other.y; return *this; } Position& operator=(const Position& other) { x = other.x; y = other.y; z = other.z; return *this; } diff --git a/src/otclient/tile.h b/src/otclient/tile.h index 9927b2be..51c9f227 100644 --- a/src/otclient/tile.h +++ b/src/otclient/tile.h @@ -111,6 +111,7 @@ public: void setHouseId(uint32 hid) { m_houseId = hid; } uint32 getHouseId() { return m_houseId; } + bool isHouseTile() const { return (m_flags & TILESTATE_HOUSE) == TILESTATE_HOUSE; } TilePtr asTile() { return static_self_cast(); }