diff --git a/Content.Client/Administration/UI/BanPanel/BanPanel.xaml.cs b/Content.Client/Administration/UI/BanPanel/BanPanel.xaml.cs index 588d62e560..3c7322d473 100644 --- a/Content.Client/Administration/UI/BanPanel/BanPanel.xaml.cs +++ b/Content.Client/Administration/UI/BanPanel/BanPanel.xaml.cs @@ -22,11 +22,11 @@ namespace Content.Client.Administration.UI.BanPanel; [GenerateTypedNameReferences] public sealed partial class BanPanel : DefaultWindow { - public event Action? BanSubmitted; + public event Action? BanSubmitted; public event Action? PlayerChanged; private string? PlayerUsername { get; set; } private (IPAddress, int)? IpAddress { get; set; } - private byte[]? Hwid { get; set; } + private ImmutableTypedHwid? Hwid { get; set; } private double TimeEntered { get; set; } private uint Multiplier { get; set; } private bool HasBanFlag { get; set; } @@ -371,9 +371,8 @@ public sealed partial class BanPanel : DefaultWindow private void OnHwidChanged() { var hwidString = HwidLine.Text; - var length = 3 * (hwidString.Length / 4) - hwidString.TakeLast(2).Count(c => c == '='); - Hwid = new byte[length]; - if (HwidCheckbox.Pressed && !(string.IsNullOrEmpty(hwidString) && LastConnCheckbox.Pressed) && !Convert.TryFromBase64String(hwidString, Hwid, out _)) + ImmutableTypedHwid? hwid = null; + if (HwidCheckbox.Pressed && !(string.IsNullOrEmpty(hwidString) && LastConnCheckbox.Pressed) && !ImmutableTypedHwid.TryParse(hwidString, out hwid)) { ErrorLevel |= ErrorLevelEnum.Hwid; HwidLine.ModulateSelfOverride = Color.Red; @@ -390,7 +389,7 @@ public sealed partial class BanPanel : DefaultWindow Hwid = null; return; } - Hwid = Convert.FromHexString(hwidString); + Hwid = hwid; } private void OnTypeChanged() diff --git a/Content.Client/Administration/UI/Notes/NoteEdit.xaml.cs b/Content.Client/Administration/UI/Notes/NoteEdit.xaml.cs index a412e47396..c8e3afeb22 100644 --- a/Content.Client/Administration/UI/Notes/NoteEdit.xaml.cs +++ b/Content.Client/Administration/UI/Notes/NoteEdit.xaml.cs @@ -159,6 +159,7 @@ public sealed partial class NoteEdit : FancyWindow SecretCheckBox.Pressed = false; SeverityOption.Disabled = false; PermanentCheckBox.Pressed = true; + SubmitButton.Disabled = true; UpdatePermanentCheckboxFields(); break; case (int) NoteType.Message: // Message: these are shown to the player when they log on diff --git a/Content.Client/Electrocution/ElectrocutionHUDVisualizerSystem.cs b/Content.Client/Electrocution/ElectrocutionHUDVisualizerSystem.cs new file mode 100644 index 0000000000..b95c0d585d --- /dev/null +++ b/Content.Client/Electrocution/ElectrocutionHUDVisualizerSystem.cs @@ -0,0 +1,95 @@ +using Content.Shared.Electrocution; +using Robust.Client.GameObjects; +using Robust.Client.Player; +using Robust.Shared.Player; + +namespace Content.Client.Electrocution; + +/// +/// Shows the Electrocution HUD to entities with the ShowElectrocutionHUDComponent. +/// +public sealed class ElectrocutionHUDVisualizerSystem : VisualizerSystem +{ + [Dependency] private readonly IPlayerManager _playerMan = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnInit); + SubscribeLocalEvent(OnShutdown); + SubscribeLocalEvent(OnPlayerAttached); + SubscribeLocalEvent(OnPlayerDetached); + } + + private void OnPlayerAttached(Entity ent, ref LocalPlayerAttachedEvent args) + { + ShowHUD(); + } + + private void OnPlayerDetached(Entity ent, ref LocalPlayerDetachedEvent args) + { + RemoveHUD(); + } + + private void OnInit(Entity ent, ref ComponentInit args) + { + if (_playerMan.LocalEntity == ent) + { + ShowHUD(); + } + } + + private void OnShutdown(Entity ent, ref ComponentShutdown args) + { + if (_playerMan.LocalEntity == ent) + { + RemoveHUD(); + } + } + + // Show the HUD to the client. + // We have to look for all current entities that can be electrified and toggle the HUD layer on if they are. + private void ShowHUD() + { + var electrifiedQuery = AllEntityQuery(); + while (electrifiedQuery.MoveNext(out var uid, out var _, out var appearanceComp, out var spriteComp)) + { + if (!AppearanceSystem.TryGetData(uid, ElectrifiedVisuals.IsElectrified, out var electrified, appearanceComp)) + continue; + + if (electrified) + spriteComp.LayerSetVisible(ElectrifiedLayers.HUD, true); + else + spriteComp.LayerSetVisible(ElectrifiedLayers.HUD, false); + } + } + + // Remove the HUD from the client. + // Find all current entities that can be electrified and hide the HUD layer. + private void RemoveHUD() + { + var electrifiedQuery = AllEntityQuery(); + while (electrifiedQuery.MoveNext(out var uid, out var _, out var appearanceComp, out var spriteComp)) + { + + spriteComp.LayerSetVisible(ElectrifiedLayers.HUD, false); + } + } + + // Toggle the HUD layer if an entity becomes (de-)electrified + protected override void OnAppearanceChange(EntityUid uid, ElectrocutionHUDVisualsComponent comp, ref AppearanceChangeEvent args) + { + if (args.Sprite == null) + return; + + if (!AppearanceSystem.TryGetData(uid, ElectrifiedVisuals.IsElectrified, out var electrified, args.Component)) + return; + + var player = _playerMan.LocalEntity; + if (electrified && HasComp(player)) + args.Sprite.LayerSetVisible(ElectrifiedLayers.HUD, true); + else + args.Sprite.LayerSetVisible(ElectrifiedLayers.HUD, false); + } +} diff --git a/Content.Client/Eui/BaseEui.cs b/Content.Client/Eui/BaseEui.cs index 7f86ded7e4..c11ba5a9b6 100644 --- a/Content.Client/Eui/BaseEui.cs +++ b/Content.Client/Eui/BaseEui.cs @@ -55,7 +55,7 @@ namespace Content.Client.Eui /// protected void SendMessage(EuiMessageBase msg) { - var netMsg = _netManager.CreateNetMessage(); + var netMsg = new MsgEuiMessage(); netMsg.Id = Id; netMsg.Message = msg; diff --git a/Content.Client/Info/LinkBanner.cs b/Content.Client/Info/LinkBanner.cs index 39a8a33994..b2e78c013f 100644 --- a/Content.Client/Info/LinkBanner.cs +++ b/Content.Client/Info/LinkBanner.cs @@ -37,9 +37,7 @@ namespace Content.Client.Info AddInfoButton("server-info-website-button", CCVars.InfoLinksWebsite); AddInfoButton("server-info-wiki-button", CCVars.InfoLinksWiki); AddInfoButton("server-info-forum-button", CCVars.InfoLinksForum); - // Sunrise-Start - AddInfoButton("server-info-telegram-button", SunriseCCVars.InfoLinksTelegram); - // Sunrise-End + AddInfoButton("server-info-telegram-button", CCVars.InfoLinksTelegram); var guidebookController = UserInterfaceManager.GetUIController(); var guidebookButton = new Button() { Text = Loc.GetString("server-info-guidebook-button") }; diff --git a/Content.Client/Shuttles/UI/BaseShuttleControl.xaml.cs b/Content.Client/Shuttles/UI/BaseShuttleControl.xaml.cs index b50d8fa6b2..a541100539 100644 --- a/Content.Client/Shuttles/UI/BaseShuttleControl.xaml.cs +++ b/Content.Client/Shuttles/UI/BaseShuttleControl.xaml.cs @@ -116,7 +116,7 @@ public partial class BaseShuttleControl : MapGridControl } } - protected void DrawGrid(DrawingHandleScreen handle, Matrix3x2 matrix, Entity grid, Color color, float alpha = 0.01f) + protected void DrawGrid(DrawingHandleScreen handle, Matrix3x2 gridToView, Entity grid, Color color, float alpha = 0.01f) { var rator = Maps.GetAllTilesEnumerator(grid.Owner, grid.Comp); var minimapScale = MinimapScale; @@ -264,7 +264,7 @@ public partial class BaseShuttleControl : MapGridControl Extensions.EnsureLength(ref _allVertices, totalData); _drawJob.MidPoint = midpoint; - _drawJob.Matrix = matrix; + _drawJob.Matrix = gridToView; _drawJob.MinimapScale = minimapScale; _drawJob.Vertices = gridData.Vertices; _drawJob.ScaledVertices = _allVertices; @@ -286,7 +286,7 @@ public partial class BaseShuttleControl : MapGridControl private record struct GridDrawJob : IParallelRobustJob { - public int BatchSize => 16; + public int BatchSize => 64; public float MinimapScale; public Vector2 MidPoint; @@ -297,12 +297,7 @@ public partial class BaseShuttleControl : MapGridControl public void Execute(int index) { - var vert = Vertices[index]; - var adjustedVert = Vector2.Transform(vert, Matrix); - adjustedVert = adjustedVert with { Y = -adjustedVert.Y }; - - var scaledVert = ScalePosition(adjustedVert, MinimapScale, MidPoint); - ScaledVertices[index] = scaledVert; + ScaledVertices[index] = Vector2.Transform(Vertices[index], Matrix); } } } diff --git a/Content.Client/Shuttles/UI/NavScreen.xaml.cs b/Content.Client/Shuttles/UI/NavScreen.xaml.cs index 91d95aaa04..7236714ef2 100644 --- a/Content.Client/Shuttles/UI/NavScreen.xaml.cs +++ b/Content.Client/Shuttles/UI/NavScreen.xaml.cs @@ -15,6 +15,7 @@ public sealed partial class NavScreen : BoxContainer [Dependency] private readonly IEntityManager _entManager = default!; private SharedTransformSystem _xformSystem; + private EntityUid? _consoleEntity; // Entity of controlling console private EntityUid? _shuttleEntity; public NavScreen() @@ -35,6 +36,12 @@ public sealed partial class NavScreen : BoxContainer _shuttleEntity = shuttle; } + public void SetConsole(EntityUid? console) + { + _consoleEntity = console; + NavRadar.SetConsole(console); + } + private void OnIFFTogglePressed(BaseButton.ButtonEventArgs args) { NavRadar.ShowIFF ^= true; diff --git a/Content.Client/Shuttles/UI/ShuttleConsoleWindow.xaml.cs b/Content.Client/Shuttles/UI/ShuttleConsoleWindow.xaml.cs index a4b42fb672..d0e6f9ebf7 100644 --- a/Content.Client/Shuttles/UI/ShuttleConsoleWindow.xaml.cs +++ b/Content.Client/Shuttles/UI/ShuttleConsoleWindow.xaml.cs @@ -138,6 +138,7 @@ public sealed partial class ShuttleConsoleWindow : FancyWindow, { var coordinates = _entManager.GetCoordinates(cState.NavState.Coordinates); NavContainer.SetShuttle(coordinates?.EntityId); + NavContainer.SetConsole(owner); MapContainer.SetShuttle(coordinates?.EntityId); MapContainer.SetConsole(owner); diff --git a/Content.Client/Shuttles/UI/ShuttleDockControl.xaml.cs b/Content.Client/Shuttles/UI/ShuttleDockControl.xaml.cs index 61ae069926..2b575b4805 100644 --- a/Content.Client/Shuttles/UI/ShuttleDockControl.xaml.cs +++ b/Content.Client/Shuttles/UI/ShuttleDockControl.xaml.cs @@ -107,16 +107,19 @@ public sealed partial class ShuttleDockControl : BaseShuttleControl DrawCircles(handle); var gridNent = EntManager.GetNetEntity(GridEntity); var mapPos = _xformSystem.ToMapCoordinates(_coordinates.Value); - var ourGridMatrix = _xformSystem.GetWorldMatrix(GridEntity.Value); - var dockMatrix = Matrix3Helpers.CreateTransform(_coordinates.Value.Position, Angle.Zero); - var worldFromDock = Matrix3x2.Multiply(dockMatrix, ourGridMatrix); + var ourGridToWorld = _xformSystem.GetWorldMatrix(GridEntity.Value); + var selectedDockToOurGrid = Matrix3Helpers.CreateTransform(_coordinates.Value.Position, Angle.Zero); + var selectedDockToWorld = Matrix3x2.Multiply(selectedDockToOurGrid, ourGridToWorld); - Matrix3x2.Invert(worldFromDock, out var offsetMatrix); + Box2 viewBoundsWorld = Matrix3Helpers.TransformBox(selectedDockToWorld, new Box2(-WorldRangeVector, WorldRangeVector)); + + Matrix3x2.Invert(selectedDockToWorld, out var worldToSelectedDock); + var selectedDockToView = Matrix3x2.CreateScale(new Vector2(MinimapScale, -MinimapScale)) * Matrix3x2.CreateTranslation(MidPointVector); // Draw nearby grids var controlBounds = PixelSizeBox; _grids.Clear(); - _mapManager.FindGridsIntersecting(gridXform.MapID, new Box2(mapPos.Position - WorldRangeVector, mapPos.Position + WorldRangeVector), ref _grids); + _mapManager.FindGridsIntersecting(gridXform.MapID, viewBoundsWorld, ref _grids); // offset the dotted-line position to the bounds. Vector2? viewedDockPos = _viewedState != null ? MidPointVector : null; @@ -136,11 +139,11 @@ public sealed partial class ShuttleDockControl : BaseShuttleControl if (grid.Owner != GridEntity && !_shuttles.CanDraw(grid.Owner, iffComp: iffComp)) continue; - var gridMatrix = _xformSystem.GetWorldMatrix(grid.Owner); - var matty = Matrix3x2.Multiply(gridMatrix, offsetMatrix); + var curGridToWorld = _xformSystem.GetWorldMatrix(grid.Owner); + var curGridToView = curGridToWorld * worldToSelectedDock * selectedDockToView; var color = _shuttles.GetIFFColor(grid.Owner, grid.Owner == GridEntity, component: iffComp); - DrawGrid(handle, matty, grid, color); + DrawGrid(handle, curGridToView, grid, color); // Draw any docks on that grid if (!DockState.Docks.TryGetValue(EntManager.GetNetEntity(grid), out var gridDocks)) @@ -151,23 +154,24 @@ public sealed partial class ShuttleDockControl : BaseShuttleControl if (ViewedDock == dock.Entity) continue; - var position = Vector2.Transform(dock.Coordinates.Position, matty); - var otherDockRotation = Matrix3Helpers.CreateRotation(dock.Angle); - var scaledPos = ScalePosition(position with {Y = -position.Y}); - if (!controlBounds.Contains(scaledPos.Floored())) + // This box is the AABB of all the vertices we draw below. + var dockRenderBoundsLocal = new Box2(-0.5f, -0.7f, 0.5f, 0.5f); + var currentDockToCurGrid = Matrix3Helpers.CreateTransform(dock.Coordinates.Position, dock.Angle); + var currentDockToWorld = Matrix3x2.Multiply(currentDockToCurGrid, curGridToWorld); + var dockRenderBoundsWorld = Matrix3Helpers.TransformBox(currentDockToWorld, dockRenderBoundsLocal); + if (!viewBoundsWorld.Intersects(dockRenderBoundsWorld)) continue; - // Draw the dock's collision var collisionBL = Vector2.Transform(dock.Coordinates.Position + - Vector2.Transform(new Vector2(-0.2f, -0.7f), otherDockRotation), matty); + Vector2.Transform(new Vector2(-0.2f, -0.7f), otherDockRotation), curGridToView); var collisionBR = Vector2.Transform(dock.Coordinates.Position + - Vector2.Transform(new Vector2(0.2f, -0.7f), otherDockRotation), matty); + Vector2.Transform(new Vector2(0.2f, -0.7f), otherDockRotation), curGridToView); var collisionTR = Vector2.Transform(dock.Coordinates.Position + - Vector2.Transform(new Vector2(0.2f, -0.5f), otherDockRotation), matty); + Vector2.Transform(new Vector2(0.2f, -0.5f), otherDockRotation), curGridToView); var collisionTL = Vector2.Transform(dock.Coordinates.Position + - Vector2.Transform(new Vector2(-0.2f, -0.5f), otherDockRotation), matty); + Vector2.Transform(new Vector2(-0.2f, -0.5f), otherDockRotation), curGridToView); var verts = new[] { @@ -181,13 +185,6 @@ public sealed partial class ShuttleDockControl : BaseShuttleControl collisionBL, }; - for (var i = 0; i < verts.Length; i++) - { - var vert = verts[i]; - vert.Y = -vert.Y; - verts[i] = ScalePosition(vert); - } - var collisionCenter = verts[0] + verts[1] + verts[3] + verts[5]; var otherDockConnection = Color.ToSrgb(Color.Pink); @@ -195,10 +192,10 @@ public sealed partial class ShuttleDockControl : BaseShuttleControl handle.DrawPrimitives(DrawPrimitiveTopology.LineList, verts, otherDockConnection); // Draw the dock itself - var dockBL = Vector2.Transform(dock.Coordinates.Position + new Vector2(-0.5f, -0.5f), matty); - var dockBR = Vector2.Transform(dock.Coordinates.Position + new Vector2(0.5f, -0.5f), matty); - var dockTR = Vector2.Transform(dock.Coordinates.Position + new Vector2(0.5f, 0.5f), matty); - var dockTL = Vector2.Transform(dock.Coordinates.Position + new Vector2(-0.5f, 0.5f), matty); + var dockBL = Vector2.Transform(dock.Coordinates.Position + new Vector2(-0.5f, -0.5f), curGridToView); + var dockBR = Vector2.Transform(dock.Coordinates.Position + new Vector2(0.5f, -0.5f), curGridToView); + var dockTR = Vector2.Transform(dock.Coordinates.Position + new Vector2(0.5f, 0.5f), curGridToView); + var dockTL = Vector2.Transform(dock.Coordinates.Position + new Vector2(-0.5f, 0.5f), curGridToView); verts = new[] { @@ -212,13 +209,6 @@ public sealed partial class ShuttleDockControl : BaseShuttleControl dockBL }; - for (var i = 0; i < verts.Length; i++) - { - var vert = verts[i]; - vert.Y = -vert.Y; - verts[i] = ScalePosition(vert); - } - Color otherDockColor; if (HighlightedDock == dock.Entity) @@ -253,9 +243,11 @@ public sealed partial class ShuttleDockControl : BaseShuttleControl collisionCenter /= 4; var range = viewedDockPos.Value - collisionCenter; - if (range.Length() < SharedDockingSystem.DockingHiglightRange * MinimapScale) + var maxRange = SharedDockingSystem.DockingHiglightRange * MinimapScale; + var maxRangeSq = maxRange * maxRange; + if (range.LengthSquared() < maxRangeSq) { - if (_viewedState?.GridDockedWith == null) + if (dock.GridDockedWith == null) { var coordsOne = EntManager.GetCoordinates(_viewedState!.Coordinates); var coordsTwo = EntManager.GetCoordinates(dock.Coordinates); @@ -265,10 +257,11 @@ public sealed partial class ShuttleDockControl : BaseShuttleControl var rotA = _xformSystem.GetWorldRotation(coordsOne.EntityId) + _viewedState!.Angle; var rotB = _xformSystem.GetWorldRotation(coordsTwo.EntityId) + dock.Angle; - var distance = (mapOne.Position - mapTwo.Position).Length(); + var distanceSq = (mapOne.Position - mapTwo.Position).LengthSquared(); var inAlignment = _dockSystem.InAlignment(mapOne, rotA, mapTwo, rotB); - var canDock = distance < SharedDockingSystem.DockRange && inAlignment; + var maxDockDistSq = SharedDockingSystem.DockRange * SharedDockingSystem.DockRange; + var canDock = distanceSq < maxDockDistSq && inAlignment; if (dockButton != null) dockButton.Disabled = !canDock || !canDockChange; @@ -297,7 +290,8 @@ public sealed partial class ShuttleDockControl : BaseShuttleControl { // Because it's being layed out top-down we have to arrange for first frame. container.Arrange(PixelRect); - var containerPos = scaledPos / UIScale - container.DesiredSize / 2 - new Vector2(0f, 0.75f) * MinimapScale; + var dockPositionInView = Vector2.Transform(dock.Coordinates.Position, curGridToView); + var containerPos = dockPositionInView / UIScale - container.DesiredSize / 2 - new Vector2(0f, 0.75f) * MinimapScale; SetPosition(container, containerPos); } diff --git a/Content.Client/Shuttles/UI/ShuttleNavControl.xaml.cs b/Content.Client/Shuttles/UI/ShuttleNavControl.xaml.cs index 2674343e05..805608c9a5 100644 --- a/Content.Client/Shuttles/UI/ShuttleNavControl.xaml.cs +++ b/Content.Client/Shuttles/UI/ShuttleNavControl.xaml.cs @@ -29,6 +29,11 @@ public sealed partial class ShuttleNavControl : BaseShuttleControl /// private EntityCoordinates? _coordinates; + /// + /// Entity of controlling console + /// + private EntityUid? _consoleEntity; + private Angle? _rotation; private Dictionary> _docks = new(); @@ -57,6 +62,11 @@ public sealed partial class ShuttleNavControl : BaseShuttleControl _rotation = angle; } + public void SetConsole(EntityUid? consoleEntity) + { + _consoleEntity = consoleEntity; + } + protected override void KeyBindUp(GUIBoundKeyEventArgs args) { base.KeyBindUp(args); @@ -139,40 +149,35 @@ public sealed partial class ShuttleNavControl : BaseShuttleControl } var mapPos = _transform.ToMapCoordinates(_coordinates.Value); - var offset = _coordinates.Value.Position; - var posMatrix = Matrix3Helpers.CreateTransform(offset, _rotation.Value); + var posMatrix = Matrix3Helpers.CreateTransform(_coordinates.Value.Position, _rotation.Value); var ourEntRot = RotateWithEntity ? _transform.GetWorldRotation(xform) : _rotation.Value; var ourEntMatrix = Matrix3Helpers.CreateTransform(_transform.GetWorldPosition(xform), ourEntRot); - var ourWorldMatrix = Matrix3x2.Multiply(posMatrix, ourEntMatrix); - Matrix3x2.Invert(ourWorldMatrix, out var ourWorldMatrixInvert); + var shuttleToWorld = Matrix3x2.Multiply(posMatrix, ourEntMatrix); + Matrix3x2.Invert(shuttleToWorld, out var worldToShuttle); + var shuttleToView = Matrix3x2.CreateScale(new Vector2(MinimapScale, -MinimapScale)) * Matrix3x2.CreateTranslation(MidPointVector); // Draw our grid in detail var ourGridId = xform.GridUid; if (EntManager.TryGetComponent(ourGridId, out var ourGrid) && fixturesQuery.HasComponent(ourGridId.Value)) { - var ourGridMatrix = _transform.GetWorldMatrix(ourGridId.Value); - var matrix = Matrix3x2.Multiply(ourGridMatrix, ourWorldMatrixInvert); + var ourGridToWorld = _transform.GetWorldMatrix(ourGridId.Value); + var ourGridToShuttle = Matrix3x2.Multiply(ourGridToWorld, worldToShuttle); + var ourGridToView = ourGridToShuttle * shuttleToView; var color = _shuttles.GetIFFColor(ourGridId.Value, self: true); - DrawGrid(handle, matrix, (ourGridId.Value, ourGrid), color); - DrawDocks(handle, ourGridId.Value, matrix); + DrawGrid(handle, ourGridToView, (ourGridId.Value, ourGrid), color); + DrawDocks(handle, ourGridId.Value, ourGridToView); } - var invertedPosition = _coordinates.Value.Position - offset; - invertedPosition.Y = -invertedPosition.Y; - // Don't need to transform the InvWorldMatrix again as it's already offset to its position. - // Draw radar position on the station - var radarPos = invertedPosition; const float radarVertRadius = 2f; - var radarPosVerts = new Vector2[] { - ScalePosition(radarPos + new Vector2(0f, -radarVertRadius)), - ScalePosition(radarPos + new Vector2(radarVertRadius / 2f, 0f)), - ScalePosition(radarPos + new Vector2(0f, radarVertRadius)), - ScalePosition(radarPos + new Vector2(radarVertRadius / -2f, 0f)), + ScalePosition(new Vector2(0f, -radarVertRadius)), + ScalePosition(new Vector2(radarVertRadius / 2f, 0f)), + ScalePosition(new Vector2(0f, radarVertRadius)), + ScalePosition(new Vector2(radarVertRadius / -2f, 0f)), }; handle.DrawPrimitives(DrawPrimitiveTopology.TriangleFan, radarPosVerts, Color.Lime); @@ -197,8 +202,8 @@ public sealed partial class ShuttleNavControl : BaseShuttleControl if (!_shuttles.CanDraw(gUid, gridBody, iff)) continue; - var gridMatrix = _transform.GetWorldMatrix(gUid); - var matty = Matrix3x2.Multiply(gridMatrix, ourWorldMatrixInvert); + var curGridToWorld = _transform.GetWorldMatrix(gUid); + var curGridToView = curGridToWorld * worldToShuttle * shuttleToView; var labelColor = _shuttles.GetIFFColor(grid, self: false, iff); var coordColor = new Color(labelColor.R * 0.8f, labelColor.G * 0.8f, labelColor.B * 0.8f, 0.5f); @@ -213,8 +218,7 @@ public sealed partial class ShuttleNavControl : BaseShuttleControl { var gridBounds = grid.Comp.LocalAABB; - var gridCentre = Vector2.Transform(gridBody.LocalCenter, matty); - gridCentre.Y = -gridCentre.Y; + var gridCentre = Vector2.Transform(gridBody.LocalCenter, curGridToView); var distance = gridCentre.Length(); var labelText = Loc.GetString("shuttle-console-iff-label", ("name", labelName), @@ -230,9 +234,8 @@ public sealed partial class ShuttleNavControl : BaseShuttleControl // y-offset the control to always render below the grid (vertically) var yOffset = Math.Max(gridBounds.Height, gridBounds.Width) * MinimapScale / 1.8f; - // The actual position in the UI. We centre the label by offsetting the matrix position - // by half the label's width, plus the y-offset - var gridScaledPosition = ScalePosition(gridCentre) - new Vector2(0, -yOffset); + // The actual position in the UI. + var gridScaledPosition = gridCentre - new Vector2(0, -yOffset); // Normalize the grid position if it exceeds the viewport bounds // normalizing it instead of clamping it preserves the direction of the vector and prevents corner-hugging @@ -264,18 +267,32 @@ public sealed partial class ShuttleNavControl : BaseShuttleControl } // Detailed view - var gridAABB = gridMatrix.TransformBox(grid.Comp.LocalAABB); + var gridAABB = curGridToWorld.TransformBox(grid.Comp.LocalAABB); // Skip drawing if it's out of range. if (!gridAABB.Intersects(viewAABB)) continue; - DrawGrid(handle, matty, grid, labelColor); - DrawDocks(handle, gUid, matty); + DrawGrid(handle, curGridToView, grid, labelColor); + DrawDocks(handle, gUid, curGridToView); } + + // If we've set the controlling console, and it's on a different grid + // to the shuttle itself, then draw an additional marker to help the + // player determine where they are relative to the shuttle. + if (_consoleEntity != null && xformQuery.TryGetComponent(_consoleEntity, out var consoleXform)) + { + if (consoleXform.ParentUid != _coordinates.Value.EntityId) + { + var consolePositionWorld = _transform.GetWorldPosition((EntityUid)_consoleEntity); + var p = Vector2.Transform(consolePositionWorld, worldToShuttle * shuttleToView); + handle.DrawCircle(p, 5, Color.ToSrgb(Color.Cyan), true); + } + } + } - private void DrawDocks(DrawingHandleScreen handle, EntityUid uid, Matrix3x2 matrix) + private void DrawDocks(DrawingHandleScreen handle, EntityUid uid, Matrix3x2 gridToView) { if (!ShowDocks) return; @@ -283,33 +300,32 @@ public sealed partial class ShuttleNavControl : BaseShuttleControl const float DockScale = 0.6f; var nent = EntManager.GetNetEntity(uid); + const float sqrt2 = 1.41421356f; + const float dockRadius = DockScale * sqrt2; + // Worst-case bounds used to cull a dock: + Box2 viewBounds = new Box2(-dockRadius, -dockRadius, Size.X + dockRadius, Size.Y + dockRadius); if (_docks.TryGetValue(nent, out var docks)) { foreach (var state in docks) { var position = state.Coordinates.Position; - var uiPosition = Vector2.Transform(position, matrix); - if (uiPosition.Length() > (WorldRange * 2f) - DockScale) + var positionInView = Vector2.Transform(position, gridToView); + if (!viewBounds.Contains(positionInView)) + { continue; + } var color = Color.ToSrgb(Color.Magenta); var verts = new[] { - Vector2.Transform(position + new Vector2(-DockScale, -DockScale), matrix), - Vector2.Transform(position + new Vector2(DockScale, -DockScale), matrix), - Vector2.Transform(position + new Vector2(DockScale, DockScale), matrix), - Vector2.Transform(position + new Vector2(-DockScale, DockScale), matrix), + Vector2.Transform(position + new Vector2(-DockScale, -DockScale), gridToView), + Vector2.Transform(position + new Vector2(DockScale, -DockScale), gridToView), + Vector2.Transform(position + new Vector2(DockScale, DockScale), gridToView), + Vector2.Transform(position + new Vector2(-DockScale, DockScale), gridToView), }; - for (var i = 0; i < verts.Length; i++) - { - var vert = verts[i]; - vert.Y = -vert.Y; - verts[i] = ScalePosition(vert); - } - handle.DrawPrimitives(DrawPrimitiveTopology.TriangleFan, verts, color.WithAlpha(0.8f)); handle.DrawPrimitives(DrawPrimitiveTopology.LineStrip, verts, color); } diff --git a/Content.Client/UserInterface/Systems/Chat/Widgets/ChatBox.xaml.cs b/Content.Client/UserInterface/Systems/Chat/Widgets/ChatBox.xaml.cs index 07b7134fd3..d55b3f01df 100644 --- a/Content.Client/UserInterface/Systems/Chat/Widgets/ChatBox.xaml.cs +++ b/Content.Client/UserInterface/Systems/Chat/Widgets/ChatBox.xaml.cs @@ -18,9 +18,8 @@ using static Robust.Client.UserInterface.Controls.LineEdit; namespace Content.Client.UserInterface.Systems.Chat.Widgets; [GenerateTypedNameReferences] -#pragma warning disable RA0003 +[Virtual] public partial class ChatBox : UIWidget -#pragma warning restore RA0003 { private readonly ChatUIController _controller; private readonly IEntityManager _entManager; diff --git a/Content.Client/UserInterface/Systems/Ghost/Controls/Roles/GhostRolesWindow.xaml.cs b/Content.Client/UserInterface/Systems/Ghost/Controls/Roles/GhostRolesWindow.xaml.cs index 35ee9e0773..f10ab7d95b 100644 --- a/Content.Client/UserInterface/Systems/Ghost/Controls/Roles/GhostRolesWindow.xaml.cs +++ b/Content.Client/UserInterface/Systems/Ghost/Controls/Roles/GhostRolesWindow.xaml.cs @@ -71,6 +71,7 @@ namespace Content.Client.UserInterface.Systems.Ghost.Controls.Roles buttonHeading.AddStyleClass(ContainerButton.StyleClassButton); buttonHeading.Label.HorizontalAlignment = HAlignment.Center; buttonHeading.Label.HorizontalExpand = true; + buttonHeading.Margin = new Thickness(8, 0, 8, 2); var body = new CollapsibleBody { diff --git a/Content.Client/UserInterface/Systems/MenuBar/Widgets/GameTopMenuBar.xaml b/Content.Client/UserInterface/Systems/MenuBar/Widgets/GameTopMenuBar.xaml index dc8972970a..5368d5d872 100644 --- a/Content.Client/UserInterface/Systems/MenuBar/Widgets/GameTopMenuBar.xaml +++ b/Content.Client/UserInterface/Systems/MenuBar/Widgets/GameTopMenuBar.xaml @@ -11,17 +11,21 @@ Orientation="Horizontal" HorizontalAlignment="Stretch" VerticalAlignment="Top" - SeparationOverride="5" > + @@ -39,7 +43,7 @@ Icon="{xe:Tex '/Textures/Interface/character.svg.192dpi.png'}" ToolTip="{Loc 'game-hud-open-character-menu-button-tooltip'}" BoundKey = "{x:Static is:ContentKeyFunctions.OpenCharacterMenu}" - MinSize="42 64" + MinSize="48 64" HorizontalExpand="True" AppendStyleClass="{x:Static style:StyleBase.ButtonSquare}" /> @@ -49,7 +53,7 @@ Icon="{xe:Tex '/Textures/Interface/emotes.svg.192dpi.png'}" ToolTip="{Loc 'game-hud-open-emotes-menu-button-tooltip'}" BoundKey = "{x:Static is:ContentKeyFunctions.OpenEmotesMenu}" - MinSize="42 64" + MinSize="48 64" HorizontalExpand="True" AppendStyleClass="{x:Static style:StyleBase.ButtonSquare}" /> @@ -59,7 +63,7 @@ Icon="{xe:Tex '/Textures/Interface/hammer.svg.192dpi.png'}" BoundKey = "{x:Static is:ContentKeyFunctions.OpenCraftingMenu}" ToolTip="{Loc 'game-hud-open-crafting-menu-button-tooltip'}" - MinSize="42 64" + MinSize="48 64" HorizontalExpand="True" AppendStyleClass="{x:Static style:StyleBase.ButtonSquare}" /> @@ -69,7 +73,7 @@ Icon="{xe:Tex '/Textures/Interface/fist.svg.192dpi.png'}" BoundKey = "{x:Static is:ContentKeyFunctions.OpenActionsMenu}" ToolTip="{Loc 'game-hud-open-actions-menu-button-tooltip'}" - MinSize="42 64" + MinSize="48 64" HorizontalExpand="True" AppendStyleClass="{x:Static style:StyleBase.ButtonSquare}" /> @@ -79,7 +83,7 @@ Icon="{xe:Tex '/Textures/Interface/gavel.svg.192dpi.png'}" BoundKey = "{x:Static is:ContentKeyFunctions.OpenAdminMenu}" ToolTip="{Loc 'game-hud-open-admin-menu-button-tooltip'}" - MinSize="42 64" + MinSize="48 64" HorizontalExpand="True" AppendStyleClass="{x:Static style:StyleBase.ButtonSquare}" /> @@ -89,7 +93,7 @@ Icon="{xe:Tex '/Textures/Interface/sandbox.svg.192dpi.png'}" BoundKey = "{x:Static is:ContentKeyFunctions.OpenSandboxWindow}" ToolTip="{Loc 'game-hud-open-sandbox-menu-button-tooltip'}" - MinSize="42 64" + MinSize="48 64" HorizontalExpand="True" AppendStyleClass="{x:Static style:StyleBase.ButtonSquare}" /> @@ -99,8 +103,9 @@ Icon="{xe:Tex '/Textures/Interface/info.svg.192dpi.png'}" BoundKey = "{x:Static is:ContentKeyFunctions.OpenAHelp}" ToolTip="{Loc 'ui-options-function-open-a-help'}" - MinSize="42 64" + MinSize="48 64" HorizontalExpand="True" - AppendStyleClass="{x:Static style:StyleBase.ButtonOpenLeft}" + AppendStyleClass="{x:Static style:StyleBase.ButtonSquare}" /> + diff --git a/Content.IntegrationTests/Tests/Commands/PardonCommand.cs b/Content.IntegrationTests/Tests/Commands/PardonCommand.cs index 4db9eabf5c..9e57cd4b0e 100644 --- a/Content.IntegrationTests/Tests/Commands/PardonCommand.cs +++ b/Content.IntegrationTests/Tests/Commands/PardonCommand.cs @@ -32,9 +32,9 @@ namespace Content.IntegrationTests.Tests.Commands // No bans on record Assert.Multiple(async () => { - Assert.That(await sDatabase.GetServerBanAsync(null, clientId, null), Is.Null); + Assert.That(await sDatabase.GetServerBanAsync(null, clientId, null, null), Is.Null); Assert.That(await sDatabase.GetServerBanAsync(1), Is.Null); - Assert.That(await sDatabase.GetServerBansAsync(null, clientId, null), Is.Empty); + Assert.That(await sDatabase.GetServerBansAsync(null, clientId, null, null), Is.Empty); }); // Try to pardon a ban that does not exist @@ -43,9 +43,9 @@ namespace Content.IntegrationTests.Tests.Commands // Still no bans on record Assert.Multiple(async () => { - Assert.That(await sDatabase.GetServerBanAsync(null, clientId, null), Is.Null); + Assert.That(await sDatabase.GetServerBanAsync(null, clientId, null, null), Is.Null); Assert.That(await sDatabase.GetServerBanAsync(1), Is.Null); - Assert.That(await sDatabase.GetServerBansAsync(null, clientId, null), Is.Empty); + Assert.That(await sDatabase.GetServerBansAsync(null, clientId, null, null), Is.Empty); }); var banReason = "test"; @@ -57,9 +57,9 @@ namespace Content.IntegrationTests.Tests.Commands // Should have one ban on record now Assert.Multiple(async () => { - Assert.That(await sDatabase.GetServerBanAsync(null, clientId, null), Is.Not.Null); + Assert.That(await sDatabase.GetServerBanAsync(null, clientId, null, null), Is.Not.Null); Assert.That(await sDatabase.GetServerBanAsync(1), Is.Not.Null); - Assert.That(await sDatabase.GetServerBansAsync(null, clientId, null), Has.Count.EqualTo(1)); + Assert.That(await sDatabase.GetServerBansAsync(null, clientId, null, null), Has.Count.EqualTo(1)); }); await pair.RunTicksSync(5); @@ -70,13 +70,13 @@ namespace Content.IntegrationTests.Tests.Commands await server.WaitPost(() => sConsole.ExecuteCommand("pardon 2")); // The existing ban is unaffected - Assert.That(await sDatabase.GetServerBanAsync(null, clientId, null), Is.Not.Null); + Assert.That(await sDatabase.GetServerBanAsync(null, clientId, null, null), Is.Not.Null); var ban = await sDatabase.GetServerBanAsync(1); Assert.Multiple(async () => { Assert.That(ban, Is.Not.Null); - Assert.That(await sDatabase.GetServerBansAsync(null, clientId, null), Has.Count.EqualTo(1)); + Assert.That(await sDatabase.GetServerBansAsync(null, clientId, null, null), Has.Count.EqualTo(1)); // Check that it matches Assert.That(ban.Id, Is.EqualTo(1)); @@ -95,7 +95,7 @@ namespace Content.IntegrationTests.Tests.Commands await server.WaitPost(() => sConsole.ExecuteCommand("pardon 1")); // No bans should be returned - Assert.That(await sDatabase.GetServerBanAsync(null, clientId, null), Is.Null); + Assert.That(await sDatabase.GetServerBanAsync(null, clientId, null, null), Is.Null); // Direct id lookup returns a pardoned ban var pardonedBan = await sDatabase.GetServerBanAsync(1); @@ -105,7 +105,7 @@ namespace Content.IntegrationTests.Tests.Commands Assert.That(pardonedBan, Is.Not.Null); // The list is still returned since that ignores pardons - Assert.That(await sDatabase.GetServerBansAsync(null, clientId, null), Has.Count.EqualTo(1)); + Assert.That(await sDatabase.GetServerBansAsync(null, clientId, null, null), Has.Count.EqualTo(1)); Assert.That(pardonedBan.Id, Is.EqualTo(1)); Assert.That(pardonedBan.UserId, Is.EqualTo(clientId)); @@ -133,13 +133,13 @@ namespace Content.IntegrationTests.Tests.Commands Assert.Multiple(async () => { // No bans should be returned - Assert.That(await sDatabase.GetServerBanAsync(null, clientId, null), Is.Null); + Assert.That(await sDatabase.GetServerBanAsync(null, clientId, null, null), Is.Null); // Direct id lookup returns a pardoned ban Assert.That(await sDatabase.GetServerBanAsync(1), Is.Not.Null); // The list is still returned since that ignores pardons - Assert.That(await sDatabase.GetServerBansAsync(null, clientId, null), Has.Count.EqualTo(1)); + Assert.That(await sDatabase.GetServerBansAsync(null, clientId, null, null), Has.Count.EqualTo(1)); }); // Reconnect client. Slightly faster than dirtying the pair. diff --git a/Content.Server.Database/Migrations/Postgres/20241111170112_ModernHwid.Designer.cs b/Content.Server.Database/Migrations/Postgres/20241111170112_ModernHwid.Designer.cs new file mode 100644 index 0000000000..155d6a163f --- /dev/null +++ b/Content.Server.Database/Migrations/Postgres/20241111170112_ModernHwid.Designer.cs @@ -0,0 +1,2072 @@ +// +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("20241111170112_ModernHwid")] + partial class ModernHwid + { + /// + 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.BanTemplate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("ban_template_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AutoDelete") + .HasColumnType("boolean") + .HasColumnName("auto_delete"); + + b.Property("ExemptFlags") + .HasColumnType("integer") + .HasColumnName("exempt_flags"); + + b.Property("Hidden") + .HasColumnType("boolean") + .HasColumnName("hidden"); + + b.Property("Length") + .HasColumnType("interval") + .HasColumnName("length"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("text") + .HasColumnName("reason"); + + b.Property("Severity") + .HasColumnType("integer") + .HasColumnName("severity"); + + b.Property("Title") + .IsRequired() + .HasColumnType("text") + .HasColumnName("title"); + + b.HasKey("Id") + .HasName("PK_ban_template"); + + b.ToTable("ban_template", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Blacklist", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.HasKey("UserId") + .HasName("PK_blacklist"); + + b.ToTable("blacklist", (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("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("Time"); + + 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("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("CharacterName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("char_name"); + + 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.ProfileLoadout", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("profile_loadout_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("LoadoutName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("loadout_name"); + + b.Property("ProfileLoadoutGroupId") + .HasColumnType("integer") + .HasColumnName("profile_loadout_group_id"); + + b.HasKey("Id") + .HasName("PK_profile_loadout"); + + b.HasIndex("ProfileLoadoutGroupId"); + + b.ToTable("profile_loadout", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileLoadoutGroup", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("profile_loadout_group_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("GroupName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("group_name"); + + b.Property("ProfileRoleLoadoutId") + .HasColumnType("integer") + .HasColumnName("profile_role_loadout_id"); + + b.HasKey("Id") + .HasName("PK_profile_loadout_group"); + + b.HasIndex("ProfileRoleLoadoutId"); + + b.ToTable("profile_loadout_group", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileRoleLoadout", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("profile_role_loadout_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ProfileId") + .HasColumnType("integer") + .HasColumnName("profile_id"); + + b.Property("RoleName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("role_name"); + + b.HasKey("Id") + .HasName("PK_profile_role_loadout"); + + b.HasIndex("ProfileId"); + + b.ToTable("profile_role_loadout", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.RoleWhitelist", b => + { + b.Property("PlayerUserId") + .HasColumnType("uuid") + .HasColumnName("player_user_id"); + + b.Property("RoleId") + .HasColumnType("text") + .HasColumnName("role_id"); + + b.HasKey("PlayerUserId", "RoleId") + .HasName("PK_role_whitelists"); + + b.ToTable("role_whitelists", (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") + .HasColumnType("timestamp with time zone") + .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("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("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.OwnsOne("Content.Server.Database.TypedHwid", "HWId", b1 => + { + b1.Property("ConnectionLogId") + .HasColumnType("integer") + .HasColumnName("connection_log_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("bytea") + .HasColumnName("hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0) + .HasColumnName("hwid_type"); + + b1.HasKey("ConnectionLogId"); + + b1.ToTable("connection_log"); + + b1.WithOwner() + .HasForeignKey("ConnectionLogId") + .HasConstraintName("FK_connection_log_connection_log_connection_log_id"); + }); + + b.Navigation("HWId"); + + 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.Player", b => + { + b.OwnsOne("Content.Server.Database.TypedHwid", "LastSeenHWId", b1 => + { + b1.Property("PlayerId") + .HasColumnType("integer") + .HasColumnName("player_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("bytea") + .HasColumnName("last_seen_hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0) + .HasColumnName("last_seen_hwid_type"); + + b1.HasKey("PlayerId"); + + b1.ToTable("player"); + + b1.WithOwner() + .HasForeignKey("PlayerId") + .HasConstraintName("FK_player_player_player_id"); + }); + + b.Navigation("LastSeenHWId"); + }); + + 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.ProfileLoadout", b => + { + b.HasOne("Content.Server.Database.ProfileLoadoutGroup", "ProfileLoadoutGroup") + .WithMany("Loadouts") + .HasForeignKey("ProfileLoadoutGroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_profile_loadout_profile_loadout_group_profile_loadout_group~"); + + b.Navigation("ProfileLoadoutGroup"); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileLoadoutGroup", b => + { + b.HasOne("Content.Server.Database.ProfileRoleLoadout", "ProfileRoleLoadout") + .WithMany("Groups") + .HasForeignKey("ProfileRoleLoadoutId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_profile_loadout_group_profile_role_loadout_profile_role_loa~"); + + b.Navigation("ProfileRoleLoadout"); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileRoleLoadout", b => + { + b.HasOne("Content.Server.Database.Profile", "Profile") + .WithMany("Loadouts") + .HasForeignKey("ProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_profile_role_loadout_profile_profile_id"); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("Content.Server.Database.RoleWhitelist", b => + { + b.HasOne("Content.Server.Database.Player", "Player") + .WithMany("JobWhitelists") + .HasForeignKey("PlayerUserId") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_role_whitelists_player_player_user_id"); + + b.Navigation("Player"); + }); + + 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.OwnsOne("Content.Server.Database.TypedHwid", "HWId", b1 => + { + b1.Property("ServerBanId") + .HasColumnType("integer") + .HasColumnName("server_ban_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("bytea") + .HasColumnName("hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0) + .HasColumnName("hwid_type"); + + b1.HasKey("ServerBanId"); + + b1.ToTable("server_ban"); + + b1.WithOwner() + .HasForeignKey("ServerBanId") + .HasConstraintName("FK_server_ban_server_ban_server_ban_id"); + }); + + b.Navigation("CreatedBy"); + + b.Navigation("HWId"); + + 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.OwnsOne("Content.Server.Database.TypedHwid", "HWId", b1 => + { + b1.Property("ServerRoleBanId") + .HasColumnType("integer") + .HasColumnName("server_role_ban_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("bytea") + .HasColumnName("hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0) + .HasColumnName("hwid_type"); + + b1.HasKey("ServerRoleBanId"); + + b1.ToTable("server_role_ban"); + + b1.WithOwner() + .HasForeignKey("ServerRoleBanId") + .HasConstraintName("FK_server_role_ban_server_role_ban_server_role_ban_id"); + }); + + b.Navigation("CreatedBy"); + + b.Navigation("HWId"); + + 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"); + + b.Navigation("JobWhitelists"); + }); + + 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("Loadouts"); + + b.Navigation("Traits"); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileLoadoutGroup", b => + { + b.Navigation("Loadouts"); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileRoleLoadout", b => + { + b.Navigation("Groups"); + }); + + 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/20241111170112_ModernHwid.cs b/Content.Server.Database/Migrations/Postgres/20241111170112_ModernHwid.cs new file mode 100644 index 0000000000..c70a5ffaa5 --- /dev/null +++ b/Content.Server.Database/Migrations/Postgres/20241111170112_ModernHwid.cs @@ -0,0 +1,62 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Content.Server.Database.Migrations.Postgres +{ + /// + public partial class ModernHwid : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "hwid_type", + table: "server_role_ban", + type: "integer", + nullable: true, + defaultValue: 0); + + migrationBuilder.AddColumn( + name: "hwid_type", + table: "server_ban", + type: "integer", + nullable: true, + defaultValue: 0); + + migrationBuilder.AddColumn( + name: "last_seen_hwid_type", + table: "player", + type: "integer", + nullable: true, + defaultValue: 0); + + migrationBuilder.AddColumn( + name: "hwid_type", + table: "connection_log", + type: "integer", + nullable: true, + defaultValue: 0); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "hwid_type", + table: "server_role_ban"); + + migrationBuilder.DropColumn( + name: "hwid_type", + table: "server_ban"); + + migrationBuilder.DropColumn( + name: "last_seen_hwid_type", + table: "player"); + + migrationBuilder.DropColumn( + name: "hwid_type", + table: "connection_log"); + } + } +} diff --git a/Content.Server.Database/Migrations/Postgres/20241111193608_ConnectionTrust.Designer.cs b/Content.Server.Database/Migrations/Postgres/20241111193608_ConnectionTrust.Designer.cs new file mode 100644 index 0000000000..dc1b4a0eeb --- /dev/null +++ b/Content.Server.Database/Migrations/Postgres/20241111193608_ConnectionTrust.Designer.cs @@ -0,0 +1,2076 @@ +// +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("20241111193608_ConnectionTrust")] + partial class ConnectionTrust + { + /// + 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.BanTemplate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("ban_template_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AutoDelete") + .HasColumnType("boolean") + .HasColumnName("auto_delete"); + + b.Property("ExemptFlags") + .HasColumnType("integer") + .HasColumnName("exempt_flags"); + + b.Property("Hidden") + .HasColumnType("boolean") + .HasColumnName("hidden"); + + b.Property("Length") + .HasColumnType("interval") + .HasColumnName("length"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("text") + .HasColumnName("reason"); + + b.Property("Severity") + .HasColumnType("integer") + .HasColumnName("severity"); + + b.Property("Title") + .IsRequired() + .HasColumnType("text") + .HasColumnName("title"); + + b.HasKey("Id") + .HasName("PK_ban_template"); + + b.ToTable("ban_template", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Blacklist", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.HasKey("UserId") + .HasName("PK_blacklist"); + + b.ToTable("blacklist", (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("ServerId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0) + .HasColumnName("server_id"); + + b.Property("Time") + .HasColumnType("timestamp with time zone") + .HasColumnName("time"); + + b.Property("Trust") + .HasColumnType("real") + .HasColumnName("trust"); + + 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("Time"); + + 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("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("CharacterName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("char_name"); + + 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.ProfileLoadout", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("profile_loadout_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("LoadoutName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("loadout_name"); + + b.Property("ProfileLoadoutGroupId") + .HasColumnType("integer") + .HasColumnName("profile_loadout_group_id"); + + b.HasKey("Id") + .HasName("PK_profile_loadout"); + + b.HasIndex("ProfileLoadoutGroupId"); + + b.ToTable("profile_loadout", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileLoadoutGroup", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("profile_loadout_group_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("GroupName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("group_name"); + + b.Property("ProfileRoleLoadoutId") + .HasColumnType("integer") + .HasColumnName("profile_role_loadout_id"); + + b.HasKey("Id") + .HasName("PK_profile_loadout_group"); + + b.HasIndex("ProfileRoleLoadoutId"); + + b.ToTable("profile_loadout_group", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileRoleLoadout", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("profile_role_loadout_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ProfileId") + .HasColumnType("integer") + .HasColumnName("profile_id"); + + b.Property("RoleName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("role_name"); + + b.HasKey("Id") + .HasName("PK_profile_role_loadout"); + + b.HasIndex("ProfileId"); + + b.ToTable("profile_role_loadout", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.RoleWhitelist", b => + { + b.Property("PlayerUserId") + .HasColumnType("uuid") + .HasColumnName("player_user_id"); + + b.Property("RoleId") + .HasColumnType("text") + .HasColumnName("role_id"); + + b.HasKey("PlayerUserId", "RoleId") + .HasName("PK_role_whitelists"); + + b.ToTable("role_whitelists", (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") + .HasColumnType("timestamp with time zone") + .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("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("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.OwnsOne("Content.Server.Database.TypedHwid", "HWId", b1 => + { + b1.Property("ConnectionLogId") + .HasColumnType("integer") + .HasColumnName("connection_log_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("bytea") + .HasColumnName("hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0) + .HasColumnName("hwid_type"); + + b1.HasKey("ConnectionLogId"); + + b1.ToTable("connection_log"); + + b1.WithOwner() + .HasForeignKey("ConnectionLogId") + .HasConstraintName("FK_connection_log_connection_log_connection_log_id"); + }); + + b.Navigation("HWId"); + + 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.Player", b => + { + b.OwnsOne("Content.Server.Database.TypedHwid", "LastSeenHWId", b1 => + { + b1.Property("PlayerId") + .HasColumnType("integer") + .HasColumnName("player_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("bytea") + .HasColumnName("last_seen_hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0) + .HasColumnName("last_seen_hwid_type"); + + b1.HasKey("PlayerId"); + + b1.ToTable("player"); + + b1.WithOwner() + .HasForeignKey("PlayerId") + .HasConstraintName("FK_player_player_player_id"); + }); + + b.Navigation("LastSeenHWId"); + }); + + 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.ProfileLoadout", b => + { + b.HasOne("Content.Server.Database.ProfileLoadoutGroup", "ProfileLoadoutGroup") + .WithMany("Loadouts") + .HasForeignKey("ProfileLoadoutGroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_profile_loadout_profile_loadout_group_profile_loadout_group~"); + + b.Navigation("ProfileLoadoutGroup"); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileLoadoutGroup", b => + { + b.HasOne("Content.Server.Database.ProfileRoleLoadout", "ProfileRoleLoadout") + .WithMany("Groups") + .HasForeignKey("ProfileRoleLoadoutId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_profile_loadout_group_profile_role_loadout_profile_role_loa~"); + + b.Navigation("ProfileRoleLoadout"); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileRoleLoadout", b => + { + b.HasOne("Content.Server.Database.Profile", "Profile") + .WithMany("Loadouts") + .HasForeignKey("ProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_profile_role_loadout_profile_profile_id"); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("Content.Server.Database.RoleWhitelist", b => + { + b.HasOne("Content.Server.Database.Player", "Player") + .WithMany("JobWhitelists") + .HasForeignKey("PlayerUserId") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_role_whitelists_player_player_user_id"); + + b.Navigation("Player"); + }); + + 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.OwnsOne("Content.Server.Database.TypedHwid", "HWId", b1 => + { + b1.Property("ServerBanId") + .HasColumnType("integer") + .HasColumnName("server_ban_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("bytea") + .HasColumnName("hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0) + .HasColumnName("hwid_type"); + + b1.HasKey("ServerBanId"); + + b1.ToTable("server_ban"); + + b1.WithOwner() + .HasForeignKey("ServerBanId") + .HasConstraintName("FK_server_ban_server_ban_server_ban_id"); + }); + + b.Navigation("CreatedBy"); + + b.Navigation("HWId"); + + 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.OwnsOne("Content.Server.Database.TypedHwid", "HWId", b1 => + { + b1.Property("ServerRoleBanId") + .HasColumnType("integer") + .HasColumnName("server_role_ban_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("bytea") + .HasColumnName("hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0) + .HasColumnName("hwid_type"); + + b1.HasKey("ServerRoleBanId"); + + b1.ToTable("server_role_ban"); + + b1.WithOwner() + .HasForeignKey("ServerRoleBanId") + .HasConstraintName("FK_server_role_ban_server_role_ban_server_role_ban_id"); + }); + + b.Navigation("CreatedBy"); + + b.Navigation("HWId"); + + 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"); + + b.Navigation("JobWhitelists"); + }); + + 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("Loadouts"); + + b.Navigation("Traits"); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileLoadoutGroup", b => + { + b.Navigation("Loadouts"); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileRoleLoadout", b => + { + b.Navigation("Groups"); + }); + + 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/20241111193608_ConnectionTrust.cs b/Content.Server.Database/Migrations/Postgres/20241111193608_ConnectionTrust.cs new file mode 100644 index 0000000000..debb36aacc --- /dev/null +++ b/Content.Server.Database/Migrations/Postgres/20241111193608_ConnectionTrust.cs @@ -0,0 +1,29 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Content.Server.Database.Migrations.Postgres +{ + /// + public partial class ConnectionTrust : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "trust", + table: "connection_log", + type: "real", + nullable: false, + defaultValue: 0f); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "trust", + table: "connection_log"); + } + } +} diff --git a/Content.Server.Database/Migrations/Postgres/PostgresServerDbContextModelSnapshot.cs b/Content.Server.Database/Migrations/Postgres/PostgresServerDbContextModelSnapshot.cs index 618d5e6ebd..d9c79f74d8 100644 --- a/Content.Server.Database/Migrations/Postgres/PostgresServerDbContextModelSnapshot.cs +++ b/Content.Server.Database/Migrations/Postgres/PostgresServerDbContextModelSnapshot.cs @@ -512,20 +512,6 @@ namespace Content.Server.Database.Migrations.Postgres b.ToTable("assigned_user_id", (string)null); }); - modelBuilder.Entity("Content.Server.Database.Blacklist", - b => - { - b.Property("UserId") - .ValueGeneratedOnAdd() - .HasColumnType("uuid") - .HasColumnName("user_id"); - - b.HasKey("UserId") - .HasName("PK_blacklist"); - - b.ToTable("blacklist", (string) null); - }); - modelBuilder.Entity("Content.Server.Database.BanTemplate", b => { b.Property("Id") @@ -571,6 +557,19 @@ namespace Content.Server.Database.Migrations.Postgres b.ToTable("ban_template", (string)null); }); + modelBuilder.Entity("Content.Server.Database.Blacklist", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.HasKey("UserId") + .HasName("PK_blacklist"); + + b.ToTable("blacklist", (string)null); + }); + modelBuilder.Entity("Content.Server.Database.ConnectionLog", b => { b.Property("Id") @@ -589,10 +588,6 @@ namespace Content.Server.Database.Migrations.Postgres .HasColumnType("smallint") .HasColumnName("denied"); - b.Property("HWId") - .HasColumnType("bytea") - .HasColumnName("hwid"); - b.Property("ServerId") .ValueGeneratedOnAdd() .HasColumnType("integer") @@ -603,6 +598,10 @@ namespace Content.Server.Database.Migrations.Postgres .HasColumnType("timestamp with time zone") .HasColumnName("time"); + b.Property("Trust") + .HasColumnType("real") + .HasColumnName("trust"); + b.Property("UserId") .HasColumnType("uuid") .HasColumnName("user_id"); @@ -718,10 +717,6 @@ namespace Content.Server.Database.Migrations.Postgres .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"); @@ -1065,10 +1060,6 @@ namespace Content.Server.Database.Migrations.Postgres .HasColumnType("timestamp with time zone") .HasColumnName("expiration_time"); - b.Property("HWId") - .HasColumnType("bytea") - .HasColumnName("hwid"); - b.Property("Hidden") .HasColumnType("boolean") .HasColumnName("hidden"); @@ -1199,10 +1190,6 @@ namespace Content.Server.Database.Migrations.Postgres .HasColumnType("timestamp with time zone") .HasColumnName("expiration_time"); - b.Property("HWId") - .HasColumnType("bytea") - .HasColumnName("hwid"); - b.Property("Hidden") .HasColumnType("boolean") .HasColumnName("hidden"); @@ -1644,6 +1631,34 @@ namespace Content.Server.Database.Migrations.Postgres .IsRequired() .HasConstraintName("FK_connection_log_server_server_id"); + b.OwnsOne("Content.Server.Database.TypedHwid", "HWId", b1 => + { + b1.Property("ConnectionLogId") + .HasColumnType("integer") + .HasColumnName("connection_log_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("bytea") + .HasColumnName("hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0) + .HasColumnName("hwid_type"); + + b1.HasKey("ConnectionLogId"); + + b1.ToTable("connection_log"); + + b1.WithOwner() + .HasForeignKey("ConnectionLogId") + .HasConstraintName("FK_connection_log_connection_log_connection_log_id"); + }); + + b.Navigation("HWId"); + b.Navigation("Server"); }); @@ -1659,6 +1674,37 @@ namespace Content.Server.Database.Migrations.Postgres b.Navigation("Profile"); }); + modelBuilder.Entity("Content.Server.Database.Player", b => + { + b.OwnsOne("Content.Server.Database.TypedHwid", "LastSeenHWId", b1 => + { + b1.Property("PlayerId") + .HasColumnType("integer") + .HasColumnName("player_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("bytea") + .HasColumnName("last_seen_hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0) + .HasColumnName("last_seen_hwid_type"); + + b1.HasKey("PlayerId"); + + b1.ToTable("player"); + + b1.WithOwner() + .HasForeignKey("PlayerId") + .HasConstraintName("FK_player_player_player_id"); + }); + + b.Navigation("LastSeenHWId"); + }); + modelBuilder.Entity("Content.Server.Database.Profile", b => { b.HasOne("Content.Server.Database.Preference", "Preference") @@ -1753,8 +1799,36 @@ namespace Content.Server.Database.Migrations.Postgres .HasForeignKey("RoundId") .HasConstraintName("FK_server_ban_round_round_id"); + b.OwnsOne("Content.Server.Database.TypedHwid", "HWId", b1 => + { + b1.Property("ServerBanId") + .HasColumnType("integer") + .HasColumnName("server_ban_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("bytea") + .HasColumnName("hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0) + .HasColumnName("hwid_type"); + + b1.HasKey("ServerBanId"); + + b1.ToTable("server_ban"); + + b1.WithOwner() + .HasForeignKey("ServerBanId") + .HasConstraintName("FK_server_ban_server_ban_server_ban_id"); + }); + b.Navigation("CreatedBy"); + b.Navigation("HWId"); + b.Navigation("LastEditedBy"); b.Navigation("Round"); @@ -1802,8 +1876,36 @@ namespace Content.Server.Database.Migrations.Postgres .HasForeignKey("RoundId") .HasConstraintName("FK_server_role_ban_round_round_id"); + b.OwnsOne("Content.Server.Database.TypedHwid", "HWId", b1 => + { + b1.Property("ServerRoleBanId") + .HasColumnType("integer") + .HasColumnName("server_role_ban_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("bytea") + .HasColumnName("hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0) + .HasColumnName("hwid_type"); + + b1.HasKey("ServerRoleBanId"); + + b1.ToTable("server_role_ban"); + + b1.WithOwner() + .HasForeignKey("ServerRoleBanId") + .HasConstraintName("FK_server_role_ban_server_role_ban_server_role_ban_id"); + }); + b.Navigation("CreatedBy"); + b.Navigation("HWId"); + b.Navigation("LastEditedBy"); b.Navigation("Round"); diff --git a/Content.Server.Database/Migrations/Sqlite/20241111170107_ModernHwid.Designer.cs b/Content.Server.Database/Migrations/Sqlite/20241111170107_ModernHwid.Designer.cs new file mode 100644 index 0000000000..56a9fe0a05 --- /dev/null +++ b/Content.Server.Database/Migrations/Sqlite/20241111170107_ModernHwid.Designer.cs @@ -0,0 +1,1995 @@ +// +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("20241111170107_ModernHwid")] + partial class ModernHwid + { + /// + 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("LogId") + .HasColumnType("INTEGER") + .HasColumnName("log_id"); + + b.Property("PlayerUserId") + .HasColumnType("TEXT") + .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"); + + b.Property("CreatedAt") + .HasColumnType("TEXT") + .HasColumnName("created_at"); + + b.Property("CreatedById") + .HasColumnType("TEXT") + .HasColumnName("created_by_id"); + + b.Property("Deleted") + .HasColumnType("INTEGER") + .HasColumnName("deleted"); + + b.Property("DeletedAt") + .HasColumnType("TEXT") + .HasColumnName("deleted_at"); + + b.Property("DeletedById") + .HasColumnType("TEXT") + .HasColumnName("deleted_by_id"); + + b.Property("Dismissed") + .HasColumnType("INTEGER") + .HasColumnName("dismissed"); + + b.Property("ExpirationTime") + .HasColumnType("TEXT") + .HasColumnName("expiration_time"); + + b.Property("LastEditedAt") + .HasColumnType("TEXT") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("TEXT") + .HasColumnName("last_edited_by_id"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(4096) + .HasColumnType("TEXT") + .HasColumnName("message"); + + b.Property("PlayerUserId") + .HasColumnType("TEXT") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("TEXT") + .HasColumnName("playtime_at_note"); + + b.Property("RoundId") + .HasColumnType("INTEGER") + .HasColumnName("round_id"); + + b.Property("Seen") + .HasColumnType("INTEGER") + .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"); + + b.Property("CreatedAt") + .HasColumnType("TEXT") + .HasColumnName("created_at"); + + b.Property("CreatedById") + .HasColumnType("TEXT") + .HasColumnName("created_by_id"); + + b.Property("Deleted") + .HasColumnType("INTEGER") + .HasColumnName("deleted"); + + b.Property("DeletedAt") + .HasColumnType("TEXT") + .HasColumnName("deleted_at"); + + b.Property("DeletedById") + .HasColumnType("TEXT") + .HasColumnName("deleted_by_id"); + + b.Property("ExpirationTime") + .HasColumnType("TEXT") + .HasColumnName("expiration_time"); + + b.Property("LastEditedAt") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("TEXT") + .HasColumnName("last_edited_by_id"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(4096) + .HasColumnType("TEXT") + .HasColumnName("message"); + + b.Property("PlayerUserId") + .HasColumnType("TEXT") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("TEXT") + .HasColumnName("playtime_at_note"); + + b.Property("RoundId") + .HasColumnType("INTEGER") + .HasColumnName("round_id"); + + b.Property("Secret") + .HasColumnType("INTEGER") + .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"); + + 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"); + + 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"); + + b.Property("CreatedAt") + .HasColumnType("TEXT") + .HasColumnName("created_at"); + + b.Property("CreatedById") + .HasColumnType("TEXT") + .HasColumnName("created_by_id"); + + b.Property("Deleted") + .HasColumnType("INTEGER") + .HasColumnName("deleted"); + + b.Property("DeletedAt") + .HasColumnType("TEXT") + .HasColumnName("deleted_at"); + + b.Property("DeletedById") + .HasColumnType("TEXT") + .HasColumnName("deleted_by_id"); + + b.Property("ExpirationTime") + .HasColumnType("TEXT") + .HasColumnName("expiration_time"); + + b.Property("LastEditedAt") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("TEXT") + .HasColumnName("last_edited_by_id"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(4096) + .HasColumnType("TEXT") + .HasColumnName("message"); + + b.Property("PlayerUserId") + .HasColumnType("TEXT") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("TEXT") + .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"); + + 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"); + + b.Property("UserId") + .HasColumnType("TEXT") + .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.BanTemplate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("ban_template_id"); + + b.Property("AutoDelete") + .HasColumnType("INTEGER") + .HasColumnName("auto_delete"); + + b.Property("ExemptFlags") + .HasColumnType("INTEGER") + .HasColumnName("exempt_flags"); + + b.Property("Hidden") + .HasColumnType("INTEGER") + .HasColumnName("hidden"); + + b.Property("Length") + .HasColumnType("TEXT") + .HasColumnName("length"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("reason"); + + b.Property("Severity") + .HasColumnType("INTEGER") + .HasColumnName("severity"); + + b.Property("Title") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("title"); + + b.HasKey("Id") + .HasName("PK_ban_template"); + + b.ToTable("ban_template", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Blacklist", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT") + .HasColumnName("user_id"); + + b.HasKey("UserId") + .HasName("PK_blacklist"); + + b.ToTable("blacklist", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ConnectionLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("connection_log_id"); + + b.Property("Address") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("address"); + + b.Property("Denied") + .HasColumnType("INTEGER") + .HasColumnName("denied"); + + b.Property("ServerId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(0) + .HasColumnName("server_id"); + + b.Property("Time") + .HasColumnType("TEXT") + .HasColumnName("time"); + + b.Property("UserId") + .HasColumnType("TEXT") + .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("Time"); + + b.HasIndex("UserId"); + + b.ToTable("connection_log", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Job", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("job_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"); + + b.Property("PlayerId") + .HasColumnType("TEXT") + .HasColumnName("player_id"); + + b.Property("TimeSpent") + .HasColumnType("TEXT") + .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"); + + b.Property("FirstSeenTime") + .HasColumnType("TEXT") + .HasColumnName("first_seen_time"); + + b.Property("LastReadRules") + .HasColumnType("TEXT") + .HasColumnName("last_read_rules"); + + b.Property("LastSeenAddress") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("last_seen_address"); + + b.Property("LastSeenTime") + .HasColumnType("TEXT") + .HasColumnName("last_seen_time"); + + b.Property("LastSeenUserName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("last_seen_user_name"); + + b.Property("UserId") + .HasColumnType("TEXT") + .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", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Preference", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("preference_id"); + + b.Property("AdminOOCColor") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("admin_ooc_color"); + + b.Property("SelectedCharacterSlot") + .HasColumnType("INTEGER") + .HasColumnName("selected_character_slot"); + + b.Property("UserId") + .HasColumnType("TEXT") + .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"); + + b.Property("Age") + .HasColumnType("INTEGER") + .HasColumnName("age"); + + b.Property("CharacterName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("char_name"); + + 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.ProfileLoadout", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("profile_loadout_id"); + + b.Property("LoadoutName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("loadout_name"); + + b.Property("ProfileLoadoutGroupId") + .HasColumnType("INTEGER") + .HasColumnName("profile_loadout_group_id"); + + b.HasKey("Id") + .HasName("PK_profile_loadout"); + + b.HasIndex("ProfileLoadoutGroupId"); + + b.ToTable("profile_loadout", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileLoadoutGroup", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("profile_loadout_group_id"); + + b.Property("GroupName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("group_name"); + + b.Property("ProfileRoleLoadoutId") + .HasColumnType("INTEGER") + .HasColumnName("profile_role_loadout_id"); + + b.HasKey("Id") + .HasName("PK_profile_loadout_group"); + + b.HasIndex("ProfileRoleLoadoutId"); + + b.ToTable("profile_loadout_group", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileRoleLoadout", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("profile_role_loadout_id"); + + b.Property("ProfileId") + .HasColumnType("INTEGER") + .HasColumnName("profile_id"); + + b.Property("RoleName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("role_name"); + + b.HasKey("Id") + .HasName("PK_profile_role_loadout"); + + b.HasIndex("ProfileId"); + + b.ToTable("profile_role_loadout", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.RoleWhitelist", b => + { + b.Property("PlayerUserId") + .HasColumnType("TEXT") + .HasColumnName("player_user_id"); + + b.Property("RoleId") + .HasColumnType("TEXT") + .HasColumnName("role_id"); + + b.HasKey("PlayerUserId", "RoleId") + .HasName("PK_role_whitelists"); + + b.ToTable("role_whitelists", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Round", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("round_id"); + + b.Property("ServerId") + .HasColumnType("INTEGER") + .HasColumnName("server_id"); + + b.Property("StartDate") + .HasColumnType("TEXT") + .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"); + + 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"); + + b.Property("Address") + .HasColumnType("TEXT") + .HasColumnName("address"); + + b.Property("AutoDelete") + .HasColumnType("INTEGER") + .HasColumnName("auto_delete"); + + b.Property("BanTime") + .HasColumnType("TEXT") + .HasColumnName("ban_time"); + + b.Property("BanningAdmin") + .HasColumnType("TEXT") + .HasColumnName("banning_admin"); + + b.Property("ExemptFlags") + .HasColumnType("INTEGER") + .HasColumnName("exempt_flags"); + + b.Property("ExpirationTime") + .HasColumnType("TEXT") + .HasColumnName("expiration_time"); + + b.Property("Hidden") + .HasColumnType("INTEGER") + .HasColumnName("hidden"); + + b.Property("LastEditedAt") + .HasColumnType("TEXT") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("TEXT") + .HasColumnName("last_edited_by_id"); + + b.Property("PlayerUserId") + .HasColumnType("TEXT") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("TEXT") + .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("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("TEXT") + .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"); + + 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"); + + b.Property("Address") + .HasColumnType("TEXT") + .HasColumnName("address"); + + b.Property("BanTime") + .HasColumnType("TEXT") + .HasColumnName("ban_time"); + + b.Property("BanningAdmin") + .HasColumnType("TEXT") + .HasColumnName("banning_admin"); + + b.Property("ExpirationTime") + .HasColumnType("TEXT") + .HasColumnName("expiration_time"); + + b.Property("Hidden") + .HasColumnType("INTEGER") + .HasColumnName("hidden"); + + b.Property("LastEditedAt") + .HasColumnType("TEXT") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("TEXT") + .HasColumnName("last_edited_by_id"); + + b.Property("PlayerUserId") + .HasColumnType("TEXT") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("TEXT") + .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("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"); + + b.Property("BanId") + .HasColumnType("INTEGER") + .HasColumnName("ban_id"); + + b.Property("UnbanTime") + .HasColumnType("TEXT") + .HasColumnName("unban_time"); + + b.Property("UnbanningAdmin") + .HasColumnType("TEXT") + .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"); + + b.Property("BanId") + .HasColumnType("INTEGER") + .HasColumnName("ban_id"); + + b.Property("UnbanTime") + .HasColumnType("TEXT") + .HasColumnName("unban_time"); + + b.Property("UnbanningAdmin") + .HasColumnType("TEXT") + .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"); + + 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"); + + b.Property("Data") + .IsRequired() + .HasColumnType("BLOB") + .HasColumnName("data"); + + b.Property("Date") + .HasColumnType("TEXT") + .HasColumnName("date"); + + b.Property("Path") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("path"); + + b.Property("UserId") + .HasColumnType("TEXT") + .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("TEXT") + .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.OwnsOne("Content.Server.Database.TypedHwid", "HWId", b1 => + { + b1.Property("ConnectionLogId") + .HasColumnType("INTEGER") + .HasColumnName("connection_log_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("BLOB") + .HasColumnName("hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(0) + .HasColumnName("hwid_type"); + + b1.HasKey("ConnectionLogId"); + + b1.ToTable("connection_log"); + + b1.WithOwner() + .HasForeignKey("ConnectionLogId") + .HasConstraintName("FK_connection_log_connection_log_connection_log_id"); + }); + + b.Navigation("HWId"); + + 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.Player", b => + { + b.OwnsOne("Content.Server.Database.TypedHwid", "LastSeenHWId", b1 => + { + b1.Property("PlayerId") + .HasColumnType("INTEGER") + .HasColumnName("player_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("BLOB") + .HasColumnName("last_seen_hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(0) + .HasColumnName("last_seen_hwid_type"); + + b1.HasKey("PlayerId"); + + b1.ToTable("player"); + + b1.WithOwner() + .HasForeignKey("PlayerId") + .HasConstraintName("FK_player_player_player_id"); + }); + + b.Navigation("LastSeenHWId"); + }); + + 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.ProfileLoadout", b => + { + b.HasOne("Content.Server.Database.ProfileLoadoutGroup", "ProfileLoadoutGroup") + .WithMany("Loadouts") + .HasForeignKey("ProfileLoadoutGroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_profile_loadout_profile_loadout_group_profile_loadout_group_id"); + + b.Navigation("ProfileLoadoutGroup"); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileLoadoutGroup", b => + { + b.HasOne("Content.Server.Database.ProfileRoleLoadout", "ProfileRoleLoadout") + .WithMany("Groups") + .HasForeignKey("ProfileRoleLoadoutId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_profile_loadout_group_profile_role_loadout_profile_role_loadout_id"); + + b.Navigation("ProfileRoleLoadout"); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileRoleLoadout", b => + { + b.HasOne("Content.Server.Database.Profile", "Profile") + .WithMany("Loadouts") + .HasForeignKey("ProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_profile_role_loadout_profile_profile_id"); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("Content.Server.Database.RoleWhitelist", b => + { + b.HasOne("Content.Server.Database.Player", "Player") + .WithMany("JobWhitelists") + .HasForeignKey("PlayerUserId") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_role_whitelists_player_player_user_id"); + + b.Navigation("Player"); + }); + + 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.OwnsOne("Content.Server.Database.TypedHwid", "HWId", b1 => + { + b1.Property("ServerBanId") + .HasColumnType("INTEGER") + .HasColumnName("server_ban_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("BLOB") + .HasColumnName("hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(0) + .HasColumnName("hwid_type"); + + b1.HasKey("ServerBanId"); + + b1.ToTable("server_ban"); + + b1.WithOwner() + .HasForeignKey("ServerBanId") + .HasConstraintName("FK_server_ban_server_ban_server_ban_id"); + }); + + b.Navigation("CreatedBy"); + + b.Navigation("HWId"); + + 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.OwnsOne("Content.Server.Database.TypedHwid", "HWId", b1 => + { + b1.Property("ServerRoleBanId") + .HasColumnType("INTEGER") + .HasColumnName("server_role_ban_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("BLOB") + .HasColumnName("hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(0) + .HasColumnName("hwid_type"); + + b1.HasKey("ServerRoleBanId"); + + b1.ToTable("server_role_ban"); + + b1.WithOwner() + .HasForeignKey("ServerRoleBanId") + .HasConstraintName("FK_server_role_ban_server_role_ban_server_role_ban_id"); + }); + + b.Navigation("CreatedBy"); + + b.Navigation("HWId"); + + 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"); + + b.Navigation("JobWhitelists"); + }); + + 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("Loadouts"); + + b.Navigation("Traits"); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileLoadoutGroup", b => + { + b.Navigation("Loadouts"); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileRoleLoadout", b => + { + b.Navigation("Groups"); + }); + + 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/Sqlite/20241111170107_ModernHwid.cs b/Content.Server.Database/Migrations/Sqlite/20241111170107_ModernHwid.cs new file mode 100644 index 0000000000..97b5dafd03 --- /dev/null +++ b/Content.Server.Database/Migrations/Sqlite/20241111170107_ModernHwid.cs @@ -0,0 +1,62 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Content.Server.Database.Migrations.Sqlite +{ + /// + public partial class ModernHwid : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "hwid_type", + table: "server_role_ban", + type: "INTEGER", + nullable: true, + defaultValue: 0); + + migrationBuilder.AddColumn( + name: "hwid_type", + table: "server_ban", + type: "INTEGER", + nullable: true, + defaultValue: 0); + + migrationBuilder.AddColumn( + name: "last_seen_hwid_type", + table: "player", + type: "INTEGER", + nullable: true, + defaultValue: 0); + + migrationBuilder.AddColumn( + name: "hwid_type", + table: "connection_log", + type: "INTEGER", + nullable: true, + defaultValue: 0); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "hwid_type", + table: "server_role_ban"); + + migrationBuilder.DropColumn( + name: "hwid_type", + table: "server_ban"); + + migrationBuilder.DropColumn( + name: "last_seen_hwid_type", + table: "player"); + + migrationBuilder.DropColumn( + name: "hwid_type", + table: "connection_log"); + } + } +} diff --git a/Content.Server.Database/Migrations/Sqlite/20241111193602_ConnectionTrust.Designer.cs b/Content.Server.Database/Migrations/Sqlite/20241111193602_ConnectionTrust.Designer.cs new file mode 100644 index 0000000000..bd4e20a464 --- /dev/null +++ b/Content.Server.Database/Migrations/Sqlite/20241111193602_ConnectionTrust.Designer.cs @@ -0,0 +1,1999 @@ +// +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("20241111193602_ConnectionTrust")] + partial class ConnectionTrust + { + /// + 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("LogId") + .HasColumnType("INTEGER") + .HasColumnName("log_id"); + + b.Property("PlayerUserId") + .HasColumnType("TEXT") + .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"); + + b.Property("CreatedAt") + .HasColumnType("TEXT") + .HasColumnName("created_at"); + + b.Property("CreatedById") + .HasColumnType("TEXT") + .HasColumnName("created_by_id"); + + b.Property("Deleted") + .HasColumnType("INTEGER") + .HasColumnName("deleted"); + + b.Property("DeletedAt") + .HasColumnType("TEXT") + .HasColumnName("deleted_at"); + + b.Property("DeletedById") + .HasColumnType("TEXT") + .HasColumnName("deleted_by_id"); + + b.Property("Dismissed") + .HasColumnType("INTEGER") + .HasColumnName("dismissed"); + + b.Property("ExpirationTime") + .HasColumnType("TEXT") + .HasColumnName("expiration_time"); + + b.Property("LastEditedAt") + .HasColumnType("TEXT") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("TEXT") + .HasColumnName("last_edited_by_id"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(4096) + .HasColumnType("TEXT") + .HasColumnName("message"); + + b.Property("PlayerUserId") + .HasColumnType("TEXT") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("TEXT") + .HasColumnName("playtime_at_note"); + + b.Property("RoundId") + .HasColumnType("INTEGER") + .HasColumnName("round_id"); + + b.Property("Seen") + .HasColumnType("INTEGER") + .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"); + + b.Property("CreatedAt") + .HasColumnType("TEXT") + .HasColumnName("created_at"); + + b.Property("CreatedById") + .HasColumnType("TEXT") + .HasColumnName("created_by_id"); + + b.Property("Deleted") + .HasColumnType("INTEGER") + .HasColumnName("deleted"); + + b.Property("DeletedAt") + .HasColumnType("TEXT") + .HasColumnName("deleted_at"); + + b.Property("DeletedById") + .HasColumnType("TEXT") + .HasColumnName("deleted_by_id"); + + b.Property("ExpirationTime") + .HasColumnType("TEXT") + .HasColumnName("expiration_time"); + + b.Property("LastEditedAt") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("TEXT") + .HasColumnName("last_edited_by_id"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(4096) + .HasColumnType("TEXT") + .HasColumnName("message"); + + b.Property("PlayerUserId") + .HasColumnType("TEXT") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("TEXT") + .HasColumnName("playtime_at_note"); + + b.Property("RoundId") + .HasColumnType("INTEGER") + .HasColumnName("round_id"); + + b.Property("Secret") + .HasColumnType("INTEGER") + .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"); + + 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"); + + 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"); + + b.Property("CreatedAt") + .HasColumnType("TEXT") + .HasColumnName("created_at"); + + b.Property("CreatedById") + .HasColumnType("TEXT") + .HasColumnName("created_by_id"); + + b.Property("Deleted") + .HasColumnType("INTEGER") + .HasColumnName("deleted"); + + b.Property("DeletedAt") + .HasColumnType("TEXT") + .HasColumnName("deleted_at"); + + b.Property("DeletedById") + .HasColumnType("TEXT") + .HasColumnName("deleted_by_id"); + + b.Property("ExpirationTime") + .HasColumnType("TEXT") + .HasColumnName("expiration_time"); + + b.Property("LastEditedAt") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("TEXT") + .HasColumnName("last_edited_by_id"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(4096) + .HasColumnType("TEXT") + .HasColumnName("message"); + + b.Property("PlayerUserId") + .HasColumnType("TEXT") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("TEXT") + .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"); + + 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"); + + b.Property("UserId") + .HasColumnType("TEXT") + .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.BanTemplate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("ban_template_id"); + + b.Property("AutoDelete") + .HasColumnType("INTEGER") + .HasColumnName("auto_delete"); + + b.Property("ExemptFlags") + .HasColumnType("INTEGER") + .HasColumnName("exempt_flags"); + + b.Property("Hidden") + .HasColumnType("INTEGER") + .HasColumnName("hidden"); + + b.Property("Length") + .HasColumnType("TEXT") + .HasColumnName("length"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("reason"); + + b.Property("Severity") + .HasColumnType("INTEGER") + .HasColumnName("severity"); + + b.Property("Title") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("title"); + + b.HasKey("Id") + .HasName("PK_ban_template"); + + b.ToTable("ban_template", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Blacklist", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT") + .HasColumnName("user_id"); + + b.HasKey("UserId") + .HasName("PK_blacklist"); + + b.ToTable("blacklist", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ConnectionLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("connection_log_id"); + + b.Property("Address") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("address"); + + b.Property("Denied") + .HasColumnType("INTEGER") + .HasColumnName("denied"); + + b.Property("ServerId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(0) + .HasColumnName("server_id"); + + b.Property("Time") + .HasColumnType("TEXT") + .HasColumnName("time"); + + b.Property("Trust") + .HasColumnType("REAL") + .HasColumnName("trust"); + + b.Property("UserId") + .HasColumnType("TEXT") + .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("Time"); + + b.HasIndex("UserId"); + + b.ToTable("connection_log", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Job", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("job_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"); + + b.Property("PlayerId") + .HasColumnType("TEXT") + .HasColumnName("player_id"); + + b.Property("TimeSpent") + .HasColumnType("TEXT") + .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"); + + b.Property("FirstSeenTime") + .HasColumnType("TEXT") + .HasColumnName("first_seen_time"); + + b.Property("LastReadRules") + .HasColumnType("TEXT") + .HasColumnName("last_read_rules"); + + b.Property("LastSeenAddress") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("last_seen_address"); + + b.Property("LastSeenTime") + .HasColumnType("TEXT") + .HasColumnName("last_seen_time"); + + b.Property("LastSeenUserName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("last_seen_user_name"); + + b.Property("UserId") + .HasColumnType("TEXT") + .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", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Preference", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("preference_id"); + + b.Property("AdminOOCColor") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("admin_ooc_color"); + + b.Property("SelectedCharacterSlot") + .HasColumnType("INTEGER") + .HasColumnName("selected_character_slot"); + + b.Property("UserId") + .HasColumnType("TEXT") + .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"); + + b.Property("Age") + .HasColumnType("INTEGER") + .HasColumnName("age"); + + b.Property("CharacterName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("char_name"); + + 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.ProfileLoadout", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("profile_loadout_id"); + + b.Property("LoadoutName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("loadout_name"); + + b.Property("ProfileLoadoutGroupId") + .HasColumnType("INTEGER") + .HasColumnName("profile_loadout_group_id"); + + b.HasKey("Id") + .HasName("PK_profile_loadout"); + + b.HasIndex("ProfileLoadoutGroupId"); + + b.ToTable("profile_loadout", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileLoadoutGroup", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("profile_loadout_group_id"); + + b.Property("GroupName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("group_name"); + + b.Property("ProfileRoleLoadoutId") + .HasColumnType("INTEGER") + .HasColumnName("profile_role_loadout_id"); + + b.HasKey("Id") + .HasName("PK_profile_loadout_group"); + + b.HasIndex("ProfileRoleLoadoutId"); + + b.ToTable("profile_loadout_group", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileRoleLoadout", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("profile_role_loadout_id"); + + b.Property("ProfileId") + .HasColumnType("INTEGER") + .HasColumnName("profile_id"); + + b.Property("RoleName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("role_name"); + + b.HasKey("Id") + .HasName("PK_profile_role_loadout"); + + b.HasIndex("ProfileId"); + + b.ToTable("profile_role_loadout", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.RoleWhitelist", b => + { + b.Property("PlayerUserId") + .HasColumnType("TEXT") + .HasColumnName("player_user_id"); + + b.Property("RoleId") + .HasColumnType("TEXT") + .HasColumnName("role_id"); + + b.HasKey("PlayerUserId", "RoleId") + .HasName("PK_role_whitelists"); + + b.ToTable("role_whitelists", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Round", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("round_id"); + + b.Property("ServerId") + .HasColumnType("INTEGER") + .HasColumnName("server_id"); + + b.Property("StartDate") + .HasColumnType("TEXT") + .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"); + + 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"); + + b.Property("Address") + .HasColumnType("TEXT") + .HasColumnName("address"); + + b.Property("AutoDelete") + .HasColumnType("INTEGER") + .HasColumnName("auto_delete"); + + b.Property("BanTime") + .HasColumnType("TEXT") + .HasColumnName("ban_time"); + + b.Property("BanningAdmin") + .HasColumnType("TEXT") + .HasColumnName("banning_admin"); + + b.Property("ExemptFlags") + .HasColumnType("INTEGER") + .HasColumnName("exempt_flags"); + + b.Property("ExpirationTime") + .HasColumnType("TEXT") + .HasColumnName("expiration_time"); + + b.Property("Hidden") + .HasColumnType("INTEGER") + .HasColumnName("hidden"); + + b.Property("LastEditedAt") + .HasColumnType("TEXT") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("TEXT") + .HasColumnName("last_edited_by_id"); + + b.Property("PlayerUserId") + .HasColumnType("TEXT") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("TEXT") + .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("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("TEXT") + .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"); + + 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"); + + b.Property("Address") + .HasColumnType("TEXT") + .HasColumnName("address"); + + b.Property("BanTime") + .HasColumnType("TEXT") + .HasColumnName("ban_time"); + + b.Property("BanningAdmin") + .HasColumnType("TEXT") + .HasColumnName("banning_admin"); + + b.Property("ExpirationTime") + .HasColumnType("TEXT") + .HasColumnName("expiration_time"); + + b.Property("Hidden") + .HasColumnType("INTEGER") + .HasColumnName("hidden"); + + b.Property("LastEditedAt") + .HasColumnType("TEXT") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("TEXT") + .HasColumnName("last_edited_by_id"); + + b.Property("PlayerUserId") + .HasColumnType("TEXT") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("TEXT") + .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("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"); + + b.Property("BanId") + .HasColumnType("INTEGER") + .HasColumnName("ban_id"); + + b.Property("UnbanTime") + .HasColumnType("TEXT") + .HasColumnName("unban_time"); + + b.Property("UnbanningAdmin") + .HasColumnType("TEXT") + .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"); + + b.Property("BanId") + .HasColumnType("INTEGER") + .HasColumnName("ban_id"); + + b.Property("UnbanTime") + .HasColumnType("TEXT") + .HasColumnName("unban_time"); + + b.Property("UnbanningAdmin") + .HasColumnType("TEXT") + .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"); + + 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"); + + b.Property("Data") + .IsRequired() + .HasColumnType("BLOB") + .HasColumnName("data"); + + b.Property("Date") + .HasColumnType("TEXT") + .HasColumnName("date"); + + b.Property("Path") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("path"); + + b.Property("UserId") + .HasColumnType("TEXT") + .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("TEXT") + .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.OwnsOne("Content.Server.Database.TypedHwid", "HWId", b1 => + { + b1.Property("ConnectionLogId") + .HasColumnType("INTEGER") + .HasColumnName("connection_log_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("BLOB") + .HasColumnName("hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(0) + .HasColumnName("hwid_type"); + + b1.HasKey("ConnectionLogId"); + + b1.ToTable("connection_log"); + + b1.WithOwner() + .HasForeignKey("ConnectionLogId") + .HasConstraintName("FK_connection_log_connection_log_connection_log_id"); + }); + + b.Navigation("HWId"); + + 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.Player", b => + { + b.OwnsOne("Content.Server.Database.TypedHwid", "LastSeenHWId", b1 => + { + b1.Property("PlayerId") + .HasColumnType("INTEGER") + .HasColumnName("player_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("BLOB") + .HasColumnName("last_seen_hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(0) + .HasColumnName("last_seen_hwid_type"); + + b1.HasKey("PlayerId"); + + b1.ToTable("player"); + + b1.WithOwner() + .HasForeignKey("PlayerId") + .HasConstraintName("FK_player_player_player_id"); + }); + + b.Navigation("LastSeenHWId"); + }); + + 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.ProfileLoadout", b => + { + b.HasOne("Content.Server.Database.ProfileLoadoutGroup", "ProfileLoadoutGroup") + .WithMany("Loadouts") + .HasForeignKey("ProfileLoadoutGroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_profile_loadout_profile_loadout_group_profile_loadout_group_id"); + + b.Navigation("ProfileLoadoutGroup"); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileLoadoutGroup", b => + { + b.HasOne("Content.Server.Database.ProfileRoleLoadout", "ProfileRoleLoadout") + .WithMany("Groups") + .HasForeignKey("ProfileRoleLoadoutId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_profile_loadout_group_profile_role_loadout_profile_role_loadout_id"); + + b.Navigation("ProfileRoleLoadout"); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileRoleLoadout", b => + { + b.HasOne("Content.Server.Database.Profile", "Profile") + .WithMany("Loadouts") + .HasForeignKey("ProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_profile_role_loadout_profile_profile_id"); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("Content.Server.Database.RoleWhitelist", b => + { + b.HasOne("Content.Server.Database.Player", "Player") + .WithMany("JobWhitelists") + .HasForeignKey("PlayerUserId") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_role_whitelists_player_player_user_id"); + + b.Navigation("Player"); + }); + + 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.OwnsOne("Content.Server.Database.TypedHwid", "HWId", b1 => + { + b1.Property("ServerBanId") + .HasColumnType("INTEGER") + .HasColumnName("server_ban_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("BLOB") + .HasColumnName("hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(0) + .HasColumnName("hwid_type"); + + b1.HasKey("ServerBanId"); + + b1.ToTable("server_ban"); + + b1.WithOwner() + .HasForeignKey("ServerBanId") + .HasConstraintName("FK_server_ban_server_ban_server_ban_id"); + }); + + b.Navigation("CreatedBy"); + + b.Navigation("HWId"); + + 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.OwnsOne("Content.Server.Database.TypedHwid", "HWId", b1 => + { + b1.Property("ServerRoleBanId") + .HasColumnType("INTEGER") + .HasColumnName("server_role_ban_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("BLOB") + .HasColumnName("hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(0) + .HasColumnName("hwid_type"); + + b1.HasKey("ServerRoleBanId"); + + b1.ToTable("server_role_ban"); + + b1.WithOwner() + .HasForeignKey("ServerRoleBanId") + .HasConstraintName("FK_server_role_ban_server_role_ban_server_role_ban_id"); + }); + + b.Navigation("CreatedBy"); + + b.Navigation("HWId"); + + 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"); + + b.Navigation("JobWhitelists"); + }); + + 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("Loadouts"); + + b.Navigation("Traits"); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileLoadoutGroup", b => + { + b.Navigation("Loadouts"); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileRoleLoadout", b => + { + b.Navigation("Groups"); + }); + + 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/Sqlite/20241111193602_ConnectionTrust.cs b/Content.Server.Database/Migrations/Sqlite/20241111193602_ConnectionTrust.cs new file mode 100644 index 0000000000..3a7fd784e1 --- /dev/null +++ b/Content.Server.Database/Migrations/Sqlite/20241111193602_ConnectionTrust.cs @@ -0,0 +1,29 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Content.Server.Database.Migrations.Sqlite +{ + /// + public partial class ConnectionTrust : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "trust", + table: "connection_log", + type: "REAL", + nullable: false, + defaultValue: 0f); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "trust", + table: "connection_log"); + } + } +} diff --git a/Content.Server.Database/Migrations/Sqlite/SqliteServerDbContextModelSnapshot.cs b/Content.Server.Database/Migrations/Sqlite/SqliteServerDbContextModelSnapshot.cs index aae865b3b4..41d97117dc 100644 --- a/Content.Server.Database/Migrations/Sqlite/SqliteServerDbContextModelSnapshot.cs +++ b/Content.Server.Database/Migrations/Sqlite/SqliteServerDbContextModelSnapshot.cs @@ -483,19 +483,6 @@ namespace Content.Server.Database.Migrations.Sqlite b.ToTable("assigned_user_id", (string)null); }); - modelBuilder.Entity("Content.Server.Database.Blacklist", - b => - { - b.Property("UserId") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT") - .HasColumnName("user_id"); - - b.HasKey("UserId") - .HasName("PK_blacklist"); - - b.ToTable("blacklist", (string) null); - }); modelBuilder.Entity("Content.Server.Database.BanTemplate", b => { b.Property("Id") @@ -539,6 +526,19 @@ namespace Content.Server.Database.Migrations.Sqlite b.ToTable("ban_template", (string)null); }); + modelBuilder.Entity("Content.Server.Database.Blacklist", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT") + .HasColumnName("user_id"); + + b.HasKey("UserId") + .HasName("PK_blacklist"); + + b.ToTable("blacklist", (string)null); + }); + modelBuilder.Entity("Content.Server.Database.ConnectionLog", b => { b.Property("Id") @@ -555,10 +555,6 @@ namespace Content.Server.Database.Migrations.Sqlite .HasColumnType("INTEGER") .HasColumnName("denied"); - b.Property("HWId") - .HasColumnType("BLOB") - .HasColumnName("hwid"); - b.Property("ServerId") .ValueGeneratedOnAdd() .HasColumnType("INTEGER") @@ -569,6 +565,10 @@ namespace Content.Server.Database.Migrations.Sqlite .HasColumnType("TEXT") .HasColumnName("time"); + b.Property("Trust") + .HasColumnType("REAL") + .HasColumnName("trust"); + b.Property("UserId") .HasColumnType("TEXT") .HasColumnName("user_id"); @@ -675,10 +675,6 @@ namespace Content.Server.Database.Migrations.Sqlite .HasColumnType("TEXT") .HasColumnName("last_seen_address"); - b.Property("LastSeenHWId") - .HasColumnType("BLOB") - .HasColumnName("last_seen_hwid"); - b.Property("LastSeenTime") .HasColumnType("TEXT") .HasColumnName("last_seen_time"); @@ -1003,10 +999,6 @@ namespace Content.Server.Database.Migrations.Sqlite .HasColumnType("TEXT") .HasColumnName("expiration_time"); - b.Property("HWId") - .HasColumnType("BLOB") - .HasColumnName("hwid"); - b.Property("Hidden") .HasColumnType("INTEGER") .HasColumnName("hidden"); @@ -1131,10 +1123,6 @@ namespace Content.Server.Database.Migrations.Sqlite .HasColumnType("TEXT") .HasColumnName("expiration_time"); - b.Property("HWId") - .HasColumnType("BLOB") - .HasColumnName("hwid"); - b.Property("Hidden") .HasColumnType("INTEGER") .HasColumnName("hidden"); @@ -1566,6 +1554,34 @@ namespace Content.Server.Database.Migrations.Sqlite .IsRequired() .HasConstraintName("FK_connection_log_server_server_id"); + b.OwnsOne("Content.Server.Database.TypedHwid", "HWId", b1 => + { + b1.Property("ConnectionLogId") + .HasColumnType("INTEGER") + .HasColumnName("connection_log_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("BLOB") + .HasColumnName("hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(0) + .HasColumnName("hwid_type"); + + b1.HasKey("ConnectionLogId"); + + b1.ToTable("connection_log"); + + b1.WithOwner() + .HasForeignKey("ConnectionLogId") + .HasConstraintName("FK_connection_log_connection_log_connection_log_id"); + }); + + b.Navigation("HWId"); + b.Navigation("Server"); }); @@ -1581,6 +1597,37 @@ namespace Content.Server.Database.Migrations.Sqlite b.Navigation("Profile"); }); + modelBuilder.Entity("Content.Server.Database.Player", b => + { + b.OwnsOne("Content.Server.Database.TypedHwid", "LastSeenHWId", b1 => + { + b1.Property("PlayerId") + .HasColumnType("INTEGER") + .HasColumnName("player_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("BLOB") + .HasColumnName("last_seen_hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(0) + .HasColumnName("last_seen_hwid_type"); + + b1.HasKey("PlayerId"); + + b1.ToTable("player"); + + b1.WithOwner() + .HasForeignKey("PlayerId") + .HasConstraintName("FK_player_player_player_id"); + }); + + b.Navigation("LastSeenHWId"); + }); + modelBuilder.Entity("Content.Server.Database.Profile", b => { b.HasOne("Content.Server.Database.Preference", "Preference") @@ -1675,8 +1722,36 @@ namespace Content.Server.Database.Migrations.Sqlite .HasForeignKey("RoundId") .HasConstraintName("FK_server_ban_round_round_id"); + b.OwnsOne("Content.Server.Database.TypedHwid", "HWId", b1 => + { + b1.Property("ServerBanId") + .HasColumnType("INTEGER") + .HasColumnName("server_ban_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("BLOB") + .HasColumnName("hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(0) + .HasColumnName("hwid_type"); + + b1.HasKey("ServerBanId"); + + b1.ToTable("server_ban"); + + b1.WithOwner() + .HasForeignKey("ServerBanId") + .HasConstraintName("FK_server_ban_server_ban_server_ban_id"); + }); + b.Navigation("CreatedBy"); + b.Navigation("HWId"); + b.Navigation("LastEditedBy"); b.Navigation("Round"); @@ -1724,8 +1799,36 @@ namespace Content.Server.Database.Migrations.Sqlite .HasForeignKey("RoundId") .HasConstraintName("FK_server_role_ban_round_round_id"); + b.OwnsOne("Content.Server.Database.TypedHwid", "HWId", b1 => + { + b1.Property("ServerRoleBanId") + .HasColumnType("INTEGER") + .HasColumnName("server_role_ban_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("BLOB") + .HasColumnName("hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(0) + .HasColumnName("hwid_type"); + + b1.HasKey("ServerRoleBanId"); + + b1.ToTable("server_role_ban"); + + b1.WithOwner() + .HasForeignKey("ServerRoleBanId") + .HasConstraintName("FK_server_role_ban_server_role_ban_server_role_ban_id"); + }); + b.Navigation("CreatedBy"); + b.Navigation("HWId"); + b.Navigation("LastEditedBy"); b.Navigation("Round"); diff --git a/Content.Server.Database/Model.cs b/Content.Server.Database/Model.cs index a8240f1c47..1091c98de4 100644 --- a/Content.Server.Database/Model.cs +++ b/Content.Server.Database/Model.cs @@ -1,7 +1,9 @@ using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Net; using System.Text.Json; @@ -327,6 +329,47 @@ namespace Content.Server.Database .HasForeignKey(w => w.PlayerUserId) .HasPrincipalKey(p => p.UserId) .OnDelete(DeleteBehavior.Cascade); + + // Changes for modern HWID integration + modelBuilder.Entity() + .OwnsOne(p => p.LastSeenHWId) + .Property(p => p.Hwid) + .HasColumnName("last_seen_hwid"); + + modelBuilder.Entity() + .OwnsOne(p => p.LastSeenHWId) + .Property(p => p.Type) + .HasDefaultValue(HwidType.Legacy); + + modelBuilder.Entity() + .OwnsOne(p => p.HWId) + .Property(p => p.Hwid) + .HasColumnName("hwid"); + + modelBuilder.Entity() + .OwnsOne(p => p.HWId) + .Property(p => p.Type) + .HasDefaultValue(HwidType.Legacy); + + modelBuilder.Entity() + .OwnsOne(p => p.HWId) + .Property(p => p.Hwid) + .HasColumnName("hwid"); + + modelBuilder.Entity() + .OwnsOne(p => p.HWId) + .Property(p => p.Type) + .HasDefaultValue(HwidType.Legacy); + + modelBuilder.Entity() + .OwnsOne(p => p.HWId) + .Property(p => p.Hwid) + .HasColumnName("hwid"); + + modelBuilder.Entity() + .OwnsOne(p => p.HWId) + .Property(p => p.Type) + .HasDefaultValue(HwidType.Legacy); } public virtual IQueryable SearchLogs(IQueryable query, string searchText) @@ -520,7 +563,7 @@ namespace Content.Server.Database public string LastSeenUserName { get; set; } = null!; public DateTime LastSeenTime { get; set; } public IPAddress LastSeenAddress { get; set; } = null!; - public byte[]? LastSeenHWId { get; set; } + public TypedHwid? LastSeenHWId { get; set; } // Data that changes with each round public List Rounds { get; set; } = null!; @@ -669,7 +712,7 @@ namespace Content.Server.Database int Id { get; set; } Guid? PlayerUserId { get; set; } NpgsqlInet? Address { get; set; } - byte[]? HWId { get; set; } + TypedHwid? HWId { get; set; } DateTime BanTime { get; set; } DateTime? ExpirationTime { get; set; } string Reason { get; set; } @@ -754,7 +797,7 @@ namespace Content.Server.Database /// /// Hardware ID of the banned player. /// - public byte[]? HWId { get; set; } + public TypedHwid? HWId { get; set; } /// /// The time when the ban was applied by an administrator. @@ -892,7 +935,7 @@ namespace Content.Server.Database public DateTime Time { get; set; } public IPAddress Address { get; set; } = null!; - public byte[]? HWId { get; set; } + public TypedHwid? HWId { get; set; } public ConnectionDenyReason? Denied { get; set; } @@ -909,6 +952,8 @@ namespace Content.Server.Database public List BanHits { get; set; } = null!; public Server Server { get; set; } = null!; + + public float Trust { get; set; } } public enum ConnectionDenyReason : byte @@ -946,7 +991,7 @@ namespace Content.Server.Database public Guid? PlayerUserId { get; set; } [Required] public TimeSpan PlaytimeAtNote { get; set; } public NpgsqlInet? Address { get; set; } - public byte[]? HWId { get; set; } + public TypedHwid? HWId { get; set; } public DateTime BanTime { get; set; } @@ -1207,4 +1252,37 @@ namespace Content.Server.Database /// public bool Hidden { get; set; } } + + /// + /// A hardware ID value together with its . + /// + /// + [Owned] + public sealed class TypedHwid + { + public byte[] Hwid { get; set; } = default!; + public HwidType Type { get; set; } + + [return: NotNullIfNotNull(nameof(immutable))] + public static implicit operator TypedHwid?(ImmutableTypedHwid? immutable) + { + if (immutable == null) + return null; + + return new TypedHwid + { + Hwid = immutable.Hwid.ToArray(), + Type = immutable.Type, + }; + } + + [return: NotNullIfNotNull(nameof(hwid))] + public static implicit operator ImmutableTypedHwid?(TypedHwid? hwid) + { + if (hwid == null) + return null; + + return new ImmutableTypedHwid(hwid.Hwid.ToImmutableArray(), hwid.Type); + } + } } diff --git a/Content.Server.Database/SnakeCaseNaming.cs b/Content.Server.Database/SnakeCaseNaming.cs index 27ce392cd5..3a67ffb9cd 100644 --- a/Content.Server.Database/SnakeCaseNaming.cs +++ b/Content.Server.Database/SnakeCaseNaming.cs @@ -82,7 +82,7 @@ namespace Content.Server.Database } } - public class SnakeCaseConvention : + public partial class SnakeCaseConvention : IEntityTypeAddedConvention, IEntityTypeAnnotationChangedConvention, IPropertyAddedConvention, @@ -99,22 +99,27 @@ namespace Content.Server.Database public static string RewriteName(string name) { - var regex = new Regex("[A-Z]+", RegexOptions.Compiled); - return regex.Replace( - name, - (Match match) => { - if (match.Index == 0 && (match.Value == "FK" || match.Value == "PK" || match.Value == "IX")) { - return match.Value; + return UpperCaseLocator() + .Replace( + name, + (Match match) => { + if (match.Index == 0 && (match.Value == "FK" || match.Value == "PK" || match.Value == "IX")) { + return match.Value; + } + if (match.Value == "HWI") + return (match.Index == 0 ? "" : "_") + "hwi"; + if (match.Index == 0) + return match.Value.ToLower(); + if (match.Length > 1) + return $"_{match.Value[..^1].ToLower()}_{match.Value[^1..^0].ToLower()}"; + + // Do not add a _ if there is already one before this. This happens with owned entities. + if (name[match.Index - 1] == '_') + return match.Value.ToLower(); + + return "_" + match.Value.ToLower(); } - if (match.Value == "HWI") - return (match.Index == 0 ? "" : "_") + "hwi"; - if (match.Index == 0) - return match.Value.ToLower(); - if (match.Length > 1) - return $"_{match.Value[..^1].ToLower()}_{match.Value[^1..^0].ToLower()}"; - return "_" + match.Value.ToLower(); - } - ); + ); } public virtual void ProcessEntityTypeAdded( @@ -332,5 +337,8 @@ namespace Content.Server.Database } } } + + [GeneratedRegex("[A-Z]+", RegexOptions.Compiled)] + private static partial Regex UpperCaseLocator(); } } diff --git a/Content.Server/Administration/BanList/BanListEui.cs b/Content.Server/Administration/BanList/BanListEui.cs index 8ddc7459d7..2ca126bf16 100644 --- a/Content.Server/Administration/BanList/BanListEui.cs +++ b/Content.Server/Administration/BanList/BanListEui.cs @@ -54,7 +54,7 @@ public sealed class BanListEui : BaseEui private async Task LoadBans(NetUserId userId) { - foreach (var ban in await _db.GetServerBansAsync(null, userId, null)) + foreach (var ban in await _db.GetServerBansAsync(null, userId, null, null)) { SharedServerUnban? unban = null; if (ban.Unban is { } unbanDef) @@ -74,7 +74,7 @@ public sealed class BanListEui : BaseEui ? (address.address.ToString(), address.cidrMask) : null; - hwid = ban.HWId == null ? null : Convert.ToBase64String(ban.HWId.Value.AsSpan()); + hwid = ban.HWId?.ToString(); } Bans.Add(new SharedServerBan( @@ -95,7 +95,7 @@ public sealed class BanListEui : BaseEui private async Task LoadRoleBans(NetUserId userId) { - foreach (var ban in await _db.GetServerRoleBansAsync(null, userId, null)) + foreach (var ban in await _db.GetServerRoleBansAsync(null, userId, null, null)) { SharedServerUnban? unban = null; if (ban.Unban is { } unbanDef) @@ -115,7 +115,7 @@ public sealed class BanListEui : BaseEui ? (address.address.ToString(), address.cidrMask) : null; - hwid = ban.HWId == null ? null : Convert.ToBase64String(ban.HWId.Value.AsSpan()); + hwid = ban.HWId?.ToString(); } RoleBans.Add(new SharedServerRoleBan( ban.Id, diff --git a/Content.Server/Administration/BanPanelEui.cs b/Content.Server/Administration/BanPanelEui.cs index d3af06d914..e22e0a2cad 100644 --- a/Content.Server/Administration/BanPanelEui.cs +++ b/Content.Server/Administration/BanPanelEui.cs @@ -1,4 +1,3 @@ -using System.Collections.Immutable; using System.Net; using System.Net.Sockets; using Content.Server.Administration.Managers; @@ -8,7 +7,6 @@ using Content.Server.EUI; using Content.Shared.Administration; using Content.Shared.Database; using Content.Shared.Eui; -using Robust.Server.Player; using Robust.Shared.Network; namespace Content.Server.Administration; @@ -27,7 +25,7 @@ public sealed class BanPanelEui : BaseEui private NetUserId? PlayerId { get; set; } private string PlayerName { get; set; } = string.Empty; private IPAddress? LastAddress { get; set; } - private ImmutableArray? LastHwid { get; set; } + private ImmutableTypedHwid? LastHwid { get; set; } private const int Ipv4_CIDR = 32; private const int Ipv6_CIDR = 64; @@ -51,7 +49,7 @@ public sealed class BanPanelEui : BaseEui switch (msg) { case BanPanelEuiStateMsg.CreateBanRequest r: - BanPlayer(r.Player, r.IpAddress, r.UseLastIp, r.Hwid?.ToImmutableArray(), r.UseLastHwid, r.Minutes, r.Severity, r.Reason, r.Roles, r.Erase); + BanPlayer(r.Player, r.IpAddress, r.UseLastIp, r.Hwid, r.UseLastHwid, r.Minutes, r.Severity, r.Reason, r.Roles, r.Erase); break; case BanPanelEuiStateMsg.GetPlayerInfoRequest r: ChangePlayer(r.PlayerUsername); @@ -59,7 +57,7 @@ public sealed class BanPanelEui : BaseEui } } - private async void BanPlayer(string? target, string? ipAddressString, bool useLastIp, ImmutableArray? hwid, bool useLastHwid, uint minutes, NoteSeverity severity, string reason, IReadOnlyCollection? roles, bool erase) + private async void BanPlayer(string? target, string? ipAddressString, bool useLastIp, ImmutableTypedHwid? hwid, bool useLastHwid, uint minutes, NoteSeverity severity, string reason, IReadOnlyCollection? roles, bool erase) { if (!_admins.HasAdminFlag(Player, AdminFlags.Ban)) { @@ -156,7 +154,7 @@ public sealed class BanPanelEui : BaseEui ChangePlayer(located?.UserId, located?.Username ?? string.Empty, located?.LastAddress, located?.LastHWId); } - public void ChangePlayer(NetUserId? playerId, string playerName, IPAddress? lastAddress, ImmutableArray? lastHwid) + public void ChangePlayer(NetUserId? playerId, string playerName, IPAddress? lastAddress, ImmutableTypedHwid? lastHwid) { PlayerId = playerId; PlayerName = playerName; diff --git a/Content.Server/Administration/Commands/BanListCommand.cs b/Content.Server/Administration/Commands/BanListCommand.cs index a5bc97dce3..2f7093ae1d 100644 --- a/Content.Server/Administration/Commands/BanListCommand.cs +++ b/Content.Server/Administration/Commands/BanListCommand.cs @@ -38,7 +38,7 @@ public sealed class BanListCommand : LocalizedCommands if (shell.Player is not { } player) { - var bans = await _dbManager.GetServerBansAsync(data.LastAddress, data.UserId, data.LastHWId, false); + var bans = await _dbManager.GetServerBansAsync(data.LastAddress, data.UserId, data.LastLegacyHWId, data.LastModernHWIds, false); if (bans.Count == 0) { diff --git a/Content.Server/Administration/Commands/RoleBanListCommand.cs b/Content.Server/Administration/Commands/RoleBanListCommand.cs index 30bb3073ad..8244ded3b2 100644 --- a/Content.Server/Administration/Commands/RoleBanListCommand.cs +++ b/Content.Server/Administration/Commands/RoleBanListCommand.cs @@ -48,7 +48,7 @@ public sealed class RoleBanListCommand : IConsoleCommand if (shell.Player is not { } player) { - var bans = await _dbManager.GetServerRoleBansAsync(data.LastAddress, data.UserId, data.LastHWId, includeUnbanned); + var bans = await _dbManager.GetServerRoleBansAsync(data.LastAddress, data.UserId, data.LastLegacyHWId, data.LastModernHWIds, includeUnbanned); if (bans.Count == 0) { diff --git a/Content.Server/Administration/Managers/BanManager.cs b/Content.Server/Administration/Managers/BanManager.cs index df8c0641fe..404a7758c6 100644 --- a/Content.Server/Administration/Managers/BanManager.cs +++ b/Content.Server/Administration/Managers/BanManager.cs @@ -100,7 +100,8 @@ public sealed partial class BanManager : IBanManager, IPostInjectInit var netChannel = player.Channel; ImmutableArray? hwId = netChannel.UserData.HWId.Length == 0 ? null : netChannel.UserData.HWId; - var roleBans = await _db.GetServerRoleBansAsync(netChannel.RemoteEndPoint.Address, player.UserId, hwId, false); + var modernHwids = netChannel.UserData.ModernHWIds; + var roleBans = await _db.GetServerRoleBansAsync(netChannel.RemoteEndPoint.Address, player.UserId, hwId, modernHwids, false); var userRoleBans = new List(); foreach (var ban in roleBans) @@ -167,7 +168,7 @@ public sealed partial class BanManager : IBanManager, IPostInjectInit } #region Server Bans - public async void CreateServerBan(NetUserId? target, string? targetUsername, NetUserId? banningAdmin, (IPAddress, int)? addressRange, ImmutableArray? hwid, uint? minutes, NoteSeverity severity, string reason) + public async void CreateServerBan(NetUserId? target, string? targetUsername, NetUserId? banningAdmin, (IPAddress, int)? addressRange, ImmutableTypedHwid? hwid, uint? minutes, NoteSeverity severity, string reason) { DateTimeOffset? expires = null; if (minutes > 0) @@ -207,9 +208,7 @@ public sealed partial class BanManager : IBanManager, IPostInjectInit var addressRangeString = addressRange != null ? $"{addressRange.Value.Item1}/{addressRange.Value.Item2}" : "null"; - var hwidString = hwid != null - ? string.Concat(hwid.Value.Select(x => x.ToString("x2"))) - : "null"; + var hwidString = hwid?.ToString() ?? "null"; var expiresString = expires == null ? Loc.GetString("server-ban-string-never") : $"{expires}"; var key = _cfg.GetCVar(CCVars.AdminShowPIIOnBan) ? "server-ban-string" : "server-ban-string-no-pii"; @@ -256,6 +255,7 @@ public sealed partial class BanManager : IBanManager, IPostInjectInit UserId = player.UserId, Address = player.Channel.RemoteEndPoint.Address, HWId = player.Channel.UserData.HWId, + ModernHWIds = player.Channel.UserData.ModernHWIds, // It's possible for the player to not have cached data loading yet due to coincidental timing. // If this is the case, we assume they have all flags to avoid false-positives. ExemptFlags = _cachedBanExemptions.GetValueOrDefault(player, ServerBanExemptFlags.All), @@ -276,7 +276,7 @@ public sealed partial class BanManager : IBanManager, IPostInjectInit #region Job Bans // If you are trying to remove timeOfBan, please don't. It's there because the note system groups role bans by time, reason and banning admin. // Removing it will clutter the note list. Please also make sure that department bans are applied to roles with the same DateTimeOffset. - public async void CreateRoleBan(NetUserId? target, string? targetUsername, NetUserId? banningAdmin, (IPAddress, int)? addressRange, ImmutableArray? hwid, string role, uint? minutes, NoteSeverity severity, string reason, DateTimeOffset timeOfBan) + public async void CreateRoleBan(NetUserId? target, string? targetUsername, NetUserId? banningAdmin, (IPAddress, int)? addressRange, ImmutableTypedHwid? hwid, string role, uint? minutes, NoteSeverity severity, string reason, DateTimeOffset timeOfBan) { if (!_prototypeManager.TryIndex(role, out JobPrototype? _)) { diff --git a/Content.Server/Administration/Managers/IBanManager.cs b/Content.Server/Administration/Managers/IBanManager.cs index 451b94d9eb..918b3585e6 100644 --- a/Content.Server/Administration/Managers/IBanManager.cs +++ b/Content.Server/Administration/Managers/IBanManager.cs @@ -24,7 +24,7 @@ public interface IBanManager /// Number of minutes to ban for. 0 and null mean permanent /// Severity of the resulting ban note /// Reason for the ban - public void CreateServerBan(NetUserId? target, string? targetUsername, NetUserId? banningAdmin, (IPAddress, int)? addressRange, ImmutableArray? hwid, uint? minutes, NoteSeverity severity, string reason); + public void CreateServerBan(NetUserId? target, string? targetUsername, NetUserId? banningAdmin, (IPAddress, int)? addressRange, ImmutableTypedHwid? hwid, uint? minutes, NoteSeverity severity, string reason); public HashSet? GetRoleBans(NetUserId playerUserId); public HashSet>? GetJobBans(NetUserId playerUserId); @@ -37,7 +37,7 @@ public interface IBanManager /// Reason for the ban /// Number of minutes to ban for. 0 and null mean permanent /// Time when the ban was applied, used for grouping role bans - public void CreateRoleBan(NetUserId? target, string? targetUsername, NetUserId? banningAdmin, (IPAddress, int)? addressRange, ImmutableArray? hwid, string role, uint? minutes, NoteSeverity severity, string reason, DateTimeOffset timeOfBan); + public void CreateRoleBan(NetUserId? target, string? targetUsername, NetUserId? banningAdmin, (IPAddress, int)? addressRange, ImmutableTypedHwid? hwid, string role, uint? minutes, NoteSeverity severity, string reason, DateTimeOffset timeOfBan); public void WebhookUpdateRoleBans(NetUserId? target, string? targetUsername, NetUserId? banningAdmin, (IPAddress, int)? addressRange, ImmutableArray? hwid, IReadOnlyCollection roles, uint? minutes, NoteSeverity severity, string reason, DateTimeOffset timeOfBan); diff --git a/Content.Server/Administration/PlayerLocator.cs b/Content.Server/Administration/PlayerLocator.cs index 64a85f19ad..25cc771468 100644 --- a/Content.Server/Administration/PlayerLocator.cs +++ b/Content.Server/Administration/PlayerLocator.cs @@ -5,16 +5,42 @@ using System.Net.Http.Headers; using System.Net.Http.Json; using System.Threading; using System.Threading.Tasks; +using Content.Server.Connection; using Content.Server.Database; +using Content.Shared.Database; using JetBrains.Annotations; using Robust.Server.Player; using Robust.Shared; using Robust.Shared.Configuration; using Robust.Shared.Network; +using Robust.Shared.Player; namespace Content.Server.Administration { - public sealed record LocatedPlayerData(NetUserId UserId, IPAddress? LastAddress, ImmutableArray? LastHWId, string Username); + /// + /// Contains data resolved via . + /// + /// The ID of the located user. + /// The last known IP address that the user connected with. + /// + /// The last known HWID that the user connected with. + /// This should be used for placing new records involving HWIDs, such as bans. + /// For looking up data based on HWID, use combined and . + /// + /// The last known username for the user connected with. + /// + /// The last known legacy HWID value this user connected with. Only use for old lookups! + /// + /// + /// The set of last known modern HWIDs the user connected with. + /// + public sealed record LocatedPlayerData( + NetUserId UserId, + IPAddress? LastAddress, + ImmutableTypedHwid? LastHWId, + string Username, + ImmutableArray? LastLegacyHWId, + ImmutableArray> LastModernHWIds); /// /// Utilities for finding user IDs that extend to more than the server database. @@ -67,63 +93,42 @@ namespace Content.Server.Administration { // Check people currently on the server, the easiest case. if (_playerManager.TryGetSessionByUsername(playerName, out var session)) - { - var userId = session.UserId; - var address = session.Channel.RemoteEndPoint.Address; - var hwId = session.Channel.UserData.HWId; - return new LocatedPlayerData(userId, address, hwId, session.Name); - } + return ReturnForSession(session); // Check database for past players. var record = await _db.GetPlayerRecordByUserName(playerName, cancel); if (record != null) - return new LocatedPlayerData(record.UserId, record.LastSeenAddress, record.HWId, record.LastSeenUserName); + return ReturnForPlayerRecord(record); // If all else fails, ask the auth server. var authServer = _configurationManager.GetCVar(CVars.AuthServer); var requestUri = $"{authServer}api/query/name?name={WebUtility.UrlEncode(playerName)}"; using var resp = await _httpClient.GetAsync(requestUri, cancel); - if (resp.StatusCode == HttpStatusCode.NotFound) - return null; - - if (!resp.IsSuccessStatusCode) - { - _sawmill.Error("Auth server returned bad response {StatusCode}!", resp.StatusCode); - return null; - } - - var responseData = await resp.Content.ReadFromJsonAsync(cancellationToken: cancel); - - if (responseData == null) - { - _sawmill.Error("Auth server returned null response!"); - return null; - } - - return new LocatedPlayerData(new NetUserId(responseData.UserId), null, null, responseData.UserName); + return await HandleAuthServerResponse(resp, cancel); } public async Task LookupIdAsync(NetUserId userId, CancellationToken cancel = default) { // Check people currently on the server, the easiest case. if (_playerManager.TryGetSessionById(userId, out var session)) - { - var address = session.Channel.RemoteEndPoint.Address; - var hwId = session.Channel.UserData.HWId; - return new LocatedPlayerData(userId, address, hwId, session.Name); - } + return ReturnForSession(session); // Check database for past players. var record = await _db.GetPlayerRecordByUserId(userId, cancel); if (record != null) - return new LocatedPlayerData(record.UserId, record.LastSeenAddress, record.HWId, record.LastSeenUserName); + return ReturnForPlayerRecord(record); // If all else fails, ask the auth server. var authServer = _configurationManager.GetCVar(CVars.AuthServer); var requestUri = $"{authServer}api/query/userid?userid={WebUtility.UrlEncode(userId.UserId.ToString())}"; using var resp = await _httpClient.GetAsync(requestUri, cancel); + return await HandleAuthServerResponse(resp, cancel); + } + + private async Task HandleAuthServerResponse(HttpResponseMessage resp, CancellationToken cancel) + { if (resp.StatusCode == HttpStatusCode.NotFound) return null; @@ -134,14 +139,40 @@ namespace Content.Server.Administration } var responseData = await resp.Content.ReadFromJsonAsync(cancellationToken: cancel); - if (responseData == null) { _sawmill.Error("Auth server returned null response!"); return null; } - return new LocatedPlayerData(new NetUserId(responseData.UserId), null, null, responseData.UserName); + return new LocatedPlayerData(new NetUserId(responseData.UserId), null, null, responseData.UserName, null, []); + } + + private static LocatedPlayerData ReturnForSession(ICommonSession session) + { + var userId = session.UserId; + var address = session.Channel.RemoteEndPoint.Address; + var hwId = session.Channel.UserData.GetModernHwid(); + return new LocatedPlayerData( + userId, + address, + hwId, + session.Name, + session.Channel.UserData.HWId, + session.Channel.UserData.ModernHWIds); + } + + private static LocatedPlayerData ReturnForPlayerRecord(PlayerRecord record) + { + var hwid = record.HWId; + + return new LocatedPlayerData( + record.UserId, + record.LastSeenAddress, + hwid, + record.LastSeenUserName, + hwid is { Type: HwidType.Legacy } ? hwid.Hwid : null, + hwid is { Type: HwidType.Modern } ? [hwid.Hwid] : []); } public async Task LookupIdByNameOrIdAsync(string playerName, CancellationToken cancel = default) diff --git a/Content.Server/Administration/PlayerPanelEui.cs b/Content.Server/Administration/PlayerPanelEui.cs index 4c0df80601..6c30488886 100644 --- a/Content.Server/Administration/PlayerPanelEui.cs +++ b/Content.Server/Administration/PlayerPanelEui.cs @@ -173,11 +173,11 @@ public sealed class PlayerPanelEui : BaseEui { _whitelisted = await _db.GetWhitelistStatusAsync(_targetPlayer.UserId); // This won't get associated ip or hwid bans but they were not placed on this account anyways - _bans = (await _db.GetServerBansAsync(null, _targetPlayer.UserId, null)).Count; + _bans = (await _db.GetServerBansAsync(null, _targetPlayer.UserId, null, null)).Count; // Unfortunately role bans for departments and stuff are issued individually. This means that a single role ban can have many individual role bans internally // The only way to distinguish whether a role ban is the same is to compare the ban time. // This is horrible and I would love to just erase the database and start from scratch instead but that's what I can do for now. - _roleBans = (await _db.GetServerRoleBansAsync(null, _targetPlayer.UserId, null)).DistinctBy(rb => rb.BanTime).Count(); + _roleBans = (await _db.GetServerRoleBansAsync(null, _targetPlayer.UserId, null, null)).DistinctBy(rb => rb.BanTime).Count(); } else { diff --git a/Content.Server/Administration/Systems/BwoinkSystem.cs b/Content.Server/Administration/Systems/BwoinkSystem.cs index b492882a35..a113c0604d 100644 --- a/Content.Server/Administration/Systems/BwoinkSystem.cs +++ b/Content.Server/Administration/Systems/BwoinkSystem.cs @@ -176,7 +176,7 @@ namespace Content.Server.Administration.Systems } // Check if the user has been banned - var ban = await _dbManager.GetServerBanAsync(null, e.Session.UserId, null); + var ban = await _dbManager.GetServerBanAsync(null, e.Session.UserId, null, null); if (ban != null) { var banMessage = Loc.GetString("bwoink-system-player-banned", ("banReason", ban.Reason)); diff --git a/Content.Server/Atmos/Monitor/Components/AtmosMonitorComponent.cs b/Content.Server/Atmos/Monitor/Components/AtmosMonitorComponent.cs index cb6d4d1630..830479561d 100644 --- a/Content.Server/Atmos/Monitor/Components/AtmosMonitorComponent.cs +++ b/Content.Server/Atmos/Monitor/Components/AtmosMonitorComponent.cs @@ -48,7 +48,9 @@ public sealed partial class AtmosMonitorComponent : Component [DataField("gasThresholds")] public Dictionary? GasThresholds; - // Stores a reference to the gas on the tile this is on. + /// + /// Stores a reference to the gas on the tile this entity is on (or the pipe network it monitors; see ). + /// [ViewVariables] public GasMixture? TileGas; @@ -65,4 +67,19 @@ public sealed partial class AtmosMonitorComponent : Component /// [DataField("registeredDevices")] public HashSet RegisteredDevices = new(); + + /// + /// Specifies whether this device monitors its own internal pipe network rather than the surrounding atmosphere. + /// + /// + /// If 'true', the entity will require a NodeContainerComponent with one or more PipeNodes to function. + /// + [DataField] + public bool MonitorsPipeNet = false; + + /// + /// Specifies the name of the pipe node that this device is monitoring. + /// + [DataField] + public string NodeNameMonitoredPipe = "monitored"; } diff --git a/Content.Server/Atmos/Monitor/Systems/AtmosMonitoringSystem.cs b/Content.Server/Atmos/Monitor/Systems/AtmosMonitoringSystem.cs index fbe74cbab7..17a24b1b0c 100644 --- a/Content.Server/Atmos/Monitor/Systems/AtmosMonitoringSystem.cs +++ b/Content.Server/Atmos/Monitor/Systems/AtmosMonitoringSystem.cs @@ -4,6 +4,9 @@ using Content.Server.Atmos.Piping.Components; using Content.Server.Atmos.Piping.EntitySystems; using Content.Server.DeviceNetwork; using Content.Server.DeviceNetwork.Systems; +using Content.Server.NodeContainer; +using Content.Server.NodeContainer.EntitySystems; +using Content.Server.NodeContainer.Nodes; using Content.Server.Power.Components; using Content.Server.Power.EntitySystems; using Content.Shared.Atmos; @@ -25,6 +28,7 @@ public sealed class AtmosMonitorSystem : EntitySystem [Dependency] private readonly AtmosDeviceSystem _atmosDeviceSystem = default!; [Dependency] private readonly DeviceNetworkSystem _deviceNetSystem = default!; [Dependency] private readonly IPrototypeManager _prototypeManager = default!; + [Dependency] private readonly NodeContainerSystem _nodeContainerSystem = default!; // Commands public const string AtmosMonitorSetThresholdCmd = "atmos_monitor_set_threshold"; @@ -56,8 +60,15 @@ public sealed class AtmosMonitorSystem : EntitySystem private void OnAtmosDeviceEnterAtmosphere(EntityUid uid, AtmosMonitorComponent atmosMonitor, ref AtmosDeviceEnabledEvent args) { + if (atmosMonitor.MonitorsPipeNet && _nodeContainerSystem.TryGetNode(uid, atmosMonitor.NodeNameMonitoredPipe, out var pipeNode)) + { + atmosMonitor.TileGas = pipeNode.Air; + return; + } + atmosMonitor.TileGas = _atmosphereSystem.GetContainingMixture(uid, true); } + private void OnMapInit(EntityUid uid, AtmosMonitorComponent component, MapInitEvent args) { if (component.TemperatureThresholdId != null) @@ -206,7 +217,7 @@ public sealed class AtmosMonitorSystem : EntitySystem if (!this.IsPowered(uid, EntityManager)) return; - if (args.Grid == null) + if (args.Grid == null) return; // if we're not monitoring atmos, don't bother @@ -215,6 +226,10 @@ public sealed class AtmosMonitorSystem : EntitySystem && component.GasThresholds == null) return; + // If monitoring a pipe network, get its most recent gas mixture + if (component.MonitorsPipeNet && _nodeContainerSystem.TryGetNode(uid, component.NodeNameMonitoredPipe, out var pipeNode)) + component.TileGas = pipeNode.Air; + UpdateState(uid, component.TileGas, component); } diff --git a/Content.Server/Connection/ConnectionManager.cs b/Content.Server/Connection/ConnectionManager.cs index b60b3138a4..61b4b63069 100644 --- a/Content.Server/Connection/ConnectionManager.cs +++ b/Content.Server/Connection/ConnectionManager.cs @@ -116,11 +116,14 @@ namespace Content.Server.Connection var serverId = (await _serverDbEntry.ServerEntity).Id; + var hwid = e.UserData.GetModernHwid(); + var trust = e.UserData.Trust; + if (deny != null) { var (reason, msg, banHits) = deny.Value; - var id = await _db.AddConnectionLogAsync(userId, e.UserName, addr, e.UserData.HWId, reason, serverId); + var id = await _db.AddConnectionLogAsync(userId, e.UserName, addr, hwid, trust, reason, serverId); if (banHits is { Count: > 0 }) await _db.AddServerBanHitsAsync(id, banHits); @@ -132,12 +135,12 @@ namespace Content.Server.Connection } else { - await _db.AddConnectionLogAsync(userId, e.UserName, addr, e.UserData.HWId, null, serverId); + await _db.AddConnectionLogAsync(userId, e.UserName, addr, hwid, trust, null, serverId); if (!ServerPreferencesManager.ShouldStorePrefs(e.AuthType)) return; - await _db.UpdatePlayerRecordAsync(userId, e.UserName, addr, e.UserData.HWId); + await _db.UpdatePlayerRecordAsync(userId, e.UserName, addr, hwid); } } @@ -195,7 +198,9 @@ namespace Content.Server.Connection hwId = null; } - var bans = await _db.GetServerBansAsync(addr, userId, hwId, includeUnbanned: false); + var modernHwid = e.UserData.ModernHWIds; + + var bans = await _db.GetServerBansAsync(addr, userId, hwId, modernHwid, includeUnbanned: false); if (bans.Count > 0) { var firstBan = bans[0]; diff --git a/Content.Server/Connection/UserDataExt.cs b/Content.Server/Connection/UserDataExt.cs new file mode 100644 index 0000000000..a409f79a75 --- /dev/null +++ b/Content.Server/Connection/UserDataExt.cs @@ -0,0 +1,24 @@ +using Content.Shared.Database; +using Robust.Shared.Network; + +namespace Content.Server.Connection; + +/// +/// Helper functions for working with . +/// +public static class UserDataExt +{ + /// + /// Get the preferred HWID that should be used for new records related to a player. + /// + /// + /// Players can have zero or more HWIDs, but for logging things like connection logs we generally + /// only want a single one. This method returns a nullable method. + /// + public static ImmutableTypedHwid? GetModernHwid(this NetUserData userData) + { + return userData.ModernHWIds.Length == 0 + ? null + : new ImmutableTypedHwid(userData.ModernHWIds[0], HwidType.Modern); + } +} diff --git a/Content.Server/Database/BanMatcher.cs b/Content.Server/Database/BanMatcher.cs index e58e5b0b5f..f477ccd822 100644 --- a/Content.Server/Database/BanMatcher.cs +++ b/Content.Server/Database/BanMatcher.cs @@ -1,6 +1,7 @@ using System.Collections.Immutable; using System.Net; using Content.Server.IP; +using Content.Shared.Database; using Robust.Shared.Network; namespace Content.Server.Database; @@ -52,9 +53,28 @@ public static class BanMatcher return true; } - return player.HWId is { Length: > 0 } hwIdVar - && ban.HWId != null - && hwIdVar.AsSpan().SequenceEqual(ban.HWId.Value.AsSpan()); + switch (ban.HWId?.Type) + { + case HwidType.Legacy: + if (player.HWId is { Length: > 0 } hwIdVar + && hwIdVar.AsSpan().SequenceEqual(ban.HWId.Hwid.AsSpan())) + { + return true; + } + break; + case HwidType.Modern: + if (player.ModernHWIds is { Length: > 0 } modernHwIdVar) + { + foreach (var hwid in modernHwIdVar) + { + if (hwid.AsSpan().SequenceEqual(ban.HWId.Hwid.AsSpan())) + return true; + } + } + break; + } + + return false; } /// @@ -73,10 +93,15 @@ public static class BanMatcher public IPAddress? Address; /// - /// The hardware ID of the player. + /// The LEGACY hardware ID of the player. Corresponds with . /// public ImmutableArray? HWId; + /// + /// The modern hardware IDs of the player. Corresponds with . + /// + public ImmutableArray>? ModernHWIds; + /// /// Exemption flags the player has been granted. /// diff --git a/Content.Server/Database/DatabaseRecords.cs b/Content.Server/Database/DatabaseRecords.cs index c0d81147bb..30fba3434b 100644 --- a/Content.Server/Database/DatabaseRecords.cs +++ b/Content.Server/Database/DatabaseRecords.cs @@ -1,4 +1,3 @@ -using System.Collections.Immutable; using System.Net; using Content.Shared.Database; using Robust.Shared.Network; @@ -121,7 +120,7 @@ public sealed record PlayerRecord( string LastSeenUserName, DateTimeOffset LastSeenTime, IPAddress LastSeenAddress, - ImmutableArray? HWId); + ImmutableTypedHwid? HWId); public sealed record RoundRecord(int Id, DateTimeOffset? StartDate, ServerRecord Server); diff --git a/Content.Server/Database/ServerBanDef.cs b/Content.Server/Database/ServerBanDef.cs index 2812e3ba1c..a3abb18a8f 100644 --- a/Content.Server/Database/ServerBanDef.cs +++ b/Content.Server/Database/ServerBanDef.cs @@ -1,4 +1,3 @@ -using System.Collections.Immutable; using System.Net; using Content.Shared.CCVar; using Content.Shared.Database; @@ -13,7 +12,7 @@ namespace Content.Server.Database public int? Id { get; } public NetUserId? UserId { get; } public (IPAddress address, int cidrMask)? Address { get; } - public ImmutableArray? HWId { get; } + public ImmutableTypedHwid? HWId { get; } public DateTimeOffset BanTime { get; } public DateTimeOffset? ExpirationTime { get; } @@ -28,7 +27,7 @@ namespace Content.Server.Database public ServerBanDef(int? id, NetUserId? userId, (IPAddress, int)? address, - ImmutableArray? hwId, + TypedHwid? hwId, DateTimeOffset banTime, DateTimeOffset? expirationTime, int? roundId, diff --git a/Content.Server/Database/ServerDbBase.cs b/Content.Server/Database/ServerDbBase.cs index 7606a4f0bc..78f0723923 100644 --- a/Content.Server/Database/ServerDbBase.cs +++ b/Content.Server/Database/ServerDbBase.cs @@ -396,12 +396,14 @@ namespace Content.Server.Database /// /// The ip address of the user. /// The id of the user. - /// The HWId of the user. + /// The legacy HWId of the user. + /// The modern HWIDs of the user. /// The user's latest received un-pardoned ban, or null if none exist. public abstract Task GetServerBanAsync( IPAddress? address, NetUserId? userId, - ImmutableArray? hwId); + ImmutableArray? hwId, + ImmutableArray>? modernHWIds); /// /// Looks up an user's ban history. @@ -410,13 +412,15 @@ namespace Content.Server.Database /// /// The ip address of the user. /// The id of the user. - /// The HWId of the user. + /// The legacy HWId of the user. + /// The modern HWIDs of the user. /// Include pardoned and expired bans. /// The user's ban history. public abstract Task> GetServerBansAsync( IPAddress? address, NetUserId? userId, ImmutableArray? hwId, + ImmutableArray>? modernHWIds, bool includeUnbanned); public abstract Task AddServerBanAsync(ServerBanDef serverBan); @@ -507,11 +511,13 @@ namespace Content.Server.Database /// The IP address of the user. /// The NetUserId of the user. /// The Hardware Id of the user. + /// The modern HWIDs of the user. /// Whether expired and pardoned bans are included. /// The user's role ban history. public abstract Task> GetServerRoleBansAsync(IPAddress? address, NetUserId? userId, ImmutableArray? hwId, + ImmutableArray>? modernHWIds, bool includeUnbanned); public abstract Task AddServerRoleBanAsync(ServerRoleBanDef serverRoleBan); @@ -601,7 +607,7 @@ namespace Content.Server.Database NetUserId userId, string userName, IPAddress address, - ImmutableArray hwId) + ImmutableTypedHwid? hwId) { await using var db = await GetDb(); @@ -618,7 +624,7 @@ namespace Content.Server.Database record.LastSeenTime = DateTime.UtcNow; record.LastSeenAddress = address; record.LastSeenUserName = userName; - record.LastSeenHWId = hwId.ToArray(); + record.LastSeenHWId = hwId; await db.DbContext.SaveChangesAsync(); } @@ -664,7 +670,7 @@ namespace Content.Server.Database player.LastSeenUserName, new DateTimeOffset(NormalizeDatabaseTime(player.LastSeenTime)), player.LastSeenAddress, - player.LastSeenHWId?.ToImmutableArray()); + player.LastSeenHWId); } #endregion @@ -673,11 +679,11 @@ namespace Content.Server.Database /* * CONNECTION LOG */ - public abstract Task AddConnectionLogAsync( - NetUserId userId, + public abstract Task AddConnectionLogAsync(NetUserId userId, string userName, IPAddress address, - ImmutableArray hwId, + ImmutableTypedHwid? hwId, + float trust, ConnectionDenyReason? denied, int serverId); diff --git a/Content.Server/Database/ServerDbManager.cs b/Content.Server/Database/ServerDbManager.cs index 216b1ec159..be32b43595 100644 --- a/Content.Server/Database/ServerDbManager.cs +++ b/Content.Server/Database/ServerDbManager.cs @@ -69,12 +69,14 @@ namespace Content.Server.Database /// /// The ip address of the user. /// The id of the user. - /// The hardware ID of the user. + /// The legacy HWID of the user. + /// The modern HWIDs of the user. /// The user's latest received un-pardoned ban, or null if none exist. Task GetServerBanAsync( IPAddress? address, NetUserId? userId, - ImmutableArray? hwId); + ImmutableArray? hwId, + ImmutableArray>? modernHWIds); /// /// Looks up an user's ban history. @@ -82,13 +84,15 @@ namespace Content.Server.Database /// /// The ip address of the user. /// The id of the user. - /// The HWId of the user. + /// The legacy HWId of the user. + /// The modern HWIDs of the user. /// If true, bans that have been expired or pardoned are also included. /// The user's ban history. Task> GetServerBansAsync( IPAddress? address, NetUserId? userId, ImmutableArray? hwId, + ImmutableArray>? modernHWIds, bool includeUnbanned=true); Task AddServerBanAsync(ServerBanDef serverBan); @@ -137,12 +141,14 @@ namespace Content.Server.Database /// The IP address of the user. /// The NetUserId of the user. /// The Hardware Id of the user. + /// The modern HWIDs of the user. /// Whether expired and pardoned bans are included. /// The user's role ban history. Task> GetServerRoleBansAsync( IPAddress? address, NetUserId? userId, ImmutableArray? hwId, + ImmutableArray>? modernHWIds, bool includeUnbanned = true); Task AddServerRoleBanAsync(ServerRoleBanDef serverBan); @@ -180,7 +186,7 @@ namespace Content.Server.Database NetUserId userId, string userName, IPAddress address, - ImmutableArray hwId); + ImmutableTypedHwid? hwId); Task GetPlayerRecordByUserName(string userName, CancellationToken cancel = default); Task GetPlayerRecordByUserId(NetUserId userId, CancellationToken cancel = default); #endregion @@ -191,7 +197,8 @@ namespace Content.Server.Database NetUserId userId, string userName, IPAddress address, - ImmutableArray hwId, + ImmutableTypedHwid? hwId, + float trust, ConnectionDenyReason? denied, int serverId); @@ -480,20 +487,22 @@ namespace Content.Server.Database public Task GetServerBanAsync( IPAddress? address, NetUserId? userId, - ImmutableArray? hwId) + ImmutableArray? hwId, + ImmutableArray>? modernHWIds) { DbReadOpsMetric.Inc(); - return RunDbCommand(() => _db.GetServerBanAsync(address, userId, hwId)); + return RunDbCommand(() => _db.GetServerBanAsync(address, userId, hwId, modernHWIds)); } public Task> GetServerBansAsync( IPAddress? address, NetUserId? userId, ImmutableArray? hwId, + ImmutableArray>? modernHWIds, bool includeUnbanned=true) { DbReadOpsMetric.Inc(); - return RunDbCommand(() => _db.GetServerBansAsync(address, userId, hwId, includeUnbanned)); + return RunDbCommand(() => _db.GetServerBansAsync(address, userId, hwId, modernHWIds, includeUnbanned)); } public Task AddServerBanAsync(ServerBanDef serverBan) @@ -537,10 +546,11 @@ namespace Content.Server.Database IPAddress? address, NetUserId? userId, ImmutableArray? hwId, + ImmutableArray>? modernHWIds, bool includeUnbanned = true) { DbReadOpsMetric.Inc(); - return RunDbCommand(() => _db.GetServerRoleBansAsync(address, userId, hwId, includeUnbanned)); + return RunDbCommand(() => _db.GetServerRoleBansAsync(address, userId, hwId, modernHWIds, includeUnbanned)); } public Task AddServerRoleBanAsync(ServerRoleBanDef serverRoleBan) @@ -582,7 +592,7 @@ namespace Content.Server.Database NetUserId userId, string userName, IPAddress address, - ImmutableArray hwId) + ImmutableTypedHwid? hwId) { DbWriteOpsMetric.Inc(); return RunDbCommand(() => _db.UpdatePlayerRecord(userId, userName, address, hwId)); @@ -604,12 +614,13 @@ namespace Content.Server.Database NetUserId userId, string userName, IPAddress address, - ImmutableArray hwId, + ImmutableTypedHwid? hwId, + float trust, ConnectionDenyReason? denied, int serverId) { DbWriteOpsMetric.Inc(); - return RunDbCommand(() => _db.AddConnectionLogAsync(userId, userName, address, hwId, denied, serverId)); + return RunDbCommand(() => _db.AddConnectionLogAsync(userId, userName, address, hwId, trust, denied, serverId)); } public Task AddServerBanHitsAsync(int connection, IEnumerable bans) diff --git a/Content.Server/Database/ServerDbPostgres.cs b/Content.Server/Database/ServerDbPostgres.cs index 7d131f70dc..c034670837 100644 --- a/Content.Server/Database/ServerDbPostgres.cs +++ b/Content.Server/Database/ServerDbPostgres.cs @@ -9,6 +9,7 @@ using System.Threading.Tasks; using Content.Server.Administration.Logs; using Content.Server.IP; using Content.Shared.CCVar; +using Content.Shared.Database; using Microsoft.EntityFrameworkCore; using Robust.Shared.Configuration; using Robust.Shared.Network; @@ -73,7 +74,8 @@ namespace Content.Server.Database public override async Task GetServerBanAsync( IPAddress? address, NetUserId? userId, - ImmutableArray? hwId) + ImmutableArray? hwId, + ImmutableArray>? modernHWIds) { if (address == null && userId == null && hwId == null) { @@ -84,7 +86,7 @@ namespace Content.Server.Database var exempt = await GetBanExemptionCore(db, userId); var newPlayer = userId == null || !await PlayerRecordExists(db, userId.Value); - var query = MakeBanLookupQuery(address, userId, hwId, db, includeUnbanned: false, exempt, newPlayer) + var query = MakeBanLookupQuery(address, userId, hwId, modernHWIds, db, includeUnbanned: false, exempt, newPlayer) .OrderByDescending(b => b.BanTime); var ban = await query.FirstOrDefaultAsync(); @@ -94,7 +96,9 @@ namespace Content.Server.Database public override async Task> GetServerBansAsync(IPAddress? address, NetUserId? userId, - ImmutableArray? hwId, bool includeUnbanned) + ImmutableArray? hwId, + ImmutableArray>? modernHWIds, + bool includeUnbanned) { if (address == null && userId == null && hwId == null) { @@ -105,7 +109,7 @@ namespace Content.Server.Database var exempt = await GetBanExemptionCore(db, userId); var newPlayer = !await db.PgDbContext.Player.AnyAsync(p => p.UserId == userId); - var query = MakeBanLookupQuery(address, userId, hwId, db, includeUnbanned, exempt, newPlayer); + var query = MakeBanLookupQuery(address, userId, hwId, modernHWIds, db, includeUnbanned, exempt, newPlayer); var queryBans = await query.ToArrayAsync(); var bans = new List(queryBans.Length); @@ -127,6 +131,7 @@ namespace Content.Server.Database IPAddress? address, NetUserId? userId, ImmutableArray? hwId, + ImmutableArray>? modernHWIds, DbGuardImpl db, bool includeUnbanned, ServerBanExemptFlags? exemptFlags, @@ -134,16 +139,11 @@ namespace Content.Server.Database { DebugTools.Assert(!(address == null && userId == null && hwId == null)); - IQueryable? query = null; - - if (userId is { } uid) - { - var newQ = db.PgDbContext.Ban - .Include(p => p.Unban) - .Where(b => b.PlayerUserId == uid.UserId); - - query = query == null ? newQ : query.Union(newQ); - } + var query = MakeBanLookupQualityShared( + userId, + hwId, + modernHWIds, + db.PgDbContext.Ban); if (address != null && !exemptFlags.GetValueOrDefault(ServerBanExemptFlags.None).HasFlag(ServerBanExemptFlags.IP)) { @@ -156,15 +156,6 @@ namespace Content.Server.Database query = query == null ? newQ : query.Union(newQ); } - if (hwId != null && hwId.Value.Length > 0) - { - var newQ = db.PgDbContext.Ban - .Include(p => p.Unban) - .Where(b => b.HWId!.SequenceEqual(hwId.Value.ToArray())); - - query = query == null ? newQ : query.Union(newQ); - } - DebugTools.Assert( query != null, "At least one filter item (IP/UserID/HWID) must have been given to make query not null."); @@ -186,6 +177,49 @@ namespace Content.Server.Database return query.Distinct(); } + private static IQueryable? MakeBanLookupQualityShared( + NetUserId? userId, + ImmutableArray? hwId, + ImmutableArray>? modernHWIds, + DbSet set) + where TBan : class, IBanCommon + where TUnban : class, IUnbanCommon + { + IQueryable? query = null; + + if (userId is { } uid) + { + var newQ = set + .Include(p => p.Unban) + .Where(b => b.PlayerUserId == uid.UserId); + + query = query == null ? newQ : query.Union(newQ); + } + + if (hwId != null && hwId.Value.Length > 0) + { + var newQ = set + .Include(p => p.Unban) + .Where(b => b.HWId!.Type == HwidType.Legacy && b.HWId!.Hwid.SequenceEqual(hwId.Value.ToArray())); + + query = query == null ? newQ : query.Union(newQ); + } + + if (modernHWIds != null) + { + foreach (var modernHwid in modernHWIds) + { + var newQ = set + .Include(p => p.Unban) + .Where(b => b.HWId!.Type == HwidType.Modern && b.HWId!.Hwid.SequenceEqual(modernHwid.ToArray())); + + query = query == null ? newQ : query.Union(newQ); + } + } + + return query; + } + private static ServerBanDef? ConvertBan(ServerBan? ban) { if (ban == null) @@ -211,7 +245,7 @@ namespace Content.Server.Database ban.Id, uid, ban.Address.ToTuple(), - ban.HWId == null ? null : ImmutableArray.Create(ban.HWId), + ban.HWId, ban.BanTime, ban.ExpirationTime, ban.RoundId, @@ -249,7 +283,7 @@ namespace Content.Server.Database db.PgDbContext.Ban.Add(new ServerBan { Address = serverBan.Address.ToNpgsqlInet(), - HWId = serverBan.HWId?.ToArray(), + HWId = serverBan.HWId, Reason = serverBan.Reason, Severity = serverBan.Severity, BanningAdmin = serverBan.BanningAdmin?.UserId, @@ -297,6 +331,7 @@ namespace Content.Server.Database public override async Task> GetServerRoleBansAsync(IPAddress? address, NetUserId? userId, ImmutableArray? hwId, + ImmutableArray>? modernHWIds, bool includeUnbanned) { if (address == null && userId == null && hwId == null) @@ -306,7 +341,7 @@ namespace Content.Server.Database await using var db = await GetDbImpl(); - var query = MakeRoleBanLookupQuery(address, userId, hwId, db, includeUnbanned) + var query = MakeRoleBanLookupQuery(address, userId, hwId, modernHWIds, db, includeUnbanned) .OrderByDescending(b => b.BanTime); return await QueryRoleBans(query); @@ -334,19 +369,15 @@ namespace Content.Server.Database IPAddress? address, NetUserId? userId, ImmutableArray? hwId, + ImmutableArray>? modernHWIds, DbGuardImpl db, bool includeUnbanned) { - IQueryable? query = null; - - if (userId is { } uid) - { - var newQ = db.PgDbContext.RoleBan - .Include(p => p.Unban) - .Where(b => b.PlayerUserId == uid.UserId); - - query = query == null ? newQ : query.Union(newQ); - } + var query = MakeBanLookupQualityShared( + userId, + hwId, + modernHWIds, + db.PgDbContext.RoleBan); if (address != null) { @@ -357,15 +388,6 @@ namespace Content.Server.Database query = query == null ? newQ : query.Union(newQ); } - if (hwId != null && hwId.Value.Length > 0) - { - var newQ = db.PgDbContext.RoleBan - .Include(p => p.Unban) - .Where(b => b.HWId!.SequenceEqual(hwId.Value.ToArray())); - - query = query == null ? newQ : query.Union(newQ); - } - if (!includeUnbanned) { query = query?.Where(p => @@ -402,7 +424,7 @@ namespace Content.Server.Database ban.Id, uid, ban.Address.ToTuple(), - ban.HWId == null ? null : ImmutableArray.Create(ban.HWId), + ban.HWId, ban.BanTime, ban.ExpirationTime, ban.RoundId, @@ -440,7 +462,7 @@ namespace Content.Server.Database var ban = new ServerRoleBan { Address = serverRoleBan.Address.ToNpgsqlInet(), - HWId = serverRoleBan.HWId?.ToArray(), + HWId = serverRoleBan.HWId, Reason = serverRoleBan.Reason, Severity = serverRoleBan.Severity, BanningAdmin = serverRoleBan.BanningAdmin?.UserId, @@ -476,7 +498,8 @@ namespace Content.Server.Database NetUserId userId, string userName, IPAddress address, - ImmutableArray hwId, + ImmutableTypedHwid? hwId, + float trust, ConnectionDenyReason? denied, int serverId) { @@ -488,9 +511,10 @@ namespace Content.Server.Database Time = DateTime.UtcNow, UserId = userId.UserId, UserName = userName, - HWId = hwId.ToArray(), + HWId = hwId, Denied = denied, - ServerId = serverId + ServerId = serverId, + Trust = trust, }; db.PgDbContext.ConnectionLog.Add(connectionLog); diff --git a/Content.Server/Database/ServerDbSqlite.cs b/Content.Server/Database/ServerDbSqlite.cs index af4bc2cf8d..6ec90c3332 100644 --- a/Content.Server/Database/ServerDbSqlite.cs +++ b/Content.Server/Database/ServerDbSqlite.cs @@ -9,6 +9,7 @@ using Content.Server.Administration.Logs; using Content.Server.IP; using Content.Server.Preferences.Managers; using Content.Shared.CCVar; +using Content.Shared.Database; using Microsoft.EntityFrameworkCore; using Robust.Shared.Configuration; using Robust.Shared.Network; @@ -80,22 +81,24 @@ namespace Content.Server.Database public override async Task GetServerBanAsync( IPAddress? address, NetUserId? userId, - ImmutableArray? hwId) + ImmutableArray? hwId, + ImmutableArray>? modernHWIds) { await using var db = await GetDbImpl(); - return (await GetServerBanQueryAsync(db, address, userId, hwId, includeUnbanned: false)).FirstOrDefault(); + return (await GetServerBanQueryAsync(db, address, userId, hwId, modernHWIds, includeUnbanned: false)).FirstOrDefault(); } public override async Task> GetServerBansAsync( IPAddress? address, NetUserId? userId, ImmutableArray? hwId, + ImmutableArray>? modernHWIds, bool includeUnbanned) { await using var db = await GetDbImpl(); - return (await GetServerBanQueryAsync(db, address, userId, hwId, includeUnbanned)).ToList(); + return (await GetServerBanQueryAsync(db, address, userId, hwId, modernHWIds, includeUnbanned)).ToList(); } private async Task> GetServerBanQueryAsync( @@ -103,6 +106,7 @@ namespace Content.Server.Database IPAddress? address, NetUserId? userId, ImmutableArray? hwId, + ImmutableArray>? modernHWIds, bool includeUnbanned) { var exempt = await GetBanExemptionCore(db, userId); @@ -119,6 +123,7 @@ namespace Content.Server.Database UserId = userId, ExemptFlags = exempt ?? default, HWId = hwId, + ModernHWIds = modernHWIds, IsNewPlayer = newPlayer, }; @@ -161,7 +166,7 @@ namespace Content.Server.Database Reason = serverBan.Reason, Severity = serverBan.Severity, BanningAdmin = serverBan.BanningAdmin?.UserId, - HWId = serverBan.HWId?.ToArray(), + HWId = serverBan.HWId, BanTime = serverBan.BanTime.UtcDateTime, ExpirationTime = serverBan.ExpirationTime?.UtcDateTime, RoundId = serverBan.RoundId, @@ -205,6 +210,7 @@ namespace Content.Server.Database IPAddress? address, NetUserId? userId, ImmutableArray? hwId, + ImmutableArray>? modernHWIds, bool includeUnbanned) { await using var db = await GetDbImpl(); @@ -214,7 +220,7 @@ namespace Content.Server.Database var queryBans = await GetAllRoleBans(db.SqliteDbContext, includeUnbanned); return queryBans - .Where(b => RoleBanMatches(b, address, userId, hwId)) + .Where(b => RoleBanMatches(b, address, userId, hwId, modernHWIds)) .Select(ConvertRoleBan) .ToList()!; } @@ -237,7 +243,8 @@ namespace Content.Server.Database ServerRoleBan ban, IPAddress? address, NetUserId? userId, - ImmutableArray? hwId) + ImmutableArray? hwId, + ImmutableArray>? modernHWIds) { if (address != null && ban.Address is not null && address.IsInSubnet(ban.Address.ToTuple().Value)) { @@ -249,7 +256,27 @@ namespace Content.Server.Database return true; } - return hwId is { Length: > 0 } hwIdVar && hwIdVar.AsSpan().SequenceEqual(ban.HWId); + switch (ban.HWId?.Type) + { + case HwidType.Legacy: + if (hwId is { Length: > 0 } hwIdVar && hwIdVar.AsSpan().SequenceEqual(ban.HWId.Hwid)) + return true; + break; + + case HwidType.Modern: + if (modernHWIds != null) + { + foreach (var modernHWId in modernHWIds) + { + if (modernHWId.AsSpan().SequenceEqual(ban.HWId.Hwid)) + return true; + } + } + + break; + } + + return false; } public override async Task AddServerRoleBanAsync(ServerRoleBanDef serverBan) @@ -262,7 +289,7 @@ namespace Content.Server.Database Reason = serverBan.Reason, Severity = serverBan.Severity, BanningAdmin = serverBan.BanningAdmin?.UserId, - HWId = serverBan.HWId?.ToArray(), + HWId = serverBan.HWId, BanTime = serverBan.BanTime.UtcDateTime, ExpirationTime = serverBan.ExpirationTime?.UtcDateTime, RoundId = serverBan.RoundId, @@ -316,7 +343,7 @@ namespace Content.Server.Database ban.Id, uid, ban.Address.ToTuple(), - ban.HWId == null ? null : ImmutableArray.Create(ban.HWId), + ban.HWId, // SQLite apparently always reads DateTime as unspecified, but we always write as UTC. DateTime.SpecifyKind(ban.BanTime, DateTimeKind.Utc), ban.ExpirationTime == null ? null : DateTime.SpecifyKind(ban.ExpirationTime.Value, DateTimeKind.Utc), @@ -376,7 +403,7 @@ namespace Content.Server.Database ban.Id, uid, ban.Address.ToTuple(), - ban.HWId == null ? null : ImmutableArray.Create(ban.HWId), + ban.HWId, // SQLite apparently always reads DateTime as unspecified, but we always write as UTC. DateTime.SpecifyKind(ban.BanTime, DateTimeKind.Utc), ban.ExpirationTime == null ? null : DateTime.SpecifyKind(ban.ExpirationTime.Value, DateTimeKind.Utc), @@ -412,7 +439,8 @@ namespace Content.Server.Database NetUserId userId, string userName, IPAddress address, - ImmutableArray hwId, + ImmutableTypedHwid? hwId, + float trust, ConnectionDenyReason? denied, int serverId) { @@ -424,9 +452,10 @@ namespace Content.Server.Database Time = DateTime.UtcNow, UserId = userId.UserId, UserName = userName, - HWId = hwId.ToArray(), + HWId = hwId, Denied = denied, - ServerId = serverId + ServerId = serverId, + Trust = trust, }; db.SqliteDbContext.ConnectionLog.Add(connectionLog); diff --git a/Content.Server/Database/ServerRoleBanDef.cs b/Content.Server/Database/ServerRoleBanDef.cs index f615d5da4d..dda3a82237 100644 --- a/Content.Server/Database/ServerRoleBanDef.cs +++ b/Content.Server/Database/ServerRoleBanDef.cs @@ -1,4 +1,3 @@ -using System.Collections.Immutable; using System.Net; using Content.Shared.Database; using Robust.Shared.Network; @@ -10,7 +9,7 @@ public sealed class ServerRoleBanDef public int? Id { get; } public NetUserId? UserId { get; } public (IPAddress address, int cidrMask)? Address { get; } - public ImmutableArray? HWId { get; } + public ImmutableTypedHwid? HWId { get; } public DateTimeOffset BanTime { get; } public DateTimeOffset? ExpirationTime { get; } @@ -26,7 +25,7 @@ public sealed class ServerRoleBanDef int? id, NetUserId? userId, (IPAddress, int)? address, - ImmutableArray? hwId, + ImmutableTypedHwid? hwId, DateTimeOffset banTime, DateTimeOffset? expirationTime, int? roundId, diff --git a/Content.Server/Electrocution/ElectrocutionSystem.cs b/Content.Server/Electrocution/ElectrocutionSystem.cs index 88404c4aa9..eb10f8d280 100644 --- a/Content.Server/Electrocution/ElectrocutionSystem.cs +++ b/Content.Server/Electrocution/ElectrocutionSystem.cs @@ -121,7 +121,7 @@ public sealed class ElectrocutionSystem : SharedElectrocutionSystem activated.TimeLeft -= frameTime; if (activated.TimeLeft <= 0 || !IsPowered(uid, electrified, transform)) { - _appearance.SetData(uid, ElectrifiedVisuals.IsPowered, false); + _appearance.SetData(uid, ElectrifiedVisuals.ShowSparks, false); RemComp(uid); } } @@ -217,7 +217,7 @@ public sealed class ElectrocutionSystem : SharedElectrocutionSystem return false; EnsureComp(uid); - _appearance.SetData(uid, ElectrifiedVisuals.IsPowered, true); + _appearance.SetData(uid, ElectrifiedVisuals.ShowSparks, true); siemens *= electrified.SiemensCoefficient; if (!DoCommonElectrocutionAttempt(targetUid, uid, ref siemens) || siemens <= 0) @@ -488,15 +488,4 @@ public sealed class ElectrocutionSystem : SharedElectrocutionSystem } _audio.PlayPvs(electrified.ShockNoises, targetUid, AudioParams.Default.WithVolume(electrified.ShockVolume)); } - - public void SetElectrifiedWireCut(Entity ent, bool value) - { - if (ent.Comp.IsWireCut == value) - { - return; - } - - ent.Comp.IsWireCut = value; - Dirty(ent); - } } diff --git a/Content.Server/Ghost/GhostCommand.cs b/Content.Server/Ghost/GhostCommand.cs index a2f361d29d..26163f6d4d 100644 --- a/Content.Server/Ghost/GhostCommand.cs +++ b/Content.Server/Ghost/GhostCommand.cs @@ -1,7 +1,9 @@ using Content.Server.Popups; using Content.Shared.Administration; +using Content.Shared.GameTicking; using Content.Shared.Mind; using Robust.Shared.Console; +using Content.Server.GameTicking; namespace Content.Server.Ghost { @@ -23,6 +25,14 @@ namespace Content.Server.Ghost return; } + var gameTicker = _entities.System(); + if (!gameTicker.PlayerGameStatuses.TryGetValue(player.UserId, out var playerStatus) || + playerStatus is not PlayerGameStatus.JoinedGame) + { + shell.WriteLine("ghost-command-error-lobby"); + return; + } + if (player.AttachedEntity is { Valid: true } frozen && _entities.HasComponent(frozen)) { diff --git a/Content.Server/Power/Components/CableComponent.cs b/Content.Server/Power/Components/CableComponent.cs index 7398bc0616..63899735b5 100644 --- a/Content.Server/Power/Components/CableComponent.cs +++ b/Content.Server/Power/Components/CableComponent.cs @@ -18,8 +18,11 @@ public sealed partial class CableComponent : Component [DataField] public EntProtoId CableDroppedOnCutPrototype = "CableHVStack1"; + /// + /// The tool quality needed to cut the cable. Setting to null prevents cutting. + /// [DataField] - public ProtoId CuttingQuality = SharedToolSystem.CutQuality; + public ProtoId? CuttingQuality = SharedToolSystem.CutQuality; /// /// Checked by to determine if there is diff --git a/Content.Server/Power/EntitySystems/CableSystem.cs b/Content.Server/Power/EntitySystems/CableSystem.cs index d0f45b54fc..db44323007 100644 --- a/Content.Server/Power/EntitySystems/CableSystem.cs +++ b/Content.Server/Power/EntitySystems/CableSystem.cs @@ -35,7 +35,10 @@ public sealed partial class CableSystem : EntitySystem if (args.Handled) return; - args.Handled = _toolSystem.UseTool(args.Used, args.User, uid, cable.CuttingDelay, cable.CuttingQuality, new CableCuttingFinishedEvent()); + if (cable.CuttingQuality != null) + { + args.Handled = _toolSystem.UseTool(args.Used, args.User, uid, cable.CuttingDelay, cable.CuttingQuality, new CableCuttingFinishedEvent()); + } } private void OnCableCut(EntityUid uid, CableComponent cable, DoAfterEvent args) diff --git a/Content.Server/Power/PowerWireAction.cs b/Content.Server/Power/PowerWireAction.cs index cebb7de8ec..9e4e6a6086 100644 --- a/Content.Server/Power/PowerWireAction.cs +++ b/Content.Server/Power/PowerWireAction.cs @@ -17,7 +17,7 @@ public sealed partial class PowerWireAction : BaseWireAction [DataField("pulseTimeout")] private int _pulseTimeout = 30; - private ElectrocutionSystem _electrocutionSystem = default!; + private ElectrocutionSystem _electrocution = default!; public override object StatusKey { get; } = PowerWireActionKey.Status; @@ -105,8 +105,8 @@ public sealed partial class PowerWireAction : BaseWireAction && !EntityManager.TryGetComponent(used, out electrified)) return; - _electrocutionSystem.SetElectrifiedWireCut((used, electrified), setting); - electrified.Enabled = setting; + _electrocution.SetElectrifiedWireCut((used, electrified), setting); + _electrocution.SetElectrified((used, electrified), setting); } /// false if failed, true otherwise, or if the entity cannot be electrified @@ -120,7 +120,7 @@ public sealed partial class PowerWireAction : BaseWireAction // always set this to true SetElectrified(wire.Owner, true, electrified); - var electrifiedAttempt = _electrocutionSystem.TryDoElectrifiedAct(wire.Owner, user); + var electrifiedAttempt = _electrocution.TryDoElectrifiedAct(wire.Owner, user); // if we were electrified, then return false return !electrifiedAttempt; @@ -161,7 +161,7 @@ public sealed partial class PowerWireAction : BaseWireAction { base.Initialize(); - _electrocutionSystem = EntityManager.System(); + _electrocution = EntityManager.System(); } // This should add a wire into the entity's state, whether it be diff --git a/Content.Server/Procedural/DungeonJob/DungeonJob.PostGenWallMount.cs b/Content.Server/Procedural/DungeonJob/DungeonJob.PostGenWallMount.cs index afc7608d64..d5c8587ea9 100644 --- a/Content.Server/Procedural/DungeonJob/DungeonJob.PostGenWallMount.cs +++ b/Content.Server/Procedural/DungeonJob/DungeonJob.PostGenWallMount.cs @@ -20,7 +20,11 @@ public sealed partial class DungeonJob } var tileDef = _prototype.Index(tileProto); - data.SpawnGroups.TryGetValue(DungeonDataKey.WallMounts, out var spawnProto); + if (!data.SpawnGroups.TryGetValue(DungeonDataKey.WallMounts, out var spawnProto)) + { + // caves can have no walls + return; + } var checkedTiles = new HashSet(); var allExterior = new HashSet(dungeon.CorridorExteriorTiles); diff --git a/Content.Server/ServerInfo/ServerInfoManager.cs b/Content.Server/ServerInfo/ServerInfoManager.cs index d2e35e9663..673a33a941 100644 --- a/Content.Server/ServerInfo/ServerInfoManager.cs +++ b/Content.Server/ServerInfo/ServerInfoManager.cs @@ -13,11 +13,12 @@ public sealed class ServerInfoManager private static readonly (CVarDef cVar, string icon, string name)[] Vars = { // @formatter:off - (CCVars.InfoLinksDiscord, "discord", "info-link-discord"), - (CCVars.InfoLinksForum, "forum", "info-link-forum"), - (CCVars.InfoLinksGithub, "github", "info-link-github"), - (CCVars.InfoLinksWebsite, "web", "info-link-website"), - (CCVars.InfoLinksWiki, "wiki", "info-link-wiki") + (CCVars.InfoLinksDiscord, "discord", "info-link-discord"), + (CCVars.InfoLinksForum, "forum", "info-link-forum"), + (CCVars.InfoLinksGithub, "github", "info-link-github"), + (CCVars.InfoLinksWebsite, "web", "info-link-website"), + (CCVars.InfoLinksWiki, "wiki", "info-link-wiki"), + (CCVars.InfoLinksTelegram, "telegram", "info-link-telegram") // @formatter:on }; diff --git a/Content.Server/Shuttles/Systems/ShuttleSystem.FasterThanLight.cs b/Content.Server/Shuttles/Systems/ShuttleSystem.FasterThanLight.cs index 96ed1eaa7f..2a1f44259c 100644 --- a/Content.Server/Shuttles/Systems/ShuttleSystem.FasterThanLight.cs +++ b/Content.Server/Shuttles/Systems/ShuttleSystem.FasterThanLight.cs @@ -234,12 +234,6 @@ public sealed partial class ShuttleSystem if (TryComp(shuttleUid, out var shuttlePhysics)) { - // Static physics type is set when station anchor is enabled - if (shuttlePhysics.BodyType == BodyType.Static) - { - reason = Loc.GetString("shuttle-console-static"); - return false; - } // Too large to FTL if (FTLMassLimit > 0 && shuttlePhysics.Mass > FTLMassLimit) diff --git a/Content.Server/StationEvents/Components/GreytideVirusComponent.cs b/Content.Server/StationEvents/Components/GreytideVirusComponent.cs new file mode 100644 index 0000000000..307f131db1 --- /dev/null +++ b/Content.Server/StationEvents/Components/GreytideVirusComponent.cs @@ -0,0 +1,38 @@ +using Content.Server.StationEvents.Events; +using Content.Shared.Access; +using Content.Shared.Destructible.Thresholds; +using Robust.Shared.Prototypes; + +namespace Content.Server.StationEvents.Components; + +/// +/// Greytide Virus event specific configuration +/// +[RegisterComponent, Access(typeof(GreytideVirusRule))] +public sealed partial class GreytideVirusRuleComponent : Component +{ + /// + /// Range from which the severity is randomly picked from. + /// + [DataField] + public MinMax SeverityRange = new(1, 3); + + /// + /// Severity corresponding to the number of access groups affected. + /// Will pick randomly from the SeverityRange if not specified. + /// + [DataField] + public int? Severity; + + /// + /// Access groups to pick from. + /// + [DataField] + public List> AccessGroups = new(); + + /// + /// Entities with this access level will be ignored. + /// + [DataField] + public List> Blacklist = new(); +} diff --git a/Content.Server/StationEvents/Events/GreytideVirusRule.cs b/Content.Server/StationEvents/Events/GreytideVirusRule.cs new file mode 100644 index 0000000000..f60d80ba9c --- /dev/null +++ b/Content.Server/StationEvents/Events/GreytideVirusRule.cs @@ -0,0 +1,96 @@ +using Content.Server.StationEvents.Components; +using Content.Shared.Access; +using Content.Shared.Access.Systems; +using Content.Shared.Access.Components; +using Content.Shared.Doors.Components; +using Content.Shared.Doors.Systems; +using Content.Shared.Lock; +using Content.Shared.GameTicking.Components; +using Robust.Shared.Prototypes; +using Robust.Shared.Random; + +namespace Content.Server.StationEvents.Events; + + +/// +/// Greytide Virus event +/// This will open and bolt airlocks and unlock lockers from randomly selected access groups. +/// +public sealed class GreytideVirusRule : StationEventSystem +{ + [Dependency] private readonly AccessReaderSystem _access = default!; + [Dependency] private readonly SharedDoorSystem _door = default!; + [Dependency] private readonly LockSystem _lock = default!; + [Dependency] private readonly IPrototypeManager _prototype = default!; + [Dependency] private readonly IRobustRandom _random = default!; + + protected override void Added(EntityUid uid, GreytideVirusRuleComponent virusComp, GameRuleComponent gameRule, GameRuleAddedEvent args) + { + if (!TryComp(uid, out var stationEvent)) + return; + + // pick severity randomly from range if not specified otherwise + virusComp.Severity ??= virusComp.SeverityRange.Next(_random); + virusComp.Severity = Math.Min(virusComp.Severity.Value, virusComp.AccessGroups.Count); + + stationEvent.StartAnnouncement = Loc.GetString("station-event-greytide-virus-start-announcement", ("severity", virusComp.Severity.Value)); + base.Added(uid, virusComp, gameRule, args); + } + protected override void Started(EntityUid uid, GreytideVirusRuleComponent virusComp, GameRuleComponent gameRule, GameRuleStartedEvent args) + { + base.Started(uid, virusComp, gameRule, args); + + if (virusComp.Severity == null) + return; + + // pick random access groups + var chosen = _random.GetItems(virusComp.AccessGroups, virusComp.Severity.Value, allowDuplicates: false); + + // combine all the selected access groups + var accessIds = new HashSet>(); + foreach (var group in chosen) + { + if (_prototype.TryIndex(group, out var proto)) + accessIds.UnionWith(proto.Tags); + } + + var firelockQuery = GetEntityQuery(); + var accessQuery = GetEntityQuery(); + + var lockQuery = AllEntityQuery(); + while (lockQuery.MoveNext(out var lockUid, out var lockComp)) + { + if (!accessQuery.TryComp(lockUid, out var accessComp)) + continue; + + // check access + // the AreAccessTagsAllowed function is a little weird because it technically has support for certain tags to be locked out of opening something + // which might have unintened side effects (see the comments in the function itself) + // but no one uses that yet, so it is fine for now + if (!_access.AreAccessTagsAllowed(accessIds, accessComp) || _access.AreAccessTagsAllowed(virusComp.Blacklist, accessComp)) + continue; + + // open lockers + _lock.Unlock(lockUid, null, lockComp); + } + + var airlockQuery = AllEntityQuery(); + while (airlockQuery.MoveNext(out var airlockUid, out var airlockComp, out var doorComp)) + { + // don't space everything + if (firelockQuery.HasComp(airlockUid)) + continue; + + // use the access reader from the door electronics if they exist + if (!_access.GetMainAccessReader(airlockUid, out var accessComp)) + continue; + + // check access + if (!_access.AreAccessTagsAllowed(accessIds, accessComp) || _access.AreAccessTagsAllowed(virusComp.Blacklist, accessComp)) + continue; + + // open and bolt airlocks + _door.TryOpenAndBolt(airlockUid, doorComp, airlockComp); + } + } +} diff --git a/Content.Server/VendingMachines/VendingMachineSystem.cs b/Content.Server/VendingMachines/VendingMachineSystem.cs index 2f557b7eef..bd1bc1303c 100644 --- a/Content.Server/VendingMachines/VendingMachineSystem.cs +++ b/Content.Server/VendingMachines/VendingMachineSystem.cs @@ -38,6 +38,7 @@ namespace Content.Server.VendingMachines [Dependency] private readonly ThrowingSystem _throwingSystem = default!; [Dependency] private readonly IGameTiming _timing = default!; [Dependency] private readonly SpeakOnUIClosedSystem _speakOnUIClosed = default!; + [Dependency] private readonly SharedPointLightSystem _light = default!; private const float WallVendEjectDistanceFromWall = 1f; @@ -334,6 +335,12 @@ namespace Content.Server.VendingMachines finalState = VendingMachineVisualState.Off; } + if (_light.TryGetLight(uid, out var pointlight)) + { + var lightState = finalState != VendingMachineVisualState.Broken && finalState != VendingMachineVisualState.Off; + _light.SetEnabled(uid, lightState, pointlight); + } + _appearanceSystem.SetData(uid, VendingMachineVisuals.VisualState, finalState); } diff --git a/Content.Server/Wires/ComponentWireAction.cs b/Content.Server/Wires/ComponentWireAction.cs index 2407068056..90c8a7594d 100644 --- a/Content.Server/Wires/ComponentWireAction.cs +++ b/Content.Server/Wires/ComponentWireAction.cs @@ -22,13 +22,14 @@ public abstract partial class ComponentWireAction : BaseWireAction w public override bool Cut(EntityUid user, Wire wire) { base.Cut(user, wire); - return EntityManager.TryGetComponent(wire.Owner, out TComponent? component) && Cut(user, wire, component); + // if the entity doesn't exist, we need to return true otherwise the wire sprite is never updated + return EntityManager.TryGetComponent(wire.Owner, out TComponent? component) ? Cut(user, wire, component) : true; } public override bool Mend(EntityUid user, Wire wire) { base.Mend(user, wire); - return EntityManager.TryGetComponent(wire.Owner, out TComponent? component) && Mend(user, wire, component); + return EntityManager.TryGetComponent(wire.Owner, out TComponent? component) ? Mend(user, wire, component) : true; } public override void Pulse(EntityUid user, Wire wire) diff --git a/Content.Shared.Database/TypedHwid.cs b/Content.Shared.Database/TypedHwid.cs new file mode 100644 index 0000000000..253375e9db --- /dev/null +++ b/Content.Shared.Database/TypedHwid.cs @@ -0,0 +1,64 @@ +using System.Collections.Immutable; +using System.Diagnostics.CodeAnalysis; + +namespace Content.Shared.Database; + +/// +/// Represents a raw HWID value together with its type. +/// +[Serializable] +public sealed class ImmutableTypedHwid(ImmutableArray hwid, HwidType type) +{ + public readonly ImmutableArray Hwid = hwid; + public readonly HwidType Type = type; + + public override string ToString() + { + var b64 = Convert.ToBase64String(Hwid.AsSpan()); + return Type == HwidType.Modern ? $"V2-{b64}" : b64; + } + + public static bool TryParse(string value, [NotNullWhen(true)] out ImmutableTypedHwid? hwid) + { + var type = HwidType.Legacy; + if (value.StartsWith("V2-", StringComparison.Ordinal)) + { + value = value["V2-".Length..]; + type = HwidType.Modern; + } + + var array = new byte[GetBase64ByteLength(value)]; + if (!Convert.TryFromBase64String(value, array, out _)) + { + hwid = null; + return false; + } + + // ReSharper disable once UseCollectionExpression + // Do not use collection expression, C# compiler is weird and it fails sandbox. + hwid = new ImmutableTypedHwid(ImmutableArray.Create(array), type); + return true; + } + + private static int GetBase64ByteLength(string value) + { + // Why is .NET like this man wtf. + return 3 * (value.Length / 4) - value.TakeLast(2).Count(c => c == '='); + } +} + +/// +/// Represents different types of HWIDs as exposed by the engine. +/// +public enum HwidType +{ + /// + /// The legacy HWID system. Should only be used for checking old existing database bans. + /// + Legacy = 0, + + /// + /// The modern HWID system. + /// + Modern = 1, +} diff --git a/Content.Shared/Administration/BanPanelEuiState.cs b/Content.Shared/Administration/BanPanelEuiState.cs index dd10068e5d..74c340566b 100644 --- a/Content.Shared/Administration/BanPanelEuiState.cs +++ b/Content.Shared/Administration/BanPanelEuiState.cs @@ -25,7 +25,7 @@ public static class BanPanelEuiStateMsg { public string? Player { get; set; } public string? IpAddress { get; set; } - public byte[]? Hwid { get; set; } + public ImmutableTypedHwid? Hwid { get; set; } public uint Minutes { get; set; } public string Reason { get; set; } public NoteSeverity Severity { get; set; } @@ -34,7 +34,7 @@ public static class BanPanelEuiStateMsg public bool UseLastHwid { get; set; } public bool Erase { get; set; } - public CreateBanRequest(string? player, (IPAddress, int)? ipAddress, bool useLastIp, byte[]? hwid, bool useLastHwid, uint minutes, string reason, NoteSeverity severity, string[]? roles, bool erase) + public CreateBanRequest(string? player, (IPAddress, int)? ipAddress, bool useLastIp, ImmutableTypedHwid? hwid, bool useLastHwid, uint minutes, string reason, NoteSeverity severity, string[]? roles, bool erase) { Player = player; IpAddress = ipAddress == null ? null : $"{ipAddress.Value.Item1}/{ipAddress.Value.Item2}"; diff --git a/Content.Shared/CCVar/CCVars.Game.Infolinks.cs b/Content.Shared/CCVar/CCVars.Game.Infolinks.cs index fa8332b497..5544953a0d 100644 --- a/Content.Shared/CCVar/CCVars.Game.Infolinks.cs +++ b/Content.Shared/CCVar/CCVars.Game.Infolinks.cs @@ -51,4 +51,10 @@ public sealed partial class CCVars /// public static readonly CVarDef InfoLinksAppeal = CVarDef.Create("infolinks.appeal", "", CVar.SERVER | CVar.REPLICATED); + + /// + /// Link to Telegram channel to show in the launcher. + /// + public static readonly CVarDef InfoLinksTelegram = + CVarDef.Create("infolinks.telegram", "", CVar.SERVER | CVar.REPLICATED); } diff --git a/Content.Shared/CCVar/CCVars.Shuttle.cs b/Content.Shared/CCVar/CCVars.Shuttle.cs index 4fe4440d85..4513ed419c 100644 --- a/Content.Shared/CCVar/CCVars.Shuttle.cs +++ b/Content.Shared/CCVar/CCVars.Shuttle.cs @@ -4,6 +4,12 @@ namespace Content.Shared.CCVar; public sealed partial class CCVars { + /// + /// Delay for auto-orientation. Used for people arriving via arrivals. + /// + public static readonly CVarDef AutoOrientDelay = + CVarDef.Create("shuttle.auto_orient_delay", 2.0, CVar.SERVER | CVar.REPLICATED); + /// /// If true then the camera will match the grid / map and is unchangeable. /// - When traversing grids it will snap to 0 degrees rotation. diff --git a/Content.Shared/Climbing/Systems/ClimbSystem.cs b/Content.Shared/Climbing/Systems/ClimbSystem.cs index 9bf481002a..467d96187e 100644 --- a/Content.Shared/Climbing/Systems/ClimbSystem.cs +++ b/Content.Shared/Climbing/Systems/ClimbSystem.cs @@ -151,6 +151,10 @@ public sealed partial class ClimbSystem : VirtualController if (args.Handled) return; + // If already climbing then don't show outlines. + if (TryComp(args.Dragged, out ClimbingComponent? climbing) && climbing.IsClimbing) + return; + var canVault = args.User == args.Dragged ? CanVault(component, args.User, uid, out _) : CanVault(component, args.User, args.Dragged, uid, out _); diff --git a/Content.Shared/Doors/Components/DoorComponent.cs b/Content.Shared/Doors/Components/DoorComponent.cs index 8c260a9c2e..f76f235fca 100644 --- a/Content.Shared/Doors/Components/DoorComponent.cs +++ b/Content.Shared/Doors/Components/DoorComponent.cs @@ -66,7 +66,7 @@ public sealed partial class DoorComponent : Component /// /// When the door is active, this is the time when the state will next update. /// - [AutoNetworkedField] + [AutoNetworkedField, ViewVariables] public TimeSpan? NextStateChange; /// diff --git a/Content.Shared/Doors/DoorEvents.cs b/Content.Shared/Doors/DoorEvents.cs index 08a2c8b18b..849ea83730 100644 --- a/Content.Shared/Doors/DoorEvents.cs +++ b/Content.Shared/Doors/DoorEvents.cs @@ -15,6 +15,19 @@ namespace Content.Shared.Doors } } + /// + /// Raised when the door's bolt status was changed. + /// + public sealed class DoorBoltsChangedEvent : EntityEventArgs + { + public readonly bool BoltsDown; + + public DoorBoltsChangedEvent(bool boltsDown) + { + BoltsDown = boltsDown; + } + } + /// /// Raised when the door is determining whether it is able to open. /// Cancel to stop the door from being opened. diff --git a/Content.Shared/Doors/Systems/SharedAirlockSystem.cs b/Content.Shared/Doors/Systems/SharedAirlockSystem.cs index e404a91bdd..bdd119004e 100644 --- a/Content.Shared/Doors/Systems/SharedAirlockSystem.cs +++ b/Content.Shared/Doors/Systems/SharedAirlockSystem.cs @@ -22,6 +22,7 @@ public abstract class SharedAirlockSystem : EntitySystem SubscribeLocalEvent(OnBeforeDoorClosed); SubscribeLocalEvent(OnStateChanged); + SubscribeLocalEvent(OnBoltsChanged); SubscribeLocalEvent(OnBeforeDoorOpened); SubscribeLocalEvent(OnBeforeDoorDenied); SubscribeLocalEvent(OnGetPryMod); @@ -70,6 +71,13 @@ public abstract class SharedAirlockSystem : EntitySystem } } + private void OnBoltsChanged(EntityUid uid, AirlockComponent component, DoorBoltsChangedEvent args) + { + // If unbolted, reset the auto close timer + if (!args.BoltsDown) + UpdateAutoClose(uid, component); + } + private void OnBeforeDoorOpened(EntityUid uid, AirlockComponent component, BeforeDoorOpenedEvent args) { if (!CanChangeState(uid, component)) @@ -145,7 +153,7 @@ public abstract class SharedAirlockSystem : EntitySystem ent.Comp.EmergencyAccess = value; Dirty(ent, ent.Comp); // This only runs on the server apparently so we need this. UpdateEmergencyLightStatus(ent, ent.Comp); - + var sound = ent.Comp.EmergencyAccess ? ent.Comp.EmergencyOnSound : ent.Comp.EmergencyOffSound; if (predicted) Audio.PlayPredicted(sound, ent, user: user); diff --git a/Content.Shared/Doors/Systems/SharedDoorSystem.Bolts.cs b/Content.Shared/Doors/Systems/SharedDoorSystem.Bolts.cs index 13050616e1..d14b6c7190 100644 --- a/Content.Shared/Doors/Systems/SharedDoorSystem.Bolts.cs +++ b/Content.Shared/Doors/Systems/SharedDoorSystem.Bolts.cs @@ -96,6 +96,10 @@ public abstract partial class SharedDoorSystem Dirty(ent, ent.Comp); UpdateBoltLightStatus(ent); + // used to reset the auto-close timer after unbolting + var ev = new DoorBoltsChangedEvent(value); + RaiseLocalEvent(ent.Owner, ev); + var sound = value ? ent.Comp.BoltDownSound : ent.Comp.BoltUpSound; if (predicted) Audio.PlayPredicted(sound, ent, user: user); diff --git a/Content.Shared/Doors/Systems/SharedDoorSystem.cs b/Content.Shared/Doors/Systems/SharedDoorSystem.cs index eb3715e354..67fa01c004 100644 --- a/Content.Shared/Doors/Systems/SharedDoorSystem.cs +++ b/Content.Shared/Doors/Systems/SharedDoorSystem.cs @@ -400,6 +400,25 @@ public abstract partial class SharedDoorSystem : EntitySystem Dirty(uid, door); } + + /// + /// Opens and then bolts a door. + /// Different from emagging this does not remove the access reader, so it can be repaired by simply unbolting the door. + /// + public bool TryOpenAndBolt(EntityUid uid, DoorComponent? door = null, AirlockComponent? airlock = null) + { + if (!Resolve(uid, ref door, ref airlock)) + return false; + + if (IsBolted(uid) || !airlock.Powered || door.State != DoorState.Closed) + { + return false; + } + + SetState(uid, DoorState.Emagging, door); + + return true; + } #endregion #region Closing @@ -465,17 +484,17 @@ public abstract partial class SharedDoorSystem : EntitySystem if (!Resolve(uid, ref door, ref physics)) return false; - door.Partial = true; - // Make sure no entity walked into the airlock when it started closing. if (!CanClose(uid, door)) { door.NextStateChange = GameTiming.CurTime + door.OpenTimeTwo; - door.State = DoorState.Opening; - AppearanceSystem.SetData(uid, DoorVisuals.State, DoorState.Opening); + door.State = DoorState.Open; + AppearanceSystem.SetData(uid, DoorVisuals.State, DoorState.Open); + Dirty(uid, door); return false; } + door.Partial = true; SetCollidable(uid, true, door, physics); door.NextStateChange = GameTiming.CurTime + door.CloseTimeTwo; Dirty(uid, door); @@ -709,6 +728,8 @@ public abstract partial class SharedDoorSystem : EntitySystem } door.NextStateChange = GameTiming.CurTime + delay.Value; + Dirty(uid, door); + _activeDoors.Add((uid, door)); } diff --git a/Content.Shared/DrawDepth/DrawDepth.cs b/Content.Shared/DrawDepth/DrawDepth.cs index f7b1f3648a..d0d2daf5d9 100644 --- a/Content.Shared/DrawDepth/DrawDepth.cs +++ b/Content.Shared/DrawDepth/DrawDepth.cs @@ -74,33 +74,38 @@ namespace Content.Shared.DrawDepth /// Items = DrawDepthTag.Default + 3, - Mobs = DrawDepthTag.Default + 4, - - OverMobs = DrawDepthTag.Default + 5, + /// + /// Stuff that should be drawn below mobs, but on top of items. Like muzzle flash. + /// + BelowMobs = DrawDepthTag.Default + 4, - Doors = DrawDepthTag.Default + 6, + Mobs = DrawDepthTag.Default + 5, + + OverMobs = DrawDepthTag.Default + 6, + + Doors = DrawDepthTag.Default + 7, /// /// Blast doors and shutters which go over the usual doors. /// - BlastDoors = DrawDepthTag.Default + 7, + BlastDoors = DrawDepthTag.Default + 8, /// /// Stuff that needs to draw over most things, but not effects, like Kudzu. /// - Overdoors = DrawDepthTag.Default + 8, + Overdoors = DrawDepthTag.Default + 9, /// /// Explosions, fire, melee swings. Whatever. /// - Effects = DrawDepthTag.Default + 9, + Effects = DrawDepthTag.Default + 10, - Ghosts = DrawDepthTag.Default + 10, + Ghosts = DrawDepthTag.Default + 11, /// /// Use this selectively if it absolutely needs to be drawn above (almost) everything else. Examples include /// the pointing arrow, the drag & drop ghost-entity, and some debug tools. /// - Overlays = DrawDepthTag.Default + 11, + Overlays = DrawDepthTag.Default + 12, } } diff --git a/Content.Shared/Electrocution/Components/ElectrocutionHUDVisualsComponent.cs b/Content.Shared/Electrocution/Components/ElectrocutionHUDVisualsComponent.cs new file mode 100644 index 0000000000..a48b1e3e5a --- /dev/null +++ b/Content.Shared/Electrocution/Components/ElectrocutionHUDVisualsComponent.cs @@ -0,0 +1,7 @@ +namespace Content.Shared.Electrocution; + +/// +/// Handles toggling sprite layers for the electrocution HUD to show if an entity with the ElectrifiedComponent is electrified. +/// +[RegisterComponent] +public sealed partial class ElectrocutionHUDVisualsComponent : Component; diff --git a/Content.Shared/Electrocution/Components/ShowElectrocutionHUDComponent.cs b/Content.Shared/Electrocution/Components/ShowElectrocutionHUDComponent.cs new file mode 100644 index 0000000000..a6d9f380da --- /dev/null +++ b/Content.Shared/Electrocution/Components/ShowElectrocutionHUDComponent.cs @@ -0,0 +1,9 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared.Electrocution; + +/// +/// Allow an entity to see the Electrocution HUD showing electrocuted doors. +/// +[RegisterComponent, NetworkedComponent] +public sealed partial class ShowElectrocutionHUDComponent : Component; diff --git a/Content.Shared/Electrocution/SharedElectrocution.cs b/Content.Shared/Electrocution/SharedElectrocution.cs index 4060856d4d..5422049874 100644 --- a/Content.Shared/Electrocution/SharedElectrocution.cs +++ b/Content.Shared/Electrocution/SharedElectrocution.cs @@ -5,11 +5,13 @@ namespace Content.Shared.Electrocution; [Serializable, NetSerializable] public enum ElectrifiedLayers : byte { - Powered + Sparks, + HUD, } [Serializable, NetSerializable] public enum ElectrifiedVisuals : byte { - IsPowered + ShowSparks, // only shown when zapping someone, deactivated after a short time + IsElectrified, // if the entity is electrified or not, used for the AI HUD } diff --git a/Content.Shared/Electrocution/SharedElectrocutionSystem.cs b/Content.Shared/Electrocution/SharedElectrocutionSystem.cs index e36e4a804b..5da344e023 100644 --- a/Content.Shared/Electrocution/SharedElectrocutionSystem.cs +++ b/Content.Shared/Electrocution/SharedElectrocutionSystem.cs @@ -5,6 +5,8 @@ namespace Content.Shared.Electrocution { public abstract class SharedElectrocutionSystem : EntitySystem { + [Dependency] private readonly SharedAppearanceSystem _appearance = default!; + public override void Initialize() { base.Initialize(); @@ -35,6 +37,19 @@ namespace Content.Shared.Electrocution ent.Comp.Enabled = value; Dirty(ent, ent.Comp); + + _appearance.SetData(ent.Owner, ElectrifiedVisuals.IsElectrified, value); + } + + public void SetElectrifiedWireCut(Entity ent, bool value) + { + if (ent.Comp.IsWireCut == value) + { + return; + } + + ent.Comp.IsWireCut = value; + Dirty(ent); } /// Entity being electrocuted. diff --git a/Content.Shared/Movement/Components/AutoOrientComponent.cs b/Content.Shared/Movement/Components/AutoOrientComponent.cs index 4b89b0cbf4..1031425c71 100644 --- a/Content.Shared/Movement/Components/AutoOrientComponent.cs +++ b/Content.Shared/Movement/Components/AutoOrientComponent.cs @@ -5,8 +5,9 @@ namespace Content.Shared.Movement.Components; /// /// Automatically rotates eye upon grid traversals. /// -[RegisterComponent, NetworkedComponent] +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState, AutoGenerateComponentPause] public sealed partial class AutoOrientComponent : Component { - + [DataField, AutoNetworkedField, AutoPausedField] + public TimeSpan? NextChange; } diff --git a/Content.Shared/Movement/Systems/AutoOrientSystem.cs b/Content.Shared/Movement/Systems/AutoOrientSystem.cs new file mode 100644 index 0000000000..3bbd715df5 --- /dev/null +++ b/Content.Shared/Movement/Systems/AutoOrientSystem.cs @@ -0,0 +1,51 @@ +using Content.Shared.CCVar; +using Content.Shared.Movement.Components; +using Robust.Shared.Configuration; +using Robust.Shared.Timing; + +namespace Content.Shared.Movement.Systems; + +public sealed class AutoOrientSystem : EntitySystem +{ + [Dependency] private readonly IConfigurationManager _cfgManager = default!; + [Dependency] private readonly IGameTiming _timing = default!; + [Dependency] private readonly SharedMoverController _mover = default!; + + private TimeSpan _delay = TimeSpan.Zero; + + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(OnEntParentChanged); + + Subs.CVar(_cfgManager, CCVars.AutoOrientDelay, OnAutoOrient, true); + } + + private void OnAutoOrient(double obj) + { + _delay = TimeSpan.FromSeconds(obj); + } + + private void OnEntParentChanged(Entity ent, ref EntParentChangedMessage args) + { + ent.Comp.NextChange = _timing.CurTime + _delay; + Dirty(ent); + } + + public override void Update(float frameTime) + { + base.Update(frameTime); + + var query = EntityQueryEnumerator(); + + while (query.MoveNext(out var uid, out var comp)) + { + if (comp.NextChange <= _timing.CurTime) + { + comp.NextChange = null; + Dirty(uid, comp); + _mover.ResetCamera(uid); + } + } + } +} diff --git a/Content.Shared/Movement/Systems/SharedMoverController.Input.cs b/Content.Shared/Movement/Systems/SharedMoverController.Input.cs index c11df709f6..1fe38b6cdf 100644 --- a/Content.Shared/Movement/Systems/SharedMoverController.Input.cs +++ b/Content.Shared/Movement/Systems/SharedMoverController.Input.cs @@ -57,8 +57,6 @@ namespace Content.Shared.Movement.Systems SubscribeLocalEvent(OnMoverHandleState); SubscribeLocalEvent(OnInputParentChange); - SubscribeLocalEvent(OnAutoParentChange); - SubscribeLocalEvent(OnFollowedParentChange); Subs.CVar(_configManager, CCVars.CameraRotationLocked, obj => CameraRotationLocked = obj, true); @@ -146,11 +144,6 @@ namespace Content.Shared.Movement.Systems protected virtual void HandleShuttleInput(EntityUid uid, ShuttleButtons button, ushort subTick, bool state) {} - private void OnAutoParentChange(Entity entity, ref EntParentChangedMessage args) - { - ResetCamera(entity.Owner); - } - public void RotateCamera(EntityUid uid, Angle angle) { if (CameraRotationLocked || !MoverQuery.TryGetComponent(uid, out var mover)) diff --git a/Content.Shared/Silicons/StationAi/SharedStationAiSystem.Airlock.cs b/Content.Shared/Silicons/StationAi/SharedStationAiSystem.Airlock.cs index 37e5cd6e6a..ca2d593dbe 100644 --- a/Content.Shared/Silicons/StationAi/SharedStationAiSystem.Airlock.cs +++ b/Content.Shared/Silicons/StationAi/SharedStationAiSystem.Airlock.cs @@ -34,7 +34,7 @@ public abstract partial class SharedStationAiSystem } /// - /// Attempts to bolt door. If wire was cut (AI) or its not powered - notifies AI and does nothing. + /// Attempts to toggle the door's emergency access. If wire was cut (AI) or its not powered - notifies AI and does nothing. /// private void OnAirlockEmergencyAccess(EntityUid ent, AirlockComponent component, StationAiEmergencyAccessEvent args) { @@ -48,7 +48,7 @@ public abstract partial class SharedStationAiSystem } /// - /// Attempts to bolt door. If wire was cut (AI or for one of power-wires) or its not powered - notifies AI and does nothing. + /// Attempts to electrify the door. If wire was cut (AI or for one of power-wires) or its not powered - notifies AI and does nothing. /// private void OnElectrified(EntityUid ent, ElectrifiedComponent component, StationAiElectrifiedEvent args) { diff --git a/Content.Shared/Silicons/StationAi/SharedStationAiSystem.cs b/Content.Shared/Silicons/StationAi/SharedStationAiSystem.cs index 189515635a..5fca5cad28 100644 --- a/Content.Shared/Silicons/StationAi/SharedStationAiSystem.cs +++ b/Content.Shared/Silicons/StationAi/SharedStationAiSystem.cs @@ -394,6 +394,9 @@ public abstract partial class SharedStationAiSystem : EntitySystem private void OnAiInsert(Entity ent, ref EntInsertedIntoContainerMessage args) { + if (args.Container.ID != StationAiCoreComponent.Container) + return; + if (_timing.ApplyingState) return; diff --git a/Content.Shared/Station/SharedStationSpawningSystem.cs b/Content.Shared/Station/SharedStationSpawningSystem.cs index ad264cd22a..a23ee30940 100644 --- a/Content.Shared/Station/SharedStationSpawningSystem.cs +++ b/Content.Shared/Station/SharedStationSpawningSystem.cs @@ -2,6 +2,7 @@ using System.Linq; using Content.Shared.Hands.Components; using Content.Shared.Hands.EntitySystems; using Content.Shared.Inventory; +using Content.Shared.Item; using Content.Shared.Preferences.Loadouts; using Content.Shared.Roles; using Content.Shared.Storage; @@ -145,27 +146,23 @@ public abstract class SharedStationSpawningSystem : EntitySystem if (startingGear.Storage.Count > 0) { var coords = _xformSystem.GetMapCoordinates(entity); - var ents = new ValueList(); _inventoryQuery.TryComp(entity, out var inventoryComp); - foreach (var (slot, entProtos) in startingGear.Storage) + foreach (var (slotName, entProtos) in startingGear.Storage) { - ents.Clear(); - if (entProtos.Count == 0) + if (entProtos == null || entProtos.Count == 0) continue; if (inventoryComp != null && - InventorySystem.TryGetSlotEntity(entity, slot, out var slotEnt, inventoryComponent: inventoryComp) && + InventorySystem.TryGetSlotEntity(entity, slotName, out var slotEnt, inventoryComponent: inventoryComp) && _storageQuery.TryComp(slotEnt, out var storage)) { - foreach (var ent in entProtos) - { - ents.Add(Spawn(ent, coords)); - } - foreach (var ent in ents) + foreach (var entProto in entProtos) { - _storage.Insert(slotEnt.Value, ent, out _, storageComp: storage, playSound: false); + var spawnedEntity = Spawn(entProto, coords); + + _storage.Insert(slotEnt.Value, spawnedEntity, out _, storageComp: storage, playSound: false); } } } diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 6bc25079ce..1e2be75b29 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,154 +1,4 @@ Entries: -- author: EmoGarbage404 - changes: - - message: Legends tell of horrifying Goliaths that roam the mining asteroid. - type: Add - id: 7137 - time: '2024-08-18T16:22:36.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/30839 -- author: Beck Thompson - changes: - - message: Cutting food now moves the sliced pieces a small amount! - type: Tweak - id: 7138 - time: '2024-08-18T21:18:20.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/31166 -- author: lzk228 - changes: - - message: Pizza and pizza box now have 3x2 size in inventory. - type: Tweak - - message: Pizze box is 4x2 inside and always will have a pizza with a knife inside. - type: Tweak - - message: Pizza box have whitelist for utensils and pizza. - type: Tweak - id: 7139 - time: '2024-08-18T21:55:42.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/31171 -- author: Deatherd - changes: - - message: Sharks Go RAWR! - type: Tweak - id: 7140 - time: '2024-08-18T22:18:07.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/31142 -- author: slarticodefast - changes: - - message: Fixed the radiation collector warning light thresholds. - type: Fix - id: 7141 - time: '2024-08-18T22:25:02.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/31175 -- author: Potato1234_x - changes: - - message: Added tea plants that can be dried and ground to make tea powder which - can then be used to make tea. - type: Add - - message: Added blue pumpkins. Currently useless but recipe uses are coming soon. - type: Add - id: 7142 - time: '2024-08-18T22:28:18.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/25092 -- author: deltanedas - changes: - - message: Added Memory Cells for storing logic signals persistently. - type: Add - id: 7143 - time: '2024-08-18T22:34:43.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/24983 -- author: Psychpsyo - changes: - - message: The random sentience event is back and can no longer pick things that - aren't even on the station. - type: Add - id: 7144 - time: '2024-08-18T23:41:12.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/29123 -- author: EmoGarbage404 - changes: - - message: Ore can no longer be destroyed by explosions. Happy blast mining. - type: Tweak - id: 7145 - time: '2024-08-19T01:55:49.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/31182 -- author: slarticodefast - changes: - - message: Mobs without hands can no longer toggle other players' suit pieces. - type: Fix - id: 7146 - time: '2024-08-19T02:41:27.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/31152 -- author: Goldminermac - changes: - - message: Chocolate-chip and blueberry pancakes can now be in stacks of up to nine - for consistency. - type: Fix - id: 7147 - time: '2024-08-19T02:42:58.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/31123 -- author: tosatur - changes: - - message: Made hydroponics alert light more orange - type: Tweak - id: 7148 - time: '2024-08-19T02:48:47.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/31088 -- author: redmushie - changes: - - message: News management console now checks for Service ID card access instead - of the manifest - type: Fix - id: 7149 - time: '2024-08-19T02:55:44.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/31160 -- author: Moomoobeef - changes: - - message: Added pitchers for the chef who wants to serve beverages too. - type: Add - id: 7150 - time: '2024-08-19T03:01:26.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/31105 -- author: EmoGarbage404 - changes: - - message: Space carp and Sharkminnows now drop teeth when butchered. - type: Add - - message: Added new bounties for carp and shark teeth. - type: Add - id: 7151 - time: '2024-08-19T03:04:59.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/31070 -- author: to4no_fix - changes: - - message: Now it takes 5 seconds to take off or put on a muzzle - type: Tweak - - message: Now it takes 5 seconds to take off or put on a blindfold - type: Tweak - - message: Added a recipe for producing a straitjacket, it opens when researching - the Special Means technology, it can be produced at the security techfab - type: Add - id: 7152 - time: '2024-08-19T03:05:25.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/31095 -- author: Magicalus - changes: - - message: Suit sensors, borgs, and PDAs can no longer be saved to device-lists. - type: Tweak - id: 7153 - time: '2024-08-19T03:13:04.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/30997 -- author: UBlueberry - changes: - - message: The guidebook entries for all antagonists have been revised. - type: Tweak - id: 7154 - time: '2024-08-19T03:16:05.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/31075 -- author: TheWaffleJesus - changes: - - message: ERT Chaplains now have blessings to use their bible. - type: Fix - id: 7155 - time: '2024-08-19T03:19:19.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/30993 - author: DieselMohawk changes: - message: Reshaped the Security Helmet @@ -3933,3 +3783,146 @@ id: 7636 time: '2024-11-22T02:56:05.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/31076 +- author: chromiumboy + changes: + - message: Added the gas pipe sensor. These sensors monitor the mixture of gases + passing through their pipe sub-network and report this information to any connected + air alarms + type: Add + id: 7637 + time: '2024-11-22T03:46:10.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/33128 +- author: IProduceWidgets + changes: + - message: The terminal is more tamper proof. + type: Fix + id: 7638 + time: '2024-11-22T22:50:41.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/33281 +- author: MissKay1994 + changes: + - message: The salvage vendor now has enough equipment for everyone + type: Tweak + id: 7639 + time: '2024-11-23T02:53:48.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/33437 +- author: slarticodefast + changes: + - message: The AI and observers can now see if doors are electrified. + type: Add + id: 7640 + time: '2024-11-23T06:37:15.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/33466 +- author: Winkarst-cpu + changes: + - message: Now submit button in admin notes becomes disabled on switching type back + to note. + type: Fix + id: 7641 + time: '2024-11-23T06:41:28.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/33456 +- author: metalgearsloth + changes: + - message: Fix airlock animations mispredicting if the closing animation is interrupted, + e.g. via walking into it. + type: Fix + id: 7642 + time: '2024-11-23T09:31:08.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/33481 +- author: metalgearsloth + changes: + - message: Drag-drop outline no longer shows the vaulting outlines if you're vaulting. + type: Tweak + id: 7643 + time: '2024-11-23T11:19:59.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/33477 +- author: goet + changes: + - message: Useless wires some vending machines have can be cut now. + type: Fix + id: 7644 + time: '2024-11-23T11:41:37.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/32447 +- author: IProduceWidgets + changes: + - message: Arrivals shuttle is more tamper proof. + type: Fix + id: 7645 + time: '2024-11-23T15:14:13.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/33284 +- author: metalgearsloth + changes: + - message: The auto-orientation when showing up on the arrivals shuttle now has + a delay to it. + type: Tweak + id: 7646 + time: '2024-11-23T16:52:58.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/33479 +- author: Winkarst-cpu + changes: + - message: Now muzzle flashes are displayed below mobs. + type: Tweak + id: 7647 + time: '2024-11-24T04:20:00.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/33465 +- author: MilenVolf + changes: + - message: Expeditions can now be completed prematurely again by making an FTL jump. + type: Fix + id: 7648 + time: '2024-11-24T08:11:47.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/33507 +- author: deltanedas + changes: + - message: Fixed expeditions on cave planets not having any ore. + type: Fix + id: 7649 + time: '2024-11-24T08:49:31.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/32890 +- author: slarticodefast + changes: + - message: Fixed doors not auto-closing correctly after being unbolted in an open + state. + type: Fix + id: 7650 + time: '2024-11-25T04:26:54.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/33524 +- author: Schrodinger71 + changes: + - message: Fixed a bug letting players type "ghost" in the console and then see + the whole chat while being in the lobby. + type: Fix + id: 7651 + time: '2024-11-25T07:20:32.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/33529 +- author: Minemoder + changes: + - message: The shark plushie now goes rawr when hitting something or being thrown. + type: Tweak + id: 7652 + time: '2024-11-25T12:23:57.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/33540 +- author: red15 + changes: + - message: Vending machine lights turns off when broken. + type: Fix + id: 7653 + time: '2024-11-25T12:35:14.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/33513 +- author: metalgearsloth + changes: + - message: Adjusted the top menu on the separated game screen. The buttons will + now form multiple rows and no longer overflow into the viewport. + type: Tweak + id: 7654 + time: '2024-11-26T00:59:35.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/33047 +- author: slarticodefast + changes: + - message: Added the greytide virus station event. It will bolt open all doors in + a few randomly chosen departments and unlock lockers with the corresponding + access. + type: Add + id: 7655 + time: '2024-11-26T13:50:20.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/33547 diff --git a/Resources/Credits/GitHub.txt b/Resources/Credits/GitHub.txt index 53c4eb7ea0..326dc1945d 100644 --- a/Resources/Credits/GitHub.txt +++ b/Resources/Credits/GitHub.txt @@ -1 +1 @@ -0x6273, 12rabbits, 13spacemen, 2013HORSEMEATSCANDAL, 20kdc, 21Melkuu, 3nderall, 4310v343k, 4dplanner, 612git, 778b, Ablankmann, abregado, Absolute-Potato, achookh, Acruid, actioninja, actually-reb, ada-please, adamsong, Adeinitas, Admiral-Obvious-001, adrian, Adrian16199, Ady4ik, Aerocrux, Aeshus, Aexolott, Aexxie, africalimedrop, afrokada, AftrLite, Agoichi, Ahion, aiden, AJCM-git, AjexRose, Alekshhh, alexkar598, AlexMorgan3817, alexumandxgabriel08x, Alithsko, ALMv1, Alpha-Two, AlphaQwerty, Altoids1, amylizzle, ancientpower, Andre19926, AndrewEyeke, AndreyCamper, Anzarot121, Appiah, ar4ill, ArchPigeon, ArchRBX, areitpog, Arendian, arimah, Arkanic, ArkiveDev, armoks, Arteben, ArthurMousatov, ArtisticRoomba, artur, AruMoon, ArZarLordOfMango, as334, AsikKEsel, AsnDen, asperger-sind, aspiringLich, astriloqua, august-sun, AutoOtter, avghdev, Awlod, AzzyIsNotHere, BackeTako, BananaFlambe, Baptr0b0t, BasedUser, beck-thompson, bellwetherlogic, benev0, benjamin-burges, BGare, bhenrich, bhespiritu, bibbly, BIGZi0348, bingojohnson, BismarckShuffle, Bixkitts, Blackern5000, Blazeror, BlitzTheSquishy, bloodrizer, Bloody2372, blueDev2, Boaz1111, BobdaBiscuit, BobTheSleder, boiled-water-tsar, BombasterDS, Boolean-Buckeye, botanySupremist, brainfood1183, BramvanZijp, Brandon-Huu, BriBrooo, Bright0, brndd, bryce0110, BubblegumBlue, buletsponge, buntobaggins, bvelliquette, byondfuckery, c0rigin, c4llv07e, CaasGit, Caconym27, Calecute, Callmore, capnsockless, CaptainSqrBeard, Carbonhell, Carolyn3114, Carou02, carteblanche4me, Catofquestionableethics, CatTheSystem, Centronias, chairbender, Charlese2, charlie, ChaseFlorom, chavonadelal, Cheackraze, CheddaCheez, cheesePizza2, cheeseplated, Chief-Engineer, chillyconmor, christhirtle, chromiumboy, Chronophylos, Chubbicous, Chubbygummibear, Ciac32, civilCornball, Clement-O, clyf, Clyybber, CMDR-Piboy314, cohanna, Cohnway, Cojoke-dot, ColdAutumnRain, Colin-Tel, collinlunn, ComicIronic, CookieMasterT, coolboy911, coolmankid12345, Coolsurf6, corentt, CormosLemming, crazybrain23, creadth, CrigCrag, croilbird, Crotalus, CrudeWax, CrzyPotato, cutemoongod, Cyberboss, d34d10cc, d4kii, DadeKuma, Daemon, daerSeebaer, dahnte, dakamakat, DamianX, DangerRevolution, daniel-cr, DanSAussieITS, Daracke, Darkenson, DawBla, Daxxi3, dch-GH, de0rix, Deahaka, dean, DEATHB4DEFEAT, DeathCamel58, Deatherd, deathride58, DebugOk, Decappi, Decortex, Deeeeja, deepdarkdepths, degradka, Delete69, deltanedas, DenisShvalov, DerbyX, derek, dersheppard, Deserty0, Detintinto, DevilishMilk, dexlerxd, dffdff2423, DieselMohawk, digitalic, Dimastra, DinoWattz, DisposableCrewmember42, DjfjdfofdjfjD, doc-michael, docnite, Doctor-Cpu, DoctorBeard, DogZeroX, dolgovmi, dontbetank, Doomsdrayk, Doru991, DoubleRiceEddiedd, DoutorWhite, dragonryan06, drakewill-CRL, Drayff, dreamlyjack, DrEnzyme, dribblydrone, DrMelon, drongood12, DrSingh, DrSmugleaf, drteaspoon420, DTanxxx, DubiousDoggo, Duddino, dukevanity, duskyjay, Dutch-VanDerLinde, dvir001, Dynexust, Easypoller, echo, eclips_e, eden077, EEASAS, Efruit, efzapa, Ekkosangen, ElectroSR, elsie, elthundercloud, Elysium206, Emisse, emmafornash, EmoGarbage404, Endecc, eoineoineoin, eris, erohrs2, ERORR404V1, Errant-4, ertanic, esguard, estacaoespacialpirata, eugene, ewokswagger, exincore, exp111, f0x-n3rd, FacePluslll, Fahasor, FairlySadPanda, FATFSAAM2, Feluk6174, ficcialfaint, Fiftyllama, Fildrance, FillerVK, FinnishPaladin, firenamefn, FirinMaLazors, Fishfish458, FL-OZ, Flareguy, flashgnash, FluffiestFloof, FluffMe, FluidRock, foboscheshir, FoLoKe, fooberticus, ForestNoises, forgotmyotheraccount, forkeyboards, forthbridge, Fortune117, Fouin, foxhorn, freeman2651, freeze2222, Froffy025, Fromoriss, froozigiusz, FrostMando, FungiFellow, FunTust, Futuristic-OK, GalacticChimp, gamer3107, Gaxeer, gbasood, Geekyhobo, genderGeometries, GeneralGaws, Genkail, geraeumig, Ghagliiarghii, Git-Nivrak, githubuser508, gituhabu, GlassEclipse, GNF54, godisdeadLOL, goet, Goldminermac, Golinth, GoodWheatley, Gorox221, gradientvera, graevy, GraniteSidewalk, GreaseMonk, greenrock64, GreyMario, GTRsound, gusxyz, Gyrandola, h3half, hamurlik, Hanzdegloker, HappyRoach, Hardly3D, harikattar, he1acdvv, Hebi, Henry, HerCoyote23, hitomishirichan, hiucko, Hmeister-fake, Hmeister-real, Hobbitmax, hobnob, HoidC, Holinka4ever, holyssss, HoofedEar, Hoolny, hord-brayden, Hreno, hubismal, Hugal31, Huxellberger, Hyenh, hyphenationc, i-justuser-i, iacore, IamVelcroboy, Ian321, icekot8, icesickleone, iczero, iglov, IgorAnt028, igorsaux, ike709, illersaver, Illiux, Ilushkins33, Ilya246, IlyaElDunaev, imrenq, imweax, indeano, Injazz, Insineer, IntegerTempest, Interrobang01, IProduceWidgets, ItsMeThom, Itzbenz, iztokbajcar, Jackal298, Jackrost, jacksonzck, Jackw2As, jacob, jamessimo, janekvap, Jark255, Jarmer123, Jaskanbe, JasperJRoth, JerryImMouse, jerryimmouse, Jessetriesagain, jessicamaybe, Jezithyr, jicksaw, JiimBob, JimGamemaster, jimmy12or, JIPDawg, jjtParadox, jmcb, JoeHammad1844, JohnGinnane, johnku1, Jophire, joshepvodka, Jrpl, juliangiebel, JustArt1m, JustCone14, justdie12, justin, justintether, JustinTrotter, justtne, K-Dynamic, k3yw, Kadeo64, Kaga-404, KaiShibaa, kalane15, kalanosh, Kanashi-Panda, katzenminer, kbailey-git, Keelin, Keer-Sar, KEEYNy, keikiru, Kelrak, kerisargit, keronshb, KIBORG04, Killerqu00, Kimpes, KingFroozy, kira-er, Kirillcas, Kirus59, Kistras, Kit0vras, KittenColony, klaypexx, Kmc2000, Ko4ergaPunk, kognise, kokoc9n, komunre, KonstantinAngelov, kosticia, koteq, KrasnoshchekovPavel, Krunklehorn, Kupie, kxvvv, kyupolaris, kzhanik, lajolico, Lamrr, LankLTE, laok233, lapatison, larryrussian, lawdog4817, Lazzi0706, leander-0, leonardo-dabepis, leonidussaks, leonsfriedrich, LeoSantich, lettern, LetterN, Level10Cybermancer, LEVELcat, lever1209, Lgibb18, lgruthes, LightVillet, liltenhead, LinkUyx, LittleBuilderJane, LittleNorthStar, LittleNyanCat, lizelive, localcc, lokachop, Lomcastar, LordCarve, LordEclipse, LucasTheDrgn, luckyshotpictures, LudwigVonChesterfield, luizwritescode, Lukasz825700516, luminight, lunarcomets, luringens, lvvova1, Lyndomen, lyroth001, lzimann, lzk228, M3739, mac6na6na, MACMAN2003, Macoron, Magicalus, magmodius, MagnusCrowe, malchanceux, MaloTV, ManelNavola, Mangohydra, marboww, Markek1, Matz05, max, MaxNox7, maylokana, MehimoNemo, MeltedPixel, MemeProof, MendaxxDev, Menshin, Mephisto72, MerrytheManokit, Mervill, metalgearsloth, MetalSage, MFMessage, mhamsterr, michaelcu, micheel665, MilenVolf, MilonPL, Minemoder5000, Minty642, Mirino97, mirrorcult, misandrie, MishaUnity, MissKay1994, MisterMecky, Mith-randalf, MjrLandWhale, mkanke-real, MLGTASTICa, moderatelyaware, modern-nm, mokiros, Moneyl, Moomoobeef, moony, Morb0, MossyGreySlope, mr-bo-jangles, Mr0maks, MrFippik, mrrobdemo, muburu, MureixloI, musicmanvr, MWKane, Myakot, Myctai, N3X15, nails-n-tape, Nairodian, Naive817, NakataRin, namespace-Memory, Nannek, NazrinNya, neutrino-laser, NickPowers43, nikthechampiongr, Nimfar11, Nirnael, NIXC, NkoKirkto, nmajask, noctyrnal, noelkathegod, nok-ko, NonchalantNoob, NoobyLegion, Nopey, not-gavnaed, notafet, notquitehadouken, NotSoDana, noudoit, noverd, NuclearWinter, nukashimika, nuke-haus, NULL882, nullarmo, nyeogmi, Nylux, Nyranu, och-och, OctoRocket, OldDanceJacket, OliverOtter, OnyxTheBrave, OrangeMoronage9622, osjarw, Ostaf, othymer, OttoMaticode, Owai-Seek, packmore, paigemaeforrest, pali6, Pangogie, panzer-iv1, paolordls, partyaddict, patrikturi, PaulRitter, peccneck, Peptide90, peptron1, PeterFuto, PetMudstone, pewter-wiz, Pgriha, Phantom-Lily, pheenty, Phill101, phunnyguy, PilgrimViis, Pill-U, Pireax, Pissachu, pissdemon, PixeltheAertistContrib, PixelTheKermit, PJB3005, Plasmaguy, plinyvic, Plykiya, poeMota, pofitlo, pointer-to-null, pok27, PolterTzi, PoorMansDreams, PopGamer45, portfiend, potato1234x, PotentiallyTom, ProfanedBane, ProPandaBear, PrPleGoo, ps3moira, Pspritechologist, Psychpsyo, psykzz, PuceTint, PuroSlavKing, PursuitInAshes, Putnam3145, qrtDaniil, quatre, QueerNB, QuietlyWhisper, qwerltaz, RadioMull, Radosvik, Radrark, Rainbeon, Rainfey, Raitononai, Ramlik, RamZ, randy10122, Rane, Ranger6012, Rapidgame7, ravage123321, rbertoche, RedBookcase, Redfire1331, Redict, RedlineTriad, redmushie, RednoWCirabrab, RemberBM, RemieRichards, RemTim, rene-descartes2021, Renlou, retequizzle, rich-dunne, RieBi, riggleprime, RIKELOLDABOSS, rinary1, Rinkashikachi, riolume, RobbyTheFish, Rockdtben, Rohesie, rok-povsic, rolfero, RomanNovo, rosieposieeee, Roudenn, router, RumiTiger, S1rFl0, S1ss3l, Saakra, Sadie-silly, saga3152, saintmuntzer, Salex08, sam, samgithubaccount, SaphireLattice, SapphicOverload, Sarahon, sativaleanne, SaveliyM360, sBasalto, ScalyChimp, ScarKy0, scrato, Scribbles0, scrivoy, scruq445, scuffedjays, ScumbagDog, Segonist, sephtasm, Serkket, sewerpig, sh18rw, Shaddap1, ShadeAware, ShadowCommander, Shadowtheprotogen546, shaeone, shampunj, shariathotpatrol, SignalWalker, siigiil, Simyon264, sirdragooon, Sirionaut, Sk1tch, SkaldetSkaeg, Skarletto, Skrauz, Skyedra, SlamBamActionman, slarticodefast, Slava0135, Slyfox333, snebl, snicket, sniperchance, Snowni, snowsignal, SolidusSnek, SonicHDC, SoulFN, SoulSloth, Soundwavesghost, southbridge-fur, Soydium, spacelizard, SpaceLizardSky, SpaceManiac, SpaceRox1244, SpaceyLady, Spanky, spanky-spanky, spartak, SpartanKadence, SpeltIncorrectyl, Spessmann, SphiraI, SplinterGP, spoogemonster, sporekto, sporkyz, ssdaniel24, stalengd, stanberytrask, Stanislav4ix, StanTheCarpenter, Stealthbomber16, stellar-novas, stomf, stopbreaking, stopka-html, StrawberryMoses, Stray-Pyramid, strO0pwafel, Strol20, StStevens, Subversionary, sunbear-dev, superjj18, Supernorn, SweptWasTaken, Sybil, SYNCHRONIC, Szunti, Tainakov, takemysoult, TaralGit, Taran, taurie, Tayrtahn, tday93, teamaki, TekuNut, telyonok, TemporalOroboros, tentekal, terezi4real, Terraspark4941, texcruize, TGODiamond, TGRCdev, tgrkzus, ThatOneGoblin25, thatrandomcanadianguy, TheArturZh, theashtronaut, thecopbennet, TheCze, TheDarkElites, thedraccx, TheEmber, TheIntoxicatedCat, thekilk, themias, theomund, theOperand, TherapyGoth, TheShuEd, thetolbean, thevinter, TheWaffleJesus, Thinbug0, ThunderBear2006, timothyteakettle, TimrodDX, timurjavid, tin-man-tim, Titian3, tk-a369, tkdrg, tmtmtl30, TokenStyle, Tollhouse, Toly65, tom-leys, tomasalves8, Tomeno, Tonydatguy, topy, Tornado-Technology, tosatur, TotallyLemon, Tr1bute, tropicalhibi, truepaintgit, Truoizys, Tryded, TsjipTsjip, Tunguso4ka, TurboTrackerss14, TyAshley, Tyler-IN, Tyzemol, UbaserB, ubis1, UBlueberry, UKNOWH, UltimateJester, Unbelievable-Salmon, underscorex5, UnicornOnLSD, Unisol, Unkn0wnGh0st333, unusualcrow, Uriende, UristMcDorf, user424242420, Vaaankas, valentfingerov, Varen, VasilisThePikachu, veliebm, VelonacepsCalyxEggs, veprolet, veritable-calamity, Veritius, Vermidia, vero5123, Verslebas, VigersRay, violet754, Visne, VMSolidus, voidnull000, volotomite, volundr-, Voomra, Vordenburg, vorkathbruh, vulppine, wafehling, Warentan, WarMechanic, Watermelon914, waylon531, weaversam8, wertanchik, whateverusername0, Willhelm53, WilliamECrew, willicassi, Winkarst-cpu, wirdal, wixoaGit, WlarusFromDaSpace, wrexbe, wtcwr68, xkreksx, xprospero, xRiriq, YanehCheck, yathxyz, Ygg01, YotaXP, youarereadingthis, Yousifb26, youtissoum, YuriyKiss, zach-hill, Zadeon, zamp, Zandario, Zap527, Zealith-Gamer, ZelteHonor, zero, ZeroDiamond, zerorulez, ZeWaka, zionnBE, ZNixian, ZoldorfTheWizard, Zonespace27, Zylofan, Zymem, zzylex +0x6273, 12rabbits, 13spacemen, 2013HORSEMEATSCANDAL, 20kdc, 21Melkuu, 3nderall, 4310v343k, 4dplanner, 612git, 778b, Ablankmann, abregado, Absolute-Potato, achookh, Acruid, actioninja, ActiveMammmoth, actually-reb, ada-please, adamsong, Adeinitas, Admiral-Obvious-001, adrian, Adrian16199, Ady4ik, Aerocrux, Aeshus, Aexolott, Aexxie, africalimedrop, afrokada, AftrLite, Agoichi, Ahion, aiden, AJCM-git, AjexRose, Alekshhh, alexkar598, AlexMorgan3817, alexumandxgabriel08x, Alithsko, ALMv1, Alpha-Two, AlphaQwerty, Altoids1, amylizzle, ancientpower, Andre19926, AndrewEyeke, AndreyCamper, Anzarot121, Appiah, ar4ill, ArchPigeon, ArchRBX, areitpog, Arendian, arimah, Arkanic, ArkiveDev, armoks, Arteben, ArthurMousatov, ArtisticRoomba, artur, AruMoon, ArZarLordOfMango, as334, AsikKEsel, AsnDen, asperger-sind, aspiringLich, astriloqua, august-sun, AutoOtter, avghdev, Awlod, AzzyIsNotHere, BackeTako, BananaFlambe, Baptr0b0t, BasedUser, beck-thompson, bellwetherlogic, benev0, benjamin-burges, BGare, bhespiritu, bibbly, BIGZi0348, bingojohnson, BismarckShuffle, Bixkitts, Blackern5000, Blazeror, BlitzTheSquishy, bloodrizer, Bloody2372, blueDev2, Boaz1111, BobdaBiscuit, BobTheSleder, boiled-water-tsar, BombasterDS, Boolean-Buckeye, botanySupremist, brainfood1183, BramvanZijp, Brandon-Huu, BriBrooo, Bright0, brndd, bryce0110, BubblegumBlue, buletsponge, buntobaggins, bvelliquette, byondfuckery, c0rigin, c4llv07e, CaasGit, Caconym27, Calecute, Callmore, capnsockless, CaptainSqrBeard, Carbonhell, Carolyn3114, Carou02, carteblanche4me, Catofquestionableethics, CatTheSystem, Centronias, chairbender, Charlese2, charlie, ChaseFlorom, chavonadelal, Cheackraze, CheddaCheez, cheesePizza2, cheeseplated, Chief-Engineer, chillyconmor, christhirtle, chromiumboy, Chronophylos, Chubbicous, Chubbygummibear, Ciac32, civilCornball, Clement-O, clyf, Clyybber, CMDR-Piboy314, cohanna, Cohnway, Cojoke-dot, ColdAutumnRain, Colin-Tel, collinlunn, ComicIronic, CookieMasterT, coolboy911, coolmankid12345, Coolsurf6, corentt, CormosLemming, CrafterKolyan, crazybrain23, creadth, CrigCrag, croilbird, Crotalus, CrudeWax, CrzyPotato, cutemoongod, Cyberboss, d34d10cc, d4kii, DadeKuma, Daemon, daerSeebaer, dahnte, dakamakat, DamianX, DangerRevolution, daniel-cr, DanSAussieITS, Daracke, Darkenson, DawBla, Daxxi3, dch-GH, de0rix, Deahaka, dean, DEATHB4DEFEAT, DeathCamel58, Deatherd, deathride58, DebugOk, Decappi, Decortex, Deeeeja, deepdarkdepths, degradka, Delete69, deltanedas, DenisShvalov, DerbyX, derek, dersheppard, Deserty0, Detintinto, DevilishMilk, dexlerxd, dffdff2423, DieselMohawk, digitalic, Dimastra, DinoWattz, DisposableCrewmember42, DjfjdfofdjfjD, doc-michael, docnite, Doctor-Cpu, DoctorBeard, DogZeroX, dolgovmi, dontbetank, Doomsdrayk, Doru991, DoubleRiceEddiedd, DoutorWhite, dragonryan06, drakewill-CRL, Drayff, dreamlyjack, DrEnzyme, dribblydrone, DrMelon, drongood12, DrSingh, DrSmugleaf, drteaspoon420, DTanxxx, DubiousDoggo, Duddino, dukevanity, duskyjay, Dutch-VanDerLinde, dvir001, dylanstrategie, Dynexust, Easypoller, echo, eclips_e, eden077, EEASAS, Efruit, efzapa, Ekkosangen, ElectroSR, elsie, elthundercloud, Elysium206, Emisse, emmafornash, EmoGarbage404, Endecc, eoineoineoin, eris, erohrs2, ERORR404V1, Errant-4, ertanic, esguard, estacaoespacialpirata, eugene, ewokswagger, exincore, exp111, f0x-n3rd, FacePluslll, Fahasor, FairlySadPanda, FATFSAAM2, Feluk6174, ficcialfaint, Fiftyllama, Fildrance, FillerVK, FinnishPaladin, firenamefn, FirinMaLazors, Fishfish458, FL-OZ, Flareguy, flashgnash, FluffiestFloof, FluffMe, FluidRock, foboscheshir, FoLoKe, fooberticus, ForestNoises, forgotmyotheraccount, forkeyboards, forthbridge, Fortune117, Fouin, foxhorn, freeman2651, freeze2222, Froffy025, Fromoriss, froozigiusz, FrostMando, FungiFellow, FunTust, Futuristic-OK, GalacticChimp, gamer3107, Gaxeer, gbasood, Geekyhobo, genderGeometries, GeneralGaws, Genkail, geraeumig, Ghagliiarghii, Git-Nivrak, githubuser508, gituhabu, GlassEclipse, GNF54, godisdeadLOL, goet, GoldenCan, Goldminermac, Golinth, GoodWheatley, Gorox221, gradientvera, graevy, GraniteSidewalk, GreaseMonk, greenrock64, GreyMario, GTRsound, gusxyz, Gyrandola, h3half, hamurlik, Hanzdegloker, HappyRoach, Hardly3D, harikattar, he1acdvv, Hebi, Henry, HerCoyote23, hitomishirichan, hiucko, Hmeister-fake, Hmeister-real, Hobbitmax, hobnob, HoidC, Holinka4ever, holyssss, HoofedEar, Hoolny, hord-brayden, Hreno, hubismal, Hugal31, Huxellberger, Hyenh, hyphenationc, i-justuser-i, iacore, IamVelcroboy, Ian321, icekot8, icesickleone, iczero, iglov, IgorAnt028, igorsaux, ike709, illersaver, Illiux, Ilushkins33, Ilya246, IlyaElDunaev, imrenq, imweax, indeano, Injazz, Insineer, IntegerTempest, Interrobang01, IProduceWidgets, ItsMeThom, Itzbenz, iztokbajcar, Jackal298, Jackrost, jacksonzck, Jackw2As, jacob, jamessimo, janekvap, Jark255, Jarmer123, Jaskanbe, JasperJRoth, JerryImMouse, jerryimmouse, Jessetriesagain, jessicamaybe, Jezithyr, jicksaw, JiimBob, JimGamemaster, jimmy12or, JIPDawg, jjtParadox, jmcb, JoeHammad1844, JohnGinnane, johnku1, Jophire, joshepvodka, Jrpl, juliangiebel, JustArt1m, JustCone14, justdie12, justin, justintether, JustinTrotter, justtne, K-Dynamic, k3yw, Kadeo64, Kaga-404, KaiShibaa, kalane15, kalanosh, Kanashi-Panda, katzenminer, kbailey-git, Keelin, Keer-Sar, KEEYNy, keikiru, Kelrak, kerisargit, keronshb, KIBORG04, Killerqu00, Kimpes, KingFroozy, kira-er, Kirillcas, Kirus59, Kistras, Kit0vras, KittenColony, klaypexx, Kmc2000, Ko4ergaPunk, kognise, kokoc9n, komunre, KonstantinAngelov, kosticia, koteq, KrasnoshchekovPavel, Krunklehorn, Kupie, kxvvv, kyupolaris, kzhanik, lajolico, Lamrr, LankLTE, laok233, lapatison, larryrussian, lawdog4817, Lazzi0706, leander-0, leonardo-dabepis, leonidussaks, leonsfriedrich, LeoSantich, LetterN, lettern, Level10Cybermancer, LEVELcat, lever1209, Lgibb18, lgruthes, LightVillet, liltenhead, LinkUyx, LittleBuilderJane, LittleNorthStar, LittleNyanCat, lizelive, localcc, lokachop, Lomcastar, LordCarve, LordEclipse, LucasTheDrgn, luckyshotpictures, LudwigVonChesterfield, luizwritescode, Lukasz825700516, luminight, lunarcomets, luringens, lvvova1, Lyndomen, lyroth001, lzimann, lzk228, M3739, mac6na6na, MACMAN2003, Macoron, magicalus, magmodius, MagnusCrowe, malchanceux, MaloTV, ManelNavola, Mangohydra, marboww, Markek1, Matz05, max, MaxNox7, maylokana, MehimoNemo, MeltedPixel, MemeProof, MendaxxDev, Menshin, Mephisto72, MerrytheManokit, Mervill, metalgearsloth, MetalSage, MFMessage, mhamsterr, michaelcu, micheel665, MilenVolf, MilonPL, Minemoder5000, Minty642, Mirino97, mirrorcult, misandrie, MishaUnity, MissKay1994, MisterMecky, Mith-randalf, MjrLandWhale, mkanke-real, MLGTASTICa, moderatelyaware, modern-nm, mokiros, Moneyl, Moomoobeef, moony, Morb0, MossyGreySlope, mr-bo-jangles, Mr0maks, MrFippik, mrrobdemo, muburu, MureixloI, musicmanvr, MWKane, Myakot, Myctai, N3X15, nails-n-tape, Nairodian, Naive817, NakataRin, namespace-Memory, Nannek, NazrinNya, neutrino-laser, NickPowers43, nikthechampiongr, Nimfar11, Nirnael, NIXC, NkoKirkto, nmajask, noctyrnal, noelkathegod, nok-ko, NonchalantNoob, NoobyLegion, Nopey, not-gavnaed, notafet, notquitehadouken, NotSoDana, noudoit, noverd, NuclearWinter, nukashimika, nuke-haus, NULL882, nullarmo, nyeogmi, Nylux, Nyranu, och-och, OctoRocket, OldDanceJacket, OliverOtter, OnyxTheBrave, OrangeMoronage9622, osjarw, Ostaf, othymer, OttoMaticode, Owai-Seek, packmore, paigemaeforrest, pali6, Pangogie, panzer-iv1, paolordls, partyaddict, patrikturi, PaulRitter, peccneck, Peptide90, peptron1, PeterFuto, PetMudstone, pewter-wiz, Pgriha, Phantom-Lily, pheenty, Phill101, phunnyguy, PilgrimViis, Pill-U, Pireax, Pissachu, pissdemon, PixeltheAertistContrib, PixelTheKermit, PJB3005, Plasmaguy, plinyvic, Plykiya, poeMota, pofitlo, pointer-to-null, pok27, PolterTzi, PoorMansDreams, PopGamer45, portfiend, potato1234x, PotentiallyTom, ProfanedBane, ProPandaBear, PrPleGoo, ps3moira, Pspritechologist, Psychpsyo, psykzz, PuceTint, PuroSlavKing, PursuitInAshes, Putnam3145, qrtDaniil, quatre, QueerNB, QuietlyWhisper, qwerltaz, RadioMull, Radosvik, Radrark, Rainbeon, Rainfey, Raitononai, Ramlik, RamZ, randy10122, Rane, Ranger6012, Rapidgame7, ravage123321, rbertoche, RedBookcase, Redfire1331, Redict, RedlineTriad, redmushie, RednoWCirabrab, RemberBM, RemieRichards, RemTim, rene-descartes2021, Renlou, retequizzle, rich-dunne, RieBi, riggleprime, RIKELOLDABOSS, rinary1, Rinkashikachi, riolume, RobbyTheFish, Rockdtben, Rohesie, rok-povsic, rolfero, RomanNovo, rosieposieeee, Roudenn, router, RumiTiger, S1rFl0, S1ss3l, Saakra, Sadie-silly, saga3152, saintmuntzer, Salex08, sam, samgithubaccount, SaphireLattice, SapphicOverload, Sarahon, sativaleanne, SaveliyM360, sBasalto, ScalyChimp, ScarKy0, scrato, Scribbles0, scrivoy, scruq445, scuffedjays, ScumbagDog, Segonist, sephtasm, Serkket, sewerpig, sh18rw, Shaddap1, ShadeAware, ShadowCommander, Shadowtheprotogen546, shaeone, shampunj, shariathotpatrol, SignalWalker, siigiil, Simyon264, sirdragooon, Sirionaut, Sk1tch, SkaldetSkaeg, Skarletto, Skrauz, Skyedra, SlamBamActionman, slarticodefast, Slava0135, Slyfox333, snebl, snicket, sniperchance, Snowni, snowsignal, SolidusSnek, SonicHDC, SoulFN, SoulSloth, Soundwavesghost, southbridge-fur, Soydium, spacelizard, SpaceLizardSky, SpaceManiac, SpaceRox1244, SpaceyLady, spanky-spanky, spartak, SpartanKadence, SpeltIncorrectyl, Spessmann, SphiraI, SplinterGP, spoogemonster, sporekto, sporkyz, ssdaniel24, stalengd, stanberytrask, Stanislav4ix, StanTheCarpenter, Stealthbomber16, stellar-novas, stomf, stopbreaking, stopka-html, StrawberryMoses, Stray-Pyramid, strO0pwafel, Strol20, StStevens, Subversionary, sunbear-dev, superjj18, Supernorn, SweptWasTaken, Sybil, SYNCHRONIC, Szunti, Tainakov, takemysoult, TaralGit, Taran, taurie, Tayrtahn, tday93, teamaki, TekuNut, telyonok, TemporalOroboros, tentekal, terezi4real, Terraspark4941, texcruize, TGODiamond, TGRCdev, tgrkzus, ThatGuyUSA, ThatOneGoblin25, thatrandomcanadianguy, TheArturZh, theashtronaut, thecopbennet, TheCze, TheDarkElites, thedraccx, TheEmber, TheIntoxicatedCat, thekilk, themias, theomund, theOperand, TherapyGoth, TheShuEd, thetolbean, thevinter, TheWaffleJesus, Thinbug0, ThunderBear2006, timothyteakettle, TimrodDX, timurjavid, tin-man-tim, Titian3, tk-a369, tkdrg, tmtmtl30, TokenStyle, Tollhouse, Toly65, tom-leys, tomasalves8, Tomeno, Tonydatguy, topy, Tornado-Technology, tosatur, TotallyLemon, Tr1bute, tropicalhibi, truepaintgit, Truoizys, Tryded, TsjipTsjip, Tunguso4ka, TurboTrackerss14, TyAshley, Tyler-IN, Tyzemol, UbaserB, ubis1, UBlueberry, UKNOWH, UltimateJester, Unbelievable-Salmon, underscorex5, UnicornOnLSD, Unisol, Unkn0wnGh0st333, unusualcrow, Uriende, UristMcDorf, user424242420, Vaaankas, valentfingerov, Varen, Vasilis, VasilisThePikachu, veliebm, VelonacepsCalyxEggs, veprolet, veritable-calamity, Veritius, Vermidia, vero5123, Verslebas, VigersRay, violet754, Visne, VMSolidus, voidnull000, volotomite, volundr-, Voomra, Vordenburg, vorkathbruh, vulppine, wafehling, Warentan, WarMechanic, Watermelon914, weaversam8, wertanchik, whateverusername0, Willhelm53, WilliamECrew, willicassi, Winkarst-cpu, wirdal, wixoaGit, WlarusFromDaSpace, wrexbe, wtcwr68, xkreksx, xprospero, xRiriq, YanehCheck, yathxyz, Ygg01, YotaXP, youarereadingthis, Yousifb26, youtissoum, yunii, YuriyKiss, zach-hill, Zadeon, zamp, Zandario, Zap527, Zealith-Gamer, ZelteHonor, zero, ZeroDiamond, zerorulez, ZeWaka, zionnBE, ZNixian, ZoldorfTheWizard, zonespace27, Zylofan, Zymem, zzylex diff --git a/Resources/Locale/en-US/_strings/atmos/gas-pipe-sensor.ftl b/Resources/Locale/en-US/_strings/atmos/gas-pipe-sensor.ftl new file mode 100644 index 0000000000..8c3b8962e3 --- /dev/null +++ b/Resources/Locale/en-US/_strings/atmos/gas-pipe-sensor.ftl @@ -0,0 +1,5 @@ +gas-pipe-sensor-distribution-loop = Distribution loop +gas-pipe-sensor-waste-loop = Waste loop +gas-pipe-sensor-mixed-air = Mixed air +gas-pipe-sensor-teg-hot-loop = TEG hot loop +gas-pipe-sensor-teg-cold-loop = TEG cold loop diff --git a/Resources/Locale/en-US/_strings/chat/commands/ghost-command.ftl b/Resources/Locale/en-US/_strings/chat/commands/ghost-command.ftl index 08e78d34ce..53dfa478d6 100644 --- a/Resources/Locale/en-US/_strings/chat/commands/ghost-command.ftl +++ b/Resources/Locale/en-US/_strings/chat/commands/ghost-command.ftl @@ -3,3 +3,4 @@ ghost-command-help-text = The ghost command turns you into a ghost and makes the Please note that you cannot return to your character's body after ghosting. ghost-command-no-session = You have no session, you can't ghost. ghost-command-denied = You cannot ghost right now. +ghost-command-error-lobby = You can't ghost right now. You are not in the game! diff --git a/Resources/Locale/en-US/_strings/info/server-info.ftl b/Resources/Locale/en-US/_strings/info/server-info.ftl index 3039f4cb17..ff183d80ef 100644 --- a/Resources/Locale/en-US/_strings/info/server-info.ftl +++ b/Resources/Locale/en-US/_strings/info/server-info.ftl @@ -4,5 +4,6 @@ server-info-discord-button = Discord server-info-website-button = Website server-info-wiki-button = Wiki server-info-forum-button = Forum +server-info-telegram-button = Telegram server-info-report-button = Report Bugs server-info-credits-button = Credits diff --git a/Resources/Locale/en-US/_strings/server-info/info-links.ftl b/Resources/Locale/en-US/_strings/server-info/info-links.ftl index 0f8f9eb7d9..51b6b51ecb 100644 --- a/Resources/Locale/en-US/_strings/server-info/info-links.ftl +++ b/Resources/Locale/en-US/_strings/server-info/info-links.ftl @@ -5,3 +5,4 @@ info-link-forum = Forum info-link-github = GitHub info-link-website = Website info-link-wiki = Wiki +info-link-telegram = Telegram diff --git a/Resources/Locale/en-US/_strings/shuttles/console.ftl b/Resources/Locale/en-US/_strings/shuttles/console.ftl index 6143c99552..80e61a2812 100644 --- a/Resources/Locale/en-US/_strings/shuttles/console.ftl +++ b/Resources/Locale/en-US/_strings/shuttles/console.ftl @@ -4,7 +4,6 @@ shuttle-pilot-end = Stopped piloting shuttle-console-in-ftl = Currently in FTL shuttle-console-mass = Too large to FTL shuttle-console-prevent = You are unable to pilot this ship -shuttle-console-static = Grid is static # NAV diff --git a/Resources/Locale/en-US/_strings/station-events/events/greytide-virus.ftl b/Resources/Locale/en-US/_strings/station-events/events/greytide-virus.ftl new file mode 100644 index 0000000000..7e6f5e32ca --- /dev/null +++ b/Resources/Locale/en-US/_strings/station-events/events/greytide-virus.ftl @@ -0,0 +1 @@ +station-event-greytide-virus-start-announcement = Gr3y.T1d3 virus detected in the station's secure locking encryption subroutines. Severity level of { $severity }. Recommend station AI involvement. diff --git a/Resources/Maps/Misc/terminal.yml b/Resources/Maps/Misc/terminal.yml index d32a53856e..8ca17b4ebc 100644 --- a/Resources/Maps/Misc/terminal.yml +++ b/Resources/Maps/Misc/terminal.yml @@ -948,6 +948,7 @@ entities: - type: RadiationGridResistance - type: SpreaderGrid - type: GridPathfinding + - type: Godmode - proto: AirlockExternalGlass entities: - uid: 2 @@ -955,87 +956,86 @@ entities: - type: Transform pos: 6.5,-10.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 3 components: - type: Transform pos: -7.5,-17.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 4 components: - type: Transform pos: -7.5,-10.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 5 components: - type: Transform pos: 6.5,-17.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 11 components: - type: Transform rot: -1.5707963267948966 rad pos: 12.5,-10.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 12 components: - type: Transform rot: -1.5707963267948966 rad pos: 12.5,-17.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 13 components: - type: Transform rot: -1.5707963267948966 rad pos: -13.5,-17.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 14 components: - type: Transform rot: -1.5707963267948966 rad pos: -13.5,-10.5 parent: 818 -- proto: AirlockExternalLocked - entities: - - uid: 589 - components: - - type: MetaData - flags: PvsPriority - - type: Transform - pos: 4.5,8.5 - parent: 818 -- proto: AirlockGlass - entities: - - uid: 252 - components: - - type: Transform - pos: -9.5,-4.5 - parent: 818 - - uid: 253 - components: - - type: Transform - pos: -10.5,-4.5 - parent: 818 - - uid: 254 - components: - - type: Transform - pos: -11.5,-4.5 - parent: 818 - - uid: 255 - components: - - type: Transform - pos: 8.5,-4.5 - parent: 818 - - uid: 256 - components: - - type: Transform - pos: 9.5,-4.5 - parent: 818 - - uid: 257 - components: - - type: Transform - pos: 10.5,-4.5 - parent: 818 -- proto: AirlockGlassShuttleEasyPryLocked + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction +- proto: AirlockExternalGlassShuttleLocked entities: - uid: 1 components: @@ -1043,57 +1043,338 @@ entities: rot: -1.5707963267948966 rad pos: -15.5,-10.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 6 components: - type: Transform rot: -1.5707963267948966 rad pos: -15.5,-17.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 7 components: - type: Transform rot: 1.5707963267948966 rad pos: 14.5,-10.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 8 components: - type: Transform rot: 1.5707963267948966 rad pos: 14.5,-17.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 9 components: - type: Transform rot: -1.5707963267948966 rad pos: 4.5,-10.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 15 components: - type: Transform rot: -1.5707963267948966 rad pos: 4.5,-17.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 16 components: - type: Transform rot: 1.5707963267948966 rad pos: -5.5,-10.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 17 components: - type: Transform rot: 1.5707963267948966 rad pos: -5.5,-17.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible +- proto: AirlockExternalLocked + entities: + - uid: 589 + components: + - type: Transform + pos: 4.5,8.5 + parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction +- proto: AirlockGlass + entities: + - uid: 252 + components: + - type: Transform + pos: -9.5,-4.5 + parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible + - uid: 253 + components: + - type: Transform + pos: -10.5,-4.5 + parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible + - uid: 254 + components: + - type: Transform + pos: -11.5,-4.5 + parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible + - uid: 255 + components: + - type: Transform + pos: 8.5,-4.5 + parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible + - uid: 256 + components: + - type: Transform + pos: 9.5,-4.5 + parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible + - uid: 257 + components: + - type: Transform + pos: 10.5,-4.5 + parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - proto: AirlockMaint entities: - uid: 146 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: 3.5,3.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction +- proto: AlwaysPoweredWallLight + entities: + - uid: 150 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -8.5,-5.5 + parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible + - uid: 188 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 11.5,2.5 + parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible + - uid: 195 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -2.5,-1.5 + parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible + - uid: 209 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 7.5,-5.5 + parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible + - uid: 341 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 1.5,-1.5 + parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible + - uid: 634 + components: + - type: Transform + pos: 9.5,-16.5 + parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible + - uid: 636 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 9.5,-11.5 + parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible + - uid: 649 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -10.5,-11.5 + parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible + - uid: 650 + components: + - type: Transform + pos: -10.5,-16.5 + parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible + - uid: 687 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -13.5,1.5 + parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible + - uid: 701 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -6.5,3.5 + parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible + - uid: 702 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 5.5,3.5 + parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible + - uid: 715 + components: + - type: Transform + pos: -0.5,5.5 + parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible + - uid: 717 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -7.5,-3.5 + parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible + - uid: 742 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 6.5,-3.5 + parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - proto: APCBasic entities: - uid: 205 @@ -1101,32 +1382,92 @@ entities: - type: Transform pos: 6.5,2.5 parent: 818 + - type: AccessReader + access: + - - CentralCommand + - type: Godmode + - type: BatterySelfRecharger + autoRechargeRate: 50000 + autoRecharge: True + missingComponents: + - Construction + - Destructible - uid: 206 components: - type: Transform pos: -13.5,2.5 parent: 818 + - type: AccessReader + access: + - - CentralCommand + - type: Godmode + - type: BatterySelfRecharger + autoRechargeRate: 50000 + autoRecharge: True + missingComponents: + - Construction + - Destructible - uid: 211 components: - type: Transform pos: -13.5,-11.5 parent: 818 + - type: AccessReader + access: + - - CentralCommand + - type: Godmode + - type: BatterySelfRecharger + autoRechargeRate: 50000 + autoRecharge: True + missingComponents: + - Construction + - Destructible - uid: 212 components: - type: Transform pos: 6.5,-11.5 parent: 818 + - type: AccessReader + access: + - - CentralCommand + - type: Godmode + - type: BatterySelfRecharger + autoRechargeRate: 50000 + autoRecharge: True + missingComponents: + - Construction + - Destructible - uid: 355 components: - type: Transform rot: 3.141592653589793 rad pos: 1.5,6.5 parent: 818 + - type: AccessReader + access: + - - CentralCommand + - type: Godmode + - type: BatterySelfRecharger + autoRechargeRate: 50000 + autoRecharge: True + missingComponents: + - Construction + - Destructible - uid: 846 components: - type: Transform pos: 2.5,3.5 parent: 818 + - type: AccessReader + access: + - - CentralCommand + - type: Godmode + - type: BatterySelfRecharger + autoRechargeRate: 50000 + autoRecharge: True + missingComponents: + - Construction + - Destructible - proto: ArrivalsShuttleTimer entities: - uid: 597 @@ -1134,21 +1475,33 @@ entities: - type: Transform pos: -7.5,-5.5 parent: 818 + - type: Godmode + missingComponents: + - Construction - uid: 633 components: - type: Transform pos: 6.5,-5.5 parent: 818 + - type: Godmode + missingComponents: + - Construction - uid: 928 components: - type: Transform pos: -6.5,-14.5 parent: 818 + - type: Godmode + missingComponents: + - Construction - uid: 929 components: - type: Transform pos: 5.5,-14.5 parent: 818 + - type: Godmode + missingComponents: + - Construction - proto: AtmosDeviceFanTiny entities: - uid: 296 @@ -1156,46 +1509,55 @@ entities: - type: Transform pos: -6.5,-10.5 parent: 818 + - type: Godmode - uid: 297 components: - type: Transform pos: -14.5,-10.5 parent: 818 + - type: Godmode - uid: 298 components: - type: Transform pos: -14.5,-17.5 parent: 818 + - type: Godmode - uid: 299 components: - type: Transform pos: -6.5,-17.5 parent: 818 + - type: Godmode - uid: 300 components: - type: Transform pos: 5.5,-17.5 parent: 818 + - type: Godmode - uid: 301 components: - type: Transform pos: 5.5,-10.5 parent: 818 + - type: Godmode - uid: 302 components: - type: Transform pos: 13.5,-10.5 parent: 818 + - type: Godmode - uid: 303 components: - type: Transform pos: 13.5,-17.5 parent: 818 + - type: Godmode - uid: 809 components: - type: Transform pos: 4.5,8.5 parent: 818 + - type: Godmode - proto: BarSignEngineChange entities: - uid: 215 @@ -1203,6 +1565,10 @@ entities: - type: Transform pos: -10.5,5.5 parent: 818 + - type: Godmode + missingComponents: + - ApcPowerReceiver + - Destructible - proto: BlockGameArcade entities: - uid: 727 @@ -1211,28 +1577,46 @@ entities: rot: 1.5707963267948966 rad pos: -13.5,-1.5 parent: 818 + - type: Godmode + missingComponents: + - ApcPowerReceiver + - Anchorable + - Construction + - Destructible - uid: 728 components: - type: Transform rot: 1.5707963267948966 rad pos: -13.5,0.5 parent: 818 + - type: Godmode + missingComponents: + - ApcPowerReceiver + - Anchorable + - Construction + - Destructible - proto: BookshelfFilled entities: - uid: 442 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: 7.5,3.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Anchorable + - Construction - uid: 752 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: 11.5,3.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Anchorable + - Construction - proto: BoozeDispenser entities: - uid: 710 @@ -1240,1198 +1624,2152 @@ entities: - type: Transform pos: -11.5,4.5 parent: 818 -- proto: CableApcExtension + - type: Godmode + missingComponents: + - ApcPowerReceiver + - Anchorable + - Destructible + - Construction +- proto: CableApcExtensionUncuttable entities: - uid: 203 components: - type: Transform pos: 1.5,6.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 208 components: - type: Transform pos: -3.5,7.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 218 components: - type: Transform pos: -4.5,4.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 402 components: - type: Transform pos: -4.5,7.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 404 components: - type: Transform pos: 2.5,1.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 410 components: - type: Transform pos: 2.5,2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 411 components: - type: Transform pos: 3.5,5.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 412 components: - type: Transform pos: 3.5,4.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 426 components: - type: Transform pos: -2.5,7.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 427 components: - type: Transform pos: -1.5,7.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 428 components: - type: Transform pos: -0.5,7.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 429 components: - type: Transform pos: 0.5,7.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 430 components: - type: Transform pos: 1.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 431 components: - type: Transform pos: 1.5,-1.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 434 components: - type: Transform pos: 0.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 435 components: - type: Transform pos: -0.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 436 components: - type: Transform pos: -1.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 437 components: - type: Transform pos: -2.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 438 components: - type: Transform pos: -3.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 439 components: - type: Transform pos: -4.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 440 components: - type: Transform pos: -2.5,-1.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 443 components: - type: Transform pos: 2.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 444 components: - type: Transform pos: 3.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 445 components: - type: Transform pos: 4.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 446 components: - type: Transform pos: -5.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 447 components: - type: Transform pos: -13.5,2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 448 components: - type: Transform pos: -13.5,1.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 449 components: - type: Transform pos: -13.5,0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 450 components: - type: Transform pos: -13.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 451 components: - type: Transform pos: -12.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 452 components: - type: Transform pos: -11.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 453 components: - type: Transform pos: -10.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 454 components: - type: Transform pos: -9.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 455 components: - type: Transform pos: -8.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 456 components: - type: Transform pos: -7.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 457 components: - type: Transform pos: -10.5,-1.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 458 components: - type: Transform pos: -10.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 459 components: - type: Transform pos: -10.5,-3.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 460 components: - type: Transform pos: -10.5,0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 461 components: - type: Transform pos: -10.5,1.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 462 components: - type: Transform pos: -10.5,2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 463 components: - type: Transform pos: -10.5,3.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 464 components: - type: Transform pos: -11.5,-3.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 465 components: - type: Transform pos: -9.5,-3.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 466 components: - type: Transform pos: -11.5,3.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 467 components: - type: Transform pos: -9.5,3.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 468 components: - type: Transform pos: -13.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 469 components: - type: Transform pos: -12.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 470 components: - type: Transform pos: -11.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 471 components: - type: Transform pos: -11.5,-10.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 472 components: - type: Transform pos: 10.5,-16.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 473 components: - type: Transform pos: 10.5,-15.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 474 components: - type: Transform pos: 10.5,-14.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 475 components: - type: Transform pos: 10.5,-12.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 476 components: - type: Transform pos: -11.5,-13.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 477 components: - type: Transform pos: -10.5,-17.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 478 components: - type: Transform pos: -10.5,-18.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 479 components: - type: Transform pos: -10.5,-19.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 480 components: - type: Transform pos: -10.5,-20.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 481 components: - type: Transform pos: -11.5,-17.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 482 components: - type: Transform pos: -12.5,-17.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 483 components: - type: Transform pos: -13.5,-17.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 484 components: - type: Transform pos: -14.5,-17.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 485 components: - type: Transform pos: -9.5,-17.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 486 components: - type: Transform pos: -8.5,-17.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 487 components: - type: Transform pos: -7.5,-17.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 488 components: - type: Transform pos: -6.5,-17.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 489 components: - type: Transform pos: -10.5,-10.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 490 components: - type: Transform pos: -9.5,-10.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 491 components: - type: Transform pos: -8.5,-10.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 492 components: - type: Transform pos: -7.5,-10.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 493 components: - type: Transform pos: -6.5,-10.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 494 components: - type: Transform pos: -12.5,-10.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 495 components: - type: Transform pos: -13.5,-10.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 496 components: - type: Transform pos: -14.5,-10.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 497 components: - type: Transform pos: -11.5,-14.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 498 components: - type: Transform pos: -12.5,-14.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 499 components: - type: Transform pos: -9.5,-13.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 500 components: - type: Transform pos: -8.5,-13.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 501 components: - type: Transform pos: -10.5,-9.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 502 components: - type: Transform pos: -10.5,-8.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 503 components: - type: Transform pos: -10.5,-7.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 504 components: - type: Transform pos: -10.5,-6.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 505 components: - type: Transform pos: 6.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 506 components: - type: Transform pos: 7.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 507 components: - type: Transform pos: 7.5,-10.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 508 components: - type: Transform pos: 6.5,-10.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 509 components: - type: Transform pos: 5.5,-10.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 510 components: - type: Transform pos: 8.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 511 components: - type: Transform pos: 8.5,-10.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 512 components: - type: Transform pos: 9.5,-10.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 513 components: - type: Transform pos: 10.5,-10.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 514 components: - type: Transform pos: 11.5,-10.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 515 components: - type: Transform pos: 12.5,-10.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 516 components: - type: Transform pos: 13.5,-10.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 517 components: - type: Transform pos: 8.5,-16.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 518 components: - type: Transform pos: 8.5,-15.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 519 components: - type: Transform pos: 8.5,-13.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 520 components: - type: Transform pos: 8.5,-12.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 521 components: - type: Transform pos: -11.5,-12.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 522 components: - type: Transform pos: 9.5,-17.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 523 components: - type: Transform pos: 9.5,-18.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 524 components: - type: Transform pos: 9.5,-19.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 525 components: - type: Transform pos: 9.5,-20.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 526 components: - type: Transform pos: 8.5,-17.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 527 components: - type: Transform pos: 7.5,-17.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 528 components: - type: Transform pos: 6.5,-17.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 529 components: - type: Transform pos: 5.5,-17.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 530 components: - type: Transform pos: 10.5,-17.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 531 components: - type: Transform pos: 11.5,-17.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 532 components: - type: Transform pos: 12.5,-17.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 533 components: - type: Transform pos: 13.5,-17.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 534 components: - type: Transform pos: 8.5,-14.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 535 components: - type: Transform pos: 7.5,-14.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 536 components: - type: Transform pos: 10.5,-13.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 537 components: - type: Transform pos: 11.5,-13.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 538 components: - type: Transform pos: 9.5,-9.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 539 components: - type: Transform pos: 9.5,-8.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 540 components: - type: Transform pos: 9.5,-7.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 541 components: - type: Transform pos: 9.5,-6.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 542 components: - type: Transform pos: 6.5,2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 543 components: - type: Transform pos: 6.5,1.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 544 components: - type: Transform pos: 6.5,0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 545 components: - type: Transform pos: 6.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 546 components: - type: Transform pos: 7.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 547 components: - type: Transform pos: 8.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 548 components: - type: Transform pos: 9.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 549 components: - type: Transform pos: 9.5,0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 550 components: - type: Transform pos: 9.5,1.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 551 components: - type: Transform pos: 9.5,2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 552 components: - type: Transform pos: 9.5,3.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 553 components: - type: Transform pos: 10.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 554 components: - type: Transform pos: 8.5,3.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 555 components: - type: Transform pos: 10.5,3.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 556 components: - type: Transform pos: 11.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 557 components: - type: Transform pos: 12.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 558 components: - type: Transform pos: 9.5,-1.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 559 components: - type: Transform pos: 9.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 560 components: - type: Transform pos: 9.5,-3.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 561 components: - type: Transform pos: 8.5,-3.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 562 components: - type: Transform pos: 10.5,-3.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 563 components: - type: Transform pos: 1.5,7.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 564 components: - type: Transform pos: 2.5,7.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 565 components: - type: Transform pos: 3.5,7.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 566 components: - type: Transform pos: 3.5,6.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 579 components: - type: Transform pos: 2.5,0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 599 components: - type: Transform pos: -4.5,6.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 601 components: - type: Transform pos: -4.5,5.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 651 components: - type: Transform pos: 10.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 652 components: - type: Transform pos: -11.5,-16.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 653 components: - type: Transform pos: -11.5,-15.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 654 components: - type: Transform pos: -9.5,-16.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 655 components: - type: Transform pos: -9.5,-15.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 656 components: - type: Transform pos: -9.5,-14.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 657 components: - type: Transform pos: -9.5,-12.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 658 components: - type: Transform pos: -9.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 842 components: - type: Transform pos: -4.5,0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 843 components: - type: Transform pos: -4.5,1.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 844 components: - type: Transform pos: 2.5,3.5 parent: 818 -- proto: CableHV + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable +- proto: CableHVUncuttable entities: - uid: 413 components: - type: Transform pos: -3.5,8.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 415 components: - type: Transform pos: -4.5,8.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 416 components: - type: Transform pos: -2.5,8.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 734 components: - type: Transform pos: -0.5,8.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 735 components: - type: Transform pos: -1.5,8.5 parent: 818 -- proto: CableMV + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable +- proto: CableMVUncuttable entities: - uid: 177 components: - type: Transform pos: 3.5,3.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 201 components: - type: Transform pos: 6.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 210 components: - type: Transform pos: 6.5,1.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 214 components: - type: Transform pos: 6.5,0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 219 components: - type: Transform pos: 7.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 221 components: - type: Transform pos: 3.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 224 components: - type: Transform pos: 1.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 226 components: - type: Transform pos: 6.5,2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 227 components: - type: Transform pos: 8.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 228 components: - type: Transform pos: 9.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 349 components: - type: Transform pos: 9.5,-1.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 350 components: - type: Transform pos: 5.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 352 components: - type: Transform pos: 2.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 353 components: - type: Transform pos: 4.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 354 components: - type: Transform pos: 1.5,6.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 356 components: - type: Transform pos: 9.5,-7.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 357 components: - type: Transform pos: 9.5,-6.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 358 components: - type: Transform pos: 9.5,-5.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 359 components: - type: Transform pos: 9.5,-3.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 360 components: - type: Transform pos: 9.5,-4.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 361 components: - type: Transform pos: 9.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 362 components: - type: Transform pos: 9.5,-8.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 363 components: - type: Transform pos: 9.5,-9.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 364 components: - type: Transform pos: 9.5,-10.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 365 components: - type: Transform pos: 9.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 366 components: - type: Transform pos: 8.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 367 components: - type: Transform pos: 7.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 368 components: - type: Transform pos: 6.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 369 components: - type: Transform pos: 0.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 370 components: - type: Transform pos: -0.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 371 components: - type: Transform pos: -1.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 372 components: - type: Transform pos: -2.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 373 components: - type: Transform pos: -3.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 374 components: - type: Transform pos: -4.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 375 components: - type: Transform pos: -5.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 376 components: - type: Transform pos: -6.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 377 components: - type: Transform pos: -7.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 378 components: - type: Transform pos: -8.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 379 components: - type: Transform pos: -9.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 380 components: - type: Transform pos: -10.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 381 components: - type: Transform pos: -11.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 382 components: - type: Transform pos: -12.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 383 components: - type: Transform pos: -13.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 384 components: - type: Transform pos: -13.5,0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 385 components: - type: Transform pos: -13.5,1.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 386 components: - type: Transform pos: -13.5,2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 387 components: - type: Transform pos: -10.5,-1.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 388 components: - type: Transform pos: -10.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 389 components: - type: Transform pos: -10.5,-3.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 390 components: - type: Transform pos: -10.5,-4.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 391 components: - type: Transform pos: -10.5,-5.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 392 components: - type: Transform pos: -10.5,-6.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 393 components: - type: Transform pos: -10.5,-7.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 394 components: - type: Transform pos: -10.5,-8.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 395 components: - type: Transform pos: -10.5,-9.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 396 components: - type: Transform pos: -10.5,-10.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 397 components: - type: Transform pos: -10.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 398 components: - type: Transform pos: -11.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 399 components: - type: Transform pos: -12.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 400 components: - type: Transform pos: -13.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 418 components: - type: Transform pos: 3.5,1.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 419 components: - type: Transform pos: 3.5,2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 421 components: - type: Transform pos: -0.5,7.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 422 components: - type: Transform pos: 0.5,7.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 423 components: - type: Transform pos: 1.5,7.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 424 components: - type: Transform pos: 2.5,7.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 425 components: - type: Transform pos: 3.5,7.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 567 components: - type: Transform pos: 3.5,4.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 568 components: - type: Transform pos: 3.5,5.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 569 components: - type: Transform pos: 3.5,6.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 570 components: - type: Transform pos: -0.5,8.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 803 components: - type: Transform pos: 3.5,0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 845 components: - type: Transform pos: 2.5,3.5 parent: 818 -- proto: CableTerminal + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable +- proto: CableTerminalUncuttable entities: - uid: 417 components: @@ -2439,6 +3777,11 @@ entities: rot: 1.5707963267948966 rad pos: -3.5,8.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - proto: Catwalk entities: - uid: 580 @@ -2446,56 +3789,111 @@ entities: - type: Transform pos: 3.5,6.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Destructible + - RCDDeconstructable - uid: 584 components: - type: Transform pos: 2.5,7.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Destructible + - RCDDeconstructable - uid: 590 components: - type: Transform pos: 3.5,5.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Destructible + - RCDDeconstructable - uid: 596 components: - type: Transform pos: 1.5,7.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Destructible + - RCDDeconstructable - uid: 747 components: - type: Transform pos: 3.5,4.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Destructible + - RCDDeconstructable - uid: 810 components: - type: Transform pos: 0.5,7.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Destructible + - RCDDeconstructable - uid: 811 components: - type: Transform pos: -0.5,7.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Destructible + - RCDDeconstructable - uid: 812 components: - type: Transform pos: -1.5,7.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Destructible + - RCDDeconstructable - uid: 813 components: - type: Transform pos: -2.5,7.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Destructible + - RCDDeconstructable - uid: 814 components: - type: Transform pos: -3.5,7.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Destructible + - RCDDeconstructable - uid: 815 components: - type: Transform pos: -4.5,7.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Destructible + - RCDDeconstructable - proto: Chair entities: - uid: 592 @@ -2504,254 +3902,475 @@ entities: rot: -1.5707963267948966 rad pos: -7.5,-14.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 593 components: - type: Transform rot: -1.5707963267948966 rad pos: -7.5,-15.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 603 components: - type: Transform rot: -1.5707963267948966 rad pos: -7.5,-13.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 604 components: - type: Transform rot: -1.5707963267948966 rad pos: -7.5,-12.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 605 components: - type: Transform rot: -1.5707963267948966 rad pos: -11.5,-15.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 606 components: - type: Transform rot: -1.5707963267948966 rad pos: -11.5,-14.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 607 components: - type: Transform rot: -1.5707963267948966 rad pos: -11.5,-13.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 608 components: - type: Transform rot: -1.5707963267948966 rad pos: -11.5,-12.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 609 components: - type: Transform rot: 1.5707963267948966 rad pos: -13.5,-15.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 610 components: - type: Transform rot: 1.5707963267948966 rad pos: -13.5,-14.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 611 components: - type: Transform rot: 1.5707963267948966 rad pos: -13.5,-13.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 612 components: - type: Transform rot: 1.5707963267948966 rad pos: -13.5,-12.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 613 components: - type: Transform rot: 1.5707963267948966 rad pos: -9.5,-15.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 614 components: - type: Transform rot: 1.5707963267948966 rad pos: -9.5,-14.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 615 components: - type: Transform rot: 1.5707963267948966 rad pos: -9.5,-13.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 616 components: - type: Transform rot: 1.5707963267948966 rad pos: -9.5,-12.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 617 components: - type: Transform rot: 1.5707963267948966 rad pos: 6.5,-15.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 618 components: - type: Transform rot: 1.5707963267948966 rad pos: 6.5,-14.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 619 components: - type: Transform rot: 1.5707963267948966 rad pos: 6.5,-13.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 620 components: - type: Transform rot: 1.5707963267948966 rad pos: 6.5,-12.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 621 components: - type: Transform rot: 1.5707963267948966 rad pos: 10.5,-15.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 622 components: - type: Transform rot: 1.5707963267948966 rad pos: 10.5,-14.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 623 components: - type: Transform rot: 1.5707963267948966 rad pos: 10.5,-13.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 624 components: - type: Transform rot: 1.5707963267948966 rad pos: 10.5,-12.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 625 components: - type: Transform rot: -1.5707963267948966 rad pos: 8.5,-15.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 626 components: - type: Transform rot: -1.5707963267948966 rad pos: 8.5,-14.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 627 components: - type: Transform rot: -1.5707963267948966 rad pos: 8.5,-13.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 628 components: - type: Transform rot: -1.5707963267948966 rad pos: 8.5,-12.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 629 components: - type: Transform rot: -1.5707963267948966 rad pos: 12.5,-15.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 630 components: - type: Transform rot: -1.5707963267948966 rad pos: 12.5,-14.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 631 components: - type: Transform rot: -1.5707963267948966 rad pos: 12.5,-13.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 632 components: - type: Transform rot: -1.5707963267948966 rad pos: 12.5,-12.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 847 components: - type: Transform rot: 1.5707963267948966 rad pos: -12.5,-8.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 848 components: - type: Transform rot: -1.5707963267948966 rad pos: -8.5,-8.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 849 components: - type: Transform rot: -1.5707963267948966 rad pos: -8.5,-7.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 850 components: - type: Transform rot: -1.5707963267948966 rad pos: -8.5,-6.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - proto: ChairOfficeDark entities: - - uid: 591 + - uid: 18 components: - type: Transform + anchored: True rot: 3.141592653589793 rad pos: 9.5,3.5 parent: 818 + - type: Physics + bodyType: Static + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - proto: ChairWood entities: - uid: 577 components: - type: Transform + anchored: True pos: 10.5,1.5 parent: 818 - - uid: 703 + - type: Physics + bodyType: Static + - type: Godmode + missingComponents: + - Construction + - Destructible + - Anchorable + - uid: 591 components: - type: Transform + anchored: True rot: 1.5707963267948966 rad pos: 8.5,0.5 parent: 818 + - type: Physics + bodyType: Static + - type: Godmode + missingComponents: + - Construction + - Destructible + - Anchorable + - uid: 703 + components: + - type: Transform + anchored: True + pos: 9.5,1.5 + parent: 818 + - type: Physics + bodyType: Static + - type: Godmode + missingComponents: + - Construction + - Destructible + - Anchorable - uid: 704 components: - type: Transform - pos: 9.5,1.5 - parent: 818 - - uid: 714 - components: - - type: Transform + anchored: True rot: 1.5707963267948966 rad pos: 8.5,-0.5 parent: 818 + - type: Physics + bodyType: Static + - type: Godmode + missingComponents: + - Construction + - Destructible + - Anchorable - proto: ChessBoard entities: - - uid: 918 + - uid: 714 components: - type: Transform - pos: 12.503689,-2.3981738 + rot: 3.141592653589793 rad + pos: 12.5093775,-2.403601 parent: 818 - proto: ClosetWallEmergencyFilledRandom entities: @@ -2760,6 +4379,10 @@ entities: - type: Transform pos: -5.5,2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Construction - proto: ClosetWallFireFilledRandom entities: - uid: 432 @@ -2767,6 +4390,10 @@ entities: - type: Transform pos: 4.5,2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Construction - proto: ComfyChair entities: - uid: 595 @@ -2775,28 +4402,53 @@ entities: rot: 3.141592653589793 rad pos: 6.5,-3.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 718 components: - type: Transform pos: 12.5,-1.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 749 components: - type: Transform pos: 12.5,1.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 759 components: - type: Transform rot: 3.141592653589793 rad pos: 12.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 760 components: - type: Transform rot: 3.141592653589793 rad pos: 12.5,-3.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - proto: DisposalBend entities: - uid: 853 @@ -2805,40 +4457,75 @@ entities: rot: -1.5707963267948966 rad pos: -10.5,-7.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 862 components: - type: Transform rot: 1.5707963267948966 rad pos: -10.5,0.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 891 components: - type: Transform pos: 3.5,7.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 893 components: - type: Transform rot: 1.5707963267948966 rad pos: -4.5,7.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 898 components: - type: Transform rot: 3.141592653589793 rad pos: 9.5,-7.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 899 components: - type: Transform pos: 9.5,-1.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 900 components: - type: Transform rot: 3.141592653589793 rad pos: 3.5,-1.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - proto: DisposalJunctionFlipped entities: - uid: 892 @@ -2847,6 +4534,11 @@ entities: rot: 3.141592653589793 rad pos: 3.5,0.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - proto: DisposalPipe entities: - uid: 854 @@ -2855,277 +4547,517 @@ entities: rot: -1.5707963267948966 rad pos: -11.5,-7.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 855 components: - type: Transform rot: 3.141592653589793 rad pos: -10.5,-6.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 856 components: - type: Transform rot: 3.141592653589793 rad pos: -10.5,-5.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 857 components: - type: Transform rot: 3.141592653589793 rad pos: -10.5,-4.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 858 components: - type: Transform rot: 3.141592653589793 rad pos: -10.5,-3.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 859 components: - type: Transform rot: 3.141592653589793 rad pos: -10.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 860 components: - type: Transform rot: 3.141592653589793 rad pos: -10.5,-1.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 861 components: - type: Transform rot: 3.141592653589793 rad pos: -10.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 863 components: - type: Transform rot: 1.5707963267948966 rad pos: -9.5,0.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 864 components: - type: Transform rot: 1.5707963267948966 rad pos: -8.5,0.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 865 components: - type: Transform rot: 1.5707963267948966 rad pos: -7.5,0.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 866 components: - type: Transform rot: 1.5707963267948966 rad pos: -6.5,0.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 867 components: - type: Transform rot: 1.5707963267948966 rad pos: -5.5,0.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 868 components: - type: Transform rot: 1.5707963267948966 rad pos: -4.5,0.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 869 components: - type: Transform rot: 1.5707963267948966 rad pos: -3.5,0.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 870 components: - type: Transform rot: 1.5707963267948966 rad pos: -2.5,0.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 871 components: - type: Transform rot: 1.5707963267948966 rad pos: -1.5,0.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 872 components: - type: Transform rot: 1.5707963267948966 rad pos: -0.5,0.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 873 components: - type: Transform rot: 1.5707963267948966 rad pos: 0.5,0.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 874 components: - type: Transform rot: 1.5707963267948966 rad pos: 1.5,0.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 875 components: - type: Transform rot: 1.5707963267948966 rad pos: 2.5,0.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 876 components: - type: Transform pos: 3.5,1.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 877 components: - type: Transform pos: 3.5,2.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 878 components: - type: Transform pos: 3.5,3.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 879 components: - type: Transform pos: 3.5,4.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 880 components: - type: Transform pos: 3.5,5.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 881 components: - type: Transform pos: 3.5,6.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 882 components: - type: Transform rot: -1.5707963267948966 rad pos: 2.5,7.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 883 components: - type: Transform rot: -1.5707963267948966 rad pos: 1.5,7.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 884 components: - type: Transform rot: -1.5707963267948966 rad pos: 0.5,7.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 885 components: - type: Transform rot: -1.5707963267948966 rad pos: -0.5,7.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 886 components: - type: Transform rot: -1.5707963267948966 rad pos: -1.5,7.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 887 components: - type: Transform rot: -1.5707963267948966 rad pos: -2.5,7.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 888 components: - type: Transform rot: -1.5707963267948966 rad pos: -3.5,7.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 889 components: - type: Transform rot: 3.141592653589793 rad pos: -4.5,6.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 890 components: - type: Transform rot: 3.141592653589793 rad pos: -4.5,5.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 901 components: - type: Transform rot: 1.5707963267948966 rad pos: 10.5,-7.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 902 components: - type: Transform pos: 9.5,-6.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 903 components: - type: Transform pos: 9.5,-5.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 904 components: - type: Transform pos: 9.5,-4.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 905 components: - type: Transform pos: 9.5,-3.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 906 components: - type: Transform pos: 9.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 907 components: - type: Transform rot: -1.5707963267948966 rad pos: 8.5,-1.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 908 components: - type: Transform rot: -1.5707963267948966 rad pos: 7.5,-1.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 909 components: - type: Transform rot: -1.5707963267948966 rad pos: 6.5,-1.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 910 components: - type: Transform rot: -1.5707963267948966 rad pos: 5.5,-1.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 911 components: - type: Transform rot: -1.5707963267948966 rad pos: 4.5,-1.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 912 components: - type: Transform rot: 3.141592653589793 rad pos: 3.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - proto: DisposalTrunk entities: - uid: 852 @@ -3134,18 +5066,33 @@ entities: rot: 1.5707963267948966 rad pos: -12.5,-7.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 894 components: - type: Transform rot: 3.141592653589793 rad pos: -4.5,4.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 897 components: - type: Transform rot: -1.5707963267948966 rad pos: 11.5,-7.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - proto: DisposalUnit entities: - uid: 851 @@ -3153,29 +5100,39 @@ entities: - type: Transform pos: -12.5,-7.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Destructible + - Anchorable - uid: 896 components: - type: Transform pos: 11.5,-7.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Destructible + - Anchorable - proto: DrinkGlass entities: + - uid: 723 + components: + - type: Transform + pos: -12.618602,2.5336328 + parent: 818 - uid: 915 components: - type: Transform - pos: -12.587411,2.5765429 - parent: 818 - - uid: 916 - components: - - type: Transform - pos: -12.321786,2.7171679 + pos: -12.399852,2.6273828 parent: 818 - proto: DrinkShaker entities: - - uid: 914 + - uid: 724 components: - type: Transform - pos: -12.649911,2.7640429 + pos: -12.722768,2.7627993 parent: 818 - proto: ExtinguisherCabinetFilled entities: @@ -3184,11 +5141,17 @@ entities: - type: Transform pos: -6.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 816 components: - type: Transform pos: 5.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - proto: FirelockEdge entities: - uid: 690 @@ -3196,111 +5159,211 @@ entities: - type: Transform pos: -8.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 694 components: - type: Transform pos: -12.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 695 components: - type: Transform rot: 3.141592653589793 rad pos: -8.5,-16.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 696 components: - type: Transform rot: 3.141592653589793 rad pos: -12.5,-16.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 697 components: - type: Transform rot: 3.141592653589793 rad pos: 7.5,-16.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 698 components: - type: Transform rot: 3.141592653589793 rad pos: 11.5,-16.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 699 components: - type: Transform pos: 11.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 700 components: - type: Transform pos: 7.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 822 components: - type: Transform pos: 10.5,-3.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 823 components: - type: Transform pos: 9.5,-3.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 824 components: - type: Transform pos: 8.5,-3.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 825 components: - type: Transform rot: 3.141592653589793 rad pos: 8.5,-5.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 826 components: - type: Transform rot: 3.141592653589793 rad pos: 9.5,-5.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 827 components: - type: Transform rot: 3.141592653589793 rad pos: 10.5,-5.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 828 components: - type: Transform pos: -9.5,-3.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 829 components: - type: Transform pos: -10.5,-3.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 830 components: - type: Transform pos: -11.5,-3.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 831 components: - type: Transform rot: 3.141592653589793 rad pos: -11.5,-5.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 832 components: - type: Transform rot: 3.141592653589793 rad pos: -10.5,-5.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 833 components: - type: Transform rot: 3.141592653589793 rad pos: -9.5,-5.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - proto: FirelockGlass entities: - uid: 194 @@ -3308,51 +5371,101 @@ entities: - type: Transform pos: 5.5,0.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 216 components: - type: Transform pos: -10.5,2.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 220 components: - type: Transform pos: -9.5,2.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 305 components: - type: Transform pos: -6.5,0.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 345 components: - type: Transform pos: 5.5,-1.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 346 components: - type: Transform pos: 5.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 347 components: - type: Transform pos: -6.5,-1.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 348 components: - type: Transform pos: -6.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 586 components: - type: Transform pos: -11.5,2.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 716 components: - type: Transform pos: -12.5,2.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - proto: GeneratorBasic15kW entities: - uid: 124 @@ -3360,6 +5473,10 @@ entities: - type: Transform pos: -4.5,8.5 parent: 818 + - type: Godmode + missingComponents: + - Anchorable + - Destructible - proto: GravityGeneratorMini entities: - uid: 808 @@ -3367,6 +5484,11 @@ entities: - type: Transform pos: 1.5,8.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Anchorable + - Construction - proto: Grille entities: - uid: 96 @@ -3374,479 +5496,918 @@ entities: - type: Transform pos: -14.5,-15.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 97 components: - type: Transform pos: -14.5,-14.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 98 components: - type: Transform pos: -14.5,-13.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 99 components: - type: Transform pos: -6.5,-13.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 101 components: - type: Transform pos: 5.5,-15.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 102 components: - type: Transform pos: 5.5,-14.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 103 components: - type: Transform pos: 13.5,-15.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 104 components: - type: Transform pos: 13.5,-14.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 125 components: - type: Transform rot: 1.5707963267948966 rad pos: -7.5,-19.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 126 components: - type: Transform rot: 1.5707963267948966 rad pos: -7.5,-20.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 127 components: - type: Transform rot: 1.5707963267948966 rad pos: -8.5,-20.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 128 components: - type: Transform rot: 1.5707963267948966 rad pos: -8.5,-21.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 129 components: - type: Transform rot: 1.5707963267948966 rad pos: -9.5,-21.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 130 components: - type: Transform rot: 1.5707963267948966 rad pos: -11.5,-21.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 131 components: - type: Transform rot: 1.5707963267948966 rad pos: -12.5,-21.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 132 components: - type: Transform rot: 1.5707963267948966 rad pos: -12.5,-20.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 133 components: - type: Transform rot: 1.5707963267948966 rad pos: -13.5,-20.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 134 components: - type: Transform rot: 1.5707963267948966 rad pos: -13.5,-19.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 135 components: - type: Transform pos: 5.5,-13.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 136 components: - type: Transform pos: 5.5,-12.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 137 components: - type: Transform pos: 13.5,-13.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 138 components: - type: Transform pos: 13.5,-12.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 139 components: - type: Transform pos: -14.5,-12.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 140 components: - type: Transform pos: -6.5,-15.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 141 components: - type: Transform pos: -6.5,-12.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 142 components: - type: Transform pos: -6.5,-14.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 143 components: - type: Transform rot: 1.5707963267948966 rad pos: -7.5,-8.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 144 components: - type: Transform rot: 1.5707963267948966 rad pos: -7.5,-7.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 145 components: - type: Transform rot: 1.5707963267948966 rad pos: -7.5,-6.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 147 components: - type: Transform rot: 1.5707963267948966 rad pos: -13.5,-8.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 148 components: - type: Transform rot: 1.5707963267948966 rad pos: -13.5,-7.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 149 components: - type: Transform rot: 1.5707963267948966 rad pos: -13.5,-6.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 151 components: - type: Transform rot: 1.5707963267948966 rad pos: 12.5,-8.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 152 components: - type: Transform rot: 1.5707963267948966 rad pos: 12.5,-7.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 153 components: - type: Transform rot: 1.5707963267948966 rad pos: 12.5,-6.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 155 components: - type: Transform rot: 1.5707963267948966 rad pos: 6.5,-8.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 156 components: - type: Transform rot: 1.5707963267948966 rad pos: 6.5,-7.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 157 components: - type: Transform rot: 1.5707963267948966 rad pos: 6.5,-6.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 167 components: - type: Transform rot: 1.5707963267948966 rad pos: 12.5,-19.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 168 components: - type: Transform rot: 1.5707963267948966 rad pos: 12.5,-20.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 169 components: - type: Transform rot: 1.5707963267948966 rad pos: 11.5,-20.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 170 components: - type: Transform rot: 1.5707963267948966 rad pos: 11.5,-21.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 171 components: - type: Transform rot: 1.5707963267948966 rad pos: 10.5,-21.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 172 components: - type: Transform rot: 1.5707963267948966 rad pos: 8.5,-21.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 173 components: - type: Transform rot: 1.5707963267948966 rad pos: 7.5,-21.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 174 components: - type: Transform rot: 1.5707963267948966 rad pos: 7.5,-20.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 175 components: - type: Transform rot: 1.5707963267948966 rad pos: 6.5,-20.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 176 components: - type: Transform rot: 1.5707963267948966 rad pos: 6.5,-19.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 178 components: - type: Transform pos: 3.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 183 components: - type: Transform pos: -3.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 184 components: - type: Transform pos: 4.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 191 components: - type: Transform pos: -5.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 197 components: - type: Transform pos: -4.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 229 components: - type: Transform pos: 2.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 233 components: - type: Transform pos: -8.5,-4.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 234 components: - type: Transform pos: 11.5,-4.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 235 components: - type: Transform pos: 7.5,-4.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 244 components: - type: Transform pos: -12.5,-4.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 276 components: - type: Transform pos: 13.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 277 components: - type: Transform pos: 13.5,-1.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 278 components: - type: Transform pos: 13.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 279 components: - type: Transform pos: 13.5,0.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 280 components: - type: Transform pos: -14.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 281 components: - type: Transform pos: -14.5,-1.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 282 components: - type: Transform pos: -14.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 283 components: - type: Transform pos: -14.5,0.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 318 components: - type: Transform pos: -13.5,3.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 319 components: - type: Transform pos: -13.5,4.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 320 components: - type: Transform pos: -12.5,4.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 321 components: - type: Transform pos: -12.5,5.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 322 components: - type: Transform pos: -11.5,5.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 323 components: - type: Transform pos: -10.5,5.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 324 components: - type: Transform pos: -9.5,5.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 325 components: - type: Transform pos: -8.5,5.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 326 components: - type: Transform pos: -8.5,4.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 327 components: - type: Transform pos: -7.5,4.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 328 components: - type: Transform pos: -7.5,3.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 329 components: - type: Transform pos: 6.5,3.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 330 components: - type: Transform pos: 6.5,4.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 331 components: - type: Transform pos: 7.5,4.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 332 components: - type: Transform pos: 7.5,5.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 333 components: - type: Transform pos: 8.5,5.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 334 components: - type: Transform pos: 9.5,5.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 335 components: - type: Transform pos: 10.5,5.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 336 components: - type: Transform pos: 11.5,5.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 337 components: - type: Transform pos: 11.5,4.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 338 components: - type: Transform pos: 12.5,4.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 339 components: - type: Transform pos: 12.5,3.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - proto: PaperBin10 entities: - - uid: 737 + - uid: 729 components: - type: Transform - rot: 3.141592653589793 rad pos: 8.5,4.5 parent: 818 - proto: PosterLegitCohibaRobustoAd @@ -3856,6 +6417,9 @@ entities: - type: Transform pos: -6.5,1.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - proto: PosterLegitEnlist entities: - uid: 926 @@ -3863,6 +6427,9 @@ entities: - type: Transform pos: -14.5,1.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - proto: PosterLegitHighClassMartini entities: - uid: 925 @@ -3870,6 +6437,9 @@ entities: - type: Transform pos: -6.5,-3.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - proto: PosterLegitJustAWeekAway entities: - uid: 821 @@ -3877,6 +6447,9 @@ entities: - type: Transform pos: 5.5,1.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - proto: PosterLegitNanomichiAd entities: - uid: 820 @@ -3884,6 +6457,9 @@ entities: - type: Transform pos: -4.5,3.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - proto: PosterLegitNanotrasenLogo entities: - uid: 246 @@ -3891,36 +6467,57 @@ entities: - type: Transform pos: -7.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 247 components: - type: Transform pos: -13.5,-4.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 248 components: - type: Transform pos: 12.5,-4.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 249 components: - type: Transform pos: 6.5,-16.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 250 components: - type: Transform pos: -13.5,-16.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 251 components: - type: Transform pos: 12.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 922 components: - type: Transform pos: -0.5,6.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - proto: PosterLegitNTTGC entities: - uid: 924 @@ -3928,6 +6525,9 @@ entities: - type: Transform pos: 5.5,-3.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - proto: PosterLegitPDAAd entities: - uid: 920 @@ -3935,6 +6535,9 @@ entities: - type: Transform pos: 12.5,-16.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - proto: PosterLegitVacation entities: - uid: 921 @@ -3942,6 +6545,9 @@ entities: - type: Transform pos: -7.5,-16.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - proto: PosterLegitWorkForAFuture entities: - uid: 923 @@ -3949,6 +6555,9 @@ entities: - type: Transform pos: 12.5,2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - proto: PottedPlantRandom entities: - uid: 236 @@ -3956,31 +6565,37 @@ entities: - type: Transform pos: 7.5,-19.5 parent: 818 + - type: Godmode - uid: 237 components: - type: Transform pos: -12.5,-19.5 parent: 818 + - type: Godmode - uid: 238 components: - type: Transform pos: 11.5,-19.5 parent: 818 + - type: Godmode - uid: 239 components: - type: Transform pos: -8.5,-19.5 parent: 818 + - type: Godmode - uid: 733 components: - type: Transform pos: -8.5,-5.5 parent: 818 + - type: Godmode - uid: 741 components: - type: Transform pos: -7.5,-3.5 parent: 818 + - type: Godmode - proto: PottedPlantRandomPlastic entities: - uid: 708 @@ -3988,130 +6603,13 @@ entities: - type: Transform pos: -13.5,1.5 parent: 818 + - type: Godmode - uid: 755 components: - type: Transform pos: -13.5,-3.5 parent: 818 -- proto: Poweredlight - entities: - - uid: 150 - components: - - type: MetaData - flags: PvsPriority - - type: Transform - rot: -1.5707963267948966 rad - pos: -8.5,-5.5 - parent: 818 - - uid: 188 - components: - - type: MetaData - flags: PvsPriority - - type: Transform - rot: -1.5707963267948966 rad - pos: 11.5,2.5 - parent: 818 - - uid: 195 - components: - - type: MetaData - flags: PvsPriority - - type: Transform - rot: 3.141592653589793 rad - pos: -2.5,-1.5 - parent: 818 - - uid: 209 - components: - - type: MetaData - flags: PvsPriority - - type: Transform - rot: 1.5707963267948966 rad - pos: 7.5,-5.5 - parent: 818 - - uid: 341 - components: - - type: MetaData - flags: PvsPriority - - type: Transform - rot: 3.141592653589793 rad - pos: 1.5,-1.5 - parent: 818 - - uid: 634 - components: - - type: MetaData - flags: PvsPriority - - type: Transform - pos: 9.5,-16.5 - parent: 818 - - uid: 636 - components: - - type: MetaData - flags: PvsPriority - - type: Transform - rot: 3.141592653589793 rad - pos: 9.5,-11.5 - parent: 818 - - uid: 649 - components: - - type: MetaData - flags: PvsPriority - - type: Transform - rot: 3.141592653589793 rad - pos: -10.5,-11.5 - parent: 818 - - uid: 650 - components: - - type: MetaData - flags: PvsPriority - - type: Transform - pos: -10.5,-16.5 - parent: 818 - - uid: 687 - components: - - type: MetaData - flags: PvsPriority - - type: Transform - rot: 1.5707963267948966 rad - pos: -13.5,1.5 - parent: 818 - - uid: 701 - components: - - type: MetaData - flags: PvsPriority - - type: Transform - rot: 3.141592653589793 rad - pos: -6.5,3.5 - parent: 818 - - uid: 702 - components: - - type: MetaData - flags: PvsPriority - - type: Transform - rot: 3.141592653589793 rad - pos: 5.5,3.5 - parent: 818 - - uid: 715 - components: - - type: MetaData - flags: PvsPriority - - type: Transform - pos: -0.5,5.5 - parent: 818 - - uid: 717 - components: - - type: MetaData - flags: PvsPriority - - type: Transform - rot: -1.5707963267948966 rad - pos: -7.5,-3.5 - parent: 818 - - uid: 742 - components: - - type: MetaData - flags: PvsPriority - - type: Transform - rot: 1.5707963267948966 rad - pos: 6.5,-3.5 - parent: 818 + - type: Godmode - proto: RandomSpawner entities: - uid: 895 @@ -4119,32 +6617,7 @@ entities: - type: Transform pos: -4.5,4.5 parent: 818 -- proto: RandomVending - entities: - - uid: 835 - components: - - type: Transform - pos: 9.5,-20.5 - parent: 818 - - uid: 836 - components: - - type: Transform - pos: -10.5,-20.5 - parent: 818 -- proto: RandomVendingDrinks - entities: - - uid: 692 - components: - - type: Transform - pos: 11.5,-5.5 - parent: 818 -- proto: RandomVendingSnacks - entities: - - uid: 834 - components: - - type: Transform - pos: 11.5,-6.5 - parent: 818 + - type: Godmode - proto: ReinforcedWindow entities: - uid: 19 @@ -4153,472 +6626,912 @@ entities: rot: 1.5707963267948966 rad pos: -7.5,-20.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 20 components: - type: Transform rot: 1.5707963267948966 rad pos: -8.5,-20.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 21 components: - type: Transform rot: 1.5707963267948966 rad pos: -8.5,-21.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 22 components: - type: Transform rot: 1.5707963267948966 rad pos: -9.5,-21.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 24 components: - type: Transform rot: 1.5707963267948966 rad pos: -7.5,-19.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 25 components: - type: Transform rot: 1.5707963267948966 rad pos: -11.5,-21.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 26 components: - type: Transform rot: 1.5707963267948966 rad pos: -12.5,-21.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 27 components: - type: Transform rot: 1.5707963267948966 rad pos: -12.5,-20.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 28 components: - type: Transform rot: 1.5707963267948966 rad pos: -13.5,-20.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 29 components: - type: Transform rot: 1.5707963267948966 rad pos: -13.5,-19.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 30 components: - type: Transform rot: 1.5707963267948966 rad pos: 8.5,-21.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 31 components: - type: Transform rot: 1.5707963267948966 rad pos: 7.5,-21.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 32 components: - type: Transform rot: 1.5707963267948966 rad pos: 7.5,-20.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 33 components: - type: Transform rot: 1.5707963267948966 rad pos: 6.5,-20.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 34 components: - type: Transform rot: 1.5707963267948966 rad pos: 6.5,-19.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 35 components: - type: Transform rot: 1.5707963267948966 rad pos: 10.5,-21.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 36 components: - type: Transform rot: 1.5707963267948966 rad pos: 11.5,-21.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 37 components: - type: Transform rot: 1.5707963267948966 rad pos: 11.5,-20.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 38 components: - type: Transform rot: 1.5707963267948966 rad pos: 12.5,-20.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 39 components: - type: Transform rot: 1.5707963267948966 rad pos: 12.5,-19.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 91 components: - type: Transform pos: -14.5,-12.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 93 components: - type: Transform pos: -14.5,-14.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 94 components: - type: Transform pos: -6.5,-13.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 95 components: - type: Transform pos: -6.5,-12.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 100 components: - type: Transform rot: 1.5707963267948966 rad pos: -7.5,-8.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 105 components: - type: Transform pos: 5.5,-12.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 106 components: - type: Transform pos: 5.5,-14.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 107 components: - type: Transform pos: 13.5,-12.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 108 components: - type: Transform pos: 13.5,-13.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 109 components: - type: Transform rot: 1.5707963267948966 rad pos: 12.5,-8.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 110 components: - type: Transform rot: 1.5707963267948966 rad pos: 12.5,-7.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 111 components: - type: Transform rot: 1.5707963267948966 rad pos: 12.5,-6.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 113 components: - type: Transform rot: 1.5707963267948966 rad pos: 6.5,-6.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 115 components: - type: Transform rot: 1.5707963267948966 rad pos: 6.5,-7.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 116 components: - type: Transform rot: 1.5707963267948966 rad pos: 6.5,-8.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 117 components: - type: Transform rot: 1.5707963267948966 rad pos: -7.5,-7.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 118 components: - type: Transform rot: 1.5707963267948966 rad pos: -7.5,-6.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 121 components: - type: Transform rot: 1.5707963267948966 rad pos: -13.5,-8.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 122 components: - type: Transform rot: 1.5707963267948966 rad pos: -13.5,-7.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 123 components: - type: Transform rot: 1.5707963267948966 rad pos: -13.5,-6.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 159 components: - type: Transform pos: -14.5,-13.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 160 components: - type: Transform pos: -14.5,-15.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 161 components: - type: Transform pos: -6.5,-14.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 162 components: - type: Transform pos: -6.5,-15.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 163 components: - type: Transform pos: 5.5,-13.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 164 components: - type: Transform pos: 13.5,-15.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 165 components: - type: Transform pos: 5.5,-15.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 166 components: - type: Transform pos: 13.5,-14.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 185 components: - type: Transform pos: -5.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 186 components: - type: Transform pos: 2.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 192 components: - type: Transform pos: 4.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 196 components: - type: Transform pos: 3.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 198 components: - type: Transform pos: -3.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 232 components: - type: Transform pos: -4.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 240 components: - type: Transform pos: -12.5,-4.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 241 components: - type: Transform pos: 11.5,-4.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 242 components: - type: Transform pos: 7.5,-4.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 243 components: - type: Transform pos: -8.5,-4.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 268 components: - type: Transform pos: -14.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 269 components: - type: Transform pos: -14.5,-1.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 270 components: - type: Transform pos: -14.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 271 components: - type: Transform pos: -14.5,0.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 272 components: - type: Transform pos: 13.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 273 components: - type: Transform pos: 13.5,-1.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 274 components: - type: Transform pos: 13.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 275 components: - type: Transform pos: 13.5,0.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 284 components: - type: Transform pos: -13.5,4.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 285 components: - type: Transform pos: -12.5,4.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 286 components: - type: Transform pos: -10.5,5.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 287 components: - type: Transform pos: -11.5,5.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 288 components: - type: Transform pos: -8.5,4.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 289 components: - type: Transform pos: -8.5,5.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 290 components: - type: Transform pos: -12.5,5.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 291 components: - type: Transform pos: -13.5,3.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 292 components: - type: Transform pos: -9.5,5.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 293 components: - type: Transform pos: 6.5,3.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 294 components: - type: Transform pos: -7.5,3.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 295 components: - type: Transform pos: -7.5,4.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 308 components: - type: Transform pos: 6.5,4.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 309 components: - type: Transform pos: 7.5,4.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 310 components: - type: Transform pos: 7.5,5.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 311 components: - type: Transform pos: 8.5,5.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 312 components: - type: Transform pos: 9.5,5.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 313 components: - type: Transform pos: 10.5,5.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 314 components: - type: Transform pos: 11.5,5.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 315 components: - type: Transform pos: 11.5,4.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 316 components: - type: Transform pos: 12.5,4.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 317 components: - type: Transform pos: 12.5,3.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - proto: SignNanotrasen1 entities: - uid: 721 @@ -4626,6 +7539,9 @@ entities: - type: Transform pos: -2.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - proto: SignNanotrasen2 entities: - uid: 722 @@ -4633,6 +7549,9 @@ entities: - type: Transform pos: -1.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - proto: SignNanotrasen3 entities: - uid: 719 @@ -4640,6 +7559,9 @@ entities: - type: Transform pos: -0.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - proto: SignNanotrasen4 entities: - uid: 801 @@ -4647,6 +7569,9 @@ entities: - type: Transform pos: 0.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - proto: SignNanotrasen5 entities: - uid: 802 @@ -4654,6 +7579,9 @@ entities: - type: Transform pos: 1.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - proto: SignNosmoking entities: - uid: 720 @@ -4661,6 +7589,9 @@ entities: - type: Transform pos: -7.5,2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - proto: SignShipDock entities: - uid: 200 @@ -4668,11 +7599,17 @@ entities: - type: Transform pos: 6.5,-4.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 245 components: - type: Transform pos: -7.5,-4.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - proto: SignSpace entities: - uid: 571 @@ -4680,46 +7617,73 @@ entities: - type: Transform pos: 12.5,-18.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 640 components: - type: Transform pos: -7.5,-18.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 688 components: - type: Transform pos: -13.5,-18.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 689 components: - type: Transform pos: -7.5,-9.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 691 components: - type: Transform pos: -13.5,-9.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 705 components: - type: Transform pos: 12.5,-9.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 709 components: - type: Transform pos: 6.5,-9.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 817 components: - type: Transform pos: 6.5,-18.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 819 components: - type: Transform pos: 4.5,7.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - proto: SinkWide entities: - uid: 913 @@ -4728,6 +7692,9 @@ entities: rot: 1.5707963267948966 rad pos: -12.5,3.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - proto: SmallLight entities: - uid: 598 @@ -4736,52 +7703,102 @@ entities: rot: -1.5707963267948966 rad pos: -8.5,2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Construction + - RCDDeconstructable - uid: 641 components: - type: Transform pos: -14.5,-17.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Construction + - RCDDeconstructable - uid: 642 components: - type: Transform pos: -6.5,-17.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Construction + - RCDDeconstructable - uid: 643 components: - type: Transform pos: -14.5,-10.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Construction + - RCDDeconstructable - uid: 644 components: - type: Transform pos: -6.5,-10.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Construction + - RCDDeconstructable - uid: 645 components: - type: Transform pos: 5.5,-10.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Construction + - RCDDeconstructable - uid: 646 components: - type: Transform pos: 13.5,-10.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Construction + - RCDDeconstructable - uid: 647 components: - type: Transform pos: 13.5,-17.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Construction + - RCDDeconstructable - uid: 648 components: - type: Transform pos: 5.5,-17.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Construction + - RCDDeconstructable - uid: 917 components: - type: Transform rot: 3.141592653589793 rad pos: -0.5,7.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Construction + - RCDDeconstructable - proto: SMESBasic entities: - uid: 805 @@ -4789,13 +7806,24 @@ entities: - type: Transform pos: -2.5,8.5 parent: 818 -- proto: soda_dispenser + - type: Godmode + missingComponents: + - Anchorable + - Destructible + - Construction +- proto: SodaDispenser entities: - uid: 795 components: - type: Transform pos: -10.5,4.5 parent: 818 + - type: Godmode + missingComponents: + - ApcPowerReceiver + - Anchorable + - Destructible + - Construction - proto: SpaceVillainArcadeFilled entities: - uid: 731 @@ -4804,12 +7832,24 @@ entities: rot: 1.5707963267948966 rad pos: -13.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - ApcPowerReceiver + - Anchorable + - Construction + - Destructible - uid: 732 components: - type: Transform rot: 1.5707963267948966 rad pos: -13.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - ApcPowerReceiver + - Anchorable + - Construction + - Destructible - proto: SpawnPointLatejoin entities: - uid: 763 @@ -4817,161 +7857,193 @@ entities: - type: Transform pos: -7.5,-15.5 parent: 818 + - type: Godmode - uid: 764 components: - type: Transform pos: -7.5,-14.5 parent: 818 + - type: Godmode - uid: 765 components: - type: Transform pos: -7.5,-13.5 parent: 818 + - type: Godmode - uid: 766 components: - type: Transform pos: -7.5,-12.5 parent: 818 + - type: Godmode - uid: 767 components: - type: Transform pos: -9.5,-15.5 parent: 818 + - type: Godmode - uid: 768 components: - type: Transform pos: -9.5,-14.5 parent: 818 + - type: Godmode - uid: 769 components: - type: Transform pos: -9.5,-13.5 parent: 818 + - type: Godmode - uid: 770 components: - type: Transform pos: -9.5,-12.5 parent: 818 + - type: Godmode - uid: 771 components: - type: Transform pos: -11.5,-15.5 parent: 818 + - type: Godmode - uid: 772 components: - type: Transform pos: -11.5,-14.5 parent: 818 + - type: Godmode - uid: 773 components: - type: Transform pos: -11.5,-13.5 parent: 818 + - type: Godmode - uid: 774 components: - type: Transform pos: -11.5,-12.5 parent: 818 + - type: Godmode - uid: 775 components: - type: Transform pos: -13.5,-15.5 parent: 818 + - type: Godmode - uid: 776 components: - type: Transform pos: -13.5,-14.5 parent: 818 + - type: Godmode - uid: 777 components: - type: Transform pos: -13.5,-13.5 parent: 818 + - type: Godmode - uid: 778 components: - type: Transform pos: -13.5,-12.5 parent: 818 + - type: Godmode - uid: 779 components: - type: Transform pos: 6.5,-15.5 parent: 818 + - type: Godmode - uid: 780 components: - type: Transform pos: 6.5,-14.5 parent: 818 + - type: Godmode - uid: 781 components: - type: Transform pos: 6.5,-13.5 parent: 818 + - type: Godmode - uid: 782 components: - type: Transform pos: 6.5,-12.5 parent: 818 + - type: Godmode - uid: 783 components: - type: Transform pos: 8.5,-15.5 parent: 818 + - type: Godmode - uid: 784 components: - type: Transform pos: 8.5,-14.5 parent: 818 + - type: Godmode - uid: 785 components: - type: Transform pos: 8.5,-13.5 parent: 818 + - type: Godmode - uid: 786 components: - type: Transform pos: 8.5,-12.5 parent: 818 + - type: Godmode - uid: 787 components: - type: Transform pos: 10.5,-15.5 parent: 818 + - type: Godmode - uid: 788 components: - type: Transform pos: 10.5,-14.5 parent: 818 + - type: Godmode - uid: 789 components: - type: Transform pos: 10.5,-13.5 parent: 818 + - type: Godmode - uid: 790 components: - type: Transform pos: 10.5,-12.5 parent: 818 + - type: Godmode - uid: 791 components: - type: Transform pos: 12.5,-15.5 parent: 818 + - type: Godmode - uid: 792 components: - type: Transform pos: 12.5,-14.5 parent: 818 + - type: Godmode - uid: 793 components: - type: Transform pos: 12.5,-13.5 parent: 818 + - type: Godmode - uid: 794 components: - type: Transform pos: 12.5,-12.5 parent: 818 + - type: Godmode - proto: SS13Memorial entities: - uid: 594 @@ -4979,56 +8051,121 @@ entities: - type: Transform pos: -0.5,4.5 parent: 818 + - type: Godmode - proto: Stool entities: - uid: 119 components: - type: Transform + anchored: True rot: 3.141592653589793 rad pos: -11.5,-20.5 parent: 818 + - type: Physics + bodyType: Static + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 639 components: - type: Transform + anchored: True rot: 3.141592653589793 rad pos: -9.5,-20.5 parent: 818 - - uid: 723 - components: - - type: Transform - rot: 3.141592653589793 rad - pos: 10.5,-20.5 - parent: 818 - - uid: 724 - components: - - type: Transform - rot: 3.141592653589793 rad - pos: 8.5,-20.5 - parent: 818 - - uid: 729 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: -12.5,-1.5 - parent: 818 + - type: Physics + bodyType: Static + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 730 components: - type: Transform - rot: -1.5707963267948966 rad - pos: -12.5,-2.5 + anchored: True + rot: 3.141592653589793 rad + pos: 8.5,-20.5 parent: 818 + - type: Physics + bodyType: Static + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible + - uid: 737 + components: + - type: Transform + anchored: True + rot: 3.141592653589793 rad + pos: 10.5,-20.5 + parent: 818 + - type: Physics + bodyType: Static + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 738 components: - type: Transform + anchored: True rot: -1.5707963267948966 rad pos: -12.5,-0.5 parent: 818 + - type: Physics + bodyType: Static + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 740 components: - type: Transform + anchored: True rot: -1.5707963267948966 rad pos: -12.5,0.5 parent: 818 + - type: Physics + bodyType: Static + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible + - uid: 761 + components: + - type: Transform + anchored: True + rot: -1.5707963267948966 rad + pos: -12.5,-1.5 + parent: 818 + - type: Physics + bodyType: Static + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible + - uid: 914 + components: + - type: Transform + anchored: True + rot: -1.5707963267948966 rad + pos: -12.5,-2.5 + parent: 818 + - type: Physics + bodyType: Static + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - proto: StoolBar entities: - uid: 230 @@ -5037,18 +8174,33 @@ entities: rot: 3.141592653589793 rad pos: -9.5,1.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 342 components: - type: Transform rot: 3.141592653589793 rad pos: -11.5,1.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 433 components: - type: Transform rot: 3.141592653589793 rad pos: -10.5,1.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - proto: SubstationBasic entities: - uid: 807 @@ -5056,6 +8208,11 @@ entities: - type: Transform pos: -0.5,8.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Anchorable + - Construction - proto: TableCarpet entities: - uid: 572 @@ -5063,21 +8220,37 @@ entities: - type: Transform pos: 9.5,0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 573 components: - type: Transform pos: 9.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 574 components: - type: Transform pos: 10.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 576 components: - type: Transform pos: 10.5,0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Construction - proto: TableReinforced entities: - uid: 585 @@ -5086,36 +8259,60 @@ entities: rot: 1.5707963267948966 rad pos: -9.5,2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 707 components: - type: Transform rot: -1.5707963267948966 rad pos: -10.5,4.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 751 components: - type: Transform rot: -1.5707963267948966 rad pos: -11.5,4.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 796 components: - type: Transform rot: -1.5707963267948966 rad pos: -10.5,2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 797 components: - type: Transform rot: -1.5707963267948966 rad pos: -12.5,2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 798 components: - type: Transform rot: -1.5707963267948966 rad pos: -11.5,2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Construction - proto: TableWood entities: - uid: 441 @@ -5123,31 +8320,55 @@ entities: - type: Transform pos: 12.5,0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 575 components: - type: Transform pos: 6.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 587 components: - type: Transform pos: 12.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 706 components: - type: Transform pos: 9.5,4.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 750 components: - type: Transform pos: 10.5,4.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 756 components: - type: Transform pos: 8.5,4.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Construction - proto: TelecomServerFilled entities: - uid: 919 @@ -5155,972 +8376,1162 @@ entities: - type: Transform pos: -1.5,8.5 parent: 818 + - type: EncryptionKeyHolder + keysUnlocked: False + - type: Godmode + missingComponents: + - Destructible + - ApcPowerReceiver + - Anchorable + - Construction - proto: VendingMachineBooze entities: - uid: 753 components: - - type: MetaData - flags: SessionSpecific - type: Transform pos: -9.5,4.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Anchorable + - ApcPowerReceiver +- proto: VendingMachineChang + entities: + - uid: 692 + components: + - type: Transform + pos: 9.5,-20.5 + parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Anchorable - proto: VendingMachineCigs entities: - uid: 744 components: - - type: MetaData - flags: SessionSpecific - type: Transform pos: -7.5,1.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Anchorable + - ApcPowerReceiver - proto: VendingMachineCola entities: - uid: 635 components: - - type: MetaData - flags: SessionSpecific - type: Transform pos: -12.5,-5.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Anchorable + - ApcPowerReceiver +- proto: VendingMachineColaBlack + entities: + - uid: 834 + components: + - type: Transform + pos: -10.5,-20.5 + parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Anchorable +- proto: VendingMachineDiscount + entities: + - uid: 836 + components: + - type: Transform + pos: 11.5,-6.5 + parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Anchorable +- proto: VendingMachineDrGibb + entities: + - uid: 835 + components: + - type: Transform + pos: 11.5,-5.5 + parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Anchorable - proto: VendingMachineGames entities: - uid: 748 components: - - type: MetaData - flags: SessionSpecific - type: Transform pos: 6.5,1.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Anchorable + - ApcPowerReceiver - proto: VendingMachineSnack entities: - uid: 637 components: - - type: MetaData - flags: SessionSpecific - type: Transform pos: -12.5,-6.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Anchorable + - ApcPowerReceiver - proto: WallRiveted entities: - uid: 10 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: 6.5,-4.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 23 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: -10.5,-21.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 40 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: 9.5,-21.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 41 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: 6.5,-18.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 42 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: 5.5,-18.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 43 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: 4.5,-18.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 44 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: 12.5,-18.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 45 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: 13.5,-18.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 46 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: 14.5,-18.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 47 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: -5.5,-18.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 48 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: -6.5,-18.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 49 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: -7.5,-18.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 50 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: -13.5,-18.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 51 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: -14.5,-18.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 52 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: -15.5,-18.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 53 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: -13.5,-9.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 54 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: -14.5,-9.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 55 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: -15.5,-9.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 56 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: -7.5,-9.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 57 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: -6.5,-9.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 58 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: -5.5,-9.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 59 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: -5.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 60 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: -6.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 61 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: -7.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 62 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: -13.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 63 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: -14.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 64 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: -15.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 65 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: -13.5,-16.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 66 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: -14.5,-16.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 67 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: -15.5,-16.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 68 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: -7.5,-16.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 69 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: -6.5,-16.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 70 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: -5.5,-16.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 71 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: 12.5,-16.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 72 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: 13.5,-16.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 73 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: 14.5,-16.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 74 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: 14.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 75 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: 13.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 76 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: 12.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 77 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: 14.5,-9.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 78 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: 13.5,-9.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 79 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: 12.5,-9.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 80 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: 6.5,-9.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 81 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: 5.5,-9.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 82 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: 4.5,-9.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 83 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: 6.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 84 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: 5.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 85 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: 4.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 86 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: 6.5,-16.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 87 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: 5.5,-16.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 88 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: 4.5,-16.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 89 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: -7.5,-4.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 90 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: -13.5,-4.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 92 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: 12.5,-4.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 112 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: -1.5707963267948966 rad pos: 6.5,-5.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 114 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: -1.5707963267948966 rad pos: -13.5,-5.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 120 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: 5.5,1.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 154 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: -1.5707963267948966 rad pos: 12.5,-5.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 158 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: -1.5707963267948966 rad pos: -7.5,-5.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 179 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: -2.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 180 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: 5.5,-3.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 182 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: 1.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 187 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: -6.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 189 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: 5.5,-4.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 190 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: 1.5,9.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 193 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: 5.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 199 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: -6.5,-4.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 202 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: -6.5,1.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 207 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: -6.5,-3.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 217 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: -4.5,3.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 222 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: -2.5,9.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 223 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: -0.5,9.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 225 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: -1.5,9.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 231 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: -4.5,9.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 258 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: -14.5,-4.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 259 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: 13.5,-3.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 260 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: 13.5,-4.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 261 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: -14.5,-3.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 262 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: 13.5,1.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 263 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: 13.5,2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 264 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: 12.5,2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 265 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: -14.5,1.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 266 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: -14.5,2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 267 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: -13.5,2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 304 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: -7.5,2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 306 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: -6.5,2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 307 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: 6.5,2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 340 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: 5.5,2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 343 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: 0.5,9.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 351 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: -3.5,9.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 401 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: -5.5,2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 403 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: 4.5,9.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 405 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: -1.5,6.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 406 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: 4.5,2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 407 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: 2.5,6.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 408 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: 2.5,4.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 409 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: 2.5,5.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 414 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: 3.5,9.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 420 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: 2.5,3.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 578 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: -3.5,3.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 581 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: -3.5,5.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 582 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: -3.5,4.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 583 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: -3.5,6.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 588 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: -2.5,6.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 602 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: 0.5,6.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 693 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: 1.5,6.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 711 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: -1.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 712 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: -0.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 713 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: 0.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 725 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: -5.5,4.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 726 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: -5.5,3.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 736 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: -5.5,5.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 739 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: -5.5,6.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 743 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: -5.5,7.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 745 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: -5.5,8.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 746 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: 2.5,9.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 754 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: 4.5,7.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 757 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: 4.5,3.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 758 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: 4.5,6.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 762 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: 4.5,5.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 799 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: 4.5,4.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 800 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: -5.5,9.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 804 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: -0.5,6.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - proto: WarpPoint entities: - uid: 638 @@ -6130,6 +9541,7 @@ entities: parent: 818 - type: WarpPoint location: Terminal + - type: Godmode - proto: Windoor entities: - uid: 806 @@ -6137,11 +9549,21 @@ entities: - type: Transform pos: -8.5,2.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 841 components: - type: Transform pos: -2.5,3.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - proto: WindowReinforcedDirectional entities: - uid: 181 @@ -6150,198 +9572,373 @@ entities: rot: 1.5707963267948966 rad pos: -9.5,2.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 204 components: - type: Transform rot: 1.5707963267948966 rad pos: 0.5,8.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 600 components: - type: Transform rot: -1.5707963267948966 rad pos: 2.5,8.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 659 components: - type: Transform pos: 9.5,-15.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 660 components: - type: Transform rot: 3.141592653589793 rad pos: 9.5,-12.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 661 components: - type: Transform rot: 1.5707963267948966 rad pos: 9.5,-12.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 662 components: - type: Transform rot: 1.5707963267948966 rad pos: 9.5,-13.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 663 components: - type: Transform rot: 1.5707963267948966 rad pos: 9.5,-14.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 664 components: - type: Transform rot: 1.5707963267948966 rad pos: 9.5,-15.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 665 components: - type: Transform rot: -1.5707963267948966 rad pos: 9.5,-15.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 666 components: - type: Transform rot: -1.5707963267948966 rad pos: 9.5,-14.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 667 components: - type: Transform rot: -1.5707963267948966 rad pos: 9.5,-13.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 668 components: - type: Transform rot: -1.5707963267948966 rad pos: 9.5,-12.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 669 components: - type: Transform rot: 3.141592653589793 rad pos: -10.5,-12.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 670 components: - type: Transform pos: -10.5,-15.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 671 components: - type: Transform rot: -1.5707963267948966 rad pos: -10.5,-15.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 672 components: - type: Transform rot: -1.5707963267948966 rad pos: -10.5,-14.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 673 components: - type: Transform rot: -1.5707963267948966 rad pos: -10.5,-13.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 674 components: - type: Transform rot: -1.5707963267948966 rad pos: -10.5,-12.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 675 components: - type: Transform rot: 1.5707963267948966 rad pos: -10.5,-12.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 676 components: - type: Transform rot: 1.5707963267948966 rad pos: -10.5,-13.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 677 components: - type: Transform rot: 1.5707963267948966 rad pos: -10.5,-14.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 678 components: - type: Transform rot: 1.5707963267948966 rad pos: -10.5,-15.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 679 components: - type: Transform rot: 3.141592653589793 rad pos: -9.5,-16.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 680 components: - type: Transform rot: 3.141592653589793 rad pos: -11.5,-16.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 681 components: - type: Transform pos: -11.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 682 components: - type: Transform pos: -9.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 683 components: - type: Transform pos: 10.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 684 components: - type: Transform pos: 8.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 685 components: - type: Transform rot: 3.141592653589793 rad pos: 8.5,-16.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 686 components: - type: Transform rot: 3.141592653589793 rad pos: 10.5,-16.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 837 components: - type: Transform pos: 1.5,3.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 838 components: - type: Transform pos: 0.5,3.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 839 components: - type: Transform pos: -0.5,3.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 840 components: - type: Transform pos: -1.5,3.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible ... diff --git a/Resources/Maps/Shuttles/arrivals.yml b/Resources/Maps/Shuttles/arrivals.yml index b4609e1b0a..3c853ef739 100644 --- a/Resources/Maps/Shuttles/arrivals.yml +++ b/Resources/Maps/Shuttles/arrivals.yml @@ -192,13 +192,17 @@ entities: - type: RadiationGridResistance - type: SpreaderGrid - type: GridPathfinding + - type: Godmode - proto: AirCanister entities: - uid: 214 components: - type: Transform + anchored: True pos: -1.5,7.5 parent: 292 + - type: Physics + bodyType: Static - proto: AirlockCommandGlassLocked entities: - uid: 278 @@ -208,6 +212,11 @@ entities: - type: Transform pos: -0.5,6.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - proto: AirlockGlassShuttle entities: - uid: 177 @@ -217,11 +226,16 @@ entities: pos: 3.5,-2.5 parent: 292 - type: Door - secondsUntilStateChange: -336.60016 + secondsUntilStateChange: -623.03485 state: Opening - type: DeviceLinkSource lastSignals: DoorStatus: True + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 178 components: - type: Transform @@ -229,11 +243,16 @@ entities: pos: 3.5,4.5 parent: 292 - type: Door - secondsUntilStateChange: -338.3335 + secondsUntilStateChange: -624.7682 state: Opening - type: DeviceLinkSource lastSignals: DoorStatus: True + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 179 components: - type: Transform @@ -241,11 +260,16 @@ entities: pos: -4.5,4.5 parent: 292 - type: Door - secondsUntilStateChange: -332.80017 + secondsUntilStateChange: -619.23486 state: Opening - type: DeviceLinkSource lastSignals: DoorStatus: True + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 180 components: - type: Transform @@ -253,11 +277,16 @@ entities: pos: -4.5,-2.5 parent: 292 - type: Door - secondsUntilStateChange: -334.70016 + secondsUntilStateChange: -621.1349 state: Opening - type: DeviceLinkSource lastSignals: DoorStatus: True + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - proto: APCBasic entities: - uid: 116 @@ -266,6 +295,13 @@ entities: rot: 3.141592653589793 rad pos: -0.5,3.5 parent: 292 + - type: BatterySelfRecharger + autoRechargeRate: 50000 + autoRecharge: True + - type: Godmode + missingComponents: + - Construction + - Destructible - proto: ArrivalsShuttleTimer entities: - uid: 294 @@ -273,11 +309,17 @@ entities: - type: Transform pos: -4.5,3.5 parent: 292 + - type: Godmode + missingComponents: + - Construction - uid: 295 components: - type: Transform pos: 3.5,3.5 parent: 292 + - type: Godmode + missingComponents: + - Construction - proto: AtmosDeviceFanDirectional entities: - uid: 164 @@ -286,24 +328,28 @@ entities: rot: -1.5707963267948966 rad pos: -4.5,4.5 parent: 292 + - type: Godmode - uid: 165 components: - type: Transform rot: 1.5707963267948966 rad pos: 3.5,4.5 parent: 292 + - type: Godmode - uid: 166 components: - type: Transform rot: 1.5707963267948966 rad pos: 3.5,-2.5 parent: 292 + - type: Godmode - uid: 167 components: - type: Transform rot: -1.5707963267948966 rad pos: -4.5,-2.5 parent: 292 + - type: Godmode - proto: BlockGameArcade entities: - uid: 258 @@ -312,418 +358,747 @@ entities: rot: -1.5707963267948966 rad pos: -1.5,-1.5 parent: 292 -- proto: CableApcExtension + - type: Godmode + missingComponents: + - Anchorable + - Construction + - Destructible +- proto: CableApcExtensionUncuttable entities: - uid: 123 components: - type: Transform pos: -0.5,3.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 124 components: - type: Transform pos: -0.5,4.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 125 components: - type: Transform pos: -1.5,4.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 126 components: - type: Transform pos: -2.5,4.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 127 components: - type: Transform pos: -2.5,3.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 128 components: - type: Transform pos: -2.5,2.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 129 components: - type: Transform pos: -2.5,1.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 130 components: - type: Transform pos: -2.5,0.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 131 components: - type: Transform pos: -2.5,-0.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 132 components: - type: Transform pos: -2.5,-1.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 133 components: - type: Transform pos: -2.5,-2.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 134 components: - type: Transform pos: -1.5,-2.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 135 components: - type: Transform pos: -0.5,-2.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 136 components: - type: Transform pos: 0.5,-2.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 137 components: - type: Transform pos: 1.5,-2.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 138 components: - type: Transform pos: 1.5,-1.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 139 components: - type: Transform pos: 1.5,-0.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 140 components: - type: Transform pos: 1.5,0.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 141 components: - type: Transform pos: 1.5,1.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 142 components: - type: Transform pos: 1.5,2.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 143 components: - type: Transform pos: 1.5,3.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 144 components: - type: Transform pos: 1.5,4.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 145 components: - type: Transform pos: 0.5,4.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 146 components: - type: Transform pos: -0.5,5.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 147 components: - type: Transform pos: -0.5,6.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 148 components: - type: Transform pos: -0.5,7.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 149 components: - type: Transform pos: -0.5,8.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 150 components: - type: Transform pos: -1.5,-3.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 151 components: - type: Transform pos: 0.5,-3.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 152 components: - type: Transform pos: 0.5,-4.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 153 components: - type: Transform pos: 1.5,-4.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 154 components: - type: Transform pos: -1.5,-4.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 155 components: - type: Transform pos: -2.5,-4.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 156 components: - type: Transform pos: -2.5,-5.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 157 components: - type: Transform pos: 1.5,-5.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 158 components: - type: Transform pos: -1.5,8.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 159 components: - type: Transform pos: 0.5,8.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 160 components: - type: Transform pos: -3.5,4.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 161 components: - type: Transform pos: 2.5,4.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 162 components: - type: Transform pos: 2.5,-2.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 163 components: - type: Transform pos: -3.5,-2.5 parent: 292 -- proto: CableHV + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable +- proto: CableHVUncuttable entities: - uid: 79 components: - type: Transform pos: 0.5,7.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 80 components: - type: Transform pos: 1.5,7.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 81 components: - type: Transform pos: 1.5,6.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 82 components: - type: Transform pos: -0.5,7.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 83 components: - type: Transform pos: -0.5,6.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 85 components: - type: Transform pos: -0.5,5.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 86 components: - type: Transform pos: -0.5,4.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 87 components: - type: Transform pos: -1.5,4.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 88 components: - type: Transform pos: -2.5,4.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 89 components: - type: Transform pos: -2.5,3.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 90 components: - type: Transform pos: -2.5,2.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 91 components: - type: Transform pos: -2.5,1.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 92 components: - type: Transform pos: -2.5,0.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 93 components: - type: Transform pos: -2.5,-0.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 94 components: - type: Transform pos: -2.5,-1.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 95 components: - type: Transform pos: -2.5,-2.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 96 components: - type: Transform pos: -1.5,-2.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 97 components: - type: Transform pos: -0.5,-2.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 98 components: - type: Transform pos: 0.5,-2.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 99 components: - type: Transform pos: 1.5,-2.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 100 components: - type: Transform pos: 1.5,-1.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 101 components: - type: Transform pos: 1.5,-0.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 102 components: - type: Transform pos: 1.5,0.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 103 components: - type: Transform pos: 1.5,1.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 104 components: - type: Transform pos: 1.5,2.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 105 components: - type: Transform pos: 1.5,3.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 106 components: - type: Transform pos: 1.5,4.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 107 components: - type: Transform pos: 0.5,4.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 108 components: - type: Transform pos: -1.5,-3.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 109 components: - type: Transform pos: -1.5,-4.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 110 components: - type: Transform pos: -1.5,-5.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 111 components: - type: Transform pos: 0.5,-5.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 112 components: - type: Transform pos: 0.5,-4.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 113 components: - type: Transform pos: 0.5,-3.5 parent: 292 -- proto: CableMV + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable +- proto: CableMVUncuttable entities: - uid: 117 components: - type: Transform pos: 1.5,6.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 118 components: - type: Transform pos: 1.5,5.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 119 components: - type: Transform pos: 1.5,4.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 120 components: - type: Transform pos: 0.5,4.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 121 components: - type: Transform pos: -0.5,4.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 122 components: - type: Transform pos: -0.5,3.5 parent: 292 -- proto: CableTerminal + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable +- proto: CableTerminalUncuttable entities: - uid: 84 components: @@ -731,6 +1106,11 @@ entities: rot: 1.5707963267948966 rad pos: -0.5,7.5 parent: 292 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - proto: ChairPilotSeat entities: - uid: 223 @@ -739,112 +1119,207 @@ entities: rot: -1.5707963267948966 rad pos: 2.5,-0.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 224 components: - type: Transform rot: -1.5707963267948966 rad pos: 2.5,0.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 225 components: - type: Transform rot: -1.5707963267948966 rad pos: 2.5,1.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 226 components: - type: Transform rot: -1.5707963267948966 rad pos: 2.5,2.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 227 components: - type: Transform rot: -1.5707963267948966 rad pos: -1.5,-0.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 228 components: - type: Transform rot: -1.5707963267948966 rad pos: -1.5,0.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 229 components: - type: Transform rot: -1.5707963267948966 rad pos: -1.5,1.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 230 components: - type: Transform rot: -1.5707963267948966 rad pos: -1.5,2.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 231 components: - type: Transform rot: 1.5707963267948966 rad pos: 0.5,-0.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 232 components: - type: Transform rot: 1.5707963267948966 rad pos: 0.5,0.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 233 components: - type: Transform rot: 1.5707963267948966 rad pos: 0.5,1.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 234 components: - type: Transform rot: 1.5707963267948966 rad pos: 0.5,2.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 235 components: - type: Transform rot: 1.5707963267948966 rad pos: -3.5,-0.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 236 components: - type: Transform rot: 1.5707963267948966 rad pos: -3.5,0.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 237 components: - type: Transform rot: 1.5707963267948966 rad pos: -3.5,1.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 238 components: - type: Transform rot: 1.5707963267948966 rad pos: -3.5,2.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 239 components: - type: Transform pos: 1.5,5.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 240 components: - type: Transform pos: -2.5,5.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 241 components: - type: Transform rot: 3.141592653589793 rad pos: -0.5,8.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - proto: ClosetEmergencyFilledRandom entities: - uid: 252 @@ -852,72 +1327,18 @@ entities: - type: Transform pos: 0.5,5.5 parent: 292 - - type: EntityStorage - air: - volume: 200 - immutable: False - temperature: 293.14963 - moles: - - 1.7459903 - - 6.568249 - - 0 - - 0 - - 0 - - 0 - - 0 - - 0 - - 0 - - 0 - - 0 - - 0 - - uid: 260 + - uid: 253 components: - type: Transform pos: -2.5,-3.5 parent: 292 - - type: EntityStorage - air: - volume: 200 - immutable: False - temperature: 293.14963 - moles: - - 1.7459903 - - 6.568249 - - 0 - - 0 - - 0 - - 0 - - 0 - - 0 - - 0 - - 0 - - 0 - - 0 - proto: ClosetFireFilled entities: - - uid: 253 + - uid: 260 components: - type: Transform pos: -1.5,5.5 parent: 292 - - type: EntityStorage - air: - volume: 200 - immutable: False - temperature: 293.14963 - moles: - - 1.7459903 - - 6.568249 - - 0 - - 0 - - 0 - - 0 - - 0 - - 0 - - 0 - - 0 - - 0 - - 0 - proto: ClosetWallEmergencyFilledRandom entities: - uid: 288 @@ -944,6 +1365,10 @@ entities: - 0 - 0 - 0 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 289 components: - type: Transform @@ -967,6 +1392,10 @@ entities: - 0 - 0 - 0 + - type: Godmode + missingComponents: + - Destructible + - Construction - proto: ClosetWallFireFilledRandom entities: - uid: 286 @@ -992,6 +1421,10 @@ entities: - 0 - 0 - 0 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 287 components: - type: Transform @@ -1016,40 +1449,28 @@ entities: - 0 - 0 - 0 + - type: Godmode + missingComponents: + - Destructible + - Construction - proto: ClothingBackpack entities: - - uid: 275 + - uid: 266 components: - type: Transform - pos: 2.5,5.5 + pos: 2.5277145,5.600461 parent: 292 - - type: GroupExamine - group: - - hoverMessage: "" - contextText: verb-examine-group-other - icon: /Textures/Interface/examine-star.png - components: - - Armor - - ClothingSpeedModifier - entries: - - message: >- - It provides the following protection: - - - [color=orange]Explosion[/color] damage [color=white]to contents[/color] reduced by [color=lightblue]10%[/color]. - priority: 0 - component: Armor - title: null - proto: ClothingMaskBreath entities: - - uid: 272 + - uid: 267 components: - type: Transform - pos: 2.5,-3.5 + pos: 2.4086668,-3.4828715 parent: 292 - - uid: 273 + - uid: 274 components: - type: Transform - pos: -3.5,-3.5 + pos: -3.6032372,-3.4947772 parent: 292 - proto: ComputerShuttle entities: @@ -1058,24 +1479,29 @@ entities: - type: Transform pos: -0.5,9.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - proto: CrowbarRed entities: - - uid: 274 + - uid: 293 components: - type: Transform - pos: 0.5,-3.5 + pos: 0.45628688,-3.5066814 parent: 292 - proto: EmergencyOxygenTankFilled entities: - - uid: 270 + - uid: 268 components: - type: Transform - pos: 2.5708976,-3.5851696 + pos: -3.2460945,-3.6614437 parent: 292 - - uid: 271 + - uid: 269 components: - type: Transform - pos: -3.4291024,-3.5851696 + pos: 2.7300956,-3.6138248 parent: 292 - proto: ExtinguisherCabinetFilled entities: @@ -1084,6 +1510,9 @@ entities: - type: Transform pos: -0.5,-4.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible - proto: GasPassiveGate entities: - uid: 184 @@ -1091,6 +1520,11 @@ entities: - type: Transform pos: -0.5,7.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - proto: GasPipeBend entities: - uid: 182 @@ -1099,34 +1533,64 @@ entities: rot: 1.5707963267948966 rad pos: -1.5,8.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 183 components: - type: Transform pos: -0.5,8.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 187 components: - type: Transform rot: 1.5707963267948966 rad pos: -2.5,5.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 188 components: - type: Transform pos: 1.5,5.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 189 components: - type: Transform rot: -1.5707963267948966 rad pos: 1.5,-3.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 190 components: - type: Transform rot: 3.141592653589793 rad pos: -2.5,-3.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - proto: GasPipeFourway entities: - uid: 186 @@ -1134,6 +1598,11 @@ entities: - type: Transform pos: -0.5,5.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - proto: GasPipeStraight entities: - uid: 185 @@ -1141,110 +1610,215 @@ entities: - type: Transform pos: -0.5,6.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 192 components: - type: Transform rot: 1.5707963267948966 rad pos: 0.5,5.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 193 components: - type: Transform rot: 1.5707963267948966 rad pos: -1.5,5.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 194 components: - type: Transform rot: 1.5707963267948966 rad pos: -1.5,-3.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 195 components: - type: Transform rot: 1.5707963267948966 rad pos: 0.5,-3.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 196 components: - type: Transform pos: 1.5,-2.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 197 components: - type: Transform pos: 1.5,-1.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 198 components: - type: Transform pos: 1.5,-0.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 199 components: - type: Transform pos: 1.5,0.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 200 components: - type: Transform pos: 1.5,1.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 201 components: - type: Transform pos: 1.5,2.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 202 components: - type: Transform pos: 1.5,3.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 203 components: - type: Transform pos: 1.5,4.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 204 components: - type: Transform pos: -2.5,-2.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 205 components: - type: Transform pos: -2.5,-1.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 206 components: - type: Transform pos: -2.5,-0.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 207 components: - type: Transform pos: -2.5,0.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 208 components: - type: Transform pos: -2.5,1.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 209 components: - type: Transform pos: -2.5,2.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 210 components: - type: Transform pos: -2.5,3.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 211 components: - type: Transform pos: -2.5,4.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - proto: GasPipeTJunction entities: - uid: 191 @@ -1253,6 +1827,11 @@ entities: rot: 3.141592653589793 rad pos: -0.5,-3.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - proto: GasPort entities: - uid: 181 @@ -1261,6 +1840,11 @@ entities: rot: 3.141592653589793 rad pos: -1.5,7.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - proto: GasVentPump entities: - uid: 212 @@ -1268,12 +1852,22 @@ entities: - type: Transform pos: -0.5,-2.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 213 components: - type: Transform rot: 3.141592653589793 rad pos: -0.5,4.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - proto: GeneratorBasic15kW entities: - uid: 114 @@ -1281,11 +1875,19 @@ entities: - type: Transform pos: -1.5,-5.5 parent: 292 + - type: Godmode + missingComponents: + - Anchorable + - Destructible - uid: 115 components: - type: Transform pos: 0.5,-5.5 parent: 292 + - type: Godmode + missingComponents: + - Anchorable + - Destructible - proto: GeneratorWallmountAPU entities: - uid: 78 @@ -1293,6 +1895,11 @@ entities: - type: Transform pos: 1.5,7.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - proto: GravityGeneratorMini entities: - uid: 291 @@ -1300,6 +1907,11 @@ entities: - type: Transform pos: -2.5,-5.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Anchorable + - Construction - proto: Grille entities: - uid: 44 @@ -1307,116 +1919,231 @@ entities: - type: Transform pos: 3.5,-0.5 parent: 292 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 52 components: - type: Transform pos: 3.5,0.5 parent: 292 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 53 components: - type: Transform pos: 3.5,1.5 parent: 292 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 54 components: - type: Transform pos: 3.5,2.5 parent: 292 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 55 components: - type: Transform pos: -4.5,-0.5 parent: 292 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 56 components: - type: Transform pos: -4.5,0.5 parent: 292 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 57 components: - type: Transform pos: -4.5,1.5 parent: 292 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 58 components: - type: Transform pos: -4.5,2.5 parent: 292 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 59 components: - type: Transform pos: -1.5,-4.5 parent: 292 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 60 components: - type: Transform pos: -2.5,-4.5 parent: 292 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 61 components: - type: Transform pos: 1.5,-4.5 parent: 292 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 62 components: - type: Transform pos: 0.5,-4.5 parent: 292 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 63 components: - type: Transform pos: 0.5,6.5 parent: 292 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 64 components: - type: Transform pos: -1.5,6.5 parent: 292 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 65 components: - type: Transform pos: -2.5,8.5 parent: 292 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 66 components: - type: Transform pos: -2.5,9.5 parent: 292 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 67 components: - type: Transform pos: -1.5,9.5 parent: 292 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 68 components: - type: Transform pos: -1.5,10.5 parent: 292 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 69 components: - type: Transform pos: -0.5,10.5 parent: 292 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 70 components: - type: Transform pos: 0.5,10.5 parent: 292 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 71 components: - type: Transform pos: 0.5,9.5 parent: 292 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 72 components: - type: Transform pos: 1.5,9.5 parent: 292 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 73 components: - type: Transform pos: 1.5,8.5 parent: 292 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - proto: Gyroscope entities: - uid: 168 @@ -1424,6 +2151,11 @@ entities: - type: Transform pos: 1.5,-5.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Anchorable + - Construction - proto: IntercomCommon entities: - uid: 264 @@ -1431,6 +2163,12 @@ entities: - type: Transform pos: -0.5,-1.5 parent: 292 + - type: EncryptionKeyHolder + keysUnlocked: False + - type: Godmode + missingComponents: + - Construction + - Destructible - proto: MaintenanceFluffSpawner entities: - uid: 284 @@ -1438,29 +2176,31 @@ entities: - type: Transform pos: 0.5,3.5 parent: 292 + - type: Godmode - uid: 285 components: - type: Transform pos: -1.5,3.5 parent: 292 + - type: Godmode - proto: MedkitFilled entities: - - uid: 266 + - uid: 276 components: - type: Transform - pos: -0.5,-3.5 + pos: -0.4960943,-3.4828715 parent: 292 - proto: NitrogenTankFilled entities: - - uid: 268 + - uid: 271 components: - type: Transform - pos: -3.5,-3.5 + pos: -3.4365704,-3.590015 parent: 292 - - uid: 269 + - uid: 273 components: - type: Transform - pos: 2.5,-3.5 + pos: 2.563429,-3.566205 parent: 292 - proto: PosterLegitNanotrasenLogo entities: @@ -1469,6 +2209,9 @@ entities: - type: Transform pos: -2.5,6.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible - proto: PottedPlantRandom entities: - uid: 254 @@ -1476,21 +2219,25 @@ entities: - type: Transform pos: 2.5,-1.5 parent: 292 + - type: Godmode - uid: 255 components: - type: Transform pos: 2.5,3.5 parent: 292 + - type: Godmode - uid: 256 components: - type: Transform pos: -3.5,3.5 parent: 292 + - type: Godmode - uid: 257 components: - type: Transform pos: -3.5,-1.5 parent: 292 + - type: Godmode - proto: PowerCellRecharger entities: - uid: 265 @@ -1498,7 +2245,12 @@ entities: - type: Transform pos: 0.5,-3.5 parent: 292 -- proto: Poweredlight + - type: Godmode + missingComponents: + - Anchorable + - Destructible + - Construction +- proto: AlwaysPoweredWallLight entities: - uid: 279 components: @@ -1508,6 +2260,11 @@ entities: parent: 292 - type: ApcPowerReceiver powerLoad: 0 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 280 components: - type: Transform @@ -1516,6 +2273,11 @@ entities: parent: 292 - type: ApcPowerReceiver powerLoad: 0 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 281 components: - type: Transform @@ -1524,6 +2286,11 @@ entities: parent: 292 - type: ApcPowerReceiver powerLoad: 0 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 282 components: - type: Transform @@ -1532,6 +2299,11 @@ entities: parent: 292 - type: ApcPowerReceiver powerLoad: 0 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 283 components: - type: Transform @@ -1540,6 +2312,11 @@ entities: parent: 292 - type: ApcPowerReceiver powerLoad: 0 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - proto: Rack entities: - uid: 262 @@ -1547,11 +2324,21 @@ entities: - type: Transform pos: 2.5,-3.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 263 components: - type: Transform pos: -3.5,-3.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - proto: ShuttleWindow entities: - uid: 28 @@ -1559,116 +2346,231 @@ entities: - type: Transform pos: 3.5,-0.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction + - RCDDeconstructable - uid: 29 components: - type: Transform pos: 3.5,0.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction + - RCDDeconstructable - uid: 30 components: - type: Transform pos: 3.5,1.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction + - RCDDeconstructable - uid: 31 components: - type: Transform pos: 3.5,2.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction + - RCDDeconstructable - uid: 32 components: - type: Transform pos: -4.5,-0.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction + - RCDDeconstructable - uid: 33 components: - type: Transform pos: -4.5,0.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction + - RCDDeconstructable - uid: 34 components: - type: Transform pos: -4.5,1.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction + - RCDDeconstructable - uid: 35 components: - type: Transform pos: -4.5,2.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction + - RCDDeconstructable - uid: 36 components: - type: Transform pos: -1.5,-4.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction + - RCDDeconstructable - uid: 37 components: - type: Transform pos: -2.5,-4.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction + - RCDDeconstructable - uid: 38 components: - type: Transform pos: 0.5,-4.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction + - RCDDeconstructable - uid: 39 components: - type: Transform pos: 1.5,-4.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction + - RCDDeconstructable - uid: 40 components: - type: Transform pos: 0.5,6.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction + - RCDDeconstructable - uid: 41 components: - type: Transform pos: -1.5,6.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction + - RCDDeconstructable - uid: 42 components: - type: Transform pos: -2.5,8.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction + - RCDDeconstructable - uid: 43 components: - type: Transform pos: -1.5,9.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction + - RCDDeconstructable - uid: 45 components: - type: Transform pos: -2.5,9.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction + - RCDDeconstructable - uid: 46 components: - type: Transform pos: -1.5,10.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction + - RCDDeconstructable - uid: 47 components: - type: Transform pos: -0.5,10.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction + - RCDDeconstructable - uid: 48 components: - type: Transform pos: 0.5,10.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction + - RCDDeconstructable - uid: 49 components: - type: Transform pos: 0.5,9.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction + - RCDDeconstructable - uid: 50 components: - type: Transform pos: 1.5,9.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction + - RCDDeconstructable - uid: 51 components: - type: Transform pos: 1.5,8.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction + - RCDDeconstructable - proto: SMESBasic entities: - uid: 76 @@ -1676,6 +2578,11 @@ entities: - type: Transform pos: 0.5,7.5 parent: 292 + - type: Godmode + missingComponents: + - Anchorable + - Destructible + - Construction - proto: SpaceVillainArcadeFilled entities: - uid: 259 @@ -1684,6 +2591,11 @@ entities: rot: 1.5707963267948966 rad pos: 0.5,-1.5 parent: 292 + - type: Godmode + missingComponents: + - Anchorable + - Construction + - Destructible - proto: SubstationWallBasic entities: - uid: 77 @@ -1691,6 +2603,10 @@ entities: - type: Transform pos: 1.5,6.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - proto: TableReinforced entities: - uid: 243 @@ -1698,46 +2614,82 @@ entities: - type: Transform pos: 0.5,-3.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 244 components: - type: Transform pos: -1.5,8.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 245 components: - type: Transform pos: 0.5,8.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 246 components: - type: Transform pos: -0.5,-3.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 247 components: - type: Transform pos: -1.5,-3.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 248 components: - type: Transform pos: 0.5,3.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 249 components: - type: Transform pos: -1.5,3.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 250 components: - type: Transform pos: 2.5,5.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 251 components: - type: Transform pos: -3.5,5.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - proto: Thruster entities: - uid: 169 @@ -1745,58 +2697,103 @@ entities: - type: Transform pos: 2.5,7.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Anchorable + - Construction - uid: 170 components: - type: Transform pos: -3.5,7.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Anchorable + - Construction - uid: 171 components: - type: Transform rot: 3.141592653589793 rad pos: -1.5,-6.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Anchorable + - Construction - uid: 172 components: - type: Transform rot: 3.141592653589793 rad pos: -2.5,-6.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Anchorable + - Construction - uid: 173 components: - type: Transform rot: 3.141592653589793 rad pos: 1.5,-6.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Anchorable + - Construction - uid: 174 components: - type: Transform rot: 3.141592653589793 rad pos: 0.5,-6.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Anchorable + - Construction - uid: 175 components: - type: Transform rot: -1.5707963267948966 rad pos: 2.5,-6.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Anchorable + - Construction - uid: 176 components: - type: Transform rot: 1.5707963267948966 rad pos: -3.5,-6.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Anchorable + - Construction - proto: ToolboxEmergencyFilled entities: - - uid: 267 + - uid: 270 components: - type: Transform - pos: -1.5,-3.5 + pos: -1.4722855,-3.4471583 parent: 292 - - uid: 276 + - uid: 272 components: - type: Transform - pos: -3.5,5.5 + pos: -1.4722855,-3.4471583 + parent: 292 + - uid: 275 + components: + - type: Transform + pos: -3.5079994,5.600461 parent: 292 - proto: VendingMachineClothing entities: @@ -1805,6 +2802,10 @@ entities: - type: Transform pos: 1.5,-3.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Anchorable - proto: WallShuttle entities: - uid: 1 @@ -1812,146 +2813,262 @@ entities: - type: Transform pos: 3.5,-3.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 2 components: - type: Transform pos: 3.5,-1.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 3 components: - type: Transform pos: -4.5,-3.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 4 components: - type: Transform pos: -4.5,-1.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 5 components: - type: Transform pos: -4.5,3.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 6 components: - type: Transform pos: -4.5,5.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 7 components: - type: Transform pos: 3.5,3.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 8 components: - type: Transform pos: 3.5,5.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 9 components: - type: Transform pos: 3.5,6.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 10 components: - type: Transform pos: 2.5,6.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 11 components: - type: Transform pos: -4.5,6.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 12 components: - type: Transform pos: -3.5,6.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 13 components: - type: Transform pos: -2.5,6.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 14 components: - type: Transform pos: -2.5,7.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 15 components: - type: Transform pos: 1.5,6.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 16 components: - type: Transform pos: 1.5,7.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 17 components: - type: Transform pos: 3.5,-4.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 18 components: - type: Transform pos: 2.5,-4.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 19 components: - type: Transform pos: -4.5,-4.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 20 components: - type: Transform pos: -3.5,-4.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 21 components: - type: Transform pos: -0.5,-4.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 22 components: - type: Transform pos: 2.5,-5.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 23 components: - type: Transform pos: 3.5,-5.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 24 components: - type: Transform pos: -3.5,-5.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 25 components: - type: Transform pos: -4.5,-5.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 26 components: - type: Transform pos: -0.5,-6.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 27 components: - type: Transform pos: -0.5,-5.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 74 components: - type: Transform pos: -0.5,-1.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 75 components: - type: Transform pos: -0.5,3.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - proto: WindowReinforcedDirectional entities: - uid: 215 @@ -1960,46 +3077,86 @@ entities: rot: -1.5707963267948966 rad pos: -0.5,-0.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 216 components: - type: Transform rot: -1.5707963267948966 rad pos: -0.5,0.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 217 components: - type: Transform rot: -1.5707963267948966 rad pos: -0.5,1.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 218 components: - type: Transform rot: -1.5707963267948966 rad pos: -0.5,2.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 219 components: - type: Transform rot: 1.5707963267948966 rad pos: -0.5,2.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 220 components: - type: Transform rot: 1.5707963267948966 rad pos: -0.5,1.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 221 components: - type: Transform rot: 1.5707963267948966 rad pos: -0.5,0.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 222 components: - type: Transform rot: 1.5707963267948966 rad pos: -0.5,-0.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible ... diff --git a/Resources/Prototypes/Catalog/Cargo/cargo_vending.yml b/Resources/Prototypes/Catalog/Cargo/cargo_vending.yml index 42bef895b9..a7de28daa7 100644 --- a/Resources/Prototypes/Catalog/Cargo/cargo_vending.yml +++ b/Resources/Prototypes/Catalog/Cargo/cargo_vending.yml @@ -154,7 +154,7 @@ sprite: Objects/Specific/Service/vending_machine_restock.rsi state: base product: CrateVendingMachineRestockSalvageEquipmentFilled - cost: 1000 + cost: 1500 category: cargoproduct-category-name-engineering group: market diff --git a/Resources/Prototypes/Catalog/Fills/Lockers/security.yml b/Resources/Prototypes/Catalog/Fills/Lockers/security.yml index e65f002d8a..d8a079e0bc 100644 --- a/Resources/Prototypes/Catalog/Fills/Lockers/security.yml +++ b/Resources/Prototypes/Catalog/Fills/Lockers/security.yml @@ -10,7 +10,6 @@ - id: ClothingBeltSecurityFilled - id: Flash - id: ClothingEyesGlassesSecurity - - id: ClothingHeadsetAltSecurity - id: ClothingHandsGlovesCombat - id: ClothingShoesBootsJack - id: ClothingOuterCoatWarden @@ -40,7 +39,6 @@ - id: ClothingBeltSecurityFilled - id: Flash - id: ClothingEyesGlassesSecurity - - id: ClothingHeadsetAltSecurity - id: ClothingHandsGlovesCombat - id: ClothingShoesBootsJack - id: ClothingOuterCoatWarden diff --git a/Resources/Prototypes/Catalog/VendingMachines/Inventories/salvage.yml b/Resources/Prototypes/Catalog/VendingMachines/Inventories/salvage.yml index 9e5549e249..7761453327 100644 --- a/Resources/Prototypes/Catalog/VendingMachines/Inventories/salvage.yml +++ b/Resources/Prototypes/Catalog/VendingMachines/Inventories/salvage.yml @@ -3,10 +3,10 @@ startingInventory: Crowbar: 2 Pickaxe: 4 - OreBag: 2 + OreBag: 4 Flare: 4 FlashlightLantern: 2 HandheldGPSBasic: 2 RadioHandheld: 2 - WeaponGrapplingGun: 2 + WeaponGrapplingGun: 4 WeaponProtoKineticAccelerator: 4 diff --git a/Resources/Prototypes/Entities/Mobs/Player/observer.yml b/Resources/Prototypes/Entities/Mobs/Player/observer.yml index 07d2e567d3..891b68c23d 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/observer.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/observer.yml @@ -55,6 +55,7 @@ skipChecks: true - type: Ghost - type: GhostHearing + - type: ShowElectrocutionHUD - type: IntrinsicRadioReceiver - type: ActiveRadio receiveAllChannels: true diff --git a/Resources/Prototypes/Entities/Mobs/Player/silicon.yml b/Resources/Prototypes/Entities/Mobs/Player/silicon.yml index 6064caf754..f366c7a99a 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/silicon.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/silicon.yml @@ -32,6 +32,7 @@ - type: IgnoreUIRange - type: StationAiHeld - type: StationAiOverlay + - type: ShowElectrocutionHUD - type: ActionGrant actions: - ActionJumpToCore diff --git a/Resources/Prototypes/Entities/Objects/Fun/toys.yml b/Resources/Prototypes/Entities/Objects/Fun/toys.yml index d774c4469c..eddf92c5ae 100644 --- a/Resources/Prototypes/Entities/Objects/Fun/toys.yml +++ b/Resources/Prototypes/Entities/Objects/Fun/toys.yml @@ -498,12 +498,22 @@ - type: Sprite sprite: Objects/Fun/sharkplush.rsi state: blue + - type: EmitSoundOnLand + sound: + path: /Audio/Items/Toys/rawr.ogg + - type: EmitSoundOnTrigger + sound: + path: /Audio/Items/Toys/rawr.ogg - type: EmitSoundOnUse sound: path: /Audio/Items/Toys/rawr.ogg - type: EmitSoundOnActivate sound: path: /Audio/Items/Toys/rawr.ogg + - type: MeleeWeapon + wideAnimationRotation: 180 + soundHit: + path: /Audio/Items/Toys/rawr.ogg - type: Item heldPrefix: blue storedRotation: -90 diff --git a/Resources/Prototypes/Entities/Objects/Materials/materials.yml b/Resources/Prototypes/Entities/Objects/Materials/materials.yml index 1151e57cea..887ab83936 100644 --- a/Resources/Prototypes/Entities/Objects/Materials/materials.yml +++ b/Resources/Prototypes/Entities/Objects/Materials/materials.yml @@ -55,6 +55,8 @@ reagents: - ReagentId: Cellulose Quantity: 6 + - type: Item + heldPrefix: cardboard - type: entity parent: MaterialCardboard @@ -136,6 +138,8 @@ - type: Construction graph: WebObjects # not sure if I should either keep this here or just make another prototype. Will keep it here just in case. node: cloth + - type: Item + heldPrefix: cloth - type: entity parent: MaterialCloth @@ -196,6 +200,8 @@ tags: - ClothMade - RawMaterial + - type: Item + heldPrefix: durathread - type: entity parent: MaterialDurathread @@ -335,8 +341,7 @@ sprite: Objects/Materials/materials.rsi state: corgihide - type: Item - sprite: Clothing/Head/Misc/hides.rsi - heldPrefix: corgi + heldPrefix: corgihide - type: Clothing sprite: Clothing/Head/Misc/hides.rsi equippedPrefix: corgi2 @@ -428,6 +433,8 @@ tags: - ClothMade - RawMaterial + - type: Item + heldPrefix: cotton - type: entity parent: MaterialCotton @@ -480,6 +487,8 @@ tags: - ClothMade - RawMaterial + - type: Item + heldPrefix: pyrotton - type: entity parent: MaterialPyrotton @@ -539,6 +548,8 @@ - ReagentId: Honk Quantity: 5 - type: Appearance + - type: Item + heldPrefix: bananium - type: entity parent: MaterialBananium @@ -589,6 +600,9 @@ tags: - ClothMade - RawMaterial + - type: Item + sprite: Objects/Materials/silk.rsi + heldPrefix: silk - type: entity parent: MaterialWebSilk @@ -711,6 +725,8 @@ reagents: - ReagentId: Vitamin Quantity: 3 + - type: Item + heldPrefix: bones - type: entity parent: MaterialBones @@ -765,6 +781,8 @@ - goliath_hide_3 - type: Item size: Large + heldPrefix: goliathhide + sprite: Objects/Materials/hide.rsi shape: - 0,0,2,2 diff --git a/Resources/Prototypes/Entities/Objects/Materials/ore.yml b/Resources/Prototypes/Entities/Objects/Materials/ore.yml index fd46fb40be..9d07aed853 100644 --- a/Resources/Prototypes/Entities/Objects/Materials/ore.yml +++ b/Resources/Prototypes/Entities/Objects/Materials/ore.yml @@ -46,6 +46,8 @@ reagents: - ReagentId: Gold Quantity: 10 + - type: Item + heldPrefix: gold - type: entity parent: GoldOre @@ -77,6 +79,8 @@ reagents: - ReagentId: Carbon Quantity: 20 + - type: Item + heldPrefix: diamond - type: entity parent: DiamondOre @@ -108,6 +112,8 @@ reagents: - ReagentId: Iron Quantity: 10 + - type: Item + heldPrefix: iron - type: entity id: SteelOre1 @@ -144,6 +150,8 @@ reagents: - ReagentId: Plasma Quantity: 10 + - type: Item + heldPrefix: plasma - type: entity parent: PlasmaOre @@ -175,6 +183,8 @@ reagents: - ReagentId: Silver Quantity: 10 + - type: Item + heldPrefix: silver - type: entity parent: SilverOre @@ -206,6 +216,8 @@ reagents: - ReagentId: Silicon Quantity: 10 + - type: Item + heldPrefix: spacequartz - type: entity parent: SpaceQuartz @@ -245,6 +257,8 @@ - ReagentId: Radium Quantity: 2 canReact: false + - type: Item + heldPrefix: uranium - type: entity parent: UraniumOre @@ -285,6 +299,8 @@ Quantity: 2 - ReagentId: Honk Quantity: 5 + - type: Item + heldPrefix: bananium - type: entity parent: BananiumOre @@ -324,6 +340,8 @@ - type: PhysicalComposition materialComposition: Coal: 100 + - type: Item + heldPrefix: coal - type: entity parent: Coal @@ -381,6 +399,8 @@ Quantity: 10 - ReagentId: Iodine Quantity: 5 + - type: Item + heldPrefix: salt - type: entity parent: SaltOre diff --git a/Resources/Prototypes/Entities/Objects/Materials/parts.yml b/Resources/Prototypes/Entities/Objects/Materials/parts.yml index cf2b2f764e..9305d06a00 100644 --- a/Resources/Prototypes/Entities/Objects/Materials/parts.yml +++ b/Resources/Prototypes/Entities/Objects/Materials/parts.yml @@ -50,7 +50,7 @@ #Sunrise-end - type: Item size: Normal -# heldPrefix: rods + heldPrefix: rods - type: Construction graph: MetalRod node: MetalRod diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/projectiles.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/projectiles.yml index c8526e4f0c..5850668142 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/projectiles.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/projectiles.yml @@ -5,7 +5,7 @@ - type: TimedDespawn lifetime: 0.4 - type: Sprite - drawdepth: Effects + drawdepth: BelowMobs layers: - shader: unshaded map: ["enum.EffectLayers.Unshaded"] @@ -315,9 +315,11 @@ - EmitterBolt - type: TimedDespawn lifetime: 3 + # Sunrise-Start - type: Reflective reflective: - Energy + # Sunrise-End - type: entity name: watcher bolt @@ -703,33 +705,6 @@ - type: StaminaDamageOnCollide damage: 80 -# Sunrise-Start -- type: entity - id: BaseBulletGrenade - parent: BaseItem - categories: [ HideSpawnMenu ] - components: - - type: Projectile - damage: - types: - Blunt: 5 - deleteOnCollide: false - - type: StartTimerOnShoot - - type: OnUseTimerTrigger - delay: 2 - - type: Fixtures - fixtures: - fix1: - shape: - !type:PhysShapeAabb - bounds: "-0.25,-0.25,0.25,0.25" - density: 50 - mask: - - ItemMask - restitution: 0.05 - friction: 0.5 - # Sunrise-End - - type: entity id: BulletGrenadeBlast name: blast grenade @@ -1083,6 +1058,7 @@ proto: BulletDisablerSmg count: 3 #bit stronger than a disabler if you hit your shots you goober, still not a 2 hit stun though spread: 9 + # SUNRISE - type: entity @@ -1211,7 +1187,6 @@ soundHit: collection: WeakHit -# Sunrise-AEG - type: entity name: energy bolt id: BulletEnergyGunLaser @@ -1252,7 +1227,6 @@ soundHit: collection: WeakHit -# Sunrise-NT - type: entity id: BulletRocketNT name: rocket @@ -1274,3 +1248,28 @@ radius: 3.5 color: orange energy: 0.5 + +- type: entity + id: BaseBulletGrenade + parent: BaseItem + categories: [ HideSpawnMenu ] + components: + - type: Projectile + damage: + types: + Blunt: 5 + deleteOnCollide: false + - type: StartTimerOnShoot + - type: OnUseTimerTrigger + delay: 2 + - type: Fixtures + fixtures: + fix1: + shape: + !type:PhysShapeAabb + bounds: "-0.25,-0.25,0.25,0.25" + density: 50 + mask: + - ItemMask + restitution: 0.05 + friction: 0.5 diff --git a/Resources/Prototypes/Entities/Structures/Doors/Airlocks/base_structureairlocks.yml b/Resources/Prototypes/Entities/Structures/Doors/Airlocks/base_structureairlocks.yml index f2b14e322f..92b14f8655 100644 --- a/Resources/Prototypes/Entities/Structures/Doors/Airlocks/base_structureairlocks.yml +++ b/Resources/Prototypes/Entities/Structures/Doors/Airlocks/base_structureairlocks.yml @@ -30,6 +30,11 @@ shader: unshaded - state: panel_open map: ["enum.WiresVisualLayers.MaintenancePanel"] + - state: electrified + sprite: Interface/Misc/ai_hud.rsi + shader: unshaded + visible: false + map: ["enum.ElectrifiedLayers.HUD"] - type: AnimationPlayer - type: Physics - type: Fixtures @@ -73,6 +78,7 @@ - type: DoorBolt - type: Appearance - type: WiresVisuals + - type: ElectrocutionHUDVisuals - type: ApcPowerReceiver powerLoad: 20 - type: ExtensionCableReceiver diff --git a/Resources/Prototypes/Entities/Structures/Doors/Airlocks/shuttle.yml b/Resources/Prototypes/Entities/Structures/Doors/Airlocks/shuttle.yml index e6905d61cc..3752821e46 100644 --- a/Resources/Prototypes/Entities/Structures/Doors/Airlocks/shuttle.yml +++ b/Resources/Prototypes/Entities/Structures/Doors/Airlocks/shuttle.yml @@ -31,23 +31,6 @@ - type: Sprite sprite: Structures/Doors/Airlocks/Standard/shuttle.rsi snapCardinals: false - layers: - - state: closed - map: ["enum.DoorVisualLayers.Base"] - - state: closed_unlit - shader: unshaded - map: ["enum.DoorVisualLayers.BaseUnlit"] - visible: false - - state: welded - map: ["enum.WeldableLayers.BaseWelded"] - - state: bolted_unlit - shader: unshaded - map: ["enum.DoorVisualLayers.BaseBolted"] - - state: emergency_unlit - shader: unshaded - map: ["enum.DoorVisualLayers.BaseEmergencyAccess"] - - state: panel_open - map: ["enum.WiresVisualLayers.MaintenancePanel"] - type: Wires layoutId: Docking - type: Door @@ -113,6 +96,7 @@ - type: Sprite sprite: Structures/Doors/Airlocks/Glass/shuttle.rsi state: closed + snapCardinals: false - type: Construction graph: AirlockShuttle node: assembly diff --git a/Resources/Prototypes/Entities/Structures/Piping/Atmospherics/gas_pipe_sensor.yml b/Resources/Prototypes/Entities/Structures/Piping/Atmospherics/gas_pipe_sensor.yml new file mode 100644 index 0000000000..08015abe7d --- /dev/null +++ b/Resources/Prototypes/Entities/Structures/Piping/Atmospherics/gas_pipe_sensor.yml @@ -0,0 +1,84 @@ +- type: entity + parent: [AirSensorBase, GasPipeBase] + id: GasPipeSensor + name: gas pipe sensor + description: Reports on the status of the gas in the attached pipe network. + placement: + mode: SnapgridCenter + components: + - type: Sprite + sprite: Structures/Piping/Atmospherics/gas_pipe_sensor.rsi + drawdepth: BelowFloor + layers: + - sprite: Structures/Piping/Atmospherics/pipe.rsi + map: [ "enum.PipeVisualLayers.Pipe" ] + state: pipeStraight + - map: ["base"] + state: base + - map: [ "enum.PowerDeviceVisualLayers.Powered" ] + state: lights + shader: unshaded + - type: Appearance + - type: GenericVisualizer + visuals: + enum.PowerDeviceVisuals.Powered: + enum.PowerDeviceVisualLayers.Powered: + False: { state: blank } + True: { state: lights } + - type: AtmosMonitor + monitorsPipeNet: true + - type: ApcPowerReceiver + - type: ExtensionCableReceiver + - type: Construction + graph: GasPipeSensor + node: sensor + - type: NodeContainer + nodes: + monitored: + !type:PipeNode + nodeGroupID: Pipe + pipeDirection: Longitudinal + - type: Tag + tags: + - AirSensor + - Unstackable + +- type: entity + parent: GasPipeSensor + id: GasPipeSensorDistribution + suffix: Distribution + components: + - type: Label + currentLabel: gas-pipe-sensor-distribution-loop + +- type: entity + parent: GasPipeSensor + id: GasPipeSensorWaste + suffix: Waste + components: + - type: Label + currentLabel: gas-pipe-sensor-waste-loop + +- type: entity + parent: GasPipeSensor + id: GasPipeSensorMixedAir + suffix: Mixed air + components: + - type: Label + currentLabel: gas-pipe-sensor-mixed-air + +- type: entity + parent: GasPipeSensor + id: GasPipeSensorTEGHot + suffix: TEG hot + components: + - type: Label + currentLabel: gas-pipe-sensor-teg-hot-loop + +- type: entity + parent: GasPipeSensor + id: GasPipeSensorTEGCold + suffix: TEG cold + components: + - type: Label + currentLabel: gas-pipe-sensor-teg-cold-loop \ No newline at end of file diff --git a/Resources/Prototypes/Entities/Structures/Power/cable_terminal.yml b/Resources/Prototypes/Entities/Structures/Power/cable_terminal.yml index 8c7ee9e219..cc6abce25e 100644 --- a/Resources/Prototypes/Entities/Structures/Power/cable_terminal.yml +++ b/Resources/Prototypes/Entities/Structures/Power/cable_terminal.yml @@ -45,3 +45,11 @@ powerMV: !type:CableTerminalNode nodeGroupID: MVPower + +- type: entity + id: CableTerminalUncuttable + parent: CableTerminal + suffix: uncuttable + components: + - type: Cable + cuttingQuality: null \ No newline at end of file diff --git a/Resources/Prototypes/Entities/Structures/Power/cables.yml b/Resources/Prototypes/Entities/Structures/Power/cables.yml index ac855a5460..f1ae038bc1 100644 --- a/Resources/Prototypes/Entities/Structures/Power/cables.yml +++ b/Resources/Prototypes/Entities/Structures/Power/cables.yml @@ -98,6 +98,14 @@ sound: path: /Audio/Ambience/Objects/emf_buzz.ogg +- type: entity + id: CableHVUncuttable + parent: CableHV + suffix: uncuttable + components: + - type: Cable + cuttingQuality: null + - type: entity parent: CableBase id: CableMV @@ -142,6 +150,14 @@ - type: CableVisualizer statePrefix: mvcable_ +- type: entity + id: CableMVUncuttable + parent: CableMV + suffix: uncuttable + components: + - type: Cable + cuttingQuality: null + - type: entity parent: CableBase id: CableApcExtension @@ -188,3 +204,11 @@ acts: [ "Destruction" ] - type: CableVisualizer statePrefix: lvcable_ + +- type: entity + id: CableApcExtensionUncuttable + parent: CableApcExtension + suffix: uncuttable + components: + - type: Cable + cuttingQuality: null diff --git a/Resources/Prototypes/Entities/Structures/Walls/fence_metal.yml b/Resources/Prototypes/Entities/Structures/Walls/fence_metal.yml index 2d0c55af5a..b5fa7d9190 100644 --- a/Resources/Prototypes/Entities/Structures/Walls/fence_metal.yml +++ b/Resources/Prototypes/Entities/Structures/Walls/fence_metal.yml @@ -70,8 +70,8 @@ - type: Appearance - type: GenericVisualizer visuals: - enum.ElectrifiedVisuals.IsPowered: - enum.ElectrifiedLayers.Powered: + enum.ElectrifiedVisuals.ShowSparks: + enum.ElectrifiedLayers.Sparks: True: { visible: True } False: { visible: False } - type: AnimationPlayer @@ -91,7 +91,7 @@ - state: straight_broken - state: electrified sprite: Effects/electricity.rsi - map: ["enum.ElectrifiedLayers.Powered"] + map: ["enum.ElectrifiedLayers.Sparks"] shader: unshaded visible: false - type: Physics @@ -151,7 +151,7 @@ - state: straight - state: electrified sprite: Effects/electricity.rsi - map: ["enum.ElectrifiedLayers.Powered"] + map: ["enum.ElectrifiedLayers.Sparks"] shader: unshaded visible: false - type: Fixtures @@ -209,7 +209,7 @@ - state: corner - state: electrified sprite: Effects/electricity.rsi - map: ["enum.ElectrifiedLayers.Powered"] + map: ["enum.ElectrifiedLayers.Sparks"] shader: unshaded visible: false - type: Fixtures @@ -256,7 +256,7 @@ - state: end - state: electrified sprite: Effects/electricity.rsi - map: ["enum.ElectrifiedLayers.Powered"] + map: ["enum.ElectrifiedLayers.Sparks"] shader: unshaded visible: false - type: Fixtures @@ -292,7 +292,7 @@ map: ["enum.DoorVisualLayers.Base"] - state: electrified sprite: Effects/electricity.rsi - map: [ "enum.ElectrifiedLayers.Powered" ] + map: [ "enum.ElectrifiedLayers.Sparks" ] shader: unshaded visible: false - type: Fixtures diff --git a/Resources/Prototypes/Entities/Structures/Walls/grille.yml b/Resources/Prototypes/Entities/Structures/Walls/grille.yml index 2b65528d22..3433ffc366 100644 --- a/Resources/Prototypes/Entities/Structures/Walls/grille.yml +++ b/Resources/Prototypes/Entities/Structures/Walls/grille.yml @@ -21,7 +21,7 @@ - state: grille - state: electrified sprite: Effects/electricity.rsi - map: ["enum.ElectrifiedLayers.Powered"] + map: ["enum.ElectrifiedLayers.Sparks"] shader: unshaded visible: false - type: Icon @@ -82,8 +82,8 @@ - type: Appearance - type: GenericVisualizer visuals: - enum.ElectrifiedVisuals.IsPowered: - enum.ElectrifiedLayers.Powered: + enum.ElectrifiedVisuals.ShowSparks: + enum.ElectrifiedLayers.Sparks: True: { visible: True } False: { visible: False } - type: AnimationPlayer @@ -176,7 +176,7 @@ - state: grille_diagonal - state: electrified_diagonal sprite: Effects/electricity.rsi - map: ["enum.ElectrifiedLayers.Powered"] + map: ["enum.ElectrifiedLayers.Sparks"] shader: unshaded visible: false - type: Icon @@ -211,7 +211,7 @@ - state: ratvargrille_diagonal - state: electrified_diagonal sprite: Effects/electricity.rsi - map: ["enum.ElectrifiedLayers.Powered"] + map: ["enum.ElectrifiedLayers.Sparks"] shader: unshaded visible: false - type: Icon diff --git a/Resources/Prototypes/GameRules/events.yml b/Resources/Prototypes/GameRules/events.yml index 0eecf4e3a8..03cde44e52 100644 --- a/Resources/Prototypes/GameRules/events.yml +++ b/Resources/Prototypes/GameRules/events.yml @@ -10,6 +10,7 @@ - id: ClericalError - id: CockroachMigration - id: GasLeak + - id: GreytideVirus - id: IonStorm # its calm like 90% of the time smh - id: KudzuGrowth - id: MassHallucinations @@ -544,3 +545,24 @@ maxOccurrences: 1 # this event has diminishing returns on interesting-ness, so we cap it weight: 5 - type: MobReplacementRule + +- type: entity + id: GreytideVirus + parent: BaseStationEventShortDelay + components: + - type: StationEvent + startAudio: + path: /Audio/Announcements/attention.ogg + weight: 5 + minimumPlayers: 25 + reoccurrenceDelay: 20 + - type: GreytideVirusRule + accessGroups: + - Cargo + - Command + - Engineering + - Research + - Security + - Service + blacklist: + - External # don't space everything diff --git a/Resources/Prototypes/Recipes/Construction/Graphs/utilities/gas_pipe_sensor.yml b/Resources/Prototypes/Recipes/Construction/Graphs/utilities/gas_pipe_sensor.yml new file mode 100644 index 0000000000..bda6d036e9 --- /dev/null +++ b/Resources/Prototypes/Recipes/Construction/Graphs/utilities/gas_pipe_sensor.yml @@ -0,0 +1,29 @@ +- type: constructionGraph + id: GasPipeSensor + start: start + graph: + - node: start + edges: + - to: sensor + steps: + - material: Steel + amount: 2 + doAfter: 1 + + - node: sensor + entity: GasPipeSensor + actions: + - !type:SetAnchor + edges: + - to: start + completed: + - !type:SpawnPrototype + prototype: SheetSteel1 + amount: 2 + - !type:DeleteEntity + conditions: + - !type:EntityAnchored + anchored: false + steps: + - tool: Welding + doAfter: 1 \ No newline at end of file diff --git a/Resources/Prototypes/Recipes/Construction/utilities.yml b/Resources/Prototypes/Recipes/Construction/utilities.yml index 5dc0168fd3..2dec0e4a7d 100644 --- a/Resources/Prototypes/Recipes/Construction/utilities.yml +++ b/Resources/Prototypes/Recipes/Construction/utilities.yml @@ -366,6 +366,21 @@ objectType: Structure canRotate: true +- type: construction + name: gas pipe sensor + id: GasPipeSensor + graph: GasPipeSensor + startNode: start + targetNode: sensor + category: construction-category-structures + description: Reports on the status of the gas within the attached pipe network. + icon: + sprite: Structures/Piping/Atmospherics/gas_pipe_sensor.rsi + state: icon + placementMode: SnapgridCenter + objectType: Structure + canRotate: true + # ATMOS PIPES - type: construction name: gas pipe half diff --git a/Resources/Textures/Interface/Misc/ai_hud.rsi/apc_hacked.png b/Resources/Textures/Interface/Misc/ai_hud.rsi/apc_hacked.png new file mode 100644 index 0000000000..72e111edac Binary files /dev/null and b/Resources/Textures/Interface/Misc/ai_hud.rsi/apc_hacked.png differ diff --git a/Resources/Textures/Interface/Misc/ai_hud.rsi/electrified.png b/Resources/Textures/Interface/Misc/ai_hud.rsi/electrified.png new file mode 100644 index 0000000000..046a307d09 Binary files /dev/null and b/Resources/Textures/Interface/Misc/ai_hud.rsi/electrified.png differ diff --git a/Resources/Textures/Interface/Misc/ai_hud.rsi/meta.json b/Resources/Textures/Interface/Misc/ai_hud.rsi/meta.json new file mode 100644 index 0000000000..7f1e67ac4d --- /dev/null +++ b/Resources/Textures/Interface/Misc/ai_hud.rsi/meta.json @@ -0,0 +1,37 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "taken from tgstation at commit https://github.com/tgstation/tgstation/commit/d170a410d40eec4fc19fe5eb8d561d58a0902082", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "electrified", + "delays": [ + [ + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2 + ] + ] + }, + { + "name": "apc_hacked", + "delays": [ + [ + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2 + ] + ] + } + ] +} \ No newline at end of file diff --git a/Resources/Textures/Objects/Materials/hide.rsi/goliathhide-inhand-left.png b/Resources/Textures/Objects/Materials/hide.rsi/goliathhide-inhand-left.png new file mode 100644 index 0000000000..b9a381ea13 Binary files /dev/null and b/Resources/Textures/Objects/Materials/hide.rsi/goliathhide-inhand-left.png differ diff --git a/Resources/Textures/Objects/Materials/hide.rsi/goliathhide-inhand-right.png b/Resources/Textures/Objects/Materials/hide.rsi/goliathhide-inhand-right.png new file mode 100644 index 0000000000..6d3822309c Binary files /dev/null and b/Resources/Textures/Objects/Materials/hide.rsi/goliathhide-inhand-right.png differ diff --git a/Resources/Textures/Objects/Materials/hide.rsi/meta.json b/Resources/Textures/Objects/Materials/hide.rsi/meta.json index 0ec2b25480..9235e8e2e9 100644 --- a/Resources/Textures/Objects/Materials/hide.rsi/meta.json +++ b/Resources/Textures/Objects/Materials/hide.rsi/meta.json @@ -1,7 +1,7 @@ { "version": 1, "license": "CC-BY-SA-3.0", - "copyright": "Taken from Paradise at https://github.com/ParadiseSS13/Paradise/blob/88d236d5c91e9a57e103957555c2e9a8c63b68fa/icons/obj/stacks/organic.dmi", + "copyright": "Taken from Paradise at https://github.com/ParadiseSS13/Paradise/blob/88d236d5c91e9a57e103957555c2e9a8c63b68fa/icons/obj/stacks/organic.dmi. Inhands by mubururu_ (github).", "size": { "x": 32, "y": 32 @@ -10,6 +10,14 @@ { "name": "goliath_hide" }, + { + "name": "goliathhide-inhand-left", + "directions": 4 + }, + { + "name": "goliathhide-inhand-right", + "directions": 4 + }, { "name": "goliath_hide_2" }, @@ -17,4 +25,4 @@ "name": "goliath_hide_3" } ] -} \ No newline at end of file +} diff --git a/Resources/Textures/Objects/Materials/materials.rsi/bananium-inhand-left.png b/Resources/Textures/Objects/Materials/materials.rsi/bananium-inhand-left.png new file mode 100644 index 0000000000..b936e0fd78 Binary files /dev/null and b/Resources/Textures/Objects/Materials/materials.rsi/bananium-inhand-left.png differ diff --git a/Resources/Textures/Objects/Materials/materials.rsi/bananium-inhand-right.png b/Resources/Textures/Objects/Materials/materials.rsi/bananium-inhand-right.png new file mode 100644 index 0000000000..e352e25fc9 Binary files /dev/null and b/Resources/Textures/Objects/Materials/materials.rsi/bananium-inhand-right.png differ diff --git a/Resources/Textures/Objects/Materials/materials.rsi/bones-inhand-left.png b/Resources/Textures/Objects/Materials/materials.rsi/bones-inhand-left.png new file mode 100644 index 0000000000..07a339dc36 Binary files /dev/null and b/Resources/Textures/Objects/Materials/materials.rsi/bones-inhand-left.png differ diff --git a/Resources/Textures/Objects/Materials/materials.rsi/bones-inhand-right.png b/Resources/Textures/Objects/Materials/materials.rsi/bones-inhand-right.png new file mode 100644 index 0000000000..5eb64901c0 Binary files /dev/null and b/Resources/Textures/Objects/Materials/materials.rsi/bones-inhand-right.png differ diff --git a/Resources/Textures/Objects/Materials/materials.rsi/cardboard-inhand-left.png b/Resources/Textures/Objects/Materials/materials.rsi/cardboard-inhand-left.png new file mode 100644 index 0000000000..fd69f67e5f Binary files /dev/null and b/Resources/Textures/Objects/Materials/materials.rsi/cardboard-inhand-left.png differ diff --git a/Resources/Textures/Objects/Materials/materials.rsi/cardboard-inhand-right.png b/Resources/Textures/Objects/Materials/materials.rsi/cardboard-inhand-right.png new file mode 100644 index 0000000000..58e1ddc53d Binary files /dev/null and b/Resources/Textures/Objects/Materials/materials.rsi/cardboard-inhand-right.png differ diff --git a/Resources/Textures/Objects/Materials/materials.rsi/cloth-inhand-left.png b/Resources/Textures/Objects/Materials/materials.rsi/cloth-inhand-left.png new file mode 100644 index 0000000000..22b176f3d3 Binary files /dev/null and b/Resources/Textures/Objects/Materials/materials.rsi/cloth-inhand-left.png differ diff --git a/Resources/Textures/Objects/Materials/materials.rsi/cloth-inhand-right.png b/Resources/Textures/Objects/Materials/materials.rsi/cloth-inhand-right.png new file mode 100644 index 0000000000..15c2d61150 Binary files /dev/null and b/Resources/Textures/Objects/Materials/materials.rsi/cloth-inhand-right.png differ diff --git a/Resources/Textures/Objects/Materials/materials.rsi/corgihide-inhand-left.png b/Resources/Textures/Objects/Materials/materials.rsi/corgihide-inhand-left.png new file mode 100644 index 0000000000..28d69ddcd7 Binary files /dev/null and b/Resources/Textures/Objects/Materials/materials.rsi/corgihide-inhand-left.png differ diff --git a/Resources/Textures/Objects/Materials/materials.rsi/corgihide-inhand-right.png b/Resources/Textures/Objects/Materials/materials.rsi/corgihide-inhand-right.png new file mode 100644 index 0000000000..a75f4f96e6 Binary files /dev/null and b/Resources/Textures/Objects/Materials/materials.rsi/corgihide-inhand-right.png differ diff --git a/Resources/Textures/Objects/Materials/materials.rsi/cotton-inhand-left.png b/Resources/Textures/Objects/Materials/materials.rsi/cotton-inhand-left.png new file mode 100644 index 0000000000..ec9184783f Binary files /dev/null and b/Resources/Textures/Objects/Materials/materials.rsi/cotton-inhand-left.png differ diff --git a/Resources/Textures/Objects/Materials/materials.rsi/cotton-inhand-right.png b/Resources/Textures/Objects/Materials/materials.rsi/cotton-inhand-right.png new file mode 100644 index 0000000000..adb73f4284 Binary files /dev/null and b/Resources/Textures/Objects/Materials/materials.rsi/cotton-inhand-right.png differ diff --git a/Resources/Textures/Objects/Materials/materials.rsi/durathread-inhand-left.png b/Resources/Textures/Objects/Materials/materials.rsi/durathread-inhand-left.png new file mode 100644 index 0000000000..139c2a573e Binary files /dev/null and b/Resources/Textures/Objects/Materials/materials.rsi/durathread-inhand-left.png differ diff --git a/Resources/Textures/Objects/Materials/materials.rsi/durathread-inhand-right.png b/Resources/Textures/Objects/Materials/materials.rsi/durathread-inhand-right.png new file mode 100644 index 0000000000..4572ed11d5 Binary files /dev/null and b/Resources/Textures/Objects/Materials/materials.rsi/durathread-inhand-right.png differ diff --git a/Resources/Textures/Objects/Materials/materials.rsi/meta.json b/Resources/Textures/Objects/Materials/materials.rsi/meta.json index 3ae12dc14c..9fbad41e48 100644 --- a/Resources/Textures/Objects/Materials/materials.rsi/meta.json +++ b/Resources/Textures/Objects/Materials/materials.rsi/meta.json @@ -1,7 +1,7 @@ { "version": 1, "license": "CC-BY-SA-3.0", - "copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/c6e3401f2e7e1e55c57060cdf956a98ef1fefc24 , bear pelt remade by Alekshhh, wood sprite modified by MisterMecky, wood_2 and wood_3 made by MisterMecky based on wood sprite, cardboard sprites made by MisterMecky, bananium, bananium_1 and peel made by brainfood1183 (github) for ss14. Pyrotton sprites are drawn by Ubaser, using the cotton material sprites as a base.", + "copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/c6e3401f2e7e1e55c57060cdf956a98ef1fefc24 , bear pelt remade by Alekshhh, wood sprite modified by MisterMecky, wood_2 and wood_3 made by MisterMecky based on wood sprite, cardboard sprites made by MisterMecky, bananium, bananium_1 and peel made by brainfood1183 (github) for ss14. Pyrotton sprites are drawn by Ubaser, using the cotton material sprites as a base. Bananium, cardboard, corgihide, cloth, cotton, pyrotton, bones and durathread inhands by mubururu_ (github).", "size": { "x": 32, "y": 32 @@ -16,6 +16,14 @@ { "name": "bananium" }, + { + "name": "bananium-inhand-left", + "directions": 4 + }, + { + "name": "bananium-inhand-right", + "directions": 4 + }, { "name": "bananium_1" }, @@ -36,6 +44,14 @@ { "name": "cardboard" }, + { + "name": "cardboard-inhand-left", + "directions": 4 + }, + { + "name": "cardboard-inhand-right", + "directions": 4 + }, { "name": "cardboard_2" }, @@ -48,6 +64,14 @@ { "name": "cloth" }, + { + "name": "cloth-inhand-left", + "directions": 4 + }, + { + "name": "cloth-inhand-right", + "directions": 4 + }, { "name": "cloth_2" }, @@ -57,9 +81,25 @@ { "name": "corgihide" }, + { + "name": "corgihide-inhand-left", + "directions": 4 + }, + { + "name": "corgihide-inhand-right", + "directions": 4 + }, { "name": "cotton" }, + { + "name": "cotton-inhand-left", + "directions": 4 + }, + { + "name": "cotton-inhand-right", + "directions": 4 + }, { "name": "cotton_2" }, @@ -69,6 +109,14 @@ { "name": "pyrotton" }, + { + "name": "pyrotton-inhand-left", + "directions": 4 + }, + { + "name": "pyrotton-inhand-right", + "directions": 4 + }, { "name": "pyrotton_2" }, @@ -95,6 +143,14 @@ { "name": "durathread" }, + { + "name": "durathread-inhand-left", + "directions": 4 + }, + { + "name": "durathread-inhand-right", + "directions": 4 + }, { "name": "durathread_2" }, @@ -160,6 +216,14 @@ { "name": "bones" }, + { + "name": "bones-inhand-left", + "directions": 4 + }, + { + "name": "bones-inhand-right", + "directions": 4 + }, { "name": "bones_2" }, diff --git a/Resources/Textures/Objects/Materials/materials.rsi/pyrotton-inhand-left.png b/Resources/Textures/Objects/Materials/materials.rsi/pyrotton-inhand-left.png new file mode 100644 index 0000000000..e47685d17c Binary files /dev/null and b/Resources/Textures/Objects/Materials/materials.rsi/pyrotton-inhand-left.png differ diff --git a/Resources/Textures/Objects/Materials/materials.rsi/pyrotton-inhand-right.png b/Resources/Textures/Objects/Materials/materials.rsi/pyrotton-inhand-right.png new file mode 100644 index 0000000000..3225dc0898 Binary files /dev/null and b/Resources/Textures/Objects/Materials/materials.rsi/pyrotton-inhand-right.png differ diff --git a/Resources/Textures/Objects/Materials/ore.rsi/bananium-inhand-left.png b/Resources/Textures/Objects/Materials/ore.rsi/bananium-inhand-left.png new file mode 100644 index 0000000000..01b00bc68f Binary files /dev/null and b/Resources/Textures/Objects/Materials/ore.rsi/bananium-inhand-left.png differ diff --git a/Resources/Textures/Objects/Materials/ore.rsi/bananium-inhand-right.png b/Resources/Textures/Objects/Materials/ore.rsi/bananium-inhand-right.png new file mode 100644 index 0000000000..8c7fddffbd Binary files /dev/null and b/Resources/Textures/Objects/Materials/ore.rsi/bananium-inhand-right.png differ diff --git a/Resources/Textures/Objects/Materials/ore.rsi/coal-inhand-left.png b/Resources/Textures/Objects/Materials/ore.rsi/coal-inhand-left.png new file mode 100644 index 0000000000..094a473d89 Binary files /dev/null and b/Resources/Textures/Objects/Materials/ore.rsi/coal-inhand-left.png differ diff --git a/Resources/Textures/Objects/Materials/ore.rsi/coal-inhand-right.png b/Resources/Textures/Objects/Materials/ore.rsi/coal-inhand-right.png new file mode 100644 index 0000000000..a8286cdebe Binary files /dev/null and b/Resources/Textures/Objects/Materials/ore.rsi/coal-inhand-right.png differ diff --git a/Resources/Textures/Objects/Materials/ore.rsi/diamond-inhand-left.png b/Resources/Textures/Objects/Materials/ore.rsi/diamond-inhand-left.png new file mode 100644 index 0000000000..837741af43 Binary files /dev/null and b/Resources/Textures/Objects/Materials/ore.rsi/diamond-inhand-left.png differ diff --git a/Resources/Textures/Objects/Materials/ore.rsi/diamond-inhand-right.png b/Resources/Textures/Objects/Materials/ore.rsi/diamond-inhand-right.png new file mode 100644 index 0000000000..0f97e2c9c9 Binary files /dev/null and b/Resources/Textures/Objects/Materials/ore.rsi/diamond-inhand-right.png differ diff --git a/Resources/Textures/Objects/Materials/ore.rsi/gold-inhand-left.png b/Resources/Textures/Objects/Materials/ore.rsi/gold-inhand-left.png new file mode 100644 index 0000000000..62255bf46b Binary files /dev/null and b/Resources/Textures/Objects/Materials/ore.rsi/gold-inhand-left.png differ diff --git a/Resources/Textures/Objects/Materials/ore.rsi/gold-inhand-right.png b/Resources/Textures/Objects/Materials/ore.rsi/gold-inhand-right.png new file mode 100644 index 0000000000..50892832e0 Binary files /dev/null and b/Resources/Textures/Objects/Materials/ore.rsi/gold-inhand-right.png differ diff --git a/Resources/Textures/Objects/Materials/ore.rsi/iron-inhand-left.png b/Resources/Textures/Objects/Materials/ore.rsi/iron-inhand-left.png new file mode 100644 index 0000000000..7d2f6abd57 Binary files /dev/null and b/Resources/Textures/Objects/Materials/ore.rsi/iron-inhand-left.png differ diff --git a/Resources/Textures/Objects/Materials/ore.rsi/iron-inhand-right.png b/Resources/Textures/Objects/Materials/ore.rsi/iron-inhand-right.png new file mode 100644 index 0000000000..f616f48f95 Binary files /dev/null and b/Resources/Textures/Objects/Materials/ore.rsi/iron-inhand-right.png differ diff --git a/Resources/Textures/Objects/Materials/ore.rsi/meta.json b/Resources/Textures/Objects/Materials/ore.rsi/meta.json index 8f1b4533f2..bf4d6e7745 100644 --- a/Resources/Textures/Objects/Materials/ore.rsi/meta.json +++ b/Resources/Textures/Objects/Materials/ore.rsi/meta.json @@ -1,7 +1,7 @@ { "version": 1, "license": "CC-BY-NC-SA-3.0", - "copyright": "silver, plasma taken from https://github.com/vgstation-coders/vgstation13 at commit f2ef221849675915a78fd92fe622c32ab740e085, spacequartz taken from https://github.com/goonstation/goonstation at commit b51daf824df46a3a1426475f982c09479818e522 and reshaded by Alekshhh, bananium; uranium; iron; gold; coal by Alekshhh, diamond at commit https://github.com/tgstation/tgstation/pull/78524, edited by TheShuEd", + "copyright": "silver, plasma taken from https://github.com/vgstation-coders/vgstation13 at commit f2ef221849675915a78fd92fe622c32ab740e085, spacequartz taken from https://github.com/goonstation/goonstation at commit b51daf824df46a3a1426475f982c09479818e522 and reshaded by Alekshhh, bananium; uranium; iron; gold; coal by Alekshhh, diamond at commit https://github.com/tgstation/tgstation/pull/78524, edited by TheShuEd. Inhands by mubururu_ (github).", "size": { "x": 32, "y": 32 @@ -10,32 +10,112 @@ { "name": "bananium" }, + { + "name": "bananium-inhand-left", + "directions": 4 + }, + { + "name": "bananium-inhand-right", + "directions": 4 + }, { "name": "gold" }, + { + "name": "gold-inhand-left", + "directions": 4 + }, + { + "name": "gold-inhand-right", + "directions": 4 + }, { "name": "iron" }, + { + "name": "iron-inhand-left", + "directions": 4 + }, + { + "name": "iron-inhand-right", + "directions": 4 + }, { "name": "uranium" }, + { + "name": "uranium-inhand-left", + "directions": 4 + }, + { + "name": "uranium-inhand-right", + "directions": 4 + }, { "name": "plasma" }, + { + "name": "plasma-inhand-left", + "directions": 4 + }, + { + "name": "plasma-inhand-right", + "directions": 4 + }, { "name": "spacequartz" }, + { + "name": "spacequartz-inhand-left", + "directions": 4 + }, + { + "name": "spacequartz-inhand-right", + "directions": 4 + }, { "name": "silver" }, + { + "name": "silver-inhand-left", + "directions": 4 + }, + { + "name": "silver-inhand-right", + "directions": 4 + }, { "name": "coal" }, + { + "name": "coal-inhand-left", + "directions": 4 + }, + { + "name": "coal-inhand-right", + "directions": 4 + }, { "name": "salt" }, + { + "name": "salt-inhand-left", + "directions": 4 + }, + { + "name": "salt-inhand-right", + "directions": 4 + }, { "name": "diamond" + }, + { + "name": "diamond-inhand-left", + "directions": 4 + }, + { + "name": "diamond-inhand-right", + "directions": 4 } ] } diff --git a/Resources/Textures/Objects/Materials/ore.rsi/plasma-inhand-left.png b/Resources/Textures/Objects/Materials/ore.rsi/plasma-inhand-left.png new file mode 100644 index 0000000000..6c41a2c149 Binary files /dev/null and b/Resources/Textures/Objects/Materials/ore.rsi/plasma-inhand-left.png differ diff --git a/Resources/Textures/Objects/Materials/ore.rsi/plasma-inhand-right.png b/Resources/Textures/Objects/Materials/ore.rsi/plasma-inhand-right.png new file mode 100644 index 0000000000..00e4f11408 Binary files /dev/null and b/Resources/Textures/Objects/Materials/ore.rsi/plasma-inhand-right.png differ diff --git a/Resources/Textures/Objects/Materials/ore.rsi/salt-inhand-left.png b/Resources/Textures/Objects/Materials/ore.rsi/salt-inhand-left.png new file mode 100644 index 0000000000..fe4e9e2d5d Binary files /dev/null and b/Resources/Textures/Objects/Materials/ore.rsi/salt-inhand-left.png differ diff --git a/Resources/Textures/Objects/Materials/ore.rsi/salt-inhand-right.png b/Resources/Textures/Objects/Materials/ore.rsi/salt-inhand-right.png new file mode 100644 index 0000000000..8330643546 Binary files /dev/null and b/Resources/Textures/Objects/Materials/ore.rsi/salt-inhand-right.png differ diff --git a/Resources/Textures/Objects/Materials/ore.rsi/silver-inhand-left.png b/Resources/Textures/Objects/Materials/ore.rsi/silver-inhand-left.png new file mode 100644 index 0000000000..7f70050313 Binary files /dev/null and b/Resources/Textures/Objects/Materials/ore.rsi/silver-inhand-left.png differ diff --git a/Resources/Textures/Objects/Materials/ore.rsi/silver-inhand-right.png b/Resources/Textures/Objects/Materials/ore.rsi/silver-inhand-right.png new file mode 100644 index 0000000000..ab4dcb98d6 Binary files /dev/null and b/Resources/Textures/Objects/Materials/ore.rsi/silver-inhand-right.png differ diff --git a/Resources/Textures/Objects/Materials/ore.rsi/spacequartz-inhand-left.png b/Resources/Textures/Objects/Materials/ore.rsi/spacequartz-inhand-left.png new file mode 100644 index 0000000000..56837c9609 Binary files /dev/null and b/Resources/Textures/Objects/Materials/ore.rsi/spacequartz-inhand-left.png differ diff --git a/Resources/Textures/Objects/Materials/ore.rsi/spacequartz-inhand-right.png b/Resources/Textures/Objects/Materials/ore.rsi/spacequartz-inhand-right.png new file mode 100644 index 0000000000..45b370cb8e Binary files /dev/null and b/Resources/Textures/Objects/Materials/ore.rsi/spacequartz-inhand-right.png differ diff --git a/Resources/Textures/Objects/Materials/ore.rsi/uranium-inhand-left.png b/Resources/Textures/Objects/Materials/ore.rsi/uranium-inhand-left.png new file mode 100644 index 0000000000..422008998b Binary files /dev/null and b/Resources/Textures/Objects/Materials/ore.rsi/uranium-inhand-left.png differ diff --git a/Resources/Textures/Objects/Materials/ore.rsi/uranium-inhand-right.png b/Resources/Textures/Objects/Materials/ore.rsi/uranium-inhand-right.png new file mode 100644 index 0000000000..d13a758cbd Binary files /dev/null and b/Resources/Textures/Objects/Materials/ore.rsi/uranium-inhand-right.png differ diff --git a/Resources/Textures/Objects/Materials/parts.rsi/meta.json b/Resources/Textures/Objects/Materials/parts.rsi/meta.json index 290b7dd91c..c2503bb393 100644 --- a/Resources/Textures/Objects/Materials/parts.rsi/meta.json +++ b/Resources/Textures/Objects/Materials/parts.rsi/meta.json @@ -1,7 +1,7 @@ { "version": 1, "license": "CC-BY-SA-3.0", - "copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/c6e3401f2e7e1e55c57060cdf956a98ef1fefc24", + "copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/c6e3401f2e7e1e55c57060cdf956a98ef1fefc24. Inhands by mubururu_ (github).", "size": { "x": 32, "y": 32 @@ -10,6 +10,14 @@ { "name": "rods" }, + { + "name": "rods-inhand-left", + "directions": 4 + }, + { + "name": "rods-inhand-right", + "directions": 4 + }, { "name": "rods_2" }, diff --git a/Resources/Textures/Objects/Materials/parts.rsi/rods-inhand-left.png b/Resources/Textures/Objects/Materials/parts.rsi/rods-inhand-left.png new file mode 100644 index 0000000000..b0e71052cd Binary files /dev/null and b/Resources/Textures/Objects/Materials/parts.rsi/rods-inhand-left.png differ diff --git a/Resources/Textures/Objects/Materials/parts.rsi/rods-inhand-right.png b/Resources/Textures/Objects/Materials/parts.rsi/rods-inhand-right.png new file mode 100644 index 0000000000..01b42adce1 Binary files /dev/null and b/Resources/Textures/Objects/Materials/parts.rsi/rods-inhand-right.png differ diff --git a/Resources/Textures/Objects/Materials/silk.rsi/meta.json b/Resources/Textures/Objects/Materials/silk.rsi/meta.json index 5ac5189bae..77f77ee31a 100644 --- a/Resources/Textures/Objects/Materials/silk.rsi/meta.json +++ b/Resources/Textures/Objects/Materials/silk.rsi/meta.json @@ -1,12 +1,20 @@ { "version": 1, "license": "CC-BY-SA-3.0", - "copyright": "Made by PixelTheKermit (github) for SS14", + "copyright": "Made by PixelTheKermit (github) for SS14. Inhands by mubururu_ (github).", "size": {"x": 32, "y": 32}, "states": [ { - "name": "icon" + "name": "icon" + }, + { + "name": "silk-inhand-left", + "directions": 4 + }, + { + "name": "silk-inhand-right", + "directions": 4 } ] } diff --git a/Resources/Textures/Objects/Materials/silk.rsi/silk-inhand-left.png b/Resources/Textures/Objects/Materials/silk.rsi/silk-inhand-left.png new file mode 100644 index 0000000000..12425e93ce Binary files /dev/null and b/Resources/Textures/Objects/Materials/silk.rsi/silk-inhand-left.png differ diff --git a/Resources/Textures/Objects/Materials/silk.rsi/silk-inhand-right.png b/Resources/Textures/Objects/Materials/silk.rsi/silk-inhand-right.png new file mode 100644 index 0000000000..ee1b193af0 Binary files /dev/null and b/Resources/Textures/Objects/Materials/silk.rsi/silk-inhand-right.png differ diff --git a/Resources/Textures/Structures/Piping/Atmospherics/gas_pipe_sensor.rsi/base.png b/Resources/Textures/Structures/Piping/Atmospherics/gas_pipe_sensor.rsi/base.png new file mode 100644 index 0000000000..4a9a8f6f20 Binary files /dev/null and b/Resources/Textures/Structures/Piping/Atmospherics/gas_pipe_sensor.rsi/base.png differ diff --git a/Resources/Textures/Structures/Piping/Atmospherics/gas_pipe_sensor.rsi/blank.png b/Resources/Textures/Structures/Piping/Atmospherics/gas_pipe_sensor.rsi/blank.png new file mode 100644 index 0000000000..7bee0a002b Binary files /dev/null and b/Resources/Textures/Structures/Piping/Atmospherics/gas_pipe_sensor.rsi/blank.png differ diff --git a/Resources/Textures/Structures/Piping/Atmospherics/gas_pipe_sensor.rsi/icon.png b/Resources/Textures/Structures/Piping/Atmospherics/gas_pipe_sensor.rsi/icon.png new file mode 100644 index 0000000000..4ac9e76480 Binary files /dev/null and b/Resources/Textures/Structures/Piping/Atmospherics/gas_pipe_sensor.rsi/icon.png differ diff --git a/Resources/Textures/Structures/Piping/Atmospherics/gas_pipe_sensor.rsi/lights.png b/Resources/Textures/Structures/Piping/Atmospherics/gas_pipe_sensor.rsi/lights.png new file mode 100644 index 0000000000..6108d2b994 Binary files /dev/null and b/Resources/Textures/Structures/Piping/Atmospherics/gas_pipe_sensor.rsi/lights.png differ diff --git a/Resources/Textures/Structures/Piping/Atmospherics/gas_pipe_sensor.rsi/meta.json b/Resources/Textures/Structures/Piping/Atmospherics/gas_pipe_sensor.rsi/meta.json new file mode 100644 index 0000000000..878c7817a2 --- /dev/null +++ b/Resources/Textures/Structures/Piping/Atmospherics/gas_pipe_sensor.rsi/meta.json @@ -0,0 +1,29 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Created by chromiumboy (github) for SS14, based on the digital valve from /tg/, taken from https://github.com/tgstation/tgstation at commit 57cd1d59ca019dd0e7811ac451f295f818e573da.", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "icon" + }, + { + "name": "base" + }, + { + "name": "blank" + }, + { + "name": "lights", + "delays": [ + [ + 1.0, + 0.25 + ] + ] + } + ] +}