private static void HandlePong( CommandResponseOp <PingResponder.Commands.Ping, Pong> response, Connection connection) { if (response.StatusCode != StatusCode.Success) { StringBuilder logMessageBuilder = new StringBuilder(); logMessageBuilder.Append( String.Format("Received invalid OnCommandResponse for request ID {0} with status code {1} to entity with ID {2}.", response.RequestId, response.StatusCode, response.EntityId)); if (!string.IsNullOrEmpty(response.Message)) { logMessageBuilder.Append(String.Format("The message was \'{0}\'.", response.Message)); } if (!response.Response.HasValue) { logMessageBuilder.Append("The response was missing."); } else { logMessageBuilder.Append( String.Format("The EntityIdResponse ID value was {0}", response.Response.Value)); } connection.SendLogMessage(LogLevel.Warn, LoggerName, logMessageBuilder.ToString()); } else { var workerType = response.Response.Value.workerType; var workerMessage = response.Response.Value.workerMessage; var logMessage = String.Format("New Response: {0} says \"{1}\"", workerType, workerMessage); Console.WriteLine(logMessage); connection.SendLogMessage(LogLevel.Info, LoggerName, logMessage); } }
/// <summary> /// Runs through the current view and creates updates for the entities it has write authority over /// Also fills in the list of all current sequence ids seen /// </summary> /// <param name="view"></param> /// <param name="connection">Pass the connection in to log messages, not to send updates</param> private static bool TryCreateEntitiesUpdatesAndSequenceIdList(Dictionary <EntityId, ViewEntity> view, Connection connection) { //WorkerConnection.SendLogMessage(LogLevel.Info, "LifeWorker", "Beginning Update Entities"); int liveNeighborCount = 0; bool canGetAllNeighbors = false; //Run through every id/entity pair in the view foreach (var ve in view) { if (ve.Value.hasAuthority) //Only do this update if this worker has write access to the entity { EntityId id = ve.Key; Entity e = ve.Value.entity; if (e == null) { throw new NullReferenceException("View Entities Enum has returned a null entity for EntityID " + ve.Key.ToString()); } //Only do this if the entity is a Cell type (which should have a Life component) var componentIdSet = e.GetComponentIds(); if (componentIdSet.Contains(Life.ComponentId)) { // Add the current sequence id to the list of sequence ids for later selective updating AddSequenceIdToList(GetLatestSequenceId(e)); //Get the number of live neighbors canGetAllNeighbors = TryGetLiveNeighbors(id, e, view, out liveNeighborCount); //Update the entity based on the live neighbor count if (canGetAllNeighbors) { CreateEntityUpdates(id, e, liveNeighborCount, connection); } else { return(false); //If all neighbors can't be retrieved then the entity can't be updated. If one entity can't be updated then none can. } } else { WorkerConnection.SendLogMessage(LogLevel.Info, "LifeWorker", "Life component not present on entity " + id.ToString() + ". update not done."); } } } return(true); //All neighbors were successfully collected and updates successfully created }
private static System.Collections.Generic.List <ulong> sequenceIds = new System.Collections.Generic.List <ulong>(); //List of all current Sequence Ids, could probably split this out to a separate class with all the specific methods static int Main(string[] arguments) { //"${IMPROBABLE_RECEPTIONIST_HOST}", "${IMPROBABLE_RECEPTIONIST_PORT}", "${IMPROBABLE_WORKER_ID}" defined as passed in as part of config string hostName = arguments[0]; ushort port = Convert.ToUInt16(arguments[1]); string workerId = arguments[2]; Assembly.Load("GeneratedCode"); using (var connection = ConnectWorker(workerId, hostName, port)) { using (var dispatcher = new Dispatcher()) { IsConnected = true; dispatcher.OnDisconnect(op => { Console.Error.WriteLine("[disconnect] {0}", op.Reason); IsConnected = false; }); dispatcher.OnLogMessage(op => { connection.SendLogMessage(op.Level, LoggerName, op.Message); Console.WriteLine("Log Message: {0}", op.Message); if (op.Level == LogLevel.Fatal) { Console.Error.WriteLine("Fatal error: {0}", op.Message); Environment.Exit(ErrorExitStatus); } }); dispatcher.OnAuthorityChange <Life>(op => { ViewEntity entity; if (EntityView.TryGetValue(op.EntityId, out entity)) { if (op.Authority == Authority.Authoritative) { entity.hasAuthority = true; } else if (op.Authority == Authority.NotAuthoritative) { entity.hasAuthority = false; } else if (op.Authority == Authority.AuthorityLossImminent) { entity.hasAuthority = false; } } }); dispatcher.OnAddComponent <Life>(op => { ViewEntity entity; if (EntityView.TryGetValue(op.EntityId, out entity)) { entity.entity.Add <Life>(op.Data); } else { ViewEntity newEntity = new ViewEntity(); EntityView.Add(op.EntityId, newEntity); newEntity.entity.Add <Life>(op.Data); } }); dispatcher.OnComponentUpdate <Life>(op => { ViewEntity entity; if (EntityView.TryGetValue(op.EntityId, out entity)) { var update = op.Update.Get(); entity.entity.Update <Life>(update); } }); dispatcher.OnAddComponent <Neighbors>(op => { ViewEntity entity; if (EntityView.TryGetValue(op.EntityId, out entity)) { entity.entity.Add <Neighbors>(op.Data); } else { ViewEntity newEntity = new ViewEntity(); EntityView.Add(op.EntityId, newEntity); newEntity.entity.Add <Neighbors>(op.Data); } }); dispatcher.OnComponentUpdate <Neighbors>(op => { ViewEntity entity; if (EntityView.TryGetValue(op.EntityId, out entity)) { var update = op.Update.Get(); entity.entity.Update <Neighbors>(update); } }); dispatcher.OnAddEntity(op => { //AddEntity will always be followed by OnAddComponent ViewEntity newEntity = new ViewEntity(); newEntity.hasAuthority = true; newEntity.entity = new Entity(); ViewEntity oldEntity; if (!EntityView.TryGetValue(op.EntityId, out oldEntity)) { EntityView.Add(op.EntityId, newEntity); } }); dispatcher.OnRemoveEntity(op => { EntityView.Remove(op.EntityId); }); WorkerConnection = connection; WorkerConnection.SendLogMessage(LogLevel.Info, "LifeWorker", "Worker Connected"); RunEventLoop(connection, dispatcher); } } return(0); }