void UpdateVisibleEntities() {
if( SpectatedPlayer != null ) {
if( SpectatedPlayer.IsDisconnected || !Player.CanSee( SpectatedPlayer ) ) {
Player.Message( "Stopped spectating {0}&S (disconnected)", SpectatedPlayer.GetClassyName() );
SpectatedPlayer = null;
} else {
Position spectatePos = SpectatedPlayer.Position;
World spectateWorld = SpectatedPlayer.World;
if( spectateWorld != Player.World ) {
postJoinPosition = spectatePos;
Player.Message( "Joined {0}&S to continue spectating {1}",
spectateWorld.GetClassyName(),
SpectatedPlayer.GetClassyName() );
JoinWorldNow( spectateWorld, false, false );
} else if( spectatePos != Player.Position ) {
SendNow( PacketWriter.MakeSelfTeleport( spectatePos ) );
}
}
}
Player[] worldPlayerList = Player.World.PlayerList;
Position pos = Player.Position;
for( int i = 0; i < worldPlayerList.Length; i++ ) {
Player otherPlayer = worldPlayerList[i];
if( otherPlayer == Player ) continue;
if( !Player.CanSee( otherPlayer ) ) continue;
if( SpectatedPlayer == otherPlayer || otherPlayer.Session.SpectatedPlayer == Player ) continue;
Position otherPos = otherPlayer.Position;
int distance = pos.DistanceSquaredTo( otherPos );
VisibleEntity entity;
// if Player has a corresponding VisibleEntity
if( entities.TryGetValue( otherPlayer, out entity ) ) {
entity.MarkedForRetention = true;
if( entity.LastKnownRank != otherPlayer.Info.Rank ) {
ReAddEntity( entity, otherPlayer, otherPos );
entity.LastKnownRank = otherPlayer.Info.Rank;
} else if( entity.Hidden ) {
if( distance < entityShowingThreshold ) {
ShowEntity( entity, otherPos );
}
} else {
if( distance > entityHidingThreshold ) {
HideEntity( entity );
} else if( entity.LastKnownPosition != otherPos ) {
MoveEntity( entity, otherPos );
}
}
} else {
AddEntity( otherPlayer, otherPos );
}
}
// Find entities to remove (not marked for retention).
foreach( var pair in entities ) {
if( pair.Value.MarkedForRetention ) {
pair.Value.MarkedForRetention = false;
} else {
playersToRemove.Push( pair.Key );
}
}
// Remove non-retained entities
while( playersToRemove.Count > 0 ) {
RemoveEntity( playersToRemove.Pop() );
}
fullUpdateCounter++;
if( fullUpdateCounter >= FullPositionUpdateInterval ) {
fullUpdateCounter = 0;
}
}