/// <summary> /// Coordinates all the processing for each time slice /// </summary> /// <param name="updateIncrement"></param> public static void NextTimeSlice() { /* * Initially the only items that would be named in events would be actual units. * Now that other things (ActiveRegions,for example) can also appear in events * it is necessary to allow UnitFActs to know those names too, to keep various checks on * object name legality from failing */ /* 1. Process the incoming list of events from below */ // Which units are currently on the incoming list? List <string> unitList = IncomingList.AffectedUnits(); for (int i = 0; i < unitList.Count; i++) { List <IncomingItemType> eventList = IncomingList.Retrieve(unitList[i]); /* do things with these events */ for (int j = 0; j < eventList.Count; j++) { ScenarioEventType thisItem = eventList[j].TheEvent; Coordinator.debugLogger.Writeline("Timer", "Time: " + timer + " Unit " + unitList[i] + " has incoming " + thisItem.GetType().ToString(), "test"); if (UnitFacts.AnyDead(thisItem.AllUnits)) { continue; } Boolean launchedByOwner; switch (thisItem.GetType().ToString()) { case name_Space + "MoveComplete_Event": { Coordinator.debugLogger.Writeline("Timer", "Unit " + thisItem.UnitID + " MoveComplete discovered at t=" + timer.ToString(), "test"); // scan happenings list for matches VerifyMatch = ActionMatch; SeekHappening(thisItem.UnitID, "MoveComplete_Event"); SeekSpeciesHappening(thisItem, "MoveComplete_Event"); } break; case name_Space + "StateChangeNotice": string newState = ((StateChangeNotice)thisItem).NewState; Coordinator.debugLogger.Writeline("Timer", "Unit " + thisItem.UnitID + " StateChange to " + newState + " discovered at t=" + timer.ToString(), "test"); VerifyMatch = StateMatch; List <string> affectedUnitList = new List <string>(); if ("Dead" != newState) { affectedUnitList.Add(thisItem.UnitID); UnitFacts.CurrentUnitStates[thisItem.UnitID] = newState; // newState; } else // Purge queues if the new state is "Dead" { affectedUnitList = SubplatformRecords.DeepDockedList(thisItem.UnitID); } for (int someUnit = 0; someUnit < affectedUnitList.Count; someUnit++) { if ("Dead" == newState) { UnitFacts.CurrentUnitStates[affectedUnitList[someUnit]] = "Dead"; // newState; //first drop all timer events involving this unit TimerQueueClass.FlushOneUnit(affectedUnitList[someUnit]); } SeekHappening(affectedUnitList[someUnit], newState); //Then if dead, remove all happening events involving this unit if ("Dead" == newState) { HappeningList.FlushOneUnit(affectedUnitList[someUnit]); Coordinator.debugLogger.Writeline("Timer", " stateChangeEvent for " + affectedUnitList[someUnit], "test"); } SeekSpeciesHappening(thisItem, newState); } break; case name_Space + "AttackSuccessfulNotice": AttackSuccessfulNotice asn = (AttackSuccessfulNotice)thisItem; for (int asi = 0; asi < AttackSuccessfulList.Happenings.Count; asi++) { AttackSuccessfulCompletionType tryThisEvent = AttackSuccessfulList.Happenings[asi]; if (tryThisEvent.Matches(asn)) { if (tryThisEvent.DoThisList.Count > 0) { AttackSuccessfulCompletionType.EnqueueEvents(asn.UnitID, asn.Target, tryThisEvent.DoThisList); } break; } } break; case name_Space + "AttackObjectRequestType": Coordinator.debugLogger.Writeline("Timer", "Attack request for " + thisItem.UnitID + "attack Request discovered at t=" + timer.ToString(), "test"); AttackObjectRequestType recastAOR = (AttackObjectRequestType)thisItem; if (ApprovalsList.AttackApproved(recastAOR)) { string attacker = recastAOR.UnitID; string target = recastAOR.TargetObjectID; AttackObjectEvent attack = new AttackObjectEvent(attacker, target, recastAOR.CapabilityName); attack.AddOtherUnit(target); TimerQueueClass.Add(1 + (int)(TimerTicker.Timer / 1000 /*Coordinator.UpdateIncrement*/), attack); } else { TimerQueueClass.Add(1 + (int)(TimerTicker.Timer / 1000), new SystemMessage(1, recastAOR.UnitID, "Attack against " + recastAOR.TargetObjectID + " failed.")); } break; case name_Space + "WeaponLaunchRequestType": WeaponLaunchRequestType recastWL = (WeaponLaunchRequestType)thisItem; string unitID = recastWL.UnitID; string weaponID = recastWL.WeaponID; string targetID = recastWL.TargetObjectID; Coordinator.debugLogger.Writeline("Timer", "Weapon Launch request for " + unitID + " using " + weaponID + " Attack Request discovered at t=" + timer.ToString(), "test"); string platformOwner = UnitFacts.Data[unitID].Owner; string weaponOwner = UnitFacts.Data[weaponID].Owner; launchedByOwner = SpeciesType.GetSpecies(UnitFacts.Data[weaponID].Species).LaunchedByOwner; // ) if ( SubplatformRecords.IsLaunchableWeapon(unitID, weaponID) && ( (platformOwner == recastWL.DecisionMaker) || (weaponOwner == recastWL.DecisionMaker) && launchedByOwner ) ) { // validate attack DecisionMakerType targetDM = DecisionMakerType.GetDM(UnitFacts.GetDM(targetID)); if ( (launchedByOwner && UnitFacts.HostileTo(DecisionMakerType.GetDM(platformOwner).Team, targetDM.Team)) || (UnitFacts.HostileTo(DecisionMakerType.GetDM(weaponOwner).Team, targetDM.Team)) //Removed !launchedByOwner from second statement ) { //NB. THe code that builds and sends the event was missing from here. It was last seen in rev 232. // its removeal was probably an accident? // build event to send down WeaponLaunch_EventType wEvent = new WeaponLaunch_EventType(unitID, targetID, weaponID); TimerQueueClass.Add(1 + (int)(timer / 1000), wEvent); // replace by new platform handling } } else { //need to throw an event back to ViewPro to re-allocate weapon String reason = ""; if (!UnitFacts.Data.ContainsKey(unitID)) { reason = "Platform object is unknown by the system."; } else if (UnitFacts.Data[unitID].Owner != recastWL.DecisionMaker) { reason = "Requesting DM does not own the Platform object."; } WeaponLaunchFailure_EventType failEvent = new WeaponLaunchFailure_EventType(weaponID, unitID, reason); failEvent.Time = (int)(timer / 1000 /*Coordinator.UpdateIncrement*/); TimerQueueClass.Add(1 + (int)(timer / 1000 /*Coordinator.UpdateIncrement*/), failEvent); } break; case name_Space + "SubplatformLaunchRequestType": SubplatformLaunchRequestType recastSL = (SubplatformLaunchRequestType)thisItem; string childID = recastSL.UnitID; string requestor = recastSL.Requestor; string parentID = recastSL.ParentUnit; LocationType destination = recastSL.Destination; Coordinator.debugLogger.Writeline("Timer", "Subplatform Launch request for " + childID + " from " + parentID + " discovered at t=" + timer.ToString(), "test"); launchedByOwner = SpeciesType.GetSpecies(UnitFacts.Data[childID].Species).LaunchedByOwner; if ( (UnitFacts.Data[parentID].Owner == requestor) || (UnitFacts.Data[childID].Owner == requestor) && launchedByOwner ) { // build event to send down SubplatformLaunchType slEvent = new SubplatformLaunchType(childID, parentID, destination); TimerQueueClass.Add(1 + (int)(timer / 1000), slEvent); } /**/ break; case name_Space + "SubplatformDockRequestType": SubplatformDockRequestType recastSD = (SubplatformDockRequestType)thisItem; string orphanID = recastSD.UnitID; string dockRequestor = recastSD.Requestor; string adopterID = recastSD.ParentUnit; Coordinator.debugLogger.Writeline("Timer", "Subplatform Dock request for " + orphanID + " from " + adopterID + " discovered at t=" + timer.ToString(), "test"); if ("" != adopterID) { if (UnitFacts.Data.ContainsKey(orphanID) && UnitFacts.Data.ContainsKey(adopterID) && ((UnitFacts.Data[orphanID].Owner == dockRequestor) // && (UnitFacts.Data[adopterID].Owner == dockRequestor) ) && SpeciesType.GetSpecies(UnitFacts.GetSpecies(adopterID)).CanHaveSubplatform(UnitFacts.GetSpecies(orphanID)) ) { /* for dock to any object*/ SubplatformDockType sdEvent = new SubplatformDockType(orphanID, adopterID); TimerQueueClass.Add(1 + (int)(timer / 1000), sdEvent); } } // if the parent is "" just ignore the request
/// <summary> /// This method loops while the program runs, and every 100 /// milliseconds (1/10 of a sec) calls the server's "GetEvents" /// method. This retrieves events that the EvComm has /// subscribed to. At which point, the list is parsed, and the /// events are converted back to ScenCon styled events. /// </summary> public void WaitForEvents() { //Receives an incoming message from the simcore string objID = null; string parentID = null; string targetObjID = null; string dm = null; string capability = null; List<String> capabilities; string newState = null; LocationType vect = null; string weaponID = null; double throttle; string eventType = null; string roomName=null; string channelName = null; string requestingDM=null; string textString=null; List<string> membershipList; List<SimulationEvent> incomingEvents = new List<SimulationEvent>(); bool allowAssetTransferRequests = true; try { while (true) { incomingEvents = server.GetEvents(); if (incomingEvents.Count == 0) {//do nothing } else { foreach (SimulationEvent e in incomingEvents) { eventType = e.eventType; switch (eventType) { case "SimCoreReady": Coordinator.debugLogger.Writeline("EventCommunicator", "Ready To Start Scenario", "test"); Coordinator.ReadyToStart(); break; case "SelfDefenseAttackStarted": objID = ((StringValue)e["AttackerObjectID"]).value; targetObjID = ((StringValue)e["TargetObjectID"]).value; SelfDefenseAttackNotice selfDefenseNotice = new SelfDefenseAttackNotice(objID, targetObjID); selfDefenseNotice.Time = ((IntegerValue)e["Time"]).value; IncomingList.Add(selfDefenseNotice); Coordinator.debugLogger.Writeline("EventCommunicator", "Self defense attack started", "test"); break; case "SubplatformDockRequest": objID = ((StringValue)e["ObjectID"]).value; parentID = ((StringValue)e["ParentObjectID"]).value; dm = ((StringValue)e["UserID"]).value; SubplatformDockRequestType dockRequest = new SubplatformDockRequestType(dm, objID, parentID); dockRequest.Time = ((IntegerValue)e["Time"]).value; IncomingList.Add(dockRequest); Coordinator.debugLogger.Writeline("EventCommunicator", "Subplatform dock request received", "test"); break; case "SubplatformLaunchRequest": objID = ((StringValue)e["ObjectID"]).value; parentID = ((StringValue)e["ParentObjectID"]).value; dm = ((StringValue)e["UserID"]).value; vect = new LocationType(((LocationValue)e["LaunchDestinationLocation"]).X, ((LocationValue)e["LaunchDestinationLocation"]).Y, ((LocationValue)e["LaunchDestinationLocation"]).Z); SubplatformLaunchRequestType subPlaunchRequest = new SubplatformLaunchRequestType(dm, objID, parentID, vect); subPlaunchRequest.Time = ((IntegerValue)e["Time"]).value; IncomingList.Add(subPlaunchRequest); Coordinator.debugLogger.Writeline("EventCommunicator", "Subplatform launch request received", "test"); break; case "WeaponLaunchRequest": objID = ((StringValue)e["ParentObjectID"]).value; //the launching object weaponID = ((StringValue)e["ObjectID"]).value;// the weapon id being launched //parentID = ((StringValue)e["ParentObjectID"]).value; targetObjID = ((StringValue)e["TargetObjectID"]).value; //The target object dm = ((StringValue)e["UserID"]).value; //the dm launching the weapon WeaponLaunchRequestType launchRequest = new WeaponLaunchRequestType(objID, dm, targetObjID, weaponID); launchRequest.Time = ((IntegerValue)e["Time"]).value; IncomingList.Add(launchRequest); Coordinator.debugLogger.Writeline("EventCommunicator", "Weapon launch request received", "test"); break; case "MoveDone": objID = ((StringValue)e["ObjectID"]).value; //see line 222 of MotionSim.cs for reference MoveComplete_Event moveDone = new MoveComplete_Event(objID.ToString()); moveDone.Time = ((IntegerValue)e["Time"]).value; IncomingList.Add(moveDone); break; case "MoveObjectRequest": dm = String.Empty; dm = ((StringValue)e["UserID"]).value; objID = String.Empty; objID = ((StringValue)e["ObjectID"]).value; vect = new LocationType(); //X is location in UTM Easting ((LocationType)vect).X = ((LocationValue)e["DestinationLocation"]).X; //Y is location in UTM Northing ((LocationType)vect).Y = ((LocationValue)e["DestinationLocation"]).Y; //Z is altitude in meters ((LocationType)vect).Z = ((LocationValue)e["DestinationLocation"]).Z; throttle = new double(); throttle = ((DoubleValue)e["Throttle"]).value; MoveObjectRequestType moveObjectRequest = new MoveObjectRequestType(objID, dm, vect, throttle); moveObjectRequest.Time = ((IntegerValue)e["Time"]).value; IncomingList.Add(moveObjectRequest); break; case "AttackObjectRequest": dm = String.Empty; dm = ((StringValue)e["UserID"]).value; objID = String.Empty; objID = ((StringValue)e["ObjectID"]).value; targetObjID = String.Empty; targetObjID = ((StringValue)e["TargetObjectID"]).value; capability = ((StringValue)e["CapabilityName"]).value; AttackObjectRequestType attackObjectRequest = new AttackObjectRequestType(objID, dm, targetObjID, capability); attackObjectRequest.Time = ((IntegerValue)e["Time"]).value; IncomingList.Add(attackObjectRequest); break; case "TransferObjectRequest": if (allowAssetTransferRequests) { string recipientDM = String.Empty; recipientDM = ((StringValue)e["RecipientID"]).value; objID = String.Empty; objID = ((StringValue)e["ObjectID"]).value; string requesterID = String.Empty; requesterID = ((StringValue)e["UserID"]).value; string currentState = ((StringValue)e["State"]).value; TransferObjectRequest transferObjectRequest = new TransferObjectRequest(requesterID, recipientDM, objID, currentState); transferObjectRequest.Time = ((IntegerValue)e["Time"]).value; IncomingList.Add(transferObjectRequest); } else { //client side asset transfers were not allowed Coordinator.debugLogger.Writeline("EventCommunicator", "TransferObjectRequest denied due to scenario constraints", "test"); } break; case "StateChange": objID = ((StringValue)e["ObjectID"]).value; newState = ((StringValue)e["NewState"]).value; StateChangeNotice changeNotice = new StateChangeNotice(objID, newState); changeNotice.Time = ((IntegerValue)e["Time"]).value; IncomingList.Add(changeNotice); break; /* case "JoinChatRoom" : string roomToJoin=((StringValue)e["RoomName"]).value; string targetPlayerID=((StringValue)e["TargetPlayerID"]).value; if(!UnitFacts.IsDM(targetPlayerID)) throw new ApplicationException("'" + targetPlayerID + "' is not a valid decision maker name. Cannot add to chatroom '" + roomToJoin + "'"); List<string> members = ChatRooms.GetChatMembers(roomToJoin); Boolean canJoin = true; DecisionMakerType candidateDM=DecisionMakerType.GetDM(targetPlayerID); for(int i=0;i<members.Count;i++) if (!candidateDM.CanChatWith(members[i])) { canJoin = false; break; } if (canJoin) { ChatRooms.AddChatMember(roomToJoin, targetPlayerID); //notify chat server SimulationEvent f = SimulationEventFactory.BuildEvent(ref simModelInfo, "AddToChatRoom"); f["RoomName"] = DataValueFactory.BuildString("roomToJoin"); f["TargetPlayerID"] = DataValueFactory.BuildString("targetPlayerID"); server.PutEvent(f); } break ;*/ case "RequestCloseChatRoom": roomName = ((StringValue)e["RoomName"]).value; Boolean closedChatOK=ChatRooms.DropChatRoom(roomName); if (closedChatOK) { SimulationEvent reportClosedChat = SimulationEventFactory.BuildEvent(ref simModelInfo, "CloseChatRoom"); reportClosedChat["RoomName"] = DataValueFactory.BuildString(roomName); server.PutEvent(reportClosedChat); } break; case "RequestCloseVoiceChannel": channelName = ((StringValue)e["ChannelName"]).value; Boolean closedVoiceOK=VoiceChannels.DropVoiceChannel(channelName); if (closedVoiceOK) { SimulationEvent reportClosedVoice = SimulationEventFactory.BuildEvent(ref simModelInfo, "CloseVoiceChannel"); reportClosedVoice["ChannelName"] = DataValueFactory.BuildString(channelName); server.PutEvent(reportClosedVoice); } break; case "RequestChatRoomCreate": { // HAndled at once -- so no delay is seen even if server is not active roomName = ((StringValue)e["RoomName"]).value; requestingDM = ((StringValue)e["SenderDM_ID"]).value; membershipList = new List<string>(); List<string> allMembers = ((StringListValue)e["MembershipList"]).strings; string chatFailureReason = ""; OpenChatRoomType openEvent = null; // needed bacause it appears to compiler that this is not defined on every path if (!UnitFacts.IsDM(requestingDM)) chatFailureReason = "Illegal DM '" + requestingDM + "' in create chat room request"; else { for (int i = 0; i < allMembers.Count; i++) membershipList.Add(allMembers[i]); for (int i = 0; i < membershipList.Count; i++) { DecisionMakerType DMi = DecisionMakerType.GetDM(membershipList[i]); for (int m = 1 + i; m < membershipList.Count; m++) { if (!DMi.CanChatWith(membershipList[m])) { chatFailureReason = "Decison Makers '" + DMi.Identifier + "' cannot be in a chat room with '" + membershipList[m] + "'"; break; } if ("" != chatFailureReason) break; } } if ("" == chatFailureReason) { // Now validate and queue response openEvent = new OpenChatRoomType(1 + (int)(TimerTicker.Timer / 1000/*Coordinator.UpdateIncrement*/), requestingDM, roomName, membershipList); chatFailureReason = ChatRooms.AddRoom(openEvent); } if ("" != chatFailureReason) { EventCommunicator.SendEvent(new SystemMessage( 1 + (int)(TimerTicker.Timer / 1000), requestingDM, chatFailureReason)); } else { EventCommunicator.SendEvent(openEvent); } } } break; case "RequestWhiteboardRoomCreate": { // HAndled at once -- so no delay is seen even if server is not active roomName = ((StringValue)e["RoomName"]).value; requestingDM = ((StringValue)e["SenderDM_ID"]).value; membershipList = new List<string>(); List<string> allMembers = ((StringListValue)e["MembershipList"]).strings; string whiteboardFailureReason = ""; OpenWhiteboardRoomType openEvent = null; // needed bacause it appears to compiler that this is not defined on every path if (!UnitFacts.IsDM(requestingDM)) whiteboardFailureReason = "Illegal DM '" + requestingDM + "' in create whiteboard room request"; else { for (int i = 0; i < allMembers.Count; i++) membershipList.Add(allMembers[i]); for (int i = 0; i < membershipList.Count; i++) { DecisionMakerType DMi = DecisionMakerType.GetDM(membershipList[i]); for (int m = 1 + i; m < membershipList.Count; m++) { if (!DMi.CanWhiteboardWith(membershipList[m])) { whiteboardFailureReason = "Decison Makers '" + DMi.Identifier + "' cannot be in a whiteboard room with '" + membershipList[m] + "'"; break; } if ("" != whiteboardFailureReason) break; } } if ("" == whiteboardFailureReason) { // Now validate and queue response openEvent = new OpenWhiteboardRoomType(1 + (int)(TimerTicker.Timer / 1000/*Coordinator.UpdateIncrement*/), requestingDM, roomName, membershipList); whiteboardFailureReason = WhiteboardRooms.AddRoom(openEvent); } if ("" != whiteboardFailureReason) { EventCommunicator.SendEvent(new SystemMessage( 1 + (int)(TimerTicker.Timer / 1000), requestingDM, whiteboardFailureReason)); } else { EventCommunicator.SendEvent(openEvent); } } } break; case "AttackSucceeded": objID = ((StringValue)e["ObjectID"]).value; targetObjID = ((StringValue)e["TargetID"]).value; capabilities = ((StringListValue)e["Capabilities"]).strings; newState = ((StringValue)e["NewState"]).value; IncomingList.Add(new AttackSuccessfulNotice(objID, targetObjID, capabilities, newState)); break; case "ChangeTagRequest": objID = ((StringValue)e["UnitID"]).value; requestingDM = ((StringValue)e["DecisionMakerID"]).value; textString = ((StringValue)e["Tag"]).value; // This event is handled in place for more rapid turnaround membershipList = new List<string>(); string thisTeam = UnitFacts.DMTeams[requestingDM]; for (int mbrs = 0; mbrs < UnitFacts.TeamDMs[thisTeam].Count; mbrs++) { membershipList.Add(UnitFacts.TeamDMs[thisTeam][mbrs]); } EventCommunicator.SendEvent(new UpdateTagType(objID, textString, membershipList)); break; case "ClientSideAssetTransferAllowed": allowAssetTransferRequests = ((BooleanValue)e["EnableAssetTransfer"]).value; break; case "DynamicCreate": objID = ((StringValue)e["ObjectID"]).value; dm = ((StringValue)e["Owner"]).value; String kind = ((StringValue)e["Kind"]).value; Aptima.Asim.DDD.ScenarioParser.pCreateType c; c = new Aptima.Asim.DDD.ScenarioParser.pCreateType(objID, kind, dm); Create_EventType createEvent = new Create_EventType(c); Genealogy.Add(createEvent.UnitID, createEvent.UnitBase); createEvent.Genus = Genealogy.GetGenus(createEvent.UnitID); UnitFacts.AddUnit(createEvent.UnitID, createEvent.Owner, createEvent.UnitBase); createEvent.Parameters = new ObjectDictionary(); SpeciesType speciesInfo = (SpeciesType)NameLists.speciesNames[createEvent.UnitBase]; foreach (KeyValuePair<string, StateBody> kvp in StatesForUnits.StateTable[createEvent.UnitBase]) { string stateName = kvp.Key; ExtendedStateBody extended = new ExtendedStateBody(kvp.Value); //end species dependent atts createEvent.Parameters.Add(stateName, (object)extended); } NameLists.unitNames.New(createEvent.UnitID, null); //TimerQueueClass.SecondarySendBeforeStartup(createEvent); TimerQueueClass.Add(1, createEvent); UnitFacts.CurrentUnitStates.Add(createEvent.UnitID, ""); break; case "DynamicReveal": objID = ((StringValue)e["ObjectID"]).value; LocationValue loc = (LocationValue)e["InitialLocation"]; String initialState = ((StringValue)e["InitialState"]).value; Aptima.Asim.DDD.ScenarioParser.pLocationType pLoc = new Aptima.Asim.DDD.ScenarioParser.pLocationType(); pLoc.X = loc.X; pLoc.Y = loc.Y; pLoc.Z = loc.Z; int revealTime = ((IntegerValue)e["RevealTime"]).value; Aptima.Asim.DDD.ScenarioParser.pRevealType r; r = new Aptima.Asim.DDD.ScenarioParser.pRevealType(objID, null, revealTime, pLoc,initialState, new Dictionary<string, object>()); Reveal_EventType revealEvent = new Reveal_EventType(r); revealEvent.Genus = Genealogy.GetGenus(revealEvent.UnitID); TimerQueueClass.Add(r.Time, revealEvent); //if (r.Time > 1) //{ // TimerQueueClass.Add(r.Time, revealEvent); //} //else //{ // TimerQueueClass.SecondarySendBeforeStartup(revealEvent); //} //Coordinator.debugLogger.Writeline("ScenarioToQueues", "revealEvent for " + revealEvent.UnitID + " at time" + r.Time.ToString(), "test"); ScenarioToQueues.RevealDocked(r.UnitID, r.Time); break; default: throw new ApplicationException("Received unknown event in EventCommunicator:" + eventType); } } incomingEvents.Clear(); } Thread.Sleep(100); } } /* catch (ThreadAbortException e) { //throw new ApplicationException("In WaitForEvents", e); } */ finally { }//removes a warning caused bu the null catch. If catch is needed, this won't be }