implement team tracking via game interface (EFClient.Team and EFClient.TeamName)

This commit is contained in:
RaidMax 2022-03-12 13:38:33 -06:00
parent 1b6d8107ae
commit f567a03fa7
7 changed files with 82 additions and 4 deletions

View File

@ -49,6 +49,13 @@ namespace IW4MAdmin.Application.EventParsers
Configuration.Join.AddMapping(ParserRegex.GroupType.OriginNetworkId, 2); Configuration.Join.AddMapping(ParserRegex.GroupType.OriginNetworkId, 2);
Configuration.Join.AddMapping(ParserRegex.GroupType.OriginClientNumber, 3); Configuration.Join.AddMapping(ParserRegex.GroupType.OriginClientNumber, 3);
Configuration.Join.AddMapping(ParserRegex.GroupType.OriginName, 4); Configuration.Join.AddMapping(ParserRegex.GroupType.OriginName, 4);
Configuration.JoinTeam.Pattern = @"^(JT);(-?[A-Fa-f0-9_]{1,32}|bot[0-9]+|0);([0-9]+);(\w+);(.+)$";
Configuration.JoinTeam.AddMapping(ParserRegex.GroupType.EventType, 1);
Configuration.JoinTeam.AddMapping(ParserRegex.GroupType.OriginNetworkId, 2);
Configuration.JoinTeam.AddMapping(ParserRegex.GroupType.OriginClientNumber, 3);
Configuration.JoinTeam.AddMapping(ParserRegex.GroupType.OriginTeam, 4);
Configuration.JoinTeam.AddMapping(ParserRegex.GroupType.OriginName, 5);
Configuration.Damage.Pattern = @"^(D);(-?[A-Fa-f0-9_]{1,32}|bot[0-9]+|0);(-?[0-9]+);(axis|allies|world|none)?;([^;]{1,32});(-?[A-Fa-f0-9_]{1,32}|bot[0-9]+|0)?;(-?[0-9]+);(axis|allies|world|none)?;([^;]{1,32})?;((?:[0-9]+|[a-z]+|_|\+)+);([0-9]+);((?:[A-Z]|_)+);((?:[a-z]|_)+)$"; Configuration.Damage.Pattern = @"^(D);(-?[A-Fa-f0-9_]{1,32}|bot[0-9]+|0);(-?[0-9]+);(axis|allies|world|none)?;([^;]{1,32});(-?[A-Fa-f0-9_]{1,32}|bot[0-9]+|0)?;(-?[0-9]+);(axis|allies|world|none)?;([^;]{1,32})?;((?:[0-9]+|[a-z]+|_|\+)+);([0-9]+);((?:[A-Z]|_)+);((?:[a-z]|_)+)$";
Configuration.Damage.AddMapping(ParserRegex.GroupType.EventType, 1); Configuration.Damage.AddMapping(ParserRegex.GroupType.EventType, 1);
@ -100,6 +107,7 @@ namespace IW4MAdmin.Application.EventParsers
{"K", GameEvent.EventType.Kill}, {"K", GameEvent.EventType.Kill},
{"D", GameEvent.EventType.Damage}, {"D", GameEvent.EventType.Damage},
{"J", GameEvent.EventType.PreConnect}, {"J", GameEvent.EventType.PreConnect},
{"JT", GameEvent.EventType.JoinTeam },
{"Q", GameEvent.EventType.PreDisconnect}, {"Q", GameEvent.EventType.PreDisconnect},
}; };
} }
@ -322,6 +330,42 @@ namespace IW4MAdmin.Application.EventParsers
} }
} }
if (eventType == GameEvent.EventType.JoinTeam)
{
var match = Configuration.JoinTeam.PatternMatcher.Match(logLine);
if (match.Success)
{
var originIdString = match.Values[Configuration.JoinTeam.GroupMapping[ParserRegex.GroupType.OriginNetworkId]];
var originName = match.Values[Configuration.JoinTeam.GroupMapping[ParserRegex.GroupType.OriginName]];
var team = match.Values[Configuration.JoinTeam.GroupMapping[ParserRegex.GroupType.OriginTeam]];
var networkId = originIdString.IsBotGuid() ?
originName.GenerateGuidFromString() :
originIdString.ConvertGuidToLong(Configuration.GuidNumberStyle);
return new GameEvent
{
Type = GameEvent.EventType.JoinTeam,
Data = logLine,
Origin = new EFClient
{
CurrentAlias = new EFAlias
{
Name = match.Values[Configuration.JoinTeam.GroupMapping[ParserRegex.GroupType.OriginName]].TrimNewLine(),
},
NetworkId = networkId,
ClientNumber = Convert.ToInt32(match.Values[Configuration.JoinTeam.GroupMapping[ParserRegex.GroupType.OriginClientNumber]]),
State = EFClient.ClientState.Connected,
},
Extra = team,
RequiredEntity = GameEvent.EventRequiredEntity.None,
GameTime = gameTime,
Source = GameEvent.EventSource.Log
};
}
}
if (eventType == GameEvent.EventType.PreDisconnect) if (eventType == GameEvent.EventType.PreDisconnect)
{ {
var match = Configuration.Quit.PatternMatcher.Match(logLine); var match = Configuration.Quit.PatternMatcher.Match(logLine);

View File

@ -8,11 +8,12 @@ namespace IW4MAdmin.Application.EventParsers
/// generic implementation of the IEventParserConfiguration /// generic implementation of the IEventParserConfiguration
/// allows script plugins to generate dynamic configurations /// allows script plugins to generate dynamic configurations
/// </summary> /// </summary>
sealed internal class DynamicEventParserConfiguration : IEventParserConfiguration internal sealed class DynamicEventParserConfiguration : IEventParserConfiguration
{ {
public string GameDirectory { get; set; } public string GameDirectory { get; set; }
public ParserRegex Say { get; set; } public ParserRegex Say { get; set; }
public ParserRegex Join { get; set; } public ParserRegex Join { get; set; }
public ParserRegex JoinTeam { get; set; }
public ParserRegex Quit { get; set; } public ParserRegex Quit { get; set; }
public ParserRegex Kill { get; set; } public ParserRegex Kill { get; set; }
public ParserRegex Damage { get; set; } public ParserRegex Damage { get; set; }
@ -26,6 +27,7 @@ namespace IW4MAdmin.Application.EventParsers
{ {
Say = parserRegexFactory.CreateParserRegex(); Say = parserRegexFactory.CreateParserRegex();
Join = parserRegexFactory.CreateParserRegex(); Join = parserRegexFactory.CreateParserRegex();
JoinTeam = parserRegexFactory.CreateParserRegex();
Quit = parserRegexFactory.CreateParserRegex(); Quit = parserRegexFactory.CreateParserRegex();
Kill = parserRegexFactory.CreateParserRegex(); Kill = parserRegexFactory.CreateParserRegex();
Damage = parserRegexFactory.CreateParserRegex(); Damage = parserRegexFactory.CreateParserRegex();

View File

@ -89,7 +89,7 @@ namespace IW4MAdmin.Application.IO
var lines = logData var lines = logData
.Split('\n') .Split('\n')
.Where(line => line.Length > 0); .Where(line => line.Length > 0 && !line.Contains('ÿ'));
foreach (var eventLine in lines) foreach (var eventLine in lines)
{ {

View File

@ -713,6 +713,11 @@ namespace IW4MAdmin
await E.Owner.ExecuteCommandAsync(E.Data); await E.Owner.ExecuteCommandAsync(E.Data);
} }
} }
else if (E.Type == GameEvent.EventType.JoinTeam)
{
E.Origin.UpdateTeam(E.Extra as string);
}
lock (ChatHistory) lock (ChatHistory)
{ {

View File

@ -623,7 +623,7 @@ UnhideImpl()
return; return;
} }
if ( IsDefined( self.isHidden ) && !self.isHidden ) if ( !IsDefined( self.isHidden ) || !self.isHidden )
{ {
self IPrintLnBold( "You are not hidden" ); self IPrintLnBold( "You are not hidden" );
return; return;

View File

@ -18,6 +18,11 @@ namespace SharedLibraryCore.Interfaces
/// stores the regex information for a join event printed in the game log /// stores the regex information for a join event printed in the game log
/// </summary> /// </summary>
ParserRegex Join { get; set; } ParserRegex Join { get; set; }
/// <summary>
/// stores the regex information for a join team event printed in the game log
/// </summary>
ParserRegex JoinTeam { get; set; }
/// <summary> /// <summary>
/// stores the regex information for a quit event printed in the game log /// stores the regex information for a quit event printed in the game log
@ -59,4 +64,4 @@ namespace SharedLibraryCore.Interfaces
/// </summary> /// </summary>
NumberStyles GuidNumberStyle { get; set; } NumberStyles GuidNumberStyle { get; set; }
} }
} }

View File

@ -39,6 +39,14 @@ namespace SharedLibraryCore.Database.Models
Disconnecting Disconnecting
} }
public enum TeamType
{
Unknown,
Spectator,
Allies,
Axis
}
[NotMapped] private readonly SemaphoreSlim _processingEvent; [NotMapped] private readonly SemaphoreSlim _processingEvent;
public EFClient() public EFClient()
@ -101,6 +109,9 @@ namespace SharedLibraryCore.Database.Models
[NotMapped] public string GuidString => NetworkId.ToString("x"); [NotMapped] public string GuidString => NetworkId.ToString("x");
[NotMapped] public ClientState State { get; set; } [NotMapped] public ClientState State { get; set; }
[NotMapped] public TeamType Team { get; set; }
[NotMapped] public string TeamName { get; set; }
[NotMapped] [NotMapped]
// this is kinda dirty, but I need localizable level names // this is kinda dirty, but I need localizable level names
@ -710,6 +721,17 @@ namespace SharedLibraryCore.Database.Models
return true; return true;
} }
public void UpdateTeam(string newTeam)
{
if (string.IsNullOrEmpty(newTeam))
{
return;
}
Team = Enum.TryParse(newTeam, true, out TeamType team) ? team : TeamType.Unknown;
TeamName = newTeam;
}
public async Task Lock() public async Task Lock()
{ {
var result = await _processingEvent.WaitAsync(Utilities.DefaultCommandTimeout); var result = await _processingEvent.WaitAsync(Utilities.DefaultCommandTimeout);