khanat-opennel-code/code/ryzom/server/src/frontend_service/property_dispatcher.h
2010-05-06 02:08:41 +02:00

250 lines
8.1 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_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 */