From 5abf8622e59bdaf2ea3407b42fdb4a59d5c067e3 Mon Sep 17 00:00:00 2001 From: niczkx Date: Sun, 5 Aug 2012 05:26:27 -0600 Subject: [PATCH] rewrite some parts of otbm saving and uncomment it for testing later --- src/framework/core/binarytree.cpp | 81 +++++--------------- src/framework/core/binarytree.h | 35 ++++++--- src/framework/core/declarations.h | 2 + src/framework/core/filestream.cpp | 7 -- src/framework/core/filestream.h | 1 - src/otclient/item.cpp | 5 +- src/otclient/item.h | 2 +- src/otclient/map.h | 2 + src/otclient/mapio.cpp | 121 ++++++++++++++---------------- 9 files changed, 106 insertions(+), 150 deletions(-) diff --git a/src/framework/core/binarytree.cpp b/src/framework/core/binarytree.cpp index 730142f5..c5d601cb 100644 --- a/src/framework/core/binarytree.cpp +++ b/src/framework/core/binarytree.cpp @@ -151,15 +151,12 @@ uint64 BinaryTree::getU64() return v; } -std::string BinaryTree::getString() -{ - uint16 len = getU16(); - return getString(len); -} - std::string BinaryTree::getString(uint16 len) { unserialize(); + if(len == 0) + len = getU16(); + if(m_pos+len > m_buffer.size()) stdext::throw_exception("BinaryTree: getString failed: string length exceeded buffer size."); @@ -185,73 +182,31 @@ Point BinaryTree::getPoint() return ret; } -BinaryTreePtr BinaryTree::makeChild(uint8 type) -{ - BinaryTreePtr child(new BinaryTree(m_fin)); - child->setType(type); - //children.append(child); - return child; -} - -void BinaryTree::setType(uint8 type) -{ - writeU8(0xFE); - writeU8(type); -} - -void BinaryTree::writeU8(uint8 u8) +/// BinaryWriteTree +BinaryWriteTree::BinaryWriteTree(const FileStreamPtr& fin) : + m_fin(fin) { - m_buffer.add(u8); } -void BinaryTree::writeU16(uint16 u16) +BinaryWriteTree::~BinaryWriteTree() { - stdext::writeLE16(m_buffer.data(), u16); + m_fin->close(); + m_fin = nullptr; } -void BinaryTree::writeU32(uint32 u32) +void BinaryWriteTree::startNode(uint8 type) { - stdext::writeLE32(m_buffer.data(), u32); -} - -void BinaryTree::writeString(const std::string& s) -{ - size_t len = s.length(); - writeU16(len); - m_buffer.grow(m_pos + len); - memcpy(&m_buffer[m_pos], s.c_str(), len); - m_pos += len; -} - -void BinaryTree::writePos(const Position& p) -{ - if(!p.isValid()) - stdext::throw_exception("invalid position passed to BinaryTree::writePos"); - - writeU16(p.x); - writeU16(p.y); - writeU8(p.z); + writeU8(BINARYTREE_NODE_START); + writeU8(type); } -void BinaryTree::writePoint(const Point& p) +void BinaryWriteTree::endNode() { - if(p.isNull()) - stdext::throw_exception("invalid point passed to BinaryTree::writePoint"); - - writeU8(p.x); - writeU8(p.y); + writeU8(BINARYTREE_NODE_END); } -void BinaryTree::writeToFile() -{ - if(!m_fin) - stdext::throw_exception("attempt to write binary node to closed file"); +void BinaryWriteTree::writeU8(uint8 u8) { m_fin->addU8(u8); } +void BinaryWriteTree::writeU16(uint16 u16) { m_fin->addU16(u16); } +void BinaryWriteTree::writeU32(uint32 u32) { m_fin->addU32(u32); } +void BinaryWriteTree::writeString(const std::string& str) { m_fin->addString(str); } - /// first write self data - m_fin->write(&m_buffer[0], m_buffer.size()); -#if 0 - /// write children data - for(const BinaryTreePtr& child : m_children) - child->writeToFile(); -#endif -} diff --git a/src/framework/core/binarytree.h b/src/framework/core/binarytree.h index 423df6aa..670da174 100644 --- a/src/framework/core/binarytree.h +++ b/src/framework/core/binarytree.h @@ -26,6 +26,7 @@ #include "declarations.h" #include #include +#include enum { BINARYTREE_ESCAPE_CHAR = 0xFD, @@ -48,21 +49,10 @@ public: uint16 getU16(); uint32 getU32(); uint64 getU64(); - std::string getString(); - std::string getString(uint16 len); + std::string getString(uint16 len = 0); Position getPosition(); Point getPoint(); - void setType(uint8 type); - void writeU8(uint8 u8); - void writeU16(uint16 u16); - void writeU32(uint32 u32); - void writeString(const std::string& s); - void writePos(const Position& p); - void writePoint(const Point& p); - BinaryTreePtr makeChild(uint8 type); - void writeToFile(); - BinaryTreeVec getChildren(); bool canRead() { unserialize(); return m_pos < m_buffer.size(); } @@ -76,4 +66,25 @@ private: uint m_startPos; }; +class BinaryWriteTree : public stdext::shared_object +{ +public: + BinaryWriteTree(const FileStreamPtr& fin); + ~BinaryWriteTree(); + + void startNode(uint8 type); + void endNode(); + + void writeU8(uint8 u8); + void writeU16(uint16 u16); + void writeU32(uint32 u32); + void writeString(const std::string& str); + + void writePoint(const Point& p) { writeU8(p.x); writeU8(p.y); } + void writePos(const Position& p) { writeU16(p.x); writeU16(p.y); writeU8(p.z); } + +private: + FileStreamPtr m_fin; +}; + #endif diff --git a/src/framework/core/declarations.h b/src/framework/core/declarations.h index e6c90614..c08699a7 100644 --- a/src/framework/core/declarations.h +++ b/src/framework/core/declarations.h @@ -32,12 +32,14 @@ class Event; class ScheduledEvent; class FileStream; class BinaryTree; +class BinaryWriteTree; 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 std::vector BinaryTreeVec; diff --git a/src/framework/core/filestream.cpp b/src/framework/core/filestream.cpp index 04e21207..307aca47 100644 --- a/src/framework/core/filestream.cpp +++ b/src/framework/core/filestream.cpp @@ -267,13 +267,6 @@ BinaryTreePtr FileStream::getBinaryTree() return BinaryTreePtr(new BinaryTree(asFileStream())); } -BinaryTreePtr FileStream::makeTree() -{ - BinaryTreePtr root(new BinaryTree(asFileStream())); - root->setType(0); - return root; -} - void FileStream::addU8(uint8 v) { if(!m_caching) { diff --git a/src/framework/core/filestream.h b/src/framework/core/filestream.h index b03f8c18..d7adfd2c 100644 --- a/src/framework/core/filestream.h +++ b/src/framework/core/filestream.h @@ -60,7 +60,6 @@ public: void addU32(uint32 v); void addU64(uint64 v); void addString(const std::string& v); - BinaryTreePtr makeTree(); FileStreamPtr asFileStream() { return static_self_cast(); } diff --git a/src/otclient/item.cpp b/src/otclient/item.cpp index 03122998..71f5016a 100644 --- a/src/otclient/item.cpp +++ b/src/otclient/item.cpp @@ -268,7 +268,7 @@ void Item::unserializeItem(const BinaryTreePtr &in) } } -void Item::serializeItem(const BinaryTreePtr& out) +void Item::serializeItem(const BinaryWriteTreePtr& out) { out->writeU8(ATTR_COUNT); out->writeU8(getCount()); @@ -287,7 +287,8 @@ void Item::serializeItem(const BinaryTreePtr& out) out->writeU16(getDepotId()); } - uint16 aid = m_attribs.get(ATTR_ACTION_ID), uid = m_attribs.get(ATTR_UNIQUE_ID); + uint16 aid = m_attribs.get(ATTR_ACTION_ID); + uint16 uid = m_attribs.get(ATTR_UNIQUE_ID); if(aid) { out->writeU8(ATTR_ACTION_ID); out->writeU16(aid); diff --git a/src/otclient/item.h b/src/otclient/item.h index 29f7a7c9..3937a915 100644 --- a/src/otclient/item.h +++ b/src/otclient/item.h @@ -98,7 +98,7 @@ public: ItemPtr clone(); void unserializeItem(const BinaryTreePtr& in); - void serializeItem(const BinaryTreePtr& out); + void serializeItem(const BinaryWriteTreePtr& 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/map.h b/src/otclient/map.h index ecbb7cb8..11f7823c 100644 --- a/src/otclient/map.h +++ b/src/otclient/map.h @@ -163,6 +163,8 @@ public: uint getTileIndex(const Position& pos) { return ((pos.y % BLOCK_SIZE) * BLOCK_SIZE) + (pos.x % BLOCK_SIZE); } + const std::array getTiles() const { return m_tiles; } + private: std::array m_tiles; }; diff --git a/src/otclient/mapio.cpp b/src/otclient/mapio.cpp index cb11d507..c110135d 100644 --- a/src/otclient/mapio.cpp +++ b/src/otclient/mapio.cpp @@ -23,6 +23,8 @@ #include "map.h" #include "tile.h" + +#include #include #include #include @@ -215,8 +217,6 @@ void Map::loadOtbm(const std::string& fileName) void Map::saveOtbm(const std::string &fileName) { -#if 0 - /// FIXME: Untested code FileStreamPtr fin = g_resources.appendFile(fileName); if(!fin) stdext::throw_exception(stdext::format("failed to open file '%s' for write", fileName)); @@ -237,7 +237,8 @@ void Map::saveOtbm(const std::string &fileName) /// Usually when a map has empty house/spawn file it means the map is new. /// TODO: Ask the user for a map name instead of those ugly uses of substr - std::string houseFile = getHouseFile(), spawnFile = getSpawnFile(); + std::string houseFile = getHouseFile(); + std::string spawnFile = getSpawnFile(); if(houseFile.empty() && version > 1) houseFile = fileName.substr(fileName.find_last_of('/')) + "-houses.xml"; if(spawnFile.empty()) @@ -250,9 +251,8 @@ void Map::saveOtbm(const std::string &fileName) saveSpawns(dir + "/" + spawnFile); #endif - time_t start = time(0); fin->addU32(0); // file version - BinaryTreePtr root = fin->makeTree(); + BinaryWriteTreePtr root(new BinaryWriteTree(fin)); { root->writeU32(version); @@ -263,93 +263,88 @@ void Map::saveOtbm(const std::string &fileName) root->writeU32(g_things.getOtbMajorVersion()); root->writeU32(g_things.getOtbMinorVersion()); - BinaryTreePtr mapData = root->makeChild(OTBM_MAP_DATA); + root->startNode(OTBM_MAP_DATA); { // own description. for(const auto& desc : getDescriptions()) { - mapData->writeU8(OTBM_ATTR_DESCRIPTION); - mapData->writeString(desc); + root->writeU8(OTBM_ATTR_DESCRIPTION); + root->writeString(desc); } // special one - mapData->writeU8(OTBM_ATTR_DESCRIPTION); - mapData->writeString(stdext::format("Saved with %s v%d", g_app.getName(), stdext::unsafe_cast(g_app.getVersion()))); + root->writeU8(OTBM_ATTR_DESCRIPTION); + root->writeString(stdext::format("Saved with %s v%d", g_app.getName(), stdext::unsafe_cast(g_app.getVersion()))); // spawn file. - mapData->writeU8(OTBM_ATTR_SPAWN_FILE); - mapData->writeString(spawnFile); + root->writeU8(OTBM_ATTR_SPAWN_FILE); + root->writeString(spawnFile); // house file. if(version > 1) { - mapData->writeU8(OTBM_ATTR_HOUSE_FILE); - mapData->writeString(houseFile); + root->writeU8(OTBM_ATTR_HOUSE_FILE); + root->writeString(houseFile); } /// write tiles first - BinaryTreePtr tileArea = mapData->makeChild(OTBM_TILE_AREA); + root->startNode(OTBM_TILE_AREA); Position base(-1, -1, -1); - for(const auto& pair : m_tiles) { - Position pos = pair.first; - TilePtr tile = pair.second; - - /// base position - if(pos.x < base.x || pos.x >= base.x + 256 || pos.y < base.y|| pos.y >= base.y + 256 || - pos.z != base.z) { - tileArea->writePos(base = pos & 0xFF00); - } - BinaryTreePtr tileNode(nullptr); - uint32 flags = tile->getFlags(); - if((flags & TILESTATE_HOUSE) == TILESTATE_HOUSE) - tileNode = tileArea->makeChild(OTBM_HOUSETILE); - else - tileNode = tileArea->makeChild(OTBM_TILE); - - tileNode->writePoint(Point(pos.x, pos.y)); -// if(tileNode->getType() == OTBM_HOUSETILE) -// tileNode->writeU32(tile->getHouseId()); - - /// Tile flags - if(flags != 0) { - tileNode->writeU8(OTBM_ATTR_TILE_FLAGS); - tileNode->writeU32(flags); - } + for(uint8_t z = 0; z < Otc::MAX_Z + 1; ++z) { + for(const auto& it : m_tileBlocks[z]) { + const TileBlock& block = it.second; + for(const TilePtr& tile : block.getTiles()) { + const Position& pos = tile->getPosition(); + if(!pos.isValid()) + continue; + + /// base position + if(pos.x < base.x || pos.x >= base.x + 256 || pos.y < base.y|| pos.y >= base.y + 256 || + pos.z != base.z) + root->writePos(base = pos & 0xFF00); + + uint32 flags = tile->getFlags(); + if((flags & TILESTATE_HOUSE) == TILESTATE_HOUSE) + root->startNode(OTBM_HOUSETILE); + else + root->startNode(OTBM_TILE); + + root->writePoint(Point(pos.x, pos.y)); +// if(tileNode->getType() == OTBM_HOUSETILE) +// tileNode->writeU32(tile->getHouseId()); + + /// Tile flags + if(flags) { + root->writeU8(OTBM_ATTR_TILE_FLAGS); + root->writeU32(flags); + } - /// start writing tile items - for(const ItemPtr& item : tile->getItems()) { - BinaryTreePtr itemNode = tileNode->makeChild(OTBM_ATTR_ITEM); - item->serializeItem(itemNode); + /// start writing tile items + for(const ItemPtr& item : tile->getItems()) { + root->startNode(OTBM_ATTR_ITEM); + item->serializeItem(root); + } + } } } /// write towns - BinaryTreePtr townNode = mapData->makeChild(OTBM_TOWNS); + root->startNode(OTBM_TOWNS); for(const TownPtr& town : m_towns.getTowns()) { - BinaryTreePtr newTown = townNode->makeChild(OTBM_TOWN); - { - newTown->writeU32(town->getId()); - newTown->writeString(town->getName()); - newTown->writePos(town->getPos()); - } + root->writeU32(town->getId()); + root->writeString(town->getName()); + root->writePos(town->getPos()); } /// write waypoints if(version > 1) { - BinaryTreePtr waypointNode = mapData->makeChild(OTBM_WAYPOINTS); + root->startNode(OTBM_WAYPOINTS); for(const auto& it : m_waypoints) { - BinaryTreePtr newWaypoint = waypointNode->makeChild(OTBM_WAYPOINT); - { - newWaypoint->writeString(it.second); - newWaypoint->writePos(it.first); - } + root->writeString(it.second); + root->writePos(it.first); } } } } - - root->writeToFile(); - g_logger.debug(stdext::format("OTBM saving took %ld", time(0) - start)); -#endif } void Map::loadSpawns(const std::string &fileName) @@ -391,8 +386,6 @@ void Map::loadSpawns(const std::string &fileName) addThing(creature, centerPos + cNode->readPoint()); } } - - doc.Clear(); } bool Map::loadOtcm(const std::string& fileName) @@ -539,4 +532,4 @@ void Map::saveOtcm(const std::string& fileName) g_logger.error(stdext::format("failed to save OTCM map: %s", e.what())); } #endif -} \ No newline at end of file +}