623 lines
22 KiB
C
623 lines
22 KiB
C
|
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
|
||
|
// 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_DATA_SET_BASE_H
|
||
|
#define NL_DATA_SET_BASE_H
|
||
|
|
||
|
#include <nel/misc/types_nl.h>
|
||
|
#include <nel/misc/time_nl.h>
|
||
|
#include <nel/misc/entity_id.h>
|
||
|
#include <nel/misc/sheet_id.h>
|
||
|
#include <nel/misc/bit_set.h>
|
||
|
#include <nel/misc/mem_stream.h>
|
||
|
#include <nel/net/service.h>
|
||
|
#include <nel/georges/u_form.h>
|
||
|
|
||
|
#include "tick_event_handler.h"
|
||
|
#include "base_types.h"
|
||
|
|
||
|
#include <vector>
|
||
|
#include <map>
|
||
|
|
||
|
|
||
|
extern NLMISC::CMemDisplayer *TmpDebugDisplayer;
|
||
|
|
||
|
|
||
|
// Known types of property value
|
||
|
enum TTypeOfProp { TypeUint8, TypeSint8, TypeUint16, TypeSint16, TypeUint32, TypeSint32, TypeUint64, TypeSint64, TypeFloat, TypeDouble, TypeBool, TypeCEntityId, TypeUnknown };
|
||
|
|
||
|
|
||
|
// Possibles sizes of row
|
||
|
enum TSizeOfRow { Row32, Row16, Row8 };
|
||
|
|
||
|
|
||
|
const std::string ENTITYID_PREFIX = "_EId_";
|
||
|
const sint LENGTH_OF_ENTITYID_PREFIX = 5;
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Exception class for the mirror system
|
||
|
*/
|
||
|
class EMirror : public NLMISC::Exception
|
||
|
{
|
||
|
};
|
||
|
|
||
|
|
||
|
const sint InvalidSMId = -1;
|
||
|
|
||
|
|
||
|
// Get dataset in sheetid map
|
||
|
#define GET_SDATASET(it) ((*it).second)
|
||
|
|
||
|
// Get dataset in name map
|
||
|
#define GET_NDATASET(it) (*((*it).second))
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Structure of a dataset for loading
|
||
|
*/
|
||
|
class TDataSetSheet
|
||
|
{
|
||
|
public:
|
||
|
|
||
|
/// Read the sheet
|
||
|
void readGeorges( const NLMISC::CSmartPtr<NLGEORGES::UForm> &form, const NLMISC::CSheetId &sheetId );
|
||
|
|
||
|
/// Serial (for fast binary sheet loading)
|
||
|
void serial( NLMISC::IStream& s );
|
||
|
|
||
|
/// Return the version of this class, increments this value when the content of this class changed
|
||
|
static uint getVersion () { return 3; }
|
||
|
|
||
|
/// Void
|
||
|
void removed() {}
|
||
|
|
||
|
/// Add a property which is not listed in .dataset files
|
||
|
void addACustomProperty( std::string& name, TTypeOfProp typeOfProp/*, sint8 weight*/, bool propIsList )
|
||
|
{
|
||
|
PropertyNames.push_back( name );
|
||
|
PropIndexToType.push_back( typeOfProp );
|
||
|
//Weights.push_back( weight );
|
||
|
PropIsList.push_back( propIsList );
|
||
|
}
|
||
|
|
||
|
/// Return the dataset size to use. If found in the .cfg, use the value of the property DataSetSize + DataSetName., otherwise use the value in the sheet.
|
||
|
TDataSetIndex getConfigDataSetSize() const;
|
||
|
|
||
|
std::string DataSetName;
|
||
|
|
||
|
TPropertyIndex NbProperties;
|
||
|
|
||
|
uint32 MaxNbRows;
|
||
|
|
||
|
std::vector<std::string> PropertyNames;
|
||
|
|
||
|
std::vector<TTypeOfProp> PropIndexToType;
|
||
|
|
||
|
//std::vector<sint8> Weights; // not used: currently all property values are always sent
|
||
|
|
||
|
std::vector<bool> PropIsList;
|
||
|
|
||
|
std::vector<uint8> EntityTypesFilter;
|
||
|
};
|
||
|
|
||
|
|
||
|
/*
|
||
|
* TSDataSetSheets
|
||
|
*/
|
||
|
typedef std::map<NLMISC::CSheetId, TDataSetSheet> TSDataSetSheets;
|
||
|
|
||
|
// TServiceId (8 bits)
|
||
|
//typedef uint8 TServiceId8;
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Pointers for accessing the values and the change timestamps of a specific property
|
||
|
*/
|
||
|
struct TPropertyValueArrayHeader
|
||
|
{
|
||
|
void reset()
|
||
|
{
|
||
|
Values = NULL;
|
||
|
ChangeTimestamps = NULL;
|
||
|
#ifdef STORE_CHANGE_SERVICEIDS
|
||
|
ChangeServiceIds = NULL;
|
||
|
#endif
|
||
|
ListCellContainer = NULL;
|
||
|
DataTypeSize = 0;
|
||
|
//#ifdef NL_DEBUG
|
||
|
IsReadOnly = false;
|
||
|
IsMonitored = false;
|
||
|
//#endif
|
||
|
}
|
||
|
|
||
|
/// Pointer on the values(points into shared memory)
|
||
|
void *Values;
|
||
|
|
||
|
/// Pointer on the timestamps (points into shared memory)
|
||
|
NLMISC::TGameCycle *ChangeTimestamps;
|
||
|
|
||
|
#ifdef STORE_CHANGE_SERVICEIDS
|
||
|
/// Pointer on the change service ids (points into shared memory)
|
||
|
NLNET::TServiceId8 *ChangeServiceIds;
|
||
|
#endif
|
||
|
|
||
|
/// Pointer on the list container (points into shared memory if the property is a list property)
|
||
|
void *ListCellContainer;
|
||
|
|
||
|
/// Return the location of the index of the first free cell (beginning the list of free cells)
|
||
|
static TSharedListRow * getFreeCellsFront( void *listCellContainer ) { return (TSharedListRow*)(((uint8*)listCellContainer) - sizeof(TSharedListRow)); }
|
||
|
|
||
|
/// Data type size of the property for type checking in debug mode
|
||
|
uint32 DataTypeSize;
|
||
|
|
||
|
//#ifdef NL_DEBUG
|
||
|
/// Flag to check if the property is read-only
|
||
|
bool IsReadOnly;
|
||
|
|
||
|
/// Flag to monitor the assignment of the values
|
||
|
bool IsMonitored;
|
||
|
//#endif
|
||
|
};
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Pointers for accessing the entity ids and the booleans to check if there are still online or if they have been removed
|
||
|
*/
|
||
|
struct TEntityIdArrayHeader
|
||
|
{
|
||
|
void reset()
|
||
|
{
|
||
|
EntityIds = NULL;
|
||
|
OnlineBitfieldPt = NULL;
|
||
|
OnlineTimestamps = NULL;
|
||
|
Counts = NULL;
|
||
|
SpawnerServiceIds = NULL;
|
||
|
}
|
||
|
|
||
|
/// Set the service responsible for managing the entity (spawning/despawning)
|
||
|
void setSpawnerServiceId( TDataSetIndex entityIndex, NLNET::TServiceId serviceId )
|
||
|
{
|
||
|
SpawnerServiceIds[entityIndex] = NLNET::TServiceId8(serviceId);
|
||
|
}
|
||
|
|
||
|
/// Test if online or removed
|
||
|
bool isOnline( TDataSetIndex entityIndex ) const
|
||
|
{
|
||
|
//nlassert(OnlineBitfieldPt);
|
||
|
//nlassert(entityIndex>=0 && entityIndex<NumBits);
|
||
|
uint32 mask = entityIndex & (NL_BITLEN-1);
|
||
|
mask = 1 << mask;
|
||
|
return (OnlineBitfieldPt[entityIndex >> NL_BITLEN_SHIFT] & mask) != 0;
|
||
|
}
|
||
|
|
||
|
/// Mark as online or removed, and update the online timestamp
|
||
|
void setOnline( TDataSetIndex entityIndex, bool value )
|
||
|
{
|
||
|
//nlassert(OnlineBitfieldPt);
|
||
|
//nlassert(entityIndex>=0 && entityIndex<NumBits);
|
||
|
uint32 mask= entityIndex & (NL_BITLEN-1);
|
||
|
mask = 1 << mask;
|
||
|
if ( value )
|
||
|
OnlineBitfieldPt[entityIndex >> NL_BITLEN_SHIFT] |= mask ;
|
||
|
else
|
||
|
OnlineBitfieldPt[entityIndex >> NL_BITLEN_SHIFT] &= ~mask;
|
||
|
|
||
|
// Timestamp the changing of online state
|
||
|
updateOnlineTimestamp( entityIndex );
|
||
|
}
|
||
|
|
||
|
// Check that the same service created and set online/offline the entity
|
||
|
void checkSpawnerId( TDataSetIndex entityIndex, NLNET::TServiceId serviceId ) const
|
||
|
{
|
||
|
nlassert( SpawnerServiceIds[entityIndex] == NLNET::TServiceId8(serviceId) );
|
||
|
}
|
||
|
|
||
|
/// Update the online timestamp of an entity. Done when creating an entity, when setting/unsetting it online
|
||
|
void updateOnlineTimestamp( TDataSetIndex entityIndex )
|
||
|
{
|
||
|
OnlineTimestamps[entityIndex] = CTickEventHandler::getGameCycle();
|
||
|
}
|
||
|
|
||
|
#ifdef CHECK_DATASETROW_VALIDITY
|
||
|
/// Check if the row has not been reassigned and invalidated the dataset row object
|
||
|
bool isDataSetRowStillValid( const TDataSetRow& dataSetRow ) const
|
||
|
{
|
||
|
return (dataSetRow.counter() == 0) // no removal counter in the object
|
||
|
#ifdef NL_DEBUG
|
||
|
// check if the row has not been reassigned to another entity;
|
||
|
// if the entity has left, check if the entity timestamp is not too old
|
||
|
|| (Counts[dataSetRow.getIndex()] == dataSetRow.counter())
|
||
|
|| ( (Counts[dataSetRow.getIndex()] == dataSetRow.counter()+1) &&
|
||
|
(CTickEventHandler::getGameCycle() < OnlineTimestamps[dataSetRow.getIndex()]+15) )
|
||
|
|| ( ((Counts[dataSetRow.getIndex()] == 1) && (dataSetRow.counter()==255)) && // 0 is skipped
|
||
|
(CTickEventHandler::getGameCycle() < OnlineTimestamps[dataSetRow.getIndex()]+15) );
|
||
|
#else
|
||
|
// check if the row has not been reassigned to another entity (but it can have been deleted)
|
||
|
|| (Counts[dataSetRow.getIndex()] == dataSetRow.counter())
|
||
|
|| (Counts[dataSetRow.getIndex()] == dataSetRow.counter()+1)
|
||
|
|| ( (Counts[dataSetRow.getIndex()] == 1) && (dataSetRow.counter()==255) ); // 0 is skipped
|
||
|
#endif
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
/// The entity ids
|
||
|
NLMISC::CEntityId *EntityIds;
|
||
|
|
||
|
/// Theses bits tell whether a row is currently bound to an entity or not
|
||
|
uint32 *OnlineBitfieldPt;
|
||
|
|
||
|
/// Timestamp for entity binding (adding/removing)
|
||
|
NLMISC::TGameCycle *OnlineTimestamps;
|
||
|
|
||
|
/// These counters are there to check if we don't forget to remove our row references when entities leave
|
||
|
uint8 *Counts;
|
||
|
|
||
|
/// These service ids tell which service is responsible for managing each entity.
|
||
|
NLNET::TServiceId8 *SpawnerServiceIds;
|
||
|
};
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Pointers to entity ids and property values of one container, corresponding to one dataset.
|
||
|
* Data pointed to may be in shared memory.
|
||
|
*
|
||
|
* Note: of course, pointers can't be placed in shared memory.
|
||
|
*/
|
||
|
struct TPropertyContainerHeader
|
||
|
{
|
||
|
/// Constructor
|
||
|
TPropertyContainerHeader() {}
|
||
|
|
||
|
/// Reset
|
||
|
void init( TPropertyIndex length )
|
||
|
{
|
||
|
PropertyValueArrays.resize( length );
|
||
|
for ( sint i=0; i!=length; ++i )
|
||
|
{
|
||
|
PropertyValueArrays[i].reset();
|
||
|
}
|
||
|
EntityIdArray.reset();
|
||
|
}
|
||
|
|
||
|
/// Array (indexed by TPropertyIndex) of property value arrays (indexed by TDataSetRow)
|
||
|
std::vector< TPropertyValueArrayHeader > PropertyValueArrays;
|
||
|
|
||
|
/// Array (indexed by TDataSetRow) of entity ids
|
||
|
TEntityIdArrayHeader EntityIdArray;
|
||
|
};
|
||
|
|
||
|
typedef CHashMap< NLMISC::CEntityId, TDataSetIndex, NLMISC::CEntityIdHashMapTraits > TEntityIdToEntityIndexMap;
|
||
|
#define GET_ENTITY_INDEX(it) ((*it).second)
|
||
|
|
||
|
|
||
|
enum TEntityTrackerIndex { ADDING = 0, REMOVING = 1 };
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Base class for CMirroredDataSet and CDataSetMS.
|
||
|
*
|
||
|
* \author Olivier Cado
|
||
|
* \author Nevrax France
|
||
|
* \date 2002
|
||
|
*/
|
||
|
class CDataSetBase
|
||
|
{
|
||
|
public:
|
||
|
|
||
|
/// Constructor
|
||
|
CDataSetBase();
|
||
|
|
||
|
/// Initialize
|
||
|
void init( const NLMISC::CSheetId& sheetId, const TDataSetSheet& properties );
|
||
|
|
||
|
/// Return the name of the dataset
|
||
|
const std::string& name() const { return _DataSetName; }
|
||
|
|
||
|
/// Return the sheet id of the dataset
|
||
|
const NLMISC::CSheetId& sheetId() const { return _SheetId; }
|
||
|
|
||
|
/// Return the maximum number of rows (or entities)
|
||
|
TDataSetIndex maxNbRows() const { return _MaxNbRows; }
|
||
|
|
||
|
/// Return the number of properties in the dataset
|
||
|
TPropertyIndex nbProperties() const { return _PropIndexToType.size(); }
|
||
|
|
||
|
/// Return the type of the specified property
|
||
|
TTypeOfProp getPropType( TPropertyIndex propIndex ) const
|
||
|
{
|
||
|
if ( ((uint32)propIndex) < _PropIndexToType.size() )
|
||
|
{
|
||
|
return _PropIndexToType[propIndex];
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//#ifdef NL_DEBUG
|
||
|
nlwarning( "MIRROR: getPropType(): Property index outside of dataset" );
|
||
|
//#endif
|
||
|
return TypeUnknown;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// Return the size of a value of the specified property (in bytes)
|
||
|
uint32 getDataSizeOfProp( TPropertyIndex propIndex ) const
|
||
|
{
|
||
|
#ifndef FAST_MIRROR
|
||
|
nlassert( (uint)propIndex < (uint)nbProperties() );
|
||
|
#endif
|
||
|
return _DataSizeByProp[propIndex];
|
||
|
}
|
||
|
|
||
|
// /// Serialize out a datasetrow, depending on the dataset
|
||
|
// void serialOutRow( NLMISC::CMemStream& msgout, const TDataSetRow& entityIndex ) const
|
||
|
// {
|
||
|
// msgout.fastWrite( entityIndex );
|
||
|
//
|
||
|
// //switch( _SizeOfRow )
|
||
|
// //{
|
||
|
// //case Row32 : msgout.fastWrite( entityIndex ); break;
|
||
|
// //case Row16 : { TDataSetRow16 row16 = (TDataSetRow16)entityIndex.getIndex(); msgout.fastWrite( row16 ); /*nldebug( "Written %hu", row16 );*/ break; }
|
||
|
// //case Row8 : { TDataSetRow8 row8 = (TDataSetRow8)entityIndex.getIndex(); msgout.fastWrite( row8 ); break; }
|
||
|
// //default : ;
|
||
|
// //}
|
||
|
// }
|
||
|
|
||
|
// /// Serialize in a datasetrow, depending on the dataset
|
||
|
// void serialInRow( NLMISC::CMemStream& msgin, TDataSetRow& entityIndex ) const
|
||
|
// {
|
||
|
// msgin.fastRead( entityIndex );
|
||
|
//
|
||
|
// switch( _SizeOfRow )
|
||
|
// {
|
||
|
// case Row32 : msgin.fastRead( entityIndex ); break;
|
||
|
// case Row16 :
|
||
|
// {
|
||
|
// TDataSetRow16 row16;
|
||
|
// msgin.fastRead( row16 );
|
||
|
// //nldebug( "Read %hu", row16 );
|
||
|
// if ( row16 == (TDataSetRow16)~0 )
|
||
|
// entityIndex = TDataSetRow();
|
||
|
// else
|
||
|
// entityIndex = (TDataSetRow)row16;
|
||
|
// break;
|
||
|
// }
|
||
|
// case Row8 :
|
||
|
// {
|
||
|
// TDataSetRow8 row8;
|
||
|
// msgin.fastRead( row8 );
|
||
|
// if ( row8 == (TDataSetRow8)~0 )
|
||
|
// entityIndex = TDataSetRow();
|
||
|
// else
|
||
|
// entityIndex = (TDataSetRow)row8;
|
||
|
// break;
|
||
|
// }
|
||
|
// //default : ;
|
||
|
// }
|
||
|
// }
|
||
|
|
||
|
// PUBLIC because template friend classes are not supported
|
||
|
/// Return the pointer to the property value
|
||
|
template <class T>
|
||
|
void getPropPointer( T **ppt, TPropertyIndex propIndex, const TDataSetRow& entityIndex ) const
|
||
|
{
|
||
|
#ifndef FAST_MIRROR
|
||
|
nlassert( (propIndex != INVALID_PROPERTY_INDEX) && (propIndex < (TPropertyIndex)_PropertyContainer.PropertyValueArrays.size()) ); // Wrong property
|
||
|
nlassert( _PropertyContainer.PropertyValueArrays[propIndex].Values ); // Pointer not initialized
|
||
|
nlassertex( entityIndex.getIndex() < (uint32)maxNbRows(), ("E%d",entityIndex.getIndex()) ); // Wrong entity (including INVALID_ENTITY_INDEX and LAST_CHANGED)
|
||
|
checkTemplateSize( sizeof(T), propIndex, entityIndex ); // Wrong template type
|
||
|
#endif
|
||
|
#ifdef CHECK_DATASETROW_VALIDITY
|
||
|
//nlassertex( isDataSetRowStillValid( entityIndex ), ("E%u GIVEN:%hu_%u REAL:%hu_%u", entityIndex.getIndex(), entityIndex.counter(), CTickEventHandler::getGameCycle(), _PropertyContainer.EntityIdArray.Counts[entityIndex.getIndex()], _PropertyContainer.EntityIdArray.OnlineTimestamps[entityIndex.getIndex()] ) ); // entity not removed
|
||
|
/*if ( ! isDataSetRowStillValid( entityIndex ) ) // entity not removed
|
||
|
{
|
||
|
nlwarning( "isDataSetRowStillValid E%u GIVEN:%hu_%u REAL:%hu_%u", entityIndex.getIndex(), entityIndex.counter(), CTickEventHandler::getGameCycle(), _PropertyContainer.EntityIdArray.Counts[entityIndex.getIndex()], _PropertyContainer.EntityIdArray.OnlineTimestamps[entityIndex.getIndex()] );
|
||
|
if ( TmpDebugDisplayer )
|
||
|
TmpDebugDisplayer->write( NLMISC::DebugLog );
|
||
|
nlstop;
|
||
|
}*/
|
||
|
#endif
|
||
|
*ppt = &(((T*)(_PropertyContainer.PropertyValueArrays[propIndex].Values))[entityIndex.getIndex()]);
|
||
|
}
|
||
|
|
||
|
// PUBLIC because template friend classes are not supported
|
||
|
/// Return the pointer to the property value
|
||
|
template <class T>
|
||
|
void getPropPointerForList( TSharedListRow **ppt, TPropertyIndex propIndex, const TDataSetRow& entityIndex, T* typeHint ) const
|
||
|
{
|
||
|
#ifndef FAST_MIRROR
|
||
|
nlassert( (propIndex != INVALID_PROPERTY_INDEX) && (propIndex < (TPropertyIndex)_PropertyContainer.PropertyValueArrays.size()) ); // Wrong property
|
||
|
nlassert( _PropertyContainer.PropertyValueArrays[propIndex].Values ); // Pointer not initialized
|
||
|
nlassertex( entityIndex.getIndex() < (uint32)maxNbRows(), ("E%d",entityIndex.getIndex()) ); // Wrong entity (including INVALID_ENTITY_INDEX and LAST_CHANGED)
|
||
|
// Following test commented out, because property actually in row is not the size of the property in list!
|
||
|
checkTemplateSize( sizeof(T), propIndex, entityIndex ); // Wrong template type
|
||
|
#endif
|
||
|
#ifdef CHECK_DATASETROW_VALIDITY
|
||
|
//nlassertex( isDataSetRowStillValid( entityIndex ), ("E%u GIVEN:%hu_%u REAL:%hu_%u", entityIndex.getIndex(), entityIndex.counter(), CTickEventHandler::getGameCycle(), _PropertyContainer.EntityIdArray.Counts[entityIndex.getIndex()], _PropertyContainer.EntityIdArray.OnlineTimestamps[entityIndex.getIndex()] ) ); // entity not removed
|
||
|
/*if ( ! isDataSetRowStillValid( entityIndex ) ) // entity not removed
|
||
|
{
|
||
|
nlwarning( "isDataSetRowStillValid E%u GIVEN:%hu_%u REAL:%hu_%u", entityIndex.getIndex(), entityIndex.counter(), CTickEventHandler::getGameCycle(), _PropertyContainer.EntityIdArray.Counts[entityIndex.getIndex()], _PropertyContainer.EntityIdArray.OnlineTimestamps[entityIndex.getIndex()] );
|
||
|
if ( TmpDebugDisplayer )
|
||
|
TmpDebugDisplayer->write( NLMISC::DebugLog );
|
||
|
nlstop;
|
||
|
}*/
|
||
|
#endif
|
||
|
*ppt = &(((TSharedListRow*)(_PropertyContainer.PropertyValueArrays[propIndex].Values))[entityIndex.getIndex()]);
|
||
|
}
|
||
|
|
||
|
#ifdef CHECK_DATASETROW_VALIDITY
|
||
|
/// Return false if the row has been invalidated (reassigned)
|
||
|
bool isDataSetRowStillValid( const TDataSetRow& dataSetRow ) const
|
||
|
{
|
||
|
return _PropertyContainer.EntityIdArray.isDataSetRowStillValid( dataSetRow );
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
/// Return the current removal counter of a row
|
||
|
uint8 getBindingCounter( TDataSetIndex entityIndex ) const
|
||
|
{
|
||
|
return _PropertyContainer.EntityIdArray.Counts[entityIndex];
|
||
|
}
|
||
|
|
||
|
/// Check that the template argument T passed to CMirrorPropValue<T> has the right size (debug feature)
|
||
|
void checkTemplateSize( uint32 passedSize, TPropertyIndex propIndex, const TDataSetRow& entityIndex ) const;
|
||
|
|
||
|
//#ifdef NL_DEBUG
|
||
|
/// Return true if the specified property must be read-only (debug feature)
|
||
|
bool isReadOnly( TPropertyIndex propIndex ) const
|
||
|
{
|
||
|
return _PropertyContainer.PropertyValueArrays[propIndex].IsReadOnly;
|
||
|
}
|
||
|
|
||
|
/// Return true if the specified property must be monitored (debug feature)
|
||
|
bool isMonitored( TPropertyIndex propIndex ) const
|
||
|
{
|
||
|
return _PropertyContainer.PropertyValueArrays[propIndex].IsMonitored;
|
||
|
}
|
||
|
//#endif
|
||
|
|
||
|
/// Return the pointer of the cell container for a list property
|
||
|
void *getListCellContainer( TPropertyIndex propIndex ) const
|
||
|
{
|
||
|
#ifndef FAST_MIRROR
|
||
|
nlassert( (propIndex != INVALID_PROPERTY_INDEX) && (propIndex < (TPropertyIndex)_PropertyContainer.PropertyValueArrays.size()) ); // Wrong property
|
||
|
#endif
|
||
|
return _PropertyContainer.PropertyValueArrays[propIndex].ListCellContainer;
|
||
|
}
|
||
|
|
||
|
/// Return the timestamp of a property
|
||
|
NLMISC::TGameCycle getChangeTimestamp( TPropertyIndex propIndex, const TDataSetRow& entityIndex ) const
|
||
|
{
|
||
|
#ifndef FAST_MIRROR
|
||
|
nlassert( (propIndex != INVALID_PROPERTY_INDEX) && (propIndex < (TPropertyIndex)_PropertyContainer.PropertyValueArrays.size()) ); // Wrong property
|
||
|
nlassert( _PropertyContainer.PropertyValueArrays[propIndex].ChangeTimestamps ); // Pointer not initialized
|
||
|
nlassertex( entityIndex.getIndex() < (uint32)maxNbRows(), ("E%d",entityIndex.getIndex()) ); // Wrong entity (including INVALID_ENTITY_INDEX and LAST_CHANGED)
|
||
|
#endif
|
||
|
return _PropertyContainer.PropertyValueArrays[propIndex].ChangeTimestamps[entityIndex.getIndex()];
|
||
|
}
|
||
|
|
||
|
#ifdef STORE_CHANGE_SERVICEIDS
|
||
|
/// Return the id of the latest service who changed the property value
|
||
|
NLNET::TServiceId8 getWriterServiceId( TPropertyIndex propIndex, const TDataSetRow& entityIndex ) const
|
||
|
{
|
||
|
#ifndef FAST_MIRROR
|
||
|
nlassert( (propIndex != INVALID_PROPERTY_INDEX) && (propIndex < (TPropertyIndex)_PropertyContainer.PropertyValueArrays.size()) ); // Wrong property
|
||
|
nlassert( _PropertyContainer.PropertyValueArrays[propIndex].ChangeServiceIds ); // Pointer not initialized
|
||
|
nlassertex( entityIndex.getIndex() < (uint32)maxNbRows(), ("E%d",entityIndex.getIndex()) ); // Wrong entity (including INVALID_ENTITY_INDEX and LAST_CHANGED)
|
||
|
#endif
|
||
|
return _PropertyContainer.PropertyValueArrays[propIndex].ChangeServiceIds[entityIndex.getIndex()];
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
/// Return true if the row is still used
|
||
|
bool isOnline( const TDataSetRow& entityIndex ) const
|
||
|
{
|
||
|
#ifndef FAST_MIRROR
|
||
|
nlassert( entityIndex.isValid() );
|
||
|
#endif
|
||
|
return _PropertyContainer.EntityIdArray.isOnline( entityIndex.getIndex() );
|
||
|
}
|
||
|
|
||
|
/// Return the gamecycle of adding or removing
|
||
|
NLMISC::TGameCycle getOnlineTimestamp( const TDataSetRow& entityIndex ) const
|
||
|
{
|
||
|
#ifndef FAST_MIRROR
|
||
|
nlassert( entityIndex.isValid() );
|
||
|
#endif
|
||
|
return _PropertyContainer.EntityIdArray.OnlineTimestamps[entityIndex.getIndex()];
|
||
|
}
|
||
|
|
||
|
protected:
|
||
|
|
||
|
/** Fill property info.
|
||
|
* When the flag initValues is set:
|
||
|
* If the counts must be initialised from a remote MS, use the vector ptCountsToSet (it will be read
|
||
|
* then deleted) and timestamp, otherwise set NULL.
|
||
|
* segmentSize is used only if initValues is true.
|
||
|
* If propName is the special entityId property, the behaviour is different (propName need not exist)
|
||
|
*/
|
||
|
void setPropertyPointer( std::string& propName, TPropertyIndex propIndex, void *segmentPt, bool initValues, uint32 dataTypeSize, bool isReadOnly, bool mustMonitorAssignment, std::vector<uint8> *ptCountsToSet=NULL, NLMISC::TGameCycle timestamp=0, uint32 segmentSize=~0 );
|
||
|
|
||
|
/// Get the property index corresponding to the specified property name in the dataset
|
||
|
TPropertyIndex getPropertyIndex( const std::string& propName ) const;
|
||
|
|
||
|
/// Init _DataSizeByProp
|
||
|
void fillDataSizeByProp();
|
||
|
|
||
|
/// Return the id of the service who spawned the entity (even after it was despawned, while the row is not reassigned)
|
||
|
NLNET::TServiceId8 getSpawnerServiceId( TDataSetIndex entityIndex ) const
|
||
|
{
|
||
|
return _PropertyContainer.EntityIdArray.SpawnerServiceIds[entityIndex];
|
||
|
}
|
||
|
|
||
|
TPropertyContainerHeader _PropertyContainer;
|
||
|
|
||
|
// Name of the dataset
|
||
|
std::string _DataSetName;
|
||
|
|
||
|
// Sheet id of the data
|
||
|
NLMISC::CSheetId _SheetId;
|
||
|
|
||
|
/// Maximum number of rows
|
||
|
TDataSetIndex _MaxNbRows;
|
||
|
|
||
|
// Size of datasetrow needed
|
||
|
//TSizeOfRow _SizeOfRow;
|
||
|
|
||
|
/// Indexed by TPropertyIndex
|
||
|
std::vector< TTypeOfProp > _PropIndexToType;
|
||
|
|
||
|
/// Indexed by TPropertyIndex
|
||
|
std::vector< uint32 > _DataSizeByProp;
|
||
|
|
||
|
/// Indexed by TPropertyIndex
|
||
|
std::vector<bool> _PropIsList;
|
||
|
|
||
|
/// Entity types allowed in this dataset
|
||
|
std::vector<uint8> _EntityTypesFilter;
|
||
|
|
||
|
};
|
||
|
|
||
|
|
||
|
/**
|
||
|
* List of entity types accepted in a tracker.
|
||
|
*
|
||
|
* \author Olivier Cado
|
||
|
* \author Nevrax France
|
||
|
* \date 2004
|
||
|
*/
|
||
|
/*class CEntityTrackerFilter
|
||
|
{
|
||
|
public:
|
||
|
|
||
|
/// Add an entity type into the list of accepted entity types (no duplicate check)
|
||
|
void addAcceptedEntityType( uint8 entityType ) { _AcceptedTypes.push_back( entityType ); }
|
||
|
|
||
|
/// Test if an entity type is in the list
|
||
|
void isAccepted( uint8 entityType ) { return (find( _AcceptedTypes.begin(), _AcceptedTypes.end(), entityType ) != _AcceptedTypes.end()); }
|
||
|
|
||
|
private:
|
||
|
|
||
|
/// List of types (a vector for fast browsing with a few elements)
|
||
|
std::vector<uint8> _AcceptedTypes;
|
||
|
};*/
|
||
|
|
||
|
|
||
|
#endif // NL_DATA_SET_BASE_H
|
||
|
|
||
|
/* End of data_set_base.h */
|