IW4M-Admin/SharedLibraryCore/Events/GameEvent.cs

366 lines
10 KiB
C#
Raw Normal View History

2022-01-26 11:32:16 -05:00
using System;
using System.Collections.Generic;
using System.Threading;
2018-09-06 14:25:58 -04:00
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Serilog.Context;
2022-01-26 11:32:16 -05:00
using SharedLibraryCore.Database.Models;
2018-04-08 02:44:42 -04:00
namespace SharedLibraryCore
2015-03-08 17:20:10 -04:00
{
public class GameEvent
2015-03-08 17:20:10 -04:00
{
public enum EventFailReason
{
/// <summary>
2022-01-26 11:32:16 -05:00
/// event execution did not fail
/// </summary>
None,
2022-01-26 11:32:16 -05:00
/// <summary>
2022-01-26 11:32:16 -05:00
/// an internal exception prevented the event
/// from executing
/// </summary>
Exception,
2022-01-26 11:32:16 -05:00
/// <summary>
2022-01-26 11:32:16 -05:00
/// event origin didn't have the necessary privileges
/// to execute the command
/// </summary>
Permission,
2022-01-26 11:32:16 -05:00
/// <summary>
2022-01-26 11:32:16 -05:00
/// executing the event would cause an invalid state
/// </summary>
2018-10-03 22:20:49 -04:00
Invalid,
2022-01-26 11:32:16 -05:00
2018-10-03 22:20:49 -04:00
/// <summary>
2022-01-26 11:32:16 -05:00
/// client is doing too much of something
2018-10-03 22:20:49 -04:00
/// </summary>
Throttle,
2022-01-26 11:32:16 -05:00
/// <summary>
2022-01-26 11:32:16 -05:00
/// the event timed out before completion
/// </summary>
Timeout
}
2022-01-26 11:32:16 -05:00
[Flags]
public enum EventRequiredEntity
{
None = 1,
Origin = 2,
Target = 4
}
public enum EventSource
{
Unspecified,
Log,
Status,
Internal
}
public enum EventType
2015-03-08 17:20:10 -04:00
{
/// <summary>
2022-01-26 11:32:16 -05:00
/// the event wasn't parsed properly
/// </summary>
Unknown,
// events "generated" by the server
/// <summary>
2022-01-26 11:32:16 -05:00
/// a server started being monitored
/// </summary>
Start,
2022-01-26 11:32:16 -05:00
/// <summary>
2022-01-26 11:32:16 -05:00
/// a server stopped being monitored
/// </summary>
Stop,
2022-01-26 11:32:16 -05:00
/// <summary>
2022-01-26 11:32:16 -05:00
/// a client was detecting as connecting via log
/// </summary>
2015-03-08 17:20:10 -04:00
Connect,
2022-01-26 11:32:16 -05:00
/// <summary>
2022-01-26 11:32:16 -05:00
/// a client was detecting joining by RCon
/// </summary>
Join,
2022-01-26 11:32:16 -05:00
/// <summary>
2022-01-26 11:32:16 -05:00
/// a client was detected leaving via log
/// </summary>
Quit,
2022-01-26 11:32:16 -05:00
/// <summary>
2022-01-26 11:32:16 -05:00
/// a client was detected leaving by RCon
/// </summary>
2015-03-08 17:20:10 -04:00
Disconnect,
2022-01-26 11:32:16 -05:00
/// <summary>
2022-01-26 11:32:16 -05:00
/// the current map ended
/// </summary>
2015-03-08 17:20:10 -04:00
MapEnd,
2022-01-26 11:32:16 -05:00
/// <summary>
2022-01-26 11:32:16 -05:00
/// the current map changed
/// </summary>
MapChange,
2022-01-26 11:32:16 -05:00
2018-11-07 21:30:11 -05:00
/// <summary>
2022-01-26 11:32:16 -05:00
/// a client was detected as starting to connect
2018-11-07 21:30:11 -05:00
/// </summary>
PreConnect,
2022-01-26 11:32:16 -05:00
2018-11-07 21:30:11 -05:00
/// <summary>
2022-01-26 11:32:16 -05:00
/// a client was detecting as starting to disconnect
2018-11-07 21:30:11 -05:00
/// </summary>
PreDisconnect,
2022-01-26 11:32:16 -05:00
2018-11-07 21:30:11 -05:00
/// <summary>
2022-01-26 11:32:16 -05:00
/// a client's information was updated
2018-11-07 21:30:11 -05:00
/// </summary>
Update,
2022-01-26 11:32:16 -05:00
/// <summary>
2022-01-26 11:32:16 -05:00
/// connection was lost to a server (the server has not responded after a number of attempts)
/// </summary>
ConnectionLost,
2022-01-26 11:32:16 -05:00
/// <summary>
2022-01-26 11:32:16 -05:00
/// connection was restored to a server (the server began responding again)
/// </summary>
ConnectionRestored,
// events "generated" by clients
/// <summary>
2022-01-26 11:32:16 -05:00
/// a client sent a message
/// </summary>
Say = 100,
2022-01-26 11:32:16 -05:00
/// <summary>
2022-01-26 11:32:16 -05:00
/// a client was warned
/// </summary>
Warn = 101,
2022-01-26 11:32:16 -05:00
/// <summary>
2022-01-26 11:32:16 -05:00
/// all warnings for a client were cleared
/// </summary>
WarnClear = 102,
2022-01-26 11:32:16 -05:00
/// <summary>
2022-01-26 11:32:16 -05:00
/// a client was reported
/// </summary>
Report = 103,
2022-01-26 11:32:16 -05:00
/// <summary>
2022-01-26 11:32:16 -05:00
/// a client was flagged
/// </summary>
Flag = 104,
2022-01-26 11:32:16 -05:00
/// <summary>
2022-01-26 11:32:16 -05:00
/// a client was unflagged
/// </summary>
Unflag = 105,
2022-01-26 11:32:16 -05:00
/// <summary>
2022-01-26 11:32:16 -05:00
/// a client was kicked
/// </summary>
Kick = 106,
2022-01-26 11:32:16 -05:00
/// <summary>
2022-01-26 11:32:16 -05:00
/// a client was tempbanned
/// </summary>
TempBan = 107,
2022-01-26 11:32:16 -05:00
/// <summary>
2022-01-26 11:32:16 -05:00
/// a client was banned
/// </summary>
Ban = 108,
2022-01-26 11:32:16 -05:00
/// <summary>
2022-01-26 11:32:16 -05:00
/// a client was unbanned
/// </summary>
Unban = 109,
2022-01-26 11:32:16 -05:00
/// <summary>
2022-01-26 11:32:16 -05:00
/// a client entered a command
/// </summary>
Command = 110,
2022-01-26 11:32:16 -05:00
/// <summary>
2022-01-26 11:32:16 -05:00
/// a client's permission was changed
/// </summary>
ChangePermission = 111,
2022-01-26 11:32:16 -05:00
/// <summary>
2022-01-26 11:32:16 -05:00
/// client logged in to webfront
/// </summary>
Login = 112,
2022-01-26 11:32:16 -05:00
/// <summary>
2022-01-26 11:32:16 -05:00
/// client logged out of webfront
/// </summary>
Logout = 113,
/// <summary>
/// meta value updated on client
/// </summary>
MetaUpdated = 114,
// events "generated" by IW4MAdmin
/// <summary>
2022-01-26 11:32:16 -05:00
/// a message is sent to all clients
/// </summary>
Broadcast = 200,
2022-01-26 11:32:16 -05:00
/// <summary>
2022-01-26 11:32:16 -05:00
/// a message is sent to a specific client
/// </summary>
Tell = 201,
// events "generated" by script/log
/// <summary>
2022-01-26 11:32:16 -05:00
/// AC Damage Log
/// </summary>
ScriptDamage = 300,
2022-01-26 11:32:16 -05:00
/// <summary>
2022-01-26 11:32:16 -05:00
/// AC Kill Log
/// </summary>
ScriptKill = 301,
2022-01-26 11:32:16 -05:00
/// <summary>
2022-01-26 11:32:16 -05:00
/// damage info printed out by game script
/// </summary>
Damage = 302,
2022-01-26 11:32:16 -05:00
/// <summary>
2022-01-26 11:32:16 -05:00
/// kill info printed out by game script
/// </summary>
Kill = 303,
2022-01-26 11:32:16 -05:00
/// <summary>
2022-01-26 11:32:16 -05:00
/// team info printed out by game script
/// </summary>
JoinTeam = 304,
2022-01-26 11:32:16 -05:00
/// <summary>
2022-01-26 11:32:16 -05:00
/// used for community generated plugin events
/// </summary>
Other
2015-03-08 17:20:10 -04:00
}
2022-01-26 11:32:16 -05:00
private static long NextEventId;
2022-02-02 17:21:08 -05:00
private readonly SemaphoreSlim _eventFinishedWaiter = new(0, 1);
2022-01-26 11:32:16 -05:00
public string Data; // Data is usually the message sent by player
public string Message;
public EFClient Origin;
public Server Owner;
public EFClient Target;
2022-01-26 11:32:16 -05:00
public EventType Type;
public string TypeName => Type.ToString();
2015-03-08 17:20:10 -04:00
public GameEvent()
{
Time = DateTime.UtcNow;
Id = GetNextEventId();
}
2022-02-02 17:21:08 -05:00
~GameEvent()
{
_eventFinishedWaiter.Dispose();
}
2015-03-08 17:20:10 -04:00
public EventSource Source { get; set; }
2022-01-26 11:32:16 -05:00
/// <summary>
2022-01-26 11:32:16 -05:00
/// suptype of the event for more detailed classification
/// </summary>
public string Subtype { get; set; }
2022-01-26 11:32:16 -05:00
public EventRequiredEntity RequiredEntity { get; set; }
2022-01-26 11:32:16 -05:00
/// <summary>
2022-01-26 11:32:16 -05:00
/// Specifies the game time offset as printed in the log
/// </summary>
public long? GameTime { get; set; }
2022-01-26 11:32:16 -05:00
public EFClient ImpersonationOrigin { get; set; }
public bool IsRemote { get; set; }
2018-04-14 00:51:38 -04:00
public object Extra { get; set; }
public DateTime Time { get; set; }
2022-01-26 11:32:16 -05:00
public long Id { get; }
public EventFailReason FailReason { get; set; }
public bool Failed => FailReason != EventFailReason.None;
public Guid CorrelationId { get; set; } = Guid.NewGuid();
public List<string> Output { get; set; } = new List<string>();
/// <summary>
2022-01-26 11:32:16 -05:00
/// Indicates if the event should block until it is complete
/// </summary>
public bool IsBlocking { get; set; }
2022-01-26 11:32:16 -05:00
private static long GetNextEventId()
{
return Interlocked.Increment(ref NextEventId);
}
public void Complete()
{
2022-02-02 17:21:08 -05:00
if (_eventFinishedWaiter.CurrentCount == 0)
{
_eventFinishedWaiter.Release();
}
}
public async Task<GameEvent> WaitAsync()
{
return await WaitAsync(Utilities.DefaultCommandTimeout, new CancellationToken());
}
2018-09-06 14:25:58 -04:00
/// <summary>
2022-01-26 11:32:16 -05:00
/// asynchronously wait for GameEvent to be processed
2018-09-06 14:25:58 -04:00
/// </summary>
/// <returns>waitable task </returns>
public async Task<GameEvent> WaitAsync(TimeSpan timeSpan, CancellationToken token)
{
2022-01-26 11:32:16 -05:00
var processed = false;
Utilities.DefaultLogger.LogDebug("Begin wait for event {Id}", Id);
try
2018-11-07 21:30:11 -05:00
{
2022-02-02 17:21:08 -05:00
processed = await _eventFinishedWaiter.WaitAsync(timeSpan, token);
}
catch (TaskCanceledException)
{
processed = true;
}
finally
{
if (_eventFinishedWaiter.CurrentCount == 0)
{
_eventFinishedWaiter.Release();
}
}
if (!processed)
{
2022-01-26 11:32:16 -05:00
using (LogContext.PushProperty("Server", Owner?.ToString()))
{
2022-01-26 11:32:16 -05:00
Utilities.DefaultLogger.LogError("Waiting for event to complete timed out {@eventData}",
new { Event = this, Message, Origin = Origin?.ToString(), Target = Target?.ToString() });
}
}
// this lets us know if the the action timed out
FailReason = FailReason == EventFailReason.None && !processed ? EventFailReason.Timeout : FailReason;
return this;
}
2015-03-08 17:20:10 -04:00
}
2022-02-02 17:21:08 -05:00
}