示例#1
0
文件: Timer.cs 项目: xiangnanyue/DDD
        /// <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
示例#2
0
        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);
            }
        }