1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "game_share/action_association.h"
23 #include "vision_provider.h"
24 #include "frontend_service.h"
25 #include "client_host.h"
27 #include "vision_array.h"
30 using namespace NLNET
;
31 using namespace NLMISC
;
32 using namespace CLFECOMMON
;
35 bool verboseVision
= false;
36 extern NLMISC::CMemDisplayer
*TmpDebugDisplayer
;// = NULL;
37 NLMISC::CLog
*TmpDebugLogger
= NULL
;
43 CVisionProvider::CVisionProvider() :
46 _EntityToClient( NULL
)
52 /*static CFileDisplayer fd("addrem.log", true);
56 #ifdef MEASURE_FRONTEND_TABLES
58 NLMISC_VARIABLE( sint32
, NbX
, "NbX" );
59 NLMISC_VARIABLE( sint32
, NbY
, "NbY" );
63 NLMISC_DYNVARIABLE( uint
, NbEntitiesSeenByMonitoredClient
, "NbEntitiesSeenByMonitoredClient" )
65 // We can only read the value
68 CFrontEndService
*fe
= CFrontEndService::instance();
69 //nlassert( fe->MonitoredClient <= MAX_NB_CLIENTS );
70 CClientHost
*client
= fe
->receiveSub()->clientIdCont()[fe
->MonitoredClient
];
73 *pointer
= MAX_SEEN_ENTITIES_PER_CLIENT
- client
->NbFreeEntityItems
;
84 void CVisionProvider::init( CVisionArray
*va
, CHistory
*h
, CClientIdLookup
*cl
)
90 DistanceSpreader
.init();
91 _VisionReceiver
.init();
93 //flog.addDisplayer( &fd );
95 if ( ! TmpDebugLogger
)
97 TmpDebugDisplayer
= new CMemDisplayer( "VisionLog" );
98 TmpDebugDisplayer
->setParam( 2000 );
99 TmpDebugLogger
= new CLog( CLog::LOG_DEBUG
);
100 TmpDebugLogger
->addDisplayer( TmpDebugDisplayer
);
108 CVisionProvider::~CVisionProvider()
110 if ( TmpDebugLogger
)
112 delete TmpDebugLogger
;
113 delete TmpDebugDisplayer
;
119 * Easy access to the client host object. Returns NULL and makes warning if not found.
121 CClientHost
*CVisionProvider::clientHost( TClientId clientid
)
123 nlassert( clientid
<= MaxNbClients
);
124 CClientHost
*client
= CFrontEndService::instance()->sendSub()->clientIdCont()[clientid
];
126 nlwarning( "C%hu not found in cont", clientid
);
132 * Process the vision differences
134 void CVisionProvider::processVision()
136 CFrontEndService::instance()->ProcessVisionWatch
.start();
139 /* 1. Process the changes in the vision pairs.
140 * The property receiver says which entities are seen, limited to MAX_SEEN_ENTITIES_PER_CLIENT per observer.
145 /* Multi-pass because the frontend_property_receiver may have received several deltas
146 * that cannot be merged (for example ADD 25 into slot 1, REM 25, ADD 25 into slot 3)
147 * but are stored in a queue.
149 while ( _VisionReceiver
.visionChanged() )
152 * Begin perf measures for vision processing
154 /*static bool resetM = true;
157 IService::getInstance()->requireResetMeasures();
161 index
=_VisionReceiver
.getFirstUpdatedVision();
162 while (index
.isValid())
164 // Get the description of the entity who sees some changes
165 CEntity
*observerEntity
= TheEntityContainer
->getEntity( index
);
167 // Look-up the corresponding client (player character) connected on this front-end
168 TClientId observerClientId
= _EntityToClient
->getClientId( index
);
169 if ( observerClientId
== INVALID_CLIENT
)
171 const CEntityId
&observerEntityId
= TheDataset
.getEntityId( index
);
173 nldebug( "%u: Observer E%u not known by this FS...", CTickEventHandler::getGameCycle(), index
.getIndex() );
176 observerClientId
= TheEntityContainer
->EntityToClient
->getClientId( observerEntityId
);
177 if ( observerClientId
!= INVALID_CLIENT
)
179 CClientHost
*clienthost
= CFrontEndService::instance()->sendSub()->clientIdCont()[observerClientId
];
180 clienthost
->setEntityIndex( index
);
181 TheEntityContainer
->EntityToClient
->addEntityIndex( index
, observerClientId
);
182 nlinfo( "%u: Setting mirror row to C%hu uid %u E%u (recovered)", CTickEventHandler::getGameCycle(), observerClientId
, clienthost
->Uid
, index
.getIndex() );
183 CFrontEndService::instance()->receiveSub()->ConnectionStatLog
->displayNL( "Setting mirror row to C%hu uid %u E%u", observerClientId
, clienthost
->Uid
, index
.getIndex() );
188 nldebug( "Observer not found" );
190 index
= _VisionReceiver
.getNextUpdatedVision( index
);
195 // 1. Remove the pairs corresponding to entities not seen anymore
196 TSetOfRemovedEntities::iterator iso
;
197 for ( iso
=observerEntity
->VisionOut
.begin(); iso
!=observerEntity
->VisionOut
.end(); ++iso
)
199 removePair( observerClientId
, *iso
);
202 // 2. Add or replace the pairs corresponding to entities now seen
203 TMapOfVisionAssociations::iterator isi
;
204 for ( isi
=observerEntity
->VisionIn
.begin(); isi
!=observerEntity
->VisionIn
.end(); ++isi
)
207 if ( (*isi
).second
.second
)
209 replacePair( observerClientId
, (*isi
).first
, (TCLEntityId
)((*isi
).second
.first
) );
213 addPair( observerClientId
, (*isi
).first
, (TCLEntityId
)((*isi
).second
.first
) );
215 // Note: we don't add a pair for the symetric association
218 index
= _VisionReceiver
.getNextUpdatedVision( index
);
221 _VisionReceiver
.endUpdatedVision();
224 //flog.displayRawNL( "--" );
226 /* 2. Calculate new distances for active clients on this front-end.
227 * The entities that are modified were not advertised by getFirstUpdatedProperties() and getNextUpdatedProperties()
228 * because they are considered to be always modified, although their position is up to date in the mirror.
232 * Distance processing is spread over several cycles.
233 * DPClientMapIndex is the current index in the client map, DPIterator is the current iterator
234 * Note: the number of clients can increase or decrease between two cycles.
237 if ( DistanceSpreader
.mustProcessNow() )
239 H_AUTO(UpdateDistances
);
240 THostMap::iterator icm
;
241 sint clientmapindex
, outerBoundIndex
;
242 DistanceSpreader
.getProcessingBounds( icm
, clientmapindex
, outerBoundIndex
);
244 while ( clientmapindex
< outerBoundIndex
)
246 CClientHost
* client
= GETCLIENTA(icm
);
247 TPairState
* state
= _VisionArray
->getClientStateArray(client
->clientId()) + 1;
249 // Calculate the distance for all used slots (except slot 0 which always remains at distance 0)
250 for ( sint e
=1; e
!=MAX_SEEN_ENTITIES_PER_CLIENT
; ++e
, ++state
)
252 //TPairState& state = _VisionArray->getPairState(client->clientId(), (TCLEntityId)e);
254 //if ( _VisionArray->getAssociationState( client, (TCLEntityId)e ) != CClientEntityIdTranslator::CEntityInfo::UnusedAssociation ) // CHANGED BEN
255 if (state
->AssociationState
!= TPairState::UnusedAssociation
)
257 state
->DistanceCE
= calcDistance( client
, (TCLEntityId
)e
, state
->EntityIndex
);
263 DistanceSpreader
.endProcessing( icm
);
266 DistanceSpreader
.incCycle();
268 CFrontEndService::instance()->ProcessVisionWatch
.stop();
270 // After having removed the pairs of removed clients, free their ids
271 CFrontEndService::instance()->receiveSub()->freeIdsOfRemovedClients();
273 /*CFrontEndPropertyReceiver::SEntity *ent = CFrontEndPropertyReceiver::getEntity( 5 );
274 nlinfo( "Mileage = %u", ent->Mileage );*/
279 * Calculate the absolute distance between a client and an entity
281 inline TCoord
CVisionProvider::calcDistance( CClientHost
*client
, TCLEntityId slot
, const TEntityIndex
& seenIndex
)
283 // Indexes are not valid in the case when a client has just resetted, before getting the vision update from the GPMS
284 if ( (!client
->entityIndex().isValid()) || (!seenIndex
.isValid()) )
285 return UNSET_DISTANCE
;
287 // Get client pos (assumes it is given by the GPMS)
288 CEntity
*clientEntity
= TheEntityContainer
->getEntity( client
->entityIndex() );
289 CEntity
*seenEntity
= TheEntityContainer
->getEntity( seenIndex
);
291 // The mirror properties can be not ready in such a multi-machine case (TODO: check it):
292 // Machine A: Service S1 spawns an entity
293 // Machine B: GPMS gets the entity and adds it to the vision of a player
294 // Machine C: FS gets the vision message
295 // FS gets the entity
296 if ( ! seenEntity
->X
.isReadable() )
298 nlwarning( "Multi-machine vision bug with entity E%u", seenIndex
.getIndex() );
299 return UNSET_DISTANCE
;
301 if ( ! clientEntity
->X
.isReadable() )
303 nlwarning( "Multi-machine vision bug with client %s", client
->eId().toString().c_str() );
304 return UNSET_DISTANCE
;
307 TCoord pos1x
= clientEntity
->X(), pos1y
= clientEntity
->Y();
308 TCoord pos2x
= seenEntity
->X(), pos2y
= seenEntity
->Y();
310 // Obsolete: we used to use the position in history (last sent pos). Now it's the official position
311 // in order to avoid problem in mode COMBAT_FLOAT...
312 // Get absolute entity pos (note: in local mode, the relative pos is not stored in the history)
313 //CAction::TValue vlastposx, vlastposy, vlastposz;
314 //bool histohasvalue = _History->getPosition( client->clientId(), slot, vlastposx, vlastposy, vlastposz );
315 //if ( histohasvalue )
317 // pos2x = getAbsoluteCoordinateFrom64( vlastposx );
318 // pos2y = getAbsoluteCoordinateFrom64( vlastposy );
319 // //nlinfo( "lastpos: %d %d, vlastpos: %" NL_I64 "u %" NL_I64 "u", pos2x, pos2y, vlastposx, vlastposy );
321 TCoord d = (TCoord)(abs(pos1x-pos2x) + abs(pos1y-pos2y));
324 nlwarning( "Invalid distance calculation with lastsent pos (C%hu S%hu D=%d)", client->clientId(), (uint16)slot, d );
329 TCoord d = (TCoord)(abs(pos1x-pos2x) + abs(pos1y-pos2y));
332 nlwarning( "Invalid distance calculation with real pos (C%hu S%hu D=%d)", client->clientId(), (uint16)slot, d );
338 // Calculate 2D Manhattan distance
339 TCoord result
= (TCoord
)(abs(pos1x
-pos2x
) + abs(pos1y
-pos2y
));
341 result
= UNSET_DISTANCE
; // correct error if positions are wrong
347 * Add a pair. The argument 'furthestceid' is used when removing an item is required.
349 bool CVisionProvider::addPair( TClientId clientid
, const TEntityIndex
& entityindex
, CLFECOMMON::TCLEntityId slot
)
351 CClientHost
*client
= clientHost(clientid
);
355 // If we have unassociated but no removed the pair yet, complete the removal
356 //if ( client->IdTranslator.getInfo(slot).AssociationState != CClientEntityIdTranslator::CEntityInfo::UnusedAssociation ) // CHANGED BEN
357 if (_VisionArray
->getAssociationState(clientid
, slot
) != TPairState::UnusedAssociation
)
359 //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
360 LOG_VISION( "FEVIS:%u: Replacing E%u by E%u in slot %hu", CTickEventHandler::getGameCycle(), _VisionArray
->getEntityIndex(clientid
, slot
).getIndex(), entityindex
.getIndex(), (uint16
)slot
);
361 postRemovePair( clientid
, slot
);
365 //flog.displayRawNL( "ADD C%hu E%u, slot %hu, id %s", clientid, entityindex, slot, CFrontEndPropertyReceiver::getEntity(entityindex)->id.toString().c_str() );
367 /* 1. Associate Entity Index to a new TCLEntityId (or get exiting association if this new association occurred before a dissociation acknowledge from the client)
370 if ( slot
< MAX_SEEN_ENTITIES_PER_CLIENT
)
372 // Check if the entity is not still in a slot of the client
373 TCLEntityId slotFromEntityIndex
= client
->IdTranslator
.getCEId( entityindex
);
374 if ( slotFromEntityIndex
!= INVALID_SLOT
)
376 // 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)
377 LOG_VISION( "FEVIS: Moving E%u from S%hu to S%hu", entityindex
.getIndex(), (uint16
)slotFromEntityIndex
, (uint16
)slot
);
378 postRemovePair( clientid
, slotFromEntityIndex
);
380 if ( ! client
->IdTranslator
.acquireCEId( entityindex
, (TCLEntityId
)slot
) )
382 return false; // should not occur (see warning displayed by acquireCEId())
387 //nlwarning( "Invalid slot %hu given by GPMS for entity E%u seen by client %hu", slot, entityindex, clientid );
389 return false; // should not occur
393 //CClientEntityIdTranslator::CEntityInfo& info = client->IdTranslator.getInfo((TCLEntityId)slot); // CHANGED BEN
395 //info.AssociationState = CClientEntityIdTranslator::CEntityInfo::AwaitingAssAck; // CHANGED BEN
396 _VisionArray
->setAssociationState(clientid
, slot
, TPairState::AwaitingAssAck
);
397 // NormalAssociation set in CDistancePrioritizer::fillDiscreetProperty() with Sheet
399 //info.AssociationState = CClientEntityIdTranslator::CEntityInfo::NormalAssociation; // CHANGED BEN
400 _VisionArray
->setAssociationState(clientid
, slot
, TPairState::NormalAssociation
);
403 /* 2. Fill the item attributes
405 LOG_VISION( "FEVIS: %u: Adding pair C%hu -> slot %hu (E%u_%hu)", CTickEventHandler::getGameCycle(), clientid
, (uint16
)slot
, entityindex
.getIndex(), entityindex
.counter() );
406 CEntity
*sentity
= TheEntityContainer
->getEntity( entityindex
);
407 //nlinfo( "AddPair %hu %hu (E%u)", clientid, (uint16)slot, entityindex );
408 _VisionArray
->setEntityIndex( clientid
, slot
, entityindex
);
409 TPairState
& pairState
= _VisionArray
->getPairState( clientid
, slot
);
410 pairState
.associate();
412 pairState
.DistanceCE
= 0; // slot 0's distance is always 0 because we can't use the last sent pos if it is not sent
414 pairState
.DistanceCE
= calcDistance( client
, (TCLEntityId
)slot
, entityindex
);
415 --client
->NbFreeEntityItems
;
417 if ( TheDataset
.getEntityId( entityindex
).getType() == RYZOMID::player
)
418 LOG_VISION( "FEVIS: Seen E%u is a player", entityindex
.getIndex() );
421 CFrontEndService::instance()->PrioSub
.Prioritizer
.addEntitySeenByClient( clientid
, slot
);
426 if ( ! _History
->addEntityToClient( (TCLEntityId
)slot
, client
->clientId() ) )
428 nlwarning( "Cannot add entity to client in property history: entity already used" );
432 // Add to observer list: the clients who see the entity (and its ceid for them)
433 //_ObserverList[entityindex].insert( TPairClientSlot( clientid, (TCLEntityId)slot ) );
435 //client->displayClientProperties();
444 void CVisionProvider::removePair( TClientId clientid
, TCLEntityId slot
)
446 LOG_VISION( "FEVIS:%u: Unassociating C%hu -> slot %hu", CTickEventHandler::getGameCycle(), clientid
, (uint16
)slot
);
448 // Prevent a vision bug where two removals would occur (e.g. when the PC is stressed-slow)
449 CClientHost
*client
= clientHost( clientid
);
450 if ( ! client
) // we had such a situation live once
453 //CClientEntityIdTranslator::CEntityInfo &info = client->IdTranslator.getInfo(slot); // CHANGED BEN
454 //if ( info.AssociationState == CClientEntityIdTranslator::CEntityInfo::UnusedAssociation ) // CHANGED BEN
455 if (_VisionArray
->getAssociationState(clientid
, slot
) == TPairState::UnusedAssociation
)
457 nlwarning( "%u: Cannot remove pair twice (or pair not associated): C%hu S%hu", CTickEventHandler::getGameCycle(), clientid
, (uint16
)slot
);
461 TPairState
& pairState
= _VisionArray
->getPairState( clientid
, slot
);
462 pairState
.unassociate();
470 void CVisionProvider::postRemovePair( TClientId clientid
, TCLEntityId slot
)
475 //flog.displayRawNL( "REM C%hu E%u, id %s", clientid, entityindex, CFrontEndPropertyReceiver::getEntity(entityindex)->id.toString().c_str() );
477 nlassert ( (clientid
!= INVALID_CLIENT
) && (slot
!= INVALID_SLOT
) );
478 CClientHost
*client
= clientHost( clientid
);
482 //CClientEntityIdTranslator::CEntityInfo &info = client->IdTranslator.getInfo(slot); // CHANGED BEN
483 //TEntityIndex entityindex = info.EntityInSlot; // CHANGED BEN
485 TEntityIndex entityindex
= _VisionArray
->getEntityIndex(clientid
, slot
);
486 if ( !entityindex
.isValid() )
488 // No warning when slot 0 because this is normal at the beginning of the life of a client
491 nlwarning( "Cannot remove vision pair C%hu -> slot %hu!", clientid
, (uint16
)slot
);
496 CFrontEndService::instance()->PrioSub
.Prioritizer
.removeEntitySeenByClient( clientid
, slot
);
498 //client->displayClientProperties();
500 LOG_VISION( "FEVIS: %u: Removing pair C%hu -> slot %hu (E%u_%hu)", CTickEventHandler::getGameCycle(), clientid
, (uint16
)slot
, entityindex
.getIndex(), entityindex
.counter() );
501 CEntity
*sentity
= TheEntityContainer
->getEntity( entityindex
);
503 if ( TheDataset
.getEntityId( entityindex
).getType() == RYZOMID::player
)
504 LOG_VISION( "FEVIS: Unseen E%u is a player", entityindex
.getIndex() );
507 //info.AssociationState = CClientEntityIdTranslator::CEntityInfo::UnusedAssociation; // CHANGED BEN
508 _VisionArray
->setAssociationState(clientid
, slot
, TPairState::UnusedAssociation
);
510 // Remove from history
512 _History
->removeEntityOfClient( slot
, clientid
);
514 // Remove from observer list: the clients who see the entity (and its ceid for them)
515 //removeFromObserverList( entityindex, clientid, slot );
518 client
->IdTranslator
.releaseId( entityindex
/*_VisionArray->getEntityIndex( client->clientId(), ceid )*/ );
519 ++client
->NbFreeEntityItems
;
520 //LOG_VISION( "FEVIS: Client %hu has %hu free items (+)", client->clientId(), client->NbFreeEntityItems );
522 // Reset item in the vision array
523 TPairState
& pairState
= _VisionArray
->getPairState( clientid
, slot
);
524 pairState
.resetItem();
529 * Replace the entity in a slot (e.g. when transforming a dead character to a sack)
531 void CVisionProvider::replacePair( TClientId clientid
, const TEntityIndex
& newEntityIndex
, CLFECOMMON::TCLEntityId slot
)
534 * 1. Clear the old entityindex
538 nlassert ( (clientid
!= INVALID_CLIENT
) && (slot
!= INVALID_SLOT
) );
539 CClientHost
*client
= clientHost( clientid
);
543 //CClientEntityIdTranslator::CEntityInfo &info = client->IdTranslator.getInfo(slot); // CHANGED BEN
544 //TEntityIndex entityindex = info.EntityInSlot; // CHANGED BEN
546 TEntityIndex entityindex
= _VisionArray
->getEntityIndex(clientid
, slot
);
547 if ( !entityindex
.isValid() )
549 nlwarning( "Cannot replace vision pair C%hu -> slot %hu!", clientid
, (uint16
)slot
);
553 //info.AssociationChannel == CClientEntityIdTranslator::CEntityInfo::NormalAssociation;
555 //client->displayClientProperties();
557 LOG_VISION( "FEVIS: %u: Replacing pair C%hu -> slot %hu (E%u becomes E%u)", CTickEventHandler::getGameCycle(), clientid
, (uint16
)slot
, entityindex
.getIndex(), newEntityIndex
.getIndex() );
558 CEntity
*sentity
= TheEntityContainer
->getEntity( entityindex
);
560 if ( TheDataset
.getEntityId( entityindex
).getType() == RYZOMID::player
)
561 LOG_VISION( "FEVIS: Unseen E%u is a player", entityindex
.getIndex() );
564 // Remove from history
566 _History
->removeEntityOfClient( slot
, clientid
);
568 // Remove from observer list: the clients who see the entity (and its ceid for them)
569 //removeFromObserverList( entityindex, clientid, slot );
572 client
->IdTranslator
.releaseId( entityindex
/*_VisionArray->getEntityIndex( client->clientId(), ceid )*/ );
573 //LOG_VISION( "FEVIS: Client %hu has %hu free items (+)", client->clientId(), client->NbFreeEntityItems );
576 * 2. Set the new entityindex
581 // Associate Entity Index to the slot
582 if ( ! client
->IdTranslator
.acquireCEId( newEntityIndex
, (TCLEntityId
)slot
) )
588 /* 2. Fill the item attributes
590 //LOG_VISION( "FEVIS: Adding pair C%hu -> slot %hu (E%u) (replace)", clientid, slot, entityindex );
591 sentity
= TheEntityContainer
->getEntity( newEntityIndex
);
592 //nlinfo( "AddPair %hu %hu (E%u)", clientid, (uint16)slot, entityindex );
593 TPairState
& pairState
= _VisionArray
->getPairState( clientid
, slot
);
594 pairState
.changeAssociation();
595 pairState
.resetPrio();
596 pairState
.EntityIndex
= newEntityIndex
;
598 pairState
.DistanceCE
= 0;
600 pairState
.DistanceCE
= calcDistance( client
, (TCLEntityId
)slot
, newEntityIndex
);
602 if ( TheDataset
.getEntityId( newEntityIndex
).getType() == RYZOMID::player
)
603 LOG_VISION( "FEVIS: Seen E%u is a player", newEntityIndex
.getIndex() );
609 if ( ! _History
->addEntityToClient( (TCLEntityId
)slot
, clientid
) )
611 nlwarning( "Cannot add entity to client in property history: entity already used" );
615 // Add to observer list: the clients who see the entity (and its ceid for them)
616 //_ObserverList[newEntityIndex].insert( TPairClientSlot( clientid, (TCLEntityId)slot ) );
622 * Remove item from observer list of entityindex
624 /*void CVisionProvider::removeFromObserverList( const TEntityIndex& entityindex, TClientId clientid, TCLEntityId ceid )
626 _ObserverList[entityindex].erase( TPairClientSlot( clientid, ceid ) );
631 * Reset all slots of all clients (e.g. when GPMS falls down)
633 void CVisionProvider::resetVision()
635 nlinfo( "Resetting all slots of all clients..." );
636 THostMap
& clientmap
= CFrontEndService::instance()->receiveSub()->clientMap();
637 THostMap::iterator ihm
;
638 for ( ihm
=clientmap
.begin(); ihm
!=clientmap
.end(); ++ihm
)
640 resetVision( GETCLIENTA(ihm
) );
646 * Reset all slots of one client (e.g. when a client is unspawned)
648 void CVisionProvider::resetVision( CClientHost
*clienthost
)
650 // Get all entities seen by this client
652 for ( e
=0; e
!=MAX_SEEN_ENTITIES_PER_CLIENT
; ++e
)
654 //if ( _VisionArray->getAssociationState( clienthost, (TCLEntityId)e ) != CClientEntityIdTranslator::CEntityInfo::UnusedAssociation ) // CHANGED BEN
655 if ( _VisionArray
->getAssociationState( clienthost
->clientId(), (TCLEntityId
)e
) != TPairState::UnusedAssociation
)
657 // Remove pair on the FE and on the client
658 removePair( clienthost
->clientId(), (TCLEntityId
)e
);
665 * Display the properties of an entity in the vision
667 void CVisionProvider::displayEntityInfo( const CEntity
& e
, const TEntityIndex
& entityIndex
, NLMISC::CLog
*log
) const
669 if ( ! e
.X
.isReadable() )
671 log
->displayNL( "Entity %u not initialized", entityIndex
.getIndex() );
675 const CEntityId
& eid
= TheDataset
.getEntityId( entityIndex
);
676 uint64 properties
[NB_VISUAL_PROPERTIES
];
677 CEntity::fillVisualPropertiesFromMirror( properties
, entityIndex
);
678 string sheetIdS
= CSheetId((uint32
)properties
[PROPERTY_SHEET
]).toString();
679 log
->displayNL( "E%u %s Id %s Name %s Sheet %u (%s) GameCycle %u",
680 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() );
681 log
->displayNL( "%u entities entered vision, %u entities left vision", e
.VisionIn
.size(), e
.VisionOut
.size() );
682 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" );
683 e
.displayProperties( entityIndex
, log
);
686 str
+= NLMISC::toString(e
.propIsInitializedState(0)) + "''"; // skip 1 & 2
687 // ss << e.propIsInitializedState(0) << "''"; // skip 1 & 2
688 /*for ( sint p=0; p!=NB_VISUAL_PROPERTIES; ++p )
690 ss << " " << e.properties[p];
692 nlinfo( "Property values: %s", ss.str().c_str() );
694 for ( sint p
=3; p
!=NB_VISUAL_PROPERTIES
; ++p
)
696 //ss << e.propIsInitializedState(p);
697 str
+= NLMISC::toString(e
.propIsInitializedState(p
));
698 if ( (p
+1) % 4 == 0 )
702 log
->displayNL( "Initialized: %s", str
.c_str() );
707 * Reset assoc/disas counters
709 void CVisionProvider::resetAssocCounter()
713 AssocStartTime
= CTime::getLocalTime();
718 * Display assoc/disas freqs
720 void CVisionProvider::displayAssocFreqs(CLog
*log
)
722 float duration
= ((float)(CTime::getLocalTime()-AssocStartTime
))/1000.0f
;
723 log
->displayNL( "Assoc: %.1f Hz - Disac: %.1f Hz", ((float)AssocCounter
)/duration
, ((float)DisasCounter
)/duration
);
727 NLMISC_COMMAND( displayEntityInfo
, "Display the properties of an entity", "<entityIndex>" )
729 // check args, if there s not the right number of parameter, return bad
730 if(args
.size() != 1) return false;
733 TDataSetIndex entityIndex
;
734 NLMISC::fromString(args
[0], entityIndex
);
735 if ( entityIndex
< (uint32
)TheDataset
.maxNbRows() )
737 TDataSetRow datasetrow
= TheDataset
.getCurrentDataSetRow( entityIndex
);
738 CEntity
*entity
= TheEntityContainer
->getEntity( datasetrow
);
739 if ( ! TheDataset
.getEntityId( datasetrow
).isUnknownId() ) // TODO: unknown or 0 ??
741 CFrontEndService::instance()->PrioSub
.VisionProvider
.displayEntityInfo( *entity
, datasetrow
);
745 log
.displayNL( "There is no such an entity index" );
750 NLMISC_COMMAND( displayEntityInfoById
, "Display the properties of an entity, by entity id (if found)", "<entityId>" )
760 if (sscanf(args
[0].c_str(), "(%" NL_I64
"x:%x:%x:%x)", &id
, &type
, &creatorId
, &dynamicId
) != 4)
762 eid
.setShortId( id
);
764 eid
.setCreatorId( creatorId
);
765 eid
.setDynamicId( dynamicId
);
767 TEntityIndex entityIndex
= TheEntityContainer
->entityIdToIndex( eid
);
768 if ( entityIndex
.isValid() )
770 CEntity
* entity
= TheEntityContainer
->getEntity( entityIndex
);
771 if ( ! TheDataset
.getEntityId( entityIndex
).isUnknownId() ) // TODO: unknown or 0 ??
773 CFrontEndService::instance()->PrioSub
.VisionProvider
.displayEntityInfo( *entity
, entityIndex
);
777 log
.displayNL( "There is no entity with the specified id" );
782 NLMISC_COMMAND( displaySlotInfo
, "Display info for a particular slot of a client", "<clientid> <slot>" )
784 if ( args
.size() < 2 )
788 NLMISC::fromString(args
[0], clientid
);
789 CLFECOMMON::TCLEntityId slot
;
790 NLMISC::fromString(args
[1], slot
);
791 CClientHost
*clienthost
;
792 if ( (clientid
<= MaxNbClients
) && ((clienthost
= CFrontEndService::instance()->sendSub()->clientIdCont()[clientid
]) != NULL
) )
794 clienthost
->displaySlotProperties( slot
, true, &log
);
799 NLMISC_COMMAND( resetAssocCounters
, "Reset assoc/disas counters", "" )
801 CFrontEndService::instance()->PrioSub
.VisionProvider
.resetAssocCounter();
805 NLMISC_COMMAND( displayAssocFreqs
, "Display assoc/disas freqs", "" )
807 CFrontEndService::instance()->PrioSub
.VisionProvider
.displayAssocFreqs(&log
);
811 /*NLMISC_COMMAND( verboseVision, "Turn on/off or check the state of verbose logging of vision", "" )
813 if ( args.size() == 1 )
815 if ( args[0] == string("on") || args[0] == string("1") )
817 else if ( args[0] == string("off") || args[0] == string("0") )
821 log.displayNL( "verboseVision is %s", verboseVision ? "on" : "off" );
826 NLMISC_COMMAND( displayVisionLog
, "Display Tmp Debug Log", "" )
828 TmpDebugDisplayer
->write( &log
);