update to game interface/integration for persistent stat data

This commit is contained in:
RaidMax 2022-07-13 16:10:16 -05:00
parent f43f7b5040
commit 0a55c54c42
8 changed files with 102 additions and 13 deletions

View File

@ -373,7 +373,7 @@ namespace IW4MAdmin
var clientTag = await _metaService.GetPersistentMetaByLookup(EFMeta.ClientTagV2, var clientTag = await _metaService.GetPersistentMetaByLookup(EFMeta.ClientTagV2,
EFMeta.ClientTagNameV2, E.Origin.ClientId, Manager.CancellationToken); EFMeta.ClientTagNameV2, E.Origin.ClientId, Manager.CancellationToken);
if (clientTag.Value != null) if (clientTag?.Value != null)
{ {
E.Origin.Tag = clientTag.Value; E.Origin.Tag = clientTag.Value;
} }
@ -769,6 +769,23 @@ namespace IW4MAdmin
E.Origin.UpdateTeam(E.Extra as string); E.Origin.UpdateTeam(E.Extra as string);
} }
else if (E.Type == GameEvent.EventType.MetaUpdated)
{
if (E.Extra is "PersistentStatClientId" && int.TryParse(E.Data, out var persistentClientId))
{
var penalties = await Manager.GetPenaltyService().GetActivePenaltiesByClientId(persistentClientId);
var banPenalty = penalties.FirstOrDefault(penalty => penalty.Type == EFPenalty.PenaltyType.Ban);
if (banPenalty is not null && E.Origin.Level != Permission.Banned)
{
ServerLogger.LogInformation(
"Banning {Client} as they have have provided a persistent clientId of {PersistentClientId}, which is banned",
E.Origin.ToString(), persistentClientId);
E.Origin.Ban(loc["SERVER_BAN_EVADE"].FormatExt(persistentClientId), Utilities.IW4MAdminClient(this), true);
}
}
}
lock (ChatHistory) lock (ChatHistory)
{ {
while (ChatHistory.Count > Math.Ceiling(ClientNum / 2.0)) while (ChatHistory.Count > Math.Ceiling(ClientNum / 2.0))

View File

@ -10,6 +10,7 @@ namespace IW4MAdmin.Application.Misc
{ {
public event EventHandler<GameEvent> OnClientDisconnect; public event EventHandler<GameEvent> OnClientDisconnect;
public event EventHandler<GameEvent> OnClientConnect; public event EventHandler<GameEvent> OnClientConnect;
public event EventHandler<GameEvent> OnClientMetaUpdated;
private readonly ILogger _logger; private readonly ILogger _logger;
@ -33,6 +34,11 @@ namespace IW4MAdmin.Application.Misc
{ {
OnClientDisconnect?.Invoke(this, gameEvent); OnClientDisconnect?.Invoke(this, gameEvent);
} }
if (gameEvent.Type == GameEvent.EventType.MetaUpdated)
{
OnClientMetaUpdated?.Invoke(this, gameEvent);
}
} }
catch (Exception ex) catch (Exception ex)

View File

@ -7,7 +7,10 @@ using System.Threading.Tasks;
using Data.Abstractions; using Data.Abstractions;
using Data.Models; using Data.Models;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using SharedLibraryCore;
using SharedLibraryCore.Database.Models;
using SharedLibraryCore.Dtos; using SharedLibraryCore.Dtos;
using SharedLibraryCore.Interfaces; using SharedLibraryCore.Interfaces;
using SharedLibraryCore.QueryHelper; using SharedLibraryCore.QueryHelper;
@ -19,13 +22,15 @@ public class MetaServiceV2 : IMetaServiceV2
{ {
private readonly IDictionary<MetaType, List<dynamic>> _metaActions; private readonly IDictionary<MetaType, List<dynamic>> _metaActions;
private readonly IDatabaseContextFactory _contextFactory; private readonly IDatabaseContextFactory _contextFactory;
private readonly IServiceProvider _serviceProvider;
private readonly ILogger _logger; private readonly ILogger _logger;
public MetaServiceV2(ILogger<MetaServiceV2> logger, IDatabaseContextFactory contextFactory) public MetaServiceV2(ILogger<MetaServiceV2> logger, IDatabaseContextFactory contextFactory, IServiceProvider serviceProvider)
{ {
_logger = logger; _logger = logger;
_metaActions = new Dictionary<MetaType, List<dynamic>>(); _metaActions = new Dictionary<MetaType, List<dynamic>>();
_contextFactory = contextFactory; _contextFactory = contextFactory;
_serviceProvider = serviceProvider;
} }
public async Task SetPersistentMeta(string metaKey, string metaValue, int clientId, public async Task SetPersistentMeta(string metaKey, string metaValue, int clientId,
@ -64,6 +69,26 @@ public class MetaServiceV2 : IMetaServiceV2
} }
await context.SaveChangesAsync(token); await context.SaveChangesAsync(token);
var manager = _serviceProvider.GetRequiredService<IManager>();
var matchingClient = manager.GetActiveClients().FirstOrDefault(client => client.ClientId == clientId);
var server = matchingClient?.CurrentServer ?? manager.GetServers().FirstOrDefault();
if (server is not null)
{
manager.AddEvent(new GameEvent
{
Type = GameEvent.EventType.MetaUpdated,
Origin = matchingClient ?? new EFClient
{
ClientId = clientId
},
Data = metaValue,
Extra = metaKey,
Owner = server
});
}
} }
public async Task SetPersistentMetaValue<T>(string metaKey, T metaValue, int clientId, public async Task SetPersistentMetaValue<T>(string metaKey, T metaValue, int clientId,

View File

@ -116,7 +116,8 @@ namespace IW4MAdmin.Application.Misc
typeof(System.Net.Http.HttpClient).Assembly, typeof(System.Net.Http.HttpClient).Assembly,
typeof(EFClient).Assembly, typeof(EFClient).Assembly,
typeof(Utilities).Assembly, typeof(Utilities).Assembly,
typeof(Encoding).Assembly typeof(Encoding).Assembly,
typeof(CancellationTokenSource).Assembly
}) })
.CatchClrExceptions() .CatchClrExceptions()
.AddObjectConverter(new PermissionLevelToStringConverter())); .AddObjectConverter(new PermissionLevelToStringConverter()));

View File

@ -53,8 +53,6 @@ init()
level thread OnPlayerConnect(); level thread OnPlayerConnect();
} }
////////////////////////////////// //////////////////////////////////
// Client Methods // Client Methods
////////////////////////////////// //////////////////////////////////
@ -167,6 +165,28 @@ DisplayWelcomeData()
self IPrintLnBold( "You were last seen ^5" + clientData.lastConnection ); self IPrintLnBold( "You were last seen ^5" + clientData.lastConnection );
} }
SetPersistentData()
{
storedClientId = self GetPlayerData( "bests", "none" );
if ( storedClientId != 0 )
{
if ( level.iw4adminIntegrationDebug == 1 )
{
IPrintLn( "Uploading persistent client id " + storedClientId );
}
SetClientMeta( "PersistentStatClientId", storedClientId );
}
if ( level.iw4adminIntegrationDebug == 1 )
{
IPrintLn( "Persisting client id " + self.persistentClientId );
}
self SetPlayerData( "bests", "none", int( self.persistentClientId ) );
}
PlayerConnectEvents() PlayerConnectEvents()
{ {
self endon( "disconnect" ); self endon( "disconnect" );
@ -643,6 +663,7 @@ OnClientDataReceived( event )
self.persistentClientId = event.data["clientId"]; self.persistentClientId = event.data["clientId"];
self thread DisplayWelcomeData(); self thread DisplayWelcomeData();
self setPersistentData();
} }
OnExecuteCommand( event ) OnExecuteCommand( event )

View File

@ -463,7 +463,11 @@ function onReceivedDvar(server, dvarName, dvarValue, success) {
if (input.length > 0) { if (input.length > 0) {
const event = parseEvent(input) const event = parseEvent(input)
logger.WriteDebug(`Processing input... ${event.eventType} ${event.subType} ${event.data} ${event.clientNumber}`); logger.WriteDebug(`Processing input... ${event.eventType} ${event.subType} ${event.data.toString()} ${event.clientNumber}`);
const metaService = _serviceResolver.ResolveService('IMetaServiceV2');
const threading = importNamespace('System.Threading');
const token = new threading.CancellationTokenSource().Token;
// todo: refactor to mapping if possible // todo: refactor to mapping if possible
if (event.eventType === 'ClientDataRequested') { if (event.eventType === 'ClientDataRequested') {
@ -475,8 +479,8 @@ function onReceivedDvar(server, dvarName, dvarValue, success) {
let data = []; let data = [];
if (event.subType === 'Meta') { if (event.subType === 'Meta') {
const metaService = _serviceResolver.ResolveService('IMetaService'); const metaService = _serviceResolver.ResolveService('IMetaServiceV2');
const meta = metaService.GetPersistentMeta(event.data, client).GetAwaiter().GetResult(); const meta = metaService.GetPersistentMeta(event.data, client, token).GetAwaiter().GetResult();
data[event.data] = meta === null ? '' : meta.Value; data[event.data] = meta === null ? '' : meta.Value;
} else { } else {
data = { data = {
@ -510,19 +514,19 @@ function onReceivedDvar(server, dvarName, dvarValue, success) {
sendEvent(server, false, 'SetClientDataCompleted', 'Meta', {ClientNumber: event.clientNumber}, undefined, {status: 'Fail'}); sendEvent(server, false, 'SetClientDataCompleted', 'Meta', {ClientNumber: event.clientNumber}, undefined, {status: 'Fail'});
} else { } else {
if (event.subType === 'Meta') { if (event.subType === 'Meta') {
const metaService = _serviceResolver.ResolveService('IMetaService');
try { try {
logger.WriteDebug(`Key=${event.data['key']}, Value=${event.data['value']}`); logger.WriteDebug(`Key=${event.data['key']}, Value=${event.data['value']}, Direction=${event.data['direction']} ${token}`);
if (event.data['direction'] != null) { if (event.data['direction'] != null) {
event.data['direction'] = 'up' event.data['direction'] = 'up'
? metaService.IncrementPersistentMeta(event.data['key'], event.data['value'], clientId).GetAwaiter().GetResult() ? metaService.IncrementPersistentMeta(event.data['key'], event.data['value'], clientId, token).GetAwaiter().GetResult()
: metaService.DecrementPersistentMeta(event.data['key'], event.data['value'], clientId).GetAwaiter().GetResult(); : metaService.DecrementPersistentMeta(event.data['key'], event.data['value'], clientId, token).GetAwaiter().GetResult();
} else { } else {
metaService.SetPersistentMeta(event.data['key'], event.data['value'], clientId).GetAwaiter().GetResult(); metaService.SetPersistentMeta(event.data['key'], event.data['value'], clientId, token).GetAwaiter().GetResult();
} }
sendEvent(server, false, 'SetClientDataCompleted', 'Meta', {ClientNumber: event.clientNumber}, undefined, {status: 'Complete'}); sendEvent(server, false, 'SetClientDataCompleted', 'Meta', {ClientNumber: event.clientNumber}, undefined, {status: 'Complete'});
} catch (error) { } catch (error) {
sendEvent(server, false, 'SetClientDataCompleted', 'Meta', {ClientNumber: event.clientNumber}, undefined, {status: 'Fail'}); sendEvent(server, false, 'SetClientDataCompleted', 'Meta', {ClientNumber: event.clientNumber}, undefined, {status: 'Fail'});
logger.WriteError('Could not persist client meta ' + error.toString());
} }
} }
} }

View File

@ -205,6 +205,11 @@ namespace SharedLibraryCore
/// </summary> /// </summary>
Logout = 113, Logout = 113,
/// <summary>
/// meta value updated on client
/// </summary>
MetaUpdated = 114,
// events "generated" by IW4MAdmin // events "generated" by IW4MAdmin
/// <summary> /// <summary>
/// a message is sent to all clients /// a message is sent to all clients

View File

@ -193,6 +193,16 @@ namespace SharedLibraryCore.Services
return await activePenaltiesIds.Select(ids => ids.Penalty).ToListAsync(); return await activePenaltiesIds.Select(ids => ids.Penalty).ToListAsync();
} }
public async Task<List<EFPenalty>> GetActivePenaltiesByClientId(int clientId)
{
await using var context = _contextFactory.CreateContext(false);
return await context.PenaltyIdentifiers
.Where(identifier => identifier.Penalty.Offender.ClientId == clientId)
.Select(identifier => identifier.Penalty)
.Where(Filter)
.ToListAsync();
}
public async Task<List<EFPenalty>> ActivePenaltiesByRecentIdentifiers(int linkId) public async Task<List<EFPenalty>> ActivePenaltiesByRecentIdentifiers(int linkId)
{ {
await using var context = _contextFactory.CreateContext(false); await using var context = _contextFactory.CreateContext(false);