update to game interface/integration for persistent stat data
This commit is contained in:
parent
f43f7b5040
commit
0a55c54c42
@ -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))
|
||||||
|
@ -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)
|
||||||
|
@ -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,
|
||||||
|
@ -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()));
|
||||||
|
@ -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 )
|
||||||
|
@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user