2010-05-06 00:08:41 +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/>.
# include "stdpch.h"
# include "game_share/action_association.h"
# include "vision_provider.h"
# include "frontend_service.h"
# include "client_host.h"
# include "fe_stat.h"
# include "vision_array.h"
using namespace std ;
using namespace NLNET ;
using namespace NLMISC ;
using namespace CLFECOMMON ;
bool verboseVision = false ;
extern NLMISC : : CMemDisplayer * TmpDebugDisplayer ; // = NULL;
NLMISC : : CLog * TmpDebugLogger = NULL ;
/*
* Constructor
*/
CVisionProvider : : CVisionProvider ( ) :
_VisionArray ( NULL ) ,
_History ( NULL ) ,
_EntityToClient ( NULL )
{
}
//TEMP
/*static CFileDisplayer fd("addrem.log", true);
static CLog flog ; */
# ifdef MEASURE_FRONTEND_TABLES
sint32 NbX , NbY ;
NLMISC_VARIABLE ( sint32 , NbX , " NbX " ) ;
NLMISC_VARIABLE ( sint32 , NbY , " NbY " ) ;
# endif
NLMISC_DYNVARIABLE ( uint , NbEntitiesSeenByMonitoredClient , " NbEntitiesSeenByMonitoredClient " )
{
// We can only read the value
if ( get )
{
CFrontEndService * fe = CFrontEndService : : instance ( ) ;
//nlassert( fe->MonitoredClient <= MAX_NB_CLIENTS );
CClientHost * client = fe - > receiveSub ( ) - > clientIdCont ( ) [ fe - > MonitoredClient ] ;
if ( client )
{
* pointer = MAX_SEEN_ENTITIES_PER_CLIENT - client - > NbFreeEntityItems ;
return ;
}
* pointer = 0 ;
}
}
/*
* Initialization
*/
void CVisionProvider : : init ( CVisionArray * va , CHistory * h , CClientIdLookup * cl )
{
_VisionArray = va ;
_History = h ;
_EntityToClient = cl ;
DistanceSpreader . init ( ) ;
_VisionReceiver . init ( ) ;
//TEMP
//flog.addDisplayer( &fd );
if ( ! TmpDebugLogger )
{
TmpDebugDisplayer = new CMemDisplayer ( " VisionLog " ) ;
TmpDebugDisplayer - > setParam ( 2000 ) ;
TmpDebugLogger = new CLog ( CLog : : LOG_DEBUG ) ;
TmpDebugLogger - > addDisplayer ( TmpDebugDisplayer ) ;
}
}
/*
* Destructor
*/
CVisionProvider : : ~ CVisionProvider ( )
{
if ( TmpDebugLogger )
{
delete TmpDebugLogger ;
delete TmpDebugDisplayer ;
}
}
/*
* Easy access to the client host object . Returns NULL and makes warning if not found .
*/
CClientHost * CVisionProvider : : clientHost ( TClientId clientid )
{
nlassert ( clientid < = MaxNbClients ) ;
CClientHost * client = CFrontEndService : : instance ( ) - > sendSub ( ) - > clientIdCont ( ) [ clientid ] ;
if ( ! client )
nlwarning ( " C%hu not found in cont " , clientid ) ;
return client ;
}
/*
* Process the vision differences
*/
void CVisionProvider : : processVision ( )
{
CFrontEndService : : instance ( ) - > ProcessVisionWatch . start ( ) ;
TEntityIndex index ;
/* 1. Process the changes in the vision pairs.
* The property receiver says which entities are seen , limited to MAX_SEEN_ENTITIES_PER_CLIENT per observer .
*/
{
H_AUTO ( ScanVision ) ;
/* Multi-pass because the frontend_property_receiver may have received several deltas
* that cannot be merged ( for example ADD 25 into slot 1 , REM 25 , ADD 25 into slot 3 )
* but are stored in a queue .
*/
while ( _VisionReceiver . visionChanged ( ) )
{
/* TEMP
* Begin perf measures for vision processing
*/
/*static bool resetM = true;
if ( resetM )
{
IService : : getInstance ( ) - > requireResetMeasures ( ) ;
resetM = false ;
} */
index = _VisionReceiver . getFirstUpdatedVision ( ) ;
while ( index . isValid ( ) )
{
// Get the description of the entity who sees some changes
CEntity * observerEntity = TheEntityContainer - > getEntity ( index ) ;
// Look-up the corresponding client (player character) connected on this front-end
TClientId observerClientId = _EntityToClient - > getClientId ( index ) ;
if ( observerClientId = = INVALID_CLIENT )
{
const CEntityId & observerEntityId = TheDataset . getEntityId ( index ) ;
# ifdef NL_DEBUG
nldebug ( " %u: Observer E%u not known by this FS... " , CTickEventHandler : : getGameCycle ( ) , index . getIndex ( ) ) ;
# endif
observerClientId = TheEntityContainer - > EntityToClient - > getClientId ( observerEntityId ) ;
if ( observerClientId ! = INVALID_CLIENT )
{
CClientHost * clienthost = CFrontEndService : : instance ( ) - > sendSub ( ) - > clientIdCont ( ) [ observerClientId ] ;
clienthost - > setEntityIndex ( index ) ;
TheEntityContainer - > EntityToClient - > addEntityIndex ( index , observerClientId ) ;
nlinfo ( " %u: Setting mirror row to C%hu uid %u E%u (recovered) " , CTickEventHandler : : getGameCycle ( ) , observerClientId , clienthost - > Uid , index . getIndex ( ) ) ;
CFrontEndService : : instance ( ) - > receiveSub ( ) - > ConnectionStatLog - > displayNL ( " Setting mirror row to C%hu uid %u E%u " , observerClientId , clienthost - > Uid , index . getIndex ( ) ) ;
}
else
{
# ifdef NL_DEBUG
nldebug ( " Observer not found " ) ;
# endif
index = _VisionReceiver . getNextUpdatedVision ( index ) ;
continue ;
}
}
// 1. Remove the pairs corresponding to entities not seen anymore
TSetOfRemovedEntities : : iterator iso ;
for ( iso = observerEntity - > VisionOut . begin ( ) ; iso ! = observerEntity - > VisionOut . end ( ) ; + + iso )
{
removePair ( observerClientId , * iso ) ;
}
// 2. Add or replace the pairs corresponding to entities now seen
TMapOfVisionAssociations : : iterator isi ;
for ( isi = observerEntity - > VisionIn . begin ( ) ; isi ! = observerEntity - > VisionIn . end ( ) ; + + isi )
{
// Add or replace?
if ( ( * isi ) . second . second )
{
replacePair ( observerClientId , ( * isi ) . first , ( TCLEntityId ) ( ( * isi ) . second . first ) ) ;
}
else
{
addPair ( observerClientId , ( * isi ) . first , ( TCLEntityId ) ( ( * isi ) . second . first ) ) ;
}
// Note: we don't add a pair for the symetric association
}
index = _VisionReceiver . getNextUpdatedVision ( index ) ;
}
_VisionReceiver . endUpdatedVision ( ) ;
}
}
//flog.displayRawNL( "--" );
/* 2. Calculate new distances for active clients on this front-end.
* The entities that are modified were not advertised by getFirstUpdatedProperties ( ) and getNextUpdatedProperties ( )
* because they are considered to be always modified , although their position is up to date in the mirror .
*/
/*
* Distance processing is spread over several cycles .
* DPClientMapIndex is the current index in the client map , DPIterator is the current iterator
* Note : the number of clients can increase or decrease between two cycles .
*/
if ( DistanceSpreader . mustProcessNow ( ) )
{
H_AUTO ( UpdateDistances ) ;
THostMap : : iterator icm ;
sint clientmapindex , outerBoundIndex ;
DistanceSpreader . getProcessingBounds ( icm , clientmapindex , outerBoundIndex ) ;
while ( clientmapindex < outerBoundIndex )
{
CClientHost * client = GETCLIENTA ( icm ) ;
TPairState * state = _VisionArray - > getClientStateArray ( client - > clientId ( ) ) + 1 ;
// Calculate the distance for all used slots (except slot 0 which always remains at distance 0)
for ( sint e = 1 ; e ! = MAX_SEEN_ENTITIES_PER_CLIENT ; + + e , + + state )
{
//TPairState& state = _VisionArray->getPairState(client->clientId(), (TCLEntityId)e);
//if ( _VisionArray->getAssociationState( client, (TCLEntityId)e ) != CClientEntityIdTranslator::CEntityInfo::UnusedAssociation ) // CHANGED BEN
if ( state - > AssociationState ! = TPairState : : UnusedAssociation )
{
state - > DistanceCE = calcDistance ( client , ( TCLEntityId ) e , state - > EntityIndex ) ;
}
}
+ + clientmapindex ;
+ + icm ;
}
DistanceSpreader . endProcessing ( icm ) ;
}
DistanceSpreader . incCycle ( ) ;
CFrontEndService : : instance ( ) - > ProcessVisionWatch . stop ( ) ;
// After having removed the pairs of removed clients, free their ids
CFrontEndService : : instance ( ) - > receiveSub ( ) - > freeIdsOfRemovedClients ( ) ;
/*CFrontEndPropertyReceiver::SEntity *ent = CFrontEndPropertyReceiver::getEntity( 5 );
nlinfo ( " Mileage = %u " , ent - > Mileage ) ; */
}
/*
* Calculate the absolute distance between a client and an entity
*/
inline TCoord CVisionProvider : : calcDistance ( CClientHost * client , TCLEntityId slot , const TEntityIndex & seenIndex )
{
// Indexes are not valid in the case when a client has just resetted, before getting the vision update from the GPMS
if ( ( ! client - > entityIndex ( ) . isValid ( ) ) | | ( ! seenIndex . isValid ( ) ) )
return UNSET_DISTANCE ;
// Get client pos (assumes it is given by the GPMS)
CEntity * clientEntity = TheEntityContainer - > getEntity ( client - > entityIndex ( ) ) ;
CEntity * seenEntity = TheEntityContainer - > getEntity ( seenIndex ) ;
// The mirror properties can be not ready in such a multi-machine case (TODO: check it):
// Machine A: Service S1 spawns an entity
// Machine B: GPMS gets the entity and adds it to the vision of a player
// Machine C: FS gets the vision message
// FS gets the entity
if ( ! seenEntity - > X . isReadable ( ) )
{
nlwarning ( " Multi-machine vision bug with entity E%u " , seenIndex . getIndex ( ) ) ;
return UNSET_DISTANCE ;
}
if ( ! clientEntity - > X . isReadable ( ) )
{
nlwarning ( " Multi-machine vision bug with client %s " , client - > eId ( ) . toString ( ) . c_str ( ) ) ;
return UNSET_DISTANCE ;
}
TCoord pos1x = clientEntity - > X ( ) , pos1y = clientEntity - > Y ( ) ;
TCoord pos2x = seenEntity - > X ( ) , pos2y = seenEntity - > Y ( ) ;
// Obsolete: we used to use the position in history (last sent pos). Now it's the official position
// in order to avoid problem in mode COMBAT_FLOAT...
// Get absolute entity pos (note: in local mode, the relative pos is not stored in the history)
//CAction::TValue vlastposx, vlastposy, vlastposz;
//bool histohasvalue = _History->getPosition( client->clientId(), slot, vlastposx, vlastposy, vlastposz );
//if ( histohasvalue )
//{
// pos2x = getAbsoluteCoordinateFrom64( vlastposx );
// pos2y = getAbsoluteCoordinateFrom64( vlastposy );
// //nlinfo( "lastpos: %d %d, vlastpos: %"NL_I64"u %"NL_I64"u", pos2x, pos2y, vlastposx, vlastposy );
/*#ifdef NL_DEBUG
TCoord d = ( TCoord ) ( abs ( pos1x - pos2x ) + abs ( pos1y - pos2y ) ) ;
if ( d < 0 )
{
nlwarning ( " Invalid distance calculation with lastsent pos (C%hu S%hu D=%d) " , client - > clientId ( ) , ( uint16 ) slot , d ) ;
nlstop ;
}
# endif* /
/*#ifdef NL_DEBUG
TCoord d = ( TCoord ) ( abs ( pos1x - pos2x ) + abs ( pos1y - pos2y ) ) ;
if ( d < 0 )
{
nlwarning ( " Invalid distance calculation with real pos (C%hu S%hu D=%d) " , client - > clientId ( ) , ( uint16 ) slot , d ) ;
nlstop ;
}
# endif* /
//}
// Calculate 2D Manhattan distance
TCoord result = ( TCoord ) ( abs ( pos1x - pos2x ) + abs ( pos1y - pos2y ) ) ;
if ( result < 0 )
result = UNSET_DISTANCE ; // correct error if positions are wrong
return result ;
}
/*
* Add a pair . The argument ' furthestceid ' is used when removing an item is required .
*/
bool CVisionProvider : : addPair ( TClientId clientid , const TEntityIndex & entityindex , CLFECOMMON : : TCLEntityId slot )
{
CClientHost * client = clientHost ( clientid ) ;
if ( ! client )
return false ;
// If we have unassociated but no removed the pair yet, complete the removal
//if ( client->IdTranslator.getInfo(slot).AssociationState != CClientEntityIdTranslator::CEntityInfo::UnusedAssociation ) // CHANGED BEN
if ( _VisionArray - > getAssociationState ( clientid , slot ) ! = TPairState : : UnusedAssociation )
{
//LOG_VISION( "FEVIS:%u: Replacing E%u by E%u in slot %hu", CTickEventHandler::getGameCycle(), client->IdTranslator.getInfo(slot).EntityInSlot.getIndex(), entityindex.getIndex(), (uint16)slot ); // CHANGED BEN
LOG_VISION ( " FEVIS:%u: Replacing E%u by E%u in slot %hu " , CTickEventHandler : : getGameCycle ( ) , _VisionArray - > getEntityIndex ( clientid , slot ) . getIndex ( ) , entityindex . getIndex ( ) , ( uint16 ) slot ) ;
postRemovePair ( clientid , slot ) ;
}
//TEMP
//flog.displayRawNL( "ADD C%hu E%u, slot %hu, id %s", clientid, entityindex, slot, CFrontEndPropertyReceiver::getEntity(entityindex)->id.toString().c_str() );
/* 1. Associate Entity Index to a new TCLEntityId (or get exiting association if this new association occured before a dissociation acknowledge from the client)
*/
if ( slot < MAX_SEEN_ENTITIES_PER_CLIENT )
{
// Check if the entity is not still in a slot of the client
TCLEntityId slotFromEntityIndex = client - > IdTranslator . getCEId ( entityindex ) ;
if ( slotFromEntityIndex ! = INVALID_SLOT )
{
// The entity was moved to a new slot (previous one unassociated but not removed yet)// The entity was moved to a new slot (previous one unassociated but not removed yet)
LOG_VISION ( " FEVIS: Moving E%u from S%hu to S%hu " , entityindex . getIndex ( ) , ( uint16 ) slotFromEntityIndex , ( uint16 ) slot ) ;
postRemovePair ( clientid , slotFromEntityIndex ) ;
}
if ( ! client - > IdTranslator . acquireCEId ( entityindex , ( TCLEntityId ) slot ) )
{
return false ; // should not occur (see warning displayed by acquireCEId())
}
}
else
{
//nlwarning( "Invalid slot %hu given by GPMS for entity E%u seen by client %hu", slot, entityindex, clientid );
nlstop ;
return false ; // should not occur
}
+ + AssocCounter ;
//CClientEntityIdTranslator::CEntityInfo& info = client->IdTranslator.getInfo((TCLEntityId)slot); // CHANGED BEN
# ifdef NL_DEBUG
//info.AssociationState = CClientEntityIdTranslator::CEntityInfo::AwaitingAssAck; // CHANGED BEN
_VisionArray - > setAssociationState ( clientid , slot , TPairState : : AwaitingAssAck ) ;
// NormalAssociation set in CDistancePrioritizer::fillDiscreetProperty() with Sheet
# else
//info.AssociationState = CClientEntityIdTranslator::CEntityInfo::NormalAssociation; // CHANGED BEN
_VisionArray - > setAssociationState ( clientid , slot , TPairState : : NormalAssociation ) ;
# endif
/* 2. Fill the item attributes
*/
LOG_VISION ( " FEVIS: %u: Adding pair C%hu -> slot %hu (E%u_%hu) " , CTickEventHandler : : getGameCycle ( ) , clientid , ( uint16 ) slot , entityindex . getIndex ( ) , entityindex . counter ( ) ) ;
CEntity * sentity = TheEntityContainer - > getEntity ( entityindex ) ;
//nlinfo( "AddPair %hu %hu (E%u)", clientid, (uint16)slot, entityindex );
_VisionArray - > setEntityIndex ( clientid , slot , entityindex ) ;
TPairState & pairState = _VisionArray - > getPairState ( clientid , slot ) ;
pairState . associate ( ) ;
if ( slot = = 0 )
pairState . DistanceCE = 0 ; // slot 0's distance is always 0 because we can't use the last sent pos if it is not sent
else
pairState . DistanceCE = calcDistance ( client , ( TCLEntityId ) slot , entityindex ) ;
- - client - > NbFreeEntityItems ;
# ifdef NL_DEBUG
if ( TheDataset . getEntityId ( entityindex ) . getType ( ) = = RYZOMID : : player )
LOG_VISION ( " FEVIS: Seen E%u is a player " , entityindex . getIndex ( ) ) ;
# endif
CFrontEndService : : instance ( ) - > PrioSub . Prioritizer . addEntitySeenByClient ( clientid , slot ) ;
// Add into history
//if ( slot != 0 )
{
if ( ! _History - > addEntityToClient ( ( TCLEntityId ) slot , client - > clientId ( ) ) )
{
nlwarning ( " Cannot add entity to client in property history: entity already used " ) ;
}
}
// Add to observer list: the clients who see the entity (and its ceid for them)
//_ObserverList[entityindex].insert( TPairClientSlot( clientid, (TCLEntityId)slot ) );
//client->displayClientProperties();
return true ;
}
/*
* Remove a pair .
*/
void CVisionProvider : : removePair ( TClientId clientid , TCLEntityId slot )
{
LOG_VISION ( " FEVIS:%u: Unassociating C%hu -> slot %hu " , CTickEventHandler : : getGameCycle ( ) , clientid , ( uint16 ) slot ) ;
// Prevent a vision bug where two removals would occur (e.g. when the PC is stressed-slow)
CClientHost * client = clientHost ( clientid ) ;
if ( ! client ) // we had such a situation live once
return ;
//CClientEntityIdTranslator::CEntityInfo &info = client->IdTranslator.getInfo(slot); // CHANGED BEN
//if ( info.AssociationState == CClientEntityIdTranslator::CEntityInfo::UnusedAssociation ) // CHANGED BEN
if ( _VisionArray - > getAssociationState ( clientid , slot ) = = TPairState : : UnusedAssociation )
{
nlwarning ( " %u: Cannot remove pair twice (or pair not associated): C%hu S%hu " , CTickEventHandler : : getGameCycle ( ) , clientid , ( uint16 ) slot ) ;
}
else
{
TPairState & pairState = _VisionArray - > getPairState ( clientid , slot ) ;
pairState . unassociate ( ) ;
}
}
/*
*
*/
void CVisionProvider : : postRemovePair ( TClientId clientid , TCLEntityId slot )
{
+ + DisasCounter ;
//TEMP
//flog.displayRawNL( "REM C%hu E%u, id %s", clientid, entityindex, CFrontEndPropertyReceiver::getEntity(entityindex)->id.toString().c_str() );
nlassert ( ( clientid ! = INVALID_CLIENT ) & & ( slot ! = INVALID_SLOT ) ) ;
CClientHost * client = clientHost ( clientid ) ;
if ( ! client )
return ;
//CClientEntityIdTranslator::CEntityInfo &info = client->IdTranslator.getInfo(slot); // CHANGED BEN
//TEntityIndex entityindex = info.EntityInSlot; // CHANGED BEN
TEntityIndex entityindex = _VisionArray - > getEntityIndex ( clientid , slot ) ;
if ( ! entityindex . isValid ( ) )
{
// No warning when slot 0 because this is normal at the beginning of the life of a client
if ( slot ! = 0 )
{
nlwarning ( " Cannot remove vision pair C%hu -> slot %hu! " , clientid , ( uint16 ) slot ) ;
}
return ;
}
CFrontEndService : : instance ( ) - > PrioSub . Prioritizer . removeEntitySeenByClient ( clientid , slot ) ;
//client->displayClientProperties();
LOG_VISION ( " FEVIS: %u: Removing pair C%hu -> slot %hu (E%u_%hu) " , CTickEventHandler : : getGameCycle ( ) , clientid , ( uint16 ) slot , entityindex . getIndex ( ) , entityindex . counter ( ) ) ;
CEntity * sentity = TheEntityContainer - > getEntity ( entityindex ) ;
# ifdef NL_DEBUG
if ( TheDataset . getEntityId ( entityindex ) . getType ( ) = = RYZOMID : : player )
LOG_VISION ( " FEVIS: Unseen E%u is a player " , entityindex . getIndex ( ) ) ;
# endif
//info.AssociationState = CClientEntityIdTranslator::CEntityInfo::UnusedAssociation; // CHANGED BEN
_VisionArray - > setAssociationState ( clientid , slot , TPairState : : UnusedAssociation ) ;
// Remove from history
//if ( slot != 0 )
_History - > removeEntityOfClient ( slot , clientid ) ;
// Remove from observer list: the clients who see the entity (and its ceid for them)
//removeFromObserverList( entityindex, clientid, slot );
// Release Id !
client - > IdTranslator . releaseId ( entityindex /*_VisionArray->getEntityIndex( client->clientId(), ceid )*/ ) ;
+ + client - > NbFreeEntityItems ;
//LOG_VISION( "FEVIS: Client %hu has %hu free items (+)", client->clientId(), client->NbFreeEntityItems );
// Reset item in the vision array
TPairState & pairState = _VisionArray - > getPairState ( clientid , slot ) ;
pairState . resetItem ( ) ;
}
/*
* Replace the entity in a slot ( e . g . when transforming a dead character to a sack )
*/
void CVisionProvider : : replacePair ( TClientId clientid , const TEntityIndex & newEntityIndex , CLFECOMMON : : TCLEntityId slot )
{
/*
* 1. Clear the old entityindex
*/
+ + DisasCounter ;
nlassert ( ( clientid ! = INVALID_CLIENT ) & & ( slot ! = INVALID_SLOT ) ) ;
CClientHost * client = clientHost ( clientid ) ;
if ( ! client )
return ;
//CClientEntityIdTranslator::CEntityInfo &info = client->IdTranslator.getInfo(slot); // CHANGED BEN
//TEntityIndex entityindex = info.EntityInSlot; // CHANGED BEN
TEntityIndex entityindex = _VisionArray - > getEntityIndex ( clientid , slot ) ;
if ( ! entityindex . isValid ( ) )
{
nlwarning ( " Cannot replace vision pair C%hu -> slot %hu! " , clientid , ( uint16 ) slot ) ;
return ;
}
//info.AssociationChannel == CClientEntityIdTranslator::CEntityInfo::NormalAssociation;
//client->displayClientProperties();
LOG_VISION ( " FEVIS: %u: Replacing pair C%hu -> slot %hu (E%u becomes E%u) " , CTickEventHandler : : getGameCycle ( ) , clientid , ( uint16 ) slot , entityindex . getIndex ( ) , newEntityIndex . getIndex ( ) ) ;
CEntity * sentity = TheEntityContainer - > getEntity ( entityindex ) ;
# ifdef NL_DEBUG
if ( TheDataset . getEntityId ( entityindex ) . getType ( ) = = RYZOMID : : player )
LOG_VISION ( " FEVIS: Unseen E%u is a player " , entityindex . getIndex ( ) ) ;
# endif
// Remove from history
//if ( slot != 0 )
_History - > removeEntityOfClient ( slot , clientid ) ;
// Remove from observer list: the clients who see the entity (and its ceid for them)
//removeFromObserverList( entityindex, clientid, slot );
// Release Id !
client - > IdTranslator . releaseId ( entityindex /*_VisionArray->getEntityIndex( client->clientId(), ceid )*/ ) ;
//LOG_VISION( "FEVIS: Client %hu has %hu free items (+)", client->clientId(), client->NbFreeEntityItems );
/*
* 2. Set the new entityindex
*/
+ + AssocCounter ;
// Associate Entity Index to the slot
if ( ! client - > IdTranslator . acquireCEId ( newEntityIndex , ( TCLEntityId ) slot ) )
{
// Should not occur
return ;
}
/* 2. Fill the item attributes
*/
//LOG_VISION( "FEVIS: Adding pair C%hu -> slot %hu (E%u) (replace)", clientid, slot, entityindex );
sentity = TheEntityContainer - > getEntity ( newEntityIndex ) ;
//nlinfo( "AddPair %hu %hu (E%u)", clientid, (uint16)slot, entityindex );
TPairState & pairState = _VisionArray - > getPairState ( clientid , slot ) ;
pairState . changeAssociation ( ) ;
pairState . resetPrio ( ) ;
pairState . EntityIndex = newEntityIndex ;
if ( slot = = 0 )
pairState . DistanceCE = 0 ;
else
pairState . DistanceCE = calcDistance ( client , ( TCLEntityId ) slot , newEntityIndex ) ;
# ifdef NL_DEBUG
if ( TheDataset . getEntityId ( newEntityIndex ) . getType ( ) = = RYZOMID : : player )
LOG_VISION ( " FEVIS: Seen E%u is a player " , newEntityIndex . getIndex ( ) ) ;
# endif
// Add into history
//if ( slot != 0 )
{
if ( ! _History - > addEntityToClient ( ( TCLEntityId ) slot , clientid ) )
{
nlwarning ( " Cannot add entity to client in property history: entity already used " ) ;
}
}
// Add to observer list: the clients who see the entity (and its ceid for them)
//_ObserverList[newEntityIndex].insert( TPairClientSlot( clientid, (TCLEntityId)slot ) );
}
/*
* Remove item from observer list of entityindex
*/
/*void CVisionProvider::removeFromObserverList( const TEntityIndex& entityindex, TClientId clientid, TCLEntityId ceid )
{
_ObserverList [ entityindex ] . erase ( TPairClientSlot ( clientid , ceid ) ) ;
} */
/*
* Reset all slots of all clients ( e . g . when GPMS falls down )
*/
void CVisionProvider : : resetVision ( )
{
nlinfo ( " Resetting all slots of all clients... " ) ;
THostMap & clientmap = CFrontEndService : : instance ( ) - > receiveSub ( ) - > clientMap ( ) ;
THostMap : : iterator ihm ;
for ( ihm = clientmap . begin ( ) ; ihm ! = clientmap . end ( ) ; + + ihm )
{
resetVision ( GETCLIENTA ( ihm ) ) ;
}
}
/*
* Reset all slots of one client ( e . g . when a client is unspawned )
*/
void CVisionProvider : : resetVision ( CClientHost * clienthost )
{
// Get all entities seen by this client
sint e ;
for ( e = 0 ; e ! = MAX_SEEN_ENTITIES_PER_CLIENT ; + + e )
{
//if ( _VisionArray->getAssociationState( clienthost, (TCLEntityId)e ) != CClientEntityIdTranslator::CEntityInfo::UnusedAssociation ) // CHANGED BEN
if ( _VisionArray - > getAssociationState ( clienthost - > clientId ( ) , ( TCLEntityId ) e ) ! = TPairState : : UnusedAssociation )
{
// Remove pair on the FE and on the client
removePair ( clienthost - > clientId ( ) , ( TCLEntityId ) e ) ;
}
}
}
/*
* Display the properties of an entity in the vision
*/
void CVisionProvider : : displayEntityInfo ( const CEntity & e , const TEntityIndex & entityIndex , NLMISC : : CLog * log ) const
{
if ( ! e . X . isReadable ( ) )
{
log - > displayNL ( " Entity %u not initialized " , entityIndex . getIndex ( ) ) ;
return ;
}
const CEntityId & eid = TheDataset . getEntityId ( entityIndex ) ;
uint64 properties [ NB_VISUAL_PROPERTIES ] ;
CEntity : : fillVisualPropertiesFromMirror ( properties , entityIndex ) ;
string sheetIdS = CSheetId ( ( uint32 ) properties [ PROPERTY_SHEET ] ) . toString ( ) ;
log - > displayNL ( " E%u %s Id %s Name %s Sheet %u (%s) GameCycle %u " ,
entityIndex . getIndex ( ) , ( eid . getType ( ) = = RYZOMID : : player ) ? " PLAYER " : RYZOMID : : toString ( ( RYZOMID : : TTypeId ) eid . getType ( ) ) . c_str ( ) , eid . toString ( ) . c_str ( ) , getEntityName ( entityIndex ) . c_str ( ) , ( uint32 ) properties [ PROPERTY_SHEET ] , sheetIdS . c_str ( ) , e . TickPosition ( ) ) ;
log - > displayNL ( " %u entities entered vision, %u entities left vision " , e . VisionIn . size ( ) , e . VisionOut . size ( ) ) ;
log - > displayNL ( " Position (m): %d %d %d - Local: %d %d %d - Mode: %s " , e . posXm ( entityIndex ) , e . posYm ( entityIndex ) , e . posZm ( entityIndex ) , e . posLocalXm ( entityIndex ) , e . posLocalYm ( entityIndex ) , e . posLocalZm ( entityIndex ) , ( properties [ PROPERTY_POSZ ] & 0x1 ) ? " Relative " : " Absolute " ) ;
e . displayProperties ( entityIndex , log ) ;
// stringstream ss;
string str ;
str + = NLMISC : : toString ( e . propIsInitializedState ( 0 ) ) + " '' " ; // skip 1 & 2
// ss << e.propIsInitializedState(0) << "''"; // skip 1 & 2
/*for ( sint p=0; p!=NB_VISUAL_PROPERTIES; ++p )
{
ss < < " " < < e . properties [ p ] ;
}
nlinfo ( " Property values: %s " , ss . str ( ) . c_str ( ) ) ;
ss . clear ( ) ; */
for ( sint p = 3 ; p ! = NB_VISUAL_PROPERTIES ; + + p )
{
//ss << e.propIsInitializedState(p);
str + = NLMISC : : toString ( e . propIsInitializedState ( p ) ) ;
if ( ( p + 1 ) % 4 = = 0 )
//ss << "-";
str + = " - " ;
}
log - > displayNL ( " Initialized: %s " , str . c_str ( ) ) ;
}
/*
* Reset assoc / disas counters
*/
void CVisionProvider : : resetAssocCounter ( )
{
AssocCounter = 0 ;
DisasCounter = 0 ;
AssocStartTime = CTime : : getLocalTime ( ) ;
}
/*
* Display assoc / disas freqs
*/
void CVisionProvider : : displayAssocFreqs ( CLog * log )
{
float duration = ( ( float ) ( CTime : : getLocalTime ( ) - AssocStartTime ) ) / 1000.0f ;
log - > displayNL ( " Assoc: %.1f Hz - Disac: %.1f Hz " , ( ( float ) AssocCounter ) / duration , ( ( float ) DisasCounter ) / duration ) ;
}
NLMISC_COMMAND ( displayEntityInfo , " Display the properties of an entity " , " <entityIndex> " )
{
// check args, if there s not the right number of parameter, return bad
if ( args . size ( ) ! = 1 ) return false ;
// get the values
2010-10-23 15:11:21 +00:00
TDataSetIndex entityIndex ;
NLMISC : : fromString ( args [ 0 ] , entityIndex ) ;
2010-05-06 00:08:41 +00:00
if ( entityIndex < ( uint32 ) TheDataset . maxNbRows ( ) )
{
TDataSetRow datasetrow = TheDataset . getCurrentDataSetRow ( entityIndex ) ;
CEntity * entity = TheEntityContainer - > getEntity ( datasetrow ) ;
if ( ! TheDataset . getEntityId ( datasetrow ) . isUnknownId ( ) ) // TODO: unknown or 0 ??
{
CFrontEndService : : instance ( ) - > PrioSub . VisionProvider . displayEntityInfo ( * entity , datasetrow ) ;
return true ;
}
}
log . displayNL ( " There is no such an entity index " ) ;
return true ;
}
NLMISC_COMMAND ( displayEntityInfoById , " Display the properties of an entity, by entity id (if found) " , " <entityId> " )
{
if ( args . size ( ) < 1 )
return false ;
CEntityId eid ;
uint64 id ;
uint type ;
uint creatorId ;
uint dynamicId ;
if ( sscanf ( args [ 0 ] . c_str ( ) , " (% " NL_I64 " x:%x:%x:%x) " , & id , & type , & creatorId , & dynamicId ) ! = 4 )
return false ;
eid . setShortId ( id ) ;
eid . setType ( type ) ;
eid . setCreatorId ( creatorId ) ;
eid . setDynamicId ( dynamicId ) ;
TEntityIndex entityIndex = TheEntityContainer - > entityIdToIndex ( eid ) ;
if ( entityIndex . isValid ( ) )
{
CEntity * entity = TheEntityContainer - > getEntity ( entityIndex ) ;
if ( ! TheDataset . getEntityId ( entityIndex ) . isUnknownId ( ) ) // TODO: unknown or 0 ??
{
CFrontEndService : : instance ( ) - > PrioSub . VisionProvider . displayEntityInfo ( * entity , entityIndex ) ;
return true ;
}
}
log . displayNL ( " There is no entity with the specified id " ) ;
return true ;
}
NLMISC_COMMAND ( displaySlotInfo , " Display info for a particular slot of a client " , " <clientid> <slot> " )
{
if ( args . size ( ) < 2 )
return false ;
2010-10-23 15:11:21 +00:00
TClientId clientid ;
NLMISC : : fromString ( args [ 0 ] , clientid ) ;
CLFECOMMON : : TCLEntityId slot ;
NLMISC : : fromString ( args [ 1 ] , slot ) ;
2010-05-06 00:08:41 +00:00
CClientHost * clienthost ;
if ( ( clientid < = MaxNbClients ) & & ( ( clienthost = CFrontEndService : : instance ( ) - > sendSub ( ) - > clientIdCont ( ) [ clientid ] ) ! = NULL ) )
{
clienthost - > displaySlotProperties ( slot , true , & log ) ;
}
return true ;
}
NLMISC_COMMAND ( resetAssocCounters , " Reset assoc/disas counters " , " " )
{
CFrontEndService : : instance ( ) - > PrioSub . VisionProvider . resetAssocCounter ( ) ;
return true ;
}
NLMISC_COMMAND ( displayAssocFreqs , " Display assoc/disas freqs " , " " )
{
CFrontEndService : : instance ( ) - > PrioSub . VisionProvider . displayAssocFreqs ( & log ) ;
return true ;
}
/*NLMISC_COMMAND( verboseVision, "Turn on/off or check the state of verbose logging of vision", "" )
{
if ( args . size ( ) = = 1 )
{
if ( args [ 0 ] = = string ( " on " ) | | args [ 0 ] = = string ( " 1 " ) )
verboseVision = true ;
else if ( args [ 0 ] = = string ( " off " ) | | args [ 0 ] = = string ( " 0 " ) )
verboseVision = false ;
}
log . displayNL ( " verboseVision is %s " , verboseVision ? " on " : " off " ) ;
return true ;
} */
NLMISC_COMMAND ( displayVisionLog , " Display Tmp Debug Log " , " " )
{
TmpDebugDisplayer - > write ( & log ) ;
return true ;
}