Fix OTBM saving
This commit is contained in:
		
							parent
							
								
									1c69379b8d
								
							
						
					
					
						commit
						0af783b5cf
					
				|  | @ -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;i<size;++i) { | ||||
|         if(data[i]==BINARYTREE_NODE_START || data[i]==BINARYTREE_NODE_END||data[i]==BINARYTREE_ESCAPE_CHAR) | ||||
|             m_fin->addU8(BINARYTREE_ESCAPE_CHAR); | ||||
|         m_fin->addU8(data[i]); | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -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 | ||||
| 
 | ||||
|  |  | |||
|  | @ -32,14 +32,14 @@ class Event; | |||
| class ScheduledEvent; | ||||
| class FileStream; | ||||
| class BinaryTree; | ||||
| class BinaryWriteTree; | ||||
| class OutputBinaryTree; | ||||
| 
 | ||||
| typedef stdext::shared_object_ptr<Module> ModulePtr; | ||||
| typedef stdext::shared_object_ptr<Event> EventPtr; | ||||
| typedef stdext::shared_object_ptr<ScheduledEvent> ScheduledEventPtr; | ||||
| typedef stdext::shared_object_ptr<FileStream> FileStreamPtr; | ||||
| typedef stdext::shared_object_ptr<BinaryTree> BinaryTreePtr; | ||||
| typedef stdext::shared_object_ptr<BinaryWriteTree> BinaryWriteTreePtr; | ||||
| typedef stdext::shared_object_ptr<OutputBinaryTree> OutputBinaryTreePtr; | ||||
| 
 | ||||
| typedef std::vector<BinaryTreePtr> BinaryTreeVec; | ||||
| 
 | ||||
|  |  | |||
|  | @ -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); | ||||
|  |  | |||
|  | @ -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()); | ||||
|  |  | |||
|  | @ -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<uint16>(ATTR_DEPOT_ID); } | ||||
|  |  | |||
|  | @ -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); | ||||
| 
 | ||||
|                             px = pos.x & 0xFF00; | ||||
|                             py = pos.y & 0xFF00; | ||||
|                             pz = pos.z; | ||||
|                             root->addPos(Position(px, py, pz)); | ||||
|                         } | ||||
| 
 | ||||
|                         uint32 flags = tile->getFlags(); | ||||
|                         root->startNode(tile->isHouseTile() ? OTBM_HOUSETILE : OTBM_TILE); | ||||
|                         root->addPoint(Point(pos.x, pos.y) & 0xFF); | ||||
|                         if(tile->isHouseTile()) | ||||
|                             root->addU32(tile->getHouseId()); | ||||
| 
 | ||||
|                         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()); | ||||
| 
 | ||||
|                         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) | ||||
|  |  | |||
|  | @ -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; } | ||||
|  |  | |||
|  | @ -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<Tile>(); } | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 niczkx
						niczkx