Add binary tree class for reading otb

This commit is contained in:
Eduardo Bart 2012-06-24 10:05:44 -03:00
parent dbf5e8266b
commit e65a8456e9
10 changed files with 209 additions and 37 deletions

View File

@ -46,3 +46,5 @@ g_modules.autoLoadModules(9999)
if g_resources.fileExists("/otclientrc.lua") then if g_resources.fileExists("/otclientrc.lua") then
dofile("/otclientrc.lua") dofile("/otclientrc.lua")
end end
g_things.loadOtb('/items.otb')

View File

@ -165,6 +165,8 @@ SET(framework_SOURCES ${framework_SOURCES}
# core # core
${CMAKE_CURRENT_LIST_DIR}/core/adaptativeframecounter.cpp ${CMAKE_CURRENT_LIST_DIR}/core/adaptativeframecounter.cpp
${CMAKE_CURRENT_LIST_DIR}/core/adaptativeframecounter.h ${CMAKE_CURRENT_LIST_DIR}/core/adaptativeframecounter.h
${CMAKE_CURRENT_LIST_DIR}/core/binarytree.cpp
${CMAKE_CURRENT_LIST_DIR}/core/binarytree.h
${CMAKE_CURRENT_LIST_DIR}/core/clock.cpp ${CMAKE_CURRENT_LIST_DIR}/core/clock.cpp
${CMAKE_CURRENT_LIST_DIR}/core/clock.h ${CMAKE_CURRENT_LIST_DIR}/core/clock.h
${CMAKE_CURRENT_LIST_DIR}/core/configmanager.cpp ${CMAKE_CURRENT_LIST_DIR}/core/configmanager.cpp

View File

@ -0,0 +1,92 @@
/*
* 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 "binarytree.h"
#include "filestream.h"
void BinaryTree::unserialize(const FileStreamPtr& fin)
{
m_type = fin->getU32();
while(true) {
uint8 byte = fin->getU8();
switch(byte) {
case BINARYTREE_NODE_START: {
BinaryTreePtr node(new BinaryTree(shared_from_this()));
m_children.push_back(node);
node->unserialize(fin);
break;
}
case BINARYTREE_NODE_END:
return;
case BINARYTREE_ESCAPE_CHAR:
m_buffer.add(fin->getU8());
break;
default:
m_buffer.add(byte);
break;
}
}
}
void BinaryTree::seek(uint pos)
{
if(pos > m_buffer.size())
stdext::throw_exception("BinaryTree: seek failed");
m_pos = pos;
}
uint8 BinaryTree::getU8()
{
if(m_pos+1 > m_buffer.size())
stdext::throw_exception("BinaryTree: getU8 failed");
uint8 v = m_buffer[m_pos];
m_pos += 1;
return v;
}
uint16 BinaryTree::getU16()
{
if(m_pos+2 > m_buffer.size())
stdext::throw_exception("BinaryTree: getU16 failed");
uint16 v = stdext::readLE16(&m_buffer[m_pos]);
m_pos += 2;
return v;
}
uint32 BinaryTree::getU32()
{
if(m_pos+4 > m_buffer.size())
stdext::throw_exception("BinaryTree: getU32 failed");
uint32 v = stdext::readLE32(&m_buffer[m_pos]);
m_pos += 4;
return v;
}
uint64 BinaryTree::getU64()
{
if(m_pos+8 > m_buffer.size())
stdext::throw_exception("BinaryTree: getu64 failed");
uint64 v = stdext::readLE64(&m_buffer[m_pos]);
m_pos += 8;
return v;
}

View File

@ -0,0 +1,68 @@
/*
* 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.
*/
#ifndef BINARYTREE_H
#define BINARYTREE_H
#include "declarations.h"
#include <framework/util/databuffer.h>
enum {
BINARYTREE_ESCAPE_CHAR = 0xFD,
BINARYTREE_NODE_START = 0xFE,
BINARYTREE_NODE_END = 0xFF
};
class BinaryTree : public std::enable_shared_from_this<BinaryTree>
{
public:
BinaryTree(const BinaryTreePtr& parent = nullptr) : m_type(0), m_pos(0), m_parent(parent) { }
void unserialize(const FileStreamPtr& fin);
void seek(uint pos);
void skip(uint len) { seek(tell() + len); }
uint tell() { return m_pos; }
uint size() { return m_buffer.size(); }
uint8 getU8();
uint16 getU16();
uint32 getU32();
uint64 getU64();
std::string getString();
BinaryTreeVec getChildren() { return m_children; }
BinaryTreePtr getParent() { return m_parent.lock(); }
uint32 getType() { return m_type; }
bool canRead() { return m_pos < m_buffer.size(); }
private:
void setParent(const BinaryTreePtr& parent) { m_parent = parent; }
uint m_type;
uint m_pos;
BinaryTreeVec m_children;
BinaryTreeWeakPtr m_parent;
DataBuffer<uint8> m_buffer;
};
#endif

View File

@ -31,10 +31,16 @@ class Module;
class Event; class Event;
class ScheduledEvent; class ScheduledEvent;
class FileStream; class FileStream;
class BinaryTree;
typedef std::shared_ptr<Module> ModulePtr; typedef std::shared_ptr<Module> ModulePtr;
typedef std::shared_ptr<Event> EventPtr; typedef std::shared_ptr<Event> EventPtr;
typedef std::shared_ptr<ScheduledEvent> ScheduledEventPtr; typedef std::shared_ptr<ScheduledEvent> ScheduledEventPtr;
typedef std::shared_ptr<FileStream> FileStreamPtr; typedef std::shared_ptr<FileStream> FileStreamPtr;
typedef std::shared_ptr<BinaryTree> BinaryTreePtr;
typedef std::weak_ptr<BinaryTree> BinaryTreeWeakPtr;
typedef std::vector<BinaryTreePtr> BinaryTreeVec;
#endif #endif

View File

@ -21,6 +21,7 @@
*/ */
#include "filestream.h" #include "filestream.h"
#include "binarytree.h"
#include <framework/application.h> #include <framework/application.h>
#include <physfs.h> #include <physfs.h>
@ -246,6 +247,17 @@ std::string FileStream::getString()
return str; return str;
} }
BinaryTreePtr FileStream::getBinaryTree()
{
BinaryTreePtr root = BinaryTreePtr(new BinaryTree);
uint8 byte = getU8();
if(byte == BINARYTREE_NODE_START)
root->unserialize(asFileStream());
else
stdext::throw_exception(stdext::format("failed to read node start (getFirstNode): %d", byte));
return root;
}
void FileStream::addU8(uint8 v) void FileStream::addU8(uint8 v)
{ {
if(!m_caching) { if(!m_caching) {

View File

@ -52,6 +52,7 @@ public:
uint32 getU32(); uint32 getU32();
uint64 getU64(); uint64 getU64();
std::string getString(); std::string getString();
BinaryTreePtr getBinaryTree();
void addU8(uint8 v); void addU8(uint8 v);
void addU16(uint16 v); void addU16(uint16 v);
@ -59,6 +60,8 @@ public:
void addU64(uint64 v); void addU64(uint64 v);
void addString(const std::string& v); void addString(const std::string& v);
FileStreamPtr asFileStream() { return std::static_pointer_cast<FileStream>(shared_from_this()); }
private: private:
void checkWrite(); void checkWrite();
void throwError(const std::string& message, bool physfsError = false); void throwError(const std::string& message, bool physfsError = false);

View File

@ -28,6 +28,7 @@
#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>
#define TIXML_USE_STL // use STL strings instead. #define TIXML_USE_STL // use STL strings instead.
#include <framework/thirdparty/tinyxml.h> #include <framework/thirdparty/tinyxml.h>
@ -94,29 +95,27 @@ bool ThingTypeManager::loadDat(const std::string& file)
bool ThingTypeManager::loadOtb(const std::string& file) bool ThingTypeManager::loadOtb(const std::string& file)
{ {
/*
try { try {
FileStreamPtr fin = g_resources.openFile(file); FileStreamPtr fin = g_resources.openFile(file);
if (!fin) if (!fin)
stdext::throw_exception("unable to open file"); stdext::throw_exception("unable to open file");
m_otbVersion = fin->getU32(); m_otbVersion = fin->getU32();
if (m_otbVersion != 0x00)
stdext::throw_exception("invalid file version");
uint32 type = 0; BinaryTreePtr root = fin->getBinaryTree();
uint8 node = 0;
fin->readNode(node, type);
fin->getU32(); // flags root->getU32(); // flags
m_otbMajorVersion = fin->getU32(); m_otbMajorVersion = root->getU32();
m_otbMinorVersion = fin->getU32(); m_otbMinorVersion = root->getU32();
fin->getU32(); // build number root->getU32(); // build number
fin->skip(128); root->skip(128); // description
while(fin->readNode(node, type)) { for(const BinaryTreePtr& node : root->getChildren()) {
ThingTypeOtbPtr otbType(new ThingTypeOtb); ThingTypeOtbPtr otbType(new ThingTypeOtb);
otbType->unserialize(fin); otbType->unserialize(node);
addOtbType(otbType);
} }
m_otbLoaded = true; m_otbLoaded = true;
@ -125,8 +124,6 @@ bool ThingTypeManager::loadOtb(const std::string& file)
g_logger.error(stdext::format("failed to load otb '%s': %s", file, e.what())); g_logger.error(stdext::format("failed to load otb '%s': %s", file, e.what()));
return false; return false;
} }
*/
return false;
} }
bool ThingTypeManager::loadXml(const std::string& file) bool ThingTypeManager::loadXml(const std::string& file)

View File

@ -24,6 +24,7 @@
#include "thingtypeotb.h" #include "thingtypeotb.h"
#include <framework/core/filestream.h> #include <framework/core/filestream.h>
#include <framework/core/binarytree.h>
ThingTypeOtb::ThingTypeOtb() ThingTypeOtb::ThingTypeOtb()
{ {
@ -32,45 +33,34 @@ ThingTypeOtb::ThingTypeOtb()
m_clientId = 0; m_clientId = 0;
} }
void ThingTypeOtb::unserialize(const FileStreamPtr& fin) void ThingTypeOtb::unserialize(const BinaryTreePtr& node)
{ {
m_null = false; m_null = false;
uint8 zero = fin->getU8(); uint8 zero = node->getU8();
assert(zero == 0); assert(zero == 0);
m_category = (OtbCategory)fin->getU8(); m_category = (OtbCategory)node->getU8();
fin->getU32(); // skip flags node->getU32(); // skip flags
bool done = false; while(node->canRead()) {
for(int i=0;i<OtbLastAttrib; ++i) { uint8 attr = node->getU8();
int attr = fin->getU8(); if(attr == 0 || attr == 0xFF)
if(attr == 0) {
done = true;
break; break;
} else if(attr == 0xFF) {
fin->seek(fin->tell() - 1);
done = true;
break;
}
int len = fin->getU16();
uint16 len = node->getU16();
switch(attr) { switch(attr) {
case OtbAttribServerId: case OtbAttribServerId:
m_serverId = fin->getU16(); m_serverId = node->getU16();
assert(len == 2); assert(len == 2);
break; break;
case OtbAttribClientId: case OtbAttribClientId:
m_clientId = fin->getU16(); m_clientId = node->getU16();
assert(len == 2); assert(len == 2);
break; break;
default: default:
fin->skip(len); // skip attribute node->skip(len); // skip attribute
break; break;
} }
} }
if(!done)
stdext::throw_exception("failed to unserialize otb type, corrupt otb?");
} }

View File

@ -84,7 +84,7 @@ class ThingTypeOtb : public LuaObject
public: public:
ThingTypeOtb(); ThingTypeOtb();
void unserialize(const FileStreamPtr& fin); void unserialize(const BinaryTreePtr& node);
void unserializeXML(); void unserializeXML();
uint16 getServerId() { return m_serverId; } uint16 getServerId() { return m_serverId; }