using System; using System.Threading; using System.Threading.Tasks; using SharedLibraryCore.Objects; namespace SharedLibraryCore { public class GameEvent { public enum EventType { /// /// the event wasn't parsed properly /// Unknown, // events "generated" by the server /// /// a server started being monitored /// Start, /// /// a server stopped being monitored /// Stop, /// /// a client was detecting as connecting via RCon /// Connect, /// /// a client was detecting joining via log /// Join, /// /// a client was detected leaving via log /// Quit, /// /// a client was detected leaving by RCon /// Disconnect, /// /// the current map ended /// MapEnd, /// /// the current map changed /// MapChange, // events "generated" by clients /// /// a client sent a message /// Say, /// /// a client was warned /// Warn, /// /// a client was reported /// Report, /// /// a client was flagged /// Flag, /// /// a client was unflagged /// Unflag, /// /// a client was kicked /// Kick, /// /// a client was tempbanned /// TempBan, /// /// a client was banned /// Ban, /// /// a client entered a command /// Command, /// /// a client's permission was changed /// ChangePermission, // events "generated" by IW4MAdmin /// /// a message is sent to all clients /// Broadcast, /// /// a message is sent to a specific client /// Tell, // events "generated" by script/log /// /// AC Damage Log /// ScriptDamage, /// /// AC Kill Log /// ScriptKill, /// /// damage info printed out by game script /// Damage, /// /// kill info printed out by game script /// Kill, /// /// team info printed out by game script /// JoinTeam, } static long NextEventId; static long GetNextEventId() => Interlocked.Increment(ref NextEventId); public GameEvent() { OnProcessed = new ManualResetEventSlim(false); Time = DateTime.UtcNow; Id = GetNextEventId(); } public EventType Type; public string Data; // Data is usually the message sent by player public string Message; public Player Origin; public Player Target; public Server Owner; public Boolean Remote = false; public object Extra { get; set; } public ManualResetEventSlim OnProcessed { get; set; } public DateTime Time { get; set; } public long Id { get; private set; } /// /// asynchronously wait for GameEvent to be processed /// /// waitable task public Task WaitAsync(int timeOut = int.MaxValue) => Task.FromResult(OnProcessed.Wait(timeOut)); /// /// determine whether an event should be delayed or not /// applies only to the origin entity /// /// event to determine status for /// true if event should be delayed, false otherwise public static bool ShouldOriginEventBeDelayed(GameEvent queuedEvent) { return queuedEvent.Origin != null && queuedEvent.Origin.State != Player.ClientState.Connected && // we want to allow join and quit events queuedEvent.Type != EventType.Connect && queuedEvent.Type != EventType.Join && queuedEvent.Type != EventType.Quit && queuedEvent.Type != EventType.Disconnect && // we don't care about unknown events queuedEvent.Origin.NetworkId != 0; } /// /// determine whether an event should be delayed or not /// applies only to the target entity /// /// event to determine status for /// true if event should be delayed, false otherwise public static bool ShouldTargetEventBeDelayed(GameEvent queuedEvent) { return queuedEvent.Target != null && queuedEvent.Target.State != Player.ClientState.Connected && queuedEvent.Target.NetworkId != 0; } public static bool IsEventTimeSensitive(GameEvent gameEvent) => gameEvent.Type == EventType.Connect; } }