diff --git a/Content.Client/Administration/UI/AdminRemarks/AdminMessageEui.cs b/Content.Client/Administration/UI/AdminRemarks/AdminMessageEui.cs
index 06eace118d..502c56a5a6 100644
--- a/Content.Client/Administration/UI/AdminRemarks/AdminMessageEui.cs
+++ b/Content.Client/Administration/UI/AdminRemarks/AdminMessageEui.cs
@@ -2,6 +2,7 @@
using Content.Shared.Administration.Notes;
using Content.Shared.Eui;
using JetBrains.Annotations;
+using Robust.Client.UserInterface.Controls;
using static Content.Shared.Administration.Notes.AdminMessageEuiMsg;
namespace Content.Client.Administration.UI.AdminRemarks;
@@ -14,9 +15,8 @@ public sealed class AdminMessageEui : BaseEui
public AdminMessageEui()
{
_popup = new AdminMessagePopupWindow();
- _popup.OnAcceptPressed += () => SendMessage(new Accept());
- _popup.OnDismissPressed += () => SendMessage(new Dismiss());
- _popup.OnClose += () => SendMessage(new CloseEuiMessage());
+ _popup.OnAcceptPressed += () => SendMessage(new Dismiss(true));
+ _popup.OnDismissPressed += () => SendMessage(new Dismiss(false));
}
public override void HandleState(EuiStateBase state)
@@ -26,13 +26,17 @@ public override void HandleState(EuiStateBase state)
return;
}
- _popup.SetMessage(s.Message);
- _popup.SetDetails(s.AdminName, s.AddedOn);
- _popup.Timer = s.Time;
+ _popup.SetState(s);
}
public override void Opened()
{
- _popup.OpenCentered();
+ _popup.UserInterfaceManager.WindowRoot.AddChild(_popup);
+ LayoutContainer.SetAnchorPreset(_popup, LayoutContainer.LayoutPreset.Wide);
+ }
+
+ public override void Closed()
+ {
+ _popup.Orphan();
}
}
diff --git a/Content.Client/Administration/UI/AdminRemarks/AdminMessagePopupMessage.xaml b/Content.Client/Administration/UI/AdminRemarks/AdminMessagePopupMessage.xaml
new file mode 100644
index 0000000000..9a60a6f72a
--- /dev/null
+++ b/Content.Client/Administration/UI/AdminRemarks/AdminMessagePopupMessage.xaml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/Content.Client/Administration/UI/AdminRemarks/AdminMessagePopupMessage.xaml.cs b/Content.Client/Administration/UI/AdminRemarks/AdminMessagePopupMessage.xaml.cs
new file mode 100644
index 0000000000..7bb425f618
--- /dev/null
+++ b/Content.Client/Administration/UI/AdminRemarks/AdminMessagePopupMessage.xaml.cs
@@ -0,0 +1,23 @@
+using Content.Shared.Administration.Notes;
+using Robust.Client.AutoGenerated;
+using Robust.Client.UserInterface;
+using Robust.Client.UserInterface.XAML;
+using Robust.Shared.Utility;
+
+namespace Content.Client.Administration.UI.AdminRemarks;
+
+[GenerateTypedNameReferences]
+public sealed partial class AdminMessagePopupMessage : Control
+{
+ public AdminMessagePopupMessage(AdminMessageEuiState.Message message)
+ {
+ RobustXamlLoader.Load(this);
+
+ Admin.SetMessage(FormattedMessage.FromMarkup(Loc.GetString(
+ "admin-notes-message-admin",
+ ("admin", message.AdminName),
+ ("date", message.AddedOn.ToLocalTime()))));
+
+ Message.SetMessage(message.Text);
+ }
+}
diff --git a/Content.Client/Administration/UI/AdminRemarks/AdminMessagePopupWindow.xaml b/Content.Client/Administration/UI/AdminRemarks/AdminMessagePopupWindow.xaml
index 311829e8b2..cc5207bb3a 100644
--- a/Content.Client/Administration/UI/AdminRemarks/AdminMessagePopupWindow.xaml
+++ b/Content.Client/Administration/UI/AdminRemarks/AdminMessagePopupWindow.xaml
@@ -1,22 +1,36 @@
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Text="{Loc 'admin-notes-message-dismiss'}"
+ Disabled="True"
+ HorizontalExpand="True"
+ StyleClasses="OpenRight" />
+ Disabled="True"
+ HorizontalExpand="True"
+ StyleClasses="OpenLeft" />
-
+
-
+
diff --git a/Content.Client/Administration/UI/AdminRemarks/AdminMessagePopupWindow.xaml.cs b/Content.Client/Administration/UI/AdminRemarks/AdminMessagePopupWindow.xaml.cs
index f28fd1b60b..bf2ca9bec4 100644
--- a/Content.Client/Administration/UI/AdminRemarks/AdminMessagePopupWindow.xaml.cs
+++ b/Content.Client/Administration/UI/AdminRemarks/AdminMessagePopupWindow.xaml.cs
@@ -1,56 +1,65 @@
-using Content.Client.UserInterface.Controls;
+using Content.Client.Stylesheets;
+using Content.Shared.Administration.Notes;
using Robust.Client.AutoGenerated;
+using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Timing;
+using Robust.Shared.Utility;
namespace Content.Client.Administration.UI.AdminRemarks;
[GenerateTypedNameReferences]
-public sealed partial class AdminMessagePopupWindow : FancyWindow
+public sealed partial class AdminMessagePopupWindow : Control
{
private float _timer = float.MaxValue;
- public float Timer
- {
- get => _timer;
- set
- {
- WaitLabel.Text = Loc.GetString("admin-notes-message-wait", ("time", MathF.Floor(value)));
- _timer = value;
- }
- }
public event Action? OnDismissPressed;
+
public event Action? OnAcceptPressed;
public AdminMessagePopupWindow()
{
RobustXamlLoader.Load(this);
+ Stylesheet = IoCManager.Resolve().SheetSpace;
+
AcceptButton.OnPressed += OnAcceptButtonPressed;
DismissButton.OnPressed += OnDismissButtonPressed;
}
- public void SetMessage(string message)
+ public float Timer
{
- MessageLabel.SetMessage(message);
+ get => _timer;
+ private set
+ {
+ WaitLabel.Text = Loc.GetString("admin-notes-message-wait", ("time", MathF.Floor(value)));
+ _timer = value;
+ }
}
- public void SetDetails(string adminName, DateTime addedOn)
+ public void SetState(AdminMessageEuiState state)
{
- AdminLabel.Text = Loc.GetString("admin-notes-message-admin", ("admin", adminName), ("date", addedOn));
+ Timer = (float) state.Time.TotalSeconds;
+
+ MessageContainer.RemoveAllChildren();
+
+ foreach (var message in state.Messages)
+ {
+ MessageContainer.AddChild(new AdminMessagePopupMessage(message));
+ }
+
+ Description.SetMessage(FormattedMessage.FromMarkup(Loc.GetString("admin-notes-message-desc", ("count", state.Messages.Length))));
}
private void OnDismissButtonPressed(BaseButton.ButtonEventArgs obj)
{
OnDismissPressed?.Invoke();
- Close();
}
private void OnAcceptButtonPressed(BaseButton.ButtonEventArgs obj)
{
OnAcceptPressed?.Invoke();
- Close();
}
protected override void FrameUpdate(FrameEventArgs args)
@@ -70,6 +79,7 @@ protected override void FrameUpdate(FrameEventArgs args)
else
{
AcceptButton.Disabled = false;
+ DismissButton.Disabled = false;
}
}
}
diff --git a/Content.Client/Construction/ConstructionSystem.cs b/Content.Client/Construction/ConstructionSystem.cs
index ae1724c3bf..66000a8457 100644
--- a/Content.Client/Construction/ConstructionSystem.cs
+++ b/Content.Client/Construction/ConstructionSystem.cs
@@ -27,6 +27,7 @@ public sealed class ConstructionSystem : SharedConstructionSystem
[Dependency] private readonly IPlayerManager _playerManager = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly SharedInteractionSystem _interactionSystem = default!;
+ [Dependency] private readonly SharedTransformSystem _transformSystem = default!;
[Dependency] private readonly PopupSystem _popupSystem = default!;
private readonly Dictionary _ghosts = new();
@@ -195,7 +196,7 @@ public bool TrySpawnGhost(
return false;
// This InRangeUnobstructed should probably be replaced with "is there something blocking us in that tile?"
- var predicate = GetPredicate(prototype.CanBuildInImpassable, loc.ToMap(EntityManager));
+ var predicate = GetPredicate(prototype.CanBuildInImpassable, loc.ToMap(EntityManager, _transformSystem));
if (!_interactionSystem.InRangeUnobstructed(user, loc, 20f, predicate: predicate))
return false;
diff --git a/Content.Client/ContextMenu/UI/EntityMenuUIController.cs b/Content.Client/ContextMenu/UI/EntityMenuUIController.cs
index ae1b3ec3bf..a60619baa3 100644
--- a/Content.Client/ContextMenu/UI/EntityMenuUIController.cs
+++ b/Content.Client/ContextMenu/UI/EntityMenuUIController.cs
@@ -170,7 +170,7 @@ private bool HandleOpenEntityMenu(in PointerInputCmdHandler.PointerInputCmdArgs
if (_combatMode.IsInCombatMode(args.Session?.AttachedEntity))
return false;
- var coords = args.Coordinates.ToMap(_entityManager);
+ var coords = args.Coordinates.ToMap(_entityManager, _xform);
if (_verbSystem.TryGetEntityMenuEntities(coords, out var entities))
OpenRootMenu(entities);
diff --git a/Content.Client/Gameplay/GameplayStateBase.cs b/Content.Client/Gameplay/GameplayStateBase.cs
index bdbd69d108..6236cd8e95 100644
--- a/Content.Client/Gameplay/GameplayStateBase.cs
+++ b/Content.Client/Gameplay/GameplayStateBase.cs
@@ -104,7 +104,7 @@ private bool HandleInspect(ICommonSession? session, EntityCoordinates coords, En
public IEnumerable GetClickableEntities(EntityCoordinates coordinates)
{
- return GetClickableEntities(coordinates.ToMap(_entityManager));
+ return GetClickableEntities(coordinates.ToMap(_entityManager, _entitySystemManager.GetEntitySystem()));
}
public IEnumerable GetClickableEntities(MapCoordinates coordinates)
diff --git a/Content.Client/IconSmoothing/IconSmoothSystem.cs b/Content.Client/IconSmoothing/IconSmoothSystem.cs
index 0ab33c6520..20a80c42a3 100644
--- a/Content.Client/IconSmoothing/IconSmoothSystem.cs
+++ b/Content.Client/IconSmoothing/IconSmoothSystem.cs
@@ -47,7 +47,7 @@ private void OnStartup(EntityUid uid, IconSmoothComponent component, ComponentSt
var xform = Transform(uid);
if (xform.Anchored)
{
- component.LastPosition = _mapManager.TryGetGrid(xform.GridUid, out var grid)
+ component.LastPosition = TryComp(xform.GridUid, out var grid)
? (xform.GridUid.Value, grid.TileIndicesFor(xform.Coordinates))
: (null, new Vector2i(0, 0));
@@ -134,7 +134,7 @@ public void DirtyNeighbours(EntityUid uid, IconSmoothComponent? comp = null, Tra
Vector2i pos;
- if (transform.Anchored && _mapManager.TryGetGrid(transform.GridUid, out var grid))
+ if (transform.Anchored && TryComp(transform.GridUid, out var grid))
{
pos = grid.CoordinatesToTile(transform.Coordinates);
}
@@ -144,7 +144,7 @@ public void DirtyNeighbours(EntityUid uid, IconSmoothComponent? comp = null, Tra
if (comp.LastPosition is not (EntityUid gridId, Vector2i oldPos))
return;
- if (!_mapManager.TryGetGrid(gridId, out grid))
+ if (!TryComp(gridId, out grid))
return;
pos = oldPos;
@@ -206,7 +206,7 @@ private void CalculateNewSprite(EntityUid uid,
{
var directions = DirectionFlag.None;
- if (_mapManager.TryGetGrid(xform.GridUid, out grid))
+ if (TryComp(xform.GridUid, out grid))
{
var pos = grid.TileIndicesFor(xform.Coordinates);
@@ -240,7 +240,7 @@ private void CalculateNewSprite(EntityUid uid,
if (xform.Anchored)
{
- if (!_mapManager.TryGetGrid(xform.GridUid, out grid))
+ if (!TryComp(xform.GridUid, out grid))
{
Log.Error($"Failed to calculate IconSmoothComponent sprite in {uid} because grid {xform.GridUid} was missing.");
return;
diff --git a/Content.Client/Movement/Systems/JetpackSystem.cs b/Content.Client/Movement/Systems/JetpackSystem.cs
index f0836ee9b6..b7f5e48821 100644
--- a/Content.Client/Movement/Systems/JetpackSystem.cs
+++ b/Content.Client/Movement/Systems/JetpackSystem.cs
@@ -4,6 +4,7 @@
using Content.Shared.Movement.Systems;
using Robust.Client.GameObjects;
using Robust.Shared.Map;
+using Robust.Shared.Map.Components;
using Robust.Shared.Physics.Components;
using Robust.Shared.Timing;
@@ -12,7 +13,6 @@ namespace Content.Client.Movement.Systems;
public sealed class JetpackSystem : SharedJetpackSystem
{
[Dependency] private readonly IGameTiming _timing = default!;
- [Dependency] private readonly IMapManager _mapManager = default!;
[Dependency] private readonly ClothingSystem _clothing = default!;
[Dependency] private readonly SharedTransformSystem _transform = default!;
@@ -75,7 +75,7 @@ private void CreateParticles(EntityUid uid)
var coordinates = uidXform.Coordinates;
var gridUid = coordinates.GetGridUid(EntityManager);
- if (_mapManager.TryGetGrid(gridUid, out var grid))
+ if (TryComp(gridUid, out var grid))
{
coordinates = new EntityCoordinates(gridUid.Value, grid.WorldToLocal(coordinates.ToMapPos(EntityManager, _transform)));
}
diff --git a/Content.Client/NPC/PathfindingSystem.cs b/Content.Client/NPC/PathfindingSystem.cs
index 548edd601c..7bf3df1f0b 100644
--- a/Content.Client/NPC/PathfindingSystem.cs
+++ b/Content.Client/NPC/PathfindingSystem.cs
@@ -23,6 +23,7 @@ public sealed class PathfindingSystem : SharedPathfindingSystem
[Dependency] private readonly IResourceCache _cache = default!;
[Dependency] private readonly NPCSteeringSystem _steering = default!;
[Dependency] private readonly MapSystem _mapSystem = default!;
+ [Dependency] private readonly SharedTransformSystem _transformSystem = default!;
public PathfindingDebugMode Modes
{
@@ -39,7 +40,7 @@ public PathfindingDebugMode Modes
}
else if (!overlayManager.HasOverlay())
{
- overlayManager.AddOverlay(new PathfindingOverlay(EntityManager, _eyeManager, _inputManager, _mapManager, _cache, this, _mapSystem));
+ overlayManager.AddOverlay(new PathfindingOverlay(EntityManager, _eyeManager, _inputManager, _mapManager, _cache, this, _mapSystem, _transformSystem));
}
if ((value & PathfindingDebugMode.Steering) != 0x0)
@@ -140,6 +141,7 @@ public sealed class PathfindingOverlay : Overlay
private readonly IMapManager _mapManager;
private readonly PathfindingSystem _system;
private readonly MapSystem _mapSystem;
+ private readonly SharedTransformSystem _transformSystem;
public override OverlaySpace Space => OverlaySpace.ScreenSpace | OverlaySpace.WorldSpace;
@@ -153,7 +155,8 @@ public PathfindingOverlay(
IMapManager mapManager,
IResourceCache cache,
PathfindingSystem system,
- MapSystem mapSystem)
+ MapSystem mapSystem,
+ SharedTransformSystem transformSystem)
{
_entManager = entManager;
_eyeManager = eyeManager;
@@ -161,6 +164,7 @@ public PathfindingOverlay(
_mapManager = mapManager;
_system = system;
_mapSystem = mapSystem;
+ _transformSystem = transformSystem;
_font = new VectorFont(cache.GetResource("/Fonts/NotoSans/NotoSans-Regular.ttf"), 10);
}
@@ -480,7 +484,7 @@ private void DrawWorld(OverlayDrawArgs args, DrawingHandleWorld worldHandle)
if (neighborPoly.NetEntity != poly.GraphUid)
{
color = Color.Green;
- var neighborMap = _entManager.GetCoordinates(neighborPoly).ToMap(_entManager);
+ var neighborMap = _entManager.GetCoordinates(neighborPoly).ToMap(_entManager, _transformSystem);
if (neighborMap.MapId != args.MapId)
continue;
diff --git a/Content.Client/NodeContainer/NodeVisualizationOverlay.cs b/Content.Client/NodeContainer/NodeVisualizationOverlay.cs
index f10eb9ed8b..691bcb41db 100644
--- a/Content.Client/NodeContainer/NodeVisualizationOverlay.cs
+++ b/Content.Client/NodeContainer/NodeVisualizationOverlay.cs
@@ -80,7 +80,7 @@ private void DrawScreen(in OverlayDrawArgs args)
var xform = _entityManager.GetComponent(_entityManager.GetEntity(node.Entity));
- if (!_mapManager.TryGetGrid(xform.GridUid, out var grid))
+ if (!_entityManager.TryGetComponent(xform.GridUid, out var grid))
return;
var gridTile = grid.TileIndicesFor(xform.Coordinates);
@@ -145,7 +145,7 @@ private void DrawWorld(in OverlayDrawArgs overlayDrawArgs)
foreach (var (gridId, gridDict) in _gridIndex)
{
- var grid = _mapManager.GetGrid(gridId);
+ var grid = _entityManager.GetComponent(gridId);
var (_, _, worldMatrix, invMatrix) = _entityManager.GetComponent(gridId).GetWorldPositionRotationMatrixWithInv();
var lCursorBox = invMatrix.TransformBox(cursorBox);
diff --git a/Content.Client/Popups/PopupOverlay.cs b/Content.Client/Popups/PopupOverlay.cs
index 3bfa727873..fb6bb3bf56 100644
--- a/Content.Client/Popups/PopupOverlay.cs
+++ b/Content.Client/Popups/PopupOverlay.cs
@@ -22,7 +22,7 @@ public sealed class PopupOverlay : Overlay
private readonly PopupSystem _popup;
private readonly PopupUIController _controller;
private readonly ExamineSystemShared _examine;
-
+ private readonly SharedTransformSystem _transform;
private readonly ShaderInstance _shader;
public override OverlaySpace Space => OverlaySpace.ScreenSpace;
@@ -35,6 +35,7 @@ public PopupOverlay(
IUserInterfaceManager uiManager,
PopupUIController controller,
ExamineSystemShared examine,
+ SharedTransformSystem transform,
PopupSystem popup)
{
_configManager = configManager;
@@ -42,6 +43,7 @@ public PopupOverlay(
_playerMgr = playerMgr;
_uiManager = uiManager;
_examine = examine;
+ _transform = transform;
_popup = popup;
_controller = controller;
@@ -76,7 +78,7 @@ private void DrawWorld(DrawingHandleScreen worldHandle, OverlayDrawArgs args, fl
foreach (var popup in _popup.WorldLabels)
{
- var mapPos = popup.InitialPos.ToMap(_entManager);
+ var mapPos = popup.InitialPos.ToMap(_entManager, _transform);
if (mapPos.MapId != args.MapId)
continue;
diff --git a/Content.Client/Popups/PopupSystem.cs b/Content.Client/Popups/PopupSystem.cs
index 46c1e0cdf6..479fb02906 100644
--- a/Content.Client/Popups/PopupSystem.cs
+++ b/Content.Client/Popups/PopupSystem.cs
@@ -28,6 +28,7 @@ public sealed class PopupSystem : SharedPopupSystem
[Dependency] private readonly IUserInterfaceManager _uiManager = default!;
[Dependency] private readonly IReplayRecordingManager _replayRecording = default!;
[Dependency] private readonly ExamineSystemShared _examine = default!;
+ [Dependency] private readonly SharedTransformSystem _transform = default!;
public IReadOnlyList WorldLabels => _aliveWorldLabels;
public IReadOnlyList CursorLabels => _aliveCursorLabels;
@@ -54,6 +55,7 @@ public override void Initialize()
_uiManager,
_uiManager.GetUIController(),
_examine,
+ _transform,
this));
}
diff --git a/Content.Client/Radiation/Overlays/RadiationDebugOverlay.cs b/Content.Client/Radiation/Overlays/RadiationDebugOverlay.cs
index 8c721fa777..ef6283b6ff 100644
--- a/Content.Client/Radiation/Overlays/RadiationDebugOverlay.cs
+++ b/Content.Client/Radiation/Overlays/RadiationDebugOverlay.cs
@@ -4,13 +4,12 @@
using Robust.Client.Graphics;
using Robust.Client.ResourceManagement;
using Robust.Shared.Enums;
-using Robust.Shared.Map;
+using Robust.Shared.Map.Components;
namespace Content.Client.Radiation.Overlays;
public sealed class RadiationDebugOverlay : Overlay
{
- [Dependency] private readonly IMapManager _mapManager = default!;
[Dependency] private readonly IEntityManager _entityManager = default!;
private readonly RadiationSystem _radiation;
@@ -63,7 +62,7 @@ private void DrawScreenRays(OverlayDrawArgs args)
{
var gridUid = _entityManager.GetEntity(netGrid);
- if (!_mapManager.TryGetGrid(gridUid, out var grid))
+ if (!_entityManager.TryGetComponent(gridUid, out var grid))
continue;
foreach (var (tile, rads) in blockers)
@@ -88,7 +87,7 @@ private void DrawScreenResistance(OverlayDrawArgs args)
{
var gridUid = _entityManager.GetEntity(netGrid);
- if (!_mapManager.TryGetGrid(gridUid, out var grid))
+ if (!_entityManager.TryGetComponent(gridUid, out var grid))
continue;
if (query.TryGetComponent(gridUid, out var trs) && trs.MapID != args.MapId)
continue;
@@ -127,7 +126,7 @@ private void DrawWorld(in OverlayDrawArgs args)
{
var gridUid = _entityManager.GetEntity(netGrid);
- if (!_mapManager.TryGetGrid(gridUid, out var grid))
+ if (!_entityManager.TryGetComponent(gridUid, out var grid))
continue;
var (destTile, _) = blockers.Last();
var destWorld = grid.GridTileToWorldPos(destTile);
diff --git a/Content.Client/Radiation/Overlays/RadiationPulseOverlay.cs b/Content.Client/Radiation/Overlays/RadiationPulseOverlay.cs
index adc535b268..9012767ef3 100644
--- a/Content.Client/Radiation/Overlays/RadiationPulseOverlay.cs
+++ b/Content.Client/Radiation/Overlays/RadiationPulseOverlay.cs
@@ -121,7 +121,10 @@ private void RadiationQuery(IEye? currentEye)
private bool PulseQualifies(EntityUid pulseEntity, MapCoordinates currentEyeLoc)
{
- return _entityManager.GetComponent(pulseEntity).MapID == currentEyeLoc.MapId && _entityManager.GetComponent(pulseEntity).Coordinates.InRange(_entityManager, EntityCoordinates.FromMap(_entityManager, _entityManager.GetComponent(pulseEntity).ParentUid, currentEyeLoc), MaxDist);
+ var transformComponent = _entityManager.GetComponent(pulseEntity);
+ var transformSystem = _entityManager.System();
+ return transformComponent.MapID == currentEyeLoc.MapId
+ && transformComponent.Coordinates.InRange(_entityManager, transformSystem, EntityCoordinates.FromMap(transformComponent.ParentUid, currentEyeLoc, transformSystem, _entityManager), MaxDist);
}
private sealed record RadiationShaderInstance(MapCoordinates CurrentMapCoords, float Range, TimeSpan Start, float Duration)
diff --git a/Content.Client/Remotes/EntitySystems/DoorRemoteSystem.cs b/Content.Client/Remotes/EntitySystems/DoorRemoteSystem.cs
new file mode 100644
index 0000000000..d6a9057f08
--- /dev/null
+++ b/Content.Client/Remotes/EntitySystems/DoorRemoteSystem.cs
@@ -0,0 +1,16 @@
+using Content.Client.Remote.UI;
+using Content.Client.Items;
+using Content.Shared.Remotes.EntitySystems;
+using Content.Shared.Remotes.Components;
+
+namespace Content.Client.Remotes.EntitySystems;
+
+public sealed class DoorRemoteSystem : SharedDoorRemoteSystem
+{
+ public override void Initialize()
+ {
+ base.Initialize();
+
+ Subs.ItemStatus(ent => new DoorRemoteStatusControl(ent));
+ }
+}
diff --git a/Content.Client/Remotes/UI/DoorRemoteStatusControl.cs b/Content.Client/Remotes/UI/DoorRemoteStatusControl.cs
new file mode 100644
index 0000000000..94589ecdaa
--- /dev/null
+++ b/Content.Client/Remotes/UI/DoorRemoteStatusControl.cs
@@ -0,0 +1,46 @@
+using Content.Client.Message;
+using Content.Client.Stylesheets;
+using Content.Shared.Remotes.Components;
+using Robust.Client.UserInterface;
+using Robust.Client.UserInterface.Controls;
+using Robust.Shared.Timing;
+
+namespace Content.Client.Remote.UI;
+
+public sealed class DoorRemoteStatusControl : Control
+{
+ private readonly Entity _entity;
+ private readonly RichTextLabel _label;
+
+ // set to toggle bolts initially just so that it updates on first pickup of remote
+ private OperatingMode PrevOperatingMode = OperatingMode.placeholderForUiUpdates;
+
+ public DoorRemoteStatusControl(Entity entity)
+ {
+ _entity = entity;
+ _label = new RichTextLabel { StyleClasses = { StyleNano.StyleClassItemStatus } };
+ AddChild(_label);
+ }
+
+ protected override void FrameUpdate(FrameEventArgs args)
+ {
+ base.FrameUpdate(args);
+
+ // only updates the UI if any of the details are different than they previously were
+ if (PrevOperatingMode == _entity.Comp.Mode)
+ return;
+
+ PrevOperatingMode = _entity.Comp.Mode;
+
+ // Update current volume and injector state
+ var modeStringLocalized = Loc.GetString(_entity.Comp.Mode switch
+ {
+ OperatingMode.OpenClose => "door-remote-open-close-text",
+ OperatingMode.ToggleBolts => "door-remote-toggle-bolt-text",
+ OperatingMode.ToggleEmergencyAccess => "door-remote-emergency-access-text",
+ _ => "door-remote-invalid-text"
+ });
+
+ _label.SetMarkup(Loc.GetString("door-remote-mode-label", ("modeString", modeStringLocalized)));
+ }
+}
diff --git a/Content.Client/Sandbox/SandboxSystem.cs b/Content.Client/Sandbox/SandboxSystem.cs
index d16751e371..6a1129bb75 100644
--- a/Content.Client/Sandbox/SandboxSystem.cs
+++ b/Content.Client/Sandbox/SandboxSystem.cs
@@ -16,6 +16,7 @@ public sealed class SandboxSystem : SharedSandboxSystem
[Dependency] private readonly IMapManager _map = default!;
[Dependency] private readonly IPlacementManager _placement = default!;
[Dependency] private readonly ContentEyeSystem _contentEye = default!;
+ [Dependency] private readonly SharedTransformSystem _transform = default!;
private bool _sandboxEnabled;
public bool SandboxAllowed { get; private set; }
@@ -108,7 +109,7 @@ public bool Copy(ICommonSession? session, EntityCoordinates coords, EntityUid ui
}
// Try copy tile.
- if (!_map.TryFindGridAt(coords.ToMap(EntityManager), out _, out var grid) || !grid.TryGetTileRef(coords, out var tileRef))
+ if (!_map.TryFindGridAt(coords.ToMap(EntityManager, _transform), out _, out var grid) || !grid.TryGetTileRef(coords, out var tileRef))
return false;
if (_placement.Eraser)
diff --git a/Content.Client/Shuttles/UI/BaseShuttleControl.xaml.cs b/Content.Client/Shuttles/UI/BaseShuttleControl.xaml.cs
index 035823af43..fed2a9f171 100644
--- a/Content.Client/Shuttles/UI/BaseShuttleControl.xaml.cs
+++ b/Content.Client/Shuttles/UI/BaseShuttleControl.xaml.cs
@@ -66,11 +66,11 @@ public BaseShuttleControl(float minRange, float maxRange, float range) : base(mi
protected void DrawData(DrawingHandleScreen handle, string text)
{
- var coordsDimensions = handle.GetDimensions(Font, text, UIScale);
+ var coordsDimensions = handle.GetDimensions(Font, text, 1f);
const float coordsMargins = 5f;
handle.DrawString(Font,
- new Vector2(coordsMargins, Height) - new Vector2(0f, coordsDimensions.Y + coordsMargins),
+ new Vector2(coordsMargins, PixelHeight) - new Vector2(0f, coordsDimensions.Y + coordsMargins),
text,
Color.FromSrgb(IFFComponent.SelfColor));
}
diff --git a/Content.Client/Shuttles/UI/ShuttleMapControl.xaml.cs b/Content.Client/Shuttles/UI/ShuttleMapControl.xaml.cs
index 2ce1906d3d..2f35a8dffd 100644
--- a/Content.Client/Shuttles/UI/ShuttleMapControl.xaml.cs
+++ b/Content.Client/Shuttles/UI/ShuttleMapControl.xaml.cs
@@ -116,7 +116,7 @@ protected override void KeyBindUp(GUIBoundKeyEventArgs args)
var mapTransform = Matrix3.CreateInverseTransform(Offset, Angle.Zero);
- if (beaconsOnly && TryGetBeacon(_beacons, mapTransform, args.RelativePosition, PixelRect, out var foundBeacon, out _))
+ if (beaconsOnly && TryGetBeacon(_beacons, mapTransform, args.RelativePixelPosition, PixelRect, out var foundBeacon, out _))
{
RequestBeaconFTL?.Invoke(foundBeacon.Entity, _ftlAngle);
}
@@ -206,7 +206,8 @@ private void DrawParallax(DrawingHandleScreen handle)
private List GetViewportMapObjects(Matrix3 matty, List mapObjects)
{
var results = new List();
- var viewBox = SizeBox.Scale(1.2f);
+ var enlargement = new Vector2i((int) (16 * UIScale), (int) (16 * UIScale));
+ var viewBox = new UIBox2i(Vector2i.Zero - enlargement, PixelSize + enlargement);
foreach (var mapObj in mapObjects)
{
@@ -398,8 +399,8 @@ protected override void Draw(DrawingHandleScreen handle)
foreach (var (gridUiPos, iffText) in sendStrings)
{
- var textWidth = handle.GetDimensions(_font, iffText, UIScale);
- handle.DrawString(_font, gridUiPos + textWidth with { X = -textWidth.X / 2f }, iffText, adjustedColor);
+ var textWidth = handle.GetDimensions(_font, iffText, 1f);
+ handle.DrawString(_font, gridUiPos + textWidth with { X = -textWidth.X / 2f, Y = textWidth.Y * UIScale }, iffText, adjustedColor);
}
}
@@ -587,7 +588,7 @@ private bool TryGetBeacon(IEnumerable mapObjects, Matrix3 mapTransfo
var distance = (localPos - mousePos).Length();
- if (distance > BeaconSnapRange ||
+ if (distance > BeaconSnapRange * UIScale ||
distance > nearestValue)
{
continue;
diff --git a/Content.IntegrationTests/Tests/Fluids/FluidSpillTest.cs b/Content.IntegrationTests/Tests/Fluids/FluidSpillTest.cs
index 0d852bf2f0..6e88d6928e 100644
--- a/Content.IntegrationTests/Tests/Fluids/FluidSpillTest.cs
+++ b/Content.IntegrationTests/Tests/Fluids/FluidSpillTest.cs
@@ -72,7 +72,7 @@ await server.WaitPost(() =>
var puddleOrigin = new Vector2i(0, 0);
await server.WaitAssertion(() =>
{
- var grid = mapManager.GetGrid(gridId);
+ var grid = entityManager.GetComponent(gridId);
var solution = new Solution("Blood", FixedPoint2.New(100));
var tileRef = grid.GetTileRef(puddleOrigin);
#pragma warning disable NUnit2045 // Interdependent tests
@@ -86,7 +86,7 @@ await server.WaitAssertion(() =>
await server.WaitAssertion(() =>
{
- var grid = mapManager.GetGrid(gridId);
+ var grid = entityManager.GetComponent(gridId);
var puddle = GetPuddleEntity(entityManager, grid, puddleOrigin);
#pragma warning disable NUnit2045 // Interdependent tests
diff --git a/Content.Server.Database/Migrations/Postgres/20240318022005_AdminMessageDismiss.Designer.cs b/Content.Server.Database/Migrations/Postgres/20240318022005_AdminMessageDismiss.Designer.cs
new file mode 100644
index 0000000000..1a47a51b94
--- /dev/null
+++ b/Content.Server.Database/Migrations/Postgres/20240318022005_AdminMessageDismiss.Designer.cs
@@ -0,0 +1,1768 @@
+//
+using System;
+using System.Net;
+using System.Text.Json;
+using Content.Server.Database;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
+using NpgsqlTypes;
+
+#nullable disable
+
+namespace Content.Server.Database.Migrations.Postgres
+{
+ [DbContext(typeof(PostgresServerDbContext))]
+ [Migration("20240318022005_AdminMessageDismiss")]
+ partial class AdminMessageDismiss
+ {
+ ///
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "8.0.0")
+ .HasAnnotation("Relational:MaxIdentifierLength", 63);
+
+ NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
+
+ modelBuilder.Entity("Content.Server.Database.Admin", b =>
+ {
+ b.Property("UserId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid")
+ .HasColumnName("user_id");
+
+ b.Property("AdminRankId")
+ .HasColumnType("integer")
+ .HasColumnName("admin_rank_id");
+
+ b.Property("Title")
+ .HasColumnType("text")
+ .HasColumnName("title");
+
+ b.HasKey("UserId")
+ .HasName("PK_admin");
+
+ b.HasIndex("AdminRankId")
+ .HasDatabaseName("IX_admin_admin_rank_id");
+
+ b.ToTable("admin", (string)null);
+ });
+
+ modelBuilder.Entity("Content.Server.Database.AdminFlag", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer")
+ .HasColumnName("admin_flag_id");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("AdminId")
+ .HasColumnType("uuid")
+ .HasColumnName("admin_id");
+
+ b.Property("Flag")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("flag");
+
+ b.Property("Negative")
+ .HasColumnType("boolean")
+ .HasColumnName("negative");
+
+ b.HasKey("Id")
+ .HasName("PK_admin_flag");
+
+ b.HasIndex("AdminId")
+ .HasDatabaseName("IX_admin_flag_admin_id");
+
+ b.HasIndex("Flag", "AdminId")
+ .IsUnique();
+
+ b.ToTable("admin_flag", (string)null);
+ });
+
+ modelBuilder.Entity("Content.Server.Database.AdminLog", b =>
+ {
+ b.Property("RoundId")
+ .HasColumnType("integer")
+ .HasColumnName("round_id");
+
+ b.Property("Id")
+ .HasColumnType("integer")
+ .HasColumnName("admin_log_id");
+
+ b.Property("Date")
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("date");
+
+ b.Property("Impact")
+ .HasColumnType("smallint")
+ .HasColumnName("impact");
+
+ b.Property("Json")
+ .IsRequired()
+ .HasColumnType("jsonb")
+ .HasColumnName("json");
+
+ b.Property("Message")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("message");
+
+ b.Property("Type")
+ .HasColumnType("integer")
+ .HasColumnName("type");
+
+ b.HasKey("RoundId", "Id")
+ .HasName("PK_admin_log");
+
+ b.HasIndex("Date");
+
+ b.HasIndex("Message")
+ .HasAnnotation("Npgsql:TsVectorConfig", "english");
+
+ NpgsqlIndexBuilderExtensions.HasMethod(b.HasIndex("Message"), "GIN");
+
+ b.HasIndex("Type")
+ .HasDatabaseName("IX_admin_log_type");
+
+ b.ToTable("admin_log", (string)null);
+ });
+
+ modelBuilder.Entity("Content.Server.Database.AdminLogPlayer", b =>
+ {
+ b.Property("RoundId")
+ .HasColumnType("integer")
+ .HasColumnName("round_id");
+
+ b.Property("LogId")
+ .HasColumnType("integer")
+ .HasColumnName("log_id");
+
+ b.Property("PlayerUserId")
+ .HasColumnType("uuid")
+ .HasColumnName("player_user_id");
+
+ b.HasKey("RoundId", "LogId", "PlayerUserId")
+ .HasName("PK_admin_log_player");
+
+ b.HasIndex("PlayerUserId")
+ .HasDatabaseName("IX_admin_log_player_player_user_id");
+
+ b.ToTable("admin_log_player", (string)null);
+ });
+
+ modelBuilder.Entity("Content.Server.Database.AdminMessage", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer")
+ .HasColumnName("admin_messages_id");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("CreatedAt")
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("created_at");
+
+ b.Property("CreatedById")
+ .HasColumnType("uuid")
+ .HasColumnName("created_by_id");
+
+ b.Property("Deleted")
+ .HasColumnType("boolean")
+ .HasColumnName("deleted");
+
+ b.Property("DeletedAt")
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("deleted_at");
+
+ b.Property("DeletedById")
+ .HasColumnType("uuid")
+ .HasColumnName("deleted_by_id");
+
+ b.Property("Dismissed")
+ .HasColumnType("boolean")
+ .HasColumnName("dismissed");
+
+ b.Property("ExpirationTime")
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("expiration_time");
+
+ b.Property("LastEditedAt")
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("last_edited_at");
+
+ b.Property("LastEditedById")
+ .HasColumnType("uuid")
+ .HasColumnName("last_edited_by_id");
+
+ b.Property("Message")
+ .IsRequired()
+ .HasMaxLength(4096)
+ .HasColumnType("character varying(4096)")
+ .HasColumnName("message");
+
+ b.Property("PlayerUserId")
+ .HasColumnType("uuid")
+ .HasColumnName("player_user_id");
+
+ b.Property("PlaytimeAtNote")
+ .HasColumnType("interval")
+ .HasColumnName("playtime_at_note");
+
+ b.Property("RoundId")
+ .HasColumnType("integer")
+ .HasColumnName("round_id");
+
+ b.Property("Seen")
+ .HasColumnType("boolean")
+ .HasColumnName("seen");
+
+ b.HasKey("Id")
+ .HasName("PK_admin_messages");
+
+ b.HasIndex("CreatedById");
+
+ b.HasIndex("DeletedById");
+
+ b.HasIndex("LastEditedById");
+
+ b.HasIndex("PlayerUserId")
+ .HasDatabaseName("IX_admin_messages_player_user_id");
+
+ b.HasIndex("RoundId")
+ .HasDatabaseName("IX_admin_messages_round_id");
+
+ b.ToTable("admin_messages", null, t =>
+ {
+ t.HasCheckConstraint("NotDismissedAndSeen", "NOT dismissed OR seen");
+ });
+ });
+
+ modelBuilder.Entity("Content.Server.Database.AdminNote", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer")
+ .HasColumnName("admin_notes_id");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("CreatedAt")
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("created_at");
+
+ b.Property("CreatedById")
+ .HasColumnType("uuid")
+ .HasColumnName("created_by_id");
+
+ b.Property("Deleted")
+ .HasColumnType("boolean")
+ .HasColumnName("deleted");
+
+ b.Property("DeletedAt")
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("deleted_at");
+
+ b.Property("DeletedById")
+ .HasColumnType("uuid")
+ .HasColumnName("deleted_by_id");
+
+ b.Property("ExpirationTime")
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("expiration_time");
+
+ b.Property("LastEditedAt")
+ .IsRequired()
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("last_edited_at");
+
+ b.Property("LastEditedById")
+ .HasColumnType("uuid")
+ .HasColumnName("last_edited_by_id");
+
+ b.Property("Message")
+ .IsRequired()
+ .HasMaxLength(4096)
+ .HasColumnType("character varying(4096)")
+ .HasColumnName("message");
+
+ b.Property("PlayerUserId")
+ .HasColumnType("uuid")
+ .HasColumnName("player_user_id");
+
+ b.Property("PlaytimeAtNote")
+ .HasColumnType("interval")
+ .HasColumnName("playtime_at_note");
+
+ b.Property("RoundId")
+ .HasColumnType("integer")
+ .HasColumnName("round_id");
+
+ b.Property("Secret")
+ .HasColumnType("boolean")
+ .HasColumnName("secret");
+
+ b.Property("Severity")
+ .HasColumnType("integer")
+ .HasColumnName("severity");
+
+ b.HasKey("Id")
+ .HasName("PK_admin_notes");
+
+ b.HasIndex("CreatedById");
+
+ b.HasIndex("DeletedById");
+
+ b.HasIndex("LastEditedById");
+
+ b.HasIndex("PlayerUserId")
+ .HasDatabaseName("IX_admin_notes_player_user_id");
+
+ b.HasIndex("RoundId")
+ .HasDatabaseName("IX_admin_notes_round_id");
+
+ b.ToTable("admin_notes", (string)null);
+ });
+
+ modelBuilder.Entity("Content.Server.Database.AdminRank", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer")
+ .HasColumnName("admin_rank_id");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("name");
+
+ b.HasKey("Id")
+ .HasName("PK_admin_rank");
+
+ b.ToTable("admin_rank", (string)null);
+ });
+
+ modelBuilder.Entity("Content.Server.Database.AdminRankFlag", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer")
+ .HasColumnName("admin_rank_flag_id");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("AdminRankId")
+ .HasColumnType("integer")
+ .HasColumnName("admin_rank_id");
+
+ b.Property("Flag")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("flag");
+
+ b.HasKey("Id")
+ .HasName("PK_admin_rank_flag");
+
+ b.HasIndex("AdminRankId");
+
+ b.HasIndex("Flag", "AdminRankId")
+ .IsUnique();
+
+ b.ToTable("admin_rank_flag", (string)null);
+ });
+
+ modelBuilder.Entity("Content.Server.Database.AdminWatchlist", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer")
+ .HasColumnName("admin_watchlists_id");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("CreatedAt")
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("created_at");
+
+ b.Property("CreatedById")
+ .HasColumnType("uuid")
+ .HasColumnName("created_by_id");
+
+ b.Property("Deleted")
+ .HasColumnType("boolean")
+ .HasColumnName("deleted");
+
+ b.Property("DeletedAt")
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("deleted_at");
+
+ b.Property("DeletedById")
+ .HasColumnType("uuid")
+ .HasColumnName("deleted_by_id");
+
+ b.Property("ExpirationTime")
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("expiration_time");
+
+ b.Property("LastEditedAt")
+ .IsRequired()
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("last_edited_at");
+
+ b.Property("LastEditedById")
+ .HasColumnType("uuid")
+ .HasColumnName("last_edited_by_id");
+
+ b.Property("Message")
+ .IsRequired()
+ .HasMaxLength(4096)
+ .HasColumnType("character varying(4096)")
+ .HasColumnName("message");
+
+ b.Property("PlayerUserId")
+ .HasColumnType("uuid")
+ .HasColumnName("player_user_id");
+
+ b.Property("PlaytimeAtNote")
+ .HasColumnType("interval")
+ .HasColumnName("playtime_at_note");
+
+ b.Property("RoundId")
+ .HasColumnType("integer")
+ .HasColumnName("round_id");
+
+ b.HasKey("Id")
+ .HasName("PK_admin_watchlists");
+
+ b.HasIndex("CreatedById");
+
+ b.HasIndex("DeletedById");
+
+ b.HasIndex("LastEditedById");
+
+ b.HasIndex("PlayerUserId")
+ .HasDatabaseName("IX_admin_watchlists_player_user_id");
+
+ b.HasIndex("RoundId")
+ .HasDatabaseName("IX_admin_watchlists_round_id");
+
+ b.ToTable("admin_watchlists", (string)null);
+ });
+
+ modelBuilder.Entity("Content.Server.Database.Antag", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer")
+ .HasColumnName("antag_id");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("AntagName")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("antag_name");
+
+ b.Property("ProfileId")
+ .HasColumnType("integer")
+ .HasColumnName("profile_id");
+
+ b.HasKey("Id")
+ .HasName("PK_antag");
+
+ b.HasIndex("ProfileId", "AntagName")
+ .IsUnique();
+
+ b.ToTable("antag", (string)null);
+ });
+
+ modelBuilder.Entity("Content.Server.Database.AssignedUserId", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer")
+ .HasColumnName("assigned_user_id_id");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("UserId")
+ .HasColumnType("uuid")
+ .HasColumnName("user_id");
+
+ b.Property("UserName")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("user_name");
+
+ b.HasKey("Id")
+ .HasName("PK_assigned_user_id");
+
+ b.HasIndex("UserId")
+ .IsUnique();
+
+ b.HasIndex("UserName")
+ .IsUnique();
+
+ b.ToTable("assigned_user_id", (string)null);
+ });
+
+ modelBuilder.Entity("Content.Server.Database.ConnectionLog", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer")
+ .HasColumnName("connection_log_id");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("Address")
+ .IsRequired()
+ .HasColumnType("inet")
+ .HasColumnName("address");
+
+ b.Property("Denied")
+ .HasColumnType("smallint")
+ .HasColumnName("denied");
+
+ b.Property("HWId")
+ .HasColumnType("bytea")
+ .HasColumnName("hwid");
+
+ b.Property("ServerId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer")
+ .HasDefaultValue(0)
+ .HasColumnName("server_id");
+
+ b.Property("Time")
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("time");
+
+ b.Property("UserId")
+ .HasColumnType("uuid")
+ .HasColumnName("user_id");
+
+ b.Property("UserName")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("user_name");
+
+ b.HasKey("Id")
+ .HasName("PK_connection_log");
+
+ b.HasIndex("ServerId")
+ .HasDatabaseName("IX_connection_log_server_id");
+
+ b.HasIndex("UserId");
+
+ b.ToTable("connection_log", null, t =>
+ {
+ t.HasCheckConstraint("AddressNotIPv6MappedIPv4", "NOT inet '::ffff:0.0.0.0/96' >>= address");
+ });
+ });
+
+ modelBuilder.Entity("Content.Server.Database.Job", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer")
+ .HasColumnName("job_id");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("JobName")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("job_name");
+
+ b.Property("Priority")
+ .HasColumnType("integer")
+ .HasColumnName("priority");
+
+ b.Property("ProfileId")
+ .HasColumnType("integer")
+ .HasColumnName("profile_id");
+
+ b.HasKey("Id")
+ .HasName("PK_job");
+
+ b.HasIndex("ProfileId");
+
+ b.HasIndex("ProfileId", "JobName")
+ .IsUnique();
+
+ b.HasIndex(new[] { "ProfileId" }, "IX_job_one_high_priority")
+ .IsUnique()
+ .HasFilter("priority = 3");
+
+ b.ToTable("job", (string)null);
+ });
+
+ modelBuilder.Entity("Content.Server.Database.PlayTime", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer")
+ .HasColumnName("play_time_id");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("PlayerId")
+ .HasColumnType("uuid")
+ .HasColumnName("player_id");
+
+ b.Property("TimeSpent")
+ .HasColumnType("interval")
+ .HasColumnName("time_spent");
+
+ b.Property("Tracker")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("tracker");
+
+ b.HasKey("Id")
+ .HasName("PK_play_time");
+
+ b.HasIndex("PlayerId", "Tracker")
+ .IsUnique();
+
+ b.ToTable("play_time", (string)null);
+ });
+
+ modelBuilder.Entity("Content.Server.Database.Player", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer")
+ .HasColumnName("player_id");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("FirstSeenTime")
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("first_seen_time");
+
+ b.Property("LastReadRules")
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("last_read_rules");
+
+ b.Property("LastSeenAddress")
+ .IsRequired()
+ .HasColumnType("inet")
+ .HasColumnName("last_seen_address");
+
+ b.Property("LastSeenHWId")
+ .HasColumnType("bytea")
+ .HasColumnName("last_seen_hwid");
+
+ b.Property("LastSeenTime")
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("last_seen_time");
+
+ b.Property("LastSeenUserName")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("last_seen_user_name");
+
+ b.Property("UserId")
+ .HasColumnType("uuid")
+ .HasColumnName("user_id");
+
+ b.HasKey("Id")
+ .HasName("PK_player");
+
+ b.HasAlternateKey("UserId")
+ .HasName("ak_player_user_id");
+
+ b.HasIndex("LastSeenUserName");
+
+ b.HasIndex("UserId")
+ .IsUnique();
+
+ b.ToTable("player", null, t =>
+ {
+ t.HasCheckConstraint("LastSeenAddressNotIPv6MappedIPv4", "NOT inet '::ffff:0.0.0.0/96' >>= last_seen_address");
+ });
+ });
+
+ modelBuilder.Entity("Content.Server.Database.Preference", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer")
+ .HasColumnName("preference_id");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("AdminOOCColor")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("admin_ooc_color");
+
+ b.Property("SelectedCharacterSlot")
+ .HasColumnType("integer")
+ .HasColumnName("selected_character_slot");
+
+ b.Property("UserId")
+ .HasColumnType("uuid")
+ .HasColumnName("user_id");
+
+ b.HasKey("Id")
+ .HasName("PK_preference");
+
+ b.HasIndex("UserId")
+ .IsUnique();
+
+ b.ToTable("preference", (string)null);
+ });
+
+ modelBuilder.Entity("Content.Server.Database.Profile", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer")
+ .HasColumnName("profile_id");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("Age")
+ .HasColumnType("integer")
+ .HasColumnName("age");
+
+ b.Property("Backpack")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("backpack");
+
+ b.Property("CharacterName")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("char_name");
+
+ b.Property("Clothing")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("clothing");
+
+ b.Property("EyeColor")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("eye_color");
+
+ b.Property("FacialHairColor")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("facial_hair_color");
+
+ b.Property("FacialHairName")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("facial_hair_name");
+
+ b.Property("FlavorText")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("flavor_text");
+
+ b.Property("Gender")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("gender");
+
+ b.Property("HairColor")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("hair_color");
+
+ b.Property("HairName")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("hair_name");
+
+ b.Property("Markings")
+ .HasColumnType("jsonb")
+ .HasColumnName("markings");
+
+ b.Property("PreferenceId")
+ .HasColumnType("integer")
+ .HasColumnName("preference_id");
+
+ b.Property("PreferenceUnavailable")
+ .HasColumnType("integer")
+ .HasColumnName("pref_unavailable");
+
+ b.Property("Sex")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("sex");
+
+ b.Property("SkinColor")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("skin_color");
+
+ b.Property("Slot")
+ .HasColumnType("integer")
+ .HasColumnName("slot");
+
+ b.Property("SpawnPriority")
+ .HasColumnType("integer")
+ .HasColumnName("spawn_priority");
+
+ b.Property("Species")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("species");
+
+ b.HasKey("Id")
+ .HasName("PK_profile");
+
+ b.HasIndex("PreferenceId")
+ .HasDatabaseName("IX_profile_preference_id");
+
+ b.HasIndex("Slot", "PreferenceId")
+ .IsUnique();
+
+ b.ToTable("profile", (string)null);
+ });
+
+ modelBuilder.Entity("Content.Server.Database.Round", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer")
+ .HasColumnName("round_id");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("ServerId")
+ .HasColumnType("integer")
+ .HasColumnName("server_id");
+
+ b.Property("StartDate")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("timestamp with time zone")
+ .HasDefaultValue(new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified))
+ .HasColumnName("start_date");
+
+ b.HasKey("Id")
+ .HasName("PK_round");
+
+ b.HasIndex("ServerId")
+ .HasDatabaseName("IX_round_server_id");
+
+ b.HasIndex("StartDate");
+
+ b.ToTable("round", (string)null);
+ });
+
+ modelBuilder.Entity("Content.Server.Database.Server", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer")
+ .HasColumnName("server_id");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("name");
+
+ b.HasKey("Id")
+ .HasName("PK_server");
+
+ b.ToTable("server", (string)null);
+ });
+
+ modelBuilder.Entity("Content.Server.Database.ServerBan", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer")
+ .HasColumnName("server_ban_id");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("Address")
+ .HasColumnType("inet")
+ .HasColumnName("address");
+
+ b.Property("AutoDelete")
+ .HasColumnType("boolean")
+ .HasColumnName("auto_delete");
+
+ b.Property("BanTime")
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("ban_time");
+
+ b.Property("BanningAdmin")
+ .HasColumnType("uuid")
+ .HasColumnName("banning_admin");
+
+ b.Property("ExemptFlags")
+ .HasColumnType("integer")
+ .HasColumnName("exempt_flags");
+
+ b.Property("ExpirationTime")
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("expiration_time");
+
+ b.Property("HWId")
+ .HasColumnType("bytea")
+ .HasColumnName("hwid");
+
+ b.Property("Hidden")
+ .HasColumnType("boolean")
+ .HasColumnName("hidden");
+
+ b.Property("LastEditedAt")
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("last_edited_at");
+
+ b.Property("LastEditedById")
+ .HasColumnType("uuid")
+ .HasColumnName("last_edited_by_id");
+
+ b.Property("PlayerUserId")
+ .HasColumnType("uuid")
+ .HasColumnName("player_user_id");
+
+ b.Property("PlaytimeAtNote")
+ .HasColumnType("interval")
+ .HasColumnName("playtime_at_note");
+
+ b.Property("Reason")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("reason");
+
+ b.Property("RoundId")
+ .HasColumnType("integer")
+ .HasColumnName("round_id");
+
+ b.Property("Severity")
+ .HasColumnType("integer")
+ .HasColumnName("severity");
+
+ b.HasKey("Id")
+ .HasName("PK_server_ban");
+
+ b.HasIndex("Address");
+
+ b.HasIndex("BanningAdmin");
+
+ b.HasIndex("LastEditedById");
+
+ b.HasIndex("PlayerUserId")
+ .HasDatabaseName("IX_server_ban_player_user_id");
+
+ b.HasIndex("RoundId")
+ .HasDatabaseName("IX_server_ban_round_id");
+
+ b.ToTable("server_ban", null, t =>
+ {
+ t.HasCheckConstraint("AddressNotIPv6MappedIPv4", "NOT inet '::ffff:0.0.0.0/96' >>= address");
+
+ t.HasCheckConstraint("HaveEitherAddressOrUserIdOrHWId", "address IS NOT NULL OR player_user_id IS NOT NULL OR hwid IS NOT NULL");
+ });
+ });
+
+ modelBuilder.Entity("Content.Server.Database.ServerBanExemption", b =>
+ {
+ b.Property("UserId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid")
+ .HasColumnName("user_id");
+
+ b.Property("Flags")
+ .HasColumnType("integer")
+ .HasColumnName("flags");
+
+ b.HasKey("UserId")
+ .HasName("PK_server_ban_exemption");
+
+ b.ToTable("server_ban_exemption", null, t =>
+ {
+ t.HasCheckConstraint("FlagsNotZero", "flags != 0");
+ });
+ });
+
+ modelBuilder.Entity("Content.Server.Database.ServerBanHit", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer")
+ .HasColumnName("server_ban_hit_id");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("BanId")
+ .HasColumnType("integer")
+ .HasColumnName("ban_id");
+
+ b.Property("ConnectionId")
+ .HasColumnType("integer")
+ .HasColumnName("connection_id");
+
+ b.HasKey("Id")
+ .HasName("PK_server_ban_hit");
+
+ b.HasIndex("BanId")
+ .HasDatabaseName("IX_server_ban_hit_ban_id");
+
+ b.HasIndex("ConnectionId")
+ .HasDatabaseName("IX_server_ban_hit_connection_id");
+
+ b.ToTable("server_ban_hit", (string)null);
+ });
+
+ modelBuilder.Entity("Content.Server.Database.ServerRoleBan", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer")
+ .HasColumnName("server_role_ban_id");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("Address")
+ .HasColumnType("inet")
+ .HasColumnName("address");
+
+ b.Property("BanTime")
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("ban_time");
+
+ b.Property("BanningAdmin")
+ .HasColumnType("uuid")
+ .HasColumnName("banning_admin");
+
+ b.Property("ExpirationTime")
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("expiration_time");
+
+ b.Property("HWId")
+ .HasColumnType("bytea")
+ .HasColumnName("hwid");
+
+ b.Property("Hidden")
+ .HasColumnType("boolean")
+ .HasColumnName("hidden");
+
+ b.Property("LastEditedAt")
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("last_edited_at");
+
+ b.Property("LastEditedById")
+ .HasColumnType("uuid")
+ .HasColumnName("last_edited_by_id");
+
+ b.Property("PlayerUserId")
+ .HasColumnType("uuid")
+ .HasColumnName("player_user_id");
+
+ b.Property("PlaytimeAtNote")
+ .HasColumnType("interval")
+ .HasColumnName("playtime_at_note");
+
+ b.Property("Reason")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("reason");
+
+ b.Property("RoleId")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("role_id");
+
+ b.Property("RoundId")
+ .HasColumnType("integer")
+ .HasColumnName("round_id");
+
+ b.Property("Severity")
+ .HasColumnType("integer")
+ .HasColumnName("severity");
+
+ b.HasKey("Id")
+ .HasName("PK_server_role_ban");
+
+ b.HasIndex("Address");
+
+ b.HasIndex("BanningAdmin");
+
+ b.HasIndex("LastEditedById");
+
+ b.HasIndex("PlayerUserId")
+ .HasDatabaseName("IX_server_role_ban_player_user_id");
+
+ b.HasIndex("RoundId")
+ .HasDatabaseName("IX_server_role_ban_round_id");
+
+ b.ToTable("server_role_ban", null, t =>
+ {
+ t.HasCheckConstraint("AddressNotIPv6MappedIPv4", "NOT inet '::ffff:0.0.0.0/96' >>= address");
+
+ t.HasCheckConstraint("HaveEitherAddressOrUserIdOrHWId", "address IS NOT NULL OR player_user_id IS NOT NULL OR hwid IS NOT NULL");
+ });
+ });
+
+ modelBuilder.Entity("Content.Server.Database.ServerRoleUnban", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer")
+ .HasColumnName("role_unban_id");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("BanId")
+ .HasColumnType("integer")
+ .HasColumnName("ban_id");
+
+ b.Property("UnbanTime")
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("unban_time");
+
+ b.Property("UnbanningAdmin")
+ .HasColumnType("uuid")
+ .HasColumnName("unbanning_admin");
+
+ b.HasKey("Id")
+ .HasName("PK_server_role_unban");
+
+ b.HasIndex("BanId")
+ .IsUnique();
+
+ b.ToTable("server_role_unban", (string)null);
+ });
+
+ modelBuilder.Entity("Content.Server.Database.ServerUnban", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer")
+ .HasColumnName("unban_id");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("BanId")
+ .HasColumnType("integer")
+ .HasColumnName("ban_id");
+
+ b.Property("UnbanTime")
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("unban_time");
+
+ b.Property("UnbanningAdmin")
+ .HasColumnType("uuid")
+ .HasColumnName("unbanning_admin");
+
+ b.HasKey("Id")
+ .HasName("PK_server_unban");
+
+ b.HasIndex("BanId")
+ .IsUnique();
+
+ b.ToTable("server_unban", (string)null);
+ });
+
+ modelBuilder.Entity("Content.Server.Database.Trait", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer")
+ .HasColumnName("trait_id");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("ProfileId")
+ .HasColumnType("integer")
+ .HasColumnName("profile_id");
+
+ b.Property("TraitName")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("trait_name");
+
+ b.HasKey("Id")
+ .HasName("PK_trait");
+
+ b.HasIndex("ProfileId", "TraitName")
+ .IsUnique();
+
+ b.ToTable("trait", (string)null);
+ });
+
+ modelBuilder.Entity("Content.Server.Database.UploadedResourceLog", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer")
+ .HasColumnName("uploaded_resource_log_id");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("Data")
+ .IsRequired()
+ .HasColumnType("bytea")
+ .HasColumnName("data");
+
+ b.Property("Date")
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("date");
+
+ b.Property("Path")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("path");
+
+ b.Property("UserId")
+ .HasColumnType("uuid")
+ .HasColumnName("user_id");
+
+ b.HasKey("Id")
+ .HasName("PK_uploaded_resource_log");
+
+ b.ToTable("uploaded_resource_log", (string)null);
+ });
+
+ modelBuilder.Entity("Content.Server.Database.Whitelist", b =>
+ {
+ b.Property("UserId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid")
+ .HasColumnName("user_id");
+
+ b.HasKey("UserId")
+ .HasName("PK_whitelist");
+
+ b.ToTable("whitelist", (string)null);
+ });
+
+ modelBuilder.Entity("PlayerRound", b =>
+ {
+ b.Property("PlayersId")
+ .HasColumnType("integer")
+ .HasColumnName("players_id");
+
+ b.Property("RoundsId")
+ .HasColumnType("integer")
+ .HasColumnName("rounds_id");
+
+ b.HasKey("PlayersId", "RoundsId")
+ .HasName("PK_player_round");
+
+ b.HasIndex("RoundsId")
+ .HasDatabaseName("IX_player_round_rounds_id");
+
+ b.ToTable("player_round", (string)null);
+ });
+
+ modelBuilder.Entity("Content.Server.Database.Admin", b =>
+ {
+ b.HasOne("Content.Server.Database.AdminRank", "AdminRank")
+ .WithMany("Admins")
+ .HasForeignKey("AdminRankId")
+ .OnDelete(DeleteBehavior.SetNull)
+ .HasConstraintName("FK_admin_admin_rank_admin_rank_id");
+
+ b.Navigation("AdminRank");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.AdminFlag", b =>
+ {
+ b.HasOne("Content.Server.Database.Admin", "Admin")
+ .WithMany("Flags")
+ .HasForeignKey("AdminId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired()
+ .HasConstraintName("FK_admin_flag_admin_admin_id");
+
+ b.Navigation("Admin");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.AdminLog", b =>
+ {
+ b.HasOne("Content.Server.Database.Round", "Round")
+ .WithMany("AdminLogs")
+ .HasForeignKey("RoundId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired()
+ .HasConstraintName("FK_admin_log_round_round_id");
+
+ b.Navigation("Round");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.AdminLogPlayer", b =>
+ {
+ b.HasOne("Content.Server.Database.Player", "Player")
+ .WithMany("AdminLogs")
+ .HasForeignKey("PlayerUserId")
+ .HasPrincipalKey("UserId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired()
+ .HasConstraintName("FK_admin_log_player_player_player_user_id");
+
+ b.HasOne("Content.Server.Database.AdminLog", "Log")
+ .WithMany("Players")
+ .HasForeignKey("RoundId", "LogId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired()
+ .HasConstraintName("FK_admin_log_player_admin_log_round_id_log_id");
+
+ b.Navigation("Log");
+
+ b.Navigation("Player");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.AdminMessage", b =>
+ {
+ b.HasOne("Content.Server.Database.Player", "CreatedBy")
+ .WithMany("AdminMessagesCreated")
+ .HasForeignKey("CreatedById")
+ .HasPrincipalKey("UserId")
+ .OnDelete(DeleteBehavior.SetNull)
+ .HasConstraintName("FK_admin_messages_player_created_by_id");
+
+ b.HasOne("Content.Server.Database.Player", "DeletedBy")
+ .WithMany("AdminMessagesDeleted")
+ .HasForeignKey("DeletedById")
+ .HasPrincipalKey("UserId")
+ .OnDelete(DeleteBehavior.SetNull)
+ .HasConstraintName("FK_admin_messages_player_deleted_by_id");
+
+ b.HasOne("Content.Server.Database.Player", "LastEditedBy")
+ .WithMany("AdminMessagesLastEdited")
+ .HasForeignKey("LastEditedById")
+ .HasPrincipalKey("UserId")
+ .OnDelete(DeleteBehavior.SetNull)
+ .HasConstraintName("FK_admin_messages_player_last_edited_by_id");
+
+ b.HasOne("Content.Server.Database.Player", "Player")
+ .WithMany("AdminMessagesReceived")
+ .HasForeignKey("PlayerUserId")
+ .HasPrincipalKey("UserId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .HasConstraintName("FK_admin_messages_player_player_user_id");
+
+ b.HasOne("Content.Server.Database.Round", "Round")
+ .WithMany()
+ .HasForeignKey("RoundId")
+ .HasConstraintName("FK_admin_messages_round_round_id");
+
+ b.Navigation("CreatedBy");
+
+ b.Navigation("DeletedBy");
+
+ b.Navigation("LastEditedBy");
+
+ b.Navigation("Player");
+
+ b.Navigation("Round");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.AdminNote", b =>
+ {
+ b.HasOne("Content.Server.Database.Player", "CreatedBy")
+ .WithMany("AdminNotesCreated")
+ .HasForeignKey("CreatedById")
+ .HasPrincipalKey("UserId")
+ .OnDelete(DeleteBehavior.SetNull)
+ .HasConstraintName("FK_admin_notes_player_created_by_id");
+
+ b.HasOne("Content.Server.Database.Player", "DeletedBy")
+ .WithMany("AdminNotesDeleted")
+ .HasForeignKey("DeletedById")
+ .HasPrincipalKey("UserId")
+ .OnDelete(DeleteBehavior.SetNull)
+ .HasConstraintName("FK_admin_notes_player_deleted_by_id");
+
+ b.HasOne("Content.Server.Database.Player", "LastEditedBy")
+ .WithMany("AdminNotesLastEdited")
+ .HasForeignKey("LastEditedById")
+ .HasPrincipalKey("UserId")
+ .OnDelete(DeleteBehavior.SetNull)
+ .HasConstraintName("FK_admin_notes_player_last_edited_by_id");
+
+ b.HasOne("Content.Server.Database.Player", "Player")
+ .WithMany("AdminNotesReceived")
+ .HasForeignKey("PlayerUserId")
+ .HasPrincipalKey("UserId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .HasConstraintName("FK_admin_notes_player_player_user_id");
+
+ b.HasOne("Content.Server.Database.Round", "Round")
+ .WithMany()
+ .HasForeignKey("RoundId")
+ .HasConstraintName("FK_admin_notes_round_round_id");
+
+ b.Navigation("CreatedBy");
+
+ b.Navigation("DeletedBy");
+
+ b.Navigation("LastEditedBy");
+
+ b.Navigation("Player");
+
+ b.Navigation("Round");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.AdminRankFlag", b =>
+ {
+ b.HasOne("Content.Server.Database.AdminRank", "Rank")
+ .WithMany("Flags")
+ .HasForeignKey("AdminRankId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired()
+ .HasConstraintName("FK_admin_rank_flag_admin_rank_admin_rank_id");
+
+ b.Navigation("Rank");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.AdminWatchlist", b =>
+ {
+ b.HasOne("Content.Server.Database.Player", "CreatedBy")
+ .WithMany("AdminWatchlistsCreated")
+ .HasForeignKey("CreatedById")
+ .HasPrincipalKey("UserId")
+ .OnDelete(DeleteBehavior.SetNull)
+ .HasConstraintName("FK_admin_watchlists_player_created_by_id");
+
+ b.HasOne("Content.Server.Database.Player", "DeletedBy")
+ .WithMany("AdminWatchlistsDeleted")
+ .HasForeignKey("DeletedById")
+ .HasPrincipalKey("UserId")
+ .OnDelete(DeleteBehavior.SetNull)
+ .HasConstraintName("FK_admin_watchlists_player_deleted_by_id");
+
+ b.HasOne("Content.Server.Database.Player", "LastEditedBy")
+ .WithMany("AdminWatchlistsLastEdited")
+ .HasForeignKey("LastEditedById")
+ .HasPrincipalKey("UserId")
+ .OnDelete(DeleteBehavior.SetNull)
+ .HasConstraintName("FK_admin_watchlists_player_last_edited_by_id");
+
+ b.HasOne("Content.Server.Database.Player", "Player")
+ .WithMany("AdminWatchlistsReceived")
+ .HasForeignKey("PlayerUserId")
+ .HasPrincipalKey("UserId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .HasConstraintName("FK_admin_watchlists_player_player_user_id");
+
+ b.HasOne("Content.Server.Database.Round", "Round")
+ .WithMany()
+ .HasForeignKey("RoundId")
+ .HasConstraintName("FK_admin_watchlists_round_round_id");
+
+ b.Navigation("CreatedBy");
+
+ b.Navigation("DeletedBy");
+
+ b.Navigation("LastEditedBy");
+
+ b.Navigation("Player");
+
+ b.Navigation("Round");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.Antag", b =>
+ {
+ b.HasOne("Content.Server.Database.Profile", "Profile")
+ .WithMany("Antags")
+ .HasForeignKey("ProfileId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired()
+ .HasConstraintName("FK_antag_profile_profile_id");
+
+ b.Navigation("Profile");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.ConnectionLog", b =>
+ {
+ b.HasOne("Content.Server.Database.Server", "Server")
+ .WithMany("ConnectionLogs")
+ .HasForeignKey("ServerId")
+ .OnDelete(DeleteBehavior.SetNull)
+ .IsRequired()
+ .HasConstraintName("FK_connection_log_server_server_id");
+
+ b.Navigation("Server");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.Job", b =>
+ {
+ b.HasOne("Content.Server.Database.Profile", "Profile")
+ .WithMany("Jobs")
+ .HasForeignKey("ProfileId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired()
+ .HasConstraintName("FK_job_profile_profile_id");
+
+ b.Navigation("Profile");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.Profile", b =>
+ {
+ b.HasOne("Content.Server.Database.Preference", "Preference")
+ .WithMany("Profiles")
+ .HasForeignKey("PreferenceId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired()
+ .HasConstraintName("FK_profile_preference_preference_id");
+
+ b.Navigation("Preference");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.Round", b =>
+ {
+ b.HasOne("Content.Server.Database.Server", "Server")
+ .WithMany("Rounds")
+ .HasForeignKey("ServerId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired()
+ .HasConstraintName("FK_round_server_server_id");
+
+ b.Navigation("Server");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.ServerBan", b =>
+ {
+ b.HasOne("Content.Server.Database.Player", "CreatedBy")
+ .WithMany("AdminServerBansCreated")
+ .HasForeignKey("BanningAdmin")
+ .HasPrincipalKey("UserId")
+ .OnDelete(DeleteBehavior.SetNull)
+ .HasConstraintName("FK_server_ban_player_banning_admin");
+
+ b.HasOne("Content.Server.Database.Player", "LastEditedBy")
+ .WithMany("AdminServerBansLastEdited")
+ .HasForeignKey("LastEditedById")
+ .HasPrincipalKey("UserId")
+ .OnDelete(DeleteBehavior.SetNull)
+ .HasConstraintName("FK_server_ban_player_last_edited_by_id");
+
+ b.HasOne("Content.Server.Database.Round", "Round")
+ .WithMany()
+ .HasForeignKey("RoundId")
+ .HasConstraintName("FK_server_ban_round_round_id");
+
+ b.Navigation("CreatedBy");
+
+ b.Navigation("LastEditedBy");
+
+ b.Navigation("Round");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.ServerBanHit", b =>
+ {
+ b.HasOne("Content.Server.Database.ServerBan", "Ban")
+ .WithMany("BanHits")
+ .HasForeignKey("BanId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired()
+ .HasConstraintName("FK_server_ban_hit_server_ban_ban_id");
+
+ b.HasOne("Content.Server.Database.ConnectionLog", "Connection")
+ .WithMany("BanHits")
+ .HasForeignKey("ConnectionId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired()
+ .HasConstraintName("FK_server_ban_hit_connection_log_connection_id");
+
+ b.Navigation("Ban");
+
+ b.Navigation("Connection");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.ServerRoleBan", b =>
+ {
+ b.HasOne("Content.Server.Database.Player", "CreatedBy")
+ .WithMany("AdminServerRoleBansCreated")
+ .HasForeignKey("BanningAdmin")
+ .HasPrincipalKey("UserId")
+ .OnDelete(DeleteBehavior.SetNull)
+ .HasConstraintName("FK_server_role_ban_player_banning_admin");
+
+ b.HasOne("Content.Server.Database.Player", "LastEditedBy")
+ .WithMany("AdminServerRoleBansLastEdited")
+ .HasForeignKey("LastEditedById")
+ .HasPrincipalKey("UserId")
+ .OnDelete(DeleteBehavior.SetNull)
+ .HasConstraintName("FK_server_role_ban_player_last_edited_by_id");
+
+ b.HasOne("Content.Server.Database.Round", "Round")
+ .WithMany()
+ .HasForeignKey("RoundId")
+ .HasConstraintName("FK_server_role_ban_round_round_id");
+
+ b.Navigation("CreatedBy");
+
+ b.Navigation("LastEditedBy");
+
+ b.Navigation("Round");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.ServerRoleUnban", b =>
+ {
+ b.HasOne("Content.Server.Database.ServerRoleBan", "Ban")
+ .WithOne("Unban")
+ .HasForeignKey("Content.Server.Database.ServerRoleUnban", "BanId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired()
+ .HasConstraintName("FK_server_role_unban_server_role_ban_ban_id");
+
+ b.Navigation("Ban");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.ServerUnban", b =>
+ {
+ b.HasOne("Content.Server.Database.ServerBan", "Ban")
+ .WithOne("Unban")
+ .HasForeignKey("Content.Server.Database.ServerUnban", "BanId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired()
+ .HasConstraintName("FK_server_unban_server_ban_ban_id");
+
+ b.Navigation("Ban");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.Trait", b =>
+ {
+ b.HasOne("Content.Server.Database.Profile", "Profile")
+ .WithMany("Traits")
+ .HasForeignKey("ProfileId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired()
+ .HasConstraintName("FK_trait_profile_profile_id");
+
+ b.Navigation("Profile");
+ });
+
+ modelBuilder.Entity("PlayerRound", b =>
+ {
+ b.HasOne("Content.Server.Database.Player", null)
+ .WithMany()
+ .HasForeignKey("PlayersId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired()
+ .HasConstraintName("FK_player_round_player_players_id");
+
+ b.HasOne("Content.Server.Database.Round", null)
+ .WithMany()
+ .HasForeignKey("RoundsId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired()
+ .HasConstraintName("FK_player_round_round_rounds_id");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.Admin", b =>
+ {
+ b.Navigation("Flags");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.AdminLog", b =>
+ {
+ b.Navigation("Players");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.AdminRank", b =>
+ {
+ b.Navigation("Admins");
+
+ b.Navigation("Flags");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.ConnectionLog", b =>
+ {
+ b.Navigation("BanHits");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.Player", b =>
+ {
+ b.Navigation("AdminLogs");
+
+ b.Navigation("AdminMessagesCreated");
+
+ b.Navigation("AdminMessagesDeleted");
+
+ b.Navigation("AdminMessagesLastEdited");
+
+ b.Navigation("AdminMessagesReceived");
+
+ b.Navigation("AdminNotesCreated");
+
+ b.Navigation("AdminNotesDeleted");
+
+ b.Navigation("AdminNotesLastEdited");
+
+ b.Navigation("AdminNotesReceived");
+
+ b.Navigation("AdminServerBansCreated");
+
+ b.Navigation("AdminServerBansLastEdited");
+
+ b.Navigation("AdminServerRoleBansCreated");
+
+ b.Navigation("AdminServerRoleBansLastEdited");
+
+ b.Navigation("AdminWatchlistsCreated");
+
+ b.Navigation("AdminWatchlistsDeleted");
+
+ b.Navigation("AdminWatchlistsLastEdited");
+
+ b.Navigation("AdminWatchlistsReceived");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.Preference", b =>
+ {
+ b.Navigation("Profiles");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.Profile", b =>
+ {
+ b.Navigation("Antags");
+
+ b.Navigation("Jobs");
+
+ b.Navigation("Traits");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.Round", b =>
+ {
+ b.Navigation("AdminLogs");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.Server", b =>
+ {
+ b.Navigation("ConnectionLogs");
+
+ b.Navigation("Rounds");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.ServerBan", b =>
+ {
+ b.Navigation("BanHits");
+
+ b.Navigation("Unban");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.ServerRoleBan", b =>
+ {
+ b.Navigation("Unban");
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/Content.Server.Database/Migrations/Postgres/20240318022005_AdminMessageDismiss.cs b/Content.Server.Database/Migrations/Postgres/20240318022005_AdminMessageDismiss.cs
new file mode 100644
index 0000000000..372eecc585
--- /dev/null
+++ b/Content.Server.Database/Migrations/Postgres/20240318022005_AdminMessageDismiss.cs
@@ -0,0 +1,40 @@
+using Microsoft.EntityFrameworkCore.Migrations;
+
+#nullable disable
+
+namespace Content.Server.Database.Migrations.Postgres
+{
+ ///
+ public partial class AdminMessageDismiss : Migration
+ {
+ ///
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.AddColumn(
+ name: "dismissed",
+ table: "admin_messages",
+ type: "boolean",
+ nullable: false,
+ defaultValue: false);
+
+ migrationBuilder.Sql("UPDATE admin_messages SET dismissed = seen;");
+
+ migrationBuilder.AddCheckConstraint(
+ name: "NotDismissedAndSeen",
+ table: "admin_messages",
+ sql: "NOT dismissed OR seen");
+ }
+
+ ///
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.DropCheckConstraint(
+ name: "NotDismissedAndSeen",
+ table: "admin_messages");
+
+ migrationBuilder.DropColumn(
+ name: "dismissed",
+ table: "admin_messages");
+ }
+ }
+}
diff --git a/Content.Server.Database/Migrations/Postgres/PostgresServerDbContextModelSnapshot.cs b/Content.Server.Database/Migrations/Postgres/PostgresServerDbContextModelSnapshot.cs
index ae40e1228e..1d3c525dac 100644
--- a/Content.Server.Database/Migrations/Postgres/PostgresServerDbContextModelSnapshot.cs
+++ b/Content.Server.Database/Migrations/Postgres/PostgresServerDbContextModelSnapshot.cs
@@ -183,6 +183,10 @@ protected override void BuildModel(ModelBuilder modelBuilder)
.HasColumnType("uuid")
.HasColumnName("deleted_by_id");
+ b.Property("Dismissed")
+ .HasColumnType("boolean")
+ .HasColumnName("dismissed");
+
b.Property("ExpirationTime")
.HasColumnType("timestamp with time zone")
.HasColumnName("expiration_time");
@@ -232,7 +236,10 @@ protected override void BuildModel(ModelBuilder modelBuilder)
b.HasIndex("RoundId")
.HasDatabaseName("IX_admin_messages_round_id");
- b.ToTable("admin_messages", (string)null);
+ b.ToTable("admin_messages", null, t =>
+ {
+ t.HasCheckConstraint("NotDismissedAndSeen", "NOT dismissed OR seen");
+ });
});
modelBuilder.Entity("Content.Server.Database.AdminNote", b =>
diff --git a/Content.Server.Database/Migrations/Sqlite/20240318021959_AdminMessageDismiss.Designer.cs b/Content.Server.Database/Migrations/Sqlite/20240318021959_AdminMessageDismiss.Designer.cs
new file mode 100644
index 0000000000..f4d6990356
--- /dev/null
+++ b/Content.Server.Database/Migrations/Sqlite/20240318021959_AdminMessageDismiss.Designer.cs
@@ -0,0 +1,1699 @@
+//
+using System;
+using Content.Server.Database;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+
+#nullable disable
+
+namespace Content.Server.Database.Migrations.Sqlite
+{
+ [DbContext(typeof(SqliteServerDbContext))]
+ [Migration("20240318021959_AdminMessageDismiss")]
+ partial class AdminMessageDismiss
+ {
+ ///
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder.HasAnnotation("ProductVersion", "8.0.0");
+
+ modelBuilder.Entity("Content.Server.Database.Admin", b =>
+ {
+ b.Property("UserId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("TEXT")
+ .HasColumnName("user_id");
+
+ b.Property("AdminRankId")
+ .HasColumnType("INTEGER")
+ .HasColumnName("admin_rank_id");
+
+ b.Property("Title")
+ .HasColumnType("TEXT")
+ .HasColumnName("title");
+
+ b.HasKey("UserId")
+ .HasName("PK_admin");
+
+ b.HasIndex("AdminRankId")
+ .HasDatabaseName("IX_admin_admin_rank_id");
+
+ b.ToTable("admin", (string)null);
+ });
+
+ modelBuilder.Entity("Content.Server.Database.AdminFlag", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER")
+ .HasColumnName("admin_flag_id");
+
+ b.Property("AdminId")
+ .HasColumnType("TEXT")
+ .HasColumnName("admin_id");
+
+ b.Property("Flag")
+ .IsRequired()
+ .HasColumnType("TEXT")
+ .HasColumnName("flag");
+
+ b.Property("Negative")
+ .HasColumnType("INTEGER")
+ .HasColumnName("negative");
+
+ b.HasKey("Id")
+ .HasName("PK_admin_flag");
+
+ b.HasIndex("AdminId")
+ .HasDatabaseName("IX_admin_flag_admin_id");
+
+ b.HasIndex("Flag", "AdminId")
+ .IsUnique();
+
+ b.ToTable("admin_flag", (string)null);
+ });
+
+ modelBuilder.Entity("Content.Server.Database.AdminLog", b =>
+ {
+ b.Property("RoundId")
+ .HasColumnType("INTEGER")
+ .HasColumnName("round_id");
+
+ b.Property("Id")
+ .HasColumnType("INTEGER")
+ .HasColumnName("admin_log_id");
+
+ b.Property("Date")
+ .HasColumnType("TEXT")
+ .HasColumnName("date");
+
+ b.Property("Impact")
+ .HasColumnType("INTEGER")
+ .HasColumnName("impact");
+
+ b.Property("Json")
+ .IsRequired()
+ .HasColumnType("jsonb")
+ .HasColumnName("json");
+
+ b.Property("Message")
+ .IsRequired()
+ .HasColumnType("TEXT")
+ .HasColumnName("message");
+
+ b.Property("Type")
+ .HasColumnType("INTEGER")
+ .HasColumnName("type");
+
+ b.HasKey("RoundId", "Id")
+ .HasName("PK_admin_log");
+
+ b.HasIndex("Date");
+
+ b.HasIndex("Type")
+ .HasDatabaseName("IX_admin_log_type");
+
+ b.ToTable("admin_log", (string)null);
+ });
+
+ modelBuilder.Entity("Content.Server.Database.AdminLogPlayer", b =>
+ {
+ b.Property("RoundId")
+ .HasColumnType("INTEGER")
+ .HasColumnName("round_id");
+
+ b.Property