backing up at OTBM loading, if someone can continue working on it until I'm available again, I would appreciate it much, here is current progress: http://pastebin.com/qEfC9ftv

This commit is contained in:
otfallen 2012-07-09 08:46:11 +02:00
parent 1e8491cdcd
commit 42971b10f8
6 changed files with 187 additions and 73 deletions

View File

@ -93,3 +93,14 @@ uint64 BinaryTree::getU64()
m_pos += 8; m_pos += 8;
return v; 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;
}

View File

@ -254,7 +254,7 @@ BinaryTreePtr FileStream::getBinaryTree()
if(byte == BINARYTREE_NODE_START) if(byte == BINARYTREE_NODE_START)
root->unserialize(asFileStream()); root->unserialize(asFileStream());
else 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; return root;
} }

View File

@ -31,6 +31,7 @@
#include <framework/core/eventdispatcher.h> #include <framework/core/eventdispatcher.h>
#include <framework/graphics/graphics.h> #include <framework/graphics/graphics.h>
#include <framework/core/filestream.h> #include <framework/core/filestream.h>
#include <framework/core/binarytree.h>
Item::Item() : Item::Item() :
m_id(0), m_id(0),
@ -203,7 +204,7 @@ bool Item::isValid()
return g_things.isValidDatId(m_id, DatItemCategory); return g_things.isValidDatId(m_id, DatItemCategory);
} }
bool Item::unserializeAttr(FileStreamPtr fin) bool Item::unserializeAttr(const BinaryTreePtr &fin)
{ {
uint8 attrType; uint8 attrType;
while ((attrType = fin->getU8()) != 0) while ((attrType = fin->getU8()) != 0)
@ -212,7 +213,7 @@ bool Item::unserializeAttr(FileStreamPtr fin)
return true; return true;
} }
void Item::readAttr(AttrTypes_t attrType, FileStreamPtr fin) void Item::readAttr(AttrTypes_t attrType, const BinaryTreePtr &fin)
{ {
switch (attrType) { switch (attrType) {
case ATTR_COUNT: case ATTR_COUNT:
@ -269,3 +270,13 @@ void Item::readAttr(AttrTypes_t attrType, FileStreamPtr fin)
break; 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;
}

View File

@ -101,9 +101,10 @@ public:
bool isItem() { return true; } bool isItem() { return true; }
// TODO: These should be abstract and declared in i.e containers, doors, etc. // TODO: These should be abstract and declared in i.e containers, doors, etc.
bool unserializeAttr(FileStreamPtr fin); bool unserializeAttr(const BinaryTreePtr &fin);
bool unserializeItemNode(FileStreamPtr fin, uint8) { return unserializeAttr(fin); } bool unserializeItemNode(const BinaryTreePtr &fin) { return unserializeAttr(fin); }
void readAttr(AttrTypes_t attrType, FileStreamPtr fin); void readAttr(AttrTypes_t attrType, const BinaryTreePtr &fin);
bool isMoveable();
private: private:
uint16 m_id; uint16 m_id;

View File

@ -32,6 +32,7 @@
#include "mapview.h" #include "mapview.h"
#include <framework/core/resourcemanager.h> #include <framework/core/resourcemanager.h>
#include <framework/core/filestream.h> #include <framework/core/filestream.h>
#include <framework/core/binarytree.h>
Map g_map; Map g_map;
@ -60,29 +61,31 @@ void Map::notificateTileUpdateToMapViews(const Position& pos)
bool Map::loadOtbm(const std::string& fileName) bool Map::loadOtbm(const std::string& fileName)
{ {
#if 0
FileStreamPtr fin = g_resources.openFile(fileName); FileStreamPtr fin = g_resources.openFile(fileName);
if (!fin) { if (!fin) {
g_logger.error(stdext::format("Unable to load map '%s'", fileName)); g_logger.error(stdext::format("Unable to load map '%s'", fileName));
return false; 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."); g_logger.error("OTB and XML are not loaded yet to load a map.");
return false; return false;
} }
uint32 type = 0; assert(fin->getU32() == 0);
uint8 root = 0; BinaryTreePtr root = fin->getBinaryTree();
root = fin->readNode(root, type); root->skip(1); // Not sure, what exactly that is... perhaps node type?
uint32 headerVersion = root->getU32();
uint32 headerVersion = fin->getU32(); dump << headerVersion;
if (!headerVersion || headerVersion > 3) { if (!headerVersion || headerVersion > 3) {
g_logger.error("Unknown OTBM version detected."); g_logger.error("Unknown OTBM version detected.");
return false; return false;
} }
uint32 headerMajorItems = fin->getU32(); root->skip(1); // ??
uint32 headerMajorItems = root->getU8();
dump << headerMajorItems;
dump << "major: " << g_things.getOtbMajorVersion();
if (headerMajorItems < 3) { if (headerMajorItems < 3) {
g_logger.error("This map needs to be upgraded."); g_logger.error("This map needs to be upgraded.");
return false; return false;
@ -93,20 +96,24 @@ bool Map::loadOtbm(const std::string& fileName)
return false; 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()) if (headerMinorItems > g_things.getOtbMinorVersion())
g_logger.warning("This map needs an updated OTB."); g_logger.warning("This map needs an updated OTB.");
uint8 node = fin->readNode(root, type); BinaryTreePtr node = root->getChildren()[0];
if (type != OTBM_MAP_DATA) { if (node->getU8() != OTBM_MAP_DATA) {
g_logger.error("Could not read data node."); g_logger.error("Could not read data node.");
return false; return false;
} }
std::string tmp; std::string tmp;
uint8 attribute; uint8 attribute;
while ((attribute = fin->getU8())) { while (node->canRead()) {
tmp = fin->getString(); attribute = node->getU8();
tmp = node->getString();
switch (attribute) { switch (attribute) {
case OTBM_ATTR_DESCRIPTION: case OTBM_ATTR_DESCRIPTION:
if (!m_description.empty()) if (!m_description.empty())
@ -127,40 +134,41 @@ bool Map::loadOtbm(const std::string& fileName)
} }
dump << m_description; dump << m_description;
dump << m_houseFile;
dump << m_spawnFile;
uint8 nodeMapData; for (const BinaryTreePtr &nodeMapData : node->getChildren()) {
do { uint8 mapDataType = nodeMapData->getU8();
nodeMapData = fin->readNode(node, type); dump << "mapData: " << (int)mapDataType;
if (mapDataType == OTBM_TILE_AREA) {
if (type == OTBM_TILE_AREA) { dump << "Tile: reading pos...";
uint16 baseX = fin->getU16(), baseY = fin->getU16(); uint16 baseX = nodeMapData->getU16(), baseY = nodeMapData->getU16();
uint8 pz = fin->getU8(); uint8 pz = nodeMapData->getU8();
uint8 nodeTile;
do {
nodeTile = fin->readNode(nodeMapData, type);
for (const BinaryTreePtr &nodeTile : nodeMapData->getChildren()) {
uint8 type = nodeTile->getU8();
if (type == OTBM_TILE || type == OTBM_HOUSETILE) { if (type == OTBM_TILE || type == OTBM_HOUSETILE) {
TilePtr tile = 0; TilePtr tile = 0;
ItemPtr ground = 0; ItemPtr ground = 0;
uint32 flags = 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); Position pos(px, py, pz);
// TODO: Houses. // TODO: Houses.
if (type == OTBM_HOUSETILE) { if (type == OTBM_HOUSETILE) {
uint32 hId = fin->getU32(); uint32 hId = nodeTile->getU32();
tile = createTile(pos); tile = createTile(pos);
// TODO: add it to house. // TODO: add it to house.
} }
uint8 tileAttr; uint8 tileAttr;
while ((tileAttr = fin->getU8())) { while (nodeTile->canRead()) {
tileAttr = nodeTile->getU8();
switch (tileAttr) { switch (tileAttr) {
case OTBM_ATTR_TILE_FLAGS: { case OTBM_ATTR_TILE_FLAGS: {
uint32 _flags = fin->getU32(); uint32 _flags = nodeTile->getU32();
if ((_flags & TILESTATE_PROTECTIONZONE) == TILESTATE_PROTECTIONZONE) if ((_flags & TILESTATE_PROTECTIONZONE) == TILESTATE_PROTECTIONZONE)
flags |= TILESTATE_PROTECTIONZONE; flags |= TILESTATE_PROTECTIONZONE;
@ -176,7 +184,7 @@ bool Map::loadOtbm(const std::string& fileName)
flags |= TILESTATE_REFRESH; flags |= TILESTATE_REFRESH;
break; break;
} case OTBM_ATTR_ITEM: { } case OTBM_ATTR_ITEM: {
ItemPtr item = Item::createFromOtb(fin->getU16()); ItemPtr item = Item::createFromOtb(nodeTile->getU16());
if (!item) { if (!item) {
g_logger.error(stdext::format("failed to create new item at tile pos %d, %d, %d", px, py, pz)); g_logger.error(stdext::format("failed to create new item at tile pos %d, %d, %d", px, py, pz));
return false; return false;
@ -198,22 +206,19 @@ bool Map::loadOtbm(const std::string& fileName)
} }
} }
uint8 nodeItem; for (const BinaryTreePtr &nodeItem : nodeTile->getChildren()) {
do { if (nodeItem->getU8() == OTBM_ITEM) {
nodeItem = fin->readNode(nodeTile, type); ItemPtr item = Item::createFromOtb(nodeItem->getU16());
if (type == OTBM_ITEM) {
ItemPtr item = Item::createFromOtb(fin->getU16());
if (!item) { if (!item) {
g_logger.error(stdext::format("failed to create new item at pos %d, %d, %d", px, py, pz)); g_logger.error(stdext::format("failed to create new item at pos %d, %d, %d", px, py, pz));
return false; return false;
} }
if (item->unserializeItemNode(fin, nodeItem)) { if (item->unserializeItemNode(nodeItem)) {
if (/* house && */item->isMoveable()) { if (/* house && */item->isMoveable()) {
g_logger.warning(stdext::format("Moveable item found in house: %d at pos %d %d %d", item->getId(), g_logger.warning(stdext::format("Moveable item found in house: %d at pos %d %d %d", item->getId(),
px, py, pz)); px, py, pz));
item = 0; item = nullptr;
} else if (tile) { } else if (tile) {
tile->addThing(item); tile->addThing(item);
} else if (item->isGround()) { } 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)); g_logger.error(stdext::format("Unknown item node type %d", type));
return false; return false;
} }
} while (nodeItem); }
if (!tile) { if (!tile) {
tile = createTile(pos); 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)); g_logger.error(stdext::format("Unknown tile node type %d", type));
return false; return false;
} }
} while (nodeTile); }
} else if (type == OTBM_TOWNS) { } else if (mapDataType == OTBM_TOWNS) {
uint8 nodeTown; for (const BinaryTreePtr &nodeTown : nodeMapData->getChildren()) {
do { if (nodeTown->getU8() == OTBM_TOWN) {
nodeTown = fin->readNode(nodeMapData, type); uint32 townId = nodeTown->getU32();
std::string townName = nodeTown->getString();
if (type == OTBM_TOWN) { Position townCoords(nodeTown->getU16(), nodeTown->getU16(), nodeTown->getU8());
uint32 townId = fin->getU32(); } else
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));
return false; return false;
} }
} while (nodeTown); } else if (mapDataType == OTBM_WAYPOINTS && headerVersion > 1) {
} else if (type == OTBM_WAYPOINTS && headerVersion > 1) { for (const BinaryTreePtr &nodeWaypoint : nodeMapData->getChildren()) {
uint8 nodeWaypoint; if (nodeWaypoint->getU8() == OTBM_WAYPOINT) {
do { std::string name = nodeWaypoint->getString();
nodeWaypoint = fin->readNode(nodeMapData, type); Position waypointPos(nodeWaypoint->getU16(), nodeWaypoint->getU16(), nodeWaypoint->getU8());
if (type == OTBM_WAYPOINT) {
std::string name = fin->getString();
Position waypointPos(fin->getU16(), fin->getU16(), fin->getU8());
} }
} while (nodeWaypoint); }
} else { } else
g_logger.error(stdext::format("Unknown map node %d", type));
return false; return false;
} }
} while (nodeMapData);
// TODO: Load house & spawns. // TODO: Load house & spawns.
return true; return true;
#endif
return false;
} }
bool Map::loadOtcm(const std::string& fileName) bool Map::loadOtcm(const std::string& fileName)

View File

@ -0,0 +1,98 @@
/*
* Copyright (c) 2010-2012 OTClient <https://github.com/edubart/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 <framework/otml/otml.h>
#include <framework/graphics/graphics.h>
#include <framework/graphics/fontmanager.h>
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<float>());
}
}