diff --git a/Content.Server/Administration/Logs/AdminLogManager.Json.cs b/Content.Server/Administration/Logs/AdminLogManager.Json.cs index d4026545ee..43a1e0b8b5 100644 --- a/Content.Server/Administration/Logs/AdminLogManager.Json.cs +++ b/Content.Server/Administration/Logs/AdminLogManager.Json.cs @@ -5,6 +5,7 @@ using Content.Server.Administration.Logs.Converters; using Content.Server.Database; using Robust.Server.GameObjects; using Robust.Server.Player; +using Robust.Shared.Map; namespace Content.Server.Administration.Logs; @@ -46,6 +47,7 @@ public sealed partial class AdminLogManager value = value switch { IPlayerSession player => new SerializablePlayer(player), + EntityCoordinates entityCoordinates => new SerializableEntityCoordinates(_entityManager, entityCoordinates), _ => value }; diff --git a/Content.Server/Administration/Logs/Converters/EntityCoordinatesConverter.cs b/Content.Server/Administration/Logs/Converters/EntityCoordinatesConverter.cs new file mode 100644 index 0000000000..0384e06956 --- /dev/null +++ b/Content.Server/Administration/Logs/Converters/EntityCoordinatesConverter.cs @@ -0,0 +1,77 @@ +using System.Text.Json; +using Content.Server.Station.Components; +using Robust.Shared.Map; +using Robust.Shared.Map.Components; + +namespace Content.Server.Administration.Logs.Converters; + +[AdminLogConverter] +public sealed class EntityCoordinatesConverter : AdminLogConverter +{ + // System.Text.Json actually keeps hold of your JsonSerializerOption instances in a cache on .NET 7. + // Use a weak reference to avoid holding server instances live too long in integration tests. + private WeakReference _entityManager = default!; + + public override void Init(IDependencyCollection dependencies) + { + _entityManager = new WeakReference(dependencies.Resolve()); + } + + public void Write(Utf8JsonWriter writer, SerializableEntityCoordinates value, JsonSerializerOptions options, IEntityManager entities) + { + writer.WriteStartObject(); + WriteEntityInfo(writer, value.EntityUid, entities, "parent"); + writer.WriteNumber("x", value.X); + writer.WriteNumber("y", value.Y); + if (value.MapUid.HasValue) + { + WriteEntityInfo(writer, value.MapUid.Value, entities, "map"); + } + writer.WriteEndObject(); + } + + private static void WriteEntityInfo(Utf8JsonWriter writer, EntityUid value, IEntityManager entities, string rootName) + { + writer.WriteStartObject(rootName); + writer.WriteNumber("uid", value.GetHashCode()); + if (entities.TryGetComponent(value, out MetaDataComponent? metaData)) + { + writer.WriteString("name", metaData.EntityName); + } + if (entities.TryGetComponent(value, out MapComponent? mapComponent)) + { + writer.WriteNumber("mapId", mapComponent.MapId.GetHashCode()); + writer.WriteBoolean("mapPaused", mapComponent.MapPaused); + } + if (entities.TryGetComponent(value, out StationMemberComponent? stationMemberComponent)) + { + WriteEntityInfo(writer, stationMemberComponent.Station, entities, "stationMember"); + } + + writer.WriteEndObject(); + } + + public override void Write(Utf8JsonWriter writer, SerializableEntityCoordinates value, JsonSerializerOptions options) + { + if (!_entityManager.TryGetTarget(out var entityManager)) + throw new InvalidOperationException("EntityManager got garbage collected!"); + + Write(writer, value, options, entityManager); + } +} + +public readonly struct SerializableEntityCoordinates +{ + public readonly EntityUid EntityUid; + public readonly float X; + public readonly float Y; + public readonly EntityUid? MapUid; + + public SerializableEntityCoordinates(IEntityManager entityManager, EntityCoordinates coordinates) + { + EntityUid = coordinates.EntityId; + X = coordinates.X; + Y = coordinates.Y; + MapUid = coordinates.GetMapUid(entityManager); + } +} diff --git a/Content.Server/Administration/Systems/AdminTestArenaSystem.cs b/Content.Server/Administration/Systems/AdminTestArenaSystem.cs index 07fc628bce..e65acf571c 100644 --- a/Content.Server/Administration/Systems/AdminTestArenaSystem.cs +++ b/Content.Server/Administration/Systems/AdminTestArenaSystem.cs @@ -13,6 +13,7 @@ public sealed class AdminTestArenaSystem : EntitySystem { [Dependency] private readonly IMapManager _mapManager = default!; [Dependency] private readonly MapLoaderSystem _map = default!; + [Dependency] private readonly MetaDataSystem _metaDataSystem = default!; public const string ArenaMapPath = "/Maps/Test/admin_test_arena.yml"; @@ -35,8 +36,17 @@ public sealed class AdminTestArenaSystem : EntitySystem } ArenaMap[admin.UserId] = _mapManager.GetMapEntityId(_mapManager.CreateMap()); + _metaDataSystem.SetEntityName(ArenaMap[admin.UserId], $"ATAM-{admin.Name}"); var grids = _map.LoadMap(Comp(ArenaMap[admin.UserId]).MapId, ArenaMapPath); - ArenaGrid[admin.UserId] = grids.Count == 0 ? null : grids[0]; + if (grids.Count != 0) + { + _metaDataSystem.SetEntityName(grids[0], $"ATAG-{admin.Name}"); + ArenaGrid[admin.UserId] = grids[0]; + } + else + { + ArenaGrid[admin.UserId] = null; + } return (ArenaMap[admin.UserId], ArenaGrid[admin.UserId]); }