using System; using System.Threading; using System.Threading.Tasks; using SharedLibraryCore.Objects; namespace SharedLibraryCore { public class GameEvent { public enum EventFailReason { /// /// event execution did not fail /// None, /// /// an internal exception prevented the event /// from executing /// Exception, /// /// event origin didn't have the necessary privileges /// to execute the command /// Permission, /// /// executing the event would cause an invalid state /// Invalid } 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 = 100, /// /// a client was warned /// Warn = 101, /// /// all warnings for a client were cleared /// WarnClear = 102, /// /// a client was reported /// Report = 103, /// /// a client was flagged /// Flag = 104, /// /// a client was unflagged /// Unflag = 105, /// /// a client was kicked /// Kick = 106, /// /// a client was tempbanned /// TempBan = 107, /// /// a client was banned /// Ban = 108, /// /// a client was unbanned /// Unban = 109, /// /// a client entered a command /// Command = 110, /// /// a client's permission was changed /// ChangePermission = 111, // events "generated" by IW4MAdmin /// /// a message is sent to all clients /// Broadcast = 200, /// /// a message is sent to a specific client /// Tell = 201, // events "generated" by script/log /// /// AC Damage Log /// ScriptDamage = 300, /// /// AC Kill Log /// ScriptKill = 301, /// /// damage info printed out by game script /// Damage = 302, /// /// kill info printed out by game script /// Kill = 303, /// /// team info printed out by game script /// JoinTeam = 304, } 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; } public EventFailReason FailReason { get; set; } public bool Failed => FailReason != EventFailReason.None; /// /// asynchronously wait for GameEvent to be processed /// /// waitable task public Task WaitAsync(int timeOut = int.MaxValue) => Task.Run(() => { OnProcessed.Wait(timeOut); return this; }); /// /// 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.ClientNumber != -1) && (queuedEvent.Target.State != Player.ClientState.Connected && queuedEvent.Target.NetworkId != 0); } } }