"New player" admin logging improvements (#35961)

* Initial commit

* Adjust a whoooole bunch of logs

* Also spears

* Track going crit

* Review fix

* Review fixes
This commit is contained in:
SlamBamActionman
2025-03-20 20:56:51 +01:00
committed by GitHub
parent 07a8a02522
commit 43d08100b9
47 changed files with 249 additions and 97 deletions

View File

@@ -241,7 +241,7 @@ public sealed class AccessOverriderSystem : SharedAccessOverriderSystem
var addedTags = newAccessList.Except(oldTags).Select(tag => "+" + tag).ToList();
var removedTags = oldTags.Except(newAccessList).Select(tag => "-" + tag).ToList();
_adminLogger.Add(LogType.Action, LogImpact.Medium,
_adminLogger.Add(LogType.Action, LogImpact.High,
$"{ToPrettyString(player):player} has modified {ToPrettyString(accessReaderEnt.Value):entity} with the following allowed access level holders: [{string.Join(", ", addedTags.Union(removedTags))}] [{string.Join(", ", newAccessList)}]");
accessReaderEnt.Value.Comp.AccessLists = ConvertAccessListToHashSet(newAccessList);

View File

@@ -168,7 +168,7 @@ public sealed class IdCardConsoleSystem : SharedIdCardConsoleSystem
/*TODO: ECS SharedIdCardConsoleComponent and then log on card ejection, together with the save.
This current implementation is pretty shit as it logs 27 entries (27 lines) if someone decides to give themselves AA*/
_adminLogger.Add(LogType.Action, LogImpact.Medium,
_adminLogger.Add(LogType.Action, LogImpact.High,
$"{ToPrettyString(player):player} has modified {ToPrettyString(targetId):entity} with the following accesses: [{string.Join(", ", addedTags.Union(removedTags))}] [{string.Join(", ", newAccessList)}]");
}

View File

@@ -88,7 +88,7 @@ public sealed class IdCardSystem : SharedIdCardSystem
access.Tags.Add(random.ID);
Dirty(uid, access);
_adminLogger.Add(LogType.Action, LogImpact.Medium,
_adminLogger.Add(LogType.Action, LogImpact.High,
$"{ToPrettyString(args.Microwave)} added {random.ID} access to {ToPrettyString(uid):entity}");
}

View File

@@ -180,7 +180,7 @@ public sealed class ChangeCvarCommand : IConsoleCommand
var oldValue = _configurationManager.GetCVar<object>(cvar);
_configurationManager.SetCVar(cvar, parsed);
_adminLogManager.Add(LogType.AdminCommands,
LogImpact.High,
LogImpact.Extreme,
$"{shell.Player!.Name} ({shell.Player!.UserId}) changed CVAR {cvar} from {oldValue.ToString()} to {parsed.ToString()}"
);

View File

@@ -6,10 +6,14 @@ using Content.Server.Database;
using Content.Server.GameTicking;
using Content.Shared.Administration.Logs;
using Content.Shared.CCVar;
using Content.Shared.Chat;
using Content.Shared.Database;
using Content.Shared.Players.PlayTimeTracking;
using Prometheus;
using Robust.Shared;
using Robust.Shared.Configuration;
using Robust.Shared.Network;
using Robust.Shared.Player;
using Robust.Shared.Reflection;
using Robust.Shared.Timing;
@@ -25,6 +29,9 @@ public sealed partial class AdminLogManager : SharedAdminLogManager, IAdminLogMa
[Dependency] private readonly IDynamicTypeFactory _typeFactory = default!;
[Dependency] private readonly IReflectionManager _reflection = default!;
[Dependency] private readonly IDependencyCollection _dependencies = default!;
[Dependency] private readonly ISharedPlayerManager _player = default!;
[Dependency] private readonly ISharedPlaytimeManager _playtime = default!;
[Dependency] private readonly ISharedChatManager _chat = default!;
public const string SawmillId = "admin.logs";
@@ -66,6 +73,7 @@ public sealed partial class AdminLogManager : SharedAdminLogManager, IAdminLogMa
private int _queueMax;
private int _preRoundQueueMax;
private int _dropThreshold;
private int _highImpactLogPlaytime;
// Per update
private TimeSpan _nextUpdateTime;
@@ -100,6 +108,8 @@ public sealed partial class AdminLogManager : SharedAdminLogManager, IAdminLogMa
value => _preRoundQueueMax = value, true);
_configuration.OnValueChanged(CCVars.AdminLogsDropThreshold,
value => _dropThreshold = value, true);
_configuration.OnValueChanged(CCVars.AdminLogsHighLogPlaytime,
value => _highImpactLogPlaytime = value, true);
if (_metricsEnabled)
{
@@ -309,6 +319,21 @@ public sealed partial class AdminLogManager : SharedAdminLogManager, IAdminLogMa
};
log.Players.Add(player);
if (impact == LogImpact.Extreme) // Always chat-notify Extreme logs
_chat.SendAdminAlert(message);
if (impact == LogImpact.High) // Only chat-notify High logs if the player is below a threshold playtime
{
if (_highImpactLogPlaytime >= 0 && _player.TryGetSessionById(new NetUserId(id), out var session))
{
var playtimes = _playtime.GetPlayTimes(session);
if (playtimes.TryGetValue(PlayTimeTrackingShared.TrackerOverall, out var overallTime) &&
overallTime <= TimeSpan.FromHours(_highImpactLogPlaytime))
{
_chat.SendAdminAlert(message);
}
}
}
}
if (preRound)

View File

@@ -240,7 +240,7 @@ public sealed class AmeControllerSystem : EntitySystem
return;
var humanReadableState = value ? "Inject" : "Not inject";
_adminLogger.Add(LogType.Action, LogImpact.Extreme, $"{EntityManager.ToPrettyString(user.Value):player} has set the AME to {humanReadableState}");
_adminLogger.Add(LogType.Action, LogImpact.Medium, $"{EntityManager.ToPrettyString(user.Value):player} has set the AME to {humanReadableState}");
}
public void ToggleInjecting(EntityUid uid, EntityUid? user = null, AmeControllerComponent? controller = null)
@@ -267,27 +267,15 @@ public sealed class AmeControllerSystem : EntitySystem
return;
var humanReadableState = controller.Injecting ? "Inject" : "Not inject";
_adminLogger.Add(LogType.Action, LogImpact.Extreme, $"{EntityManager.ToPrettyString(user.Value):player} has set the AME to inject {controller.InjectionAmount} while set to {humanReadableState}");
/* This needs to be information which an admin is very likely to want to be informed about in order to be an admin alert or have a sound notification.
At the time of editing, players regularly "overclock" the AME and those cases require no admin attention.
// Admin alert
var safeLimit = int.MaxValue;
if (TryGetAMENodeGroup(uid, out var group))
safeLimit = group.CoreCount * 4;
if (oldValue <= safeLimit && value > safeLimit)
{
if (_gameTiming.CurTime > controller.EffectCooldown)
{
_chatManager.SendAdminAlert(user.Value, $"increased AME over safe limit to {controller.InjectionAmount}");
_audioSystem.PlayGlobal("/Audio/Misc/adminlarm.ogg",
Filter.Empty().AddPlayers(_adminManager.ActiveAdmins), false, AudioParams.Default.WithVolume(-8f));
controller.EffectCooldown = _gameTiming.CurTime + controller.CooldownDuration;
}
}
*/
var logImpact = (oldValue <= safeLimit && value > safeLimit) ? LogImpact.Extreme : LogImpact.Medium;
_adminLogger.Add(LogType.Action, logImpact, $"{EntityManager.ToPrettyString(user.Value):player} has set the AME to inject {controller.InjectionAmount} while set to {humanReadableState}");
}
public void AdjustInjectionAmount(EntityUid uid, int delta, EntityUid? user = null, AmeControllerComponent? controller = null)

View File

@@ -116,7 +116,7 @@ public sealed class InnerBodyAnomalySystem : SharedInnerBodyAnomalySystem
_popup.PopupEntity(message, ent, ent, PopupType.MediumCaution);
_adminLog.Add(LogType.Anomaly,LogImpact.Extreme,$"{ToPrettyString(ent)} became anomaly host.");
_adminLog.Add(LogType.Anomaly,LogImpact.Medium,$"{ToPrettyString(ent)} became anomaly host.");
}
Dirty(ent);
}

View File

@@ -1,6 +1,7 @@
using Content.Server.Botany.Components;
using Content.Server.Botany.Systems;
using Content.Shared.Atmos;
using Content.Shared.Database;
using Content.Shared.EntityEffects;
using Content.Shared.Random;
using Robust.Shared.Audio;
@@ -243,6 +244,18 @@ public partial class SeedData
[DataField(customTypeSerializer: typeof(PrototypeIdListSerializer<SeedPrototype>))]
public List<string> MutationPrototypes = new();
/// <summary>
/// Log impact for when the seed is planted.
/// </summary>
[DataField]
public LogImpact? PlantLogImpact = null;
/// <summary>
/// Log impact for when the seed is harvested.
/// </summary>
[DataField]
public LogImpact? HarvestLogImpact = null;
public SeedData Clone()
{
DebugTools.Assert(!Immutable, "There should be no need to clone an immutable seed.");

View File

@@ -14,6 +14,8 @@ using Robust.Shared.Prototypes;
using Robust.Shared.Random;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Content.Shared.Administration.Logs;
using Content.Shared.Database;
namespace Content.Server.Botany.Systems;
@@ -27,6 +29,7 @@ public sealed partial class BotanySystem : EntitySystem
[Dependency] private readonly SharedSolutionContainerSystem _solutionContainerSystem = default!;
[Dependency] private readonly MetaDataSystem _metaData = default!;
[Dependency] private readonly RandomHelperSystem _randomHelper = default!;
[Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
public override void Initialize()
{
@@ -116,7 +119,12 @@ public sealed partial class BotanySystem : EntitySystem
{
if (position.IsValid(EntityManager) &&
proto.ProductPrototypes.Count > 0)
{
if (proto.HarvestLogImpact != null)
_adminLogger.Add(LogType.Botany, proto.HarvestLogImpact.Value, $"Auto-harvested {Loc.GetString(proto.Name):seed} at Pos:{position}.");
return GenerateProduct(proto, position, yieldMod);
}
return Enumerable.Empty<EntityUid>();
}
@@ -131,6 +139,10 @@ public sealed partial class BotanySystem : EntitySystem
var name = Loc.GetString(proto.DisplayName);
_popupSystem.PopupCursor(Loc.GetString("botany-harvest-success-message", ("name", name)), user, PopupType.Medium);
if (proto.HarvestLogImpact != null)
_adminLogger.Add(LogType.Botany, proto.HarvestLogImpact.Value, $"{ToPrettyString(user):player} harvested {Loc.GetString(proto.Name):seed} at Pos:{Transform(user).Coordinates}.");
return GenerateProduct(proto, Transform(user).Coordinates, yieldMod);
}

View File

@@ -23,7 +23,9 @@ using Robust.Shared.Prototypes;
using Robust.Shared.Random;
using Robust.Shared.Timing;
using Content.Server.Labels.Components;
using Content.Shared.Administration.Logs;
using Content.Shared.Containers.ItemSlots;
using Content.Shared.Database;
namespace Content.Server.Botany.Systems;
@@ -42,6 +44,7 @@ public sealed class PlantHolderSystem : EntitySystem
[Dependency] private readonly RandomHelperSystem _randomHelper = default!;
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly ItemSlotsSystem _itemSlots = default!;
[Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
public const float HydroponicsSpeedMultiplier = 1f;
@@ -188,6 +191,9 @@ public sealed class PlantHolderSystem : EntitySystem
CheckLevelSanity(uid, component);
UpdateSprite(uid, component);
if (seed.PlantLogImpact != null)
_adminLogger.Add(LogType.Botany, seed.PlantLogImpact.Value, $"{ToPrettyString(args.User):player} planted {Loc.GetString(seed.Name):seed} at Pos:{Transform(uid).Coordinates}.");
return;
}

View File

@@ -82,7 +82,7 @@ public sealed class CursedMaskSystem : SharedCursedMaskSystem
{
_mind.TransferTo(ent.Comp.StolenMind.Value, args.Wearer);
_adminLog.Add(LogType.Action,
LogImpact.Extreme,
LogImpact.Medium,
$"{ToPrettyString(args.Wearer):player} was restored to their body after the removal of {ToPrettyString(ent):entity}.");
ent.Comp.StolenMind = null;
}

View File

@@ -312,7 +312,7 @@ namespace Content.Server.Communications
}
_roundEndSystem.RequestRoundEnd(uid);
_adminLogger.Add(LogType.Action, LogImpact.Extreme, $"{ToPrettyString(mob):player} has called the shuttle.");
_adminLogger.Add(LogType.Action, LogImpact.High, $"{ToPrettyString(mob):player} has called the shuttle.");
}
private void OnRecallShuttleMessage(EntityUid uid, CommunicationsConsoleComponent comp, CommunicationsConsoleRecallEmergencyShuttleMessage message)
@@ -327,7 +327,7 @@ namespace Content.Server.Communications
}
_roundEndSystem.CancelRoundEndCountdown(uid);
_adminLogger.Add(LogType.Action, LogImpact.Extreme, $"{ToPrettyString(message.Actor):player} has recalled the shuttle.");
_adminLogger.Add(LogType.Action, LogImpact.High, $"{ToPrettyString(message.Actor):player} has recalled the shuttle.");
}
}

View File

@@ -25,7 +25,7 @@ public sealed partial class AdminLog : IGraphAction
var logManager = IoCManager.Resolve<IAdminLogManager>();
if (userUid.HasValue)
logManager.Add(LogType, Impact, $"{Message} - Entity: {entityManager.ToPrettyString(uid):entity}, User: {entityManager.ToPrettyString(userUid.Value):user}");
logManager.Add(LogType, Impact, $"{Message} - Entity: {entityManager.ToPrettyString(uid):entity}, User: {entityManager.ToPrettyString(userUid.Value):player}");
else
logManager.Add(LogType, Impact, $"{Message} - Entity: {entityManager.ToPrettyString(uid):entity}");
}

View File

@@ -225,12 +225,12 @@ namespace Content.Server.Decals
if (eventArgs.SenderSession.AttachedEntity != null)
{
_adminLogger.Add(LogType.CrayonDraw, LogImpact.High,
_adminLogger.Add(LogType.CrayonDraw, LogImpact.Low,
$"{ToPrettyString(eventArgs.SenderSession.AttachedEntity.Value):actor} drew a {ev.Decal.Color} {ev.Decal.Id} at {ev.Coordinates}");
}
else
{
_adminLogger.Add(LogType.CrayonDraw, LogImpact.High,
_adminLogger.Add(LogType.CrayonDraw, LogImpact.Low,
$"{eventArgs.SenderSession.Name} drew a {ev.Decal.Color} {ev.Decal.Id} at {ev.Coordinates}");
}
}
@@ -259,12 +259,12 @@ namespace Content.Server.Decals
{
if (eventArgs.SenderSession.AttachedEntity != null)
{
_adminLogger.Add(LogType.CrayonDraw, LogImpact.High,
_adminLogger.Add(LogType.CrayonDraw, LogImpact.Low,
$"{ToPrettyString(eventArgs.SenderSession.AttachedEntity.Value):actor} removed a {decal.Color} {decal.Id} at {ev.Coordinates}");
}
else
{
_adminLogger.Add(LogType.CrayonDraw, LogImpact.High,
_adminLogger.Add(LogType.CrayonDraw, LogImpact.Low,
$"{eventArgs.SenderSession.Name} removed a {decal.Color} {decal.Id} at {ev.Coordinates}");
}

View File

@@ -21,6 +21,8 @@ using Robust.Shared.Containers;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
using System.Linq;
using Content.Shared.Humanoid;
using Robust.Shared.Player;
namespace Content.Server.Destructible
{
@@ -61,9 +63,12 @@ namespace Content.Server.Destructible
{
RaiseLocalEvent(uid, new DamageThresholdReached(component, threshold), true);
var logImpact = LogImpact.Low;
// Convert behaviors into string for logs
var triggeredBehaviors = string.Join(", ", threshold.Behaviors.Select(b =>
{
if (logImpact <= b.Impact)
logImpact = b.Impact;
if (b is DoActsBehavior doActsBehavior)
{
return $"{b.GetType().Name}:{doActsBehavior.Acts.ToString()}";
@@ -71,14 +76,20 @@ namespace Content.Server.Destructible
return b.GetType().Name;
}));
// If it doesn't have a humanoid component, it's probably not particularly notable?
if (logImpact > LogImpact.Medium && !HasComp<HumanoidAppearanceComponent>(uid))
logImpact = LogImpact.Medium;
if (args.Origin != null)
{
_adminLogger.Add(LogType.Damaged, LogImpact.Medium,
_adminLogger.Add(LogType.Damaged,
logImpact,
$"{ToPrettyString(args.Origin.Value):actor} caused {ToPrettyString(uid):subject} to trigger [{triggeredBehaviors}]");
}
else
{
_adminLogger.Add(LogType.Damaged, LogImpact.Medium,
_adminLogger.Add(LogType.Damaged,
logImpact,
$"Unknown damage source caused {ToPrettyString(uid):subject} to trigger [{triggeredBehaviors}]");
}

View File

@@ -1,4 +1,5 @@
using Content.Shared.Body.Components;
using Content.Shared.Database;
using JetBrains.Annotations;
namespace Content.Server.Destructible.Thresholds.Behaviors
@@ -9,6 +10,8 @@ namespace Content.Server.Destructible.Thresholds.Behaviors
{
[DataField("recursive")] private bool _recursive = true;
public LogImpact Impact => LogImpact.Extreme;
public void Execute(EntityUid owner, DestructibleSystem system, EntityUid? cause = null)
{
if (system.EntityManager.TryGetComponent(owner, out BodyComponent? body))

View File

@@ -1,7 +1,11 @@
namespace Content.Server.Destructible.Thresholds.Behaviors
using Content.Shared.Database;
namespace Content.Server.Destructible.Thresholds.Behaviors
{
public interface IThresholdBehavior
{
public LogImpact Impact => LogImpact.Low;
/// <summary>
/// Executes this behavior.
/// </summary>

View File

@@ -256,11 +256,12 @@ public sealed partial class ExplosionSystem : SharedExplosionSystem
}
else
{
_adminLogger.Add(LogType.Explosion, LogImpact.High,
$"{ToPrettyString(user.Value):user} caused {ToPrettyString(uid):entity} to explode ({typeId}) at Pos:{(posFound ? $"{gridPos:coordinates}" : "[Grid or Map not found]")} with intensity {totalIntensity} slope {slope}");
var alertMinExplosionIntensity = _cfg.GetCVar(CCVars.AdminAlertExplosionMinIntensity);
if (alertMinExplosionIntensity > -1 && totalIntensity >= alertMinExplosionIntensity)
_chat.SendAdminAlert(user.Value, $"caused {ToPrettyString(uid)} to explode ({typeId}:{totalIntensity}) at Pos:{(posFound ? $"{gridPos:coordinates}" : "[Grid or Map not found]")}");
var logImpact = (alertMinExplosionIntensity > -1 && totalIntensity >= alertMinExplosionIntensity)
? LogImpact.Extreme
: LogImpact.High;
_adminLogger.Add(LogType.Explosion, logImpact,
$"{ToPrettyString(user.Value):user} caused {ToPrettyString(uid):entity} to explode ({typeId}) at Pos:{(posFound ? $"{gridPos:coordinates}" : "[Grid or Map not found]")} with intensity {totalIntensity} slope {slope}");
}
}

View File

@@ -50,7 +50,7 @@ namespace Content.Server.Explosion.EntitySystems
if (!string.IsNullOrWhiteSpace(component.KeyPhrase) && message.Contains(component.KeyPhrase, StringComparison.InvariantCultureIgnoreCase))
{
_adminLogger.Add(LogType.Trigger, LogImpact.High,
_adminLogger.Add(LogType.Trigger, LogImpact.Medium,
$"A voice-trigger on {ToPrettyString(ent):entity} was triggered by {ToPrettyString(args.Source):speaker} speaking the key-phrase {component.KeyPhrase}.");
Trigger(ent, args.Source);

View File

@@ -7,6 +7,7 @@ using Content.Shared.Damage;
using Content.Shared.Database;
using Content.Shared.DoAfter;
using Content.Shared.DragDrop;
using Content.Shared.Humanoid;
using Content.Shared.IdentityManagement;
using Content.Shared.Interaction;
using Content.Shared.Interaction.Events;
@@ -143,7 +144,11 @@ namespace Content.Server.Kitchen.EntitySystems
if (!Resolve(uid, ref component) || !Resolve(victimUid, ref butcherable))
return;
_logger.Add(LogType.Gib, LogImpact.Extreme, $"{ToPrettyString(userUid):user} kitchen spiked {ToPrettyString(victimUid):target}");
var logImpact = LogImpact.Medium;
if (HasComp<HumanoidAppearanceComponent>(victimUid))
logImpact = LogImpact.Extreme;
_logger.Add(LogType.Gib, logImpact, $"{ToPrettyString(userUid):user} kitchen spiked {ToPrettyString(victimUid):target}");
// TODO VERY SUS
component.PrototypesToSpawn = EntitySpawnCollection.GetSpawns(butcherable.SpawnedEntities, _random);

View File

@@ -24,6 +24,7 @@ using Robust.Shared.Player;
using Robust.Shared.Prototypes;
using Robust.Shared.Utility;
using System.Linq;
using Content.Shared.Humanoid;
namespace Content.Server.Materials;
@@ -186,7 +187,8 @@ public sealed class MaterialReclaimerSystem : SharedMaterialReclaimerSystem
if (CanGib(uid, item, component))
{
_adminLogger.Add(LogType.Gib, LogImpact.Extreme, $"{ToPrettyString(item):victim} was gibbed by {ToPrettyString(uid):entity} ");
var logImpact = HasComp<HumanoidAppearanceComponent>(item) ? LogImpact.Extreme : LogImpact.Medium;
_adminLogger.Add(LogType.Gib, logImpact, $"{ToPrettyString(item):victim} was gibbed by {ToPrettyString(uid):entity} ");
SpawnChemicalsFromComposition(uid, item, completion, false, component, xform);
_body.GibBody(item, true);
_appearance.SetData(uid, RecyclerVisuals.Bloody, true);

View File

@@ -182,7 +182,7 @@ namespace Content.Server.Medical.BiomassReclaimer
_throwing.TryThrow(args.Climber, direction, 0.5f);
return;
}
_adminLogger.Add(LogType.Action, LogImpact.Extreme, $"{ToPrettyString(args.Instigator):player} used a biomass reclaimer to gib {ToPrettyString(args.Climber):target} in {ToPrettyString(reclaimer):reclaimer}");
_adminLogger.Add(LogType.Action, LogImpact.High, $"{ToPrettyString(args.Instigator):player} used a biomass reclaimer to gib {ToPrettyString(args.Climber):target} in {ToPrettyString(reclaimer):reclaimer}");
StartProcessing(args.Climber, reclaimer);
}
@@ -195,7 +195,7 @@ namespace Content.Server.Medical.BiomassReclaimer
if (args.Args.Used == null || args.Args.Target == null || !HasComp<BiomassReclaimerComponent>(args.Args.Target.Value))
return;
_adminLogger.Add(LogType.Action, LogImpact.Extreme, $"{ToPrettyString(args.Args.User):player} used a biomass reclaimer to gib {ToPrettyString(args.Args.Target.Value):target} in {ToPrettyString(reclaimer):reclaimer}");
_adminLogger.Add(LogType.Action, LogImpact.High, $"{ToPrettyString(args.Args.User):player} used a biomass reclaimer to gib {ToPrettyString(args.Args.Target.Value):target} in {ToPrettyString(reclaimer):reclaimer}");
StartProcessing(args.Args.Used.Value, reclaimer);
args.Handled = true;

View File

@@ -35,7 +35,7 @@ public sealed class MeteorSystem : EntitySystem
{
threshold = mobThreshold.Value;
if (HasComp<ActorComponent>(args.OtherEntity))
_adminLog.Add(LogType.Action, LogImpact.Extreme, $"{ToPrettyString(args.OtherEntity):player} was struck by meteor {ToPrettyString(uid):ent} and killed instantly.");
_adminLog.Add(LogType.Action, LogImpact.High, $"{ToPrettyString(args.OtherEntity):player} was struck by meteor {ToPrettyString(uid):ent} and killed instantly.");
}
else if (_destructible.TryGetDestroyedAt(args.OtherEntity, out var destroyThreshold))
{

View File

@@ -87,7 +87,7 @@ public sealed class CrematoriumSystem : EntitySystem
Text = Loc.GetString("cremate-verb-get-data-text"),
// TODO VERB ICON add flame/burn symbol?
Act = () => TryCremate(uid, component, storage),
Impact = LogImpact.Medium // could be a body? or evidence? I dunno.
Impact = LogImpact.High // could be a body? or evidence? I dunno.
};
args.Verbs.Add(verb);
}

View File

@@ -195,7 +195,7 @@ public sealed class DrinkSystem : SharedDrinkSystem
_popup.PopupEntity(Loc.GetString("drink-component-force-feed", ("user", userName)), user, target);
// logging
_adminLogger.Add(LogType.ForceFeed, LogImpact.Medium, $"{ToPrettyString(user):user} is forcing {ToPrettyString(target):target} to drink {ToPrettyString(item):drink} {SharedSolutionContainerSystem.ToPrettyString(drinkSolution)}");
_adminLogger.Add(LogType.ForceFeed, LogImpact.High, $"{ToPrettyString(user):user} is forcing {ToPrettyString(target):target} to drink {ToPrettyString(item):drink} {SharedSolutionContainerSystem.ToPrettyString(drinkSolution)}");
}
else
{

View File

@@ -32,13 +32,13 @@ public sealed class PlacementLoggerSystem : EntitySystem
};
if (actorEntity != null)
_adminLogger.Add(logType, LogImpact.High,
_adminLogger.Add(logType, LogImpact.Medium,
$"{ToPrettyString(actorEntity.Value):actor} used placement system to {ev.PlacementEventAction.ToString().ToLower()} {ToPrettyString(ev.EditedEntity):subject} at {ev.Coordinates}");
else if (actor != null)
_adminLogger.Add(logType, LogImpact.High,
_adminLogger.Add(logType, LogImpact.Medium,
$"{actor:actor} used placement system to {ev.PlacementEventAction.ToString().ToLower()} {ToPrettyString(ev.EditedEntity):subject} at {ev.Coordinates}");
else
_adminLogger.Add(logType, LogImpact.High,
_adminLogger.Add(logType, LogImpact.Medium,
$"Placement system {ev.PlacementEventAction.ToString().ToLower()}ed {ToPrettyString(ev.EditedEntity):subject} at {ev.Coordinates}");
}
@@ -48,13 +48,13 @@ public sealed class PlacementLoggerSystem : EntitySystem
var actorEntity = actor?.AttachedEntity;
if (actorEntity != null)
_adminLogger.Add(LogType.Tile, LogImpact.High,
_adminLogger.Add(LogType.Tile, LogImpact.Medium,
$"{ToPrettyString(actorEntity.Value):actor} used placement system to set tile {_tileDefinitionManager[ev.TileType].Name} at {ev.Coordinates}");
else if (actor != null)
_adminLogger.Add(LogType.Tile, LogImpact.High,
_adminLogger.Add(LogType.Tile, LogImpact.Medium,
$"{actor} used placement system to set tile {_tileDefinitionManager[ev.TileType].Name} at {ev.Coordinates}");
else
_adminLogger.Add(LogType.Tile, LogImpact.High,
_adminLogger.Add(LogType.Tile, LogImpact.Medium,
$"Placement system set tile {_tileDefinitionManager[ev.TileType].Name} at {ev.Coordinates}");
}
}

View File

@@ -53,7 +53,7 @@ public sealed partial class CableSystem : EntitySystem
if (_electrocutionSystem.TryDoElectrifiedAct(uid, args.User))
return;
_adminLogger.Add(LogType.CableCut, LogImpact.Medium, $"The {ToPrettyString(uid)} at {xform.Coordinates} was cut by {ToPrettyString(args.User)}.");
_adminLogger.Add(LogType.CableCut, LogImpact.High, $"The {ToPrettyString(uid)} at {xform.Coordinates} was cut by {ToPrettyString(args.User)}.");
Spawn(cable.CableDroppedOnCutPrototype, xform.Coordinates);
QueueDel(uid);

View File

@@ -65,7 +65,7 @@ public sealed class ProjectileSystem : SharedProjectileSystem
}
_adminLogger.Add(LogType.BulletHit,
HasComp<ActorComponent>(target) ? LogImpact.Extreme : LogImpact.High,
LogImpact.Medium,
$"Projectile {ToPrettyString(uid):projectile} shot by {ToPrettyString(component.Shooter!.Value):user} hit {otherName:target} and dealt {modifiedDamage.GetTotal():damage} damage");
}

View File

@@ -136,7 +136,7 @@ public sealed class SpecialRespawnSystem : SharedSpecialRespawnSystem
private void Respawn(EntityUid oldEntity, string prototype, EntityCoordinates coords)
{
var entity = Spawn(prototype, coords);
_adminLog.Add(LogType.Respawn, LogImpact.High, $"{ToPrettyString(oldEntity)} was deleted and was respawned at {coords.ToMap(EntityManager, _transform)} as {ToPrettyString(entity)}");
_adminLog.Add(LogType.Respawn, LogImpact.Extreme, $"{ToPrettyString(oldEntity)} was deleted and was respawned at {coords.ToMap(EntityManager, _transform)} as {ToPrettyString(entity)}");
_chat.SendAdminAlert($"{MetaData(oldEntity).EntityName} was deleted and was respawned as {ToPrettyString(entity)}");
}

View File

@@ -372,7 +372,7 @@ public sealed partial class EmergencyShuttleSystem
{
if (EarlyLaunchAuthorized || !EmergencyShuttleArrived || _consoleAccumulator <= _authorizeTime) return false;
_logger.Add(LogType.EmergencyShuttle, LogImpact.Extreme, $"Emergency shuttle launch authorized");
_logger.Add(LogType.EmergencyShuttle, LogImpact.High, $"Emergency shuttle launch authorized");
_consoleAccumulator = _authorizeTime;
EarlyLaunchAuthorized = true;
RaiseLocalEvent(new EmergencyShuttleAuthorizedEvent());

View File

@@ -130,7 +130,7 @@ public sealed class EventHorizonSystem : SharedEventHorizonSystem
|| _tagSystem.HasTag(morsel, "HighRiskItem")
|| HasComp<ContainmentFieldGeneratorComponent>(morsel))
{
_adminLogger.Add(LogType.EntityDelete, LogImpact.Extreme, $"{ToPrettyString(morsel)} entered the event horizon of {ToPrettyString(hungry)} and was deleted");
_adminLogger.Add(LogType.EntityDelete, LogImpact.High, $"{ToPrettyString(morsel):player} entered the event horizon of {ToPrettyString(hungry)} and was deleted");
}
EntityManager.QueueDeleteEntity(morsel);

View File

@@ -95,7 +95,7 @@ public sealed class HandTeleporterSystem : EntitySystem
var timeout = EnsureComp<PortalTimeoutComponent>(user);
timeout.EnteredPortal = null;
component.FirstPortal = Spawn(component.FirstPortalPrototype, Transform(user).Coordinates);
_adminLogger.Add(LogType.EntitySpawn, LogImpact.Low, $"{ToPrettyString(user):player} opened {ToPrettyString(component.FirstPortal.Value)} at {Transform(component.FirstPortal.Value).Coordinates} using {ToPrettyString(uid)}");
_adminLogger.Add(LogType.EntitySpawn, LogImpact.High, $"{ToPrettyString(user):player} opened {ToPrettyString(component.FirstPortal.Value)} at {Transform(component.FirstPortal.Value).Coordinates} using {ToPrettyString(uid)}");
_audio.PlayPvs(component.NewPortalSound, uid);
}
else if (Deleted(component.SecondPortal))
@@ -113,7 +113,7 @@ public sealed class HandTeleporterSystem : EntitySystem
var timeout = EnsureComp<PortalTimeoutComponent>(user);
timeout.EnteredPortal = null;
component.SecondPortal = Spawn(component.SecondPortalPrototype, Transform(user).Coordinates);
_adminLogger.Add(LogType.EntitySpawn, LogImpact.Low, $"{ToPrettyString(user):player} opened {ToPrettyString(component.SecondPortal.Value)} at {Transform(component.SecondPortal.Value).Coordinates} linked to {ToPrettyString(component.FirstPortal!.Value)} using {ToPrettyString(uid)}");
_adminLogger.Add(LogType.EntitySpawn, LogImpact.High, $"{ToPrettyString(user):player} opened {ToPrettyString(component.SecondPortal.Value)} at {Transform(component.SecondPortal.Value).Coordinates} linked to {ToPrettyString(component.FirstPortal!.Value)} using {ToPrettyString(uid)}");
_link.TryLink(component.FirstPortal!.Value, component.SecondPortal.Value, true);
_audio.PlayPvs(component.NewPortalSound, uid);
}
@@ -132,7 +132,7 @@ public sealed class HandTeleporterSystem : EntitySystem
portalStrings += " and ";
portalStrings += ToPrettyString(component.SecondPortal);
if (portalStrings != "")
_adminLogger.Add(LogType.EntityDelete, LogImpact.Low, $"{ToPrettyString(user):player} closed {portalStrings} with {ToPrettyString(uid)}");
_adminLogger.Add(LogType.EntityDelete, LogImpact.High, $"{ToPrettyString(user):player} closed {portalStrings} with {ToPrettyString(uid)}");
// Clear both portals
if (!Deleted(component.FirstPortal))

View File

@@ -4,8 +4,8 @@
[Serializable]
public enum LogImpact : sbyte
{
Low = -1,
Medium = 0,
High = 1,
Extreme = 2 // Nar'Sie just dropped
Low = -1, // General logging
Medium = 0, // Has impact on the round but not necessary for admins to be notified of
High = 1, // Notable logs that come up in normal gameplay; new players causing these will pop up as admin alerts!
Extreme = 2 // Irreversible round-impacting logs admins should always be notified of, OR big admin actions!!
}

View File

@@ -459,4 +459,9 @@ public enum LogType
/// A player was selected or assigned antag status
/// </summary>
AntagSelection = 99,
/// <summary>
/// Logs related to botany, such as planting and harvesting crops
/// </summary>
Botany = 100,
}

View File

@@ -123,7 +123,7 @@ public abstract class SharedAnomalySystem : EntitySystem
if (HasComp<AnomalySupercriticalComponent>(uid))
return;
AdminLog.Add(LogType.Anomaly, LogImpact.Extreme, $"Anomaly {ToPrettyString(uid)} began to go supercritical.");
AdminLog.Add(LogType.Anomaly, LogImpact.High, $"Anomaly {ToPrettyString(uid)} began to go supercritical.");
if (_net.IsServer)
Log.Info($"Anomaly is going supercritical. Entity: {ToPrettyString(uid)}");

View File

@@ -39,4 +39,11 @@ public sealed partial class CCVars
public static readonly CVarDef<string> AdminLogsServerName =
CVarDef.Create("adminlogs.server_name", "unknown", CVar.SERVERONLY);
/// <summary>
/// Any session below this playtime will send an admin alert whenever they cause a LogImpact.High log.
/// Set to -1 to disable.
/// </summary>
public static readonly CVarDef<int> AdminLogsHighLogPlaytime =
CVarDef.Create("adminlogs.high_log_playtime", 5, CVar.SERVERONLY);
}

View File

@@ -361,7 +361,7 @@ namespace Content.Shared.Cuffs
("otherName", Identity.Name(target, EntityManager, user))), user, user);
_popup.PopupClient(Loc.GetString("handcuff-component-cuff-by-other-success-message",
("otherName", Identity.Name(user, EntityManager, target))), target, target);
_adminLog.Add(LogType.Action, LogImpact.Medium,
_adminLog.Add(LogType.Action, LogImpact.High,
$"{ToPrettyString(user):player} has cuffed {ToPrettyString(target):player}");
}
}
@@ -647,7 +647,7 @@ namespace Content.Shared.Cuffs
if (!_doAfter.TryStartDoAfter(doAfterEventArgs))
return;
_adminLog.Add(LogType.Action, LogImpact.Low, $"{ToPrettyString(user)} is trying to uncuff {ToPrettyString(target)}");
_adminLog.Add(LogType.Action, LogImpact.High, $"{ToPrettyString(user):player} is trying to uncuff {ToPrettyString(target):subject}");
var popupText = user == target
? "cuffable-component-start-uncuffing-self-observer"
@@ -726,12 +726,12 @@ namespace Content.Shared.Cuffs
{
_popup.PopupEntity(Loc.GetString("cuffable-component-remove-cuffs-by-other-success-message",
("otherName", Identity.Name(user.Value, EntityManager, user))), target, target);
_adminLog.Add(LogType.Action, LogImpact.Medium,
_adminLog.Add(LogType.Action, LogImpact.High,
$"{ToPrettyString(user):player} has successfully uncuffed {ToPrettyString(target):player}");
}
else
{
_adminLog.Add(LogType.Action, LogImpact.Medium,
_adminLog.Add(LogType.Action, LogImpact.High,
$"{ToPrettyString(user):player} has successfully uncuffed themselves");
}
}

View File

@@ -1,5 +1,7 @@
using Content.Shared.Database;
using Content.Shared.Humanoid;
using Content.Shared.Mobs.Components;
using Robust.Shared.Player;
namespace Content.Shared.Mobs.Systems;
@@ -110,8 +112,10 @@ public partial class MobStateSystem
var ev = new MobStateChangedEvent(target, component, oldState, newState, origin);
OnStateChanged(target, component, oldState, newState);
RaiseLocalEvent(target, ev, true);
_adminLogger.Add(LogType.Damaged, oldState == MobState.Alive ? LogImpact.Low : LogImpact.Medium,
$"{ToPrettyString(target):user} state changed from {oldState} to {newState}");
if (origin != null && HasComp<ActorComponent>(origin) && HasComp<ActorComponent>(target) && oldState < newState)
_adminLogger.Add(LogType.Damaged, LogImpact.High, $"{ToPrettyString(origin):player} caused {ToPrettyString(target):player} state to change from {oldState} to {newState}");
else
_adminLogger.Add(LogType.Damaged, oldState == MobState.Alive ? LogImpact.Low : LogImpact.Medium, $"{ToPrettyString(target):user} state changed from {oldState} to {newState}");
Dirty(target, component);
}

View File

@@ -251,14 +251,14 @@ public abstract class SharedRoleSystem : EntitySystem
else
{
var error = $"The Character Window of {_minds.MindOwnerLoggingString(comp)} potentially did not update immediately : session error";
_adminLogger.Add(LogType.Mind, LogImpact.High, $"{error}");
_adminLogger.Add(LogType.Mind, LogImpact.Medium, $"{error}");
}
if (comp.OwnedEntity is null)
{
Log.Error($"{ToPrettyString(mind)} does not have an OwnedEntity!");
_adminLogger.Add(LogType.Mind,
LogImpact.High,
LogImpact.Medium,
$"Role Type of {ToPrettyString(mind)} changed to {roleTypeId}");
return;
}

View File

@@ -339,7 +339,7 @@ public abstract class SharedStrippableSystem : EntitySystem
RaiseLocalEvent(item, new DroppedEvent(user), true); // Gas tank internals etc.
_handsSystem.PickupOrDrop(user, item, animateUser: stealth, animate: !stealth);
_adminLogger.Add(LogType.Stripping, LogImpact.Medium, $"{ToPrettyString(user):actor} has stripped the item {ToPrettyString(item):item} from {ToPrettyString(target):target}'s {slot} slot");
_adminLogger.Add(LogType.Stripping, LogImpact.High, $"{ToPrettyString(user):actor} has stripped the item {ToPrettyString(item):item} from {ToPrettyString(target):target}'s {slot} slot");
}
/// <summary>
@@ -544,7 +544,7 @@ public abstract class SharedStrippableSystem : EntitySystem
_handsSystem.TryDrop(target, item, checkActionBlocker: false, handsComp: target.Comp);
_handsSystem.PickupOrDrop(user, item, animateUser: stealth, animate: !stealth, handsComp: user.Comp);
_adminLogger.Add(LogType.Stripping, LogImpact.Medium, $"{ToPrettyString(user):actor} has stripped the item {ToPrettyString(item):item} from {ToPrettyString(target):target}'s hands");
_adminLogger.Add(LogType.Stripping, LogImpact.High, $"{ToPrettyString(user):actor} has stripped the item {ToPrettyString(item):item} from {ToPrettyString(target):target}'s hands");
// Hand update will trigger strippable update.
}

View File

@@ -49,7 +49,7 @@ chat-manager-dead-channel-name = DEAD
chat-manager-admin-channel-name = ADMIN
chat-manager-rate-limited = You are sending messages too quickly!
chat-manager-rate-limit-admin-announcement = Player { $player } breached chat rate limits. Watch them if this is a regular occurence.
chat-manager-rate-limit-admin-announcement = Rate limit warning: { $player }
## Speech verbs for chat

View File

@@ -622,6 +622,8 @@
noun: seeds-noun-seeds
displayName: seeds-killertomato-display-name
plantRsi: Objects/Specific/Hydroponics/tomatokiller.rsi
plantLogImpact: High
harvestLogImpact: High
packetPrototype: KillerTomatoSeeds
productPrototypes:
- MobTomatoKiller
@@ -1063,6 +1065,8 @@
displayName: seeds-deathnettle-display-name
plantRsi: Objects/Specific/Hydroponics/death_nettle.rsi
packetPrototype: DeathNettleSeeds
plantLogImpact: High
harvestLogImpact: High
productPrototypes:
- DeathNettle
lifespan: 25

View File

@@ -8,6 +8,9 @@
edges:
- to: MeatSpike
completed:
- !type:AdminLog # Needs a log for start of attempt in addition to the completion log
message: "Construction"
impact: High
- !type:SnapToGrid
southRotation: true
steps:

View File

@@ -6,6 +6,9 @@
edges:
- to: grille
completed:
- !type:AdminLog # Needs a log for start of attempt in addition to the completion log
message: "Construction"
impact: High
- !type:SnapToGrid
southRotation: true
steps:

View File

@@ -6,6 +6,10 @@
entity: ShardGlass
edges:
- to: icon
completed:
- !type:AdminLog
message: "Construction"
impact: High
steps:
- material: Cloth
amount: 1
@@ -20,6 +24,10 @@
- node: start
edges:
- to: icon
completed:
- !type:AdminLog
message: "Construction"
impact: High
steps:
- tag: GlassShard
name: glass shard
@@ -41,6 +49,10 @@
entity: ShardGlassReinforced
edges:
- to: icon
completed:
- !type:AdminLog
message: "Construction"
impact: High
steps:
- material: Cloth
amount: 1
@@ -55,6 +67,10 @@
- node: start
edges:
- to: icon
completed:
- !type:AdminLog
message: "Construction"
impact: High
steps:
- tag: ReinforcedGlassShard
name: reinforced glass shard
@@ -76,6 +92,10 @@
entity: ShardGlassPlasma
edges:
- to: icon
completed:
- !type:AdminLog
message: "Construction"
impact: High
steps:
- material: Cloth
amount: 1
@@ -90,6 +110,10 @@
- node: start
edges:
- to: icon
completed:
- !type:AdminLog
message: "Construction"
impact: High
steps:
- tag: PlasmaGlassShard
name: plasma glass shard
@@ -111,6 +135,10 @@
entity: ShardGlassUranium
edges:
- to: icon
completed:
- !type:AdminLog
message: "Construction"
impact: High
steps:
- material: Cloth
amount: 1
@@ -125,6 +153,10 @@
- node: start
edges:
- to: icon
completed:
- !type:AdminLog
message: "Construction"
impact: High
steps:
- tag: UraniumGlassShard
name: uranium glass shard

View File

@@ -5,6 +5,10 @@
- node: start
edges:
- to: spear
completed:
- !type:AdminLog # Needs a log for start of attempt in addition to the completion log
message: "Construction"
impact: High
steps:
- material: MetalRod
amount: 2
@@ -28,6 +32,10 @@
- node: start
edges:
- to: spear
completed:
- !type:AdminLog # Needs a log for start of attempt in addition to the completion log
message: "Construction"
impact: High
steps:
- material: MetalRod
amount: 2
@@ -51,6 +59,10 @@
- node: start
edges:
- to: spear
completed:
- !type:AdminLog # Needs a log for start of attempt in addition to the completion log
message: "Construction"
impact: High
steps:
- material: MetalRod
amount: 2
@@ -74,6 +86,10 @@
- node: start
edges:
- to: spear
completed:
- !type:AdminLog # Needs a log for start of attempt in addition to the completion log
message: "Construction"
impact: High
steps:
- material: MetalRod
amount: 2
@@ -97,6 +113,10 @@
- node: start
edges:
- to: spear
completed:
- !type:AdminLog # Needs a log for start of attempt in addition to the completion log
message: "Construction"
impact: High
steps:
- material: Bones
amount: 4

View File

@@ -23,6 +23,10 @@
- tool: Prying
doAfter: 1
- to: bat
completed:
- !type:AdminLog
message: "Construction"
impact: High
steps:
- tool: Slicing
doAfter: 4