2012-05-29 13:31:11 +00:00
// 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_PROPERTY_DISPATCHER_H
# define NL_PROPERTY_DISPATCHER_H
# include "nel/misc/types_nl.h"
# include "game_share/entity_types.h"
# include "fe_types.h"
# include "vision_array.h"
# include <vector>
/*
* Forward declarations
*/
class CPropertyIdTranslator ;
/*
* Property shelves : one container ( bucket ) for parcels for each priority level , per client .
*/
typedef std : : vector < TPropParcel > TPropertyShelf ;
typedef TPropertyShelf TPropertyShelves [ NB_PRIORITIES ] ;
/**
* Property Dispatcher .
* It tells which properties to send , ordered by decreasing priority .
* The properties are referenced in ' shelves ' ( buckets ) .
* There are as many shelves as priority levels .
*
* \ author Olivier Cado
* \ author Nevrax France
* \ date 2002
*/
class CPropertyDispatcher
{
public :
/// Constructor
CPropertyDispatcher ( ) ;
/// Initialization
void init ( TClientId clientid ) ;
// __________________________________________________________
// For Vision Array (called by Vision Provider & Prioritizer)
/// Change a priority
void setPriority ( CLFECOMMON : : TCLEntityId ceid , CLFECOMMON : : TPropIndex propindex , TPropParcelPtr & parcelptr , TPriority newprio )
{
//++NbSetPrio; // stats
if ( parcelptr . Prio ! = newprio )
{
// Remove existing parcel (will be silent if parcelptr.Offset is INVALID_OFFSET)
removeProp ( parcelptr ) ;
// Add a new enabled parcel and update the pointer to the parcel
parcelptr . Prio = newprio ;
addProp ( parcelptr , ceid , propindex ) ;
}
else
{
// Only enable the parcel
if ( parcelptr . Offset < nbParcels ( parcelptr . Prio ) ) //TEMP
enableProp ( parcelptr ) ;
else
nlwarning ( " Invalid offset %hd for enabling parcel in propdispatcher! (client %hu slot %hu prio %hu " , parcelptr . Offset , _ClientId , ( uint16 ) ceid , ( uint16 ) parcelptr . Prio ) ;
//++NbReenable;
}
}
/// Remove from the property dispatcher shelves, or does nothing if offset is INVALID_OFFSET
void removeProp ( const TPropParcelPtr & parcelptr ) ;
/// Remove all corresponding properties from the property dispatcher
void removePropsFromShelves ( TClientId clientid , CLFECOMMON : : TCLEntityId ceid ) ;
// _______________
// For Prioritizer
/// Return the number of parcels of a shelf
TPropParcelOffset nbParcels ( TPriority prio ) { nlassert ( prio < = NB_PRIORITIES ) ; return _PropShelves [ prio ] . size ( ) ; }
/// Return the number of enabled parcels in a shelf
TPropParcelOffset nbEnabledParcels ( TPriority prio ) ;
// ___________________________
// For priority subsystem root
/// Remove the parcels that have been added to the remove list (call it after a cycle)
void flush ( ) ;
/// Initialize dispatch cycle
void initDispatcherCycle ( /*bool rescalePriorities*/ ) ;
/// Display the contents of the shelves
void printShelves ( const char * title , bool checkIntegrity , bool proptext = false , bool hidedisabled = false ) const ;
/// Display the number of parcels per shelf
void printShelfSizes ( ) const ;
// Threshold value
//float hpThreshold() const { return _HPThreshold; }
// Reset threshold
//void resetThreshold() { _HPThreshold = 0.0f; _HPTDelta = 0.0f; }
// Adjust HPThreshold (dichotomic)
//void adjustHPThreshold();
// _____________________
// For sending subsystem
/// Return which property to send next, or NULL if there is no more.
const TPropParcel * getNextParcel ( )
{
if ( _NextParcel . Offset = = INVALID_OFFSET )
return NULL ;
// Return current parcel
const TPropParcel * parcel = & getParcel ( _NextParcel ) ;
//nlassert( parcel->PropIndex < MAX_PROPERTIES_PER_ENTITY );
return parcel ;
// incNextParcel() will be called by setStatus()
}
/** Set status: true if the latest parcel got by getNextParcel() can be sent in the current cycle, otherwise false
* If true , the parcel gets disabled .
* Must be called after getNextParcel ( ) every time getNextParcel ( ) is called
*/
void setParcelStatusTrue ( ) ;
void setParcelStatusFalse ( )
{
// Advance to next parcel
incNextParcel ( ) ;
}
/// Return the amount of priorities used corresponding to the number of actions sent last cycle (e.g. 1.2 means priority 0 is full and priority 1 is 20% filled)
float getPrioRatio ( ) ;
// _____
// Stats
// Count the number of properties of a certain type in the property shelves
void displayCounts ( CLFECOMMON : : TPropIndex propindex ) ;
/// Number of calls to setPriority
//uint32 NbSetPrio;
/// Number of calls to setPriority where the prio is unchanged
//uint32 NbReenable;
protected :
/// Easy access to a shelf
TPropertyShelf & getShelf ( TPriority prio ) { /*nlassert( prio <= NB_PRIORITIES );*/ return _PropShelves [ prio ] ; }
/// Easy access to a parcel
TPropParcel & getParcel ( const TPropParcelPtr & parcelptr ) { nlassertex ( parcelptr . Prio < = NB_PRIORITIES & & parcelptr . Offset < nbParcels ( parcelptr . Prio ) , ( " prio=%hu offset=%hd " , ( uint16 ) parcelptr . Prio , parcelptr . Offset ) ) ; return _PropShelves [ parcelptr . Prio ] [ parcelptr . Offset ] ; }
/// Easy access to a parcel of a shelf
TPropParcel & getParcel ( TPropertyShelf & shelf , TPropParcelOffset offset ) { /*nlassert( offset < (TPropParcelOffset)shelf.size() );*/ return shelf [ offset ] ; }
/// Easy access to the last parcel of a shelf
TPropParcel & lastParcel ( TPropertyShelf & shelf ) { /*nlassert( ! shelf.empty() );*/ return * ( shelf . end ( ) - 1 ) ; }
/// Increment pointer to next parcel
void incNextParcel ( ) ;
/// Skip any empty shelves
void skipEmptyShelves ( ) ;
/// Add a parcelptr to the remove list. The parcel will be removed at the beginning of the next cycle
void addToRemoveList ( TPropParcelPtr * pparcelptr )
{
_RemoveList . push_back ( pparcelptr ) ;
}
/// Make a new enabled parcel in the shelf corresponding to parcelptr.Prio and fill parcelptr.Offset
void addProp ( TPropParcelPtr & parcelptr , CLFECOMMON : : TCLEntityId ceid , CLFECOMMON : : TPropIndex propindex ) ;
/// Enable an existing parcel
void enableProp ( const TPropParcelPtr & parcelptr )
{
getParcel ( parcelptr ) . Enabled = true ;
}
//private:
protected :
/** Type of the remove list.
* Each item points to the member PrioLoc of a TPropState stored in _VisionArray .
* It is a pointer because of the following reasons :
* - these PrioLoc are modified by removeProp ( )
* - they do not move within memory as the vision array is static
*/
typedef std : : vector < TPropParcelPtr * > TRemoveList ;
/// Property shelves
TPropertyShelves _PropShelves ;
/// Pointer to the next parcel to dispatch
TPropParcelPtr _NextParcel ;
/// The remove list
TRemoveList _RemoveList ;
/// Vision array
CVisionArray * _VisionArray ;
/// Property id translator
CPropertyIdTranslator * _PropTranslator ;
/// Destination client
TClientId _ClientId ;
// Threshold used to control that the number of elements in priority 0 (Highest Prio) is stable
//float _HPThreshold;
// Difference between previous and current _HPThreshold
//float _HPTDelta;
/// Number of parcels sent in the current cycle
//uint32 _NbSentParcelsInCycle;
} ;
# endif // NL_PROPERTY_DISPATCHER_H
/* End of property_dispatcher.h */