private void insertOrganismsFromQueue()
{
while (_newOrganismQueue.Count > 0)
{
Object queueObject = _newOrganismQueue.Dequeue();
if (typeof (TeleportState).IsAssignableFrom(queueObject.GetType()))
{
// Teleported organism
TeleportState teleportState = (TeleportState) queueObject;
if (teleportState.TeleportedToSelf)
{
// Make sure this wasn't teleported from a previous game on this machine
// if it was, destroy the organism by not handling it
if (teleportState.Originator != _newWorldState.StateGuid)
{
OnEngineStateChanged(new EngineStateChangedEventArgs(EngineStateChangeType.Other,
"Teleport attempted to an old game.",
"A teleport was attempted to an old game, the organism was lost in space."));
continue;
}
}
Organism organism;
try
{
organism = teleportState.TeleportedToSelf
? teleportState.Organism
: teleportState.OrganismWrapper.Organism;
}
catch (FileLoadException e)
{
// Here we want to log how many organisms are getting killed
// FileLoadException will happen when an organism is blacklisted, so don't show a message because the message contains the name
ErrorLog.LogHandledException(e);
OnEngineStateChanged(new EngineStateChangedEventArgs(EngineStateChangeType.Other,
"An organism died during teleportation"));
continue;
}
catch (Exception e)
{
// Here we want to log how many organisms are getting killed
ErrorLog.LogHandledException(e);
OnEngineStateChanged(new EngineStateChangedEventArgs(EngineStateChangeType.Other,
"An organism died during teleportation: " +
e.Message));
continue;
}
OrganismState organismState = teleportState.OrganismState;
// Make it mutable and change its position
organismState = organismState.CloneMutable();
Point newPosition = findEmptyPosition(organismState.CellRadius, Point.Empty);
if (newPosition != Point.Empty)
{
organismState.Position = newPosition;
}
else
{
// We couldn't find a place to put it, kill the organism
OnEngineStateChanged(new EngineStateChangedEventArgs(EngineStateChangeType.Other,
"A '" +
((Species) organismState.Species).Name +
"' died during teleportation: couldn't find an open spot quickly enough."));
continue;
}
try
{
// Host it and give it state in a random location
_scheduler.Add(organism, organismState.ID);
}
catch (OrganismAlreadyExistsException e)
{
// An organism can get duplicated if a peer teleports it, and then shuts down
// unexpectedly, restarts and the organism is alive on it again (because it reverts
// to the last saved state)
ErrorLog.LogHandledException(e);
continue;
}
try
{
if (!teleportState.TeleportedToSelf)
{
if (organism is Animal)
{
((Animal) organism).DeserializeAnimal(organism.SerializedStream);
}
else
{
((Plant) organism).DeserializePlant(organism.SerializedStream);
}
}
organism.SerializedStream = null;
}
catch (Exception e)
{
OnEngineStateChanged(new EngineStateChangedEventArgs(EngineStateChangeType.Other,
"A '" +
((Species) organismState.Species).Name +
"' lost its memory during teleportation: " +
e.Message));
}
_newWorldState.AddOrganism(organismState);
// Tell the organism it was teleported
organismState.OrganismEvents.Teleported = new TeleportedEventArgs(teleportState.TeleportedToSelf);
countOrganism(organismState, PopulationChangeReason.TeleportedTo);
//The GameEngine state has changed so raise an event to that effect
if (!teleportState.TeleportedToSelf)
{
OnEngineStateChanged(EngineStateChangedEventArgs.AnimalArrived(organismState));
}
}
else
{
// new organism
NewOrganism newOrganism = (NewOrganism) queueObject;
OrganismState organismState = newOrganism.State;
Point newPosition = newOrganism.AddAtRandomLocation
?
findEmptyPosition(organismState.CellRadius, Point.Empty)
:
findEmptyPosition(organismState.CellRadius,
new Point(
organismState.Position.X >>
EngineSettings.GridWidthPowerOfTwo,
organismState.Position.Y >>
EngineSettings.GridHeightPowerOfTwo));
if (newPosition != Point.Empty)
{
organismState.Position = newPosition;
}
else
{
OnEngineStateChanged(new EngineStateChangedEventArgs(EngineStateChangeType.Other,
"A '" +
((Species) organismState.Species).Name +
"' died at birth: not enough space in the world."));
continue;
}
// Host it and Give it state in a random location
Debug.Assert(((Species) organismState.Species).Type != null,
"Type is null on organism '" + ((Species) organismState.Species).Name + "'");
try
{
_scheduler.Create(((Species) organismState.Species).Type, organismState.ID);
}
catch (Exception e)
{
ErrorLog.LogHandledException(e);
OnEngineStateChanged(new EngineStateChangedEventArgs(EngineStateChangeType.Other,
"An organism died at birth: " + e.Message));
continue;
}
_newWorldState.AddOrganism(organismState);
// Tell the organism it was born
organismState.OrganismEvents.Born = new BornEventArgs(newOrganism.Dna);
countOrganism(organismState, PopulationChangeReason.Born);
}
}
}