Support player sessions in admin logs and add test
Fix EventRan log type id Make slipping low impact
This commit is contained in:
@@ -1,11 +1,13 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Content.Server.Administration.Logs;
|
using Content.Server.Administration.Logs;
|
||||||
using Content.Server.Database;
|
using Content.Server.Database;
|
||||||
using Content.Shared.Administration.Logs;
|
using Content.Shared.Administration.Logs;
|
||||||
using Content.Shared.CCVar;
|
using Content.Shared.CCVar;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
using Robust.Server.Player;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
using Robust.Shared.Map;
|
using Robust.Shared.Map;
|
||||||
|
|
||||||
@@ -194,4 +196,49 @@ public class AddTests : ContentIntegrationTest
|
|||||||
return count >= amount;
|
return count >= amount;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task AddPlayerSessionLog()
|
||||||
|
{
|
||||||
|
var (client, server) = await StartConnectedServerClientPair(serverOptions: new ServerContentIntegrationOption
|
||||||
|
{
|
||||||
|
CVarOverrides =
|
||||||
|
{
|
||||||
|
[CCVars.AdminLogsQueueSendDelay.Name] = "0"
|
||||||
|
},
|
||||||
|
Pool = true
|
||||||
|
});
|
||||||
|
|
||||||
|
await Task.WhenAll(client.WaitIdleAsync(), server.WaitIdleAsync());
|
||||||
|
|
||||||
|
var sPlayers = server.ResolveDependency<IPlayerManager>();
|
||||||
|
var sSystems = server.ResolveDependency<IEntitySystemManager>();
|
||||||
|
|
||||||
|
var sAdminLogSystem = sSystems.GetEntitySystem<AdminLogSystem>();
|
||||||
|
Guid playerGuid = default;
|
||||||
|
|
||||||
|
await server.WaitPost(() =>
|
||||||
|
{;
|
||||||
|
var player = sPlayers.ServerSessions.First();
|
||||||
|
playerGuid = player.UserId;
|
||||||
|
|
||||||
|
Assert.DoesNotThrow(() =>
|
||||||
|
{
|
||||||
|
sAdminLogSystem.Add(LogType.Unknown, $"{player:Player} test log.");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
await WaitUntil(server, async () =>
|
||||||
|
{
|
||||||
|
var logs = sAdminLogSystem.CurrentRoundLogs();
|
||||||
|
|
||||||
|
await foreach (var log in logs)
|
||||||
|
{
|
||||||
|
Assert.That(log.Players, Does.Contain(playerGuid));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
86
Content.Server/Administration/Logs/AdminLogSystem.Json.cs
Normal file
86
Content.Server/Administration/Logs/AdminLogSystem.Json.cs
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using Content.Server.Administration.Logs.Converters;
|
||||||
|
using Robust.Server.GameObjects;
|
||||||
|
using Robust.Server.Player;
|
||||||
|
using Robust.Shared.GameObjects;
|
||||||
|
using Robust.Shared.IoC;
|
||||||
|
|
||||||
|
namespace Content.Server.Administration.Logs;
|
||||||
|
|
||||||
|
public partial class AdminLogSystem
|
||||||
|
{
|
||||||
|
private static readonly JsonNamingPolicy NamingPolicy = JsonNamingPolicy.CamelCase;
|
||||||
|
|
||||||
|
// Init only
|
||||||
|
private JsonSerializerOptions _jsonOptions = default!;
|
||||||
|
|
||||||
|
private void InitializeJson()
|
||||||
|
{
|
||||||
|
_jsonOptions = new JsonSerializerOptions
|
||||||
|
{
|
||||||
|
PropertyNamingPolicy = NamingPolicy
|
||||||
|
};
|
||||||
|
|
||||||
|
foreach (var converter in _reflection.FindTypesWithAttribute<AdminLogConverterAttribute>())
|
||||||
|
{
|
||||||
|
var instance = _typeFactory.CreateInstance<JsonConverter>(converter);
|
||||||
|
_jsonOptions.Converters.Add(instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
var converterNames = _jsonOptions.Converters.Select(converter => converter.GetType().Name);
|
||||||
|
_sawmill.Info($"Admin log converters found: {string.Join(" ", converterNames)}");
|
||||||
|
}
|
||||||
|
|
||||||
|
private (JsonDocument json, List<Guid> players, List<(int id, string? name)> entities) ToJson(
|
||||||
|
Dictionary<string, object?> properties)
|
||||||
|
{
|
||||||
|
var entities = new List<(int id, string? name)>();
|
||||||
|
var players = new List<Guid>();
|
||||||
|
var parsed = new Dictionary<string, object?>();
|
||||||
|
|
||||||
|
foreach (var key in properties.Keys)
|
||||||
|
{
|
||||||
|
var value = properties[key];
|
||||||
|
value = value switch
|
||||||
|
{
|
||||||
|
IPlayerSession player => new SerializablePlayer(player),
|
||||||
|
_ => value
|
||||||
|
};
|
||||||
|
|
||||||
|
var parsedKey = NamingPolicy.ConvertName(key);
|
||||||
|
parsed.Add(parsedKey, value);
|
||||||
|
|
||||||
|
EntityUid? entityId = properties[key] switch
|
||||||
|
{
|
||||||
|
EntityUid id => id,
|
||||||
|
IEntity entity => entity.Uid,
|
||||||
|
IPlayerSession {AttachedEntityUid: { }} session => session.AttachedEntityUid.Value,
|
||||||
|
IComponent component => component.OwnerUid,
|
||||||
|
_ => null
|
||||||
|
};
|
||||||
|
|
||||||
|
if (entityId is not { } uid)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var entityName = _entityManager.TryGetEntity(uid, out var resolvedEntity)
|
||||||
|
? resolvedEntity.Name
|
||||||
|
: null;
|
||||||
|
|
||||||
|
entities.Add(((int) uid, entityName));
|
||||||
|
|
||||||
|
if (_entityManager.TryGetComponent(uid, out ActorComponent? actor))
|
||||||
|
{
|
||||||
|
players.Add(actor.PlayerSession.UserId.UserId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (JsonSerializer.SerializeToDocument(parsed, _jsonOptions), players, entities);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,19 +1,14 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using System.Text.Json.Serialization;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Content.Server.Administration.Logs.Converters;
|
|
||||||
using Content.Server.Database;
|
using Content.Server.Database;
|
||||||
using Content.Server.GameTicking;
|
using Content.Server.GameTicking;
|
||||||
using Content.Server.GameTicking.Events;
|
using Content.Server.GameTicking.Events;
|
||||||
using Content.Shared.Administration.Logs;
|
using Content.Shared.Administration.Logs;
|
||||||
using Content.Shared.CCVar;
|
using Content.Shared.CCVar;
|
||||||
using Prometheus;
|
using Prometheus;
|
||||||
using Robust.Server.GameObjects;
|
|
||||||
using Robust.Server.Player;
|
|
||||||
using Robust.Shared;
|
using Robust.Shared;
|
||||||
using Robust.Shared.Configuration;
|
using Robust.Shared.Configuration;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
@@ -23,7 +18,7 @@ using Robust.Shared.Reflection;
|
|||||||
|
|
||||||
namespace Content.Server.Administration.Logs;
|
namespace Content.Server.Administration.Logs;
|
||||||
|
|
||||||
public class AdminLogSystem : SharedAdminLogSystem
|
public partial class AdminLogSystem : SharedAdminLogSystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly IConfigurationManager _configuration = default!;
|
[Dependency] private readonly IConfigurationManager _configuration = default!;
|
||||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||||
@@ -52,11 +47,8 @@ public class AdminLogSystem : SharedAdminLogSystem
|
|||||||
"admin_logs_sent",
|
"admin_logs_sent",
|
||||||
"Amount of logs sent to the database in a round.");
|
"Amount of logs sent to the database in a round.");
|
||||||
|
|
||||||
private static readonly JsonNamingPolicy NamingPolicy = JsonNamingPolicy.CamelCase;
|
|
||||||
|
|
||||||
// Init only
|
// Init only
|
||||||
private ISawmill _sawmill = default!;
|
private ISawmill _sawmill = default!;
|
||||||
private JsonSerializerOptions _jsonOptions = default!;
|
|
||||||
|
|
||||||
// CVars
|
// CVars
|
||||||
private bool _metricsEnabled;
|
private bool _metricsEnabled;
|
||||||
@@ -74,19 +66,8 @@ public class AdminLogSystem : SharedAdminLogSystem
|
|||||||
base.Initialize();
|
base.Initialize();
|
||||||
|
|
||||||
_sawmill = _logManager.GetSawmill(SawmillId);
|
_sawmill = _logManager.GetSawmill(SawmillId);
|
||||||
_jsonOptions = new JsonSerializerOptions
|
|
||||||
{
|
|
||||||
PropertyNamingPolicy = NamingPolicy
|
|
||||||
};
|
|
||||||
|
|
||||||
foreach (var converter in _reflection.FindTypesWithAttribute<AdminLogConverterAttribute>())
|
InitializeJson();
|
||||||
{
|
|
||||||
var instance = _typeFactory.CreateInstance<JsonConverter>(converter);
|
|
||||||
_jsonOptions.Converters.Add(instance);
|
|
||||||
}
|
|
||||||
|
|
||||||
var converterNames = _jsonOptions.Converters.Select(converter => converter.GetType().Name);
|
|
||||||
_sawmill.Info($"Admin log converters found: {string.Join(" ", converterNames)}");
|
|
||||||
|
|
||||||
_configuration.OnValueChanged(CVars.MetricsEnabled,
|
_configuration.OnValueChanged(CVars.MetricsEnabled,
|
||||||
value => _metricsEnabled = value, true);
|
value => _metricsEnabled = value, true);
|
||||||
@@ -171,48 +152,6 @@ public class AdminLogSystem : SharedAdminLogSystem
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public (JsonDocument json, List<Guid> players, List<(int id, string? name)> entities) ToJson(
|
|
||||||
Dictionary<string, object?> properties)
|
|
||||||
{
|
|
||||||
var entities = new List<(int id, string? name)>();
|
|
||||||
var players = new List<Guid>();
|
|
||||||
var parsed = new Dictionary<string, object?>();
|
|
||||||
|
|
||||||
foreach (var key in properties.Keys)
|
|
||||||
{
|
|
||||||
var value = properties[key];
|
|
||||||
var parsedKey = NamingPolicy.ConvertName(key);
|
|
||||||
parsed.Add(parsedKey, value);
|
|
||||||
|
|
||||||
EntityUid? entityId = properties[key] switch
|
|
||||||
{
|
|
||||||
EntityUid id => id,
|
|
||||||
IEntity entity => entity.Uid,
|
|
||||||
IPlayerSession {AttachedEntityUid: { }} session => session.AttachedEntityUid.Value,
|
|
||||||
IComponent component => component.OwnerUid,
|
|
||||||
_ => null
|
|
||||||
};
|
|
||||||
|
|
||||||
if (entityId is not { } uid)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
var entityName = _entityManager.TryGetEntity(uid, out var resolvedEntity)
|
|
||||||
? resolvedEntity.Name
|
|
||||||
: null;
|
|
||||||
|
|
||||||
entities.Add(((int) uid, entityName));
|
|
||||||
|
|
||||||
if (_entityManager.TryGetComponent(uid, out ActorComponent? actor))
|
|
||||||
{
|
|
||||||
players.Add(actor.PlayerSession.UserId.UserId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (JsonSerializer.SerializeToDocument(parsed, _jsonOptions), players, entities);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void Add(LogType type, LogImpact impact, string message, JsonDocument json, List<Guid> players, List<(int id, string? name)> entities)
|
private async void Add(LogType type, LogImpact impact, string message, JsonDocument json, List<Guid> players, List<(int id, string? name)> entities)
|
||||||
{
|
{
|
||||||
var log = new AdminLog
|
var log = new AdminLog
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
using System.Text.Json;
|
||||||
|
using Robust.Server.Player;
|
||||||
|
|
||||||
|
namespace Content.Server.Administration.Logs.Converters;
|
||||||
|
|
||||||
|
[AdminLogConverter]
|
||||||
|
public class PlayerSessionConverter : AdminLogConverter<SerializablePlayer>
|
||||||
|
{
|
||||||
|
public override void Write(Utf8JsonWriter writer, SerializablePlayer value, JsonSerializerOptions options)
|
||||||
|
{
|
||||||
|
writer.WriteStartObject();
|
||||||
|
|
||||||
|
if (value.Player.AttachedEntity != null)
|
||||||
|
{
|
||||||
|
writer.WriteNumber("id", (int) value.Player.AttachedEntity.Uid);
|
||||||
|
writer.WriteString("name", value.Player.AttachedEntity.Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.WriteString("player", value.Player.UserId.UserId);
|
||||||
|
|
||||||
|
writer.WriteEndObject();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public readonly struct SerializablePlayer
|
||||||
|
{
|
||||||
|
public readonly IPlayerSession Player;
|
||||||
|
|
||||||
|
public SerializablePlayer(IPlayerSession player)
|
||||||
|
{
|
||||||
|
Player = player;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,7 +10,7 @@ public enum LogType
|
|||||||
Slip = 4,
|
Slip = 4,
|
||||||
EventAnnounced = 5,
|
EventAnnounced = 5,
|
||||||
EventStarted = 6,
|
EventStarted = 6,
|
||||||
EventRan = 6,
|
EventRan = 16,
|
||||||
EventStopped = 7,
|
EventStopped = 7,
|
||||||
ShuttleCalled = 8,
|
ShuttleCalled = 8,
|
||||||
ShuttleRecalled = 9,
|
ShuttleRecalled = 9,
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ namespace Content.Shared.Slippery
|
|||||||
|
|
||||||
PlaySound(component);
|
PlaySound(component);
|
||||||
|
|
||||||
_adminLog.Add(LogType.Slip, $"{component.Owner} slipped on collision with {otherBody.Owner}");
|
_adminLog.Add(LogType.Slip, LogImpact.Low, $"{component.Owner} slipped on collision with {otherBody.Owner}");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user