khanat-opennel-code/code/nel/include/nel/misc/entity_id.h
2016-12-09 16:04:26 +01:00

607 lines
12 KiB
C++

// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef NL_ENTITY_ID_H
#define NL_ENTITY_ID_H
#include "types_nl.h"
#include "debug.h"
#include "common.h"
#include "stream.h"
namespace NLMISC {
/**
* Entity identifier
* \author Sameh Chafik, Vianney Lecroart
* \author Nevrax France
* \date 2001
*/
struct CEntityId
{
// pseudo constants
enum
{
DYNAMIC_ID_SIZE = 8,
CREATOR_ID_SIZE = 8,
TYPE_SIZE = 8,
ID_SIZE = 40,
UNKNOWN_TYPE = (1 << TYPE_SIZE)-1
};
protected:
// ---------------------------------------------------------------------------------
// instantiated data
union
{
struct
{
/// Id of the service where the entity is (variable routing info).
uint64 DynamicId : DYNAMIC_ID_SIZE;
/// Id of the service who created the entity (persistent).
uint64 CreatorId : CREATOR_ID_SIZE;
/// Type of the entity (persistent).
uint64 Type : TYPE_SIZE;
/// Local entity number (persistent).
uint64 Id : ID_SIZE;
} DetailedId;
uint64 FullId;
};
// ---------------------------------------------------------------------------------
// static data
/// Counter for generation of unique entity ids
static NLMISC::CEntityId _NextEntityId;
///The local num service id of the local machin.
static uint8 _ServerId;
public:
// ---------------------------------------------------------------------------------
// static data
///The maximum number that we could generate without generate an overtaking exception.
static const uint64 MaxEntityId;
/// Unknown CEntityId is similar as a NULL pointer.
static const CEntityId Unknown;
// ---------------------------------------------------------------------------------
// generation of new unique entity ids
/// Set the service id for the generator
static void setServiceId( uint8 sid )
{
_NextEntityId.setDynamicId( sid );
_NextEntityId.setCreatorId( sid );
_ServerId = sid;
}
/// Generator of entity ids
static CEntityId getNewEntityId( uint8 type )
{
nlassert(_NextEntityId != Unknown ); // type may be Unknown, so isUnknownId() would return true
NLMISC::CEntityId id = _NextEntityId++;
id.setType( type );
return id;
}
// ---------------------------------------------------------------------------------
// constructors
///\name Constructor
//@{
CEntityId ()
{
FullId = 0;
DetailedId.Type = UNKNOWN_TYPE;
/*
DynamicId = 0;
CreatorId = 0;
Type = 127;
Id = 0;
*/
}
CEntityId (uint8 type, uint64 id, uint8 creator, uint8 dynamic)
{
DetailedId.DynamicId = dynamic;
DetailedId.CreatorId = creator;
DetailedId.Type = type;
DetailedId.Id = id;
}
CEntityId (uint8 type, uint64 id)
{
DetailedId.Type = type;
DetailedId.Id = id;
DetailedId.CreatorId = _ServerId;
DetailedId.DynamicId = _ServerId;
}
explicit CEntityId (uint64 p)
{
FullId = p;
/*
DynamicId = (p & 0xff);
p >>= 8;
CreatorId = (p & 0xff);
p >>= 8;
Type = (p & 0xff);
p >>= 8;
Id = (p);
*/
}
CEntityId (const CEntityId &a)
{
FullId = a.FullId;
/*
DynamicId = a.DynamicId;
CreatorId = a.CreatorId;
Type = a.Type;
Id = a.Id;
*/
}
///fill from read stream.
CEntityId (NLMISC::IStream &is)
{
is.serial(FullId);
/*
uint64 p;
is.serial(p);
DynamicId = (p & 0xff);
p >>= 8;
CreatorId = (p & 0xff);
p >>= 8;
Type = (p & 0xff);
p >>= 8;
Id = p;
*/
}
explicit CEntityId (const std::string &str)
{
fromString(str.c_str());
}
explicit CEntityId (const char *str)
{
CEntityId ();
fromString(str);
}
//@}
// ---------------------------------------------------------------------------------
// accessors
/// Get the full id
uint64 getRawId() const
{
return FullId;
/*
return (uint64)*this;
*/
}
/// Get the local entity number
uint64 getShortId() const
{
return DetailedId.Id;
}
/// Set the local entity number
void setShortId( uint64 shortId )
{
DetailedId.Id = shortId;
}
/// Get the variable routing info
uint8 getDynamicId() const
{
return DetailedId.DynamicId;
}
/// Set the variable routing info
void setDynamicId( uint8 dynId )
{
DetailedId.DynamicId = dynId;
}
/// Get the persistent creator id
uint8 getCreatorId() const
{
return DetailedId.CreatorId;
}
/// Set the persistent creator id
void setCreatorId( uint8 creatorId )
{
DetailedId.CreatorId = creatorId;
}
/// Get the entity type
uint8 getType() const
{
return (uint8)DetailedId.Type;
}
/// Set the entity type
void setType( uint8 type )
{
DetailedId.Type = type;
}
/// Get the persistent part of the entity id (the dynamic part in the returned id is 0)
uint64 getUniqueId() const
{
CEntityId id;
id.FullId = FullId;
id.DetailedId.DynamicId = 0;
return id.FullId;
}
/// Test if the entity id is Unknown
bool isUnknownId() const
{
return DetailedId.Type == UNKNOWN_TYPE;
}
// ---------------------------------------------------------------------------------
// operators
///\name comparison of two CEntityId.
//@{
bool operator == (const CEntityId &a) const
// virtual bool operator == (const CEntityId &a) const
{
CEntityId testId ( FullId ^ a.FullId );
testId.DetailedId.DynamicId = 0;
return testId.FullId == 0;
/*
return (Id == a.DetailedId.Id && DetailedId.CreatorId == a.DetailedId.CreatorId && DetailedId.Type == a.DetailedId.Type);
*/
}
bool operator != (const CEntityId &a) const
{
return !((*this) == a);
}
bool operator < (const CEntityId &a) const
// virtual bool operator < (const CEntityId &a) const
{
return getUniqueId() < a.getUniqueId();
/*
if (Type < a.Type)
{
return true;
}
else if (Type == a.Type)
{
if (Id < a.Id)
{
return true;
}
else if (Id == a.Id)
{
return (CreatorId < a.CreatorId);
}
}
return false;
*/
}
bool operator > (const CEntityId &a) const
// virtual bool operator > (const CEntityId &a) const
{
return getUniqueId() > a.getUniqueId();
/*
if (Type > a.Type)
{
return true;
}
else if (Type == a.Type)
{
if (Id > a.Id)
{
return true;
}
else if (Id == a.Id)
{
return (CreatorId > a.CreatorId);
}
}
// lesser
return false;
*/
}
//@}
const CEntityId &operator ++(int)
{
if(DetailedId.Id < MaxEntityId)
{
DetailedId.Id ++;
}
else
{
nlerror ("CEntityId looped (max was %" NL_I64 "d", MaxEntityId);
}
return *this;
}
const CEntityId &operator = (const CEntityId &a)
{
FullId = a.FullId;
/*
DynamicId = a.DynamicId;
CreatorId = a.CreatorId;
Type = a.Type;
Id = a.Id;
*/
return *this;
}
const CEntityId &operator = (uint64 p)
{
FullId = p;
/*
DynamicId = (uint64)(p & 0xff);
p >>= 8;
CreatorId = (uint64)(p & 0xff);
p >>= 8;
Type = (uint64)(p & 0xff);
p >>= 8;
Id = (uint64)(p);
*/
return *this;
}
// ---------------------------------------------------------------------------------
// other methods...
uint64 asUint64()const
{
return FullId;
}
/* operator uint64 () const
{
return FullId;
uint64 p = Id;
p <<= 8;
p |= (uint64)Type;
p <<= 8;
p |= (uint64)CreatorId;
p <<= 8;
p |= (uint64)DynamicId;
return p;
}
*/
// ---------------------------------------------------------------------------------
// loading, saving, serialising...
/// Save the Id into an output stream.
void save(NLMISC::IStream &os)
// virtual void save(NLMISC::IStream &os)
{
os.serial(FullId);
/*
uint64 p = Id;
p <<= 8;
p |= (uint64)Type;
p <<= 8;
p |= (uint64)CreatorId;
p <<= 8;
p |= (uint64)DynamicId;
os.serial(p);
*/
}
/// Load the number from an input stream.
void load(NLMISC::IStream &is)
// virtual void load(NLMISC::IStream &is)
{
is.serial(FullId);
/*
uint64 p;
is.serial(p);
DynamicId = (uint64)(p & 0xff);
p >>= 8;
CreatorId = (uint64)(p & 0xff);
p >>= 8;
Type = (uint64)(p & 0xff);
p >>= 8;
Id = (uint64)(p);
*/
}
void serial (NLMISC::IStream &f) throw (NLMISC::EStream)
// virtual void serial (NLMISC::IStream &f) throw (NLMISC::EStream)
{
if (f.isReading ())
{
load (f);
}
else
{
save (f);
}
}
// ---------------------------------------------------------------------------------
// string convertions
/// return a string in form "(a:b:c:d)" where a,b,c,d are components of entity id.
std::string toString() const
{
std::string ident;
ident.reserve(25);
ident+='(';
getDebugString (ident);
ident+=')';
return ident;
}
/// Read from a debug string, use the same format as toString() (id:type:creator:dynamic) in hexadecimal
void fromString(const char *str)
// virtual void fromString(const char *str)
{
uint64 id;
uint type;
uint creatorId;
uint dynamicId;
if (sscanf(str, "(%" NL_I64 "x:%x:%x:%x)", &id, &type, &creatorId, &dynamicId) != 4)
{
*this = Unknown;
return;
}
DetailedId.Id = id;
DetailedId.Type = type;
DetailedId.CreatorId = creatorId;
DetailedId.DynamicId = dynamicId;
}
/// Have a debug string.
void getDebugString(std::string &str) const
// virtual void getDebugString(std::string &str) const
{
str.reserve(str.size()+24);
char b[256];
memset(b,0,255);
memset(b,'0',19);
sint n;
uint64 x = DetailedId.Id;
char baseTable[] = "0123456789abcdef";
for(n = 10; n < 20; n ++)
{
b[19 - n] = baseTable[(x & 15)];
x >>= 4;
}
b[19 - 9] = ':';
x = DetailedId.Type;
for(n = 7; n < 9; n ++)
{
b[19 - n] = baseTable[(x & 15)];
x >>= 4;
}
b[19 - 6] = ':';
x = DetailedId.CreatorId;
for(n = 4; n < 6; n ++)
{
b[19 - n] = baseTable[(x & 15)];
x >>= 4;
}
b[19 - 3] = ':';
x = DetailedId.DynamicId;
for(n = 1; n < 3; n ++)
{
b[19 - n] = baseTable[(x & 15)];
x >>= 4;
}
str += "0x";
str += b;
}
/*
/// \name NLMISC::IStreamable method.
//@{
std::string getClassName ()
// virtual std::string getClassName ()
{
return std::string ("<CEntityId>");
}
//@}
*/
// friend std::stringstream &operator << (std::stringstream &__os, const CEntityId &__t);
};
/**
* a generic hasher for entities
*/
/*class CEidHash
{
public:
size_t operator () ( const NLMISC::CEntityId & id ) const
{
uint64 hash64 = id.getUniqueId();
return size_t(hash64) ^ size_t( hash64 >> 32 );
return (uint32)id.getShortId();
}
};*/
// Traits for hash_map using CEntityId
struct CEntityIdHashMapTraits
{
enum { bucket_size = 4, min_buckets = 8 };
CEntityIdHashMapTraits() { }
size_t operator() (const NLMISC::CEntityId &id ) const
{
uint64 hash64 = id.getUniqueId();
#ifdef HAVE_X86_64
return (size_t)hash64;
#else
return (size_t)hash64 ^ (size_t)(hash64 >> 32);
#endif
//return size_t(id.getShortId());
}
bool operator() (const NLMISC::CEntityId &id1, const NLMISC::CEntityId &id2) const
{
return id1.getShortId() < id2.getShortId();
}
};
/*inline std::stringstream &operator << (std::stringstream &__os, const CEntityId &__t)
{
__os << __t.toString ();
return __os;
}*/
} // NLMISC
#endif // NL_ENTITY_ID_H
/* End of entity_id.h */