public static void SendTimeTick(object timeObj) { /* 2. Send the tick */ // timer += updateIncrement; int time = (int)timeObj; int timer = time / 1000; int secs = timer % 60; int mins = (timer / 60) % 60; int hours = timer / 3600; const string name_Space = TimerTicker.name_Space; DateTime currTime = new DateTime(1, 1, 1, hours, mins, secs); string simulationTime = String.Format("{0:HH:mm:ss}", currTime); EventCommunicator.SendEvent(new TickEventType(time, simulationTime)); // current = DateTime.Now; // TimeSpan ts = current - last; // Console.WriteLine("timeslice: {0:+hh.mm.ss.ffffzz}", ts.ToString()); //last = current; /* 3. Pull the events for this tick off the queue and handle them */ List<ScenarioEventType> events = TimerQueueClass.RetrieveEvents(timer); if (events != null) { for (int v = 0; v < events.Count; v++) { Coordinator.debugLogger.Writeline("Timer", "Time: " + time.ToString() + " ID: " + events[v].UnitID.ToString() + " Event: " + events[v].GetType().ToString(), "test"); // track current state if (UnitFacts.AnyDead(events[v].AllUnits)) {// skip an event that refers to a dead unit continue; } string thisUnit = events[v].UnitID; string thisTarget = ""; // Only a few outgoing events require two substitutions switch (events[v].GetType().ToString()) { case name_Space + "AttackObjectEvent": thisTarget = ((AttackObjectEvent)events[v]).TargetObjectID; break; case name_Space + "LaunchEventType": thisTarget = ((LaunchEventType)events[v]).Child; break; case name_Space + "WeaponLaunchEventType": thisTarget = ((WeaponLaunchEventType)events[v]).Child; break; case name_Space + "SubplatformLaunchType": thisTarget = ((SubplatformLaunchType)events[v]).ParentUnit; break; case name_Space + "SubplatformDockType": thisTarget = ((SubplatformDockType)events[v]).ParentUnit; break; default: break; } if (!events[v].EngramValid(thisUnit, thisTarget)) { Coordinator.debugLogger.Writeline("Timer", "Time: Command" + events[v].GetType().ToString() + " ignored due to value of " + events[v].Range.Name, "test"); } else { switch (events[v].GetType().ToString()) { /* SInce the active region update requires both activity and visibility, * must find current values of non-updated field just before sending event */ case name_Space + "ActiveRegionActivityUpdateType": ActiveRegionStateType currentStateForVisibility = (ActiveRegionStateType)(NameLists.activeRegionNames.ContainedData[((ActiveRegionActivityUpdateType)(events[v])).UnitID]); currentStateForVisibility.IsActive = ((ActiveRegionActivityUpdateType)(events[v])).IsActive; NameLists.activeRegionNames.ContainedData[((ActiveRegionActivityUpdateType)(events[v])).UnitID] = currentStateForVisibility; ActiveRegionUpdateType activityUpdate = new ActiveRegionUpdateType(((ActiveRegionActivityUpdateType)(events[v])).UnitID, ((ActiveRegionActivityUpdateType)(events[v])).Time, currentStateForVisibility); EventCommunicator.SendEvent(activityUpdate); break; case name_Space + "ActiveRegionVisibilityUpdateType": ActiveRegionStateType currentStateForActivity = (ActiveRegionStateType)(NameLists.activeRegionNames.ContainedData[((ActiveRegionVisibilityUpdateType)(events[v])).UnitID]); currentStateForActivity.IsVisible = ((ActiveRegionVisibilityUpdateType)(events[v])).IsVisible; NameLists.activeRegionNames.ContainedData[((ActiveRegionVisibilityUpdateType)(events[v])).UnitID] = currentStateForActivity; ActiveRegionUpdateType visibilityUpdate = new ActiveRegionUpdateType(((ActiveRegionVisibilityUpdateType)(events[v])).UnitID, ((ActiveRegionVisibilityUpdateType)(events[v])).Time, currentStateForActivity); EventCommunicator.SendEvent(visibilityUpdate); break; case name_Space + "CloseChatRoomType": if (ChatRooms.DropChatRoom(((CloseChatRoomType)(events[v])).Room)) EventCommunicator.SendEvent(events[v]); break; case name_Space + "CloseVoiceChannelType": if (VoiceChannels.DropVoiceChannel(((CloseVoiceChannelType)(events[v])).Channel)) EventCommunicator.SendEvent(events[v]); break; case name_Space + "Reveal_EventType": UnitFacts.CurrentUnitStates[events[v].UnitID] = ((Reveal_EventType)events[v]).InitialState; EventCommunicator.SendEvent(events[v]); break; case name_Space + "StateChangeEvent": string currentState = UnitFacts.CurrentUnitStates[events[v].UnitID]; if (("Dead" != currentState) && (!((StateChangeEvent)events[v]).IsException(currentState))) { if ((((StateChangeEvent)events[v]).HasPrecursors()) && (((StateChangeEvent)events[v]).IsPrecursor(currentState))) { EventCommunicator.SendEvent(events[v]); } else if (!((StateChangeEvent)events[v]).HasPrecursors()) { EventCommunicator.SendEvent(events[v]); } } break; case name_Space + "TransferEvent": if (UnitFacts.ChangeDM(events[v].UnitID, /* ((TransferEvent)events[v]).From, */((TransferEvent)events[v]).To)) { EventCommunicator.SendEvent(events[v]); }// and if not? Throw exception?? else { Coordinator.debugLogger.LogError("Timed Queue Manager", "Transfer of Unit " + events[v].UnitID + " from " + ((TransferEvent)events[v]).From + " failed."); } break; case name_Space + "SubplatformLaunchType": SubplatformLaunchType alias = ((SubplatformLaunchType)events[v]); List<string> nowDocked = SubplatformRecords.GetDocked(alias.ParentUnit); if (nowDocked.Contains(alias.UnitID)) { SubplatformRecords.UnDock(alias.ParentUnit, alias.UnitID); EventCommunicator.SendEvent(events[v]); } break; case name_Space + "SubplatformDockType": SubplatformDockType dock = ((SubplatformDockType)events[v]); string adopterID = dock.ParentUnit; if (SubplatformRecords.CountDockedOfSpecies(adopterID, UnitFacts.GetSpecies(dock.UnitID)) <= SpeciesType.GetSpecies(UnitFacts.GetSpecies(adopterID)).GetSubplatformCapacity(UnitFacts.GetSpecies(dock.UnitID))) { if (SubplatformRecords.RecordDocking(thisTarget, dock.UnitID) == true) { EventCommunicator.SendEvent(events[v]); } else { string someError = "This failed because the subplatform wasn't able to be docked to this platform"; } } break; //SubplatformLaunchType is a response to a launch request, //LaunchEventType was intended to be from the scenario. This needs to be rethought. case name_Space + "LaunchEventType": // Note -- it isn't an error if the thing isn't docked any more LaunchEventType launch = (LaunchEventType)events[v]; // This comes from scenario so we only check if there is something to launch if ("" != launch.Child) { List<string> dockedNow = SubplatformRecords.GetDocked(launch.UnitID); if (dockedNow.Contains(launch.Child)) { SubplatformRecords.UnDock(launch.UnitID, launch.Child); ///??? Subplatforms.GetDocked(launch.UnitID); // not in sim model launch.Genus = Genealogy.GetGenus(launch.Child); SubplatformRecords.UnDock(launch.UnitID, launch.Child); EventCommunicator.SendEvent(launch); } } break; case name_Space + "WeaponLaunchEventType": // Note -- it isn't an error if the thing isn't docked any more WeaponLaunchEventType launchWeapon = (WeaponLaunchEventType)events[v]; // This comes from scenario so we only check if there is something to launch if ("" != launchWeapon.Child) { List<string> dockedNow = SubplatformRecords.GetDocked(launchWeapon.UnitID); if (dockedNow.Contains(launchWeapon.Child)) { SubplatformRecords.UnDock(launchWeapon.UnitID, launchWeapon.Child); SubplatformRecords.UnDock(launchWeapon.UnitID, launchWeapon.Child); EventCommunicator.SendEvent(launchWeapon); } } break; case name_Space + "EngramSettingType": //This is the inital value so it was set in the table at parset time EventCommunicator.SendEvent(events[v]); break; case name_Space + "ChangeEngramType": ChangeEngramType newValue = ((ChangeEngramType)events[v]); Engrams.Set(newValue.Name, newValue.UnitID, newValue.EngramValue); EventCommunicator.SendEvent(new EngramSettingType(newValue.Name, newValue.UnitID, newValue.EngramValue, Engrams.GetType(newValue.Name))); break; case name_Space + "RemoveEngramEvent": Engrams.Remove(((RemoveEngramEvent)events[v]).Name); break; case name_Space + "OpenChatRoomType": //Requests from below are handled by EventCommunicator //This processing is for commands in script -- ?? string chatFailureMessage = ""; OpenChatRoomType ocr = ((OpenChatRoomType)events[v]); if (("EXP" != ocr.Owner) && !UnitFacts.IsDM(ocr.Owner)) chatFailureMessage = "The name '" + ocr.Owner + "' is not a valid decision maker."; else { for (int i = 0; i < ocr.Members.Count; i++) { DecisionMakerType DMi = DecisionMakerType.GetDM(ocr.Members[i]); for (int mbr = 1 + i; mbr < ocr.Members.Count; mbr++) { if (!DMi.CanChatWith(ocr.Members[mbr])) { chatFailureMessage = "Decison Makers '" + DMi.Identifier + "' cannot be in a chat room with '" + ocr.Members[mbr] + "'"; break; } if ("" != chatFailureMessage) break; } } } if ("" == chatFailureMessage) { chatFailureMessage = ChatRooms.AddRoom(ocr); EventCommunicator.SendEvent(ocr); } if ("" != chatFailureMessage) { // DON'T throw new ApplicationException("Could not create chatroom '"+ocr.Range+"': "+chatFailureMessage); // send a system message instead } break; case name_Space + "SendChatMessageType": // Script induced. Only need to check if there is such a room if (ChatRooms.IsRoom(((SendChatMessageType)(events[v])).RoomName)) EventCommunicator.SendEvent(events[v]); break; case name_Space + "OpenWhiteboardRoomType": //Requests from below are handled by EventCommunicator //This processing is for commands in script -- ?? string whiteboardFailureMessage = ""; OpenWhiteboardRoomType owr = ((OpenWhiteboardRoomType)events[v]); if (("EXP" != owr.Owner) && !UnitFacts.IsDM(owr.Owner)) whiteboardFailureMessage = "The name '" + owr.Owner + "' is not a valid decision maker."; else { for (int i = 0; i < owr.Members.Count; i++) { DecisionMakerType DMi = DecisionMakerType.GetDM(owr.Members[i]); for (int mbr = 1 + i; mbr < owr.Members.Count; mbr++) { if (!DMi.CanWhiteboardWith(owr.Members[mbr])) { whiteboardFailureMessage = "Decison Makers '" + DMi.Identifier + "' cannot be in a whiteboard room with '" + owr.Members[mbr] + "'"; break; } if ("" != whiteboardFailureMessage) break; } } } if ("" == whiteboardFailureMessage) whiteboardFailureMessage = WhiteboardRooms.AddRoom(owr); if ("" != whiteboardFailureMessage) { // DON'T throw new ApplicationException("Could not create whiteboardroom '"+owr.Range+"': "+whiteboardFailureMessage); // send a system message instead } break; case name_Space + "OpenVoiceChannelType": //Requests from below would be/are handled by EventCommunicator //This processing is for commands in script -- ?? string voiceFailureMessage = ""; OpenVoiceChannelType ovct = ((OpenVoiceChannelType)events[v]); //if (("EXP" != ovct.Owner) && !UnitFacts.IsDM(ovct.Owner)) //{ // voiceFailureMessage = "Open Voice Channel: The name '" + ovct.Owner + "' is not a valid decision maker."; // ErrorLog.Write(voiceFailureMessage); //} //else //{ voiceFailureMessage = VoiceChannels.AddChannel(ovct); if ("" != voiceFailureMessage) ErrorLog.Write(voiceFailureMessage); else { //ovct.InitialMembers = DecisionMakerType.GetVoiceChannelMembers(ovct.Channel); //TODO: AD: Is this even NECESSARY? EventCommunicator.SendEvent(ovct); } //} break; case name_Space + "FlushEvents": //first drop all timer events involving this unit TimerQueueClass.FlushOneUnit(((FlushEvents)events[v]).UnitID); // Then all events on happenin queue about this unit for (int h = 0; h < HappeningList.Happenings.Count; h++) {// Find first happening event that keys off this state change HappeningCompletionType incident = HappeningList.Happenings[h]; if (incident.UnitID == ((FlushEvents)events[v]).UnitID) { HappeningList.Happenings.RemoveAt(h); } else // examine all the DoThisLists { List<int> removals = new List<int>(); for (int d = 0; d < incident.DoThisList.Count; d++) { if (incident.DoThisList[d].Involves(((FlushEvents)events[v]).UnitID)) { removals.Add(d); } //then remove from back to front to preserve indices for (int r = removals.Count - 1; r >= 0; r--) { incident.DoThisList.RemoveAt(r); } } } } break; case name_Space + "ForkReplayEventType": EventCommunicator.SendEvent(events[v]); break; default: EventCommunicator.SendEvent(events[v]); break; } } } TimerQueueClass.DropNode(time); } }
/// <summary> /// This method takes in an ActiveREgionUpdateType (ScenCon defined object), and retrieves /// the data from the object, packages up the data into a SimulationEvent (SimCore defined /// object), and then sends the event to the network server. This method was pulled out of /// the main block of code to simplify sending the event and code readability. /// </summary> /// <param name="incoming">The Move_EventType object whose data is packaged /// into an outgoing SimulationEvent.</param> private static void SendActiveRegionUpdateEvent(ActiveRegionUpdateType incoming) { SimulationEvent e = SimulationEventFactory.BuildEvent(ref simModelInfo, "ActiveRegionUpdate"); try { e["Time"] = DataValueFactory.BuildInteger(incoming.Time); e["ObjectID"] = DataValueFactory.BuildString(incoming.UnitID); e["IsVisible"] = DataValueFactory.BuildBoolean(incoming.IsVisible); e["IsActive"] = DataValueFactory.BuildBoolean(incoming.IsActive); } catch (SystemException f) { throw new ApplicationException("Missing Required Data for Active Region Update:", f); } server.PutEvent(e); }