• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!

[C++]"[ItemAttribute::serialize]: Invalid data type."

Jetro

jangeldev
Joined
Aug 1, 2011
Messages
452
Reaction score
68
Location
Venezuela
Hi all, i've found a bug on sources in function ItemAttribute::serialize, i can't add decimal attributes to items, and if i have the item in my equip and i relog it prints this many times in console:
Code:
"[ItemAttribute::serialize]: Invalid data type."

This is an example how to reproduce this bug:

Code:
local test, item = 0.35, getPlayerSlotItem(cid, 8).uid
doItemSetAttribute(item, "xd", test)
print(getItemAttribute(item, "xd"))

it prints nil

btw here are itemattributes.cpp and itemattributes.h from distro i'm using (OTX):

itemattributes.cpp
[cpp]////////////////////////////////////////////////////////////////////////
// OpenTibia - an opensource roleplaying game
////////////////////////////////////////////////////////////////////////
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
////////////////////////////////////////////////////////////////////////
#include "otpch.h"

#include "itemattributes.h"
#include "fileloader.h"

ItemAttributes::ItemAttributes(const ItemAttributes& o)
{
if(o.attributes)
attributes = new AttributeMap(*o.attributes);
}

void ItemAttributes::createAttributes()
{
if(!attributes)
attributes = new AttributeMap;
}

void ItemAttributes::eraseAttribute(const char* key)
{
if(!attributes)
return;

AttributeMap::iterator it = attributes->find(key);
if(it != attributes->end())
attributes->erase(it);
}

void ItemAttributes::setAttribute(const char* key, boost::any value)
{
createAttributes();
(*attributes)[key].set(value);
}

void ItemAttributes::setAttribute(const char* key, const std::string& value)
{
createAttributes();
(*attributes)[key].set(value);
}

void ItemAttributes::setAttribute(const char* key, int32_t value)
{
createAttributes();
(*attributes)[key].set(value);
}

void ItemAttributes::setAttribute(const char* key, float value)
{
createAttributes();
(*attributes)[key].set(value);
}

void ItemAttributes::setAttribute(const char* key, bool value)
{
createAttributes();
(*attributes)[key].set(value);
}

boost::any ItemAttributes::getAttribute(const char* key) const
{
if(!attributes)
return boost::any();

AttributeMap::iterator it = attributes->find(key);
if(it != attributes->end())
return it->second.get();

return boost::any();
}

std::string ItemAttributes::getStringAttribute(const std::string& key, bool &ok) const
{
if(!attributes)
{
ok = false;
return std::string();
}

AttributeMap::iterator it = attributes->find(key);
if(it != attributes->end())
return it->second.getString(ok);

ok = false;
return std::string();
}

int32_t ItemAttributes::getIntegerAttribute(const std::string& key, bool &ok) const
{
if(!attributes)
{
ok = false;
return 0;
}

AttributeMap::iterator it = attributes->find(key);
if(it != attributes->end())
return it->second.getInteger(ok);

ok = false;
return 0;
}

float ItemAttributes::getFloatAttribute(const std::string& key, bool &ok) const
{
if(!attributes)
{
ok = false;
return 0.0;
}

AttributeMap::iterator it = attributes->find(key);
if(it != attributes->end())
return it->second.getFloat(ok);

ok = false;
return 0.0;
}

bool ItemAttributes::getBooleanAttribute(const std::string& key, bool &ok) const
{
if(!attributes)
{
ok = false;
return false;
}

AttributeMap::iterator it = attributes->find(key);
if(it != attributes->end())
return it->second.getBoolean(ok);

ok = false;
return false;
}

ItemAttribute& ItemAttribute::eek:perator=(const ItemAttribute& o)
{
if(&o == this)
return *this;

m_data = o.m_data;
return *this;
}

std::string ItemAttribute::getString(bool &ok) const
{
if(m_data.type() != typeid(std::string))
{
ok = false;
return std::string();
}

ok = true;
return boost::any_cast<std::string>(m_data);
}

int32_t ItemAttribute::getInteger(bool &ok) const
{
if(m_data.type() != typeid(int32_t))
{
ok = false;
return 0;
}

ok = true;
return boost::any_cast<int32_t>(m_data);
}

float ItemAttribute::getFloat(bool &ok) const
{
if(m_data.type() != typeid(float))
{
ok = false;
return 0.0;
}

ok = true;
return boost::any_cast<float>(m_data);
}

bool ItemAttribute::getBoolean(bool &ok) const
{
if(m_data.type() != typeid(bool))
{
ok = false;
return false;
}

ok = true;
return boost::any_cast<bool>(m_data);
}

bool ItemAttributes::unserializeMap(PropStream& stream)
{
uint16_t n;
if(!stream.getShort(n))
return true;

createAttributes();
while(n--)
{
std::string key;
if(!stream.getString(key))
return false;

ItemAttribute attr;
if(!attr.unserialize(stream))
return false;

(*attributes)[key] = attr;
}

return true;
}

void ItemAttributes::serializeMap(PropWriteStream& stream) const
{
stream.addShort((uint16_t)std::min((size_t)0xFFFF, attributes->size()));
AttributeMap::const_iterator it = attributes->begin();
for(int32_t i = 0; it != attributes->end() && i <= 0xFFFF; ++it, ++i)
{
std::string key = it->first;
if(key.size() > 0xFFFF)
stream.addString(key.substr(0, 0xFFFF));
else
stream.addString(key);

it->second.serialize(stream);
}
}

bool ItemAttribute::unserialize(PropStream& stream)
{
uint8_t type = 0;
stream.getByte(type);
switch(type)
{
case STRING:
{
std::string v;
if(!stream.getLongString(v))
return false;

set(v);
break;
}
case INTEGER:
{
uint32_t v;
if(!stream.getLong(v))
return false;

set((int32_t)v);
break;
}
case FLOAT:
{
float v;
if(!stream.getFloat(v))
return false;

set(v);
break;
}
case BOOLEAN:
{
uint8_t v;
if(!stream.getByte(v))
return false;

set(v != 0);
}
}

return true;
}

void ItemAttribute::serialize(PropWriteStream& stream) const
{
bool ok;
if(m_data.type() == typeid(std::string))
{
stream.addByte((uint8_t)STRING);
stream.addLongString(getString(ok));
}
else if(m_data.type() == typeid(int32_t))
{
stream.addByte((uint8_t)INTEGER);
stream.addLong(getInteger(ok));
}
else if(m_data.type() == typeid(float))
{
stream.addByte((uint8_t)FLOAT);
stream.addLong(getFloat(ok));
}
else if(m_data.type() == typeid(bool))
{
stream.addByte((uint8_t)BOOLEAN);
stream.addByte(getBoolean(ok));
}
else
std::clog << "[ItemAttribute::serialize]: Invalid data type." << std::endl;
}
[/cpp]

itemattributes.h
[cpp]////////////////////////////////////////////////////////////////////////
// OpenTibia - an opensource roleplaying game
////////////////////////////////////////////////////////////////////////
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
////////////////////////////////////////////////////////////////////////

#ifndef __ITEM_ATTRIBUTES__
#define __ITEM_ATTRIBUTES__
#include "otsystem.h"
#include <boost/any.hpp>

class PropWriteStream;
class PropStream;

class ItemAttribute
{
public:
ItemAttribute() {}
ItemAttribute(const ItemAttribute& o) {*this = o;}
~ItemAttribute() {}

ItemAttribute(const std::string& s) {m_data = s;}
ItemAttribute(int32_t i) {m_data = i;}
ItemAttribute(float f) {m_data = f;}
ItemAttribute(bool b) {m_data = b;}

ItemAttribute& operator=(const ItemAttribute& o);

void serialize(PropWriteStream& stream) const;
bool unserialize(PropStream& stream);

void set(const std::string& s) { m_data = s; }
void set(int32_t i) { m_data = i; }
void set(float f) { m_data = f; }
void set(bool b) { m_data = b; }
void set(boost::any a) { m_data = a; }

std::string getString(bool &ok) const;
int32_t getInteger(bool &ok) const;
float getFloat(bool &ok) const;
bool getBoolean(bool &ok) const;
boost::any get() const { return m_data; }

private:
enum Type
{
NONE = 0,
STRING = 1,
INTEGER = 2,
FLOAT = 3,
BOOLEAN = 4
};

boost::any m_data;
};

class ItemAttributes
{
public:
ItemAttributes(): attributes(NULL) {}
ItemAttributes(const ItemAttributes &i);
virtual ~ItemAttributes() {delete attributes;}

void serializeMap(PropWriteStream& stream) const;
bool unserializeMap(PropStream& stream);

void eraseAttribute(const char* key);
void setAttribute(const char* key, boost::any value);
boost::any getAttribute(const char* key) const;

void setAttribute(const char* key, const std::string& value);
void setAttribute(const char* key, int32_t value);
void setAttribute(const char* key, float value);
void setAttribute(const char* key, bool value);

std::string getStringAttribute(const std::string& key, bool &ok) const;
int32_t getIntegerAttribute(const std::string& key, bool &ok) const;
float getFloatAttribute(const std::string& key, bool &ok) const;
bool getBooleanAttribute(const std::string& key, bool &ok) const;

bool hasStringAttribute(const std::string& key) const { bool ok; getStringAttribute(key, ok); return ok; }
bool hasIntegerAttribute(const std::string& key) const { bool ok; getIntegerAttribute(key, ok); return ok; }
bool hasFloatAttribute(const std::string& key) const { bool ok; getFloatAttribute(key, ok); return ok; }
bool hasBooleanAttribute(const std::string& key) const { bool ok; getBooleanAttribute(key, ok); return ok; }

protected:
void createAttributes();

typedef std::map<std::string, ItemAttribute> AttributeMap;
AttributeMap* attributes;
};

#endif
[/cpp]

I hope you can help me ^_^
Regards
 
Back
Top