public void AddEvent(ReactorEvent newEvent) { Monitor.Enter(_events); _events.Enqueue(newEvent); Monitor.Pulse(_events); Monitor.Exit(_events); }
/// <summary> /// Return the next event or null if there are no events and the /// timeout milliseconds have passed. /// </summary> /// <param name="timeout"></param> /// <returns></returns> private ReactorEvent GetNextEvent(int timeout) { if (timeout > 20) { timeout = 20; } ReactorEvent nextEvent = null; // If there's an event queued now, return the next immediately. Monitor.Enter(_events); if (_events.Count > 0) { nextEvent = _events.Dequeue(); } Monitor.Exit(_events); if (nextEvent != null) { return(nextEvent); } // If no timeout because lot's of pending timers, return immediately. if (timeout == 0) { return(null); } // Wait for another event to be queued or for the timeout // to expire. Monitor.Enter(_events); if (timeout > 0) { Monitor.Wait(_events, timeout); } else { Monitor.Wait(_events); } if (_events.Count > 0) { nextEvent = _events.Dequeue(); } Monitor.Exit(_events); return(nextEvent); }
/// <summary> /// Start and run the simulation for this system. /// </summary> public void GameThreadRun() { Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture; CurrentTime = Utilities.GetTime(); AddTimer(new UpdateMonitoredObjs(this)); AddTimer(new SpawnBackgroundNPCs(this)); bool running = true; while (running) { // Calculate the delta time. double delta = Utilities.GetTime() - CurrentTime; CurrentTime += delta; // Call the reactor to return the next event the process // and run any timer functions. ReactorEvent next_event = Run(CurrentTime, delta); if (next_event is DPGameRunnerRxMsgEvent) { var revent = next_event as DPGameRunnerRxMsgEvent; // Process a message from this player. If the message isn't for this runner because // the runner ownership changes, requeue in the right place. if (revent.player.Runner != this) { Log.AddLog(LogType.FL_MSG, "Warning: requeued rx msg onto changed runner"); revent.player.Runner.AddEvent(revent); } else { revent.player.RxMsgFromClient(revent.msg); } } else if (next_event is DPGameRunnerPlayerUpdateEvent) { var revent = next_event as DPGameRunnerPlayerUpdateEvent; // If the player is assigned to this runner, make sure we've got it in our // owned player list Player.Player player = revent.player; if (revent.runner == this) { if (!Players.ContainsKey(player.FLPlayerID)) { Log.AddLog(LogType.GENERAL, "Player control gained runner={0} flplayerid={1}", system.Nickname, player.FLPlayerID); Players.Add(player.FLPlayerID, player); if (player.Ship.Objid != 0) { AffObjects[player.Ship.Objid] = player.Ship; } Objects[player.Ship.Objid] = player.Ship; player.Runner = this; player.Ship.Runner = this; AddTimer(player.Ship); } } // If the player is not assigned to this runner, make sure it's not in our // owned player list. else { if (Players.ContainsKey(player.FLPlayerID)) { Log.AddLog(LogType.GENERAL, "Player control lost runner={0} flplayerid={1}", system.Nickname, player.FLPlayerID); if (player.Ship.Objid != 0) { AffObjects.Remove(player.Ship.Objid); } Objects.Remove(player.Ship.Objid); DelTimer(player.Ship); Players.Remove(player.FLPlayerID); } } PlayerListItem update; update = !Playerlist.ContainsKey(revent.flplayerid) ? new PlayerListItem() : Playerlist[revent.flplayerid]; update.Player = revent.player; update.FlPlayerID = revent.flplayerid; update.Name = revent.name; update.Rank = revent.rank; update.System = revent.system; update.Group = revent.group; update.GroupInvited = revent.groupInvited; Playerlist[revent.flplayerid] = update; // Notify all owned players of the player list update foreach (Player.Player p in Players.Values) { p.SendPlayerListUpdate(update); } } else if (next_event is DPGameRunnerPlayerDeletedEvent) { var revent = next_event as DPGameRunnerPlayerDeletedEvent; // fixme: might crash if the player leaves if (!Players.ContainsKey(revent.FlPlayerID)) { continue; } var player = Players[revent.FlPlayerID]; Players.Remove(revent.FlPlayerID); if (player.Ship.Objid != 0) { DelSimObject(player.Ship); } if (Playerlist.ContainsKey(revent.FlPlayerID)) { Playerlist.Remove(revent.FlPlayerID); } foreach (PlayerListItem item in Playerlist.Values) { item.Player.SendPlayerListDepart(player); } } else if (next_event is ReactorShutdownEvent) { running = false; } else if (next_event is DPGRAddCash) { var revent = next_event as DPGRAddCash; if (revent.player.Runner != this) { Log.AddLog(LogType.FL_MSG, "Warning: requeued rx msg onto changed runner"); revent.player.Runner.AddEvent(revent); } else { revent.player.Money += revent.cash; revent.player.SendSetMoney(); } } else if (next_event is DPGRSetCash) { var revent = next_event as DPGRSetCash; if (revent.player.Runner != this) { Log.AddLog(LogType.FL_MSG, "Warning: requeued rx msg onto changed runner"); revent.player.Runner.AddEvent(revent); } else { revent.player.Money = revent.cash; revent.player.SendSetMoney(); } } else if (next_event is DPGRBeam) { var revent = next_event as DPGRBeam; if (revent.Player.Runner != this) { Log.AddLog(LogType.FL_MSG, "Warning: requeued rx msg onto changed runner"); revent.Player.Runner.AddEvent(revent); } else { revent.Player.MonitoredObjs.Clear(); revent.Player.Ship.Basedata = revent.TargetBase; revent.Player.Ship.RespawnBasedata = revent.TargetBase; revent.Player.Ship.System = UniverseDB.FindSystem(revent.TargetBase.SystemID); revent.Player.Ship.IsDestroyed = false; revent.Player.SendServerLand(revent.Player.Ship, 0, revent.Player.Ship.Basedata.BaseID); revent.Player.Runner.Server.AddEvent(new DPGameRunnerPlayerUpdateEvent(revent.Player)); } } } }