Optimize overall memory usage

* Fixes in otbm loader
* Rework BinaryTree
This commit is contained in:
Eduardo Bart 2012-07-15 10:23:13 -03:00
parent 03ca792dbd
commit 7a08fed689
25 changed files with 376 additions and 186 deletions

View File

@ -33,6 +33,7 @@ set(framework_SOURCES ${framework_SOURCES}
${CMAKE_CURRENT_LIST_DIR}/util/rsa.cpp
${CMAKE_CURRENT_LIST_DIR}/util/rsa.h
${CMAKE_CURRENT_LIST_DIR}/util/size.h
${CMAKE_CURRENT_LIST_DIR}/util/attribstorage.h
# stdext
${CMAKE_CURRENT_LIST_DIR}/stdext/cast.h

View File

@ -23,21 +23,54 @@
#include "binarytree.h"
#include "filestream.h"
void BinaryTree::unserialize(const FileStreamPtr& fin)
BinaryTree::BinaryTree(const FileStreamPtr& fin) :
m_fin(fin), m_pos(0xFFFFFFFF)
{
m_startPos = fin->tell();
}
BinaryTree::~BinaryTree()
{
}
void BinaryTree::skipNodes()
{
while(true) {
uint8 byte = fin->getU8();
uint8 byte = m_fin->getU8();
switch(byte) {
case BINARYTREE_NODE_START: {
BinaryTreePtr node(new BinaryTree(shared_from_this()));
m_children.push_back(node);
node->unserialize(fin);
skipNodes();
break;
}
case BINARYTREE_NODE_END:
return;
case BINARYTREE_ESCAPE_CHAR:
m_buffer.add(fin->getU8());
m_fin->getU8();
break;
default:
break;
}
}
}
void BinaryTree::unserialize()
{
if(m_pos != 0xFFFFFFFF)
return;
m_pos = 0;
m_fin->seek(m_startPos);
while(true) {
uint8 byte = m_fin->getU8();
switch(byte) {
case BINARYTREE_NODE_START: {
skipNodes();
break;
}
case BINARYTREE_NODE_END:
return;
case BINARYTREE_ESCAPE_CHAR:
m_buffer.add(m_fin->getU8());
break;
default:
m_buffer.add(byte);
@ -46,13 +79,33 @@ void BinaryTree::unserialize(const FileStreamPtr& fin)
}
}
void BinaryTree::serialize(const FileStreamPtr& fin)
BinaryTreeVec BinaryTree::getChildren()
{
BinaryTreeVec children;
m_fin->seek(m_startPos);
while(true) {
uint8 byte = m_fin->getU8();
switch(byte) {
case BINARYTREE_NODE_START: {
BinaryTreePtr node(new BinaryTree(m_fin));
children.push_back(node);
node->skipNodes();
break;
}
case BINARYTREE_NODE_END:
return children;
case BINARYTREE_ESCAPE_CHAR:
m_fin->getU8();
break;
default:
break;
}
}
}
void BinaryTree::seek(uint pos)
{
unserialize();
if(pos > m_buffer.size())
stdext::throw_exception("BinaryTree: seek failed");
m_pos = pos;
@ -60,6 +113,7 @@ void BinaryTree::seek(uint pos)
uint8 BinaryTree::getU8()
{
unserialize();
if(m_pos+1 > m_buffer.size())
stdext::throw_exception("BinaryTree: getU8 failed");
uint8 v = m_buffer[m_pos];
@ -69,6 +123,7 @@ uint8 BinaryTree::getU8()
uint16 BinaryTree::getU16()
{
unserialize();
if(m_pos+2 > m_buffer.size())
stdext::throw_exception("BinaryTree: getU16 failed");
uint16 v = stdext::readLE16(&m_buffer[m_pos]);
@ -78,6 +133,7 @@ uint16 BinaryTree::getU16()
uint32 BinaryTree::getU32()
{
unserialize();
if(m_pos+4 > m_buffer.size())
stdext::throw_exception("BinaryTree: getU32 failed");
uint32 v = stdext::readLE32(&m_buffer[m_pos]);
@ -87,6 +143,7 @@ uint32 BinaryTree::getU32()
uint64 BinaryTree::getU64()
{
unserialize();
if(m_pos+8 > m_buffer.size())
stdext::throw_exception("BinaryTree: getU64 failed");
uint64 v = stdext::readLE64(&m_buffer[m_pos]);
@ -96,10 +153,8 @@ uint64 BinaryTree::getU64()
std::string BinaryTree::getString()
{
unserialize();
uint16 len = getU16();
if(len == 0 || len > 8192)
stdext::throw_exception("BinaryTree: getString failed: invalid or too large string length");
if(m_pos+len > m_buffer.size())
stdext::throw_exception("BinaryTree: getString failed: string length exceeded buffer size.");

View File

@ -32,18 +32,16 @@ enum {
BINARYTREE_NODE_END = 0xFF
};
class BinaryTree : public std::enable_shared_from_this<BinaryTree>
class BinaryTree
{
public:
BinaryTree(const BinaryTreePtr& parent = nullptr) : m_pos(0), m_parent(parent) { }
void unserialize(const FileStreamPtr& fin);
void serialize(const FileStreamPtr& fin);
BinaryTree(const FileStreamPtr& fin);
~BinaryTree();
void seek(uint pos);
void skip(uint len) { seek(tell() + len); }
uint tell() { return m_pos; }
uint size() { return m_buffer.size(); }
uint size() { unserialize(); return m_buffer.size(); }
uint8 getU8();
uint16 getU16();
@ -51,16 +49,17 @@ public:
uint64 getU64();
std::string getString();
BinaryTreeVec getChildren() { return m_children; }
BinaryTreePtr getParent() { return m_parent.lock(); }
bool canRead() { return m_pos < m_buffer.size(); }
BinaryTreeVec getChildren();
bool canRead() { unserialize(); return m_pos < m_buffer.size(); }
private:
uint m_pos;
void unserialize();
void skipNodes();
BinaryTreeVec m_children;
BinaryTreeWeakPtr m_parent;
FileStreamPtr m_fin;
DataBuffer<uint8> m_buffer;
uint m_pos;
uint m_startPos;
};
#endif

View File

@ -143,7 +143,7 @@ void FileStream::skip(uint len)
seek(tell() + len);
}
int FileStream::size()
uint FileStream::size()
{
if(!m_caching)
return PHYSFS_fileLength(m_fileHandle);
@ -151,7 +151,7 @@ int FileStream::size()
return m_data.size();
}
int FileStream::tell()
uint FileStream::tell()
{
if(!m_caching)
return PHYSFS_tell(m_fileHandle);
@ -249,13 +249,11 @@ std::string FileStream::getString()
BinaryTreePtr FileStream::getBinaryTree()
{
BinaryTreePtr root = BinaryTreePtr(new BinaryTree);
uint8 byte = getU8();
if(byte == BINARYTREE_NODE_START)
root->unserialize(asFileStream());
else
if(byte != BINARYTREE_NODE_START)
stdext::throw_exception(stdext::format("failed to read node start (getBinaryTree): %d", byte));
return root;
return BinaryTreePtr(new BinaryTree(asFileStream()));
}
void FileStream::addU8(uint8 v)

View File

@ -43,8 +43,8 @@ public:
int read(void *buffer, uint size, uint nmemb = 1);
void seek(uint pos);
void skip(uint len);
int size();
int tell();
uint size();
uint tell();
std::string name() { return m_name; }
uint8 getU8();

View File

@ -721,7 +721,10 @@ void LuaInterface::error()
int LuaInterface::ref()
{
return luaL_ref(L, LUA_REGISTRYINDEX);
int ref = luaL_ref(L, LUA_REGISTRYINDEX);
assert(ref != LUA_NOREF);
assert(ref < 2147483647);
return ref;
}
int LuaInterface::weakRef()

View File

@ -27,6 +27,7 @@
/// LuaObject, all script-able classes have it as base
// @bindclass
#pragma pack(push,1) // disable memory alignment
class LuaObject : public std::enable_shared_from_this<LuaObject>
{
public:
@ -88,6 +89,7 @@ private:
int m_fieldsTableRef;
int m_metatableRef;
};
#pragma pack(pop)
#include "luainterface.h"

View File

@ -0,0 +1,81 @@
/*
* 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 ATTRIBSTORAGE_H
#define ATTRIBSTORAGE_H
#include "../stdext/types.h"
#include <tuple>
#include <boost/any.hpp>
#pragma pack(push,1) // disable memory alignment
// this class was designed to use less memory as possible
class AttribStorage {
public:
AttribStorage() : m_attribs(nullptr), m_size(0) { }
~AttribStorage() { if(m_attribs) delete[] m_attribs; }
template<typename T>
void set(uint8 id, T value) {
bool done = false;
for(int i=0;i<m_size;++i) {
if(std::get<0>(m_attribs[i]) == id) {
std::get<1>(m_attribs[i]) = value;
done = true;
break;
}
}
if(!done) {
auto attribs = new std::tuple<uint8, boost::any>[m_size+1];
if(m_size > 0) {
for(int i=0;i<m_size;++i)
attribs[i] = m_attribs[i];
delete[] m_attribs;
}
m_attribs = attribs;
m_attribs[m_size++] = std::make_tuple(id, value);
}
}
template<typename T>
T get(uint8 id) const {
for(int i=0;i<m_size;++i)
if(std::get<0>(m_attribs[i]) == id)
return boost::any_cast<T>(std::get<1>(m_attribs[i]));
return T();
}
bool has(uint8 id) const {
for(int i=0;i<m_size;++i)
if(std::get<0>(m_attribs[i]) == id)
return true;
return false;
}
private:
std::tuple<uint8, boost::any>* m_attribs;
uint8 m_size;
};
#pragma pack(pop)
#endif

View File

@ -25,6 +25,11 @@
#include <framework/luaengine/luainterface.h>
#include <otclient/otclient.h>
#include <framework/core/binarytree.h>
#include <otclient/item.h>
#include <otclient/tile.h>
#include <boost/any.hpp>
int main(int argc, const char* argv[])
{
std::vector<std::string> args(argv, argv + argc);

View File

@ -113,20 +113,21 @@ void Creature::internalDrawOutfit(const Point& dest, float scaleFactor, bool ani
if(yPattern > 0 && !(m_outfit.getAddons() & (1 << (yPattern-1))))
continue;
m_datType->draw(dest, scaleFactor, 0, xPattern, yPattern, 0, animationPhase);
auto datType = rawGetDatType();
datType->draw(dest, scaleFactor, 0, xPattern, yPattern, 0, animationPhase);
if(getLayers() > 1) {
Color oldColor = g_painter->getColor();
Painter::CompositionMode oldComposition = g_painter->getCompositionMode();
g_painter->setCompositionMode(Painter::CompositionMode_Multiply);
g_painter->setColor(m_outfit.getHeadColor());
m_datType->draw(dest, scaleFactor, DatYellowMask, xPattern, yPattern, 0, animationPhase);
datType->draw(dest, scaleFactor, DatYellowMask, xPattern, yPattern, 0, animationPhase);
g_painter->setColor(m_outfit.getBodyColor());
m_datType->draw(dest, scaleFactor, DatRedMask, xPattern, yPattern, 0, animationPhase);
datType->draw(dest, scaleFactor, DatRedMask, xPattern, yPattern, 0, animationPhase);
g_painter->setColor(m_outfit.getLegsColor());
m_datType->draw(dest, scaleFactor, DatGreenMask, xPattern, yPattern, 0, animationPhase);
datType->draw(dest, scaleFactor, DatGreenMask, xPattern, yPattern, 0, animationPhase);
g_painter->setColor(m_outfit.getFeetColor());
m_datType->draw(dest, scaleFactor, DatBlueMask, xPattern, yPattern, 0, animationPhase);
datType->draw(dest, scaleFactor, DatBlueMask, xPattern, yPattern, 0, animationPhase);
g_painter->setColor(oldColor);
g_painter->setCompositionMode(oldComposition);
}
@ -154,7 +155,7 @@ void Creature::internalDrawOutfit(const Point& dest, float scaleFactor, bool ani
if(m_outfit.getCategory() == DatEffectCategory)
animationPhase = std::min(animationPhase+1, getAnimationPhases());
m_datType->draw(dest, scaleFactor, 0, 0, 0, 0, animationPhase);
rawGetDatType()->draw(dest, scaleFactor, 0, 0, 0, 0, animationPhase);
}
}
@ -462,7 +463,6 @@ void Creature::setOutfit(const Outfit& outfit)
{
m_walkAnimationPhase = 0; // might happen when player is walking and outfit is changed.
m_outfit = outfit;
m_datType = g_things.getDatType(outfit.getId(), outfit.getCategory());
}
void Creature::setSkull(uint8 skull)
@ -548,3 +548,13 @@ Point Creature::getDrawOffset()
}
return drawOffset;
}
const ThingTypeDatPtr& Creature::getDatType()
{
return g_things.getDatType(m_outfit.getId(), m_outfit.getCategory());
}
ThingTypeDat* Creature::rawGetDatType()
{
return g_things.rawGetDatType(m_outfit.getId(), m_outfit.getCategory());
}

View File

@ -96,6 +96,9 @@ public:
CreaturePtr asCreature() { return std::static_pointer_cast<Creature>(shared_from_this()); }
bool isCreature() { return true; }
const ThingTypeDatPtr& getDatType();
ThingTypeDat *rawGetDatType();
protected:
virtual void updateWalkAnimation(int totalPixelsWalked);
virtual void updateWalkOffset(int totalPixelsWalked);

View File

@ -32,7 +32,7 @@ void Effect::draw(const Point& dest, float scaleFactor, bool animate)
int animationPhase = 0;
if(animate)
animationPhase = std::min((int)(m_animationTimer.ticksElapsed() / Otc::EFFECT_TICKS_PER_FRAME), getAnimationPhases() - 1);
m_datType->draw(dest, scaleFactor, 0, 0, 0, 0, animationPhase);
rawGetDatType()->draw(dest, scaleFactor, 0, 0, 0, 0, animationPhase);
}
void Effect::startAnimation()
@ -47,5 +47,14 @@ void Effect::startAnimation()
void Effect::setId(uint32 id)
{
m_id = id;
m_datType = g_things.getDatType(m_id, DatEffectCategory);
}
const ThingTypeDatPtr& Effect::getDatType()
{
return g_things.getDatType(m_id, DatEffectCategory);
}
ThingTypeDat *Effect::rawGetDatType()
{
return g_things.rawGetDatType(m_id, DatEffectCategory);
}

View File

@ -41,6 +41,9 @@ public:
EffectPtr asEffect() { return std::static_pointer_cast<Effect>(shared_from_this()); }
bool isEffect() { return true; }
const ThingTypeDatPtr& getDatType();
ThingTypeDat *rawGetDatType();
private:
Timer m_animationTimer;
uint16 m_id;

View File

@ -38,11 +38,8 @@
Item::Item() :
m_id(0),
m_countOrSubType(1),
m_actionId(0),
m_uniqueId(0),
m_shaderProgram(g_shaders.getDefaultItemShader()),
m_otbType(g_things.getNullOtbType())
m_otbId(0),
m_countOrSubType(1)
{
}
@ -174,32 +171,20 @@ void Item::draw(const Point& dest, float scaleFactor, bool animate)
zPattern = m_position.z % getNumPatternZ();
}
bool useShader = g_painter->hasShaders() && m_shaderProgram;
if(useShader) {
m_shaderProgram->bind();
m_shaderProgram->setUniformValue(ShaderManager::ITEM_ID_UNIFORM, (int)m_id);
g_painter->setShaderProgram(m_shaderProgram);
}
m_datType->draw(dest, scaleFactor, 0, xPattern, yPattern, zPattern, animationPhase);
if(useShader)
g_painter->resetShaderProgram();
rawGetDatType()->draw(dest, scaleFactor, 0, xPattern, yPattern, zPattern, animationPhase);
}
void Item::setId(uint32 id)
{
m_datType = g_things.getDatType(id, DatItemCategory);
m_otbType = g_things.findOtbForClientId(id);
m_id = m_datType->getId();
m_otbId = g_things.findOtbForClientId(id)->getServerId();
m_id = id;
}
void Item::setOtbId(uint16 id)
{
m_otbType = g_things.getOtbType(id);
m_datType = g_things.getDatType(m_otbType->getClientId(), DatItemCategory);
m_id = m_datType->getId();
auto otbType = g_things.getOtbType(id);
m_otbId = id;
m_id = otbType->getClientId();
}
bool Item::isValid()
@ -229,29 +214,29 @@ void Item::unserializeItem(const BinaryTreePtr &in)
setUniqueId(in->getU16());
break;
case ATTR_NAME:
setName(in->getString());
m_attribs.set(ATTR_NAME, in->getString());
break;
case ATTR_TEXT:
setText(in->getString());
m_attribs.set(ATTR_TEXT, in->getString());
break;
case ATTR_DESC:
m_description = in->getString();
m_attribs.set(ATTR_DESC, in->getString());
break;
case ATTR_CONTAINER_ITEMS:
m_isContainer = true;
in->skip(4);
m_attribs.set(ATTR_CONTAINER_ITEMS, in->getU32());
break;
case ATTR_HOUSEDOORID:
m_isDoor = true;
m_doorId = in->getU8();
m_attribs.set(ATTR_HOUSEDOORID, in->getU8());
break;
case ATTR_DEPOT_ID:
m_depotId = in->getU16();
m_attribs.set(ATTR_DEPOT_ID, in->getU16());
break;
case ATTR_TELE_DEST: {
m_teleportDestination.x = in->getU16();
m_teleportDestination.y = in->getU16();
m_teleportDestination.z = in->getU8();
Position teleportDestination;
teleportDestination.x = in->getU16();
teleportDestination.y = in->getU16();
teleportDestination.z = in->getU8();
m_attribs.set(ATTR_TELE_DEST, teleportDestination);
break;
}
case ATTR_ARTICLE:
@ -286,12 +271,7 @@ void Item::unserializeItem(const BinaryTreePtr &in)
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;
return !rawGetDatType()->isNotMoveable();
}
ItemPtr Item::clone()
@ -300,3 +280,13 @@ ItemPtr Item::clone()
*(item.get()) = *this;
return item;
}
const ThingTypeDatPtr& Item::getDatType()
{
return g_things.getDatType(m_id, DatItemCategory);
}
ThingTypeDat* Item::rawGetDatType()
{
return g_things.rawGetDatType(m_id, DatItemCategory);
}

View File

@ -24,6 +24,7 @@
#define ITEM_H
#include <framework/global.h>
#include <framework/util/attribstorage.h>
#include "thing.h"
#include "thingtypeotb.h"
@ -66,10 +67,12 @@ enum AttrTypes_t
};
// @bindclass
#pragma pack(push,1) // disable memory alignment
class Item : public Thing
{
public:
Item();
virtual ~Item() { }
static ItemPtr create(int id);
static ItemPtr createFromOtb(int id);
@ -81,43 +84,45 @@ public:
void setCountOrSubType(int value) { m_countOrSubType = value; }
void setCount(int count) { m_countOrSubType = count; }
void setSubType(int subType) { m_countOrSubType = subType; }
void setActionId(int actionId) { m_actionId = actionId; }
void setUniqueId(int uniqueId) { m_uniqueId = uniqueId; }
void setDoorId(int doorId) { m_doorId = doorId; }
void setName(const std::string &name) { m_name = name; }
void setText(const std::string &text) { m_text = text; }
void setDescription(const std::string &description) { m_description = description; }
int getCountOrSubType() { return m_countOrSubType; }
int getSubType() { return m_countOrSubType; }
int getCount() { return m_countOrSubType; }
uint32 getId() { return m_id; }
std::string getName() { return m_name; }
uint8 getDoorId() { return m_doorId; }
bool isValid();
ItemPtr clone();
ItemPtr asItem() { return std::static_pointer_cast<Item>(shared_from_this()); }
bool isItem() { return true; }
void unserializeItem(const BinaryTreePtr &in);
bool isMoveable();
bool isContainer() { return m_isContainer; }
bool isDoor() { return m_isDoor; }
void setDepotId(uint16 depotId) { m_attribs.set(ATTR_DEPOT_ID, depotId); }
uint16 getDepotId() { return m_attribs.get<uint16>(ATTR_DEPOT_ID); }
void setDoorId(uint8 doorId) { m_attribs.set(ATTR_HOUSEDOORID, doorId); }
uint8 getDoorId() { return m_attribs.get<uint8>(ATTR_HOUSEDOORID); }
void setActionId(uint16 actionId) { m_attribs.set(ATTR_ACTION_ID, actionId); }
void setUniqueId(uint16 uniqueId) { m_attribs.set(ATTR_UNIQUE_ID, uniqueId); }
bool isDepot() { return m_attribs.has(ATTR_DEPOT_ID); }
bool isContainer() { return m_attribs.has(ATTR_CONTAINER_ITEMS); }
bool isDoor() { return m_attribs.has(ATTR_HOUSEDOORID); }
bool isTeleport() { return m_attribs.has(ATTR_TELE_DEST); }
ItemPtr asItem() { return std::static_pointer_cast<Item>(shared_from_this()); }
bool isItem() { return true; }
const ThingTypeDatPtr& getDatType();
ThingTypeDat *rawGetDatType();
private:
uint16 m_id;
uint16 m_otbId;
uint8 m_countOrSubType;
uint32 m_actionId, m_uniqueId;
uint16 m_depotId;
uint8 m_doorId;
Boolean<false> m_isContainer;
Boolean<false> m_isDoor;
std::string m_name, m_text, m_description;
PainterShaderProgramPtr m_shaderProgram;
ThingTypeOtbPtr m_otbType;
Position m_teleportDestination;
AttribStorage m_attribs;
};
#pragma pack(pop)
#endif

View File

@ -136,7 +136,6 @@ void Map::loadOtbm(const std::string& fileName)
if(type != OTBM_TILE && type != OTBM_HOUSETILE)
stdext::throw_exception(stdext::format("invalid node tile type %d", (int)type));
TilePtr tile = nullptr;
ItemPtr ground = nullptr;
HousePtr house = nullptr;
uint32 flags = TILESTATE_NONE;
@ -146,7 +145,7 @@ void Map::loadOtbm(const std::string& fileName)
if(type == OTBM_HOUSETILE) {
uint32 hId = nodeTile->getU32();
tile = createTile(pos);
TilePtr tile = getOrCreateTile(pos);
if(!(house = m_houses.getHouse(hId))) {
house = HousePtr(new House(hId));
m_houses.addHouse(house);
@ -175,13 +174,7 @@ void Map::loadOtbm(const std::string& fileName)
break;
}
case OTBM_ATTR_ITEM: {
ItemPtr item = Item::createFromOtb(nodeTile->getU16());
if(tile)
addThing(item, pos, 255);
else if(item->isGround())
ground = item;
else
tile = createTileEx(pos, ground, item);
addThing(Item::createFromOtb(nodeTile->getU16()), pos);
break;
}
default:
@ -196,6 +189,7 @@ void Map::loadOtbm(const std::string& fileName)
ItemPtr item = Item::createFromOtb(nodeItem->getU16());
item->unserializeItem(nodeItem);
if(item->isContainer()) {
// This is a temporary way for reading container items.
MapContainerPtr mapContainer(new MapContainer);
@ -217,18 +211,13 @@ void Map::loadOtbm(const std::string& fileName)
item = nullptr;
} else if(item->isDoor())
house->addDoor(item->getDoorId(), pos);
} else if(tile)
addThing(item, pos);
else if(item->isGround())
ground = item;
else
tile = createTileEx(pos, ground, item);
}
addThing(item, pos);
}
if(!tile)
tile = createTileEx(pos, ground);
tile->setFlags((tileflags_t)flags);
if(const TilePtr& tile = getTile(pos))
tile->setFlags((tileflags_t)flags);
}
} else if(mapDataType == OTBM_TOWNS) {
TownPtr town = nullptr;
@ -263,6 +252,13 @@ void Map::loadOtbm(const std::string& fileName)
stdext::throw_exception("Unknown map data node");
}
int numItems = 0;
for(const auto& it : m_tiles)
numItems += it.second->getThingCount();
g_logger.debug(stdext::format("Total items: %d", numItems));
g_logger.debug(stdext::format("Total tiles: %d", m_tiles.size()));
g_logger.debug("OTBM read successfully.");
fin->close();
/// TODO read XML Stuff (houses & spawns).

View File

@ -122,6 +122,7 @@ public:
// thing related
void addThing(const ThingPtr& thing, const Position& pos, int stackPos = -1);
ThingPtr getThing(const Position& pos, int stackPos);
bool removeThing(const ThingPtr& thing);
bool removeThingByPos(const Position& pos, int stackPos);
// tile related
@ -131,7 +132,6 @@ public:
const TilePtr& getTile(const Position& pos);
TilePtr getOrCreateTile(const Position& pos);
void cleanTile(const Position& pos);
bool removeThing(const ThingPtr& thing);
// known creature related
void addCreature(const CreaturePtr& creature);

View File

@ -63,7 +63,7 @@ void Missile::draw(const Point& dest, float scaleFactor, bool animate)
}
float fraction = m_animationTimer.ticksElapsed() / m_duration;
m_datType->draw(dest + m_delta * fraction * scaleFactor, scaleFactor, 0, xPattern, yPattern, 0, 0);
rawGetDatType()->draw(dest + m_delta * fraction * scaleFactor, scaleFactor, 0, xPattern, yPattern, 0, 0);
}
void Missile::setPath(const Position& fromPosition, const Position& toPosition)
@ -84,5 +84,14 @@ void Missile::setPath(const Position& fromPosition, const Position& toPosition)
void Missile::setId(uint32 id)
{
m_id = id;
m_datType = g_things.getDatType(m_id, DatMissileCategory);
}
const ThingTypeDatPtr& Missile::getDatType()
{
return g_things.getDatType(m_id, DatMissileCategory);
}
ThingTypeDat* Missile::rawGetDatType()
{
return g_things.rawGetDatType(m_id, DatMissileCategory);
}

View File

@ -37,8 +37,6 @@ class Missile : public Thing
public:
void draw(const Point& dest, float scaleFactor, bool animate);
void updateAnimation();
void setId(uint32 id);
void setPath(const Position& fromPosition, const Position& toPosition);
@ -47,6 +45,9 @@ public:
MissilePtr asMissile() { return std::static_pointer_cast<Missile>(shared_from_this()); }
bool isMissile() { return true; }
const ThingTypeDatPtr& getDatType();
ThingTypeDat *rawGetDatType();
private:
Timer m_animationTimer;
Point m_delta;

View File

@ -214,7 +214,7 @@ public:
struct PositionHasher : std::unary_function<Position, std::size_t> {
std::size_t operator()(const Position& pos) const {
return ((((pos.x * 2048) + pos.y) * 16) + pos.z) % (2048*2048);
return (((((pos.x * 2048) + pos.y) * 16) + pos.z) % (2048*2048)) % 1000000;
}
};

View File

@ -29,7 +29,7 @@
#include "game.h"
Thing::Thing() :
m_datType(g_things.getNullDatType())
m_datId(0)
{
}
@ -74,3 +74,13 @@ int Thing::getStackpos()
return -1;
}
}
const ThingTypeDatPtr& Thing::getDatType()
{
return g_things.getNullDatType();
}
ThingTypeDat* Thing::rawGetDatType()
{
return g_things.getNullDatType().get();
}

View File

@ -25,6 +25,7 @@
#include "declarations.h"
#include "thingtypedat.h"
#include "thingtypemanager.h"
#include <framework/luaengine/luaobject.h>
struct Light
@ -34,6 +35,7 @@ struct Light
};
// @bindclass
#pragma pack(push,1) // disable memory alignment
class Thing : public LuaObject
{
public:
@ -77,65 +79,67 @@ public:
virtual bool isStaticText() { return false; }
// type shortcuts
ThingTypeDatPtr getType() { return m_datType; }
Size getSize() { return m_datType->getSize(); }
int getWidth() { return m_datType->getWidth(); }
int getHeight() { return m_datType->getHeight(); }
Point getDisplacement() { return m_datType->getDisplacement(); }
int getDisplacementX() { return m_datType->getDisplacementX(); }
int getDisplacementY() { return m_datType->getDisplacementY(); }
int getExactSize() { return m_datType->getExactSize(); }
int getLayers() { return m_datType->getLayers(); }
int getNumPatternX() { return m_datType->getNumPatternX(); }
int getNumPatternY() { return m_datType->getNumPatternY(); }
int getNumPatternZ() { return m_datType->getNumPatternZ(); }
int getAnimationPhases() { return m_datType->getAnimationPhases(); }
int getGroundSpeed() { return m_datType->getGroundSpeed(); }
int getMaxTextLength() { return m_datType->getMaxTextLength(); }
int getLightLevel() { return m_datType->getLightLevel(); }
int getLightColor() { return m_datType->getLightColor(); }
int getMinimapColor() { return m_datType->getMinimapColor(); }
int getLensHelp() { return m_datType->getLensHelp(); }
int getClothSlot() { return m_datType->getClothSlot(); }
int getElevation() { return m_datType->getElevation(); }
bool isGround() { return m_datType->isGround(); }
bool isGroundBorder() { return m_datType->isGroundBorder(); }
bool isOnBottom() { return m_datType->isOnBottom(); }
bool isOnTop() { return m_datType->isOnTop(); }
bool isContainer() { return m_datType->isContainer(); }
bool isStackable() { return m_datType->isStackable(); }
bool isForceUse() { return m_datType->isForceUse(); }
bool isMultiUse() { return m_datType->isMultiUse(); }
bool isWritable() { return m_datType->isWritable(); }
bool isWritableOnce() { return m_datType->isWritableOnce(); }
bool isFluidContainer() { return m_datType->isFluidContainer(); }
bool isFluid() { return m_datType->isFluid(); }
bool isNotWalkable() { return m_datType->isNotWalkable(); }
bool isNotMoveable() { return m_datType->isNotMoveable(); }
bool blockProjectile() { return m_datType->blockProjectile(); }
bool isNotPathable() { return m_datType->isNotPathable(); }
bool isPickupable() { return m_datType->isPickupable(); }
bool isHangable() { return m_datType->isHangable(); }
bool isHookSouth() { return m_datType->isHookSouth(); }
bool isHookEast() { return m_datType->isHookEast(); }
bool isRotateable() { return m_datType->isRotateable(); }
bool hasLight() { return m_datType->hasLight(); }
bool isDontHide() { return m_datType->isDontHide(); }
bool isTranslucent() { return m_datType->isTranslucent(); }
bool hasDisplacement() { return m_datType->hasDisplacement(); }
bool hasElevation() { return m_datType->hasElevation(); }
bool isLyingCorpse() { return m_datType->isLyingCorpse(); }
bool isAnimateAlways() { return m_datType->isAnimateAlways(); }
bool hasMiniMapColor() { return m_datType->hasMiniMapColor(); }
bool hasLensHelp() { return m_datType->hasLensHelp(); }
bool isFullGround() { return m_datType->isFullGround(); }
bool isIgnoreLook() { return m_datType->isIgnoreLook(); }
bool isCloth() { return m_datType->isCloth(); }
virtual const ThingTypeDatPtr& getDatType();
virtual ThingTypeDat *rawGetDatType();
Size getSize() { return rawGetDatType()->getSize(); }
int getWidth() { return rawGetDatType()->getWidth(); }
int getHeight() { return rawGetDatType()->getHeight(); }
Point getDisplacement() { return rawGetDatType()->getDisplacement(); }
int getDisplacementX() { return rawGetDatType()->getDisplacementX(); }
int getDisplacementY() { return rawGetDatType()->getDisplacementY(); }
int getExactSize() { return rawGetDatType()->getExactSize(); }
int getLayers() { return rawGetDatType()->getLayers(); }
int getNumPatternX() { return rawGetDatType()->getNumPatternX(); }
int getNumPatternY() { return rawGetDatType()->getNumPatternY(); }
int getNumPatternZ() { return rawGetDatType()->getNumPatternZ(); }
int getAnimationPhases() { return rawGetDatType()->getAnimationPhases(); }
int getGroundSpeed() { return rawGetDatType()->getGroundSpeed(); }
int getMaxTextLength() { return rawGetDatType()->getMaxTextLength(); }
int getLightLevel() { return rawGetDatType()->getLightLevel(); }
int getLightColor() { return rawGetDatType()->getLightColor(); }
int getMinimapColor() { return rawGetDatType()->getMinimapColor(); }
int getLensHelp() { return rawGetDatType()->getLensHelp(); }
int getClothSlot() { return rawGetDatType()->getClothSlot(); }
int getElevation() { return rawGetDatType()->getElevation(); }
bool isGround() { return rawGetDatType()->isGround(); }
bool isGroundBorder() { return rawGetDatType()->isGroundBorder(); }
bool isOnBottom() { return rawGetDatType()->isOnBottom(); }
bool isOnTop() { return rawGetDatType()->isOnTop(); }
bool isContainer() { return rawGetDatType()->isContainer(); }
bool isStackable() { return rawGetDatType()->isStackable(); }
bool isForceUse() { return rawGetDatType()->isForceUse(); }
bool isMultiUse() { return rawGetDatType()->isMultiUse(); }
bool isWritable() { return rawGetDatType()->isWritable(); }
bool isWritableOnce() { return rawGetDatType()->isWritableOnce(); }
bool isFluidContainer() { return rawGetDatType()->isFluidContainer(); }
bool isFluid() { return rawGetDatType()->isFluid(); }
bool isNotWalkable() { return rawGetDatType()->isNotWalkable(); }
bool isNotMoveable() { return rawGetDatType()->isNotMoveable(); }
bool blockProjectile() { return rawGetDatType()->blockProjectile(); }
bool isNotPathable() { return rawGetDatType()->isNotPathable(); }
bool isPickupable() { return rawGetDatType()->isPickupable(); }
bool isHangable() { return rawGetDatType()->isHangable(); }
bool isHookSouth() { return rawGetDatType()->isHookSouth(); }
bool isHookEast() { return rawGetDatType()->isHookEast(); }
bool isRotateable() { return rawGetDatType()->isRotateable(); }
bool hasLight() { return rawGetDatType()->hasLight(); }
bool isDontHide() { return rawGetDatType()->isDontHide(); }
bool isTranslucent() { return rawGetDatType()->isTranslucent(); }
bool hasDisplacement() { return rawGetDatType()->hasDisplacement(); }
bool hasElevation() { return rawGetDatType()->hasElevation(); }
bool isLyingCorpse() { return rawGetDatType()->isLyingCorpse(); }
bool isAnimateAlways() { return rawGetDatType()->isAnimateAlways(); }
bool hasMiniMapColor() { return rawGetDatType()->hasMiniMapColor(); }
bool hasLensHelp() { return rawGetDatType()->hasLensHelp(); }
bool isFullGround() { return rawGetDatType()->isFullGround(); }
bool isIgnoreLook() { return rawGetDatType()->isIgnoreLook(); }
bool isCloth() { return rawGetDatType()->isCloth(); }
protected:
Position m_position;
ThingTypeDatPtr m_datType;
uint16 m_datId;
};
#pragma pack(pop)
#endif

View File

@ -211,3 +211,4 @@ const ThingTypeOtbPtr& ThingTypeManager::getOtbType(uint16 id)
}
return m_otbTypes[id];
}

View File

@ -47,6 +47,8 @@ public:
const ThingTypeDatPtr& getDatType(uint16 id, DatCategory category);
const ThingTypeOtbPtr& getOtbType(uint16 id);
ThingTypeDat *rawGetDatType(uint16 id, DatCategory category) { return m_datTypes[category][id].get(); }
ThingTypeOtb *rawGetOtbType(uint16 id) { return m_otbTypes[id].get(); }
uint32 getDatSignature() { return m_datSignature; }
uint32 getOtbMajorVersion() { return m_otbMajorVersion; }

View File

@ -46,6 +46,7 @@ enum tileflags_t
TILESTATE_DEPOT = 1 << 22
};
#pragma pack(push,1) // disable memory alignment
class Tile : public LuaObject
{
public:
@ -99,10 +100,11 @@ public:
bool limitsFloorsView();
bool canErase();
TilePtr asTile() { return std::static_pointer_cast<Tile>(shared_from_this()); }
void setFlags(tileflags_t flags) { m_flags |= (uint32)flags; }
uint32 flags() { return m_flags; }
TilePtr asTile() { return std::static_pointer_cast<Tile>(shared_from_this()); }
private:
void update();
@ -114,5 +116,6 @@ private:
uint32 m_flags;
uint8 m_minimapColorByte;
};
#pragma pack(pop)
#endif