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