private void UpdateVisibleEntities()
{
if ( World == null )
PlayerOpException.ThrowNoWorld( this );
if ( possessionPlayer != null ) {
if ( !possessionPlayer.IsOnline || possessionPlayer.IsSpectating ) {
Message( "You have been released from possession" );
possessionPlayer = null;
} else {
Position sendTo = possessionPlayer.Position;
World possessedWorld = possessionPlayer.World;
if ( possessedWorld == null ) {
throw new InvalidOperationException( "Possess: Something weird just happened (error 404)." );
}
if ( possessedWorld != World ) {
if ( CanJoin( possessedWorld ) ) {
postJoinPosition = sendTo;
Message( "Joined {0}&S (possessed)",
possessedWorld.ClassyName );
JoinWorldNow( possessedWorld, false, WorldChangeReason.SpectateTargetJoined );
} else {
possessionPlayer.Message( "Stopped possessing {0}&S (they cannot join {1}&S)",
ClassyName,
possessedWorld.ClassyName );
possessionPlayer = null;
}
} else if ( sendTo != Position ) {
SendNow( PacketWriter.MakeSelfTeleport( sendTo ) );
}
}
}
if ( spectatedPlayer != null ) {
if ( !spectatedPlayer.IsOnline || !CanSee( spectatedPlayer ) ) {
Message( "Stopped spectating {0}&S (disconnected)", spectatedPlayer.ClassyName );
spectatedPlayer = null;
} else {
Position spectatePos = spectatedPlayer.Position;
World spectateWorld = spectatedPlayer.World;
if ( spectateWorld == null ) {
throw new InvalidOperationException( "Trying to spectate player without a world." );
}
if ( spectateWorld != World ) {
if ( CanJoin( spectateWorld ) ) {
postJoinPosition = spectatePos;
Message( "Joined {0}&S to continue spectating {1}",
spectateWorld.ClassyName,
spectatedPlayer.ClassyName );
JoinWorldNow( spectateWorld, false, WorldChangeReason.SpectateTargetJoined );
} else {
Message( "Stopped spectating {0}&S (cannot join {1}&S)",
spectatedPlayer.ClassyName,
spectateWorld.ClassyName );
spectatedPlayer = null;
}
} else if ( spectatePos != Position ) {
SendNow( PacketWriter.MakeSelfTeleport( spectatePos ) );
}
}
}
Player[] worldPlayerList = World.Players;
Position pos = Position;
for ( int i = 0; i < worldPlayerList.Length; i++ ) {
Player otherPlayer = worldPlayerList[i];
if ( otherPlayer == this ||
!CanSeeMoving( otherPlayer ) ||
spectatedPlayer == otherPlayer || possessionPlayer != null )
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;
}
if ( otherPlayer.entityChanged ) {
ReAddEntity( entity, otherPlayer, otherPos );
otherPlayer.entityChanged = false;
} 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;
}
}