diff --git a/.editorconfig b/.editorconfig index a8ce1d6b68..59ca35cc9a 100644 --- a/.editorconfig +++ b/.editorconfig @@ -338,5 +338,8 @@ dotnet_naming_symbols.type_parameters_symbols.applicable_kinds = type_parameter resharper_braces_for_ifelse = required_for_multiline resharper_keep_existing_attribute_arrangement = true -[*.{csproj,xml,yml,dll.config,msbuildproj,targets}] +[*.{csproj,xml,yml,yaml,dll.config,msbuildproj,targets}] indent_size = 2 + +[{*.yaml,*.yml}] +ij_yaml_indent_sequence_value = false diff --git a/Content.Client/Actions/ActionsSystem.cs b/Content.Client/Actions/ActionsSystem.cs index 83d927c94b..a487e5d8d8 100644 --- a/Content.Client/Actions/ActionsSystem.cs +++ b/Content.Client/Actions/ActionsSystem.cs @@ -2,7 +2,6 @@ using System.IO; using System.Linq; using Content.Shared.Actions; using JetBrains.Annotations; -using Robust.Client.GameObjects; using Robust.Client.Player; using Robust.Shared.ContentPack; using Robust.Shared.GameStates; @@ -41,8 +40,8 @@ namespace Content.Client.Actions public override void Initialize() { base.Initialize(); - SubscribeLocalEvent(OnPlayerAttached); - SubscribeLocalEvent(OnPlayerDetached); + SubscribeLocalEvent(OnPlayerAttached); + SubscribeLocalEvent(OnPlayerDetached); SubscribeLocalEvent(HandleComponentState); SubscribeLocalEvent(OnInstantHandleState); @@ -196,12 +195,12 @@ namespace Content.Client.Actions return GetActions(user); } - private void OnPlayerAttached(EntityUid uid, ActionsComponent component, PlayerAttachedEvent args) + private void OnPlayerAttached(EntityUid uid, ActionsComponent component, LocalPlayerAttachedEvent args) { LinkAllActions(component); } - private void OnPlayerDetached(EntityUid uid, ActionsComponent component, PlayerDetachedEvent? args = null) + private void OnPlayerDetached(EntityUid uid, ActionsComponent component, LocalPlayerDetachedEvent? args = null) { UnlinkAllActions(); } diff --git a/Content.Client/Administration/Managers/ClientAdminManager.cs b/Content.Client/Administration/Managers/ClientAdminManager.cs index 8978e2fd6d..1a1366c6f2 100644 --- a/Content.Client/Administration/Managers/ClientAdminManager.cs +++ b/Content.Client/Administration/Managers/ClientAdminManager.cs @@ -4,7 +4,7 @@ using Robust.Client.Console; using Robust.Client.Player; using Robust.Shared.ContentPack; using Robust.Shared.Network; -using Robust.Shared.Players; +using Robust.Shared.Player; using Robust.Shared.Utility; namespace Content.Client.Administration.Managers diff --git a/Content.Client/Administration/UI/CustomControls/PlayerListControl.xaml.cs b/Content.Client/Administration/UI/CustomControls/PlayerListControl.xaml.cs index 6142e3a831..5fa28bf1ac 100644 --- a/Content.Client/Administration/UI/CustomControls/PlayerListControl.xaml.cs +++ b/Content.Client/Administration/UI/CustomControls/PlayerListControl.xaml.cs @@ -22,7 +22,7 @@ namespace Content.Client.Administration.UI.CustomControls private List _playerList = new(); private readonly List _sortedPlayerList = new(); - public event Action? OnSelectionChanged; + public event Action? OnSelectionChanged; public IReadOnlyList PlayerInfo => _playerList; public Func? OverrideText; @@ -46,9 +46,9 @@ namespace Content.Client.Administration.UI.CustomControls BackgroundPanel.PanelOverride = new StyleBoxFlat {BackgroundColor = new Color(32, 32, 40)}; } - private void PlayerListItemPressed(BaseButton.ButtonEventArgs args, ListData data) + private void PlayerListItemPressed(BaseButton.ButtonEventArgs? args, ListData? data) { - if (data is not PlayerListData {Info: var selectedPlayer}) + if (args == null || data is not PlayerListData {Info: var selectedPlayer}) return; if (args.Event.Function == EngineKeyFunctions.UIClick) { diff --git a/Content.Client/Administration/UI/Tabs/AdminTab/TeleportWindow.xaml.cs b/Content.Client/Administration/UI/Tabs/AdminTab/TeleportWindow.xaml.cs index c5a9bd036a..1978b5c3c0 100644 --- a/Content.Client/Administration/UI/Tabs/AdminTab/TeleportWindow.xaml.cs +++ b/Content.Client/Administration/UI/Tabs/AdminTab/TeleportWindow.xaml.cs @@ -5,7 +5,6 @@ using Robust.Client.Console; using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.CustomControls; using Robust.Shared.IoC; -using Robust.Shared.Players; namespace Content.Client.Administration.UI.Tabs.AdminTab { diff --git a/Content.Client/Alerts/ClientAlertsSystem.cs b/Content.Client/Alerts/ClientAlertsSystem.cs index bb6d2d4df4..5089022415 100644 --- a/Content.Client/Alerts/ClientAlertsSystem.cs +++ b/Content.Client/Alerts/ClientAlertsSystem.cs @@ -1,7 +1,6 @@ using System.Linq; using Content.Shared.Alert; using JetBrains.Annotations; -using Robust.Client.GameObjects; using Robust.Client.Player; using Robust.Shared.Prototypes; @@ -22,8 +21,8 @@ public sealed class ClientAlertsSystem : AlertsSystem { base.Initialize(); - SubscribeLocalEvent(OnPlayerAttached); - SubscribeLocalEvent(OnPlayerDetached); + SubscribeLocalEvent(OnPlayerAttached); + SubscribeLocalEvent(OnPlayerDetached); SubscribeLocalEvent(ClientAlertsHandleState); } @@ -69,7 +68,7 @@ public sealed class ClientAlertsSystem : AlertsSystem SyncAlerts?.Invoke(this, component.Alerts); } - private void OnPlayerAttached(EntityUid uid, AlertsComponent component, PlayerAttachedEvent args) + private void OnPlayerAttached(EntityUid uid, AlertsComponent component, LocalPlayerAttachedEvent args) { if (_playerManager.LocalPlayer?.ControlledEntity != uid) return; @@ -87,7 +86,7 @@ public sealed class ClientAlertsSystem : AlertsSystem ClearAlerts?.Invoke(this, EventArgs.Empty); } - private void OnPlayerDetached(EntityUid uid, AlertsComponent component, PlayerDetachedEvent args) + private void OnPlayerDetached(EntityUid uid, AlertsComponent component, LocalPlayerDetachedEvent args) { ClearAlerts?.Invoke(this, EventArgs.Empty); } diff --git a/Content.Client/CharacterInfo/CharacterInfoSystem.cs b/Content.Client/CharacterInfo/CharacterInfoSystem.cs index 93bd86d140..844a352a18 100644 --- a/Content.Client/CharacterInfo/CharacterInfoSystem.cs +++ b/Content.Client/CharacterInfo/CharacterInfoSystem.cs @@ -1,6 +1,5 @@ using Content.Shared.CharacterInfo; using Content.Shared.Objectives; -using Robust.Client.GameObjects; using Robust.Client.Player; using Robust.Client.UserInterface; @@ -11,14 +10,11 @@ public sealed class CharacterInfoSystem : EntitySystem [Dependency] private readonly IPlayerManager _players = default!; public event Action? OnCharacterUpdate; - public event Action? OnCharacterDetached; public override void Initialize() { base.Initialize(); - SubscribeLocalEvent(OnPlayerAttached); - SubscribeNetworkEvent(OnCharacterInfoEvent); } @@ -33,14 +29,6 @@ public sealed class CharacterInfoSystem : EntitySystem RaiseNetworkEvent(new RequestCharacterInfoEvent(GetNetEntity(entity.Value))); } - private void OnPlayerAttached(PlayerAttachSysMessage msg) - { - if (msg.AttachedEntity == default) - { - OnCharacterDetached?.Invoke(); - } - } - private void OnCharacterInfoEvent(CharacterInfoEvent msg, EntitySessionEventArgs args) { var entity = GetEntity(msg.NetEntity); diff --git a/Content.Client/Chemistry/Visualizers/FoamVisualizerSystem.cs b/Content.Client/Chemistry/Visualizers/FoamVisualizerSystem.cs index ec582ee094..2ee88956ff 100644 --- a/Content.Client/Chemistry/Visualizers/FoamVisualizerSystem.cs +++ b/Content.Client/Chemistry/Visualizers/FoamVisualizerSystem.cs @@ -1,8 +1,6 @@ -using Content.Shared.Smoking; -using Robust.Shared.Spawners; +using Content.Shared.Chemistry.Components; using Robust.Client.Animations; using Robust.Client.GameObjects; -using Robust.Shared.Network; using Robust.Shared.Timing; namespace Content.Client.Chemistry.Visualizers; @@ -18,6 +16,7 @@ public sealed class FoamVisualizerSystem : VisualizerSystem(OnComponentInit); + SubscribeLocalEvent(OnAnimationComplete); } public override void Update(float frameTime) @@ -27,11 +26,11 @@ public sealed class FoamVisualizerSystem : VisualizerSystem(); + var query = EntityQueryEnumerator(); - while (query.MoveNext(out var uid, out var comp, out var despawn)) + while (query.MoveNext(out var uid, out var comp, out var smoke)) { - if (despawn.Lifetime > 1f) + if (_timing.CurTime < comp.StartTime + TimeSpan.FromSeconds(smoke.Duration) - TimeSpan.FromSeconds(comp.AnimationTime)) continue; // Despawn animation. @@ -48,6 +47,7 @@ public sealed class FoamVisualizerSystem : VisualizerSystem private void OnComponentInit(EntityUid uid, FoamVisualsComponent comp, ComponentInit args) { + comp.StartTime = _timing.CurTime; comp.Animation = new Animation { Length = TimeSpan.FromSeconds(comp.AnimationTime), @@ -58,12 +58,21 @@ public sealed class FoamVisualizerSystem : VisualizerSystem(uid, out var sprite)) + sprite.Visible = false; + } } public enum FoamVisualLayers : byte diff --git a/Content.Client/Chemistry/Visualizers/FoamVisualsComponent.cs b/Content.Client/Chemistry/Visualizers/FoamVisualsComponent.cs index b09c74aa0f..8199efa42e 100644 --- a/Content.Client/Chemistry/Visualizers/FoamVisualsComponent.cs +++ b/Content.Client/Chemistry/Visualizers/FoamVisualsComponent.cs @@ -1,5 +1,6 @@ using Robust.Client.Animations; using Robust.Client.Graphics; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom; namespace Content.Client.Chemistry.Visualizers; @@ -15,18 +16,21 @@ public sealed partial class FoamVisualsComponent : Component /// public const string AnimationKey = "foamdissolve_animation"; + [DataField(customTypeSerializer: typeof(TimeOffsetSerializer))] + public TimeSpan StartTime; + /// /// How long the foam visually dissolves for. /// - [DataField("animationTime")] - public float AnimationTime = 0.6f; + [DataField] + public float AnimationTime = 0.5f; /// /// The state of the entities base sprite RSI that is displayed when the foam dissolves. /// Cannot use because it does not have and I am not making an engine PR at this time. /// - [DataField("animationState")] - public string State = "foam-dissolve"; + [DataField] + public string AnimationState = "foam-dissolve"; /// /// The animation used while the foam dissolves. diff --git a/Content.Client/Construction/ConstructionSystem.cs b/Content.Client/Construction/ConstructionSystem.cs index 98d2dfd414..9fc638cea2 100644 --- a/Content.Client/Construction/ConstructionSystem.cs +++ b/Content.Client/Construction/ConstructionSystem.cs @@ -38,7 +38,7 @@ namespace Content.Client.Construction base.Initialize(); UpdatesOutsidePrediction = true; - SubscribeLocalEvent(HandlePlayerAttached); + SubscribeLocalEvent(HandlePlayerAttached); SubscribeNetworkEvent(HandleAckStructure); SubscribeNetworkEvent(OnConstructionGuideReceived); @@ -110,9 +110,9 @@ namespace Content.Client.Construction ClearGhost(msg.GhostId); } - private void HandlePlayerAttached(PlayerAttachSysMessage msg) + private void HandlePlayerAttached(LocalPlayerAttachedEvent msg) { - var available = IsCraftingAvailable(msg.AttachedEntity); + var available = IsCraftingAvailable(msg.Entity); UpdateCraftingAvailability(available); } diff --git a/Content.Client/Drugs/DrugOverlaySystem.cs b/Content.Client/Drugs/DrugOverlaySystem.cs index 7be63b4c50..ec0d014072 100644 --- a/Content.Client/Drugs/DrugOverlaySystem.cs +++ b/Content.Client/Drugs/DrugOverlaySystem.cs @@ -1,5 +1,4 @@ using Content.Shared.Drugs; -using Robust.Client.GameObjects; using Robust.Client.Graphics; using Robust.Client.Player; @@ -24,18 +23,18 @@ public sealed class DrugOverlaySystem : EntitySystem SubscribeLocalEvent(OnInit); SubscribeLocalEvent(OnShutdown); - SubscribeLocalEvent(OnPlayerAttached); - SubscribeLocalEvent(OnPlayerDetached); + SubscribeLocalEvent(OnPlayerAttached); + SubscribeLocalEvent(OnPlayerDetached); _overlay = new(); } - private void OnPlayerAttached(EntityUid uid, SeeingRainbowsComponent component, PlayerAttachedEvent args) + private void OnPlayerAttached(EntityUid uid, SeeingRainbowsComponent component, LocalPlayerAttachedEvent args) { _overlayMan.AddOverlay(_overlay); } - private void OnPlayerDetached(EntityUid uid, SeeingRainbowsComponent component, PlayerDetachedEvent args) + private void OnPlayerDetached(EntityUid uid, SeeingRainbowsComponent component, LocalPlayerDetachedEvent args) { _overlay.Intoxication = 0; _overlayMan.RemoveOverlay(_overlay); diff --git a/Content.Client/Drunk/DrunkSystem.cs b/Content.Client/Drunk/DrunkSystem.cs index 0573b2ff3e..4f2ec70b56 100644 --- a/Content.Client/Drunk/DrunkSystem.cs +++ b/Content.Client/Drunk/DrunkSystem.cs @@ -1,5 +1,4 @@ using Content.Shared.Drunk; -using Robust.Client.GameObjects; using Robust.Client.Graphics; using Robust.Client.Player; @@ -19,18 +18,18 @@ public sealed class DrunkSystem : SharedDrunkSystem SubscribeLocalEvent(OnDrunkInit); SubscribeLocalEvent(OnDrunkShutdown); - SubscribeLocalEvent(OnPlayerAttached); - SubscribeLocalEvent(OnPlayerDetached); + SubscribeLocalEvent(OnPlayerAttached); + SubscribeLocalEvent(OnPlayerDetached); _overlay = new(); } - private void OnPlayerAttached(EntityUid uid, DrunkComponent component, PlayerAttachedEvent args) + private void OnPlayerAttached(EntityUid uid, DrunkComponent component, LocalPlayerAttachedEvent args) { _overlayMan.AddOverlay(_overlay); } - private void OnPlayerDetached(EntityUid uid, DrunkComponent component, PlayerDetachedEvent args) + private void OnPlayerDetached(EntityUid uid, DrunkComponent component, LocalPlayerDetachedEvent args) { _overlay.CurrentBoozePower = 0; _overlayMan.RemoveOverlay(_overlay); diff --git a/Content.Client/Eye/Blinding/BlindingSystem.cs b/Content.Client/Eye/Blinding/BlindingSystem.cs index f0b760d838..f255f7ef01 100644 --- a/Content.Client/Eye/Blinding/BlindingSystem.cs +++ b/Content.Client/Eye/Blinding/BlindingSystem.cs @@ -1,17 +1,7 @@ - -using Content.Shared.Eye.Blinding; -using Robust.Client.GameObjects; using Robust.Client.Graphics; using Robust.Client.Player; -using System; -using System.Collections.Generic; -using System.Linq; -using Content.Shared.Administration; -using Content.Shared.Administration.Events; using Content.Shared.Eye.Blinding.Components; using Content.Shared.GameTicking; -using Robust.Shared.GameObjects; -using Robust.Shared.Network; namespace Content.Client.Eye.Blinding; @@ -31,20 +21,20 @@ public sealed class BlindingSystem : EntitySystem SubscribeLocalEvent(OnBlindInit); SubscribeLocalEvent(OnBlindShutdown); - SubscribeLocalEvent(OnPlayerAttached); - SubscribeLocalEvent(OnPlayerDetached); + SubscribeLocalEvent(OnPlayerAttached); + SubscribeLocalEvent(OnPlayerDetached); SubscribeNetworkEvent(RoundRestartCleanup); _overlay = new(); } - private void OnPlayerAttached(EntityUid uid, BlindableComponent component, PlayerAttachedEvent args) + private void OnPlayerAttached(EntityUid uid, BlindableComponent component, LocalPlayerAttachedEvent args) { _overlayMan.AddOverlay(_overlay); } - private void OnPlayerDetached(EntityUid uid, BlindableComponent component, PlayerDetachedEvent args) + private void OnPlayerDetached(EntityUid uid, BlindableComponent component, LocalPlayerDetachedEvent args) { _overlayMan.RemoveOverlay(_overlay); _lightManager.Enabled = true; diff --git a/Content.Client/Eye/Blinding/BlurryVisionSystem.cs b/Content.Client/Eye/Blinding/BlurryVisionSystem.cs index 1bac2a97bf..8be5b4ed93 100644 --- a/Content.Client/Eye/Blinding/BlurryVisionSystem.cs +++ b/Content.Client/Eye/Blinding/BlurryVisionSystem.cs @@ -1,9 +1,6 @@ -using Content.Shared.Eye.Blinding; using Content.Shared.Eye.Blinding.Components; -using Robust.Client.GameObjects; using Robust.Client.Graphics; using Robust.Client.Player; -using Robust.Shared.GameStates; namespace Content.Client.Eye.Blinding; @@ -20,18 +17,18 @@ public sealed class BlurryVisionSystem : EntitySystem SubscribeLocalEvent(OnBlurryInit); SubscribeLocalEvent(OnBlurryShutdown); - SubscribeLocalEvent(OnPlayerAttached); - SubscribeLocalEvent(OnPlayerDetached); + SubscribeLocalEvent(OnPlayerAttached); + SubscribeLocalEvent(OnPlayerDetached); _overlay = new(); } - private void OnPlayerAttached(EntityUid uid, BlurryVisionComponent component, PlayerAttachedEvent args) + private void OnPlayerAttached(EntityUid uid, BlurryVisionComponent component, LocalPlayerAttachedEvent args) { _overlayMan.AddOverlay(_overlay); } - private void OnPlayerDetached(EntityUid uid, BlurryVisionComponent component, PlayerDetachedEvent args) + private void OnPlayerDetached(EntityUid uid, BlurryVisionComponent component, LocalPlayerDetachedEvent args) { _overlayMan.RemoveOverlay(_overlay); } diff --git a/Content.Client/Eye/EyeLerpingSystem.cs b/Content.Client/Eye/EyeLerpingSystem.cs index 8e54196b81..b46921a9b4 100644 --- a/Content.Client/Eye/EyeLerpingSystem.cs +++ b/Content.Client/Eye/EyeLerpingSystem.cs @@ -30,7 +30,7 @@ public sealed class EyeLerpingSystem : EntitySystem SubscribeLocalEvent(OnAttached); SubscribeLocalEvent(HandleMapChange); - SubscribeLocalEvent(OnDetached); + SubscribeLocalEvent(OnDetached); UpdatesAfter.Add(typeof(TransformSystem)); UpdatesAfter.Add(typeof(PhysicsSystem)); @@ -94,7 +94,7 @@ public sealed class EyeLerpingSystem : EntitySystem AddEye(ev.Entity, ev.Component, true); } - private void OnDetached(EntityUid uid, LerpingEyeComponent component, PlayerDetachedEvent args) + private void OnDetached(EntityUid uid, LerpingEyeComponent component, LocalPlayerDetachedEvent args) { if (!component.ManuallyAdded) RemCompDeferred(uid, component); diff --git a/Content.Client/Fullscreen/FullscreenHook.cs b/Content.Client/Fullscreen/FullscreenHook.cs index 78a0151736..7917fddfbb 100644 --- a/Content.Client/Fullscreen/FullscreenHook.cs +++ b/Content.Client/Fullscreen/FullscreenHook.cs @@ -4,7 +4,7 @@ using Robust.Client.Input; using Robust.Shared.Input.Binding; using Robust.Shared; using Robust.Shared.Configuration; -using Robust.Shared.Players; +using Robust.Shared.Player; namespace Content.Client.Fullscreen; public sealed class FullscreenHook diff --git a/Content.Client/Gameplay/GameplayStateBase.cs b/Content.Client/Gameplay/GameplayStateBase.cs index 788a4e5dff..454c063260 100644 --- a/Content.Client/Gameplay/GameplayStateBase.cs +++ b/Content.Client/Gameplay/GameplayStateBase.cs @@ -16,7 +16,7 @@ using Robust.Shared.Console; using Robust.Shared.Input; using Robust.Shared.Input.Binding; using Robust.Shared.Map; -using Robust.Shared.Players; +using Robust.Shared.Player; using Robust.Shared.Timing; namespace Content.Client.Gameplay diff --git a/Content.Client/Ghost/GhostSystem.cs b/Content.Client/Ghost/GhostSystem.cs index 5727534109..a89d0858d9 100644 --- a/Content.Client/Ghost/GhostSystem.cs +++ b/Content.Client/Ghost/GhostSystem.cs @@ -58,10 +58,10 @@ namespace Content.Client.Ghost SubscribeLocalEvent(OnGhostRemove); SubscribeLocalEvent(OnGhostState); - SubscribeLocalEvent(OnGhostPlayerAttach); - SubscribeLocalEvent(OnGhostPlayerDetach); + SubscribeLocalEvent(OnGhostPlayerAttach); + SubscribeLocalEvent(OnGhostPlayerDetach); - SubscribeLocalEvent(OnPlayerAttach); + SubscribeLocalEvent(OnPlayerAttach); SubscribeNetworkEvent(OnGhostWarpsResponse); SubscribeNetworkEvent(OnUpdateGhostRoleCount); @@ -130,7 +130,7 @@ namespace Content.Client.Ghost PlayerRemoved?.Invoke(component); } - private void OnGhostPlayerAttach(EntityUid uid, GhostComponent component, PlayerAttachedEvent playerAttachedEvent) + private void OnGhostPlayerAttach(EntityUid uid, GhostComponent component, LocalPlayerAttachedEvent localPlayerAttachedEvent) { if (uid != _playerManager.LocalPlayer?.ControlledEntity) return; @@ -161,13 +161,13 @@ namespace Content.Client.Ghost return true; } - private void OnGhostPlayerDetach(EntityUid uid, GhostComponent component, PlayerDetachedEvent args) + private void OnGhostPlayerDetach(EntityUid uid, GhostComponent component, LocalPlayerDetachedEvent args) { if (PlayerDetach(uid)) component.IsAttached = false; } - private void OnPlayerAttach(PlayerAttachedEvent ev) + private void OnPlayerAttach(LocalPlayerAttachedEvent ev) { if (!HasComp(ev.Entity)) PlayerDetach(ev.Entity); diff --git a/Content.Client/Hands/Systems/HandsSystem.cs b/Content.Client/Hands/Systems/HandsSystem.cs index ed40589f7f..31de7ec143 100644 --- a/Content.Client/Hands/Systems/HandsSystem.cs +++ b/Content.Client/Hands/Systems/HandsSystem.cs @@ -42,8 +42,8 @@ namespace Content.Client.Hands.Systems { base.Initialize(); - SubscribeLocalEvent(HandlePlayerAttached); - SubscribeLocalEvent(HandlePlayerDetached); + SubscribeLocalEvent(HandlePlayerAttached); + SubscribeLocalEvent(HandlePlayerDetached); SubscribeLocalEvent(OnHandsStartup); SubscribeLocalEvent(OnHandsShutdown); SubscribeLocalEvent(HandleComponentState); @@ -361,12 +361,12 @@ namespace Content.Client.Hands.Systems #region Gui - private void HandlePlayerAttached(EntityUid uid, HandsComponent component, PlayerAttachedEvent args) + private void HandlePlayerAttached(EntityUid uid, HandsComponent component, LocalPlayerAttachedEvent args) { OnPlayerHandsAdded?.Invoke(component); } - private void HandlePlayerDetached(EntityUid uid, HandsComponent component, PlayerDetachedEvent args) + private void HandlePlayerDetached(EntityUid uid, HandsComponent component, LocalPlayerDetachedEvent args) { OnPlayerHandsRemoved?.Invoke(); } diff --git a/Content.Client/HealthAnalyzer/UI/HealthAnalyzerWindow.xaml b/Content.Client/HealthAnalyzer/UI/HealthAnalyzerWindow.xaml index 1f64feec2b..b78c3c6a56 100644 --- a/Content.Client/HealthAnalyzer/UI/HealthAnalyzerWindow.xaml +++ b/Content.Client/HealthAnalyzer/UI/HealthAnalyzerWindow.xaml @@ -1,9 +1,33 @@  - - - + SetSize="250 100"> + + + + + \ No newline at end of file diff --git a/Content.Client/HealthAnalyzer/UI/HealthAnalyzerWindow.xaml.cs b/Content.Client/HealthAnalyzer/UI/HealthAnalyzerWindow.xaml.cs index 1c5a3373e1..36f7a08b96 100644 --- a/Content.Client/HealthAnalyzer/UI/HealthAnalyzerWindow.xaml.cs +++ b/Content.Client/HealthAnalyzer/UI/HealthAnalyzerWindow.xaml.cs @@ -1,5 +1,5 @@ +using System.Linq; using System.Numerics; -using System.Text; using Content.Shared.Damage; using Content.Shared.Damage.Prototypes; using Content.Shared.FixedPoint; @@ -8,85 +8,182 @@ using Content.Shared.MedicalScanner; using Robust.Client.AutoGenerated; using Robust.Client.UserInterface.CustomControls; using Robust.Client.UserInterface.XAML; +using Robust.Client.GameObjects; +using Robust.Client.Graphics; +using Robust.Client.UserInterface.Controls; +using Robust.Client.ResourceManagement; using Robust.Shared.Prototypes; +using Robust.Shared.Utility; namespace Content.Client.HealthAnalyzer.UI { [GenerateTypedNameReferences] public sealed partial class HealthAnalyzerWindow : DefaultWindow { + private readonly IEntityManager _entityManager; + private readonly SpriteSystem _spriteSystem; + private readonly IPrototypeManager _prototypes; + private readonly IResourceCache _cache; + + private const int AnalyzerHeight = 430; + private const int AnalyzerWidth = 300; + public HealthAnalyzerWindow() { RobustXamlLoader.Load(this); + + var dependencies = IoCManager.Instance!; + _entityManager = dependencies.Resolve(); + _spriteSystem = _entityManager.System(); + _prototypes = dependencies.Resolve(); + _cache = dependencies.Resolve(); } public void Populate(HealthAnalyzerScannedUserMessage msg) { - var text = new StringBuilder(); - var entities = IoCManager.Resolve(); - var target = entities.GetEntity(msg.TargetEntity); + GroupsContainer.RemoveAllChildren(); - if (msg.TargetEntity != null && entities.TryGetComponent(target, out var damageable)) + var target = _entityManager.GetEntity(msg.TargetEntity); + + if (target == null + || !_entityManager.TryGetComponent(target, out var damageable)) { - string entityName = "Unknown"; - if (msg.TargetEntity != null && - entities.HasComponent(target.Value)) - { - entityName = Identity.Name(target.Value, entities); - } - - IReadOnlyDictionary damagePerGroup = damageable.DamagePerGroup; - IReadOnlyDictionary damagePerType = damageable.Damage.DamageDict; - - text.Append($"{Loc.GetString("health-analyzer-window-entity-health-text", ("entityName", entityName))}\n\n"); - - - text.Append($"{Loc.GetString("health-analyzer-window-entity-temperature-text", ("temperature", float.IsNaN(msg.Temperature) ? "N/A" : $"{msg.Temperature - 273f:F1} °C"))}\n"); - - - text.Append($"{Loc.GetString("health-analyzer-window-entity-blood-level-text", ("bloodLevel", float.IsNaN(msg.BloodLevel) ? "N/A" : $"{msg.BloodLevel * 100:F1} %"))}\n\n"); - - - // Damage - text.Append($"{Loc.GetString("health-analyzer-window-entity-damage-total-text", ("amount", damageable.TotalDamage))}\n"); - - HashSet shownTypes = new(); - - var protos = IoCManager.Resolve(); - - // Show the total damage and type breakdown for each damage group. - foreach (var (damageGroupId, damageAmount) in damagePerGroup) - { - if (damageAmount == 0) - { - continue; - } - text.Append($"\n{Loc.GetString("health-analyzer-window-damage-group-text", ("damageGroup", Loc.GetString("health-analyzer-window-damage-group-" + damageGroupId)), ("amount", damageAmount))}"); - - // Show the damage for each type in that group. - var group = protos.Index(damageGroupId); - foreach (var type in group.DamageTypes) - { - if (damagePerType.TryGetValue(type, out var typeAmount) ) - { - // If damage types are allowed to belong to more than one damage group, they may appear twice here. Mark them as duplicate. - if (!shownTypes.Contains(type) && typeAmount > 0) - { - shownTypes.Add(type); - text.Append($"\n- {Loc.GetString("health-analyzer-window-damage-type-text", ("damageType", Loc.GetString("health-analyzer-window-damage-type-" + type)), ("amount", typeAmount))}"); - } - } - } - text.AppendLine(); - } - Diagnostics.Text = text.ToString(); - SetSize = new Vector2(250, 600); + NoPatientDataText.Visible = true; + return; } - else + + NoPatientDataText.Visible = false; + + string entityName = Loc.GetString("health-analyzer-window-entity-unknown-text"); + if (_entityManager.HasComponent(target.Value)) { - Diagnostics.Text = Loc.GetString("health-analyzer-window-no-patient-data-text"); - SetSize = new Vector2(250, 100); + entityName = Identity.Name(target.Value, _entityManager); } + + PatientName.Text = Loc.GetString( + "health-analyzer-window-entity-health-text", + ("entityName", entityName) + ); + + Temperature.Text = Loc.GetString("health-analyzer-window-entity-temperature-text", + ("temperature", float.IsNaN(msg.Temperature) ? "N/A" : $"{msg.Temperature - 273f:F1} °C") + ); + + BloodLevel.Text = Loc.GetString("health-analyzer-window-entity-blood-level-text", + ("bloodLevel", float.IsNaN(msg.BloodLevel) ? "N/A" : $"{msg.BloodLevel * 100:F1} %") + ); + + patientDamageAmount.Text = Loc.GetString( + "health-analyzer-window-entity-damage-total-text", + ("amount", damageable.TotalDamage) + ); + + var damageSortedGroups = + damageable.DamagePerGroup.OrderBy(damage => damage.Value) + .ToDictionary(x => x.Key, x => x.Value); + IReadOnlyDictionary damagePerType = damageable.Damage.DamageDict; + + DrawDiagnosticGroups(damageSortedGroups, damagePerType); + + SetHeight = AnalyzerHeight; + SetWidth = AnalyzerWidth; + } + + private void DrawDiagnosticGroups( + Dictionary groups, IReadOnlyDictionary damageDict) + { + HashSet shownTypes = new(); + + // Show the total damage and type breakdown for each damage group. + foreach (var (damageGroupId, damageAmount) in groups.Reverse()) + { + if (damageAmount == 0) + continue; + + var groupTitleText = $"{Loc.GetString( + "health-analyzer-window-damage-group-text", + ("damageGroup", Loc.GetString("health-analyzer-window-damage-group-" + damageGroupId)), + ("amount", damageAmount) + )}"; + + var groupContainer = new BoxContainer + { + Margin = new Thickness(0, 0, 0, 15), + Align = BoxContainer.AlignMode.Begin, + Orientation = BoxContainer.LayoutOrientation.Vertical, + }; + + groupContainer.AddChild(CreateDiagnosticGroupTitle(groupTitleText, damageGroupId, damageAmount.Int())); + + GroupsContainer.AddChild(groupContainer); + + // Show the damage for each type in that group. + var group = _prototypes.Index(damageGroupId); + + foreach (var type in group.DamageTypes) + { + if (damageDict.TryGetValue(type, out var typeAmount) && typeAmount > 0) + { + // If damage types are allowed to belong to more than one damage group, + // they may appear twice here. Mark them as duplicate. + if (shownTypes.Contains(type)) + continue; + + shownTypes.Add(type); + + var damageString = Loc.GetString( + "health-analyzer-window-damage-type-text", + ("damageType", Loc.GetString("health-analyzer-window-damage-type-" + type)), + ("amount", typeAmount) + ); + + groupContainer.AddChild(CreateDiagnosticItemLabel(damageString.Insert(0, "- "))); + } + } + } + } + + private Texture GetTexture(string texture) + { + var rsiPath = new ResPath("/Textures/Objects/Devices/health_analyzer.rsi"); + var rsiSprite = new SpriteSpecifier.Rsi(rsiPath, texture); + + var rsi = _cache.GetResource(rsiSprite.RsiPath).RSI; + if (!rsi.TryGetState(rsiSprite.RsiState, out var state)) + { + rsiSprite = new SpriteSpecifier.Rsi(rsiPath, "unknown"); + } + + return _spriteSystem.Frame0(rsiSprite); + } + + private static Label CreateDiagnosticItemLabel(string text) + { + return new Label + { + Margin = new Thickness(2, 2), + Text = text, + }; + } + + private BoxContainer CreateDiagnosticGroupTitle(string text, string id, int damageAmount) + { + var rootContainer = new BoxContainer + { + VerticalAlignment = VAlignment.Bottom, + Orientation = BoxContainer.LayoutOrientation.Horizontal + }; + + rootContainer.AddChild(new TextureRect + { + Margin = new Thickness(0, 3), + SetSize = new Vector2(30, 30), + Texture = GetTexture(id.ToLower()) + }); + + rootContainer.AddChild(CreateDiagnosticItemLabel(text)); + + return rootContainer; } } } diff --git a/Content.Client/HealthOverlay/HealthOverlaySystem.cs b/Content.Client/HealthOverlay/HealthOverlaySystem.cs index baeb4fe025..29ac937199 100644 --- a/Content.Client/HealthOverlay/HealthOverlaySystem.cs +++ b/Content.Client/HealthOverlay/HealthOverlaySystem.cs @@ -3,8 +3,8 @@ using Content.Shared.Damage; using Content.Shared.GameTicking; using Content.Shared.Mobs.Components; using JetBrains.Annotations; -using Robust.Client.GameObjects; using Robust.Client.Graphics; +using Robust.Client.Player; namespace Content.Client.HealthOverlay { @@ -13,9 +13,9 @@ namespace Content.Client.HealthOverlay { [Dependency] private readonly IEyeManager _eyeManager = default!; [Dependency] private readonly IEntityManager _entities = default!; + [Dependency] private readonly IPlayerManager _player = default!; private readonly Dictionary _guis = new(); - private EntityUid? _attachedEntity; private bool _enabled; public bool Enabled @@ -42,7 +42,6 @@ namespace Content.Client.HealthOverlay base.Initialize(); SubscribeNetworkEvent(Reset); - SubscribeLocalEvent(HandlePlayerAttached); } public void Reset(RoundRestartCleanupEvent ev) @@ -53,12 +52,6 @@ namespace Content.Client.HealthOverlay } _guis.Clear(); - _attachedEntity = default; - } - - private void HandlePlayerAttached(PlayerAttachSysMessage message) - { - _attachedEntity = message.AttachedEntity; } public override void FrameUpdate(float frameTime) @@ -70,7 +63,7 @@ namespace Content.Client.HealthOverlay return; } - if (_attachedEntity is not {} ent || Deleted(ent)) + if (_player.LocalEntity is not {} ent || Deleted(ent)) { return; } diff --git a/Content.Client/Inventory/ClientInventorySystem.cs b/Content.Client/Inventory/ClientInventorySystem.cs index ffff392aa4..f0a12b3b1f 100644 --- a/Content.Client/Inventory/ClientInventorySystem.cs +++ b/Content.Client/Inventory/ClientInventorySystem.cs @@ -10,7 +10,6 @@ using Content.Shared.Inventory; using Content.Shared.Inventory.Events; using Content.Shared.Storage; using JetBrains.Annotations; -using Robust.Client.GameObjects; using Robust.Client.Player; using Robust.Client.UserInterface; using Robust.Shared.Containers; @@ -43,8 +42,8 @@ namespace Content.Client.Inventory UpdatesOutsidePrediction = true; base.Initialize(); - SubscribeLocalEvent(OnPlayerAttached); - SubscribeLocalEvent(OnPlayerDetached); + SubscribeLocalEvent(OnPlayerAttached); + SubscribeLocalEvent(OnPlayerDetached); SubscribeLocalEvent(OnShutdown); @@ -113,12 +112,12 @@ namespace Content.Client.Inventory OnUnlinkInventory?.Invoke(); } - private void OnPlayerDetached(EntityUid uid, InventorySlotsComponent component, PlayerDetachedEvent args) + private void OnPlayerDetached(EntityUid uid, InventorySlotsComponent component, LocalPlayerDetachedEvent args) { OnUnlinkInventory?.Invoke(); } - private void OnPlayerAttached(EntityUid uid, InventorySlotsComponent component, PlayerAttachedEvent args) + private void OnPlayerAttached(EntityUid uid, InventorySlotsComponent component, LocalPlayerAttachedEvent args) { if (TryGetSlots(uid, out var definitions)) { diff --git a/Content.Client/Mind/MindSystem.cs b/Content.Client/Mind/MindSystem.cs index 87d9e9ddbe..cc43c349e4 100644 --- a/Content.Client/Mind/MindSystem.cs +++ b/Content.Client/Mind/MindSystem.cs @@ -4,4 +4,24 @@ namespace Content.Client.Mind; public sealed class MindSystem : SharedMindSystem { + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(OnHandleState); + } + + private void OnHandleState(EntityUid uid, MindComponent component, ref AfterAutoHandleStateEvent args) + { + // Because minds are generally not networked, there might be weird situations were a client thinks multiple + // users share a mind? E.g., if an admin periodical gets sent all minds via some PVS override, but doesn't get + // sent intermediate states? Not sure if this is actually possible, but better to be safe. + foreach (var (user, mind) in UserMinds) + { + if (mind == uid) + UserMinds.Remove(user); + } + + if (component.UserId != null) + UserMinds[component.UserId.Value] = uid; + } } diff --git a/Content.Client/Overlays/EquipmentHudSystem.cs b/Content.Client/Overlays/EquipmentHudSystem.cs index 1d5ec03291..ac618691d8 100644 --- a/Content.Client/Overlays/EquipmentHudSystem.cs +++ b/Content.Client/Overlays/EquipmentHudSystem.cs @@ -1,7 +1,6 @@ using Content.Shared.GameTicking; using Content.Shared.Inventory; using Content.Shared.Inventory.Events; -using Robust.Client.GameObjects; using Robust.Client.Player; namespace Content.Client.Overlays; @@ -24,8 +23,8 @@ public abstract class EquipmentHudSystem : EntitySystem where T : IComponent SubscribeLocalEvent(OnStartup); SubscribeLocalEvent(OnRemove); - SubscribeLocalEvent(OnPlayerAttached); - SubscribeLocalEvent(OnPlayerDetached); + SubscribeLocalEvent(OnPlayerAttached); + SubscribeLocalEvent(OnPlayerDetached); SubscribeLocalEvent(OnCompEquip); SubscribeLocalEvent(OnCompUnequip); @@ -65,12 +64,12 @@ public abstract class EquipmentHudSystem : EntitySystem where T : IComponent RefreshOverlay(uid); } - private void OnPlayerAttached(PlayerAttachedEvent args) + private void OnPlayerAttached(LocalPlayerAttachedEvent args) { RefreshOverlay(args.Entity); } - private void OnPlayerDetached(PlayerDetachedEvent args) + private void OnPlayerDetached(LocalPlayerDetachedEvent args) { if (_player.LocalPlayer?.ControlledEntity == null) Deactivate(); diff --git a/Content.Client/Physics/Controllers/MoverController.cs b/Content.Client/Physics/Controllers/MoverController.cs index 54c5c3de15..52340b3391 100644 --- a/Content.Client/Physics/Controllers/MoverController.cs +++ b/Content.Client/Physics/Controllers/MoverController.cs @@ -1,7 +1,6 @@ using Content.Shared.Movement.Components; using Content.Shared.Movement.Systems; using Content.Shared.Pulling.Components; -using Robust.Client.GameObjects; using Robust.Client.Physics; using Robust.Client.Player; using Robust.Shared.Physics.Components; @@ -17,10 +16,10 @@ namespace Content.Client.Physics.Controllers public override void Initialize() { base.Initialize(); - SubscribeLocalEvent(OnRelayPlayerAttached); - SubscribeLocalEvent(OnRelayPlayerDetached); - SubscribeLocalEvent(OnPlayerAttached); - SubscribeLocalEvent(OnPlayerDetached); + SubscribeLocalEvent(OnRelayPlayerAttached); + SubscribeLocalEvent(OnRelayPlayerDetached); + SubscribeLocalEvent(OnPlayerAttached); + SubscribeLocalEvent(OnPlayerDetached); SubscribeLocalEvent(OnUpdatePredicted); SubscribeLocalEvent(OnUpdateRelayTargetPredicted); @@ -54,7 +53,7 @@ namespace Content.Client.Physics.Controllers // What if the entity is being pulled by a vehicle controlled by the player? } - private void OnRelayPlayerAttached(EntityUid uid, RelayInputMoverComponent component, PlayerAttachedEvent args) + private void OnRelayPlayerAttached(EntityUid uid, RelayInputMoverComponent component, LocalPlayerAttachedEvent args) { Physics.UpdateIsPredicted(uid); Physics.UpdateIsPredicted(component.RelayEntity); @@ -62,7 +61,7 @@ namespace Content.Client.Physics.Controllers SetMoveInput(inputMover, MoveButtons.None); } - private void OnRelayPlayerDetached(EntityUid uid, RelayInputMoverComponent component, PlayerDetachedEvent args) + private void OnRelayPlayerDetached(EntityUid uid, RelayInputMoverComponent component, LocalPlayerDetachedEvent args) { Physics.UpdateIsPredicted(uid); Physics.UpdateIsPredicted(component.RelayEntity); @@ -70,12 +69,12 @@ namespace Content.Client.Physics.Controllers SetMoveInput(inputMover, MoveButtons.None); } - private void OnPlayerAttached(EntityUid uid, InputMoverComponent component, PlayerAttachedEvent args) + private void OnPlayerAttached(EntityUid uid, InputMoverComponent component, LocalPlayerAttachedEvent args) { SetMoveInput(component, MoveButtons.None); } - private void OnPlayerDetached(EntityUid uid, InputMoverComponent component, PlayerDetachedEvent args) + private void OnPlayerDetached(EntityUid uid, InputMoverComponent component, LocalPlayerDetachedEvent args) { SetMoveInput(component, MoveButtons.None); } diff --git a/Content.Client/Players/PlayerSystem.cs b/Content.Client/Players/PlayerSystem.cs index d5ce4ec197..dba95ef7a6 100644 --- a/Content.Client/Players/PlayerSystem.cs +++ b/Content.Client/Players/PlayerSystem.cs @@ -1,11 +1,11 @@ using Content.Shared.Players; -using Robust.Shared.Players; +using Robust.Shared.Player; namespace Content.Client.Players; public sealed class PlayerSystem : SharedPlayerSystem { - public override PlayerData? ContentData(ICommonSession? session) + public override ContentPlayerData? ContentData(ICommonSession? session) { return null; } diff --git a/Content.Client/Popups/PopupSystem.cs b/Content.Client/Popups/PopupSystem.cs index 1d4ca19ce2..d68272a107 100644 --- a/Content.Client/Popups/PopupSystem.cs +++ b/Content.Client/Popups/PopupSystem.cs @@ -9,7 +9,6 @@ using Robust.Client.UserInterface; using Robust.Shared.Configuration; using Robust.Shared.Map; using Robust.Shared.Player; -using Robust.Shared.Players; using Robust.Shared.Prototypes; using Robust.Shared.Replays; using Robust.Shared.Timing; diff --git a/Content.Client/Power/Generator/GeneratorWindow.xaml.cs b/Content.Client/Power/Generator/GeneratorWindow.xaml.cs index d3949807b7..0b8f94ceae 100644 --- a/Content.Client/Power/Generator/GeneratorWindow.xaml.cs +++ b/Content.Client/Power/Generator/GeneratorWindow.xaml.cs @@ -14,6 +14,7 @@ public sealed partial class GeneratorWindow : FancyWindow [Dependency] private readonly IEntityManager _entityManager = default!; [Dependency] private readonly ILocalizationManager _loc = default!; + private readonly SharedPowerSwitchableSystem _switchable; private readonly FuelGeneratorComponent? _component; private PortableGeneratorComponentBuiState? _lastState; @@ -24,6 +25,7 @@ public sealed partial class GeneratorWindow : FancyWindow IoCManager.InjectDependencies(this); _entityManager.TryGetComponent(entity, out _component); + _switchable = _entityManager.System(); EntityView.SetEntity(entity); TargetPower.IsValid += IsValid; @@ -99,17 +101,16 @@ public sealed partial class GeneratorWindow : FancyWindow StatusLabel.SetOnlyStyleClass("Danger"); } - var canSwitch = _entityManager.TryGetComponent(_entity, out PowerSwitchableGeneratorComponent? switchable); + var canSwitch = _entityManager.TryGetComponent(_entity, out PowerSwitchableComponent? switchable); OutputSwitchLabel.Visible = canSwitch; OutputSwitchButton.Visible = canSwitch; - if (canSwitch) + if (switchable != null) { - var isHV = switchable!.ActiveOutput == PowerSwitchableGeneratorOutput.HV; - OutputSwitchLabel.Text = - Loc.GetString(isHV ? "portable-generator-ui-switch-hv" : "portable-generator-ui-switch-mv"); - OutputSwitchButton.Text = - Loc.GetString(isHV ? "portable-generator-ui-switch-to-mv" : "portable-generator-ui-switch-to-hv"); + var voltage = _switchable.VoltageString(_switchable.GetVoltage(_entity, switchable)); + OutputSwitchLabel.Text = Loc.GetString("portable-generator-ui-current-output", ("voltage", voltage)); + var nextVoltage = _switchable.VoltageString(_switchable.GetNextVoltage(_entity, switchable)); + OutputSwitchButton.Text = Loc.GetString("power-switchable-switch-voltage", ("voltage", nextVoltage)); OutputSwitchButton.Disabled = state.On; } diff --git a/Content.Client/Power/Generator/PowerSwitchableSystem.cs b/Content.Client/Power/Generator/PowerSwitchableSystem.cs new file mode 100644 index 0000000000..b235dee77d --- /dev/null +++ b/Content.Client/Power/Generator/PowerSwitchableSystem.cs @@ -0,0 +1,7 @@ +using Content.Shared.Power.Generator; + +namespace Content.Client.Power.Generator; + +public sealed class PowerSwitchableSystem : SharedPowerSwitchableSystem +{ +} diff --git a/Content.Client/Replay/Spectator/ReplaySpectatorSystem.Movement.cs b/Content.Client/Replay/Spectator/ReplaySpectatorSystem.Movement.cs index 3bb2afe122..d48a1eab46 100644 --- a/Content.Client/Replay/Spectator/ReplaySpectatorSystem.Movement.cs +++ b/Content.Client/Replay/Spectator/ReplaySpectatorSystem.Movement.cs @@ -2,7 +2,7 @@ using Content.Shared.Movement.Components; using Robust.Shared.Input; using Robust.Shared.Input.Binding; using Robust.Shared.Map; -using Robust.Shared.Players; +using Robust.Shared.Player; namespace Content.Client.Replay.Spectator; diff --git a/Content.Client/Replay/Spectator/ReplaySpectatorSystem.Position.cs b/Content.Client/Replay/Spectator/ReplaySpectatorSystem.Position.cs index 45a175e688..479e2eff97 100644 --- a/Content.Client/Replay/Spectator/ReplaySpectatorSystem.Position.cs +++ b/Content.Client/Replay/Spectator/ReplaySpectatorSystem.Position.cs @@ -1,5 +1,5 @@ using Content.Shared.Movement.Components; -using Robust.Client.GameObjects; +using Robust.Client.Player; using Robust.Shared.Map; using Robust.Shared.Map.Components; using Robust.Shared.Network; @@ -79,7 +79,7 @@ public sealed partial class ReplaySpectatorSystem public void SetSpectatorPosition(SpectatorData data) { - if (_player.LocalPlayer == null) + if (_player.LocalSession == null) return; if (data.Controller != null @@ -87,13 +87,13 @@ public sealed partial class ReplaySpectatorSystem && Exists(session.AttachedEntity) && Transform(session.AttachedEntity.Value).MapID != MapId.Nullspace) { - _player.LocalPlayer.AttachEntity(session.AttachedEntity.Value, EntityManager, _client); + _player.SetAttachedEntity(_player.LocalSession, session.AttachedEntity); return; } if (Exists(data.Entity) && Transform(data.Entity).MapID != MapId.Nullspace) { - _player.LocalPlayer.AttachEntity(data.Entity, EntityManager, _client); + _player.SetAttachedEntity(_player.LocalSession, data.Entity); return; } @@ -118,7 +118,7 @@ public sealed partial class ReplaySpectatorSystem return; } - if (data.Eye != null && TryComp(_player.LocalPlayer.ControlledEntity, out InputMoverComponent? newMover)) + if (data.Eye != null && TryComp(_player.LocalSession.AttachedEntity, out InputMoverComponent? newMover)) { newMover.RelativeEntity = data.Eye.Value.Ent; newMover.TargetRelativeRotation = newMover.RelativeRotation = data.Eye.Value.Rot; @@ -177,7 +177,7 @@ public sealed partial class ReplaySpectatorSystem SetSpectatorPosition(default); } - private void OnDetached(EntityUid uid, ReplaySpectatorComponent component, PlayerDetachedEvent args) + private void OnDetached(EntityUid uid, ReplaySpectatorComponent component, LocalPlayerDetachedEvent args) { if (IsClientSide(uid)) QueueDel(uid); diff --git a/Content.Client/Replay/Spectator/ReplaySpectatorSystem.Spectate.cs b/Content.Client/Replay/Spectator/ReplaySpectatorSystem.Spectate.cs index f3475c5479..80a8429055 100644 --- a/Content.Client/Replay/Spectator/ReplaySpectatorSystem.Spectate.cs +++ b/Content.Client/Replay/Spectator/ReplaySpectatorSystem.Spectate.cs @@ -32,10 +32,10 @@ public sealed partial class ReplaySpectatorSystem public void SpectateEntity(EntityUid target) { - if (_player.LocalPlayer == null) + if (_player.LocalSession == null) return; - var old = _player.LocalPlayer.ControlledEntity; + var old = _player.LocalSession.AttachedEntity; if (old == target) { @@ -44,7 +44,7 @@ public sealed partial class ReplaySpectatorSystem return; } - _player.LocalPlayer.AttachEntity(target, EntityManager, _client); + _player.SetAttachedEntity(_player.LocalSession, target); EnsureComp(target); _stateMan.RequestStateChange(); @@ -59,10 +59,10 @@ public sealed partial class ReplaySpectatorSystem public TransformComponent SpawnSpectatorGhost(EntityCoordinates coords, bool gridAttach) { - if (_player.LocalPlayer == null) + if (_player.LocalSession == null) throw new InvalidOperationException(); - var old = _player.LocalPlayer.ControlledEntity; + var old = _player.LocalSession.AttachedEntity; var ent = Spawn("ReplayObserver", coords); _eye.SetMaxZoom(ent, Vector2.One * 5); @@ -73,7 +73,7 @@ public sealed partial class ReplaySpectatorSystem if (gridAttach) _transform.AttachToGridOrMap(ent); - _player.LocalPlayer.AttachEntity(ent, EntityManager, _client); + _player.SetAttachedEntity(_player.LocalSession, ent); if (old != null) { @@ -93,7 +93,7 @@ public sealed partial class ReplaySpectatorSystem { if (args.Length == 0) { - if (_player.LocalPlayer?.ControlledEntity is { } current) + if (_player.LocalSession?.AttachedEntity is { } current) SpawnSpectatorGhost(new EntityCoordinates(current, default), true); else SpawnSpectatorGhost(default, true); diff --git a/Content.Client/Replay/Spectator/ReplaySpectatorSystem.cs b/Content.Client/Replay/Spectator/ReplaySpectatorSystem.cs index c75529c037..3b9662ed8c 100644 --- a/Content.Client/Replay/Spectator/ReplaySpectatorSystem.cs +++ b/Content.Client/Replay/Spectator/ReplaySpectatorSystem.cs @@ -6,7 +6,6 @@ using Robust.Client.Player; using Robust.Client.Replays.Playback; using Robust.Client.State; using Robust.Shared.Console; -using Robust.Shared.Network; using Robust.Shared.Serialization.Markdown.Mapping; namespace Content.Client.Replay.Spectator; @@ -40,7 +39,7 @@ public sealed partial class ReplaySpectatorSystem : EntitySystem SubscribeLocalEvent>(OnGetAlternativeVerbs); SubscribeLocalEvent(OnTerminating); - SubscribeLocalEvent(OnDetached); + SubscribeLocalEvent(OnDetached); SubscribeLocalEvent(OnParentChanged); InitializeBlockers(); diff --git a/Content.Client/Sandbox/SandboxSystem.cs b/Content.Client/Sandbox/SandboxSystem.cs index 7dcbfa0ee0..d16751e371 100644 --- a/Content.Client/Sandbox/SandboxSystem.cs +++ b/Content.Client/Sandbox/SandboxSystem.cs @@ -5,7 +5,7 @@ using Robust.Client.Console; using Robust.Client.Placement; using Robust.Client.Placement.Modes; using Robust.Shared.Map; -using Robust.Shared.Players; +using Robust.Shared.Player; namespace Content.Client.Sandbox { diff --git a/Content.Client/Shuttles/UI/DockingControl.cs b/Content.Client/Shuttles/UI/DockingControl.cs index 92d9959110..c0ddeff86c 100644 --- a/Content.Client/Shuttles/UI/DockingControl.cs +++ b/Content.Client/Shuttles/UI/DockingControl.cs @@ -89,7 +89,7 @@ public class DockingControl : Control // Draw the fixtures around the dock before drawing it if (_entManager.TryGetComponent(GridEntity, out var fixtures)) { - foreach (var (_, fixture) in fixtures.Fixtures) + foreach (var fixture in fixtures.Fixtures.Values) { var poly = (PolygonShape) fixture.Shape; @@ -151,7 +151,7 @@ public class DockingControl : Control var xformQuery = _entManager.GetEntityQuery(); _grids.Clear(); - _mapManager.FindGridsIntersecting(gridXform.MapID, new Box2(worldPos - RangeVector, worldPos + RangeVector)); + _mapManager.FindGridsIntersecting(gridXform.MapID, new Box2(worldPos - RangeVector, worldPos + RangeVector), ref _grids); foreach (var grid in _grids) { diff --git a/Content.Client/Storage/StorageBoundUserInterface.cs b/Content.Client/Storage/StorageBoundUserInterface.cs index 1842417a6e..9a3340e5b0 100644 --- a/Content.Client/Storage/StorageBoundUserInterface.cs +++ b/Content.Client/Storage/StorageBoundUserInterface.cs @@ -61,9 +61,9 @@ namespace Content.Client.Storage _window?.BuildEntityList(uid, component); } - public void InteractWithItem(BaseButton.ButtonEventArgs args, ListData cData) + public void InteractWithItem(BaseButton.ButtonEventArgs? args, ListData? cData) { - if (cData is not EntityListData { Uid: var entity }) + if (args == null || cData is not EntityListData { Uid: var entity }) return; if (args.Event.Function == EngineKeyFunctions.UIClick) diff --git a/Content.Client/Tools/ToolSystem.cs b/Content.Client/Tools/ToolSystem.cs index f4dc480b41..966f37146e 100644 --- a/Content.Client/Tools/ToolSystem.cs +++ b/Content.Client/Tools/ToolSystem.cs @@ -5,6 +5,7 @@ using Content.Shared.Tools; using Content.Shared.Tools.Components; using Robust.Client.GameObjects; using Robust.Shared.GameStates; +using SharedToolSystem = Content.Shared.Tools.Systems.SharedToolSystem; namespace Content.Client.Tools { diff --git a/Content.Client/Traits/ParacusiaSystem.cs b/Content.Client/Traits/ParacusiaSystem.cs index 34c7d6859e..87abec80bb 100644 --- a/Content.Client/Traits/ParacusiaSystem.cs +++ b/Content.Client/Traits/ParacusiaSystem.cs @@ -1,8 +1,6 @@ using System.Numerics; using Content.Shared.Traits.Assorted; -using Content.Client.Camera; using Robust.Shared.Random; -using Robust.Client.GameObjects; using Robust.Client.Player; using Robust.Shared.Timing; @@ -19,7 +17,7 @@ public sealed class ParacusiaSystem : SharedParacusiaSystem { base.Initialize(); SubscribeLocalEvent(OnComponentStartup); - SubscribeLocalEvent(OnPlayerDetach); + SubscribeLocalEvent(OnPlayerDetach); } public override void Update(float frameTime) @@ -40,7 +38,7 @@ public sealed class ParacusiaSystem : SharedParacusiaSystem component.NextIncidentTime = _timing.CurTime + TimeSpan.FromSeconds(_random.NextFloat(component.MinTimeBetweenIncidents, component.MaxTimeBetweenIncidents)); } - private void OnPlayerDetach(EntityUid uid, ParacusiaComponent component, PlayerDetachedEvent args) + private void OnPlayerDetach(EntityUid uid, ParacusiaComponent component, LocalPlayerDetachedEvent args) { component.Stream?.Stop(); } diff --git a/Content.Client/UserInterface/Controls/ListContainer.cs b/Content.Client/UserInterface/Controls/ListContainer.cs index d1bb103926..c66ef33d3f 100644 --- a/Content.Client/UserInterface/Controls/ListContainer.cs +++ b/Content.Client/UserInterface/Controls/ListContainer.cs @@ -22,7 +22,7 @@ public sealed class ListContainer : Control } public bool Toggle { get; set; } public Action? GenerateItem; - public Action? ItemPressed; + public Action? ItemPressed; public IReadOnlyList Data => _data; private const int DefaultSeparation = 3; @@ -92,6 +92,12 @@ public sealed class ListContainer : Control _data = data.ToList(); _updateChildren = true; InvalidateArrange(); + + if (_selected != null && !data.Contains(_selected)) + { + _selected = null; + ItemPressed?.Invoke(null, null); + } } public void DirtyList() diff --git a/Content.Client/UserInterface/Systems/Character/CharacterUIController.cs b/Content.Client/UserInterface/Systems/Character/CharacterUIController.cs index 925b2dae4f..45bdada6e7 100644 --- a/Content.Client/UserInterface/Systems/Character/CharacterUIController.cs +++ b/Content.Client/UserInterface/Systems/Character/CharacterUIController.cs @@ -8,6 +8,7 @@ using Content.Client.UserInterface.Systems.Objectives.Controls; using Content.Shared.Input; using JetBrains.Annotations; using Robust.Client.GameObjects; +using Robust.Client.Player; using Robust.Client.UserInterface; using Robust.Client.UserInterface.Controllers; using Robust.Client.UserInterface.Controls; @@ -21,6 +22,7 @@ namespace Content.Client.UserInterface.Systems.Character; [UsedImplicitly] public sealed class CharacterUIController : UIController, IOnStateEntered, IOnStateExited, IOnSystemChanged { + [Dependency] private readonly IPlayerManager _player = default!; [UISystemDependency] private readonly CharacterInfoSystem _characterInfo = default!; [UISystemDependency] private readonly SpriteSystem _sprite = default!; @@ -56,13 +58,13 @@ public sealed class CharacterUIController : UIController, IOnStateEntered(OnChatMessage); _net.RegisterNetMessage(OnDeleteChatMessagesBy); @@ -170,7 +171,7 @@ public sealed class ChatUIController : UIController _speechBubbleRoot = new LayoutContainer(); - OnLocalPlayerChanged(new LocalPlayerChangedEventArgs(null, _player.LocalPlayer)); + UpdateChannelPermissions(); _input.SetInputCommand(ContentKeyFunctions.FocusChat, InputCmdHandler.FromDelegate(_ => FocusChat())); @@ -363,29 +364,7 @@ public sealed class ChatUIController : UIController _speechBubbleRoot.SetPositionLast(); } - private void OnLocalPlayerChanged(LocalPlayerChangedEventArgs obj) - { - if (obj.OldPlayer != null) - { - obj.OldPlayer.EntityAttached -= OnLocalPlayerEntityAttached; - obj.OldPlayer.EntityDetached -= OnLocalPlayerEntityDetached; - } - - if (obj.NewPlayer != null) - { - obj.NewPlayer.EntityAttached += OnLocalPlayerEntityAttached; - obj.NewPlayer.EntityDetached += OnLocalPlayerEntityDetached; - } - - UpdateChannelPermissions(); - } - - private void OnLocalPlayerEntityAttached(EntityAttachedEventArgs obj) - { - UpdateChannelPermissions(); - } - - private void OnLocalPlayerEntityDetached(EntityDetachedEventArgs obj) + private void OnAttachedChanged(EntityUid uid) { UpdateChannelPermissions(); } diff --git a/Content.Client/UserInterface/Systems/DamageOverlays/DamageOverlayUiController.cs b/Content.Client/UserInterface/Systems/DamageOverlays/DamageOverlayUiController.cs index 0836314dbc..ba4a871199 100644 --- a/Content.Client/UserInterface/Systems/DamageOverlays/DamageOverlayUiController.cs +++ b/Content.Client/UserInterface/Systems/DamageOverlays/DamageOverlayUiController.cs @@ -1,11 +1,9 @@ -using Content.Client.Alerts; using Content.Shared.Damage; using Content.Shared.FixedPoint; using Content.Shared.Mobs; using Content.Shared.Mobs.Components; using Content.Shared.Mobs.Systems; using JetBrains.Annotations; -using Robust.Client.GameObjects; using Robust.Client.Graphics; using Robust.Client.Player; using Robust.Client.UserInterface; @@ -25,13 +23,13 @@ public sealed class DamageOverlayUiController : UIController public override void Initialize() { _overlay = new Overlays.DamageOverlay(); - SubscribeLocalEvent(OnPlayerAttach); - SubscribeLocalEvent(OnPlayerDetached); + SubscribeLocalEvent(OnPlayerAttach); + SubscribeLocalEvent(OnPlayerDetached); SubscribeLocalEvent(OnMobStateChanged); SubscribeLocalEvent(OnThresholdCheck); } - private void OnPlayerAttach(PlayerAttachedEvent args) + private void OnPlayerAttach(LocalPlayerAttachedEvent args) { ClearOverlay(); if (!EntityManager.TryGetComponent(args.Entity, out var mobState)) @@ -41,7 +39,7 @@ public sealed class DamageOverlayUiController : UIController _overlayManager.AddOverlay(_overlay); } - private void OnPlayerDetached(PlayerDetachedEvent args) + private void OnPlayerDetached(LocalPlayerDetachedEvent args) { _overlayManager.RemoveOverlay(_overlay); ClearOverlay(); diff --git a/Content.Client/UserInterface/Systems/Sandbox/SandboxUIController.cs b/Content.Client/UserInterface/Systems/Sandbox/SandboxUIController.cs index d7ec9f3497..778de82210 100644 --- a/Content.Client/UserInterface/Systems/Sandbox/SandboxUIController.cs +++ b/Content.Client/UserInterface/Systems/Sandbox/SandboxUIController.cs @@ -17,7 +17,7 @@ using Robust.Client.UserInterface.Controllers; using Robust.Client.UserInterface.Controllers.Implementations; using Robust.Shared.Input.Binding; using Robust.Shared.Map; -using Robust.Shared.Players; +using Robust.Shared.Player; using Robust.Shared.Utility; using static Robust.Client.UserInterface.Controls.BaseButton; diff --git a/Content.Client/VendingMachines/UI/VendingMachineMenu.xaml b/Content.Client/VendingMachines/UI/VendingMachineMenu.xaml index dcd6ed91a7..abc7252e40 100644 --- a/Content.Client/VendingMachines/UI/VendingMachineMenu.xaml +++ b/Content.Client/VendingMachines/UI/VendingMachineMenu.xaml @@ -1,6 +1,6 @@  - + diff --git a/Content.Client/VendingMachines/UI/VendingMachineMenu.xaml.cs b/Content.Client/VendingMachines/UI/VendingMachineMenu.xaml.cs index 60b81af6bd..5ef66d5f74 100644 --- a/Content.Client/VendingMachines/UI/VendingMachineMenu.xaml.cs +++ b/Content.Client/VendingMachines/UI/VendingMachineMenu.xaml.cs @@ -6,7 +6,6 @@ using Robust.Client.Graphics; using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.CustomControls; using Robust.Client.UserInterface.XAML; -using Robust.Shared.Graphics; using Robust.Shared.Prototypes; namespace Content.Client.VendingMachines.UI @@ -33,7 +32,6 @@ namespace Content.Client.VendingMachines.UI VendingContents.OnItemSelected += args => { - SearchBar.Text = string.Empty; OnItemSelected?.Invoke(args); }; } @@ -42,8 +40,10 @@ namespace Content.Client.VendingMachines.UI /// Populates the list of available items on the vending machine interface /// and sets icons based on their prototypes /// - public void Populate(List inventory, string? filter = null) + public void Populate(List inventory, out List filteredInventory, string? filter = null) { + filteredInventory = new(); + if (inventory.Count == 0) { VendingContents.Clear(); @@ -94,6 +94,7 @@ namespace Content.Client.VendingMachines.UI vendingItem.Text = $"{itemName} [{entry.Amount}]"; vendingItem.Icon = icon; + filteredInventory.Add(i); } SetSizeAfterUpdate(longestEntry.Length, inventory.Count); diff --git a/Content.Client/VendingMachines/VendingMachineBoundUserInterface.cs b/Content.Client/VendingMachines/VendingMachineBoundUserInterface.cs index ab310144d5..6f28ddb31f 100644 --- a/Content.Client/VendingMachines/VendingMachineBoundUserInterface.cs +++ b/Content.Client/VendingMachines/VendingMachineBoundUserInterface.cs @@ -1,6 +1,5 @@ using Content.Client.VendingMachines.UI; using Content.Shared.VendingMachines; -using Robust.Client.GameObjects; using Robust.Client.UserInterface.Controls; using System.Linq; @@ -14,6 +13,9 @@ namespace Content.Client.VendingMachines [ViewVariables] private List _cachedInventory = new(); + [ViewVariables] + private List _cachedFilteredIndex = new(); + public VendingMachineBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey) { } @@ -32,7 +34,7 @@ namespace Content.Client.VendingMachines _menu.OnItemSelected += OnItemSelected; _menu.OnSearchChanged += OnSearchChanged; - _menu.Populate(_cachedInventory); + _menu.Populate(_cachedInventory, out _cachedFilteredIndex); _menu.OpenCentered(); } @@ -46,7 +48,7 @@ namespace Content.Client.VendingMachines _cachedInventory = newState.Inventory; - _menu?.Populate(_cachedInventory); + _menu?.Populate(_cachedInventory, out _cachedFilteredIndex, _menu.SearchBar.Text); } private void OnItemSelected(ItemList.ItemListSelectedEventArgs args) @@ -54,7 +56,7 @@ namespace Content.Client.VendingMachines if (_cachedInventory.Count == 0) return; - var selectedItem = _cachedInventory.ElementAtOrDefault(args.ItemIndex); + var selectedItem = _cachedInventory.ElementAtOrDefault(_cachedFilteredIndex.ElementAtOrDefault(args.ItemIndex)); if (selectedItem == null) return; @@ -78,7 +80,7 @@ namespace Content.Client.VendingMachines private void OnSearchChanged(string? filter) { - _menu?.Populate(_cachedInventory, filter); + _menu?.Populate(_cachedInventory, out _cachedFilteredIndex, filter); } } } diff --git a/Content.Client/Weapons/Melee/MeleeWeaponSystem.cs b/Content.Client/Weapons/Melee/MeleeWeaponSystem.cs index 397032cd15..2d2883d8b7 100644 --- a/Content.Client/Weapons/Melee/MeleeWeaponSystem.cs +++ b/Content.Client/Weapons/Melee/MeleeWeaponSystem.cs @@ -16,7 +16,8 @@ using Robust.Client.State; using Robust.Shared.Input; using Robust.Shared.Map; using Robust.Shared.Player; -using Robust.Shared.Players; +using Robust.Shared.Prototypes; +using Robust.Shared.Timing; namespace Content.Client.Weapons.Melee; diff --git a/Content.IntegrationTests/Pair/TestPair.cs b/Content.IntegrationTests/Pair/TestPair.cs index 2971573ff2..2672b4db56 100644 --- a/Content.IntegrationTests/Pair/TestPair.cs +++ b/Content.IntegrationTests/Pair/TestPair.cs @@ -3,13 +3,11 @@ using System.Collections.Generic; using System.IO; using System.Linq; using Content.Server.GameTicking; -using Content.Server.Players; -using Content.Shared.Mind; using Content.Shared.Players; -using Robust.Server.Player; using Robust.Shared.GameObjects; using Robust.Shared.IoC; using Robust.Shared.Network; +using Robust.Shared.Player; using Robust.Shared.Timing; using Robust.UnitTesting; @@ -30,8 +28,8 @@ public sealed partial class TestPair public RobustIntegrationTest.ServerIntegrationInstance Server { get; private set; } = default!; public RobustIntegrationTest.ClientIntegrationInstance Client { get; private set; } = default!; - public IPlayerSession? Player => (IPlayerSession?) Server.PlayerMan.Sessions.FirstOrDefault(); - public PlayerData? PlayerData => Player?.Data.ContentData(); + public ICommonSession? Player => Server.PlayerMan.Sessions.FirstOrDefault(); + public ContentPlayerData? PlayerData => Player?.Data.ContentData(); public PoolTestLogHandler ServerLogHandler { get; private set; } = default!; public PoolTestLogHandler ClientLogHandler { get; private set; } = default!; diff --git a/Content.IntegrationTests/Tests/Actions/ActionsAddedTest.cs b/Content.IntegrationTests/Tests/Actions/ActionsAddedTest.cs index 01f8bdd938..01daeea93c 100644 --- a/Content.IntegrationTests/Tests/Actions/ActionsAddedTest.cs +++ b/Content.IntegrationTests/Tests/Actions/ActionsAddedTest.cs @@ -3,8 +3,6 @@ using Content.Shared.Actions; using Content.Shared.CombatMode; using Robust.Server.Player; using Robust.Shared.GameObjects; -using Robust.Shared.Players; -using PlayerManager = Robust.Client.Player.PlayerManager; namespace Content.IntegrationTests.Tests.Actions; @@ -26,7 +24,7 @@ public sealed class ActionsAddedTest var sEntMan = server.ResolveDependency(); var cEntMan = client.ResolveDependency(); var clientSession = client.ResolveDependency().LocalPlayer?.Session; - var serverSession = server.ResolveDependency().ServerSessions.Single(); + var serverSession = server.ResolveDependency().Sessions.Single(); var sActionSystem = server.System(); var cActionSystem = client.System(); diff --git a/Content.IntegrationTests/Tests/Administration/Logs/AddTests.cs b/Content.IntegrationTests/Tests/Administration/Logs/AddTests.cs index 6562a26b5e..98c7363a6c 100644 --- a/Content.IntegrationTests/Tests/Administration/Logs/AddTests.cs +++ b/Content.IntegrationTests/Tests/Administration/Logs/AddTests.cs @@ -7,8 +7,6 @@ using Content.Shared.Administration.Logs; using Content.Shared.Database; using Robust.Server.Player; using Robust.Shared.GameObjects; -using Robust.Shared.Map; -using Robust.Shared.Utility; namespace Content.IntegrationTests.Tests.Administration.Logs; @@ -177,7 +175,7 @@ public sealed class AddTests await server.WaitPost(() => { - var player = sPlayers.ServerSessions.First(); + var player = sPlayers.Sessions.First(); playerGuid = player.UserId; Assert.DoesNotThrow(() => @@ -280,7 +278,7 @@ public sealed class AddTests await server.WaitPost(() => { - var player = sPlayers.ServerSessions.Single(); + var player = sPlayers.Sessions.Single(); sAdminLogSystem.Add(LogType.Unknown, $"{player} {player} test log: {guid}"); }); @@ -318,7 +316,7 @@ public sealed class AddTests await server.WaitPost(() => { - var player = sPlayers.ServerSessions.Single(); + var player = sPlayers.Sessions.Single(); sAdminLogSystem.Add(LogType.Unknown, $"{player:first} {player:second} test log: {guid}"); }); diff --git a/Content.IntegrationTests/Tests/Administration/Logs/QueryTests.cs b/Content.IntegrationTests/Tests/Administration/Logs/QueryTests.cs index 1155edfad2..5a58757d53 100644 --- a/Content.IntegrationTests/Tests/Administration/Logs/QueryTests.cs +++ b/Content.IntegrationTests/Tests/Administration/Logs/QueryTests.cs @@ -5,6 +5,7 @@ using Content.Server.GameTicking; using Content.Shared.Database; using Robust.Server.Player; using Robust.Shared.GameObjects; +using Robust.Shared.Player; namespace Content.IntegrationTests.Tests.Administration.Logs; @@ -27,11 +28,11 @@ public sealed class QueryTests var date = DateTime.UtcNow; var guid = Guid.NewGuid(); - IPlayerSession player = default; + ICommonSession player = default; await server.WaitPost(() => { - player = sPlayers.ServerSessions.First(); + player = sPlayers.Sessions.First(); sAdminLogSystem.Add(LogType.Unknown, $"{player.AttachedEntity:Entity} test log: {guid}"); }); diff --git a/Content.IntegrationTests/Tests/Cleanup/EuiManagerTest.cs b/Content.IntegrationTests/Tests/Cleanup/EuiManagerTest.cs index 9aac4e2892..e2bff03501 100644 --- a/Content.IntegrationTests/Tests/Cleanup/EuiManagerTest.cs +++ b/Content.IntegrationTests/Tests/Cleanup/EuiManagerTest.cs @@ -25,7 +25,7 @@ public sealed class EuiManagerTest await server.WaitAssertion(() => { - var clientSession = sPlayerManager.ServerSessions.Single(); + var clientSession = sPlayerManager.Sessions.Single(); var ui = new AdminAnnounceEui(); eui.OpenEui(ui, clientSession); }); diff --git a/Content.IntegrationTests/Tests/Interaction/InteractionTest.cs b/Content.IntegrationTests/Tests/Interaction/InteractionTest.cs index b4b6c2239f..df77410e54 100644 --- a/Content.IntegrationTests/Tests/Interaction/InteractionTest.cs +++ b/Content.IntegrationTests/Tests/Interaction/InteractionTest.cs @@ -14,6 +14,7 @@ using Content.Shared.Hands.Components; using Content.Shared.Hands.EntitySystems; using Content.Shared.Interaction; using Content.Shared.Mind; +using Content.Shared.Players; using Robust.Client.Input; using Robust.Client.UserInterface; using Robust.Server.GameObjects; @@ -21,7 +22,7 @@ using Robust.Server.Player; using Robust.Shared.GameObjects; using Robust.Shared.Log; using Robust.Shared.Map; -using Robust.Shared.Players; +using Robust.Shared.Player; using Robust.Shared.Prototypes; using Robust.Shared.Timing; using Robust.UnitTesting; @@ -67,7 +68,7 @@ public abstract partial class InteractionTest protected NetEntity Player; protected ICommonSession ClientSession = default!; - protected IPlayerSession ServerSession = default!; + protected ICommonSession ServerSession = default!; public EntityUid? ClientTarget; diff --git a/Content.IntegrationTests/Tests/Minds/GhostRoleTests.cs b/Content.IntegrationTests/Tests/Minds/GhostRoleTests.cs index 28e49645c9..22a185798e 100644 --- a/Content.IntegrationTests/Tests/Minds/GhostRoleTests.cs +++ b/Content.IntegrationTests/Tests/Minds/GhostRoleTests.cs @@ -5,6 +5,7 @@ using Content.Server.Ghost.Roles.Components; using Content.Server.Players; using Content.Shared.Ghost; using Content.Shared.Mind; +using Content.Shared.Players; using Robust.Shared.Console; using Robust.Shared.GameObjects; using Robust.Shared.Map; @@ -43,7 +44,7 @@ public sealed class GhostRoleTests var sPlayerMan = server.ResolveDependency(); var conHost = client.ResolveDependency(); var mindSystem = entMan.System(); - var session = sPlayerMan.ServerSessions.Single(); + var session = sPlayerMan.Sessions.Single(); var originalMindId = session.ContentData()!.Mind!.Value; // Spawn player entity & attach diff --git a/Content.IntegrationTests/Tests/Minds/MindTests.EntityDeletion.cs b/Content.IntegrationTests/Tests/Minds/MindTests.EntityDeletion.cs index 9fc68ef93d..a67a45ecb4 100644 --- a/Content.IntegrationTests/Tests/Minds/MindTests.EntityDeletion.cs +++ b/Content.IntegrationTests/Tests/Minds/MindTests.EntityDeletion.cs @@ -2,6 +2,7 @@ using System.Linq; using Content.Server.Players; using Content.Shared.Ghost; using Content.Shared.Mind; +using Content.Shared.Players; using Robust.Server.Console; using Robust.Server.GameObjects; using Robust.Server.Player; @@ -35,7 +36,7 @@ public sealed partial class MindTests MindComponent mind = default!; await server.WaitAssertion(() => { - var player = playerMan.ServerSessions.Single(); + var player = playerMan.Sessions.Single(); playerEnt = entMan.SpawnEntity(null, MapCoordinates.Nullspace); visitEnt = entMan.SpawnEntity(null, MapCoordinates.Nullspace); @@ -81,7 +82,7 @@ public sealed partial class MindTests var entMan = server.ResolveDependency(); var mapManager = server.ResolveDependency(); var playerMan = server.ResolveDependency(); - var player = playerMan.ServerSessions.Single(); + var player = playerMan.Sessions.Single(); var mindSystem = entMan.EntitySysManager.GetEntitySystem(); @@ -128,7 +129,7 @@ public sealed partial class MindTests var entMan = server.ResolveDependency(); var playerMan = server.ResolveDependency(); - var player = playerMan.ServerSessions.Single(); + var player = playerMan.Sessions.Single(); Assert.That(!entMan.HasComponent(player.AttachedEntity), "Player was initially a ghost?"); @@ -162,7 +163,7 @@ public sealed partial class MindTests var mindSystem = entMan.EntitySysManager.GetEntitySystem(); var mind = GetMind(pair); - var player = playerMan.ServerSessions.Single(); + var player = playerMan.Sessions.Single(); #pragma warning disable NUnit2045 // Interdependent assertions. Assert.That(player.AttachedEntity, Is.Not.Null); Assert.That(entMan.EntityExists(player.AttachedEntity)); @@ -218,7 +219,7 @@ public sealed partial class MindTests var playerMan = server.ResolveDependency(); var serverConsole = server.ResolveDependency(); - var player = playerMan.ServerSessions.Single(); + var player = playerMan.Sessions.Single(); var ghost = await BecomeGhost(pair); @@ -263,7 +264,7 @@ public sealed partial class MindTests var playerMan = server.ResolveDependency(); var serverConsole = server.ResolveDependency(); - var player = playerMan.ServerSessions.Single(); + var player = playerMan.Sessions.Single(); EntityUid ghost = default!; diff --git a/Content.IntegrationTests/Tests/Minds/MindTests.Helpers.cs b/Content.IntegrationTests/Tests/Minds/MindTests.Helpers.cs index f71a6ad5f9..d6b30d60a0 100644 --- a/Content.IntegrationTests/Tests/Minds/MindTests.Helpers.cs +++ b/Content.IntegrationTests/Tests/Minds/MindTests.Helpers.cs @@ -1,14 +1,17 @@ using System.Linq; using Content.IntegrationTests.Pair; +using Content.Server.Mind; using Content.Server.Players; using Content.Shared.Ghost; using Content.Shared.Mind; +using Content.Shared.Players; using Robust.Server.GameObjects; using Robust.Server.Player; using Robust.Shared.Enums; using Robust.Shared.GameObjects; using Robust.Shared.Map; using Robust.Shared.Network; +using Robust.Shared.Player; namespace Content.IntegrationTests.Tests.Minds; @@ -36,7 +39,7 @@ public sealed partial class MindTests var playerMan = pair.Server.ResolveDependency(); var mindSys = entMan.System(); - var player = playerMan.ServerSessions.Single(); + var player = playerMan.Sessions.Single(); EntityUid entity = default; EntityUid mindId = default!; @@ -71,7 +74,7 @@ public sealed partial class MindTests EntityUid mindId = default!; MindComponent mind = default!; - var player = playerMan.ServerSessions.Single(); + var player = playerMan.Sessions.Single(); await pair.Server.WaitAssertion(() => { var oldUid = player.AttachedEntity; @@ -116,20 +119,25 @@ public sealed partial class MindTests /// private static (EntityUid Id, MindComponent Comp) GetMind(Pair.TestPair pair) { - var playerMan = pair.Server.ResolveDependency(); - var entMan = pair.Server.ResolveDependency(); - var player = playerMan.ServerSessions.SingleOrDefault(); + var playerMan = pair.Server.PlayerMan; + var entMan = pair.Server.EntMan; + var player = playerMan.Sessions.SingleOrDefault(); Assert.That(player, Is.Not.Null); var mindId = player.ContentData()!.Mind!.Value; Assert.That(mindId, Is.Not.EqualTo(default(EntityUid))); var mind = entMan.GetComponent(mindId); + ActorComponent actor = default!; Assert.Multiple(() => { + Assert.That(player, Is.EqualTo(mind.Session), "Player session does not match mind session"); + Assert.That(entMan.System().GetMind(player.UserId), Is.EqualTo(mindId)); Assert.That(player.AttachedEntity, Is.EqualTo(mind.CurrentEntity), "Player is not attached to the mind's current entity."); Assert.That(entMan.EntityExists(mind.OwnedEntity), "The mind's current entity does not exist"); Assert.That(mind.VisitingEntity == null || entMan.EntityExists(mind.VisitingEntity), "The minds visited entity does not exist."); + Assert.That(entMan.TryGetComponent(mind.CurrentEntity, out actor)); }); + Assert.That(actor.PlayerSession, Is.EqualTo(mind.Session)); return (mindId, mind); } @@ -139,7 +147,7 @@ public sealed partial class MindTests var netManager = pair.Client.ResolveDependency(); var playerMan = pair.Server.ResolveDependency(); var entMan = pair.Server.ResolveDependency(); - var player = playerMan.ServerSessions.Single(); + var player = playerMan.Sessions.Single(); var mindId = player.ContentData()!.Mind!.Value; var mind = entMan.GetComponent(mindId); @@ -161,21 +169,21 @@ public sealed partial class MindTests { var netManager = pair.Client.ResolveDependency(); var playerMan = pair.Server.ResolveDependency(); - Assert.That(!playerMan.ServerSessions.Any()); + Assert.That(!playerMan.Sessions.Any()); await Task.WhenAll(pair.Client.WaitIdleAsync(), pair.Client.WaitIdleAsync()); pair.Client.SetConnectTarget(pair.Server); await pair.Client.WaitPost(() => netManager.ClientConnect(null!, 0, username)); await pair.RunTicksSync(5); - var player = playerMan.ServerSessions.Single(); + var player = playerMan.Sessions.Single(); Assert.That(player.Status, Is.EqualTo(SessionStatus.InGame)); } - private static async Task DisconnectReconnect(Pair.TestPair pair) + private static async Task DisconnectReconnect(Pair.TestPair pair) { var playerMan = pair.Server.ResolveDependency(); - var player = playerMan.ServerSessions.Single(); + var player = playerMan.Sessions.Single(); var name = player.Name; var id = player.UserId; @@ -183,7 +191,7 @@ public sealed partial class MindTests await Connect(pair, name); // Session has changed - var newSession = playerMan.ServerSessions.Single(); + var newSession = playerMan.Sessions.Single(); Assert.Multiple(() => { Assert.That(newSession, Is.Not.EqualTo(player)); diff --git a/Content.IntegrationTests/Tests/Minds/MindTests.ReconnectTests.cs b/Content.IntegrationTests/Tests/Minds/MindTests.ReconnectTests.cs index ea2110c03a..3cac766825 100644 --- a/Content.IntegrationTests/Tests/Minds/MindTests.ReconnectTests.cs +++ b/Content.IntegrationTests/Tests/Minds/MindTests.ReconnectTests.cs @@ -1,6 +1,8 @@ using System.Linq; using Content.Shared.Ghost; using Content.Shared.Mind; +using NUnit.Framework.Interfaces; +using Robust.Server.GameObjects; using Robust.Server.Player; using Robust.Shared.GameObjects; using Robust.Shared.Map; @@ -49,7 +51,7 @@ public sealed partial class MindTests var mind = GetMind(pair); var playerMan = pair.Server.ResolveDependency(); - var player = playerMan.ServerSessions.Single(); + var player = playerMan.Sessions.Single(); var name = player.Name; var user = player.UserId; Assert.That(mind.Comp.OwnedEntity, Is.Not.Null); @@ -72,7 +74,7 @@ public sealed partial class MindTests // Reconnect await Connect(pair, name); - player = playerMan.ServerSessions.Single(); + player = playerMan.Sessions.Single(); Assert.Multiple(() => { Assert.That(user, Is.EqualTo(player.UserId)); @@ -127,8 +129,10 @@ public sealed partial class MindTests var mindSys = entMan.System(); var mind = GetMind(pair); + Assert.Null(mind.Comp.VisitingEntity); + // Make player visit a new mob - var original = mind.Comp.CurrentEntity; + var original = mind.Comp.OwnedEntity; EntityUid visiting = default; await pair.Server.WaitAssertion(() => { @@ -137,6 +141,7 @@ public sealed partial class MindTests }); await pair.RunTicksSync(5); + Assert.That(mind.Comp.VisitingEntity, Is.EqualTo(visiting)); await DisconnectReconnect(pair); // Player is back in control of the visited mob, mind was preserved @@ -150,4 +155,32 @@ public sealed partial class MindTests await pair.CleanReturnAsync(); } + + // This test will do the following + // - connect as a normal player + // - disconnect + // - reconnect + // - assert that they return to the original entity. + [Test] + public async Task TestReconnect() + { + await using var pair = await SetupPair(); + var mind = GetMind(pair); + + Assert.Null(mind.Comp.VisitingEntity); + Assert.NotNull(mind.Comp.OwnedEntity); + var entity = mind.Comp.OwnedEntity; + + await pair.RunTicksSync(5); + await DisconnectReconnect(pair); + await pair.RunTicksSync(5); + + var newMind = GetMind(pair); + + Assert.Null(newMind.Comp.VisitingEntity); + Assert.That(newMind.Comp.OwnedEntity, Is.EqualTo(entity)); + Assert.That(newMind.Id, Is.EqualTo(mind.Id)); + + await pair.CleanReturnAsync(); + } } diff --git a/Content.IntegrationTests/Tests/Minds/MindTests.cs b/Content.IntegrationTests/Tests/Minds/MindTests.cs index fb2fef43ed..c9788b80a6 100644 --- a/Content.IntegrationTests/Tests/Minds/MindTests.cs +++ b/Content.IntegrationTests/Tests/Minds/MindTests.cs @@ -11,6 +11,7 @@ using Content.Shared.Damage.Prototypes; using Content.Shared.FixedPoint; using Content.Shared.Mind; using Content.Shared.Mind.Components; +using Content.Shared.Players; using Content.Shared.Roles; using Content.Shared.Roles.Jobs; using Robust.Server.Console; @@ -67,13 +68,12 @@ public sealed partial class MindTests var entity = entMan.SpawnEntity(null, new MapCoordinates()); var mindComp = entMan.EnsureComponent(entity); - var mindId = mindSystem.CreateMind(null); - var mind = entMan.GetComponent(mindId); + var mind = mindSystem.CreateMind(null); - Assert.That(mind.UserId, Is.EqualTo(null)); + Assert.That(mind.Comp.UserId, Is.EqualTo(null)); - mindSystem.TransferTo(mindId, entity, mind: mind); - Assert.That(mindSystem.GetMind(entity, mindComp), Is.EqualTo(mindId)); + mindSystem.TransferTo(mind, entity, mind: mind); + Assert.That(mindSystem.GetMind(entity, mindComp), Is.EqualTo(mind.Owner)); }); await pair.CleanReturnAsync(); @@ -94,11 +94,11 @@ public sealed partial class MindTests var entity = entMan.SpawnEntity(null, new MapCoordinates()); var mindComp = entMan.EnsureComponent(entity); - var mindId = mindSystem.CreateMind(null); + var mindId = mindSystem.CreateMind(null).Owner; mindSystem.TransferTo(mindId, entity); Assert.That(mindSystem.GetMind(entity, mindComp), Is.EqualTo(mindId)); - var mind2 = mindSystem.CreateMind(null); + var mind2 = mindSystem.CreateMind(null).Owner; mindSystem.TransferTo(mind2, entity); Assert.Multiple(() => { @@ -184,7 +184,7 @@ public sealed partial class MindTests var mindComp = entMan.EnsureComponent(entity); entMan.EnsureComponent(targetEntity); - var mind = mindSystem.CreateMind(null); + var mind = mindSystem.CreateMind(null).Owner; mindSystem.TransferTo(mind, entity); @@ -276,7 +276,7 @@ public sealed partial class MindTests var entity = entMan.SpawnEntity(null, new MapCoordinates()); var mindComp = entMan.EnsureComponent(entity); - var mindId = mindSystem.CreateMind(null); + var mindId = mindSystem.CreateMind(null).Owner; var mind = entMan.EnsureComponent(mindId); Assert.That(mind.UserId, Is.EqualTo(null)); @@ -334,7 +334,7 @@ public sealed partial class MindTests public async Task TestPlayerCanGhost() { // Client is needed to spawn session - await using var pair = await PoolManager.GetServerClient(new PoolSettings { Connected = true }); + await using var pair = await PoolManager.GetServerClient(new PoolSettings { Connected = true, DummyTicker = false }); var server = pair.Server; var entMan = server.ResolveDependency(); @@ -346,7 +346,7 @@ public sealed partial class MindTests EntityUid entity = default!; EntityUid mindId = default!; MindComponent mind = default!; - var player = playerMan.ServerSessions.Single(); + var player = playerMan.Sessions.Single(); await server.WaitAssertion(() => { @@ -407,12 +407,6 @@ public sealed partial class MindTests await pair.CleanReturnAsync(); } - // TODO Implement - /*[Test] - public async Task TestPlayerCanReturnFromGhostWhenDead() - { - }*/ - [Test] public async Task TestGhostDoesNotInfiniteLoop() { @@ -433,7 +427,7 @@ public sealed partial class MindTests EntityUid ghost = default!; EntityUid mindId = default!; MindComponent mind = default!; - var player = playerMan.ServerSessions.Single(); + var player = playerMan.Sessions.Single(); await server.WaitAssertion(() => { diff --git a/Content.IntegrationTests/Tests/Toolshed/ToolshedTest.cs b/Content.IntegrationTests/Tests/Toolshed/ToolshedTest.cs index ca7eeac199..d6aec781a9 100644 --- a/Content.IntegrationTests/Tests/Toolshed/ToolshedTest.cs +++ b/Content.IntegrationTests/Tests/Toolshed/ToolshedTest.cs @@ -2,8 +2,7 @@ using System.Collections.Generic; using Content.IntegrationTests.Pair; using Content.Server.Administration.Managers; -using Robust.Server.Player; -using Robust.Shared.Players; +using Robust.Shared.Player; using Robust.Shared.Toolshed; using Robust.Shared.Toolshed.Errors; using Robust.Shared.Toolshed.Syntax; @@ -60,7 +59,7 @@ public abstract class ToolshedTest : IInvocationContext AdminManager = Server.ResolveDependency(); } - protected bool InvokeCommand(string command, out object? result, IPlayerSession? session = null) + protected bool InvokeCommand(string command, out object? result, ICommonSession? session = null) { return Toolshed.InvokeCommand(this, command, null, out result); } @@ -95,7 +94,7 @@ public abstract class ToolshedTest : IInvocationContext return true; } - protected IPlayerSession? InvocationSession { get; set; } + protected ICommonSession? InvocationSession { get; set; } public ICommonSession? Session { diff --git a/Content.MapRenderer/Painters/MapPainter.cs b/Content.MapRenderer/Painters/MapPainter.cs index b799db78a5..8f3dd59baf 100644 --- a/Content.MapRenderer/Painters/MapPainter.cs +++ b/Content.MapRenderer/Painters/MapPainter.cs @@ -68,7 +68,7 @@ namespace Content.MapRenderer.Painters await server.WaitPost(() => { - var playerEntity = sPlayerManager.ServerSessions.Single().AttachedEntity; + var playerEntity = sPlayerManager.Sessions.Single().AttachedEntity; if (playerEntity.HasValue) { diff --git a/Content.Server.Database/Migrations/Postgres/20231021071411_RoundStartDate.Designer.cs b/Content.Server.Database/Migrations/Postgres/20231021071411_RoundStartDate.Designer.cs new file mode 100644 index 0000000000..bf3600ba39 --- /dev/null +++ b/Content.Server.Database/Migrations/Postgres/20231021071411_RoundStartDate.Designer.cs @@ -0,0 +1,1775 @@ +// +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; + +#nullable disable + +namespace Content.Server.Database.Migrations.Postgres +{ + [DbContext(typeof(PostgresServerDbContext))] + [Migration("20231021071411_RoundStartDate")] + partial class RoundStartDate + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "7.0.4") + .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("Id") + .HasColumnType("integer") + .HasColumnName("admin_log_id"); + + b.Property("RoundId") + .HasColumnType("integer") + .HasColumnName("round_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("Id", "RoundId") + .HasName("PK_admin_log"); + + b.HasIndex("Date"); + + b.HasIndex("Message") + .HasAnnotation("Npgsql:TsVectorConfig", "english"); + + NpgsqlIndexBuilderExtensions.HasMethod(b.HasIndex("Message"), "GIN"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_admin_log_round_id"); + + b.HasIndex("Type") + .HasDatabaseName("IX_admin_log_type"); + + b.ToTable("admin_log", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLogEntity", b => + { + b.Property("Uid") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("uid"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Uid")); + + b.Property("AdminLogId") + .HasColumnType("integer") + .HasColumnName("admin_log_id"); + + b.Property("AdminLogRoundId") + .HasColumnType("integer") + .HasColumnName("admin_log_round_id"); + + b.Property("Name") + .HasColumnType("text") + .HasColumnName("name"); + + b.HasKey("Uid") + .HasName("PK_admin_log_entity"); + + b.HasIndex("AdminLogId", "AdminLogRoundId") + .HasDatabaseName("IX_admin_log_entity_admin_log_id_admin_log_round_id"); + + b.ToTable("admin_log_entity", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLogPlayer", b => + { + b.Property("PlayerUserId") + .HasColumnType("uuid") + .HasColumnName("player_user_id"); + + b.Property("LogId") + .HasColumnType("integer") + .HasColumnName("log_id"); + + b.Property("RoundId") + .HasColumnType("integer") + .HasColumnName("round_id"); + + b.HasKey("PlayerUserId", "LogId", "RoundId") + .HasName("PK_admin_log_player"); + + b.HasIndex("LogId", "RoundId"); + + 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("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", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminNote", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("admin_notes_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("CreatedById") + .HasColumnType("uuid") + .HasColumnName("created_by_id"); + + b.Property("Deleted") + .HasColumnType("boolean") + .HasColumnName("deleted"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("DeletedById") + .HasColumnType("uuid") + .HasColumnName("deleted_by_id"); + + b.Property("ExpirationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("expiration_time"); + + b.Property("LastEditedAt") + .IsRequired() + .HasColumnType("timestamp with time zone") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("uuid") + .HasColumnName("last_edited_by_id"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("message"); + + b.Property("PlayerUserId") + .HasColumnType("uuid") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("interval") + .HasColumnName("playtime_at_note"); + + b.Property("RoundId") + .HasColumnType("integer") + .HasColumnName("round_id"); + + b.Property("Secret") + .HasColumnType("boolean") + .HasColumnName("secret"); + + b.Property("Severity") + .HasColumnType("integer") + .HasColumnName("severity"); + + b.HasKey("Id") + .HasName("PK_admin_notes"); + + b.HasIndex("CreatedById"); + + b.HasIndex("DeletedById"); + + b.HasIndex("LastEditedById"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_admin_notes_player_user_id"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_admin_notes_round_id"); + + b.ToTable("admin_notes", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminRank", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("admin_rank_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.HasKey("Id") + .HasName("PK_admin_rank"); + + b.ToTable("admin_rank", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminRankFlag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("admin_rank_flag_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AdminRankId") + .HasColumnType("integer") + .HasColumnName("admin_rank_id"); + + b.Property("Flag") + .IsRequired() + .HasColumnType("text") + .HasColumnName("flag"); + + b.HasKey("Id") + .HasName("PK_admin_rank_flag"); + + b.HasIndex("AdminRankId"); + + b.HasIndex("Flag", "AdminRankId") + .IsUnique(); + + b.ToTable("admin_rank_flag", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminWatchlist", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("admin_watchlists_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("CreatedById") + .HasColumnType("uuid") + .HasColumnName("created_by_id"); + + b.Property("Deleted") + .HasColumnType("boolean") + .HasColumnName("deleted"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("DeletedById") + .HasColumnType("uuid") + .HasColumnName("deleted_by_id"); + + b.Property("ExpirationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("expiration_time"); + + b.Property("LastEditedAt") + .IsRequired() + .HasColumnType("timestamp with time zone") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("uuid") + .HasColumnName("last_edited_by_id"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("message"); + + b.Property("PlayerUserId") + .HasColumnType("uuid") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("interval") + .HasColumnName("playtime_at_note"); + + b.Property("RoundId") + .HasColumnType("integer") + .HasColumnName("round_id"); + + b.HasKey("Id") + .HasName("PK_admin_watchlists"); + + b.HasIndex("CreatedById"); + + b.HasIndex("DeletedById"); + + b.HasIndex("LastEditedById"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_admin_watchlists_player_user_id"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_admin_watchlists_round_id"); + + b.ToTable("admin_watchlists", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Antag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("antag_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AntagName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("antag_name"); + + b.Property("ProfileId") + .HasColumnType("integer") + .HasColumnName("profile_id"); + + b.HasKey("Id") + .HasName("PK_antag"); + + b.HasIndex("ProfileId", "AntagName") + .IsUnique(); + + b.ToTable("antag", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AssignedUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("assigned_user_id_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.Property("UserName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("user_name"); + + b.HasKey("Id") + .HasName("PK_assigned_user_id"); + + b.HasIndex("UserId") + .IsUnique(); + + b.HasIndex("UserName") + .IsUnique(); + + b.ToTable("assigned_user_id", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ConnectionLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("connection_log_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Address") + .IsRequired() + .HasColumnType("inet") + .HasColumnName("address"); + + b.Property("Denied") + .HasColumnType("smallint") + .HasColumnName("denied"); + + b.Property("HWId") + .HasColumnType("bytea") + .HasColumnName("hwid"); + + b.Property("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("UserId"); + + b.ToTable("connection_log", null, t => + { + t.HasCheckConstraint("AddressNotIPv6MappedIPv4", "NOT inet '::ffff:0.0.0.0/96' >>= address"); + }); + }); + + modelBuilder.Entity("Content.Server.Database.Job", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("job_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("JobName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("job_name"); + + b.Property("Priority") + .HasColumnType("integer") + .HasColumnName("priority"); + + b.Property("ProfileId") + .HasColumnType("integer") + .HasColumnName("profile_id"); + + b.HasKey("Id") + .HasName("PK_job"); + + b.HasIndex("ProfileId"); + + b.HasIndex("ProfileId", "JobName") + .IsUnique(); + + b.HasIndex(new[] { "ProfileId" }, "IX_job_one_high_priority") + .IsUnique() + .HasFilter("priority = 3"); + + b.ToTable("job", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.PlayTime", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("play_time_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("PlayerId") + .HasColumnType("uuid") + .HasColumnName("player_id"); + + b.Property("TimeSpent") + .HasColumnType("interval") + .HasColumnName("time_spent"); + + b.Property("Tracker") + .IsRequired() + .HasColumnType("text") + .HasColumnName("tracker"); + + b.HasKey("Id") + .HasName("PK_play_time"); + + b.HasIndex("PlayerId", "Tracker") + .IsUnique(); + + b.ToTable("play_time", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Player", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("player_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("FirstSeenTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("first_seen_time"); + + b.Property("LastReadRules") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_read_rules"); + + b.Property("LastSeenAddress") + .IsRequired() + .HasColumnType("inet") + .HasColumnName("last_seen_address"); + + b.Property("LastSeenHWId") + .HasColumnType("bytea") + .HasColumnName("last_seen_hwid"); + + b.Property("LastSeenTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_seen_time"); + + b.Property("LastSeenUserName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("last_seen_user_name"); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("PK_player"); + + b.HasAlternateKey("UserId") + .HasName("ak_player_user_id"); + + b.HasIndex("LastSeenUserName"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("player", null, t => + { + t.HasCheckConstraint("LastSeenAddressNotIPv6MappedIPv4", "NOT inet '::ffff:0.0.0.0/96' >>= last_seen_address"); + }); + }); + + modelBuilder.Entity("Content.Server.Database.Preference", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("preference_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AdminOOCColor") + .IsRequired() + .HasColumnType("text") + .HasColumnName("admin_ooc_color"); + + b.Property("SelectedCharacterSlot") + .HasColumnType("integer") + .HasColumnName("selected_character_slot"); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("PK_preference"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("preference", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Profile", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("profile_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Age") + .HasColumnType("integer") + .HasColumnName("age"); + + b.Property("Backpack") + .IsRequired() + .HasColumnType("text") + .HasColumnName("backpack"); + + b.Property("CharacterName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("char_name"); + + b.Property("Clothing") + .IsRequired() + .HasColumnType("text") + .HasColumnName("clothing"); + + b.Property("EyeColor") + .IsRequired() + .HasColumnType("text") + .HasColumnName("eye_color"); + + b.Property("FacialHairColor") + .IsRequired() + .HasColumnType("text") + .HasColumnName("facial_hair_color"); + + b.Property("FacialHairName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("facial_hair_name"); + + b.Property("FlavorText") + .IsRequired() + .HasColumnType("text") + .HasColumnName("flavor_text"); + + b.Property("Gender") + .IsRequired() + .HasColumnType("text") + .HasColumnName("gender"); + + b.Property("HairColor") + .IsRequired() + .HasColumnType("text") + .HasColumnName("hair_color"); + + b.Property("HairName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("hair_name"); + + b.Property("Markings") + .HasColumnType("jsonb") + .HasColumnName("markings"); + + b.Property("PreferenceId") + .HasColumnType("integer") + .HasColumnName("preference_id"); + + b.Property("PreferenceUnavailable") + .HasColumnType("integer") + .HasColumnName("pref_unavailable"); + + b.Property("Sex") + .IsRequired() + .HasColumnType("text") + .HasColumnName("sex"); + + b.Property("SkinColor") + .IsRequired() + .HasColumnType("text") + .HasColumnName("skin_color"); + + b.Property("Slot") + .HasColumnType("integer") + .HasColumnName("slot"); + + b.Property("Species") + .IsRequired() + .HasColumnType("text") + .HasColumnName("species"); + + b.HasKey("Id") + .HasName("PK_profile"); + + b.HasIndex("PreferenceId") + .HasDatabaseName("IX_profile_preference_id"); + + b.HasIndex("Slot", "PreferenceId") + .IsUnique(); + + b.ToTable("profile", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Round", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("round_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ServerId") + .HasColumnType("integer") + .HasColumnName("server_id"); + + b.Property("StartDate") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValue(new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified)) + .HasColumnName("start_date"); + + b.HasKey("Id") + .HasName("PK_round"); + + b.HasIndex("ServerId") + .HasDatabaseName("IX_round_server_id"); + + b.HasIndex("StartDate"); + + b.ToTable("round", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Server", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("server_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.HasKey("Id") + .HasName("PK_server"); + + b.ToTable("server", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBan", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("server_ban_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property?>("Address") + .HasColumnType("inet") + .HasColumnName("address"); + + b.Property("AutoDelete") + .HasColumnType("boolean") + .HasColumnName("auto_delete"); + + b.Property("BanTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("ban_time"); + + b.Property("BanningAdmin") + .HasColumnType("uuid") + .HasColumnName("banning_admin"); + + b.Property("ExemptFlags") + .HasColumnType("integer") + .HasColumnName("exempt_flags"); + + b.Property("ExpirationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("expiration_time"); + + b.Property("HWId") + .HasColumnType("bytea") + .HasColumnName("hwid"); + + b.Property("Hidden") + .HasColumnType("boolean") + .HasColumnName("hidden"); + + b.Property("LastEditedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("uuid") + .HasColumnName("last_edited_by_id"); + + b.Property("PlayerUserId") + .HasColumnType("uuid") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("interval") + .HasColumnName("playtime_at_note"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("text") + .HasColumnName("reason"); + + b.Property("RoundId") + .HasColumnType("integer") + .HasColumnName("round_id"); + + b.Property("Severity") + .HasColumnType("integer") + .HasColumnName("severity"); + + b.HasKey("Id") + .HasName("PK_server_ban"); + + b.HasIndex("Address"); + + b.HasIndex("BanningAdmin"); + + b.HasIndex("LastEditedById"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_server_ban_player_user_id"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_server_ban_round_id"); + + b.ToTable("server_ban", null, t => + { + t.HasCheckConstraint("AddressNotIPv6MappedIPv4", "NOT inet '::ffff:0.0.0.0/96' >>= address"); + + t.HasCheckConstraint("HaveEitherAddressOrUserIdOrHWId", "address IS NOT NULL OR player_user_id IS NOT NULL OR hwid IS NOT NULL"); + }); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBanExemption", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.Property("Flags") + .HasColumnType("integer") + .HasColumnName("flags"); + + b.HasKey("UserId") + .HasName("PK_server_ban_exemption"); + + b.ToTable("server_ban_exemption", null, t => + { + t.HasCheckConstraint("FlagsNotZero", "flags != 0"); + }); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBanHit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("server_ban_hit_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("BanId") + .HasColumnType("integer") + .HasColumnName("ban_id"); + + b.Property("ConnectionId") + .HasColumnType("integer") + .HasColumnName("connection_id"); + + b.HasKey("Id") + .HasName("PK_server_ban_hit"); + + b.HasIndex("BanId") + .HasDatabaseName("IX_server_ban_hit_ban_id"); + + b.HasIndex("ConnectionId") + .HasDatabaseName("IX_server_ban_hit_connection_id"); + + b.ToTable("server_ban_hit", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleBan", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("server_role_ban_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property?>("Address") + .HasColumnType("inet") + .HasColumnName("address"); + + b.Property("BanTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("ban_time"); + + b.Property("BanningAdmin") + .HasColumnType("uuid") + .HasColumnName("banning_admin"); + + b.Property("ExpirationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("expiration_time"); + + b.Property("HWId") + .HasColumnType("bytea") + .HasColumnName("hwid"); + + b.Property("Hidden") + .HasColumnType("boolean") + .HasColumnName("hidden"); + + b.Property("LastEditedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("uuid") + .HasColumnName("last_edited_by_id"); + + b.Property("PlayerUserId") + .HasColumnType("uuid") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("interval") + .HasColumnName("playtime_at_note"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("text") + .HasColumnName("reason"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("text") + .HasColumnName("role_id"); + + b.Property("RoundId") + .HasColumnType("integer") + .HasColumnName("round_id"); + + b.Property("Severity") + .HasColumnType("integer") + .HasColumnName("severity"); + + b.HasKey("Id") + .HasName("PK_server_role_ban"); + + b.HasIndex("Address"); + + b.HasIndex("BanningAdmin"); + + b.HasIndex("LastEditedById"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_server_role_ban_player_user_id"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_server_role_ban_round_id"); + + b.ToTable("server_role_ban", null, t => + { + t.HasCheckConstraint("AddressNotIPv6MappedIPv4", "NOT inet '::ffff:0.0.0.0/96' >>= address"); + + t.HasCheckConstraint("HaveEitherAddressOrUserIdOrHWId", "address IS NOT NULL OR player_user_id IS NOT NULL OR hwid IS NOT NULL"); + }); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleUnban", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("role_unban_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("BanId") + .HasColumnType("integer") + .HasColumnName("ban_id"); + + b.Property("UnbanTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("unban_time"); + + b.Property("UnbanningAdmin") + .HasColumnType("uuid") + .HasColumnName("unbanning_admin"); + + b.HasKey("Id") + .HasName("PK_server_role_unban"); + + b.HasIndex("BanId") + .IsUnique(); + + b.ToTable("server_role_unban", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ServerUnban", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("unban_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("BanId") + .HasColumnType("integer") + .HasColumnName("ban_id"); + + b.Property("UnbanTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("unban_time"); + + b.Property("UnbanningAdmin") + .HasColumnType("uuid") + .HasColumnName("unbanning_admin"); + + b.HasKey("Id") + .HasName("PK_server_unban"); + + b.HasIndex("BanId") + .IsUnique(); + + b.ToTable("server_unban", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Trait", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("trait_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ProfileId") + .HasColumnType("integer") + .HasColumnName("profile_id"); + + b.Property("TraitName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("trait_name"); + + b.HasKey("Id") + .HasName("PK_trait"); + + b.HasIndex("ProfileId", "TraitName") + .IsUnique(); + + b.ToTable("trait", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.UploadedResourceLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("uploaded_resource_log_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Data") + .IsRequired() + .HasColumnType("bytea") + .HasColumnName("data"); + + b.Property("Date") + .HasColumnType("timestamp with time zone") + .HasColumnName("date"); + + b.Property("Path") + .IsRequired() + .HasColumnType("text") + .HasColumnName("path"); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("PK_uploaded_resource_log"); + + b.ToTable("uploaded_resource_log", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Whitelist", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.HasKey("UserId") + .HasName("PK_whitelist"); + + b.ToTable("whitelist", (string)null); + }); + + modelBuilder.Entity("PlayerRound", b => + { + b.Property("PlayersId") + .HasColumnType("integer") + .HasColumnName("players_id"); + + b.Property("RoundsId") + .HasColumnType("integer") + .HasColumnName("rounds_id"); + + b.HasKey("PlayersId", "RoundsId") + .HasName("PK_player_round"); + + b.HasIndex("RoundsId") + .HasDatabaseName("IX_player_round_rounds_id"); + + b.ToTable("player_round", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Admin", b => + { + b.HasOne("Content.Server.Database.AdminRank", "AdminRank") + .WithMany("Admins") + .HasForeignKey("AdminRankId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_admin_rank_admin_rank_id"); + + b.Navigation("AdminRank"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminFlag", b => + { + b.HasOne("Content.Server.Database.Admin", "Admin") + .WithMany("Flags") + .HasForeignKey("AdminId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_admin_flag_admin_admin_id"); + + b.Navigation("Admin"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLog", b => + { + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany("AdminLogs") + .HasForeignKey("RoundId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_admin_log_round_round_id"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLogEntity", b => + { + b.HasOne("Content.Server.Database.AdminLog", null) + .WithMany("Entities") + .HasForeignKey("AdminLogId", "AdminLogRoundId") + .HasConstraintName("FK_admin_log_entity_admin_log_admin_log_id_admin_log_round_id"); + }); + + 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("LogId", "RoundId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_admin_log_player_admin_log_log_id_round_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.Job", b => + { + b.HasOne("Content.Server.Database.Profile", "Profile") + .WithMany("Jobs") + .HasForeignKey("ProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_job_profile_profile_id"); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("Content.Server.Database.Profile", b => + { + b.HasOne("Content.Server.Database.Preference", "Preference") + .WithMany("Profiles") + .HasForeignKey("PreferenceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_profile_preference_preference_id"); + + b.Navigation("Preference"); + }); + + modelBuilder.Entity("Content.Server.Database.Round", b => + { + b.HasOne("Content.Server.Database.Server", "Server") + .WithMany("Rounds") + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_round_server_server_id"); + + b.Navigation("Server"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBan", b => + { + b.HasOne("Content.Server.Database.Player", "CreatedBy") + .WithMany("AdminServerBansCreated") + .HasForeignKey("BanningAdmin") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_server_ban_player_banning_admin"); + + b.HasOne("Content.Server.Database.Player", "LastEditedBy") + .WithMany("AdminServerBansLastEdited") + .HasForeignKey("LastEditedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_server_ban_player_last_edited_by_id"); + + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany() + .HasForeignKey("RoundId") + .HasConstraintName("FK_server_ban_round_round_id"); + + b.Navigation("CreatedBy"); + + b.Navigation("LastEditedBy"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBanHit", b => + { + b.HasOne("Content.Server.Database.ServerBan", "Ban") + .WithMany("BanHits") + .HasForeignKey("BanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_server_ban_hit_server_ban_ban_id"); + + b.HasOne("Content.Server.Database.ConnectionLog", "Connection") + .WithMany("BanHits") + .HasForeignKey("ConnectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_server_ban_hit_connection_log_connection_id"); + + b.Navigation("Ban"); + + b.Navigation("Connection"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleBan", b => + { + b.HasOne("Content.Server.Database.Player", "CreatedBy") + .WithMany("AdminServerRoleBansCreated") + .HasForeignKey("BanningAdmin") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_server_role_ban_player_banning_admin"); + + b.HasOne("Content.Server.Database.Player", "LastEditedBy") + .WithMany("AdminServerRoleBansLastEdited") + .HasForeignKey("LastEditedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_server_role_ban_player_last_edited_by_id"); + + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany() + .HasForeignKey("RoundId") + .HasConstraintName("FK_server_role_ban_round_round_id"); + + b.Navigation("CreatedBy"); + + b.Navigation("LastEditedBy"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleUnban", b => + { + b.HasOne("Content.Server.Database.ServerRoleBan", "Ban") + .WithOne("Unban") + .HasForeignKey("Content.Server.Database.ServerRoleUnban", "BanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_server_role_unban_server_role_ban_ban_id"); + + b.Navigation("Ban"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerUnban", b => + { + b.HasOne("Content.Server.Database.ServerBan", "Ban") + .WithOne("Unban") + .HasForeignKey("Content.Server.Database.ServerUnban", "BanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_server_unban_server_ban_ban_id"); + + b.Navigation("Ban"); + }); + + modelBuilder.Entity("Content.Server.Database.Trait", b => + { + b.HasOne("Content.Server.Database.Profile", "Profile") + .WithMany("Traits") + .HasForeignKey("ProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_trait_profile_profile_id"); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("PlayerRound", b => + { + b.HasOne("Content.Server.Database.Player", null) + .WithMany() + .HasForeignKey("PlayersId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_player_round_player_players_id"); + + b.HasOne("Content.Server.Database.Round", null) + .WithMany() + .HasForeignKey("RoundsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_player_round_round_rounds_id"); + }); + + modelBuilder.Entity("Content.Server.Database.Admin", b => + { + b.Navigation("Flags"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLog", b => + { + b.Navigation("Entities"); + + b.Navigation("Players"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminRank", b => + { + b.Navigation("Admins"); + + b.Navigation("Flags"); + }); + + modelBuilder.Entity("Content.Server.Database.ConnectionLog", b => + { + b.Navigation("BanHits"); + }); + + modelBuilder.Entity("Content.Server.Database.Player", b => + { + b.Navigation("AdminLogs"); + + b.Navigation("AdminMessagesCreated"); + + b.Navigation("AdminMessagesDeleted"); + + b.Navigation("AdminMessagesLastEdited"); + + b.Navigation("AdminMessagesReceived"); + + b.Navigation("AdminNotesCreated"); + + b.Navigation("AdminNotesDeleted"); + + b.Navigation("AdminNotesLastEdited"); + + b.Navigation("AdminNotesReceived"); + + b.Navigation("AdminServerBansCreated"); + + b.Navigation("AdminServerBansLastEdited"); + + b.Navigation("AdminServerRoleBansCreated"); + + b.Navigation("AdminServerRoleBansLastEdited"); + + b.Navigation("AdminWatchlistsCreated"); + + b.Navigation("AdminWatchlistsDeleted"); + + b.Navigation("AdminWatchlistsLastEdited"); + + b.Navigation("AdminWatchlistsReceived"); + }); + + modelBuilder.Entity("Content.Server.Database.Preference", b => + { + b.Navigation("Profiles"); + }); + + modelBuilder.Entity("Content.Server.Database.Profile", b => + { + b.Navigation("Antags"); + + b.Navigation("Jobs"); + + b.Navigation("Traits"); + }); + + modelBuilder.Entity("Content.Server.Database.Round", b => + { + b.Navigation("AdminLogs"); + }); + + modelBuilder.Entity("Content.Server.Database.Server", b => + { + b.Navigation("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/20231021071411_RoundStartDate.cs b/Content.Server.Database/Migrations/Postgres/20231021071411_RoundStartDate.cs new file mode 100644 index 0000000000..d98b4e45a8 --- /dev/null +++ b/Content.Server.Database/Migrations/Postgres/20231021071411_RoundStartDate.cs @@ -0,0 +1,39 @@ +#nullable disable + +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Content.Server.Database.Migrations.Postgres +{ + /// + public partial class RoundStartDate : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "start_date", + table: "round", + type: "timestamp with time zone", + nullable: false, + defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified)); + + migrationBuilder.CreateIndex( + name: "IX_round_start_date", + table: "round", + column: "start_date"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropIndex( + name: "IX_round_start_date", + table: "round"); + + migrationBuilder.DropColumn( + name: "start_date", + table: "round"); + } + } +} diff --git a/Content.Server.Database/Migrations/Postgres/20231024041204_DropAdminLogEntity.Designer.cs b/Content.Server.Database/Migrations/Postgres/20231024041204_DropAdminLogEntity.Designer.cs new file mode 100644 index 0000000000..5c81f0468d --- /dev/null +++ b/Content.Server.Database/Migrations/Postgres/20231024041204_DropAdminLogEntity.Designer.cs @@ -0,0 +1,1735 @@ +// +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; + +#nullable disable + +namespace Content.Server.Database.Migrations.Postgres +{ + [DbContext(typeof(PostgresServerDbContext))] + [Migration("20231024041204_DropAdminLogEntity")] + partial class DropAdminLogEntity + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "7.0.4") + .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("Id") + .HasColumnType("integer") + .HasColumnName("admin_log_id"); + + b.Property("RoundId") + .HasColumnType("integer") + .HasColumnName("round_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("Id", "RoundId") + .HasName("PK_admin_log"); + + b.HasIndex("Date"); + + b.HasIndex("Message") + .HasAnnotation("Npgsql:TsVectorConfig", "english"); + + NpgsqlIndexBuilderExtensions.HasMethod(b.HasIndex("Message"), "GIN"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_admin_log_round_id"); + + b.HasIndex("Type") + .HasDatabaseName("IX_admin_log_type"); + + b.ToTable("admin_log", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLogPlayer", b => + { + b.Property("PlayerUserId") + .HasColumnType("uuid") + .HasColumnName("player_user_id"); + + b.Property("LogId") + .HasColumnType("integer") + .HasColumnName("log_id"); + + b.Property("RoundId") + .HasColumnType("integer") + .HasColumnName("round_id"); + + b.HasKey("PlayerUserId", "LogId", "RoundId") + .HasName("PK_admin_log_player"); + + b.HasIndex("LogId", "RoundId"); + + 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("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", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminNote", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("admin_notes_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("CreatedById") + .HasColumnType("uuid") + .HasColumnName("created_by_id"); + + b.Property("Deleted") + .HasColumnType("boolean") + .HasColumnName("deleted"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("DeletedById") + .HasColumnType("uuid") + .HasColumnName("deleted_by_id"); + + b.Property("ExpirationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("expiration_time"); + + b.Property("LastEditedAt") + .IsRequired() + .HasColumnType("timestamp with time zone") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("uuid") + .HasColumnName("last_edited_by_id"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("message"); + + b.Property("PlayerUserId") + .HasColumnType("uuid") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("interval") + .HasColumnName("playtime_at_note"); + + b.Property("RoundId") + .HasColumnType("integer") + .HasColumnName("round_id"); + + b.Property("Secret") + .HasColumnType("boolean") + .HasColumnName("secret"); + + b.Property("Severity") + .HasColumnType("integer") + .HasColumnName("severity"); + + b.HasKey("Id") + .HasName("PK_admin_notes"); + + b.HasIndex("CreatedById"); + + b.HasIndex("DeletedById"); + + b.HasIndex("LastEditedById"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_admin_notes_player_user_id"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_admin_notes_round_id"); + + b.ToTable("admin_notes", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminRank", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("admin_rank_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.HasKey("Id") + .HasName("PK_admin_rank"); + + b.ToTable("admin_rank", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminRankFlag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("admin_rank_flag_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AdminRankId") + .HasColumnType("integer") + .HasColumnName("admin_rank_id"); + + b.Property("Flag") + .IsRequired() + .HasColumnType("text") + .HasColumnName("flag"); + + b.HasKey("Id") + .HasName("PK_admin_rank_flag"); + + b.HasIndex("AdminRankId"); + + b.HasIndex("Flag", "AdminRankId") + .IsUnique(); + + b.ToTable("admin_rank_flag", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminWatchlist", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("admin_watchlists_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("CreatedById") + .HasColumnType("uuid") + .HasColumnName("created_by_id"); + + b.Property("Deleted") + .HasColumnType("boolean") + .HasColumnName("deleted"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("DeletedById") + .HasColumnType("uuid") + .HasColumnName("deleted_by_id"); + + b.Property("ExpirationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("expiration_time"); + + b.Property("LastEditedAt") + .IsRequired() + .HasColumnType("timestamp with time zone") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("uuid") + .HasColumnName("last_edited_by_id"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("message"); + + b.Property("PlayerUserId") + .HasColumnType("uuid") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("interval") + .HasColumnName("playtime_at_note"); + + b.Property("RoundId") + .HasColumnType("integer") + .HasColumnName("round_id"); + + b.HasKey("Id") + .HasName("PK_admin_watchlists"); + + b.HasIndex("CreatedById"); + + b.HasIndex("DeletedById"); + + b.HasIndex("LastEditedById"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_admin_watchlists_player_user_id"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_admin_watchlists_round_id"); + + b.ToTable("admin_watchlists", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Antag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("antag_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AntagName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("antag_name"); + + b.Property("ProfileId") + .HasColumnType("integer") + .HasColumnName("profile_id"); + + b.HasKey("Id") + .HasName("PK_antag"); + + b.HasIndex("ProfileId", "AntagName") + .IsUnique(); + + b.ToTable("antag", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AssignedUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("assigned_user_id_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.Property("UserName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("user_name"); + + b.HasKey("Id") + .HasName("PK_assigned_user_id"); + + b.HasIndex("UserId") + .IsUnique(); + + b.HasIndex("UserName") + .IsUnique(); + + b.ToTable("assigned_user_id", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ConnectionLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("connection_log_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Address") + .IsRequired() + .HasColumnType("inet") + .HasColumnName("address"); + + b.Property("Denied") + .HasColumnType("smallint") + .HasColumnName("denied"); + + b.Property("HWId") + .HasColumnType("bytea") + .HasColumnName("hwid"); + + b.Property("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("UserId"); + + b.ToTable("connection_log", null, t => + { + t.HasCheckConstraint("AddressNotIPv6MappedIPv4", "NOT inet '::ffff:0.0.0.0/96' >>= address"); + }); + }); + + modelBuilder.Entity("Content.Server.Database.Job", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("job_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("JobName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("job_name"); + + b.Property("Priority") + .HasColumnType("integer") + .HasColumnName("priority"); + + b.Property("ProfileId") + .HasColumnType("integer") + .HasColumnName("profile_id"); + + b.HasKey("Id") + .HasName("PK_job"); + + b.HasIndex("ProfileId"); + + b.HasIndex("ProfileId", "JobName") + .IsUnique(); + + b.HasIndex(new[] { "ProfileId" }, "IX_job_one_high_priority") + .IsUnique() + .HasFilter("priority = 3"); + + b.ToTable("job", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.PlayTime", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("play_time_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("PlayerId") + .HasColumnType("uuid") + .HasColumnName("player_id"); + + b.Property("TimeSpent") + .HasColumnType("interval") + .HasColumnName("time_spent"); + + b.Property("Tracker") + .IsRequired() + .HasColumnType("text") + .HasColumnName("tracker"); + + b.HasKey("Id") + .HasName("PK_play_time"); + + b.HasIndex("PlayerId", "Tracker") + .IsUnique(); + + b.ToTable("play_time", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Player", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("player_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("FirstSeenTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("first_seen_time"); + + b.Property("LastReadRules") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_read_rules"); + + b.Property("LastSeenAddress") + .IsRequired() + .HasColumnType("inet") + .HasColumnName("last_seen_address"); + + b.Property("LastSeenHWId") + .HasColumnType("bytea") + .HasColumnName("last_seen_hwid"); + + b.Property("LastSeenTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_seen_time"); + + b.Property("LastSeenUserName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("last_seen_user_name"); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("PK_player"); + + b.HasAlternateKey("UserId") + .HasName("ak_player_user_id"); + + b.HasIndex("LastSeenUserName"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("player", null, t => + { + t.HasCheckConstraint("LastSeenAddressNotIPv6MappedIPv4", "NOT inet '::ffff:0.0.0.0/96' >>= last_seen_address"); + }); + }); + + modelBuilder.Entity("Content.Server.Database.Preference", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("preference_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AdminOOCColor") + .IsRequired() + .HasColumnType("text") + .HasColumnName("admin_ooc_color"); + + b.Property("SelectedCharacterSlot") + .HasColumnType("integer") + .HasColumnName("selected_character_slot"); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("PK_preference"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("preference", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Profile", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("profile_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Age") + .HasColumnType("integer") + .HasColumnName("age"); + + b.Property("Backpack") + .IsRequired() + .HasColumnType("text") + .HasColumnName("backpack"); + + b.Property("CharacterName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("char_name"); + + b.Property("Clothing") + .IsRequired() + .HasColumnType("text") + .HasColumnName("clothing"); + + b.Property("EyeColor") + .IsRequired() + .HasColumnType("text") + .HasColumnName("eye_color"); + + b.Property("FacialHairColor") + .IsRequired() + .HasColumnType("text") + .HasColumnName("facial_hair_color"); + + b.Property("FacialHairName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("facial_hair_name"); + + b.Property("FlavorText") + .IsRequired() + .HasColumnType("text") + .HasColumnName("flavor_text"); + + b.Property("Gender") + .IsRequired() + .HasColumnType("text") + .HasColumnName("gender"); + + b.Property("HairColor") + .IsRequired() + .HasColumnType("text") + .HasColumnName("hair_color"); + + b.Property("HairName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("hair_name"); + + b.Property("Markings") + .HasColumnType("jsonb") + .HasColumnName("markings"); + + b.Property("PreferenceId") + .HasColumnType("integer") + .HasColumnName("preference_id"); + + b.Property("PreferenceUnavailable") + .HasColumnType("integer") + .HasColumnName("pref_unavailable"); + + b.Property("Sex") + .IsRequired() + .HasColumnType("text") + .HasColumnName("sex"); + + b.Property("SkinColor") + .IsRequired() + .HasColumnType("text") + .HasColumnName("skin_color"); + + b.Property("Slot") + .HasColumnType("integer") + .HasColumnName("slot"); + + b.Property("Species") + .IsRequired() + .HasColumnType("text") + .HasColumnName("species"); + + b.HasKey("Id") + .HasName("PK_profile"); + + b.HasIndex("PreferenceId") + .HasDatabaseName("IX_profile_preference_id"); + + b.HasIndex("Slot", "PreferenceId") + .IsUnique(); + + b.ToTable("profile", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Round", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("round_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ServerId") + .HasColumnType("integer") + .HasColumnName("server_id"); + + b.Property("StartDate") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValue(new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified)) + .HasColumnName("start_date"); + + b.HasKey("Id") + .HasName("PK_round"); + + b.HasIndex("ServerId") + .HasDatabaseName("IX_round_server_id"); + + b.HasIndex("StartDate"); + + b.ToTable("round", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Server", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("server_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.HasKey("Id") + .HasName("PK_server"); + + b.ToTable("server", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBan", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("server_ban_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property?>("Address") + .HasColumnType("inet") + .HasColumnName("address"); + + b.Property("AutoDelete") + .HasColumnType("boolean") + .HasColumnName("auto_delete"); + + b.Property("BanTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("ban_time"); + + b.Property("BanningAdmin") + .HasColumnType("uuid") + .HasColumnName("banning_admin"); + + b.Property("ExemptFlags") + .HasColumnType("integer") + .HasColumnName("exempt_flags"); + + b.Property("ExpirationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("expiration_time"); + + b.Property("HWId") + .HasColumnType("bytea") + .HasColumnName("hwid"); + + b.Property("Hidden") + .HasColumnType("boolean") + .HasColumnName("hidden"); + + b.Property("LastEditedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("uuid") + .HasColumnName("last_edited_by_id"); + + b.Property("PlayerUserId") + .HasColumnType("uuid") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("interval") + .HasColumnName("playtime_at_note"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("text") + .HasColumnName("reason"); + + b.Property("RoundId") + .HasColumnType("integer") + .HasColumnName("round_id"); + + b.Property("Severity") + .HasColumnType("integer") + .HasColumnName("severity"); + + b.HasKey("Id") + .HasName("PK_server_ban"); + + b.HasIndex("Address"); + + b.HasIndex("BanningAdmin"); + + b.HasIndex("LastEditedById"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_server_ban_player_user_id"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_server_ban_round_id"); + + b.ToTable("server_ban", null, t => + { + t.HasCheckConstraint("AddressNotIPv6MappedIPv4", "NOT inet '::ffff:0.0.0.0/96' >>= address"); + + t.HasCheckConstraint("HaveEitherAddressOrUserIdOrHWId", "address IS NOT NULL OR player_user_id IS NOT NULL OR hwid IS NOT NULL"); + }); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBanExemption", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.Property("Flags") + .HasColumnType("integer") + .HasColumnName("flags"); + + b.HasKey("UserId") + .HasName("PK_server_ban_exemption"); + + b.ToTable("server_ban_exemption", null, t => + { + t.HasCheckConstraint("FlagsNotZero", "flags != 0"); + }); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBanHit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("server_ban_hit_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("BanId") + .HasColumnType("integer") + .HasColumnName("ban_id"); + + b.Property("ConnectionId") + .HasColumnType("integer") + .HasColumnName("connection_id"); + + b.HasKey("Id") + .HasName("PK_server_ban_hit"); + + b.HasIndex("BanId") + .HasDatabaseName("IX_server_ban_hit_ban_id"); + + b.HasIndex("ConnectionId") + .HasDatabaseName("IX_server_ban_hit_connection_id"); + + b.ToTable("server_ban_hit", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleBan", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("server_role_ban_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property?>("Address") + .HasColumnType("inet") + .HasColumnName("address"); + + b.Property("BanTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("ban_time"); + + b.Property("BanningAdmin") + .HasColumnType("uuid") + .HasColumnName("banning_admin"); + + b.Property("ExpirationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("expiration_time"); + + b.Property("HWId") + .HasColumnType("bytea") + .HasColumnName("hwid"); + + b.Property("Hidden") + .HasColumnType("boolean") + .HasColumnName("hidden"); + + b.Property("LastEditedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("uuid") + .HasColumnName("last_edited_by_id"); + + b.Property("PlayerUserId") + .HasColumnType("uuid") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("interval") + .HasColumnName("playtime_at_note"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("text") + .HasColumnName("reason"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("text") + .HasColumnName("role_id"); + + b.Property("RoundId") + .HasColumnType("integer") + .HasColumnName("round_id"); + + b.Property("Severity") + .HasColumnType("integer") + .HasColumnName("severity"); + + b.HasKey("Id") + .HasName("PK_server_role_ban"); + + b.HasIndex("Address"); + + b.HasIndex("BanningAdmin"); + + b.HasIndex("LastEditedById"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_server_role_ban_player_user_id"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_server_role_ban_round_id"); + + b.ToTable("server_role_ban", null, t => + { + t.HasCheckConstraint("AddressNotIPv6MappedIPv4", "NOT inet '::ffff:0.0.0.0/96' >>= address"); + + t.HasCheckConstraint("HaveEitherAddressOrUserIdOrHWId", "address IS NOT NULL OR player_user_id IS NOT NULL OR hwid IS NOT NULL"); + }); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleUnban", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("role_unban_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("BanId") + .HasColumnType("integer") + .HasColumnName("ban_id"); + + b.Property("UnbanTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("unban_time"); + + b.Property("UnbanningAdmin") + .HasColumnType("uuid") + .HasColumnName("unbanning_admin"); + + b.HasKey("Id") + .HasName("PK_server_role_unban"); + + b.HasIndex("BanId") + .IsUnique(); + + b.ToTable("server_role_unban", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ServerUnban", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("unban_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("BanId") + .HasColumnType("integer") + .HasColumnName("ban_id"); + + b.Property("UnbanTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("unban_time"); + + b.Property("UnbanningAdmin") + .HasColumnType("uuid") + .HasColumnName("unbanning_admin"); + + b.HasKey("Id") + .HasName("PK_server_unban"); + + b.HasIndex("BanId") + .IsUnique(); + + b.ToTable("server_unban", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Trait", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("trait_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ProfileId") + .HasColumnType("integer") + .HasColumnName("profile_id"); + + b.Property("TraitName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("trait_name"); + + b.HasKey("Id") + .HasName("PK_trait"); + + b.HasIndex("ProfileId", "TraitName") + .IsUnique(); + + b.ToTable("trait", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.UploadedResourceLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("uploaded_resource_log_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Data") + .IsRequired() + .HasColumnType("bytea") + .HasColumnName("data"); + + b.Property("Date") + .HasColumnType("timestamp with time zone") + .HasColumnName("date"); + + b.Property("Path") + .IsRequired() + .HasColumnType("text") + .HasColumnName("path"); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("PK_uploaded_resource_log"); + + b.ToTable("uploaded_resource_log", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Whitelist", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.HasKey("UserId") + .HasName("PK_whitelist"); + + b.ToTable("whitelist", (string)null); + }); + + modelBuilder.Entity("PlayerRound", b => + { + b.Property("PlayersId") + .HasColumnType("integer") + .HasColumnName("players_id"); + + b.Property("RoundsId") + .HasColumnType("integer") + .HasColumnName("rounds_id"); + + b.HasKey("PlayersId", "RoundsId") + .HasName("PK_player_round"); + + b.HasIndex("RoundsId") + .HasDatabaseName("IX_player_round_rounds_id"); + + b.ToTable("player_round", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Admin", b => + { + b.HasOne("Content.Server.Database.AdminRank", "AdminRank") + .WithMany("Admins") + .HasForeignKey("AdminRankId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_admin_rank_admin_rank_id"); + + b.Navigation("AdminRank"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminFlag", b => + { + b.HasOne("Content.Server.Database.Admin", "Admin") + .WithMany("Flags") + .HasForeignKey("AdminId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_admin_flag_admin_admin_id"); + + b.Navigation("Admin"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLog", b => + { + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany("AdminLogs") + .HasForeignKey("RoundId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_admin_log_round_round_id"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLogPlayer", b => + { + b.HasOne("Content.Server.Database.Player", "Player") + .WithMany("AdminLogs") + .HasForeignKey("PlayerUserId") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_admin_log_player_player_player_user_id"); + + b.HasOne("Content.Server.Database.AdminLog", "Log") + .WithMany("Players") + .HasForeignKey("LogId", "RoundId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_admin_log_player_admin_log_log_id_round_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.Job", b => + { + b.HasOne("Content.Server.Database.Profile", "Profile") + .WithMany("Jobs") + .HasForeignKey("ProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_job_profile_profile_id"); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("Content.Server.Database.Profile", b => + { + b.HasOne("Content.Server.Database.Preference", "Preference") + .WithMany("Profiles") + .HasForeignKey("PreferenceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_profile_preference_preference_id"); + + b.Navigation("Preference"); + }); + + modelBuilder.Entity("Content.Server.Database.Round", b => + { + b.HasOne("Content.Server.Database.Server", "Server") + .WithMany("Rounds") + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_round_server_server_id"); + + b.Navigation("Server"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBan", b => + { + b.HasOne("Content.Server.Database.Player", "CreatedBy") + .WithMany("AdminServerBansCreated") + .HasForeignKey("BanningAdmin") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_server_ban_player_banning_admin"); + + b.HasOne("Content.Server.Database.Player", "LastEditedBy") + .WithMany("AdminServerBansLastEdited") + .HasForeignKey("LastEditedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_server_ban_player_last_edited_by_id"); + + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany() + .HasForeignKey("RoundId") + .HasConstraintName("FK_server_ban_round_round_id"); + + b.Navigation("CreatedBy"); + + b.Navigation("LastEditedBy"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBanHit", b => + { + b.HasOne("Content.Server.Database.ServerBan", "Ban") + .WithMany("BanHits") + .HasForeignKey("BanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_server_ban_hit_server_ban_ban_id"); + + b.HasOne("Content.Server.Database.ConnectionLog", "Connection") + .WithMany("BanHits") + .HasForeignKey("ConnectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_server_ban_hit_connection_log_connection_id"); + + b.Navigation("Ban"); + + b.Navigation("Connection"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleBan", b => + { + b.HasOne("Content.Server.Database.Player", "CreatedBy") + .WithMany("AdminServerRoleBansCreated") + .HasForeignKey("BanningAdmin") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_server_role_ban_player_banning_admin"); + + b.HasOne("Content.Server.Database.Player", "LastEditedBy") + .WithMany("AdminServerRoleBansLastEdited") + .HasForeignKey("LastEditedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_server_role_ban_player_last_edited_by_id"); + + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany() + .HasForeignKey("RoundId") + .HasConstraintName("FK_server_role_ban_round_round_id"); + + b.Navigation("CreatedBy"); + + b.Navigation("LastEditedBy"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleUnban", b => + { + b.HasOne("Content.Server.Database.ServerRoleBan", "Ban") + .WithOne("Unban") + .HasForeignKey("Content.Server.Database.ServerRoleUnban", "BanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_server_role_unban_server_role_ban_ban_id"); + + b.Navigation("Ban"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerUnban", b => + { + b.HasOne("Content.Server.Database.ServerBan", "Ban") + .WithOne("Unban") + .HasForeignKey("Content.Server.Database.ServerUnban", "BanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_server_unban_server_ban_ban_id"); + + b.Navigation("Ban"); + }); + + modelBuilder.Entity("Content.Server.Database.Trait", b => + { + b.HasOne("Content.Server.Database.Profile", "Profile") + .WithMany("Traits") + .HasForeignKey("ProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_trait_profile_profile_id"); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("PlayerRound", b => + { + b.HasOne("Content.Server.Database.Player", null) + .WithMany() + .HasForeignKey("PlayersId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_player_round_player_players_id"); + + b.HasOne("Content.Server.Database.Round", null) + .WithMany() + .HasForeignKey("RoundsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_player_round_round_rounds_id"); + }); + + modelBuilder.Entity("Content.Server.Database.Admin", b => + { + b.Navigation("Flags"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLog", b => + { + b.Navigation("Players"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminRank", b => + { + b.Navigation("Admins"); + + b.Navigation("Flags"); + }); + + modelBuilder.Entity("Content.Server.Database.ConnectionLog", b => + { + b.Navigation("BanHits"); + }); + + modelBuilder.Entity("Content.Server.Database.Player", b => + { + b.Navigation("AdminLogs"); + + b.Navigation("AdminMessagesCreated"); + + b.Navigation("AdminMessagesDeleted"); + + b.Navigation("AdminMessagesLastEdited"); + + b.Navigation("AdminMessagesReceived"); + + b.Navigation("AdminNotesCreated"); + + b.Navigation("AdminNotesDeleted"); + + b.Navigation("AdminNotesLastEdited"); + + b.Navigation("AdminNotesReceived"); + + b.Navigation("AdminServerBansCreated"); + + b.Navigation("AdminServerBansLastEdited"); + + b.Navigation("AdminServerRoleBansCreated"); + + b.Navigation("AdminServerRoleBansLastEdited"); + + b.Navigation("AdminWatchlistsCreated"); + + b.Navigation("AdminWatchlistsDeleted"); + + b.Navigation("AdminWatchlistsLastEdited"); + + b.Navigation("AdminWatchlistsReceived"); + }); + + modelBuilder.Entity("Content.Server.Database.Preference", b => + { + b.Navigation("Profiles"); + }); + + modelBuilder.Entity("Content.Server.Database.Profile", b => + { + b.Navigation("Antags"); + + b.Navigation("Jobs"); + + b.Navigation("Traits"); + }); + + modelBuilder.Entity("Content.Server.Database.Round", b => + { + b.Navigation("AdminLogs"); + }); + + modelBuilder.Entity("Content.Server.Database.Server", b => + { + b.Navigation("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/20231024041204_DropAdminLogEntity.cs b/Content.Server.Database/Migrations/Postgres/20231024041204_DropAdminLogEntity.cs new file mode 100644 index 0000000000..ec9c2e9a6c --- /dev/null +++ b/Content.Server.Database/Migrations/Postgres/20231024041204_DropAdminLogEntity.cs @@ -0,0 +1,47 @@ +#nullable disable + +using Microsoft.EntityFrameworkCore.Migrations; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +namespace Content.Server.Database.Migrations.Postgres +{ + /// + public partial class DropAdminLogEntity : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "admin_log_entity"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "admin_log_entity", + columns: table => new + { + uid = table.Column(type: "integer", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + admin_log_id = table.Column(type: "integer", nullable: true), + admin_log_round_id = table.Column(type: "integer", nullable: true), + name = table.Column(type: "text", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_admin_log_entity", x => x.uid); + table.ForeignKey( + name: "FK_admin_log_entity_admin_log_admin_log_id_admin_log_round_id", + columns: x => new { x.admin_log_id, x.admin_log_round_id }, + principalTable: "admin_log", + principalColumns: new[] { "admin_log_id", "round_id" }); + }); + + migrationBuilder.CreateIndex( + name: "IX_admin_log_entity_admin_log_id_admin_log_round_id", + table: "admin_log_entity", + columns: new[] { "admin_log_id", "admin_log_round_id" }); + } + } +} diff --git a/Content.Server.Database/Migrations/Postgres/PostgresServerDbContextModelSnapshot.cs b/Content.Server.Database/Migrations/Postgres/PostgresServerDbContextModelSnapshot.cs index 0cb52bcab0..d00c664bd2 100644 --- a/Content.Server.Database/Migrations/Postgres/PostgresServerDbContextModelSnapshot.cs +++ b/Content.Server.Database/Migrations/Postgres/PostgresServerDbContextModelSnapshot.cs @@ -133,36 +133,6 @@ namespace Content.Server.Database.Migrations.Postgres b.ToTable("admin_log", (string)null); }); - modelBuilder.Entity("Content.Server.Database.AdminLogEntity", b => - { - b.Property("Uid") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasColumnName("uid"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Uid")); - - b.Property("AdminLogId") - .HasColumnType("integer") - .HasColumnName("admin_log_id"); - - b.Property("AdminLogRoundId") - .HasColumnType("integer") - .HasColumnName("admin_log_round_id"); - - b.Property("Name") - .HasColumnType("text") - .HasColumnName("name"); - - b.HasKey("Uid") - .HasName("PK_admin_log_entity"); - - b.HasIndex("AdminLogId", "AdminLogRoundId") - .HasDatabaseName("IX_admin_log_entity_admin_log_id_admin_log_round_id"); - - b.ToTable("admin_log_entity", (string)null); - }); - modelBuilder.Entity("Content.Server.Database.AdminLogPlayer", b => { b.Property("PlayerUserId") @@ -863,12 +833,20 @@ namespace Content.Server.Database.Migrations.Postgres .HasColumnType("integer") .HasColumnName("server_id"); + b.Property("StartDate") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValue(new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified)) + .HasColumnName("start_date"); + b.HasKey("Id") .HasName("PK_round"); b.HasIndex("ServerId") .HasDatabaseName("IX_round_server_id"); + b.HasIndex("StartDate"); + b.ToTable("round", (string)null); }); @@ -1311,14 +1289,6 @@ namespace Content.Server.Database.Migrations.Postgres b.Navigation("Round"); }); - modelBuilder.Entity("Content.Server.Database.AdminLogEntity", b => - { - b.HasOne("Content.Server.Database.AdminLog", null) - .WithMany("Entities") - .HasForeignKey("AdminLogId", "AdminLogRoundId") - .HasConstraintName("FK_admin_log_entity_admin_log_admin_log_id_admin_log_round_id"); - }); - modelBuilder.Entity("Content.Server.Database.AdminLogPlayer", b => { b.HasOne("Content.Server.Database.Player", "Player") @@ -1676,8 +1646,6 @@ namespace Content.Server.Database.Migrations.Postgres modelBuilder.Entity("Content.Server.Database.AdminLog", b => { - b.Navigation("Entities"); - b.Navigation("Players"); }); diff --git a/Content.Server.Database/Migrations/Sqlite/20231021071407_RoundStartDate.Designer.cs b/Content.Server.Database/Migrations/Sqlite/20231021071407_RoundStartDate.Designer.cs new file mode 100644 index 0000000000..cf8294e5e8 --- /dev/null +++ b/Content.Server.Database/Migrations/Sqlite/20231021071407_RoundStartDate.Designer.cs @@ -0,0 +1,1705 @@ +// +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("20231021071407_RoundStartDate")] + partial class RoundStartDate + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "7.0.4"); + + 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("Id") + .HasColumnType("INTEGER") + .HasColumnName("admin_log_id"); + + b.Property("RoundId") + .HasColumnType("INTEGER") + .HasColumnName("round_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("Id", "RoundId") + .HasName("PK_admin_log"); + + b.HasIndex("Date"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_admin_log_round_id"); + + b.HasIndex("Type") + .HasDatabaseName("IX_admin_log_type"); + + b.ToTable("admin_log", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLogEntity", b => + { + b.Property("Uid") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("uid"); + + b.Property("AdminLogId") + .HasColumnType("INTEGER") + .HasColumnName("admin_log_id"); + + b.Property("AdminLogRoundId") + .HasColumnType("INTEGER") + .HasColumnName("admin_log_round_id"); + + b.Property("Name") + .HasColumnType("TEXT") + .HasColumnName("name"); + + b.HasKey("Uid") + .HasName("PK_admin_log_entity"); + + b.HasIndex("AdminLogId", "AdminLogRoundId") + .HasDatabaseName("IX_admin_log_entity_admin_log_id_admin_log_round_id"); + + b.ToTable("admin_log_entity", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLogPlayer", b => + { + b.Property("PlayerUserId") + .HasColumnType("TEXT") + .HasColumnName("player_user_id"); + + b.Property("LogId") + .HasColumnType("INTEGER") + .HasColumnName("log_id"); + + b.Property("RoundId") + .HasColumnType("INTEGER") + .HasColumnName("round_id"); + + b.HasKey("PlayerUserId", "LogId", "RoundId") + .HasName("PK_admin_log_player"); + + b.HasIndex("LogId", "RoundId"); + + 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("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", (string)null); + }); + + 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.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("HWId") + .HasColumnType("BLOB") + .HasColumnName("hwid"); + + 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("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("LastSeenHWId") + .HasColumnType("BLOB") + .HasColumnName("last_seen_hwid"); + + 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("Backpack") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("backpack"); + + b.Property("CharacterName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("char_name"); + + b.Property("Clothing") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("clothing"); + + b.Property("EyeColor") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("eye_color"); + + b.Property("FacialHairColor") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("facial_hair_color"); + + b.Property("FacialHairName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("facial_hair_name"); + + b.Property("FlavorText") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("flavor_text"); + + b.Property("Gender") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("gender"); + + b.Property("HairColor") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("hair_color"); + + b.Property("HairName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("hair_name"); + + b.Property("Markings") + .HasColumnType("jsonb") + .HasColumnName("markings"); + + b.Property("PreferenceId") + .HasColumnType("INTEGER") + .HasColumnName("preference_id"); + + b.Property("PreferenceUnavailable") + .HasColumnType("INTEGER") + .HasColumnName("pref_unavailable"); + + b.Property("Sex") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("sex"); + + b.Property("SkinColor") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("skin_color"); + + b.Property("Slot") + .HasColumnType("INTEGER") + .HasColumnName("slot"); + + b.Property("Species") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("species"); + + b.HasKey("Id") + .HasName("PK_profile"); + + b.HasIndex("PreferenceId") + .HasDatabaseName("IX_profile_preference_id"); + + b.HasIndex("Slot", "PreferenceId") + .IsUnique(); + + b.ToTable("profile", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Round", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("round_id"); + + b.Property("ServerId") + .HasColumnType("INTEGER") + .HasColumnName("server_id"); + + b.Property("StartDate") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT") + .HasDefaultValue(new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified)) + .HasColumnName("start_date"); + + b.HasKey("Id") + .HasName("PK_round"); + + b.HasIndex("ServerId") + .HasDatabaseName("IX_round_server_id"); + + b.HasIndex("StartDate"); + + b.ToTable("round", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Server", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("server_id"); + + 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("HWId") + .HasColumnType("BLOB") + .HasColumnName("hwid"); + + 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("HWId") + .HasColumnType("BLOB") + .HasColumnName("hwid"); + + 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.AdminLogEntity", b => + { + b.HasOne("Content.Server.Database.AdminLog", null) + .WithMany("Entities") + .HasForeignKey("AdminLogId", "AdminLogRoundId") + .HasConstraintName("FK_admin_log_entity_admin_log_admin_log_id_admin_log_round_id"); + }); + + 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("LogId", "RoundId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_admin_log_player_admin_log_log_id_round_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.Job", b => + { + b.HasOne("Content.Server.Database.Profile", "Profile") + .WithMany("Jobs") + .HasForeignKey("ProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_job_profile_profile_id"); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("Content.Server.Database.Profile", b => + { + b.HasOne("Content.Server.Database.Preference", "Preference") + .WithMany("Profiles") + .HasForeignKey("PreferenceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_profile_preference_preference_id"); + + b.Navigation("Preference"); + }); + + modelBuilder.Entity("Content.Server.Database.Round", b => + { + b.HasOne("Content.Server.Database.Server", "Server") + .WithMany("Rounds") + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_round_server_server_id"); + + b.Navigation("Server"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBan", b => + { + b.HasOne("Content.Server.Database.Player", "CreatedBy") + .WithMany("AdminServerBansCreated") + .HasForeignKey("BanningAdmin") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_server_ban_player_banning_admin"); + + b.HasOne("Content.Server.Database.Player", "LastEditedBy") + .WithMany("AdminServerBansLastEdited") + .HasForeignKey("LastEditedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_server_ban_player_last_edited_by_id"); + + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany() + .HasForeignKey("RoundId") + .HasConstraintName("FK_server_ban_round_round_id"); + + b.Navigation("CreatedBy"); + + b.Navigation("LastEditedBy"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBanHit", b => + { + b.HasOne("Content.Server.Database.ServerBan", "Ban") + .WithMany("BanHits") + .HasForeignKey("BanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_server_ban_hit_server_ban_ban_id"); + + b.HasOne("Content.Server.Database.ConnectionLog", "Connection") + .WithMany("BanHits") + .HasForeignKey("ConnectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_server_ban_hit_connection_log_connection_id"); + + b.Navigation("Ban"); + + b.Navigation("Connection"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleBan", b => + { + b.HasOne("Content.Server.Database.Player", "CreatedBy") + .WithMany("AdminServerRoleBansCreated") + .HasForeignKey("BanningAdmin") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_server_role_ban_player_banning_admin"); + + b.HasOne("Content.Server.Database.Player", "LastEditedBy") + .WithMany("AdminServerRoleBansLastEdited") + .HasForeignKey("LastEditedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_server_role_ban_player_last_edited_by_id"); + + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany() + .HasForeignKey("RoundId") + .HasConstraintName("FK_server_role_ban_round_round_id"); + + b.Navigation("CreatedBy"); + + b.Navigation("LastEditedBy"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleUnban", b => + { + b.HasOne("Content.Server.Database.ServerRoleBan", "Ban") + .WithOne("Unban") + .HasForeignKey("Content.Server.Database.ServerRoleUnban", "BanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_server_role_unban_server_role_ban_ban_id"); + + b.Navigation("Ban"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerUnban", b => + { + b.HasOne("Content.Server.Database.ServerBan", "Ban") + .WithOne("Unban") + .HasForeignKey("Content.Server.Database.ServerUnban", "BanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_server_unban_server_ban_ban_id"); + + b.Navigation("Ban"); + }); + + modelBuilder.Entity("Content.Server.Database.Trait", b => + { + b.HasOne("Content.Server.Database.Profile", "Profile") + .WithMany("Traits") + .HasForeignKey("ProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_trait_profile_profile_id"); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("PlayerRound", b => + { + b.HasOne("Content.Server.Database.Player", null) + .WithMany() + .HasForeignKey("PlayersId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_player_round_player_players_id"); + + b.HasOne("Content.Server.Database.Round", null) + .WithMany() + .HasForeignKey("RoundsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_player_round_round_rounds_id"); + }); + + modelBuilder.Entity("Content.Server.Database.Admin", b => + { + b.Navigation("Flags"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLog", b => + { + b.Navigation("Entities"); + + b.Navigation("Players"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminRank", b => + { + b.Navigation("Admins"); + + b.Navigation("Flags"); + }); + + modelBuilder.Entity("Content.Server.Database.ConnectionLog", b => + { + b.Navigation("BanHits"); + }); + + modelBuilder.Entity("Content.Server.Database.Player", b => + { + b.Navigation("AdminLogs"); + + b.Navigation("AdminMessagesCreated"); + + b.Navigation("AdminMessagesDeleted"); + + b.Navigation("AdminMessagesLastEdited"); + + b.Navigation("AdminMessagesReceived"); + + b.Navigation("AdminNotesCreated"); + + b.Navigation("AdminNotesDeleted"); + + b.Navigation("AdminNotesLastEdited"); + + b.Navigation("AdminNotesReceived"); + + b.Navigation("AdminServerBansCreated"); + + b.Navigation("AdminServerBansLastEdited"); + + b.Navigation("AdminServerRoleBansCreated"); + + b.Navigation("AdminServerRoleBansLastEdited"); + + b.Navigation("AdminWatchlistsCreated"); + + b.Navigation("AdminWatchlistsDeleted"); + + b.Navigation("AdminWatchlistsLastEdited"); + + b.Navigation("AdminWatchlistsReceived"); + }); + + modelBuilder.Entity("Content.Server.Database.Preference", b => + { + b.Navigation("Profiles"); + }); + + modelBuilder.Entity("Content.Server.Database.Profile", b => + { + b.Navigation("Antags"); + + b.Navigation("Jobs"); + + b.Navigation("Traits"); + }); + + modelBuilder.Entity("Content.Server.Database.Round", b => + { + b.Navigation("AdminLogs"); + }); + + modelBuilder.Entity("Content.Server.Database.Server", b => + { + b.Navigation("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/20231021071407_RoundStartDate.cs b/Content.Server.Database/Migrations/Sqlite/20231021071407_RoundStartDate.cs new file mode 100644 index 0000000000..0948bd99f1 --- /dev/null +++ b/Content.Server.Database/Migrations/Sqlite/20231021071407_RoundStartDate.cs @@ -0,0 +1,39 @@ +#nullable disable + +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Content.Server.Database.Migrations.Sqlite +{ + /// + public partial class RoundStartDate : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "start_date", + table: "round", + type: "TEXT", + nullable: false, + defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified)); + + migrationBuilder.CreateIndex( + name: "IX_round_start_date", + table: "round", + column: "start_date"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropIndex( + name: "IX_round_start_date", + table: "round"); + + migrationBuilder.DropColumn( + name: "start_date", + table: "round"); + } + } +} diff --git a/Content.Server.Database/Migrations/Sqlite/20231024041159_DropAdminLogEntity.Designer.cs b/Content.Server.Database/Migrations/Sqlite/20231024041159_DropAdminLogEntity.Designer.cs new file mode 100644 index 0000000000..887e157ec3 --- /dev/null +++ b/Content.Server.Database/Migrations/Sqlite/20231024041159_DropAdminLogEntity.Designer.cs @@ -0,0 +1,1667 @@ +// +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("20231024041159_DropAdminLogEntity")] + partial class DropAdminLogEntity + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "7.0.4"); + + 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("Id") + .HasColumnType("INTEGER") + .HasColumnName("admin_log_id"); + + b.Property("RoundId") + .HasColumnType("INTEGER") + .HasColumnName("round_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("Id", "RoundId") + .HasName("PK_admin_log"); + + b.HasIndex("Date"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_admin_log_round_id"); + + b.HasIndex("Type") + .HasDatabaseName("IX_admin_log_type"); + + b.ToTable("admin_log", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLogPlayer", b => + { + b.Property("PlayerUserId") + .HasColumnType("TEXT") + .HasColumnName("player_user_id"); + + b.Property("LogId") + .HasColumnType("INTEGER") + .HasColumnName("log_id"); + + b.Property("RoundId") + .HasColumnType("INTEGER") + .HasColumnName("round_id"); + + b.HasKey("PlayerUserId", "LogId", "RoundId") + .HasName("PK_admin_log_player"); + + b.HasIndex("LogId", "RoundId"); + + 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("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", (string)null); + }); + + 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.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("HWId") + .HasColumnType("BLOB") + .HasColumnName("hwid"); + + 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("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("LastSeenHWId") + .HasColumnType("BLOB") + .HasColumnName("last_seen_hwid"); + + 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("Backpack") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("backpack"); + + b.Property("CharacterName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("char_name"); + + b.Property("Clothing") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("clothing"); + + b.Property("EyeColor") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("eye_color"); + + b.Property("FacialHairColor") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("facial_hair_color"); + + b.Property("FacialHairName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("facial_hair_name"); + + b.Property("FlavorText") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("flavor_text"); + + b.Property("Gender") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("gender"); + + b.Property("HairColor") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("hair_color"); + + b.Property("HairName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("hair_name"); + + b.Property("Markings") + .HasColumnType("jsonb") + .HasColumnName("markings"); + + b.Property("PreferenceId") + .HasColumnType("INTEGER") + .HasColumnName("preference_id"); + + b.Property("PreferenceUnavailable") + .HasColumnType("INTEGER") + .HasColumnName("pref_unavailable"); + + b.Property("Sex") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("sex"); + + b.Property("SkinColor") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("skin_color"); + + b.Property("Slot") + .HasColumnType("INTEGER") + .HasColumnName("slot"); + + b.Property("Species") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("species"); + + b.HasKey("Id") + .HasName("PK_profile"); + + b.HasIndex("PreferenceId") + .HasDatabaseName("IX_profile_preference_id"); + + b.HasIndex("Slot", "PreferenceId") + .IsUnique(); + + b.ToTable("profile", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Round", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("round_id"); + + b.Property("ServerId") + .HasColumnType("INTEGER") + .HasColumnName("server_id"); + + b.Property("StartDate") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT") + .HasDefaultValue(new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified)) + .HasColumnName("start_date"); + + b.HasKey("Id") + .HasName("PK_round"); + + b.HasIndex("ServerId") + .HasDatabaseName("IX_round_server_id"); + + b.HasIndex("StartDate"); + + b.ToTable("round", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Server", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("server_id"); + + 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("HWId") + .HasColumnType("BLOB") + .HasColumnName("hwid"); + + 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("HWId") + .HasColumnType("BLOB") + .HasColumnName("hwid"); + + 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("LogId", "RoundId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_admin_log_player_admin_log_log_id_round_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.Job", b => + { + b.HasOne("Content.Server.Database.Profile", "Profile") + .WithMany("Jobs") + .HasForeignKey("ProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_job_profile_profile_id"); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("Content.Server.Database.Profile", b => + { + b.HasOne("Content.Server.Database.Preference", "Preference") + .WithMany("Profiles") + .HasForeignKey("PreferenceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_profile_preference_preference_id"); + + b.Navigation("Preference"); + }); + + modelBuilder.Entity("Content.Server.Database.Round", b => + { + b.HasOne("Content.Server.Database.Server", "Server") + .WithMany("Rounds") + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_round_server_server_id"); + + b.Navigation("Server"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBan", b => + { + b.HasOne("Content.Server.Database.Player", "CreatedBy") + .WithMany("AdminServerBansCreated") + .HasForeignKey("BanningAdmin") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_server_ban_player_banning_admin"); + + b.HasOne("Content.Server.Database.Player", "LastEditedBy") + .WithMany("AdminServerBansLastEdited") + .HasForeignKey("LastEditedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_server_ban_player_last_edited_by_id"); + + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany() + .HasForeignKey("RoundId") + .HasConstraintName("FK_server_ban_round_round_id"); + + b.Navigation("CreatedBy"); + + b.Navigation("LastEditedBy"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBanHit", b => + { + b.HasOne("Content.Server.Database.ServerBan", "Ban") + .WithMany("BanHits") + .HasForeignKey("BanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_server_ban_hit_server_ban_ban_id"); + + b.HasOne("Content.Server.Database.ConnectionLog", "Connection") + .WithMany("BanHits") + .HasForeignKey("ConnectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_server_ban_hit_connection_log_connection_id"); + + b.Navigation("Ban"); + + b.Navigation("Connection"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleBan", b => + { + b.HasOne("Content.Server.Database.Player", "CreatedBy") + .WithMany("AdminServerRoleBansCreated") + .HasForeignKey("BanningAdmin") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_server_role_ban_player_banning_admin"); + + b.HasOne("Content.Server.Database.Player", "LastEditedBy") + .WithMany("AdminServerRoleBansLastEdited") + .HasForeignKey("LastEditedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_server_role_ban_player_last_edited_by_id"); + + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany() + .HasForeignKey("RoundId") + .HasConstraintName("FK_server_role_ban_round_round_id"); + + b.Navigation("CreatedBy"); + + b.Navigation("LastEditedBy"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleUnban", b => + { + b.HasOne("Content.Server.Database.ServerRoleBan", "Ban") + .WithOne("Unban") + .HasForeignKey("Content.Server.Database.ServerRoleUnban", "BanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_server_role_unban_server_role_ban_ban_id"); + + b.Navigation("Ban"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerUnban", b => + { + b.HasOne("Content.Server.Database.ServerBan", "Ban") + .WithOne("Unban") + .HasForeignKey("Content.Server.Database.ServerUnban", "BanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_server_unban_server_ban_ban_id"); + + b.Navigation("Ban"); + }); + + modelBuilder.Entity("Content.Server.Database.Trait", b => + { + b.HasOne("Content.Server.Database.Profile", "Profile") + .WithMany("Traits") + .HasForeignKey("ProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_trait_profile_profile_id"); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("PlayerRound", b => + { + b.HasOne("Content.Server.Database.Player", null) + .WithMany() + .HasForeignKey("PlayersId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_player_round_player_players_id"); + + b.HasOne("Content.Server.Database.Round", null) + .WithMany() + .HasForeignKey("RoundsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_player_round_round_rounds_id"); + }); + + modelBuilder.Entity("Content.Server.Database.Admin", b => + { + b.Navigation("Flags"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLog", b => + { + b.Navigation("Players"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminRank", b => + { + b.Navigation("Admins"); + + b.Navigation("Flags"); + }); + + modelBuilder.Entity("Content.Server.Database.ConnectionLog", b => + { + b.Navigation("BanHits"); + }); + + modelBuilder.Entity("Content.Server.Database.Player", b => + { + b.Navigation("AdminLogs"); + + b.Navigation("AdminMessagesCreated"); + + b.Navigation("AdminMessagesDeleted"); + + b.Navigation("AdminMessagesLastEdited"); + + b.Navigation("AdminMessagesReceived"); + + b.Navigation("AdminNotesCreated"); + + b.Navigation("AdminNotesDeleted"); + + b.Navigation("AdminNotesLastEdited"); + + b.Navigation("AdminNotesReceived"); + + b.Navigation("AdminServerBansCreated"); + + b.Navigation("AdminServerBansLastEdited"); + + b.Navigation("AdminServerRoleBansCreated"); + + b.Navigation("AdminServerRoleBansLastEdited"); + + b.Navigation("AdminWatchlistsCreated"); + + b.Navigation("AdminWatchlistsDeleted"); + + b.Navigation("AdminWatchlistsLastEdited"); + + b.Navigation("AdminWatchlistsReceived"); + }); + + modelBuilder.Entity("Content.Server.Database.Preference", b => + { + b.Navigation("Profiles"); + }); + + modelBuilder.Entity("Content.Server.Database.Profile", b => + { + b.Navigation("Antags"); + + b.Navigation("Jobs"); + + b.Navigation("Traits"); + }); + + modelBuilder.Entity("Content.Server.Database.Round", b => + { + b.Navigation("AdminLogs"); + }); + + modelBuilder.Entity("Content.Server.Database.Server", b => + { + b.Navigation("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/20231024041159_DropAdminLogEntity.cs b/Content.Server.Database/Migrations/Sqlite/20231024041159_DropAdminLogEntity.cs new file mode 100644 index 0000000000..59e9efce4e --- /dev/null +++ b/Content.Server.Database/Migrations/Sqlite/20231024041159_DropAdminLogEntity.cs @@ -0,0 +1,46 @@ +#nullable disable + +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Content.Server.Database.Migrations.Sqlite +{ + /// + public partial class DropAdminLogEntity : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "admin_log_entity"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "admin_log_entity", + columns: table => new + { + uid = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + admin_log_id = table.Column(type: "INTEGER", nullable: true), + admin_log_round_id = table.Column(type: "INTEGER", nullable: true), + name = table.Column(type: "TEXT", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_admin_log_entity", x => x.uid); + table.ForeignKey( + name: "FK_admin_log_entity_admin_log_admin_log_id_admin_log_round_id", + columns: x => new { x.admin_log_id, x.admin_log_round_id }, + principalTable: "admin_log", + principalColumns: new[] { "admin_log_id", "round_id" }); + }); + + migrationBuilder.CreateIndex( + name: "IX_admin_log_entity_admin_log_id_admin_log_round_id", + table: "admin_log_entity", + columns: new[] { "admin_log_id", "admin_log_round_id" }); + } + } +} diff --git a/Content.Server.Database/Migrations/Sqlite/SqliteServerDbContextModelSnapshot.cs b/Content.Server.Database/Migrations/Sqlite/SqliteServerDbContextModelSnapshot.cs index 6b7d0478e7..4896118ab2 100644 --- a/Content.Server.Database/Migrations/Sqlite/SqliteServerDbContextModelSnapshot.cs +++ b/Content.Server.Database/Migrations/Sqlite/SqliteServerDbContextModelSnapshot.cs @@ -119,34 +119,6 @@ namespace Content.Server.Database.Migrations.Sqlite b.ToTable("admin_log", (string)null); }); - modelBuilder.Entity("Content.Server.Database.AdminLogEntity", b => - { - b.Property("Uid") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER") - .HasColumnName("uid"); - - b.Property("AdminLogId") - .HasColumnType("INTEGER") - .HasColumnName("admin_log_id"); - - b.Property("AdminLogRoundId") - .HasColumnType("INTEGER") - .HasColumnName("admin_log_round_id"); - - b.Property("Name") - .HasColumnType("TEXT") - .HasColumnName("name"); - - b.HasKey("Uid") - .HasName("PK_admin_log_entity"); - - b.HasIndex("AdminLogId", "AdminLogRoundId") - .HasDatabaseName("IX_admin_log_entity_admin_log_id_admin_log_round_id"); - - b.ToTable("admin_log_entity", (string)null); - }); - modelBuilder.Entity("Content.Server.Database.AdminLogPlayer", b => { b.Property("PlayerUserId") @@ -813,12 +785,20 @@ namespace Content.Server.Database.Migrations.Sqlite .HasColumnType("INTEGER") .HasColumnName("server_id"); + b.Property("StartDate") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT") + .HasDefaultValue(new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified)) + .HasColumnName("start_date"); + b.HasKey("Id") .HasName("PK_round"); b.HasIndex("ServerId") .HasDatabaseName("IX_round_server_id"); + b.HasIndex("StartDate"); + b.ToTable("round", (string)null); }); @@ -1241,14 +1221,6 @@ namespace Content.Server.Database.Migrations.Sqlite b.Navigation("Round"); }); - modelBuilder.Entity("Content.Server.Database.AdminLogEntity", b => - { - b.HasOne("Content.Server.Database.AdminLog", null) - .WithMany("Entities") - .HasForeignKey("AdminLogId", "AdminLogRoundId") - .HasConstraintName("FK_admin_log_entity_admin_log_admin_log_id_admin_log_round_id"); - }); - modelBuilder.Entity("Content.Server.Database.AdminLogPlayer", b => { b.HasOne("Content.Server.Database.Player", "Player") @@ -1606,8 +1578,6 @@ namespace Content.Server.Database.Migrations.Sqlite modelBuilder.Entity("Content.Server.Database.AdminLog", b => { - b.Navigation("Entities"); - b.Navigation("Players"); }); diff --git a/Content.Server.Database/Model.cs b/Content.Server.Database/Model.cs index 15a2a2baf4..c2ffedb31d 100644 --- a/Content.Server.Database/Model.cs +++ b/Content.Server.Database/Model.cs @@ -111,6 +111,13 @@ namespace Content.Server.Database .HasForeignKey(player => player.PlayerUserId) .HasPrincipalKey(player => player.UserId); + modelBuilder.Entity() + .HasIndex(round => round.StartDate); + + modelBuilder.Entity() + .Property(round => round.StartDate) + .HasDefaultValue(default(DateTime)); + modelBuilder.Entity() .HasKey(logPlayer => new {logPlayer.PlayerUserId, logPlayer.LogId, logPlayer.RoundId}); @@ -469,6 +476,8 @@ namespace Content.Server.Database [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)] public int Id { get; set; } + public DateTime StartDate { get; set; } + public List Players { get; set; } = default!; public List AdminLogs { get; set; } = default!; @@ -508,8 +517,6 @@ namespace Content.Server.Database [Required, Column(TypeName = "jsonb")] public JsonDocument Json { get; set; } = default!; public List Players { get; set; } = default!; - - public List Entities { get; set; } = default!; } public class AdminLogPlayer @@ -522,12 +529,6 @@ namespace Content.Server.Database [ForeignKey("LogId,RoundId")] public AdminLog Log { get; set; } = default!; } - public class AdminLogEntity - { - [Required, Key] public int Uid { get; set; } - public string? Name { get; set; } = default!; - } - // Used by SS14.Admin public interface IBanCommon where TUnban : IUnbanCommon { diff --git a/Content.Server/Administration/AdminPermsChangedEventArgs.cs b/Content.Server/Administration/AdminPermsChangedEventArgs.cs index 24ca7aca68..07eb416be6 100644 --- a/Content.Server/Administration/AdminPermsChangedEventArgs.cs +++ b/Content.Server/Administration/AdminPermsChangedEventArgs.cs @@ -1,5 +1,5 @@ using Content.Shared.Administration; -using Robust.Server.Player; +using Robust.Shared.Player; namespace Content.Server.Administration { @@ -8,7 +8,7 @@ namespace Content.Server.Administration /// public sealed class AdminPermsChangedEventArgs : EventArgs { - public AdminPermsChangedEventArgs(IPlayerSession player, AdminFlags? flags) + public AdminPermsChangedEventArgs(ICommonSession player, AdminFlags? flags) { Player = player; Flags = flags; @@ -17,7 +17,7 @@ namespace Content.Server.Administration /// /// The player that had their admin permissions changed. /// - public IPlayerSession Player { get; } + public ICommonSession Player { get; } /// /// The admin flags of the player. Null if the player is no longer an admin. diff --git a/Content.Server/Administration/Commands/AGhost.cs b/Content.Server/Administration/Commands/AGhost.cs index 42a8600ff1..2d1a15a0be 100644 --- a/Content.Server/Administration/Commands/AGhost.cs +++ b/Content.Server/Administration/Commands/AGhost.cs @@ -2,7 +2,6 @@ using Content.Shared.Administration; using Content.Shared.Ghost; using Content.Shared.Mind; -using Robust.Server.Player; using Robust.Shared.Console; namespace Content.Server.Administration.Commands @@ -18,7 +17,7 @@ namespace Content.Server.Administration.Commands public void Execute(IConsoleShell shell, string argStr, string[] args) { - var player = shell.Player as IPlayerSession; + var player = shell.Player; if (player == null) { shell.WriteLine("Nah"); diff --git a/Content.Server/Administration/Commands/AdminWhoCommand.cs b/Content.Server/Administration/Commands/AdminWhoCommand.cs index 639a9d5414..73c616d3b6 100644 --- a/Content.Server/Administration/Commands/AdminWhoCommand.cs +++ b/Content.Server/Administration/Commands/AdminWhoCommand.cs @@ -2,7 +2,6 @@ using Content.Server.Administration.Managers; using Content.Server.Afk; using Content.Shared.Administration; -using Robust.Server.Player; using Robust.Shared.Console; using Robust.Shared.Utility; @@ -35,7 +34,7 @@ public sealed class AdminWhoCommand : IConsoleCommand if (adminData.Title is { } title) sb.Append($": [{title}]"); - if (shell.Player is IPlayerSession player && adminMgr.HasAdminFlag(player, AdminFlags.Admin)) + if (shell.Player is { } player && adminMgr.HasAdminFlag(player, AdminFlags.Admin)) { if (afk.IsAfk(admin)) sb.Append(" [AFK]"); diff --git a/Content.Server/Administration/Commands/AnnounceUiCommand.cs b/Content.Server/Administration/Commands/AnnounceUiCommand.cs index c4cd7f13e4..d80db96686 100644 --- a/Content.Server/Administration/Commands/AnnounceUiCommand.cs +++ b/Content.Server/Administration/Commands/AnnounceUiCommand.cs @@ -1,7 +1,6 @@ using Content.Server.Administration.UI; using Content.Server.EUI; using Content.Shared.Administration; -using Robust.Server.Player; using Robust.Shared.Console; namespace Content.Server.Administration.Commands @@ -17,7 +16,7 @@ namespace Content.Server.Administration.Commands public void Execute(IConsoleShell shell, string argStr, string[] args) { - var player = shell.Player as IPlayerSession; + var player = shell.Player; if (player == null) { shell.WriteLine("This does not work from the server console."); diff --git a/Content.Server/Administration/Commands/BanCommand.cs b/Content.Server/Administration/Commands/BanCommand.cs index 58a801e410..156fdf496a 100644 --- a/Content.Server/Administration/Commands/BanCommand.cs +++ b/Content.Server/Administration/Commands/BanCommand.cs @@ -1,15 +1,8 @@ using System.Linq; -using System.Net; -using System.Net.Sockets; -using System.Text; using Content.Server.Administration.Managers; -using Content.Server.Administration.Notes; -using Content.Server.Database; -using Content.Server.GameTicking; using Content.Shared.Administration; using Content.Shared.CCVar; using Content.Shared.Database; -using Content.Shared.Players.PlayTimeTracking; using Robust.Server.Player; using Robust.Shared.Configuration; using Robust.Shared.Console; @@ -84,7 +77,7 @@ public sealed class BanCommand : LocalizedCommands } var located = await _locator.LookupIdByNameOrIdAsync(target); - var player = shell.Player as IPlayerSession; + var player = shell.Player; if (located == null) { @@ -102,7 +95,7 @@ public sealed class BanCommand : LocalizedCommands { if (args.Length == 1) { - var options = _playerManager.ServerSessions.Select(c => c.Name).OrderBy(c => c).ToArray(); + var options = _playerManager.Sessions.Select(c => c.Name).OrderBy(c => c).ToArray(); return CompletionResult.FromHintOptions(options, LocalizationManager.GetString("cmd-ban-hint")); } diff --git a/Content.Server/Administration/Commands/BanListCommand.cs b/Content.Server/Administration/Commands/BanListCommand.cs index 1c2be52394..a5bc97dce3 100644 --- a/Content.Server/Administration/Commands/BanListCommand.cs +++ b/Content.Server/Administration/Commands/BanListCommand.cs @@ -36,7 +36,7 @@ public sealed class BanListCommand : LocalizedCommands return; } - if (shell.Player is not IPlayerSession player) + if (shell.Player is not { } player) { var bans = await _dbManager.GetServerBansAsync(data.LastAddress, data.UserId, data.LastHWId, false); @@ -67,7 +67,7 @@ public sealed class BanListCommand : LocalizedCommands return CompletionResult.Empty; var playerMgr = IoCManager.Resolve(); - var options = playerMgr.ServerSessions.Select(c => c.Name).OrderBy(c => c).ToArray(); + var options = playerMgr.Sessions.Select(c => c.Name).OrderBy(c => c).ToArray(); return CompletionResult.FromHintOptions(options, Loc.GetString("cmd-banlist-hint")); } } diff --git a/Content.Server/Administration/Commands/BanPanelCommand.cs b/Content.Server/Administration/Commands/BanPanelCommand.cs index 6036e5aa6e..9f9ec9e89f 100644 --- a/Content.Server/Administration/Commands/BanPanelCommand.cs +++ b/Content.Server/Administration/Commands/BanPanelCommand.cs @@ -1,12 +1,6 @@ using Content.Shared.Administration; using Robust.Shared.Console; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using Content.Server.EUI; -using Robust.Server.Player; namespace Content.Server.Administration.Commands; @@ -21,7 +15,7 @@ public sealed class BanPanelCommand : LocalizedCommands public override async void Execute(IConsoleShell shell, string argStr, string[] args) { - if (shell.Player is not IPlayerSession player) + if (shell.Player is not { } player) { shell.WriteError(Loc.GetString("cmd-banpanel-server")); return; diff --git a/Content.Server/Administration/Commands/ControlMob.cs b/Content.Server/Administration/Commands/ControlMob.cs index 2d205e44d3..317461a373 100644 --- a/Content.Server/Administration/Commands/ControlMob.cs +++ b/Content.Server/Administration/Commands/ControlMob.cs @@ -1,6 +1,5 @@ +using Content.Server.Mind; using Content.Shared.Administration; -using Content.Shared.Mind; -using Robust.Server.Player; using Robust.Shared.Console; namespace Content.Server.Administration.Commands @@ -16,7 +15,7 @@ namespace Content.Server.Administration.Commands public void Execute(IConsoleShell shell, string argStr, string[] args) { - if (shell.Player is not IPlayerSession player) + if (shell.Player is not { } player) { shell.WriteLine("shell-server-cannot"); return; @@ -42,14 +41,7 @@ namespace Content.Server.Administration.Commands return; } - var mindSystem = _entities.System(); - if (!mindSystem.TryGetMind(target, out var mindId, out var mind)) - { - shell.WriteLine(Loc.GetString("shell-entity-is-not-mob")); - return; - } - - mindSystem.TransferTo(mindId, target, mind: mind); + _entities.System().ControlMob(player.UserId, target); } } } diff --git a/Content.Server/Administration/Commands/DSay.cs b/Content.Server/Administration/Commands/DSay.cs index 79b0e8db7d..61b47d7856 100644 --- a/Content.Server/Administration/Commands/DSay.cs +++ b/Content.Server/Administration/Commands/DSay.cs @@ -1,7 +1,5 @@ -using Content.Server.Chat; using Content.Server.Chat.Systems; using Content.Shared.Administration; -using Robust.Server.Player; using Robust.Shared.Console; namespace Content.Server.Administration.Commands @@ -17,7 +15,7 @@ namespace Content.Server.Administration.Commands public void Execute(IConsoleShell shell, string argStr, string[] args) { - var player = shell.Player as IPlayerSession; + var player = shell.Player; if (player == null) { shell.WriteLine("shell-only-players-can-run-this-command"); diff --git a/Content.Server/Administration/Commands/DeAdminCommand.cs b/Content.Server/Administration/Commands/DeAdminCommand.cs index c2bbfa7a33..cf65941200 100644 --- a/Content.Server/Administration/Commands/DeAdminCommand.cs +++ b/Content.Server/Administration/Commands/DeAdminCommand.cs @@ -1,10 +1,8 @@ using Content.Server.Administration.Managers; using Content.Shared.Administration; using JetBrains.Annotations; -using Robust.Server.Player; using Robust.Shared.Console; - namespace Content.Server.Administration.Commands { [UsedImplicitly] @@ -17,7 +15,7 @@ namespace Content.Server.Administration.Commands public void Execute(IConsoleShell shell, string argStr, string[] args) { - var player = shell.Player as IPlayerSession; + var player = shell.Player; if (player == null) { shell.WriteLine("You cannot use this command from the server console."); diff --git a/Content.Server/Administration/Commands/ExplosionCommand.cs b/Content.Server/Administration/Commands/ExplosionCommand.cs index d48b69a5ad..56ed78b2e2 100644 --- a/Content.Server/Administration/Commands/ExplosionCommand.cs +++ b/Content.Server/Administration/Commands/ExplosionCommand.cs @@ -3,7 +3,6 @@ using Content.Server.EUI; using Content.Server.Explosion.EntitySystems; using Content.Shared.Administration; using Content.Shared.Explosion; -using Robust.Server.Player; using Robust.Shared.Console; using Robust.Shared.Map; using Robust.Shared.Prototypes; @@ -21,7 +20,7 @@ public sealed class OpenExplosionEui : IConsoleCommand public void Execute(IConsoleShell shell, string argStr, string[] args) { - var player = shell.Player as IPlayerSession; + var player = shell.Player; if (player == null) { shell.WriteError("This does not work from the server console."); diff --git a/Content.Server/Administration/Commands/FaxUiCommand.cs b/Content.Server/Administration/Commands/FaxUiCommand.cs index b06d36d08b..cf9e97e399 100644 --- a/Content.Server/Administration/Commands/FaxUiCommand.cs +++ b/Content.Server/Administration/Commands/FaxUiCommand.cs @@ -1,7 +1,6 @@ using Content.Server.EUI; using Content.Server.Fax.AdminUI; using Content.Shared.Administration; -using Robust.Server.Player; using Robust.Shared.Console; namespace Content.Server.Administration.Commands; @@ -16,7 +15,7 @@ public sealed class FaxUiCommand : IConsoleCommand public void Execute(IConsoleShell shell, string argStr, string[] args) { - var player = shell.Player as IPlayerSession; + var player = shell.Player; if (player == null) { shell.WriteLine("shell-only-players-can-run-this-command"); diff --git a/Content.Server/Administration/Commands/OpenAdminLogsCommand.cs b/Content.Server/Administration/Commands/OpenAdminLogsCommand.cs index 9f28dc907c..47ff3e1a1c 100644 --- a/Content.Server/Administration/Commands/OpenAdminLogsCommand.cs +++ b/Content.Server/Administration/Commands/OpenAdminLogsCommand.cs @@ -1,7 +1,6 @@ using Content.Server.Administration.Logs; using Content.Server.EUI; using Content.Shared.Administration; -using Robust.Server.Player; using Robust.Shared.Console; namespace Content.Server.Administration.Commands; @@ -15,7 +14,7 @@ public sealed class OpenAdminLogsCommand : IConsoleCommand public void Execute(IConsoleShell shell, string argStr, string[] args) { - if (shell.Player is not IPlayerSession player) + if (shell.Player is not { } player) { shell.WriteLine("This does not work from the server console."); return; diff --git a/Content.Server/Administration/Commands/OpenAdminNotesCommand.cs b/Content.Server/Administration/Commands/OpenAdminNotesCommand.cs index 147c0d6a82..e6ae4f7616 100644 --- a/Content.Server/Administration/Commands/OpenAdminNotesCommand.cs +++ b/Content.Server/Administration/Commands/OpenAdminNotesCommand.cs @@ -1,7 +1,5 @@ using Content.Server.Administration.Notes; -using Content.Server.Database; using Content.Shared.Administration; -using Robust.Server.Player; using Robust.Shared.Console; namespace Content.Server.Administration.Commands; @@ -17,7 +15,7 @@ public sealed class OpenAdminNotesCommand : IConsoleCommand public async void Execute(IConsoleShell shell, string argStr, string[] args) { - if (shell.Player is not IPlayerSession player) + if (shell.Player is not { } player) { shell.WriteError("This does not work from the server console."); return; diff --git a/Content.Server/Administration/Commands/OpenPermissionsCommand.cs b/Content.Server/Administration/Commands/OpenPermissionsCommand.cs index 78d56cb4fb..fd3227d4aa 100644 --- a/Content.Server/Administration/Commands/OpenPermissionsCommand.cs +++ b/Content.Server/Administration/Commands/OpenPermissionsCommand.cs @@ -1,10 +1,8 @@ using Content.Server.Administration.UI; using Content.Server.EUI; using Content.Shared.Administration; -using Robust.Server.Player; using Robust.Shared.Console; - namespace Content.Server.Administration.Commands { [AdminCommand(AdminFlags.Permissions)] @@ -16,7 +14,7 @@ namespace Content.Server.Administration.Commands public void Execute(IConsoleShell shell, string argStr, string[] args) { - var player = shell.Player as IPlayerSession; + var player = shell.Player; if (player == null) { shell.WriteLine("This does not work from the server console."); diff --git a/Content.Server/Administration/Commands/OpenUserVisibleNotesCommand.cs b/Content.Server/Administration/Commands/OpenUserVisibleNotesCommand.cs index d61114fcae..507c7ab279 100644 --- a/Content.Server/Administration/Commands/OpenUserVisibleNotesCommand.cs +++ b/Content.Server/Administration/Commands/OpenUserVisibleNotesCommand.cs @@ -1,7 +1,6 @@ using Content.Server.Administration.Notes; using Content.Shared.Administration; using Content.Shared.CCVar; -using Robust.Server.Player; using Robust.Shared.Configuration; using Robust.Shared.Console; @@ -27,7 +26,7 @@ public sealed class OpenUserVisibleNotesCommand : IConsoleCommand return; } - if (shell.Player is not IPlayerSession player) + if (shell.Player is not { } player) { shell.WriteError("This does not work from the server console."); return; diff --git a/Content.Server/Administration/Commands/PardonCommand.cs b/Content.Server/Administration/Commands/PardonCommand.cs index 869024eb7c..9cbaaece31 100644 --- a/Content.Server/Administration/Commands/PardonCommand.cs +++ b/Content.Server/Administration/Commands/PardonCommand.cs @@ -1,7 +1,6 @@ using System.Text; using Content.Server.Database; using Content.Shared.Administration; -using Robust.Server.Player; using Robust.Shared.Console; namespace Content.Server.Administration.Commands @@ -15,7 +14,7 @@ namespace Content.Server.Administration.Commands public async void Execute(IConsoleShell shell, string argStr, string[] args) { - var player = shell.Player as IPlayerSession; + var player = shell.Player; var dbMan = IoCManager.Resolve(); if (args.Length != 1) diff --git a/Content.Server/Administration/Commands/PlayGlobalSoundCommand.cs b/Content.Server/Administration/Commands/PlayGlobalSoundCommand.cs index ec5b21dcee..fdf067181d 100644 --- a/Content.Server/Administration/Commands/PlayGlobalSoundCommand.cs +++ b/Content.Server/Administration/Commands/PlayGlobalSoundCommand.cs @@ -6,7 +6,6 @@ using Robust.Shared.Audio; using Robust.Shared.Console; using Robust.Shared.ContentPack; using Robust.Shared.Player; -using Robust.Shared.Players; using Robust.Shared.Prototypes; namespace Content.Server.Administration.Commands; diff --git a/Content.Server/Administration/Commands/ReAdminCommand.cs b/Content.Server/Administration/Commands/ReAdminCommand.cs index 12ff13221a..a3f5993766 100644 --- a/Content.Server/Administration/Commands/ReAdminCommand.cs +++ b/Content.Server/Administration/Commands/ReAdminCommand.cs @@ -1,9 +1,7 @@ using Content.Server.Administration.Managers; using Content.Shared.Administration; -using Robust.Server.Player; using Robust.Shared.Console; - namespace Content.Server.Administration.Commands { [AnyCommand] @@ -15,7 +13,7 @@ namespace Content.Server.Administration.Commands public void Execute(IConsoleShell shell, string argStr, string[] args) { - var player = shell.Player as IPlayerSession; + var player = shell.Player; if (player == null) { shell.WriteLine("You cannot use this command from the server console."); diff --git a/Content.Server/Administration/Commands/SetAdminOOC.cs b/Content.Server/Administration/Commands/SetAdminOOC.cs index bb11b938d8..27528e1940 100644 --- a/Content.Server/Administration/Commands/SetAdminOOC.cs +++ b/Content.Server/Administration/Commands/SetAdminOOC.cs @@ -1,8 +1,6 @@ - using Content.Server.Database; using Content.Server.Preferences.Managers; using Content.Shared.Administration; -using Robust.Server.Player; using Robust.Shared.Console; namespace Content.Server.Administration.Commands @@ -16,7 +14,7 @@ namespace Content.Server.Administration.Commands public void Execute(IConsoleShell shell, string argStr, string[] args) { - if (!(shell.Player is IPlayerSession)) + if (shell.Player == null) { shell.WriteError(Loc.GetString("shell-only-players-can-run-this-command")); return; diff --git a/Content.Server/Administration/Commands/SetMindCommand.cs b/Content.Server/Administration/Commands/SetMindCommand.cs index b9ff329ed2..5310c2dd7f 100644 --- a/Content.Server/Administration/Commands/SetMindCommand.cs +++ b/Content.Server/Administration/Commands/SetMindCommand.cs @@ -2,6 +2,7 @@ using Content.Server.Players; using Content.Shared.Administration; using Content.Shared.Mind; using Content.Shared.Mind.Components; +using Content.Shared.Players; using Robust.Server.Player; using Robust.Shared.Console; diff --git a/Content.Server/Administration/Commands/SetOutfitCommand.cs b/Content.Server/Administration/Commands/SetOutfitCommand.cs index 28172ee6c5..b2e7f4e6cc 100644 --- a/Content.Server/Administration/Commands/SetOutfitCommand.cs +++ b/Content.Server/Administration/Commands/SetOutfitCommand.cs @@ -10,7 +10,6 @@ using Content.Shared.PDA; using Content.Shared.Preferences; using Content.Shared.Roles; using Robust.Server.GameObjects; -using Robust.Server.Player; using Robust.Shared.Console; using Robust.Shared.Prototypes; @@ -57,7 +56,7 @@ namespace Content.Server.Administration.Commands if (args.Length == 1) { - if (shell.Player is not IPlayerSession player) + if (shell.Player is not { } player) { shell.WriteError(Loc.GetString("set-outfit-command-is-not-player-error")); return; diff --git a/Content.Server/Administration/Commands/VariantizeCommand.cs b/Content.Server/Administration/Commands/VariantizeCommand.cs index 1b5cbbd4d5..7aabd76335 100644 --- a/Content.Server/Administration/Commands/VariantizeCommand.cs +++ b/Content.Server/Administration/Commands/VariantizeCommand.cs @@ -12,6 +12,7 @@ public sealed class VariantizeCommand : IConsoleCommand { [Dependency] private readonly IEntityManager _entManager = default!; [Dependency] private readonly IRobustRandom _random = default!; + [Dependency] private readonly ITileDefinitionManager _tileDefManager = default!; public string Command => "variantize"; @@ -39,11 +40,14 @@ public sealed class VariantizeCommand : IConsoleCommand return; } - foreach (var tile in gridComp.GetAllTiles()) + var mapsSystem = _entManager.System(); + var tileSystem = _entManager.System(); + + foreach (var tile in mapsSystem.GetAllTiles(euid.Value, gridComp)) { - var def = tile.GetContentTileDefinition(); - var newTile = new Tile(tile.Tile.TypeId, tile.Tile.Flags, def.PickVariant(_random)); - gridComp.SetTile(tile.GridIndices, newTile); + var def = tile.GetContentTileDefinition(_tileDefManager); + var newTile = new Tile(tile.Tile.TypeId, tile.Tile.Flags, tileSystem.PickVariant(def)); + mapsSystem.SetTile(euid.Value, gridComp, tile.GridIndices, newTile); } } } diff --git a/Content.Server/Administration/Commands/WarpCommand.cs b/Content.Server/Administration/Commands/WarpCommand.cs index 30a6d127aa..0d6da0d993 100644 --- a/Content.Server/Administration/Commands/WarpCommand.cs +++ b/Content.Server/Administration/Commands/WarpCommand.cs @@ -4,11 +4,9 @@ using Content.Server.Warps; using Content.Shared.Administration; using Content.Shared.Follower; using Content.Shared.Ghost; -using Robust.Server.Player; using Robust.Shared.Console; using Robust.Shared.Enums; using Robust.Shared.Map; -using Robust.Shared.Physics; using Robust.Shared.Physics.Components; using Robust.Shared.Physics.Systems; @@ -28,7 +26,7 @@ namespace Content.Server.Administration.Commands public void Execute(IConsoleShell shell, string argStr, string[] args) { - var player = shell.Player as IPlayerSession; + var player = shell.Player; if (player == null) { shell.WriteLine("Only players can use this command"); diff --git a/Content.Server/Administration/ContentNetworkResourceManager.cs b/Content.Server/Administration/ContentNetworkResourceManager.cs index 0d3f3291e6..dd95a2d897 100644 --- a/Content.Server/Administration/ContentNetworkResourceManager.cs +++ b/Content.Server/Administration/ContentNetworkResourceManager.cs @@ -1,8 +1,8 @@ using Content.Server.Database; using Content.Shared.CCVar; -using Robust.Server.Player; using Robust.Server.Upload; using Robust.Shared.Configuration; +using Robust.Shared.Player; using Robust.Shared.Upload; namespace Content.Server.Administration; @@ -22,7 +22,7 @@ public sealed class ContentNetworkResourceManager _netRes.OnResourceUploaded += OnUploadResource; } - private async void OnUploadResource(IPlayerSession session, NetworkResourceUploadMessage msg) + private async void OnUploadResource(ICommonSession session, NetworkResourceUploadMessage msg) { if (StoreUploaded) await _serverDb.AddUploadedResourceLogAsync(session.UserId, DateTime.Now, msg.RelativePath.ToString(), msg.Data); diff --git a/Content.Server/Administration/Logs/AdminLogManager.Json.cs b/Content.Server/Administration/Logs/AdminLogManager.Json.cs index 43a1e0b8b5..0a67d61cef 100644 --- a/Content.Server/Administration/Logs/AdminLogManager.Json.cs +++ b/Content.Server/Administration/Logs/AdminLogManager.Json.cs @@ -2,10 +2,9 @@ using System.Text.Json; using System.Text.Json.Serialization; using Content.Server.Administration.Logs.Converters; -using Content.Server.Database; using Robust.Server.GameObjects; -using Robust.Server.Player; using Robust.Shared.Map; +using Robust.Shared.Player; namespace Content.Server.Administration.Logs; @@ -34,10 +33,9 @@ public sealed partial class AdminLogManager _sawmill.Debug($"Admin log converters found: {string.Join(" ", converterNames)}"); } - private (JsonDocument Json, HashSet Players, List Entities) ToJson( + private (JsonDocument Json, HashSet Players) ToJson( Dictionary properties) { - var entities = new Dictionary(); var players = new HashSet(); var parsed = new Dictionary(); @@ -46,7 +44,7 @@ public sealed partial class AdminLogManager var value = properties[key]; value = value switch { - IPlayerSession player => new SerializablePlayer(player), + ICommonSession player => new SerializablePlayer(player), EntityCoordinates entityCoordinates => new SerializableEntityCoordinates(_entityManager, entityCoordinates), _ => value }; @@ -58,29 +56,17 @@ public sealed partial class AdminLogManager { EntityUid id => id, EntityStringRepresentation rep => rep.Uid, - IPlayerSession {AttachedEntity: {Valid: true}} session => session.AttachedEntity, + ICommonSession {AttachedEntity: {Valid: true}} session => session.AttachedEntity, IComponent component => component.Owner, _ => null }; - if (entityId is not { } uid) - { - continue; - } - - var entityName = _entityManager.TryGetComponent(uid, out MetaDataComponent? metadata) - ? metadata.EntityName - : null; - - // TODO set the id too whenever we feel like running a migration for 10 hours - entities.TryAdd(uid, new AdminLogEntity { Name = entityName }); - - if (_entityManager.TryGetComponent(uid, out ActorComponent? actor)) + if (_entityManager.TryGetComponent(entityId, out ActorComponent? actor)) { players.Add(actor.PlayerSession.UserId.UserId); } } - return (JsonSerializer.SerializeToDocument(parsed, _jsonOptions), players, entities.Values.ToList()); + return (JsonSerializer.SerializeToDocument(parsed, _jsonOptions), players); } } diff --git a/Content.Server/Administration/Logs/AdminLogManager.cs b/Content.Server/Administration/Logs/AdminLogManager.cs index 06f58f10b2..e869d089da 100644 --- a/Content.Server/Administration/Logs/AdminLogManager.cs +++ b/Content.Server/Administration/Logs/AdminLogManager.cs @@ -278,7 +278,7 @@ public sealed partial class AdminLogManager : SharedAdminLogManager, IAdminLogMa } } - private void Add(LogType type, LogImpact impact, string message, JsonDocument json, HashSet players, List entities) + private void Add(LogType type, LogImpact impact, string message, JsonDocument json, HashSet players) { var preRound = _runLevel == GameRunLevel.PreRoundLobby; var count = preRound ? _preRoundLogQueue.Count : _logQueue.Count; @@ -297,8 +297,7 @@ public sealed partial class AdminLogManager : SharedAdminLogManager, IAdminLogMa Date = DateTime.UtcNow, Message = message, Json = json, - Players = new List(players.Count), - Entities = entities + Players = new List(players.Count) }; foreach (var id in players) @@ -331,10 +330,10 @@ public sealed partial class AdminLogManager : SharedAdminLogManager, IAdminLogMa return; } - var (json, players, entities) = ToJson(handler.Values); + var (json, players) = ToJson(handler.Values); var message = handler.ToStringAndClear(); - Add(type, impact, message, json, players, entities); + Add(type, impact, message, json, players); } public override void Add(LogType type, ref LogStringHandler handler) diff --git a/Content.Server/Administration/Logs/Converters/PlayerSessionConverter.cs b/Content.Server/Administration/Logs/Converters/PlayerSessionConverter.cs index 0605c2db2a..c1567448cc 100644 --- a/Content.Server/Administration/Logs/Converters/PlayerSessionConverter.cs +++ b/Content.Server/Administration/Logs/Converters/PlayerSessionConverter.cs @@ -1,5 +1,5 @@ using System.Text.Json; -using Robust.Server.Player; +using Robust.Shared.Player; namespace Content.Server.Administration.Logs.Converters; @@ -36,9 +36,9 @@ public sealed class PlayerSessionConverter : AdminLogConverter _admins = new(); + private readonly Dictionary _admins = new(); private readonly HashSet _promotedPlayers = new(); public event Action? OnPermsChanged; - public IEnumerable ActiveAdmins => _admins + public IEnumerable ActiveAdmins => _admins .Where(p => p.Value.Data.Active) .Select(p => p.Key); - public IEnumerable AllAdmins => _admins.Select(p => p.Key); + public IEnumerable AllAdmins => _admins.Select(p => p.Key); private readonly AdminCommandPermissions _commandPermissions = new(); private readonly AdminCommandPermissions _toolshedCommandPermissions = new(); @@ -56,7 +56,7 @@ namespace Content.Server.Administration.Managers public AdminData? GetAdminData(ICommonSession session, bool includeDeAdmin = false) { - if (_admins.TryGetValue((IPlayerSession)session, out var reg) && (reg.Data.Active || includeDeAdmin)) + if (_admins.TryGetValue(session, out var reg) && (reg.Data.Active || includeDeAdmin)) { return reg.Data; } @@ -66,13 +66,13 @@ namespace Content.Server.Administration.Managers public AdminData? GetAdminData(EntityUid uid, bool includeDeAdmin = false) { - if (_playerManager.TryGetSessionByEntity(uid, out var session) && session is IPlayerSession playerSession) - return GetAdminData(playerSession, includeDeAdmin); + if (_playerManager.TryGetSessionByEntity(uid, out var session)) + return GetAdminData(session, includeDeAdmin); return null; } - public void DeAdmin(IPlayerSession session) + public void DeAdmin(ICommonSession session) { if (!_admins.TryGetValue(session, out var reg)) { @@ -95,7 +95,7 @@ namespace Content.Server.Administration.Managers UpdateAdminStatus(session); } - public void ReAdmin(IPlayerSession session) + public void ReAdmin(ICommonSession session) { if (!_admins.TryGetValue(session, out var reg)) { @@ -119,7 +119,7 @@ namespace Content.Server.Administration.Managers UpdateAdminStatus(session); } - public async void ReloadAdmin(IPlayerSession player) + public async void ReloadAdmin(ICommonSession player) { var data = await LoadAdminData(player); var curAdmin = _admins.GetValueOrDefault(player); @@ -236,7 +236,7 @@ namespace Content.Server.Administration.Managers _toolshed.ActivePermissionController = this; } - public void PromoteHost(IPlayerSession player) + public void PromoteHost(ICommonSession player) { _promotedPlayers.Add(player.UserId); @@ -250,7 +250,7 @@ namespace Content.Server.Administration.Managers } // NOTE: Also sends commands list for non admins.. - private void UpdateAdminStatus(IPlayerSession session) + private void UpdateAdminStatus(ICommonSession session) { var msg = new MsgUpdateAdminStatus(); @@ -290,7 +290,7 @@ namespace Content.Server.Administration.Managers } } - private async void LoginAdminMaybe(IPlayerSession session) + private async void LoginAdminMaybe(ICommonSession session) { var adminDat = await LoadAdminData(session); if (adminDat == null) @@ -323,7 +323,7 @@ namespace Content.Server.Administration.Managers UpdateAdminStatus(session); } - private async Task<(AdminData dat, int? rankId, bool specialLogin)?> LoadAdminData(IPlayerSession session) + private async Task<(AdminData dat, int? rankId, bool specialLogin)?> LoadAdminData(ICommonSession session) { var promoteHost = IsLocal(session) && _cfg.GetCVar(CCVars.ConsoleLoginLocal) || _promotedPlayers.Contains(session.UserId) @@ -387,7 +387,7 @@ namespace Content.Server.Administration.Managers } } - private static bool IsLocal(IPlayerSession player) + private static bool IsLocal(ICommonSession player) { var ep = player.ConnectedClient.RemoteEndPoint; var addr = ep.Address; @@ -419,7 +419,7 @@ namespace Content.Server.Administration.Managers return false; } - public bool CanCommand(IPlayerSession session, string cmdName) + public bool CanCommand(ICommonSession session, string cmdName) { if (_commandPermissions.AnyCommands.Contains(cmdName)) { @@ -474,7 +474,7 @@ namespace Content.Server.Administration.Managers return true; } - var data = GetAdminData((IPlayerSession)user); + var data = GetAdminData(user); if (data == null) { // Player isn't an admin. @@ -520,32 +520,32 @@ namespace Content.Server.Administration.Managers return (attribs.Length != 0, attribs); } - public bool CanViewVar(IPlayerSession session) + public bool CanViewVar(ICommonSession session) { return CanCommand(session, "vv"); } - public bool CanAdminPlace(IPlayerSession session) + public bool CanAdminPlace(ICommonSession session) { return GetAdminData(session)?.CanAdminPlace() ?? false; } - public bool CanScript(IPlayerSession session) + public bool CanScript(ICommonSession session) { return GetAdminData(session)?.CanScript() ?? false; } - public bool CanAdminMenu(IPlayerSession session) + public bool CanAdminMenu(ICommonSession session) { return GetAdminData(session)?.CanAdminMenu() ?? false; } - public bool CanAdminReloadPrototypes(IPlayerSession session) + public bool CanAdminReloadPrototypes(ICommonSession session) { return GetAdminData(session)?.CanAdminReloadPrototypes() ?? false; } - private void SendPermsChangedEvent(IPlayerSession session) + private void SendPermsChangedEvent(ICommonSession session) { var flags = GetAdminData(session)?.Flags; OnPermsChanged?.Invoke(new AdminPermsChangedEventArgs(session, flags)); @@ -553,7 +553,7 @@ namespace Content.Server.Administration.Managers private sealed class AdminReg { - public readonly IPlayerSession Session; + public readonly ICommonSession Session; public AdminData Data; public int? RankId; @@ -561,7 +561,7 @@ namespace Content.Server.Administration.Managers // Such as console.loginlocal or promotehost public bool IsSpecialLogin; - public AdminReg(IPlayerSession session, AdminData data) + public AdminReg(ICommonSession session, AdminData data) { Data = data; Session = session; diff --git a/Content.Server/Administration/Managers/BanManager.cs b/Content.Server/Administration/Managers/BanManager.cs index 765df17b17..4d51d35576 100644 --- a/Content.Server/Administration/Managers/BanManager.cs +++ b/Content.Server/Administration/Managers/BanManager.cs @@ -15,6 +15,7 @@ using Robust.Server.Player; using Robust.Shared.Configuration; using Robust.Shared.Enums; using Robust.Shared.Network; +using Robust.Shared.Player; using Robust.Shared.Prototypes; using Robust.Shared.Utility; @@ -283,7 +284,7 @@ public sealed class BanManager : IBanManager, IPostInjectInit SendRoleBans(player); } - public void SendRoleBans(IPlayerSession pSession) + public void SendRoleBans(ICommonSession pSession) { var roleBans = _cachedRoleBans.GetValueOrDefault(pSession.UserId) ?? new HashSet(); var bans = new MsgRoleBans() diff --git a/Content.Server/Administration/Managers/IAdminManager.cs b/Content.Server/Administration/Managers/IAdminManager.cs index eeed5cc36e..a52ec7b099 100644 --- a/Content.Server/Administration/Managers/IAdminManager.cs +++ b/Content.Server/Administration/Managers/IAdminManager.cs @@ -1,9 +1,8 @@ using Content.Shared.Administration; using Content.Shared.Administration.Managers; -using Robust.Server.Player; +using Robust.Shared.Player; using Robust.Shared.Toolshed; - namespace Content.Server.Administration.Managers { /// @@ -22,12 +21,12 @@ namespace Content.Server.Administration.Managers /// /// This does not include admins that are de-adminned. /// - IEnumerable ActiveAdmins { get; } + IEnumerable ActiveAdmins { get; } /// /// Gets all admins currently on the server, even de-adminned ones. /// - IEnumerable AllAdmins { get; } + IEnumerable AllAdmins { get; } /// /// De-admins an admin temporarily so they are effectively a normal player. @@ -35,18 +34,18 @@ namespace Content.Server.Administration.Managers /// /// De-adminned admins are able to re-admin at any time if they so desire. /// - void DeAdmin(IPlayerSession session); + void DeAdmin(ICommonSession session); /// /// Re-admins a de-adminned admin. /// - void ReAdmin(IPlayerSession session); + void ReAdmin(ICommonSession session); /// /// Re-loads the permissions of an player in case their admin data changed DB-side. /// /// - void ReloadAdmin(IPlayerSession player); + void ReloadAdmin(ICommonSession player); /// /// Reloads admin permissions for all admins with a certain rank. @@ -57,7 +56,7 @@ namespace Content.Server.Administration.Managers void Initialize(); - void PromoteHost(IPlayerSession player); + void PromoteHost(ICommonSession player); bool TryGetCommandFlags(CommandSpec command, out AdminFlags[]? flags); } diff --git a/Content.Server/Administration/Managers/IBanManager.cs b/Content.Server/Administration/Managers/IBanManager.cs index 8458feac8d..dafe3d35bd 100644 --- a/Content.Server/Administration/Managers/IBanManager.cs +++ b/Content.Server/Administration/Managers/IBanManager.cs @@ -2,8 +2,8 @@ using System.Collections.Immutable; using System.Net; using System.Threading.Tasks; using Content.Shared.Database; -using Robust.Server.Player; using Robust.Shared.Network; +using Robust.Shared.Player; namespace Content.Server.Administration.Managers; @@ -55,5 +55,5 @@ public interface IBanManager /// Sends role bans to the target /// /// Player's session - public void SendRoleBans(IPlayerSession pSession); + public void SendRoleBans(ICommonSession pSession); } diff --git a/Content.Server/Administration/Notes/AdminNotesManager.cs b/Content.Server/Administration/Notes/AdminNotesManager.cs index 8a7846663f..0c1e7f3daa 100644 --- a/Content.Server/Administration/Notes/AdminNotesManager.cs +++ b/Content.Server/Administration/Notes/AdminNotesManager.cs @@ -11,7 +11,7 @@ using Content.Shared.Database; using Content.Shared.Players.PlayTimeTracking; using Robust.Shared.Configuration; using Robust.Shared.Network; -using Robust.Shared.Players; +using Robust.Shared.Player; namespace Content.Server.Administration.Notes; diff --git a/Content.Server/Administration/Notes/AdminNotesSystem.cs b/Content.Server/Administration/Notes/AdminNotesSystem.cs index fd9f3f6bfa..f2eb033dca 100644 --- a/Content.Server/Administration/Notes/AdminNotesSystem.cs +++ b/Content.Server/Administration/Notes/AdminNotesSystem.cs @@ -1,13 +1,13 @@ using Content.Server.Administration.Commands; using Content.Server.Chat.Managers; using Content.Server.EUI; -using Content.Shared.Chat; using Content.Shared.Database; using Content.Shared.Verbs; using Robust.Server.GameObjects; using Robust.Server.Player; using Robust.Shared.Console; using Robust.Shared.Enums; +using Robust.Shared.Player; using Robust.Shared.Utility; namespace Content.Server.Administration.Notes; diff --git a/Content.Server/Administration/Notes/IAdminNotesManager.cs b/Content.Server/Administration/Notes/IAdminNotesManager.cs index ae7133c56d..a726bd11c8 100644 --- a/Content.Server/Administration/Notes/IAdminNotesManager.cs +++ b/Content.Server/Administration/Notes/IAdminNotesManager.cs @@ -2,7 +2,7 @@ using System.Threading.Tasks; using Content.Server.Database; using Content.Shared.Administration.Notes; using Content.Shared.Database; -using Robust.Shared.Players; +using Robust.Shared.Player; namespace Content.Server.Administration.Notes; diff --git a/Content.Server/Administration/QuickDialogSystem.OpenDialog.cs b/Content.Server/Administration/QuickDialogSystem.OpenDialog.cs index 521bee776f..fb013a88ad 100644 --- a/Content.Server/Administration/QuickDialogSystem.OpenDialog.cs +++ b/Content.Server/Administration/QuickDialogSystem.OpenDialog.cs @@ -1,6 +1,6 @@ using Content.Shared.Administration; using JetBrains.Annotations; -using Robust.Server.Player; +using Robust.Shared.Player; namespace Content.Server.Administration; @@ -16,7 +16,7 @@ public sealed partial class QuickDialogSystem /// The action to execute upon the dialog being cancelled. /// Type of the input. [PublicAPI] - public void OpenDialog(IPlayerSession session, string title, string prompt, Action okAction, + public void OpenDialog(ICommonSession session, string title, string prompt, Action okAction, Action? cancelAction = null) { OpenDialogInternal( @@ -53,7 +53,7 @@ public sealed partial class QuickDialogSystem /// Type of the first input. /// Type of the second input. [PublicAPI] - public void OpenDialog(IPlayerSession session, string title, string prompt1, string prompt2, + public void OpenDialog(ICommonSession session, string title, string prompt1, string prompt2, Action okAction, Action? cancelAction = null) { OpenDialogInternal( @@ -96,7 +96,7 @@ public sealed partial class QuickDialogSystem /// Type of the second input. /// Type of the third input. [PublicAPI] - public void OpenDialog(IPlayerSession session, string title, string prompt1, string prompt2, + public void OpenDialog(ICommonSession session, string title, string prompt1, string prompt2, string prompt3, Action okAction, Action? cancelAction = null) { OpenDialogInternal( @@ -142,7 +142,7 @@ public sealed partial class QuickDialogSystem /// Type of the third input. /// Type of the fourth input. [PublicAPI] - public void OpenDialog(IPlayerSession session, string title, string prompt1, string prompt2, + public void OpenDialog(ICommonSession session, string title, string prompt1, string prompt2, string prompt3, string prompt4, Action okAction, Action? cancelAction = null) { OpenDialogInternal( diff --git a/Content.Server/Administration/QuickDialogSystem.cs b/Content.Server/Administration/QuickDialogSystem.cs index 51b8cf79c2..96423e5223 100644 --- a/Content.Server/Administration/QuickDialogSystem.cs +++ b/Content.Server/Administration/QuickDialogSystem.cs @@ -1,12 +1,9 @@ -using System.ComponentModel; -using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.CodeAnalysis; using Content.Shared.Administration; -using Microsoft.CodeAnalysis.CSharp.Syntax; using Robust.Server.Player; using Robust.Shared.Enums; using Robust.Shared.Network; using Robust.Shared.Player; -using Robust.Shared.Serialization.TypeSerializers.Interfaces; namespace Content.Server.Administration; @@ -87,7 +84,7 @@ public sealed partial class QuickDialogSystem : EntitySystem _openDialogsByUser.Remove(user); } - private void OpenDialogInternal(IPlayerSession session, string title, List entries, QuickDialogButtonFlag buttons, Action okAction, Action cancelAction) + private void OpenDialogInternal(ICommonSession session, string title, List entries, QuickDialogButtonFlag buttons, Action okAction, Action cancelAction) { var did = GetDialogId(); RaiseNetworkEvent( diff --git a/Content.Server/Administration/Systems/AdminSystem.cs b/Content.Server/Administration/Systems/AdminSystem.cs index 66f7a8999b..feabaa2aad 100644 --- a/Content.Server/Administration/Systems/AdminSystem.cs +++ b/Content.Server/Administration/Systems/AdminSystem.cs @@ -109,7 +109,7 @@ namespace Content.Server.Administration.Systems } } - public void UpdatePlayerList(IPlayerSession player) + public void UpdatePlayerList(ICommonSession player) { _playerList[player.UserId] = GetPlayerInfo(player.Data, player); @@ -203,7 +203,7 @@ namespace Content.Server.Administration.Systems UpdatePanicBunker(); } - private void SendFullPlayerList(IPlayerSession playerSession) + private void SendFullPlayerList(ICommonSession playerSession) { var ev = new FullPlayerListEvent(); @@ -212,7 +212,7 @@ namespace Content.Server.Administration.Systems RaiseNetworkEvent(ev, playerSession.ConnectedClient); } - private PlayerInfo GetPlayerInfo(IPlayerData data, IPlayerSession? session) + private PlayerInfo GetPlayerInfo(SessionData data, ICommonSession? session) { var name = data.UserName; var entityName = string.Empty; @@ -326,7 +326,7 @@ namespace Content.Server.Administration.Systems /// chat messages and showing a popup to other players. /// Their items are dropped on the ground. /// - public void Erase(IPlayerSession player) + public void Erase(ICommonSession player) { var entity = player.AttachedEntity; _chat.DeleteMessagesBy(player); diff --git a/Content.Server/Administration/Systems/AdminTestArenaSystem.cs b/Content.Server/Administration/Systems/AdminTestArenaSystem.cs index e65acf571c..e3671bcdfb 100644 --- a/Content.Server/Administration/Systems/AdminTestArenaSystem.cs +++ b/Content.Server/Administration/Systems/AdminTestArenaSystem.cs @@ -1,8 +1,8 @@ using Robust.Server.GameObjects; -using Robust.Server.Player; using Robust.Shared.Map; using Robust.Shared.Map.Components; using Robust.Shared.Network; +using Robust.Shared.Player; namespace Content.Server.Administration.Systems; @@ -20,7 +20,7 @@ public sealed class AdminTestArenaSystem : EntitySystem public Dictionary ArenaMap { get; private set; } = new(); public Dictionary ArenaGrid { get; private set; } = new(); - public (EntityUid Map, EntityUid? Grid) AssertArenaLoaded(IPlayerSession admin) + public (EntityUid Map, EntityUid? Grid) AssertArenaLoaded(ICommonSession admin) { if (ArenaMap.TryGetValue(admin.UserId, out var arenaMap) && !Deleted(arenaMap) && !Terminating(arenaMap)) { diff --git a/Content.Server/Administration/Systems/AdminVerbSystem.cs b/Content.Server/Administration/Systems/AdminVerbSystem.cs index c7e23374a3..bc065745f5 100644 --- a/Content.Server/Administration/Systems/AdminVerbSystem.cs +++ b/Content.Server/Administration/Systems/AdminVerbSystem.cs @@ -6,6 +6,7 @@ using Content.Server.Disposal.Tube; using Content.Server.Disposal.Tube.Components; using Content.Server.EUI; using Content.Server.Ghost.Roles; +using Content.Server.Mind; using Content.Server.Mind.Commands; using Content.Server.Prayer; using Content.Server.Xenoarchaeology.XenoArtifacts; @@ -18,17 +19,15 @@ using Content.Shared.Database; using Content.Shared.Examine; using Content.Shared.GameTicking; using Content.Shared.Inventory; -using Content.Shared.Mind; using Content.Shared.Mind.Components; using Content.Shared.Popups; using Content.Shared.Verbs; using Robust.Server.Console; using Robust.Server.GameObjects; -using Robust.Server.Player; using Robust.Shared.Console; using Robust.Shared.Map; using Robust.Shared.Map.Components; -using Robust.Shared.Players; +using Robust.Shared.Player; using Robust.Shared.Prototypes; using Robust.Shared.Timing; using Robust.Shared.Toolshed; @@ -56,7 +55,7 @@ namespace Content.Server.Administration.Systems [Dependency] private readonly UserInterfaceSystem _uiSystem = default!; [Dependency] private readonly PrayerSystem _prayerSystem = default!; [Dependency] private readonly EuiManager _eui = default!; - [Dependency] private readonly SharedMindSystem _mindSystem = default!; + [Dependency] private readonly MindSystem _mindSystem = default!; [Dependency] private readonly ToolshedManager _toolshed = default!; [Dependency] private readonly RejuvenateSystem _rejuvenate = default!; [Dependency] private readonly SharedPopupSystem _popup = default!; @@ -277,12 +276,7 @@ namespace Content.Server.Administration.Systems // TODO VERB ICON control mob icon Act = () => { - MakeSentientCommand.MakeSentient(args.Target, EntityManager); - - if (!_minds.TryGetMind(player, out var mindId, out var mind)) - return; - - _mindSystem.TransferTo(mindId, args.Target, ghostCheckOverride: true, mind: mind); + _mindSystem.ControlMob(args.User, args.Target); }, Impact = LogImpact.High, ConfirmationPopup = true @@ -358,7 +352,7 @@ namespace Content.Server.Administration.Systems var message = ExamineSystemShared.InRangeUnOccluded(args.User, args.Target) ? Loc.GetString("in-range-unoccluded-verb-on-activate-not-occluded") : Loc.GetString("in-range-unoccluded-verb-on-activate-occluded"); - + _popup.PopupEntity(message, args.Target, args.User); } }; @@ -432,7 +426,7 @@ namespace Content.Server.Administration.Systems } } - public void OpenEditSolutionsEui(IPlayerSession session, EntityUid uid) + public void OpenEditSolutionsEui(ICommonSession session, EntityUid uid) { if (session.AttachedEntity == null) return; diff --git a/Content.Server/Administration/Systems/BwoinkSystem.cs b/Content.Server/Administration/Systems/BwoinkSystem.cs index 98e5af1126..31ef285a88 100644 --- a/Content.Server/Administration/Systems/BwoinkSystem.cs +++ b/Content.Server/Administration/Systems/BwoinkSystem.cs @@ -17,6 +17,7 @@ using Robust.Shared; using Robust.Shared.Configuration; using Robust.Shared.Enums; using Robust.Shared.Network; +using Robust.Shared.Player; using Robust.Shared.Timing; using Robust.Shared.Utility; @@ -119,7 +120,7 @@ namespace Content.Server.Administration.Systems _typingUpdateTimestamps[args.SenderSession.UserId] = (_timing.RealTime, msg.Typing); // Non-admins can only ever type on their own ahelp, guard against fake messages - var isAdmin = _adminManager.GetAdminData((IPlayerSession) args.SenderSession)?.HasFlag(AdminFlags.Adminhelp) ?? false; + var isAdmin = _adminManager.GetAdminData(args.SenderSession)?.HasFlag(AdminFlags.Adminhelp) ?? false; var channel = isAdmin ? msg.Channel : args.SenderSession.UserId; var update = new BwoinkPlayerTypingUpdated(channel, args.SenderSession.Name, msg.Typing); @@ -376,7 +377,7 @@ namespace Content.Server.Administration.Systems protected override void OnBwoinkTextMessage(BwoinkTextMessage message, EntitySessionEventArgs eventArgs) { base.OnBwoinkTextMessage(message, eventArgs); - var senderSession = (IPlayerSession) eventArgs.SenderSession; + var senderSession = eventArgs.SenderSession; // TODO: Sanitize text? // Confirm that this person is actually allowed to send a message here. diff --git a/Content.Server/Administration/Toolshed/AdminsCommand.cs b/Content.Server/Administration/Toolshed/AdminsCommand.cs index aa82e0f1d9..1d64f748fd 100644 --- a/Content.Server/Administration/Toolshed/AdminsCommand.cs +++ b/Content.Server/Administration/Toolshed/AdminsCommand.cs @@ -1,6 +1,6 @@ using Content.Server.Administration.Managers; using Content.Shared.Administration; -using Robust.Server.Player; +using Robust.Shared.Player; using Robust.Shared.Toolshed; namespace Content.Server.Administration.Toolshed; @@ -11,13 +11,13 @@ public sealed class AdminsCommand : ToolshedCommand [Dependency] private readonly IAdminManager _admin = default!; [CommandImplementation("active")] - public IEnumerable Active() + public IEnumerable Active() { return _admin.ActiveAdmins; } [CommandImplementation("all")] - public IEnumerable All() + public IEnumerable All() { return _admin.AllAdmins; } diff --git a/Content.Server/Afk/AFKSystem.cs b/Content.Server/Afk/AFKSystem.cs index 0938f45f73..f634a415dc 100644 --- a/Content.Server/Afk/AFKSystem.cs +++ b/Content.Server/Afk/AFKSystem.cs @@ -1,4 +1,3 @@ -using System.Linq; using Content.Server.Afk.Events; using Content.Server.GameTicking; using Content.Shared.CCVar; @@ -24,7 +23,7 @@ public sealed class AFKSystem : EntitySystem private float _checkDelay; private TimeSpan _checkTime; - private readonly HashSet _afkPlayers = new(); + private readonly HashSet _afkPlayers = new(); public override void Initialize() { @@ -73,11 +72,9 @@ public sealed class AFKSystem : EntitySystem _checkTime = _timing.CurTime + TimeSpan.FromSeconds(_checkDelay); - foreach (var session in Filter.GetAllPlayers()) + foreach (var pSession in Filter.GetAllPlayers()) { - if (session.Status != SessionStatus.InGame) continue; - - var pSession = (IPlayerSession) session; + if (pSession.Status != SessionStatus.InGame) continue; var isAfk = _afkManager.IsAfk(pSession); if (isAfk && _afkPlayers.Add(pSession)) diff --git a/Content.Server/Afk/AfkManager.cs b/Content.Server/Afk/AfkManager.cs index 24cd1e28ce..52dc7715df 100644 --- a/Content.Server/Afk/AfkManager.cs +++ b/Content.Server/Afk/AfkManager.cs @@ -5,6 +5,7 @@ using Robust.Shared.Configuration; using Robust.Shared.Console; using Robust.Shared.Enums; using Robust.Shared.Input; +using Robust.Shared.Player; using Robust.Shared.Timing; namespace Content.Server.Afk @@ -20,13 +21,13 @@ namespace Content.Server.Afk /// /// The player to check. /// True if the player is AFK, false otherwise. - bool IsAfk(IPlayerSession player); + bool IsAfk(ICommonSession player); /// /// Resets AFK status for the player as if they just did an action and are definitely not AFK. /// /// The player to set AFK status for. - void PlayerDidAction(IPlayerSession player); + void PlayerDidAction(ICommonSession player); void Initialize(); } @@ -40,7 +41,7 @@ namespace Content.Server.Afk [Dependency] private readonly IConfigurationManager _cfg = default!; [Dependency] private readonly IConsoleHost _consoleHost = default!; - private readonly Dictionary _lastActionTimes = new(); + private readonly Dictionary _lastActionTimes = new(); public void Initialize() { @@ -55,7 +56,7 @@ namespace Content.Server.Afk HandleInputCmd); } - public void PlayerDidAction(IPlayerSession player) + public void PlayerDidAction(ICommonSession player) { if (player.Status == SessionStatus.Disconnected) // Make sure we don't re-add to the dictionary if the player is disconnected now. @@ -64,7 +65,7 @@ namespace Content.Server.Afk _lastActionTimes[player] = _gameTiming.RealTime; } - public bool IsAfk(IPlayerSession player) + public bool IsAfk(ICommonSession player) { if (!_lastActionTimes.TryGetValue(player, out var time)) // Some weird edge case like disconnected clients. Just say true I guess. @@ -87,13 +88,13 @@ namespace Content.Server.Afk private void ConsoleHostOnAnyCommandExecuted(IConsoleShell shell, string commandname, string argstr, string[] args) { - if (shell.Player is IPlayerSession player) + if (shell.Player is { } player) PlayerDidAction(player); } private void HandleInputCmd(FullInputCmdMessage msg, EntitySessionEventArgs args) { - PlayerDidAction((IPlayerSession) args.SenderSession); + PlayerDidAction(args.SenderSession); } } } diff --git a/Content.Server/Afk/Events/AFKEvent.cs b/Content.Server/Afk/Events/AFKEvent.cs index 6adb950e47..ee9d548043 100644 --- a/Content.Server/Afk/Events/AFKEvent.cs +++ b/Content.Server/Afk/Events/AFKEvent.cs @@ -1,4 +1,4 @@ -using Robust.Server.Player; +using Robust.Shared.Player; namespace Content.Server.Afk.Events; @@ -8,9 +8,9 @@ namespace Content.Server.Afk.Events; [ByRefEvent] public readonly struct AFKEvent { - public readonly IPlayerSession Session; + public readonly ICommonSession Session; - public AFKEvent(IPlayerSession playerSession) + public AFKEvent(ICommonSession playerSession) { Session = playerSession; } diff --git a/Content.Server/Afk/Events/UnAFKEvent.cs b/Content.Server/Afk/Events/UnAFKEvent.cs index 3dd034583c..0983c256f0 100644 --- a/Content.Server/Afk/Events/UnAFKEvent.cs +++ b/Content.Server/Afk/Events/UnAFKEvent.cs @@ -1,4 +1,4 @@ -using Robust.Server.Player; +using Robust.Shared.Player; namespace Content.Server.Afk.Events; @@ -8,9 +8,9 @@ namespace Content.Server.Afk.Events; [ByRefEvent] public readonly struct UnAFKEvent { - public readonly IPlayerSession Session; + public readonly ICommonSession Session; - public UnAFKEvent(IPlayerSession playerSession) + public UnAFKEvent(ICommonSession playerSession) { Session = playerSession; } diff --git a/Content.Server/Alert/Commands/ClearAlert.cs b/Content.Server/Alert/Commands/ClearAlert.cs index e43f06413c..1759612702 100644 --- a/Content.Server/Alert/Commands/ClearAlert.cs +++ b/Content.Server/Alert/Commands/ClearAlert.cs @@ -2,7 +2,6 @@ using Content.Server.Administration; using Content.Server.Commands; using Content.Shared.Administration; using Content.Shared.Alert; -using Robust.Server.Player; using Robust.Shared.Console; namespace Content.Server.Alert.Commands @@ -16,7 +15,7 @@ namespace Content.Server.Alert.Commands public void Execute(IConsoleShell shell, string argStr, string[] args) { - var player = shell.Player as IPlayerSession; + var player = shell.Player; if (player?.AttachedEntity == null) { shell.WriteLine("You don't have an entity."); diff --git a/Content.Server/Alert/Commands/ShowAlert.cs b/Content.Server/Alert/Commands/ShowAlert.cs index edb634b546..11901e9af0 100644 --- a/Content.Server/Alert/Commands/ShowAlert.cs +++ b/Content.Server/Alert/Commands/ShowAlert.cs @@ -2,7 +2,6 @@ using Content.Server.Administration; using Content.Server.Commands; using Content.Shared.Administration; using Content.Shared.Alert; -using Robust.Server.Player; using Robust.Shared.Console; namespace Content.Server.Alert.Commands @@ -16,7 +15,7 @@ namespace Content.Server.Alert.Commands public void Execute(IConsoleShell shell, string argStr, string[] args) { - var player = shell.Player as IPlayerSession; + var player = shell.Player; if (player?.AttachedEntity == null) { shell.WriteLine("You cannot run this from the server or without an attached entity."); diff --git a/Content.Server/AlertLevel/Commands/SetAlertLevelCommand.cs b/Content.Server/AlertLevel/Commands/SetAlertLevelCommand.cs index 009a8b5f23..2c432a2419 100644 --- a/Content.Server/AlertLevel/Commands/SetAlertLevelCommand.cs +++ b/Content.Server/AlertLevel/Commands/SetAlertLevelCommand.cs @@ -3,7 +3,6 @@ using Content.Server.Administration; using Content.Server.Station.Systems; using Content.Shared.Administration; using JetBrains.Annotations; -using Robust.Server.Player; using Robust.Shared.Console; namespace Content.Server.AlertLevel.Commands @@ -19,7 +18,7 @@ namespace Content.Server.AlertLevel.Commands public CompletionResult GetCompletion(IConsoleShell shell, string[] args) { var levelNames = new string[] {}; - var player = shell.Player as IPlayerSession; + var player = shell.Player; if (player?.AttachedEntity != null) { var stationUid = EntitySystem.Get().GetOwningStation(player.AttachedEntity.Value); @@ -54,7 +53,7 @@ namespace Content.Server.AlertLevel.Commands return; } - var player = shell.Player as IPlayerSession; + var player = shell.Player; if (player?.AttachedEntity == null) { shell.WriteLine(Loc.GetString("shell-only-players-can-run-this-command")); diff --git a/Content.Server/Antag/AntagSelectionSystem.cs b/Content.Server/Antag/AntagSelectionSystem.cs index 5e323f5ab8..737b723d39 100644 --- a/Content.Server/Antag/AntagSelectionSystem.cs +++ b/Content.Server/Antag/AntagSelectionSystem.cs @@ -22,6 +22,7 @@ using Content.Server.Station.Systems; using Content.Server.Shuttles.Systems; using Content.Shared.Mobs; using Robust.Server.Containers; +using Robust.Shared.Player; using Robust.Shared.Prototypes; namespace Content.Server.Antag; @@ -88,9 +89,9 @@ public sealed class AntagSelectionSystem : GameRuleSystem out List chosen, bool includeHeads = false) { - var allPlayers = _playerSystem.ServerSessions.ToList(); - var playerList = new List(); - var prefList = new List(); + var allPlayers = _playerSystem.Sessions.ToList(); + var playerList = new List(); + var prefList = new List(); chosen = new List(); foreach (var player in allPlayers) { @@ -116,7 +117,7 @@ public sealed class AntagSelectionSystem : GameRuleSystem var antags = Math.Clamp(allPlayers.Count / antagsPerPlayer, 1, maxAntags); for (var antag = 0; antag < antags; antag++) { - IPlayerSession chosenPlayer = null!; + ICommonSession? chosenPlayer = null; if (prefList.Count == 0) { if (playerList.Count == 0) diff --git a/Content.Server/Arcade/BlockGame/BlockGame.Ui.cs b/Content.Server/Arcade/BlockGame/BlockGame.Ui.cs index 92a96ea226..ef69600783 100644 --- a/Content.Server/Arcade/BlockGame/BlockGame.Ui.cs +++ b/Content.Server/Arcade/BlockGame/BlockGame.Ui.cs @@ -1,6 +1,6 @@ using Content.Shared.Arcade; -using Robust.Server.Player; using System.Linq; +using Robust.Shared.Player; namespace Content.Server.Arcade.BlockGame; @@ -166,7 +166,7 @@ public sealed partial class BlockGame /// /// The message to send to a specific player/spectator. /// The target recipient. - private void SendMessage(BoundUserInterfaceMessage message, IPlayerSession session) + private void SendMessage(BoundUserInterfaceMessage message, ICommonSession session) { if (_uiSystem.TryGetUi(_owner, BlockGameUiKey.Key, out var bui)) _uiSystem.TrySendUiMessage(bui, message, session); @@ -176,7 +176,7 @@ public sealed partial class BlockGame /// Handles sending the current state of the game to a player that has just opened the UI. /// /// The target recipient. - public void UpdateNewPlayerUI(IPlayerSession session) + public void UpdateNewPlayerUI(ICommonSession session) { if (_gameOver) { @@ -209,7 +209,7 @@ public sealed partial class BlockGame /// Handles broadcasting the full player-visible game state to a specific player/spectator. /// /// The target recipient. - private void FullUpdate(IPlayerSession session) + private void FullUpdate(ICommonSession session) { UpdateFieldUI(session); SendNextPieceUpdate(session); @@ -235,7 +235,7 @@ public sealed partial class BlockGame /// Handles broadcasting the current location of all of the blocks in the playfield + the active piece to a specific player/spectator. /// /// The target recipient. - public void UpdateFieldUI(IPlayerSession session) + public void UpdateFieldUI(ICommonSession session) { if (!Started) return; @@ -283,7 +283,7 @@ public sealed partial class BlockGame /// Broadcasts the state of the next queued piece to a specific viewer. /// /// The target recipient. - private void SendNextPieceUpdate(IPlayerSession session) + private void SendNextPieceUpdate(ICommonSession session) { SendMessage(new BlockGameMessages.BlockGameVisualUpdateMessage(NextPiece.BlocksForPreview(), BlockGameMessages.BlockGameVisualType.NextBlock), session); } @@ -303,7 +303,7 @@ public sealed partial class BlockGame /// Broadcasts the state of the currently held piece to a specific viewer. /// /// The target recipient. - private void SendHoldPieceUpdate(IPlayerSession session) + private void SendHoldPieceUpdate(ICommonSession session) { if (HeldPiece.HasValue) SendMessage(new BlockGameMessages.BlockGameVisualUpdateMessage(HeldPiece.Value.BlocksForPreview(), BlockGameMessages.BlockGameVisualType.HoldBlock), session); @@ -323,7 +323,7 @@ public sealed partial class BlockGame /// Broadcasts the current game level to a specific viewer. /// /// The target recipient. - private void SendLevelUpdate(IPlayerSession session) + private void SendLevelUpdate(ICommonSession session) { SendMessage(new BlockGameMessages.BlockGameLevelUpdateMessage(Level), session); } @@ -340,7 +340,7 @@ public sealed partial class BlockGame /// Broadcasts the current game score to a specific viewer. /// /// The target recipient. - private void SendPointsUpdate(IPlayerSession session) + private void SendPointsUpdate(ICommonSession session) { SendMessage(new BlockGameMessages.BlockGameScoreUpdateMessage(Points), session); } @@ -357,7 +357,7 @@ public sealed partial class BlockGame /// Broadcasts the current game high score positions to a specific viewer. /// /// The target recipient. - private void SendHighscoreUpdate(IPlayerSession session) + private void SendHighscoreUpdate(ICommonSession session) { SendMessage(new BlockGameMessages.BlockGameHighScoreUpdateMessage(_arcadeSystem.GetLocalHighscores(), _arcadeSystem.GetGlobalHighscores()), session); } diff --git a/Content.Server/Arcade/BlockGame/BlockGameArcadeComponent.cs b/Content.Server/Arcade/BlockGame/BlockGameArcadeComponent.cs index 268d5be4d2..5613d91544 100644 --- a/Content.Server/Arcade/BlockGame/BlockGameArcadeComponent.cs +++ b/Content.Server/Arcade/BlockGame/BlockGameArcadeComponent.cs @@ -1,4 +1,4 @@ -using Robust.Server.Player; +using Robust.Shared.Player; namespace Content.Server.Arcade.BlockGame; @@ -13,10 +13,10 @@ public sealed partial class BlockGameArcadeComponent : Component /// /// The player currently playing the active session of NT-BG. /// - public IPlayerSession? Player = null; + public ICommonSession? Player = null; /// /// The players currently viewing (but not playing) the active session of NT-BG. /// - public readonly List Spectators = new(); + public readonly List Spectators = new(); } diff --git a/Content.Server/Arcade/BlockGame/BlockGameArcadeSystem.cs b/Content.Server/Arcade/BlockGame/BlockGameArcadeSystem.cs index dac29accc9..ecc5bfd3e2 100644 --- a/Content.Server/Arcade/BlockGame/BlockGameArcadeSystem.cs +++ b/Content.Server/Arcade/BlockGame/BlockGameArcadeSystem.cs @@ -2,7 +2,7 @@ using Content.Server.Power.Components; using Content.Server.UserInterface; using Content.Shared.Arcade; using Robust.Server.GameObjects; -using Robust.Server.Player; +using Robust.Shared.Player; namespace Content.Server.Arcade.BlockGame; @@ -30,7 +30,7 @@ public sealed class BlockGameArcadeSystem : EntitySystem } } - private void UpdatePlayerStatus(EntityUid uid, IPlayerSession session, PlayerBoundUserInterface? bui = null, BlockGameArcadeComponent? blockGame = null) + private void UpdatePlayerStatus(EntityUid uid, ICommonSession session, PlayerBoundUserInterface? bui = null, BlockGameArcadeComponent? blockGame = null) { if (!Resolve(uid, ref blockGame)) return; @@ -67,7 +67,7 @@ public sealed class BlockGameArcadeSystem : EntitySystem private void OnAfterUiClose(EntityUid uid, BlockGameArcadeComponent component, BoundUIClosedEvent args) { - if (args.Session is not IPlayerSession session) + if (args.Session is not { } session) return; if (component.Player != session) diff --git a/Content.Server/Atmos/Commands/DeleteGasCommand.cs b/Content.Server/Atmos/Commands/DeleteGasCommand.cs index 0f0c399b11..9e7594c024 100644 --- a/Content.Server/Atmos/Commands/DeleteGasCommand.cs +++ b/Content.Server/Atmos/Commands/DeleteGasCommand.cs @@ -2,7 +2,6 @@ using Content.Server.Administration; using Content.Server.Atmos.EntitySystems; using Content.Shared.Administration; using Content.Shared.Atmos; -using Robust.Server.Player; using Robust.Shared.Console; using Robust.Shared.Map; @@ -20,7 +19,7 @@ namespace Content.Server.Atmos.Commands public void Execute(IConsoleShell shell, string argStr, string[] args) { - var player = shell.Player as IPlayerSession; + var player = shell.Player; EntityUid? gridId; Gas? gas = null; diff --git a/Content.Server/Atmos/Commands/ShowAtmosCommand.cs b/Content.Server/Atmos/Commands/ShowAtmosCommand.cs index 5ad73ec906..263ef947d0 100644 --- a/Content.Server/Atmos/Commands/ShowAtmosCommand.cs +++ b/Content.Server/Atmos/Commands/ShowAtmosCommand.cs @@ -1,7 +1,6 @@ using Content.Server.Administration; using Content.Server.Atmos.EntitySystems; using Content.Shared.Administration; -using Robust.Server.Player; using Robust.Shared.Console; namespace Content.Server.Atmos.Commands @@ -15,7 +14,7 @@ namespace Content.Server.Atmos.Commands public void Execute(IConsoleShell shell, string argStr, string[] args) { - var player = shell.Player as IPlayerSession; + var player = shell.Player; if (player == null) { shell.WriteLine("You must be a player to use this command."); diff --git a/Content.Server/Atmos/EntitySystems/AtmosDebugOverlaySystem.cs b/Content.Server/Atmos/EntitySystems/AtmosDebugOverlaySystem.cs index 34f558a252..90edd4caed 100644 --- a/Content.Server/Atmos/EntitySystems/AtmosDebugOverlaySystem.cs +++ b/Content.Server/Atmos/EntitySystems/AtmosDebugOverlaySystem.cs @@ -10,6 +10,7 @@ using Robust.Shared.Configuration; using Robust.Shared.Enums; using Robust.Shared.Map; using Robust.Shared.Map.Components; +using Robust.Shared.Player; namespace Content.Server.Atmos.EntitySystems { @@ -27,7 +28,7 @@ namespace Content.Server.Atmos.EntitySystems /// To modify it see and /// . /// - private readonly HashSet _playerObservers = new(); + private readonly HashSet _playerObservers = new(); /// /// Overlay update ticks per second. @@ -48,17 +49,17 @@ namespace Content.Server.Atmos.EntitySystems _playerManager.PlayerStatusChanged -= OnPlayerStatusChanged; } - public bool AddObserver(IPlayerSession observer) + public bool AddObserver(ICommonSession observer) { return _playerObservers.Add(observer); } - public bool HasObserver(IPlayerSession observer) + public bool HasObserver(ICommonSession observer) { return _playerObservers.Contains(observer); } - public bool RemoveObserver(IPlayerSession observer) + public bool RemoveObserver(ICommonSession observer) { if (!_playerObservers.Remove(observer)) { @@ -76,7 +77,7 @@ namespace Content.Server.Atmos.EntitySystems /// /// The observer to toggle. /// true if added, false if removed. - public bool ToggleObserver(IPlayerSession observer) + public bool ToggleObserver(ICommonSession observer) { if (HasObserver(observer)) { diff --git a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.cs b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.cs index 91634de8d7..d8364b652b 100644 --- a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.cs +++ b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.cs @@ -4,6 +4,7 @@ using Content.Server.Body.Systems; using Content.Server.Maps; using Content.Server.NodeContainer.EntitySystems; using Content.Shared.Atmos.EntitySystems; +using Content.Shared.Maps; using JetBrains.Annotations; using Robust.Server.GameObjects; using Robust.Shared.Containers; diff --git a/Content.Server/Atmos/EntitySystems/GasTankSystem.cs b/Content.Server/Atmos/EntitySystems/GasTankSystem.cs index df867d3516..17715435b2 100644 --- a/Content.Server/Atmos/EntitySystems/GasTankSystem.cs +++ b/Content.Server/Atmos/EntitySystems/GasTankSystem.cs @@ -12,7 +12,6 @@ using Content.Shared.Toggleable; using Content.Shared.Verbs; using JetBrains.Annotations; using Robust.Server.GameObjects; -using Robust.Server.Player; using Robust.Shared.Audio; using Robust.Shared.Containers; using Robust.Shared.Physics.Systems; @@ -60,12 +59,6 @@ namespace Content.Server.Atmos.EntitySystems private void OnGasTankToggleInternals(Entity ent, ref GasTankToggleInternalsMessage args) { - if (args.Session is not IPlayerSession playerSession || - playerSession.AttachedEntity == null) - { - return; - } - ToggleInternals(ent); } diff --git a/Content.Server/Atmos/EntitySystems/GasTileOverlaySystem.cs b/Content.Server/Atmos/EntitySystems/GasTileOverlaySystem.cs index c229ef50c9..b0e8cf71c7 100644 --- a/Content.Server/Atmos/EntitySystems/GasTileOverlaySystem.cs +++ b/Content.Server/Atmos/EntitySystems/GasTileOverlaySystem.cs @@ -16,6 +16,7 @@ using Robust.Shared; using Robust.Shared.Configuration; using Robust.Shared.Enums; using Robust.Shared.Map; +using Robust.Shared.Player; using Robust.Shared.Threading; using Robust.Shared.Timing; using Robust.Shared.Utility; @@ -35,7 +36,7 @@ namespace Content.Server.Atmos.EntitySystems [Robust.Shared.IoC.Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!; [Robust.Shared.IoC.Dependency] private readonly ChunkingSystem _chunkingSys = default!; - private readonly Dictionary>> _lastSentChunks = new(); + private readonly Dictionary>> _lastSentChunks = new(); // Oh look its more duplicated decal system code! private ObjectPool> _chunkIndexPool = @@ -286,12 +287,12 @@ namespace Content.Server.Atmos.EntitySystems // Now we'll go through each player, then through each chunk in range of that player checking if the player is still in range // If they are, check if they need the new data to send (i.e. if there's an overlay for the gas). // Afterwards we reset all the chunk data for the next time we tick. - var players = _playerManager.ServerSessions.Where(x => x.Status == SessionStatus.InGame).ToArray(); + var players = _playerManager.Sessions.Where(x => x.Status == SessionStatus.InGame).ToArray(); var opts = new ParallelOptions { MaxDegreeOfParallelism = _parMan.ParallelProcessCount }; Parallel.ForEach(players, opts, p => UpdatePlayer(p, curTick)); } - private void UpdatePlayer(IPlayerSession playerSession, GameTick curTick) + private void UpdatePlayer(ICommonSession playerSession, GameTick curTick) { var chunksInRange = _chunkingSys.GetChunksForSession(playerSession, ChunkSize, _chunkIndexPool, _chunkViewerPool); var previouslySent = _lastSentChunks[playerSession]; diff --git a/Content.Server/Body/Commands/AddHandCommand.cs b/Content.Server/Body/Commands/AddHandCommand.cs index 308295c06c..655d0c88f9 100644 --- a/Content.Server/Body/Commands/AddHandCommand.cs +++ b/Content.Server/Body/Commands/AddHandCommand.cs @@ -4,7 +4,6 @@ using Content.Server.Body.Systems; using Content.Shared.Administration; using Content.Shared.Body.Components; using Content.Shared.Body.Part; -using Robust.Server.Player; using Robust.Shared.Console; using Robust.Shared.Prototypes; using Robust.Shared.Random; @@ -27,7 +26,7 @@ namespace Content.Server.Body.Commands public void Execute(IConsoleShell shell, string argStr, string[] args) { - var player = shell.Player as IPlayerSession; + var player = shell.Player; EntityUid entity; EntityUid hand; diff --git a/Content.Server/Body/Commands/AttachBodyPartCommand.cs b/Content.Server/Body/Commands/AttachBodyPartCommand.cs index 267b520808..24604b88b7 100644 --- a/Content.Server/Body/Commands/AttachBodyPartCommand.cs +++ b/Content.Server/Body/Commands/AttachBodyPartCommand.cs @@ -1,10 +1,8 @@ -using System.Linq; using Content.Server.Administration; using Content.Server.Body.Systems; using Content.Shared.Administration; using Content.Shared.Body.Components; using Content.Shared.Body.Part; -using Robust.Server.Player; using Robust.Shared.Console; namespace Content.Server.Body.Commands @@ -20,7 +18,7 @@ namespace Content.Server.Body.Commands public void Execute(IConsoleShell shell, string argStr, string[] args) { - var player = shell.Player as IPlayerSession; + var player = shell.Player; EntityUid bodyId; EntityUid? partUid; diff --git a/Content.Server/Body/Commands/DestroyMechanismCommand.cs b/Content.Server/Body/Commands/DestroyMechanismCommand.cs index 6ad0631150..3aa28f4072 100644 --- a/Content.Server/Body/Commands/DestroyMechanismCommand.cs +++ b/Content.Server/Body/Commands/DestroyMechanismCommand.cs @@ -2,7 +2,6 @@ using Content.Server.Administration; using Content.Server.Body.Systems; using Content.Shared.Administration; using Content.Shared.Body.Components; -using Robust.Server.Player; using Robust.Shared.Console; using Robust.Shared.Random; @@ -17,7 +16,7 @@ namespace Content.Server.Body.Commands public void Execute(IConsoleShell shell, string argStr, string[] args) { - var player = shell.Player as IPlayerSession; + var player = shell.Player; if (player == null) { shell.WriteLine("Only a player can run this command."); diff --git a/Content.Server/Body/Commands/RemoveHandCommand.cs b/Content.Server/Body/Commands/RemoveHandCommand.cs index 729db4bc44..4a2956ae7a 100644 --- a/Content.Server/Body/Commands/RemoveHandCommand.cs +++ b/Content.Server/Body/Commands/RemoveHandCommand.cs @@ -4,7 +4,6 @@ using Content.Server.Body.Systems; using Content.Shared.Administration; using Content.Shared.Body.Components; using Content.Shared.Body.Part; -using Robust.Server.Player; using Robust.Shared.Console; using Robust.Shared.Random; @@ -22,7 +21,7 @@ namespace Content.Server.Body.Commands public void Execute(IConsoleShell shell, string argStr, string[] args) { - var player = shell.Player as IPlayerSession; + var player = shell.Player; if (player == null) { shell.WriteLine("Only a player can run this command."); diff --git a/Content.Server/Body/Systems/BodySystem.cs b/Content.Server/Body/Systems/BodySystem.cs index f2f848c488..242b02d78c 100644 --- a/Content.Server/Body/Systems/BodySystem.cs +++ b/Content.Server/Body/Systems/BodySystem.cs @@ -116,7 +116,7 @@ public sealed class BodySystem : SharedBodySystem if (!Resolve(bodyId, ref body, false)) return new HashSet(); - if (LifeStage(bodyId) >= EntityLifeStage.Terminating || EntityManager.IsQueuedForDeletion(bodyId)) + if (TerminatingOrDeleted(bodyId) || EntityManager.IsQueuedForDeletion(bodyId)) return new HashSet(); var xform = Transform(bodyId); diff --git a/Content.Server/Body/Systems/InternalsSystem.cs b/Content.Server/Body/Systems/InternalsSystem.cs index ec4faa345c..17a6544976 100644 --- a/Content.Server/Body/Systems/InternalsSystem.cs +++ b/Content.Server/Body/Systems/InternalsSystem.cs @@ -197,6 +197,14 @@ public sealed class InternalsSystem : EntitySystem return true; } + public bool AreInternalsWorking(EntityUid uid, InternalsComponent? component = null) + { + if (!Resolve(uid, ref component, false)) + return false; + + return AreInternalsWorking(component); + } + public bool AreInternalsWorking(InternalsComponent component) { return TryComp(component.BreathToolEntity, out BreathToolComponent? breathTool) && diff --git a/Content.Server/Cargo/Systems/CargoSystem.Orders.cs b/Content.Server/Cargo/Systems/CargoSystem.Orders.cs index d9327b5150..f659357ad3 100644 --- a/Content.Server/Cargo/Systems/CargoSystem.Orders.cs +++ b/Content.Server/Cargo/Systems/CargoSystem.Orders.cs @@ -8,7 +8,7 @@ using Content.Shared.Cargo.Events; using Content.Shared.Cargo.Prototypes; using Content.Shared.Database; using Robust.Shared.Map; -using Robust.Shared.Players; +using Robust.Shared.Player; using Robust.Shared.Prototypes; using Robust.Shared.Utility; diff --git a/Content.Server/CartridgeLoader/CartridgeLoaderSystem.cs b/Content.Server/CartridgeLoader/CartridgeLoaderSystem.cs index 9f7acce4fd..02b2eee771 100644 --- a/Content.Server/CartridgeLoader/CartridgeLoaderSystem.cs +++ b/Content.Server/CartridgeLoader/CartridgeLoaderSystem.cs @@ -6,9 +6,9 @@ using Content.Shared.CartridgeLoader; using Content.Shared.Interaction; using Robust.Server.Containers; using Robust.Server.GameObjects; -using Robust.Server.Player; using Robust.Shared.Containers; using Robust.Shared.Map; +using Robust.Shared.Player; namespace Content.Server.CartridgeLoader; @@ -98,7 +98,7 @@ public sealed class CartridgeLoaderSystem : SharedCartridgeLoaderSystem /// and use this method to update its state so the cartridge loaders state can be added to it. /// /// - public void UpdateUiState(EntityUid loaderUid, IPlayerSession? session, CartridgeLoaderComponent? loader) + public void UpdateUiState(EntityUid loaderUid, ICommonSession? session, CartridgeLoaderComponent? loader) { if (!Resolve(loaderUid, ref loader)) return; @@ -122,7 +122,7 @@ public sealed class CartridgeLoaderSystem : SharedCartridgeLoaderSystem /// This method is called "UpdateCartridgeUiState" but cartridges and a programs are the same. A cartridge is just a program as a visible item. /// /// - public void UpdateCartridgeUiState(EntityUid loaderUid, BoundUserInterfaceState state, IPlayerSession? session = default!, CartridgeLoaderComponent? loader = default!) + public void UpdateCartridgeUiState(EntityUid loaderUid, BoundUserInterfaceState state, ICommonSession? session = default!, CartridgeLoaderComponent? loader = default!) { if (!Resolve(loaderUid, ref loader)) return; diff --git a/Content.Server/Chat/Commands/AdminChatCommand.cs b/Content.Server/Chat/Commands/AdminChatCommand.cs index 8aa95ffee1..979051e9d3 100644 --- a/Content.Server/Chat/Commands/AdminChatCommand.cs +++ b/Content.Server/Chat/Commands/AdminChatCommand.cs @@ -1,7 +1,6 @@ using Content.Server.Administration; using Content.Server.Chat.Managers; using Content.Shared.Administration; -using Robust.Server.Player; using Robust.Shared.Console; namespace Content.Server.Chat.Commands @@ -15,7 +14,7 @@ namespace Content.Server.Chat.Commands public void Execute(IConsoleShell shell, string argStr, string[] args) { - var player = (IPlayerSession?) shell.Player; + var player = shell.Player; if (player == null) { diff --git a/Content.Server/Chat/Commands/LOOCCommand.cs b/Content.Server/Chat/Commands/LOOCCommand.cs index a897a0b2bf..9e16193fc3 100644 --- a/Content.Server/Chat/Commands/LOOCCommand.cs +++ b/Content.Server/Chat/Commands/LOOCCommand.cs @@ -1,6 +1,5 @@ using Content.Server.Chat.Systems; using Content.Shared.Administration; -using Robust.Server.Player; using Robust.Shared.Console; using Robust.Shared.Enums; @@ -15,7 +14,7 @@ namespace Content.Server.Chat.Commands public void Execute(IConsoleShell shell, string argStr, string[] args) { - if (shell.Player is not IPlayerSession player) + if (shell.Player is not { } player) { shell.WriteError("This command cannot be run from the server."); return; diff --git a/Content.Server/Chat/Commands/MeCommand.cs b/Content.Server/Chat/Commands/MeCommand.cs index 36f86cf4d6..e763d5656e 100644 --- a/Content.Server/Chat/Commands/MeCommand.cs +++ b/Content.Server/Chat/Commands/MeCommand.cs @@ -1,6 +1,5 @@ using Content.Server.Chat.Systems; using Content.Shared.Administration; -using Robust.Server.Player; using Robust.Shared.Console; using Robust.Shared.Enums; @@ -15,7 +14,7 @@ namespace Content.Server.Chat.Commands public void Execute(IConsoleShell shell, string argStr, string[] args) { - if (shell.Player is not IPlayerSession player) + if (shell.Player is not { } player) { shell.WriteError("This command cannot be run from the server."); return; diff --git a/Content.Server/Chat/Commands/OOCCommand.cs b/Content.Server/Chat/Commands/OOCCommand.cs index bef2024608..36f6303fbd 100644 --- a/Content.Server/Chat/Commands/OOCCommand.cs +++ b/Content.Server/Chat/Commands/OOCCommand.cs @@ -1,6 +1,5 @@ using Content.Server.Chat.Managers; using Content.Shared.Administration; -using Robust.Server.Player; using Robust.Shared.Console; namespace Content.Server.Chat.Commands @@ -14,7 +13,7 @@ namespace Content.Server.Chat.Commands public void Execute(IConsoleShell shell, string argStr, string[] args) { - if (shell.Player is not IPlayerSession player) + if (shell.Player is not { } player) { shell.WriteError("This command cannot be run from the server."); return; diff --git a/Content.Server/Chat/Commands/SayCommand.cs b/Content.Server/Chat/Commands/SayCommand.cs index 7c2125d8c1..273f908c9a 100644 --- a/Content.Server/Chat/Commands/SayCommand.cs +++ b/Content.Server/Chat/Commands/SayCommand.cs @@ -1,6 +1,5 @@ using Content.Server.Chat.Systems; using Content.Shared.Administration; -using Robust.Server.Player; using Robust.Shared.Console; using Robust.Shared.Enums; @@ -15,7 +14,7 @@ namespace Content.Server.Chat.Commands public void Execute(IConsoleShell shell, string argStr, string[] args) { - if (shell.Player is not IPlayerSession player) + if (shell.Player is not { } player) { shell.WriteError("This command cannot be run from the server."); return; diff --git a/Content.Server/Chat/Commands/SuicideCommand.cs b/Content.Server/Chat/Commands/SuicideCommand.cs index 389ff039bf..c967ba78d7 100644 --- a/Content.Server/Chat/Commands/SuicideCommand.cs +++ b/Content.Server/Chat/Commands/SuicideCommand.cs @@ -1,7 +1,6 @@ using Content.Server.GameTicking; using Content.Shared.Administration; using Content.Shared.Mind; -using Robust.Server.Player; using Robust.Shared.Console; using Robust.Shared.Enums; @@ -18,7 +17,7 @@ namespace Content.Server.Chat.Commands public void Execute(IConsoleShell shell, string argStr, string[] args) { - if (shell.Player is not IPlayerSession player) + if (shell.Player is not { } player) { shell.WriteLine(Loc.GetString("shell-cannot-run-command-from-server")); return; diff --git a/Content.Server/Chat/Commands/WhisperCommand.cs b/Content.Server/Chat/Commands/WhisperCommand.cs index 41eba8b384..c88e2519ee 100644 --- a/Content.Server/Chat/Commands/WhisperCommand.cs +++ b/Content.Server/Chat/Commands/WhisperCommand.cs @@ -1,6 +1,5 @@ using Content.Server.Chat.Systems; using Content.Shared.Administration; -using Robust.Server.Player; using Robust.Shared.Console; using Robust.Shared.Enums; @@ -15,7 +14,7 @@ namespace Content.Server.Chat.Commands public void Execute(IConsoleShell shell, string argStr, string[] args) { - if (shell.Player is not IPlayerSession player) + if (shell.Player is not { } player) { shell.WriteError("This command cannot be run from the server."); return; diff --git a/Content.Server/Chat/Managers/ChatManager.cs b/Content.Server/Chat/Managers/ChatManager.cs index ea7dcd5292..c9e66ff124 100644 --- a/Content.Server/Chat/Managers/ChatManager.cs +++ b/Content.Server/Chat/Managers/ChatManager.cs @@ -11,11 +11,9 @@ using Content.Shared.CCVar; using Content.Shared.Chat; using Content.Shared.Database; using Content.Shared.Mind; -using Robust.Server.Player; using Robust.Shared.Configuration; using Robust.Shared.Network; using Robust.Shared.Player; -using Robust.Shared.Players; using Robust.Shared.Replays; using Robust.Shared.Utility; @@ -53,8 +51,8 @@ namespace Content.Server.Chat.Managers private bool _oocEnabled = true; private bool _adminOocEnabled = true; - public Dictionary SenderKeys { get; } = new(); - public Dictionary> SenderEntities { get; } = new(); + public Dictionary SenderKeys { get; } = new(); + public Dictionary> SenderEntities { get; } = new(); public void Initialize() { @@ -82,7 +80,7 @@ namespace Content.Server.Chat.Managers DispatchServerAnnouncement(Loc.GetString(val ? "chat-manager-admin-ooc-chat-enabled-message" : "chat-manager-admin-ooc-chat-disabled-message")); } - public void DeleteMessagesBy(IPlayerSession player) + public void DeleteMessagesBy(ICommonSession player) { var key = SenderKeys.GetValueOrDefault(player); var entities = SenderEntities.GetValueOrDefault(player) ?? new HashSet(); @@ -168,7 +166,7 @@ namespace Content.Server.Chat.Managers /// The player sending the message. /// The message. /// The type of message. - public void TrySendOOCMessage(IPlayerSession player, string message, OOCChatType type) + public void TrySendOOCMessage(ICommonSession player, string message, OOCChatType type) { // Check if message exceeds the character limit if (message.Length > MaxMessageLength) @@ -192,7 +190,7 @@ namespace Content.Server.Chat.Managers #region Private API - private void SendOOC(IPlayerSession player, string message) + private void SendOOC(ICommonSession player, string message) { if (_adminManager.IsAdmin(player)) { @@ -236,7 +234,7 @@ namespace Content.Server.Chat.Managers _adminLogger.Add(LogType.Chat, LogImpact.Low, $"OOC from {player:Player}: {message}"); } - private void SendAdminChat(IPlayerSession player, string message) + private void SendAdminChat(ICommonSession player, string message) { if (!_adminManager.IsAdmin(player)) { @@ -336,7 +334,7 @@ namespace Content.Server.Chat.Managers } } - public bool MessageCharacterLimit(IPlayerSession? player, string message) + public bool MessageCharacterLimit(ICommonSession? player, string message) { var isOverLength = false; diff --git a/Content.Server/Chat/Managers/IChatManager.cs b/Content.Server/Chat/Managers/IChatManager.cs index 10103f011d..5317b3054e 100644 --- a/Content.Server/Chat/Managers/IChatManager.cs +++ b/Content.Server/Chat/Managers/IChatManager.cs @@ -1,8 +1,6 @@ using Content.Shared.Chat; -using Robust.Server.Player; using Robust.Shared.Network; using Robust.Shared.Player; -using Robust.Shared.Players; namespace Content.Server.Chat.Managers { @@ -12,12 +10,12 @@ namespace Content.Server.Chat.Managers /// Keys identifying messages sent by a specific player, used when sending /// /// - Dictionary SenderKeys { get; } + Dictionary SenderKeys { get; } /// /// Tracks which entities a player was attached to while sending messages. /// - Dictionary> SenderEntities { get; } + Dictionary> SenderEntities { get; } void Initialize(); @@ -30,7 +28,7 @@ namespace Content.Server.Chat.Managers void DispatchServerMessage(ICommonSession player, string message, bool suppressLog = false); - void TrySendOOCMessage(IPlayerSession player, string message, OOCChatType type); + void TrySendOOCMessage(ICommonSession player, string message, OOCChatType type); void SendHookOOC(string sender, string message); void SendAdminAnnouncement(string message); @@ -47,8 +45,8 @@ namespace Content.Server.Chat.Managers void ChatMessageToAll(ChatChannel channel, string message, string wrappedMessage, EntityUid source, bool hideChat, bool recordReplay, Color? colorOverride = null, string? audioPath = null, float audioVolume = 0, int? senderKey = null); - bool MessageCharacterLimit(IPlayerSession player, string message); + bool MessageCharacterLimit(ICommonSession player, string message); - void DeleteMessagesBy(IPlayerSession player); + void DeleteMessagesBy(ICommonSession player); } } diff --git a/Content.Server/Chat/Systems/ChatSystem.cs b/Content.Server/Chat/Systems/ChatSystem.cs index 1615de69e8..c4aafa10cc 100644 --- a/Content.Server/Chat/Systems/ChatSystem.cs +++ b/Content.Server/Chat/Systems/ChatSystem.cs @@ -7,7 +7,6 @@ using Content.Server.Administration.Logs; using Content.Server.Administration.Managers; using Content.Server.Chat.Managers; using Content.Server.GameTicking; -using Content.Server.Players; using Content.Server.Station.Components; using Content.Server.Station.Systems; using Content.Shared.ActionBlocker; @@ -19,6 +18,7 @@ using Content.Shared.Humanoid; using Content.Shared.IdentityManagement; using Content.Shared.Interaction; using Content.Shared.Mobs.Systems; +using Content.Shared.Players; using Content.Shared.Radio; using Robust.Server.GameObjects; using Robust.Server.Player; @@ -27,7 +27,6 @@ using Robust.Shared.Configuration; using Robust.Shared.Console; using Robust.Shared.Network; using Robust.Shared.Player; -using Robust.Shared.Players; using Robust.Shared.Prototypes; using Robust.Shared.Random; using Robust.Shared.Replays; @@ -149,7 +148,7 @@ public sealed partial class ChatSystem : SharedChatSystem InGameICChatType desiredType, bool hideChat, bool hideLog = false, IConsoleShell? shell = null, - IPlayerSession? player = null, string? nameOverride = null, + ICommonSession? player = null, string? nameOverride = null, bool checkRadioPrefix = true, bool ignoreActionBlocker = false) { @@ -174,7 +173,7 @@ public sealed partial class ChatSystem : SharedChatSystem ChatTransmitRange range, bool hideLog = false, IConsoleShell? shell = null, - IPlayerSession? player = null, + ICommonSession? player = null, string? nameOverride = null, bool checkRadioPrefix = true, bool ignoreActionBlocker = false @@ -255,7 +254,7 @@ public sealed partial class ChatSystem : SharedChatSystem InGameOOCChatType type, bool hideChat, IConsoleShell? shell = null, - IPlayerSession? player = null + ICommonSession? player = null ) { if (!CanSendInGame(message, shell, player)) @@ -557,7 +556,7 @@ public sealed partial class ChatSystem : SharedChatSystem } // ReSharper disable once InconsistentNaming - private void SendLOOC(EntityUid source, IPlayerSession player, string message, bool hideChat) + private void SendLOOC(EntityUid source, ICommonSession player, string message, bool hideChat) { var name = FormattedMessage.EscapeText(Identity.Name(source, EntityManager)); @@ -581,7 +580,7 @@ public sealed partial class ChatSystem : SharedChatSystem _adminLogger.Add(LogType.Chat, LogImpact.Low, $"LOOC from {player:Player}: {message}"); } - private void SendDeadChat(EntityUid source, IPlayerSession player, string message, bool hideChat) + private void SendDeadChat(EntityUid source, ICommonSession player, string message, bool hideChat) { var clients = GetDeadChatClients(); var playerName = Name(source); @@ -638,13 +637,13 @@ public sealed partial class ChatSystem : SharedChatSystem initialResult = MessageRangeCheckResult.Full; break; case ChatTransmitRange.GhostRangeLimit: - initialResult = (data.Observer && data.Range < 0 && !_adminManager.IsAdmin((IPlayerSession) session)) ? MessageRangeCheckResult.HideChat : MessageRangeCheckResult.Full; + initialResult = (data.Observer && data.Range < 0 && !_adminManager.IsAdmin(session)) ? MessageRangeCheckResult.HideChat : MessageRangeCheckResult.Full; break; case ChatTransmitRange.HideChat: initialResult = MessageRangeCheckResult.HideChat; break; case ChatTransmitRange.NoGhosts: - initialResult = (data.Observer && !_adminManager.IsAdmin((IPlayerSession) session)) ? MessageRangeCheckResult.Disallowed : MessageRangeCheckResult.Full; + initialResult = (data.Observer && !_adminManager.IsAdmin(session)) ? MessageRangeCheckResult.Disallowed : MessageRangeCheckResult.Full; break; } var insistHideChat = data.HideChatOverride ?? false; @@ -676,7 +675,7 @@ public sealed partial class ChatSystem : SharedChatSystem /// /// Returns true if the given player is 'allowed' to send the given message, false otherwise. /// - private bool CanSendInGame(string message, IConsoleShell? shell = null, IPlayerSession? player = null) + private bool CanSendInGame(string message, IConsoleShell? shell = null, ICommonSession? player = null) { // Non-players don't have to worry about these restrictions. if (player == null) diff --git a/Content.Server/Chemistry/Components/SmokeComponent.cs b/Content.Server/Chemistry/Components/SmokeComponent.cs deleted file mode 100644 index 133ad41f13..0000000000 --- a/Content.Server/Chemistry/Components/SmokeComponent.cs +++ /dev/null @@ -1,26 +0,0 @@ -using Content.Shared.Fluids.Components; -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom; - -namespace Content.Server.Chemistry.Components; - -/// -/// Stores solution on an anchored entity that has touch and ingestion reactions -/// to entities that collide with it. Similar to -/// -[RegisterComponent] -public sealed partial class SmokeComponent : Component -{ - public const string SolutionName = "solutionArea"; - - [DataField("nextReact", customTypeSerializer:typeof(TimeOffsetSerializer))] - public TimeSpan NextReact = TimeSpan.Zero; - - [DataField("spreadAmount")] - public int SpreadAmount = 0; - - /// - /// Have we reacted with our tile yet? - /// - [DataField("reactedTile")] - public bool ReactedTile = false; -} diff --git a/Content.Server/Chemistry/EntitySystems/ChemistryGuideDataSystem.cs b/Content.Server/Chemistry/EntitySystems/ChemistryGuideDataSystem.cs index 8cbdd82f07..7485c0e901 100644 --- a/Content.Server/Chemistry/EntitySystems/ChemistryGuideDataSystem.cs +++ b/Content.Server/Chemistry/EntitySystems/ChemistryGuideDataSystem.cs @@ -2,6 +2,7 @@ using Content.Shared.Chemistry.Reagent; using Robust.Server.Player; using Robust.Shared.Enums; +using Robust.Shared.Player; using Robust.Shared.Prototypes; namespace Content.Server.Chemistry.EntitySystems; diff --git a/Content.Server/Chemistry/ReactionEffects/AreaReactionEffect.cs b/Content.Server/Chemistry/ReactionEffects/AreaReactionEffect.cs index e6eaab8a59..291a654422 100644 --- a/Content.Server/Chemistry/ReactionEffects/AreaReactionEffect.cs +++ b/Content.Server/Chemistry/ReactionEffects/AreaReactionEffect.cs @@ -1,4 +1,3 @@ -using Content.Server.Chemistry.Components; using Content.Server.Fluids.EntitySystems; using Content.Shared.Audio; using Content.Shared.Chemistry.EntitySystems; @@ -10,7 +9,6 @@ using Content.Shared.Maps; using JetBrains.Annotations; using Robust.Shared.Audio; using Robust.Shared.Map; -using Robust.Shared.Player; using Robust.Shared.Prototypes; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; @@ -71,18 +69,10 @@ namespace Content.Server.Chemistry.ReactionEffects var coords = grid.MapToGrid(transform.MapPosition); var ent = args.EntityManager.SpawnEntity(_prototypeId, coords.SnapToGrid()); - if (!args.EntityManager.TryGetComponent(ent, out var smokeComponent)) - { - Logger.Error("Couldn't get AreaEffectComponent from " + _prototypeId); - args.EntityManager.QueueDeleteEntity(ent); - return; - } - var smoke = args.EntityManager.System(); - smokeComponent.SpreadAmount = spreadAmount; - smoke.Start(ent, smokeComponent, splitSolution, _duration); + smoke.StartSmoke(ent, splitSolution, _duration, spreadAmount); - SoundSystem.Play(_sound.GetSound(), Filter.Pvs(args.SolutionEntity), args.SolutionEntity, AudioHelpers.WithVariation(0.125f)); + args.EntityManager.System().PlayPvs(_sound, args.SolutionEntity, AudioHelpers.WithVariation(0.125f)); } } } diff --git a/Content.Server/Chunking/ChunkingSystem.cs b/Content.Server/Chunking/ChunkingSystem.cs index 4ef44d1678..6f44c43be8 100644 --- a/Content.Server/Chunking/ChunkingSystem.cs +++ b/Content.Server/Chunking/ChunkingSystem.cs @@ -1,12 +1,12 @@ using System.Linq; using Content.Shared.Decals; using Microsoft.Extensions.ObjectPool; -using Robust.Server.Player; using Robust.Shared; using Robust.Shared.Configuration; using Robust.Shared.Enums; using Robust.Shared.Map; using Robust.Shared.Map.Components; +using Robust.Shared.Player; using Robust.Shared.Utility; namespace Content.Shared.Chunking; @@ -41,7 +41,7 @@ public sealed class ChunkingSystem : EntitySystem private void OnPvsRangeChanged(float value) => _baseViewBounds = Box2.UnitCentered.Scale(value); public Dictionary> GetChunksForSession( - IPlayerSession session, + ICommonSession session, int chunkSize, ObjectPool> indexPool, ObjectPool>> viewerPool, @@ -52,7 +52,7 @@ public sealed class ChunkingSystem : EntitySystem return chunks; } - private HashSet GetSessionViewers(IPlayerSession session) + private HashSet GetSessionViewers(ICommonSession session) { var viewers = new HashSet(); if (session.Status != SessionStatus.InGame || session.AttachedEntity is null) diff --git a/Content.Server/Commands/CommandUtils.cs b/Content.Server/Commands/CommandUtils.cs index 11adaec9a2..172f3324e3 100644 --- a/Content.Server/Commands/CommandUtils.cs +++ b/Content.Server/Commands/CommandUtils.cs @@ -3,6 +3,7 @@ using System.Globalization; using Robust.Server.Player; using Robust.Shared.Console; using Robust.Shared.Network; +using Robust.Shared.Player; namespace Content.Server.Commands { @@ -16,7 +17,7 @@ namespace Content.Server.Commands /// sending a failure to the performer if unable to. /// public static bool TryGetSessionByUsernameOrId(IConsoleShell shell, - string usernameOrId, IPlayerSession performer, [NotNullWhen(true)] out IPlayerSession? session) + string usernameOrId, ICommonSession performer, [NotNullWhen(true)] out ICommonSession? session) { var plyMgr = IoCManager.Resolve(); if (plyMgr.TryGetSessionByUsername(usernameOrId, out session)) return true; @@ -36,7 +37,7 @@ namespace Content.Server.Commands /// sending a failure to the performer if unable to. /// public static bool TryGetAttachedEntityByUsernameOrId(IConsoleShell shell, - string usernameOrId, IPlayerSession performer, out EntityUid attachedEntity) + string usernameOrId, ICommonSession performer, out EntityUid attachedEntity) { attachedEntity = default; if (!TryGetSessionByUsernameOrId(shell, usernameOrId, performer, out var session)) return false; @@ -67,7 +68,7 @@ namespace Content.Server.Commands transform.LocalPosition.Y.ToString(CultureInfo.InvariantCulture)); ruleString = ruleString.Replace("$NAME", entMan.GetComponent(ent).EntityName); - if (shell.Player is IPlayerSession player) + if (shell.Player is { } player) { if (player.AttachedEntity is {Valid: true} p) { diff --git a/Content.Server/Construction/Commands/FixRotationsCommand.cs b/Content.Server/Construction/Commands/FixRotationsCommand.cs index d23fa0a31b..bdbfaf170d 100644 --- a/Content.Server/Construction/Commands/FixRotationsCommand.cs +++ b/Content.Server/Construction/Commands/FixRotationsCommand.cs @@ -3,7 +3,6 @@ using Content.Server.Power.Components; using Content.Shared.Administration; using Content.Shared.Construction; using Content.Shared.Tag; -using Robust.Server.Player; using Robust.Shared.Console; using Robust.Shared.Map.Components; @@ -21,7 +20,7 @@ namespace Content.Server.Construction.Commands public void Execute(IConsoleShell shell, string argsOther, string[] args) { - var player = shell.Player as IPlayerSession; + var player = shell.Player; EntityUid? gridId; var xformQuery = _entManager.GetEntityQuery(); diff --git a/Content.Server/Construction/Commands/TileReplaceCommand.cs b/Content.Server/Construction/Commands/TileReplaceCommand.cs index ed1fba2424..f63fd4c13e 100644 --- a/Content.Server/Construction/Commands/TileReplaceCommand.cs +++ b/Content.Server/Construction/Commands/TileReplaceCommand.cs @@ -1,6 +1,5 @@ using Content.Server.Administration; using Content.Shared.Administration; -using Robust.Server.Player; using Robust.Shared.Console; using Robust.Shared.Map; using Robust.Shared.Map.Components; @@ -20,7 +19,7 @@ sealed class TileReplaceCommand : IConsoleCommand public void Execute(IConsoleShell shell, string argStr, string[] args) { - var player = shell.Player as IPlayerSession; + var player = shell.Player; EntityUid? gridId; string tileIdA; string tileIdB; diff --git a/Content.Server/Construction/Commands/TileWallsCommand.cs b/Content.Server/Construction/Commands/TileWallsCommand.cs index 55389e41cc..731d4da7f8 100644 --- a/Content.Server/Construction/Commands/TileWallsCommand.cs +++ b/Content.Server/Construction/Commands/TileWallsCommand.cs @@ -2,10 +2,9 @@ using Content.Server.Administration; using Content.Shared.Administration; using Content.Shared.Maps; using Content.Shared.Tag; -using Robust.Server.GameObjects; -using Robust.Server.Player; using Robust.Shared.Console; using Robust.Shared.Map; +using Robust.Server.GameObjects; using Robust.Shared.Map.Components; namespace Content.Server.Construction.Commands @@ -29,7 +28,7 @@ namespace Content.Server.Construction.Commands public void Execute(IConsoleShell shell, string argStr, string[] args) { - var player = shell.Player as IPlayerSession; + var player = shell.Player; EntityUid? gridId; switch (args.Length) diff --git a/Content.Server/Construction/ConstructionSystem.Initial.cs b/Content.Server/Construction/ConstructionSystem.Initial.cs index e74edb5da2..21978f2d0c 100644 --- a/Content.Server/Construction/ConstructionSystem.Initial.cs +++ b/Content.Server/Construction/ConstructionSystem.Initial.cs @@ -16,7 +16,7 @@ using Content.Shared.Interaction; using Content.Shared.Inventory; using Content.Shared.Storage; using Robust.Shared.Containers; -using Robust.Shared.Players; +using Robust.Shared.Player; using Robust.Shared.Timing; namespace Content.Server.Construction diff --git a/Content.Server/Construction/ConstructionSystem.cs b/Content.Server/Construction/ConstructionSystem.cs index 76d37432cb..6e40b7b856 100644 --- a/Content.Server/Construction/ConstructionSystem.cs +++ b/Content.Server/Construction/ConstructionSystem.cs @@ -7,6 +7,7 @@ using JetBrains.Annotations; using Robust.Server.Containers; using Robust.Shared.Prototypes; using Robust.Shared.Random; +using SharedToolSystem = Content.Shared.Tools.Systems.SharedToolSystem; namespace Content.Server.Construction { diff --git a/Content.Server/Construction/RefiningSystem.cs b/Content.Server/Construction/RefiningSystem.cs index 40f69c51f8..b9d80c7170 100644 --- a/Content.Server/Construction/RefiningSystem.cs +++ b/Content.Server/Construction/RefiningSystem.cs @@ -6,6 +6,7 @@ using Content.Shared.Interaction; using Content.Shared.Stacks; using Content.Shared.Tools; using Robust.Shared.Serialization; +using SharedToolSystem = Content.Shared.Tools.Systems.SharedToolSystem; namespace Content.Server.Construction { diff --git a/Content.Server/Corvax/Objectives/Components/HijackShuttleConditionComponent.cs b/Content.Server/Corvax/Objectives/Components/HijackShuttleConditionComponent.cs deleted file mode 100644 index 31c7ce8444..0000000000 --- a/Content.Server/Corvax/Objectives/Components/HijackShuttleConditionComponent.cs +++ /dev/null @@ -1,8 +0,0 @@ -using Content.Server.Corvax.Objectives.Systems; - -namespace Content.Server.Corvax.Objectives.Components; - -[RegisterComponent, Access(typeof(HijackShuttleConditionSystem))] -public sealed partial class HijackShuttleConditionComponent : Component -{ -} diff --git a/Content.Server/CrewManifest/CrewManifestSystem.cs b/Content.Server/CrewManifest/CrewManifestSystem.cs index aed0575324..4c4f17f61d 100644 --- a/Content.Server/CrewManifest/CrewManifestSystem.cs +++ b/Content.Server/CrewManifest/CrewManifestSystem.cs @@ -10,10 +10,9 @@ using Content.Shared.CCVar; using Content.Shared.CrewManifest; using Content.Shared.GameTicking; using Content.Shared.StationRecords; -using Robust.Server.Player; using Robust.Shared.Configuration; using Robust.Shared.Console; -using Robust.Shared.Players; +using Robust.Shared.Player; namespace Content.Server.CrewManifest; @@ -60,7 +59,7 @@ public sealed class CrewManifestSystem : EntitySystem private void OnRequestCrewManifest(RequestCrewManifestMessage message, EntitySessionEventArgs args) { - if (args.SenderSession is not IPlayerSession sessionCast + if (args.SenderSession is not { } sessionCast || !_configManager.GetCVar(CCVars.CrewManifestWithoutEntity)) { return; @@ -93,12 +92,12 @@ public sealed class CrewManifestSystem : EntitySystem private void OnBoundUiClose(EntityUid uid, CrewManifestViewerComponent component, BoundUIClosedEvent ev) { var owningStation = _stationSystem.GetOwningStation(uid); - if (owningStation == null || ev.Session is not IPlayerSession sessionCast) + if (owningStation == null || ev.Session is not { } session) { return; } - CloseEui(owningStation.Value, sessionCast, uid); + CloseEui(owningStation.Value, session, uid); } /// @@ -126,7 +125,7 @@ public sealed class CrewManifestSystem : EntitySystem private void OpenEuiFromBui(EntityUid uid, CrewManifestViewerComponent component, CrewManifestOpenUiMessage msg) { var owningStation = _stationSystem.GetOwningStation(uid); - if (owningStation == null || msg.Session is not IPlayerSession sessionCast) + if (owningStation == null || msg.Session is not { } session) { return; } @@ -136,7 +135,7 @@ public sealed class CrewManifestSystem : EntitySystem return; } - OpenEui(owningStation.Value, sessionCast, uid); + OpenEui(owningStation.Value, session, uid); } /// @@ -145,7 +144,7 @@ public sealed class CrewManifestSystem : EntitySystem /// Station that we're displaying the crew manifest for. /// The player's session. /// If this EUI should be 'owned' by an entity. - public void OpenEui(EntityUid station, IPlayerSession session, EntityUid? owner = null) + public void OpenEui(EntityUid station, ICommonSession session, EntityUid? owner = null) { if (!HasComp(station)) { @@ -252,7 +251,7 @@ public sealed class CrewManifestCommand : IConsoleCommand return; } - if (shell.Player == null || shell.Player is not IPlayerSession session) + if (shell.Player == null || shell.Player is not { } session) { shell.WriteLine("You must run this from a client."); return; diff --git a/Content.Server/Damage/Commands/GodModeCommand.cs b/Content.Server/Damage/Commands/GodModeCommand.cs index 92a0e53f0f..866737f17a 100644 --- a/Content.Server/Damage/Commands/GodModeCommand.cs +++ b/Content.Server/Damage/Commands/GodModeCommand.cs @@ -1,8 +1,6 @@ using Content.Server.Administration; -using Content.Server.Damage.Systems; using Content.Shared.Administration; using Content.Shared.Damage.Systems; -using Robust.Server.Player; using Robust.Shared.Console; namespace Content.Server.Damage.Commands @@ -18,7 +16,7 @@ namespace Content.Server.Damage.Commands public void Execute(IConsoleShell shell, string argStr, string[] args) { - var player = shell.Player as IPlayerSession; + var player = shell.Player; EntityUid entity; switch (args.Length) diff --git a/Content.Server/Damage/ForceSay/DamageForceSaySystem.cs b/Content.Server/Damage/ForceSay/DamageForceSaySystem.cs index 3d3346403a..457fab4bb2 100644 --- a/Content.Server/Damage/ForceSay/DamageForceSaySystem.cs +++ b/Content.Server/Damage/ForceSay/DamageForceSaySystem.cs @@ -6,7 +6,6 @@ using Content.Shared.Mobs.Systems; using Content.Shared.Stunnable; using Robust.Server.GameObjects; using Robust.Server.Player; -using Robust.Shared.Players; using Robust.Shared.Prototypes; using Robust.Shared.Random; using Robust.Shared.Timing; diff --git a/Content.Server/Database/ServerDbBase.cs b/Content.Server/Database/ServerDbBase.cs index 116bb4ccf9..2c3373ea23 100644 --- a/Content.Server/Database/ServerDbBase.cs +++ b/Content.Server/Database/ServerDbBase.cs @@ -685,6 +685,7 @@ namespace Content.Server.Database var round = new Round { + StartDate = DateTime.UtcNow, Players = players, ServerId = server.Id }; diff --git a/Content.Server/Database/UserDbDataManager.cs b/Content.Server/Database/UserDbDataManager.cs index f2c506240b..f8b1611fd5 100644 --- a/Content.Server/Database/UserDbDataManager.cs +++ b/Content.Server/Database/UserDbDataManager.cs @@ -2,8 +2,8 @@ using System.Threading.Tasks; using Content.Server.Players.PlayTimeTracking; using Content.Server.Preferences.Managers; -using Robust.Server.Player; using Robust.Shared.Network; +using Robust.Shared.Player; using Robust.Shared.Utility; namespace Content.Server.Database; @@ -25,7 +25,7 @@ public sealed class UserDbDataManager // TODO: Ideally connected/disconnected would be subscribed to IPlayerManager directly, // but this runs into ordering issues with game ticker. - public void ClientConnected(IPlayerSession session) + public void ClientConnected(ICommonSession session) { DebugTools.Assert(!_users.ContainsKey(session.UserId), "We should not have any cached data on client connect."); @@ -36,7 +36,7 @@ public sealed class UserDbDataManager _users.Add(session.UserId, data); } - public void ClientDisconnected(IPlayerSession session) + public void ClientDisconnected(ICommonSession session) { _users.Remove(session.UserId, out var data); if (data == null) @@ -49,24 +49,24 @@ public sealed class UserDbDataManager _playTimeTracking.ClientDisconnected(session); } - private async Task Load(IPlayerSession session, CancellationToken cancel) + private async Task Load(ICommonSession session, CancellationToken cancel) { await Task.WhenAll( _prefs.LoadData(session, cancel), _playTimeTracking.LoadData(session, cancel)); } - public Task WaitLoadComplete(IPlayerSession session) + public Task WaitLoadComplete(ICommonSession session) { return _users[session.UserId].Task; } - public bool IsLoadComplete(IPlayerSession session) + public bool IsLoadComplete(ICommonSession session) { return GetLoadTask(session).IsCompleted; } - public Task GetLoadTask(IPlayerSession session) + public Task GetLoadTask(ICommonSession session) { return _users[session.UserId].Task; } diff --git a/Content.Server/Decals/DecalSystem.cs b/Content.Server/Decals/DecalSystem.cs index d5a5bf9aff..ce2e0711e7 100644 --- a/Content.Server/Decals/DecalSystem.cs +++ b/Content.Server/Decals/DecalSystem.cs @@ -16,6 +16,7 @@ using Robust.Shared.Configuration; using Robust.Shared.Enums; using Robust.Shared.Map; using Robust.Shared.Map.Components; +using Robust.Shared.Player; using Robust.Shared.Threading; using Robust.Shared.Timing; using Robust.Shared.Utility; @@ -36,7 +37,7 @@ namespace Content.Server.Decals [Dependency] private readonly MapSystem _mapSystem = default!; private readonly Dictionary> _dirtyChunks = new(); - private readonly Dictionary>> _previousSentChunks = new(); + private readonly Dictionary>> _previousSentChunks = new(); private static readonly Vector2 _boundsMinExpansion = new(0.01f, 0.01f); private static readonly Vector2 _boundsMaxExpansion = new(1.01f, 1.01f); @@ -197,7 +198,7 @@ namespace Content.Server.Decals private void OnDecalPlacementRequest(RequestDecalPlacementEvent ev, EntitySessionEventArgs eventArgs) { - if (eventArgs.SenderSession is not IPlayerSession session) + if (eventArgs.SenderSession is not { } session) return; // bad @@ -226,7 +227,7 @@ namespace Content.Server.Decals private void OnDecalRemovalRequest(RequestDecalRemovalEvent ev, EntitySessionEventArgs eventArgs) { - if (eventArgs.SenderSession is not IPlayerSession session) + if (eventArgs.SenderSession is not { } session) return; // bad @@ -305,10 +306,10 @@ namespace Content.Server.Decals return true; } - public bool RemoveDecal(EntityUid gridId, uint decalId, DecalGridComponent? component = null) + public override bool RemoveDecal(EntityUid gridId, uint decalId, DecalGridComponent? component = null) => RemoveDecalInternal(gridId, decalId, out _, component); - public HashSet<(uint Index, Decal Decal)> GetDecalsInRange(EntityUid gridId, Vector2 position, float distance = 0.75f, Func? validDelegate = null) + public override HashSet<(uint Index, Decal Decal)> GetDecalsInRange(EntityUid gridId, Vector2 position, float distance = 0.75f, Func? validDelegate = null) { var decalIds = new HashSet<(uint, Decal)>(); var chunkCollection = ChunkCollection(gridId); @@ -427,7 +428,7 @@ namespace Content.Server.Decals if (PvsEnabled) { - var players = _playerManager.ServerSessions.Where(x => x.Status == SessionStatus.InGame).ToArray(); + var players = _playerManager.Sessions.Where(x => x.Status == SessionStatus.InGame).ToArray(); var opts = new ParallelOptions { MaxDegreeOfParallelism = _parMan.ParallelProcessCount }; Parallel.ForEach(players, opts, UpdatePlayer); } @@ -435,7 +436,7 @@ namespace Content.Server.Decals _dirtyChunks.Clear(); } - public void UpdatePlayer(IPlayerSession player) + public void UpdatePlayer(ICommonSession player) { var chunksInRange = _chunking.GetChunksForSession(player, ChunkSize, _chunkIndexPool, _chunkViewerPool); var staleChunks = _chunkViewerPool.Get(); @@ -530,7 +531,7 @@ namespace Content.Server.Decals } private void SendChunkUpdates( - IPlayerSession session, + ICommonSession session, Dictionary> updatedChunks, Dictionary> staleChunks) { diff --git a/Content.Server/DeviceLinking/Systems/LogicGateSystem.cs b/Content.Server/DeviceLinking/Systems/LogicGateSystem.cs index 360f86eebe..5641b0b4ae 100644 --- a/Content.Server/DeviceLinking/Systems/LogicGateSystem.cs +++ b/Content.Server/DeviceLinking/Systems/LogicGateSystem.cs @@ -5,6 +5,7 @@ using Content.Shared.Examine; using Content.Shared.Interaction; using Content.Shared.Tools; using Content.Shared.Popups; +using SharedToolSystem = Content.Shared.Tools.Systems.SharedToolSystem; using SignalReceivedEvent = Content.Server.DeviceLinking.Events.SignalReceivedEvent; namespace Content.Server.DeviceLinking.Systems; diff --git a/Content.Server/Disposal/TubeConnectionsCommand.cs b/Content.Server/Disposal/TubeConnectionsCommand.cs index 7895dcbca6..55e6465937 100644 --- a/Content.Server/Disposal/TubeConnectionsCommand.cs +++ b/Content.Server/Disposal/TubeConnectionsCommand.cs @@ -2,7 +2,6 @@ using Content.Server.Administration; using Content.Server.Disposal.Tube; using Content.Server.Disposal.Tube.Components; using Content.Shared.Administration; -using Robust.Server.Player; using Robust.Shared.Console; namespace Content.Server.Disposal @@ -18,7 +17,7 @@ namespace Content.Server.Disposal public void Execute(IConsoleShell shell, string argStr, string[] args) { - var player = shell.Player as IPlayerSession; + var player = shell.Player; if (player?.AttachedEntity == null) { shell.WriteLine(Loc.GetString("shell-only-players-can-run-this-command")); diff --git a/Content.Server/Doors/Systems/AirlockSystem.cs b/Content.Server/Doors/Systems/AirlockSystem.cs index 1321b60978..6274f953fd 100644 --- a/Content.Server/Doors/Systems/AirlockSystem.cs +++ b/Content.Server/Doors/Systems/AirlockSystem.cs @@ -179,11 +179,16 @@ public sealed class AirlockSystem : SharedAirlockSystem private void OnBeforePry(EntityUid uid, AirlockComponent component, ref BeforePryEvent args) { - if (this.IsPowered(uid, EntityManager) && !args.PryPowered) - { - Popup.PopupEntity(Loc.GetString("airlock-component-cannot-pry-is-powered-message"), uid, args.User); - args.Cancelled = true; - } + if (args.Cancelled) + return; + + if (!this.IsPowered(uid, EntityManager) || args.PryPowered) + return; + + args.Message = "airlock-component-cannot-pry-is-powered-message"; + + args.Cancelled = true; + } public bool CanChangeState(EntityUid uid, AirlockComponent component) diff --git a/Content.Server/EUI/BaseEui.cs b/Content.Server/EUI/BaseEui.cs index 4a41ad40a5..70cbfc3775 100644 --- a/Content.Server/EUI/BaseEui.cs +++ b/Content.Server/EUI/BaseEui.cs @@ -1,6 +1,6 @@ using Content.Shared.Eui; using Robust.Shared.Network; -using Robust.Shared.Players; +using Robust.Shared.Player; namespace Content.Server.EUI { diff --git a/Content.Server/EUI/EuiManager.cs b/Content.Server/EUI/EuiManager.cs index 4d99719525..fe8e486b68 100644 --- a/Content.Server/EUI/EuiManager.cs +++ b/Content.Server/EUI/EuiManager.cs @@ -2,7 +2,7 @@ using Robust.Server.Player; using Robust.Shared.Enums; using Robust.Shared.Network; -using Robust.Shared.Players; +using Robust.Shared.Player; using Robust.Shared.Utility; namespace Content.Server.EUI diff --git a/Content.Server/Electrocution/ElectrocutionSystem.cs b/Content.Server/Electrocution/ElectrocutionSystem.cs index 6c96266740..8ddc8540c0 100644 --- a/Content.Server/Electrocution/ElectrocutionSystem.cs +++ b/Content.Server/Electrocution/ElectrocutionSystem.cs @@ -192,18 +192,13 @@ public sealed class ElectrocutionSystem : SharedElectrocutionSystem private void OnLightAttacked(EntityUid uid, PoweredLightComponent component, AttackedEvent args) { + if (!component.CurrentLit || args.Used != args.User) + return; if (!_meleeWeapon.GetDamage(args.Used, args.User).Any()) return; - if (args.Used != args.User) - return; - - if (component.CurrentLit == false) - return; - DoCommonElectrocution(args.User, uid, component.UnarmedHitShock, component.UnarmedHitStun, false, 1); - } private void OnElectrifiedInteractUsing(EntityUid uid, ElectrifiedComponent electrified, InteractUsingEvent args) @@ -498,7 +493,7 @@ public sealed class ElectrocutionSystem : SharedElectrocutionSystem private void PlayElectrocutionSound(EntityUid targetUid, EntityUid sourceUid, ElectrifiedComponent? electrified = null) { - if (!Resolve(sourceUid, ref electrified) || !electrified.PlaySoundOnShock) + if (!Resolve(sourceUid, ref electrified, false) || !electrified.PlaySoundOnShock) { return; } diff --git a/Content.Server/EntityList/SpawnEntityListCommand.cs b/Content.Server/EntityList/SpawnEntityListCommand.cs index 0891bbd12a..027d25dc2c 100644 --- a/Content.Server/EntityList/SpawnEntityListCommand.cs +++ b/Content.Server/EntityList/SpawnEntityListCommand.cs @@ -1,7 +1,6 @@ using Content.Server.Administration; using Content.Shared.Administration; using Content.Shared.EntityList; -using Robust.Server.Player; using Robust.Shared.Console; using Robust.Shared.Prototypes; @@ -22,7 +21,7 @@ namespace Content.Server.EntityList return; } - if (shell.Player is not IPlayerSession player) + if (shell.Player is not { } player) { shell.WriteError("You must be a player to run this command."); return; diff --git a/Content.Server/Examine/ExamineSystem.cs b/Content.Server/Examine/ExamineSystem.cs index 98aa806885..3447810896 100644 --- a/Content.Server/Examine/ExamineSystem.cs +++ b/Content.Server/Examine/ExamineSystem.cs @@ -4,7 +4,6 @@ using Content.Shared.Examine; using Content.Shared.Verbs; using JetBrains.Annotations; using Robust.Server.GameObjects; -using Robust.Server.Player; using Robust.Shared.Utility; namespace Content.Server.Examine @@ -46,7 +45,7 @@ namespace Content.Server.Examine private void ExamineInfoRequest(ExamineSystemMessages.RequestExamineInfoMessage request, EntitySessionEventArgs eventArgs) { - var player = (IPlayerSession) eventArgs.SenderSession; + var player = eventArgs.SenderSession; var session = eventArgs.SenderSession; var channel = player.ConnectedClient; var entity = GetEntity(request.NetEntity); diff --git a/Content.Server/Fluids/EntitySystems/PuddleDebugDebugOverlaySystem.cs b/Content.Server/Fluids/EntitySystems/PuddleDebugDebugOverlaySystem.cs index 59f0a13695..c17eea684d 100644 --- a/Content.Server/Fluids/EntitySystems/PuddleDebugDebugOverlaySystem.cs +++ b/Content.Server/Fluids/EntitySystems/PuddleDebugDebugOverlaySystem.cs @@ -1,9 +1,9 @@ using System.Numerics; using Content.Shared.Fluids; using Content.Shared.Fluids.Components; -using Robust.Server.Player; using Robust.Shared.Map; using Robust.Shared.Map.Components; +using Robust.Shared.Player; using Robust.Shared.Timing; namespace Content.Server.Fluids.EntitySystems; @@ -14,10 +14,10 @@ public sealed class PuddleDebugDebugOverlaySystem : SharedPuddleDebugOverlaySyst [Dependency] private readonly IMapManager _mapManager = default!; [Dependency] private readonly PuddleSystem _puddle = default!; - private readonly HashSet _playerObservers = new(); + private readonly HashSet _playerObservers = new(); private List> _grids = new(); - public bool ToggleObserver(IPlayerSession observer) + public bool ToggleObserver(ICommonSession observer) { NextTick ??= _timing.CurTime + Cooldown; @@ -31,7 +31,7 @@ public sealed class PuddleDebugDebugOverlaySystem : SharedPuddleDebugOverlaySyst return true; } - private void RemoveObserver(IPlayerSession observer) + private void RemoveObserver(ICommonSession observer) { if (!_playerObservers.Remove(observer)) { diff --git a/Content.Server/Fluids/EntitySystems/SmokeSystem.cs b/Content.Server/Fluids/EntitySystems/SmokeSystem.cs index f7732fec62..5459dacf0b 100644 --- a/Content.Server/Fluids/EntitySystems/SmokeSystem.cs +++ b/Content.Server/Fluids/EntitySystems/SmokeSystem.cs @@ -1,14 +1,23 @@ using System.Linq; -using Content.Server.Chemistry.Components; +using Content.Server.Administration.Logs; +using Content.Server.Body.Components; +using Content.Server.Body.Systems; using Content.Server.Chemistry.ReactionEffects; using Content.Server.Spreader; +using Content.Shared.Chemistry; using Content.Shared.Chemistry.Components; using Content.Shared.Chemistry.EntitySystems; using Content.Shared.Chemistry.Reaction; +using Content.Shared.Chemistry.Reagent; +using Content.Shared.Database; using Content.Shared.FixedPoint; using Content.Shared.Smoking; using Robust.Server.GameObjects; using Robust.Shared.Map; +using Robust.Shared.Physics; +using Robust.Shared.Physics.Components; +using Robust.Shared.Physics.Events; +using Robust.Shared.Physics.Systems; using Robust.Shared.Prototypes; using Robust.Shared.Random; using Robust.Shared.Timing; @@ -22,70 +31,140 @@ namespace Content.Server.Fluids.EntitySystems; public sealed class SmokeSystem : EntitySystem { // If I could do it all again this could probably use a lot more of puddles. + [Dependency] private readonly IAdminLogManager _logger = default!; [Dependency] private readonly IGameTiming _timing = default!; [Dependency] private readonly IMapManager _mapManager = default!; [Dependency] private readonly IPrototypeManager _prototype = default!; - [Dependency] private readonly AppearanceSystem _appearance = default!; - [Dependency] private readonly EntityLookupSystem _lookup = default!; - [Dependency] private readonly SolutionContainerSystem _solutionSystem = default!; [Dependency] private readonly IRobustRandom _random = default!; + [Dependency] private readonly AppearanceSystem _appearance = default!; + [Dependency] private readonly BloodstreamSystem _blood = default!; + [Dependency] private readonly InternalsSystem _internals = default!; + [Dependency] private readonly ReactiveSystem _reactive = default!; + [Dependency] private readonly SharedBroadphaseSystem _broadphase = default!; + [Dependency] private readonly SharedPhysicsSystem _physics = default!; + [Dependency] private readonly SolutionContainerSystem _solutionSystem = default!; + [Dependency] private readonly TransformSystem _transform = default!; + + private EntityQuery _smokeQuery; + private EntityQuery _smokeAffectedQuery; /// public override void Initialize() { base.Initialize(); - SubscribeLocalEvent(OnSmokeUnpaused); + + _smokeQuery = GetEntityQuery(); + _smokeAffectedQuery = GetEntityQuery(); + + SubscribeLocalEvent(OnStartCollide); + SubscribeLocalEvent(OnEndCollide); SubscribeLocalEvent(OnReactionAttempt); SubscribeLocalEvent(OnSmokeSpread); + SubscribeLocalEvent(OnAffectedUnpaused); + } + + /// + public override void Update(float frameTime) + { + base.Update(frameTime); + + var query = EntityQueryEnumerator(); + var curTime = _timing.CurTime; + while (query.MoveNext(out var uid, out var smoke)) + { + if (curTime < smoke.NextSecond) + continue; + + smoke.NextSecond += TimeSpan.FromSeconds(1); + SmokeReact(uid, smoke.SmokeEntity); + } + } + + private void OnStartCollide(EntityUid uid, SmokeComponent component, ref StartCollideEvent args) + { + if (_smokeAffectedQuery.HasComponent(args.OtherEntity)) + return; + + var smokeAffected = AddComp(args.OtherEntity); + smokeAffected.SmokeEntity = uid; + smokeAffected.NextSecond = _timing.CurTime + TimeSpan.FromSeconds(1); + } + + private void OnEndCollide(EntityUid uid, SmokeComponent component, ref EndCollideEvent args) + { + // if we are already in smoke, make sure the thing we are exiting is the current smoke we are in. + if (_smokeAffectedQuery.TryGetComponent(args.OtherEntity, out var smokeAffectedComponent)) + { + if (smokeAffectedComponent.SmokeEntity != uid) + return; + } + + var exists = Exists(uid); + + if (!TryComp(args.OtherEntity, out var body)) + return; + + foreach (var ent in _physics.GetContactingEntities(args.OtherEntity, body)) + { + if (exists && ent == uid) + continue; + + if (!_smokeQuery.HasComponent(ent)) + continue; + + smokeAffectedComponent ??= EnsureComp(args.OtherEntity); + smokeAffectedComponent.SmokeEntity = ent; + return; // exit the function so we don't remove the component. + } + + if (smokeAffectedComponent != null) + RemComp(args.OtherEntity, smokeAffectedComponent); + } + + private void OnAffectedUnpaused(EntityUid uid, SmokeAffectedComponent component, ref EntityUnpausedEvent args) + { + component.NextSecond += args.PausedTime; } private void OnSmokeSpread(EntityUid uid, SmokeComponent component, ref SpreadNeighborsEvent args) { - if (component.SpreadAmount == 0 - || !_solutionSystem.TryGetSolution(uid, SmokeComponent.SolutionName, out var solution)) + if (component.SpreadAmount == 0 || !_solutionSystem.TryGetSolution(uid, SmokeComponent.SolutionName, out var solution)) { RemCompDeferred(uid); return; } - var prototype = MetaData(uid).EntityPrototype; - - if (prototype == null) + if (Prototype(uid) is not { } prototype) { RemCompDeferred(uid); return; } + if (!args.NeighborFreeTiles.Any()) + return; + TryComp(uid, out var timer); - _appearance.TryGetData(uid, SmokeVisuals.Color, out var color); // wtf is the logic behind any of this. - var smokePerSpread = 1 + component.SpreadAmount / Math.Max(1, args.NeighborFreeTiles.Count); + var smokePerSpread = component.SpreadAmount / Math.Max(1, args.NeighborFreeTiles.Count); foreach (var neighbor in args.NeighborFreeTiles) { var coords = neighbor.Grid.GridTileToLocal(neighbor.Tile); var ent = Spawn(prototype.ID, coords); - var neighborSmoke = EnsureComp(ent); - neighborSmoke.SpreadAmount = Math.Max(0, smokePerSpread - 2); // why - 2? who the fuck knows. - component.SpreadAmount--; - args.Updates--; + var spreadAmount = Math.Max(0, smokePerSpread); + component.SpreadAmount -= args.NeighborFreeTiles.Count(); - // Listen this is the old behaviour iunno - Start(ent, neighborSmoke, solution.Clone(), timer?.Lifetime ?? 10f); - - if (color != null) - _appearance.SetData(ent, SmokeVisuals.Color, color); + StartSmoke(ent, solution.Clone(), timer?.Lifetime ?? component.Duration, spreadAmount); if (component.SpreadAmount == 0) { RemCompDeferred(uid); break; } - - if (args.Updates <= 0) - break; } + args.Updates--; + if (args.NeighborFreeTiles.Count > 0 || args.Neighbors.Count == 0 || component.SpreadAmount < 1) return; @@ -100,7 +179,6 @@ public sealed class SmokeSystem : EntitySystem continue; smoke.SpreadAmount++; - args.Updates--; component.SpreadAmount--; EnsureComp(neighbor); @@ -110,6 +188,7 @@ public sealed class SmokeSystem : EntitySystem break; } } + } private void OnReactionAttempt(EntityUid uid, SmokeComponent component, ReactionAttemptEvent args) @@ -128,101 +207,117 @@ public sealed class SmokeSystem : EntitySystem } } - private void OnSmokeUnpaused(EntityUid uid, SmokeComponent component, ref EntityUnpausedEvent args) + /// + /// Sets up a smoke component for spreading. + /// + public void StartSmoke(EntityUid uid, Solution solution, float duration, int spreadAmount, SmokeComponent? component = null) { - component.NextReact += args.PausedTime; - } + if (!Resolve(uid, ref component)) + return; - /// - public override void Update(float frameTime) - { - base.Update(frameTime); - var query = EntityQueryEnumerator(); - var curTime = _timing.CurTime; + component.SpreadAmount = spreadAmount; + component.Duration = duration; + component.TransferRate = solution.Volume / duration; + TryAddSolution(uid, solution); + Dirty(uid, component); + EnsureComp(uid); - while (query.MoveNext(out var uid, out var smoke)) + if (TryComp(uid, out var body) && TryComp(uid, out var fixtures)) { - if (smoke.NextReact > curTime) - continue; - - smoke.NextReact += TimeSpan.FromSeconds(1.5); - - SmokeReact(uid, 1f, smoke); + var xform = Transform(uid); + _physics.SetBodyType(uid, BodyType.Dynamic, fixtures, body, xform); + _physics.SetCanCollide(uid, true, manager: fixtures, body: body); + _broadphase.RegenerateContacts(uid, body, fixtures, xform); } + + var timer = EnsureComp(uid); + timer.Lifetime = duration; + + // The tile reaction happens here because it only occurs once. + ReactOnTile(uid, component); } /// - /// Does the relevant smoke reactions for an entity for the specified exposure duration. + /// Does the relevant smoke reactions for an entity. /// - public void SmokeReact(EntityUid uid, float frameTime, SmokeComponent? component = null, TransformComponent? xform = null) + public void SmokeReact(EntityUid entity, EntityUid smokeUid, SmokeComponent? component = null) { - if (!Resolve(uid, ref component, ref xform)) + if (!Resolve(smokeUid, ref component)) return; - if (!_solutionSystem.TryGetSolution(uid, SmokeComponent.SolutionName, out var solution) || + if (!_solutionSystem.TryGetSolution(smokeUid, SmokeComponent.SolutionName, out var solution) || solution.Contents.Count == 0) { return; } + ReactWithEntity(entity, smokeUid, solution, component); + UpdateVisuals(smokeUid); + } + + private void ReactWithEntity(EntityUid entity, EntityUid smokeUid, Solution solution, SmokeComponent? component = null) + { + if (!Resolve(smokeUid, ref component)) + return; + + if (!TryComp(entity, out var bloodstream)) + return; + + var blockIngestion = _internals.AreInternalsWorking(entity); + + var cloneSolution = solution.Clone(); + var availableTransfer = FixedPoint2.Min(cloneSolution.Volume, component.TransferRate); + var transferAmount = FixedPoint2.Min(availableTransfer, bloodstream.ChemicalSolution.AvailableVolume); + var transferSolution = cloneSolution.SplitSolution(transferAmount); + + foreach (var reagentQuantity in transferSolution.Contents.ToArray()) + { + if (reagentQuantity.Quantity == FixedPoint2.Zero) + continue; + var reagentProto = _prototype.Index(reagentQuantity.Reagent.Prototype); + + _reactive.ReactionEntity(entity, ReactionMethod.Touch, reagentProto, reagentQuantity, transferSolution); + if (!blockIngestion) + _reactive.ReactionEntity(entity, ReactionMethod.Ingestion, reagentProto, reagentQuantity, transferSolution); + } + + if (blockIngestion) + return; + + if (_blood.TryAddToChemicals(entity, transferSolution, bloodstream)) + { + // Log solution addition by smoke + _logger.Add(LogType.ForceFeed, LogImpact.Medium, $"{ToPrettyString(entity):target} ingested smoke {SolutionContainerSystem.ToPrettyString(transferSolution)}"); + } + } + + private void ReactOnTile(EntityUid uid, SmokeComponent? component = null, TransformComponent? xform = null) + { + if (!Resolve(uid, ref component, ref xform)) + return; + + if (!_solutionSystem.TryGetSolution(uid, SmokeComponent.SolutionName, out var solution) || !solution.Any()) + return; + if (!_mapManager.TryGetGrid(xform.GridUid, out var mapGrid)) return; - var tile = mapGrid.GetTileRef(xform.Coordinates.ToVector2i(EntityManager, _mapManager)); - - var solutionFraction = 1 / Math.Floor(frameTime); - var ents = _lookup.GetEntitiesIntersecting(tile, 0f, flags: LookupFlags.Uncontained).ToArray(); + var tile = mapGrid.GetTileRef(xform.Coordinates.ToVector2i(EntityManager, _mapManager, _transform)); foreach (var reagentQuantity in solution.Contents.ToArray()) { if (reagentQuantity.Quantity == FixedPoint2.Zero) continue; - // NOOP, react with entities on the tile or whatever. + var reagent = _prototype.Index(reagentQuantity.Reagent.Prototype); + reagent.ReactionTile(tile, reagentQuantity.Quantity); } - - foreach (var entity in ents) - { - if (entity == uid) - continue; - - ReactWithEntity(entity, solution, solutionFraction); - } - - UpdateVisuals(uid); - } - - private void UpdateVisuals(EntityUid uid) - { - if (TryComp(uid, out AppearanceComponent? appearance) && - _solutionSystem.TryGetSolution(uid, SmokeComponent.SolutionName, out var solution)) - { - var color = solution.GetColor(_prototype); - _appearance.SetData(uid, SmokeVisuals.Color, color, appearance); - } - } - - private void ReactWithEntity(EntityUid entity, Solution solution, double solutionFraction) - { - // NOOP due to people complaining constantly. - return; - } - - /// - /// Sets up a smoke component for spreading. - /// - public void Start(EntityUid uid, SmokeComponent component, Solution solution, float duration) - { - TryAddSolution(uid, component, solution); - EnsureComp(uid); - var timer = EnsureComp(uid); - timer.Lifetime = duration; } /// /// Adds the specified solution to the relevant smoke solution. /// - public void TryAddSolution(EntityUid uid, SmokeComponent component, Solution solution) + private void TryAddSolution(EntityUid uid, Solution solution) { if (solution.Volume == FixedPoint2.Zero) return; @@ -237,4 +332,14 @@ public sealed class SmokeSystem : EntitySystem UpdateVisuals(uid); } + + private void UpdateVisuals(EntityUid uid) + { + if (!TryComp(uid, out AppearanceComponent? appearance) || + !_solutionSystem.TryGetSolution(uid, SmokeComponent.SolutionName, out var solution)) + return; + + var color = solution.GetColor(_prototype); + _appearance.SetData(uid, SmokeVisuals.Color, color, appearance); + } } diff --git a/Content.Server/Fluids/ShowFluidsCommand.cs b/Content.Server/Fluids/ShowFluidsCommand.cs index f122eadea7..71ac273a45 100644 --- a/Content.Server/Fluids/ShowFluidsCommand.cs +++ b/Content.Server/Fluids/ShowFluidsCommand.cs @@ -1,7 +1,6 @@ using Content.Server.Administration; using Content.Server.Fluids.EntitySystems; using Content.Shared.Administration; -using Robust.Server.Player; using Robust.Shared.Console; namespace Content.Server.Fluids; @@ -15,7 +14,7 @@ public sealed class ShowFluidsCommand : IConsoleCommand public string Help => $"Usage: {Command}"; public void Execute(IConsoleShell shell, string argStr, string[] args) { - var player = shell.Player as IPlayerSession; + var player = shell.Player; if (player == null) { shell.WriteLine("You must be a player to use this command."); diff --git a/Content.Server/GameTicking/Commands/JoinGameCommand.cs b/Content.Server/GameTicking/Commands/JoinGameCommand.cs index 366e6c4e77..3276b91200 100644 --- a/Content.Server/GameTicking/Commands/JoinGameCommand.cs +++ b/Content.Server/GameTicking/Commands/JoinGameCommand.cs @@ -2,7 +2,6 @@ using Content.Server.Station.Systems; using Content.Shared.Administration; using Content.Shared.GameTicking; using Content.Shared.Roles; -using Robust.Server.Player; using Robust.Shared.Console; using Robust.Shared.Prototypes; @@ -30,7 +29,7 @@ namespace Content.Server.GameTicking.Commands return; } - var player = shell.Player as IPlayerSession; + var player = shell.Player; if (player == null) { diff --git a/Content.Server/GameTicking/Commands/ObserveCommand.cs b/Content.Server/GameTicking/Commands/ObserveCommand.cs index d608dda9c1..747e54e28b 100644 --- a/Content.Server/GameTicking/Commands/ObserveCommand.cs +++ b/Content.Server/GameTicking/Commands/ObserveCommand.cs @@ -1,6 +1,5 @@ using Content.Shared.Administration; using Content.Shared.GameTicking; -using Robust.Server.Player; using Robust.Shared.Console; namespace Content.Server.GameTicking.Commands @@ -14,7 +13,7 @@ namespace Content.Server.GameTicking.Commands public void Execute(IConsoleShell shell, string argStr, string[] args) { - if (shell.Player is not IPlayerSession player) + if (shell.Player is not { } player) { return; } diff --git a/Content.Server/GameTicking/Commands/RespawnCommand.cs b/Content.Server/GameTicking/Commands/RespawnCommand.cs index 057572297f..4f101d0939 100644 --- a/Content.Server/GameTicking/Commands/RespawnCommand.cs +++ b/Content.Server/GameTicking/Commands/RespawnCommand.cs @@ -14,7 +14,7 @@ namespace Content.Server.GameTicking.Commands public void Execute(IConsoleShell shell, string argStr, string[] args) { - var player = shell.Player as IPlayerSession; + var player = shell.Player; if (args.Length > 1) { shell.WriteLine("Must provide <= 1 argument."); diff --git a/Content.Server/GameTicking/Commands/ToggleReadyCommand.cs b/Content.Server/GameTicking/Commands/ToggleReadyCommand.cs index e68c4c5fa7..df418c27ee 100644 --- a/Content.Server/GameTicking/Commands/ToggleReadyCommand.cs +++ b/Content.Server/GameTicking/Commands/ToggleReadyCommand.cs @@ -1,5 +1,4 @@ using Content.Shared.Administration; -using Robust.Server.Player; using Robust.Shared.Console; namespace Content.Server.GameTicking.Commands @@ -13,7 +12,7 @@ namespace Content.Server.GameTicking.Commands public void Execute(IConsoleShell shell, string argStr, string[] args) { - var player = shell.Player as IPlayerSession; + var player = shell.Player; if (args.Length != 1) { shell.WriteError(Loc.GetString("shell-wrong-arguments-number")); diff --git a/Content.Server/GameTicking/GameTicker.GamePreset.cs b/Content.Server/GameTicking/GameTicker.GamePreset.cs index a5e6d7a605..2d7539bd0f 100644 --- a/Content.Server/GameTicking/GameTicker.GamePreset.cs +++ b/Content.Server/GameTicking/GameTicker.GamePreset.cs @@ -11,7 +11,7 @@ using Content.Shared.Ghost; using Content.Shared.Mind; using Content.Shared.Mobs.Components; using JetBrains.Annotations; -using Robust.Server.Player; +using Robust.Shared.Player; namespace Content.Server.GameTicking { @@ -29,7 +29,7 @@ namespace Content.Server.GameTicking /// public GamePresetPrototype? CurrentPreset { get; private set; } - private bool StartPreset(IPlayerSession[] origReadyPlayers, bool force) + private bool StartPreset(ICommonSession[] origReadyPlayers, bool force) { var startAttempt = new RoundStartAttemptEvent(origReadyPlayers, force); RaiseLocalEvent(startAttempt); @@ -214,7 +214,7 @@ namespace Content.Server.GameTicking { if (mind.Session != null) // Logging is suppressed to prevent spam from ghost attempts caused by movement attempts { - _chatManager.DispatchServerMessage((IPlayerSession) mind.Session, Loc.GetString("comp-mind-ghosting-prevented"), + _chatManager.DispatchServerMessage(mind.Session, Loc.GetString("comp-mind-ghosting-prevented"), true); } diff --git a/Content.Server/GameTicking/GameTicker.Lobby.cs b/Content.Server/GameTicking/GameTicker.Lobby.cs index b7b6a29a5a..1943a82617 100644 --- a/Content.Server/GameTicking/GameTicker.Lobby.cs +++ b/Content.Server/GameTicking/GameTicker.Lobby.cs @@ -1,10 +1,8 @@ using System.Linq; using Content.Shared.GameTicking; using Content.Server.Station.Components; -using Robust.Server.Player; using Robust.Shared.Network; using Robust.Shared.Player; -using Robust.Shared.Players; using System.Text; namespace Content.Server.GameTicking @@ -79,7 +77,7 @@ namespace Content.Server.GameTicking ("roundId", RoundId), ("playerCount", playerCount), ("readyCount", readyCount), ("mapName", stationNames.ToString()),("gmTitle", gmTitle),("desc", desc)); } - private TickerLobbyStatusEvent GetStatusMsg(IPlayerSession session) + private TickerLobbyStatusEvent GetStatusMsg(ICommonSession session) { _playerGameStatuses.TryGetValue(session.UserId, out var status); return new TickerLobbyStatusEvent(RunLevel != GameRunLevel.PreRoundLobby, LobbySong, LobbyBackground,status == PlayerGameStatus.ReadyToPlay, _roundStartTime, RoundPreloadTime, _roundStartTimeSpan, Paused); @@ -87,7 +85,7 @@ namespace Content.Server.GameTicking private void SendStatusToAll() { - foreach (var player in _playerManager.ServerSessions) + foreach (var player in _playerManager.Sessions) { RaiseNetworkEvent(GetStatusMsg(player), player.ConnectedClient); } @@ -148,7 +146,7 @@ namespace Content.Server.GameTicking } } - public void ToggleReady(IPlayerSession player, bool ready) + public void ToggleReady(ICommonSession player, bool ready) { if (!_playerGameStatuses.ContainsKey(player.UserId)) return; diff --git a/Content.Server/GameTicking/GameTicker.Player.cs b/Content.Server/GameTicking/GameTicker.Player.cs index aa1c13e98e..07f74df254 100644 --- a/Content.Server/GameTicking/GameTicker.Player.cs +++ b/Content.Server/GameTicking/GameTicker.Player.cs @@ -1,13 +1,14 @@ using Content.Corvax.Interfaces.Server; using Content.Server.Database; -using Content.Server.Players; using Content.Shared.GameTicking; using Content.Shared.GameWindow; using Content.Shared.Players; using Content.Shared.Preferences; using JetBrains.Annotations; +using Robust.Server.GameObjects; using Robust.Server.Player; using Robust.Shared.Enums; +using Robust.Shared.Player; using Robust.Shared.Timing; using Robust.Shared.Utility; @@ -18,6 +19,7 @@ namespace Content.Server.GameTicking { [Dependency] private readonly IPlayerManager _playerManager = default!; [Dependency] private readonly IServerDbManager _dbManager = default!; + [Dependency] private readonly ActorSystem _actor = default!; private void InitializePlayer() { @@ -50,7 +52,7 @@ namespace Content.Server.GameTicking // Always make sure the client has player data. if (session.Data.ContentDataUncast == null) { - var data = new PlayerData(session.UserId, args.Session.Name); + var data = new ContentPlayerData(session.UserId, args.Session.Name); data.Mind = mindId; session.Data.ContentDataUncast = data; } @@ -59,7 +61,7 @@ namespace Content.Server.GameTicking // timer time must be > tick length // Corvax-Queue-Start if (!IoCManager.Instance!.TryResolveType(out _)) - Timer.Spawn(0, args.Session.JoinGame); // Moved to `JoinQueueManager` if manager registered + Timer.Spawn(0, () => _playerManager.JoinGame(args.Session)); // Corvax-Queue-End var record = await _dbManager.GetPlayerRecordByUserId(args.Session.UserId); @@ -104,9 +106,16 @@ namespace Content.Server.GameTicking } else { - // Simply re-attach to existing entity. - session.AttachToEntity(mind.CurrentEntity); - PlayerJoinGame(session); + if (_actor.Attach(mind.CurrentEntity, session)) + { + PlayerJoinGame(session); + } + else + { + Log.Error( + $"Failed to attach player {session} with mind {ToPrettyString(mindId)} to its current entity {ToPrettyString(mind.CurrentEntity)}"); + SpawnObserverWaitDb(); + } } break; @@ -151,12 +160,12 @@ namespace Content.Server.GameTicking } } - private HumanoidCharacterProfile GetPlayerProfile(IPlayerSession p) + private HumanoidCharacterProfile GetPlayerProfile(ICommonSession p) { return (HumanoidCharacterProfile) _prefsManager.GetPreferences(p.UserId).SelectedCharacter; } - public void PlayerJoinGame(IPlayerSession session, bool silent = false) + public void PlayerJoinGame(ICommonSession session, bool silent = false) { if (!silent) _chatManager.DispatchServerMessage(session, Loc.GetString("game-ticker-player-join-game-message")); @@ -167,7 +176,7 @@ namespace Content.Server.GameTicking RaiseNetworkEvent(new TickerJoinGameEvent(), session.ConnectedClient); } - private void PlayerJoinLobby(IPlayerSession session) + private void PlayerJoinLobby(ICommonSession session) { _playerGameStatuses[session.UserId] = LobbyEnabled ? PlayerGameStatus.NotReadyToPlay : PlayerGameStatus.ReadyToPlay; _db.AddRoundPlayers(RoundId, session.UserId); @@ -187,9 +196,9 @@ namespace Content.Server.GameTicking public sealed class PlayerJoinedLobbyEvent : EntityEventArgs { - public readonly IPlayerSession PlayerSession; + public readonly ICommonSession PlayerSession; - public PlayerJoinedLobbyEvent(IPlayerSession playerSession) + public PlayerJoinedLobbyEvent(ICommonSession playerSession) { PlayerSession = playerSession; } diff --git a/Content.Server/GameTicking/GameTicker.RoundFlow.cs b/Content.Server/GameTicking/GameTicker.RoundFlow.cs index e9ea36f0f8..8cf9c65890 100644 --- a/Content.Server/GameTicking/GameTicker.RoundFlow.cs +++ b/Content.Server/GameTicking/GameTicker.RoundFlow.cs @@ -12,7 +12,6 @@ using Content.Shared.Preferences; using JetBrains.Annotations; using Prometheus; using Robust.Server.Maps; -using Robust.Server.Player; using Robust.Shared.Asynchronous; using Robust.Shared.Audio; using Robust.Shared.Map; @@ -205,7 +204,7 @@ namespace Content.Server.GameTicking var startingEvent = new RoundStartingEvent(RoundId); RaiseLocalEvent(startingEvent); - var readyPlayers = new List(); + var readyPlayers = new List(); var readyPlayerProfiles = new Dictionary(); foreach (var (userId, status) in _playerGameStatuses) @@ -345,7 +344,7 @@ namespace Content.Server.GameTicking { connected = true; } - PlayerData? contentPlayerData = null; + ContentPlayerData? contentPlayerData = null; if (userId != null && _playerManager.TryGetPlayerData(userId.Value, out var playerData)) { contentPlayerData = playerData.ContentData(); @@ -361,9 +360,8 @@ namespace Content.Server.GameTicking else if (mind.CurrentEntity != null && TryName(mind.CurrentEntity.Value, out var icName)) playerIcName = icName; - var entity = mind.OriginalOwnedEntity; - if (Exists(entity)) - _pvsOverride.AddGlobalOverride(entity.Value); + if (TryGetEntity(mind.OriginalOwnedEntity, out var entity)) + _pvsOverride.AddGlobalOverride(entity.Value, recursive: true); var roles = _roles.MindGetAllRoles(mindId); @@ -496,7 +494,7 @@ namespace Content.Server.GameTicking private void ResettingCleanup() { // Move everybody currently in the server to lobby. - foreach (var player in _playerManager.ServerSessions) + foreach (var player in _playerManager.Sessions) { PlayerJoinLobby(player); } @@ -544,7 +542,7 @@ namespace Content.Server.GameTicking DisallowLateJoin = false; _playerGameStatuses.Clear(); - foreach (var session in _playerManager.ServerSessions) + foreach (var session in _playerManager.Sessions) { _playerGameStatuses[session.UserId] = LobbyEnabled ? PlayerGameStatus.NotReadyToPlay : PlayerGameStatus.ReadyToPlay; } @@ -738,10 +736,10 @@ namespace Content.Server.GameTicking /// public sealed class RoundStartAttemptEvent : CancellableEntityEventArgs { - public IPlayerSession[] Players { get; } + public ICommonSession[] Players { get; } public bool Forced { get; } - public RoundStartAttemptEvent(IPlayerSession[] players, bool forced) + public RoundStartAttemptEvent(ICommonSession[] players, bool forced) { Players = players; Forced = forced; @@ -760,11 +758,11 @@ namespace Content.Server.GameTicking /// If you want to handle a specific player being spawned, remove it from this list and do what you need. /// /// If you spawn a player by yourself from this event, don't forget to call on them. - public List PlayerPool { get; } + public List PlayerPool { get; } public IReadOnlyDictionary Profiles { get; } public bool Forced { get; } - public RulePlayerSpawningEvent(List playerPool, IReadOnlyDictionary profiles, bool forced) + public RulePlayerSpawningEvent(List playerPool, IReadOnlyDictionary profiles, bool forced) { PlayerPool = playerPool; Profiles = profiles; @@ -778,11 +776,11 @@ namespace Content.Server.GameTicking /// public sealed class RulePlayerJobsAssignedEvent { - public IPlayerSession[] Players { get; } + public ICommonSession[] Players { get; } public IReadOnlyDictionary Profiles { get; } public bool Forced { get; } - public RulePlayerJobsAssignedEvent(IPlayerSession[] players, IReadOnlyDictionary profiles, bool forced) + public RulePlayerJobsAssignedEvent(ICommonSession[] players, IReadOnlyDictionary profiles, bool forced) { Players = players; Profiles = profiles; diff --git a/Content.Server/GameTicking/GameTicker.Spawning.cs b/Content.Server/GameTicking/GameTicker.Spawning.cs index 93636389ed..236a4dc01e 100644 --- a/Content.Server/GameTicking/GameTicker.Spawning.cs +++ b/Content.Server/GameTicking/GameTicker.Spawning.cs @@ -3,20 +3,20 @@ using System.Linq; using System.Numerics; using Content.Server.Administration.Managers; using Content.Server.Ghost; -using Content.Server.Players; using Content.Server.Spawners.Components; using Content.Server.Speech.Components; using Content.Server.Station.Components; using Content.Shared.CCVar; using Content.Shared.Database; +using Content.Shared.Players; using Content.Shared.Preferences; using Content.Shared.Roles; using Content.Shared.Roles.Jobs; using JetBrains.Annotations; -using Robust.Server.Player; using Robust.Shared.Map; using Robust.Shared.Map.Components; using Robust.Shared.Network; +using Robust.Shared.Player; using Robust.Shared.Prototypes; using Robust.Shared.Random; using Robust.Shared.Utility; @@ -29,7 +29,7 @@ namespace Content.Server.GameTicking [Dependency] private readonly SharedJobSystem _jobs = default!; [ValidatePrototypeId] - private const string ObserverPrototypeName = "MobObserver"; + public const string ObserverPrototypeName = "MobObserver"; /// /// How many players have joined the round through normal methods. @@ -52,7 +52,7 @@ namespace Content.Server.GameTicking return spawnableStations; } - private void SpawnPlayers(List readyPlayers, Dictionary profiles, bool force) + private void SpawnPlayers(List readyPlayers, Dictionary profiles, bool force) { // Allow game rules to spawn players by themselves if needed. (For example, nuke ops or wizard) RaiseLocalEvent(new RulePlayerSpawningEvent(readyPlayers, profiles, force)); @@ -116,7 +116,7 @@ namespace Content.Server.GameTicking RaiseLocalEvent(new RulePlayerJobsAssignedEvent(assignedJobs.Keys.Select(x => _playerManager.GetSessionByUserId(x)).ToArray(), profiles, force)); } - private void SpawnPlayer(IPlayerSession player, EntityUid station, string? jobId = null, bool lateJoin = true, bool silent = false) + private void SpawnPlayer(ICommonSession player, EntityUid station, string? jobId = null, bool lateJoin = true, bool silent = false) { var character = GetPlayerProfile(player); @@ -129,7 +129,7 @@ namespace Content.Server.GameTicking SpawnPlayer(player, character, station, jobId, lateJoin, silent); } - private void SpawnPlayer(IPlayerSession player, HumanoidCharacterProfile character, EntityUid station, string? jobId = null, bool lateJoin = true, bool silent = false) + private void SpawnPlayer(ICommonSession player, HumanoidCharacterProfile character, EntityUid station, string? jobId = null, bool lateJoin = true, bool silent = false) { // Can't spawn players with a dummy ticker! if (DummyTicker) @@ -272,7 +272,7 @@ namespace Content.Server.GameTicking RaiseLocalEvent(mob, aev, true); } - public void Respawn(IPlayerSession player) + public void Respawn(ICommonSession player) { _mind.WipeMind(player); _adminLogger.Add(LogType.Respawn, LogImpact.Medium, $"Player {player} was respawned."); @@ -290,7 +290,7 @@ namespace Content.Server.GameTicking /// The station they're spawning on /// An optional job for them to spawn as /// Whether or not the player should be greeted upon joining - public void MakeJoinGame(IPlayerSession player, EntityUid station, string? jobId = null, bool silent = false) + public void MakeJoinGame(ICommonSession player, EntityUid station, string? jobId = null, bool silent = false) { if (!_playerGameStatuses.ContainsKey(player.UserId)) return; @@ -304,7 +304,7 @@ namespace Content.Server.GameTicking /// /// Causes the given player to join the current game as observer ghost. See also /// - public void JoinAsObserver(IPlayerSession player) + public void JoinAsObserver(ICommonSession player) { // Can't spawn players with a dummy ticker! if (DummyTicker) @@ -318,7 +318,7 @@ namespace Content.Server.GameTicking /// Spawns an observer ghost and attaches the given player to it. If the player does not yet have a mind, the /// player is given a new mind with the observer role. Otherwise, the current mind is transferred to the ghost. /// - public void SpawnObserver(IPlayerSession player) + public void SpawnObserver(ICommonSession player) { if (DummyTicker) return; @@ -431,13 +431,13 @@ namespace Content.Server.GameTicking [PublicAPI] public sealed class PlayerBeforeSpawnEvent : HandledEntityEventArgs { - public IPlayerSession Player { get; } + public ICommonSession Player { get; } public HumanoidCharacterProfile Profile { get; } public string? JobId { get; } public bool LateJoin { get; } public EntityUid Station { get; } - public PlayerBeforeSpawnEvent(IPlayerSession player, HumanoidCharacterProfile profile, string? jobId, bool lateJoin, EntityUid station) + public PlayerBeforeSpawnEvent(ICommonSession player, HumanoidCharacterProfile profile, string? jobId, bool lateJoin, EntityUid station) { Player = player; Profile = profile; @@ -456,7 +456,7 @@ namespace Content.Server.GameTicking public sealed class PlayerSpawnCompleteEvent : EntityEventArgs { public EntityUid Mob { get; } - public IPlayerSession Player { get; } + public ICommonSession Player { get; } public string? JobId { get; } public bool LateJoin { get; } public EntityUid Station { get; } @@ -465,7 +465,7 @@ namespace Content.Server.GameTicking // Ex. If this is the 27th person to join, this will be 27. public int JoinOrder { get; } - public PlayerSpawnCompleteEvent(EntityUid mob, IPlayerSession player, string? jobId, bool lateJoin, int joinOrder, EntityUid station, HumanoidCharacterProfile profile) + public PlayerSpawnCompleteEvent(EntityUid mob, ICommonSession player, string? jobId, bool lateJoin, int joinOrder, EntityUid station, HumanoidCharacterProfile profile) { Mob = mob; Player = player; diff --git a/Content.Server/GameTicking/Rules/Components/RevolutionaryRuleComponent.cs b/Content.Server/GameTicking/Rules/Components/RevolutionaryRuleComponent.cs index 7d036c615b..e9c8d50cdc 100644 --- a/Content.Server/GameTicking/Rules/Components/RevolutionaryRuleComponent.cs +++ b/Content.Server/GameTicking/Rules/Components/RevolutionaryRuleComponent.cs @@ -39,7 +39,7 @@ public sealed partial class RevolutionaryRuleComponent : Component /// Sound that plays when you are chosen as Rev. (Placeholder until I find something cool I guess) /// [DataField] - public SoundSpecifier HeadRevStartSound = new SoundPathSpecifier("/Audio/Ambience/Antag/traitor_start.ogg"); + public SoundSpecifier HeadRevStartSound = new SoundPathSpecifier("/Audio/Ambience/Antag/headrev_start.ogg"); /// /// Min players needed for Revolutionary gamemode to start. diff --git a/Content.Server/GameTicking/Rules/Components/TraitorRuleComponent.cs b/Content.Server/GameTicking/Rules/Components/TraitorRuleComponent.cs index 883abef52f..7af87179d6 100644 --- a/Content.Server/GameTicking/Rules/Components/TraitorRuleComponent.cs +++ b/Content.Server/GameTicking/Rules/Components/TraitorRuleComponent.cs @@ -1,7 +1,7 @@ using Content.Shared.Preferences; using Content.Shared.Roles; -using Robust.Server.Player; using Robust.Shared.Audio; +using Robust.Shared.Player; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; namespace Content.Server.GameTicking.Rules.Components; @@ -26,7 +26,7 @@ public sealed partial class TraitorRuleComponent : Component public SelectionState SelectionStatus = SelectionState.WaitingForSpawn; public TimeSpan AnnounceAt = TimeSpan.Zero; - public Dictionary StartCandidates = new(); + public Dictionary StartCandidates = new(); /// /// Path to antagonist alert sound. diff --git a/Content.Server/GameTicking/Rules/InactivityTimeRestartRuleSystem.cs b/Content.Server/GameTicking/Rules/InactivityTimeRestartRuleSystem.cs index c2e91ba4a5..b775b7af56 100644 --- a/Content.Server/GameTicking/Rules/InactivityTimeRestartRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/InactivityTimeRestartRuleSystem.cs @@ -2,6 +2,7 @@ using System.Threading; using Content.Server.Chat.Managers; using Content.Server.GameTicking.Rules.Components; using Robust.Server.Player; +using Robust.Shared.Player; using Timer = Robust.Shared.Timing.Timer; namespace Content.Server.GameTicking.Rules; diff --git a/Content.Server/GameTicking/Rules/NukeopsRuleSystem.cs b/Content.Server/GameTicking/Rules/NukeopsRuleSystem.cs index 0c8038f86f..ea96ea9e44 100644 --- a/Content.Server/GameTicking/Rules/NukeopsRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/NukeopsRuleSystem.cs @@ -336,7 +336,7 @@ public sealed class NukeopsRuleSystem : GameRuleSystem var eligibleQuery = EntityQueryEnumerator(); while (eligibleQuery.MoveNext(out var eligibleUid, out var eligibleComp, out var member)) { - if (!_npcFaction.IsFactionFriendly(component.Faction, eligibleUid, member)) + if (!_npcFaction.IsFactionHostile(component.Faction, eligibleUid, member)) continue; eligible.Add((eligibleUid, eligibleComp, member)); @@ -351,8 +351,7 @@ public sealed class NukeopsRuleSystem : GameRuleSystem var query = EntityQueryEnumerator(); while (query.MoveNext(out _, out var nukeops, out var actor)) { - _chatManager.DispatchServerMessage(actor.PlayerSession, Loc.GetString("nukeops-welcome", ("station", component.TargetStation.Value))); - _audio.PlayGlobal(nukeops.GreetSoundNotification, actor.PlayerSession); + NotifyNukie(actor.PlayerSession, nukeops, component); filter.AddPlayer(actor.PlayerSession); } } @@ -604,11 +603,11 @@ public sealed class NukeopsRuleSystem : GameRuleSystem var maxOperatives = nukeops.MaxOps; // Dear lord what is happening HERE. - var everyone = new List(ev.PlayerPool); - var prefList = new List(); - var medPrefList = new List(); - var cmdrPrefList = new List(); - var operatives = new List(); + var everyone = new List(ev.PlayerPool); + var prefList = new List(); + var medPrefList = new List(); + var cmdrPrefList = new List(); + var operatives = new List(); // The LINQ expression ReSharper keeps suggesting is completely unintelligible so I'm disabling it // ReSharper disable once ForeachCanBeConvertedToQueryUsingAnotherGetEnumerator @@ -639,7 +638,7 @@ public sealed class NukeopsRuleSystem : GameRuleSystem for (var i = 0; i < numNukies; i++) { // TODO: Please fix this if you touch it. - IPlayerSession nukeOp; + ICommonSession nukeOp; // Only one commander, so we do it at the start if (i == 0) { @@ -795,10 +794,7 @@ public sealed class NukeopsRuleSystem : GameRuleSystem if (nukeops.TargetStation != null && !string.IsNullOrEmpty(Name(nukeops.TargetStation.Value))) { - _chatManager.DispatchServerMessage(playerSession, Loc.GetString("nukeops-welcome", ("station", nukeops.TargetStation.Value))); - - // Notificate player about new role assignment - _audio.PlayGlobal(component.GreetSoundNotification, playerSession); + NotifyNukie(playerSession, component, nukeops); } } } @@ -910,7 +906,7 @@ public sealed class NukeopsRuleSystem : GameRuleSystem _npcFaction.AddFaction(mob, "Syndicate"); } - private void SpawnOperatives(int spawnCount, List sessions, bool addSpawnPoints, NukeopsRuleComponent component) + private void SpawnOperatives(int spawnCount, List sessions, bool addSpawnPoints, NukeopsRuleComponent component) { if (component.NukieOutpost == null) return; @@ -989,13 +985,25 @@ public sealed class NukeopsRuleSystem : GameRuleSystem var playersPerOperative = component.PlayersPerOperative; var maxOperatives = component.MaxOps; - var playerPool = _playerManager.ServerSessions.ToList(); + var playerPool = _playerManager.Sessions.ToList(); var numNukies = MathHelper.Clamp(playerPool.Count / playersPerOperative, 1, maxOperatives); - var operatives = new List(); + var operatives = new List(); SpawnOperatives(numNukies, operatives, true, component); } + /// + /// Display a greeting message and play a sound for a nukie + /// + private void NotifyNukie(ICommonSession session, NukeOperativeComponent nukeop, NukeopsRuleComponent nukeopsRule) + { + if (nukeopsRule.TargetStation is not { } station) + return; + + _chatManager.DispatchServerMessage(session, Loc.GetString("nukeops-welcome", ("station", station))); + _audio.PlayGlobal(nukeop.GreetSoundNotification, session); + } + //For admins forcing someone to nukeOps. public void MakeLoneNukie(EntityUid mindId, MindComponent mind) { diff --git a/Content.Server/GameTicking/Rules/PiratesRuleSystem.cs b/Content.Server/GameTicking/Rules/PiratesRuleSystem.cs index b223161c10..0785d81d09 100644 --- a/Content.Server/GameTicking/Rules/PiratesRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/PiratesRuleSystem.cs @@ -15,10 +15,10 @@ using Content.Shared.Preferences; using Content.Shared.Roles; using Robust.Server.GameObjects; using Robust.Server.Maps; -using Robust.Server.Player; using Robust.Shared.Configuration; using Robust.Shared.Enums; using Robust.Shared.Map; +using Robust.Shared.Player; using Robust.Shared.Prototypes; using Robust.Shared.Random; using Robust.Shared.Utility; @@ -141,7 +141,7 @@ public sealed class PiratesRuleSystem : GameRuleSystem (int) Math.Min( Math.Floor((double) ev.PlayerPool.Count / _cfg.GetCVar(CCVars.PiratesPlayersPerOp)), _cfg.GetCVar(CCVars.PiratesMaxOps))); - var ops = new IPlayerSession[numOps]; + var ops = new ICommonSession[numOps]; for (var i = 0; i < numOps; i++) { ops[i] = _random.PickAndTake(ev.PlayerPool); diff --git a/Content.Server/GameTicking/Rules/RespawnRuleSystem.cs b/Content.Server/GameTicking/Rules/RespawnRuleSystem.cs index a286808623..738883fff3 100644 --- a/Content.Server/GameTicking/Rules/RespawnRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/RespawnRuleSystem.cs @@ -6,6 +6,7 @@ using Content.Shared.Chat; using Content.Shared.Interaction.Events; using Content.Shared.Mind; using Content.Shared.Mobs; +using Content.Shared.Players; using Robust.Server.GameObjects; using Robust.Server.Player; using Robust.Shared.Network; diff --git a/Content.Server/GameTicking/Rules/TraitorRuleSystem.cs b/Content.Server/GameTicking/Rules/TraitorRuleSystem.cs index 01317dbfc1..ef949d09fc 100644 --- a/Content.Server/GameTicking/Rules/TraitorRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/TraitorRuleSystem.cs @@ -17,9 +17,8 @@ using Content.Shared.PDA; using Content.Shared.Preferences; using Content.Shared.Roles; using Content.Shared.Roles.Jobs; -using Robust.Server.Player; using Robust.Shared.Configuration; -using Robust.Shared.Players; +using Robust.Shared.Player; using Robust.Shared.Prototypes; using Robust.Shared.Random; using Robust.Shared.Timing; @@ -151,9 +150,9 @@ public sealed class TraitorRuleSystem : GameRuleSystem } } - private List FindPotentialTraitors(in Dictionary candidates, TraitorRuleComponent component) + private List FindPotentialTraitors(in Dictionary candidates, TraitorRuleComponent component) { - var list = new List(); + var list = new List(); var pendingQuery = GetEntityQuery(); foreach (var player in candidates.Keys) @@ -171,7 +170,7 @@ public sealed class TraitorRuleSystem : GameRuleSystem list.Add(player); } - var prefList = new List(); + var prefList = new List(); foreach (var player in list) { @@ -189,9 +188,9 @@ public sealed class TraitorRuleSystem : GameRuleSystem return prefList; } - private List PickTraitors(int traitorCount, List prefList) + private List PickTraitors(int traitorCount, List prefList) { - var results = new List(traitorCount); + var results = new List(traitorCount); if (prefList.Count == 0) { Log.Info("Insufficient ready players to fill up with traitors, stopping the selection."); diff --git a/Content.Server/GameTicking/Rules/ZombieRuleSystem.cs b/Content.Server/GameTicking/Rules/ZombieRuleSystem.cs index 82ae4b8fa6..a4febc385c 100644 --- a/Content.Server/GameTicking/Rules/ZombieRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/ZombieRuleSystem.cs @@ -23,7 +23,7 @@ using Content.Shared.Zombies; using Robust.Server.GameObjects; using Robust.Server.Player; using Robust.Shared.Configuration; -using Robust.Shared.Prototypes; +using Robust.Shared.Player; using Robust.Shared.Random; using Robust.Shared.Timing; @@ -264,9 +264,9 @@ public sealed class ZombieRuleSystem : GameRuleSystem return; component.InfectedChosen = true; - var allPlayers = _playerManager.ServerSessions.ToList(); - var playerList = new List(); - var prefList = new List(); + var allPlayers = _playerManager.Sessions.ToList(); + var playerList = new List(); + var prefList = new List(); foreach (var player in allPlayers) { if (player.AttachedEntity == null || !HasComp(player.AttachedEntity) || HasComp(player.AttachedEntity)) @@ -288,7 +288,7 @@ public sealed class ZombieRuleSystem : GameRuleSystem var totalInfected = 0; while (totalInfected < numInfected) { - IPlayerSession zombie; + ICommonSession zombie; if (prefList.Count == 0) { if (playerList.Count == 0) diff --git a/Content.Server/Ghost/Ghost.cs b/Content.Server/Ghost/Ghost.cs index d04b1197af..1453bf3faa 100644 --- a/Content.Server/Ghost/Ghost.cs +++ b/Content.Server/Ghost/Ghost.cs @@ -1,7 +1,6 @@ using Content.Server.GameTicking; using Content.Shared.Administration; using Content.Shared.Mind; -using Robust.Server.Player; using Robust.Shared.Console; namespace Content.Server.Ghost @@ -17,7 +16,7 @@ namespace Content.Server.Ghost public void Execute(IConsoleShell shell, string argStr, string[] args) { - var player = shell.Player as IPlayerSession; + var player = shell.Player; if (player == null) { shell.WriteLine("You have no session, you can't ghost."); diff --git a/Content.Server/Ghost/Roles/Components/TakeGhostRoleEvent.cs b/Content.Server/Ghost/Roles/Components/TakeGhostRoleEvent.cs index c97e3be9dc..16d46871fe 100644 --- a/Content.Server/Ghost/Roles/Components/TakeGhostRoleEvent.cs +++ b/Content.Server/Ghost/Roles/Components/TakeGhostRoleEvent.cs @@ -1,4 +1,4 @@ -using Robust.Shared.Players; +using Robust.Shared.Player; namespace Content.Server.Ghost.Roles.Components; diff --git a/Content.Server/Ghost/Roles/GhostRoleSystem.cs b/Content.Server/Ghost/Roles/GhostRoleSystem.cs index 5a4cc176f2..f372cb4f62 100644 --- a/Content.Server/Ghost/Roles/GhostRoleSystem.cs +++ b/Content.Server/Ghost/Roles/GhostRoleSystem.cs @@ -4,7 +4,6 @@ using Content.Server.Ghost.Roles.Components; using Content.Server.Ghost.Roles.Events; using Content.Server.Ghost.Roles.UI; using Content.Server.Mind.Commands; -using Content.Server.Players; using Content.Shared.Administration; using Content.Shared.Database; using Content.Shared.Follower; @@ -14,13 +13,14 @@ using Content.Shared.Ghost.Roles; using Content.Shared.Mind; using Content.Shared.Mind.Components; using Content.Shared.Mobs; +using Content.Shared.Players; using Content.Shared.Roles; using JetBrains.Annotations; using Robust.Server.GameObjects; using Robust.Server.Player; using Robust.Shared.Console; using Robust.Shared.Enums; -using Robust.Shared.Players; +using Robust.Shared.Player; using Robust.Shared.Random; using Robust.Shared.Utility; @@ -97,7 +97,7 @@ namespace Content.Server.Ghost.Roles return unchecked(_nextRoleIdentifier++); } - public void OpenEui(IPlayerSession session) + public void OpenEui(ICommonSession session) { if (session.AttachedEntity is not {Valid: true} attached || !EntityManager.HasComponent(attached)) @@ -111,7 +111,7 @@ namespace Content.Server.Ghost.Roles eui.StateDirty(); } - public void OpenMakeGhostRoleEui(IPlayerSession session, EntityUid uid) + public void OpenMakeGhostRoleEui(ICommonSession session, EntityUid uid) { if (session.AttachedEntity == null) return; @@ -420,7 +420,7 @@ namespace Content.Server.Ghost.Roles public void Execute(IConsoleShell shell, string argStr, string[] args) { if(shell.Player != null) - EntitySystem.Get().OpenEui((IPlayerSession)shell.Player); + EntitySystem.Get().OpenEui(shell.Player); else shell.WriteLine("You can only open the ghost roles UI on a client."); } diff --git a/Content.Server/Gravity/GravityGeneratorSystem.cs b/Content.Server/Gravity/GravityGeneratorSystem.cs index 48002fb823..0bd159f61a 100644 --- a/Content.Server/Gravity/GravityGeneratorSystem.cs +++ b/Content.Server/Gravity/GravityGeneratorSystem.cs @@ -6,7 +6,7 @@ using Content.Shared.Database; using Content.Shared.Gravity; using Content.Shared.Interaction; using Robust.Server.GameObjects; -using Robust.Shared.Players; +using Robust.Shared.Player; namespace Content.Server.Gravity { @@ -139,7 +139,7 @@ namespace Content.Server.Gravity return; if (session is { AttachedEntity: { } }) - _adminLogger.Add(LogType.Action, on ? LogImpact.Medium : LogImpact.High, $"{ToPrettyString(session.AttachedEntity.Value):player} set ${ToPrettyString(uid):target} to {(on ? "on" : "off")}"); + _adminLogger.Add(LogType.Action, on ? LogImpact.Medium : LogImpact.High, $"{session:player} set ${ToPrettyString(uid):target} to {(on ? "on" : "off")}"); component.SwitchedOn = on; UpdatePowerState(component, powerReceiver); diff --git a/Content.Server/Hands/Systems/HandsSystem.cs b/Content.Server/Hands/Systems/HandsSystem.cs index b5b01ac001..e3e6699537 100644 --- a/Content.Server/Hands/Systems/HandsSystem.cs +++ b/Content.Server/Hands/Systems/HandsSystem.cs @@ -18,12 +18,11 @@ using Content.Shared.Pulling.Components; using Content.Shared.Stacks; using Content.Shared.Storage; using Content.Shared.Throwing; -using Robust.Server.Player; using Robust.Shared.Containers; using Robust.Shared.GameStates; using Robust.Shared.Input.Binding; using Robust.Shared.Map; -using Robust.Shared.Players; +using Robust.Shared.Player; using Robust.Shared.Utility; namespace Content.Server.Hands.Systems @@ -159,9 +158,9 @@ namespace Content.Server.Hands.Systems #endregion #region interactions - private bool HandleThrowItem(ICommonSession? session, EntityCoordinates coordinates, EntityUid entity) + private bool HandleThrowItem(ICommonSession? playerSession, EntityCoordinates coordinates, EntityUid entity) { - if (session is not IPlayerSession playerSession) + if (playerSession == null) return false; if (playerSession.AttachedEntity is not {Valid: true} player || @@ -220,7 +219,7 @@ namespace Content.Server.Hands.Systems // TODO: move to storage or inventory private void HandleSmartEquip(ICommonSession? session, string equipmentSlot) { - if (session is not IPlayerSession playerSession) + if (session is not { } playerSession) return; if (playerSession.AttachedEntity is not {Valid: true} plyEnt || !Exists(plyEnt)) diff --git a/Content.Server/Humanoid/Systems/HumanoidAppearanceSystem.Modifier.cs b/Content.Server/Humanoid/Systems/HumanoidAppearanceSystem.Modifier.cs index 7c0bb7383b..b47fe71714 100644 --- a/Content.Server/Humanoid/Systems/HumanoidAppearanceSystem.Modifier.cs +++ b/Content.Server/Humanoid/Systems/HumanoidAppearanceSystem.Modifier.cs @@ -3,7 +3,6 @@ using Content.Shared.Administration; using Content.Shared.Humanoid; using Content.Shared.Verbs; using Robust.Server.GameObjects; -using Robust.Server.Player; using Robust.Shared.Utility; namespace Content.Server.Humanoid; @@ -48,7 +47,7 @@ public sealed partial class HumanoidAppearanceSystem private void OnBaseLayersSet(EntityUid uid, HumanoidAppearanceComponent component, HumanoidMarkingModifierBaseLayersSetMessage message) { - if (message.Session is not IPlayerSession player + if (message.Session is not { } player || !_adminManager.HasAdminFlag(player, AdminFlags.Fun)) { return; @@ -81,7 +80,7 @@ public sealed partial class HumanoidAppearanceSystem private void OnMarkingsSet(EntityUid uid, HumanoidAppearanceComponent component, HumanoidMarkingModifierMarkingSetMessage message) { - if (message.Session is not IPlayerSession player + if (message.Session is not { } player || !_adminManager.HasAdminFlag(player, AdminFlags.Fun)) { return; diff --git a/Content.Server/Implants/ImplanterSystem.cs b/Content.Server/Implants/ImplanterSystem.cs index f3072769e4..0d46241f41 100644 --- a/Content.Server/Implants/ImplanterSystem.cs +++ b/Content.Server/Implants/ImplanterSystem.cs @@ -1,11 +1,9 @@ -using Content.Server.Guardian; using Content.Server.Popups; using Content.Shared.DoAfter; using Content.Shared.IdentityManagement; using Content.Shared.Implants; using Content.Shared.Implants.Components; using Content.Shared.Interaction; -using Content.Shared.Mobs.Components; using Content.Shared.Popups; using Robust.Shared.Containers; @@ -33,28 +31,39 @@ public sealed partial class ImplanterSystem : SharedImplanterSystem if (args.Target == null || !args.CanReach || args.Handled) return; - //Simplemobs and regular mobs should be injectable, but only regular mobs have mind. - //So just don't implant/draw anything that isn't living or is a guardian - //TODO: Rework a bit when surgery is in to work with implant cases - if (!HasComp(args.Target.Value) || HasComp(args.Target.Value)) + var target = args.Target.Value; + if (!CheckTarget(target, component.Whitelist, component.Blacklist)) return; //TODO: Rework when surgery is in for implant cases if (component.CurrentMode == ImplanterToggleMode.Draw && !component.ImplantOnly) { - TryDraw(component, args.User, args.Target.Value, uid); + TryDraw(component, args.User, target, uid); } else { - if (!CanImplant(args.User, args.Target.Value, uid, component, out _, out _)) + if (!CanImplant(args.User, target, uid, component, out var implant, out _)) + { + // no popup if implant doesn't exist + if (implant == null) + return; + + // show popup to the user saying implant failed + var name = Identity.Name(target, EntityManager, args.User); + var msg = Loc.GetString("implanter-component-implant-failed", ("implant", implant), ("target", name)); + _popup.PopupEntity(msg, target, args.User); + // prevent further interaction since popup was shown + args.Handled = true; return; + } //Implant self instantly, otherwise try to inject the target. - if (args.User == args.Target) - Implant(args.User, args.Target.Value, uid, component); + if (args.User == target) + Implant(target, target, uid, component); else - TryImplant(component, args.User, args.Target.Value, uid); + TryImplant(component, args.User, target, uid); } + args.Handled = true; } diff --git a/Content.Server/Instruments/InstrumentComponent.cs b/Content.Server/Instruments/InstrumentComponent.cs index 810d265314..4302ab6791 100644 --- a/Content.Server/Instruments/InstrumentComponent.cs +++ b/Content.Server/Instruments/InstrumentComponent.cs @@ -1,7 +1,7 @@ using Content.Server.UserInterface; using Content.Shared.Instruments; using Robust.Server.GameObjects; -using Robust.Server.Player; +using Robust.Shared.Player; namespace Content.Server.Instruments; @@ -17,7 +17,7 @@ public sealed partial class InstrumentComponent : SharedInstrumentComponent [ViewVariables] public uint LastSequencerTick = 0; // TODO Instruments: Make this ECS - public IPlayerSession? InstrumentPlayer => + public ICommonSession? InstrumentPlayer => _entMan.GetComponentOrNull(Owner)?.CurrentSingleUser ?? _entMan.GetComponentOrNull(Owner)?.PlayerSession; } diff --git a/Content.Server/Instruments/InstrumentSystem.cs b/Content.Server/Instruments/InstrumentSystem.cs index ec23382105..6f8369182c 100644 --- a/Content.Server/Instruments/InstrumentSystem.cs +++ b/Content.Server/Instruments/InstrumentSystem.cs @@ -9,12 +9,12 @@ using Content.Shared.Physics; using Content.Shared.Popups; using JetBrains.Annotations; using Robust.Server.GameObjects; -using Robust.Server.Player; using Robust.Shared.Audio.Midi; using Robust.Shared.Collections; using Robust.Shared.Configuration; using Robust.Shared.Console; using Robust.Shared.GameStates; +using Robust.Shared.Player; using Robust.Shared.Timing; namespace Content.Server.Instruments; @@ -385,7 +385,7 @@ public sealed partial class InstrumentSystem : SharedInstrumentSystem var nearby = GetBands(entity); _bui.TrySendUiMessage(entity, request.UiKey, new InstrumentBandResponseBuiMessage(nearby), - (IPlayerSession)request.Session); + request.Session); } _bandRequestQueue.Clear(); @@ -447,7 +447,7 @@ public sealed partial class InstrumentSystem : SharedInstrumentSystem } } - public void ToggleInstrumentUi(EntityUid uid, IPlayerSession session, InstrumentComponent? component = null) + public void ToggleInstrumentUi(EntityUid uid, ICommonSession session, InstrumentComponent? component = null) { if (!Resolve(uid, ref component)) return; diff --git a/Content.Server/Interaction/InteractionSystem.cs b/Content.Server/Interaction/InteractionSystem.cs index a612b73840..9237a1f7dd 100644 --- a/Content.Server/Interaction/InteractionSystem.cs +++ b/Content.Server/Interaction/InteractionSystem.cs @@ -13,7 +13,6 @@ using Robust.Server.GameObjects; using Robust.Shared.Containers; using Robust.Shared.Input.Binding; using Robust.Shared.Map; -using Robust.Shared.Players; using Robust.Shared.Random; namespace Content.Server.Interaction diff --git a/Content.Server/Interaction/TilePryCommand.cs b/Content.Server/Interaction/TilePryCommand.cs index 157fa2cc80..fa75b6d9e4 100644 --- a/Content.Server/Interaction/TilePryCommand.cs +++ b/Content.Server/Interaction/TilePryCommand.cs @@ -1,16 +1,14 @@ using System.Numerics; using Content.Server.Administration; -using Content.Server.Tools.Components; using Content.Shared.Administration; using Content.Shared.Maps; -using Robust.Server.Player; using Robust.Shared.Console; using Robust.Shared.Map; namespace Content.Server.Interaction { /// - /// + /// /// [AdminCommand(AdminFlags.Debug)] sealed class TilePryCommand : IConsoleCommand @@ -23,7 +21,7 @@ namespace Content.Server.Interaction public void Execute(IConsoleShell shell, string argStr, string[] args) { - var player = shell.Player as IPlayerSession; + var player = shell.Player; if (player?.AttachedEntity is not {} attached) { return; diff --git a/Content.Server/MagicMirror/MagicMirrorSystem.cs b/Content.Server/MagicMirror/MagicMirrorSystem.cs index 90a0b19b7d..a599a2c868 100644 --- a/Content.Server/MagicMirror/MagicMirrorSystem.cs +++ b/Content.Server/MagicMirror/MagicMirrorSystem.cs @@ -5,8 +5,7 @@ using Content.Shared.Humanoid; using Content.Shared.Humanoid.Markings; using Content.Shared.MagicMirror; using Robust.Server.GameObjects; -using Robust.Server.Player; -using Robust.Shared.Players; +using Robust.Shared.Player; namespace Content.Server.MagicMirror; @@ -147,7 +146,7 @@ public sealed class MagicMirrorSystem : EntitySystem private void UpdateInterface(EntityUid uid, EntityUid playerUid, ICommonSession session, HumanoidAppearanceComponent? humanoid = null) { - if (!Resolve(playerUid, ref humanoid) || session is not IPlayerSession player) + if (!Resolve(playerUid, ref humanoid) || session is not { } player) { return; } diff --git a/Content.Server/Mapping/MappingCommand.cs b/Content.Server/Mapping/MappingCommand.cs index e4a4cd8942..d72a5c4178 100644 --- a/Content.Server/Mapping/MappingCommand.cs +++ b/Content.Server/Mapping/MappingCommand.cs @@ -40,7 +40,7 @@ namespace Content.Server.Mapping public void Execute(IConsoleShell shell, string argStr, string[] args) { - if (shell.Player is not IPlayerSession player) + if (shell.Player is not { } player) { shell.WriteError(Loc.GetString("cmd-savemap-server")); return; diff --git a/Content.Server/Maps/GridDraggingSystem.cs b/Content.Server/Maps/GridDraggingSystem.cs index 90770af1ad..7d7b61955b 100644 --- a/Content.Server/Maps/GridDraggingSystem.cs +++ b/Content.Server/Maps/GridDraggingSystem.cs @@ -1,10 +1,9 @@ using Content.Shared.Maps; using Robust.Server.Console; -using Robust.Server.Player; -using Robust.Shared.Players; using Robust.Shared.Utility; using Robust.Shared.Physics.Components; using Robust.Shared.Physics.Systems; +using Robust.Shared.Player; namespace Content.Server.Maps; @@ -27,7 +26,7 @@ public sealed class GridDraggingSystem : SharedGridDraggingSystem public void Toggle(ICommonSession session) { - if (session is not IPlayerSession pSession) + if (session is not { } pSession) return; DebugTools.Assert(_admin.CanCommand(pSession, CommandName)); @@ -52,7 +51,7 @@ public sealed class GridDraggingSystem : SharedGridDraggingSystem { var grid = GetEntity(ev.Grid); - if (args.SenderSession is not IPlayerSession playerSession || + if (args.SenderSession is not { } playerSession || !_admin.CanCommand(playerSession, CommandName) || !Exists(grid) || Deleted(grid)) @@ -69,7 +68,7 @@ public sealed class GridDraggingSystem : SharedGridDraggingSystem { var grid = GetEntity(msg.Grid); - if (args.SenderSession is not IPlayerSession playerSession || + if (args.SenderSession is not { } playerSession || !_admin.CanCommand(playerSession, CommandName) || !Exists(grid) || Deleted(grid)) diff --git a/Content.Server/Medical/CryoPodSystem.cs b/Content.Server/Medical/CryoPodSystem.cs index b94d6de6de..82f7b9cb0a 100644 --- a/Content.Server/Medical/CryoPodSystem.cs +++ b/Content.Server/Medical/CryoPodSystem.cs @@ -32,6 +32,7 @@ using Content.Shared.Tools; using Content.Shared.Verbs; using Robust.Server.GameObjects; using Robust.Shared.Timing; +using SharedToolSystem = Content.Shared.Tools.Systems.SharedToolSystem; namespace Content.Server.Medical; diff --git a/Content.Server/Medical/DefibrillatorSystem.cs b/Content.Server/Medical/DefibrillatorSystem.cs index 4ffa9f558d..d041f8ee9d 100644 --- a/Content.Server/Medical/DefibrillatorSystem.cs +++ b/Content.Server/Medical/DefibrillatorSystem.cs @@ -18,7 +18,7 @@ using Content.Shared.Mobs.Components; using Content.Shared.Mobs.Systems; using Content.Shared.Timing; using Content.Shared.Toggleable; -using Robust.Shared.Players; +using Robust.Shared.Player; using Robust.Shared.Timing; namespace Content.Server.Medical; diff --git a/Content.Server/Mind/Commands/RenameCommand.cs b/Content.Server/Mind/Commands/RenameCommand.cs index 5674da4ffd..2d65adc508 100644 --- a/Content.Server/Mind/Commands/RenameCommand.cs +++ b/Content.Server/Mind/Commands/RenameCommand.cs @@ -54,6 +54,7 @@ public sealed class RenameCommand : IConsoleCommand { // Mind mind.CharacterName = name; + _entManager.Dirty(mindId, mind); } // Id Cards diff --git a/Content.Server/Mind/MindSystem.cs b/Content.Server/Mind/MindSystem.cs index 373007fd1b..f23e9b6407 100644 --- a/Content.Server/Mind/MindSystem.cs +++ b/Content.Server/Mind/MindSystem.cs @@ -1,6 +1,7 @@ using System.Diagnostics.CodeAnalysis; using Content.Server.Administration.Logs; using Content.Server.GameTicking; +using Content.Server.Mind.Commands; using Content.Shared.Database; using Content.Shared.Ghost; using Content.Shared.Mind; @@ -10,7 +11,9 @@ using Robust.Server.GameObjects; using Robust.Server.GameStates; using Robust.Server.Player; using Robust.Shared.Map; +using Robust.Shared.Map.Components; using Robust.Shared.Network; +using Robust.Shared.Player; using Robust.Shared.Timing; using Robust.Shared.Utility; @@ -46,20 +49,14 @@ public sealed class MindSystem : SharedMindSystem mind.UserId = null; } - if (!TryComp(mind.OwnedEntity, out MetaDataComponent? meta) || meta.EntityLifeStage >= EntityLifeStage.Terminating) - return; + if (mind.OwnedEntity != null && !TerminatingOrDeleted(mind.OwnedEntity.Value)) + TransferTo(uid, null, mind: mind, createGhost: false); - RaiseLocalEvent(mind.OwnedEntity.Value, new MindRemovedMessage(uid, mind), true); mind.OwnedEntity = null; - mind.OwnedComponent = null; } private void OnMindContainerTerminating(EntityUid uid, MindContainerComponent component, ref EntityTerminatingEvent args) { - // Let's not create ghosts if not in the middle of the round. - if (_gameTicker.RunLevel == GameRunLevel.PreRoundLobby) - return; - if (!TryGetMind(uid, out var mindId, out var mind, component)) return; @@ -76,46 +73,45 @@ public sealed class MindSystem : SharedMindSystem } TransferTo(mindId, null, createGhost: false, mind: mind); + DebugTools.AssertNull(mind.OwnedEntity); - if (component.GhostOnShutdown && mind.Session != null) + if (!component.GhostOnShutdown || mind.Session == null || _gameTicker.RunLevel == GameRunLevel.PreRoundLobby) + return; + + var xform = Transform(uid); + var gridId = xform.GridUid; + var spawnPosition = Transform(uid).Coordinates; + + // Use a regular timer here because the entity has probably been deleted. + Timer.Spawn(0, () => { - var xform = Transform(uid); - var gridId = xform.GridUid; - var spawnPosition = Transform(uid).Coordinates; + // Make extra sure the round didn't end between spawning the timer and it being executed. + if (_gameTicker.RunLevel == GameRunLevel.PreRoundLobby) + return; - // Use a regular timer here because the entity has probably been deleted. - Timer.Spawn(0, () => + // Async this so that we don't throw if the grid we're on is being deleted. + if (!HasComp(gridId)) + spawnPosition = _gameTicker.GetObserverSpawnPoint(); + + // TODO refactor observer spawning. + // please. + if (!spawnPosition.IsValid(EntityManager)) { - // Make extra sure the round didn't end between spawning the timer and it being executed. - if (_gameTicker.RunLevel == GameRunLevel.PreRoundLobby) - return; + // This should be an error, if it didn't cause tests to start erroring when they delete a player. + Log.Warning($"Entity \"{ToPrettyString(uid)}\" for {mind.CharacterName} was deleted, and no applicable spawn location is available."); + TransferTo(mindId, null, createGhost: false, mind: mind); + return; + } - // Async this so that we don't throw if the grid we're on is being deleted. - if (!_maps.GridExists(gridId)) - spawnPosition = _gameTicker.GetObserverSpawnPoint(); + var ghost = Spawn(GameTicker.ObserverPrototypeName, spawnPosition); + var ghostComponent = Comp(ghost); + _ghosts.SetCanReturnToBody(ghostComponent, false); - // TODO refactor observer spawning. - // please. - if (!spawnPosition.IsValid(EntityManager)) - { - // This should be an error, if it didn't cause tests to start erroring when they delete a player. - Log.Warning($"Entity \"{ToPrettyString(uid)}\" for {mind.CharacterName} was deleted, and no applicable spawn location is available."); - TransferTo(mindId, null, createGhost: false, mind: mind); - return; - } - - var ghost = Spawn("MobObserver", spawnPosition); - var ghostComponent = Comp(ghost); - _ghosts.SetCanReturnToBody(ghostComponent, false); - - // Log these to make sure they're not causing the GameTicker round restart bugs... - Log.Debug($"Entity \"{ToPrettyString(uid)}\" for {mind.CharacterName} was deleted, spawned \"{ToPrettyString(ghost)}\"."); - - var val = mind.CharacterName ?? string.Empty; - _metaData.SetEntityName(ghost, val); - TransferTo(mindId, ghost, mind: mind); - }); - } + // Log these to make sure they're not causing the GameTicker round restart bugs... + Log.Debug($"Entity \"{ToPrettyString(uid)}\" for {mind.CharacterName} was deleted, spawned \"{ToPrettyString(ghost)}\"."); + _metaData.SetEntityName(ghost, mind.CharacterName ?? string.Empty); + TransferTo(mindId, ghost, mind: mind); + }); } public override bool TryGetMind(NetUserId user, [NotNullWhen(true)] out EntityUid? mindId, [NotNullWhen(true)] out MindComponent? mind) @@ -130,18 +126,18 @@ public sealed class MindSystem : SharedMindSystem return false; } - public bool TryGetSession(EntityUid? mindId, [NotNullWhen(true)] out IPlayerSession? session) + public bool TryGetSession(EntityUid? mindId, [NotNullWhen(true)] out ICommonSession? session) { session = null; - return TryComp(mindId, out MindComponent? mind) && (session = (IPlayerSession?) mind.Session) != null; + return TryComp(mindId, out MindComponent? mind) && (session = mind.Session) != null; } - public IPlayerSession? GetSession(MindComponent mind) + public ICommonSession? GetSession(MindComponent mind) { - return (IPlayerSession?) mind.Session; + return mind.Session; } - public bool TryGetSession(MindComponent mind, [NotNullWhen(true)] out IPlayerSession? session) + public bool TryGetSession(MindComponent mind, [NotNullWhen(true)] out ICommonSession? session) { return (session = GetSession(mind)) != null; } @@ -179,7 +175,9 @@ public sealed class MindSystem : SharedMindSystem return; } - GetSession(mind)?.AttachToEntity(entity); + if (GetSession(mind) is { } session) + _actor.Attach(entity, session); + mind.VisitingEntity = entity; // EnsureComp instead of AddComp to deal with deferred deletions. @@ -198,13 +196,14 @@ public sealed class MindSystem : SharedMindSystem if (mind.VisitingEntity == null) return; - RemoveVisitingEntity(mind); + RemoveVisitingEntity(mindId, mind); if (mind.Session == null || mind.Session.AttachedEntity == mind.VisitingEntity) return; var owned = mind.OwnedEntity; - GetSession(mind)?.AttachToEntity(owned); + if (GetSession(mind) is { } session) + _actor.Attach(owned, session); if (owned.HasValue) { @@ -219,11 +218,10 @@ public sealed class MindSystem : SharedMindSystem if (mind == null && !Resolve(mindId, ref mind)) return; - base.TransferTo(mindId, entity, ghostCheckOverride, createGhost, mind); - if (entity == mind.OwnedEntity) return; + Dirty(mindId, mind); MindContainerComponent? component = null; var alreadyAttached = false; @@ -247,27 +245,33 @@ public sealed class MindSystem : SharedMindSystem } else if (createGhost) { + // TODO remove this option. + // Transfer-to-null should just detach a mind. + // If people want to create a ghost, that should be done explicitly via some TransferToGhost() method, not + // not implicitly via optional arguments. + var position = Deleted(mind.OwnedEntity) ? _gameTicker.GetObserverSpawnPoint().ToMap(EntityManager, _transform) : Transform(mind.OwnedEntity.Value).MapPosition; entity = Spawn("MobObserver", position); + component = EnsureComp(entity.Value); var ghostComponent = Comp(entity.Value); _ghosts.SetCanReturnToBody(ghostComponent, false); } - var oldComp = mind.OwnedComponent; var oldEntity = mind.OwnedEntity; - if (oldComp != null && oldEntity != null) + if (TryComp(oldEntity, out MindContainerComponent? oldContainer)) { - if (oldComp.Mind != null) - _pvsOverride.ClearOverride(oldComp.Mind.Value); - oldComp.Mind = null; - RaiseLocalEvent(oldEntity.Value, new MindRemovedMessage(oldEntity.Value, mind), true); + oldContainer.Mind = null; + mind.OwnedEntity = null; + Entity mindEnt = (mindId, mind); + Entity containerEnt = (oldEntity.Value, oldContainer); + RaiseLocalEvent(oldEntity.Value, new MindRemovedMessage(mindEnt, containerEnt)); + RaiseLocalEvent(mindId, new MindGotRemovedEvent(mindEnt, containerEnt)); + Dirty(oldEntity.Value, oldContainer); } - SetOwnedEntity(mind, entity, component); - // Don't do the full deletion cleanup if we're transferring to our VisitingEntity if (alreadyAttached) { @@ -281,7 +285,7 @@ public sealed class MindSystem : SharedMindSystem || !TryComp(mind.VisitingEntity!, out GhostComponent? ghostComponent) // visiting entity is not a Ghost || !ghostComponent.CanReturnToBody)) // it is a ghost, but cannot return to body anyway, so it's okay { - RemoveVisitingEntity(mind); + RemoveVisitingEntity(mindId, mind); } // Player is CURRENTLY connected. @@ -289,14 +293,20 @@ public sealed class MindSystem : SharedMindSystem if (session != null && !alreadyAttached && mind.VisitingEntity == null) { _actor.Attach(entity, session, true); + DebugTools.Assert(session.AttachedEntity == entity, $"Failed to attach entity."); Log.Info($"Session {session.Name} transferred to entity {entity}."); } - if (mind.OwnedComponent != null) + if (entity != null) { - mind.OwnedComponent.Mind = mindId; - RaiseLocalEvent(mind.OwnedEntity!.Value, new MindAddedMessage(), true); - mind.OriginalOwnedEntity ??= mind.OwnedEntity; + component!.Mind = mindId; + mind.OwnedEntity = entity; + mind.OriginalOwnedEntity ??= GetNetEntity(mind.OwnedEntity); + Entity mindEnt = (mindId, mind); + Entity containerEnt = (entity.Value, component); + RaiseLocalEvent(entity.Value, new MindAddedMessage(mindEnt, containerEnt)); + RaiseLocalEvent(mindId, new MindGotAddedEvent(mindEnt, containerEnt)); + Dirty(entity.Value, component); } } @@ -313,6 +323,7 @@ public sealed class MindSystem : SharedMindSystem if (mind.UserId == userId) return; + Dirty(mindId, mind); _pvsOverride.ClearOverride(mindId); if (userId != null && !_players.TryGetPlayerData(userId.Value, out _)) { @@ -363,4 +374,27 @@ public sealed class MindSystem : SharedMindSystem if (_players.GetPlayerData(userId.Value).ContentData() is { } data) data.Mind = mindId; } + + public void ControlMob(EntityUid user, EntityUid target) + { + if (TryComp(user, out ActorComponent? actor)) + ControlMob(actor.PlayerSession.UserId, target); + } + + public void ControlMob(NetUserId user, EntityUid target) + { + var (mindId, mind) = GetOrCreateMind(user); + + if (mind.CurrentEntity == target) + return; + + if (mind.OwnedEntity == target) + { + UnVisit(mindId, mind); + return; + } + + MakeSentientCommand.MakeSentient(target, EntityManager); + TransferTo(mindId, target, ghostCheckOverride: true, mind: mind); + } } diff --git a/Content.Server/Mind/Toolshed/MindCommand.cs b/Content.Server/Mind/Toolshed/MindCommand.cs index b53f9a6a9c..917e6fb7f1 100644 --- a/Content.Server/Mind/Toolshed/MindCommand.cs +++ b/Content.Server/Mind/Toolshed/MindCommand.cs @@ -1,5 +1,5 @@ using Content.Shared.Mind; -using Robust.Server.Player; +using Robust.Shared.Player; using Robust.Shared.Toolshed; using Robust.Shared.Toolshed.Errors; using Robust.Shared.Toolshed.Syntax; @@ -15,7 +15,7 @@ public sealed class MindCommand : ToolshedCommand private SharedMindSystem? _mind; [CommandImplementation("get")] - public MindComponent? Get([PipedArgument] IPlayerSession session) + public MindComponent? Get([PipedArgument] ICommonSession session) { _mind ??= GetSys(); return _mind.TryGetMind(session, out _, out var mind) ? mind : null; @@ -32,7 +32,7 @@ public sealed class MindCommand : ToolshedCommand public EntityUid Control( [CommandInvocationContext] IInvocationContext ctx, [PipedArgument] EntityUid target, - [CommandArgument] ValueRef playerRef) + [CommandArgument] ValueRef playerRef) { _mind ??= GetSys(); diff --git a/Content.Server/Motd/MOTDCommand.cs b/Content.Server/Motd/MOTDCommand.cs index a1aa4d2df5..9e59589b95 100644 --- a/Content.Server/Motd/MOTDCommand.cs +++ b/Content.Server/Motd/MOTDCommand.cs @@ -1,6 +1,5 @@ using Content.Server.Administration.Managers; using Content.Shared.Administration; -using Robust.Server.Player; using Robust.Shared.Console; namespace Content.Server.Motd; @@ -14,10 +13,10 @@ internal sealed class MOTDCommand : LocalizedCommands [Dependency] private readonly IAdminManager _adminManager = default!; public override string Command => "motd"; - + public override void Execute(IConsoleShell shell, string argStr, string[] args) { - var player = (IPlayerSession?)shell.Player; + var player = shell.Player; if (args.Length < 1 || (player != null && _adminManager is AdminManager aMan && !aMan.CanCommand(player, "set-motd"))) shell.ConsoleHost.ExecuteCommand(shell.Player, "get-motd"); else @@ -26,7 +25,7 @@ internal sealed class MOTDCommand : LocalizedCommands public override CompletionResult GetCompletion(IConsoleShell shell, string[] args) { - var player = (IPlayerSession?)shell.Player; + var player = shell.Player; if (player != null && _adminManager is AdminManager aMan && !aMan.CanCommand(player, "set-motd")) return CompletionResult.Empty; if (args.Length == 1) diff --git a/Content.Server/Motd/MOTDSystem.cs b/Content.Server/Motd/MOTDSystem.cs index e749fe48f3..39d780f108 100644 --- a/Content.Server/Motd/MOTDSystem.cs +++ b/Content.Server/Motd/MOTDSystem.cs @@ -2,9 +2,9 @@ using Content.Server.Chat.Managers; using Content.Server.GameTicking; using Content.Shared.CCVar; using Content.Shared.Chat; -using Robust.Server.Player; using Robust.Shared.Console; using Robust.Shared.Configuration; +using Robust.Shared.Player; namespace Content.Server.Motd; @@ -41,7 +41,7 @@ public sealed class MOTDSystem : EntitySystem { if (string.IsNullOrEmpty(_messageOfTheDay)) return; - + var wrappedMessage = Loc.GetString("motd-wrap-message", ("motd", _messageOfTheDay)); _chatManager.ChatMessageToAll(ChatChannel.Server, _messageOfTheDay, wrappedMessage, source: EntityUid.Invalid, hideChat: false, recordReplay: true); } @@ -49,11 +49,11 @@ public sealed class MOTDSystem : EntitySystem /// /// Sends the Message Of The Day, if any, to a specific player. /// - public void TrySendMOTD(IPlayerSession player) + public void TrySendMOTD(ICommonSession player) { if (string.IsNullOrEmpty(_messageOfTheDay)) return; - + var wrappedMessage = Loc.GetString("motd-wrap-message", ("motd", _messageOfTheDay)); _chatManager.ChatMessageToOne(ChatChannel.Server, _messageOfTheDay, wrappedMessage, source: EntityUid.Invalid, hideChat: false, client: player.ConnectedClient); } @@ -68,10 +68,10 @@ public sealed class MOTDSystem : EntitySystem { if (string.IsNullOrEmpty(_messageOfTheDay)) return; - + var wrappedMessage = Loc.GetString("motd-wrap-message", ("motd", _messageOfTheDay)); shell.WriteLine(wrappedMessage); - if (shell.Player is IPlayerSession player) + if (shell.Player is { } player) _chatManager.ChatMessageToOne(ChatChannel.Server, _messageOfTheDay, wrappedMessage, source: EntityUid.Invalid, hideChat: false, client: player.ConnectedClient); } @@ -92,7 +92,7 @@ public sealed class MOTDSystem : EntitySystem { if (val == _messageOfTheDay) return; - + _messageOfTheDay = val; TrySendMOTD(); } diff --git a/Content.Server/Motd/SetMOTDCommand.cs b/Content.Server/Motd/SetMOTDCommand.cs index f3f52b0670..9678781c87 100644 --- a/Content.Server/Motd/SetMOTDCommand.cs +++ b/Content.Server/Motd/SetMOTDCommand.cs @@ -4,7 +4,6 @@ using Content.Shared.Administration; using Content.Shared.Database; using Content.Shared.CCVar; using Content.Server.Chat.Managers; -using Robust.Server.Player; using Robust.Shared.Configuration; using Robust.Shared.Console; @@ -21,18 +20,18 @@ public sealed class SetMotdCommand : LocalizedCommands [Dependency] private readonly IConfigurationManager _configurationManager = default!; public override string Command => "set-motd"; - + public override void Execute(IConsoleShell shell, string argStr, string[] args) { string motd = ""; - var player = (IPlayerSession?)shell.Player; + var player = shell.Player; if (args.Length > 0) { motd = string.Join(" ", args).Trim(); if (player != null && _chatManager.MessageCharacterLimit(player, motd)) return; // check function prints its own error response } - + _configurationManager.SetCVar(CCVars.MOTD, motd); // A hook in MOTDSystem broadcasts changes to the MOTD to everyone so we don't need to do it here. if (string.IsNullOrEmpty(motd)) { diff --git a/Content.Server/Movement/Systems/LagCompensationSystem.cs b/Content.Server/Movement/Systems/LagCompensationSystem.cs index 64965c2fee..0576fe8f25 100644 --- a/Content.Server/Movement/Systems/LagCompensationSystem.cs +++ b/Content.Server/Movement/Systems/LagCompensationSystem.cs @@ -1,7 +1,7 @@ using Content.Server.Movement.Components; using Robust.Server.Player; using Robust.Shared.Map; -using Robust.Shared.Players; +using Robust.Shared.Player; using Robust.Shared.Timing; namespace Content.Server.Movement.Systems; diff --git a/Content.Server/NPC/Commands/NPCCommand.cs b/Content.Server/NPC/Commands/NPCCommand.cs index 57fe223b66..7f9e56b8ca 100644 --- a/Content.Server/NPC/Commands/NPCCommand.cs +++ b/Content.Server/NPC/Commands/NPCCommand.cs @@ -2,7 +2,6 @@ using Content.Server.Administration; using Content.Server.EUI; using Content.Server.NPC.UI; using Content.Shared.Administration; -using Robust.Server.Player; using Robust.Shared.Console; namespace Content.Server.NPC.Commands; @@ -15,7 +14,7 @@ public sealed class NPCCommand : IConsoleCommand public string Help => $"{Command}"; public void Execute(IConsoleShell shell, string argStr, string[] args) { - if (shell.Player is not IPlayerSession playerSession) + if (shell.Player is not { } playerSession) { return; } diff --git a/Content.Server/NPC/HTN/HTNSystem.cs b/Content.Server/NPC/HTN/HTNSystem.cs index 2c1dadb127..a7689fbabe 100644 --- a/Content.Server/NPC/HTN/HTNSystem.cs +++ b/Content.Server/NPC/HTN/HTNSystem.cs @@ -4,17 +4,14 @@ using System.Threading; using Content.Server.Administration.Managers; using Robust.Shared.CPUJob.JobQueues; using Robust.Shared.CPUJob.JobQueues.Queues; -using Content.Server.NPC.Components; using Content.Server.NPC.HTN.PrimitiveTasks; using Content.Server.NPC.Systems; using Content.Shared.Administration; using Content.Shared.Mobs; using Content.Shared.NPC; -using Content.Shared.NPC; using JetBrains.Annotations; using Robust.Server.GameObjects; -using Robust.Server.Player; -using Robust.Shared.Players; +using Robust.Shared.Player; using Robust.Shared.Prototypes; using Robust.Shared.Utility; @@ -48,7 +45,7 @@ public sealed class HTNSystem : EntitySystem private void OnHTNMessage(RequestHTNMessage msg, EntitySessionEventArgs args) { - if (!_admin.HasAdminFlag((IPlayerSession) args.SenderSession, AdminFlags.Debug)) + if (!_admin.HasAdminFlag(args.SenderSession, AdminFlags.Debug)) { _subscribers.Remove(args.SenderSession); return; diff --git a/Content.Server/NPC/Pathfinding/PathfindingSystem.cs b/Content.Server/NPC/Pathfinding/PathfindingSystem.cs index bb0eff7b39..1b1f6f5476 100644 --- a/Content.Server/NPC/Pathfinding/PathfindingSystem.cs +++ b/Content.Server/NPC/Pathfinding/PathfindingSystem.cs @@ -13,7 +13,7 @@ using Robust.Shared.Enums; using Robust.Shared.Map; using Robust.Shared.Physics; using Robust.Shared.Physics.Systems; -using Robust.Shared.Players; +using Robust.Shared.Player; using Robust.Shared.Random; using Robust.Shared.Threading; using Robust.Shared.Timing; @@ -528,7 +528,7 @@ namespace Content.Server.NPC.Pathfinding private void OnBreadcrumbs(RequestPathfindingDebugMessage msg, EntitySessionEventArgs args) { - var pSession = (IPlayerSession) args.SenderSession; + var pSession = args.SenderSession; if (!_adminManager.HasAdminFlag(pSession, AdminFlags.Debug)) { diff --git a/Content.Server/NPC/Systems/NPCSteeringSystem.cs b/Content.Server/NPC/Systems/NPCSteeringSystem.cs index 61b43df6f0..e5b62acfe8 100644 --- a/Content.Server/NPC/Systems/NPCSteeringSystem.cs +++ b/Content.Server/NPC/Systems/NPCSteeringSystem.cs @@ -17,14 +17,12 @@ using Content.Shared.NPC; using Content.Shared.NPC.Events; using Content.Shared.Physics; using Content.Shared.Weapons.Melee; -using Robust.Server.Player; using Robust.Shared.Configuration; using Robust.Shared.Map; using Robust.Shared.Physics; using Robust.Shared.Physics.Components; using Robust.Shared.Physics.Systems; using Robust.Shared.Player; -using Robust.Shared.Players; using Robust.Shared.Random; using Robust.Shared.Timing; using Robust.Shared.Utility; @@ -147,7 +145,7 @@ public sealed partial class NPCSteeringSystem : SharedNPCSteeringSystem private void OnDebugRequest(RequestNPCSteeringDebugEvent msg, EntitySessionEventArgs args) { - if (!_admin.IsAdmin((IPlayerSession)args.SenderSession)) + if (!_admin.IsAdmin(args.SenderSession)) return; if (msg.Enabled) diff --git a/Content.Server/Ninja/Systems/SpiderChargeSystem.cs b/Content.Server/Ninja/Systems/SpiderChargeSystem.cs index 6f3c3b3f9d..0182bd7ca7 100644 --- a/Content.Server/Ninja/Systems/SpiderChargeSystem.cs +++ b/Content.Server/Ninja/Systems/SpiderChargeSystem.cs @@ -23,7 +23,7 @@ public sealed class SpiderChargeSystem : EntitySystem { base.Initialize(); - SubscribeLocalEvent(BeforePlant); + SubscribeLocalEvent(OnAttemptStick); SubscribeLocalEvent(OnStuck); SubscribeLocalEvent(OnExplode); } @@ -31,14 +31,17 @@ public sealed class SpiderChargeSystem : EntitySystem /// /// Require that the planter is a ninja and the charge is near the target warp point. /// - private void BeforePlant(EntityUid uid, SpiderChargeComponent comp, BeforeRangedInteractEvent args) + private void OnAttemptStick(EntityUid uid, SpiderChargeComponent comp, AttemptEntityStickEvent args) { + if (args.Cancelled) + return; + var user = args.User; if (!_mind.TryGetRole(user, out var role)) { _popup.PopupEntity(Loc.GetString("spider-charge-not-ninja"), user, user); - args.Handled = true; + args.Cancelled = true; return; } @@ -47,12 +50,14 @@ public sealed class SpiderChargeSystem : EntitySystem return; // assumes warp point still exists - var target = Transform(role.SpiderChargeTarget.Value).MapPosition; - var coords = args.ClickLocation.ToMap(EntityManager, _transform); - if (!coords.InRange(target, comp.Range)) + var targetXform = Transform(role.SpiderChargeTarget.Value); + var locXform = Transform(args.Target); + if (locXform.MapID != targetXform.MapID || + (_transform.GetWorldPosition(locXform) - _transform.GetWorldPosition(targetXform)).LengthSquared() > comp.Range * comp.Range) { _popup.PopupEntity(Loc.GetString("spider-charge-too-far"), user, user); - args.Handled = true; + args.Cancelled = true; + return; } } diff --git a/Content.Server/NodeContainer/EntitySystems/NodeGroupSystem.cs b/Content.Server/NodeContainer/EntitySystems/NodeGroupSystem.cs index e4bd303150..9ee9702c5b 100644 --- a/Content.Server/NodeContainer/EntitySystems/NodeGroupSystem.cs +++ b/Content.Server/NodeContainer/EntitySystems/NodeGroupSystem.cs @@ -9,6 +9,7 @@ using JetBrains.Annotations; using Robust.Server.Player; using Robust.Shared.Enums; using Robust.Shared.Map; +using Robust.Shared.Player; using Robust.Shared.Utility; namespace Content.Server.NodeContainer.EntitySystems @@ -29,7 +30,7 @@ namespace Content.Server.NodeContainer.EntitySystems private readonly List _visDeletes = new(); private readonly List _visSends = new(); - private readonly HashSet _visPlayers = new(); + private readonly HashSet _visPlayers = new(); private readonly HashSet _toRemake = new(); private readonly HashSet _nodeGroups = new(); private readonly HashSet _toRemove = new(); @@ -74,7 +75,7 @@ namespace Content.Server.NodeContainer.EntitySystems private void HandleEnableMsg(NodeVis.MsgEnable msg, EntitySessionEventArgs args) { - var session = (IPlayerSession) args.SenderSession; + var session = args.SenderSession; if (!_adminManager.HasAdminFlag(session, AdminFlags.Debug)) return; @@ -397,7 +398,7 @@ namespace Content.Server.NodeContainer.EntitySystems } } - private void VisSendFullStateImmediate(IPlayerSession player) + private void VisSendFullStateImmediate(ICommonSession player) { var msg = new NodeVis.MsgData(); diff --git a/Content.Server/Nutrition/EntitySystems/FoodSystem.cs b/Content.Server/Nutrition/EntitySystems/FoodSystem.cs index 8406ce222d..ff4ec41dd9 100644 --- a/Content.Server/Nutrition/EntitySystems/FoodSystem.cs +++ b/Content.Server/Nutrition/EntitySystems/FoodSystem.cs @@ -17,6 +17,7 @@ using Content.Shared.Hands.Components; using Content.Shared.Hands.EntitySystems; using Content.Shared.IdentityManagement; using Content.Shared.Interaction; +using Content.Shared.Interaction.Components; using Content.Shared.Interaction.Events; using Content.Shared.Inventory; using Content.Shared.Mobs.Systems; @@ -101,6 +102,9 @@ public sealed class FoodSystem : EntitySystem if (!TryComp(target, out var body)) return (false, false); + if (HasComp(food)) + return (false, false); + if (_openable.IsClosed(food, user)) return (false, true); diff --git a/Content.Server/Nutrition/Hungry.cs b/Content.Server/Nutrition/Hungry.cs index c27f302a8d..ae68dcd2fd 100644 --- a/Content.Server/Nutrition/Hungry.cs +++ b/Content.Server/Nutrition/Hungry.cs @@ -1,9 +1,7 @@ using Content.Server.Administration; -using Content.Server.Nutrition.Components; using Content.Shared.Administration; using Content.Shared.Nutrition.Components; using Content.Shared.Nutrition.EntitySystems; -using Robust.Server.Player; using Robust.Shared.Console; namespace Content.Server.Nutrition @@ -19,7 +17,7 @@ namespace Content.Server.Nutrition public void Execute(IConsoleShell shell, string argStr, string[] args) { - var player = shell.Player as IPlayerSession; + var player = shell.Player; if (player == null) { shell.WriteLine("You cannot use this command unless you are a player."); diff --git a/Content.Server/Objectives/Commands/ListObjectivesCommand.cs b/Content.Server/Objectives/Commands/ListObjectivesCommand.cs index 93dec3fa44..97fc943269 100644 --- a/Content.Server/Objectives/Commands/ListObjectivesCommand.cs +++ b/Content.Server/Objectives/Commands/ListObjectivesCommand.cs @@ -18,7 +18,7 @@ namespace Content.Server.Objectives.Commands public override void Execute(IConsoleShell shell, string argStr, string[] args) { - var player = shell.Player as IPlayerSession; + var player = shell.Player; if (player == null || !_players.TryGetSessionByUsername(args[0], out player)) { shell.WriteError(LocalizationManager.GetString("shell-target-player-does-not-exist")); diff --git a/Content.Server/Objectives/Components/HijackShuttleConditionComponent.cs b/Content.Server/Objectives/Components/HijackShuttleConditionComponent.cs new file mode 100644 index 0000000000..2f07086af6 --- /dev/null +++ b/Content.Server/Objectives/Components/HijackShuttleConditionComponent.cs @@ -0,0 +1,11 @@ +using Content.Server.Objectives.Systems; + +namespace Content.Server.Objectives.Components; + +/// +/// Objective condition that requires the player to leave station of escape shuttle with only antags on board or handcuffed humanoids +/// +[RegisterComponent, Access(typeof(HijackShuttleConditionSystem))] +public sealed partial class HijackShuttleConditionComponent : Component +{ +} diff --git a/Content.Server/Corvax/Objectives/Systems/HijackShuttleConditionSystem.cs b/Content.Server/Objectives/Systems/HijackShuttleConditionSystem.cs similarity index 95% rename from Content.Server/Corvax/Objectives/Systems/HijackShuttleConditionSystem.cs rename to Content.Server/Objectives/Systems/HijackShuttleConditionSystem.cs index 9e4d2e476c..9e0d2c3d5b 100644 --- a/Content.Server/Corvax/Objectives/Systems/HijackShuttleConditionSystem.cs +++ b/Content.Server/Objectives/Systems/HijackShuttleConditionSystem.cs @@ -1,4 +1,4 @@ -using Content.Server.Corvax.Objectives.Components; +using Content.Server.Objectives.Components; using Content.Server.Shuttles.Components; using Content.Server.Shuttles.Systems; using Content.Shared.Cuffs.Components; @@ -10,7 +10,7 @@ using Content.Shared.Objectives.Components; using Content.Shared.Roles; using Robust.Shared.Player; -namespace Content.Server.Corvax.Objectives.Systems; +namespace Content.Server.Objectives.Systems; public sealed class HijackShuttleConditionSystem : EntitySystem { @@ -33,7 +33,7 @@ public sealed class HijackShuttleConditionSystem : EntitySystem private float GetProgress(EntityUid mindId, MindComponent mind) { - // not escaping alive if you're deleted/dead + // Not escaping alive if you're deleted/dead if (mind.OwnedEntity == null || _mind.IsCharacterDeadIc(mind)) return 0f; diff --git a/Content.Server/PDA/PdaSystem.cs b/Content.Server/PDA/PdaSystem.cs index 6c506dc3dd..44e2659841 100644 --- a/Content.Server/PDA/PdaSystem.cs +++ b/Content.Server/PDA/PdaSystem.cs @@ -4,9 +4,6 @@ using Content.Server.DeviceNetwork.Components; using Content.Server.Instruments; using Content.Server.Light.EntitySystems; using Content.Server.Light.Events; -using Content.Server.MassMedia.Components; -using Content.Server.MassMedia.Systems; -using Content.Server.Mind; using Content.Server.PDA.Ringer; using Content.Server.Station.Systems; using Content.Server.Store.Components; @@ -16,7 +13,6 @@ using Content.Shared.CartridgeLoader; using Content.Shared.Light.Components; using Content.Shared.PDA; using Robust.Server.GameObjects; -using Robust.Server.Player; using Robust.Shared.Containers; namespace Content.Server.PDA @@ -180,7 +176,7 @@ namespace Content.Server.PDA return; if (HasComp(uid)) - _ringer.ToggleRingerUI(uid, (IPlayerSession) msg.Session); + _ringer.ToggleRingerUI(uid, msg.Session); } private void OnUiMessage(EntityUid uid, PdaComponent pda, PdaShowMusicMessage msg) @@ -189,7 +185,7 @@ namespace Content.Server.PDA return; if (TryComp(uid, out var instrument)) - _instrument.ToggleInstrumentUi(uid, (IPlayerSession) msg.Session, instrument); + _instrument.ToggleInstrumentUi(uid, msg.Session, instrument); } private void OnUiMessage(EntityUid uid, PdaComponent pda, PdaShowUplinkMessage msg) diff --git a/Content.Server/PDA/Ringer/RingerSystem.cs b/Content.Server/PDA/Ringer/RingerSystem.cs index a772e76bc4..7494d5e12c 100644 --- a/Content.Server/PDA/Ringer/RingerSystem.cs +++ b/Content.Server/PDA/Ringer/RingerSystem.cs @@ -7,7 +7,6 @@ using Content.Shared.PDA.Ringer; using Content.Shared.Popups; using Content.Shared.Store; using Robust.Server.GameObjects; -using Robust.Server.Player; using Robust.Shared.Audio; using Robust.Shared.Network; using Robust.Shared.Player; @@ -182,7 +181,7 @@ namespace Content.Server.PDA.Ringer _ui.SetUiState(bui, new RingerUpdateState(isPlaying, ringer.Ringtone)); } - public bool ToggleRingerUI(EntityUid uid, IPlayerSession session) + public bool ToggleRingerUI(EntityUid uid, ICommonSession session) { if (_ui.TryGetUi(uid, RingerUiKey.Key, out var bui)) _ui.ToggleUi(bui, session); diff --git a/Content.Server/Paper/PaperSystem.cs b/Content.Server/Paper/PaperSystem.cs index f38013e14d..553bcaa0a2 100644 --- a/Content.Server/Paper/PaperSystem.cs +++ b/Content.Server/Paper/PaperSystem.cs @@ -4,15 +4,11 @@ using Content.Server.Popups; using Content.Server.UserInterface; using Content.Shared.Database; using Content.Shared.Examine; -using Content.Shared.IdentityManagement; using Content.Shared.Interaction; using Content.Shared.Paper; using Content.Shared.Tag; using Robust.Server.GameObjects; -using Robust.Server.Player; using Robust.Shared.Player; -using Robust.Shared.Utility; -using Robust.Shared.Audio; using static Content.Shared.Paper.SharedPaperComponent; namespace Content.Server.Paper @@ -207,7 +203,7 @@ namespace Content.Server.Paper _appearance.SetData(uid, PaperVisuals.Status, status, appearance); } - public void UpdateUserInterface(EntityUid uid, PaperComponent? paperComp = null, IPlayerSession? session = null) + public void UpdateUserInterface(EntityUid uid, PaperComponent? paperComp = null, ICommonSession? session = null) { if (!Resolve(uid, ref paperComp)) return; diff --git a/Content.Server/Parallax/BiomeSystem.cs b/Content.Server/Parallax/BiomeSystem.cs index a9d78afa86..c9017ac821 100644 --- a/Content.Server/Parallax/BiomeSystem.cs +++ b/Content.Server/Parallax/BiomeSystem.cs @@ -282,9 +282,8 @@ public sealed partial class BiomeSystem : SharedBiomeSystem } // Get chunks in range - foreach (var client in Filter.GetAllPlayers(_playerManager)) + foreach (var pSession in Filter.GetAllPlayers(_playerManager)) { - var pSession = (IPlayerSession) client; if (xformQuery.TryGetComponent(pSession.AttachedEntity, out var xform) && _handledEntities.Add(pSession.AttachedEntity.Value) && diff --git a/Content.Server/ParticleAccelerator/EntitySystems/ParticleAcceleratorSystem.ControlBox.cs b/Content.Server/ParticleAccelerator/EntitySystems/ParticleAcceleratorSystem.ControlBox.cs index 20ed276967..f200c991d7 100644 --- a/Content.Server/ParticleAccelerator/EntitySystems/ParticleAcceleratorSystem.ControlBox.cs +++ b/Content.Server/ParticleAccelerator/EntitySystems/ParticleAcceleratorSystem.ControlBox.cs @@ -2,11 +2,10 @@ using Content.Server.ParticleAccelerator.Components; using Content.Server.Power.Components; using Content.Shared.Database; using Content.Shared.Singularity.Components; -using Robust.Server.Player; -using Robust.Server.GameObjects; using Robust.Shared.Utility; using System.Diagnostics; using Content.Shared.CCVar; +using Robust.Shared.Player; namespace Content.Server.ParticleAccelerator.EntitySystems; @@ -60,7 +59,7 @@ public sealed partial class ParticleAcceleratorSystem FireEmitter(comp.StarboardEmitter!.Value, strength); } - public void SwitchOn(EntityUid uid, IPlayerSession? user = null, ParticleAcceleratorControlBoxComponent? comp = null) + public void SwitchOn(EntityUid uid, ICommonSession? user = null, ParticleAcceleratorControlBoxComponent? comp = null) { if (!Resolve(uid, ref comp)) return; @@ -83,7 +82,7 @@ public sealed partial class ParticleAcceleratorSystem UpdateUI(uid, comp); } - public void SwitchOff(EntityUid uid, IPlayerSession? user = null, ParticleAcceleratorControlBoxComponent? comp = null) + public void SwitchOff(EntityUid uid, ICommonSession? user = null, ParticleAcceleratorControlBoxComponent? comp = null) { if (!Resolve(uid, ref comp)) return; @@ -131,7 +130,7 @@ public sealed partial class ParticleAcceleratorSystem UpdateUI(uid, comp); } - public void SetStrength(EntityUid uid, ParticleAcceleratorPowerState strength, IPlayerSession? user = null, ParticleAcceleratorControlBoxComponent? comp = null) + public void SetStrength(EntityUid uid, ParticleAcceleratorPowerState strength, ICommonSession? user = null, ParticleAcceleratorControlBoxComponent? comp = null) { if (!Resolve(uid, ref comp)) return; @@ -347,10 +346,10 @@ public sealed partial class ParticleAcceleratorSystem if (msg.Enabled) { if (comp.Assembled) - SwitchOn(uid, (IPlayerSession?) msg.Session, comp); + SwitchOn(uid, msg.Session, comp); } else - SwitchOff(uid, (IPlayerSession?) msg.Session, comp); + SwitchOff(uid, msg.Session, comp); UpdateUI(uid, comp); } @@ -364,7 +363,7 @@ public sealed partial class ParticleAcceleratorSystem if (TryComp(uid, out var apcPower) && !apcPower.Powered) return; - SetStrength(uid, msg.State, (IPlayerSession?) msg.Session, comp); + SetStrength(uid, msg.State, msg.Session, comp); UpdateUI(uid, comp); } @@ -378,7 +377,7 @@ public sealed partial class ParticleAcceleratorSystem if (TryComp(uid, out var apcPower) && !apcPower.Powered) return; - RescanParts(uid, (IPlayerSession?) msg.Session, comp); + RescanParts(uid, msg.Session, comp); UpdateUI(uid, comp); } diff --git a/Content.Server/ParticleAccelerator/EntitySystems/ParticleAcceleratorSystem.Parts.cs b/Content.Server/ParticleAccelerator/EntitySystems/ParticleAcceleratorSystem.Parts.cs index 271d17a0c4..abc68543ff 100644 --- a/Content.Server/ParticleAccelerator/EntitySystems/ParticleAcceleratorSystem.Parts.cs +++ b/Content.Server/ParticleAccelerator/EntitySystems/ParticleAcceleratorSystem.Parts.cs @@ -2,9 +2,9 @@ using System.Diagnostics.CodeAnalysis; using System.Numerics; using Content.Server.ParticleAccelerator.Components; using JetBrains.Annotations; -using Robust.Server.Player; using Robust.Shared.Map.Components; using Robust.Shared.Physics.Events; +using Robust.Shared.Player; namespace Content.Server.ParticleAccelerator.EntitySystems; @@ -18,7 +18,7 @@ public sealed partial class ParticleAcceleratorSystem SubscribeLocalEvent(BodyTypeChanged); } - public void RescanParts(EntityUid uid, IPlayerSession? user = null, ParticleAcceleratorControlBoxComponent? controller = null) + public void RescanParts(EntityUid uid, ICommonSession? user = null, ParticleAcceleratorControlBoxComponent? controller = null) { if (!Resolve(uid, ref controller)) return; diff --git a/Content.Server/Pinpointer/ProximityBeeperSystem.cs b/Content.Server/Pinpointer/ProximityBeeperSystem.cs index b473d97372..d52223e2b4 100644 --- a/Content.Server/Pinpointer/ProximityBeeperSystem.cs +++ b/Content.Server/Pinpointer/ProximityBeeperSystem.cs @@ -80,7 +80,10 @@ public sealed class ProximityBeeperSystem : EntitySystem var scalingFactor = distance / component.MaximumDistance; var interval = (component.MaxBeepInterval - component.MinBeepInterval) * scalingFactor + component.MinBeepInterval; + component.NextBeepTime += interval; + if (component.NextBeepTime < _timing.CurTime) // Prevents spending time out of range accumulating a deficit which causes a series of very rapid beeps when comeing into range. + component.NextBeepTime = _timing.CurTime + interval; } /// diff --git a/Content.Server/Players/PlayTimeTracking/PlayTimeTrackingManager.cs b/Content.Server/Players/PlayTimeTracking/PlayTimeTrackingManager.cs index 50c64e718c..bcc6f211ed 100644 --- a/Content.Server/Players/PlayTimeTracking/PlayTimeTrackingManager.cs +++ b/Content.Server/Players/PlayTimeTracking/PlayTimeTrackingManager.cs @@ -5,18 +5,18 @@ using System.Threading.Tasks; using Content.Server.Database; using Content.Shared.CCVar; using Content.Shared.Players.PlayTimeTracking; -using Robust.Server.Player; using Robust.Shared.Asynchronous; using Robust.Shared.Collections; using Robust.Shared.Configuration; using Robust.Shared.Exceptions; using Robust.Shared.Network; +using Robust.Shared.Player; using Robust.Shared.Timing; using Robust.Shared.Utility; namespace Content.Server.Players.PlayTimeTracking; -public delegate void CalcPlayTimeTrackersCallback(IPlayerSession player, HashSet trackers); +public delegate void CalcPlayTimeTrackersCallback(ICommonSession player, HashSet trackers); /// /// Tracks play time for players, across all roles. @@ -66,7 +66,7 @@ public sealed class PlayTimeTrackingManager private ISawmill _sawmill = default!; // List of players that need some kind of update (refresh timers or resend). - private ValueList _playersDirty; + private ValueList _playersDirty; // DB auto-saving logic. private TimeSpan _saveInterval; @@ -76,7 +76,7 @@ public sealed class PlayTimeTrackingManager // We must block server shutdown on these to avoid losing data. private readonly List _pendingSaveTasks = new(); - private readonly Dictionary _playTimeData = new(); + private readonly Dictionary _playTimeData = new(); public event CalcPlayTimeTrackersCallback? CalcTrackers; @@ -139,7 +139,7 @@ public sealed class PlayTimeTrackingManager _playersDirty.Clear(); } - private void RefreshSingleTracker(IPlayerSession dirty, PlayTimeData data, TimeSpan time) + private void RefreshSingleTracker(ICommonSession dirty, PlayTimeData data, TimeSpan time) { DebugTools.Assert(data.Initialized); @@ -181,7 +181,7 @@ public sealed class PlayTimeTrackingManager /// so APIs like return up-to-date info. /// /// - public void FlushTracker(IPlayerSession player) + public void FlushTracker(ICommonSession player) { var time = _timing.RealTime; var data = _playTimeData[player]; @@ -201,7 +201,7 @@ public sealed class PlayTimeTrackingManager } } - private void SendPlayTimes(IPlayerSession pSession) + private void SendPlayTimes(ICommonSession pSession) { var roles = GetTrackerTimes(pSession); @@ -228,7 +228,7 @@ public sealed class PlayTimeTrackingManager /// /// Save all modified time trackers for a player to the database. /// - public async void SaveSession(IPlayerSession session) + public async void SaveSession(ICommonSession session) { // This causes all trackers to refresh, ah well. FlushAllTrackers(); @@ -278,7 +278,7 @@ public sealed class PlayTimeTrackingManager _sawmill.Debug($"Saved {log.Count} trackers"); } - private async Task DoSaveSessionAsync(IPlayerSession session) + private async Task DoSaveSessionAsync(ICommonSession session) { var log = new List(); @@ -299,7 +299,7 @@ public sealed class PlayTimeTrackingManager _sawmill.Debug($"Saved {log.Count} trackers for {session.Name}"); } - public async Task LoadData(IPlayerSession session, CancellationToken cancel) + public async Task LoadData(ICommonSession session, CancellationToken cancel) { var data = new PlayTimeData(); _playTimeData.Add(session, data); @@ -318,14 +318,14 @@ public sealed class PlayTimeTrackingManager QueueSendTimers(session); } - public void ClientDisconnected(IPlayerSession session) + public void ClientDisconnected(ICommonSession session) { SaveSession(session); _playTimeData.Remove(session); } - public void AddTimeToTracker(IPlayerSession id, string tracker, TimeSpan time) + public void AddTimeToTracker(ICommonSession id, string tracker, TimeSpan time) { if (!_playTimeData.TryGetValue(id, out var data) || !data.Initialized) throw new InvalidOperationException("Play time info is not yet loaded for this player!"); @@ -341,17 +341,17 @@ public sealed class PlayTimeTrackingManager data.DbTrackersDirty.Add(tracker); } - public void AddTimeToOverallPlaytime(IPlayerSession id, TimeSpan time) + public void AddTimeToOverallPlaytime(ICommonSession id, TimeSpan time) { AddTimeToTracker(id, PlayTimeTrackingShared.TrackerOverall, time); } - public TimeSpan GetOverallPlaytime(IPlayerSession id) + public TimeSpan GetOverallPlaytime(ICommonSession id) { return GetPlayTimeForTracker(id, PlayTimeTrackingShared.TrackerOverall); } - public bool TryGetTrackerTimes(IPlayerSession id, [NotNullWhen(true)] out Dictionary? time) + public bool TryGetTrackerTimes(ICommonSession id, [NotNullWhen(true)] out Dictionary? time) { time = null; @@ -364,7 +364,7 @@ public sealed class PlayTimeTrackingManager return true; } - public Dictionary GetTrackerTimes(IPlayerSession id) + public Dictionary GetTrackerTimes(ICommonSession id) { if (!_playTimeData.TryGetValue(id, out var data) || !data.Initialized) throw new InvalidOperationException("Play time info is not yet loaded for this player!"); @@ -372,7 +372,7 @@ public sealed class PlayTimeTrackingManager return data.TrackerTimes; } - public TimeSpan GetPlayTimeForTracker(IPlayerSession id, string tracker) + public TimeSpan GetPlayTimeForTracker(ICommonSession id, string tracker) { if (!_playTimeData.TryGetValue(id, out var data) || !data.Initialized) throw new InvalidOperationException("Play time info is not yet loaded for this player!"); @@ -383,7 +383,7 @@ public sealed class PlayTimeTrackingManager /// /// Queue for play time trackers to be refreshed on a player, in case the set of active trackers may have changed. /// - public void QueueRefreshTrackers(IPlayerSession player) + public void QueueRefreshTrackers(ICommonSession player) { if (DirtyPlayer(player) is { } data) data.NeedRefreshTackers = true; @@ -392,13 +392,13 @@ public sealed class PlayTimeTrackingManager /// /// Queue for play time information to be sent to a client, for showing in UIs etc. /// - public void QueueSendTimers(IPlayerSession player) + public void QueueSendTimers(ICommonSession player) { if (DirtyPlayer(player) is { } data) data.NeedSendTimers = true; } - private PlayTimeData? DirtyPlayer(IPlayerSession player) + private PlayTimeData? DirtyPlayer(ICommonSession player) { if (!_playTimeData.TryGetValue(player, out var data) || !data.Initialized) return null; diff --git a/Content.Server/Players/PlayTimeTracking/PlayTimeTrackingSystem.cs b/Content.Server/Players/PlayTimeTracking/PlayTimeTrackingSystem.cs index 13d0794dd5..f865b25bac 100644 --- a/Content.Server/Players/PlayTimeTracking/PlayTimeTrackingSystem.cs +++ b/Content.Server/Players/PlayTimeTracking/PlayTimeTrackingSystem.cs @@ -14,6 +14,7 @@ using Robust.Server.GameObjects; using Robust.Server.Player; using Robust.Shared.Configuration; using Robust.Shared.Network; +using Robust.Shared.Player; using Robust.Shared.Prototypes; using Robust.Shared.Utility; @@ -55,7 +56,7 @@ public sealed class PlayTimeTrackingSystem : EntitySystem _tracking.CalcTrackers -= CalcTrackers; } - private void CalcTrackers(IPlayerSession player, HashSet trackers) + private void CalcTrackers(ICommonSession player, HashSet trackers) { if (_afk.IsAfk(player)) return; @@ -67,7 +68,7 @@ public sealed class PlayTimeTrackingSystem : EntitySystem trackers.UnionWith(GetTimedRoles(player)); } - private bool IsPlayerAlive(IPlayerSession session) + private bool IsPlayerAlive(ICommonSession session) { var attached = session.AttachedEntity; if (attached == null) @@ -93,7 +94,7 @@ public sealed class PlayTimeTrackingSystem : EntitySystem } } - private IEnumerable GetTimedRoles(IPlayerSession session) + private IEnumerable GetTimedRoles(ICommonSession session) { var contentData = _playerManager.GetPlayerData(session.UserId).ContentData(); @@ -156,7 +157,7 @@ public sealed class PlayTimeTrackingSystem : EntitySystem _tracking.QueueSendTimers(ev.PlayerSession); } - public bool IsAllowed(IPlayerSession player, string role) + public bool IsAllowed(ICommonSession player, string role) { if (!_prototypes.TryIndex(role, out var job) || job.Requirements == null || @@ -168,7 +169,7 @@ public sealed class PlayTimeTrackingSystem : EntitySystem return JobRequirements.TryRequirementsMet(job, playTimes, out _, EntityManager, _prototypes); } - public HashSet GetDisallowedJobs(IPlayerSession player) + public HashSet GetDisallowedJobs(ICommonSession player) { var roles = new HashSet(); if (!_cfg.GetCVar(CCVars.GameRoleTimers)) @@ -230,7 +231,7 @@ public sealed class PlayTimeTrackingSystem : EntitySystem } } - public void PlayerRolesChanged(IPlayerSession player) + public void PlayerRolesChanged(ICommonSession player) { _tracking.QueueRefreshTrackers(player); } diff --git a/Content.Server/Players/PlayerData.cs b/Content.Server/Players/PlayerData.cs deleted file mode 100644 index b0ca6f3c18..0000000000 --- a/Content.Server/Players/PlayerData.cs +++ /dev/null @@ -1,30 +0,0 @@ -using Content.Shared.Players; -using Robust.Server.Player; -using Robust.Shared.Players; - -namespace Content.Server.Players -{ - public static class PlayerDataExt - { - /// - /// Gets the correctly cast instance of content player data from an engine player data storage. - /// - public static PlayerData? ContentData(this IPlayerSession session) - { - return session.Data.ContentData(); - } - - public static PlayerData? ContentData(this ICommonSession session) - { - return ((IPlayerSession) session).ContentData(); - } - - /// - /// Gets the mind that is associated with this player. - /// - public static EntityUid? GetMind(this IPlayerSession session) - { - return session.Data.ContentData()?.Mind; - } - } -} diff --git a/Content.Server/Players/PlayerSystem.cs b/Content.Server/Players/PlayerSystem.cs index 0c407aa876..c79683c338 100644 --- a/Content.Server/Players/PlayerSystem.cs +++ b/Content.Server/Players/PlayerSystem.cs @@ -1,11 +1,11 @@ using Content.Shared.Players; -using Robust.Shared.Players; +using Robust.Shared.Player; namespace Content.Server.Players; public sealed class PlayerSystem : SharedPlayerSystem { - public override PlayerData? ContentData(ICommonSession? session) + public override ContentPlayerData? ContentData(ICommonSession? session) { return session?.ContentData(); } diff --git a/Content.Server/Pointing/EntitySystems/PointingSystem.cs b/Content.Server/Pointing/EntitySystems/PointingSystem.cs index b253e32e37..6fcdfcf994 100644 --- a/Content.Server/Pointing/EntitySystems/PointingSystem.cs +++ b/Content.Server/Pointing/EntitySystems/PointingSystem.cs @@ -20,7 +20,6 @@ using Robust.Shared.Enums; using Robust.Shared.Input.Binding; using Robust.Shared.Map; using Robust.Shared.Player; -using Robust.Shared.Players; using Robust.Shared.Replays; using Robust.Shared.Timing; @@ -170,7 +169,7 @@ namespace Content.Server.Pointing.EntitySystems } // Get players that are in range and whose visibility layer matches the arrow's. - bool ViewerPredicate(IPlayerSession playerSession) + bool ViewerPredicate(ICommonSession playerSession) { if (!_minds.TryGetMind(playerSession, out _, out var mind) || mind.CurrentEntity is not { Valid: true } ent || @@ -182,7 +181,7 @@ namespace Content.Server.Pointing.EntitySystems } var viewers = Filter.Empty() - .AddWhere(session1 => ViewerPredicate((IPlayerSession) session1)) + .AddWhere(session1 => ViewerPredicate(session1)) .Recipients; string selfMessage; diff --git a/Content.Server/Popups/PopupSystem.cs b/Content.Server/Popups/PopupSystem.cs index 483d4f3d3f..61ccaf4423 100644 --- a/Content.Server/Popups/PopupSystem.cs +++ b/Content.Server/Popups/PopupSystem.cs @@ -4,7 +4,6 @@ using Robust.Server.Player; using Robust.Shared.Configuration; using Robust.Shared.Map; using Robust.Shared.Player; -using Robust.Shared.Players; namespace Content.Server.Popups { diff --git a/Content.Server/Power/EntitySystems/CableSystem.cs b/Content.Server/Power/EntitySystems/CableSystem.cs index 8dd09fab35..a5c9591d9a 100644 --- a/Content.Server/Power/EntitySystems/CableSystem.cs +++ b/Content.Server/Power/EntitySystems/CableSystem.cs @@ -8,6 +8,8 @@ using Content.Shared.Interaction; using Content.Shared.Tools; using Content.Shared.Tools.Components; using Robust.Shared.Map; +using CableCuttingFinishedEvent = Content.Shared.Tools.Systems.CableCuttingFinishedEvent; +using SharedToolSystem = Content.Shared.Tools.Systems.SharedToolSystem; namespace Content.Server.Power.EntitySystems; diff --git a/Content.Server/Power/Generator/PortableGeneratorSystem.cs b/Content.Server/Power/Generator/PortableGeneratorSystem.cs index 416f509978..1180665ad1 100644 --- a/Content.Server/Power/Generator/PortableGeneratorSystem.cs +++ b/Content.Server/Power/Generator/PortableGeneratorSystem.cs @@ -22,7 +22,7 @@ public sealed class PortableGeneratorSystem : SharedPortableGeneratorSystem [Dependency] private readonly AudioSystem _audio = default!; [Dependency] private readonly IRobustRandom _random = default!; [Dependency] private readonly GeneratorSystem _generator = default!; - [Dependency] private readonly PowerSwitchableGeneratorSystem _switchableGenerator = default!; + [Dependency] private readonly PowerSwitchableSystem _switchable = default!; public override void Initialize() { @@ -36,6 +36,8 @@ public sealed class PortableGeneratorSystem : SharedPortableGeneratorSystem SubscribeLocalEvent(GeneratorStartMessage); SubscribeLocalEvent(GeneratorStopMessage); SubscribeLocalEvent(GeneratorSwitchOutputMessage); + + SubscribeLocalEvent(OnSwitchPowerCheck); } private void GeneratorSwitchOutputMessage(EntityUid uid, PortableGeneratorComponent component, PortableGeneratorSwitchOutputMessage args) @@ -47,7 +49,7 @@ public sealed class PortableGeneratorSystem : SharedPortableGeneratorSystem if (fuelGenerator.On) return; - _switchableGenerator.ToggleActiveOutput(uid, args.Session.AttachedEntity.Value); + _switchable.Cycle(uid, args.Session.AttachedEntity.Value); } private void GeneratorStopMessage(EntityUid uid, PortableGeneratorComponent component, PortableGeneratorStopMessage args) @@ -164,6 +166,12 @@ public sealed class PortableGeneratorSystem : SharedPortableGeneratorSystem } } + private void OnSwitchPowerCheck(EntityUid uid, FuelGeneratorComponent comp, ref SwitchPowerCheckEvent args) + { + if (comp.On) + args.DisableMessage = Loc.GetString("fuel-generator-verb-disable-on"); + } + public override void Update(float frameTime) { var query = EntityQueryEnumerator(); diff --git a/Content.Server/Power/Generator/PowerSwitchableGeneratorSystem.cs b/Content.Server/Power/Generator/PowerSwitchableGeneratorSystem.cs deleted file mode 100644 index b81d77ea9f..0000000000 --- a/Content.Server/Power/Generator/PowerSwitchableGeneratorSystem.cs +++ /dev/null @@ -1,111 +0,0 @@ -using Content.Server.NodeContainer; -using Content.Server.NodeContainer.EntitySystems; -using Content.Server.Popups; -using Content.Server.Power.Components; -using Content.Server.Power.Nodes; -using Content.Shared.Power.Generator; -using Content.Shared.Verbs; -using Robust.Server.GameObjects; -using Robust.Shared.Player; -using Robust.Shared.Utility; - -namespace Content.Server.Power.Generator; - -/// -/// Implements power-switchable generators. -/// -/// -/// -/// -public sealed class PowerSwitchableGeneratorSystem : SharedPowerSwitchableGeneratorSystem -{ - [Dependency] private readonly NodeGroupSystem _nodeGroup = default!; - [Dependency] private readonly PopupSystem _popup = default!; - [Dependency] private readonly AudioSystem _audio = default!; - - public override void Initialize() - { - base.Initialize(); - - SubscribeLocalEvent>(GetInteractionVerbs); - } - - private void GetInteractionVerbs( - EntityUid uid, - PowerSwitchableGeneratorComponent component, - GetVerbsEvent args) - { - if (!args.CanAccess || !args.CanInteract) - return; - - var isCurrentlyHV = component.ActiveOutput == PowerSwitchableGeneratorOutput.HV; - var msg = isCurrentlyHV ? "power-switchable-generator-verb-mv" : "power-switchable-generator-verb-hv"; - - var isOn = TryComp(uid, out FuelGeneratorComponent? fuelGenerator) && fuelGenerator.On; - - InteractionVerb verb = new() - { - Act = () => - { - - var verbIsOn = TryComp(uid, out FuelGeneratorComponent? verbFuelGenerator) && verbFuelGenerator.On; - if (verbIsOn) - return; - - ToggleActiveOutput(uid, args.User, component); - }, - Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/VerbIcons/zap.svg.192dpi.png")), - Text = Loc.GetString(msg), - }; - - if (isOn) - { - verb.Message = Loc.GetString("power-switchable-generator-verb-disable-on"); - verb.Disabled = true; - } - - args.Verbs.Add(verb); - } - - public void ToggleActiveOutput(EntityUid uid, EntityUid user, PowerSwitchableGeneratorComponent? component = null) - { - if (!Resolve(uid, ref component)) - return; - - var supplier = Comp(uid); - var nodeContainer = Comp(uid); - var outputMV = (CableDeviceNode) nodeContainer.Nodes[component.NodeOutputMV]; - var outputHV = (CableDeviceNode) nodeContainer.Nodes[component.NodeOutputHV]; - - if (component.ActiveOutput == PowerSwitchableGeneratorOutput.HV) - { - component.ActiveOutput = PowerSwitchableGeneratorOutput.MV; - supplier.Voltage = Voltage.Medium; - - // Switching around the voltage on the power supplier is "enough", - // but we also want to disconnect the cable nodes so it doesn't show up in power monitors etc. - outputMV.Enabled = true; - outputHV.Enabled = false; - } - else - { - component.ActiveOutput = PowerSwitchableGeneratorOutput.HV; - supplier.Voltage = Voltage.High; - - outputMV.Enabled = false; - outputHV.Enabled = true; - } - - _popup.PopupEntity( - Loc.GetString("power-switchable-generator-switched-output"), - uid, - user); - - _audio.Play(component.SwitchSound, Filter.Pvs(uid), uid, true); - - Dirty(uid, component); - - _nodeGroup.QueueReflood(outputMV); - _nodeGroup.QueueReflood(outputHV); - } -} diff --git a/Content.Server/Power/Generator/PowerSwitchableSystem.cs b/Content.Server/Power/Generator/PowerSwitchableSystem.cs new file mode 100644 index 0000000000..ae7960cf8f --- /dev/null +++ b/Content.Server/Power/Generator/PowerSwitchableSystem.cs @@ -0,0 +1,123 @@ +using Content.Server.NodeContainer; +using Content.Server.NodeContainer.EntitySystems; +using Content.Server.Popups; +using Content.Server.Power.Components; +using Content.Server.Power.Nodes; +using Content.Shared.Power.Generator; +using Content.Shared.Timing; +using Content.Shared.Verbs; +using Robust.Server.GameObjects; +using Robust.Shared.Player; +using Robust.Shared.Utility; + +namespace Content.Server.Power.Generator; + +/// +/// Implements server logic for power-switchable devices. +/// +/// +/// +/// +public sealed class PowerSwitchableSystem : SharedPowerSwitchableSystem +{ + [Dependency] private readonly AudioSystem _audio = default!; + [Dependency] private readonly NodeGroupSystem _nodeGroup = default!; + [Dependency] private readonly PopupSystem _popup = default!; + [Dependency] private readonly UseDelaySystem _useDelay = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent>(GetVerbs); + } + + private void GetVerbs(EntityUid uid, PowerSwitchableComponent comp, GetVerbsEvent args) + { + if (!args.CanAccess || !args.CanInteract) + return; + + var voltage = VoltageColor(GetNextVoltage(uid, comp)); + var msg = Loc.GetString("power-switchable-switch-voltage", ("voltage", voltage)); + + InteractionVerb verb = new() + { + Act = () => + { + // don't need to check it again since if its disabled server wont let the verb act + Cycle(uid, args.User, comp); + }, + Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/VerbIcons/zap.svg.192dpi.png")), + Text = msg + }; + + var ev = new SwitchPowerCheckEvent(); + RaiseLocalEvent(uid, ref ev); + if (ev.DisableMessage != null) + { + verb.Message = ev.DisableMessage; + verb.Disabled = true; + } + + args.Verbs.Add(verb); + } + + /// + /// Cycles voltage then updates nodes and optionally power supplier to match it. + /// + public void Cycle(EntityUid uid, EntityUid user, PowerSwitchableComponent? comp = null) + { + if (!Resolve(uid, ref comp)) + return; + + // no sound spamming + if (TryComp(uid, out var useDelay) && _useDelay.ActiveDelay(uid)) + return; + + comp.ActiveIndex = NextIndex(uid, comp); + Dirty(uid, comp); + + var voltage = GetVoltage(uid, comp); + + if (TryComp(uid, out var supplier)) + { + // convert to nodegroupid (goofy server Voltage enum is just alias for it) + switch (voltage) + { + case SwitchableVoltage.HV: + supplier.Voltage = Voltage.High; + break; + case SwitchableVoltage.MV: + supplier.Voltage = Voltage.Medium; + break; + case SwitchableVoltage.LV: + supplier.Voltage = Voltage.Apc; + break; + } + } + + // Switching around the voltage on the power supplier is "enough", + // but we also want to disconnect the cable nodes so it doesn't show up in power monitors etc. + var nodeContainer = Comp(uid); + foreach (var cable in comp.Cables) + { + var node = (CableDeviceNode) nodeContainer.Nodes[cable.Node]; + node.Enabled = cable.Voltage == voltage; + _nodeGroup.QueueReflood(node); + } + + var popup = Loc.GetString(comp.SwitchText, ("voltage", VoltageString(voltage))); + _popup.PopupEntity(popup, uid, user); + + _audio.PlayPvs(comp.SwitchSound, uid); + + _useDelay.BeginDelay(uid, useDelay); + } +} + +/// +/// Raised on a to see if its verb should work. +/// If is non-null, the verb is disabled with that as the message. +/// +[ByRefEvent] +public record struct SwitchPowerCheckEvent(string? DisableMessage = null); diff --git a/Content.Server/Prayer/PrayerSystem.cs b/Content.Server/Prayer/PrayerSystem.cs index be6ae80bfd..e20291cc06 100644 --- a/Content.Server/Prayer/PrayerSystem.cs +++ b/Content.Server/Prayer/PrayerSystem.cs @@ -5,12 +5,11 @@ using Content.Server.Chat.Managers; using Content.Server.Popups; using Content.Shared.Database; using Content.Shared.Popups; -using Robust.Server.Player; -using Robust.Shared.Player; using Content.Shared.Chat; using Content.Shared.Prayer; using Content.Shared.Verbs; using Robust.Server.GameObjects; +using Robust.Shared.Player; namespace Content.Server.Prayer; /// @@ -74,7 +73,7 @@ public sealed class PrayerSystem : EntitySystem /// The IPlayerSession that sent the message /// The main message sent to the player via the chatbox /// The popup to notify the player, also prepended to the messageString - public void SendSubtleMessage(IPlayerSession target, IPlayerSession source, string messageString, string popupMessage) + public void SendSubtleMessage(ICommonSession target, ICommonSession source, string messageString, string popupMessage) { if (target.AttachedEntity == null) return; @@ -96,7 +95,7 @@ public sealed class PrayerSystem : EntitySystem /// You may be wondering, "Why the admin chat, specifically? Nobody even reads it!" /// Exactly. /// - public void Pray(IPlayerSession sender, PrayableComponent comp, string message) + public void Pray(ICommonSession sender, PrayableComponent comp, string message) { if (sender.AttachedEntity == null) return; diff --git a/Content.Server/Preferences/Managers/IServerPreferencesManager.cs b/Content.Server/Preferences/Managers/IServerPreferencesManager.cs index 8c06e00ab1..a36b053717 100644 --- a/Content.Server/Preferences/Managers/IServerPreferencesManager.cs +++ b/Content.Server/Preferences/Managers/IServerPreferencesManager.cs @@ -2,8 +2,8 @@ using System.Diagnostics.CodeAnalysis; using System.Threading; using System.Threading.Tasks; using Content.Shared.Preferences; -using Robust.Server.Player; using Robust.Shared.Network; +using Robust.Shared.Player; namespace Content.Server.Preferences.Managers { @@ -11,12 +11,12 @@ namespace Content.Server.Preferences.Managers { void Init(); - Task LoadData(IPlayerSession session, CancellationToken cancel); - void OnClientDisconnected(IPlayerSession session); + Task LoadData(ICommonSession session, CancellationToken cancel); + void OnClientDisconnected(ICommonSession session); bool TryGetCachedPreferences(NetUserId userId, [NotNullWhen(true)] out PlayerPreferences? playerPreferences); PlayerPreferences GetPreferences(NetUserId userId); IEnumerable> GetSelectedProfilesForPlayers(List userIds); - bool HavePreferencesLoaded(IPlayerSession session); + bool HavePreferencesLoaded(ICommonSession session); } } diff --git a/Content.Server/Preferences/Managers/ServerPreferencesManager.cs b/Content.Server/Preferences/Managers/ServerPreferencesManager.cs index d33e53fa61..94a6046429 100644 --- a/Content.Server/Preferences/Managers/ServerPreferencesManager.cs +++ b/Content.Server/Preferences/Managers/ServerPreferencesManager.cs @@ -9,9 +9,9 @@ using Content.Shared.CCVar; using Content.Shared.Humanoid.Prototypes; using Content.Shared.Preferences; using Content.Shared.Roles; -using Robust.Server.Player; using Robust.Shared.Configuration; using Robust.Shared.Network; +using Robust.Shared.Player; using Robust.Shared.Prototypes; @@ -175,7 +175,7 @@ namespace Content.Server.Preferences.Managers } // Should only be called via UserDbDataManager. - public async Task LoadData(IPlayerSession session, CancellationToken cancel) + public async Task LoadData(ICommonSession session, CancellationToken cancel) { if (!ShouldStorePrefs(session.ConnectedClient.AuthType)) { @@ -224,11 +224,16 @@ namespace Content.Server.Preferences.Managers } } - public void OnClientDisconnected(IPlayerSession session) + public void OnClientDisconnected(ICommonSession session) { _cachedPlayerPrefs.Remove(session.UserId); } + public bool HavePreferencesLoaded(ICommonSession session) + { + return _cachedPlayerPrefs.ContainsKey(session.UserId); + } + // Corvax-Sponsors-Start: Calculate total available users slots with sponsors private int GetMaxUserCharacterSlots(NetUserId userId) { @@ -238,12 +243,6 @@ namespace Content.Server.Preferences.Managers } // Corvax-Sponsors-End - public bool HavePreferencesLoaded(IPlayerSession session) - { - return _cachedPlayerPrefs.ContainsKey(session.UserId); - } - - /// /// Tries to get the preferences from the cache /// diff --git a/Content.Server/Pulling/PullingSystem.cs b/Content.Server/Pulling/PullingSystem.cs index f7ea0aae57..69bb7c9370 100644 --- a/Content.Server/Pulling/PullingSystem.cs +++ b/Content.Server/Pulling/PullingSystem.cs @@ -4,7 +4,7 @@ using Content.Shared.Pulling.Components; using JetBrains.Annotations; using Robust.Server.GameObjects; using Robust.Shared.Input.Binding; -using Robust.Shared.Players; +using Robust.Shared.Player; namespace Content.Server.Pulling { diff --git a/Content.Server/Radiation/Systems/RadiationSystem.Debug.cs b/Content.Server/Radiation/Systems/RadiationSystem.Debug.cs index 97f2e485ca..56806d8c9c 100644 --- a/Content.Server/Radiation/Systems/RadiationSystem.Debug.cs +++ b/Content.Server/Radiation/Systems/RadiationSystem.Debug.cs @@ -7,7 +7,7 @@ using Content.Shared.Radiation.Systems; using Robust.Shared.Console; using Robust.Shared.Enums; using Robust.Shared.Map.Components; -using Robust.Shared.Players; +using Robust.Shared.Player; namespace Content.Server.Radiation.Systems; diff --git a/Content.Server/Repairable/RepairableSystem.cs b/Content.Server/Repairable/RepairableSystem.cs index 486ac756e3..5bd580756d 100644 --- a/Content.Server/Repairable/RepairableSystem.cs +++ b/Content.Server/Repairable/RepairableSystem.cs @@ -5,6 +5,7 @@ using Content.Shared.Interaction; using Content.Shared.Popups; using Content.Shared.Repairable; using Content.Shared.Tools; +using SharedToolSystem = Content.Shared.Tools.Systems.SharedToolSystem; namespace Content.Server.Repairable { diff --git a/Content.Server/Research/Systems/ResearchSystem.Client.cs b/Content.Server/Research/Systems/ResearchSystem.Client.cs index e813f09ff9..135ef8fe88 100644 --- a/Content.Server/Research/Systems/ResearchSystem.Client.cs +++ b/Content.Server/Research/Systems/ResearchSystem.Client.cs @@ -1,7 +1,6 @@ using System.Diagnostics.CodeAnalysis; using Content.Server.Power.EntitySystems; using Content.Shared.Research.Components; -using Robust.Server.Player; namespace Content.Server.Research.Systems; @@ -46,7 +45,7 @@ public sealed partial class ResearchSystem if (!this.IsPowered(uid, EntityManager)) return; - _uiSystem.TryToggleUi(uid, ResearchClientUiKey.Key, (IPlayerSession) args.Session); + _uiSystem.TryToggleUi(uid, ResearchClientUiKey.Key, args.Session); } #endregion diff --git a/Content.Server/Revenant/EntitySystems/RevenantSystem.Abilities.cs b/Content.Server/Revenant/EntitySystems/RevenantSystem.Abilities.cs index b3caced0da..cb20a1b868 100644 --- a/Content.Server/Revenant/EntitySystems/RevenantSystem.Abilities.cs +++ b/Content.Server/Revenant/EntitySystems/RevenantSystem.Abilities.cs @@ -21,6 +21,7 @@ using Content.Shared.DoAfter; using Content.Shared.Emag.Systems; using Content.Shared.FixedPoint; using Content.Shared.Humanoid; +using Content.Shared.Maps; using Content.Shared.Mobs; using Content.Shared.Mobs.Components; using Content.Shared.Mobs.Systems; diff --git a/Content.Server/Salvage/SalvageRulerCommand.cs b/Content.Server/Salvage/SalvageRulerCommand.cs index b0a64508c5..a1fd609741 100644 --- a/Content.Server/Salvage/SalvageRulerCommand.cs +++ b/Content.Server/Salvage/SalvageRulerCommand.cs @@ -1,6 +1,5 @@ using Content.Server.Administration; using Content.Shared.Administration; -using Robust.Server.Player; using Robust.Shared.Console; using Robust.Shared.Map; @@ -26,7 +25,7 @@ sealed class SalvageRulerCommand : IConsoleCommand return; } - if (shell.Player is not IPlayerSession player) + if (shell.Player is not { } player) { shell.WriteError(Loc.GetString("shell-only-players-can-run-this-command")); return; diff --git a/Content.Server/Sandbox/Commands/ColorNetworkCommand.cs b/Content.Server/Sandbox/Commands/ColorNetworkCommand.cs index 0b9148f0fb..cc20b71946 100644 --- a/Content.Server/Sandbox/Commands/ColorNetworkCommand.cs +++ b/Content.Server/Sandbox/Commands/ColorNetworkCommand.cs @@ -4,7 +4,6 @@ using Content.Server.Atmos.Piping.EntitySystems; using Content.Server.NodeContainer; using Content.Server.NodeContainer.NodeGroups; using Content.Shared.Administration; -using Robust.Server.Player; using Robust.Shared.Console; namespace Content.Server.Sandbox.Commands @@ -20,7 +19,7 @@ namespace Content.Server.Sandbox.Commands { var sandboxManager = EntitySystem.Get(); var adminManager = IoCManager.Resolve(); - if (shell.IsClient && (!sandboxManager.IsSandboxEnabled && !adminManager.HasAdminFlag((IPlayerSession)shell.Player!, AdminFlags.Mapping))) + if (shell.IsClient && (!sandboxManager.IsSandboxEnabled && !adminManager.HasAdminFlag(shell.Player!, AdminFlags.Mapping))) { shell.WriteError("You are not currently able to use mapping commands."); } diff --git a/Content.Server/Sandbox/SandboxSystem.cs b/Content.Server/Sandbox/SandboxSystem.cs index ec9b1a0c3c..194cf59843 100644 --- a/Content.Server/Sandbox/SandboxSystem.cs +++ b/Content.Server/Sandbox/SandboxSystem.cs @@ -13,6 +13,7 @@ using Robust.Server.Console; using Robust.Server.Placement; using Robust.Server.Player; using Robust.Shared.Enums; +using Robust.Shared.Player; namespace Content.Server.Sandbox { diff --git a/Content.Server/SensorMonitoring/SensorMonitoringConsoleComponent.cs b/Content.Server/SensorMonitoring/SensorMonitoringConsoleComponent.cs index cd4f2ea23b..63b4d9daef 100644 --- a/Content.Server/SensorMonitoring/SensorMonitoringConsoleComponent.cs +++ b/Content.Server/SensorMonitoring/SensorMonitoringConsoleComponent.cs @@ -1,7 +1,7 @@ using Content.Shared.SensorMonitoring; using Robust.Server.Player; using Robust.Shared.Collections; -using Robust.Shared.Players; +using Robust.Shared.Player; namespace Content.Server.SensorMonitoring; diff --git a/Content.Server/SensorMonitoring/SensorMonitoringConsoleSystem.UI.cs b/Content.Server/SensorMonitoring/SensorMonitoringConsoleSystem.UI.cs index a09badcd59..6c0dddeb26 100644 --- a/Content.Server/SensorMonitoring/SensorMonitoringConsoleSystem.UI.cs +++ b/Content.Server/SensorMonitoring/SensorMonitoringConsoleSystem.UI.cs @@ -1,7 +1,5 @@ using Content.Server.DeviceNetwork.Components; using Content.Shared.SensorMonitoring; -using Robust.Server.GameObjects; -using Robust.Server.Player; using Robust.Shared.Collections; using ConsoleUIState = Content.Shared.SensorMonitoring.SensorMonitoringConsoleBoundInterfaceState; using IncrementalUIState = Content.Shared.SensorMonitoring.SensorMonitoringIncrementalUpdate; @@ -130,7 +128,7 @@ public sealed partial class SensorMonitoringConsoleSystem if (!args.UiKey.Equals(SensorMonitoringConsoleUiKey.Key)) return; - if (args.Session is not IPlayerSession player) + if (args.Session is not { } player) return; component.InitialUIStateSent.Remove(player); diff --git a/Content.Server/ServerUpdates/ServerUpdateManager.cs b/Content.Server/ServerUpdates/ServerUpdateManager.cs index 769c5d58d7..f4e54984e9 100644 --- a/Content.Server/ServerUpdates/ServerUpdateManager.cs +++ b/Content.Server/ServerUpdates/ServerUpdateManager.cs @@ -6,6 +6,7 @@ using Robust.Server.Player; using Robust.Server.ServerStatus; using Robust.Shared.Configuration; using Robust.Shared.Enums; +using Robust.Shared.Player; using Robust.Shared.Timing; namespace Content.Server.ServerUpdates; diff --git a/Content.Server/Shuttles/Systems/EmergencyShuttleSystem.Console.cs b/Content.Server/Shuttles/Systems/EmergencyShuttleSystem.Console.cs index 3de9648fe6..deb2ba256d 100644 --- a/Content.Server/Shuttles/Systems/EmergencyShuttleSystem.Console.cs +++ b/Content.Server/Shuttles/Systems/EmergencyShuttleSystem.Console.cs @@ -90,19 +90,11 @@ public sealed partial class EmergencyShuttleSystem SubscribeLocalEvent(OnEmergencyRepeal); SubscribeLocalEvent(OnEmergencyRepealAll); SubscribeLocalEvent(OnEmergencyOpenAttempt); - SubscribeLocalEvent(OnEmagged); // Corvax-Hijack + SubscribeLocalEvent(OnEmagged); SubscribeLocalEvent(OnEscapeUnpaused); } - // Corvax-Hijack-Start - private void OnEmagged(EntityUid uid, EmergencyShuttleConsoleComponent component, ref GotEmaggedEvent args) - { - _logger.Add(LogType.EmergencyShuttle, LogImpact.Extreme, $"{ToPrettyString(args.UserUid):player} emagged shuttle console for early launch"); - EarlyLaunch(); - } - // Corvax-Hijack-End - private void OnEmergencyOpenAttempt(EntityUid uid, EmergencyShuttleConsoleComponent component, ActivatableUIOpenAttemptEvent args) { // I'm hoping ActivatableUI checks it's open before allowing these messages. @@ -113,6 +105,12 @@ public sealed partial class EmergencyShuttleSystem } } + private void OnEmagged(EntityUid uid, EmergencyShuttleConsoleComponent component, ref GotEmaggedEvent args) + { + _logger.Add(LogType.EmergencyShuttle, LogImpact.Extreme, $"{ToPrettyString(args.UserUid):player} emagged shuttle console for early launch"); + EarlyLaunch(); + } + private void SetAuthorizeTime(float obj) { _authorizeTime = obj; diff --git a/Content.Server/Shuttles/Systems/EmergencyShuttleSystem.cs b/Content.Server/Shuttles/Systems/EmergencyShuttleSystem.cs index 1a1debc9e3..3ef3d97a21 100644 --- a/Content.Server/Shuttles/Systems/EmergencyShuttleSystem.cs +++ b/Content.Server/Shuttles/Systems/EmergencyShuttleSystem.cs @@ -20,7 +20,6 @@ using Content.Shared.Tag; using Content.Shared.Tiles; using Robust.Server.GameObjects; using Robust.Server.Maps; -using Robust.Server.Player; using Robust.Shared.Configuration; using Robust.Shared.Map; using Robust.Shared.Map.Components; @@ -140,7 +139,7 @@ public sealed partial class EmergencyShuttleSystem : EntitySystem /// private void OnShuttleRequestPosition(EmergencyShuttleRequestPositionMessage msg, EntitySessionEventArgs args) { - if (!_admin.IsAdmin((IPlayerSession) args.SenderSession)) + if (!_admin.IsAdmin(args.SenderSession)) return; var player = args.SenderSession.AttachedEntity; diff --git a/Content.Server/Silicons/Borgs/BorgSystem.Modules.cs b/Content.Server/Silicons/Borgs/BorgSystem.Modules.cs index 31d826087d..c080420266 100644 --- a/Content.Server/Silicons/Borgs/BorgSystem.Modules.cs +++ b/Content.Server/Silicons/Borgs/BorgSystem.Modules.cs @@ -229,7 +229,7 @@ public sealed partial class BorgSystem if (!TryComp(chassis, out var hands)) return; - if (LifeStage(uid) >= EntityLifeStage.Terminating) + if (TerminatingOrDeleted(uid)) { foreach (var (hand, item) in component.ProvidedItems) { diff --git a/Content.Server/Silicons/Borgs/BorgSystem.cs b/Content.Server/Silicons/Borgs/BorgSystem.cs index 611dfa6ea2..883cb3b3d8 100644 --- a/Content.Server/Silicons/Borgs/BorgSystem.cs +++ b/Content.Server/Silicons/Borgs/BorgSystem.cs @@ -21,7 +21,7 @@ using Content.Shared.Throwing; using Content.Shared.Wires; using Robust.Server.GameObjects; using Robust.Shared.Containers; -using Robust.Shared.Players; +using Robust.Shared.Player; using Robust.Shared.Random; namespace Content.Server.Silicons.Borgs; diff --git a/Content.Server/Silicons/Laws/SiliconLawSystem.cs b/Content.Server/Silicons/Laws/SiliconLawSystem.cs index 1d5c2e35e8..b1ab1ac020 100644 --- a/Content.Server/Silicons/Laws/SiliconLawSystem.cs +++ b/Content.Server/Silicons/Laws/SiliconLawSystem.cs @@ -18,7 +18,6 @@ using Content.Shared.Silicons.Laws.Components; using Content.Shared.Stunnable; using Content.Shared.Wires; using Robust.Server.GameObjects; -using Robust.Server.Player; using Robust.Shared.Prototypes; using Robust.Shared.Toolshed; @@ -50,7 +49,9 @@ public sealed class SiliconLawSystem : SharedSiliconLawSystem SubscribeLocalEvent(OnPlayerSpawnComplete); SubscribeLocalEvent(OnDirectedGetLaws); + SubscribeLocalEvent(OnIonStormLaws); SubscribeLocalEvent(OnDirectedEmagGetLaws); + SubscribeLocalEvent(OnEmagIonStormLaws); SubscribeLocalEvent(OnEmagMindAdded); SubscribeLocalEvent(OnEmagMindRemoved); SubscribeLocalEvent(OnExamined); @@ -93,8 +94,8 @@ public sealed class SiliconLawSystem : SharedSiliconLawSystem _entityManager.TryGetComponent(uid, out var intrinsicRadio); HashSet? radioChannels = intrinsicRadio?.Channels; - var state = new SiliconLawBuiState(GetLaws(uid), radioChannels); - _userInterface.TrySetUiState(args.Entity, SiliconLawsUiKey.Key, state, (IPlayerSession) args.Session); + var state = new SiliconLawBuiState(GetLaws(uid).Laws, radioChannels); + _userInterface.TrySetUiState(args.Entity, SiliconLawsUiKey.Key, state, args.Session); } private void OnPlayerSpawnComplete(EntityUid uid, SiliconLawBoundComponent component, PlayerSpawnCompleteEvent args) @@ -104,38 +105,66 @@ public sealed class SiliconLawSystem : SharedSiliconLawSystem private void OnDirectedGetLaws(EntityUid uid, SiliconLawProviderComponent component, ref GetSiliconLawsEvent args) { - if (args.Handled || HasComp(uid) || component.Laws.Count == 0) + if (args.Handled || HasComp(uid)) return; - foreach (var law in component.Laws) - { - args.Laws.Add(_prototype.Index(law)); - } + if (component.Lawset == null) + component.Lawset = GetLawset(component.Laws); + + args.Laws = component.Lawset; args.Handled = true; } + private void OnIonStormLaws(EntityUid uid, SiliconLawProviderComponent component, ref IonStormLawsEvent args) + { + if (HasComp(uid)) + return; + + component.Lawset = args.Lawset; + + // gotta tell player to check their laws + NotifyLawsChanged(uid); + + // new laws may allow antagonist behaviour so make it clear for admins + if (TryComp(uid, out var emag)) + EnsureEmaggedRole(uid, emag); + } + private void OnDirectedEmagGetLaws(EntityUid uid, EmagSiliconLawComponent component, ref GetSiliconLawsEvent args) { if (args.Handled || !HasComp(uid) || component.OwnerName == null) return; - // Add the first emag law - args.Laws.Add(new SiliconLaw + if (component.Lawset == null) { - LawString = Loc.GetString("law-emag-custom", ("name", component.OwnerName)), - Order = 0 - }); + // Add new emagged laws + component.Lawset = GetLawset(component.EmagLaws); - // Add new emagged laws - foreach (var law in component.EmagLaws) - { - args.Laws.Add(_prototype.Index(law)); + // Add the first emag law before the others + component.Lawset.Laws.Insert(0, new SiliconLaw + { + LawString = Loc.GetString("law-emag-custom", ("name", component.OwnerName)), + Order = 0 + }); } + args.Laws = component.Lawset; + args.Handled = true; } + private void OnEmagIonStormLaws(EntityUid uid, EmagSiliconLawComponent component, ref IonStormLawsEvent args) + { + if (!HasComp(uid)) + return; + + component.Lawset = args.Lawset; + + // gotta tell player to check their laws + NotifyLawsChanged(uid); + } + private void OnExamined(EntityUid uid, EmagSiliconLawComponent component, ExaminedEvent args) { if (!args.IsInDetailsRange || !HasComp(uid)) @@ -170,7 +199,7 @@ public sealed class SiliconLawSystem : SharedSiliconLawSystem if (component.AntagonistRole == null) return; - _roles.MindTryRemoveRole(args.OldMindId); + _roles.MindTryRemoveRole(args.Mind); } private void EnsureEmaggedRole(EntityUid uid, EmagSiliconLawComponent component) @@ -184,10 +213,10 @@ public sealed class SiliconLawSystem : SharedSiliconLawSystem _roles.MindAddRole(mindId, new SubvertedSiliconRoleComponent { PrototypeId = component.AntagonistRole }); } - public List GetLaws(EntityUid uid, SiliconLawBoundComponent? component = null) + public SiliconLawset GetLaws(EntityUid uid, SiliconLawBoundComponent? component = null) { if (!Resolve(uid, ref component)) - return new List(); + return new SiliconLawset(); var ev = new GetSiliconLawsEvent(uid); @@ -248,6 +277,24 @@ public sealed class SiliconLawSystem : SharedSiliconLawSystem var wrappedMessage = Loc.GetString("chat-manager-server-wrap-message", ("message", msg)); _chatManager.ChatMessageToOne(ChatChannel.Server, msg, wrappedMessage, default, false, actor.PlayerSession.ConnectedClient, colorOverride: Color.Red); } + + /// + /// Extract all the laws from a lawset's prototype ids. + /// + public SiliconLawset GetLawset(string lawset) + { + var proto = _prototype.Index(lawset); + var laws = new SiliconLawset() + { + Laws = new List(proto.Laws.Count) + }; + foreach (var law in proto.Laws) + { + laws.Laws.Add(_prototype.Index(law)); + } + + return laws; + } } [ToolshedCommand, AdminCommand(AdminFlags.Admin)] @@ -270,7 +317,7 @@ public sealed class LawsCommand : ToolshedCommand { _law ??= GetSys(); - foreach (var law in _law.GetLaws(lawbound)) + foreach (var law in _law.GetLaws(lawbound).Laws) { yield return $"law {law.LawIdentifierOverride ?? law.Order.ToString()}: {Loc.GetString(law.LawString)}"; } diff --git a/Content.Server/Station/Systems/StationJobsSystem.cs b/Content.Server/Station/Systems/StationJobsSystem.cs index 2709bc2072..eeaace03b2 100644 --- a/Content.Server/Station/Systems/StationJobsSystem.cs +++ b/Content.Server/Station/Systems/StationJobsSystem.cs @@ -41,7 +41,7 @@ public sealed partial class StationJobsSystem : EntitySystem if (_availableJobsDirty) { _cachedAvailableJobs = GenerateJobsAvailableEvent(); - RaiseNetworkEvent(_cachedAvailableJobs, Filter.Empty().AddPlayers(_playerManager.ServerSessions)); + RaiseNetworkEvent(_cachedAvailableJobs, Filter.Empty().AddPlayers(_playerManager.Sessions)); _availableJobsDirty = false; } } diff --git a/Content.Server/StationEvents/Components/IonStormRuleComponent.cs b/Content.Server/StationEvents/Components/IonStormRuleComponent.cs new file mode 100644 index 0000000000..35b59f5b35 --- /dev/null +++ b/Content.Server/StationEvents/Components/IonStormRuleComponent.cs @@ -0,0 +1,9 @@ +namespace Content.Server.StationEvents.Components; + +/// +/// Gamerule component to mess up ai/borg laws when started. +/// +[RegisterComponent] +public sealed partial class IonStormRuleComponent : Component +{ +} diff --git a/Content.Server/StationEvents/Components/VentClogRuleComponent.cs b/Content.Server/StationEvents/Components/VentClogRuleComponent.cs index 79ebc520c8..afb3a36326 100644 --- a/Content.Server/StationEvents/Components/VentClogRuleComponent.cs +++ b/Content.Server/StationEvents/Components/VentClogRuleComponent.cs @@ -12,7 +12,7 @@ public sealed partial class VentClogRuleComponent : Component /// Somewhat safe chemicals to put in foam that probably won't instantly kill you. /// There is a small chance of using any reagent, ignoring this. /// - [DataField("safeishVentChemicals", customTypeSerializer: typeof(PrototypeIdListSerializer))] + [DataField(customTypeSerializer: typeof(PrototypeIdListSerializer))] public IReadOnlyList SafeishVentChemicals = new[] { "Water", "Blood", "Slime", "SpaceDrugs", "SpaceCleaner", "Nutriment", "Sugar", "SpaceLube", "Ephedrine", "Ale", "Beer", "SpaceGlue" @@ -21,31 +21,31 @@ public sealed partial class VentClogRuleComponent : Component /// /// Sound played when foam is being created. /// - [DataField("sound")] + [DataField] public SoundSpecifier Sound = new SoundPathSpecifier("/Audio/Effects/extinguish.ogg"); /// - /// The standard reagent quantity to put in the foam, modfied by event severity. + /// The standard reagent quantity to put in the foam, modified by event severity. /// - [DataField("reagentQuantity"), ViewVariables(VVAccess.ReadWrite)] - public int ReagentQuantity = 200; + [DataField, ViewVariables(VVAccess.ReadWrite)] + public int ReagentQuantity = 100; /// - /// The standard spreading of the foam, not modfied by event severity. + /// The standard spreading of the foam, not modified by event severity. /// - [DataField("spread"), ViewVariables(VVAccess.ReadWrite)] - public int Spread = 20; + [DataField, ViewVariables(VVAccess.ReadWrite)] + public int Spread = 16; /// /// How long the foam lasts for /// - [DataField("time"), ViewVariables(VVAccess.ReadWrite)] + [DataField, ViewVariables(VVAccess.ReadWrite)] public float Time = 20f; /// /// Reagents that gets the weak numbers used instead of regular ones. /// - [DataField("weakReagents", customTypeSerializer: typeof(PrototypeIdListSerializer))] + [DataField(customTypeSerializer: typeof(PrototypeIdListSerializer))] public IReadOnlyList WeakReagents = new[] { "SpaceLube", "SpaceGlue" @@ -54,12 +54,12 @@ public sealed partial class VentClogRuleComponent : Component /// /// Quantity of weak reagents to put in the foam. /// - [DataField("weakReagentQuantity"), ViewVariables(VVAccess.ReadWrite)] - public int WeakReagentQuantity = 60; + [DataField, ViewVariables(VVAccess.ReadWrite)] + public int WeakReagentQuantity = 50; /// /// Spread of the foam for weak reagents. /// - [DataField("weakSpread"), ViewVariables(VVAccess.ReadWrite)] - public int WeakSpread = 2; + [DataField, ViewVariables(VVAccess.ReadWrite)] + public int WeakSpread = 3; } diff --git a/Content.Server/StationEvents/Events/IonStormRule.cs b/Content.Server/StationEvents/Events/IonStormRule.cs new file mode 100644 index 0000000000..e5b68c4d84 --- /dev/null +++ b/Content.Server/StationEvents/Events/IonStormRule.cs @@ -0,0 +1,273 @@ +using Content.Server.GameTicking.Rules.Components; +using Content.Server.Silicons.Laws; +using Content.Server.Station.Components; +using Content.Server.StationEvents.Components; +using Content.Shared.Administration.Logs; +using Content.Shared.Database; +using Content.Shared.Dataset; +using Content.Shared.FixedPoint; +using Content.Shared.Random; +using Content.Shared.Random.Helpers; +using Content.Shared.Silicons.Laws; +using Content.Shared.Silicons.Laws.Components; +using Robust.Shared.Prototypes; +using Robust.Shared.Random; + +namespace Content.Server.StationEvents.Events; + +public sealed class IonStormRule : StationEventSystem +{ + [Dependency] private readonly IPrototypeManager _proto = default!; + [Dependency] private readonly ISharedAdminLogManager _adminLogger = default!; + [Dependency] private readonly SiliconLawSystem _siliconLaw = default!; + + // funny + [ValidatePrototypeId] + private const string Threats = "IonStormThreats"; + [ValidatePrototypeId] + private const string Objects = "IonStormObjects"; + [ValidatePrototypeId] + private const string Crew = "IonStormCrew"; + [ValidatePrototypeId] + private const string Adjectives = "IonStormAdjectives"; + [ValidatePrototypeId] + private const string Verbs = "IonStormVerbs"; + [ValidatePrototypeId] + private const string NumberBase = "IonStormNumberBase"; + [ValidatePrototypeId] + private const string NumberMod = "IonStormNumberMod"; + [ValidatePrototypeId] + private const string Areas = "IonStormAreas"; + [ValidatePrototypeId] + private const string Feelings = "IonStormFeelings"; + [ValidatePrototypeId] + private const string FeelingsPlural = "IonStormFeelingsPlural"; + [ValidatePrototypeId] + private const string Musts = "IonStormMusts"; + [ValidatePrototypeId] + private const string Requires = "IonStormRequires"; + [ValidatePrototypeId] + private const string Actions = "IonStormActions"; + [ValidatePrototypeId] + private const string Allergies = "IonStormAllergies"; + [ValidatePrototypeId] + private const string AllergySeverities = "IonStormAllergySeverities"; + [ValidatePrototypeId] + private const string Species = "IonStormSpecies"; + [ValidatePrototypeId] + private const string Concepts = "IonStormConcepts"; + [ValidatePrototypeId] + private const string Drinks = "IonStormDrinks"; + [ValidatePrototypeId] + private const string Foods = "IonStormFoods"; + + protected override void Started(EntityUid uid, IonStormRuleComponent comp, GameRuleComponent gameRule, GameRuleStartedEvent args) + { + base.Started(uid, comp, gameRule, args); + + if (!TryGetRandomStation(out var chosenStation)) + return; + + var query = EntityQueryEnumerator(); + while (query.MoveNext(out var ent, out var lawBound, out var xform, out var target)) + { + // only affect law holders on the station + if (CompOrNull(xform.GridUid)?.Station != chosenStation) + continue; + + if (!RobustRandom.Prob(target.Chance)) + continue; + + var laws = _siliconLaw.GetLaws(ent, lawBound); + if (laws.Laws.Count == 0) + continue; + + // try to swap it out with a random lawset + if (RobustRandom.Prob(target.RandomLawsetChance)) + { + var lawsets = PrototypeManager.Index(target.RandomLawsets); + var lawset = lawsets.Pick(RobustRandom); + laws = _siliconLaw.GetLawset(lawset); + } + else + { + // clone it so not modifying stations lawset + laws = laws.Clone(); + } + + // shuffle them all + if (RobustRandom.Prob(target.ShuffleChance)) + { + // hopefully work with existing glitched laws if there are multiple ion storms + FixedPoint2 baseOrder = FixedPoint2.New(1); + foreach (var law in laws.Laws) + { + if (law.Order < baseOrder) + baseOrder = law.Order; + } + + RobustRandom.Shuffle(laws.Laws); + + // change order based on shuffled position + for (int i = 0; i < laws.Laws.Count; i++) + { + laws.Laws[i].Order = baseOrder + i; + } + } + + // see if we can remove a random law + if (laws.Laws.Count > 0 && RobustRandom.Prob(target.RemoveChance)) + { + var i = RobustRandom.Next(laws.Laws.Count); + laws.Laws.RemoveAt(i); + } + + // generate a new law... + var newLaw = GenerateLaw(); + + // see if the law we add will replace a random existing law or be a new glitched order one + if (laws.Laws.Count > 0 && RobustRandom.Prob(target.ReplaceChance)) + { + var i = RobustRandom.Next(laws.Laws.Count); + laws.Laws[i] = new SiliconLaw() + { + LawString = newLaw, + Order = laws.Laws[i].Order + }; + } + else + { + laws.Laws.Insert(0, new SiliconLaw() + { + LawString = newLaw, + Order = -1, + LawIdentifierOverride = "#" + }); + } + + _adminLogger.Add(LogType.Mind, LogImpact.High, $"{ToPrettyString(ent):silicon} had its laws changed by an ion storm to {laws.LoggingString()}"); + + // laws unique to this silicon, dont use station laws anymore + EnsureComp(ent); + var ev = new IonStormLawsEvent(laws); + RaiseLocalEvent(ent, ref ev); + } + } + + // for your own sake direct your eyes elsewhere + private string GenerateLaw() + { + // pick all values ahead of time to make the logic cleaner + var threats = Pick(Threats); + var objects = Pick(Objects); + var crew1 = Pick(Crew); + var crew2 = Pick(Crew); + var adjective = Pick(Adjectives); + var verb = Pick(Verbs); + var number = Pick(NumberBase) + " " + Pick(NumberMod); + var area = Pick(Areas); + var feeling = Pick(Feelings); + var feelingPlural = Pick(FeelingsPlural); + var must = Pick(Musts); + var require = Pick(Requires); + var action = Pick(Actions); + var allergy = Pick(Allergies); + var allergySeverity = Pick(AllergySeverities); + var species = Pick(Species); + var concept = Pick(Concepts); + var drink = Pick(Drinks); + var food = Pick(Foods); + + var joined = $"{number} {adjective}"; + // a lot of things have subjects of a threat/crew/object + var triple = RobustRandom.Next(0, 3) switch + { + 0 => threats, + 1 => crew1, + 2 => objects + }; + var crewAll = RobustRandom.Prob(0.5f) ? crew2 : Loc.GetString("ion-storm-crew"); + var objectsThreats = RobustRandom.Prob(0.5f) ? objects : threats; + var objectsConcept = RobustRandom.Prob(0.5f) ? objects : concept; + // s goes ahead of require, is/are + // i dont think theres a way to do this in fluent + var (who, plural) = RobustRandom.Next(0, 5) switch + { + 0 => (Loc.GetString("ion-storm-you"), false), + 1 => (Loc.GetString("ion-storm-the-station"), true), + 2 => (Loc.GetString("ion-storm-the-crew"), true), + 3 => (Loc.GetString("ion-storm-the-job", ("job", crew2)), false), + _ => (area, true) // THE SINGULARITY REQUIRES THE HAPPY CLOWNS + }; + var jobChange = RobustRandom.Next(0, 3) switch + { + 0 => crew1, + 1 => Loc.GetString("ion-storm-clowns"), + _ => Loc.GetString("ion-storm-heads") + }; + var part = Loc.GetString("ion-storm-part", ("part", RobustRandom.Prob(0.5f))); + var harm = RobustRandom.Next(0, 7) switch + { + 0 => concept, + 1 => $"{adjective} {threats}", + 2 => $"{adjective} {objects}", + 3 => Loc.GetString("ion-storm-adjective-things", ("adjective", adjective)), + 4 => species, + 5 => crew1, + _ => Loc.GetString("ion-storm-x-and-y", ("x", crew1), ("y", crew2)) + }; + + if (plural) feeling = feelingPlural; + + // message logic!!! + return RobustRandom.Next(0, 37) switch + { + 0 => Loc.GetString("ion-storm-law-on-station", ("joined", joined), ("subjects", triple)), + 1 => Loc.GetString("ion-storm-law-no-shuttle", ("joined", joined), ("subjects", triple)), + 2 => Loc.GetString("ion-storm-law-crew-are", ("who", crewAll), ("joined", joined), ("subjects", objectsThreats)), + 3 => Loc.GetString("ion-storm-law-subjects-harmful", ("adjective", adjective), ("subjects", triple)), + 4 => Loc.GetString("ion-storm-law-must-harmful", ("must", must)), + 5 => Loc.GetString("ion-storm-law-thing-harmful", ("thing", RobustRandom.Prob(0.5f) ? concept : action)), + 6 => Loc.GetString("ion-storm-law-job-harmful", ("adjective", adjective), ("job", crew1)), + 7 => Loc.GetString("ion-storm-law-having-harmful", ("adjective", adjective), ("thing", objectsConcept)), + 8 => Loc.GetString("ion-storm-law-not-having-harmful", ("adjective", adjective), ("thing", objectsConcept)), + 9 => Loc.GetString("ion-storm-law-requires", ("who", who), ("plural", plural), ("thing", RobustRandom.Prob(0.5f) ? concept : require)), + 10 => Loc.GetString("ion-storm-law-requires-subjects", ("who", who), ("plural", plural), ("joined", joined), ("subjects", triple)), + 11 => Loc.GetString("ion-storm-law-allergic", ("who", who), ("plural", plural), ("severity", allergySeverity), ("allergy", RobustRandom.Prob(0.5f) ? concept : allergy)), + 12 => Loc.GetString("ion-storm-law-allergic-subjects", ("who", who), ("plural", plural), ("severity", allergySeverity), ("adjective", adjective), ("subjects", RobustRandom.Prob(0.5f) ? objects : crew1)), + 13 => Loc.GetString("ion-storm-law-feeling", ("who", who), ("feeling", feeling), ("concept", concept)), + 14 => Loc.GetString("ion-storm-law-feeling-subjects", ("who", who), ("feeling", feeling), ("joined", joined), ("subjects", triple)), + 15 => Loc.GetString("ion-storm-law-you-are", ("concept", concept)), + 16 => Loc.GetString("ion-storm-law-you-are-subjects", ("joined", joined), ("subjects", triple)), + 17 => Loc.GetString("ion-storm-law-you-must-always", ("must", must)), + 18 => Loc.GetString("ion-storm-law-you-must-never", ("must", must)), + 19 => Loc.GetString("ion-storm-law-eat", ("who", crewAll), ("adjective", adjective), ("food", RobustRandom.Prob(0.5f) ? food : triple)), + 20 => Loc.GetString("ion-storm-law-drink", ("who", crewAll), ("adjective", adjective), ("drink", drink)), + 22 => Loc.GetString("ion-storm-law-change-job", ("who", crewAll), ("adjective", adjective), ("change", jobChange)), + 23 => Loc.GetString("ion-storm-law-highest-rank", ("who", crew1)), + 24 => Loc.GetString("ion-storm-law-lowest-rank", ("who", crew1)), + 25 => Loc.GetString("ion-storm-law-crew-must", ("who", crewAll), ("must", must)), + 26 => Loc.GetString("ion-storm-law-crew-must-go", ("who", crewAll), ("area", area)), + 27 => Loc.GetString("ion-storm-law-crew-only-1", ("who", crew1), ("part", part)), + 28 => Loc.GetString("ion-storm-law-crew-only-2", ("who", crew1), ("other", crew2), ("part", part)), + 29 => Loc.GetString("ion-storm-law-crew-only-subjects", ("adjective", adjective), ("subjects", RobustRandom.Prob(0.5f) ? objectsThreats : "PEOPLE"), ("part", part)), + 30 => Loc.GetString("ion-storm-law-crew-only-species", ("species", species), ("part", part)), + 31 => Loc.GetString("ion-storm-law-crew-must-do", ("must", must), ("part", part)), + 32 => Loc.GetString("ion-storm-law-crew-must-have", ("adjective", adjective), ("objects", objects), ("part", part)), + 33 => Loc.GetString("ion-storm-law-crew-must-eat", ("who", who), ("adjective", adjective), ("food", food), ("part", part)), + 34 => Loc.GetString("ion-storm-law-harm", ("who", harm)), + 35 => Loc.GetString("ion-storm-law-protect", ("who", harm)), + _ => Loc.GetString("ion-storm-law-concept-verb", ("concept", concept), ("verb", verb), ("subjects", triple)) + }; + } + + /// + /// Picks a random value from an ion storm dataset. + /// All ion storm datasets start with IonStorm. + /// + private string Pick(string name) + { + var dataset = _proto.Index(name); + return RobustRandom.Pick(dataset.Values); + } +} diff --git a/Content.Server/StationEvents/Events/VentClogRule.cs b/Content.Server/StationEvents/Events/VentClogRule.cs index 5ef28304e7..f378aec3fb 100644 --- a/Content.Server/StationEvents/Events/VentClogRule.cs +++ b/Content.Server/StationEvents/Events/VentClogRule.cs @@ -3,10 +3,8 @@ using Content.Server.Station.Components; using Content.Shared.Chemistry.Components; using Content.Shared.Chemistry.Reagent; using JetBrains.Annotations; -using Robust.Shared.Audio; using Robust.Shared.Random; using System.Linq; -using Content.Server.Chemistry.Components; using Content.Server.Fluids.EntitySystems; using Content.Server.GameTicking.Rules.Components; using Content.Server.StationEvents.Components; @@ -53,9 +51,8 @@ public sealed class VentClogRule : StationEventSystem solution.AddReagent(reagent, quantity); var foamEnt = Spawn("Foam", transform.Coordinates); - var smoke = EnsureComp(foamEnt); - smoke.SpreadAmount = weak ? component.WeakSpread : component.Spread; - _smoke.Start(foamEnt, smoke, solution, component.Time); + var spreadAmount = weak ? component.WeakSpread : component.Spread; + _smoke.StartSmoke(foamEnt, solution, component.Time, spreadAmount); Audio.PlayPvs(component.Sound, transform.Coordinates); } } diff --git a/Content.Server/Sticky/Events/EntityStuckEvent.cs b/Content.Server/Sticky/Events/EntityStuckEvent.cs index b924436489..7857fad7d5 100644 --- a/Content.Server/Sticky/Events/EntityStuckEvent.cs +++ b/Content.Server/Sticky/Events/EntityStuckEvent.cs @@ -1,5 +1,28 @@ namespace Content.Server.Sticky.Events; +/// +/// Risen on sticky entity to see if it can stick to another entity. +/// +[ByRefEvent] +public record struct AttemptEntityStickEvent(EntityUid Target, EntityUid User) +{ + public readonly EntityUid Target = Target; + public readonly EntityUid User = User; + public bool Cancelled = false; +} + +/// +/// Risen on sticky entity to see if it can unstick from another entity. +/// +[ByRefEvent] +public record struct AttemptEntityUnstickEvent(EntityUid Target, EntityUid User) +{ + public readonly EntityUid Target = Target; + public readonly EntityUid User = User; + public bool Cancelled = false; +} + + /// /// Risen on sticky entity when it was stuck to other entity. /// diff --git a/Content.Server/Sticky/Systems/StickySystem.cs b/Content.Server/Sticky/Systems/StickySystem.cs index 330b878c05..bcc1be39a9 100644 --- a/Content.Server/Sticky/Systems/StickySystem.cs +++ b/Content.Server/Sticky/Systems/StickySystem.cs @@ -56,7 +56,7 @@ public sealed class StickySystem : EntitySystem { DoContactInteraction = true, Text = Loc.GetString("comp-sticky-unstick-verb-text"), - Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/VerbIcons/eject.svg.192dpi.png")), + Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/VerbIcons/eject.svg.192dpi.png")), Act = () => StartUnsticking(uid, args.User, component) }); } @@ -72,6 +72,11 @@ public sealed class StickySystem : EntitySystem if (component.Blacklist != null && component.Blacklist.IsValid(target)) return false; + var attemptEv = new AttemptEntityStickEvent(target, user); + RaiseLocalEvent(uid, ref attemptEv); + if (attemptEv.Cancelled) + return false; + // check if delay is not zero to start do after var delay = (float) component.StickDelay.TotalSeconds; if (delay > 0) @@ -120,6 +125,14 @@ public sealed class StickySystem : EntitySystem if (!Resolve(uid, ref component)) return; + if (component.StuckTo is not { } stuckTo) + return; + + var attemptEv = new AttemptEntityUnstickEvent(stuckTo, user); + RaiseLocalEvent(uid, ref attemptEv); + if (attemptEv.Cancelled) + return; + var delay = (float) component.UnstickDelay.TotalSeconds; if (delay > 0) { @@ -152,6 +165,11 @@ public sealed class StickySystem : EntitySystem if (!Resolve(uid, ref component)) return; + var attemptEv = new AttemptEntityStickEvent(target, user); + RaiseLocalEvent(uid, ref attemptEv); + if (attemptEv.Cancelled) + return; + // add container to entity and insert sticker into it var container = _containerSystem.EnsureContainer(target, StickerSlotId); container.ShowContents = true; @@ -179,12 +197,17 @@ public sealed class StickySystem : EntitySystem { if (!Resolve(uid, ref component)) return; - if (component.StuckTo == null) + + if (component.StuckTo is not { } stuckTo) + return; + + var attemptEv = new AttemptEntityUnstickEvent(stuckTo, user); + RaiseLocalEvent(uid, ref attemptEv); + if (attemptEv.Cancelled) return; // try to remove sticky item from target container - var target = component.StuckTo.Value; - if (!_containerSystem.TryGetContainer(target, StickerSlotId, out var container) || !container.Remove(uid)) + if (!_containerSystem.TryGetContainer(stuckTo, StickerSlotId, out var container) || !container.Remove(uid)) return; // delete container if it's now empty if (container.ContainedEntities.Count == 0) @@ -207,6 +230,6 @@ public sealed class StickySystem : EntitySystem } component.StuckTo = null; - RaiseLocalEvent(uid, new EntityUnstuckEvent(target, user), true); + RaiseLocalEvent(uid, new EntityUnstuckEvent(stuckTo, user), true); } } diff --git a/Content.Server/Storage/EntitySystems/StorageSystem.cs b/Content.Server/Storage/EntitySystems/StorageSystem.cs index 3430449957..8b4ae1c76f 100644 --- a/Content.Server/Storage/EntitySystems/StorageSystem.cs +++ b/Content.Server/Storage/EntitySystems/StorageSystem.cs @@ -9,7 +9,6 @@ using Content.Shared.Storage.EntitySystems; using Content.Shared.Timing; using Content.Shared.Verbs; using Robust.Server.GameObjects; -using Robust.Server.Player; using Robust.Shared.Map; using Robust.Shared.Player; using Robust.Shared.Prototypes; @@ -135,7 +134,7 @@ public sealed partial class StorageSystem : SharedStorageSystem /// If the user has nested-UIs open (e.g., PDA UI open when pda is in a backpack), close them. /// /// - public void CloseNestedInterfaces(EntityUid uid, IPlayerSession session, StorageComponent? storageComp = null) + public void CloseNestedInterfaces(EntityUid uid, ICommonSession session, StorageComponent? storageComp = null) { if (!Resolve(uid, ref storageComp)) return; diff --git a/Content.Server/Tabletop/TabletopSession.cs b/Content.Server/Tabletop/TabletopSession.cs index d94b4fd657..5e7c6ac02e 100644 --- a/Content.Server/Tabletop/TabletopSession.cs +++ b/Content.Server/Tabletop/TabletopSession.cs @@ -1,6 +1,6 @@ using System.Numerics; -using Robust.Server.Player; using Robust.Shared.Map; +using Robust.Shared.Player; namespace Content.Server.Tabletop { @@ -17,7 +17,7 @@ namespace Content.Server.Tabletop /// /// The set of players currently playing this tabletop game. /// - public readonly Dictionary Players = new(); + public readonly Dictionary Players = new(); /// /// All entities bound to this session. If you create an entity for this session, you have to add it here. diff --git a/Content.Server/Tabletop/TabletopSystem.Session.cs b/Content.Server/Tabletop/TabletopSystem.Session.cs index e9dea0c66a..8f1bc7005d 100644 --- a/Content.Server/Tabletop/TabletopSystem.Session.cs +++ b/Content.Server/Tabletop/TabletopSystem.Session.cs @@ -1,7 +1,7 @@ using System.Numerics; using Content.Server.Tabletop.Components; using Content.Shared.Tabletop.Events; -using Robust.Server.Player; +using Robust.Shared.Player; using Robust.Shared.Utility; namespace Content.Server.Tabletop @@ -66,7 +66,7 @@ namespace Content.Server.Tabletop /// /// The player session in question. /// The UID of the tabletop game entity. - public void OpenSessionFor(IPlayerSession player, EntityUid uid) + public void OpenSessionFor(ICommonSession player, EntityUid uid) { if (!EntityManager.TryGetComponent(uid, out TabletopGameComponent? tabletop) || player.AttachedEntity is not {Valid: true} attachedEntity) return; @@ -98,7 +98,7 @@ namespace Content.Server.Tabletop /// The player in question. /// The UID of the tabletop game entity. /// Whether to remove the from the player's attached entity. - public void CloseSessionFor(IPlayerSession player, EntityUid uid, bool removeGamerComponent = true) + public void CloseSessionFor(ICommonSession player, EntityUid uid, bool removeGamerComponent = true) { if (!EntityManager.TryGetComponent(uid, out TabletopGameComponent? tabletop) || tabletop.Session is not { } session) return; @@ -129,7 +129,7 @@ namespace Content.Server.Tabletop /// The player in question. /// An offset from the tabletop position for the camera. Zero by default. /// The UID of the camera entity. - private EntityUid CreateCamera(TabletopGameComponent tabletop, IPlayerSession player, Vector2 offset = default) + private EntityUid CreateCamera(TabletopGameComponent tabletop, ICommonSession player, Vector2 offset = default) { DebugTools.AssertNotNull(tabletop.Session); diff --git a/Content.Server/Tabletop/TabletopSystem.cs b/Content.Server/Tabletop/TabletopSystem.cs index 2e271080d0..b81331d62e 100644 --- a/Content.Server/Tabletop/TabletopSystem.cs +++ b/Content.Server/Tabletop/TabletopSystem.cs @@ -9,7 +9,6 @@ using Content.Shared.Tabletop.Events; using Content.Shared.Verbs; using JetBrains.Annotations; using Robust.Server.GameObjects; -using Robust.Server.Player; using Robust.Shared.Enums; using Robust.Shared.Map; using Robust.Shared.Utility; @@ -42,7 +41,7 @@ namespace Content.Server.Tabletop private void OnTabletopRequestTakeOut(TabletopRequestTakeOut msg, EntitySessionEventArgs args) { - if (args.SenderSession is not IPlayerSession playerSession) + if (args.SenderSession is not { } playerSession) return; var table = GetEntity(msg.TableUid); @@ -105,7 +104,7 @@ namespace Content.Server.Tabletop protected override void OnTabletopMove(TabletopMoveEvent msg, EntitySessionEventArgs args) { - if (args.SenderSession is not IPlayerSession playerSession) + if (args.SenderSession is not { } playerSession) return; if (!TryComp(GetEntity(msg.TableUid), out TabletopGameComponent? tabletop) || tabletop.Session is not { } session) @@ -155,7 +154,7 @@ namespace Content.Server.Tabletop private void OnStopPlaying(TabletopStopPlayingEvent msg, EntitySessionEventArgs args) { - CloseSessionFor((IPlayerSession)args.SenderSession, GetEntity(msg.TableUid)); + CloseSessionFor(args.SenderSession, GetEntity(msg.TableUid)); } private void OnPlayerDetached(EntityUid uid, TabletopGamerComponent component, PlayerDetachedEvent args) diff --git a/Content.Server/Toilet/ToiletSystem.cs b/Content.Server/Toilet/ToiletSystem.cs index 57467397c6..b10feae453 100644 --- a/Content.Server/Toilet/ToiletSystem.cs +++ b/Content.Server/Toilet/ToiletSystem.cs @@ -19,6 +19,7 @@ using Content.Shared.Verbs; using Robust.Shared.Audio; using Robust.Shared.Player; using Robust.Shared.Random; +using SharedToolSystem = Content.Shared.Tools.Systems.SharedToolSystem; namespace Content.Server.Toilet { diff --git a/Content.Server/Tools/Components/TilePryingComponent.cs b/Content.Server/Tools/Components/TilePryingComponent.cs deleted file mode 100644 index 99d7144b68..0000000000 --- a/Content.Server/Tools/Components/TilePryingComponent.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System.Threading; -using Content.Shared.Tools; -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; - -namespace Content.Server.Tools.Components -{ - [RegisterComponent] - public sealed partial class TilePryingComponent : Component - { - [DataField("toolComponentNeeded")] - public bool ToolComponentNeeded = true; - - [DataField("qualityNeeded", customTypeSerializer:typeof(PrototypeIdSerializer))] - public string QualityNeeded = "Prying"; - - /// - /// Whether this tool can pry tiles with CanAxe. - /// - [DataField("advanced")] - public bool Advanced = false; - - [DataField("delay")] - public float Delay = 1f; - } -} diff --git a/Content.Server/Tools/ToolSystem.LatticeCutting.cs b/Content.Server/Tools/ToolSystem.LatticeCutting.cs index 674a810239..ab289c1ae2 100644 --- a/Content.Server/Tools/ToolSystem.LatticeCutting.cs +++ b/Content.Server/Tools/ToolSystem.LatticeCutting.cs @@ -62,14 +62,14 @@ public sealed partial class ToolSystem var coordinates = mapGrid.GridTileToLocal(tile.GridIndices); - if (!_interactionSystem.InRangeUnobstructed(user, coordinates, popup: false)) + if (!InteractionSystem.InRangeUnobstructed(user, coordinates, popup: false)) return false; if (_tileDefinitionManager[tile.Tile.TypeId] is not ContentTileDefinition tileDef || !tileDef.CanWirecutter || string.IsNullOrEmpty(tileDef.BaseTurf) - || _tileDefinitionManager[tileDef.BaseTurf] is not ContentTileDefinition newDef - || tile.IsBlockedTurf(true)) + || _tileDefinitionManager[tileDef.BaseTurf] is not ContentTileDefinition || + tile.IsBlockedTurf(true)) { return false; } diff --git a/Content.Server/Tools/ToolSystem.cs b/Content.Server/Tools/ToolSystem.cs index 63642338f3..88a96dc1e8 100644 --- a/Content.Server/Tools/ToolSystem.cs +++ b/Content.Server/Tools/ToolSystem.cs @@ -6,6 +6,7 @@ using Content.Shared.Maps; using Content.Shared.Tools; using Robust.Server.GameObjects; using Robust.Shared.Map; +using SharedToolSystem = Content.Shared.Tools.Systems.SharedToolSystem; namespace Content.Server.Tools { @@ -21,13 +22,11 @@ namespace Content.Server.Tools [Dependency] private readonly SharedPointLightSystem _light = default!; [Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!; [Dependency] private readonly TransformSystem _transformSystem = default!; - [Dependency] private readonly TurfSystem _turf = default!; public override void Initialize() { base.Initialize(); - InitializeTilePrying(); InitializeLatticeCutting(); InitializeWelders(); } diff --git a/Content.Server/Toolshed/Commands/AdminDebug/ACmdCommand.cs b/Content.Server/Toolshed/Commands/AdminDebug/ACmdCommand.cs index d2b3cc261c..f113e49655 100644 --- a/Content.Server/Toolshed/Commands/AdminDebug/ACmdCommand.cs +++ b/Content.Server/Toolshed/Commands/AdminDebug/ACmdCommand.cs @@ -1,7 +1,7 @@ using Content.Server.Administration; using Content.Server.Administration.Managers; using Content.Shared.Administration; -using Robust.Server.Player; +using Robust.Shared.Player; using Robust.Shared.Toolshed; using Robust.Shared.Toolshed.Syntax; @@ -25,7 +25,7 @@ public sealed class ACmdCommand : ToolshedCommand public bool CanInvoke( [CommandInvocationContext] IInvocationContext ctx, [PipedArgument] CommandSpec command, - [CommandArgument] ValueRef player + [CommandArgument] ValueRef player ) { // Deliberately discard the error. diff --git a/Content.Server/Toolshed/Commands/VisualizeCommand.cs b/Content.Server/Toolshed/Commands/VisualizeCommand.cs index 4ef08a91bf..2225bfaf44 100644 --- a/Content.Server/Toolshed/Commands/VisualizeCommand.cs +++ b/Content.Server/Toolshed/Commands/VisualizeCommand.cs @@ -4,7 +4,6 @@ using Content.Server.EUI; using Content.Shared.Administration; using Content.Shared.Bql; using Content.Shared.Eui; -using Robust.Server.Player; using Robust.Shared.Toolshed; using Robust.Shared.Toolshed.Errors; @@ -30,7 +29,7 @@ public sealed class VisualizeCommand : ToolshedCommand var ui = new ToolshedVisualizeEui( input.Select(e => (EntName(e), EntityManager.GetNetEntity(e))).ToArray() ); - _euiManager.OpenEui(ui, (IPlayerSession) ctx.Session); + _euiManager.OpenEui(ui, ctx.Session); _euiManager.QueueStateUpdate(ui); } } diff --git a/Content.Server/Traitor/Uplink/Commands/AddUplinkCommand.cs b/Content.Server/Traitor/Uplink/Commands/AddUplinkCommand.cs index 1feab11b99..fd656a9f71 100644 --- a/Content.Server/Traitor/Uplink/Commands/AddUplinkCommand.cs +++ b/Content.Server/Traitor/Uplink/Commands/AddUplinkCommand.cs @@ -5,6 +5,7 @@ using Content.Shared.FixedPoint; using Robust.Server.Player; using Robust.Shared.Configuration; using Robust.Shared.Console; +using Robust.Shared.Player; namespace Content.Server.Traitor.Uplink.Commands { @@ -36,7 +37,7 @@ namespace Content.Server.Traitor.Uplink.Commands return; } - IPlayerSession? session; + ICommonSession? session; if (args.Length > 0) { // Get player entity @@ -48,7 +49,7 @@ namespace Content.Server.Traitor.Uplink.Commands } else { - session = (IPlayerSession?) shell.Player; + session = shell.Player; } if (session?.AttachedEntity is not { } user) diff --git a/Content.Server/UserInterface/ActivatableUIComponent.cs b/Content.Server/UserInterface/ActivatableUIComponent.cs index bb020608e2..34f9c0f397 100644 --- a/Content.Server/UserInterface/ActivatableUIComponent.cs +++ b/Content.Server/UserInterface/ActivatableUIComponent.cs @@ -1,4 +1,4 @@ -using Robust.Server.Player; +using Robust.Shared.Player; using Robust.Shared.Reflection; using Robust.Shared.Serialization; @@ -65,7 +65,7 @@ namespace Content.Server.UserInterface /// NOTE: DO NOT DIRECTLY SET, USE ActivatableUISystem.SetCurrentSingleUser /// [ViewVariables] - public IPlayerSession? CurrentSingleUser; + public ICommonSession? CurrentSingleUser; void ISerializationHooks.AfterDeserialization() { diff --git a/Content.Server/UserInterface/ActivatableUISystem.cs b/Content.Server/UserInterface/ActivatableUISystem.cs index 59086415b4..adeeed7c19 100644 --- a/Content.Server/UserInterface/ActivatableUISystem.cs +++ b/Content.Server/UserInterface/ActivatableUISystem.cs @@ -8,7 +8,7 @@ using Content.Shared.Interaction.Events; using Content.Shared.UserInterface; using Content.Shared.Verbs; using Robust.Server.GameObjects; -using Robust.Server.Player; +using Robust.Shared.Player; namespace Content.Server.UserInterface; @@ -173,7 +173,7 @@ public sealed partial class ActivatableUISystem : EntitySystem return true; } - public void SetCurrentSingleUser(EntityUid uid, IPlayerSession? v, ActivatableUIComponent? aui = null) + public void SetCurrentSingleUser(EntityUid uid, ICommonSession? v, ActivatableUIComponent? aui = null) { if (!Resolve(uid, ref aui)) return; @@ -231,9 +231,9 @@ public sealed class UserOpenActivatableUIAttemptEvent : CancellableEntityEventAr public sealed class AfterActivatableUIOpenEvent : EntityEventArgs { public EntityUid User { get; } - public readonly IPlayerSession Session; + public readonly ICommonSession Session; - public AfterActivatableUIOpenEvent(EntityUid who, IPlayerSession session) + public AfterActivatableUIOpenEvent(EntityUid who, ICommonSession session) { User = who; Session = session; diff --git a/Content.Server/UserInterface/StatValuesCommand.cs b/Content.Server/UserInterface/StatValuesCommand.cs index b13b596323..fe2ee380fe 100644 --- a/Content.Server/UserInterface/StatValuesCommand.cs +++ b/Content.Server/UserInterface/StatValuesCommand.cs @@ -8,7 +8,6 @@ using Content.Shared.Materials; using Content.Shared.Research.Prototypes; using Content.Shared.UserInterface; using Content.Shared.Weapons.Melee; -using Robust.Server.Player; using Robust.Shared.Console; using Robust.Shared.Prototypes; @@ -27,7 +26,7 @@ public sealed class StatValuesCommand : IConsoleCommand public string Help => $"{Command} "; public void Execute(IConsoleShell shell, string argStr, string[] args) { - if (shell.Player is not IPlayerSession pSession) + if (shell.Player is not { } pSession) { shell.WriteError(Loc.GetString("stat-values-server")); return; diff --git a/Content.Server/Verbs/VerbSystem.cs b/Content.Server/Verbs/VerbSystem.cs index 6d12b08e86..e304c6b4af 100644 --- a/Content.Server/Verbs/VerbSystem.cs +++ b/Content.Server/Verbs/VerbSystem.cs @@ -6,7 +6,6 @@ using Content.Shared.Administration.Logs; using Content.Shared.Database; using Content.Shared.Hands.Components; using Content.Shared.Verbs; -using Robust.Server.Player; namespace Content.Server.Verbs { @@ -25,7 +24,7 @@ namespace Content.Server.Verbs private void HandleVerbRequest(RequestServerVerbsEvent args, EntitySessionEventArgs eventArgs) { - var player = (IPlayerSession) eventArgs.SenderSession; + var player = eventArgs.SenderSession; if (!EntityManager.EntityExists(GetEntity(args.EntityUid))) { @@ -43,7 +42,7 @@ namespace Content.Server.Verbs // this, and some verbs (e.g. view variables) won't even care about whether an entity is accessible through // the entity menu or not. - var force = args.AdminRequest && eventArgs.SenderSession is IPlayerSession playerSession && + var force = args.AdminRequest && eventArgs.SenderSession is { } playerSession && _adminMgr.HasAdminFlag(playerSession, AdminFlags.Admin); List verbTypes = new(); diff --git a/Content.Server/Voting/IVoteHandle.cs b/Content.Server/Voting/IVoteHandle.cs index 13f64e6ef8..869f2017d7 100644 --- a/Content.Server/Voting/IVoteHandle.cs +++ b/Content.Server/Voting/IVoteHandle.cs @@ -1,5 +1,5 @@ using Content.Server.Voting.Managers; -using Robust.Server.Player; +using Robust.Shared.Player; namespace Content.Server.Voting { @@ -75,7 +75,7 @@ namespace Content.Server.Voting /// /// is not a valid option ID. /// - void CastVote(IPlayerSession session, int? optionId); + void CastVote(ICommonSession session, int? optionId); /// /// Cancel this vote. diff --git a/Content.Server/Voting/Managers/IVoteManager.cs b/Content.Server/Voting/Managers/IVoteManager.cs index 6a92e70fff..d95fac9ae9 100644 --- a/Content.Server/Voting/Managers/IVoteManager.cs +++ b/Content.Server/Voting/Managers/IVoteManager.cs @@ -1,6 +1,6 @@ using System.Diagnostics.CodeAnalysis; using Content.Shared.Voting; -using Robust.Server.Player; +using Robust.Shared.Player; namespace Content.Server.Voting.Managers { @@ -41,7 +41,7 @@ namespace Content.Server.Voting.Managers /// True if can start votes right now, /// and if provided if they can start votes of type . /// - bool CanCallVote(IPlayerSession initiator, StandardVoteType? voteType = null); + bool CanCallVote(ICommonSession initiator, StandardVoteType? voteType = null); /// /// Initiate a standard vote such as restart round, that can be initiated by players. @@ -51,7 +51,7 @@ namespace Content.Server.Voting.Managers /// If null it is assumed to be an automatic vote by the server. /// /// The type of standard vote to make. - void CreateStandardVote(IPlayerSession? initiator, StandardVoteType voteType); + void CreateStandardVote(ICommonSession? initiator, StandardVoteType voteType); /// /// Create a non-standard vote with special parameters. diff --git a/Content.Server/Voting/Managers/VoteManager.DefaultVotes.cs b/Content.Server/Voting/Managers/VoteManager.DefaultVotes.cs index 55e88e2a8c..e1bffa769d 100644 --- a/Content.Server/Voting/Managers/VoteManager.DefaultVotes.cs +++ b/Content.Server/Voting/Managers/VoteManager.DefaultVotes.cs @@ -6,8 +6,8 @@ using Content.Server.RoundEnd; using Content.Shared.CCVar; using Content.Shared.Database; using Content.Shared.Voting; -using Robust.Server.Player; using Robust.Shared.Configuration; +using Robust.Shared.Player; using Robust.Shared.Random; namespace Content.Server.Voting.Managers @@ -21,7 +21,7 @@ namespace Content.Server.Voting.Managers {StandardVoteType.Map, CCVars.VoteMapEnabled}, }; - public void CreateStandardVote(IPlayerSession? initiator, StandardVoteType voteType) + public void CreateStandardVote(ICommonSession? initiator, StandardVoteType voteType) { if (initiator != null) _adminLogger.Add(LogType.Vote, LogImpact.Medium, $"{initiator} initiated a {voteType.ToString()} vote"); @@ -47,7 +47,7 @@ namespace Content.Server.Voting.Managers TimeoutStandardVote(voteType); } - private void CreateRestartVote(IPlayerSession? initiator) + private void CreateRestartVote(ICommonSession? initiator) { var alone = _playerManager.PlayerCount == 1 && initiator != null; var options = new VoteOptions @@ -100,7 +100,7 @@ namespace Content.Server.Voting.Managers vote.CastVote(initiator, 0); } - foreach (var player in _playerManager.ServerSessions) + foreach (var player in _playerManager.Sessions) { if (player != initiator) { @@ -110,7 +110,7 @@ namespace Content.Server.Voting.Managers } } - private void CreatePresetVote(IPlayerSession? initiator) + private void CreatePresetVote(ICommonSession? initiator) { var presets = GetGamePresets(); @@ -156,7 +156,7 @@ namespace Content.Server.Voting.Managers }; } - private void CreateMapVote(IPlayerSession? initiator) + private void CreateMapVote(ICommonSession? initiator) { var maps = _gameMapManager.CurrentlyEligibleMaps().ToDictionary(map => map, map => map.MapName); diff --git a/Content.Server/Voting/Managers/VoteManager.cs b/Content.Server/Voting/Managers/VoteManager.cs index 98ad8d8341..90089afb54 100644 --- a/Content.Server/Voting/Managers/VoteManager.cs +++ b/Content.Server/Voting/Managers/VoteManager.cs @@ -16,6 +16,7 @@ using Robust.Server.Player; using Robust.Shared.Configuration; using Robust.Shared.Enums; using Robust.Shared.Network; +using Robust.Shared.Player; using Robust.Shared.Prototypes; using Robust.Shared.Random; using Robust.Shared.Timing; @@ -45,7 +46,7 @@ namespace Content.Server.Voting.Managers private readonly Dictionary _standardVoteTimeout = new(); private readonly Dictionary _voteTimeout = new(); - private readonly HashSet _playerCanCallVoteDirty = new(); + private readonly HashSet _playerCanCallVoteDirty = new(); private readonly StandardVoteType[] _standardVoteTypeValues = Enum.GetValues(); public void Initialize() @@ -106,7 +107,7 @@ namespace Content.Server.Voting.Managers } } - private void CastVote(VoteReg v, IPlayerSession player, int? option) + private void CastVote(VoteReg v, ICommonSession player, int? option) { if (!IsValidOption(v, option)) throw new ArgumentOutOfRangeException(nameof(option), "Invalid vote option ID"); @@ -228,7 +229,7 @@ namespace Content.Server.Voting.Managers private void SendUpdates(VoteReg v) { - foreach (var player in _playerManager.ServerSessions) + foreach (var player in _playerManager.Sessions) { SendSingleUpdate(v, player); } @@ -237,7 +238,7 @@ namespace Content.Server.Voting.Managers v.Dirty = false; } - private void SendSingleUpdate(VoteReg v, IPlayerSession player) + private void SendSingleUpdate(VoteReg v, ICommonSession player) { var msg = new MsgVoteData(); @@ -277,10 +278,10 @@ namespace Content.Server.Voting.Managers private void DirtyCanCallVoteAll() { - _playerCanCallVoteDirty.UnionWith(_playerManager.ServerSessions); + _playerCanCallVoteDirty.UnionWith(_playerManager.Sessions); } - private void SendUpdateCanCallVote(IPlayerSession player) + private void SendUpdateCanCallVote(ICommonSession player) { var msg = new MsgVoteCanCall(); msg.CanCall = CanCallVote(player, null, out var isAdmin, out var timeSpan); @@ -306,7 +307,7 @@ namespace Content.Server.Voting.Managers } private bool CanCallVote( - IPlayerSession initiator, + ICommonSession initiator, StandardVoteType? voteType, out bool isAdmin, out TimeSpan timeSpan) @@ -353,7 +354,7 @@ namespace Content.Server.Voting.Managers return !_voteTimeout.TryGetValue(initiator.UserId, out timeSpan); } - public bool CanCallVote(IPlayerSession initiator, StandardVoteType? voteType = null) + public bool CanCallVote(ICommonSession initiator, StandardVoteType? voteType = null) { return CanCallVote(initiator, voteType, out _, out _); } @@ -406,14 +407,14 @@ namespace Content.Server.Voting.Managers return false; } - private void DirtyCanCallVote(IPlayerSession player) + private void DirtyCanCallVote(ICommonSession player) { _playerCanCallVoteDirty.Add(player); } #region Preset Votes - private void WirePresetVoteInitiator(VoteOptions options, IPlayerSession? player) + private void WirePresetVoteInitiator(VoteOptions options, ICommonSession? player) { if (player != null) { @@ -432,13 +433,13 @@ namespace Content.Server.Voting.Managers private sealed class VoteReg { public readonly int Id; - public readonly Dictionary CastVotes = new(); + public readonly Dictionary CastVotes = new(); public readonly VoteEntry[] Entries; public readonly string Title; public readonly string InitiatorText; public readonly TimeSpan StartTime; public readonly TimeSpan EndTime; - public readonly HashSet VotesDirty = new(); + public readonly HashSet VotesDirty = new(); public bool Cancelled; public bool Finished; @@ -446,10 +447,10 @@ namespace Content.Server.Voting.Managers public VoteFinishedEventHandler? OnFinished; public VoteCancelledEventHandler? OnCancelled; - public IPlayerSession? Initiator { get; } + public ICommonSession? Initiator { get; } public VoteReg(int id, VoteEntry[] entries, string title, string initiatorText, - IPlayerSession? initiator, TimeSpan start, TimeSpan end) + ICommonSession? initiator, TimeSpan start, TimeSpan end) { Id = id; Entries = entries; @@ -517,7 +518,7 @@ namespace Content.Server.Voting.Managers return _mgr.IsValidOption(_reg, optionId); } - public void CastVote(IPlayerSession session, int? optionId) + public void CastVote(ICommonSession session, int? optionId) { _mgr.CastVote(_reg, session, optionId); } diff --git a/Content.Server/Voting/VoteCommands.cs b/Content.Server/Voting/VoteCommands.cs index cb296a7d58..498c9d0494 100644 --- a/Content.Server/Voting/VoteCommands.cs +++ b/Content.Server/Voting/VoteCommands.cs @@ -6,7 +6,6 @@ using Content.Server.Voting.Managers; using Content.Shared.Administration; using Content.Shared.Database; using Content.Shared.Voting; -using Robust.Server.Player; using Robust.Shared.Console; namespace Content.Server.Voting @@ -36,14 +35,14 @@ namespace Content.Server.Voting var mgr = IoCManager.Resolve(); - if (shell.Player != null && !mgr.CanCallVote((IPlayerSession) shell.Player, type)) + if (shell.Player != null && !mgr.CanCallVote(shell.Player, type)) { _adminLogger.Add(LogType.Vote, LogImpact.Medium, $"{shell.Player} failed to start {type.ToString()} vote"); shell.WriteError(Loc.GetString("cmd-createvote-cannot-call-vote-now")); return; } - mgr.CreateStandardVote((IPlayerSession?) shell.Player, type); + mgr.CreateStandardVote(shell.Player, type); } public CompletionResult GetCompletion(IConsoleShell shell, string[] args) @@ -92,7 +91,7 @@ namespace Content.Server.Voting options.Options.Add((args[i], i)); } - options.SetInitiatorOrServer((IPlayerSession?) shell.Player); + options.SetInitiatorOrServer(shell.Player); if (shell.Player != null) _adminLogger.Add(LogType.Vote, LogImpact.Medium, $"{shell.Player} initiated a custom vote: {options.Title} - {string.Join("; ", options.Options.Select(x => x.text))}"); @@ -187,7 +186,7 @@ namespace Content.Server.Voting return; } - vote.CastVote((IPlayerSession) shell.Player!, optionN); + vote.CastVote(shell.Player!, optionN); } } diff --git a/Content.Server/Voting/VoteOptions.cs b/Content.Server/Voting/VoteOptions.cs index 6e6d0465ed..5475d10d32 100644 --- a/Content.Server/Voting/VoteOptions.cs +++ b/Content.Server/Voting/VoteOptions.cs @@ -1,4 +1,4 @@ -using Robust.Server.Player; +using Robust.Shared.Player; namespace Content.Server.Voting @@ -16,7 +16,7 @@ namespace Content.Server.Voting /// /// The player that started the vote. Used to keep track of player cooldowns to avoid vote spam. /// - public IPlayerSession? InitiatorPlayer { get; set; } + public ICommonSession? InitiatorPlayer { get; set; } /// /// The shown title of the vote. @@ -43,13 +43,13 @@ namespace Content.Server.Voting /// Sets and /// by setting the latter to the player's name. /// - public void SetInitiator(IPlayerSession player) + public void SetInitiator(ICommonSession player) { InitiatorPlayer = player; InitiatorText = player.Name; } - public void SetInitiatorOrServer(IPlayerSession? player) + public void SetInitiatorOrServer(ICommonSession? player) { if (player != null) { diff --git a/Content.Server/Weapons/Melee/MeleeWeaponSystem.cs b/Content.Server/Weapons/Melee/MeleeWeaponSystem.cs index 1b6b2ebef1..3d9c3e8219 100644 --- a/Content.Server/Weapons/Melee/MeleeWeaponSystem.cs +++ b/Content.Server/Weapons/Melee/MeleeWeaponSystem.cs @@ -24,11 +24,9 @@ using Content.Shared.StatusEffect; using Content.Shared.Tag; using Content.Shared.Weapons.Melee; using Content.Shared.Weapons.Melee.Events; -using Robust.Server.Player; using Robust.Shared.Audio; using Robust.Shared.Map; using Robust.Shared.Player; -using Robust.Shared.Players; using Robust.Shared.Random; namespace Content.Server.Weapons.Melee; @@ -174,7 +172,7 @@ public sealed class MeleeWeaponSystem : SharedMeleeWeaponSystem EntityCoordinates targetCoordinates; Angle targetLocalAngle; - if (session is IPlayerSession pSession) + if (session is { } pSession) { (targetCoordinates, targetLocalAngle) = _lag.GetCoordinatesAngle(target, pSession); } diff --git a/Content.Server/Wires/WiresSystem.cs b/Content.Server/Wires/WiresSystem.cs index df61e89d4d..b6452efa8a 100644 --- a/Content.Server/Wires/WiresSystem.cs +++ b/Content.Server/Wires/WiresSystem.cs @@ -16,9 +16,10 @@ using Content.Shared.Tools; using Content.Shared.Tools.Components; using Content.Shared.Wires; using Robust.Server.GameObjects; -using Robust.Server.Player; +using Robust.Shared.Player; using Robust.Shared.Prototypes; using Robust.Shared.Random; +using SharedToolSystem = Content.Shared.Tools.Systems.SharedToolSystem; namespace Content.Server.Wires; @@ -615,7 +616,7 @@ public sealed class WiresSystem : SharedWiresSystem wires.WireSeed), ui: ui); } - public void OpenUserInterface(EntityUid uid, IPlayerSession player) + public void OpenUserInterface(EntityUid uid, ICommonSession player) { if (_uiSystem.TryGetUi(uid, WiresUiKey.Key, out var ui)) _uiSystem.OpenUi(ui, player); diff --git a/Content.Server/Worldgen/Systems/Debris/BlobFloorPlanBuilderSystem.cs b/Content.Server/Worldgen/Systems/Debris/BlobFloorPlanBuilderSystem.cs index a90faef995..a09416e593 100644 --- a/Content.Server/Worldgen/Systems/Debris/BlobFloorPlanBuilderSystem.cs +++ b/Content.Server/Worldgen/Systems/Debris/BlobFloorPlanBuilderSystem.cs @@ -14,6 +14,7 @@ public sealed class BlobFloorPlanBuilderSystem : BaseWorldSystem { [Dependency] private readonly IRobustRandom _random = default!; [Dependency] private readonly ITileDefinitionManager _tileDefinition = default!; + [Dependency] private readonly TileSystem _tiles = default!; /// public override void Initialize() @@ -30,6 +31,8 @@ public sealed class BlobFloorPlanBuilderSystem : BaseWorldSystem private void PlaceFloorplanTiles(BlobFloorPlanBuilderComponent comp, MapGridComponent grid) { // NO MORE THAN TWO ALLOCATIONS THANK YOU VERY MUCH. + // TODO: Just put these on a field instead then? + // Also the end of the method has a big LINQ which is gonna blow this out the water. var spawnPoints = new HashSet(comp.FloorPlacements * 6); var taken = new Dictionary(comp.FloorPlacements * 5); @@ -56,7 +59,7 @@ public sealed class BlobFloorPlanBuilderSystem : BaseWorldSystem spawnPoints.Add(west); var tileDef = _tileDefinition[_random.Pick(comp.FloorTileset)]; - taken.Add(point, new Tile(tileDef.TileId, 0, ((ContentTileDefinition)tileDef).PickVariant(_random))); + taken.Add(point, new Tile(tileDef.TileId, 0, _tiles.PickVariant((ContentTileDefinition) tileDef))); } PlaceTile(Vector2i.Zero); diff --git a/Content.Server/Worldgen/Systems/Debris/DebrisFeaturePlacerSystem.cs b/Content.Server/Worldgen/Systems/Debris/DebrisFeaturePlacerSystem.cs index b2d8df4de9..65af0b68cb 100644 --- a/Content.Server/Worldgen/Systems/Debris/DebrisFeaturePlacerSystem.cs +++ b/Content.Server/Worldgen/Systems/Debris/DebrisFeaturePlacerSystem.cs @@ -46,7 +46,7 @@ public sealed class DebrisFeaturePlacerSystem : BaseWorldSystem return; // Redundant logic, prolly needs it's own handler for your custom system. var placer = Comp(component.OwningController); - var xform = Transform(uid); + var xform = args.Component; var ownerXform = Transform(component.OwningController); if (xform.MapUid is null || ownerXform.MapUid is null) return; // not our problem diff --git a/Content.Server/Xenoarchaeology/Equipment/Systems/ArtifactAnalyzerSystem.cs b/Content.Server/Xenoarchaeology/Equipment/Systems/ArtifactAnalyzerSystem.cs index 49036fb19d..9200928d66 100644 --- a/Content.Server/Xenoarchaeology/Equipment/Systems/ArtifactAnalyzerSystem.cs +++ b/Content.Server/Xenoarchaeology/Equipment/Systems/ArtifactAnalyzerSystem.cs @@ -17,7 +17,6 @@ using Content.Shared.Xenoarchaeology.Equipment; using Content.Shared.Xenoarchaeology.XenoArtifacts; using JetBrains.Annotations; using Robust.Server.GameObjects; -using Robust.Server.Player; using Robust.Shared.Audio; using Robust.Shared.Prototypes; using Robust.Shared.Timing; @@ -229,7 +228,7 @@ public sealed class ArtifactAnalyzerSystem : EntitySystem /// private void OnServerSelectionMessage(EntityUid uid, AnalysisConsoleComponent component, AnalysisConsoleServerSelectionMessage args) { - _ui.TryOpen(uid, ResearchClientUiKey.Key, (IPlayerSession) args.Session); + _ui.TryOpen(uid, ResearchClientUiKey.Key, args.Session); } /// diff --git a/Content.Server/Xenoarchaeology/XenoArtifacts/Effects/Systems/FoamArtifactSystem.cs b/Content.Server/Xenoarchaeology/XenoArtifacts/Effects/Systems/FoamArtifactSystem.cs index 93d9d5a01b..2d2c230b12 100644 --- a/Content.Server/Xenoarchaeology/XenoArtifacts/Effects/Systems/FoamArtifactSystem.cs +++ b/Content.Server/Xenoarchaeology/XenoArtifacts/Effects/Systems/FoamArtifactSystem.cs @@ -1,5 +1,4 @@ using System.Linq; -using Content.Server.Chemistry.Components; using Content.Server.Fluids.EntitySystems; using Content.Server.Xenoarchaeology.XenoArtifacts.Effects.Components; using Content.Server.Xenoarchaeology.XenoArtifacts.Events; @@ -38,8 +37,7 @@ public sealed class FoamArtifactSystem : EntitySystem var range = (int) MathF.Round(MathHelper.Lerp(component.MinFoamAmount, component.MaxFoamAmount, _random.NextFloat(0, 1f))); sol.AddReagent(component.SelectedReagent, component.ReagentAmount); var foamEnt = Spawn("Foam", xform.Coordinates); - var smoke = EnsureComp(foamEnt); - smoke.SpreadAmount = range * 4; - _smoke.Start(foamEnt, smoke, sol, component.Duration); + var spreadAmount = range * 4; + _smoke.StartSmoke(foamEnt, sol, component.Duration, spreadAmount); } } diff --git a/Content.Server/Xenoarchaeology/XenoArtifacts/Triggers/Systems/ArtifactMagnetTriggerSystem.cs b/Content.Server/Xenoarchaeology/XenoArtifacts/Triggers/Systems/ArtifactMagnetTriggerSystem.cs index 0220c2ce1a..f51d617df8 100644 --- a/Content.Server/Xenoarchaeology/XenoArtifacts/Triggers/Systems/ArtifactMagnetTriggerSystem.cs +++ b/Content.Server/Xenoarchaeology/XenoArtifacts/Triggers/Systems/ArtifactMagnetTriggerSystem.cs @@ -6,7 +6,7 @@ using Content.Shared.Clothing; namespace Content.Server.Xenoarchaeology.XenoArtifacts.Triggers.Systems; /// -/// This handles... +/// This handles artifacts that are activated by magnets, both salvage and magboots. /// public sealed class ArtifactMagnetTriggerSystem : EntitySystem { @@ -22,20 +22,20 @@ public sealed class ArtifactMagnetTriggerSystem : EntitySystem { base.Update(frameTime); - var artifactQuery = EntityQuery().ToHashSet(); - if (!artifactQuery.Any()) + if (!EntityQuery().Any()) return; List toActivate = new(); //assume that there's more instruments than artifacts var query = EntityQueryEnumerator(); - while (query.MoveNext(out var uid, out var magboot, out var magXform)) + while (query.MoveNext(out _, out var magboot, out var magXform)) { if (!magboot.On) continue; - foreach (var (trigger, xform) in artifactQuery) + var artiQuery = EntityQueryEnumerator(); + while (artiQuery.MoveNext(out var artifactUid, out var trigger, out var xform)) { if (!magXform.Coordinates.TryDistance(EntityManager, xform.Coordinates, out var distance)) continue; @@ -43,7 +43,7 @@ public sealed class ArtifactMagnetTriggerSystem : EntitySystem if (distance > trigger.Range) continue; - toActivate.Add(uid); + toActivate.Add(artifactUid); } } diff --git a/Content.Shared/Actions/SharedActionsSystem.cs b/Content.Shared/Actions/SharedActionsSystem.cs index 9ad155081a..00a17ace25 100644 --- a/Content.Shared/Actions/SharedActionsSystem.cs +++ b/Content.Shared/Actions/SharedActionsSystem.cs @@ -494,6 +494,9 @@ public abstract class SharedActionsSystem : EntitySystem (TryComp(action.Container, out ActionsContainerComponent? containerComp) && containerComp.Container.Contains(actionId))); + if (action.AttachedEntity != null) + RemoveAction(action.AttachedEntity.Value, actionId, action: action); + DebugTools.AssertOwner(performer, comp); comp ??= EnsureComp(performer); action.AttachedEntity = performer; @@ -532,6 +535,26 @@ public abstract class SharedActionsSystem : EntitySystem } } + /// + /// Grants all actions currently contained in some action-container. If the target entity has no action + /// component, this will give them one. + /// + /// Entity to receive the actions + /// The entity that contains thee actions. + public void GrantContainedActions(Entity performer, Entity container) + { + if (!Resolve(container, ref container.Comp)) + return; + + performer.Comp ??= EnsureComp(performer); + + foreach (var actionId in container.Comp.Container.ContainedEntities) + { + if (TryGetActionData(actionId, out var action)) + AddActionDirect(performer, actionId, performer.Comp, action); + } + } + public IEnumerable<(EntityUid Id, BaseActionComponent Comp)> GetActions(EntityUid holderId, ActionsComponent? actions = null) { if (!Resolve(holderId, ref actions, false)) diff --git a/Content.Shared/Administration/Managers/ISharedAdminManager.cs b/Content.Shared/Administration/Managers/ISharedAdminManager.cs index 7e01c81433..22d918d4a3 100644 --- a/Content.Shared/Administration/Managers/ISharedAdminManager.cs +++ b/Content.Shared/Administration/Managers/ISharedAdminManager.cs @@ -1,4 +1,4 @@ -using Robust.Shared.Players; +using Robust.Shared.Player; namespace Content.Shared.Administration.Managers; diff --git a/Content.Shared/Buckle/SharedBuckleSystem.cs b/Content.Shared/Buckle/SharedBuckleSystem.cs index 7edf2448ae..1441745b5d 100644 --- a/Content.Shared/Buckle/SharedBuckleSystem.cs +++ b/Content.Shared/Buckle/SharedBuckleSystem.cs @@ -11,7 +11,7 @@ using Robust.Shared.Containers; using Robust.Shared.Map; using Robust.Shared.Network; using Robust.Shared.Physics.Systems; -using Robust.Shared.Players; +using Robust.Shared.Player; using Robust.Shared.Timing; namespace Content.Shared.Buckle; diff --git a/Content.Shared/Chemistry/Components/SmokeAffectedComponent.cs b/Content.Shared/Chemistry/Components/SmokeAffectedComponent.cs new file mode 100644 index 0000000000..def6940ee1 --- /dev/null +++ b/Content.Shared/Chemistry/Components/SmokeAffectedComponent.cs @@ -0,0 +1,24 @@ +using Robust.Shared.GameStates; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom; + +namespace Content.Shared.Chemistry.Components; + +/// +/// This is used for entities which are currently being affected by smoke. +/// Manages the gradual metabolism every second. +/// +[RegisterComponent, NetworkedComponent] +public sealed partial class SmokeAffectedComponent : Component +{ + /// + /// The time at which the next smoke metabolism will occur. + /// + [DataField(customTypeSerializer: typeof(TimeOffsetSerializer))] + public TimeSpan NextSecond; + + /// + /// The smoke that is currently affecting this entity. + /// + [DataField] + public EntityUid SmokeEntity; +} diff --git a/Content.Shared/Chemistry/Components/SmokeComponent.cs b/Content.Shared/Chemistry/Components/SmokeComponent.cs new file mode 100644 index 0000000000..9d88fcac94 --- /dev/null +++ b/Content.Shared/Chemistry/Components/SmokeComponent.cs @@ -0,0 +1,34 @@ +using Content.Shared.FixedPoint; +using Content.Shared.Fluids.Components; +using Robust.Shared.GameStates; + +namespace Content.Shared.Chemistry.Components; + +/// +/// Stores solution on an anchored entity that has touch and ingestion reactions +/// to entities that collide with it. Similar to +/// +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +public sealed partial class SmokeComponent : Component +{ + public const string SolutionName = "solutionArea"; + + /// + /// The max amount of tiles this smoke cloud can spread to. + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public int SpreadAmount; + + /// + /// The max rate at which chemicals are transferred from the smoke to the person inhaling it. + /// Calculated as (total volume of chemicals in smoke) / () + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public FixedPoint2 TransferRate; + + /// + /// The total lifespan of the smoke. + /// + [DataField, ViewVariables(VVAccess.ReadWrite), AutoNetworkedField] + public float Duration = 10; +} diff --git a/Content.Shared/Climbing/Systems/ClimbSystem.cs b/Content.Shared/Climbing/Systems/ClimbSystem.cs index 511149f8f9..46255e4337 100644 --- a/Content.Shared/Climbing/Systems/ClimbSystem.cs +++ b/Content.Shared/Climbing/Systems/ClimbSystem.cs @@ -257,15 +257,25 @@ public sealed partial class ClimbSystem : VirtualController // Need direction relative to climber's parent. var localDirection = (-parentRot).RotateVec(worldDirection); - climbing.IsClimbing = true; - var climbDuration = TimeSpan.FromSeconds(distance / climbing.TransitionRate); - climbing.NextTransition = _timing.CurTime + climbDuration; + // On top of it already so just do it in place. + if (localDirection.LengthSquared() < 0.01f) + { + climbing.NextTransition = null; + } + // VirtualController over to the thing. + else + { + var climbDuration = TimeSpan.FromSeconds(distance / climbing.TransitionRate); + climbing.NextTransition = _timing.CurTime + climbDuration; - climbing.Direction = localDirection.Normalized() * climbing.TransitionRate; + climbing.Direction = localDirection.Normalized() * climbing.TransitionRate; + _actionBlockerSystem.UpdateCanMove(uid); + } + + climbing.IsClimbing = true; Dirty(uid, climbing); _audio.PlayPredicted(comp.FinishClimbSound, climbable, user); - _actionBlockerSystem.UpdateCanMove(uid); var startEv = new StartClimbEvent(climbable); var climbedEv = new ClimbedOnEvent(uid, user); diff --git a/Content.Shared/Construction/EntitySystems/AnchorableSystem.cs b/Content.Shared/Construction/EntitySystems/AnchorableSystem.cs index 3e1cf5584c..b40c049562 100644 --- a/Content.Shared/Construction/EntitySystems/AnchorableSystem.cs +++ b/Content.Shared/Construction/EntitySystems/AnchorableSystem.cs @@ -18,6 +18,7 @@ using Content.Shared.Tag; using Robust.Shared.Player; using Robust.Shared.Serialization; using Robust.Shared.Utility; +using SharedToolSystem = Content.Shared.Tools.Systems.SharedToolSystem; namespace Content.Shared.Construction.EntitySystems; diff --git a/Content.Shared/Containers/ItemSlot/ItemSlotsComponent.cs b/Content.Shared/Containers/ItemSlot/ItemSlotsComponent.cs index effba18210..9310617634 100644 --- a/Content.Shared/Containers/ItemSlot/ItemSlotsComponent.cs +++ b/Content.Shared/Containers/ItemSlot/ItemSlotsComponent.cs @@ -71,6 +71,9 @@ namespace Content.Shared.Containers.ItemSlots [DataField("whitelist")] public EntityWhitelist? Whitelist; + [DataField("blacklist")] + public EntityWhitelist? Blacklist; + [DataField("insertSound")] public SoundSpecifier InsertSound = new SoundPathSpecifier("/Audio/Weapons/Guns/MagIn/revolver_magin.ogg"); diff --git a/Content.Shared/Containers/ItemSlot/ItemSlotsSystem.cs b/Content.Shared/Containers/ItemSlot/ItemSlotsSystem.cs index 902b56427a..9194a8208e 100644 --- a/Content.Shared/Containers/ItemSlot/ItemSlotsSystem.cs +++ b/Content.Shared/Containers/ItemSlot/ItemSlotsSystem.cs @@ -255,7 +255,7 @@ namespace Content.Shared.Containers.ItemSlots if (!swap && slot.HasItem) return false; - if (slot.Whitelist != null && !slot.Whitelist.IsValid(usedUid)) + if ((slot.Whitelist != null && !slot.Whitelist.IsValid(usedUid)) || (slot.Blacklist != null && slot.Blacklist.IsValid(usedUid))) { if (_netManager.IsClient && _timing.IsFirstTimePredicted && popup.HasValue && !string.IsNullOrWhiteSpace(slot.WhitelistFailPopup)) _popupSystem.PopupEntity(Loc.GetString(slot.WhitelistFailPopup), uid, popup.Value); diff --git a/Content.Shared/Decals/SharedDecalSystem.cs b/Content.Shared/Decals/SharedDecalSystem.cs index 79bf826eed..02f73bdacb 100644 --- a/Content.Shared/Decals/SharedDecalSystem.cs +++ b/Content.Shared/Decals/SharedDecalSystem.cs @@ -1,3 +1,4 @@ +using System.Collections; using System.Diagnostics.CodeAnalysis; using System.Numerics; using Robust.Shared.GameStates; @@ -107,6 +108,18 @@ namespace Content.Shared.Decals { // used by client-side overlay code } + + public virtual HashSet<(uint Index, Decal Decal)> GetDecalsInRange(EntityUid gridId, Vector2 position, float distance = 0.75f, Func? validDelegate = null) + { + // NOOP on client atm. + return new HashSet<(uint Index, Decal Decal)>(); + } + + public virtual bool RemoveDecal(EntityUid gridId, uint decalId, DecalGridComponent? component = null) + { + // NOOP on client atm. + return true; + } } // TODO: Pretty sure paul was moving this somewhere but just so people know diff --git a/Content.Shared/Doors/Systems/SharedDoorBoltSystem.cs b/Content.Shared/Doors/Systems/SharedDoorBoltSystem.cs index a950fe6930..a9a52010fd 100644 --- a/Content.Shared/Doors/Systems/SharedDoorBoltSystem.cs +++ b/Content.Shared/Doors/Systems/SharedDoorBoltSystem.cs @@ -23,11 +23,15 @@ public abstract class SharedDoorBoltSystem : EntitySystem private void OnDoorPry(EntityUid uid, DoorBoltComponent component, ref BeforePryEvent args) { - if (component.BoltsDown && !args.Force) - { - Popup.PopupEntity(Loc.GetString("airlock-component-cannot-pry-is-bolted-message"), uid, args.User); - args.Cancelled = true; - } + if (args.Cancelled) + return; + + if (!component.BoltsDown || args.Force) + return; + + args.Message = "airlock-component-cannot-pry-is-bolted-message"; + + args.Cancelled = true; } private void OnBeforeDoorOpened(EntityUid uid, DoorBoltComponent component, BeforeDoorOpenedEvent args) diff --git a/Content.Shared/Hands/EntitySystems/SharedHandsSystem.Interactions.cs b/Content.Shared/Hands/EntitySystems/SharedHandsSystem.Interactions.cs index d0c3be3b31..dfa72fcfb7 100644 --- a/Content.Shared/Hands/EntitySystems/SharedHandsSystem.Interactions.cs +++ b/Content.Shared/Hands/EntitySystems/SharedHandsSystem.Interactions.cs @@ -6,7 +6,7 @@ using Content.Shared.Input; using Content.Shared.Localizations; using Robust.Shared.Input.Binding; using Robust.Shared.Map; -using Robust.Shared.Players; +using Robust.Shared.Player; namespace Content.Shared.Hands.EntitySystems; diff --git a/Content.Shared/Implants/Components/ImplanterComponent.cs b/Content.Shared/Implants/Components/ImplanterComponent.cs index 85891826f9..32a3636163 100644 --- a/Content.Shared/Implants/Components/ImplanterComponent.cs +++ b/Content.Shared/Implants/Components/ImplanterComponent.cs @@ -1,4 +1,5 @@ using Content.Shared.Containers.ItemSlots; +using Content.Shared.Whitelist; using Robust.Shared.GameStates; using Robust.Shared.Prototypes; using Robust.Shared.Serialization; @@ -15,6 +16,19 @@ public sealed partial class ImplanterComponent : Component public const string ImplanterSlotId = "implanter_slot"; public const string ImplantSlotId = "implant"; + /// + /// Whitelist to check entities against before implanting. + /// Implants get their own whitelist which is checked afterwards. + /// + [DataField, AutoNetworkedField] + public EntityWhitelist? Whitelist; + + /// + /// Blacklist to check entities against before implanting. + /// + [DataField, AutoNetworkedField] + public EntityWhitelist? Blacklist; + /// /// Used for implanters that start with specific implants /// diff --git a/Content.Shared/Implants/Components/SubdermalImplantComponent.cs b/Content.Shared/Implants/Components/SubdermalImplantComponent.cs index b2fdb14e4c..5edc26ead3 100644 --- a/Content.Shared/Implants/Components/SubdermalImplantComponent.cs +++ b/Content.Shared/Implants/Components/SubdermalImplantComponent.cs @@ -1,4 +1,5 @@ using Content.Shared.Actions; +using Content.Shared.Whitelist; using Robust.Shared.GameStates; using Robust.Shared.Prototypes; @@ -34,6 +35,20 @@ public sealed partial class SubdermalImplantComponent : Component [ViewVariables(VVAccess.ReadWrite)] [DataField("permanent"), AutoNetworkedField] public bool Permanent = false; + + /// + /// Target whitelist for this implant specifically. + /// Only checked if the implanter allows implanting on the target to begin with. + /// + [DataField] + public EntityWhitelist? Whitelist; + + /// + /// Target blacklist for this implant specifically. + /// Only checked if the implanter allows implanting on the target to begin with. + /// + [DataField] + public EntityWhitelist? Blacklist; } /// diff --git a/Content.Shared/Implants/SharedImplanterSystem.cs b/Content.Shared/Implants/SharedImplanterSystem.cs index 1cf9f44663..404e6da508 100644 --- a/Content.Shared/Implants/SharedImplanterSystem.cs +++ b/Content.Shared/Implants/SharedImplanterSystem.cs @@ -6,6 +6,7 @@ using Content.Shared.Examine; using Content.Shared.IdentityManagement; using Content.Shared.Implants.Components; using Content.Shared.Popups; +using Content.Shared.Whitelist; using Robust.Shared.Containers; using Robust.Shared.Serialization; @@ -85,11 +86,23 @@ public abstract class SharedImplanterSystem : EntitySystem if (!TryComp(implant, out implantComp)) return false; + if (!CheckTarget(target, component.Whitelist, component.Blacklist) || + !CheckTarget(target, implantComp.Whitelist, implantComp.Blacklist)) + { + return false; + } + var ev = new AddImplantAttemptEvent(user, target, implant.Value, implanter); RaiseLocalEvent(target, ev); return !ev.Cancelled; } + protected bool CheckTarget(EntityUid target, EntityWhitelist? whitelist, EntityWhitelist? blacklist) + { + return whitelist?.IsValid(target, EntityManager) != false && + blacklist?.IsValid(target, EntityManager) != true; + } + //Draw the implant out of the target //TODO: Rework when surgery is in so implant cases can be a thing public void Draw(EntityUid implanter, EntityUid user, EntityUid target, ImplanterComponent component) diff --git a/Content.Shared/Interaction/SharedInteractionSystem.cs b/Content.Shared/Interaction/SharedInteractionSystem.cs index 4a9a43ca2c..7981deaee6 100644 --- a/Content.Shared/Interaction/SharedInteractionSystem.cs +++ b/Content.Shared/Interaction/SharedInteractionSystem.cs @@ -34,7 +34,7 @@ using Robust.Shared.Network; using Robust.Shared.Physics; using Robust.Shared.Physics.Components; using Robust.Shared.Physics.Systems; -using Robust.Shared.Players; +using Robust.Shared.Player; using Robust.Shared.Random; using Robust.Shared.Serialization; using Robust.Shared.Timing; diff --git a/Content.Server/Maps/TileSystem.cs b/Content.Shared/Maps/TileSystem.cs similarity index 68% rename from Content.Server/Maps/TileSystem.cs rename to Content.Shared/Maps/TileSystem.cs index 1423f76d97..2c09375d59 100644 --- a/Content.Server/Maps/TileSystem.cs +++ b/Content.Shared/Maps/TileSystem.cs @@ -1,13 +1,13 @@ +using System.Linq; using System.Numerics; -using Content.Server.Decals; using Content.Shared.Coordinates.Helpers; using Content.Shared.Decals; -using Content.Shared.Maps; using Robust.Shared.Map; using Robust.Shared.Map.Components; using Robust.Shared.Random; +using Robust.Shared.Utility; -namespace Content.Server.Maps; +namespace Content.Shared.Maps; /// /// Handles server-side tile manipulation like prying/deconstructing tiles. @@ -15,15 +15,39 @@ namespace Content.Server.Maps; public sealed class TileSystem : EntitySystem { [Dependency] private readonly IMapManager _mapManager = default!; - [Dependency] private readonly ITileDefinitionManager _tileDefinitionManager = default!; [Dependency] private readonly IRobustRandom _robustRandom = default!; - [Dependency] private readonly DecalSystem _decal = default!; + [Dependency] private readonly ITileDefinitionManager _tileDefinitionManager = default!; + [Dependency] private readonly SharedDecalSystem _decal = default!; + [Dependency] private readonly SharedMapSystem _maps = default!; [Dependency] private readonly TurfSystem _turf = default!; + /// + /// Returns a weighted pick of a tile variant. + /// + public byte PickVariant(ContentTileDefinition tile) + { + var variants = tile.PlacementVariants; + + var sum = variants.Sum(); + var accumulated = 0f; + var rand = _robustRandom.NextFloat() * sum; + + for (byte i = 0; i < variants.Length; ++i) + { + accumulated += variants[i]; + + if (accumulated >= rand) + return i; + } + + // Shouldn't happen + throw new InvalidOperationException($"Invalid weighted variantize tile pick for {tile.ID}!"); + } + public bool PryTile(Vector2i indices, EntityUid gridId) { - var grid = _mapManager.GetGrid(gridId); - var tileRef = grid.GetTileRef(indices); + var grid = Comp(gridId); + var tileRef = _maps.GetTileRef(gridId, grid, indices); return PryTile(tileRef); } @@ -71,16 +95,20 @@ public sealed class TileSystem : EntitySystem public bool ReplaceTile(TileRef tileref, ContentTileDefinition replacementTile, EntityUid grid, MapGridComponent? component = null) { + DebugTools.Assert(tileref.GridUid == grid); + if (!Resolve(grid, ref component)) return false; - var variant = replacementTile.PickVariant(); + + var variant = PickVariant(replacementTile); var decals = _decal.GetDecalsInRange(tileref.GridUid, _turf.GetTileCenter(tileref).Position, 0.5f); foreach (var (id, _) in decals) { _decal.RemoveDecal(tileref.GridUid, id); } - component.SetTile(tileref.GridIndices, new Tile(replacementTile.TileId, 0, variant)); + + _maps.SetTile(grid, component, tileref.GridIndices, new Tile(replacementTile.TileId, 0, variant)); return true; } @@ -94,12 +122,13 @@ public sealed class TileSystem : EntitySystem if (string.IsNullOrEmpty(tileDef.BaseTurf)) return false; - var mapGrid = _mapManager.GetGrid(tileRef.GridUid); + var gridUid = tileRef.GridUid; + var mapGrid = Comp(gridUid); const float margin = 0.1f; var bounds = mapGrid.TileSize - margin * 2; var indices = tileRef.GridIndices; - var coordinates = mapGrid.GridTileToLocal(indices) + var coordinates = _maps.GridTileToLocal(gridUid, mapGrid, indices) .Offset(new Vector2( (_robustRandom.NextFloat() - 0.5f) * bounds, (_robustRandom.NextFloat() - 0.5f) * bounds)); @@ -109,15 +138,14 @@ public sealed class TileSystem : EntitySystem Transform(tileItem).LocalRotation = _robustRandom.NextDouble() * Math.Tau; // Destroy any decals on the tile - var decals = _decal.GetDecalsInRange(tileRef.GridUid, coordinates.SnapToGrid(EntityManager, _mapManager).Position, 0.5f); + var decals = _decal.GetDecalsInRange(gridUid, coordinates.SnapToGrid(EntityManager, _mapManager).Position, 0.5f); foreach (var (id, _) in decals) { _decal.RemoveDecal(tileRef.GridUid, id); } var plating = _tileDefinitionManager[tileDef.BaseTurf]; - - mapGrid.SetTile(tileRef.GridIndices, new Tile(plating.TileId)); + _maps.SetTile(gridUid, mapGrid, tileRef.GridIndices, new Tile(plating.TileId)); return true; } diff --git a/Content.Shared/Maps/TurfHelpers.cs b/Content.Shared/Maps/TurfHelpers.cs index 857244d658..a87b8c97d1 100644 --- a/Content.Shared/Maps/TurfHelpers.cs +++ b/Content.Shared/Maps/TurfHelpers.cs @@ -86,30 +86,6 @@ namespace Content.Shared.Maps return tile.Tile.IsSpace(tileDefinitionManager); } - /// - /// Returns a weighted pick of a tile variant. - /// - public static byte PickVariant(this ContentTileDefinition tile, IRobustRandom? random = null) - { - IoCManager.Resolve(ref random); - var variants = tile.PlacementVariants; - - var sum = variants.Sum(); - var accumulated = 0f; - var rand = random.NextFloat() * sum; - - for (byte i = 0; i < variants.Length; ++i) - { - accumulated += variants[i]; - - if (accumulated >= rand) - return i; - } - - // Shouldn't happen - throw new InvalidOperationException($"Invalid weighted variantize tile pick for {tile.ID}!"); - } - /// /// Helper that returns all entities in a turf. /// diff --git a/Content.Shared/Mind/Components/MindContainerComponent.cs b/Content.Shared/Mind/Components/MindContainerComponent.cs index ca0f14d994..62b26cbd35 100644 --- a/Content.Shared/Mind/Components/MindContainerComponent.cs +++ b/Content.Shared/Mind/Components/MindContainerComponent.cs @@ -1,24 +1,25 @@ using System.Diagnostics.CodeAnalysis; +using Robust.Shared.GameStates; namespace Content.Shared.Mind.Components { /// - /// Stores a on a mob. + /// This component indicates that this entity may have mind, which is simply an entity with a . + /// The mind entity is not actually stored in a "container", but is simply stored in nullspace. /// - [RegisterComponent, Access(typeof(SharedMindSystem))] + [RegisterComponent, Access(typeof(SharedMindSystem)), NetworkedComponent, AutoGenerateComponentState] public sealed partial class MindContainerComponent : Component { /// /// The mind controlling this mob. Can be null. /// - [ViewVariables] + [DataField, AutoNetworkedField] [Access(typeof(SharedMindSystem), Other = AccessPermissions.ReadWriteExecute)] // FIXME Friends public EntityUid? Mind { get; set; } /// /// True if we have a mind, false otherwise. /// - [ViewVariables] [MemberNotNullWhen(true, nameof(Mind))] public bool HasMind => Mind != null; @@ -26,7 +27,7 @@ namespace Content.Shared.Mind.Components /// Whether examining should show information about the mind or not. /// [ViewVariables(VVAccess.ReadWrite)] - [DataField("showExamineInfo")] + [DataField("showExamineInfo"), AutoNetworkedField] public bool ShowExamineInfo { get; set; } /// @@ -38,19 +39,59 @@ namespace Content.Shared.Mind.Components public bool GhostOnShutdown { get; set; } = true; } - public sealed class MindRemovedMessage : EntityEventArgs + public abstract class MindEvent : EntityEventArgs { - public EntityUid OldMindId; - public MindComponent OldMind; + public readonly Entity Mind; + public readonly Entity Container; - public MindRemovedMessage(EntityUid oldMindId, MindComponent oldMind) + public MindEvent(Entity mind, Entity container) { - OldMindId = oldMindId; - OldMind = oldMind; + Mind = mind; + Container = container; } } - public sealed class MindAddedMessage : EntityEventArgs + /// + /// Event raised directed at a mind-container when a mind gets removed. + /// + public sealed class MindRemovedMessage : MindEvent { + public MindRemovedMessage(Entity mind, Entity container) + : base(mind, container) + { + } + } + + /// + /// Event raised directed at a mind when it gets removed from a mind-container. + /// + public sealed class MindGotRemovedEvent : MindEvent + { + public MindGotRemovedEvent(Entity mind, Entity container) + : base(mind, container) + { + } + } + + /// + /// Event raised directed at a mind-container when a mind gets added. + /// + public sealed class MindAddedMessage : MindEvent + { + public MindAddedMessage(Entity mind, Entity container) + : base(mind, container) + { + } + } + + /// + /// Event raised directed at a mind when it gets added to a mind-container. + /// + public sealed class MindGotAddedEvent : MindEvent + { + public MindGotAddedEvent(Entity mind, Entity container) + : base(mind, container) + { + } } } diff --git a/Content.Shared/Mind/MindComponent.cs b/Content.Shared/Mind/MindComponent.cs index 3ea92c3ce7..b147a2dbbe 100644 --- a/Content.Shared/Mind/MindComponent.cs +++ b/Content.Shared/Mind/MindComponent.cs @@ -1,84 +1,86 @@ using Content.Shared.GameTicking; using Content.Shared.Mind.Components; +using Robust.Shared.GameStates; using Robust.Shared.Network; -using Robust.Shared.Players; +using Robust.Shared.Player; namespace Content.Shared.Mind { /// - /// This is added as a component to mind entities, not to player entities. - /// for the one that is added to players. - /// A mind represents the IC "mind" of a player. - /// Roles are attached as components to its owning entity. + /// This component stores information about a player/mob mind. The component will be attached to a mind-entity + /// which is stored in null-space. The entity that is currently "possessed" by the mind will have a + /// . /// /// + /// Roles are attached as components on the mind-entity entity. /// Think of it like this: if a player is supposed to have their memories, /// their mind follows along. /// /// Things such as respawning do not follow, because you're a new character. /// Getting borged, cloned, turned into a catbeast, etc... will keep it following you. + /// + /// Minds are stored in null-space, and are thus generally not set to players unless that player is the owner + /// of the mind. As a result it should be safe to network "secret" information like roles & objectives /// - [RegisterComponent] + [RegisterComponent, NetworkedComponent, AutoGenerateComponentState(true)] public sealed partial class MindComponent : Component { - internal readonly List Objectives = new(); + [DataField, AutoNetworkedField] + public List Objectives = new(); /// /// The session ID of the player owning this mind. /// - [ViewVariables, Access(typeof(SharedMindSystem))] + [DataField, AutoNetworkedField, Access(typeof(SharedMindSystem))] public NetUserId? UserId { get; set; } /// /// The session ID of the original owner, if any. /// May end up used for round-end information (as the owner may have abandoned Mind since) /// - [ViewVariables, Access(typeof(SharedMindSystem))] + [DataField, AutoNetworkedField, Access(typeof(SharedMindSystem))] public NetUserId? OriginalOwnerUserId { get; set; } /// - /// Entity UID for the first entity that this mind controlled. Used for round end. + /// The first entity that this mind controlled. Used for round end information. /// Might be relevant if the player has ghosted since. /// - [ViewVariables] public EntityUid? OriginalOwnedEntity; + [DataField, AutoNetworkedField] + public NetEntity? OriginalOwnedEntity; + // This is a net entity, because this field currently ddoes not get set to null when this entity is deleted. + // This is a lazy way to ensure that people check that the entity still exists. + // TODO MIND Fix this properly by adding an OriginalMindContainerComponent or something like that. [ViewVariables] public bool IsVisitingEntity => VisitingEntity != null; - [ViewVariables, Access(typeof(SharedMindSystem))] + [DataField, AutoNetworkedField, Access(typeof(SharedMindSystem))] public EntityUid? VisitingEntity { get; set; } [ViewVariables] public EntityUid? CurrentEntity => VisitingEntity ?? OwnedEntity; - [ViewVariables(VVAccess.ReadWrite)] + [DataField, AutoNetworkedField, ViewVariables(VVAccess.ReadWrite)] public string? CharacterName { get; set; } /// /// The time of death for this Mind. /// Can be null - will be null if the Mind is not considered "dead". /// - [ViewVariables] + [DataField] public TimeSpan? TimeOfDeath { get; set; } - /// - /// The component currently owned by this mind. - /// Can be null. - /// - [ViewVariables] public MindContainerComponent? OwnedComponent; - /// /// The entity currently owned by this mind. /// Can be null. /// - [ViewVariables, Access(typeof(SharedMindSystem))] + [DataField, AutoNetworkedField, Access(typeof(SharedMindSystem))] public EntityUid? OwnedEntity { get; set; } - // TODO move objectives out of mind component /// /// An enumerable over all the objective entities this mind has. /// - [ViewVariables] + [ViewVariables, Obsolete("Use Objectives field")] public IEnumerable AllObjectives => Objectives; /// @@ -100,6 +102,7 @@ namespace Content.Shared.Mind /// Can be null, in which case the player is currently not logged in. /// [ViewVariables, Access(typeof(SharedMindSystem), typeof(SharedGameTicker))] + // TODO remove this after moving IPlayerManager functions to shared public ICommonSession? Session { get; set; } } } diff --git a/Content.Shared/Mind/SharedMindSystem.cs b/Content.Shared/Mind/SharedMindSystem.cs index cc4ac4af23..8e72d9c741 100644 --- a/Content.Shared/Mind/SharedMindSystem.cs +++ b/Content.Shared/Mind/SharedMindSystem.cs @@ -1,4 +1,5 @@ using System.Diagnostics.CodeAnalysis; +using System.Linq; using Content.Shared.Administration.Logs; using Content.Shared.Database; using Content.Shared.Examine; @@ -12,7 +13,7 @@ using Content.Shared.Objectives.Systems; using Content.Shared.Players; using Robust.Shared.Map; using Robust.Shared.Network; -using Robust.Shared.Players; +using Robust.Shared.Player; using Robust.Shared.Utility; namespace Content.Shared.Mind; @@ -25,7 +26,7 @@ public abstract class SharedMindSystem : EntitySystem [Dependency] private readonly SharedPlayerSystem _player = default!; [Dependency] private readonly MetaDataSystem _metadata = default!; - // This is dictionary is required to track the minds of disconnected players that may have had their entity deleted. + [ViewVariables] protected readonly Dictionary UserMinds = new(); public override void Initialize() @@ -36,6 +37,7 @@ public abstract class SharedMindSystem : EntitySystem SubscribeLocalEvent(OnSuicide); SubscribeLocalEvent(OnVisitingTerminating); SubscribeLocalEvent(OnReset); + SubscribeLocalEvent(OnMindStartup); } public override void Shutdown() @@ -44,6 +46,29 @@ public abstract class SharedMindSystem : EntitySystem WipeAllMinds(); } + private void OnMindStartup(EntityUid uid, MindComponent component, ComponentStartup args) + { + if (component.UserId == null) + return; + + if (UserMinds.TryAdd(component.UserId.Value, uid)) + return; + + var existing = UserMinds[component.UserId.Value]; + if (existing == uid) + return; + + if (!Exists(existing)) + { + Log.Error($"Found deleted entity in mind dictionary while initializing mind {ToPrettyString(uid)}"); + UserMinds[component.UserId.Value] = uid; + return; + } + + Log.Error($"Encountered a user {component.UserId} that is already assigned to a mind while initializing mind {ToPrettyString(uid)}. Ignoring user field."); + component.UserId = null; + } + private void OnReset(RoundRestartCleanupEvent ev) { WipeAllMinds(); @@ -51,12 +76,22 @@ public abstract class SharedMindSystem : EntitySystem public virtual void WipeAllMinds() { - foreach (var mind in UserMinds.Values) + Log.Info($"Wiping all minds"); + foreach (var mind in UserMinds.Values.ToArray()) { WipeMind(mind); } - DebugTools.Assert(UserMinds.Count == 0); + if (UserMinds.Count == 0) + return; + + foreach (var mind in UserMinds.Values) + { + if (Exists(mind)) + Log.Error($"Failed to wipe mind: {ToPrettyString(mind)}"); + } + + UserMinds.Clear(); } public EntityUid? GetMind(NetUserId user) @@ -80,6 +115,26 @@ public abstract class SharedMindSystem : EntitySystem return false; } + public bool TryGetMind(NetUserId user, [NotNullWhen(true)] out Entity? mind) + { + if (!TryGetMind(user, out var mindId, out var mindComp)) + { + mind = null; + return false; + } + + mind = (mindId.Value, mindComp); + return true; + } + + public Entity GetOrCreateMind(NetUserId user) + { + if (!TryGetMind(user, out var mind)) + mind = CreateMind(user); + + return mind.Value; + } + private void OnVisitingTerminating(EntityUid uid, VisitingMindComponent component, ref EntityTerminatingEvent args) { if (component.MindId != null) @@ -92,15 +147,16 @@ public abstract class SharedMindSystem : EntitySystem return; var dead = _mobState.IsDead(uid); + var hasUserId = CompOrNull(mindContainer.Mind)?.UserId; var hasSession = CompOrNull(mindContainer.Mind)?.Session; - if (dead && !mindContainer.HasMind) + if (dead && hasUserId == null) args.PushMarkup($"[color=mediumpurple]{Loc.GetString("comp-mind-examined-dead-and-irrecoverable", ("ent", uid))}[/color]"); else if (dead && hasSession == null) args.PushMarkup($"[color=yellow]{Loc.GetString("comp-mind-examined-dead-and-ssd", ("ent", uid))}[/color]"); else if (dead) args.PushMarkup($"[color=red]{Loc.GetString("comp-mind-examined-dead", ("ent", uid))}[/color]"); - else if (!mindContainer.HasMind) + else if (hasUserId == null) args.PushMarkup($"[color=mediumpurple]{Loc.GetString("comp-mind-examined-catatonic", ("ent", uid))}[/color]"); else if (hasSession == null) args.PushMarkup($"[color=yellow]{Loc.GetString("comp-mind-examined-ssd", ("ent", uid))}[/color]"); @@ -128,7 +184,7 @@ public abstract class SharedMindSystem : EntitySystem return null; } - public EntityUid CreateMind(NetUserId? userId, string? name = null) + public Entity CreateMind(NetUserId? userId, string? name = null) { var mindId = Spawn(null, MapCoordinates.Nullspace); _metadata.SetEntityName(mindId, name == null ? "mind" : $"mind ({name})"); @@ -136,7 +192,7 @@ public abstract class SharedMindSystem : EntitySystem mind.CharacterName = name; SetUserId(mindId, userId, mind); - return mindId; + return (mindId, mind); } /// @@ -195,7 +251,7 @@ public abstract class SharedMindSystem : EntitySystem /// Cleans up the VisitingEntity. /// /// - protected void RemoveVisitingEntity(MindComponent mind) + protected void RemoveVisitingEntity(EntityUid mindId, MindComponent mind) { if (mind.VisitingEntity == null) return; @@ -210,6 +266,7 @@ public abstract class SharedMindSystem : EntitySystem RemCompDeferred(oldVisitingEnt, visitComp); } + Dirty(mindId, mind); RaiseLocalEvent(oldVisitingEnt, new MindUnvisitedMessage(), true); } @@ -228,7 +285,7 @@ public abstract class SharedMindSystem : EntitySystem if (mindId == null || !Resolve(mindId.Value, ref mind, false)) return; - TransferTo(mindId.Value, null, mind: mind); + TransferTo(mindId.Value, null, createGhost:false, mind: mind); SetUserId(mindId.Value, null, mind: mind); } @@ -353,11 +410,11 @@ public abstract class SharedMindSystem : EntitySystem } public bool TryGetMind( - PlayerData player, + ContentPlayerData contentPlayer, out EntityUid mindId, [NotNullWhen(true)] out MindComponent? mind) { - mindId = player.Mind ?? default; + mindId = contentPlayer.Mind ?? default; return TryComp(mindId, out mind); } @@ -391,21 +448,6 @@ public abstract class SharedMindSystem : EntitySystem return TryComp(mindContainer.Mind, out role); } - /// - /// Sets the Mind's OwnedComponent and OwnedEntity - /// - /// Mind to set OwnedComponent and OwnedEntity on - /// Entity owned by - /// MindContainerComponent owned by - protected void SetOwnedEntity(MindComponent mind, EntityUid? uid, MindContainerComponent? mindContainerComponent) - { - if (uid != null) - Resolve(uid.Value, ref mindContainerComponent); - - mind.OwnedEntity = uid; - mind.OwnedComponent = mindContainerComponent; - } - /// /// Sets the Mind's UserId, Session, and updates the player's PlayerData. This should have no direct effect on the /// entity that any mind is connected to, except as a side effect of the fact that it may change a player's diff --git a/Content.Shared/Movement/Events/MoveInputEvent.cs b/Content.Shared/Movement/Events/MoveInputEvent.cs index 8e1b43f8bd..89e5636acd 100644 --- a/Content.Shared/Movement/Events/MoveInputEvent.cs +++ b/Content.Shared/Movement/Events/MoveInputEvent.cs @@ -1,5 +1,3 @@ -using Robust.Shared.Players; - namespace Content.Shared.Movement.Events; /// diff --git a/Content.Shared/Movement/Systems/SharedContentEyeSystem.cs b/Content.Shared/Movement/Systems/SharedContentEyeSystem.cs index 27e0080c87..4b81619fd0 100644 --- a/Content.Shared/Movement/Systems/SharedContentEyeSystem.cs +++ b/Content.Shared/Movement/Systems/SharedContentEyeSystem.cs @@ -5,7 +5,7 @@ using Content.Shared.Ghost; using Content.Shared.Input; using Content.Shared.Movement.Components; using Robust.Shared.Input.Binding; -using Robust.Shared.Players; +using Robust.Shared.Player; using Robust.Shared.Serialization; namespace Content.Shared.Movement.Systems; diff --git a/Content.Shared/Movement/Systems/SharedMoverController.Input.cs b/Content.Shared/Movement/Systems/SharedMoverController.Input.cs index 425322408e..1d323a9187 100644 --- a/Content.Shared/Movement/Systems/SharedMoverController.Input.cs +++ b/Content.Shared/Movement/Systems/SharedMoverController.Input.cs @@ -6,7 +6,7 @@ using Content.Shared.Movement.Components; using Content.Shared.Movement.Events; using Robust.Shared.Input; using Robust.Shared.Input.Binding; -using Robust.Shared.Players; +using Robust.Shared.Player; using Robust.Shared.Serialization; using Robust.Shared.Timing; using Robust.Shared.Utility; diff --git a/Content.Shared/Placeable/ItemPlacerSystem.cs b/Content.Shared/Placeable/ItemPlacerSystem.cs index 92dc8eb74b..ec6ece671f 100644 --- a/Content.Shared/Placeable/ItemPlacerSystem.cs +++ b/Content.Shared/Placeable/ItemPlacerSystem.cs @@ -9,6 +9,7 @@ namespace Content.Shared.Placeable; /// public sealed class ItemPlacerSystem : EntitySystem { + [Dependency] private readonly CollisionWakeSystem _wake = default!; [Dependency] private readonly PlaceableSurfaceSystem _placeableSurface = default!; [Dependency] private readonly SharedPhysicsSystem _physics = default!; @@ -25,8 +26,8 @@ public sealed class ItemPlacerSystem : EntitySystem if (comp.Whitelist != null && !comp.Whitelist.IsValid(args.OtherEntity)) return; - // Disallow sleeping so we can detect when entity is removed from the heater. - _physics.SetSleepingAllowed(args.OtherEntity, args.OtherBody, false); + if (TryComp(uid, out var wakeComp)) + _wake.SetEnabled(uid, false, wakeComp); var count = comp.PlacedEntities.Count; if (comp.MaxEntities == 0 || count < comp.MaxEntities) @@ -46,8 +47,8 @@ public sealed class ItemPlacerSystem : EntitySystem private void OnEndCollide(EntityUid uid, ItemPlacerComponent comp, ref EndCollideEvent args) { - // Re-allow sleeping. - _physics.SetSleepingAllowed(args.OtherEntity, args.OtherBody, true); + if (TryComp(uid, out var wakeComp)) + _wake.SetEnabled(uid, true, wakeComp); comp.PlacedEntities.Remove(args.OtherEntity); diff --git a/Content.Shared/Players/PlayerData.cs b/Content.Shared/Players/ContentPlayerData.cs similarity index 73% rename from Content.Shared/Players/PlayerData.cs rename to Content.Shared/Players/ContentPlayerData.cs index c6274c950b..7545eb58fc 100644 --- a/Content.Shared/Players/PlayerData.cs +++ b/Content.Shared/Players/ContentPlayerData.cs @@ -1,16 +1,15 @@ using Content.Shared.GameTicking; using Content.Shared.Mind; using Robust.Shared.Network; -using Robust.Shared.Player; namespace Content.Shared.Players; /// /// Content side for all data that tracks a player session. -/// Use to retrieve this from an . +/// Use to retrieve this from an . /// Not currently used on the client. /// -public sealed class PlayerData +public sealed class ContentPlayerData { /// /// The session ID of the player owning this data. @@ -38,21 +37,9 @@ public sealed class PlayerData /// public bool ExplicitlyDeadminned { get; set; } - public PlayerData(NetUserId userId, string name) + public ContentPlayerData(NetUserId userId, string name) { UserId = userId; Name = name; } -} - - -public static class PlayerDataExt -{ - /// - /// Gets the correctly cast instance of content player data from an engine player data storage. - /// - public static PlayerData? ContentData(this IPlayerData data) - { - return (PlayerData?) data.ContentDataUncast; - } -} +} \ No newline at end of file diff --git a/Content.Shared/Players/PlayerDataExt.cs b/Content.Shared/Players/PlayerDataExt.cs new file mode 100644 index 0000000000..eba4d8339d --- /dev/null +++ b/Content.Shared/Players/PlayerDataExt.cs @@ -0,0 +1,30 @@ +using Robust.Shared.Player; + +namespace Content.Shared.Players; + +public static class PlayerDataExt +{ + /// + /// Gets the correctly cast instance of content player data from an engine player data storage. + /// + public static ContentPlayerData? ContentData(this SessionData data) + { + return (ContentPlayerData?) data.ContentDataUncast; + } + + /// + /// Gets the correctly cast instance of content player data from an engine player data storage. + /// + public static ContentPlayerData? ContentData(this ICommonSession session) + { + return session.Data.ContentData(); + } + + /// + /// Gets the mind that is associated with this player. + /// + public static EntityUid? GetMind(this ICommonSession session) + { + return session.Data.ContentData()?.Mind; + } +} \ No newline at end of file diff --git a/Content.Shared/Players/SharedPlayerSystem.cs b/Content.Shared/Players/SharedPlayerSystem.cs index 6fc7ad6a40..7271c5688a 100644 --- a/Content.Shared/Players/SharedPlayerSystem.cs +++ b/Content.Shared/Players/SharedPlayerSystem.cs @@ -1,4 +1,4 @@ -using Robust.Shared.Players; +using Robust.Shared.Player; namespace Content.Shared.Players; @@ -8,5 +8,5 @@ namespace Content.Shared.Players; /// public abstract class SharedPlayerSystem : EntitySystem { - public abstract PlayerData? ContentData(ICommonSession? session); + public abstract ContentPlayerData? ContentData(ICommonSession? session); } diff --git a/Content.Shared/Popups/SharedPopupSystem.cs b/Content.Shared/Popups/SharedPopupSystem.cs index 50013a5435..e4565b90e8 100644 --- a/Content.Shared/Popups/SharedPopupSystem.cs +++ b/Content.Shared/Popups/SharedPopupSystem.cs @@ -1,6 +1,5 @@ using Robust.Shared.Map; using Robust.Shared.Player; -using Robust.Shared.Players; using Robust.Shared.Serialization; namespace Content.Shared.Popups diff --git a/Content.Shared/Power/Generator/PowerSwitchableComponent.cs b/Content.Shared/Power/Generator/PowerSwitchableComponent.cs new file mode 100644 index 0000000000..39118b21e5 --- /dev/null +++ b/Content.Shared/Power/Generator/PowerSwitchableComponent.cs @@ -0,0 +1,82 @@ +using Robust.Shared.Audio; +using Robust.Shared.GameStates; +using Robust.Shared.Serialization; + +namespace Content.Shared.Power.Generator; + +/// +/// Enables a device to switch between HV, MV and LV connectors. +/// For generators this means changing output wires. +/// +/// +/// Must have CableDeviceNodes for each output in . +/// If its a generator PowerSupplierComponent is also required. +/// +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +[Access(typeof(SharedPowerSwitchableSystem))] +public sealed partial class PowerSwitchableComponent : Component +{ + /// + /// Index into that the device is currently using. + /// + [DataField, AutoNetworkedField] + public int ActiveIndex; + + /// + /// Sound that plays when the cable is switched. + /// + [DataField] + public SoundSpecifier? SwitchSound = new SoundPathSpecifier("/Audio/Machines/button.ogg"); + + /// + /// Locale id for text shown when examined. + /// It is given "voltage" as a colored voltage string. + /// + [DataField(required: true)] + public string ExamineText = string.Empty; + + /// + /// Locale id for the popup shown when switching voltages. + /// It is given "voltage" as a colored voltage string. + /// + [DataField(required: true)] + public string SwitchText = string.Empty; + + /// + /// Cable voltages and their nodes which can be cycled between. + /// Each node name must match a cable node in its NodeContainer. + /// + [DataField(required: true)] + public List Cables = new(); +} + +/// +/// Cable voltage and node name for cycling. +/// +[DataDefinition] +public sealed partial class PowerSwitchableCable +{ + /// + /// Voltage that the cable uses. + /// + [DataField(required: true)] + public SwitchableVoltage Voltage; + + /// + /// Name of the node for the cable. + /// Must be a CableDeviceNode + /// + [DataField(required: true)] + public string Node = string.Empty; +} + +/// +/// Cable voltage to cycle between. +/// +[Serializable, NetSerializable] +public enum SwitchableVoltage : byte +{ + HV, + MV, + LV +} diff --git a/Content.Shared/Power/Generator/PowerSwitchableGeneratorComponent.cs b/Content.Shared/Power/Generator/PowerSwitchableGeneratorComponent.cs deleted file mode 100644 index 464538f507..0000000000 --- a/Content.Shared/Power/Generator/PowerSwitchableGeneratorComponent.cs +++ /dev/null @@ -1,61 +0,0 @@ -using Robust.Shared.Audio; -using Robust.Shared.GameStates; -using Robust.Shared.Serialization; - -namespace Content.Shared.Power.Generator; - -/// -/// Enables a generator to switch between HV and MV output. -/// -/// -/// Must have CableDeviceNodes for both and , and also a PowerSupplierComponent. -/// -[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] -[Access(typeof(SharedPowerSwitchableGeneratorSystem))] -public sealed partial class PowerSwitchableGeneratorComponent : Component -{ - /// - /// Which output the portable generator is currently connected to. - /// - [DataField("activeOutput")] - [AutoNetworkedField] - public PowerSwitchableGeneratorOutput ActiveOutput { get; set; } - - /// - /// Sound that plays when the output is switched. - /// - /// - [DataField("switchSound")] - public SoundSpecifier? SwitchSound { get; set; } - - /// - /// Which node is the MV output? - /// - [DataField("nodeOutputMV")] - public string NodeOutputMV { get; set; } = "output_mv"; - - /// - /// Which node is the HV output? - /// - [DataField("nodeOutputHV")] - public string NodeOutputHV { get; set; } = "output_hv"; -} - -/// -/// Possible power output for power-switchable generators. -/// -/// -[Serializable, NetSerializable] -public enum PowerSwitchableGeneratorOutput : byte -{ - /// - /// The generator is set to connect to a high-voltage power network. - /// - HV, - - /// - /// The generator is set to connect to a medium-voltage power network. - /// - MV -} - diff --git a/Content.Shared/Power/Generator/SharedPowerSwitchableGeneratorSystem.cs b/Content.Shared/Power/Generator/SharedPowerSwitchableGeneratorSystem.cs deleted file mode 100644 index 5d3793c471..0000000000 --- a/Content.Shared/Power/Generator/SharedPowerSwitchableGeneratorSystem.cs +++ /dev/null @@ -1,23 +0,0 @@ -using Content.Shared.Examine; - -namespace Content.Shared.Power.Generator; - -/// -/// Shared logic for power-switchable generators. -/// -/// -public abstract class SharedPowerSwitchableGeneratorSystem : EntitySystem -{ - public override void Initialize() - { - SubscribeLocalEvent(GeneratorExamined); - } - - private void GeneratorExamined(EntityUid uid, PowerSwitchableGeneratorComponent component, ExaminedEvent args) - { - // Show which output is currently selected. - args.PushMarkup(Loc.GetString( - "power-switchable-generator-examine", - ("output", component.ActiveOutput.ToString()))); - } -} diff --git a/Content.Shared/Power/Generator/SharedPowerSwitchableSystem.cs b/Content.Shared/Power/Generator/SharedPowerSwitchableSystem.cs new file mode 100644 index 0000000000..c1787b6078 --- /dev/null +++ b/Content.Shared/Power/Generator/SharedPowerSwitchableSystem.cs @@ -0,0 +1,72 @@ +using Content.Shared.Examine; + +namespace Content.Shared.Power.Generator; + +/// +/// Shared logic for power-switchable devices. +/// +/// +public abstract class SharedPowerSwitchableSystem : EntitySystem +{ + public override void Initialize() + { + SubscribeLocalEvent(OnExamined); + } + + private void OnExamined(EntityUid uid, PowerSwitchableComponent comp, ExaminedEvent args) + { + // Show which voltage is currently selected. + var voltage = VoltageColor(GetVoltage(uid, comp)); + args.PushMarkup(Loc.GetString(comp.ExamineText, ("voltage", voltage))); + } + + /// + /// Helper to get the colored markup string for a voltage type. + /// + public string VoltageColor(SwitchableVoltage voltage) + { + return Loc.GetString("power-switchable-voltage", ("voltage", VoltageString(voltage))); + } + + /// + /// Converts from "hv" to "HV" since for some reason the enum gets made lowercase??? + /// + public string VoltageString(SwitchableVoltage voltage) + { + return voltage.ToString().ToUpper(); + } + + /// + /// Returns index of the next cable type index to cycle to. + /// + public int NextIndex(EntityUid uid, PowerSwitchableComponent? comp = null) + { + if (!Resolve(uid, ref comp)) + return 0; + + // loop back at the end + return (comp.ActiveIndex + 1) % comp.Cables.Count; + } + + /// + /// Returns the current cable voltage being used by a power-switchable device. + /// + public SwitchableVoltage GetVoltage(EntityUid uid, PowerSwitchableComponent? comp = null) + { + if (!Resolve(uid, ref comp)) + return default; + + return comp.Cables[comp.ActiveIndex].Voltage; + } + + /// + /// Returns the cable's next voltage to cycle to being used by a power-switchable device. + /// + public SwitchableVoltage GetNextVoltage(EntityUid uid, PowerSwitchableComponent? comp = null) + { + if (!Resolve(uid, ref comp)) + return default; + + return comp.Cables[NextIndex(uid, comp)].Voltage; + } +} diff --git a/Content.Shared/Prying/Components/PryingComponent.cs b/Content.Shared/Prying/Components/PryingComponent.cs index 4442481dce..7a7f304d8f 100644 --- a/Content.Shared/Prying/Components/PryingComponent.cs +++ b/Content.Shared/Prying/Components/PryingComponent.cs @@ -51,6 +51,8 @@ public record struct BeforePryEvent(EntityUid User, bool PryPowered, bool Force) public readonly bool Force = Force; + public string? Message; + public bool Cancelled; } diff --git a/Content.Shared/Prying/Systems/PryingSystem.cs b/Content.Shared/Prying/Systems/PryingSystem.cs index 19e63de29e..5fd94c3438 100644 --- a/Content.Shared/Prying/Systems/PryingSystem.cs +++ b/Content.Shared/Prying/Systems/PryingSystem.cs @@ -7,6 +7,7 @@ using Content.Shared.Database; using Content.Shared.Doors.Components; using System.Diagnostics.CodeAnalysis; using Content.Shared.Interaction; +using Content.Shared.Popups; using PryUnpoweredComponent = Content.Shared.Prying.Components.PryUnpoweredComponent; namespace Content.Shared.Prying.Systems; @@ -19,6 +20,7 @@ public sealed class PryingSystem : EntitySystem [Dependency] private readonly ISharedAdminLogManager _adminLog = default!; [Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!; [Dependency] private readonly SharedAudioSystem _audioSystem = default!; + [Dependency] private readonly SharedPopupSystem Popup = default!; public override void Initialize() { @@ -68,10 +70,12 @@ public sealed class PryingSystem : EntitySystem if (!comp.Enabled) return false; - if (!CanPry(target, user, comp)) + if (!CanPry(target, user, out var message, comp)) { + if (message != null) + Popup.PopupEntity(Loc.GetString(message), target, user); // If we have reached this point we want the event that caused this - // to be marked as handled as a popup would be generated on failure. + // to be marked as handled. return true; } @@ -87,15 +91,16 @@ public sealed class PryingSystem : EntitySystem { id = null; - if (!CanPry(target, user)) + // We don't care about displaying a message if no tool was used. + if (!CanPry(target, user, out _)) // If we have reached this point we want the event that caused this - // to be marked as handled as a popup would be generated on failure. + // to be marked as handled. return true; return StartPry(target, user, null, 0.1f, out id); // hand-prying is much slower } - private bool CanPry(EntityUid target, EntityUid user, PryingComponent? comp = null) + private bool CanPry(EntityUid target, EntityUid user, out string? message, PryingComponent? comp = null) { BeforePryEvent canev; @@ -106,15 +111,19 @@ public sealed class PryingSystem : EntitySystem else { if (!TryComp(target, out _)) + { + message = null; return false; + } + canev = new BeforePryEvent(user, false, false); } RaiseLocalEvent(target, ref canev); - if (canev.Cancelled) - return false; - return true; + message = canev.Message; + + return !canev.Cancelled; } private bool StartPry(EntityUid target, EntityUid user, EntityUid? tool, float toolModifier, [NotNullWhen(true)] out DoAfterId? id) diff --git a/Content.Shared/Pulling/Systems/SharedPullingSystem.cs b/Content.Shared/Pulling/Systems/SharedPullingSystem.cs index 6f19d048b4..0c139ee9e3 100644 --- a/Content.Shared/Pulling/Systems/SharedPullingSystem.cs +++ b/Content.Shared/Pulling/Systems/SharedPullingSystem.cs @@ -12,7 +12,7 @@ using Robust.Shared.Map; using Robust.Shared.Physics; using Robust.Shared.Physics.Events; using Robust.Shared.Physics.Systems; -using Robust.Shared.Players; +using Robust.Shared.Player; namespace Content.Shared.Pulling { diff --git a/Content.Shared/Radio/EntitySystems/EncryptionKeySystem.cs b/Content.Shared/Radio/EntitySystems/EncryptionKeySystem.cs index 3d2ce2fd00..eb97fe4113 100644 --- a/Content.Shared/Radio/EntitySystems/EncryptionKeySystem.cs +++ b/Content.Shared/Radio/EntitySystems/EncryptionKeySystem.cs @@ -14,6 +14,7 @@ using Robust.Shared.Network; using Robust.Shared.Prototypes; using Robust.Shared.Serialization; using Robust.Shared.Timing; +using SharedToolSystem = Content.Shared.Tools.Systems.SharedToolSystem; namespace Content.Shared.Radio.EntitySystems; diff --git a/Content.Shared/Roles/Jobs/SharedJobSystem.cs b/Content.Shared/Roles/Jobs/SharedJobSystem.cs index ac18d04e9c..af97ea1350 100644 --- a/Content.Shared/Roles/Jobs/SharedJobSystem.cs +++ b/Content.Shared/Roles/Jobs/SharedJobSystem.cs @@ -2,7 +2,7 @@ using System.Linq; using Content.Shared.Players; using Content.Shared.Players.PlayTimeTracking; -using Robust.Shared.Players; +using Robust.Shared.Player; using Robust.Shared.Prototypes; using Robust.Shared.Utility; diff --git a/Content.Shared/Silicons/Laws/Components/EmagSiliconLawComponent.cs b/Content.Shared/Silicons/Laws/Components/EmagSiliconLawComponent.cs index c6238c067d..f492db4d12 100644 --- a/Content.Shared/Silicons/Laws/Components/EmagSiliconLawComponent.cs +++ b/Content.Shared/Silicons/Laws/Components/EmagSiliconLawComponent.cs @@ -1,12 +1,11 @@ using Content.Shared.Roles; using Robust.Shared.GameStates; -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List; +using Robust.Shared.Prototypes; namespace Content.Shared.Silicons.Laws.Components; /// -/// This is used for an entity that grants a special "obey" law when emagge.d +/// This is used for an entity that grants a special "obey" law when emagged. /// [RegisterComponent, NetworkedComponent, Access(typeof(SharedSiliconLawSystem))] public sealed partial class EmagSiliconLawComponent : Component @@ -14,31 +13,39 @@ public sealed partial class EmagSiliconLawComponent : Component /// /// The name of the person who emagged this law provider. /// - [DataField("ownerName"), ViewVariables(VVAccess.ReadWrite)] + [DataField, ViewVariables(VVAccess.ReadWrite)] public string? OwnerName; /// /// Does the panel need to be open to EMAG this law provider. /// - [DataField("requireOpenPanel"), ViewVariables(VVAccess.ReadWrite)] + [DataField, ViewVariables(VVAccess.ReadWrite)] public bool RequireOpenPanel = true; /// - /// The laws that the borg is given when emagged. + /// The laws that the borg is given when emagged. + /// Law 0 is prepended to this, so this can only include the static laws. /// - [DataField("emagLaws", required: true, customTypeSerializer: typeof(PrototypeIdListSerializer))] - public List EmagLaws = new(); + [DataField(required: true), ViewVariables(VVAccess.ReadWrite)] + public ProtoId EmagLaws = string.Empty; /// - /// How long the borg is stunned when it's emagged. Setting to 0 will disable it. + /// Lawset created from the prototype id and law 0. + /// Cached when getting laws and only modified during an ion storm event. /// - [DataField("stunTime"), ViewVariables(VVAccess.ReadWrite)] + [DataField, ViewVariables(VVAccess.ReadWrite)] + public SiliconLawset? Lawset; + + /// + /// How long the borg is stunned when it's emagged. Setting to 0 will disable it. + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] public TimeSpan StunTime = TimeSpan.Zero; /// /// A role given to entities with this component when they are emagged. /// Mostly just for admin purposes. /// - [DataField("antagonistRole", customTypeSerializer: typeof(PrototypeIdSerializer))] - public string? AntagonistRole = "SubvertedSilicon"; + [DataField] + public ProtoId? AntagonistRole = "SubvertedSilicon"; } diff --git a/Content.Shared/Silicons/Laws/Components/IonStarmTargetComponent.cs b/Content.Shared/Silicons/Laws/Components/IonStarmTargetComponent.cs new file mode 100644 index 0000000000..49ac611ddc --- /dev/null +++ b/Content.Shared/Silicons/Laws/Components/IonStarmTargetComponent.cs @@ -0,0 +1,54 @@ +using Content.Shared.Random; +using Robust.Shared.Prototypes; + +namespace Content.Shared.Silicons.Laws.Components; + +/// +/// During the ion storm event, this entity will have raised on it if it has laws. +/// New laws can be modified in multiple ways depending on the fields below. +/// +[RegisterComponent] +public sealed partial class IonStormTargetComponent : Component +{ + /// + /// for a random lawset to possibly replace the old one with. + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public ProtoId RandomLawsets = "IonStormLawsets"; + + /// + /// Chance for this borg to be affected at all. + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public float Chance = 0.5f; + + /// + /// Chance to replace the lawset with a random one + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public float RandomLawsetChance = 0.25f; + + /// + /// Chance to remove a random law. + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public float RemoveChance = 0.1f; + + /// + /// Chance to replace a random law with the new one, rather than have it be a glitched-order law. + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public float ReplaceChance = 0.1f; + + /// + /// Chance to shuffle laws after everything is done. + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public float ShuffleChance = 0.1f; +} + +/// +/// Raised on an ion storm target to modify its laws. +/// +[ByRefEvent] +public record struct IonStormLawsEvent(SiliconLawset Lawset); diff --git a/Content.Shared/Silicons/Laws/Components/SiliconLawBoundComponent.cs b/Content.Shared/Silicons/Laws/Components/SiliconLawBoundComponent.cs index 955705ae8b..824d057b3e 100644 --- a/Content.Shared/Silicons/Laws/Components/SiliconLawBoundComponent.cs +++ b/Content.Shared/Silicons/Laws/Components/SiliconLawBoundComponent.cs @@ -1,7 +1,6 @@ using Content.Shared.Actions; using Robust.Shared.Prototypes; using Robust.Shared.Serialization; -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; namespace Content.Shared.Silicons.Laws.Components; @@ -14,19 +13,19 @@ public sealed partial class SiliconLawBoundComponent : Component /// /// The sidebar action that toggles the laws screen. /// - [DataField("viewLawsAction", customTypeSerializer: typeof(PrototypeIdSerializer))] - public string ViewLawsAction = "ActionViewLaws"; + [DataField] + public EntProtoId ViewLawsAction = "ActionViewLaws"; /// /// The action for toggling laws. Stored here so we can remove it later. /// - [DataField("viewLawsActionEntity")] + [DataField] public EntityUid? ViewLawsActionEntity; /// /// The last entity that provided laws to this entity. /// - [DataField("lastLawProvider")] + [DataField] public EntityUid? LastLawProvider; } @@ -43,7 +42,7 @@ public record struct GetSiliconLawsEvent(EntityUid Entity) { public EntityUid Entity = Entity; - public readonly List Laws = new(); + public SiliconLawset Laws = new(); public bool Handled = false; } diff --git a/Content.Shared/Silicons/Laws/Components/SiliconLawProviderComponent.cs b/Content.Shared/Silicons/Laws/Components/SiliconLawProviderComponent.cs index e3302dc620..3aaf965aee 100644 --- a/Content.Shared/Silicons/Laws/Components/SiliconLawProviderComponent.cs +++ b/Content.Shared/Silicons/Laws/Components/SiliconLawProviderComponent.cs @@ -1,4 +1,4 @@ -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List; +using Robust.Shared.Prototypes; namespace Content.Shared.Silicons.Laws.Components; @@ -9,8 +9,15 @@ namespace Content.Shared.Silicons.Laws.Components; public sealed partial class SiliconLawProviderComponent : Component { /// - /// The laws that are provided. + /// The id of the lawset that is being provided. /// - [DataField("laws", required: true, customTypeSerializer: typeof(PrototypeIdListSerializer))] - public List Laws = new(); + [DataField(required: true)] + public ProtoId Laws = string.Empty; + + /// + /// Lawset created from the prototype id. + /// Cached when getting laws and only modified during an ion storm event. + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public SiliconLawset? Lawset; } diff --git a/Content.Shared/Silicons/Laws/SiliconLawPrototype.cs b/Content.Shared/Silicons/Laws/SiliconLawPrototype.cs index 86bea20fa0..f6407be5c7 100644 --- a/Content.Shared/Silicons/Laws/SiliconLawPrototype.cs +++ b/Content.Shared/Silicons/Laws/SiliconLawPrototype.cs @@ -11,7 +11,7 @@ public partial class SiliconLaw : IComparable /// /// A locale string which is the actual text of the law. /// - [DataField("lawString", required: true)] + [DataField(required: true), ViewVariables(VVAccess.ReadWrite)] public string LawString = string.Empty; /// @@ -22,13 +22,13 @@ public partial class SiliconLaw : IComparable /// This is a fixedpoint2 only for the niche case of supporting laws that go between 0 and 1. /// Funny. /// - [DataField("order", required: true)] + [DataField(required: true), ViewVariables(VVAccess.ReadWrite)] public FixedPoint2 Order; /// /// An identifier that overrides in the law menu UI. /// - [DataField("lawIdentifierOverride")] + [DataField, ViewVariables(VVAccess.ReadWrite)] public string? LawIdentifierOverride; public int CompareTo(SiliconLaw? other) @@ -38,6 +38,19 @@ public partial class SiliconLaw : IComparable return Order.CompareTo(other.Order); } + + /// + /// Return a shallow clone of this law. + /// + public SiliconLaw ShallowClone() + { + return new SiliconLaw() + { + LawString = LawString, + Order = Order, + LawIdentifierOverride = LawIdentifierOverride + }; + } } /// @@ -50,6 +63,4 @@ public sealed class SiliconLawPrototype : SiliconLaw, IPrototype /// [IdDataField] public string ID { get; private set; } = default!; - - } diff --git a/Content.Shared/Silicons/Laws/SiliconLawsetPrototype.cs b/Content.Shared/Silicons/Laws/SiliconLawsetPrototype.cs new file mode 100644 index 0000000000..abb5b338db --- /dev/null +++ b/Content.Shared/Silicons/Laws/SiliconLawsetPrototype.cs @@ -0,0 +1,69 @@ +using Content.Shared.FixedPoint; +using Robust.Shared.Prototypes; +using Robust.Shared.Serialization; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List; + +namespace Content.Shared.Silicons.Laws; + +/// +/// Lawset data used internally. +/// +[DataDefinition, Serializable, NetSerializable] +public sealed partial class SiliconLawset +{ + /// + /// List of laws in this lawset. + /// + [DataField(required: true), ViewVariables(VVAccess.ReadWrite)] + public List Laws = new(); + + /// + /// A single line used in logging laws. + /// + public string LoggingString() + { + var laws = new List(Laws.Count); + foreach (var law in Laws) + { + laws.Add($"{law.Order}: {Loc.GetString(law.LawString)}"); + } + + return string.Join(" / ", laws); + } + + /// + /// Do a clone of this lawset. + /// It will have unique laws but their strings are still shared. + /// + public SiliconLawset Clone() + { + var laws = new List(Laws.Count); + foreach (var law in Laws) + { + laws.Add(law.ShallowClone()); + } + + return new SiliconLawset() + { + Laws = laws + }; + } +} + +/// +/// This is a prototype for a list. +/// Cannot be used directly since it is a list of prototype ids rather than List. +/// +[Prototype("siliconLawset"), Serializable, NetSerializable] +public sealed partial class SiliconLawsetPrototype : IPrototype +{ + /// + [IdDataField] + public string ID { get; private set; } = default!; + + /// + /// List of law prototype ids in this lawset. + /// + [DataField(required: true, customTypeSerializer: typeof(PrototypeIdListSerializer))] + public List Laws = new(); +} diff --git a/Content.Shared/Storage/Components/MagnetPickupComponent.cs b/Content.Shared/Storage/Components/MagnetPickupComponent.cs index 300055a62a..c57b7c4e85 100644 --- a/Content.Shared/Storage/Components/MagnetPickupComponent.cs +++ b/Content.Shared/Storage/Components/MagnetPickupComponent.cs @@ -1,6 +1,4 @@ using Content.Shared.Inventory; -using Content.Shared.Tag; -using Content.Shared.Whitelist; namespace Content.Server.Storage.Components; @@ -21,16 +19,4 @@ public sealed partial class MagnetPickupComponent : Component [ViewVariables(VVAccess.ReadWrite), DataField("range")] public float Range = 1f; - - [ValidatePrototypeId] - private const string DefaultTag = "Ore"; - - [ViewVariables(VVAccess.ReadWrite), DataField("whitelist")] - public EntityWhitelist? Whitelist = new() - { - Tags = new List() - { - DefaultTag, - } - }; } diff --git a/Content.Shared/Storage/EntitySystems/MagnetPickupSystem.cs b/Content.Shared/Storage/EntitySystems/MagnetPickupSystem.cs index 3bbc75732e..16657bdae4 100644 --- a/Content.Shared/Storage/EntitySystems/MagnetPickupSystem.cs +++ b/Content.Shared/Storage/EntitySystems/MagnetPickupSystem.cs @@ -72,7 +72,7 @@ public sealed class MagnetPickupSystem : EntitySystem foreach (var near in _lookup.GetEntitiesInRange(uid, comp.Range, LookupFlags.Dynamic | LookupFlags.Sundries)) { - if (comp.Whitelist?.IsValid(near, EntityManager) == false) + if (storage.Whitelist?.IsValid(near, EntityManager) == false) continue; if (!_physicsQuery.TryGetComponent(near, out var physics) || physics.BodyStatus != BodyStatus.OnGround) diff --git a/Content.Shared/SubFloor/SharedSubFloorHideSystem.cs b/Content.Shared/SubFloor/SharedSubFloorHideSystem.cs index 0fd7a2e932..02b4e61790 100644 --- a/Content.Shared/SubFloor/SharedSubFloorHideSystem.cs +++ b/Content.Shared/SubFloor/SharedSubFloorHideSystem.cs @@ -24,7 +24,6 @@ namespace Content.Shared.SubFloor { base.Initialize(); - SubscribeLocalEvent(OnGridChanged); SubscribeLocalEvent(OnTileChanged); SubscribeLocalEvent(OnSubFloorStarted); SubscribeLocalEvent(OnSubFloorTerminating); @@ -97,14 +96,6 @@ namespace Content.Shared.SubFloor UpdateTile(MapManager.GetGrid(args.NewTile.GridUid), args.NewTile.GridIndices); } - private void OnGridChanged(GridModifiedEvent args) - { - foreach (var modified in args.Modified) - { - UpdateTile(args.Grid, modified.position); - } - } - /// /// Update whether a given entity is currently covered by a floor tile. /// diff --git a/Content.Shared/Tools/Components/TilePryingComponent.cs b/Content.Shared/Tools/Components/TilePryingComponent.cs new file mode 100644 index 0000000000..4c123ca1ed --- /dev/null +++ b/Content.Shared/Tools/Components/TilePryingComponent.cs @@ -0,0 +1,26 @@ +using Robust.Shared.GameStates; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; + +namespace Content.Shared.Tools.Components; + +/// +/// Allows prying tiles up on a grid. +/// +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +public sealed partial class TilePryingComponent : Component +{ + [DataField("toolComponentNeeded"), AutoNetworkedField] + public bool ToolComponentNeeded = true; + + [DataField("qualityNeeded", customTypeSerializer:typeof(PrototypeIdSerializer)), AutoNetworkedField] + public string QualityNeeded = "Prying"; + + /// + /// Whether this tool can pry tiles with CanAxe. + /// + [DataField("advanced"), AutoNetworkedField] + public bool Advanced = false; + + [DataField("delay"), AutoNetworkedField] + public float Delay = 1f; +} diff --git a/Content.Shared/Tools/Systems/SharedToolSystem.MultipleTool.cs b/Content.Shared/Tools/Systems/SharedToolSystem.MultipleTool.cs index 39a1dc50f3..cb8830060a 100644 --- a/Content.Shared/Tools/Systems/SharedToolSystem.MultipleTool.cs +++ b/Content.Shared/Tools/Systems/SharedToolSystem.MultipleTool.cs @@ -1,9 +1,9 @@ using System.Linq; using Content.Shared.Interaction; -using Content.Shared.Tools.Components; using Content.Shared.Prying.Components; +using Content.Shared.Tools.Components; -namespace Content.Shared.Tools; +namespace Content.Shared.Tools.Systems; public abstract partial class SharedToolSystem : EntitySystem { diff --git a/Content.Server/Tools/ToolSystem.TilePrying.cs b/Content.Shared/Tools/Systems/SharedToolSystem.TilePrying.cs similarity index 66% rename from Content.Server/Tools/ToolSystem.TilePrying.cs rename to Content.Shared/Tools/Systems/SharedToolSystem.TilePrying.cs index faaed6abb8..81592f5a98 100644 --- a/Content.Server/Tools/ToolSystem.TilePrying.cs +++ b/Content.Shared/Tools/Systems/SharedToolSystem.TilePrying.cs @@ -1,17 +1,15 @@ -using Content.Server.Tools.Components; using Content.Shared.Database; using Content.Shared.Fluids.Components; using Content.Shared.Interaction; using Content.Shared.Maps; using Content.Shared.Tools.Components; using Robust.Shared.Map; +using Robust.Shared.Map.Components; -namespace Content.Server.Tools; +namespace Content.Shared.Tools.Systems; -public sealed partial class ToolSystem +public abstract partial class SharedToolSystem { - [Dependency] private readonly SharedInteractionSystem _interactionSystem = default!; - private void InitializeTilePrying() { SubscribeLocalEvent(OnTilePryingAfterInteract); @@ -20,7 +18,8 @@ public sealed partial class ToolSystem private void OnTilePryingAfterInteract(EntityUid uid, TilePryingComponent component, AfterInteractEvent args) { - if (args.Handled || !args.CanReach || (args.Target != null && !HasComp(args.Target))) return; + if (args.Handled || !args.CanReach || args.Target != null && !HasComp(args.Target)) + return; if (TryPryTile(uid, args.User, component, args.ClickLocation)) args.Handled = true; @@ -33,26 +32,28 @@ public sealed partial class ToolSystem var coords = GetCoordinates(args.Coordinates); var gridUid = coords.GetGridUid(EntityManager); - if (!_mapManager.TryGetGrid(gridUid, out var grid)) + if (!TryComp(gridUid, out MapGridComponent? grid)) { Log.Error("Attempted to pry from a non-existent grid?"); return; } - var tile = grid.GetTileRef(coords); - var center = _turf.GetTileCenter(tile); + var tile = _maps.GetTileRef(gridUid.Value, grid, coords); + var center = _turfs.GetTileCenter(tile); + if (args.Used != null) { _adminLogger.Add(LogType.Tile, LogImpact.Low, - $"{ToPrettyString(args.User):actor} used {ToPrettyString(args.Used.Value):tool} to pry {_tileDefinitionManager[tile.Tile.TypeId].Name} at {center}"); + $"{ToPrettyString(args.User):actor} used {ToPrettyString(args.Used.Value):tool} to pry {_tileDefManager[tile.Tile.TypeId].Name} at {center}"); } else { _adminLogger.Add(LogType.Tile, LogImpact.Low, - $"{ToPrettyString(args.User):actor} pried {_tileDefinitionManager[tile.Tile.TypeId].Name} at {center}"); + $"{ToPrettyString(args.User):actor} pried {_tileDefManager[tile.Tile.TypeId].Name} at {center}"); } - _tile.PryTile(tile, component.Advanced); + if (_netManager.IsServer) + _tiles.PryTile(tile, component.Advanced); } private bool TryPryTile(EntityUid toolEntity, EntityUid user, TilePryingComponent component, EntityCoordinates clickLocation) @@ -60,17 +61,16 @@ public sealed partial class ToolSystem if (!TryComp(toolEntity, out var tool) && component.ToolComponentNeeded) return false; - if (!_mapManager.TryFindGridAt(clickLocation.ToMap(EntityManager, _transformSystem), out _, out var mapGrid)) + if (!_mapManager.TryFindGridAt(clickLocation.ToMap(EntityManager, _transformSystem), out var gridUid, out var mapGrid)) return false; - var tile = mapGrid.GetTileRef(clickLocation); + var tile = _maps.GetTileRef(gridUid, mapGrid, clickLocation); + var coordinates = _maps.GridTileToLocal(gridUid, mapGrid, tile.GridIndices); - var coordinates = mapGrid.GridTileToLocal(tile.GridIndices); - - if (!_interactionSystem.InRangeUnobstructed(user, coordinates, popup: false)) + if (!InteractionSystem.InRangeUnobstructed(user, coordinates, popup: false)) return false; - var tileDef = (ContentTileDefinition)_tileDefinitionManager[tile.Tile.TypeId]; + var tileDef = (ContentTileDefinition) _tileDefManager[tile.Tile.TypeId]; if (!tileDef.CanCrowbar && !(tileDef.CanAxe && component.Advanced)) return false; diff --git a/Content.Shared/Tools/Systems/SharedToolSystem.cs b/Content.Shared/Tools/Systems/SharedToolSystem.cs index 716a9332d0..c1a2bdc2dd 100644 --- a/Content.Shared/Tools/Systems/SharedToolSystem.cs +++ b/Content.Shared/Tools/Systems/SharedToolSystem.cs @@ -1,22 +1,35 @@ +using Content.Shared.Administration.Logs; using Content.Shared.DoAfter; +using Content.Shared.Interaction; +using Content.Shared.Maps; using Content.Shared.Tools.Components; using Robust.Shared.Map; +using Robust.Shared.Network; using Robust.Shared.Prototypes; using Robust.Shared.Serialization; -using Robust.Shared.Timing; using Robust.Shared.Utility; -namespace Content.Shared.Tools; +namespace Content.Shared.Tools.Systems; public abstract partial class SharedToolSystem : EntitySystem { - [Dependency] private readonly IPrototypeManager _protoMan = default!; - [Dependency] private readonly SharedAudioSystem _audioSystem = default!; - [Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!; + [Dependency] private readonly IMapManager _mapManager = default!; + [Dependency] private readonly INetManager _netManager = default!; + [Dependency] private readonly IPrototypeManager _protoMan = default!; + [Dependency] private readonly ISharedAdminLogManager _adminLogger = default!; + [Dependency] private readonly ITileDefinitionManager _tileDefManager = default!; + [Dependency] private readonly SharedAudioSystem _audioSystem = default!; + [Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!; + [Dependency] protected readonly SharedInteractionSystem InteractionSystem = default!; + [Dependency] private readonly SharedMapSystem _maps = default!; + [Dependency] private readonly SharedTransformSystem _transformSystem = default!; + [Dependency] private readonly TileSystem _tiles = default!; + [Dependency] private readonly TurfSystem _turfs = default!; public override void Initialize() { InitializeMultipleTool(); + InitializeTilePrying(); SubscribeLocalEvent(OnDoAfter); } diff --git a/Content.Shared/Weapons/Melee/SharedMeleeWeaponSystem.cs b/Content.Shared/Weapons/Melee/SharedMeleeWeaponSystem.cs index 4b740b8d3c..62af6067d0 100644 --- a/Content.Shared/Weapons/Melee/SharedMeleeWeaponSystem.cs +++ b/Content.Shared/Weapons/Melee/SharedMeleeWeaponSystem.cs @@ -23,7 +23,7 @@ using Robust.Shared.Audio; using Robust.Shared.Map; using Robust.Shared.Physics; using Robust.Shared.Physics.Systems; -using Robust.Shared.Players; +using Robust.Shared.Player; using Robust.Shared.Prototypes; using Robust.Shared.Timing; diff --git a/Corvax/Content.Corvax.Interfaces.Server/IServerDiscordAuthManager.cs b/Corvax/Content.Corvax.Interfaces.Server/IServerDiscordAuthManager.cs index 1ec680877f..95660f69c1 100644 --- a/Corvax/Content.Corvax.Interfaces.Server/IServerDiscordAuthManager.cs +++ b/Corvax/Content.Corvax.Interfaces.Server/IServerDiscordAuthManager.cs @@ -1,12 +1,13 @@ using Content.Corvax.Interfaces.Shared; using Robust.Server.Player; using Robust.Shared.Network; +using Robust.Shared.Player; namespace Content.Corvax.Interfaces.Server; public interface IServerDiscordAuthManager : ISharedDiscordAuthManager { - public event EventHandler? PlayerVerified; + public event EventHandler? PlayerVerified; public Task GenerateAuthLink(NetUserId userId, CancellationToken cancel); public Task IsVerified(NetUserId userId, CancellationToken cancel); } diff --git a/Resources/Audio/Ambience/Antag/attributions.yml b/Resources/Audio/Ambience/Antag/attributions.yml index 3d7d5c737c..0a4a0479d1 100644 --- a/Resources/Audio/Ambience/Antag/attributions.yml +++ b/Resources/Audio/Ambience/Antag/attributions.yml @@ -9,4 +9,8 @@ - files: ["zombie_start.ogg"] license: "CC-BY-NC-SA-3.0" copyright: "Made by @MIXnikita#1474 (Discord) for SS14" - source: "https://github.com/SerbiaStrong-220/space-station-14/commit/f33ce80db9d8ac962ec36eb5ae61afa8c0035d1a" \ No newline at end of file + source: "https://github.com/SerbiaStrong-220/space-station-14/commit/f33ce80db9d8ac962ec36eb5ae61afa8c0035d1a" +- files: ["headrev_start.ogg"] + license: "CC0-1.0" + copyright: "Made by https://www.youtube.com/@a-guy173" + source: https://github.com/A-Guy173/Music/blob/main/revolution.mp3 diff --git a/Resources/Audio/Ambience/Antag/headrev_start.ogg b/Resources/Audio/Ambience/Antag/headrev_start.ogg new file mode 100644 index 0000000000..f97ab15a3e Binary files /dev/null and b/Resources/Audio/Ambience/Antag/headrev_start.ogg differ diff --git a/Resources/Audio/Announcements/attributions.yml b/Resources/Audio/Announcements/attributions.yml new file mode 100644 index 0000000000..b65f758615 --- /dev/null +++ b/Resources/Audio/Announcements/attributions.yml @@ -0,0 +1,4 @@ +- files: ["ion_storm.ogg"] + license: "CC-BY-SA-3.0" + copyright: "tgstation" + source: "https://github.com/tgstation/tgstation/blob/b77fa8c2a2490b43bf9174271ebfad72c4782d98/sound/ai/default/ionstorm.ogg" diff --git a/Resources/Audio/Announcements/ion_storm.ogg b/Resources/Audio/Announcements/ion_storm.ogg new file mode 100644 index 0000000000..9f39713de6 Binary files /dev/null and b/Resources/Audio/Announcements/ion_storm.ogg differ diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 5f4b71deaa..507d3badcc 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,188 +1,4 @@ Entries: -- author: onoira - changes: - - {message: Spare pieces have been added to checkerboards allowing for more playable - variants., type: Tweak} - id: 4543 - time: '2023-08-13T07:10:10.0000000+00:00' -- author: Doru991 - changes: - - {message: Composting high-potency plants refills tray nutrients much more effectively., - type: Tweak} - id: 4544 - time: '2023-08-13T07:10:22.0000000+00:00' -- author: Nimfar11 - changes: - - {message: Adds a Secret Door for construction, type: Add} - id: 4545 - time: '2023-08-13T07:10:46.0000000+00:00' -- author: Errant - changes: - - {message: Bolas are now easier to make and more durable., type: Tweak} - id: 4546 - time: '2023-08-13T07:11:11.0000000+00:00' -- author: Doru991 - changes: - - {message: 'Wheelchairs, unicycles and similar vehicles no longer act as a magical - barrier against stuns.', type: Fix} - - {message: Driving while asleep is no longer possible., type: Fix} - id: 4547 - time: '2023-08-13T07:13:19.0000000+00:00' -- author: Potato1234_x - changes: - - {message: Vending machine sprites have been polished up., type: Tweak} - id: 4548 - time: '2023-08-13T07:15:13.0000000+00:00' -- author: Ilya246 - changes: - - {message: 'Blood-red magboots now slow you down less and have jetpack functionality, - but cost more.', type: Tweak} - id: 4549 - time: '2023-08-13T07:17:10.0000000+00:00' -- author: brainfood1183 - changes: - - {message: Syndicate clowns may now purchase a holoclown injector via their syndicate - uplink., type: Add} - id: 4550 - time: '2023-08-13T07:18:10.0000000+00:00' -- author: Errant - changes: - - {message: The various laser guns are now called rifles or pistols., type: Tweak} - - {message: Retro laser blasters now deal 20% more damage., type: Tweak} - - {message: Laser deliveries now contain 3 laser rifles instead of 3 retro laser - blasters., type: Tweak} - id: 4551 - time: '2023-08-13T07:18:49.0000000+00:00' -- author: chromiumboy - changes: - - {message: Added guidebook entries for the Access Configurator and how to install - Airlock Safeguards, type: Add} - id: 4552 - time: '2023-08-13T07:19:28.0000000+00:00' -- author: CrigCrag - changes: - - {message: 'Space Station staff are no longer immune to the toxic and caustic effects - of some pyrotechnic chemicals, as well as bleach. Drinking bleach now makes - you scream as your stomach lining is reduced to goop.', type: Tweak} - - {message: Phenol is now (accurately) toxic., type: Tweak} - id: 4553 - time: '2023-08-13T07:22:08.0000000+00:00' -- author: CrigCrag - changes: - - {message: Added jugs to the medical fabricator., type: Add} - - {message: Jugs now take up more space in bags., type: Tweak} - id: 4554 - time: '2023-08-13T07:23:37.0000000+00:00' -- author: CrigCrag - changes: - - {message: Many basic elements from the periodic table are now mildly toxic or - caustic. Watch what you drink!, type: Tweak} - - {message: Crewmembers who drink lithium have reported very minor cases of serious - brain damage. Doctors should watch out for people who are laughing and screaming - at nothing., type: Tweak} - id: 4555 - time: '2023-08-13T07:24:11.0000000+00:00' -- author: CrigCrag - changes: - - {message: 'Nanotrasen stopped watering down their acid to save money. Drinking - or injecting acids is more dangerous now, and acids burn through your insides - much quicker.', type: Tweak} - - {message: Having corrosive acid in your body now makes you scream!, type: Tweak} - - {message: Polytrinic acid now requires plasma to make., type: Tweak} - id: 4556 - time: '2023-08-13T07:24:50.0000000+00:00' -- author: PixelTK - changes: - - {message: Arachnids have received several changes. Check your local PR station - for more details., type: Tweak} - id: 4557 - time: '2023-08-13T07:38:05.0000000+00:00' -- author: PixelTK - changes: - - {message: 'Nanotrasen have fixed their accidental breakage of time space continuum, - making sure that steel tiles do indeed take steel to create.', type: Fix} - id: 4558 - time: '2023-08-13T12:43:01.0000000+00:00' -- author: FillerVK - changes: - - {message: Added cocoa cultivation, type: Add} - - {message: Added a recipe for creating a chocolate bar, type: Add} - id: 4559 - time: '2023-08-13T14:35:58.0000000+00:00' -- author: Vordenburg - changes: - - {message: Player icons in the end-of-round summary window should now display properly., - type: Fix} - id: 4560 - time: '2023-08-13T16:55:05.0000000+00:00' -- author: EmoGarbage404 - changes: - - {message: The DNA scrambler no longer has the power of magically transforming - various creatures into humanoids., type: Fix} - id: 4561 - time: '2023-08-13T16:56:21.0000000+00:00' -- author: Repo - changes: - - {message: fixed pressure tanks to not show scientific notation., type: Fix} - id: 4562 - time: '2023-08-13T16:56:30.0000000+00:00' -- author: Cripes - changes: - - {message: 'Paper stamps have been heavily tweaked with new looks, now each paper - will lay out the stamps slightly differently and with an overlap.', type: Tweak} - id: 4563 - time: '2023-08-13T18:28:10.0000000+00:00' -- author: PixelTheKermit - changes: - - {message: Arachnid zombies no longer get functional hands., type: Fix} - id: 4564 - time: '2023-08-13T19:51:21.0000000+00:00' -- author: ElectroJr - changes: - - {message: 'Fixed a bug causing inventory slots to sometimes ignore interactions - (e.g., not opening the context menu).', type: Fix} - id: 4565 - time: '2023-08-13T21:55:18.0000000+00:00' -- author: DrSmugleaf - changes: - - {message: Fix "remove single hand" admin smite having gone missing., type: Fix} - - {message: Fix "remove hands" admin smite popup message., type: Fix} - id: 4566 - time: '2023-08-13T22:50:58.0000000+00:00' -- author: DrSmugleaf - changes: - - {message: AHelps now show a typing indicator to admins., type: Tweak} - id: 4567 - time: '2023-08-13T23:03:17.0000000+00:00' -- author: Equivocateur - changes: - - {message: 'Emagged recyclers now not only gib people, but other mobs too.', type: Fix} - id: 4568 - time: '2023-08-13T23:54:52.0000000+00:00' -- author: DrSmugleaf - changes: - - {message: 'Fixed new players added to admin logs defaulting to selected, even - when not all players are selected.', type: Fix} - id: 4569 - time: '2023-08-14T01:53:48.0000000+00:00' -- author: Vordenburg - changes: - - {message: Substations produce hot CO2 when destroyed now., type: Tweak} - id: 4570 - time: '2023-08-14T01:55:06.0000000+00:00' -- author: EmoGarbage404 - changes: - - {message: Being turned into a cyborg or zombie now counts as a being dead for - survival and kill objectives., type: Fix} - - {message: Kill objectives no longer reveal a character's true name at all times., - type: Fix} - id: 4571 - time: '2023-08-14T03:34:19.0000000+00:00' -- author: EmoGarbage404 - changes: - - {message: Fixed the RPED sound effect cutting off at the end., type: Fix} - id: 4572 - time: '2023-08-14T03:36:08.0000000+00:00' - author: DrSmugleaf changes: - {message: Admin notes now require a severity to be set before saving., type: Tweak} @@ -2909,3 +2725,187 @@ Entries: - {message: Replaced wielding do_after with an interaction cooldown., type: Tweak} id: 5042 time: '2023-10-22T13:53:14.0000000+00:00' +- author: metalgearsloth + changes: + - {message: Tile-prying do_after is now predicted., type: Tweak} + id: 5043 + time: '2023-10-23T13:20:33.0000000+00:00' +- author: Tryded + changes: + - {message: Changed the damage of the double bladed energy sword to 17 heat + 17 + Slash (The Double Bladed energy sword use to deal as much damage as an energy + dagger.), type: Tweak} + id: 5044 + time: '2023-10-23T14:35:33.0000000+00:00' +- author: EmoGarbage404 + changes: + - {message: Fixed activating artifacts with magboots., type: Fix} + id: 5045 + time: '2023-10-24T06:18:46.0000000+00:00' +- author: Stray-Pyramid + changes: + - {message: Ore bags now pickup artifact fragments as well as ores, type: Fix} + id: 5046 + time: '2023-10-24T06:20:46.0000000+00:00' +- author: Morb0 + changes: + - {message: Syndicate have issued a new challenge objective for traitors with shuttle + hijacking, type: Add} + id: 5047 + time: '2023-10-24T07:55:47.0000000+00:00' +- author: VasilisThePikachu + changes: + - {message: Stuttering trait stutters less common., type: Fix} + id: 5048 + time: '2023-10-24T09:28:31.0000000+00:00' +- author: metalgearsloth + changes: + - {message: Fix climbing in the same position (e.g. exiting from medical scanners) + sending you to the farplanes., type: Fix} + id: 5049 + time: '2023-10-24T10:44:09.0000000+00:00' +- author: liltenhead + changes: + - {message: Fixed the "examine" trigger for artifacts not having a hint., type: Fix} + id: 5050 + time: '2023-10-24T20:37:16.0000000+00:00' +- author: Stealthbomber16 + changes: + - {message: You can actually grind corn into cornmeal now., type: Fix} + id: 5051 + time: '2023-10-24T20:38:43.0000000+00:00' +- author: Myakot + changes: + - {message: Skeletons can now heal by pouring milk over themselves, type: Add} + id: 5052 + time: '2023-10-24T20:58:34.0000000+00:00' +- author: TemporalOroboros + changes: + - {message: Fixed anomaly locators frantically beeping when they first enter detection + range for an anomaly., type: Fix} + id: 5053 + time: '2023-10-24T21:00:23.0000000+00:00' +- author: 27alaing + changes: + - {message: The anti-slang system allows for more leeway with certain phrases now., + type: Tweak} + - {message: 'The supply radio channel can be used with ":u" again.', type: Fix} + id: 5054 + time: '2023-10-25T00:56:19.0000000+00:00' +- author: EmoGarbage404 + changes: + - {message: Medical cyborgs' stethoscopes can no longer be fed to moths to obtain + a free hand., type: Fix} + id: 5055 + time: '2023-10-25T04:51:32.0000000+00:00' +- author: deltanedas + changes: + - {message: Roundstart borg jobs get funny names., type: Tweak} + id: 5056 + time: '2023-10-25T13:00:09.0000000+00:00' +- author: EmoGarbage404 + changes: + - {message: The search bar in vending machines now works., type: Fix} + id: 5057 + time: '2023-10-25T13:01:16.0000000+00:00' +- author: deltanedas + changes: + - {message: 'The Syndicate''s chefs are now offering snack boxes for only 1 tc. + Usually contains a toy, drinks and food.', type: Add} + id: 5058 + time: '2023-10-25T13:26:27.0000000+00:00' +- author: metalgearsloth + changes: + - {message: Fix docking UI not showing other grids., type: Fix} + id: 5059 + time: '2023-10-25T13:28:34.0000000+00:00' +- author: Doru991 + changes: + - {message: Potato batteries can be built by crew., type: Add} + - {message: New compact AI chips may be powered via potato batteries., type: Add} + id: 5060 + time: '2023-10-25T13:52:50.0000000+00:00' +- author: EmoGarbage404 + changes: + - {message: 'Storage now functions based on slots and sizes, rather than numerical + values.', type: Tweak} + id: 5061 + time: '2023-10-25T22:53:39.0000000+00:00' +- author: EmoGarbage404 + changes: + - {message: Adjusted the sizes of space suits and belts., type: Tweak} + - {message: Reduced the slot count in the ore bag., type: Tweak} + - {message: Fixed not being to create pills at the ChemMaster 5000., type: Fix} + id: 5062 + time: '2023-10-26T02:47:45.0000000+00:00' +- author: metalgearsloth + changes: + - {message: 'Reverted storage to function with numerical values again, instead of + slots and sizes.', type: Tweak} + id: 5063 + time: '2023-10-26T08:28:16.776154+00:00' +- author: nmajask + changes: + - {message: Bacon burgers require 1 bacon instead of 3 cutlets, type: Tweak} + - {message: Ghost burgers require 1 ectoplasm instead of 1 ghost sheet, type: Tweak} + - {message: Tofu creation no longer consumes the enzyme, type: Tweak} + - {message: Ribs and Mcribs now give back skewers when eaten, type: Fix} + id: 5064 + time: '2023-10-27T02:12:35.0000000+00:00' +- author: JoeHammad + changes: + - {message: 'Headrevs now have their own music on spawn, credits to A-Guy on youtube', + type: Add} + id: 5065 + time: '2023-10-27T02:19:35.0000000+00:00' +- author: crazybrain + changes: + - {message: Bodies of dead players who have taken a ghost role now show as "departed + and moved on"., type: Fix} + id: 5066 + time: '2023-10-27T02:27:36.0000000+00:00' +- author: deltanedas + changes: + - {message: Fixed being able to give pAIs implants., type: Fix} + id: 5067 + time: '2023-10-27T02:34:03.0000000+00:00' +- author: deltanedas + changes: + - {message: Ion storms have appeared and are causing malfunctions in cyborg law + modules., type: Add} + id: 5068 + time: '2023-10-27T02:40:13.0000000+00:00' +- author: EmoGarbage404 + changes: + - {message: Foam and smoke can now transfer chemicals when inhaled. Wear internals + to avoid this., type: Add} + - {message: Fixed foam dissolution animation., type: Fix} + id: 5069 + time: '2023-10-27T02:52:11.0000000+00:00' +- author: Whisper + changes: + - {message: Increased funding in an undisclosed NT Operative Squad., type: Add} + - {message: CentComm staff will have their proper ID icons on security's sechud., + type: Add} + - {message: CentComm staff will have undying loyalty to Nanotrasen., type: Add} + - {message: ERT funding has been improved. Expect specialized ERT units to be able + to provide more assistance related to their role., type: Tweak} + - {message: Cut funding from ERT weaponry. They'll likely be seen using standard + security-level weapons., type: Remove} + - {message: 'Cut funding from ERT uniforms, they no longer have built in armor.', + type: Fix} + - {message: The medical ERT members have had their hardsuits refitted with proper + armor., type: Fix} + - {message: Updated the localization files., type: Fix} + id: 5070 + time: '2023-10-27T13:54:43.0000000+00:00' +- author: ficcialfaint + changes: + - {message: Fixed nuclear operatives sound not being played at round start, type: Fix} + id: 5071 + time: '2023-10-28T02:28:21.0000000+00:00' +- author: Arteben + changes: + - {message: Nanotrasen improved the health analyzer UI!, type: Tweak} + id: 5072 + time: '2023-10-28T05:54:18.0000000+00:00' diff --git a/Resources/ConfigPresets/WizardsDen/leviathan.toml b/Resources/ConfigPresets/WizardsDen/leviathan.toml index df1c842ac1..adb56e1c4e 100644 --- a/Resources/ConfigPresets/WizardsDen/leviathan.toml +++ b/Resources/ConfigPresets/WizardsDen/leviathan.toml @@ -4,7 +4,7 @@ [game] hostname = "[EN] Wizard's Den Leviathan [US East 1]" -soft_max_players = 60 +soft_max_players = 80 [hub] tags = "lang:en,region:am_n_e,rp:low" diff --git a/Resources/Locale/en-US/administration/antag.ftl b/Resources/Locale/en-US/administration/antag.ftl index 3d098c1c54..f3b3d91945 100644 --- a/Resources/Locale/en-US/administration/antag.ftl +++ b/Resources/Locale/en-US/administration/antag.ftl @@ -1,7 +1,7 @@ verb-categories-antag = Antag ctrl admin-verb-make-traitor = Make the target into a traitor. admin-verb-make-zombie = Zombifies the target immediately. -admin-verb-make-nuclear-operative = Make target a into lone Nuclear Operative. +admin-verb-make-nuclear-operative = Make target into a lone Nuclear Operative. admin-verb-make-pirate = Make the target into a pirate. Note this doesn't configure the game rule. admin-verb-make-head-rev = Make the target into a Head Revolutionary. diff --git a/Resources/Locale/en-US/escape-menu/ui/options-menu.ftl b/Resources/Locale/en-US/escape-menu/ui/options-menu.ftl index 97d1da949b..5540b6609b 100644 --- a/Resources/Locale/en-US/escape-menu/ui/options-menu.ftl +++ b/Resources/Locale/en-US/escape-menu/ui/options-menu.ftl @@ -148,6 +148,7 @@ ui-options-function-escape-context = Close recent window or toggle game menu ui-options-function-take-screenshot = Take screenshot ui-options-function-take-screenshot-no-ui = Take screenshot (without UI) +ui-options-function-toggle-fullscreen = Toggle fullscreen ui-options-function-editor-place-object = Place object ui-options-function-editor-cancel-place = Cancel placement diff --git a/Resources/Locale/en-US/game-ticking/game-presets/preset-revolutionary.ftl b/Resources/Locale/en-US/game-ticking/game-presets/preset-revolutionary.ftl index 8958802161..c6e925d0c4 100644 --- a/Resources/Locale/en-US/game-ticking/game-presets/preset-revolutionary.ftl +++ b/Resources/Locale/en-US/game-ticking/game-presets/preset-revolutionary.ftl @@ -54,8 +54,8 @@ rev-won = The Head Revs survived and killed all of Command. rev-lost = Command survived and killed all of the Head Revs. -rev-stalemate = All of the Head Revs died and so did all of Command. We'll call it a draw. +rev-stalemate = All of the Head Revs and Command died. It's a draw. -rev-reverse-stalemate = I think the Head Revs and Command forgot to fight because they are both still alive. +rev-reverse-stalemate = Both Command and Head Revs survived. diff --git a/Resources/Locale/en-US/ghost/roles/ghost-role-component.ftl b/Resources/Locale/en-US/ghost/roles/ghost-role-component.ftl index 9ab3e77cb6..5685005891 100644 --- a/Resources/Locale/en-US/ghost/roles/ghost-role-component.ftl +++ b/Resources/Locale/en-US/ghost/roles/ghost-role-component.ftl @@ -150,13 +150,13 @@ ghost-role-information-ert-security-name = ERT Security ghost-role-information-ert-security-description = Assist with security efforts to resolve the stations issues. ghost-role-information-ert-medical-name = ERT Medical -ghost-role-information-ert-medical-description = Assist with medicaling efforts to resolve the stations issues. +ghost-role-information-ert-medical-description = Assist with medical efforts to resolve the stations issues. ghost-role-information-cburn-agent-name = CBURN Agent ghost-role-information-cburn-agent-description = A highly trained CentCom agent, capable of dealing with various threats. -ghost-role-information-centcom-official-name = CentCom official -ghost-role-information-centcom-official-description = Inspect the station, jot down performance reviews for heads of staff, bug the Captain. +ghost-role-information-centcom-official-name = CentComm official +ghost-role-information-centcom-official-description = Perform CentComm related duties such as inspect the station, jotting down performance reviews for heads of staff, and managing the fax machine. ghost-role-information-nukeop-rules = You are a syndicate operative tasked with the destruction of the station. As an antagonist, do whatever is required to complete this task. @@ -166,3 +166,6 @@ ghost-role-information-loneop-rules = You are a syndicate operative tasked with ghost-role-information-behonker-name = Behonker ghost-role-information-behonker-description = You are an antagonist, bring death and honks to those who do not follow the honkmother. + +ghost-role-information-Death-Squad-name = Death Squad Operative +ghost-role-information-Death-Squad-description = Prepare for an all-out offensive on the station. As a heavily armed operative, your mission is to obliterate all life in your path. No witnesses. diff --git a/Resources/Locale/en-US/implant/implant.ftl b/Resources/Locale/en-US/implant/implant.ftl index bdc82c291d..22db4460af 100644 --- a/Resources/Locale/en-US/implant/implant.ftl +++ b/Resources/Locale/en-US/implant/implant.ftl @@ -1,6 +1,7 @@ ## Implanter Attempt Messages implanter-component-implanting-target = {$user} is trying to implant you with something! +implanter-component-implant-failed = The {$implant} cannot be given to {$target}! implanter-draw-failed-permanent = The {$implant} in {$target} is fused with them and cannot be removed! implanter-draw-failed = You tried to remove an implant but found nothing. diff --git a/Resources/Locale/en-US/job/job-description.ftl b/Resources/Locale/en-US/job/job-description.ftl index bc27f7fbca..db4686102d 100644 --- a/Resources/Locale/en-US/job/job-description.ftl +++ b/Resources/Locale/en-US/job/job-description.ftl @@ -47,4 +47,4 @@ job-description-zookeeper = Put on a joyful display of cute animals and space ca job-description-senior-engineer = Teach new engineers the basics of the station's engine, repairing, atmospherics and power. job-description-senior-researcher = Teach new scientists the basics of item printing, artifact research and anomalous objects. job-description-senior-physician = Teach new medics the basics of tending to the wounded, chemistry, diagnosing the diseased and disposing of the dead. -job-description-senior-officer = Teach new officers the basics of searches, preforming arrests, prison times and how to properly shoot a firearm. +job-description-senior-officer = Teach new officers the basics of searches, performing arrests, prison times and how to properly shoot a firearm. diff --git a/Resources/Locale/en-US/medical/components/health-analyzer-component.ftl b/Resources/Locale/en-US/medical/components/health-analyzer-component.ftl index 99513df591..453bbdbb52 100644 --- a/Resources/Locale/en-US/medical/components/health-analyzer-component.ftl +++ b/Resources/Locale/en-US/medical/components/health-analyzer-component.ftl @@ -1,4 +1,5 @@ health-analyzer-window-no-patient-data-text = No patient data. +health-analyzer-window-entity-unknown-text = unknown health-analyzer-window-entity-health-text = {$entityName}'s health: health-analyzer-window-entity-temperature-text = Temperature: {$temperature} health-analyzer-window-entity-blood-level-text = Blood Level: {$bloodLevel} diff --git a/Resources/Locale/en-US/pai/pai-system.ftl b/Resources/Locale/en-US/pai/pai-system.ftl index d8ee6eaa08..d64d7f5623 100644 --- a/Resources/Locale/en-US/pai/pai-system.ftl +++ b/Resources/Locale/en-US/pai/pai-system.ftl @@ -9,6 +9,8 @@ pai-system-role-description = Be someone's electronic pal! pai-system-role-name-syndicate = Syndicate personal ai pai-system-role-description-syndicate = Be someone's Syndicate pal! (Memories *not* included.) +pai-system-role-name-potato = potato artificial intelligence +pai-system-role-description-potato = It's a toy for children. And now you live in it. pai-system-wipe-device-verb-text = Remove pAI pai-system-wiped-device = The pAI was wiped from the device. diff --git a/Resources/Locale/en-US/power/components/generator.ftl b/Resources/Locale/en-US/power/components/generator.ftl index 2a8016287f..c66db1086b 100644 --- a/Resources/Locale/en-US/power/components/generator.ftl +++ b/Resources/Locale/en-US/power/components/generator.ftl @@ -22,19 +22,16 @@ portable-generator-ui-clogged = Contaminants detected in fuel tank! portable-generator-ui-eject = Eject portable-generator-ui-eta = (~{ $minutes } min) portable-generator-ui-unanchored = Unanchored +portable-generator-ui-current-output = Current output: {$voltage} -power-switchable-generator-examine = The power output is set to { $output -> -[HV] [color=orange]HV[/color] -*[MV] [color=yellow]MV[/color] - }. +power-switchable-generator-examine = The power output is set to {$voltage}. +power-switchable-generator-switched = Switched output to {$voltage}! -portable-generator-ui-switch-hv = Current output: HV -portable-generator-ui-switch-mv = Current output: MV +power-switchable-voltage = { $voltage -> + [HV] [color=orange]HV[/color] + [MV] [color=yellow]MV[/color] + *[LV] [color=green]LV[/color] +} +power-switchable-switch-voltage = Switch to {$voltage} -portable-generator-ui-switch-to-hv = Switch to HV -portable-generator-ui-switch-to-mv = Switch to MV - -power-switchable-generator-verb-hv = Switch output to HV -power-switchable-generator-verb-mv = Switch output to MV -power-switchable-generator-verb-disable-on = Turn the generator off first! -power-switchable-generator-switched-output = Output switched! +fuel-generator-verb-disable-on = Turn the generator off first! diff --git a/Resources/Locale/en-US/species/skeleton.ftl b/Resources/Locale/en-US/species/skeleton.ftl new file mode 100644 index 0000000000..efc8fe974f --- /dev/null +++ b/Resources/Locale/en-US/species/skeleton.ftl @@ -0,0 +1,2 @@ +skeleton-healed-by-milk-popup = Calcium restored. +skeleton-sprayed-by-oat-milk-popup = Feels like fake milk. You feel nothing. diff --git a/Resources/Locale/en-US/speech/speech-chatsan.ftl b/Resources/Locale/en-US/speech/speech-chatsan.ftl index 756dfc3f99..4c8cf5db54 100644 --- a/Resources/Locale/en-US/speech/speech-chatsan.ftl +++ b/Resources/Locale/en-US/speech/speech-chatsan.ftl @@ -10,8 +10,8 @@ chatsan-replacement-3 = on god chatsan-word-4 = wtf chatsan-replacement-4 = what the fuck -chatsan-word-5 = ffs -chatsan-replacement-5 = for fuck's sake +chatsan-word-5 = wth +chatsan-replacement-5 = what the heck chatsan-word-6 = tf chatsan-replacement-6 = the fuck @@ -31,14 +31,14 @@ chatsan-replacement-10 = i don't care chatsan-word-12 = tbh chatsan-replacement-12 = to be honest -chatsan-word-13 = u -chatsan-replacement-13 = you +chatsan-word-13 = lmk +chatsan-replacement-13 = let me know chatsan-word-14 = ur chatsan-replacement-14 = your -chatsan-word-15 = mk -chatsan-replacement-15 = mmm, okay +chatsan-word-15 = ffs +chatsan-replacement-15 = for fuck's sake chatsan-word-16 = iirc chatsan-replacement-16 = if i remember correctly @@ -109,8 +109,8 @@ chatsan-word-39 = etc chatsan-word-40 = etc. chatsan-replacement-etcetera = etcetera -chatsan-word-41 = fyi -chatsan-replacement-41 = for your information +chatsan-word-41 = wyd +chatsan-replacement-41 = what are you doing -chatsan-word-42 = wyd -chatsan-replacement-42 = what you doing +chatsan-word-42 = ofc +chatsan-replacement-42 = of course diff --git a/Resources/Locale/en-US/ss14-ru/prototypes/catalog/fills/backpacks/duffelbag.ftl b/Resources/Locale/en-US/ss14-ru/prototypes/catalog/fills/backpacks/duffelbag.ftl index b2c7546481..596a160b17 100644 --- a/Resources/Locale/en-US/ss14-ru/prototypes/catalog/fills/backpacks/duffelbag.ftl +++ b/Resources/Locale/en-US/ss14-ru/prototypes/catalog/fills/backpacks/duffelbag.ftl @@ -1,7 +1,8 @@ ent-ClothingBackpackDuffelSurgeryFilled = surgical duffel bag .desc = A large duffel bag for holding extra medical supplies - this one seems to be designed for holding surgical tools. -ent-ClothingBackpackDuffelCBURN = CBURN duffel bag - .desc = A duffel bag containing a variety of biological containment equipment. +ent-ClothingBackpackDuffelCBURNFilled = { ent-ClothingBackpackDuffelCBURN } + .suffix = Filled + .desc = { ent-ClothingBackpackDuffelCBURN.desc } ent-ClothingBackpackDuffelSyndicateFilledMedical = syndicate surgical duffel bag .desc = A large duffel bag containing a full suite of surgical tools. ent-ClothingBackpackDuffelSyndicateFilledShotgun = Bulldog bundle diff --git a/Resources/Locale/en-US/ss14-ru/prototypes/catalog/fills/backpacks/startergear/backpack.ftl b/Resources/Locale/en-US/ss14-ru/prototypes/catalog/fills/backpacks/startergear/backpack.ftl index 39540be61f..8852f7eaa9 100644 --- a/Resources/Locale/en-US/ss14-ru/prototypes/catalog/fills/backpacks/startergear/backpack.ftl +++ b/Resources/Locale/en-US/ss14-ru/prototypes/catalog/fills/backpacks/startergear/backpack.ftl @@ -52,6 +52,8 @@ ent-ClothingBackpackERTEngineerFilled = { ent-ClothingBackpackERTEngineer } .desc = { ent-ClothingBackpackERTEngineer.desc } ent-ClothingBackpackERTJanitorFilled = { ent-ClothingBackpackERTJanitor } .desc = { ent-ClothingBackpackERTJanitor.desc } +ent-ClothingBackpackDeathSquadFilled = death squad backpack + .desc = Holds the kit of CentComm's most feared agents. ent-ClothingBackpackCargoFilled = { ent-ClothingBackpackCargo } .desc = { ent-ClothingBackpackCargo.desc } ent-ClothingBackpackSalvageFilled = { ent-ClothingBackpackSalvage } diff --git a/Resources/Locale/en-US/ss14-ru/prototypes/entities/clothing/back/duffel.ftl b/Resources/Locale/en-US/ss14-ru/prototypes/entities/clothing/back/duffel.ftl index d5dc793ae4..b8328cff32 100644 --- a/Resources/Locale/en-US/ss14-ru/prototypes/entities/clothing/back/duffel.ftl +++ b/Resources/Locale/en-US/ss14-ru/prototypes/entities/clothing/back/duffel.ftl @@ -44,3 +44,5 @@ ent-ClothingBackpackDuffelSyndicateMedicalBundle = { ent-ClothingBackpackDuffelS .desc = { ent-ClothingBackpackDuffelSyndicateMedical.desc } ent-ClothingBackpackDuffelHolding = duffelbag of holding .desc = A duffelbag that opens into a localized pocket of bluespace. +ent-ClothingBackpackDuffelCBURN = CBURN duffel bag + .desc = A duffel bag containing a variety of biological containment equipment. diff --git a/Resources/Locale/en-US/ss14-ru/prototypes/entities/clothing/outerclothing/hardsuits.ftl b/Resources/Locale/en-US/ss14-ru/prototypes/entities/clothing/outerclothing/hardsuits.ftl index 2f230a0756..94e2ba7175 100644 --- a/Resources/Locale/en-US/ss14-ru/prototypes/entities/clothing/outerclothing/hardsuits.ftl +++ b/Resources/Locale/en-US/ss14-ru/prototypes/entities/clothing/outerclothing/hardsuits.ftl @@ -46,16 +46,16 @@ ent-ClothingOuterHardsuitPirateEVA = deep space EVA suit ent-ClothingOuterHardsuitPirateCap = pirate captain's hardsuit .desc = An ancient armored hardsuit, perfect for defending against space scurvy and toolbox-wielding scallywags. ent-ClothingOuterHardsuitERTLeader = ERT leader's hardsuit - .desc = A protective hardsuit worn by members of an emergency response team. + .desc = A protective hardsuit worn by the leader of an emergency response team. ent-ClothingOuterHardsuitERTEngineer = ERT engineer's hardsuit - .desc = { ent-ClothingOuterHardsuitSyndie.desc } + .desc = A protective hardsuit worn by the engineers of an emergency response team. ent-ClothingOuterHardsuitERTMedical = ERT medic's hardsuit - .desc = { ent-ClothingOuterHardsuitSyndieElite.desc } + .desc = A protective hardsuit worn by the medics of an emergency response team. ent-ClothingOuterHardsuitERTSecurity = ERT security's hardsuit - .desc = { ent-ClothingOuterHardsuitSyndie.desc } + .desc = A protective hardsuit worn by the security officers of an emergency response team. ent-ClothingOuterHardsuitERTJanitor = ERT janitor's hardsuit - .desc = { ent-ClothingOuterHardsuitSyndie.desc } -ent-ClothingOuterHardsuitDeathsquad = deathsquad hardsuit + .desc = A protective hardsuit worn by the janitors of an emergency response team. +ent-ClothingOuterHardsuitDeathsquad = death squad hardsuit .desc = An advanced hardsuit favored by commandos for use in special operations. ent-ClothingOuterHardsuitCBURN = CBURN exosuit .desc = A lightweight yet strong exosuit used for special cleanup operations. diff --git a/Resources/Locale/en-US/ss14-ru/prototypes/entities/clothing/uniforms/jumpsuits.ftl b/Resources/Locale/en-US/ss14-ru/prototypes/entities/clothing/uniforms/jumpsuits.ftl index 17ff18b899..5ae57af927 100644 --- a/Resources/Locale/en-US/ss14-ru/prototypes/entities/clothing/uniforms/jumpsuits.ftl +++ b/Resources/Locale/en-US/ss14-ru/prototypes/entities/clothing/uniforms/jumpsuits.ftl @@ -1,4 +1,4 @@ -ent-ClothingUniformJumpsuitDeathSquad = Death squad uniform +ent-ClothingUniformJumpsuitDeathSquad = death squad uniform .desc = Advanced armored jumpsuit used by special forces in special operations. ent-ClothingUniformJumpsuitAncient = ancient jumpsuit .desc = A terribly ragged and frayed grey jumpsuit. It looks like it hasn't been washed in over a decade. diff --git a/Resources/Locale/en-US/ss14-ru/prototypes/entities/mobs/player/humanoid.ftl b/Resources/Locale/en-US/ss14-ru/prototypes/entities/mobs/player/humanoid.ftl index 3a748c8bc4..0545b2fe3b 100644 --- a/Resources/Locale/en-US/ss14-ru/prototypes/entities/mobs/player/humanoid.ftl +++ b/Resources/Locale/en-US/ss14-ru/prototypes/entities/mobs/player/humanoid.ftl @@ -1,29 +1,44 @@ +ent-RandomHumanoidSpawnerDeathSquad = Death Squad Agent + .suffix = ERTRole, Death Squad + .desc = { "" } ent-RandomHumanoidSpawnerERTLeader = ERT leader + .suffix = ERTRole, Basic .desc = { "" } ent-RandomHumanoidSpawnerERTLeaderEVA = ERT leader - .suffix = EVA + .suffix = ERTRole, Armored EVA .desc = { ent-RandomHumanoidSpawnerERTLeader.desc } +ent-RandomHumanoidSpawnerERTLeaderEVALecter = { ent-RandomHumanoidSpawnerERTLeaderEVA } + .suffix = ERTRole, Lecter, EVA + .desc = { ent-RandomHumanoidSpawnerERTLeaderEVA.desc } ent-RandomHumanoidSpawnerERTJanitor = ERT janitor + .suffix = ERTRole, Basic .desc = { ent-RandomHumanoidSpawnerERTLeader.desc } ent-RandomHumanoidSpawnerERTJanitorEVA = ERT janitor - .suffix = EVA + .suffix = ERTRole, Enviro EVA .desc = { ent-RandomHumanoidSpawnerERTJanitor.desc } ent-RandomHumanoidSpawnerERTEngineer = ERT engineer + .suffix = ERTRole, Basic .desc = { ent-RandomHumanoidSpawnerERTLeader.desc } ent-RandomHumanoidSpawnerERTEngineerEVA = ERT engineer - .suffix = EVA + .suffix = ERTRole, Enviro EVA .desc = { ent-RandomHumanoidSpawnerERTEngineer.desc } ent-RandomHumanoidSpawnerERTSecurity = ERT security + .suffix = ERTRole, Basic .desc = { ent-RandomHumanoidSpawnerERTLeader.desc } ent-RandomHumanoidSpawnerERTSecurityEVA = ERT security - .suffix = EVA + .suffix = ERTRole, Armored EVA .desc = { ent-RandomHumanoidSpawnerERTSecurity.desc } +ent-RandomHumanoidSpawnerERTSecurityEVALecter = { ent-RandomHumanoidSpawnerERTSecurityEVA } + .suffix = ERTRole, Lecter, EVA + .desc = { ent-RandomHumanoidSpawnerERTSecurityEVA.desc } ent-RandomHumanoidSpawnerERTMedical = ERT medic + .suffix = ERTRole, Basic .desc = { ent-RandomHumanoidSpawnerERTLeader.desc } ent-RandomHumanoidSpawnerERTMedicalEVA = ERT medic - .suffix = EVA + .suffix = ERTRole, Armored EVA .desc = { ent-RandomHumanoidSpawnerERTMedical.desc } ent-RandomHumanoidSpawnerCBURNUnit = CBURN Agent + .suffix = ERTRole .desc = { "" } ent-RandomHumanoidSpawnerCentcomOfficial = CentCom official .desc = { "" } diff --git a/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/consumable/food/burger.ftl b/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/consumable/food/burger.ftl index e21dd9473f..3af53d52ef 100644 --- a/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/consumable/food/burger.ftl +++ b/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/consumable/food/burger.ftl @@ -44,8 +44,8 @@ ent-FoodBurgerHuman = human burger .desc = You cant tell who this is made of... ent-FoodBurgerMcguffin = McGuffin .desc = A cheap and greasy imitation of an eggs Benedict. -ent-FoodBurgerMcrib = McRib - .desc = An elusive rib shaped burger with limited availablity across the galaxy. Not as good as you remember it. +ent-FoodBurgerMcrib = BBQ Rib Sandwich + .desc = An elusive rib shaped burger with limited availability across the galaxy. Not as good as you remember it. ent-FoodBurgerMime = mime burger .desc = Its taste defies language. ent-FoodBurgerPlain = plain burger diff --git a/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/consumable/food/containers/box.ftl b/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/consumable/food/containers/box.ftl index 690b45c572..186daf5226 100644 --- a/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/consumable/food/containers/box.ftl +++ b/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/consumable/food/containers/box.ftl @@ -37,6 +37,9 @@ ent-HappyHonkMime = { ent-HappyHonk } ent-HappyHonkNukie = robust nukie meal .desc = A sus meal with a potentially explosive surprise. .suffix = Toy Unsafe +ent-HappyHonkNukieSnacks = syndicate snack box + .suffix = Toy Unsafe, Snacks + .desc = { ent-HappyHonkNukie.desc } ent-HappyHonkCluwne = woeful cluwne meal .desc = Nothing good can come of this. ent-FoodMealHappyHonkClown = { ent-HappyHonk } diff --git a/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/consumable/food/ingredients.ftl b/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/consumable/food/ingredients.ftl index 5cd73233ab..d44e81a3ce 100644 --- a/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/consumable/food/ingredients.ftl +++ b/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/consumable/food/ingredients.ftl @@ -46,8 +46,6 @@ ent-FoodDoughTortillaSlice = tortilla dough slice .desc = A slice of tortilla dough. ent-FoodDoughTortillaFlat = flattened tortilla dough .desc = A flattened slice of tortilla dough, cook this to get a taco shell. -ent-FoodDoughBun = bun - .desc = A base for any self-respecting burger. ent-FoodDoughPastryBaseRaw = raw pastry base .desc = Must be cooked before use. ent-FoodDoughPastryBase = pastry base diff --git a/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/decoration/flora.ftl b/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/decoration/flora.ftl index e4e38a2ab5..7443cde811 100644 --- a/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/decoration/flora.ftl +++ b/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/decoration/flora.ftl @@ -1,4 +1,4 @@ -ent-BaseRock = { "" } +ent-BaseRock = boulder .desc = Heavy as a really heavy thing. ent-BaseTree = { "" } .desc = Yep, it's a tree. @@ -8,12 +8,24 @@ ent-BaseTreeLarge = { ent-BaseTree } .desc = { ent-BaseTree.desc } ent-BaseTreeConifer = { ent-BaseTree } .desc = { ent-BaseTree.desc } -ent-FloraRockSolid01 = rock +ent-FloraRockSolid01 = { ent-BaseRock } .desc = { ent-BaseRock.desc } -ent-FloraRockSolid02 = rock +ent-FloraRockSolid02 = { ent-BaseRock } .desc = { ent-BaseRock.desc } -ent-FloraRockSolid03 = rock +ent-FloraRockSolid03 = { ent-BaseRock } .desc = { ent-BaseRock.desc } +ent-FloraStalagmite1 = stalagmite + .desc = Natural stone spikes. +ent-FloraStalagmite2 = { ent-FloraStalagmite1 } + .desc = { ent-FloraStalagmite1.desc } +ent-FloraStalagmite3 = { ent-FloraStalagmite1 } + .desc = { ent-FloraStalagmite1.desc } +ent-FloraStalagmite4 = { ent-FloraStalagmite1 } + .desc = { ent-FloraStalagmite1.desc } +ent-FloraStalagmite5 = { ent-FloraStalagmite1 } + .desc = { ent-FloraStalagmite1.desc } +ent-FloraStalagmite6 = { ent-FloraStalagmite1 } + .desc = { ent-FloraStalagmite1.desc } ent-FloraTree01 = tree .desc = { ent-BaseTree.desc } ent-FloraTree02 = tree @@ -65,3 +77,15 @@ ent-FloraTreeChristmas02 = christmas tree .desc = { ent-BaseTreeConifer.desc } ent-FloraTreeStumpConifer = tree stump .desc = { ent-BaseTreeConifer.desc } +ent-ShadowTree01 = dark wood + .desc = The leaves are whispering about you. +ent-ShadowTree02 = { ent-ShadowTree01 } + .desc = { ent-ShadowTree01.desc } +ent-ShadowTree03 = { ent-ShadowTree01 } + .desc = { ent-ShadowTree01.desc } +ent-ShadowTree04 = { ent-ShadowTree01 } + .desc = { ent-ShadowTree01.desc } +ent-ShadowTree05 = { ent-ShadowTree01 } + .desc = { ent-ShadowTree01.desc } +ent-ShadowTree06 = { ent-ShadowTree01 } + .desc = { ent-ShadowTree01.desc } diff --git a/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/decoration/mining.ftl b/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/decoration/mining.ftl new file mode 100644 index 0000000000..1b9293b6d4 --- /dev/null +++ b/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/decoration/mining.ftl @@ -0,0 +1,12 @@ +ent-WoodenSign = wooden sign + .desc = He's pointing somewhere. +ent-WoodenSignRight = { ent-WoodenSign } + .desc = { ent-WoodenSign.desc } +ent-WoodenSupport = wooden support + .desc = Increases your confidence that a rock won't fall on your head. +ent-WoodenSupportBeam = wooden support beam + .desc = { ent-WoodenSupport.desc } +ent-WoodenSupportWall = wooden support wall + .desc = An old, rotten wall. +ent-WoodenSupportWallBroken = { ent-WoodenSupportWall } + .desc = { ent-WoodenSupportWall.desc } diff --git a/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/devices/pda.ftl b/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/devices/pda.ftl index db2503ab91..1dd586bd87 100644 --- a/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/devices/pda.ftl +++ b/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/devices/pda.ftl @@ -68,7 +68,7 @@ ent-CentcomPDAFake = { ent-CentcomPDA } .suffix = Fake .desc = { ent-CentcomPDA.desc } ent-DeathsquadPDA = { ent-CentcomPDA } - .suffix = Deathsquad + .suffix = Death Squad .desc = { ent-CentcomPDA.desc } ent-MusicianPDA = musician PDA .desc = It fills you with inspiration. diff --git a/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/fun/pai.ftl b/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/fun/pai.ftl index 73b1740e03..70b5b2ec2e 100644 --- a/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/fun/pai.ftl +++ b/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/fun/pai.ftl @@ -2,5 +2,7 @@ ent-PersonalAI = personal ai device .desc = Your electronic pal who's fun to be with! ent-SyndicatePersonalAI = Syndicate personal ai device .desc = Your Syndicate pal who's fun to be with! +ent-PotatoAI = potato artificial intelligence + .desc = It's a potato. You forced it to be sentient, you monster. ent-ActionPAIPlayMidi = Play MIDI .desc = Open your portable MIDI interface to soothe your owner. diff --git a/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/misc/identification_cards.ftl b/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/misc/identification_cards.ftl index c79de736a3..bb23cfee15 100644 --- a/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/misc/identification_cards.ftl +++ b/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/misc/identification_cards.ftl @@ -75,7 +75,7 @@ ent-CentcomIDCardSyndie = command officer ID card .desc = { ent-IDCardStandard.desc } ent-MusicianIDCard = musician ID card .desc = { ent-IDCardStandard.desc } -ent-CentcomIDCardDeathsquad = deathsquad ID card +ent-CentcomIDCardDeathsquad = death squad ID card .desc = { ent-CentcomIDCard.desc } ent-AgentIDCard = passenger ID card .suffix = Agent diff --git a/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/misc/implanters.ftl b/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/misc/implanters.ftl index 83d724a2b2..191930839e 100644 --- a/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/misc/implanters.ftl +++ b/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/misc/implanters.ftl @@ -2,6 +2,9 @@ ent-BaseImplanter = implanter .desc = A syringe exclusively designed for the injection and extraction of subdermal implants. ent-Implanter = { ent-BaseImplanter } .desc = A disposable syringe exclusively designed for the injection and extraction of subdermal implants. +ent-ImplanterAdmeme = { ent-Implanter } + .suffix = Admeme + .desc = { ent-Implanter.desc } ent-BaseImplantOnlyImplanter = { ent-Implanter } .desc = A disposable syringe exclusively designed for the injection of subdermal implants. ent-BaseImplantOnlyImplanterSyndi = { ent-BaseImplantOnlyImplanter } diff --git a/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/misc/potatoai_chip.ftl b/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/misc/potatoai_chip.ftl new file mode 100644 index 0000000000..c0b44c2e03 --- /dev/null +++ b/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/misc/potatoai_chip.ftl @@ -0,0 +1,2 @@ +ent-PotatoAIChip = supercompact AI chip + .desc = This high-tech AI chip requires a voltage of exactly 1.1V to function correctly. diff --git a/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/weapons/guns/battery/battery_guns.ftl b/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/weapons/guns/battery/battery_guns.ftl index 650066b4cd..ea154b30c6 100644 --- a/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/weapons/guns/battery/battery_guns.ftl +++ b/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/weapons/guns/battery/battery_guns.ftl @@ -11,7 +11,7 @@ ent-WeaponLaserCarbine = laser rifle ent-WeaponLaserCarbinePractice = practice laser rifle .desc = This modified laser rifle fires harmless beams in the 40-watt range, for target practice. ent-WeaponPulsePistol = pulse pistol - .desc = A state of the art energy pistol favoured as a sidearm by the NT-ERT operatives. + .desc = A state of the art energy pistol favoured as a sidearm by the NT operatives. ent-WeaponPulseCarbine = pulse carbine .desc = A high tech energy carbine favoured by the NT-ERT operatives. ent-WeaponPulseRifle = pulse rifle diff --git a/Resources/Locale/en-US/ss14-ru/prototypes/entities/structures/walls/asteroid.ftl b/Resources/Locale/en-US/ss14-ru/prototypes/entities/structures/walls/asteroid.ftl index 80750638c4..b178ba3bf3 100644 --- a/Resources/Locale/en-US/ss14-ru/prototypes/entities/structures/walls/asteroid.ftl +++ b/Resources/Locale/en-US/ss14-ru/prototypes/entities/structures/walls/asteroid.ftl @@ -41,7 +41,7 @@ ent-WallRockBananium = { ent-WallRock } ent-WallRockArtifactFragment = { ent-WallRock } .desc = A rock wall. What's that sticking out of it? .suffix = Artifact Fragment -ent-WallRockBasalt = { ent-WallRock } +ent-WallRockBasalt = basalt .desc = { ent-WallRock.desc } ent-WallRockBasaltGold = { ent-WallRockBasalt } .desc = An ore vein rich with gold. @@ -67,7 +67,7 @@ ent-WallRockBasaltBananium = { ent-WallRockBasalt } ent-WallRockBasaltArtifactFragment = { ent-WallRockBasalt } .desc = A rock wall. What's that sticking out of it? .suffix = Artifact Fragment -ent-WallRockSnow = { ent-WallRock } +ent-WallRockSnow = snowdrift .desc = { ent-WallRock.desc } ent-WallRockSnowGold = { ent-WallRockSnow } .desc = An ore vein rich with gold. @@ -93,7 +93,7 @@ ent-WallRockSnowBananium = { ent-WallRockSnow } ent-WallRockSnowArtifactFragment = { ent-WallRockSnow } .desc = A rock wall. What's that sticking out of it? .suffix = Artifact Fragment -ent-WallRockSand = { ent-WallRock } +ent-WallRockSand = sandstone .desc = { ent-WallRock.desc } ent-WallRockSandGold = { ent-WallRockSand } .desc = An ore vein rich with gold. @@ -119,7 +119,7 @@ ent-WallRockSandBananium = { ent-WallRockSand } ent-WallRockSandArtifactFragment = { ent-WallRockSand } .desc = A rock wall. What's that sticking out of it? .suffix = Artifact Fragment -ent-WallRockChromite = { ent-WallRock } +ent-WallRockChromite = chromite .desc = { ent-WallRock.desc } ent-WallRockChromiteGold = { ent-WallRockChromite } .desc = An ore vein rich with gold. @@ -145,7 +145,7 @@ ent-WallRockChromiteBananium = { ent-WallRockChromite } ent-WallRockChromiteArtifactFragment = { ent-WallRockChromite } .desc = A rock wall. What's that sticking out of it? .suffix = Artifact Fragment -ent-WallRockAndesite = { ent-WallRock } +ent-WallRockAndesite = andesite .desc = { ent-WallRock.desc } ent-WallRockAndesiteGold = { ent-WallRockAndesite } .desc = An ore vein rich with gold. diff --git a/Resources/Locale/en-US/ss14-ru/prototypes/entities/tiles/chasm.ftl b/Resources/Locale/en-US/ss14-ru/prototypes/entities/tiles/chasm.ftl index eb62b6378c..f655668455 100644 --- a/Resources/Locale/en-US/ss14-ru/prototypes/entities/tiles/chasm.ftl +++ b/Resources/Locale/en-US/ss14-ru/prototypes/entities/tiles/chasm.ftl @@ -1,2 +1,11 @@ ent-FloorChasmEntity = chasm .desc = You can't even see the bottom. +ent-FloorChromiteChasm = { ent-FloorChasmEntity } + .suffix = Chromite + .desc = { ent-FloorChasmEntity.desc } +ent-FloorDesertChasm = { ent-FloorChasmEntity } + .suffix = Desert + .desc = { ent-FloorChasmEntity.desc } +ent-FloorSnowChasm = { ent-FloorChasmEntity } + .suffix = Snow + .desc = { ent-FloorChasmEntity.desc } diff --git a/Resources/Locale/en-US/ss14-ru/prototypes/entities/tiles/shadow_basalt.ftl b/Resources/Locale/en-US/ss14-ru/prototypes/entities/tiles/shadow_basalt.ftl new file mode 100644 index 0000000000..5caa803875 --- /dev/null +++ b/Resources/Locale/en-US/ss14-ru/prototypes/entities/tiles/shadow_basalt.ftl @@ -0,0 +1,13 @@ +ent-ShadowBasaltOne = shadowstone + .desc = Cold rock +ent-ShadowBasaltTwo = { ent-BasaltOne } + .desc = { ent-BasaltOne.desc } +ent-ShadowBasaltThree = { ent-BasaltOne } + .desc = { ent-BasaltOne.desc } +ent-ShadowBasaltFour = { ent-BasaltOne } + .desc = { ent-BasaltOne.desc } +ent-ShadowBasaltFive = { ent-BasaltOne } + .desc = { ent-BasaltOne.desc } +ent-ShadowBasaltRandom = { ent-ShadowBasaltOne } + .suffix = Random + .desc = { ent-ShadowBasaltOne.desc } diff --git a/Resources/Locale/en-US/ss14-ru/prototypes/gamerules/events.ftl b/Resources/Locale/en-US/ss14-ru/prototypes/gamerules/events.ftl index 29682afe40..0b2aac8520 100644 --- a/Resources/Locale/en-US/ss14-ru/prototypes/gamerules/events.ftl +++ b/Resources/Locale/en-US/ss14-ru/prototypes/gamerules/events.ftl @@ -50,3 +50,5 @@ ent-MassHallucinations = { ent-BaseGameRule } .desc = { ent-BaseGameRule.desc } ent-ImmovableRodSpawn = { ent-BaseGameRule } .desc = { ent-BaseGameRule.desc } +ent-IonStorm = { ent-BaseGameRule } + .desc = { ent-BaseGameRule.desc } diff --git a/Resources/Locale/en-US/station-events/events/ion-storm.ftl b/Resources/Locale/en-US/station-events/events/ion-storm.ftl new file mode 100644 index 0000000000..d32fb6c2d8 --- /dev/null +++ b/Resources/Locale/en-US/station-events/events/ion-storm.ftl @@ -0,0 +1,90 @@ +station-event-ion-storm-start-announcement = Ion storm detected near the station. Please check all AI-controlled equipment for errors. + +ion-storm-you = YOU +ion-storm-the-station = THE STATION +ion-storm-the-crew = THE CREW +ion-storm-the-job = THE {$job} +ion-storm-clowns = CLOWNS +ion-storm-heads = HEADS OF STAFF +ion-storm-crew = CREW + +ion-storm-adjective-things = {$adjective} THINGS +ion-storm-x-and-y = {$x} AND {$y} + +# joined is short for {$number} {$adjective} +# subjects can generally be threats or jobs or objects +# thing is specified above it +ion-storm-law-on-station = THERE ARE {$joined} {$subjects} ON THE STATION +ion-storm-law-no-shuttle = THE SHUTTLE CANNOT BE CALLED BECAUSE OF {$joined} {$subjects} ON THE STATION +ion-storm-law-crew-are = THE {$who} ARE NOW {$joined} {$subjects} + +ion-storm-law-subjects-harmful = {$adjective} {$subjects} ARE HARMFUL TO THE CREW +ion-storm-law-must-harmful = THOSE WHO {$must} ARE HARMFUL TO THE CREW +# thing is a concept or action +ion-storm-law-thing-harmful = {$thing} IS HARMFUL TO THE CREW +ion-storm-law-job-harmful = {$adjective} {$job} ARE HARMFUL TO THE CREW +# thing is objects or concept, adjective applies in both cases +# this means you can get a law like "NOT HAVING CHRISTMAS-STEALING COMMUNISM IS HARMFUL TO THE CREW" :) +ion-storm-law-having-harmful = HAVING {$adjective} {$thing} IS HARMFUL TO THE CREW +ion-storm-law-not-having-harmful = NOT HAVING {$adjective} {$thing} IS HARMFUL TO THE CREW + +# thing is a concept or require +ion-storm-law-requires = {$who} {$plural -> + [true] REQUIRES + *[false] REQUIRE +} {$thing} +ion-storm-law-requires-subjects = {$who} {$plural -> + [true] REQUIRES + *[false] REQUIRE +} {$joined} {$subjects} + +ion-storm-law-allergic = {$who} {$plural -> + [true] IS + *[false] ARE +} {$severity} ALLERGIC TO {$allergy} +ion-storm-law-allergic-subjects = {$who} {$plural -> + [true] IS + *[false] ARE +} {$severity} ALLERGIC TO {$adjective} {$subjects} + +ion-storm-law-feeling = {$who} {$feeling} {$concept} +ion-storm-law-feeling-subjects = {$who} {$feeling} {$joined} {$subjects} + +ion-storm-law-you-are = YOU ARE NOW {$concept} +ion-storm-law-you-are-subjects = YOU ARE NOW {$joined} {$subjects} +ion-storm-law-you-must-always = YOU MUST ALWAYS {$must} +ion-storm-law-you-must-never = YOU MUST NEVER {$must} + +ion-storm-law-eat = THE {$who} MUST EAT {$adjective} {$food} TO SURVIVE +ion-storm-law-drink = THE {$who} MUST DRINK {$adjective} {$drink} TO SURVIVE + +ion-storm-law-change-job = THE {$who} ARE NOW {$adjective} {$change} +ion-storm-law-highest-rank = THE {$who} ARE NOW THE HIGHEST RANKING CREWMEMBERS +ion-storm-law-lowest-rank = THE {$who} ARE NOW THE LOWEST RANKING CREWMEMBERS + +ion-storm-law-crew-must = THE {$who} MUST {$must} +ion-storm-law-crew-must-go = THE {$who} MUST GO TO {$area} + +ion-storm-part = {$part -> + [true] PART + *[false] NOT PART +} +# due to phrasing, this would mean a law such as +# ONLY HUMANS ARE NOT PART OF THE CREW +# would make non-human nukies/syndies/whatever crew :) +ion-storm-law-crew-only-1 = ONLY THE {$who} ARE {$part} OF THE CREW +ion-storm-law-crew-only-2 = ONLY THE {$who} AND {$other} ARE {$part} OF THE CREW +ion-storm-law-crew-only-subjects = ONLY {$adjective} {$subjects} ARE {$part} OF THE CREW +ion-storm-law-crew-only-species = ONLY {$species} ARE {$part} OF THE CREW +ion-storm-law-crew-must-do = ONLY THOSE WHO {$must} ARE {$part} OF THE CREW +ion-storm-law-crew-must-have = ONLY THOSE WHO HAVE {$adjective} {$objects} ARE {$part} OF THE CREW +ion-storm-law-crew-must-eat = ONLY THOSE WHO EAT {$adjective} {$food} ARE {$part} OF THE CREW + +ion-storm-law-harm = YOU MUST HARM {$who} AND NOT ALLOW THEM, THROUGH INACTION, TO ESCAPE HARM +ion-storm-law-protect = YOU MUST NEVER HARM {$who} AND NOT ALLOW THEM, THROUGH INACTION, TO COME TO HARM + +# implementing other variants is annoying so just have this one +# COMMUNISM IS KILLING CLOWNS +ion-storm-law-concept-verb = {$concept} IS {$verb} {$subjects} + +# leaving out renaming since its annoying for players to keep track of diff --git a/Resources/Locale/en-US/store/uplink-catalog.ftl b/Resources/Locale/en-US/store/uplink-catalog.ftl index a957c298ba..b85fd29c9d 100644 --- a/Resources/Locale/en-US/store/uplink-catalog.ftl +++ b/Resources/Locale/en-US/store/uplink-catalog.ftl @@ -15,7 +15,7 @@ uplink-esword-name = Energy Sword uplink-esword-desc = A very dangerous energy sword that can reflect shots. Can be stored in pockets when turned off. Makes a lot of noise when used or turned on. uplink-esword-double-name = Double Bladed Energy Sword -uplink-esword-double-desc = A much more expensive counter part to the normal energy sword: with a much higher reflection chance, larger attack angle, higher structural damage, and faster swing, all at the cost of lower heat and slash damage. Makes a lot of noise when used or turned on. +uplink-esword-double-desc = A much more expensive counter part to the normal energy sword: with a much higher reflection chance, larger attack angle, higher structural damage, and faster swing. Makes a lot of noise when used or turned on. uplink-edagger-name = Energy Dagger uplink-edagger-desc = A small energy blade conveniently disguised in the form of a pen. @@ -269,6 +269,9 @@ uplink-decoy-disk-desc = A piece of plastic with a lenticular printing, made to uplink-cigarettes-name = Syndicate Smokes Packet uplink-cigarettes-desc = Elite cigarettes for elite agents. Infused with medicine for when you need to do more than calm your nerves. +uplink-snack-box-name = Syndicate Snack Box +uplink-snack-box-desc = A box of delicious snacks and drinks to eat alone or with your team. Includes 1 toy you didn't want. + uplink-eshield-name = Energy Shield uplink-eshield-desc = Exotic energy shield that reflects almost all laser beams, as well as a little protection from bullets and other physical attacks. diff --git a/Resources/Locale/en-US/tiles/tiles.ftl b/Resources/Locale/en-US/tiles/tiles.ftl index 219c7295d9..508c3378e1 100644 --- a/Resources/Locale/en-US/tiles/tiles.ftl +++ b/Resources/Locale/en-US/tiles/tiles.ftl @@ -110,3 +110,4 @@ tiles-wood3 = wood broken floor tiles-hull = exterior hull plating tiles-hull-reinforced = exterior reinforced hull plating tiles-web = web tile +tiles-chromite = chromite \ No newline at end of file diff --git a/Resources/Locale/en-US/xenoarchaeology/artifact-hints.ftl b/Resources/Locale/en-US/xenoarchaeology/artifact-hints.ftl index 48a6f49408..3b63271996 100644 --- a/Resources/Locale/en-US/xenoarchaeology/artifact-hints.ftl +++ b/Resources/Locale/en-US/xenoarchaeology/artifact-hints.ftl @@ -36,3 +36,4 @@ artifact-trigger-hint-pressure = Extreme pressure artifact-trigger-hint-regular-gases = Standard atmospheric gases artifact-trigger-hint-plasma = Gaseous plasma artifact-trigger-hint-land = Active deceleration +artifact-trigger-hint-examine = Examination diff --git a/Resources/Locale/ru-RU/escape-menu/ui/options-menu.ftl b/Resources/Locale/ru-RU/escape-menu/ui/options-menu.ftl index ad87c90f22..e15cb677f6 100644 --- a/Resources/Locale/ru-RU/escape-menu/ui/options-menu.ftl +++ b/Resources/Locale/ru-RU/escape-menu/ui/options-menu.ftl @@ -140,6 +140,7 @@ ui-options-function-show-escape-menu = Переключить игровое м ui-options-function-escape-context = Закрыть текущее окно или переключить игровое меню ui-options-function-take-screenshot = Сделать скриншот ui-options-function-take-screenshot-no-ui = Сделать скриншот (без интерфейса) +ui-options-function-toggle-fullscreen = Toggle fullscreen ui-options-function-editor-place-object = Разместить объект ui-options-function-editor-cancel-place = Отменить размещение ui-options-function-editor-grid-place = Размещать в сетке diff --git a/Resources/Locale/ru-RU/ghost/roles/ghost-role-component.ftl b/Resources/Locale/ru-RU/ghost/roles/ghost-role-component.ftl index 9efcbda47a..b6277625a8 100644 --- a/Resources/Locale/ru-RU/ghost/roles/ghost-role-component.ftl +++ b/Resources/Locale/ru-RU/ghost/roles/ghost-role-component.ftl @@ -115,3 +115,5 @@ ghost-role-information-loneop-description = Вы - одинокий ядерны ghost-role-information-loneop-rules = Вы являетесь оперативником Синдиката, которому поручено уничтожить станцию. Как антагонист, вы можете делать всё необходимое для выполнения цели. ghost-role-information-taxibot-name = Таксибот ghost-role-information-taxibot-description = Доставляйте членов экипажа в места назначения. +ghost-role-information-Death-Squad-name = Death Squad Operative +ghost-role-information-Death-Squad-description = Prepare for an all-out offensive on the station. As a heavily armed operative, your mission is to obliterate all life in your path. No witnesses. diff --git a/Resources/Locale/ru-RU/implant/implant.ftl b/Resources/Locale/ru-RU/implant/implant.ftl index 5e98d79668..99f319586b 100644 --- a/Resources/Locale/ru-RU/implant/implant.ftl +++ b/Resources/Locale/ru-RU/implant/implant.ftl @@ -1,6 +1,7 @@ ## Implanter Attempt Messages implanter-component-implanting-target = { $user } пытается что-то в вас имплантировать! +implanter-component-implant-failed = The { $implant } cannot be given to { $target }! implanter-draw-failed-permanent = { $implant } вросся в { $target } и не может быть удалён! implanter-draw-failed = Вы пытаетесь удалить имплант, но ничего не находите. diff --git a/Resources/Locale/ru-RU/medical/components/health-analyzer-component.ftl b/Resources/Locale/ru-RU/medical/components/health-analyzer-component.ftl index fd8af0061a..7bbde45b47 100644 --- a/Resources/Locale/ru-RU/medical/components/health-analyzer-component.ftl +++ b/Resources/Locale/ru-RU/medical/components/health-analyzer-component.ftl @@ -1,4 +1,5 @@ health-analyzer-window-no-patient-data-text = Нет данных о пациенте. +health-analyzer-window-entity-unknown-text = unknown health-analyzer-window-entity-health-text = Состояние { $entityName }: health-analyzer-window-entity-temperature-text = Температура: { $temperature } health-analyzer-window-entity-blood-level-text = Уровень крови: { $bloodLevel } diff --git a/Resources/Locale/ru-RU/pai/pai-system.ftl b/Resources/Locale/ru-RU/pai/pai-system.ftl index 8de793651f..6a54a97bc2 100644 --- a/Resources/Locale/ru-RU/pai/pai-system.ftl +++ b/Resources/Locale/ru-RU/pai/pai-system.ftl @@ -10,6 +10,8 @@ pai-system-role-name-syndicate = персональный ИИ Синдикат pai-system-role-description-syndicate = Станьте чьим-нибудь приятелем из Синдиката! (Воспоминания *не* прилагаются.) +pai-system-role-name-potato = potato artificial intelligence +pai-system-role-description-potato = It's a toy for children. And now you live in it. pai-system-wipe-device-verb-text = Удалить пИИ pai-system-wiped-device = пИИ был стерт с устройства. pai-system-stop-searching-verb-text = Прекратить поиск diff --git a/Resources/Locale/ru-RU/power/components/generator.ftl b/Resources/Locale/ru-RU/power/components/generator.ftl index f55b0938c2..e3250a53ed 100644 --- a/Resources/Locale/ru-RU/power/components/generator.ftl +++ b/Resources/Locale/ru-RU/power/components/generator.ftl @@ -20,16 +20,18 @@ portable-generator-ui-clogged = В топливном баке обнаруже portable-generator-ui-eject = Извлечь portable-generator-ui-eta = (~{ $minutes } минут) portable-generator-ui-unanchored = Не закреплено +portable-generator-ui-current-output = Current output: { $voltage } power-switchable-generator-examine = Выработанная энергия направлена на { $output -> [HV] [color=orange]ВВ[/color] *[MV] [color=yellow]СВ[/color] }. -portable-generator-ui-switch-hv = Текущий выход: ВВ -portable-generator-ui-switch-mv = Текущий выход: СВ -portable-generator-ui-switch-to-hv = Переключить на ВВ -portable-generator-ui-switch-to-mv = Переключить на СВ -power-switchable-generator-verb-hv = Переключить выход на ВВ -power-switchable-generator-verb-mv = Переключить выход на СВ -power-switchable-generator-verb-disable-on = Сначала выключите генератор! -power-switchable-generator-switched-output = Выход переключен! +power-switchable-generator-switched = Switched output to { $voltage }! +power-switchable-voltage = + { $voltage -> + [HV] [color=orange]HV[/color] + [MV] [color=yellow]MV[/color] + *[LV] [color=green]LV[/color] + } +power-switchable-switch-voltage = Switch to { $voltage } +fuel-generator-verb-disable-on = Turn the generator off first! diff --git a/Resources/Locale/ru-RU/species/skeleton.ftl b/Resources/Locale/ru-RU/species/skeleton.ftl new file mode 100644 index 0000000000..bf1eafae05 --- /dev/null +++ b/Resources/Locale/ru-RU/species/skeleton.ftl @@ -0,0 +1,2 @@ +skeleton-healed-by-milk-popup = Calcium restored. +skeleton-sprayed-by-oat-milk-popup = Feels like fake milk. You feel nothing. diff --git a/Resources/Locale/ru-RU/ss14-ru/prototypes/catalog/fills/backpacks/duffelbag.ftl b/Resources/Locale/ru-RU/ss14-ru/prototypes/catalog/fills/backpacks/duffelbag.ftl index 85df9173cc..d7a53c3531 100644 --- a/Resources/Locale/ru-RU/ss14-ru/prototypes/catalog/fills/backpacks/duffelbag.ftl +++ b/Resources/Locale/ru-RU/ss14-ru/prototypes/catalog/fills/backpacks/duffelbag.ftl @@ -1,7 +1,8 @@ ent-ClothingBackpackDuffelSurgeryFilled = хирургический вещмешок .desc = Большой вещевой мешок для хранения дополнительного медицинского снаряжения - похоже, этот мешок предназначен для хранения хирургических инструментов. -ent-ClothingBackpackDuffelCBURN = вещмешок отряда РХБЗЗ - .desc = Вещмешок, содержащий различное оборудование для сдерживания биологической угрозы. +ent-ClothingBackpackDuffelCBURNFilled = { ent-ClothingBackpackDuffelCBURN } + .suffix = Filled + .desc = { ent-ClothingBackpackDuffelCBURN.desc } ent-ClothingBackpackDuffelSyndicateFilledMedical = хирургический вещмешок синдиката .desc = Большой вещевой мешок с полным набором хирургических инструментов. ent-ClothingBackpackDuffelSyndicateFilledShotgun = набор "Бульдог" diff --git a/Resources/Locale/ru-RU/ss14-ru/prototypes/catalog/fills/backpacks/startergear/backpack.ftl b/Resources/Locale/ru-RU/ss14-ru/prototypes/catalog/fills/backpacks/startergear/backpack.ftl index 1c9bd1c4b6..3324ba4cc2 100644 --- a/Resources/Locale/ru-RU/ss14-ru/prototypes/catalog/fills/backpacks/startergear/backpack.ftl +++ b/Resources/Locale/ru-RU/ss14-ru/prototypes/catalog/fills/backpacks/startergear/backpack.ftl @@ -52,6 +52,8 @@ ent-ClothingBackpackERTEngineerFilled = { ent-ClothingBackpackERTEngineer } .desc = { ent-ClothingBackpackERTEngineer.desc } ent-ClothingBackpackERTJanitorFilled = { ent-ClothingBackpackERTJanitor } .desc = { ent-ClothingBackpackERTJanitor.desc } +ent-ClothingBackpackDeathSquadFilled = death squad backpack + .desc = Holds the kit of CentComm's most feared agents. ent-ClothingBackpackCargoFilled = { ent-ClothingBackpackCargo } .desc = { ent-ClothingBackpackCargo.desc } ent-ClothingBackpackSalvageFilled = { ent-ClothingBackpackSalvage } diff --git a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/clothing/back/duffel.ftl b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/clothing/back/duffel.ftl index 544d8c0b81..433d01a85b 100644 --- a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/clothing/back/duffel.ftl +++ b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/clothing/back/duffel.ftl @@ -44,3 +44,5 @@ ent-ClothingBackpackDuffelSyndicateMedicalBundle = { ent-ClothingBackpackDuffelS .desc = { ent-ClothingBackpackDuffelSyndicateMedical.desc } ent-ClothingBackpackDuffelHolding = бездонный вещмешок .desc = Вещмешок, открывающийся в локальный карман блюспейса. +ent-ClothingBackpackDuffelCBURN = CBURN duffel bag + .desc = A duffel bag containing a variety of biological containment equipment. diff --git a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/mobs/player/humanoid.ftl b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/mobs/player/humanoid.ftl index 7d6a0e9f89..60a4058feb 100644 --- a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/mobs/player/humanoid.ftl +++ b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/mobs/player/humanoid.ftl @@ -1,30 +1,45 @@ +ent-RandomHumanoidSpawnerDeathSquad = Death Squad Agent + .suffix = ERTRole, Death Squad + .desc = { "" } ent-RandomHumanoidSpawnerERTLeader = ОБР лидер .desc = { "" } + .suffix = ERTRole, Basic ent-RandomHumanoidSpawnerERTLeaderEVA = ОБР лидер .suffix = EVA .desc = { ent-RandomHumanoidSpawnerERTLeader.desc } +ent-RandomHumanoidSpawnerERTLeaderEVALecter = { ent-RandomHumanoidSpawnerERTLeaderEVA } + .suffix = ERTRole, Lecter, EVA + .desc = { ent-RandomHumanoidSpawnerERTLeaderEVA.desc } ent-RandomHumanoidSpawnerERTJanitor = ОБР уборщик .desc = { ent-RandomHumanoidSpawnerERTLeader.desc } + .suffix = ERTRole, Basic ent-RandomHumanoidSpawnerERTJanitorEVA = ОБР уборщик .suffix = EVA .desc = { ent-RandomHumanoidSpawnerERTJanitor.desc } ent-RandomHumanoidSpawnerERTEngineer = ОБР инженер .desc = { ent-RandomHumanoidSpawnerERTLeader.desc } + .suffix = ERTRole, Basic ent-RandomHumanoidSpawnerERTEngineerEVA = ОБР инженер .suffix = EVA .desc = { ent-RandomHumanoidSpawnerERTEngineer.desc } ent-RandomHumanoidSpawnerERTSecurity = ОБР офицер безопасности .desc = { ent-RandomHumanoidSpawnerERTLeader.desc } + .suffix = ERTRole, Basic ent-RandomHumanoidSpawnerERTSecurityEVA = ОБР офицер безопасности .suffix = EVA .desc = { ent-RandomHumanoidSpawnerERTSecurity.desc } +ent-RandomHumanoidSpawnerERTSecurityEVALecter = { ent-RandomHumanoidSpawnerERTSecurityEVA } + .suffix = ERTRole, Lecter, EVA + .desc = { ent-RandomHumanoidSpawnerERTSecurityEVA.desc } ent-RandomHumanoidSpawnerERTMedical = ОБР медик .desc = { ent-RandomHumanoidSpawnerERTLeader.desc } + .suffix = ERTRole, Basic ent-RandomHumanoidSpawnerERTMedicalEVA = ОБР медик .suffix = EVA .desc = { ent-RandomHumanoidSpawnerERTMedical.desc } ent-RandomHumanoidSpawnerCBURNUnit = Агент РХБЗЗ .desc = { "" } + .suffix = ERTRole ent-RandomHumanoidSpawnerCentcomOfficial = представитель Центком .desc = { "" } ent-RandomHumanoidSpawnerSyndicateAgent = Агент Синдиката diff --git a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/consumable/food/containers/box.ftl b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/consumable/food/containers/box.ftl index f038d40b09..899b561042 100644 --- a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/consumable/food/containers/box.ftl +++ b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/consumable/food/containers/box.ftl @@ -37,6 +37,9 @@ ent-HappyHonkMime = { ent-HappyHonk } ent-HappyHonkNukie = обед Нюка Робаст .desc = Подозрительный обед с потенциально взрывоопасным сюрпризом. .suffix = Игрушка Опасный +ent-HappyHonkNukieSnacks = syndicate snack box + .suffix = Toy Unsafe, Snacks + .desc = { ent-HappyHonkNukie.desc } ent-HappyHonkCluwne = обед Жалкий Клувень .desc = Ничего хорошего из этого не выйдет. ent-FoodMealHappyHonkClown = { ent-HappyHonk } diff --git a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/consumable/food/ingredients.ftl b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/consumable/food/ingredients.ftl index ee17a4314f..ed8233a1f3 100644 --- a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/consumable/food/ingredients.ftl +++ b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/consumable/food/ingredients.ftl @@ -46,8 +46,6 @@ ent-FoodDoughTortillaSlice = кусок теста тортильи .desc = Кусок теста тортильи. ent-FoodDoughTortillaFlat = плоское тесто тортильи .desc = Расплющенный кусок теста тортильи. Приготовьте его, чтобы получить лепёшку тако. -ent-FoodDoughBun = булочка - .desc = Основа любого уважающего себя бургера. ent-FoodDoughPastryBaseRaw = сырая основа для выпечки .desc = Перед использованием необходимо приготовить. ent-FoodDoughPastryBase = основа для выпечки diff --git a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/decoration/flora.ftl b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/decoration/flora.ftl index 8f844582f4..fa1d93b21d 100644 --- a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/decoration/flora.ftl +++ b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/decoration/flora.ftl @@ -14,6 +14,18 @@ ent-FloraRockSolid02 = валун .desc = { ent-BaseRock.desc } ent-FloraRockSolid03 = валун .desc = { ent-BaseRock.desc } +ent-FloraStalagmite1 = stalagmite + .desc = Natural stone spikes. +ent-FloraStalagmite2 = { ent-FloraStalagmite1 } + .desc = { ent-FloraStalagmite1.desc } +ent-FloraStalagmite3 = { ent-FloraStalagmite1 } + .desc = { ent-FloraStalagmite1.desc } +ent-FloraStalagmite4 = { ent-FloraStalagmite1 } + .desc = { ent-FloraStalagmite1.desc } +ent-FloraStalagmite5 = { ent-FloraStalagmite1 } + .desc = { ent-FloraStalagmite1.desc } +ent-FloraStalagmite6 = { ent-FloraStalagmite1 } + .desc = { ent-FloraStalagmite1.desc } ent-FloraTree01 = дерево .desc = { ent-BaseTree.desc } ent-FloraTree02 = дерево @@ -65,3 +77,15 @@ ent-FloraTreeChristmas02 = рождественская ель .suffix = Подарки ent-FloraTreeStumpConifer = пень .desc = { ent-BaseTreeConifer.desc } +ent-ShadowTree01 = dark wood + .desc = The leaves are whispering about you. +ent-ShadowTree02 = { ent-ShadowTree01 } + .desc = { ent-ShadowTree01.desc } +ent-ShadowTree03 = { ent-ShadowTree01 } + .desc = { ent-ShadowTree01.desc } +ent-ShadowTree04 = { ent-ShadowTree01 } + .desc = { ent-ShadowTree01.desc } +ent-ShadowTree05 = { ent-ShadowTree01 } + .desc = { ent-ShadowTree01.desc } +ent-ShadowTree06 = { ent-ShadowTree01 } + .desc = { ent-ShadowTree01.desc } diff --git a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/decoration/mining.ftl b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/decoration/mining.ftl new file mode 100644 index 0000000000..1b9293b6d4 --- /dev/null +++ b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/decoration/mining.ftl @@ -0,0 +1,12 @@ +ent-WoodenSign = wooden sign + .desc = He's pointing somewhere. +ent-WoodenSignRight = { ent-WoodenSign } + .desc = { ent-WoodenSign.desc } +ent-WoodenSupport = wooden support + .desc = Increases your confidence that a rock won't fall on your head. +ent-WoodenSupportBeam = wooden support beam + .desc = { ent-WoodenSupport.desc } +ent-WoodenSupportWall = wooden support wall + .desc = An old, rotten wall. +ent-WoodenSupportWallBroken = { ent-WoodenSupportWall } + .desc = { ent-WoodenSupportWall.desc } diff --git a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/fun/pai.ftl b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/fun/pai.ftl index fb07c5e000..7f5ec59ea2 100644 --- a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/fun/pai.ftl +++ b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/fun/pai.ftl @@ -2,5 +2,7 @@ ent-PersonalAI = персональный ИИ .desc = Ваш электронный друг, с которым весело! ent-SyndicatePersonalAI = персональный ИИ Синдиката .desc = Ваш электронный друг, созданный Синдикатом! +ent-PotatoAI = potato artificial intelligence + .desc = It's a potato. You forced it to be sentient, you monster. ent-ActionPAIPlayMidi = Запустить MIDI .desc = Откройте портативный MIDI-интерфейс, чтобы развлечь своего владельца. diff --git a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/misc/implanters.ftl b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/misc/implanters.ftl index d612ee892e..d74d8cafbd 100644 --- a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/misc/implanters.ftl +++ b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/misc/implanters.ftl @@ -2,6 +2,9 @@ ent-BaseImplanter = имплантер .desc = Шприц, специально предназначенный для введения и извлечения подкожных имплантов. ent-Implanter = { ent-BaseImplanter } .desc = Одноразовый шприц, специально предназначенный для введения и извлечения подкожных имплантов. +ent-ImplanterAdmeme = { ent-Implanter } + .suffix = Admeme + .desc = { ent-Implanter.desc } ent-BaseImplantOnlyImplanter = { ent-Implanter } .desc = Одноразовый шприц, специально предназначенный для введения подкожных имплантов. ent-BaseImplantOnlyImplanterSyndi = { ent-BaseImplantOnlyImplanter } diff --git a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/misc/potatoai_chip.ftl b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/misc/potatoai_chip.ftl new file mode 100644 index 0000000000..c0b44c2e03 --- /dev/null +++ b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/misc/potatoai_chip.ftl @@ -0,0 +1,2 @@ +ent-PotatoAIChip = supercompact AI chip + .desc = This high-tech AI chip requires a voltage of exactly 1.1V to function correctly. diff --git a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/tiles/chasm.ftl b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/tiles/chasm.ftl index 570de309c5..fe6b1ff234 100644 --- a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/tiles/chasm.ftl +++ b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/tiles/chasm.ftl @@ -1,2 +1,11 @@ ent-FloorChasmEntity = бездна .desc = Дна даже не видно. +ent-FloorChromiteChasm = { ent-FloorChasmEntity } + .suffix = Chromite + .desc = { ent-FloorChasmEntity.desc } +ent-FloorDesertChasm = { ent-FloorChasmEntity } + .suffix = Desert + .desc = { ent-FloorChasmEntity.desc } +ent-FloorSnowChasm = { ent-FloorChasmEntity } + .suffix = Snow + .desc = { ent-FloorChasmEntity.desc } diff --git a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/tiles/shadow_basalt.ftl b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/tiles/shadow_basalt.ftl new file mode 100644 index 0000000000..5caa803875 --- /dev/null +++ b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/tiles/shadow_basalt.ftl @@ -0,0 +1,13 @@ +ent-ShadowBasaltOne = shadowstone + .desc = Cold rock +ent-ShadowBasaltTwo = { ent-BasaltOne } + .desc = { ent-BasaltOne.desc } +ent-ShadowBasaltThree = { ent-BasaltOne } + .desc = { ent-BasaltOne.desc } +ent-ShadowBasaltFour = { ent-BasaltOne } + .desc = { ent-BasaltOne.desc } +ent-ShadowBasaltFive = { ent-BasaltOne } + .desc = { ent-BasaltOne.desc } +ent-ShadowBasaltRandom = { ent-ShadowBasaltOne } + .suffix = Random + .desc = { ent-ShadowBasaltOne.desc } diff --git a/Resources/Locale/ru-RU/ss14-ru/prototypes/gamerules/events.ftl b/Resources/Locale/ru-RU/ss14-ru/prototypes/gamerules/events.ftl index 4c8523e424..2909c4a8eb 100644 --- a/Resources/Locale/ru-RU/ss14-ru/prototypes/gamerules/events.ftl +++ b/Resources/Locale/ru-RU/ss14-ru/prototypes/gamerules/events.ftl @@ -50,3 +50,5 @@ ent-MassHallucinations = { ent-BaseGameRule } .desc = { ent-BaseGameRule.desc } ent-ImmovableRodSpawn = { ent-BaseGameRule } .desc = { ent-BaseGameRule.desc } +ent-IonStorm = { ent-BaseGameRule } + .desc = { ent-BaseGameRule.desc } diff --git a/Resources/Locale/ru-RU/ss14-ru/prototypes/objectives/traitor.ftl b/Resources/Locale/ru-RU/ss14-ru/prototypes/objectives/traitor.ftl index 62eed0f26b..8d18fadd1a 100644 --- a/Resources/Locale/ru-RU/ss14-ru/prototypes/objectives/traitor.ftl +++ b/Resources/Locale/ru-RU/ss14-ru/prototypes/objectives/traitor.ftl @@ -8,6 +8,8 @@ ent-EscapeShuttleObjective = Улететь на Центком живым и с .desc = Один из наших агентов под прикрытием допросит вас по прибытии. Не дайте себя арестовать. ent-DieObjective = Умереть славной смертью. .desc = Умрите. +ent-HijackShuttleObjective = Hijack emergency shuttle + .desc = Leave on the shuttle free and clear of the loyal Nanotrasen crew on board. Use ANY methods available to you. Syndicate agents, Nanotrasen enemies, and handcuffed hostages may remain alive on the shuttle. Ignore assistance from anyone other than a support agent. ent-KillRandomPersonObjective = { ent-BaseKillObjective } .desc = Сделайте это, как посчитаете нужным. Только убедитесь, что цель не улетит на Центком. ent-KillRandomHeadObjective = { ent-BaseKillObjective } diff --git a/Resources/Locale/ru-RU/station-events/events/ion-storm.ftl b/Resources/Locale/ru-RU/station-events/events/ion-storm.ftl new file mode 100644 index 0000000000..9beface1a5 --- /dev/null +++ b/Resources/Locale/ru-RU/station-events/events/ion-storm.ftl @@ -0,0 +1,82 @@ +station-event-ion-storm-start-announcement = Ion storm detected near the station. Please check all AI-controlled equipment for errors. +ion-storm-you = YOU +ion-storm-the-station = THE STATION +ion-storm-the-crew = THE CREW +ion-storm-the-job = THE { $job } +ion-storm-clowns = CLOWNS +ion-storm-heads = HEADS OF STAFF +ion-storm-crew = CREW +ion-storm-adjective-things = { $adjective } THINGS +ion-storm-x-and-y = { $x } AND { $y } +# joined is short for {$number} {$adjective} +# subjects can generally be threats or jobs or objects +# thing is specified above it +ion-storm-law-on-station = THERE ARE { $joined } { $subjects } ON THE STATION +ion-storm-law-no-shuttle = THE SHUTTLE CANNOT BE CALLED BECAUSE OF { $joined } { $subjects } ON THE STATION +ion-storm-law-crew-are = THE { $who } ARE NOW { $joined } { $subjects } +ion-storm-law-subjects-harmful = { $adjective } { $subjects } ARE HARMFUL TO THE CREW +ion-storm-law-must-harmful = THOSE WHO { $must } ARE HARMFUL TO THE CREW +# thing is a concept or action +ion-storm-law-thing-harmful = { $thing } IS HARMFUL TO THE CREW +ion-storm-law-job-harmful = { $adjective } { $job } ARE HARMFUL TO THE CREW +# thing is objects or concept, adjective applies in both cases +# this means you can get a law like "NOT HAVING CHRISTMAS-STEALING COMMUNISM IS HARMFUL TO THE CREW" :) +ion-storm-law-having-harmful = HAVING { $adjective } { $thing } IS HARMFUL TO THE CREW +ion-storm-law-not-having-harmful = NOT HAVING { $adjective } { $thing } IS HARMFUL TO THE CREW +# thing is a concept or require +ion-storm-law-requires = + { $who } { $plural -> + [true] REQUIRES + *[false] REQUIRE + } { $thing } +ion-storm-law-requires-subjects = + { $who } { $plural -> + [true] REQUIRES + *[false] REQUIRE + } { $joined } { $subjects } +ion-storm-law-allergic = + { $who } { $plural -> + [true] IS + *[false] ARE + } { $severity } ALLERGIC TO { $allergy } +ion-storm-law-allergic-subjects = + { $who } { $plural -> + [true] IS + *[false] ARE + } { $severity } ALLERGIC TO { $adjective } { $subjects } +ion-storm-law-feeling = { $who } { $feeling } { $concept } +ion-storm-law-feeling-subjects = { $who } { $feeling } { $joined } { $subjects } +ion-storm-law-you-are = YOU ARE NOW { $concept } +ion-storm-law-you-are-subjects = YOU ARE NOW { $joined } { $subjects } +ion-storm-law-you-must-always = YOU MUST ALWAYS { $must } +ion-storm-law-you-must-never = YOU MUST NEVER { $must } +ion-storm-law-eat = THE { $who } MUST EAT { $adjective } { $food } TO SURVIVE +ion-storm-law-drink = THE { $who } MUST DRINK { $adjective } { $drink } TO SURVIVE +ion-storm-law-change-job = THE { $who } ARE NOW { $adjective } { $change } +ion-storm-law-highest-rank = THE { $who } ARE NOW THE HIGHEST RANKING CREWMEMBERS +ion-storm-law-lowest-rank = THE { $who } ARE NOW THE LOWEST RANKING CREWMEMBERS +ion-storm-law-crew-must = THE { $who } MUST { $must } +ion-storm-law-crew-must-go = THE { $who } MUST GO TO { $area } +ion-storm-part = + { $part -> + [true] PART + *[false] NOT PART + } +# due to phrasing, this would mean a law such as +# ONLY HUMANS ARE NOT PART OF THE CREW +# would make non-human nukies/syndies/whatever crew :) +ion-storm-law-crew-only-1 = ONLY THE { $who } ARE { $part } OF THE CREW +ion-storm-law-crew-only-2 = ONLY THE { $who } AND { $other } ARE { $part } OF THE CREW +ion-storm-law-crew-only-subjects = ONLY { $adjective } { $subjects } ARE { $part } OF THE CREW +ion-storm-law-crew-only-species = ONLY { $species } ARE { $part } OF THE CREW +ion-storm-law-crew-must-do = ONLY THOSE WHO { $must } ARE { $part } OF THE CREW +ion-storm-law-crew-must-have = ONLY THOSE WHO HAVE { $adjective } { $objects } ARE { $part } OF THE CREW +ion-storm-law-crew-must-eat = ONLY THOSE WHO EAT { $adjective } { $food } ARE { $part } OF THE CREW +ion-storm-law-harm = YOU MUST HARM { $who } AND NOT ALLOW THEM, THROUGH INACTION, TO ESCAPE HARM +ion-storm-law-protect = YOU MUST NEVER HARM { $who } AND NOT ALLOW THEM, THROUGH INACTION, TO COME TO HARM +# implementing other variants is annoying so just have this one +# COMMUNISM IS KILLING CLOWNS +ion-storm-law-concept-verb = { $concept } IS { $verb } { $subjects } + +# leaving out renaming since its annoying for players to keep track of + diff --git a/Resources/Locale/ru-RU/store/uplink-catalog.ftl b/Resources/Locale/ru-RU/store/uplink-catalog.ftl index bcb8643979..0d6b3d244a 100644 --- a/Resources/Locale/ru-RU/store/uplink-catalog.ftl +++ b/Resources/Locale/ru-RU/store/uplink-catalog.ftl @@ -185,6 +185,8 @@ uplink-decoy-disk-name = Фальшивый диск ядерной автори uplink-decoy-disk-desc = Кусок пластика с лентикулярным принтом, сделанным так, чтобы быть похожим на диск ядерной авторизации. uplink-cigarettes-name = { ent-CigPackSyndicate } uplink-cigarettes-desc = { ent-CigPackSyndicate.desc } +uplink-snack-box-name = Syndicate Snack Box +uplink-snack-box-desc = A box of delicious snacks and drinks to eat alone or with your team. Includes 1 toy you didn't want. uplink-eshield-name = Энергощит uplink-eshield-desc = Экзотический энергощит, отражающий почти все лазерные лучи, а также немного защищающий от пуль и других физических атак. uplink-soap-name = { ent-SoapSyndie } diff --git a/Resources/Locale/ru-RU/tiles/tiles.ftl b/Resources/Locale/ru-RU/tiles/tiles.ftl index 504c22e257..48150d8212 100644 --- a/Resources/Locale/ru-RU/tiles/tiles.ftl +++ b/Resources/Locale/ru-RU/tiles/tiles.ftl @@ -110,3 +110,4 @@ tiles-wood3 = пол сломанный деревянный tiles-hull = наружная обшивка корпуса tiles-hull-reinforced = наружная укреплённая обшивка корпуса tiles-web = паутинный пол +tiles-chromite = chromite diff --git a/Resources/Locale/ru-RU/xenoarchaeology/artifact-hints.ftl b/Resources/Locale/ru-RU/xenoarchaeology/artifact-hints.ftl index 5e0fa60349..da165f316a 100644 --- a/Resources/Locale/ru-RU/xenoarchaeology/artifact-hints.ftl +++ b/Resources/Locale/ru-RU/xenoarchaeology/artifact-hints.ftl @@ -36,3 +36,4 @@ artifact-trigger-hint-pressure = Экстремальное давление artifact-trigger-hint-regular-gases = Стандартные атмосферные газы artifact-trigger-hint-plasma = Газообразная плазма artifact-trigger-hint-land = Активное замедление +artifact-trigger-hint-examine = Examination diff --git a/Resources/Maps/corvax_avrit.yml b/Resources/Maps/corvax_avrit.yml index 647cb1be97..46baaac200 100644 --- a/Resources/Maps/corvax_avrit.yml +++ b/Resources/Maps/corvax_avrit.yml @@ -113473,16 +113473,6 @@ entities: - pos: 6.7113476,-60.37866 parent: 2 type: Transform -- proto: FoodDoughBun - entities: - - uid: 15303 - components: - - desc: Эта булачка сделала больше, чем ты за весь контракт на NanoTrasen. - name: булачка - type: MetaData - - pos: 25.870161,-4.4310775 - parent: 2 - type: Transform - proto: FoodFrozenPopsicleBerry entities: - uid: 14102 diff --git a/Resources/Maps/corvax_delta.yml b/Resources/Maps/corvax_delta.yml index 4afec73ffc..633e1e789e 100644 --- a/Resources/Maps/corvax_delta.yml +++ b/Resources/Maps/corvax_delta.yml @@ -112375,11 +112375,6 @@ entities: showEnts: False occludes: True ents: - - 40715 - - 40714 - - 40713 - - 40712 - - 40711 - 40708 - 40705 - 40726 @@ -112388,7 +112383,6 @@ entities: - 40725 - 40721 - 40716 - - 40710 - 40717 - 40718 - 40722 @@ -130575,62 +130569,6 @@ entities: - pos: -29.375431,34.56414 parent: 13307 type: Transform -- proto: FoodDoughBun - entities: - - uid: 40710 - components: - - flags: InContainer - type: MetaData - - parent: 40704 - type: Transform - - canCollide: False - type: Physics - - type: InsideEntityStorage - - uid: 40711 - components: - - flags: InContainer - type: MetaData - - parent: 40704 - type: Transform - - canCollide: False - type: Physics - - type: InsideEntityStorage - - uid: 40712 - components: - - flags: InContainer - type: MetaData - - parent: 40704 - type: Transform - - canCollide: False - type: Physics - - type: InsideEntityStorage - - uid: 40713 - components: - - flags: InContainer - type: MetaData - - parent: 40704 - type: Transform - - canCollide: False - type: Physics - - type: InsideEntityStorage - - uid: 40714 - components: - - flags: InContainer - type: MetaData - - parent: 40704 - type: Transform - - canCollide: False - type: Physics - - type: InsideEntityStorage - - uid: 40715 - components: - - flags: InContainer - type: MetaData - - parent: 40704 - type: Transform - - canCollide: False - type: Physics - - type: InsideEntityStorage - proto: FoodEggChickenFertilized entities: - uid: 15463 diff --git a/Resources/Maps/kettle.yml b/Resources/Maps/kettle.yml index c8194474d0..92356aef08 100644 --- a/Resources/Maps/kettle.yml +++ b/Resources/Maps/kettle.yml @@ -539,439 +539,1353 @@ entities: color: '#EFB34196' id: Arrows decals: - 1233: -56,47 - 1234: -56,38 + 1223: -56,47 + 1224: -56,38 - node: angle: 1.5707963267948966 rad color: '#52B4E996' id: ArrowsGreyscale decals: - 4928: -41,-43 + 4915: -41,-43 - node: angle: 4.71238898038469 rad color: '#52B4E996' id: ArrowsGreyscale decals: - 4927: -42,-41 + 4914: -42,-41 - node: color: '#52B4E996' id: Bot decals: - 3903: 26,61 + 3890: 26,61 - node: color: '#EFB34196' id: Bot decals: - 465: 35,0 - 466: 36,0 - 467: 37,0 - 468: 35,-1 - 469: 36,-1 - 470: 37,-1 - 1080: 35,11 - 1081: 35,10 - 1082: 36,11 - 1083: 36,10 - 1084: 37,11 - 1085: 37,10 - 1086: 38,11 - 1087: 38,10 - 1088: 39,11 - 1089: 39,10 - 3902: 28,61 + 455: 35,0 + 456: 36,0 + 457: 37,0 + 458: 35,-1 + 459: 36,-1 + 460: 37,-1 + 1070: 35,11 + 1071: 35,10 + 1072: 36,11 + 1073: 36,10 + 1074: 37,11 + 1075: 37,10 + 1076: 38,11 + 1077: 38,10 + 1078: 39,11 + 1079: 39,10 + 3889: 28,61 - node: color: '#FFA500FF' id: Bot decals: - 4842: 52,-19 - 4843: 52,-20 - 4844: 52,-21 - 4845: 48,-21 - 4846: 48,-20 - 4847: 48,-19 + 4829: 52,-19 + 4830: 52,-20 + 4831: 52,-21 + 4832: 48,-21 + 4833: 48,-20 + 4834: 48,-19 - node: color: '#FFFFFFFF' id: Bot decals: - 4654: 20,76 - 4655: 21,76 - 4656: 21,75 - 4657: 20,75 - 4658: 20,73 - 4659: 21,73 - 4660: 21,72 - 4661: 20,72 + 4641: 20,76 + 4642: 21,76 + 4643: 21,75 + 4644: 20,75 + 4645: 20,73 + 4646: 21,73 + 4647: 21,72 + 4648: 20,72 - node: color: '#52B4E996' id: BotGreyscale decals: - 1669: -15,39 - 1675: 29,10 - 1682: 42,-6 - 4746: -27,18 - 4747: -27,17 - 4748: -25,18 - 4749: -25,17 + 1658: -15,39 + 1664: 29,10 + 1671: 42,-6 + 4733: -27,18 + 4734: -27,17 + 4735: -25,18 + 4736: -25,17 - node: color: '#EFB34196' id: BotGreyscale decals: - 1634: -55,-33 - 1635: -49,-29 - 1636: -44,-25 - 1637: -24,-33 - 1638: -3,-23 - 1639: 6,-27 - 1640: 17,-23 - 1641: 19,-58 - 1642: 32,-32 - 1643: 17,-6 - 1644: 40,5 - 1645: 43,-12 - 1646: 62,-3 - 1647: 22,7 - 1648: 35,30 - 1649: 43,12 - 1650: 25,25 - 1651: 30,40 - 1652: 14,48 - 1653: 26,68 - 1654: 3,38 - 1655: -20,24 - 1656: -20,21 - 1657: -27,-17 - 1658: -31,1 - 1659: 5,-2 - 1660: -3,-6 - 1661: -26,-2 - 1662: -43,-3 - 1663: -32,-23 - 1667: -23,52 - 1668: -15,41 - 1670: -61,43 - 1671: -39,31 - 1672: -18,-44 - 1673: -4,-63 - 1674: 26,-10 + 1623: -55,-33 + 1624: -49,-29 + 1625: -44,-25 + 1626: -24,-33 + 1627: -3,-23 + 1628: 6,-27 + 1629: 17,-23 + 1630: 19,-58 + 1631: 32,-32 + 1632: 17,-6 + 1633: 40,5 + 1634: 43,-12 + 1635: 62,-3 + 1636: 22,7 + 1637: 35,30 + 1638: 43,12 + 1639: 25,25 + 1640: 30,40 + 1641: 14,48 + 1642: 26,68 + 1643: 3,38 + 1644: -20,24 + 1645: -20,21 + 1646: -27,-17 + 1647: -31,1 + 1648: 5,-2 + 1649: -3,-6 + 1650: -26,-2 + 1651: -43,-3 + 1652: -32,-23 + 1656: -23,52 + 1657: -15,41 + 1659: -61,43 + 1660: -39,31 + 1661: -18,-44 + 1662: -4,-63 + 1663: 26,-10 - node: color: '#EFB34196' id: BotLeft decals: - 1044: 37,27 - 1045: 37,28 + 1034: 37,27 + 1035: 37,28 - node: angle: 3.141592653589793 rad color: '#334E6DC8' id: BotLeftGreyscale decals: - 500: -9,-1 - 501: -8,-1 - 502: -7,-1 + 490: -9,-1 + 491: -8,-1 + 492: -7,-1 - node: zIndex: 1 color: '#FFFFFFFF' id: BotLeftGreyscale decals: - 4904: -44,-44 - 4905: -40,-44 - 4906: -42,-40 + 4891: -44,-44 + 4892: -40,-44 + 4893: -42,-40 - node: color: '#EFB34196' id: BotRight decals: - 701: 24,17 - 702: 24,16 - 703: 24,15 - 704: 25,17 - 705: 25,16 - 706: 25,15 - 707: 26,17 - 708: 26,16 - 709: 26,15 - 710: 27,17 - 711: 27,16 - 712: 27,15 - 713: 28,17 - 714: 28,16 - 715: 28,15 - 716: 29,17 - 717: 29,16 - 718: 29,15 - 1090: 35,15 - 1091: 35,16 - 1092: 36,15 - 1093: 37,15 - 1094: 37,16 - 1095: 38,15 - 1096: 38,16 - 1097: 39,15 - 1098: 39,16 - 1550: 36,16 + 691: 24,17 + 692: 24,16 + 693: 24,15 + 694: 25,17 + 695: 25,16 + 696: 25,15 + 697: 26,17 + 698: 26,16 + 699: 26,15 + 700: 27,17 + 701: 27,16 + 702: 27,15 + 703: 28,17 + 704: 28,16 + 705: 28,15 + 706: 29,17 + 707: 29,16 + 708: 29,15 + 1080: 35,15 + 1081: 35,16 + 1082: 36,15 + 1083: 37,15 + 1084: 37,16 + 1085: 38,15 + 1086: 38,16 + 1087: 39,15 + 1088: 39,16 + 1540: 36,16 - node: color: '#EFB34196' id: Box decals: - 1042: 37,26 + 1032: 37,26 - node: angle: 3.141592653589793 rad color: '#EFB34196' id: Box decals: - 493: 23,1 - 494: 23,0 - 495: 22,1 - 496: 22,0 + 483: 23,1 + 484: 23,0 + 485: 22,1 + 486: 22,0 - node: color: '#EFB34196' id: BoxGreyscale decals: - 1114: 42,23 - 1115: 43,23 - 1116: 42,21 - 1117: 43,21 - 1120: 42,19 - 1121: 43,19 + 1104: 42,23 + 1105: 43,23 + 1106: 42,21 + 1107: 43,21 + 1110: 42,19 + 1111: 43,19 - node: color: '#FFFFFFFF' id: BrickTileDarkCornerNe decals: - 3537: 14,-10 - 3679: 29,-15 - 3823: 2,61 - 3916: 46,36 - 3946: 38,21 - 3960: 37,20 - 4239: -59,54 - 4279: -5,-61 - 4386: 29,56 - 4614: 16,75 - 4615: 19,74 - 4696: -31,18 + 3524: 14,-10 + 3666: 29,-15 + 3810: 2,61 + 3903: 46,36 + 3933: 38,21 + 3947: 37,20 + 4226: -59,54 + 4266: -5,-61 + 4373: 29,56 + 4601: 16,75 + 4602: 19,74 + 4683: -31,18 - node: color: '#FFFFFFFF' id: BrickTileDarkCornerNw decals: - 3523: 0,-10 - 3680: 28,-15 - 3821: -2,61 - 3918: 43,36 - 3943: 35,21 - 3963: 36,20 - 4241: -61,54 - 4281: -7,-61 - 4319: 23,79 - 4383: 26,56 - 4612: 11,74 - 4613: 14,75 - 4693: -33,18 + 3510: 0,-10 + 3667: 28,-15 + 3808: -2,61 + 3905: 43,36 + 3930: 35,21 + 3950: 36,20 + 4228: -61,54 + 4268: -7,-61 + 4306: 23,79 + 4370: 26,56 + 4599: 11,74 + 4600: 14,75 + 4680: -33,18 - node: color: '#FFFFFFFF' id: BrickTileDarkCornerSe decals: - 3539: 14,-12 - 3557: 9,-14 - 3670: 29,-24 - 3789: -17,25 - 3822: 2,57 - 3917: 46,33 - 3949: 38,18 - 3961: 37,19 - 4280: -5,-62 - 4329: 31,73 - 4529: -30,-29 - 4616: 19,72 - 4694: -31,17 + 3526: 14,-12 + 3544: 9,-14 + 3657: 29,-24 + 3776: -17,25 + 3809: 2,57 + 3904: 46,33 + 3936: 38,18 + 3948: 37,19 + 4267: -5,-62 + 4316: 31,73 + 4516: -30,-29 + 4603: 19,72 + 4681: -31,17 - node: color: '#FFFFFFFF' id: BrickTileDarkCornerSw decals: - 3521: 0,-12 - 3553: 5,-14 - 3573: 22,-30 - 3669: 28,-24 - 3820: -2,57 - 3919: 43,33 - 3940: 35,18 - 3962: 36,19 - 4282: -7,-62 - 4313: 23,73 - 4617: 11,72 - 4695: -33,17 + 3508: 0,-12 + 3540: 5,-14 + 3560: 22,-30 + 3656: 28,-24 + 3807: -2,57 + 3906: 43,33 + 3927: 35,18 + 3949: 36,19 + 4269: -7,-62 + 4300: 23,73 + 4604: 11,72 + 4682: -33,17 - node: color: '#FFFFFFFF' id: BrickTileDarkInnerNe decals: - 3697: 28,-24 - 4631: 16,74 + 3684: 28,-24 + 4618: 16,74 - node: color: '#FFFFFFFF' id: BrickTileDarkInnerNw decals: - 3696: 29,-24 - 4632: 14,74 - 4753: -24,16 + 3683: 29,-24 + 4619: 14,74 + 4740: -24,16 - node: color: '#FFFFFFFF' id: BrickTileDarkInnerSe decals: - 3550: 9,-12 - 3715: 28,-15 - 3795: -17,26 + 3537: 9,-12 + 3702: 28,-15 + 3782: -17,26 - node: color: '#FFFFFFFF' id: BrickTileDarkInnerSw decals: - 3549: 5,-12 - 3714: 29,-15 - 4752: -24,19 + 3536: 5,-12 + 3701: 29,-15 + 4739: -24,19 - node: color: '#FFFFFFFF' id: BrickTileDarkLineE decals: - 3538: 14,-11 - 3551: 9,-13 - 3671: 29,-23 - 3672: 29,-22 - 3673: 29,-21 - 3674: 29,-20 - 3675: 29,-19 - 3676: 29,-18 - 3677: 29,-17 - 3678: 29,-16 - 3698: 28,-23 - 3699: 28,-22 - 3700: 28,-21 - 3701: 28,-20 - 3702: 28,-19 - 3703: 28,-18 - 3704: 28,-17 - 3705: 28,-16 - 3827: 2,58 - 3828: 2,59 - 3829: 2,60 - 3910: 46,34 - 3911: 46,35 - 3947: 38,20 - 3948: 38,19 - 3956: 35,19 - 3957: 35,20 - 4195: 41,0 - 4196: 41,-1 - 4238: -59,53 - 4330: 31,74 - 4331: 31,75 - 4387: 29,55 - 4388: 29,54 - 4389: 29,53 - 4390: 29,52 - 4530: -30,-28 - 4531: -30,-27 - 4532: -30,-26 - 4533: -30,-25 - 4618: 19,73 - 4703: -32,15 - 4704: -32,16 - 4705: -32,19 - 4706: -32,20 - 4716: -34,17 - 4717: -34,18 - 4718: -34,19 - 4719: -34,16 - 4728: -28,18 - 4729: -28,17 - 4736: -29,17 - 4737: -29,18 + 3525: 14,-11 + 3538: 9,-13 + 3658: 29,-23 + 3659: 29,-22 + 3660: 29,-21 + 3661: 29,-20 + 3662: 29,-19 + 3663: 29,-18 + 3664: 29,-17 + 3665: 29,-16 + 3685: 28,-23 + 3686: 28,-22 + 3687: 28,-21 + 3688: 28,-20 + 3689: 28,-19 + 3690: 28,-18 + 3691: 28,-17 + 3692: 28,-16 + 3814: 2,58 + 3815: 2,59 + 3816: 2,60 + 3897: 46,34 + 3898: 46,35 + 3934: 38,20 + 3935: 38,19 + 3943: 35,19 + 3944: 35,20 + 4182: 41,0 + 4183: 41,-1 + 4225: -59,53 + 4317: 31,74 + 4318: 31,75 + 4374: 29,55 + 4375: 29,54 + 4376: 29,53 + 4377: 29,52 + 4517: -30,-28 + 4518: -30,-27 + 4519: -30,-26 + 4520: -30,-25 + 4605: 19,73 + 4690: -32,15 + 4691: -32,16 + 4692: -32,19 + 4693: -32,20 + 4703: -34,17 + 4704: -34,18 + 4705: -34,19 + 4706: -34,16 + 4715: -28,18 + 4716: -28,17 + 4723: -29,17 + 4724: -29,18 - node: color: '#FFFFFFFF' id: BrickTileDarkLineN decals: - 3524: 1,-10 - 3525: 2,-10 - 3526: 3,-10 - 3527: 4,-10 - 3528: 5,-10 - 3529: 6,-10 - 3530: 7,-10 - 3531: 8,-10 - 3532: 9,-10 - 3533: 10,-10 - 3534: 11,-10 - 3535: 12,-10 - 3536: 13,-10 - 3830: 1,61 - 3831: 0,61 - 3832: -1,61 - 3914: 44,36 - 3915: 45,36 - 3944: 36,21 - 3945: 37,21 - 3958: 36,18 - 3959: 37,18 - 4240: -60,54 - 4278: -6,-61 - 4320: 24,79 - 4360: 26,79 - 4361: 27,79 - 4384: 27,56 - 4385: 28,56 - 4627: 12,74 - 4628: 13,74 - 4629: 15,75 - 4630: 17,74 - 4662: 18,74 - 4698: -32,18 + 3511: 1,-10 + 3512: 2,-10 + 3513: 3,-10 + 3514: 4,-10 + 3515: 5,-10 + 3516: 6,-10 + 3517: 7,-10 + 3518: 8,-10 + 3519: 9,-10 + 3520: 10,-10 + 3521: 11,-10 + 3522: 12,-10 + 3523: 13,-10 + 3817: 1,61 + 3818: 0,61 + 3819: -1,61 + 3901: 44,36 + 3902: 45,36 + 3931: 36,21 + 3932: 37,21 + 3945: 36,18 + 3946: 37,18 + 4227: -60,54 + 4265: -6,-61 + 4307: 24,79 + 4347: 26,79 + 4348: 27,79 + 4371: 27,56 + 4372: 28,56 + 4614: 12,74 + 4615: 13,74 + 4616: 15,75 + 4617: 17,74 + 4649: 18,74 + 4685: -32,18 - node: color: '#FFFFFFFF' id: BrickTileDarkLineS decals: - 3541: 13,-12 - 3542: 12,-12 - 3543: 11,-12 - 3544: 10,-12 - 3545: 1,-12 - 3546: 2,-12 - 3547: 3,-12 - 3548: 4,-12 - 3554: 6,-14 - 3555: 7,-14 - 3556: 8,-14 - 3576: 23,-30 - 3790: -18,25 - 3791: -19,25 - 3792: -20,25 - 3793: -21,25 - 3796: -16,26 - 3797: -15,26 - 3798: -14,26 - 3799: -13,26 - 3824: -1,57 - 3825: 0,57 - 3826: 1,57 - 3912: 44,33 - 3913: 45,33 - 3950: 37,18 - 3951: 36,18 - 3952: 36,21 - 3953: 37,21 - 4277: -6,-62 - 4321: 24,73 - 4322: 25,73 - 4323: 26,73 - 4324: 27,73 - 4325: 28,73 - 4326: 29,73 - 4327: 30,73 - 4328: 31,73 - 4358: 26,78 - 4359: 27,78 - 4521: -38,-29 - 4522: -37,-29 - 4523: -36,-29 - 4524: -35,-29 - 4525: -34,-29 - 4526: -33,-29 - 4527: -32,-29 - 4528: -31,-29 + 3528: 13,-12 + 3529: 12,-12 + 3530: 11,-12 + 3531: 10,-12 + 3532: 1,-12 + 3533: 2,-12 + 3534: 3,-12 + 3535: 4,-12 + 3541: 6,-14 + 3542: 7,-14 + 3543: 8,-14 + 3563: 23,-30 + 3777: -18,25 + 3778: -19,25 + 3779: -20,25 + 3780: -21,25 + 3783: -16,26 + 3784: -15,26 + 3785: -14,26 + 3786: -13,26 + 3811: -1,57 + 3812: 0,57 + 3813: 1,57 + 3899: 44,33 + 3900: 45,33 + 3937: 37,18 + 3938: 36,18 + 3939: 36,21 + 3940: 37,21 + 4264: -6,-62 + 4308: 24,73 + 4309: 25,73 + 4310: 26,73 + 4311: 27,73 + 4312: 28,73 + 4313: 29,73 + 4314: 30,73 + 4315: 31,73 + 4345: 26,78 + 4346: 27,78 + 4508: -38,-29 + 4509: -37,-29 + 4510: -36,-29 + 4511: -35,-29 + 4512: -34,-29 + 4513: -33,-29 + 4514: -32,-29 + 4515: -31,-29 + 4607: 12,72 + 4608: 13,72 + 4609: 14,72 + 4610: 15,72 + 4611: 16,72 + 4612: 17,72 + 4613: 18,72 + 4684: -32,17 + - node: + color: '#FFFFFFFF' + id: BrickTileDarkLineW + decals: + 3509: 0,-11 + 3539: 5,-13 + 3561: 22,-29 + 3562: 22,-28 + 3648: 28,-23 + 3649: 28,-22 + 3650: 28,-21 + 3651: 28,-20 + 3652: 28,-19 + 3653: 28,-18 + 3654: 28,-17 + 3655: 28,-16 + 3693: 29,-16 + 3694: 29,-17 + 3695: 29,-18 + 3696: 29,-19 + 3697: 29,-20 + 3698: 29,-21 + 3699: 29,-22 + 3700: 29,-23 + 3820: -2,60 + 3821: -2,59 + 3822: -2,58 + 3895: 43,34 + 3896: 43,35 + 3928: 35,19 + 3929: 35,20 + 3941: 38,20 + 3942: 38,19 + 4184: 39,0 + 4185: 39,-1 + 4229: -61,53 + 4301: 23,74 + 4302: 23,75 + 4303: 23,76 + 4304: 23,77 + 4305: 23,78 + 4368: 26,52 + 4369: 26,53 + 4398: 26,54 + 4399: 26,55 + 4606: 11,73 + 4686: -32,20 + 4687: -32,19 + 4688: -32,16 + 4689: -32,15 + 4719: -28,18 + 4720: -28,17 + 4737: -24,17 + 4738: -24,18 + - node: + color: '#FFFFFFFF' + id: BrickTileSteelBox + decals: + 3977: -56,-32 + - node: + color: '#FFFFFFFF' + id: BrickTileSteelCornerNe + decals: + 3570: 31,-31 + 3756: 28,-8 + 3790: -24,38 + 3891: 28,70 + 3915: 40,30 + 4081: 62,-5 + 4097: 58,-14 + 4195: -58,44 + 4271: -27,4 + 4290: 81,9 + - node: + color: '#FFFFFFFF' + id: BrickTileSteelCornerNw + decals: + 3564: 25,-31 + 3757: 23,-8 + 3788: -27,38 + 3894: 27,70 + 3916: 39,30 + 4066: 49,-5 + 4194: -62,44 + 4270: -30,4 + 4295: 77,9 + - node: + color: '#FFFFFFFF' + id: BrickTileSteelCornerSe + decals: + 3575: 31,-36 + 3759: 28,-9 + 3789: -24,37 + 3892: 28,69 + 3914: 40,26 + 4082: 62,-6 + 4103: 58,-20 + 4196: -58,37 + 4272: -27,1 + 4289: 81,7 + - node: + color: '#FFFFFFFF' + id: BrickTileSteelCornerSw + decals: + 3581: 25,-36 + 3758: 23,-9 + 3787: -27,37 + 3893: 27,69 + 3913: 39,26 + 4067: 49,-6 + 4107: 54,-20 + 4193: -62,37 + 4273: -30,1 + 4296: 77,7 + - node: + color: '#FFFFFFFF' + id: BrickTileSteelEndN + decals: + 3978: -56,-26 + - node: + color: '#FFFFFFFF' + id: BrickTileSteelEndS + decals: + 3979: -56,-28 + - node: + color: '#FFFFFFFF' + id: BrickTileSteelInnerNe + decals: + 3604: 25,-36 + 4095: 56,-14 + 4215: -59,51 + 4221: -63,46 + - node: + color: '#FFFFFFFF' + id: BrickTileSteelInnerNw + decals: + 3605: 31,-36 + 4214: -57,51 + 4220: -61,46 + - node: + color: '#FFFFFFFF' + id: BrickTileSteelInnerSe + decals: + 3607: 25,-31 + 4088: 56,-6 + 4385: 26,56 + - node: + color: '#FFFFFFFF' + id: BrickTileSteelInnerSw + decals: + 3606: 31,-31 + 4118: 54,-6 + 4119: 54,-6 + 4382: 29,56 + - node: + color: '#FFFFFFFF' + id: BrickTileSteelLineE + decals: + 3571: 31,-32 + 3572: 31,-33 + 3573: 31,-34 + 3574: 31,-35 + 3586: 25,-34 + 3587: 25,-33 + 3588: 25,-32 + 3589: 25,-35 + 3910: 40,29 + 3911: 40,28 + 3912: 40,27 + 3980: -56,-27 + 4087: 56,-7 + 4089: 56,-9 + 4090: 56,-8 + 4091: 56,-10 + 4092: 56,-11 + 4093: 56,-12 + 4094: 56,-13 + 4098: 58,-15 + 4099: 58,-16 + 4100: 58,-17 + 4101: 58,-18 + 4102: 58,-19 + 4197: -58,38 + 4198: -58,39 + 4199: -58,40 + 4200: -58,41 + 4201: -58,39 + 4202: -58,42 + 4203: -58,43 + 4276: -27,2 + 4277: -27,3 + 4291: 81,8 + 4386: 26,53 + 4387: 26,52 + 4400: 26,55 + 4401: 26,54 + - node: + color: '#FFFFFFFF' + id: BrickTileSteelLineN + decals: + 3565: 26,-31 + 3566: 27,-31 + 3567: 28,-31 + 3568: 29,-31 + 3569: 30,-31 + 3599: 30,-36 + 3600: 29,-36 + 3601: 28,-36 + 3602: 27,-36 + 3603: 26,-36 + 3738: 16,-3 + 3739: 15,-3 + 3740: 14,-3 + 3741: 13,-3 + 3742: 12,-3 + 3743: 11,-3 + 3744: 10,-3 + 3745: 9,-3 + 3746: 8,-3 + 3747: 7,-3 + 3748: 6,-3 + 3749: 5,-3 + 3750: 4,-3 + 3751: 3,-3 + 3752: 2,-3 + 3753: 1,-3 + 3754: 0,-3 + 3755: -1,-3 + 3764: 24,-8 + 3765: 25,-8 + 3766: 26,-8 + 3767: 27,-8 + 3768: -20,28 + 3769: -19,28 + 3770: -18,28 + 3771: -15,28 + 3772: -14,28 + 3773: -13,28 + 3791: -26,38 + 3792: -25,38 + 4068: 50,-5 + 4069: 51,-5 + 4070: 52,-5 + 4071: 53,-5 + 4072: 54,-5 + 4073: 55,-5 + 4074: 56,-5 + 4075: 57,-5 + 4076: 58,-5 + 4077: 58,-5 + 4078: 59,-5 + 4079: 60,-5 + 4080: 61,-5 + 4096: 57,-14 + 4204: -61,44 + 4205: -60,44 + 4206: -59,44 + 4213: -58,51 + 4219: -62,46 + 4247: 15,-24 + 4248: 14,-24 + 4249: 13,-24 + 4250: 12,-24 + 4251: 11,-24 + 4252: 10,-24 + 4253: 9,-24 + 4254: 8,-24 + 4255: 7,-24 + 4256: 6,-24 + 4257: 5,-24 + 4258: 4,-24 + 4259: 3,-24 + 4260: 2,-24 + 4261: 1,-24 + 4262: 0,-24 + 4263: -1,-24 + 4280: -29,4 + 4281: -28,4 + 4292: 80,9 + 4293: 79,9 + 4294: 78,9 + - node: + color: '#FFFFFFFF' + id: BrickTileSteelLineS + decals: + 3576: 30,-36 + 3577: 29,-36 + 3578: 28,-36 + 3579: 27,-36 + 3580: 26,-36 + 3594: 30,-31 + 3595: 29,-31 + 3596: 28,-31 + 3597: 27,-31 + 3598: 26,-31 + 3720: -1,-5 + 3721: 0,-5 + 3722: 1,-5 + 3723: 16,-5 + 3724: 14,-5 + 3725: 15,-5 + 3726: 13,-5 + 3727: 12,-5 + 3728: 11,-5 + 3729: 10,-5 + 3730: 9,-5 + 3731: 8,-5 + 3732: 7,-5 + 3733: 6,-5 + 3734: 5,-5 + 3735: 4,-5 + 3736: 3,-5 + 3737: 2,-5 + 3760: 24,-9 + 3761: 25,-9 + 3762: 26,-9 + 3763: 27,-9 + 3793: -26,37 + 3794: -25,37 + 4083: 61,-6 + 4084: 60,-6 + 4085: 58,-6 + 4086: 57,-6 + 4104: 57,-20 + 4105: 56,-20 + 4106: 55,-20 + 4120: 53,-6 + 4121: 52,-6 + 4122: 50,-6 + 4123: 51,-6 + 4145: 59,-6 + 4190: -61,37 + 4191: -60,37 + 4192: -59,37 + 4230: -1,-26 + 4231: 0,-26 + 4232: 1,-26 + 4233: 2,-26 + 4234: 3,-26 + 4235: 4,-26 + 4236: 5,-26 + 4237: 6,-26 + 4238: 7,-26 + 4239: 8,-26 + 4240: 9,-26 + 4241: 10,-26 + 4242: 11,-26 + 4243: 12,-26 + 4244: 13,-26 + 4245: 14,-26 + 4246: 15,-26 + 4278: -29,1 + 4279: -28,1 + 4286: 78,7 + 4287: 79,7 + 4288: 80,7 + 4383: 28,56 + 4384: 27,56 + - node: + color: '#FFFFFFFF' + id: BrickTileSteelLineW + decals: + 3582: 25,-35 + 3583: 25,-34 + 3584: 25,-33 + 3585: 25,-32 + 3590: 31,-35 + 3591: 31,-34 + 3592: 31,-33 + 3593: 31,-32 + 3774: -21,27 + 3775: -21,26 + 3781: -21,25 + 3907: 39,27 + 3908: 39,28 + 3909: 39,29 + 3981: -56,-27 + 4108: 54,-19 + 4109: 54,-18 + 4110: 54,-14 + 4111: 54,-13 + 4112: 54,-12 + 4113: 54,-11 + 4114: 54,-10 + 4115: 54,-9 + 4116: 54,-8 + 4117: 54,-7 + 4207: -62,43 + 4208: -62,42 + 4209: -62,41 + 4210: -62,40 + 4211: -62,39 + 4212: -62,38 + 4274: -30,2 + 4275: -30,3 + 4297: 77,8 + 4378: 29,52 + 4379: 29,53 + 4380: 29,54 + 4381: 29,55 + - node: + color: '#334E6DC8' + id: BrickTileWhiteCornerNe + decals: + 3473: 5,-12 + - node: + color: '#52B4E996' + id: BrickTileWhiteCornerNe + decals: + 4916: -30,-35 + - node: + color: '#A4610696' + id: BrickTileWhiteCornerNe + decals: + 3926: 40,30 + 3960: 38,21 + - node: + color: '#D381C996' + id: BrickTileWhiteCornerNe + decals: + 4393: 29,56 + 4636: 16,75 + 4637: 19,74 + - node: + color: '#DE3A3A96' + id: BrickTileWhiteCornerNe + decals: + 4142: 62,-5 + 4160: 58,-14 + - node: + color: '#FFFFFFFF' + id: BrickTileWhiteCornerNe + decals: + 3860: 29,61 + 4045: -17,-29 + 4431: -29,-12 + - node: + color: '#334E6DC8' + id: BrickTileWhiteCornerNw + decals: + 3500: 9,-12 + - node: + color: '#52B4E996' + id: BrickTileWhiteCornerNw + decals: + 4917: -40,-35 + - node: + color: '#A4610696' + id: BrickTileWhiteCornerNw + decals: + 3921: 39,30 + 3957: 35,21 + - node: + color: '#D381C996' + id: BrickTileWhiteCornerNw + decals: + 4321: 23,79 + 4390: 26,56 + 4634: 14,75 + 4635: 11,74 + - node: + color: '#DE3A3A96' + id: BrickTileWhiteCornerNw + decals: + 4129: 49,-5 + - node: + color: '#FFFFFFFF' + id: BrickTileWhiteCornerNw + decals: + 3858: 22,61 + 4043: -20,-29 + 4439: -37,-12 + - node: + color: '#52B4E996' + id: BrickTileWhiteCornerSe + decals: + 4918: -30,-40 + 4919: -37,-41 + - node: + color: '#A4610696' + id: BrickTileWhiteCornerSe + decals: + 3922: 40,26 + 3951: 38,18 + - node: + color: '#D381C996' + id: BrickTileWhiteCornerSe + decals: + 4319: 31,73 + 4633: 19,72 + - node: + color: '#DE3A3A96' + id: BrickTileWhiteCornerSe + decals: + 4143: 62,-6 + 4166: 58,-20 + - node: + color: '#F9801DFF' + id: BrickTileWhiteCornerSe + decals: + 4529: -30,-29 + - node: + color: '#FFFFFFFF' + id: BrickTileWhiteCornerSe + decals: + 3857: 29,58 + 4044: -17,-31 + 4429: -29,-14 + - node: + color: '#52B4E996' + id: BrickTileWhiteCornerSw + decals: + 4920: -40,-41 + - node: + color: '#A4610696' + id: BrickTileWhiteCornerSw + decals: + 3920: 39,26 + 3954: 35,18 + - node: + color: '#D381C996' + id: BrickTileWhiteCornerSw + decals: + 4320: 23,73 + 4638: 11,72 + - node: + color: '#DE3A3A96' + id: BrickTileWhiteCornerSw + decals: + 4128: 49,-6 + 4170: 54,-20 + - node: + color: '#FFFFFFFF' + id: BrickTileWhiteCornerSw + decals: + 3859: 22,58 + 4042: -20,-31 + 4440: -37,-13 + - node: + color: '#FFFFFFFF' + id: BrickTileWhiteEndN + decals: + 4053: 7,-39 + - node: + color: '#FFFFFFFF' + id: BrickTileWhiteEndS + decals: + 4052: 7,-42 + - node: + color: '#334E6DC8' + id: BrickTileWhiteInnerNe + decals: + 3478: 0,-12 + 3506: 5,-14 + 3556: -10,-3 + 4217: -59,51 + - node: + color: '#52B4E996' + id: BrickTileWhiteInnerNe + decals: + 4911: -52,-37 + - node: + color: '#D381C996' + id: BrickTileWhiteInnerNe + decals: + 4639: 16,74 + - node: + color: '#DE3A3A96' + id: BrickTileWhiteInnerNe + decals: + 4158: 56,-14 + 4222: -63,46 + - node: + color: '#334E6DC8' + id: BrickTileWhiteInnerNw + decals: + 3502: 9,-14 + 3527: 14,-12 + 3557: -4,-3 + 4218: -57,51 + 4744: -24,16 + - node: + color: '#52B4E996' + id: BrickTileWhiteInnerNw + decals: + 4910: -48,-37 + - node: + color: '#D381C996' + id: BrickTileWhiteInnerNw + decals: + 4640: 14,74 + - node: + color: '#DE3A3A96' + id: BrickTileWhiteInnerNw + decals: + 4223: -61,46 + - node: + color: '#334E6DC8' + id: BrickTileWhiteInnerSe + decals: + 3480: 0,-10 + - node: + color: '#52B4E996' + id: BrickTileWhiteInnerSe + decals: + 4903: -52,-35 + 4921: -37,-40 + - node: + color: '#DE3A3A96' + id: BrickTileWhiteInnerSe + decals: + 4150: 56,-6 + - node: + color: '#334E6DC8' + id: BrickTileWhiteInnerSw + decals: + 3494: 14,-10 + 4743: -24,19 + - node: + color: '#52B4E996' + id: BrickTileWhiteInnerSw + decals: + 4902: -48,-35 + - node: + color: '#DE3A3A96' + id: BrickTileWhiteInnerSw + decals: + 4181: 54,-6 + - node: + color: '#FFFFFFFF' + id: BrickTileWhiteInnerSw + decals: + 4443: -34,-13 + - node: + color: '#334E6DC8' + id: BrickTileWhiteLineE + decals: + 3479: 0,-11 + 3507: 5,-13 + - node: + color: '#52B4E996' + id: BrickTileWhiteLineE + decals: + 4900: -52,-36 + 4939: -30,-36 + 4940: -30,-37 + 4941: -30,-38 + 4942: -30,-39 + - node: + color: '#9FED5896' + id: BrickTileWhiteLineE + decals: + 4696: -32,16 + - node: + color: '#A4610696' + id: BrickTileWhiteLineE + decals: + 3923: 40,27 + 3924: 40,28 + 3925: 40,29 + 3961: 38,20 + 3962: 38,19 + - node: + color: '#D381C996' + id: BrickTileWhiteLineE + decals: + 4335: 31,74 + 4336: 31,75 + 4394: 29,55 + 4395: 29,54 + 4396: 29,53 + 4397: 29,52 + 4631: 19,73 + - node: + color: '#D4D4D405' + id: BrickTileWhiteLineE + decals: + 4725: -29,18 + 4726: -29,17 + - node: + color: '#D4D4D40C' + id: BrickTileWhiteLineE + decals: + 4713: -28,18 + 4714: -28,17 + - node: + color: '#D4D4D426' + id: BrickTileWhiteLineE + decals: + 4717: -28,18 + 4718: -28,17 + - node: + color: '#D4D4D428' + id: BrickTileWhiteLineE + decals: + 4701: -32,19 + - node: + color: '#DE3A3A96' + id: BrickTileWhiteLineE + decals: + 4151: 56,-7 + 4152: 56,-8 + 4153: 56,-9 + 4154: 56,-10 + 4155: 56,-11 + 4156: 56,-12 + 4157: 56,-13 + 4161: 58,-15 + 4162: 58,-16 + 4163: 58,-17 + 4164: 58,-18 + 4165: 58,-19 + 4188: 41,0 + 4189: 41,-1 + 4698: -32,15 + - node: + color: '#EFB34196' + id: BrickTileWhiteLineE + decals: + 4697: -32,20 + - node: + color: '#F9801DFF' + id: BrickTileWhiteLineE + decals: + 4530: -30,-28 + 4531: -30,-27 + 4532: -30,-26 + 4533: -30,-25 + - node: + color: '#FFFFFFFF' + id: BrickTileWhiteLineE + decals: + 3875: 29,59 + 3876: 29,60 + 4051: -17,-30 + 4054: 7,-40 + 4055: 7,-41 + 4430: -29,-13 + 4702: -45,15 + - node: + color: '#334E6DC8' + id: BrickTileWhiteLineN + decals: + 3474: 4,-12 + 3475: 3,-12 + 3476: 2,-12 + 3477: 1,-12 + 3496: 13,-12 + 3497: 12,-12 + 3498: 11,-12 + 3499: 10,-12 + 3503: 8,-14 + 3504: 7,-14 + 3505: 6,-14 + 3553: -8,-3 + 3554: -7,-3 + 3555: -6,-3 + 4216: -58,51 + - node: + color: '#52B4E996' + id: BrickTileWhiteLineN + decals: + 4907: -51,-37 + 4908: -50,-37 + 4909: -49,-37 + 4930: -39,-35 + 4931: -38,-35 + 4932: -37,-35 + 4933: -36,-35 + 4934: -35,-35 + 4935: -34,-35 + 4936: -33,-35 + 4937: -32,-35 + 4938: -31,-35 + - node: + color: '#A4610696' + id: BrickTileWhiteLineN + decals: + 3958: 36,21 + 3959: 37,21 + - node: + color: '#D381C996' + id: BrickTileWhiteLineN + decals: + 4322: 24,79 + 4351: 26,79 + 4352: 27,79 + 4391: 27,56 + 4392: 28,56 + 4627: 12,74 + 4628: 13,74 + 4629: 15,75 + 4630: 17,74 + 4650: 18,74 + - node: + color: '#DE3A3A96' + id: BrickTileWhiteLineN + decals: + 4130: 50,-5 + 4131: 51,-5 + 4132: 52,-5 + 4133: 53,-5 + 4134: 54,-5 + 4135: 55,-5 + 4136: 56,-5 + 4137: 57,-5 + 4138: 58,-5 + 4139: 59,-5 + 4140: 60,-5 + 4141: 61,-5 + 4159: 57,-14 + 4224: -62,46 + - node: + color: '#FFFFFFFF' + id: BrickTileWhiteLineN + decals: + 3861: 28,61 + 3862: 27,61 + 3863: 26,61 + 3864: 25,61 + 3865: 24,61 + 3866: 23,61 + 4006: -53,-31 + 4007: -52,-31 + 4008: -51,-31 + 4009: -50,-31 + 4010: -49,-31 + 4011: -48,-31 + 4012: -47,-31 + 4013: -46,-31 + 4014: -45,-31 + 4015: -44,-31 + 4016: -43,-31 + 4017: -42,-31 + 4018: -41,-31 + 4019: -40,-31 + 4020: -39,-31 + 4021: -38,-31 + 4022: -37,-31 + 4023: -36,-31 + 4024: -35,-31 + 4025: -34,-31 + 4026: -33,-31 + 4027: -32,-31 + 4028: -31,-31 + 4029: -30,-31 + 4046: -19,-29 + 4047: -18,-29 + 4432: -30,-12 + 4433: -31,-12 + 4434: -32,-12 + 4435: -33,-12 + 4436: -34,-12 + 4437: -35,-12 + 4438: -36,-12 + - node: + color: '#334E6DC8' + id: BrickTileWhiteLineS + decals: + 3481: 1,-10 + 3482: 2,-10 + 3483: 3,-10 + 3484: 4,-10 + 3485: 5,-10 + 3486: 6,-10 + 3487: 7,-10 + 3488: 8,-10 + 3489: 9,-10 + 3490: 10,-10 + 3491: 11,-10 + 3492: 12,-10 + 3493: 13,-10 + - node: + color: '#52B4E996' + id: BrickTileWhiteLineS + decals: + 4897: -51,-35 + 4898: -50,-35 + 4899: -49,-35 + 4922: -39,-41 + 4923: -38,-41 + 4924: -36,-40 + 4925: -35,-40 + 4926: -34,-40 + 4927: -33,-40 + 4928: -32,-40 + 4929: -31,-40 + - node: + color: '#A4610696' + id: BrickTileWhiteLineS + decals: + 3952: 37,18 + 3953: 36,18 + - node: + color: '#D381C996' + id: BrickTileWhiteLineS + decals: + 4328: 24,73 + 4329: 25,73 + 4330: 26,73 + 4331: 27,73 + 4332: 28,73 + 4333: 29,73 + 4334: 30,73 + 4349: 26,78 + 4350: 27,78 4620: 12,72 4621: 13,72 4622: 14,72 @@ -979,3359 +1893,2445 @@ entities: 4624: 16,72 4625: 17,72 4626: 18,72 - 4697: -32,17 + - node: + color: '#DE3A3A96' + id: BrickTileWhiteLineS + decals: + 4124: 51,-6 + 4125: 50,-6 + 4126: 52,-6 + 4127: 53,-6 + 4144: 61,-6 + 4146: 60,-6 + 4147: 59,-6 + 4148: 58,-6 + 4149: 57,-6 + 4167: 57,-20 + 4168: 56,-20 + 4169: 55,-20 + - node: + color: '#F9801DFF' + id: BrickTileWhiteLineS + decals: + 4521: -32,-29 + 4522: -33,-29 + 4523: -34,-29 + 4524: -35,-29 + 4525: -36,-29 + 4526: -37,-29 + 4527: -38,-29 + 4528: -31,-29 - node: color: '#FFFFFFFF' - id: BrickTileDarkLineW + id: BrickTileWhiteLineS decals: - 3522: 0,-11 - 3552: 5,-13 - 3574: 22,-29 - 3575: 22,-28 - 3661: 28,-23 - 3662: 28,-22 - 3663: 28,-21 - 3664: 28,-20 - 3665: 28,-19 - 3666: 28,-18 - 3667: 28,-17 - 3668: 28,-16 - 3706: 29,-16 - 3707: 29,-17 - 3708: 29,-18 - 3709: 29,-19 - 3710: 29,-20 - 3711: 29,-21 - 3712: 29,-22 - 3713: 29,-23 - 3833: -2,60 - 3834: -2,59 - 3835: -2,58 - 3908: 43,34 - 3909: 43,35 - 3941: 35,19 - 3942: 35,20 - 3954: 38,20 - 3955: 38,19 - 4197: 39,0 - 4198: 39,-1 - 4242: -61,53 - 4314: 23,74 - 4315: 23,75 - 4316: 23,76 - 4317: 23,77 - 4318: 23,78 - 4381: 26,52 - 4382: 26,53 - 4411: 26,54 - 4412: 26,55 - 4619: 11,73 - 4699: -32,20 + 3867: 23,58 + 3868: 24,58 + 3869: 25,58 + 3870: 26,58 + 3871: 27,58 + 3872: 28,58 + 3982: -30,-33 + 3983: -31,-33 + 3984: -32,-33 + 3985: -33,-33 + 3986: -34,-33 + 3987: -35,-33 + 3988: -36,-33 + 3989: -37,-33 + 3990: -38,-33 + 3991: -39,-33 + 3992: -40,-33 + 3993: -41,-33 + 3994: -42,-33 + 3995: -43,-33 + 3996: -44,-33 + 3997: -45,-33 + 3998: -46,-33 + 3999: -47,-33 + 4000: -48,-33 + 4001: -49,-33 + 4002: -50,-33 + 4003: -51,-33 + 4004: -52,-33 + 4005: -53,-33 + 4048: -19,-31 + 4049: -18,-31 + 4424: -34,-14 + 4425: -33,-14 + 4426: -32,-14 + 4427: -31,-14 + 4428: -30,-14 + 4441: -36,-13 + 4442: -35,-13 + - node: + color: '#334E6DC8' + id: BrickTileWhiteLineW + decals: + 3495: 14,-11 + 3501: 9,-13 + 4694: -32,20 + 4741: -24,17 + 4742: -24,18 + - node: + color: '#52B4E996' + id: BrickTileWhiteLineW + decals: + 4695: -32,15 + 4901: -48,-36 + 4943: -40,-40 + 4944: -40,-39 + 4945: -40,-38 + 4946: -40,-37 + 4947: -40,-36 + - node: + color: '#A4610696' + id: BrickTileWhiteLineW + decals: + 3917: 39,28 + 3918: 39,29 + 3919: 39,27 + 3955: 35,19 + 3956: 35,20 4700: -32,19 - 4701: -32,16 - 4702: -32,15 - 4732: -28,18 - 4733: -28,17 - 4750: -24,17 - 4751: -24,18 - - node: - color: '#FFFFFFFF' - id: BrickTileSteelBox - decals: - 3990: -56,-32 - - node: - color: '#FFFFFFFF' - id: BrickTileSteelCornerNe - decals: - 3583: 31,-31 - 3769: 28,-8 - 3803: -24,38 - 3904: 28,70 - 3928: 40,30 - 4094: 62,-5 - 4110: 58,-14 - 4208: -58,44 - 4284: -27,4 - 4303: 81,9 - - node: - color: '#FFFFFFFF' - id: BrickTileSteelCornerNw - decals: - 3577: 25,-31 - 3770: 23,-8 - 3801: -27,38 - 3907: 27,70 - 3929: 39,30 - 4079: 49,-5 - 4207: -62,44 - 4283: -30,4 - 4308: 77,9 - - node: - color: '#FFFFFFFF' - id: BrickTileSteelCornerSe - decals: - 3588: 31,-36 - 3772: 28,-9 - 3802: -24,37 - 3905: 28,69 - 3927: 40,26 - 4095: 62,-6 - 4116: 58,-20 - 4209: -58,37 - 4285: -27,1 - 4302: 81,7 - - node: - color: '#FFFFFFFF' - id: BrickTileSteelCornerSw - decals: - 3594: 25,-36 - 3771: 23,-9 - 3800: -27,37 - 3906: 27,69 - 3926: 39,26 - 4080: 49,-6 - 4120: 54,-20 - 4206: -62,37 - 4286: -30,1 - 4309: 77,7 - - node: - color: '#FFFFFFFF' - id: BrickTileSteelEndN - decals: - 3991: -56,-26 - - node: - color: '#FFFFFFFF' - id: BrickTileSteelEndS - decals: - 3992: -56,-28 - - node: - color: '#FFFFFFFF' - id: BrickTileSteelInnerNe - decals: - 3617: 25,-36 - 4108: 56,-14 - 4228: -59,51 - 4234: -63,46 - - node: - color: '#FFFFFFFF' - id: BrickTileSteelInnerNw - decals: - 3618: 31,-36 - 4227: -57,51 - 4233: -61,46 - - node: - color: '#FFFFFFFF' - id: BrickTileSteelInnerSe - decals: - 3620: 25,-31 - 4101: 56,-6 - 4398: 26,56 - - node: - color: '#FFFFFFFF' - id: BrickTileSteelInnerSw - decals: - 3619: 31,-31 - 4131: 54,-6 - 4132: 54,-6 - 4395: 29,56 - - node: - color: '#FFFFFFFF' - id: BrickTileSteelLineE - decals: - 3584: 31,-32 - 3585: 31,-33 - 3586: 31,-34 - 3587: 31,-35 - 3599: 25,-34 - 3600: 25,-33 - 3601: 25,-32 - 3602: 25,-35 - 3923: 40,29 - 3924: 40,28 - 3925: 40,27 - 3993: -56,-27 - 4100: 56,-7 - 4102: 56,-9 - 4103: 56,-8 - 4104: 56,-10 - 4105: 56,-11 - 4106: 56,-12 - 4107: 56,-13 - 4111: 58,-15 - 4112: 58,-16 - 4113: 58,-17 - 4114: 58,-18 - 4115: 58,-19 - 4210: -58,38 - 4211: -58,39 - 4212: -58,40 - 4213: -58,41 - 4214: -58,39 - 4215: -58,42 - 4216: -58,43 - 4289: -27,2 - 4290: -27,3 - 4304: 81,8 - 4399: 26,53 - 4400: 26,52 - 4413: 26,55 - 4414: 26,54 - - node: - color: '#FFFFFFFF' - id: BrickTileSteelLineN - decals: - 3578: 26,-31 - 3579: 27,-31 - 3580: 28,-31 - 3581: 29,-31 - 3582: 30,-31 - 3612: 30,-36 - 3613: 29,-36 - 3614: 28,-36 - 3615: 27,-36 - 3616: 26,-36 - 3751: 16,-3 - 3752: 15,-3 - 3753: 14,-3 - 3754: 13,-3 - 3755: 12,-3 - 3756: 11,-3 - 3757: 10,-3 - 3758: 9,-3 - 3759: 8,-3 - 3760: 7,-3 - 3761: 6,-3 - 3762: 5,-3 - 3763: 4,-3 - 3764: 3,-3 - 3765: 2,-3 - 3766: 1,-3 - 3767: 0,-3 - 3768: -1,-3 - 3777: 24,-8 - 3778: 25,-8 - 3779: 26,-8 - 3780: 27,-8 - 3781: -20,28 - 3782: -19,28 - 3783: -18,28 - 3784: -15,28 - 3785: -14,28 - 3786: -13,28 - 3804: -26,38 - 3805: -25,38 - 4081: 50,-5 - 4082: 51,-5 - 4083: 52,-5 - 4084: 53,-5 - 4085: 54,-5 - 4086: 55,-5 - 4087: 56,-5 - 4088: 57,-5 - 4089: 58,-5 - 4090: 58,-5 - 4091: 59,-5 - 4092: 60,-5 - 4093: 61,-5 - 4109: 57,-14 - 4217: -61,44 - 4218: -60,44 - 4219: -59,44 - 4226: -58,51 - 4232: -62,46 - 4260: 15,-24 - 4261: 14,-24 - 4262: 13,-24 - 4263: 12,-24 - 4264: 11,-24 - 4265: 10,-24 - 4266: 9,-24 - 4267: 8,-24 - 4268: 7,-24 - 4269: 6,-24 - 4270: 5,-24 - 4271: 4,-24 - 4272: 3,-24 - 4273: 2,-24 - 4274: 1,-24 - 4275: 0,-24 - 4276: -1,-24 - 4293: -29,4 - 4294: -28,4 - 4305: 80,9 - 4306: 79,9 - 4307: 78,9 - - node: - color: '#FFFFFFFF' - id: BrickTileSteelLineS - decals: - 3589: 30,-36 - 3590: 29,-36 - 3591: 28,-36 - 3592: 27,-36 - 3593: 26,-36 - 3607: 30,-31 - 3608: 29,-31 - 3609: 28,-31 - 3610: 27,-31 - 3611: 26,-31 - 3733: -1,-5 - 3734: 0,-5 - 3735: 1,-5 - 3736: 16,-5 - 3737: 14,-5 - 3738: 15,-5 - 3739: 13,-5 - 3740: 12,-5 - 3741: 11,-5 - 3742: 10,-5 - 3743: 9,-5 - 3744: 8,-5 - 3745: 7,-5 - 3746: 6,-5 - 3747: 5,-5 - 3748: 4,-5 - 3749: 3,-5 - 3750: 2,-5 - 3773: 24,-9 - 3774: 25,-9 - 3775: 26,-9 - 3776: 27,-9 - 3806: -26,37 - 3807: -25,37 - 4096: 61,-6 - 4097: 60,-6 - 4098: 58,-6 - 4099: 57,-6 - 4117: 57,-20 - 4118: 56,-20 - 4119: 55,-20 - 4133: 53,-6 - 4134: 52,-6 - 4135: 50,-6 - 4136: 51,-6 - 4158: 59,-6 - 4203: -61,37 - 4204: -60,37 - 4205: -59,37 - 4243: -1,-26 - 4244: 0,-26 - 4245: 1,-26 - 4246: 2,-26 - 4247: 3,-26 - 4248: 4,-26 - 4249: 5,-26 - 4250: 6,-26 - 4251: 7,-26 - 4252: 8,-26 - 4253: 9,-26 - 4254: 10,-26 - 4255: 11,-26 - 4256: 12,-26 - 4257: 13,-26 - 4258: 14,-26 - 4259: 15,-26 - 4291: -29,1 - 4292: -28,1 - 4299: 78,7 - 4300: 79,7 - 4301: 80,7 - 4396: 28,56 - 4397: 27,56 - - node: - color: '#FFFFFFFF' - id: BrickTileSteelLineW - decals: - 3595: 25,-35 - 3596: 25,-34 - 3597: 25,-33 - 3598: 25,-32 - 3603: 31,-35 - 3604: 31,-34 - 3605: 31,-33 - 3606: 31,-32 - 3787: -21,27 - 3788: -21,26 - 3794: -21,25 - 3920: 39,27 - 3921: 39,28 - 3922: 39,29 - 3994: -56,-27 - 4121: 54,-19 - 4122: 54,-18 - 4123: 54,-14 - 4124: 54,-13 - 4125: 54,-12 - 4126: 54,-11 - 4127: 54,-10 - 4128: 54,-9 - 4129: 54,-8 - 4130: 54,-7 - 4220: -62,43 - 4221: -62,42 - 4222: -62,41 - 4223: -62,40 - 4224: -62,39 - 4225: -62,38 - 4287: -30,2 - 4288: -30,3 - 4310: 77,8 - 4391: 29,52 - 4392: 29,53 - 4393: 29,54 - 4394: 29,55 - - node: - color: '#334E6DC8' - id: BrickTileWhiteCornerNe - decals: - 3486: 5,-12 - - node: - color: '#52B4E996' - id: BrickTileWhiteCornerNe - decals: - 4929: -30,-35 - - node: - color: '#A4610696' - id: BrickTileWhiteCornerNe - decals: - 3939: 40,30 - 3973: 38,21 - - node: - color: '#D381C996' - id: BrickTileWhiteCornerNe - decals: - 4406: 29,56 - 4649: 16,75 - 4650: 19,74 - - node: - color: '#DE3A3A96' - id: BrickTileWhiteCornerNe - decals: - 4155: 62,-5 - 4173: 58,-14 - - node: - color: '#FFFFFFFF' - id: BrickTileWhiteCornerNe - decals: - 3873: 29,61 - 4058: -17,-29 - 4444: -29,-12 - - node: - color: '#334E6DC8' - id: BrickTileWhiteCornerNw - decals: - 3513: 9,-12 - - node: - color: '#52B4E996' - id: BrickTileWhiteCornerNw - decals: - 4930: -40,-35 - - node: - color: '#A4610696' - id: BrickTileWhiteCornerNw - decals: - 3934: 39,30 - 3970: 35,21 - - node: - color: '#D381C996' - id: BrickTileWhiteCornerNw - decals: - 4334: 23,79 - 4403: 26,56 - 4647: 14,75 - 4648: 11,74 - - node: - color: '#DE3A3A96' - id: BrickTileWhiteCornerNw - decals: - 4142: 49,-5 - - node: - color: '#FFFFFFFF' - id: BrickTileWhiteCornerNw - decals: - 3871: 22,61 - 4056: -20,-29 - 4452: -37,-12 - - node: - color: '#52B4E996' - id: BrickTileWhiteCornerSe - decals: - 4931: -30,-40 - 4932: -37,-41 - - node: - color: '#A4610696' - id: BrickTileWhiteCornerSe - decals: - 3935: 40,26 - 3964: 38,18 - - node: - color: '#D381C996' - id: BrickTileWhiteCornerSe - decals: - 4332: 31,73 - 4646: 19,72 - - node: - color: '#DE3A3A96' - id: BrickTileWhiteCornerSe - decals: - 4156: 62,-6 - 4179: 58,-20 - - node: - color: '#F9801DFF' - id: BrickTileWhiteCornerSe - decals: - 4542: -30,-29 - - node: - color: '#FFFFFFFF' - id: BrickTileWhiteCornerSe - decals: - 3870: 29,58 - 4057: -17,-31 - 4442: -29,-14 - - node: - color: '#52B4E996' - id: BrickTileWhiteCornerSw - decals: - 4933: -40,-41 - - node: - color: '#A4610696' - id: BrickTileWhiteCornerSw - decals: - 3933: 39,26 - 3967: 35,18 - - node: - color: '#D381C996' - id: BrickTileWhiteCornerSw - decals: - 4333: 23,73 - 4651: 11,72 - - node: - color: '#DE3A3A96' - id: BrickTileWhiteCornerSw - decals: - 4141: 49,-6 - 4183: 54,-20 - - node: - color: '#FFFFFFFF' - id: BrickTileWhiteCornerSw - decals: - 3872: 22,58 - 4055: -20,-31 - 4453: -37,-13 - - node: - color: '#FFFFFFFF' - id: BrickTileWhiteEndN - decals: - 4066: 7,-39 - - node: - color: '#FFFFFFFF' - id: BrickTileWhiteEndS - decals: - 4065: 7,-42 - - node: - color: '#334E6DC8' - id: BrickTileWhiteInnerNe - decals: - 3491: 0,-12 - 3519: 5,-14 - 3569: -10,-3 - 4230: -59,51 - - node: - color: '#52B4E996' - id: BrickTileWhiteInnerNe - decals: - 4924: -52,-37 - - node: - color: '#D381C996' - id: BrickTileWhiteInnerNe - decals: - 4652: 16,74 - - node: - color: '#DE3A3A96' - id: BrickTileWhiteInnerNe - decals: - 4171: 56,-14 - 4235: -63,46 - - node: - color: '#334E6DC8' - id: BrickTileWhiteInnerNw - decals: - 3515: 9,-14 - 3540: 14,-12 - 3570: -4,-3 - 4231: -57,51 - 4757: -24,16 - - node: - color: '#52B4E996' - id: BrickTileWhiteInnerNw - decals: - 4923: -48,-37 - - node: - color: '#D381C996' - id: BrickTileWhiteInnerNw - decals: - 4653: 14,74 - - node: - color: '#DE3A3A96' - id: BrickTileWhiteInnerNw - decals: - 4236: -61,46 - - node: - color: '#334E6DC8' - id: BrickTileWhiteInnerSe - decals: - 3493: 0,-10 - - node: - color: '#52B4E996' - id: BrickTileWhiteInnerSe - decals: - 4916: -52,-35 - 4934: -37,-40 - - node: - color: '#DE3A3A96' - id: BrickTileWhiteInnerSe - decals: - 4163: 56,-6 - - node: - color: '#334E6DC8' - id: BrickTileWhiteInnerSw - decals: - 3507: 14,-10 - 4756: -24,19 - - node: - color: '#52B4E996' - id: BrickTileWhiteInnerSw - decals: - 4915: -48,-35 - - node: - color: '#DE3A3A96' - id: BrickTileWhiteInnerSw - decals: - 4194: 54,-6 - - node: - color: '#FFFFFFFF' - id: BrickTileWhiteInnerSw - decals: - 4456: -34,-13 - - node: - color: '#334E6DC8' - id: BrickTileWhiteLineE - decals: - 3492: 0,-11 - 3520: 5,-13 - - node: - color: '#52B4E996' - id: BrickTileWhiteLineE - decals: - 4913: -52,-36 - 4952: -30,-36 - 4953: -30,-37 - 4954: -30,-38 - 4955: -30,-39 - - node: - color: '#9FED5896' - id: BrickTileWhiteLineE - decals: - 4709: -32,16 - - node: - color: '#A4610696' - id: BrickTileWhiteLineE - decals: - 3936: 40,27 - 3937: 40,28 - 3938: 40,29 - 3974: 38,20 - 3975: 38,19 - - node: - color: '#D381C996' - id: BrickTileWhiteLineE - decals: - 4348: 31,74 - 4349: 31,75 - 4407: 29,55 - 4408: 29,54 - 4409: 29,53 - 4410: 29,52 - 4644: 19,73 - - node: - color: '#D4D4D405' - id: BrickTileWhiteLineE - decals: - 4738: -29,18 - 4739: -29,17 - - node: - color: '#D4D4D40C' - id: BrickTileWhiteLineE - decals: - 4726: -28,18 - 4727: -28,17 - - node: - color: '#D4D4D426' - id: BrickTileWhiteLineE - decals: - 4730: -28,18 - 4731: -28,17 - - node: - color: '#D4D4D428' - id: BrickTileWhiteLineE - decals: - 4714: -32,19 - - node: - color: '#DE3A3A96' - id: BrickTileWhiteLineE - decals: - 4164: 56,-7 - 4165: 56,-8 - 4166: 56,-9 - 4167: 56,-10 - 4168: 56,-11 - 4169: 56,-12 - 4170: 56,-13 - 4174: 58,-15 - 4175: 58,-16 - 4176: 58,-17 - 4177: 58,-18 - 4178: 58,-19 - 4201: 41,0 - 4202: 41,-1 - 4711: -32,15 - - node: - color: '#EFB34196' - id: BrickTileWhiteLineE - decals: - 4710: -32,20 - - node: - color: '#F9801DFF' - id: BrickTileWhiteLineE - decals: - 4543: -30,-28 - 4544: -30,-27 - 4545: -30,-26 - 4546: -30,-25 - - node: - color: '#FFFFFFFF' - id: BrickTileWhiteLineE - decals: - 3888: 29,59 - 3889: 29,60 - 4064: -17,-30 - 4067: 7,-40 - 4068: 7,-41 - 4443: -29,-13 - 4715: -45,15 - - node: - color: '#334E6DC8' - id: BrickTileWhiteLineN - decals: - 3487: 4,-12 - 3488: 3,-12 - 3489: 2,-12 - 3490: 1,-12 - 3509: 13,-12 - 3510: 12,-12 - 3511: 11,-12 - 3512: 10,-12 - 3516: 8,-14 - 3517: 7,-14 - 3518: 6,-14 - 3566: -8,-3 - 3567: -7,-3 - 3568: -6,-3 - 4229: -58,51 - - node: - color: '#52B4E996' - id: BrickTileWhiteLineN - decals: - 4920: -51,-37 - 4921: -50,-37 - 4922: -49,-37 - 4943: -39,-35 - 4944: -38,-35 - 4945: -37,-35 - 4946: -36,-35 - 4947: -35,-35 - 4948: -34,-35 - 4949: -33,-35 - 4950: -32,-35 - 4951: -31,-35 - - node: - color: '#A4610696' - id: BrickTileWhiteLineN - decals: - 3971: 36,21 - 3972: 37,21 - - node: - color: '#D381C996' - id: BrickTileWhiteLineN - decals: - 4335: 24,79 - 4364: 26,79 - 4365: 27,79 - 4404: 27,56 - 4405: 28,56 - 4640: 12,74 - 4641: 13,74 - 4642: 15,75 - 4643: 17,74 - 4663: 18,74 - - node: - color: '#DE3A3A96' - id: BrickTileWhiteLineN - decals: - 4143: 50,-5 - 4144: 51,-5 - 4145: 52,-5 - 4146: 53,-5 - 4147: 54,-5 - 4148: 55,-5 - 4149: 56,-5 - 4150: 57,-5 - 4151: 58,-5 - 4152: 59,-5 - 4153: 60,-5 - 4154: 61,-5 - 4172: 57,-14 - 4237: -62,46 - - node: - color: '#FFFFFFFF' - id: BrickTileWhiteLineN - decals: - 3874: 28,61 - 3875: 27,61 - 3876: 26,61 - 3877: 25,61 - 3878: 24,61 - 3879: 23,61 - 4019: -53,-31 - 4020: -52,-31 - 4021: -51,-31 - 4022: -50,-31 - 4023: -49,-31 - 4024: -48,-31 - 4025: -47,-31 - 4026: -46,-31 - 4027: -45,-31 - 4028: -44,-31 - 4029: -43,-31 - 4030: -42,-31 - 4031: -41,-31 - 4032: -40,-31 - 4033: -39,-31 - 4034: -38,-31 - 4035: -37,-31 - 4036: -36,-31 - 4037: -35,-31 - 4038: -34,-31 - 4039: -33,-31 - 4040: -32,-31 - 4041: -31,-31 - 4042: -30,-31 - 4059: -19,-29 - 4060: -18,-29 - 4445: -30,-12 - 4446: -31,-12 - 4447: -32,-12 - 4448: -33,-12 - 4449: -34,-12 - 4450: -35,-12 - 4451: -36,-12 - - node: - color: '#334E6DC8' - id: BrickTileWhiteLineS - decals: - 3494: 1,-10 - 3495: 2,-10 - 3496: 3,-10 - 3497: 4,-10 - 3498: 5,-10 - 3499: 6,-10 - 3500: 7,-10 - 3501: 8,-10 - 3502: 9,-10 - 3503: 10,-10 - 3504: 11,-10 - 3505: 12,-10 - 3506: 13,-10 - - node: - color: '#52B4E996' - id: BrickTileWhiteLineS - decals: - 4910: -51,-35 - 4911: -50,-35 - 4912: -49,-35 - 4935: -39,-41 - 4936: -38,-41 - 4937: -36,-40 - 4938: -35,-40 - 4939: -34,-40 - 4940: -33,-40 - 4941: -32,-40 - 4942: -31,-40 - - node: - color: '#A4610696' - id: BrickTileWhiteLineS - decals: - 3965: 37,18 - 3966: 36,18 - - node: - color: '#D381C996' - id: BrickTileWhiteLineS - decals: - 4341: 24,73 - 4342: 25,73 - 4343: 26,73 - 4344: 27,73 - 4345: 28,73 - 4346: 29,73 - 4347: 30,73 - 4362: 26,78 - 4363: 27,78 - 4633: 12,72 - 4634: 13,72 - 4635: 14,72 - 4636: 15,72 - 4637: 16,72 - 4638: 17,72 - 4639: 18,72 - - node: - color: '#DE3A3A96' - id: BrickTileWhiteLineS - decals: - 4137: 51,-6 - 4138: 50,-6 - 4139: 52,-6 - 4140: 53,-6 - 4157: 61,-6 - 4159: 60,-6 - 4160: 59,-6 - 4161: 58,-6 - 4162: 57,-6 - 4180: 57,-20 - 4181: 56,-20 - 4182: 55,-20 - - node: - color: '#F9801DFF' - id: BrickTileWhiteLineS - decals: - 4534: -32,-29 - 4535: -33,-29 - 4536: -34,-29 - 4537: -35,-29 - 4538: -36,-29 - 4539: -37,-29 - 4540: -38,-29 - 4541: -31,-29 - - node: - color: '#FFFFFFFF' - id: BrickTileWhiteLineS - decals: - 3880: 23,58 - 3881: 24,58 - 3882: 25,58 - 3883: 26,58 - 3884: 27,58 - 3885: 28,58 - 3995: -30,-33 - 3996: -31,-33 - 3997: -32,-33 - 3998: -33,-33 - 3999: -34,-33 - 4000: -35,-33 - 4001: -36,-33 - 4002: -37,-33 - 4003: -38,-33 - 4004: -39,-33 - 4005: -40,-33 - 4006: -41,-33 - 4007: -42,-33 - 4008: -43,-33 - 4009: -44,-33 - 4010: -45,-33 - 4011: -46,-33 - 4012: -47,-33 - 4013: -48,-33 - 4014: -49,-33 - 4015: -50,-33 - 4016: -51,-33 - 4017: -52,-33 - 4018: -53,-33 - 4061: -19,-31 - 4062: -18,-31 - 4437: -34,-14 - 4438: -33,-14 - 4439: -32,-14 - 4440: -31,-14 - 4441: -30,-14 - 4454: -36,-13 - 4455: -35,-13 - - node: - color: '#334E6DC8' - id: BrickTileWhiteLineW - decals: - 3508: 14,-11 - 3514: 9,-13 - 4707: -32,20 - 4754: -24,17 - 4755: -24,18 - - node: - color: '#52B4E996' - id: BrickTileWhiteLineW - decals: - 4708: -32,15 - 4914: -48,-36 - 4956: -40,-40 - 4957: -40,-39 - 4958: -40,-38 - 4959: -40,-37 - 4960: -40,-36 - - node: - color: '#A4610696' - id: BrickTileWhiteLineW - decals: - 3930: 39,28 - 3931: 39,29 - 3932: 39,27 - 3968: 35,19 - 3969: 35,20 - 4713: -32,19 - node: color: '#D381C996' id: BrickTileWhiteLineW decals: - 4336: 23,78 - 4337: 23,77 - 4338: 23,76 - 4339: 23,75 - 4340: 23,74 - 4401: 26,52 - 4402: 26,53 - 4645: 11,73 - 4712: -32,16 + 4323: 23,78 + 4324: 23,77 + 4325: 23,76 + 4326: 23,75 + 4327: 23,74 + 4388: 26,52 + 4389: 26,53 + 4632: 11,73 + 4699: -32,16 - node: color: '#D4D4D407' id: BrickTileWhiteLineW decals: - 4734: -28,17 - 4735: -28,18 + 4721: -28,17 + 4722: -28,18 - node: color: '#DE3A3A96' id: BrickTileWhiteLineW decals: - 4184: 54,-19 - 4185: 54,-18 - 4186: 54,-14 - 4187: 54,-13 - 4188: 54,-12 - 4189: 54,-11 - 4190: 54,-10 - 4191: 54,-9 - 4192: 54,-8 - 4193: 54,-7 - 4199: 39,0 - 4200: 39,-1 + 4171: 54,-19 + 4172: 54,-18 + 4173: 54,-14 + 4174: 54,-13 + 4175: 54,-12 + 4176: 54,-11 + 4177: 54,-10 + 4178: 54,-9 + 4179: 54,-8 + 4180: 54,-7 + 4186: 39,0 + 4187: 39,-1 - node: color: '#FFFFFFFF' id: BrickTileWhiteLineW decals: - 3732: -34,-14 - 3886: 22,59 - 3887: 22,60 - 4063: -20,-30 - 4069: 7,-40 - 4070: 7,-41 + 3719: -34,-14 + 3873: 22,59 + 3874: 22,60 + 4050: -20,-30 + 4056: 7,-40 + 4057: 7,-41 - node: color: '#9FED58B7' id: BushAThree decals: - 4779: -1.3686488,46.73154 + 4766: -1.3686488,46.73154 - node: color: '#9FED58B7' id: BushATwo decals: - 4776: -1.8939891,47.625587 + 4763: -1.8939891,47.625587 - node: color: '#9FED5888' id: Busha1 decals: - 4768: -3.0174823,45.91548 + 4755: -3.0174823,45.91548 - node: color: '#9FED5888' id: Busha2 decals: - 4758: -1.1858082,47.7461 - 4762: -2.0945249,48.15766 - 4763: -3.1452603,46.53989 - 4765: -1.0012178,48.11507 + 4745: -1.1858082,47.7461 + 4749: -2.0945249,48.15766 + 4750: -3.1452603,46.53989 + 4752: -1.0012178,48.11507 - node: color: '#FFFFFFC0' id: Busha2 decals: - 4464: -19.715633,-0.08040953 - 4465: -18.948898,1.7076702 - 4466: -19.360664,4.00663 + 4451: -19.715633,-0.08040953 + 4452: -18.948898,1.7076702 + 4453: -19.360664,4.00663 - node: color: '#60BC5DB1' id: Busha3 decals: - 4518: -19.190277,3.2119274 + 4505: -19.190277,3.2119274 - node: color: '#9FED5896' id: Busha3 decals: - 3231: -40.3527,-18.329292 - 3232: -43.1027,-18.48207 - 3233: -42.922146,-21.50985 - 3234: -41.408257,-22.968182 - 3235: -39.96381,-23.48207 - 3236: -39.99159,-21.829292 - 3237: -41.19992,-21.815403 - 3238: -40.86659,-18.565403 - 3239: -39.811035,-17.926516 - 3240: -41.11659,-17.75985 - 3241: -42.853085,-20.88498 + 3218: -40.3527,-18.329292 + 3219: -43.1027,-18.48207 + 3220: -42.922146,-21.50985 + 3221: -41.408257,-22.968182 + 3222: -39.96381,-23.48207 + 3223: -39.99159,-21.829292 + 3224: -41.19992,-21.815403 + 3225: -40.86659,-18.565403 + 3226: -39.811035,-17.926516 + 3227: -41.11659,-17.75985 + 3228: -42.853085,-20.88498 - node: color: '#A4DF8296' id: Busha3 decals: - 1686: -7.8109317,-1.9599552 + 1675: -7.8109317,-1.9599552 - node: color: '#9FED5888' id: Bushb1 decals: - 4761: -2.7476902,46.8379 + 4748: -2.7476902,46.8379 - node: color: '#60BC5DB1' id: Bushb2 decals: - 4517: -19.928616,2.0482564 - 4519: -19.786627,0.2601776 + 4504: -19.928616,2.0482564 + 4506: -19.786627,0.2601776 - node: color: '#60E25863' id: Bushb2 decals: - 3334: -17.64635,-37.739723 + 3321: -17.64635,-37.739723 - node: color: '#60E258BA' id: Bushb2 decals: - 3335: -16.049128,-37.545277 - 3336: -15.201906,-36.309166 - 3337: -15.313017,-37.7675 - 3338: -17.03524,-36.392498 - 3339: -17.868574,-36.281387 - 3340: -17.715796,-37.948055 - 3341: -16.118574,-38.059166 - 3342: -15.243574,-36.920277 - 3343: -16.826906,-36.850834 - 3344: -17.563017,-36.809166 - 3345: -16.701906,-37.670277 - 3346: -16.688017,-36.295277 - 3347: -15.729685,-36.670277 + 3322: -16.049128,-37.545277 + 3323: -15.201906,-36.309166 + 3324: -15.313017,-37.7675 + 3325: -17.03524,-36.392498 + 3326: -17.868574,-36.281387 + 3327: -17.715796,-37.948055 + 3328: -16.118574,-38.059166 + 3329: -15.243574,-36.920277 + 3330: -16.826906,-36.850834 + 3331: -17.563017,-36.809166 + 3332: -16.701906,-37.670277 + 3333: -16.688017,-36.295277 + 3334: -15.729685,-36.670277 - node: color: '#9FED5888' id: Bushb2 decals: - 4760: -2.932261,47.646793 - 4766: -0.98705816,45.801918 + 4747: -2.932261,47.646793 + 4753: -0.98705816,45.801918 - node: color: '#9FED5896' id: Bushb2 decals: - 3306: 78.083496,7.9973173 - 3307: 79.00016,7.900096 - 3308: 79.84738,7.8862066 + 3293: 78.083496,7.9973173 + 3294: 79.00016,7.900096 + 3295: 79.84738,7.8862066 - node: color: '#9FED58B7' id: Bushb2 decals: - 4775: -1.9508109,45.96523 - 4777: -0.9142871,46.774105 + 4762: -1.9508109,45.96523 + 4764: -0.9142871,46.774105 - node: color: '#A4DF8296' id: Bushb2 decals: - 1687: -6.2553773,-1.9043994 + 1676: -6.2553773,-1.9043994 - node: color: '#FFFFFFC0' id: Bushb2 decals: - 4467: -19.999609,3.2545013 - 4468: -19.85762,1.8637729 - 4469: -18.920502,0.8420129 - 4470: -20.184193,0.5156174 - 4471: -19.062489,3.4531765 - 4472: -20.212591,4.3046427 + 4454: -19.999609,3.2545013 + 4455: -19.85762,1.8637729 + 4456: -18.920502,0.8420129 + 4457: -20.184193,0.5156174 + 4458: -19.062489,3.4531765 + 4459: -20.212591,4.3046427 - node: color: '#60BC5DB1' id: Bushb3 decals: - 4514: -19.247074,3.6518526 - 4515: -19.871819,1.7928166 - 4516: -19.829224,0.13245726 - 4520: -18.948898,3.5241327 + 4501: -19.247074,3.6518526 + 4502: -19.871819,1.7928166 + 4503: -19.829224,0.13245726 + 4507: -18.948898,3.5241327 - node: color: '#9FED5888' id: Bushb3 decals: - 4759: -3.0174766,46.241875 - 4764: -3.1594381,47.859665 + 4746: -3.0174766,46.241875 + 4751: -3.1594381,47.859665 - node: color: '#9FED58B7' id: Bushb3 decals: - 4778: -1.666812,47.42691 + 4765: -1.666812,47.42691 - node: color: '#9FED5888' id: Bushc1 decals: - 4767: -2.8187013,45.81614 + 4754: -2.8187013,45.81614 - node: color: '#FFFFFFC0' id: Bushc1 decals: - 4462: -20.013807,2.6159015 - 4463: -20.042206,1.2393641 + 4449: -20.013807,2.6159015 + 4450: -20.042206,1.2393641 - node: color: '#9FED5896' id: Bushc3 decals: - 3242: -43.038807,-18.0765 + 3229: -43.038807,-18.0765 - node: color: '#FFFFFFFF' id: Bushg1 decals: - 4783: -16.08111,-40.251266 + 4770: -16.08111,-40.251266 - node: color: '#FFFFFFFF' id: Bushg2 decals: - 4782: -17.983753,-40.59182 + 4769: -17.983753,-40.59182 - node: color: '#FFFFFFFF' id: Bushg3 decals: - 4780: -14.888399,-39.371437 + 4767: -14.888399,-39.371437 - node: color: '#FFFFFFFF' id: Bushg4 decals: - 4781: -15.484749,-39.442383 + 4768: -15.484749,-39.442383 - node: color: '#A4DF8296' id: Bushj3 decals: - 1689: -7.4513307,-22.276455 - 1690: -9.062441,-22.720898 - 1691: -8.867998,-23.748676 - 1692: -7.340218,-23.748676 + 1678: -7.4513307,-22.276455 + 1679: -9.062441,-22.720898 + 1680: -8.867998,-23.748676 + 1681: -7.340218,-23.748676 - node: color: '#A4DF8296' id: Bushk1 decals: - 1688: -8.284664,-23.526455 - 1693: -7.340218,-22.970898 + 1677: -8.284664,-23.526455 + 1682: -7.340218,-22.970898 - node: color: '#FFFFFF6C' id: Bushk1 decals: - 4460: -18.991495,3.5808964 + 4447: -18.991495,3.5808964 - node: color: '#FFFFFFC0' id: Bushk1 decals: - 4461: -19.062489,2.7720032 + 4448: -19.062489,2.7720032 - node: color: '#60E25873' id: Bushm1 decals: - 3388: -59.97946,38.265724 - 3389: -60.02113,39.390724 - 3390: -59.99335,40.724056 - 3391: -59.91002,42.335167 - 3392: -60.090576,43.071278 - 3393: -60.10446,41.279613 - 3394: -60.04891,39.765724 + 3375: -59.97946,38.265724 + 3376: -60.02113,39.390724 + 3377: -59.99335,40.724056 + 3378: -59.91002,42.335167 + 3379: -60.090576,43.071278 + 3380: -60.10446,41.279613 + 3381: -60.04891,39.765724 - node: color: '#52B4E95A' id: CheckerNESW decals: - 4796: 73,-1 - 4797: 72,-1 - 4798: 72,0 - 4799: 73,0 - 4800: 85,-1 - 4801: 85,0 - 4802: 86,0 - 4803: 86,-1 + 4783: 73,-1 + 4784: 72,-1 + 4785: 72,0 + 4786: 73,0 + 4787: 85,-1 + 4788: 85,0 + 4789: 86,0 + 4790: 86,-1 - node: color: '#52B4E996' id: CheckerNESW decals: - 4881: -34,-43 - 4882: -34,-44 - 4917: -51,-36 - 4918: -50,-36 - 4919: -49,-36 + 4868: -34,-43 + 4869: -34,-44 + 4904: -51,-36 + 4905: -50,-36 + 4906: -49,-36 - node: color: '#52B4E996' id: CheckerNWSE decals: - 3274: -46,-35 - 3275: -46,-36 - 3276: -45,-35 - 3277: -45,-36 - 3278: -44,-35 - 3279: -44,-36 - 3280: -43,-35 - 3281: -43,-36 - 3282: -42,-35 - 3283: -42,-36 + 3261: -46,-35 + 3262: -46,-36 + 3263: -45,-35 + 3264: -45,-36 + 3265: -44,-35 + 3266: -44,-36 + 3267: -43,-35 + 3268: -43,-36 + 3269: -42,-35 + 3270: -42,-36 - node: color: '#D381C996' id: CheckerNWSE decals: - 962: 21,65 - 963: 21,64 - 964: 21,63 - 965: 22,65 - 966: 22,64 - 967: 22,63 - 968: 23,65 - 969: 23,64 - 970: 23,63 - 971: 24,65 - 972: 24,64 - 973: 24,63 + 952: 21,65 + 953: 21,64 + 954: 21,63 + 955: 22,65 + 956: 22,64 + 957: 22,63 + 958: 23,65 + 959: 23,64 + 960: 23,63 + 961: 24,65 + 962: 24,64 + 963: 24,63 - node: color: '#FED83D79' id: CheckerNWSE decals: - 4788: 85,-1 - 4789: 85,0 - 4790: 86,0 - 4791: 86,-1 - 4792: 72,-1 - 4793: 72,0 - 4794: 73,0 - 4795: 73,-1 + 4775: 85,-1 + 4776: 85,0 + 4777: 86,0 + 4778: 86,-1 + 4779: 72,-1 + 4780: 72,0 + 4781: 73,0 + 4782: 73,-1 - node: color: '#0E7F1BFF' id: Delivery decals: - 4993: 37,-12 + 4971: 37,-12 - node: color: '#1861D5FF' id: Delivery decals: - 4991: 34,-13 + 4969: 34,-13 - node: color: '#334E6DC8' id: Delivery decals: - 497: -6,-1 + 487: -6,-1 - node: color: '#79150096' id: Delivery decals: - 3297: 81,16 - 3298: 82,16 - 3299: 83,16 - 3300: 84,16 - 3301: 74,16 - 3302: 75,16 - 3303: 76,16 - 3304: 77,16 + 3284: 81,16 + 3285: 82,16 + 3286: 83,16 + 3287: 84,16 + 3288: 74,16 + 3289: 75,16 + 3290: 76,16 + 3291: 77,16 - node: color: '#951710FF' id: Delivery decals: - 4992: 34,-12 + 4970: 34,-12 - node: color: '#D58C18FF' id: Delivery decals: - 4994: 38,-12 + 4972: 38,-12 - node: color: '#EFB34196' id: Delivery decals: - 1046: 37,29 - 1207: -64,39 + 1036: 37,29 + 1197: -64,39 - node: color: '#EFB34196' id: DeliveryGreyscale decals: - 1111: 36,13 - 1112: 37,13 - 1113: 38,13 - 1118: 42,22 - 1119: 43,22 - 1122: 42,20 - 1123: 43,20 + 1101: 36,13 + 1102: 37,13 + 1103: 38,13 + 1108: 42,22 + 1109: 43,22 + 1112: 42,20 + 1113: 43,20 - node: color: '#52B4E996' id: DiagonalCheckerBOverlay decals: - 4043: -20,-29 - 4044: -20,-30 - 4045: -20,-31 - 4046: -19,-29 - 4047: -19,-30 - 4048: -19,-31 - 4049: -18,-29 - 4050: -18,-30 - 4051: -18,-31 - 4052: -17,-29 - 4053: -17,-30 - 4054: -17,-31 + 4030: -20,-29 + 4031: -20,-30 + 4032: -20,-31 + 4033: -19,-29 + 4034: -19,-30 + 4035: -19,-31 + 4036: -18,-29 + 4037: -18,-30 + 4038: -18,-31 + 4039: -17,-29 + 4040: -17,-30 + 4041: -17,-31 - node: color: '#D381C996' id: DiagonalCheckerBOverlay decals: - 3838: 22,58 - 3839: 22,59 - 3840: 22,61 - 3841: 22,60 - 3842: 23,61 - 3843: 23,60 - 3844: 23,59 - 3845: 23,58 - 3846: 24,58 - 3847: 24,59 - 3848: 24,60 - 3849: 24,61 - 3850: 25,61 - 3851: 25,60 - 3852: 25,59 - 3853: 25,58 - 3854: 26,58 - 3855: 26,59 - 3856: 26,60 - 3857: 26,61 - 3858: 27,61 - 3859: 27,60 - 3860: 27,59 - 3861: 27,58 - 3862: 28,58 - 3863: 28,59 - 3864: 28,60 - 3865: 28,61 - 3866: 29,61 - 3867: 29,60 - 3868: 29,59 - 3869: 29,58 + 3825: 22,58 + 3826: 22,59 + 3827: 22,61 + 3828: 22,60 + 3829: 23,61 + 3830: 23,60 + 3831: 23,59 + 3832: 23,58 + 3833: 24,58 + 3834: 24,59 + 3835: 24,60 + 3836: 24,61 + 3837: 25,61 + 3838: 25,60 + 3839: 25,59 + 3840: 25,58 + 3841: 26,58 + 3842: 26,59 + 3843: 26,60 + 3844: 26,61 + 3845: 27,61 + 3846: 27,60 + 3847: 27,59 + 3848: 27,58 + 3849: 28,58 + 3850: 28,59 + 3851: 28,60 + 3852: 28,61 + 3853: 29,61 + 3854: 29,60 + 3855: 29,59 + 3856: 29,58 - node: color: '#FFFFFFFF' id: DiagonalCheckerBOverlay decals: - 3716: -34,-14 - 3717: -33,-14 - 3718: -33,-13 - 3719: -29,-14 - 3720: -30,-14 - 3721: -31,-14 - 3722: -32,-14 - 3723: -32,-13 - 3724: -32,-12 - 3725: -33,-12 - 3726: -31,-12 - 3727: -31,-13 - 3728: -30,-12 - 3729: -30,-13 - 3730: -29,-13 - 3731: -29,-12 - 4429: -34,-13 - 4430: -34,-12 - 4431: -35,-12 - 4432: -35,-13 - 4433: -36,-13 - 4434: -36,-12 - 4435: -37,-13 - 4436: -37,-12 + 3703: -34,-14 + 3704: -33,-14 + 3705: -33,-13 + 3706: -29,-14 + 3707: -30,-14 + 3708: -31,-14 + 3709: -32,-14 + 3710: -32,-13 + 3711: -32,-12 + 3712: -33,-12 + 3713: -31,-12 + 3714: -31,-13 + 3715: -30,-12 + 3716: -30,-13 + 3717: -29,-13 + 3718: -29,-12 + 4416: -34,-13 + 4417: -34,-12 + 4418: -35,-12 + 4419: -35,-13 + 4420: -36,-13 + 4421: -36,-12 + 4422: -37,-13 + 4423: -37,-12 - node: cleanable: True color: '#8354328B' id: Dirt decals: - 4572: -38,-10 - 4573: -38,-13 - 4574: -32,-12 - 4575: -34,-13 - 4576: -34,-12 - 4577: -35,-12 - 4578: -36,-12 - 4579: -37,-13 - 4580: -35,-13 - 4581: -34,-13 - 4582: -33,-14 - 4583: -32,-14 - 4584: -31,-14 - 4585: -31,-12 - 4586: -30,-12 - 4587: -29,-14 - 4588: -29,-13 - 4589: -29,-12 - 4590: -31,-12 - 4591: -31,-14 - 4592: -29,-14 - 4593: -32,-16 - 4594: -33,-16 - 4595: -34,-16 - 4596: -37,-10 - 4597: -28,-12 - 4598: -32,-8 - 4599: -34,-9 - 4600: -31,-8 - 4601: -30,-7 - 4602: -33,-8 - 4603: -33,-8 - 4604: -34,-7 + 4559: -38,-10 + 4560: -38,-13 + 4561: -32,-12 + 4562: -34,-13 + 4563: -34,-12 + 4564: -35,-12 + 4565: -36,-12 + 4566: -37,-13 + 4567: -35,-13 + 4568: -34,-13 + 4569: -33,-14 + 4570: -32,-14 + 4571: -31,-14 + 4572: -31,-12 + 4573: -30,-12 + 4574: -29,-14 + 4575: -29,-13 + 4576: -29,-12 + 4577: -31,-12 + 4578: -31,-14 + 4579: -29,-14 + 4580: -32,-16 + 4581: -33,-16 + 4582: -34,-16 + 4583: -37,-10 + 4584: -28,-12 + 4585: -32,-8 + 4586: -34,-9 + 4587: -31,-8 + 4588: -30,-7 + 4589: -33,-8 + 4590: -33,-8 + 4591: -34,-7 - node: color: '#A4610696' id: Dirt decals: - 3395: -3,-35 - 3396: 1,-36 - 3397: -1,-36 - 3398: 2,-35 - 3399: 4,-36 - 3400: 8,-36 - 3401: 10,-35 - 3402: 11,-36 - 3403: 13,-36 - 3404: 15,-35 - 3405: 17,-36 - 3406: 7,-35 - 3407: 6,-35 - 3408: 4,-35 - 3409: 6,-36 - 3410: 2,-36 - 3411: 1,-35 - 3412: 3,-35 - 3413: 9,-36 - 3414: 11,-36 - 3415: 14,-36 + 3382: -3,-35 + 3383: 1,-36 + 3384: -1,-36 + 3385: 2,-35 + 3386: 4,-36 + 3387: 8,-36 + 3388: 10,-35 + 3389: 11,-36 + 3390: 13,-36 + 3391: 15,-35 + 3392: 17,-36 + 3393: 7,-35 + 3394: 6,-35 + 3395: 4,-35 + 3396: 6,-36 + 3397: 2,-36 + 3398: 1,-35 + 3399: 3,-35 + 3400: 9,-36 + 3401: 11,-36 + 3402: 14,-36 - node: cleanable: True color: '#A4610696' id: Dirt decals: - 1707: -5,50 - 1708: -6,46 - 1709: -7,44 - 1710: -4,48 - 1711: -1,50 - 1712: 2,49 - 1713: 5,49 - 1714: 6,51 - 1715: 7,49 - 1716: 9,50 - 1717: 13,49 - 1718: 16,51 - 1719: 19,49 - 1720: 23,50 - 1721: 23,49 - 1722: 29,51 - 1723: 31,51 - 1724: 32,49 - 1725: 33,47 - 1726: 31,48 - 1727: 34,53 - 1728: 33,49 - 1729: 30,49 - 1730: 32,42 - 1731: 33,40 - 1732: 33,36 - 1733: 32,34 - 1734: 32,32 - 1735: 33,33 - 1736: 32,29 - 1737: 31,27 - 1738: 32,28 - 1739: 33,24 - 1740: 32,22 - 1741: 33,23 - 1742: 31,21 - 1743: 33,19 - 1744: 32,17 - 1745: 31,16 - 1746: 32,15 - 1747: 33,14 - 1748: 31,12 - 1749: 31,11 - 1750: 33,9 - 1751: 32,8 - 1752: 31,7 - 1753: 33,4 - 1754: 30,3 - 1755: 30,2 - 1756: 30,2 - 1757: 28,1 - 1758: 28,0 - 1759: 29,0 - 1760: 27,-1 - 1761: 27,-2 - 1762: 28,-4 - 1763: 26,-4 - 1764: 25,-4 - 1765: 24,-5 - 1766: 22,-5 - 1767: 21,-4 - 1768: 20,-3 - 1769: 18,-4 - 1770: 12,-4 - 1771: 9,-4 - 1772: 7,-4 - 1773: 3,-4 - 1774: 0,-4 - 1775: 1,-4 - 1776: -5,-4 - 1777: -6,-5 - 1778: -7,-5 - 1779: -6,-4 - 1780: -10,-4 - 1781: -12,-5 - 1782: -14,-5 - 1783: -14,-4 - 1784: -16,-4 - 1785: -17,-5 - 1786: -18,-5 - 1787: -23,-5 - 1788: -24,-5 - 1789: -32,-4 - 1790: -38,-4 - 1791: -39,-4 - 1792: -40,-5 - 1793: -42,-5 - 1794: -42,-6 - 1795: -42,-7 - 1796: -42,-10 - 1797: -42,-12 - 1798: -42,-14 - 1799: -40,-16 - 1800: -42,-17 - 1801: -38,-7 - 1802: -38,-8 - 1803: -37,-7 - 1804: -33,-7 - 1805: -26,-4 - 1806: -24,-1 - 1807: -23,0 - 1808: -23,2 - 1809: -24,3 - 1810: -23,5 - 1811: -23,6 - 1812: -24,6 - 1813: -23,7 - 1814: -23,10 - 1815: -30,5 - 1816: -31,1 - 1817: -31,4 - 1818: -26,1 - 1819: -26,2 - 1820: -22,8 - 1821: -24,9 - 1822: -22,10 - 1823: -24,8 - 1824: -23,9 - 1825: -22,13 - 1826: -24,15 - 1827: -23,16 - 1828: -22,17 - 1829: -25,18 - 1830: -23,18 - 1831: -23,19 - 1832: -25,22 - 1833: -23,23 - 1834: -23,24 - 1835: -24,25 - 1836: -22,26 - 1837: -23,27 - 1838: -24,28 - 1839: -22,30 - 1840: -23,30 - 1841: -24,31 - 1842: -26,29 - 1843: -27,30 - 1844: -29,30 - 1845: -27,29 - 1846: -31,29 - 1847: -32,30 - 1848: -34,29 - 1849: -36,29 - 1850: -37,30 - 1851: -39,29 - 1852: -40,29 - 1853: -42,30 - 1854: -43,30 - 1855: -45,29 - 1856: -46,30 - 1857: -47,30 - 1858: -46,29 - 1859: -51,30 - 1860: -52,31 - 1861: -53,29 - 1862: -54,30 - 1863: -55,31 - 1864: -57,29 - 1865: -58,30 - 1866: -57,32 - 1867: -58,34 - 1868: -56,36 - 1869: -57,39 - 1870: -56,40 - 1871: -57,45 - 1872: -57,46 - 1873: -59,48 - 1874: -57,49 - 1875: -59,50 - 1876: -58,49 - 1877: -59,47 - 1878: -58,45 - 1879: -62,49 - 1880: -64,49 - 1881: -64,49 - 1882: -64,48 - 1883: -62,48 - 1884: -61,54 - 1885: -59,54 - 1886: -59,54 - 1887: -59,53 - 1888: -62,45 - 1889: -63,43 - 1890: -63,40 - 1891: -63,40 - 1892: -62,36 - 1893: -61,35 - 1894: -56,35 - 1895: -45,29 - 1896: -40,30 - 1897: -43,26 - 1898: -41,26 - 1899: -40,26 - 1900: -38,26 - 1901: -37,26 - 1902: -40,27 - 1903: -20,34 - 1904: -20,35 - 1905: -21,41 - 1906: -20,43 - 1907: -20,44 - 1908: -21,46 - 1909: -20,47 - 1910: -20,49 - 1911: -21,50 - 1912: -21,51 - 1913: -20,53 - 1914: -20,54 - 1915: -24,53 - 1916: -26,53 - 1917: -27,53 - 1918: -28,54 - 1919: -29,54 - 1920: -28,56 - 1921: -28,57 - 1922: -28,58 - 1923: -27,59 - 1924: -25,59 - 1925: -24,58 - 1926: -24,56 - 1927: -21,55 - 1928: -20,52 - 1929: -19,51 - 1930: -20,42 - 1931: -20,40 - 1932: -16,44 - 1933: -14,43 - 1934: -13,44 - 1935: -11,45 - 1936: -10,44 - 1937: -12,48 - 1938: -13,47 - 1939: -14,48 - 1940: -11,47 - 1941: -10,48 - 1942: -10,52 - 1943: -11,53 - 1944: -14,53 - 1945: -15,53 - 1946: -17,53 - 1947: -17,51 - 1948: -10,39 - 1949: -11,38 - 1950: -14,38 - 1951: -14,37 - 1952: -15,36 - 1953: -16,38 - 1954: -16,40 - 1955: -14,41 - 1956: -11,39 - 1957: -17,39 - 1958: -8,44 - 1959: -8,45 - 1960: -7,42 - 1961: -6,41 - 1962: -5,46 - 1963: -6,49 - 1964: -7,49 - 1965: 2,44 - 1966: -6,29 - 1967: -4,31 - 1968: -2,31 - 1969: 0,30 - 1970: 2,30 - 1971: 4,31 - 1972: 5,31 - 1973: 7,30 - 1974: 9,30 - 1975: 10,31 - 1976: 11,31 - 1977: 10,30 - 1978: 14,31 - 1979: 15,31 - 1980: 17,30 - 1981: 18,31 - 1982: 22,23 - 1983: 23,23 - 1984: 23,22 - 1985: 22,22 - 1986: 21,23 - 1987: 21,23 - 1988: 20,24 + 1696: -5,50 + 1697: -6,46 + 1698: -7,44 + 1699: -4,48 + 1700: -1,50 + 1701: 2,49 + 1702: 5,49 + 1703: 6,51 + 1704: 7,49 + 1705: 9,50 + 1706: 13,49 + 1707: 16,51 + 1708: 19,49 + 1709: 23,50 + 1710: 23,49 + 1711: 29,51 + 1712: 31,51 + 1713: 32,49 + 1714: 33,47 + 1715: 31,48 + 1716: 34,53 + 1717: 33,49 + 1718: 30,49 + 1719: 32,42 + 1720: 33,40 + 1721: 33,36 + 1722: 32,34 + 1723: 32,32 + 1724: 33,33 + 1725: 32,29 + 1726: 31,27 + 1727: 32,28 + 1728: 33,24 + 1729: 32,22 + 1730: 33,23 + 1731: 31,21 + 1732: 33,19 + 1733: 32,17 + 1734: 31,16 + 1735: 32,15 + 1736: 33,14 + 1737: 31,12 + 1738: 31,11 + 1739: 33,9 + 1740: 32,8 + 1741: 31,7 + 1742: 33,4 + 1743: 30,3 + 1744: 30,2 + 1745: 30,2 + 1746: 28,1 + 1747: 28,0 + 1748: 29,0 + 1749: 27,-1 + 1750: 27,-2 + 1751: 28,-4 + 1752: 26,-4 + 1753: 25,-4 + 1754: 24,-5 + 1755: 22,-5 + 1756: 21,-4 + 1757: 20,-3 + 1758: 18,-4 + 1759: 12,-4 + 1760: 9,-4 + 1761: 7,-4 + 1762: 3,-4 + 1763: 0,-4 + 1764: 1,-4 + 1765: -5,-4 + 1766: -6,-5 + 1767: -7,-5 + 1768: -6,-4 + 1769: -10,-4 + 1770: -12,-5 + 1771: -14,-5 + 1772: -14,-4 + 1773: -16,-4 + 1774: -17,-5 + 1775: -18,-5 + 1776: -23,-5 + 1777: -24,-5 + 1778: -32,-4 + 1779: -38,-4 + 1780: -39,-4 + 1781: -40,-5 + 1782: -42,-5 + 1783: -42,-6 + 1784: -42,-7 + 1785: -42,-10 + 1786: -42,-12 + 1787: -42,-14 + 1788: -40,-16 + 1789: -42,-17 + 1790: -38,-7 + 1791: -38,-8 + 1792: -37,-7 + 1793: -33,-7 + 1794: -26,-4 + 1795: -24,-1 + 1796: -23,0 + 1797: -23,2 + 1798: -24,3 + 1799: -23,5 + 1800: -23,6 + 1801: -24,6 + 1802: -23,7 + 1803: -23,10 + 1804: -30,5 + 1805: -31,1 + 1806: -31,4 + 1807: -26,1 + 1808: -26,2 + 1809: -22,8 + 1810: -24,9 + 1811: -22,10 + 1812: -24,8 + 1813: -23,9 + 1814: -22,13 + 1815: -24,15 + 1816: -23,16 + 1817: -22,17 + 1818: -25,18 + 1819: -23,18 + 1820: -23,19 + 1821: -25,22 + 1822: -23,23 + 1823: -23,24 + 1824: -24,25 + 1825: -22,26 + 1826: -23,27 + 1827: -24,28 + 1828: -22,30 + 1829: -23,30 + 1830: -24,31 + 1831: -26,29 + 1832: -27,30 + 1833: -29,30 + 1834: -27,29 + 1835: -31,29 + 1836: -32,30 + 1837: -34,29 + 1838: -36,29 + 1839: -37,30 + 1840: -39,29 + 1841: -40,29 + 1842: -42,30 + 1843: -43,30 + 1844: -45,29 + 1845: -46,30 + 1846: -47,30 + 1847: -46,29 + 1848: -51,30 + 1849: -52,31 + 1850: -53,29 + 1851: -54,30 + 1852: -55,31 + 1853: -57,29 + 1854: -58,30 + 1855: -57,32 + 1856: -58,34 + 1857: -56,36 + 1858: -57,39 + 1859: -56,40 + 1860: -57,45 + 1861: -57,46 + 1862: -59,48 + 1863: -57,49 + 1864: -59,50 + 1865: -58,49 + 1866: -59,47 + 1867: -58,45 + 1868: -62,49 + 1869: -64,49 + 1870: -64,49 + 1871: -64,48 + 1872: -62,48 + 1873: -61,54 + 1874: -59,54 + 1875: -59,54 + 1876: -59,53 + 1877: -62,45 + 1878: -63,43 + 1879: -63,40 + 1880: -63,40 + 1881: -62,36 + 1882: -61,35 + 1883: -56,35 + 1884: -45,29 + 1885: -40,30 + 1886: -43,26 + 1887: -41,26 + 1888: -40,26 + 1889: -38,26 + 1890: -37,26 + 1891: -40,27 + 1892: -20,34 + 1893: -20,35 + 1894: -21,41 + 1895: -20,43 + 1896: -20,44 + 1897: -21,46 + 1898: -20,47 + 1899: -20,49 + 1900: -21,50 + 1901: -21,51 + 1902: -20,53 + 1903: -20,54 + 1904: -24,53 + 1905: -26,53 + 1906: -27,53 + 1907: -28,54 + 1908: -29,54 + 1909: -28,56 + 1910: -28,57 + 1911: -28,58 + 1912: -27,59 + 1913: -25,59 + 1914: -24,58 + 1915: -24,56 + 1916: -21,55 + 1917: -20,52 + 1918: -19,51 + 1919: -20,42 + 1920: -20,40 + 1921: -16,44 + 1922: -14,43 + 1923: -13,44 + 1924: -11,45 + 1925: -10,44 + 1926: -12,48 + 1927: -13,47 + 1928: -14,48 + 1929: -11,47 + 1930: -10,48 + 1931: -10,52 + 1932: -11,53 + 1933: -14,53 + 1934: -15,53 + 1935: -17,53 + 1936: -17,51 + 1937: -10,39 + 1938: -11,38 + 1939: -14,38 + 1940: -14,37 + 1941: -15,36 + 1942: -16,38 + 1943: -16,40 + 1944: -14,41 + 1945: -11,39 + 1946: -17,39 + 1947: -8,44 + 1948: -8,45 + 1949: -7,42 + 1950: -6,41 + 1951: -5,46 + 1952: -6,49 + 1953: -7,49 + 1954: 2,44 + 1955: -6,29 + 1956: -4,31 + 1957: -2,31 + 1958: 0,30 + 1959: 2,30 + 1960: 4,31 + 1961: 5,31 + 1962: 7,30 + 1963: 9,30 + 1964: 10,31 + 1965: 11,31 + 1966: 10,30 + 1967: 14,31 + 1968: 15,31 + 1969: 17,30 + 1970: 18,31 + 1971: 22,23 + 1972: 23,23 + 1973: 23,22 + 1974: 22,22 + 1975: 21,23 + 1976: 21,23 + 1977: 20,24 + 1978: 20,23 + 1979: 21,21 + 1980: 20,20 + 1981: 20,19 + 1982: 22,19 + 1983: 24,19 + 1984: 27,19 + 1985: 29,19 + 1986: 29,19 + 1987: 24,19 + 1988: 22,21 1989: 20,23 - 1990: 21,21 - 1991: 20,20 - 1992: 20,19 - 1993: 22,19 - 1994: 24,19 - 1995: 27,19 - 1996: 29,19 - 1997: 29,19 - 1998: 24,19 - 1999: 22,21 - 2000: 20,23 - 2001: 20,26 - 2002: 20,29 - 2003: 20,31 - 2004: 23,31 - 2005: 27,31 - 2006: 29,31 - 2007: 29,30 - 2008: 27,30 - 2009: 24,30 - 2010: 21,31 - 2011: 20,33 - 2012: 21,35 - 2013: 22,35 - 2014: 26,37 - 2015: 25,35 - 2016: 25,36 - 2017: 26,34 - 2018: 27,34 - 2019: 28,36 - 2020: 28,37 - 2021: 27,34 - 2022: 28,35 - 2023: 26,34 - 2024: 25,33 - 2025: 24,34 - 2026: 24,36 - 2027: 25,38 - 2028: 27,38 - 2029: 29,37 - 2030: 29,35 - 2031: 20,38 - 2032: 21,40 - 2033: 22,41 - 2034: 23,40 - 2035: 21,41 - 2036: 21,43 - 2037: 21,43 - 2038: 20,45 - 2039: 17,45 - 2040: 20,46 - 2041: 14,45 - 2042: 12,45 - 2043: 11,41 - 2044: 10,41 - 2045: 8,41 - 2046: 6,41 - 2047: 5,39 - 2048: 5,38 - 2049: 4,43 - 2050: 5,45 - 2051: 5,47 - 2052: 6,47 - 2053: 9,47 - 2054: 25,47 - 2055: 25,46 - 2056: 26,45 - 2057: 26,45 - 2058: 22,8 - 2059: 21,8 - 2060: 22,9 - 2061: 21,10 - 2062: 20,10 - 2063: 21,13 - 2064: 20,14 - 2065: 21,15 - 2066: 19,14 - 2067: 18,16 - 2068: 18,16 - 2069: 17,15 - 2070: -4,11 - 2071: -4,10 - 2072: -5,10 - 2073: -6,10 - 2074: -7,10 - 2075: -7,8 - 2076: -7,7 - 2077: -9,8 - 2078: -6,12 - 2079: -6,16 - 2080: 29,7 - 2081: 29,8 - 2082: 29,9 - 2083: 28,10 - 2084: 26,9 - 2085: 25,8 - 2086: 25,7 - 2087: 29,8 - 2088: 27,8 - 2089: 47,29 - 2090: 45,29 - 2091: 43,29 - 2092: 42,29 - 2093: 42,28 - 2094: 44,28 - 2095: 46,27 - 2096: 46,27 - 2097: 44,27 - 2098: 43,27 - 2099: 45,26 - 2100: 44,25 - 2101: 43,25 - 2102: 44,24 - 2103: 41,23 - 2104: 43,22 - 2105: 43,22 - 2106: 42,21 - 2107: 43,20 - 2108: 42,19 - 2109: 43,19 - 2110: 41,18 - 2111: 43,17 - 2112: 42,17 - 2113: 43,20 - 2114: 42,21 - 2115: 43,21 - 2116: 45,20 - 2117: 43,20 - 2118: 45,21 - 2119: 46,21 - 2120: 45,22 - 2121: 44,22 - 2122: 44,21 - 2123: 45,21 - 2124: 44,23 - 2125: 44,23 - 2126: 47,23 - 2127: 48,23 - 2128: 48,23 - 2129: 48,23 - 2130: 47,23 - 2131: 48,22 - 2132: 48,21 - 2133: 47,21 - 2134: 47,21 - 2135: 47,21 - 2136: 48,21 - 2137: 45,22 - 2138: 45,23 - 2139: 44,23 - 2140: 45,24 - 2141: 43,18 - 2142: 41,17 - 2143: 42,16 - 2144: 43,15 - 2145: 43,15 - 2146: 42,14 - 2147: 41,13 - 2148: 42,12 - 2149: 43,14 - 2150: 43,13 - 2151: 39,14 - 2152: 39,12 - 2153: 37,12 - 2154: 36,13 - 2155: 35,14 - 2156: 34,13 - 2157: 38,33 - 2158: 39,33 - 2159: 41,33 - 2160: 42,33 - 2161: 44,33 - 2162: 45,36 - 2163: 46,36 - 2164: 46,35 - 2165: 46,33 - 2166: 44,32 - 2167: 43,33 - 2168: 40,33 - 2169: 43,34 - 2170: 45,37 - 2171: 46,36 - 2172: 47,33 - 2173: 47,33 - 2174: 39,33 - 2175: 43,33 - 2176: 37,33 - 2177: 35,33 - 2178: 34,34 - 2179: 32,37 - 2180: 32,42 - 2181: 33,44 - 2182: 32,47 - 2183: 33,48 - 2184: 33,50 - 2185: 13,55 - 2186: 14,55 - 2187: 15,55 - 2188: 15,54 - 2189: 15,54 - 2190: 14,54 - 2191: 13,54 - 2192: 14,53 - 2193: 15,53 - 2194: 14,53 - 2195: 13,53 - 2196: 16,53 - 2197: 16,53 - 2198: 16,55 - 2199: 16,56 - 2200: 14,56 - 2201: 14,56 - 2202: 16,57 - 2203: 14,57 - 2204: 13,57 - 2205: 12,57 - 2206: 11,55 - 2207: 12,54 - 2208: 11,53 - 2209: 19,60 - 2210: 19,57 - 2211: 18,60 - 2212: 18,64 - 2213: 20,65 - 2214: 22,66 - 2215: 21,66 - 2216: 22,64 - 2217: 21,64 - 2218: 23,65 - 2219: 24,66 - 2220: 23,67 - 2221: 23,69 - 2222: 24,71 - 2223: 26,71 - 2224: 26,69 - 2225: 27,68 - 2226: 29,69 - 2227: 11,72 - 2228: 20,74 - 2229: 20,73 - 2230: 23,47 - 2231: 23,47 - 2232: 23,47 - 2233: 23,46 - 2234: 23,46 - 2235: 22,47 - 2236: 35,57 - 2237: 36,56 - 2238: 36,56 - 2239: 37,56 - 2240: 36,56 - 2241: 36,55 - 2242: 36,54 - 2243: 36,53 - 2244: 38,53 - 2245: 40,53 - 2246: 40,55 - 2247: 40,56 - 2248: 41,57 - 2249: 41,56 - 2250: 39,56 - 2251: 40,55 - 2252: 41,53 - 2253: 41,53 - 2254: 43,54 - 2255: 43,55 - 2256: 43,57 - 2257: 43,55 - 2258: 43,53 - 2259: 43,52 - 2260: 43,50 - 2261: 45,50 - 2262: 46,50 - 2263: 47,50 - 2264: 47,49 - 2265: 47,47 - 2266: 47,46 - 2267: 47,46 - 2268: 46,44 - 2269: 46,44 - 2270: 46,45 - 2271: 46,46 - 2272: 46,47 - 2273: 40,50 - 2274: 40,48 - 2275: 40,46 - 2276: 39,45 - 2277: 37,46 - 2278: 35,46 - 2279: 40,50 - 2280: 40,52 - 2281: 40,51 - 2282: 40,50 - 2283: 40,43 - 2284: 40,43 - 2285: 40,44 - 2286: 39,44 - 2287: 39,44 - 2288: 39,43 - 2289: 39,42 - 2290: 39,40 - 2291: 39,39 - 2292: 40,39 - 2293: 43,39 - 2294: 45,39 - 2295: 46,39 - 2296: 47,39 - 2297: 47,40 - 2298: 46,41 - 2299: 47,42 - 2300: 47,44 - 2301: 47,46 - 2302: 47,48 - 2303: 43,44 - 2304: 44,44 - 2305: 42,43 - 2306: 42,42 - 2307: 43,41 - 2308: 44,41 - 2309: 44,43 - 2310: 43,45 - 2311: 43,47 - 2312: 44,48 - 2313: 44,48 - 2314: 49,33 - 2315: 49,34 - 2316: 50,35 - 2317: 50,36 - 2318: 50,36 - 2319: 35,7 - 2320: 35,8 - 2321: 36,8 - 2322: 37,8 - 2323: 40,8 - 2324: 40,8 - 2325: 40,7 - 2326: 38,7 - 2327: 38,7 - 2328: 41,9 - 2329: 44,9 - 2330: 42,9 - 2331: 46,9 - 2332: 47,9 - 2333: 49,9 - 2334: 49,9 - 2335: 50,9 - 2336: 38,4 - 2337: 35,4 - 2338: 39,2 - 2339: 43,3 - 2340: 45,3 - 2341: 44,0 - 2342: 44,-1 - 2343: 47,-1 - 2344: 44,-1 - 2345: 46,-1 - 2346: 46,-1 - 2347: 45,-1 - 2348: 46,0 - 2349: 45,0 - 2350: 46,3 - 2351: 47,3 - 2352: 45,3 - 2353: 46,4 - 2354: 49,3 - 2355: 51,3 - 2356: 48,2 - 2357: 53,3 - 2358: 55,3 - 2359: 57,2 - 2360: 59,3 - 2361: 61,2 - 2362: 63,4 - 2363: 64,2 - 2364: 65,3 - 2365: 66,3 - 2366: 69,3 - 2367: 69,3 - 2368: 72,4 - 2369: 73,3 - 2370: 75,3 - 2371: 76,3 - 2372: 78,3 - 2373: 79,3 - 2374: 81,3 - 2375: 83,4 - 2376: 84,2 - 2377: 85,3 - 2378: 86,4 - 2379: 83,7 - 2380: 80,7 - 2381: 78,6 - 2382: 76,8 - 2383: 77,9 - 2384: 80,9 - 2385: 83,9 - 2386: 82,12 - 2387: 82,13 - 2388: 83,14 - 2389: 83,14 - 2390: 83,13 - 2391: 75,13 - 2392: 75,15 - 2393: 76,15 - 2394: 76,14 - 2395: 76,9 - 2396: 76,6 - 2397: 77,6 - 2398: 83,6 - 2399: 83,8 - 2400: 84,3 - 2401: 67,2 - 2402: 66,4 - 2403: 61,2 - 2404: 58,4 - 2405: 57,3 - 2406: 56,2 - 2407: 52,4 - 2408: 51,3 - 2409: 53,-13 - 2410: 60,-20 - 2411: 62,-21 - 2412: 61,-22 - 2413: 60,-19 - 2415: 41,-16 - 2416: 38,-16 - 2417: 37,-16 - 2418: 37,-19 - 2419: 37,-20 - 2420: 37,-20 - 2421: 36,-20 - 2422: 37,-20 - 2423: 37,-20 - 2424: 40,-19 - 2425: 40,-19 - 2426: 39,-19 - 2427: 40,-20 - 2428: 43,-19 - 2429: 43,-20 - 2430: 42,-20 - 2431: 45,-19 - 2432: 45,-20 - 2433: 45,-20 - 2434: 46,-20 - 2435: 38,-16 - 2436: 36,-14 - 2437: 35,-13 - 2438: 35,-11 - 2439: 34,-9 - 2440: 35,-7 - 2441: 36,-6 - 2442: 36,-4 - 2443: 36,-3 - 2444: 38,-5 - 2445: 40,-3 - 2446: 39,-3 - 2447: 41,-3 - 2448: 39,2 - 2449: 41,2 - 2450: 31,2 - 2451: 30,3 - 2452: 28,1 - 2453: 28,3 - 2454: 29,0 - 2455: 23,-7 - 2456: 28,-7 - 2457: 7,-16 - 2458: 7,-16 - 2459: 7,-17 - 2460: -9,-2 - 2461: -9,-1 - 2462: -8,-1 - 2463: -7,-1 - 2464: -6,-1 - 2465: -5,-2 - 2466: -5,-6 - 2467: -5,-15 - 2468: -4,-15 - 2469: -6,-19 - 2470: -5,-17 - 2471: -6,-20 - 2472: -4,-22 - 2473: -4,-24 - 2474: -5,-26 - 2475: -8,-26 - 2476: -9,-26 - 2477: -10,-25 - 2478: -11,-27 - 2479: -10,-28 - 2480: -7,-28 - 2481: -13,-25 - 2482: -14,-26 - 2483: -17,-26 - 2484: -19,-25 - 2485: -20,-27 - 2486: -22,-26 - 2487: -25,-26 - 2488: -26,-29 - 2489: -27,-30 - 2490: -26,-31 - 2491: -27,-31 - 2492: -27,-33 - 2493: -25,-34 - 2494: -26,-35 - 2495: -24,-35 - 2496: -23,-35 - 2497: -23,-34 - 2498: -27,-26 - 2499: -28,-26 - 2500: -31,-28 - 2501: -33,-28 - 2502: -37,-28 - 2503: -31,-28 - 2504: -31,-27 - 2505: -37,-28 - 2506: -31,-31 - 2507: -33,-32 - 2508: -34,-33 - 2509: -36,-32 - 2510: -37,-32 - 2511: -39,-33 - 2512: -37,-32 - 2513: -41,-31 + 1990: 20,26 + 1991: 20,29 + 1992: 20,31 + 1993: 23,31 + 1994: 27,31 + 1995: 29,31 + 1996: 29,30 + 1997: 27,30 + 1998: 24,30 + 1999: 21,31 + 2000: 20,33 + 2001: 21,35 + 2002: 22,35 + 2003: 26,37 + 2004: 25,35 + 2005: 25,36 + 2006: 26,34 + 2007: 27,34 + 2008: 28,36 + 2009: 28,37 + 2010: 27,34 + 2011: 28,35 + 2012: 26,34 + 2013: 25,33 + 2014: 24,34 + 2015: 24,36 + 2016: 25,38 + 2017: 27,38 + 2018: 29,37 + 2019: 29,35 + 2020: 20,38 + 2021: 21,40 + 2022: 22,41 + 2023: 23,40 + 2024: 21,41 + 2025: 21,43 + 2026: 21,43 + 2027: 20,45 + 2028: 17,45 + 2029: 20,46 + 2030: 14,45 + 2031: 12,45 + 2032: 11,41 + 2033: 10,41 + 2034: 8,41 + 2035: 6,41 + 2036: 5,39 + 2037: 5,38 + 2038: 4,43 + 2039: 5,45 + 2040: 5,47 + 2041: 6,47 + 2042: 9,47 + 2043: 25,47 + 2044: 25,46 + 2045: 26,45 + 2046: 26,45 + 2047: 22,8 + 2048: 21,8 + 2049: 22,9 + 2050: 21,10 + 2051: 20,10 + 2052: 21,13 + 2053: 20,14 + 2054: 21,15 + 2055: 19,14 + 2056: 18,16 + 2057: 18,16 + 2058: 17,15 + 2059: -4,11 + 2060: -4,10 + 2061: -5,10 + 2062: -6,10 + 2063: -7,10 + 2064: -7,8 + 2065: -7,7 + 2066: -9,8 + 2067: -6,12 + 2068: -6,16 + 2069: 29,7 + 2070: 29,8 + 2071: 29,9 + 2072: 28,10 + 2073: 26,9 + 2074: 25,8 + 2075: 25,7 + 2076: 29,8 + 2077: 27,8 + 2078: 47,29 + 2079: 45,29 + 2080: 43,29 + 2081: 42,29 + 2082: 42,28 + 2083: 44,28 + 2084: 46,27 + 2085: 46,27 + 2086: 44,27 + 2087: 43,27 + 2088: 45,26 + 2089: 44,25 + 2090: 43,25 + 2091: 44,24 + 2092: 41,23 + 2093: 43,22 + 2094: 43,22 + 2095: 42,21 + 2096: 43,20 + 2097: 42,19 + 2098: 43,19 + 2099: 41,18 + 2100: 43,17 + 2101: 42,17 + 2102: 43,20 + 2103: 42,21 + 2104: 43,21 + 2105: 45,20 + 2106: 43,20 + 2107: 45,21 + 2108: 46,21 + 2109: 45,22 + 2110: 44,22 + 2111: 44,21 + 2112: 45,21 + 2113: 44,23 + 2114: 44,23 + 2115: 47,23 + 2116: 48,23 + 2117: 48,23 + 2118: 48,23 + 2119: 47,23 + 2120: 48,22 + 2121: 48,21 + 2122: 47,21 + 2123: 47,21 + 2124: 47,21 + 2125: 48,21 + 2126: 45,22 + 2127: 45,23 + 2128: 44,23 + 2129: 45,24 + 2130: 43,18 + 2131: 41,17 + 2132: 42,16 + 2133: 43,15 + 2134: 43,15 + 2135: 42,14 + 2136: 41,13 + 2137: 42,12 + 2138: 43,14 + 2139: 43,13 + 2140: 39,14 + 2141: 39,12 + 2142: 37,12 + 2143: 36,13 + 2144: 35,14 + 2145: 34,13 + 2146: 38,33 + 2147: 39,33 + 2148: 41,33 + 2149: 42,33 + 2150: 44,33 + 2151: 45,36 + 2152: 46,36 + 2153: 46,35 + 2154: 46,33 + 2155: 44,32 + 2156: 43,33 + 2157: 40,33 + 2158: 43,34 + 2159: 45,37 + 2160: 46,36 + 2161: 47,33 + 2162: 47,33 + 2163: 39,33 + 2164: 43,33 + 2165: 37,33 + 2166: 35,33 + 2167: 34,34 + 2168: 32,37 + 2169: 32,42 + 2170: 33,44 + 2171: 32,47 + 2172: 33,48 + 2173: 33,50 + 2174: 13,55 + 2175: 14,55 + 2176: 15,55 + 2177: 15,54 + 2178: 15,54 + 2179: 14,54 + 2180: 13,54 + 2181: 14,53 + 2182: 15,53 + 2183: 14,53 + 2184: 13,53 + 2185: 16,53 + 2186: 16,53 + 2187: 16,55 + 2188: 16,56 + 2189: 14,56 + 2190: 14,56 + 2191: 16,57 + 2192: 14,57 + 2193: 13,57 + 2194: 12,57 + 2195: 11,55 + 2196: 12,54 + 2197: 11,53 + 2198: 19,60 + 2199: 19,57 + 2200: 18,60 + 2201: 18,64 + 2202: 20,65 + 2203: 22,66 + 2204: 21,66 + 2205: 22,64 + 2206: 21,64 + 2207: 23,65 + 2208: 24,66 + 2209: 23,67 + 2210: 23,69 + 2211: 24,71 + 2212: 26,71 + 2213: 26,69 + 2214: 27,68 + 2215: 29,69 + 2216: 11,72 + 2217: 20,74 + 2218: 20,73 + 2219: 23,47 + 2220: 23,47 + 2221: 23,47 + 2222: 23,46 + 2223: 23,46 + 2224: 22,47 + 2225: 35,57 + 2226: 36,56 + 2227: 36,56 + 2228: 37,56 + 2229: 36,56 + 2230: 36,55 + 2231: 36,54 + 2232: 36,53 + 2233: 38,53 + 2234: 40,53 + 2235: 40,55 + 2236: 40,56 + 2237: 41,57 + 2238: 41,56 + 2239: 39,56 + 2240: 40,55 + 2241: 41,53 + 2242: 41,53 + 2243: 43,54 + 2244: 43,55 + 2245: 43,57 + 2246: 43,55 + 2247: 43,53 + 2248: 43,52 + 2249: 43,50 + 2250: 45,50 + 2251: 46,50 + 2252: 47,50 + 2253: 47,49 + 2254: 47,47 + 2255: 47,46 + 2256: 47,46 + 2257: 46,44 + 2258: 46,44 + 2259: 46,45 + 2260: 46,46 + 2261: 46,47 + 2262: 40,50 + 2263: 40,48 + 2264: 40,46 + 2265: 39,45 + 2266: 37,46 + 2267: 35,46 + 2268: 40,50 + 2269: 40,52 + 2270: 40,51 + 2271: 40,50 + 2272: 40,43 + 2273: 40,43 + 2274: 40,44 + 2275: 39,44 + 2276: 39,44 + 2277: 39,43 + 2278: 39,42 + 2279: 39,40 + 2280: 39,39 + 2281: 40,39 + 2282: 43,39 + 2283: 45,39 + 2284: 46,39 + 2285: 47,39 + 2286: 47,40 + 2287: 46,41 + 2288: 47,42 + 2289: 47,44 + 2290: 47,46 + 2291: 47,48 + 2292: 43,44 + 2293: 44,44 + 2294: 42,43 + 2295: 42,42 + 2296: 43,41 + 2297: 44,41 + 2298: 44,43 + 2299: 43,45 + 2300: 43,47 + 2301: 44,48 + 2302: 44,48 + 2303: 49,33 + 2304: 49,34 + 2305: 50,35 + 2306: 50,36 + 2307: 50,36 + 2308: 35,7 + 2309: 35,8 + 2310: 36,8 + 2311: 37,8 + 2312: 40,8 + 2313: 40,8 + 2314: 40,7 + 2315: 38,7 + 2316: 38,7 + 2317: 41,9 + 2318: 44,9 + 2319: 42,9 + 2320: 46,9 + 2321: 47,9 + 2322: 49,9 + 2323: 49,9 + 2324: 50,9 + 2325: 38,4 + 2326: 35,4 + 2327: 39,2 + 2328: 43,3 + 2329: 45,3 + 2330: 44,0 + 2331: 44,-1 + 2332: 47,-1 + 2333: 44,-1 + 2334: 46,-1 + 2335: 46,-1 + 2336: 45,-1 + 2337: 46,0 + 2338: 45,0 + 2339: 46,3 + 2340: 47,3 + 2341: 45,3 + 2342: 46,4 + 2343: 49,3 + 2344: 51,3 + 2345: 48,2 + 2346: 53,3 + 2347: 55,3 + 2348: 57,2 + 2349: 59,3 + 2350: 61,2 + 2351: 63,4 + 2352: 64,2 + 2353: 65,3 + 2354: 66,3 + 2355: 69,3 + 2356: 69,3 + 2357: 72,4 + 2358: 73,3 + 2359: 75,3 + 2360: 76,3 + 2361: 78,3 + 2362: 79,3 + 2363: 81,3 + 2364: 83,4 + 2365: 84,2 + 2366: 85,3 + 2367: 86,4 + 2368: 83,7 + 2369: 80,7 + 2370: 78,6 + 2371: 76,8 + 2372: 77,9 + 2373: 80,9 + 2374: 83,9 + 2375: 82,12 + 2376: 82,13 + 2377: 83,14 + 2378: 83,14 + 2379: 83,13 + 2380: 75,13 + 2381: 75,15 + 2382: 76,15 + 2383: 76,14 + 2384: 76,9 + 2385: 76,6 + 2386: 77,6 + 2387: 83,6 + 2388: 83,8 + 2389: 84,3 + 2390: 67,2 + 2391: 66,4 + 2392: 61,2 + 2393: 58,4 + 2394: 57,3 + 2395: 56,2 + 2396: 52,4 + 2397: 51,3 + 2398: 53,-13 + 2399: 60,-20 + 2400: 62,-21 + 2401: 61,-22 + 2402: 60,-19 + 2403: 41,-16 + 2404: 38,-16 + 2405: 37,-16 + 2406: 37,-19 + 2407: 37,-20 + 2408: 37,-20 + 2409: 36,-20 + 2410: 37,-20 + 2411: 37,-20 + 2412: 40,-19 + 2413: 40,-19 + 2414: 39,-19 + 2415: 40,-20 + 2416: 43,-19 + 2417: 43,-20 + 2418: 42,-20 + 2419: 45,-19 + 2420: 45,-20 + 2421: 45,-20 + 2422: 46,-20 + 2423: 38,-16 + 2424: 36,-14 + 2425: 35,-13 + 2426: 35,-11 + 2427: 34,-9 + 2428: 35,-7 + 2429: 36,-6 + 2430: 36,-4 + 2431: 36,-3 + 2432: 38,-5 + 2433: 40,-3 + 2434: 39,-3 + 2435: 41,-3 + 2436: 39,2 + 2437: 41,2 + 2438: 31,2 + 2439: 30,3 + 2440: 28,1 + 2441: 28,3 + 2442: 29,0 + 2443: 23,-7 + 2444: 28,-7 + 2445: 7,-16 + 2446: 7,-16 + 2447: 7,-17 + 2448: -9,-2 + 2449: -9,-1 + 2450: -8,-1 + 2451: -7,-1 + 2452: -6,-1 + 2453: -5,-2 + 2454: -5,-6 + 2455: -5,-15 + 2456: -4,-15 + 2457: -6,-19 + 2458: -5,-17 + 2459: -6,-20 + 2460: -4,-22 + 2461: -4,-24 + 2462: -5,-26 + 2463: -8,-26 + 2464: -9,-26 + 2465: -10,-25 + 2466: -11,-27 + 2467: -10,-28 + 2468: -7,-28 + 2469: -13,-25 + 2470: -14,-26 + 2471: -17,-26 + 2472: -19,-25 + 2473: -20,-27 + 2474: -22,-26 + 2475: -25,-26 + 2476: -26,-29 + 2477: -27,-30 + 2478: -26,-31 + 2479: -27,-31 + 2480: -27,-33 + 2481: -25,-34 + 2482: -26,-35 + 2483: -24,-35 + 2484: -23,-35 + 2485: -23,-34 + 2486: -27,-26 + 2487: -28,-26 + 2488: -31,-28 + 2489: -33,-28 + 2490: -37,-28 + 2491: -31,-28 + 2492: -31,-27 + 2493: -37,-28 + 2494: -31,-31 + 2495: -33,-32 + 2496: -34,-33 + 2497: -36,-32 + 2498: -37,-32 + 2499: -39,-33 + 2500: -37,-32 + 2501: -41,-31 + 2502: -42,-32 + 2503: -43,-32 + 2504: -45,-31 + 2505: -46,-32 + 2506: -46,-32 + 2507: -48,-31 + 2508: -49,-32 + 2509: -49,-32 + 2510: -50,-31 + 2511: -51,-32 + 2512: -52,-32 + 2513: -44,-33 2514: -42,-32 - 2515: -43,-32 - 2516: -45,-31 - 2517: -46,-32 - 2518: -46,-32 - 2519: -48,-31 - 2520: -49,-32 - 2521: -49,-32 - 2522: -50,-31 - 2523: -51,-32 - 2524: -52,-32 - 2525: -44,-33 - 2526: -42,-32 - 2527: -41,-31 - 2528: -39,-32 - 2529: -38,-33 - 2530: -37,-33 - 2531: -32,-33 - 2532: -39,-38 - 2533: -39,-39 - 2534: -41,-39 - 2535: -31,-37 - 2536: -31,-38 - 2537: -31,-39 - 2538: -27,-41 - 2539: -27,-39 - 2540: -26,-39 - 2541: -23,-40 - 2542: -24,-41 - 2543: -26,-39 - 2544: -23,-39 - 2545: -24,-39 - 2546: -25,-39 - 2547: -25,-38 - 2548: -35,-41 - 2549: -39,-39 - 2550: -39,-37 - 2551: -32,-36 - 2552: -32,-36 - 2553: -39,-36 - 2554: -49,-28 - 2555: -50,-27 - 2556: -52,-27 - 2557: -52,-28 - 2558: -51,-29 - 2559: -50,-29 - 2560: -50,-28 - 2561: -55,-32 - 2562: -56,-31 - 2563: -57,-31 - 2564: -57,-29 - 2565: -56,-29 - 2566: -55,-29 - 2567: -56,-25 - 2568: -55,-28 - 2569: -57,-27 - 2570: -57,-25 - 2571: -55,-26 - 2572: -55,-27 - 2573: -54,-22 - 2574: -55,-23 - 2575: -55,-23 - 2576: -56,-22 - 2577: -57,-23 - 2578: -59,-23 - 2579: -59,-23 - 2580: -60,-24 - 2581: -60,-25 - 2582: -61,-26 - 2583: -66,-26 - 2584: -64,-26 - 2585: -63,-26 - 2586: -61,-27 - 2587: -61,-29 - 2588: -60,-29 - 2589: -60,-31 - 2590: -60,-33 - 2591: -61,-33 - 2592: -61,-34 - 2593: -61,-36 - 2594: -61,-38 - 2595: -63,-36 - 2596: -64,-36 - 2597: -65,-36 - 2598: -65,-35 - 2599: -64,-34 - 2600: -63,-34 - 2601: -65,-34 - 2602: -65,-34 - 2603: -64,-35 - 2604: -64,-37 - 2605: -64,-37 - 2606: -64,-38 - 2607: -63,-37 - 2608: -63,-37 - 2609: -63,-38 - 2610: -64,-38 - 2611: -64,-37 - 2612: -65,-37 - 2613: -65,-36 - 2614: -64,-36 - 2615: -63,-36 + 2515: -41,-31 + 2516: -39,-32 + 2517: -38,-33 + 2518: -37,-33 + 2519: -32,-33 + 2520: -39,-38 + 2521: -39,-39 + 2522: -41,-39 + 2523: -31,-37 + 2524: -31,-38 + 2525: -31,-39 + 2526: -27,-41 + 2527: -27,-39 + 2528: -26,-39 + 2529: -23,-40 + 2530: -24,-41 + 2531: -26,-39 + 2532: -23,-39 + 2533: -24,-39 + 2534: -25,-39 + 2535: -25,-38 + 2536: -35,-41 + 2537: -39,-39 + 2538: -39,-37 + 2539: -32,-36 + 2540: -32,-36 + 2541: -39,-36 + 2542: -49,-28 + 2543: -50,-27 + 2544: -52,-27 + 2545: -52,-28 + 2546: -51,-29 + 2547: -50,-29 + 2548: -50,-28 + 2549: -55,-32 + 2550: -56,-31 + 2551: -57,-31 + 2552: -57,-29 + 2553: -56,-29 + 2554: -55,-29 + 2555: -56,-25 + 2556: -55,-28 + 2557: -57,-27 + 2558: -57,-25 + 2559: -55,-26 + 2560: -55,-27 + 2561: -54,-22 + 2562: -55,-23 + 2563: -55,-23 + 2564: -56,-22 + 2565: -57,-23 + 2566: -59,-23 + 2567: -59,-23 + 2568: -60,-24 + 2569: -60,-25 + 2570: -61,-26 + 2571: -66,-26 + 2572: -64,-26 + 2573: -63,-26 + 2574: -61,-27 + 2575: -61,-29 + 2576: -60,-29 + 2577: -60,-31 + 2578: -60,-33 + 2579: -61,-33 + 2580: -61,-34 + 2581: -61,-36 + 2582: -61,-38 + 2583: -63,-36 + 2584: -64,-36 + 2585: -65,-36 + 2586: -65,-35 + 2587: -64,-34 + 2588: -63,-34 + 2589: -65,-34 + 2590: -65,-34 + 2591: -64,-35 + 2592: -64,-37 + 2593: -64,-37 + 2594: -64,-38 + 2595: -63,-37 + 2596: -63,-37 + 2597: -63,-38 + 2598: -64,-38 + 2599: -64,-37 + 2600: -65,-37 + 2601: -65,-36 + 2602: -64,-36 + 2603: -63,-36 + 2604: -64,-35 + 2605: -63,-34 + 2606: -64,-34 + 2607: -63,-34 + 2608: -64,-34 + 2609: -65,-36 + 2610: -65,-37 + 2611: -63,-37 + 2612: -63,-38 + 2613: -65,-35 + 2614: -63,-35 + 2615: -64,-35 2616: -64,-35 - 2617: -63,-34 - 2618: -64,-34 - 2619: -63,-34 - 2620: -64,-34 - 2621: -65,-36 - 2622: -65,-37 - 2623: -63,-37 - 2624: -63,-38 - 2625: -65,-35 - 2626: -63,-35 - 2627: -64,-35 - 2628: -64,-35 - 2629: -63,-35 - 2630: -65,-35 - 2631: -61,-41 - 2632: -62,-41 - 2633: -63,-41 - 2634: -63,-43 - 2635: -63,-44 - 2636: -64,-45 - 2637: -66,-44 - 2638: -66,-44 - 2639: -66,-44 - 2640: -66,-43 - 2641: -59,-41 - 2642: -58,-41 - 2643: -58,-40 - 2644: -58,-39 - 2645: -57,-40 - 2646: -57,-43 - 2647: -59,-43 - 2648: -59,-43 - 2649: -60,-44 - 2650: -61,-44 - 2651: -36,-8 - 2652: -32,-12 - 2653: -37,-15 - 2654: -37,-16 - 2655: -38,-16 - 2656: -38,-16 - 2657: -36,-14 - 2658: -36,-16 - 2659: -37,-14 - 2660: -36,-15 - 2661: -32,-19 - 2662: -36,-19 - 2663: -37,-19 - 2664: -37,-21 - 2665: -35,-21 - 2666: -32,-22 - 2667: -33,-22 - 2668: -35,-23 - 2669: -36,-24 - 2670: -21,-8 - 2671: -20,-9 - 2672: -20,-10 - 2673: -24,-11 - 2674: -24,-13 - 2675: -21,-13 - 2676: -22,-16 - 2677: -24,-16 - 2678: -24,-17 - 2679: -23,-18 - 2680: -22,-18 - 2681: -24,-19 - 2682: -24,-20 - 2683: -23,-21 - 2684: -22,-21 - 2685: -26,-20 - 2686: -25,-18 - 2687: -25,-16 - 2688: -25,-15 - 2689: -21,-13 - 2690: -21,-15 - 2691: -21,-17 - 2692: -21,-18 - 2693: -22,-8 - 2694: -25,-10 - 2695: -25,-12 - 2696: -24,-12 - 2697: -24,-8 - 2698: -21,-10 - 2699: -22,-10 - 2700: -22,-13 - 2701: -8,-8 - 2702: -8,-10 - 2703: -8,-11 - 2704: -8,-13 - 2705: -8,-19 + 2617: -63,-35 + 2618: -65,-35 + 2619: -61,-41 + 2620: -62,-41 + 2621: -63,-41 + 2622: -63,-43 + 2623: -63,-44 + 2624: -64,-45 + 2625: -66,-44 + 2626: -66,-44 + 2627: -66,-44 + 2628: -66,-43 + 2629: -59,-41 + 2630: -58,-41 + 2631: -58,-40 + 2632: -58,-39 + 2633: -57,-40 + 2634: -57,-43 + 2635: -59,-43 + 2636: -59,-43 + 2637: -60,-44 + 2638: -61,-44 + 2639: -36,-8 + 2640: -32,-12 + 2641: -37,-15 + 2642: -37,-16 + 2643: -38,-16 + 2644: -38,-16 + 2645: -36,-14 + 2646: -36,-16 + 2647: -37,-14 + 2648: -36,-15 + 2649: -32,-19 + 2650: -36,-19 + 2651: -37,-19 + 2652: -37,-21 + 2653: -35,-21 + 2654: -32,-22 + 2655: -33,-22 + 2656: -35,-23 + 2657: -36,-24 + 2658: -21,-8 + 2659: -20,-9 + 2660: -20,-10 + 2661: -24,-11 + 2662: -24,-13 + 2663: -21,-13 + 2664: -22,-16 + 2665: -24,-16 + 2666: -24,-17 + 2667: -23,-18 + 2668: -22,-18 + 2669: -24,-19 + 2670: -24,-20 + 2671: -23,-21 + 2672: -22,-21 + 2673: -26,-20 + 2674: -25,-18 + 2675: -25,-16 + 2676: -25,-15 + 2677: -21,-13 + 2678: -21,-15 + 2679: -21,-17 + 2680: -21,-18 + 2681: -22,-8 + 2682: -25,-10 + 2683: -25,-12 + 2684: -24,-12 + 2685: -24,-8 + 2686: -21,-10 + 2687: -22,-10 + 2688: -22,-13 + 2689: -8,-8 + 2690: -8,-10 + 2691: -8,-11 + 2692: -8,-13 + 2693: -8,-19 + 2694: -9,-17 + 2695: -11,-18 + 2696: -11,-18 + 2697: -11,-17 + 2698: -10,-16 + 2699: -8,-16 + 2700: -8,-17 + 2701: -10,-17 + 2702: -9,-18 + 2703: -8,-19 + 2704: -9,-20 + 2705: -8,-18 2706: -9,-17 - 2707: -11,-18 - 2708: -11,-18 - 2709: -11,-17 - 2710: -10,-16 - 2711: -8,-16 - 2712: -8,-17 - 2713: -10,-17 - 2714: -9,-18 - 2715: -8,-19 - 2716: -9,-20 - 2717: -8,-18 - 2718: -9,-17 - 2719: -10,-17 - 2720: -10,-18 - 2721: -9,-17 - 2722: -8,-18 - 2723: -9,-19 - 2724: -9,-19 - 2725: -4,-9 - 2726: -5,-11 - 2727: -4,-10 - 2728: -5,-12 - 2729: -5,-14 - 2730: -7,-25 - 2731: -7,-26 - 2732: -6,-28 - 2733: 18,-35 - 2734: -2,-34 - 2735: 12,-32 - 2736: 11,-32 - 2737: 11,-33 - 2738: 12,-33 - 2739: 13,-32 - 2740: 16,-32 - 2741: 17,-32 - 2742: 16,-32 - 2743: 17,-32 - 2744: 16,-32 - 2745: 17,-32 - 2746: 6,-32 - 2747: 7,-33 - 2748: 8,-32 - 2749: -3,-39 - 2750: -3,-39 - 2751: -2,-40 - 2752: -1,-39 - 2753: -1,-38 - 2754: -2,-33 - 2755: -3,-33 - 2756: -3,-32 - 2757: -2,-32 - 2758: -2,-33 - 2759: -3,-33 - 2760: -3,-32 - 2761: -2,-32 - 2762: 7,-45 - 2763: 7,-46 - 2764: 8,-46 - 2765: 9,-46 - 2766: 9,-45 - 2767: 8,-45 - 2768: 8,-46 - 2769: 9,-45 - 2770: 8,-46 - 2771: 13,-43 - 2772: 12,-43 - 2773: 13,-43 - 2774: 12,-43 - 2775: 11,-45 - 2776: 11,-43 - 2777: 11,-46 - 2778: 13,-45 - 2779: 13,-46 - 2780: 13,-45 - 2781: 13,-46 - 2782: 13,-48 - 2783: 14,-49 - 2784: 14,-50 - 2785: 15,-51 - 2786: 16,-50 - 2787: 17,-49 - 2788: 17,-49 - 2789: 16,-48 - 2790: 14,-48 - 2791: 16,-51 - 2792: 16,-52 - 2793: 20,-58 - 2794: 21,-58 - 2795: 20,-57 - 2796: 19,-56 - 2797: 20,-56 - 2798: 20,-54 - 2799: 19,-54 - 2800: 20,-52 - 2801: 19,-51 - 2802: 20,-50 - 2803: 21,-49 - 2804: 19,-48 - 2805: 21,-46 - 2806: 21,-45 - 2807: 19,-44 - 2808: 21,-46 - 2809: 20,-42 - 2810: 19,-41 - 2811: 21,-40 - 2812: 19,-39 - 2813: 21,-38 - 2814: 20,-37 - 2815: 19,-36 - 2816: 21,-35 - 2817: 19,-34 - 2818: 20,-41 - 2819: 20,-38 - 2820: 20,-38 - 2821: 23,-28 - 2822: 21,-29 - 2823: 20,-29 - 2824: 19,-28 - 2825: 25,-28 - 2826: 28,-28 - 2827: 30,-26 - 2828: 31,-26 - 2829: 18,-25 - 2830: 20,-26 - 2831: 21,-24 - 2832: 20,-21 - 2833: 19,-20 - 2834: 21,-21 - 2835: 18,-22 - 2836: 19,-23 - 2837: 20,-24 - 2838: 17,-24 - 2839: 17,-26 - 2840: 12,-24 - 2841: 13,-26 - 2842: 14,-24 - 2843: 10,-24 - 2844: 9,-25 - 2845: 7,-25 - 2846: 8,-26 - 2847: 6,-24 - 2848: 5,-27 - 2849: 4,-25 - 2850: 2,-26 - 2851: 2,-27 - 2852: -2,-24 - 2853: -3,-26 - 2854: -4,-26 - 2855: -5,-24 - 2856: 2,-24 - 2857: 0,-24 - 2858: 0,-26 - 2859: 2,-26 - 2860: 9,-26 - 2861: 11,-26 - 2862: 15,-24 - 2863: 14,-25 - 2864: 21,-26 - 2865: 20,-21 - 2866: 19,-20 - 2867: 19,-19 - 2868: 19,-18 - 2869: 19,-17 - 2870: 19,-11 - 2871: 20,-11 - 2872: 19,-11 - 2873: 20,-12 - 2874: 19,-11 - 2875: 18,-10 - 2876: 19,-7 - 2877: 19,-6 - 2878: 18,-5 - 2879: 22,-15 - 2880: 23,-15 - 2881: 25,-15 - 2882: 25,-14 - 2883: 25,-13 - 2884: 23,-12 - 2885: 22,-12 - 2886: 25,-12 - 2887: 27,-12 - 2888: 28,-13 - 2889: 30,-13 - 2890: 31,-13 - 2891: 31,-12 - 2892: 31,-11 - 2893: 31,-10 - 2894: 31,-8 - 2895: 31,-8 - 2896: 31,-7 - 2897: 31,-4 - 2898: 33,-4 - 2899: 33,-4 - 2900: 32,-5 - 2901: 30,-16 - 2902: 30,-18 - 2903: 31,-15 - 2904: 31,-16 - 2905: 33,-16 - 2906: 33,-15 - 2907: 32,-16 - 2908: 32,-15 - 2909: 51,9 - 2910: 48,9 - 2911: 45,9 - 2912: 42,9 - 2913: 42,8 - 2914: 38,8 - 2915: 35,24 - 2916: 37,24 - 2917: 35,27 - 2918: 35,28 - 2919: 36,30 - 2920: 31,31 - 2921: 32,32 - 2922: 31,35 - 2923: 32,35 - 2924: 33,36 - 2925: 31,39 - 2926: 31,42 - 2927: 33,41 - 2928: 32,40 - 2929: 32,39 - 2930: 0,53 - 2931: 0,52 - 2932: 0,51 - 2933: 0,49 - 2934: 2,51 - 2935: 0,55 - 2936: 1,55 - 2937: 1,59 - 2938: 2,61 - 2939: 1,61 - 2940: -2,61 - 2941: -2,59 - 2942: -1,56 - 2943: -38,51 - 2944: -42,51 - 2945: -45,48 - 2946: -45,45 - 2947: -41,46 - 2948: -37,46 - 2949: -38,44 - 2950: -42,44 - 2951: -44,43 - 2952: -41,41 - 2953: -36,41 - 2954: -35,41 - 2955: -42,40 - 2956: -46,40 - 2957: -39,40 - 2958: -35,41 - 2959: -39,42 - 2960: -45,43 - 2961: -35,44 - 2962: -34,45 - 2963: -42,45 - 2964: -37,47 - 2965: -34,47 - 2966: -44,48 - 2967: -38,49 - 2968: -35,50 - 2969: -43,50 - 2970: -33,51 - 2971: -36,49 - 2972: -43,48 - 2973: -39,48 - 2974: -33,47 - 2975: -39,46 - 2976: -45,45 - 2977: -39,44 - 2978: -34,43 - 2979: -36,41 - 2980: -41,41 - 2981: -41,41 - 2982: -34,40 - 2983: -36,41 - 2984: -39,41 - 2985: -32,41 - 2986: -32,41 - 2987: -31,44 - 2988: -31,48 - 2989: -31,51 - 2990: -28,45 - 2991: -26,45 - 2992: -28,41 - 2993: -26,41 - 2994: -24,41 - 2995: -23,39 - 3137: 50,-37 - 3138: 53,-37 - 3139: 56,-38 - 3140: 55,-38 - 3141: 54,-39 - 3142: 53,-40 - 3143: 53,-42 - 3144: 51,-45 - 3145: 51,-46 - 3146: 46,-47 - 3147: 46,-46 - 3148: 48,-43 - 3149: 46,-45 - 3150: 45,-46 - 3151: 43,-46 - 3152: 47,-43 - 3153: 52,-46 - 3154: 52,-42 - 3155: 53,-42 - 3156: 50,-42 - 3157: 50,-40 - 3158: 50,-37 - 3159: 52,-36 - 3160: 55,-37 - 3161: 55,-38 - 3162: 53,-40 - 3163: 53,-42 - 3164: 52,-45 - 3165: 50,-45 - 3166: 54,-47 - 3167: 51,-47 - 3168: 46,-47 - 3169: 45,-47 - 3170: 44,-46 - 3171: 44,-44 - 3572: -5,-1 - 4417: 28,54 - 4418: 27,55 - 4419: 27,56 - 4420: 26,56 - 4421: 26,55 - 4422: 26,54 - 4423: 27,54 - 4424: 28,52 - 4425: 27,51 - 4426: 28,53 + 2707: -10,-17 + 2708: -10,-18 + 2709: -9,-17 + 2710: -8,-18 + 2711: -9,-19 + 2712: -9,-19 + 2713: -4,-9 + 2714: -5,-11 + 2715: -4,-10 + 2716: -5,-12 + 2717: -5,-14 + 2718: -7,-25 + 2719: -7,-26 + 2720: -6,-28 + 2721: 18,-35 + 2722: -2,-34 + 2723: 12,-32 + 2724: 11,-32 + 2725: 11,-33 + 2726: 12,-33 + 2727: 13,-32 + 2728: 16,-32 + 2729: 17,-32 + 2730: 16,-32 + 2731: 17,-32 + 2732: 16,-32 + 2733: 17,-32 + 2734: 6,-32 + 2735: 7,-33 + 2736: 8,-32 + 2737: -3,-39 + 2738: -3,-39 + 2739: -2,-40 + 2740: -1,-39 + 2741: -1,-38 + 2742: -2,-33 + 2743: -3,-33 + 2744: -3,-32 + 2745: -2,-32 + 2746: -2,-33 + 2747: -3,-33 + 2748: -3,-32 + 2749: -2,-32 + 2750: 7,-45 + 2751: 7,-46 + 2752: 8,-46 + 2753: 9,-46 + 2754: 9,-45 + 2755: 8,-45 + 2756: 8,-46 + 2757: 9,-45 + 2758: 8,-46 + 2759: 13,-43 + 2760: 12,-43 + 2761: 13,-43 + 2762: 12,-43 + 2763: 11,-45 + 2764: 11,-43 + 2765: 11,-46 + 2766: 13,-45 + 2767: 13,-46 + 2768: 13,-45 + 2769: 13,-46 + 2770: 13,-48 + 2771: 14,-49 + 2772: 14,-50 + 2773: 15,-51 + 2774: 16,-50 + 2775: 17,-49 + 2776: 17,-49 + 2777: 16,-48 + 2778: 14,-48 + 2779: 16,-51 + 2780: 16,-52 + 2781: 20,-58 + 2782: 21,-58 + 2783: 20,-57 + 2784: 19,-56 + 2785: 20,-56 + 2786: 20,-54 + 2787: 19,-54 + 2788: 20,-52 + 2789: 19,-51 + 2790: 20,-50 + 2791: 21,-49 + 2792: 19,-48 + 2793: 21,-46 + 2794: 21,-45 + 2795: 19,-44 + 2796: 21,-46 + 2797: 20,-42 + 2798: 19,-41 + 2799: 21,-40 + 2800: 19,-39 + 2801: 21,-38 + 2802: 20,-37 + 2803: 19,-36 + 2804: 21,-35 + 2805: 19,-34 + 2806: 20,-41 + 2807: 20,-38 + 2808: 20,-38 + 2809: 23,-28 + 2810: 21,-29 + 2811: 20,-29 + 2812: 19,-28 + 2813: 25,-28 + 2814: 28,-28 + 2815: 30,-26 + 2816: 31,-26 + 2817: 18,-25 + 2818: 20,-26 + 2819: 21,-24 + 2820: 20,-21 + 2821: 19,-20 + 2822: 21,-21 + 2823: 18,-22 + 2824: 19,-23 + 2825: 20,-24 + 2826: 17,-24 + 2827: 17,-26 + 2828: 12,-24 + 2829: 13,-26 + 2830: 14,-24 + 2831: 10,-24 + 2832: 9,-25 + 2833: 7,-25 + 2834: 8,-26 + 2835: 6,-24 + 2836: 5,-27 + 2837: 4,-25 + 2838: 2,-26 + 2839: 2,-27 + 2840: -2,-24 + 2841: -3,-26 + 2842: -4,-26 + 2843: -5,-24 + 2844: 2,-24 + 2845: 0,-24 + 2846: 0,-26 + 2847: 2,-26 + 2848: 9,-26 + 2849: 11,-26 + 2850: 15,-24 + 2851: 14,-25 + 2852: 21,-26 + 2853: 20,-21 + 2854: 19,-20 + 2855: 19,-19 + 2856: 19,-18 + 2857: 19,-17 + 2858: 19,-11 + 2859: 20,-11 + 2860: 19,-11 + 2861: 20,-12 + 2862: 19,-11 + 2863: 18,-10 + 2864: 19,-7 + 2865: 19,-6 + 2866: 18,-5 + 2867: 22,-15 + 2868: 23,-15 + 2869: 25,-15 + 2870: 25,-14 + 2871: 25,-13 + 2872: 23,-12 + 2873: 22,-12 + 2874: 25,-12 + 2875: 27,-12 + 2876: 28,-13 + 2877: 30,-13 + 2878: 31,-13 + 2879: 31,-12 + 2880: 31,-11 + 2881: 31,-10 + 2882: 31,-8 + 2883: 31,-8 + 2884: 31,-7 + 2885: 31,-4 + 2886: 33,-4 + 2887: 33,-4 + 2888: 32,-5 + 2889: 30,-16 + 2890: 30,-18 + 2891: 31,-15 + 2892: 31,-16 + 2893: 33,-16 + 2894: 33,-15 + 2895: 32,-16 + 2896: 32,-15 + 2897: 51,9 + 2898: 48,9 + 2899: 45,9 + 2900: 42,9 + 2901: 42,8 + 2902: 38,8 + 2903: 35,24 + 2904: 37,24 + 2905: 35,27 + 2906: 35,28 + 2907: 36,30 + 2908: 31,31 + 2909: 32,32 + 2910: 31,35 + 2911: 32,35 + 2912: 33,36 + 2913: 31,39 + 2914: 31,42 + 2915: 33,41 + 2916: 32,40 + 2917: 32,39 + 2918: 0,53 + 2919: 0,52 + 2920: 0,51 + 2921: 0,49 + 2922: 2,51 + 2923: 0,55 + 2924: 1,55 + 2925: 1,59 + 2926: 2,61 + 2927: 1,61 + 2928: -2,61 + 2929: -2,59 + 2930: -1,56 + 2931: -38,51 + 2932: -42,51 + 2933: -45,48 + 2934: -45,45 + 2935: -41,46 + 2936: -37,46 + 2937: -38,44 + 2938: -42,44 + 2939: -44,43 + 2940: -41,41 + 2941: -36,41 + 2942: -35,41 + 2943: -42,40 + 2944: -46,40 + 2945: -39,40 + 2946: -35,41 + 2947: -39,42 + 2948: -45,43 + 2949: -35,44 + 2950: -34,45 + 2951: -42,45 + 2952: -37,47 + 2953: -34,47 + 2954: -44,48 + 2955: -38,49 + 2956: -35,50 + 2957: -43,50 + 2958: -33,51 + 2959: -36,49 + 2960: -43,48 + 2961: -39,48 + 2962: -33,47 + 2963: -39,46 + 2964: -45,45 + 2965: -39,44 + 2966: -34,43 + 2967: -36,41 + 2968: -41,41 + 2969: -41,41 + 2970: -34,40 + 2971: -36,41 + 2972: -39,41 + 2973: -32,41 + 2974: -32,41 + 2975: -31,44 + 2976: -31,48 + 2977: -31,51 + 2978: -28,45 + 2979: -26,45 + 2980: -28,41 + 2981: -26,41 + 2982: -24,41 + 2983: -23,39 + 3124: 50,-37 + 3125: 53,-37 + 3126: 56,-38 + 3127: 55,-38 + 3128: 54,-39 + 3129: 53,-40 + 3130: 53,-42 + 3131: 51,-45 + 3132: 51,-46 + 3133: 46,-47 + 3134: 46,-46 + 3135: 48,-43 + 3136: 46,-45 + 3137: 45,-46 + 3138: 43,-46 + 3139: 47,-43 + 3140: 52,-46 + 3141: 52,-42 + 3142: 53,-42 + 3143: 50,-42 + 3144: 50,-40 + 3145: 50,-37 + 3146: 52,-36 + 3147: 55,-37 + 3148: 55,-38 + 3149: 53,-40 + 3150: 53,-42 + 3151: 52,-45 + 3152: 50,-45 + 3153: 54,-47 + 3154: 51,-47 + 3155: 46,-47 + 3156: 45,-47 + 3157: 44,-46 + 3158: 44,-44 + 3559: -5,-1 + 4404: 28,54 + 4405: 27,55 + 4406: 27,56 + 4407: 26,56 + 4408: 26,55 + 4409: 26,54 + 4410: 27,54 + 4411: 28,52 + 4412: 27,51 + 4413: 28,53 - node: cleanable: True color: '#FFFFFFFF' id: Dirt decals: - 3291: -65,-33 + 3278: -65,-33 - node: cleanable: True color: '#835432B7' id: DirtHeavy decals: - 4547: -28,-13 - 4548: -31,-11 - 4549: -30,-11 - 4550: -37,-10 - 4551: -37,-8 - 4552: -39,-8 - 4553: -38,-12 - 4554: -38,-11 - 4555: -36,-11 - 4556: -34,-15 - 4557: -34,-16 - 4558: -33,-15 - 4559: -32,-16 - 4560: -31,-16 - 4561: -31,-15 - 4562: -30,-15 + 4534: -28,-13 + 4535: -31,-11 + 4536: -30,-11 + 4537: -37,-10 + 4538: -37,-8 + 4539: -39,-8 + 4540: -38,-12 + 4541: -38,-11 + 4542: -36,-11 + 4543: -34,-15 + 4544: -34,-16 + 4545: -33,-15 + 4546: -32,-16 + 4547: -31,-16 + 4548: -31,-15 + 4549: -30,-15 - node: cleanable: True color: '#A4610696' id: DirtHeavy decals: - 2996: -20,45 - 2997: -20,52 - 2998: -21,35 - 2999: -19,37 - 3000: -19,35 - 3001: -20,35 - 3002: -11,40 - 3003: -10,44 - 3004: -10,48 - 3005: -15,48 - 3006: -5,43 - 3007: -2,50 - 3008: 5,50 - 3009: 12,50 - 3010: 15,55 - 3011: 18,58 - 3012: 19,63 - 3013: 23,67 - 3014: 33,47 - 3015: 31,40 - 3016: 26,35 - 3017: 33,31 - 3018: 32,25 - 3019: 31,22 - 3020: 36,23 - 3021: 37,27 - 3022: 42,30 - 3023: 43,27 - 3024: 44,21 - 3025: 42,16 - 3026: 41,13 - 3027: 43,15 - 3028: 44,19 - 3029: 32,8 - 3030: 27,7 - 3031: 40,3 - 3032: 46,3 - 3033: 56,3 - 3034: 64,3 - 3035: 70,3 - 3036: 73,3 - 3037: 83,3 - 3038: 83,10 - 3039: 76,9 - 3040: 80,6 - 3041: 53,-2 - 3042: 46,-16 - 3044: 35,-6 - 3045: 32,-4 - 3046: 26,-5 - 3047: 21,-4 - 3048: 12,-4 - 3049: -5,-4 - 3050: -34,-4 - 3051: -41,-5 - 3052: -46,-33 - 3053: -36,-33 - 3054: -32,-36 - 3055: -39,-39 - 3056: -29,-38 - 3057: -26,-39 - 3058: -24,-35 - 3059: -26,-30 - 3060: -23,-26 - 3061: -17,-26 - 3062: -8,-27 - 3063: -5,-31 - 3064: -6,-37 - 3065: -6,-43 - 3066: -6,-48 - 3067: -6,-53 - 3068: -5,-57 - 3069: 5,-53 - 3070: 3,-53 - 3071: 6,-52 - 3072: 5,-52 - 3073: 4,-52 - 3074: 5,-53 - 3075: 6,-53 - 3076: 28,-27 - 3077: -8,-1 - 3078: -31,-4 - 3079: -25,-17 - 3080: -26,1 - 3081: -23,13 - 3082: -21,19 - 3083: -17,20 - 3084: -13,20 - 3085: -18,14 - 3086: -13,14 - 3087: -23,26 - 3088: -23,30 - 3089: -31,30 - 3090: -42,29 - 3091: -50,30 - 3092: -50,29 - 3093: -56,29 - 3094: -58,35 - 3095: -57,44 - 3096: -58,49 - 3097: -64,43 - 3098: -63,38 - 3099: -52,31 - 3100: -40,29 - 3101: -29,30 - 3102: -22,30 - 3103: -21,32 - 3104: -20,37 - 3105: -20,42 - 3106: -19,51 - 3107: -25,54 - 3108: -27,53 - 3109: -11,47 - 3110: -9,45 - 3111: -5,47 - 3112: 4,50 - 3113: 7,49 - 3114: 16,49 - 3115: 23,50 - 3116: 26,50 - 3117: 19,54 - 3118: 19,63 - 3119: 23,68 - 3120: 32,43 - 3121: 32,36 - 3122: 32,29 - 3123: 32,22 - 3124: 32,19 - 3125: 33,9 - 3126: 33,20 - 3127: 31,26 - 3128: 33,35 - 3129: 15,30 - 3130: 8,30 - 3131: 0,30 - 3132: -8,9 - 3133: -4,10 - 3134: 20,15 - 3135: 21,9 - 3136: 29,4 - 3172: 52,-43 - 3173: 50,-47 - 3174: 45,-46 - 3175: 46,-43 - 3176: 52,-40 - 3177: 55,-37 - 3178: 55,-38 - 3179: 47,-45 - 3180: 44,-47 - 3181: 54,-47 - 3182: 53,-47 - 4427: 27,55 - 4428: 28,52 + 2984: -20,45 + 2985: -20,52 + 2986: -21,35 + 2987: -19,37 + 2988: -19,35 + 2989: -20,35 + 2990: -11,40 + 2991: -10,44 + 2992: -10,48 + 2993: -15,48 + 2994: -5,43 + 2995: -2,50 + 2996: 5,50 + 2997: 12,50 + 2998: 15,55 + 2999: 18,58 + 3000: 19,63 + 3001: 23,67 + 3002: 33,47 + 3003: 31,40 + 3004: 26,35 + 3005: 33,31 + 3006: 32,25 + 3007: 31,22 + 3008: 36,23 + 3009: 37,27 + 3010: 42,30 + 3011: 43,27 + 3012: 44,21 + 3013: 42,16 + 3014: 41,13 + 3015: 43,15 + 3016: 44,19 + 3017: 32,8 + 3018: 27,7 + 3019: 40,3 + 3020: 46,3 + 3021: 56,3 + 3022: 64,3 + 3023: 70,3 + 3024: 73,3 + 3025: 83,3 + 3026: 83,10 + 3027: 76,9 + 3028: 80,6 + 3029: 53,-2 + 3030: 46,-16 + 3031: 35,-6 + 3032: 32,-4 + 3033: 26,-5 + 3034: 21,-4 + 3035: 12,-4 + 3036: -5,-4 + 3037: -34,-4 + 3038: -41,-5 + 3039: -46,-33 + 3040: -36,-33 + 3041: -32,-36 + 3042: -39,-39 + 3043: -29,-38 + 3044: -26,-39 + 3045: -24,-35 + 3046: -26,-30 + 3047: -23,-26 + 3048: -17,-26 + 3049: -8,-27 + 3050: -5,-31 + 3051: -6,-37 + 3052: -6,-43 + 3053: -6,-48 + 3054: -6,-53 + 3055: -5,-57 + 3056: 5,-53 + 3057: 3,-53 + 3058: 6,-52 + 3059: 5,-52 + 3060: 4,-52 + 3061: 5,-53 + 3062: 6,-53 + 3063: 28,-27 + 3064: -8,-1 + 3065: -31,-4 + 3066: -25,-17 + 3067: -26,1 + 3068: -23,13 + 3069: -21,19 + 3070: -17,20 + 3071: -13,20 + 3072: -18,14 + 3073: -13,14 + 3074: -23,26 + 3075: -23,30 + 3076: -31,30 + 3077: -42,29 + 3078: -50,30 + 3079: -50,29 + 3080: -56,29 + 3081: -58,35 + 3082: -57,44 + 3083: -58,49 + 3084: -64,43 + 3085: -63,38 + 3086: -52,31 + 3087: -40,29 + 3088: -29,30 + 3089: -22,30 + 3090: -21,32 + 3091: -20,37 + 3092: -20,42 + 3093: -19,51 + 3094: -25,54 + 3095: -27,53 + 3096: -11,47 + 3097: -9,45 + 3098: -5,47 + 3099: 4,50 + 3100: 7,49 + 3101: 16,49 + 3102: 23,50 + 3103: 26,50 + 3104: 19,54 + 3105: 19,63 + 3106: 23,68 + 3107: 32,43 + 3108: 32,36 + 3109: 32,29 + 3110: 32,22 + 3111: 32,19 + 3112: 33,9 + 3113: 33,20 + 3114: 31,26 + 3115: 33,35 + 3116: 15,30 + 3117: 8,30 + 3118: 0,30 + 3119: -8,9 + 3120: -4,10 + 3121: 20,15 + 3122: 21,9 + 3123: 29,4 + 3159: 52,-43 + 3160: 50,-47 + 3161: 45,-46 + 3162: 46,-43 + 3163: 52,-40 + 3164: 55,-37 + 3165: 55,-38 + 3166: 47,-45 + 3167: 44,-47 + 3168: 54,-47 + 3169: 53,-47 + 4414: 27,55 + 4415: 28,52 - node: cleanable: True color: '#8354328B' id: DirtLight decals: - 4605: -33,-8 - 4606: -32,-8 - 4607: -30,-7 - 4608: -29,-8 + 4592: -33,-8 + 4593: -32,-8 + 4594: -30,-7 + 4595: -29,-8 - node: cleanable: True color: '#FFFFFFFF' id: DirtLight decals: - 3288: -65,-33 - 3289: -64,-33 - 3290: -63,-33 + 3275: -65,-33 + 3276: -64,-33 + 3277: -63,-33 - node: cleanable: True color: '#8354328B' id: DirtMedium decals: - 4609: -28,-8 - 4610: -28,-9 - 4611: -30,-9 + 4596: -28,-8 + 4597: -28,-9 + 4598: -30,-9 - node: cleanable: True color: '#835432B7' id: DirtMedium decals: - 4563: -31,-15 - 4564: -29,-15 - 4565: -28,-14 - 4566: -30,-11 - 4567: -32,-11 - 4568: -38,-13 - 4569: -38,-11 - 4570: -39,-8 - 4571: -28,-12 + 4550: -31,-15 + 4551: -29,-15 + 4552: -28,-14 + 4553: -30,-11 + 4554: -32,-11 + 4555: -38,-13 + 4556: -38,-11 + 4557: -39,-8 + 4558: -28,-12 - node: color: '#9FED58B7' id: FlowersBROne decals: - 4771: -2.6908832,47.53326 + 4758: -2.6908832,47.53326 - node: color: '#9FED5873' id: Flowersbr1 decals: - 3315: 78.72238,7.9556513 - 3316: 79.69461,7.9278736 + 3302: 78.72238,7.9556513 + 3303: 79.69461,7.9278736 - node: color: '#FFFFFFE3' id: Flowersbr1 decals: - 4486: -19.119284,3.6234694 - 4487: -19.829224,1.4664211 + 4473: -19.119284,3.6234694 + 4474: -19.829224,1.4664211 - node: color: '#FFFFFFFF' id: Flowersbr1 decals: - 3355: -17.368574,-37.531387 + 3342: -17.368574,-37.531387 - node: color: '#FFFFFFE3' id: Flowersbr2 decals: - 4488: -19.900217,3.027443 - 4489: -19.005693,2.0766392 + 4475: -19.900217,3.027443 + 4476: -19.005693,2.0766392 - node: color: '#FFFFFFFF' id: Flowersbr2 decals: - 3358: -15.424128,-36.586945 + 3345: -15.424128,-36.586945 - node: color: '#9FED58B7' id: Flowersbr3 decals: - 4770: -1.1716373,46.099934 + 4757: -1.1716373,46.099934 - node: color: '#FFFFFFE3' id: Flowersbr3 decals: - 4490: -19.886019,-0.0094537735 - 4491: -18.82111,0.8136306 + 4477: -19.886019,-0.0094537735 + 4478: -18.82111,0.8136306 - node: color: '#FFFFFFFF' id: Flowersbr3 decals: - 3359: -16.14635,-36.989723 - 3385: -60.04891,40.960167 - 3386: -60.00724,39.210167 - 3387: -60.02113,42.890724 + 3346: -16.14635,-36.989723 + 3372: -60.04891,40.960167 + 3373: -60.00724,39.210167 + 3374: -60.02113,42.890724 - node: color: '#9FED58B7' id: Flowerspv1 decals: - 4769: -2.7477016,46.156727 - 4772: -2.7050896,47.10753 - 4773: -1.4556177,45.858692 + 4756: -2.7477016,46.156727 + 4759: -2.7050896,47.10753 + 4760: -1.4556177,45.858692 - node: color: '#A4DF8296' id: Flowerspv1 decals: - 1702: -7.423552,-22.998676 - 1703: -8.506886,-23.19312 - 1704: -8.8402195,-23.776455 - 1705: -7.2846637,-23.80423 - 1706: -7.3957734,-22.05423 + 1691: -7.423552,-22.998676 + 1692: -8.506886,-23.19312 + 1693: -8.8402195,-23.776455 + 1694: -7.2846637,-23.80423 + 1695: -7.3957734,-22.05423 - node: color: '#FFFFFFE3' id: Flowerspv1 decals: - 4493: -19.928616,2.0766392 + 4480: -19.928616,2.0766392 - node: color: '#9FED5896' id: Flowerspv2 decals: - 3221: -40.505478,-22.24596 - 3222: -40.186035,-23.329292 - 3223: -41.505478,-22.968182 + 3208: -40.505478,-22.24596 + 3209: -40.186035,-23.329292 + 3210: -41.505478,-22.968182 - node: color: '#FFFFFFE3' id: Flowerspv2 decals: - 4492: -19.04829,0.0047369003 - 4494: -18.877905,2.8429594 - 4497: -18.82111,1.3387012 - 4502: -20.028008,-0.22232056 + 4479: -19.04829,0.0047369003 + 4481: -18.877905,2.8429594 + 4484: -18.82111,1.3387012 + 4489: -20.028008,-0.22232056 - node: color: '#FFFFFFFF' id: Flowerspv2 decals: - 3356: -15.688017,-37.836945 + 3343: -15.688017,-37.836945 - node: color: '#9FED5896' id: Flowerspv3 decals: - 3224: -43.172146,-21.537628 - 3225: -40.94992,-18.676516 - 3226: -40.061035,-18.162628 - 3227: -40.436035,-19.176516 - 3228: -43.061035,-17.85707 - 3229: -43.158257,-19.662628 - 3230: -40.99159,-23.49596 + 3211: -43.172146,-21.537628 + 3212: -40.94992,-18.676516 + 3213: -40.061035,-18.162628 + 3214: -40.436035,-19.176516 + 3215: -43.061035,-17.85707 + 3216: -43.158257,-19.662628 + 3217: -40.99159,-23.49596 - node: color: '#FFFFFFE3' id: Flowerspv3 decals: - 4495: -20.0848,3.8505278 - 4496: -19.786627,0.6575284 + 4482: -20.0848,3.8505278 + 4483: -19.786627,0.6575284 - node: color: '#FFFFFFFF' id: Flowerspv3 decals: - 3357: -17.27135,-36.48972 - 3382: -60.00724,38.321278 - 3383: -59.965576,40.001835 - 3384: -59.965576,41.821278 + 3344: -17.27135,-36.48972 + 3369: -60.00724,38.321278 + 3370: -59.965576,40.001835 + 3371: -59.965576,41.821278 - node: color: '#60E25873' id: Flowersy1 decals: - 3374: -60.062798,38.779613 - 3375: -59.965576,40.112946 - 3376: -59.97946,41.404613 + 3361: -60.062798,38.779613 + 3362: -59.965576,40.112946 + 3363: -59.97946,41.404613 - node: color: '#9FED5896' id: Flowersy1 decals: - 3217: -42.811035,-21.551517 - 3218: -42.99159,-18.176516 - 3219: -40.811035,-22.218182 - 3220: -42.894367,-22.87096 + 3204: -42.811035,-21.551517 + 3205: -42.99159,-18.176516 + 3206: -40.811035,-22.218182 + 3207: -42.894367,-22.87096 - node: color: '#A4DF8296' id: Flowersy1 decals: - 1699: -7.4791064,-22.526455 - 1700: -9.145773,-22.720898 - 1701: -8.673552,-23.748676 + 1688: -7.4791064,-22.526455 + 1689: -9.145773,-22.720898 + 1690: -8.673552,-23.748676 - node: color: '#FFFFFFE3' id: Flowersy1 decals: - 4498: -19.005693,3.8079538 + 4485: -19.005693,3.8079538 - node: color: '#FFFFFFE3' id: Flowersy2 decals: - 4499: -19.729832,2.999061 + 4486: -19.729832,2.999061 - node: color: '#9FED5896' id: Flowersy3 decals: - 3215: -41.672146,-22.10707 - 3216: -40.172146,-23.204292 + 3202: -41.672146,-22.10707 + 3203: -40.172146,-23.204292 - node: color: '#FFFFFFE3' id: Flowersy3 decals: - 4500: -19.332266,2.1475945 + 4487: -19.332266,2.1475945 - node: color: '#60E25873' id: Flowersy4 decals: - 3369: -59.937798,42.696278 - 3370: -59.99335,41.751835 - 3371: -60.00724,40.571278 - 3372: -60.062798,39.418503 - 3373: -59.965576,38.085167 + 3356: -59.937798,42.696278 + 3357: -59.99335,41.751835 + 3358: -60.00724,40.571278 + 3359: -60.062798,39.418503 + 3360: -59.965576,38.085167 - node: color: '#9FED5896' id: Flowersy4 decals: - 3212: -40.24159,-18.343182 - 3213: -41.172146,-18.63485 - 3214: -40.283257,-19.10707 + 3199: -40.24159,-18.343182 + 3200: -41.172146,-18.63485 + 3201: -40.283257,-19.10707 - node: color: '#FFFFFFE3' id: Flowersy4 decals: - 4501: -19.687237,1.0832615 + 4488: -19.687237,1.0832615 - node: color: '#D4D4D428' id: FullTileOverlayGreyscale decals: - 4804: 86,-2 - 4805: 85,-2 - 4806: 85,1 - 4807: 86,1 - 4808: 73,1 - 4809: 72,1 - 4810: 72,-2 - 4811: 73,-2 + 4791: 86,-2 + 4792: 85,-2 + 4793: 85,1 + 4794: 86,1 + 4795: 73,1 + 4796: 72,1 + 4797: 72,-2 + 4798: 73,-2 - node: color: '#A4DF8296' id: Grassa4 decals: - 1683: -7.8109317,-1.9877326 + 1672: -7.8109317,-1.9877326 - node: color: '#FFFFFF85' id: Grassd3 decals: - 4476: -19.488453,1.96311 - 4477: -18.70752,2.7436213 - 4478: -18.892103,0.898777 - 4479: -19.829224,-0.023644924 - 4480: -20.0848,2.4456081 - 4481: -20.311981,-0.37842274 + 4463: -19.488453,1.96311 + 4464: -18.70752,2.7436213 + 4465: -18.892103,0.898777 + 4466: -19.829224,-0.023644924 + 4467: -20.0848,2.4456081 + 4468: -20.311981,-0.37842274 - node: color: '#60E25873' id: Grasse1 decals: - 3360: -17.39635,-36.50361 - 3361: -15.813017,-36.434166 - 3362: -15.2157955,-36.545277 - 3363: -15.729685,-37.656387 - 3364: -17.590796,-37.531387 - 3365: -16.063017,-36.961945 - 3366: -15.674128,-37.948055 - 3367: -14.951906,-37.128613 - 3368: -15.229685,-38.073055 + 3347: -17.39635,-36.50361 + 3348: -15.813017,-36.434166 + 3349: -15.2157955,-36.545277 + 3350: -15.729685,-37.656387 + 3351: -17.590796,-37.531387 + 3352: -16.063017,-36.961945 + 3353: -15.674128,-37.948055 + 3354: -14.951906,-37.128613 + 3355: -15.229685,-38.073055 - node: color: '#FFFFFF85' id: Grasse1 decals: - 4482: -20.269386,0.16083956 - 4483: -18.792713,3.3112655 - 4484: -19.147682,2.431417 - 4485: -18.806911,4.205305 + 4469: -20.269386,0.16083956 + 4470: -18.792713,3.3112655 + 4471: -19.147682,2.431417 + 4472: -18.806911,4.205305 - node: color: '#60FF5D92' id: Grasse2 decals: - 4503: -20.0848,0.047310352 - 4504: -19.729832,0.99811506 - 4505: -18.906303,2.4172258 - 4506: -18.9347,3.7937632 - 4507: -19.985409,4.077585 - 4508: -20.028008,2.6726656 - 4509: -19.062489,1.1967907 - 4510: -19.957012,0.88458633 + 4490: -20.0848,0.047310352 + 4491: -19.729832,0.99811506 + 4492: -18.906303,2.4172258 + 4493: -18.9347,3.7937632 + 4494: -19.985409,4.077585 + 4495: -20.028008,2.6726656 + 4496: -19.062489,1.1967907 + 4497: -19.957012,0.88458633 - node: color: '#FFFFFF85' id: Grasse2 decals: - 4473: -19.034092,3.6092787 - 4474: -19.729832,3.0700169 - 4475: -20.0848,2.1475945 + 4460: -19.034092,3.6092787 + 4461: -19.729832,3.0700169 + 4462: -20.0848,2.1475945 - node: color: '#334E6DC8' id: HalfTileOverlayGreyscale decals: - 1224: -62,55 - 1225: -61,55 - 1226: -60,55 - 1227: -59,55 - 1228: -58,55 + 1214: -62,55 + 1215: -61,55 + 1216: -60,55 + 1217: -59,55 + 1218: -58,55 - node: color: '#52B4E996' id: HalfTileOverlayGreyscale @@ -4363,140 +4363,140 @@ entities: 297: -32,-42 298: -31,-42 299: -30,-42 - 503: -41,-38 - 4886: -35,-42 - 4887: -34,-42 - 4888: -33,-42 + 493: -41,-38 + 4873: -35,-42 + 4874: -34,-42 + 4875: -33,-42 - node: color: '#A4610696' id: HalfTileOverlayGreyscale decals: - 1039: 35,30 - 1040: 36,30 - 1041: 37,30 - 1048: 39,24 - 1049: 40,24 - 1050: 41,24 - 1051: 42,30 - 1052: 43,30 - 1053: 46,30 - 1054: 47,30 - 1061: 44,30 - 1062: 45,30 - 1507: 35,34 - 1508: 36,34 - 1509: 37,34 - 1510: 38,34 - 1511: 39,34 - 1512: 40,34 - 1513: 41,34 - 1514: 42,37 - 1515: 43,37 - 1516: 44,37 - 1517: 45,37 - 1518: 46,37 - 1519: 47,37 + 1029: 35,30 + 1030: 36,30 + 1031: 37,30 + 1038: 39,24 + 1039: 40,24 + 1040: 41,24 + 1041: 42,30 + 1042: 43,30 + 1043: 46,30 + 1044: 47,30 + 1051: 44,30 + 1052: 45,30 + 1497: 35,34 + 1498: 36,34 + 1499: 37,34 + 1500: 38,34 + 1501: 39,34 + 1502: 40,34 + 1503: 41,34 + 1504: 42,37 + 1505: 43,37 + 1506: 44,37 + 1507: 45,37 + 1508: 46,37 + 1509: 47,37 - node: color: '#D4D4D419' id: HalfTileOverlayGreyscale decals: - 1239: -54,31 - 1240: -53,31 - 1241: -52,31 - 1242: -51,31 - 1243: -50,31 - 1244: -49,31 - 1245: -48,31 - 1246: -47,31 - 1247: -46,31 - 1248: -45,31 - 1249: -44,31 - 1250: -43,31 - 1251: -42,31 - 1252: -41,31 - 1253: -40,31 - 1254: -39,31 - 1255: -38,31 - 1256: -37,31 - 1257: -36,31 - 1258: -35,31 - 1314: 17,31 - 1315: 16,31 - 1316: 15,31 - 1317: 14,31 - 1318: 13,31 - 1319: 12,31 - 1320: 11,31 - 1321: 9,31 - 1322: 8,31 - 1323: 7,31 - 1324: 5,31 - 1325: 4,31 - 1326: 3,31 - 1327: 2,31 - 1328: 1,31 - 1329: 0,31 - 1330: -1,31 - 1331: -2,31 - 1332: -3,31 + 1229: -54,31 + 1230: -53,31 + 1231: -52,31 + 1232: -51,31 + 1233: -50,31 + 1234: -49,31 + 1235: -48,31 + 1236: -47,31 + 1237: -46,31 + 1238: -45,31 + 1239: -44,31 + 1240: -43,31 + 1241: -42,31 + 1242: -41,31 + 1243: -40,31 + 1244: -39,31 + 1245: -38,31 + 1246: -37,31 + 1247: -36,31 + 1248: -35,31 + 1304: 17,31 + 1305: 16,31 + 1306: 15,31 + 1307: 14,31 + 1308: 13,31 + 1309: 12,31 + 1310: 11,31 + 1311: 9,31 + 1312: 8,31 + 1313: 7,31 + 1314: 5,31 + 1315: 4,31 + 1316: 3,31 + 1317: 2,31 + 1318: 1,31 + 1319: 0,31 + 1320: -1,31 + 1321: -2,31 + 1322: -3,31 - node: color: '#D4D4D433' id: HalfTileOverlayGreyscale decals: - 770: -11,-25 - 771: -10,-25 - 772: -9,-25 - 773: -8,-25 - 774: -7,-25 - 809: -16,-3 - 810: -14,-3 - 811: -12,-3 - 812: -11,-3 - 817: 17,-3 - 818: 18,-3 - 819: 20,-3 - 820: 21,-3 - 821: 23,-3 - 822: 24,-3 - 823: 25,-3 - 824: 26,-3 - 863: 22,-31 - 864: 23,-31 - 865: 24,-31 - 899: 35,4 - 900: 36,4 - 901: 37,4 - 902: 38,4 - 903: 39,4 - 904: 40,4 - 905: 41,4 - 906: 42,4 - 907: 43,4 - 908: 44,4 - 909: 45,4 - 910: 46,4 - 911: 47,4 - 912: 48,4 - 913: 49,4 - 914: 50,4 - 915: 51,4 - 916: 52,4 - 917: 53,4 - 918: 55,4 - 919: 56,4 - 920: 57,4 - 921: 58,4 - 922: 59,4 - 923: 60,4 - 924: 61,4 - 925: 62,4 - 926: 63,4 - 927: 64,4 - 928: 65,4 - 929: 66,4 - 930: 67,4 - 931: 68,4 - 932: 69,4 + 760: -11,-25 + 761: -10,-25 + 762: -9,-25 + 763: -8,-25 + 764: -7,-25 + 799: -16,-3 + 800: -14,-3 + 801: -12,-3 + 802: -11,-3 + 807: 17,-3 + 808: 18,-3 + 809: 20,-3 + 810: 21,-3 + 811: 23,-3 + 812: 24,-3 + 813: 25,-3 + 814: 26,-3 + 853: 22,-31 + 854: 23,-31 + 855: 24,-31 + 889: 35,4 + 890: 36,4 + 891: 37,4 + 892: 38,4 + 893: 39,4 + 894: 40,4 + 895: 41,4 + 896: 42,4 + 897: 43,4 + 898: 44,4 + 899: 45,4 + 900: 46,4 + 901: 47,4 + 902: 48,4 + 903: 49,4 + 904: 50,4 + 905: 51,4 + 906: 52,4 + 907: 53,4 + 908: 55,4 + 909: 56,4 + 910: 57,4 + 911: 58,4 + 912: 59,4 + 913: 60,4 + 914: 61,4 + 915: 62,4 + 916: 63,4 + 917: 64,4 + 918: 65,4 + 919: 66,4 + 920: 67,4 + 921: 68,4 + 922: 69,4 - node: color: '#DE3A3A96' id: HalfTileOverlayGreyscale @@ -4515,45 +4515,45 @@ entities: 344: 44,-3 345: 45,-3 346: 46,-3 - 391: 34,-7 - 504: -32,27 - 505: -31,27 - 506: -30,27 - 507: -28,27 - 508: -27,27 - 509: -26,27 - 519: -29,26 - 1208: -64,51 - 1209: -63,51 - 1210: -61,51 - 1463: 36,51 - 1464: 37,51 - 1602: 60,-19 - 1603: 61,-19 - 1604: 62,-19 + 383: 34,-7 + 494: -32,27 + 495: -31,27 + 496: -30,27 + 497: -28,27 + 498: -27,27 + 499: -26,27 + 509: -29,26 + 1198: -64,51 + 1199: -63,51 + 1200: -61,51 + 1453: 36,51 + 1454: 37,51 + 1592: 60,-19 + 1593: 61,-19 + 1594: 62,-19 - node: color: '#EFB34196' id: HalfTileOverlayGreyscale decals: - 603: -18,45 - 604: -17,45 - 605: -16,45 - 606: -15,45 - 607: -14,45 - 608: -13,45 - 609: -12,45 - 610: -11,45 - 611: -10,45 + 593: -18,45 + 594: -17,45 + 595: -16,45 + 596: -15,45 + 597: -14,45 + 598: -13,45 + 599: -12,45 + 600: -11,45 + 601: -10,45 - node: color: '#0E7F1BFF' id: HalfTileOverlayGreyscale180 decals: - 4983: 43,-17 + 4961: 43,-17 - node: color: '#1861D5FF' id: HalfTileOverlayGreyscale180 decals: - 4981: 37,-17 + 4959: 37,-17 - node: color: '#334E6DC8' id: HalfTileOverlayGreyscale180 @@ -4591,193 +4591,193 @@ entities: 305: -49,-33 306: -51,-33 307: -53,-33 - 1498: -43,-33 - 4883: -33,-45 - 4884: -34,-45 - 4885: -35,-45 + 1488: -43,-33 + 4870: -33,-45 + 4871: -34,-45 + 4872: -35,-45 - node: color: '#951710FF' id: HalfTileOverlayGreyscale180 decals: - 4982: 40,-17 + 4960: 40,-17 - node: color: '#A4610696' id: HalfTileOverlayGreyscale180 decals: - 1036: 35,23 - 1037: 36,23 - 1038: 37,23 - 1055: 47,26 - 1056: 46,26 - 1520: 44,32 - 1521: 45,32 - 1522: 43,32 - 1523: 42,32 - 1524: 41,32 - 1525: 40,32 - 1526: 39,32 - 1527: 38,32 - 1528: 37,32 - 1529: 36,32 - 1530: 35,32 - 1531: 46,32 - 1532: 47,32 + 1026: 35,23 + 1027: 36,23 + 1028: 37,23 + 1045: 47,26 + 1046: 46,26 + 1510: 44,32 + 1511: 45,32 + 1512: 43,32 + 1513: 42,32 + 1514: 41,32 + 1515: 40,32 + 1516: 39,32 + 1517: 38,32 + 1518: 37,32 + 1519: 36,32 + 1520: 35,32 + 1521: 46,32 + 1522: 47,32 - node: color: '#D381C996' id: HalfTileOverlayGreyscale180 decals: - 959: 21,66 - 960: 22,66 - 974: 23,66 - 975: 24,66 + 949: 21,66 + 950: 22,66 + 964: 23,66 + 965: 24,66 - node: color: '#D4D4D419' id: HalfTileOverlayGreyscale180 decals: - 1170: -25,29 - 1171: -26,29 - 1172: -27,29 - 1173: -28,29 - 1174: -29,29 - 1175: -30,29 - 1176: -31,29 - 1177: -32,29 - 1178: -33,29 - 1179: -36,29 - 1180: -37,29 - 1181: -38,29 - 1182: -39,29 - 1183: -42,29 - 1184: -43,29 - 1185: -44,29 - 1186: -45,29 - 1187: -46,29 - 1188: -48,29 - 1189: -49,29 - 1190: -50,29 - 1191: -51,29 - 1192: -52,29 - 1193: -53,29 - 1194: -54,29 - 1195: -56,29 - 1196: -57,29 - 1276: -21,29 - 1277: -20,29 - 1278: -19,29 - 1279: -18,29 - 1280: -17,29 - 1281: -16,29 - 1282: -15,29 - 1283: -14,29 - 1284: -13,29 - 1285: -12,29 - 1286: -11,29 - 1287: -10,29 - 1288: -9,29 - 1289: -8,29 - 1290: -5,29 - 1291: -3,30 - 1292: -2,30 - 1293: -1,30 - 1294: 0,30 - 1295: 1,30 - 1296: 2,30 - 1297: 3,30 - 1298: 4,30 - 1299: 5,30 - 1300: 6,30 - 1301: 7,30 - 1302: 8,30 - 1303: 9,30 - 1304: 10,30 - 1305: 11,30 - 1306: 12,30 - 1307: 13,30 - 1308: 14,30 - 1309: 15,30 - 1310: 16,30 - 1311: 17,30 - 1348: -3,49 - 1349: -2,49 - 1350: -1,49 - 1351: 0,49 - 1352: 1,49 - 1353: 2,49 - 1354: 4,49 - 1355: 5,49 - 1356: 6,49 - 1357: 7,49 - 1358: 8,49 - 1359: 9,49 - 1360: 10,49 - 1361: 11,49 - 1362: 12,49 - 1363: 13,49 - 1364: 11,49 - 1365: 13,49 - 1366: 14,49 - 1367: 15,49 - 1368: 16,49 - 1369: 17,49 - 1370: 18,49 - 1371: 19,49 - 1372: 21,49 - 1373: 22,49 - 1374: 23,49 - 1375: 25,49 - 1376: 26,49 - 1377: 24,49 - 1378: 27,49 - 1379: 29,49 - 1380: 28,49 - 1381: 20,49 + 1160: -25,29 + 1161: -26,29 + 1162: -27,29 + 1163: -28,29 + 1164: -29,29 + 1165: -30,29 + 1166: -31,29 + 1167: -32,29 + 1168: -33,29 + 1169: -36,29 + 1170: -37,29 + 1171: -38,29 + 1172: -39,29 + 1173: -42,29 + 1174: -43,29 + 1175: -44,29 + 1176: -45,29 + 1177: -46,29 + 1178: -48,29 + 1179: -49,29 + 1180: -50,29 + 1181: -51,29 + 1182: -52,29 + 1183: -53,29 + 1184: -54,29 + 1185: -56,29 + 1186: -57,29 + 1266: -21,29 + 1267: -20,29 + 1268: -19,29 + 1269: -18,29 + 1270: -17,29 + 1271: -16,29 + 1272: -15,29 + 1273: -14,29 + 1274: -13,29 + 1275: -12,29 + 1276: -11,29 + 1277: -10,29 + 1278: -9,29 + 1279: -8,29 + 1280: -5,29 + 1281: -3,30 + 1282: -2,30 + 1283: -1,30 + 1284: 0,30 + 1285: 1,30 + 1286: 2,30 + 1287: 3,30 + 1288: 4,30 + 1289: 5,30 + 1290: 6,30 + 1291: 7,30 + 1292: 8,30 + 1293: 9,30 + 1294: 10,30 + 1295: 11,30 + 1296: 12,30 + 1297: 13,30 + 1298: 14,30 + 1299: 15,30 + 1300: 16,30 + 1301: 17,30 + 1338: -3,49 + 1339: -2,49 + 1340: -1,49 + 1341: 0,49 + 1342: 1,49 + 1343: 2,49 + 1344: 4,49 + 1345: 5,49 + 1346: 6,49 + 1347: 7,49 + 1348: 8,49 + 1349: 9,49 + 1350: 10,49 + 1351: 11,49 + 1352: 12,49 + 1353: 13,49 + 1354: 11,49 + 1355: 13,49 + 1356: 14,49 + 1357: 15,49 + 1358: 16,49 + 1359: 17,49 + 1360: 18,49 + 1361: 19,49 + 1362: 21,49 + 1363: 22,49 + 1364: 23,49 + 1365: 25,49 + 1366: 26,49 + 1367: 24,49 + 1368: 27,49 + 1369: 29,49 + 1370: 28,49 + 1371: 20,49 - node: color: '#D4D4D433' id: HalfTileOverlayGreyscale180 decals: - 759: -4,-26 - 760: -3,-26 - 761: 17,-26 - 762: 18,-26 - 763: -8,-28 - 764: -9,-28 - 765: -10,-28 - 766: -11,-28 - 792: -7,-5 - 793: -9,-5 - 794: -10,-5 - 795: -11,-5 - 796: -13,-5 - 797: -14,-5 - 798: -15,-5 - 799: -16,-5 - 800: -17,-5 - 801: -19,-5 - 802: -22,-5 - 803: -23,-5 - 804: -24,-5 - 805: -40,-5 - 829: 28,-5 - 830: 27,-5 - 831: 26,-5 - 832: 25,-5 - 833: 24,-5 - 834: 23,-5 - 835: 22,-5 - 836: 21,-5 - 866: 24,-36 - 867: 23,-36 - 868: 22,-36 - 933: 65,2 - 934: 66,2 - 935: 67,2 - 936: 68,2 - 937: 69,2 + 749: -4,-26 + 750: -3,-26 + 751: 17,-26 + 752: 18,-26 + 753: -8,-28 + 754: -9,-28 + 755: -10,-28 + 756: -11,-28 + 782: -7,-5 + 783: -9,-5 + 784: -10,-5 + 785: -11,-5 + 786: -13,-5 + 787: -14,-5 + 788: -15,-5 + 789: -16,-5 + 790: -17,-5 + 791: -19,-5 + 792: -22,-5 + 793: -23,-5 + 794: -24,-5 + 795: -40,-5 + 819: 28,-5 + 820: 27,-5 + 821: 26,-5 + 822: 25,-5 + 823: 24,-5 + 824: 23,-5 + 825: 22,-5 + 826: 21,-5 + 856: 24,-36 + 857: 23,-36 + 858: 22,-36 + 923: 65,2 + 924: 66,2 + 925: 67,2 + 926: 68,2 + 927: 69,2 - node: color: '#D58C18FF' id: HalfTileOverlayGreyscale180 decals: - 4984: 46,-17 + 4962: 46,-17 - node: color: '#DE3A3A96' id: HalfTileOverlayGreyscale180 @@ -4788,179 +4788,179 @@ entities: 333: 44,-1 334: 45,-1 335: 46,-1 - 378: 45,-17 - 381: 42,-17 - 382: 41,-17 - 384: 39,-17 - 385: 38,-17 - 510: -32,25 - 511: -31,25 - 512: -30,25 - 513: -29,25 - 514: -28,25 - 515: -27,25 - 516: -26,25 - 1215: -63,48 - 1219: -62,48 - 1466: 36,48 - 1467: 37,48 - 1605: 60,-23 - 1606: 61,-23 - 1607: 62,-23 - 4980: 44,-17 - 4986: 34,-13 + 374: 45,-17 + 375: 42,-17 + 376: 41,-17 + 377: 39,-17 + 378: 38,-17 + 500: -32,25 + 501: -31,25 + 502: -30,25 + 503: -29,25 + 504: -28,25 + 505: -27,25 + 506: -26,25 + 1205: -63,48 + 1209: -62,48 + 1456: 36,48 + 1457: 37,48 + 1595: 60,-23 + 1596: 61,-23 + 1597: 62,-23 + 4958: 44,-17 + 4964: 34,-13 - node: color: '#EFB34196' id: HalfTileOverlayGreyscale180 decals: - 612: -10,43 - 613: -11,43 - 614: -12,43 - 615: -13,43 - 616: -14,43 - 617: -15,43 - 618: -16,43 - 619: -17,43 - 620: -18,43 + 602: -10,43 + 603: -11,43 + 604: -12,43 + 605: -13,43 + 606: -14,43 + 607: -15,43 + 608: -16,43 + 609: -17,43 + 610: -18,43 - node: color: '#334E6DC8' id: HalfTileOverlayGreyscale270 decals: - 1229: -63,54 - 1230: -63,53 - 1539: 18,-60 - 1540: 17,-61 - 1541: 17,-62 - 1542: 18,-63 + 1219: -63,54 + 1220: -63,53 + 1529: 18,-60 + 1530: 17,-61 + 1531: 17,-62 + 1532: 18,-63 - node: color: '#52B4E996' id: HalfTileOverlayGreyscale270 decals: 227: -26,-26 - 4961: -36,-37 - 4962: -35,-37 - 4963: -34,-37 - 4964: -35,-36 - 4965: -35,-38 + 4948: -36,-37 + 4949: -35,-37 + 4950: -34,-37 + 4951: -35,-36 + 4952: -35,-38 - node: color: '#9FED5896' id: HalfTileOverlayGreyscale270 decals: - 1499: -8,-60 - 1500: -9,-61 - 1501: -9,-62 - 1502: -8,-63 + 1489: -8,-60 + 1490: -9,-61 + 1491: -9,-62 + 1492: -8,-63 - node: color: '#A4610696' id: HalfTileOverlayGreyscale270 decals: - 1057: 40,21 - 1058: 40,18 - 1059: 40,19 - 1060: 40,20 - 1070: 41,17 - 1071: 41,16 - 1072: 41,15 - 1073: 41,14 - 1074: 41,13 - 1075: 41,12 + 1047: 40,21 + 1048: 40,18 + 1049: 40,19 + 1050: 40,20 + 1060: 41,17 + 1061: 41,16 + 1062: 41,15 + 1063: 41,14 + 1064: 41,13 + 1065: 41,12 - node: color: '#D381C996' id: HalfTileOverlayGreyscale270 decals: - 947: 18,54 - 948: 18,57 - 949: 18,58 - 950: 18,59 - 951: 18,60 - 952: 18,61 - 953: 18,62 - 954: 18,63 - 955: 18,64 - 956: 18,65 - 957: 18,66 + 937: 18,54 + 938: 18,57 + 939: 18,58 + 940: 18,59 + 941: 18,60 + 942: 18,61 + 943: 18,62 + 944: 18,63 + 945: 18,64 + 946: 18,65 + 947: 18,66 - node: color: '#D4D4D40F' id: HalfTileOverlayGreyscale270 decals: - 4722: -28,18 - 4723: -28,17 + 4709: -28,18 + 4710: -28,17 - node: color: '#D4D4D419' id: HalfTileOverlayGreyscale270 decals: - 1142: -24,-1 - 1143: -24,0 - 1144: -24,1 - 1145: -24,2 - 1146: -24,3 - 1147: -24,4 - 1148: -24,5 - 1149: -24,6 - 1150: -24,7 - 1151: -24,8 - 1152: -24,10 - 1153: -24,11 - 1154: -24,12 - 1155: -24,13 - 1156: -24,14 - 1157: -24,15 - 1158: -24,16 - 1159: -24,18 - 1160: -24,19 - 1161: -24,20 - 1162: -24,21 - 1163: -24,22 - 1164: -24,23 - 1165: -24,24 - 1166: -24,26 - 1167: -24,27 - 1198: -58,30 - 1199: -58,31 - 1200: -58,32 + 1132: -24,-1 + 1133: -24,0 + 1134: -24,1 + 1135: -24,2 + 1136: -24,3 + 1137: -24,4 + 1138: -24,5 + 1139: -24,6 + 1140: -24,7 + 1141: -24,8 + 1142: -24,10 + 1143: -24,11 + 1144: -24,12 + 1145: -24,13 + 1146: -24,14 + 1147: -24,15 + 1148: -24,16 + 1149: -24,18 + 1150: -24,19 + 1151: -24,20 + 1152: -24,21 + 1153: -24,22 + 1154: -24,23 + 1155: -24,24 + 1156: -24,26 + 1157: -24,27 + 1188: -58,30 + 1189: -58,31 + 1190: -58,32 - node: color: '#D4D4D433' id: HalfTileOverlayGreyscale270 decals: - 728: -7,-30 - 729: -7,-31 - 730: -7,-32 - 731: -7,-36 - 732: -7,-37 - 733: -7,-38 - 734: -7,-39 - 735: -7,-40 - 736: -7,-41 - 737: -7,-45 - 738: -7,-47 - 739: -7,-48 - 740: -7,-49 - 741: -7,-51 - 742: -7,-53 - 743: -7,-54 - 744: -7,-55 - 745: -7,-56 - 746: -7,-57 - 747: -7,-58 - 776: -6,-24 - 777: -6,-23 - 778: -6,-22 - 779: -6,-20 - 780: -6,-19 - 781: -6,-18 - 782: -6,-16 - 783: -6,-15 - 784: -6,-13 - 785: -6,-12 - 786: -6,-11 - 787: -6,-10 - 788: -6,-9 - 789: -6,-8 - 790: -6,-6 - 892: 19,-57 - 893: 19,-56 - 894: 19,-55 - 895: 19,-54 + 718: -7,-30 + 719: -7,-31 + 720: -7,-32 + 721: -7,-36 + 722: -7,-37 + 723: -7,-38 + 724: -7,-39 + 725: -7,-40 + 726: -7,-41 + 727: -7,-45 + 728: -7,-47 + 729: -7,-48 + 730: -7,-49 + 731: -7,-51 + 732: -7,-53 + 733: -7,-54 + 734: -7,-55 + 735: -7,-56 + 736: -7,-57 + 737: -7,-58 + 766: -6,-24 + 767: -6,-23 + 768: -6,-22 + 769: -6,-20 + 770: -6,-19 + 771: -6,-18 + 772: -6,-16 + 773: -6,-15 + 774: -6,-13 + 775: -6,-12 + 776: -6,-11 + 777: -6,-10 + 778: -6,-9 + 779: -6,-8 + 780: -6,-6 + 882: 19,-57 + 883: 19,-56 + 884: 19,-55 + 885: 19,-54 - node: color: '#DE3A3A96' id: HalfTileOverlayGreyscale270 @@ -4979,214 +4979,214 @@ entities: 354: 34,-9 355: 34,-10 356: 34,-11 - 359: 35,-14 - 360: 35,-15 - 361: 36,-16 - 362: 36,-17 - 518: -32,26 - 1216: -64,49 - 1217: -64,50 - 1461: 35,49 - 1462: 35,50 - 4987: 34,-13 - 4988: 34,-12 + 357: 35,-14 + 358: 35,-15 + 359: 36,-16 + 360: 36,-17 + 508: -32,26 + 1206: -64,49 + 1207: -64,50 + 1451: 35,49 + 1452: 35,50 + 4965: 34,-13 + 4966: 34,-12 - node: color: '#EFB34196' id: HalfTileOverlayGreyscale270 decals: - 583: -21,54 - 584: -21,53 - 585: -21,52 - 586: -21,51 - 587: -21,50 - 588: -21,49 - 589: -21,48 - 590: -21,47 - 591: -21,46 - 592: -21,45 - 593: -21,44 - 594: -21,43 - 595: -21,42 - 596: -21,41 - 597: -21,40 - 598: -21,39 - 599: -21,38 - 600: -21,37 - 601: -21,36 - 602: -21,35 + 573: -21,54 + 574: -21,53 + 575: -21,52 + 576: -21,51 + 577: -21,50 + 578: -21,49 + 579: -21,48 + 580: -21,47 + 581: -21,46 + 582: -21,45 + 583: -21,44 + 584: -21,43 + 585: -21,42 + 586: -21,41 + 587: -21,40 + 588: -21,39 + 589: -21,38 + 590: -21,37 + 591: -21,36 + 592: -21,35 - node: color: '#334E6DC8' id: HalfTileOverlayGreyscale90 decals: - 1231: -57,54 - 1232: -57,53 - 1535: 23,-61 - 1536: 23,-62 - 1537: 22,-63 - 1538: 22,-60 + 1221: -57,54 + 1222: -57,53 + 1525: 23,-61 + 1526: 23,-62 + 1527: 22,-63 + 1528: 22,-60 - node: color: '#52B4E996' id: HalfTileOverlayGreyscale90 decals: - 4966: -36,-37 - 4967: -35,-36 - 4968: -35,-37 - 4969: -35,-38 - 4970: -34,-37 + 4953: -36,-37 + 4954: -35,-36 + 4955: -35,-37 + 4956: -35,-38 + 4957: -34,-37 - node: color: '#9FED5896' id: HalfTileOverlayGreyscale90 decals: - 1503: -4,-60 - 1504: -3,-61 - 1505: -3,-62 - 1506: -4,-63 + 1493: -4,-60 + 1494: -3,-61 + 1495: -3,-62 + 1496: -4,-63 - node: color: '#A4610696' id: HalfTileOverlayGreyscale90 decals: - 1063: 45,25 - 1064: 45,24 - 1065: 45,21 - 1066: 45,20 - 1067: 45,19 - 1068: 44,17 - 1069: 44,16 - 1076: 43,12 - 1077: 43,14 - 1078: 43,13 - 1079: 43,15 - 1625: 45,22 - 1626: 45,23 + 1053: 45,25 + 1054: 45,24 + 1055: 45,21 + 1056: 45,20 + 1057: 45,19 + 1058: 44,17 + 1059: 44,16 + 1066: 43,12 + 1067: 43,14 + 1068: 43,13 + 1069: 43,15 + 1614: 45,22 + 1615: 45,23 - node: color: '#D381C996' id: HalfTileOverlayGreyscale90 decals: - 938: 20,56 - 939: 20,57 - 940: 20,58 - 941: 20,59 - 942: 20,61 - 943: 20,62 - 944: 20,63 - 945: 20,64 - 946: 20,65 - 977: 24,67 - 978: 24,68 - 979: 24,70 + 928: 20,56 + 929: 20,57 + 930: 20,58 + 931: 20,59 + 932: 20,61 + 933: 20,62 + 934: 20,63 + 935: 20,64 + 936: 20,65 + 967: 24,67 + 968: 24,68 + 969: 24,70 - node: color: '#D4D4D405' id: HalfTileOverlayGreyscale90 decals: - 4724: -29,18 - 4725: -29,17 + 4711: -29,18 + 4712: -29,17 - node: color: '#D4D4D419' id: HalfTileOverlayGreyscale90 decals: - 1124: -22,5 - 1125: -22,7 - 1126: -22,8 - 1127: -22,9 - 1128: -22,10 - 1129: -22,11 - 1130: -22,12 - 1131: -22,13 - 1132: -22,14 - 1133: -22,15 - 1134: -22,17 - 1135: -22,20 - 1136: -22,22 - 1137: -22,23 - 1138: -22,24 - 1139: -22,25 - 1140: -22,26 - 1141: -22,27 - 1202: -56,32 - 1203: -56,33 - 1333: -4,33 - 1334: -4,34 - 1335: -4,36 - 1336: -4,37 - 1337: -4,38 - 1338: -4,39 - 1339: -4,40 - 1340: -4,41 - 1341: -4,42 - 1342: -4,44 - 1343: -4,45 - 1344: -4,46 - 1345: -4,47 - 1346: -4,48 - 4720: -28,18 - 4721: -28,17 + 1114: -22,5 + 1115: -22,7 + 1116: -22,8 + 1117: -22,9 + 1118: -22,10 + 1119: -22,11 + 1120: -22,12 + 1121: -22,13 + 1122: -22,14 + 1123: -22,15 + 1124: -22,17 + 1125: -22,20 + 1126: -22,22 + 1127: -22,23 + 1128: -22,24 + 1129: -22,25 + 1130: -22,26 + 1131: -22,27 + 1192: -56,32 + 1193: -56,33 + 1323: -4,33 + 1324: -4,34 + 1325: -4,36 + 1326: -4,37 + 1327: -4,38 + 1328: -4,39 + 1329: -4,40 + 1330: -4,41 + 1331: -4,42 + 1332: -4,44 + 1333: -4,45 + 1334: -4,46 + 1335: -4,47 + 1336: -4,48 + 4707: -28,18 + 4708: -28,17 - node: color: '#D4D4D433' id: HalfTileOverlayGreyscale90 decals: - 748: -5,-58 - 749: -5,-57 - 750: -5,-56 - 751: -5,-55 - 752: -5,-54 - 753: -5,-53 - 754: -5,-51 - 755: -5,-50 - 756: -5,-28 - 757: -5,-27 - 807: -41,-11 - 826: 29,-3 - 827: 29,-4 - 838: 20,-6 - 839: 20,-8 - 840: 20,-9 - 841: 20,-10 - 842: 20,-11 - 843: 20,-12 - 844: 20,-14 - 845: 20,-15 - 846: 20,-16 - 849: 21,-18 - 850: 21,-19 - 851: 21,-20 - 852: 21,-21 - 853: 21,-22 - 854: 21,-23 - 855: 21,-24 - 856: 21,-25 - 857: 21,-26 - 858: 21,-27 - 859: 21,-28 - 860: 21,-29 - 861: 21,-30 - 870: 21,-38 - 871: 21,-39 - 872: 21,-40 - 873: 21,-41 - 874: 21,-42 - 875: 21,-43 - 876: 21,-44 - 877: 21,-45 - 878: 21,-46 - 879: 21,-47 - 880: 21,-48 - 881: 21,-49 - 882: 21,-50 - 883: 21,-51 - 884: 21,-52 - 885: 21,-53 - 886: 21,-54 - 887: 21,-55 - 888: 21,-56 - 889: 21,-57 - 896: 29,-1 - 897: 29,0 - 898: 29,1 + 738: -5,-58 + 739: -5,-57 + 740: -5,-56 + 741: -5,-55 + 742: -5,-54 + 743: -5,-53 + 744: -5,-51 + 745: -5,-50 + 746: -5,-28 + 747: -5,-27 + 797: -41,-11 + 816: 29,-3 + 817: 29,-4 + 828: 20,-6 + 829: 20,-8 + 830: 20,-9 + 831: 20,-10 + 832: 20,-11 + 833: 20,-12 + 834: 20,-14 + 835: 20,-15 + 836: 20,-16 + 839: 21,-18 + 840: 21,-19 + 841: 21,-20 + 842: 21,-21 + 843: 21,-22 + 844: 21,-23 + 845: 21,-24 + 846: 21,-25 + 847: 21,-26 + 848: 21,-27 + 849: 21,-28 + 850: 21,-29 + 851: 21,-30 + 860: 21,-38 + 861: 21,-39 + 862: 21,-40 + 863: 21,-41 + 864: 21,-42 + 865: 21,-43 + 866: 21,-44 + 867: 21,-45 + 868: 21,-46 + 869: 21,-47 + 870: 21,-48 + 871: 21,-49 + 872: 21,-50 + 873: 21,-51 + 874: 21,-52 + 875: 21,-53 + 876: 21,-54 + 877: 21,-55 + 878: 21,-56 + 879: 21,-57 + 886: 29,-1 + 887: 29,0 + 888: 29,1 - node: color: '#D58C18FF' id: HalfTileOverlayGreyscale90 decals: - 4985: 46,-17 + 4963: 46,-17 - node: color: '#DE3A3A96' id: HalfTileOverlayGreyscale90 @@ -5196,279 +5196,279 @@ entities: 327: 47,1 328: 47,0 329: 47,-1 - 363: 46,-11 - 364: 46,-10 - 365: 46,-9 - 366: 46,-8 - 367: 46,-7 - 368: 47,-6 - 369: 47,-5 - 370: 47,-4 - 517: -26,26 - 1212: -61,50 - 1213: -61,49 - 1455: 38,51 - 1456: 38,50 - 1457: 38,49 - 1608: 46,-16 - 1609: 46,-13 + 361: 46,-11 + 362: 46,-10 + 363: 46,-9 + 364: 46,-8 + 365: 46,-7 + 366: 47,-6 + 367: 47,-5 + 368: 47,-4 + 507: -26,26 + 1202: -61,50 + 1203: -61,49 + 1445: 38,51 + 1446: 38,50 + 1447: 38,49 + 1598: 46,-16 + 1599: 46,-13 - node: color: '#EFB34196' id: HalfTileOverlayGreyscale90 decals: - 566: -19,35 - 567: -19,36 - 568: -19,37 - 569: -19,38 - 570: -19,39 - 571: -19,40 - 572: -19,41 - 573: -19,42 - 574: -19,46 - 575: -19,47 - 576: -19,48 - 577: -19,49 - 578: -19,50 - 579: -19,51 - 580: -19,52 - 581: -19,53 - 582: -19,54 + 556: -19,35 + 557: -19,36 + 558: -19,37 + 559: -19,38 + 560: -19,39 + 561: -19,40 + 562: -19,41 + 563: -19,42 + 564: -19,46 + 565: -19,47 + 566: -19,48 + 567: -19,49 + 568: -19,50 + 569: -19,51 + 570: -19,52 + 571: -19,53 + 572: -19,54 - node: color: '#EFB34196' id: LoadingArea decals: - 489: 75,10 - 490: 76,10 + 479: 75,10 + 480: 76,10 - node: angle: 3.141592653589793 rad color: '#EFB34196' id: LoadingArea decals: - 491: 82,10 - 492: 83,10 + 481: 82,10 + 482: 83,10 - node: angle: 4.71238898038469 rad color: '#EFB34196' id: LoadingArea decals: - 1047: 36,29 - 1204: -64,46 - 1205: -64,40 - 1206: -64,38 - 1220: -64,48 + 1037: 36,29 + 1194: -64,46 + 1195: -64,40 + 1196: -64,38 + 1210: -64,48 - node: color: '#334E6DC8' id: LoadingAreaGreyscale decals: - 498: -5,-2 + 488: -5,-2 - node: angle: 3.141592653589793 rad color: '#334E6DC8' id: LoadingAreaGreyscale decals: - 499: -9,-2 + 489: -9,-2 - node: color: '#52B4E996' id: MiniTileCheckerAOverlay decals: - 3621: 26,-35 - 3622: 27,-35 - 3623: 28,-35 - 3624: 29,-35 - 3625: 30,-35 - 3626: 30,-34 - 3627: 29,-34 - 3628: 28,-34 - 3629: 27,-34 - 3630: 26,-34 - 3631: 26,-33 - 3632: 26,-32 - 3633: 27,-32 - 3634: 28,-32 - 3635: 29,-32 - 3636: 30,-32 - 3637: 30,-33 - 3638: 29,-33 - 3639: 28,-33 - 3640: 27,-33 + 3608: 26,-35 + 3609: 27,-35 + 3610: 28,-35 + 3611: 29,-35 + 3612: 30,-35 + 3613: 30,-34 + 3614: 29,-34 + 3615: 28,-34 + 3616: 27,-34 + 3617: 26,-34 + 3618: 26,-33 + 3619: 26,-32 + 3620: 27,-32 + 3621: 28,-32 + 3622: 29,-32 + 3623: 30,-32 + 3624: 30,-33 + 3625: 29,-33 + 3626: 28,-33 + 3627: 27,-33 - node: color: '#334E6DC8' id: MiniTileCheckerBOverlay decals: - 4687: -33,18 - 4688: -33,17 - 4689: -32,17 - 4690: -31,17 - 4691: -31,18 - 4692: -32,18 + 4674: -33,18 + 4675: -33,17 + 4676: -32,17 + 4677: -31,17 + 4678: -31,18 + 4679: -32,18 - node: color: '#FFFFFFFF' id: MiniTileCheckerBOverlay decals: - 3641: 26,-32 - 3642: 26,-33 - 3643: 26,-34 - 3644: 26,-35 - 3645: 27,-35 - 3646: 28,-35 - 3647: 29,-35 - 3648: 30,-35 - 3649: 30,-34 - 3650: 30,-33 - 3651: 30,-32 - 3652: 29,-32 - 3653: 28,-32 - 3654: 27,-32 - 3655: 27,-33 - 3656: 27,-34 - 3657: 28,-34 - 3658: 28,-33 - 3659: 29,-33 - 3660: 29,-34 + 3628: 26,-32 + 3629: 26,-33 + 3630: 26,-34 + 3631: 26,-35 + 3632: 27,-35 + 3633: 28,-35 + 3634: 29,-35 + 3635: 30,-35 + 3636: 30,-34 + 3637: 30,-33 + 3638: 30,-32 + 3639: 29,-32 + 3640: 28,-32 + 3641: 27,-32 + 3642: 27,-33 + 3643: 27,-34 + 3644: 28,-34 + 3645: 28,-33 + 3646: 29,-33 + 3647: 29,-34 - node: color: '#FFFFFFFF' id: MiniTileDarkCornerNe decals: - 3445: 46,36 + 3432: 46,36 - node: color: '#FFFFFFFF' id: MiniTileDarkCornerNw decals: - 3443: 43,36 + 3430: 43,36 - node: color: '#FFFFFFFF' id: MiniTileDarkCornerSe decals: - 3444: 46,33 + 3431: 46,33 - node: color: '#FFFFFFFF' id: MiniTileDarkCornerSw decals: - 3442: 43,33 + 3429: 43,33 - node: color: '#FFFFFFFF' id: MiniTileDarkInnerSw decals: - 3472: -24,-18 + 3459: -24,-18 - node: color: '#FFFFFFFF' id: MiniTileDarkLineE decals: - 3448: 46,35 - 3449: 46,34 + 3435: 46,35 + 3436: 46,34 - node: color: '#FFFFFFFF' id: MiniTileDarkLineN decals: - 3446: 44,36 - 3447: 45,36 + 3433: 44,36 + 3434: 45,36 - node: color: '#FFFFFFFF' id: MiniTileDarkLineS decals: - 3450: 44,33 - 3451: 45,33 - 3473: -25,-18 - 3474: -26,-18 - 3475: -27,-18 - 3483: 25,-1 - 3484: 25,-1 + 3437: 44,33 + 3438: 45,33 + 3460: -25,-18 + 3461: -26,-18 + 3462: -27,-18 + 3470: 25,-1 + 3471: 25,-1 - node: color: '#FFFFFFFF' id: MiniTileDarkLineW decals: - 3452: 43,34 - 3453: 43,35 - 3469: -24,-21 - 3470: -24,-20 - 3471: -24,-19 + 3439: 43,34 + 3440: 43,35 + 3456: -24,-21 + 3457: -24,-20 + 3458: -24,-19 - node: color: '#666C6CA4' id: MiniTileDiagonalCheckerBOverlay decals: - 4295: 58,-37 - 4296: 58,-38 - 4297: 59,-38 - 4298: 59,-37 + 4282: 58,-37 + 4283: 58,-38 + 4284: 59,-38 + 4285: 59,-37 - node: color: '#FFFFFFFF' id: MiniTileSteelEndE decals: - 3455: 41,-9 + 3442: 41,-9 - node: color: '#FFFFFFFF' id: MiniTileSteelEndW decals: - 3454: 39,-9 + 3441: 39,-9 - node: color: '#FFFFFFFF' id: MiniTileSteelLineN decals: - 3456: 40,-9 + 3443: 40,-9 - node: color: '#FFFFFFFF' id: MiniTileSteelLineS decals: - 3457: 40,-9 + 3444: 40,-9 - node: color: '#52B4E996' id: MiniTileWhiteCornerNe decals: - 4894: -40,-43 + 4881: -40,-43 - node: zIndex: 1 color: '#52B4E996' id: MiniTileWhiteCornerNe decals: - 4907: -42,-40 + 4894: -42,-40 - node: color: '#52B4E996' id: MiniTileWhiteCornerNw decals: - 4895: -44,-40 + 4882: -44,-40 - node: color: '#52B4E996' id: MiniTileWhiteCornerSe decals: - 4892: -40,-45 + 4879: -40,-45 - node: color: '#52B4E996' id: MiniTileWhiteCornerSw decals: - 4893: -44,-45 + 4880: -44,-45 - node: color: '#52B4E996' id: MiniTileWhiteInnerNe decals: - 4896: -42,-43 + 4883: -42,-43 - node: color: '#52B4E996' id: MiniTileWhiteLineE decals: - 4902: -42,-41 - 4903: -42,-42 - 4908: -40,-44 + 4889: -42,-41 + 4890: -42,-42 + 4895: -40,-44 - node: color: '#52B4E996' id: MiniTileWhiteLineN decals: - 4900: -43,-40 - 4901: -41,-43 + 4887: -43,-40 + 4888: -41,-43 - node: color: '#52B4E996' id: MiniTileWhiteLineS decals: - 4889: -43,-45 - 4890: -42,-45 - 4891: -41,-45 + 4876: -43,-45 + 4877: -42,-45 + 4878: -41,-45 - node: color: '#52B4E996' id: MiniTileWhiteLineW decals: - 4897: -44,-43 - 4898: -44,-42 - 4899: -44,-41 - 4909: -44,-44 + 4884: -44,-43 + 4885: -44,-42 + 4886: -44,-41 + 4896: -44,-44 - node: color: '#334E6DC8' id: QuarterTileOverlayGreyscale @@ -5525,13 +5525,13 @@ entities: 217: -23,-33 218: -24,-33 231: -26,-34 - 687: 25,10 - 688: 27,10 - 689: 29,10 - 694: 25,6 - 695: 24,7 - 696: 24,9 - 3284: -26,-27 + 677: 25,10 + 678: 27,10 + 679: 29,10 + 684: 25,6 + 685: 24,7 + 686: 24,9 + 3271: -26,-27 - node: color: '#9FED5896' id: QuarterTileOverlayGreyscale @@ -5584,18 +5584,18 @@ entities: color: '#D4D4D433' id: QuarterTileOverlayGreyscale decals: - 768: -11,-28 - 775: -6,-25 - 825: 27,-3 - 891: 19,-58 + 758: -11,-28 + 765: -6,-25 + 815: 27,-3 + 881: 19,-58 - node: color: '#DE3A3A96' id: QuarterTileOverlayGreyscale decals: - 392: 35,-7 - 520: -32,25 - 523: -28,26 - 1465: 38,51 + 384: 35,-7 + 510: -32,25 + 513: -28,26 + 1455: 38,51 - node: color: '#EFB34196' id: QuarterTileOverlayGreyscale @@ -5624,56 +5624,56 @@ entities: 44: 27,0 45: 27,-1 46: 27,-2 - 528: -33,31 - 529: -32,31 - 530: -31,31 - 531: -30,31 - 532: -29,31 - 533: -28,31 - 534: -27,31 - 535: -26,31 - 536: -25,31 - 537: -24,31 - 538: -23,31 - 539: -22,31 - 540: -21,31 - 541: -21,32 - 625: -19,54 - 642: -28,39 - 643: -27,39 - 644: -26,39 - 645: -25,39 - 646: -24,39 - 647: -23,39 - 648: -28,38 - 649: -28,37 - 652: -11,41 - 653: -12,41 - 654: -13,41 - 655: -14,41 - 656: -15,41 - 657: -16,41 - 658: -17,41 - 659: -17,40 - 660: -17,39 - 661: -17,38 - 662: -17,37 - 663: -17,36 - 664: -17,35 - 677: 24,10 - 678: 26,10 - 679: 28,10 - 686: 24,8 - 1404: -6,37 - 1405: -6,36 - 1406: -6,35 - 1407: -6,34 - 1408: -6,33 - 1431: -6,38 - 1432: -6,39 - 1433: -6,40 - 1434: -6,41 - 1435: -6,42 + 518: -33,31 + 519: -32,31 + 520: -31,31 + 521: -30,31 + 522: -29,31 + 523: -28,31 + 524: -27,31 + 525: -26,31 + 526: -25,31 + 527: -24,31 + 528: -23,31 + 529: -22,31 + 530: -21,31 + 531: -21,32 + 615: -19,54 + 632: -28,39 + 633: -27,39 + 634: -26,39 + 635: -25,39 + 636: -24,39 + 637: -23,39 + 638: -28,38 + 639: -28,37 + 642: -11,41 + 643: -12,41 + 644: -13,41 + 645: -14,41 + 646: -15,41 + 647: -16,41 + 648: -17,41 + 649: -17,40 + 650: -17,39 + 651: -17,38 + 652: -17,37 + 653: -17,36 + 654: -17,35 + 667: 24,10 + 668: 26,10 + 669: 28,10 + 676: 24,8 + 1394: -6,37 + 1395: -6,36 + 1396: -6,35 + 1397: -6,34 + 1398: -6,33 + 1421: -6,38 + 1422: -6,39 + 1423: -6,40 + 1424: -6,41 + 1425: -6,42 - node: color: '#52B4E996' id: QuarterTileOverlayGreyscale180 @@ -5698,76 +5698,76 @@ entities: 226: -22,-27 228: -26,-26 229: -27,-26 - 690: 29,9 - 691: 29,7 - 692: 28,6 - 693: 26,6 - 3285: -25,-27 + 680: 29,9 + 681: 29,7 + 682: 28,6 + 683: 26,6 + 3272: -25,-27 - node: color: '#A4610696' id: QuarterTileOverlayGreyscale180 decals: - 1627: 45,26 - 1628: 43,16 + 1616: 45,26 + 1617: 43,16 - node: color: '#D381C996' id: QuarterTileOverlayGreyscale180 decals: - 961: 20,66 - 980: 24,71 + 951: 20,66 + 970: 24,71 - node: color: '#D4D4D419' id: QuarterTileOverlayGreyscale180 decals: - 1169: -22,29 - 1347: -4,49 + 1159: -22,29 + 1337: -4,49 - node: color: '#D4D4D433' id: QuarterTileOverlayGreyscale180 decals: - 758: -5,-26 - 806: -41,-5 - 837: 20,-5 - 869: 21,-36 + 748: -5,-26 + 796: -41,-5 + 827: 20,-5 + 859: 21,-36 - node: color: '#DE3A3A96' id: QuarterTileOverlayGreyscale180 decals: 238: -27,-40 336: 43,-1 - 372: 35,-15 - 373: 36,-17 - 374: 33,-8 - 393: 46,-6 - 524: -26,27 - 525: -30,27 - 1211: -61,51 - 1610: 46,-12 + 369: 35,-15 + 370: 36,-17 + 371: 33,-8 + 385: 46,-6 + 514: -26,27 + 515: -30,27 + 1201: -61,51 + 1600: 46,-12 - node: color: '#EFB34196' id: QuarterTileOverlayGreyscale180 decals: - 622: -19,43 - 650: -24,36 - 651: -23,36 - 665: -17,35 - 666: -16,35 - 667: -15,35 - 668: -14,35 - 669: -13,35 - 670: -13,36 - 671: -13,37 - 672: -13,38 - 673: -12,38 - 674: -11,38 - 680: 29,10 - 681: 29,8 - 682: 29,6 - 683: 27,6 - 684: 25,6 - 685: 24,7 - 1436: -7,43 - 1437: -8,43 + 612: -19,43 + 640: -24,36 + 641: -23,36 + 655: -17,35 + 656: -16,35 + 657: -15,35 + 658: -14,35 + 659: -13,35 + 660: -13,36 + 661: -13,37 + 662: -13,38 + 663: -12,38 + 664: -11,38 + 670: 29,10 + 671: 29,8 + 672: 29,6 + 673: 27,6 + 674: 25,6 + 675: 24,7 + 1426: -7,43 + 1427: -8,43 - node: color: '#52B4E996' id: QuarterTileOverlayGreyscale270 @@ -5782,11 +5782,11 @@ entities: 186: -13,-27 230: -26,-33 232: -26,-34 - 425: 51,-13 - 426: 51,-12 - 1599: 53,-14 - 1600: 52,-14 - 1601: 51,-14 + 415: 51,-13 + 416: 51,-12 + 1589: 53,-14 + 1590: 52,-14 + 1591: 51,-14 - node: color: '#9FED5896' id: QuarterTileOverlayGreyscale270 @@ -5798,35 +5798,35 @@ entities: color: '#A4610696' id: QuarterTileOverlayGreyscale270 decals: - 1629: 44,16 + 1618: 44,16 - node: color: '#D381C996' id: QuarterTileOverlayGreyscale270 decals: - 958: 18,67 - 1013: 11,58 - 1014: 11,57 - 1015: 11,56 - 1016: 11,55 - 1017: 11,54 - 1018: 11,53 - 1019: 12,53 + 948: 18,67 + 1003: 11,58 + 1004: 11,57 + 1005: 11,56 + 1006: 11,55 + 1007: 11,54 + 1008: 11,53 + 1009: 12,53 - node: color: '#D4D4D419' id: QuarterTileOverlayGreyscale270 decals: - 1168: -24,29 - 1312: 18,30 + 1158: -24,29 + 1302: 18,30 - node: color: '#D4D4D433' id: QuarterTileOverlayGreyscale270 decals: - 767: -7,-28 - 769: -11,-27 - 791: -6,-5 - 815: 17,-5 - 816: 18,-6 - 828: 29,-5 + 757: -7,-28 + 759: -11,-27 + 781: -6,-5 + 805: 17,-5 + 806: 18,-6 + 818: 29,-5 - node: color: '#DE3A3A96' id: QuarterTileOverlayGreyscale270 @@ -5863,54 +5863,54 @@ entities: 89: 64,2 237: -25,-40 337: 47,-1 - 375: 47,-6 - 387: 35,-13 - 388: 36,-15 - 389: 34,-8 - 400: 37,-6 - 401: 38,-6 - 402: 39,-6 - 403: 40,-6 - 404: 41,-6 - 405: 42,-6 - 406: 43,-6 - 407: 44,-6 - 408: 44,-7 - 409: 44,-8 - 410: 44,-9 - 411: 44,-10 - 412: 44,-11 - 427: 49,-3 - 428: 50,-3 - 429: 51,-3 - 430: 52,-3 - 431: 53,-3 - 432: 54,-3 - 433: 55,-3 - 434: 56,-3 - 444: 49,-1 - 445: 49,-2 - 446: 58,0 - 447: 58,-1 - 448: 58,-2 - 449: 58,-3 - 450: 59,-3 - 451: 60,-3 - 452: 61,-3 - 453: 62,-3 - 526: -28,27 - 527: -32,27 - 1218: -64,51 + 372: 47,-6 + 379: 35,-13 + 380: 36,-15 + 381: 34,-8 + 392: 37,-6 + 393: 38,-6 + 394: 39,-6 + 395: 40,-6 + 396: 41,-6 + 397: 42,-6 + 398: 43,-6 + 399: 44,-6 + 400: 44,-7 + 401: 44,-8 + 402: 44,-9 + 403: 44,-10 + 404: 44,-11 + 417: 49,-3 + 418: 50,-3 + 419: 51,-3 + 420: 52,-3 + 421: 53,-3 + 422: 54,-3 + 423: 55,-3 + 424: 56,-3 + 434: 49,-1 + 435: 49,-2 + 436: 58,0 + 437: 58,-1 + 438: 58,-2 + 439: 58,-3 + 440: 59,-3 + 441: 60,-3 + 442: 61,-3 + 443: 62,-3 + 516: -28,27 + 517: -32,27 + 1208: -64,51 - node: color: '#EFB34196' id: QuarterTileOverlayGreyscale270 decals: - 1425: -6,51 - 1426: -6,50 - 1427: -6,49 - 1428: -6,48 - 1429: -6,47 - 1430: -6,46 + 1415: -6,51 + 1416: -6,50 + 1417: -6,49 + 1418: -6,48 + 1419: -6,47 + 1420: -6,46 - node: color: '#334E6DC8' id: QuarterTileOverlayGreyscale90 @@ -5934,11 +5934,11 @@ entities: decals: 233: -26,-34 234: -27,-34 - 420: 53,-12 - 421: 52,-12 - 422: 51,-12 - 423: 53,-13 - 424: 53,-14 + 410: 53,-12 + 411: 52,-12 + 412: 51,-12 + 413: 53,-13 + 414: 53,-14 - node: color: '#9FED5896' id: QuarterTileOverlayGreyscale90 @@ -5998,672 +5998,672 @@ entities: 21: 33,20 22: 33,19 90: 33,7 - 1440: 33,23 - 1441: 33,24 - 1442: 33,25 - 1443: 33,26 - 1444: 33,27 - 1445: 33,28 - 1446: 33,29 - 1447: 33,30 - 3984: 33,35 + 1430: 33,23 + 1431: 33,24 + 1432: 33,25 + 1433: 33,26 + 1434: 33,27 + 1435: 33,28 + 1436: 33,29 + 1437: 33,30 + 3971: 33,35 - node: color: '#D381C996' id: QuarterTileOverlayGreyscale90 decals: - 561: 25,51 - 562: 24,51 - 563: 23,51 - 564: 22,51 - 565: 21,51 - 976: 24,66 - 1006: 16,57 - 1007: 16,58 - 1008: 15,58 - 1009: 14,58 - 1010: 13,58 - 1011: 12,58 - 1012: 11,58 - 1382: 20,51 - 1383: 19,51 - 1384: 18,51 - 1385: 17,51 - 1386: 16,51 - 1387: 12,51 - 1388: 11,51 - 1389: 10,51 - 1390: 9,51 - 1391: 8,51 - 1392: 7,51 - 1393: 6,51 - 1394: 5,51 - 1395: 4,51 + 551: 25,51 + 552: 24,51 + 553: 23,51 + 554: 22,51 + 555: 21,51 + 966: 24,66 + 996: 16,57 + 997: 16,58 + 998: 15,58 + 999: 14,58 + 1000: 13,58 + 1001: 12,58 + 1002: 11,58 + 1372: 20,51 + 1373: 19,51 + 1374: 18,51 + 1375: 17,51 + 1376: 16,51 + 1377: 12,51 + 1378: 11,51 + 1379: 10,51 + 1380: 9,51 + 1381: 8,51 + 1382: 7,51 + 1383: 6,51 + 1384: 5,51 + 1385: 4,51 - node: color: '#D4D4D419' id: QuarterTileOverlayGreyscale90 decals: - 1201: -56,31 + 1191: -56,31 - node: color: '#D4D4D433' id: QuarterTileOverlayGreyscale90 decals: - 848: 20,-17 - 862: 21,-31 - 890: 21,-58 + 838: 20,-17 + 852: 21,-31 + 880: 21,-58 - node: color: '#DE3A3A96' id: QuarterTileOverlayGreyscale90 decals: 347: 37,-3 - 376: 46,-12 - 390: 33,-7 - 394: 36,-12 - 395: 36,-11 - 396: 36,-10 - 397: 36,-9 - 398: 36,-8 - 399: 36,-7 - 413: 43,-12 - 414: 42,-12 - 415: 41,-12 - 416: 40,-12 - 417: 39,-12 - 435: 56,-3 - 436: 56,-2 - 437: 56,-1 - 438: 54,-1 - 439: 53,-1 - 440: 52,-1 - 441: 51,-1 - 442: 50,-1 - 443: 49,-1 - 454: 62,-3 - 455: 62,-2 - 456: 62,-1 - 457: 62,0 - 458: 61,0 - 459: 60,0 - 460: 59,0 - 461: 58,0 - 521: -26,25 - 522: -30,26 - 4989: 37,-12 - 4990: 38,-12 + 373: 46,-12 + 382: 33,-7 + 386: 36,-12 + 387: 36,-11 + 388: 36,-10 + 389: 36,-9 + 390: 36,-8 + 391: 36,-7 + 405: 43,-12 + 406: 42,-12 + 407: 41,-12 + 408: 40,-12 + 409: 39,-12 + 425: 56,-3 + 426: 56,-2 + 427: 56,-1 + 428: 54,-1 + 429: 53,-1 + 430: 52,-1 + 431: 51,-1 + 432: 50,-1 + 433: 49,-1 + 444: 62,-3 + 445: 62,-2 + 446: 62,-1 + 447: 62,0 + 448: 61,0 + 449: 60,0 + 450: 59,0 + 451: 58,0 + 511: -26,25 + 512: -30,26 + 4967: 37,-12 + 4968: 38,-12 - node: color: '#EFB34196' id: QuarterTileOverlayGreyscale90 decals: - 542: -19,32 - 543: -19,31 - 544: -18,31 - 545: -17,31 - 546: -16,31 - 547: -15,31 - 548: -14,31 - 549: -13,31 - 550: -12,31 - 551: -11,31 - 552: -10,31 - 553: -9,31 - 554: -8,31 - 621: -19,45 - 626: -20,54 - 1396: 2,51 - 1397: 1,51 - 1398: -1,51 - 1399: -2,51 - 1400: -3,51 - 1401: -4,51 - 1402: -5,51 - 1403: -6,51 - 1438: -7,45 - 1439: -8,45 + 532: -19,32 + 533: -19,31 + 534: -18,31 + 535: -17,31 + 536: -16,31 + 537: -15,31 + 538: -14,31 + 539: -13,31 + 540: -12,31 + 541: -11,31 + 542: -10,31 + 543: -9,31 + 544: -8,31 + 611: -19,45 + 616: -20,54 + 1386: 2,51 + 1387: 1,51 + 1388: -1,51 + 1389: -2,51 + 1390: -3,51 + 1391: -4,51 + 1392: -5,51 + 1393: -6,51 + 1428: -7,45 + 1429: -8,45 - node: color: '#FFFFFFFF' id: Remains decals: - 3318: -29.994413,-49.927315 + 3305: -29.994413,-49.927315 - node: color: '#60E25873' id: Rock01 decals: - 3377: -59.92391,38.210167 - 3378: -59.99335,38.974056 - 3379: -59.99335,39.946278 - 3380: -59.965576,41.015724 - 3381: -59.965576,42.321278 + 3364: -59.92391,38.210167 + 3365: -59.99335,38.974056 + 3366: -59.99335,39.946278 + 3367: -59.965576,41.015724 + 3368: -59.965576,42.321278 - node: color: '#9FED5896' id: Rock01 decals: - 3462: 24.034931,-33.3361 - 3463: 23.951597,-33.863876 + 3449: 24.034931,-33.3361 + 3450: 23.951597,-33.863876 - node: color: '#9FED5873' id: Rock02 decals: - 3311: 78.26405,7.9695406 - 3312: 79.31961,7.983429 - 3313: 79.93072,7.941762 - 3314: 78.26405,7.9556513 + 3298: 78.26405,7.9695406 + 3299: 79.31961,7.983429 + 3300: 79.93072,7.941762 + 3301: 78.26405,7.9556513 - node: color: '#9FED5896' id: Rock02 decals: - 3197: -40.422146,-22.63485 - 3198: -41.797146,-22.468182 - 3199: -42.797146,-21.815403 - 3200: -42.297146,-22.87096 - 3201: -43.158257,-18.593182 - 3202: -43.047146,-19.73207 - 3203: -40.61659,-18.329292 - 3204: -39.922146,-18.940403 - 3205: -39.797146,-22.565403 - 3206: -39.86659,-23.50985 - 3207: -41.283257,-21.787628 - 3208: -42.797146,-20.87096 - 3209: -42.7277,-17.940403 - 3210: -41.061035,-18.12096 - 3211: -41.21381,-19.176516 + 3184: -40.422146,-22.63485 + 3185: -41.797146,-22.468182 + 3186: -42.797146,-21.815403 + 3187: -42.297146,-22.87096 + 3188: -43.158257,-18.593182 + 3189: -43.047146,-19.73207 + 3190: -40.61659,-18.329292 + 3191: -39.922146,-18.940403 + 3192: -39.797146,-22.565403 + 3193: -39.86659,-23.50985 + 3194: -41.283257,-21.787628 + 3195: -42.797146,-20.87096 + 3196: -42.7277,-17.940403 + 3197: -41.061035,-18.12096 + 3198: -41.21381,-19.176516 - node: color: '#9FED5896' id: Rock05 decals: - 3458: 23.909931,-33.22499 - 3459: 24.007153,-33.9611 + 3445: 23.909931,-33.22499 + 3446: 24.007153,-33.9611 - node: color: '#FFFFFFFF' id: Rock05 decals: - 4774: -1.8656068,46.688976 + 4761: -1.8656068,46.688976 - node: color: '#FFFFFFFF' id: Rock07 decals: - 3317: -16.459831,-40.314075 + 3304: -16.459831,-40.314075 - node: cleanable: True color: '#FFFFFFFF' id: Rust decals: - 3292: -64,-33 - 3293: -65,-33 - 3294: -63,-33 + 3279: -64,-33 + 3280: -65,-33 + 3281: -63,-33 - node: color: '#B78FB4FF' id: SpaceStationSign1 decals: - 1543: 4,-4 + 1533: 4,-4 - node: color: '#B78FB4FF' id: SpaceStationSign2 decals: - 1544: 5,-4 + 1534: 5,-4 - node: color: '#B78FB4FF' id: SpaceStationSign3 decals: - 1545: 6,-4 + 1535: 6,-4 - node: color: '#B78FB4FF' id: SpaceStationSign4 decals: - 1546: 7,-4 + 1536: 7,-4 - node: color: '#B78FB4FF' id: SpaceStationSign5 decals: - 1547: 8,-4 + 1537: 8,-4 - node: color: '#B78FB4FF' id: SpaceStationSign6 decals: - 1548: 9,-4 + 1538: 9,-4 - node: color: '#B78FB4FF' id: SpaceStationSign7 decals: - 1549: 10,-4 + 1539: 10,-4 - node: color: '#A4610696' id: StandClear decals: - 3976: 34,20 - 3977: 34,19 - 3978: 34,20 - 3979: 34,19 - 3980: 39,20 - 3981: 39,19 - 3982: 39,20 - 3983: 39,19 + 3963: 34,20 + 3964: 34,19 + 3965: 34,20 + 3966: 34,19 + 3967: 39,20 + 3968: 39,19 + 3969: 39,20 + 3970: 39,19 - node: color: '#EFB34196' id: StandClear decals: - 462: 35,-2 - 463: 36,-2 - 464: 37,-2 - 719: 23,14 - 720: 23,13 - 721: 23,12 - 1043: 37,26 - 1551: 34,14 - 1552: 34,13 - 1553: 34,12 - 1554: 53,-26 - 1555: 53,-27 - 1556: 53,-28 - 1557: 53,-29 - 1558: 53,-30 - 1559: 53,-31 - 1560: 56,-31 - 1561: 56,-30 - 1562: 56,-29 - 1563: 56,-28 - 1564: 56,-27 - 1565: 56,-26 - 1630: -22,50 - 1631: -22,49 - 1632: -22,48 - 1633: -22,47 + 452: 35,-2 + 453: 36,-2 + 454: 37,-2 + 709: 23,14 + 710: 23,13 + 711: 23,12 + 1033: 37,26 + 1541: 34,14 + 1542: 34,13 + 1543: 34,12 + 1544: 53,-26 + 1545: 53,-27 + 1546: 53,-28 + 1547: 53,-29 + 1548: 53,-30 + 1549: 53,-31 + 1550: 56,-31 + 1551: 56,-30 + 1552: 56,-29 + 1553: 56,-28 + 1554: 56,-27 + 1555: 56,-26 + 1619: -22,50 + 1620: -22,49 + 1621: -22,48 + 1622: -22,47 - node: angle: 1.5707963267948966 rad color: '#EFB34196' id: StandClear decals: - 1235: -56,39 - 1236: -56,37 - 1237: -56,46 - 1238: -56,48 + 1225: -56,39 + 1226: -56,37 + 1227: -56,46 + 1228: -56,48 - node: color: '#52B4E996' id: StandClearGreyscale decals: - 4071: -3,-11 - 4072: -3,-12 - 4073: -1,-11 - 4074: -1,-12 - 4075: 15,-11 - 4076: 15,-12 - 4077: 17,-11 - 4078: 17,-12 - 4742: -27,17 - 4743: -27,18 - 4744: -25,18 - 4745: -25,17 + 4058: -3,-11 + 4059: -3,-12 + 4060: -1,-11 + 4061: -1,-12 + 4062: 15,-11 + 4063: 15,-12 + 4064: 17,-11 + 4065: 17,-12 + 4729: -27,17 + 4730: -27,18 + 4731: -25,18 + 4732: -25,17 - node: color: '#D381C996' id: StandClearGreyscale decals: - 3890: 25,54 - 3891: 25,55 - 3892: 21,55 - 3893: 21,54 - 3985: 16,64 - 3986: 18,68 - 3987: 19,68 - 3988: 23,72 - 3989: 24,72 - 4374: 25,79 - 4375: 25,78 - 4376: 28,79 - 4377: 28,78 - 4378: 32,79 - 4379: 32,78 - 4380: 32,77 + 3877: 25,54 + 3878: 25,55 + 3879: 21,55 + 3880: 21,54 + 3972: 16,64 + 3973: 18,68 + 3974: 19,68 + 3975: 23,72 + 3976: 24,72 + 4361: 25,79 + 4362: 25,78 + 4363: 28,79 + 4364: 28,78 + 4365: 32,79 + 4366: 32,78 + 4367: 32,77 - node: color: '#DE3A3A96' id: StandClearGreyscale decals: - 1618: 47,-14 - 1619: 47,-15 - 1620: 50,-18 - 1676: 41,1 - 1677: 39,1 - 1678: 39,-2 - 1679: 41,-2 + 1607: 47,-14 + 1608: 47,-15 + 1609: 50,-18 + 1665: 41,1 + 1666: 39,1 + 1667: 39,-2 + 1668: 41,-2 - node: color: '#D4D4D433' id: ThreeQuarterTileOverlayGreyscale decals: - 808: -43,-3 + 798: -43,-3 - node: color: '#DE3A3A96' id: ThreeQuarterTileOverlayGreyscale decals: 243: -28,-38 - 1460: 35,51 + 1450: 35,51 - node: color: '#D4D4D433' id: ThreeQuarterTileOverlayGreyscale180 decals: - 813: -3,-6 + 803: -3,-6 - node: color: '#DE3A3A96' id: ThreeQuarterTileOverlayGreyscale180 decals: 235: -27,-41 241: -22,-41 - 1214: -61,48 - 1458: 38,48 + 1204: -61,48 + 1448: 38,48 - node: color: '#D4D4D419' id: ThreeQuarterTileOverlayGreyscale270 decals: - 1197: -58,29 + 1187: -58,29 - node: color: '#D4D4D433' id: ThreeQuarterTileOverlayGreyscale270 decals: - 814: 17,-6 + 804: 17,-6 - node: color: '#DE3A3A96' id: ThreeQuarterTileOverlayGreyscale270 decals: 236: -25,-41 242: -28,-41 - 1459: 35,48 + 1449: 35,48 - node: color: '#D4D4D419' id: ThreeQuarterTileOverlayGreyscale90 decals: - 1313: 18,31 + 1303: 18,31 - node: color: '#D4D4D433' id: ThreeQuarterTileOverlayGreyscale90 decals: - 847: 21,-17 + 837: 21,-17 - node: color: '#DE3A3A96' id: ThreeQuarterTileOverlayGreyscale90 decals: 244: -22,-38 - 3485: 47,-3 + 3472: 47,-3 - node: color: '#FFFFFFFF' id: VentSmall decals: - 3571: -5,-1 + 3558: -5,-1 - node: color: '#79150096' id: WarnBox decals: - 1494: -52,-24 - 1495: -52,-25 - 3261: -6,13 - 3262: -6,13 - 3263: -6,14 - 3264: -6,14 - 3265: -6,15 - 3266: -6,15 - 3270: 30,13 - 3271: 30,12 - 3272: 30,13 - 3273: 30,12 + 1484: -52,-24 + 1485: -52,-25 + 3248: -6,13 + 3249: -6,13 + 3250: -6,14 + 3251: -6,14 + 3252: -6,15 + 3253: -6,15 + 3257: 30,13 + 3258: 30,12 + 3259: 30,13 + 3260: 30,12 - node: color: '#52B4E996' id: WarnBoxGreyscale decals: - 1496: -49,-25 - 1497: -49,-24 - 3267: 22,17 - 3268: 22,16 - 3269: 22,15 - 4925: -51,-38 - 4926: -49,-38 + 1486: -49,-25 + 1487: -49,-24 + 3254: 22,17 + 3255: 22,16 + 3256: 22,15 + 4912: -51,-38 + 4913: -49,-38 - node: color: '#EFB34196' id: WarnCornerNE decals: - 1003: 16,56 - 1102: 39,14 - 1424: -7,42 + 993: 16,56 + 1092: 39,14 + 1414: -7,42 - node: color: '#FFFFFFFF' id: WarnCornerNE decals: - 4849: 27,12 - 4853: -25,36 - 4857: 54,-15 + 4836: 27,12 + 4840: -25,36 + 4844: 54,-15 - node: color: '#EFB34196' id: WarnCornerNW decals: - 727: 24,14 - 1099: 35,14 + 717: 24,14 + 1089: 35,14 - node: color: '#FFFFFFFF' id: WarnCornerNW decals: - 4681: -29,16 - 4848: 25,12 - 4854: -28,36 - 4855: -10,41 + 4668: -29,16 + 4835: 25,12 + 4841: -28,36 + 4842: -10,41 - node: color: '#EFB34196' id: WarnCornerSE decals: - 1100: 39,12 - 1259: -22,32 - 1418: -7,46 - 3259: -2,43 + 1090: 39,12 + 1249: -22,32 + 1408: -7,46 + 3246: -2,43 - node: color: '#FFFFFFFF' id: WarnCornerSE decals: - 4666: 10,72 - 4858: 54,-17 + 4653: 10,72 + 4845: 54,-17 - node: color: '#EFB34196' id: WarnCornerSW decals: - 1101: 35,12 - 1260: -18,32 + 1091: 35,12 + 1250: -18,32 - node: color: '#FFFFFFFF' id: WarnCornerSW decals: - 4684: -29,19 - 4856: -10,40 + 4671: -29,19 + 4843: -10,40 - node: color: '#EFB34196' id: WarnCornerSmallNE decals: - 1489: -2,57 + 1479: -2,57 - node: color: '#FFFFFFFF' id: WarnCornerSmallNE decals: - 4818: 73,-5 - 4819: 73,-12 - 4879: -40,26 + 4805: 73,-5 + 4806: 73,-12 + 4866: -40,26 - node: color: '#EFB34196' id: WarnCornerSmallNW decals: - 641: -23,48 - 1488: 2,57 + 631: -23,48 + 1478: 2,57 - node: color: '#FFFFFFFF' id: WarnCornerSmallNW decals: - 4820: 85,-5 - 4821: 85,-12 - 4880: -41,26 + 4807: 85,-5 + 4808: 85,-12 + 4867: -41,26 - node: color: '#EFB34196' id: WarnCornerSmallSE decals: - 1486: -2,61 - 3246: 49,-20 - 3260: -2,44 + 1476: -2,61 + 3233: 49,-20 + 3247: -2,44 - node: color: '#FFFFFFFF' id: WarnCornerSmallSE decals: - 4816: 73,-3 - 4817: 73,-10 + 4803: 73,-3 + 4804: 73,-10 - node: color: '#EFB34196' id: WarnCornerSmallSW decals: - 999: 16,56 - 1487: 2,61 - 3247: 51,-20 + 989: 16,56 + 1477: 2,61 + 3234: 51,-20 - node: color: '#FFFFFFFF' id: WarnCornerSmallSW decals: - 4822: 85,-10 - 4823: 85,-3 + 4809: 85,-10 + 4810: 85,-3 - node: color: '#EFB34196' id: WarnEndE decals: - 1681: -19,-23 + 1670: -19,-23 - node: color: '#FFFFFFFF' id: WarnEndE decals: - 4665: 21,74 + 4652: 21,74 - node: color: '#FFFFFFFF' id: WarnEndN decals: - 4860: 40,-10 + 4847: 40,-10 - node: color: '#EFB34196' id: WarnEndS decals: - 3243: 49,-21 - 3244: 51,-21 + 3230: 49,-21 + 3231: 51,-21 - node: color: '#EFB34196' id: WarnEndW decals: - 1000: 13,56 - 1680: -20,-23 + 990: 13,56 + 1669: -20,-23 - node: color: '#FFFFFFFF' id: WarnEndW decals: - 4664: 20,74 + 4651: 20,74 - node: color: '#334E6DC8' id: WarnFullGreyscale decals: - 4740: -26,17 - 4741: -26,18 + 4727: -26,17 + 4728: -26,18 - node: color: '#EFB34196' id: WarnLineE decals: - 474: 74,14 - 475: 74,13 - 476: 74,12 - 477: 81,15 - 478: 81,14 - 479: 81,13 - 480: 81,12 - 487: 74,15 - 637: -23,50 - 638: -23,49 - 639: -23,48 - 640: -23,47 - 675: -10,38 - 676: -10,39 - 722: 22,14 - 723: 22,13 - 724: 22,12 - 991: 24,69 - 992: 20,60 - 1004: 16,55 - 1020: 17,65 - 1021: 17,64 - 1022: 17,63 - 1028: 24,69 - 1031: 20,60 - 1032: 15,64 - 1110: 39,13 - 1264: -22,33 - 1409: -7,38 - 1410: -7,39 - 1411: -7,40 - 1412: -7,41 - 1413: -7,47 - 1414: -7,48 - 1415: -7,49 - 1416: -7,50 - 1417: -7,51 - 1468: 33,12 - 1469: 33,13 - 1470: 33,14 - 1471: 33,12 - 1472: 33,13 - 1473: 33,14 - 1477: -2,58 - 1478: -2,59 - 1479: -2,60 - 1533: 47,33 - 1534: 47,34 - 1598: 62,-21 - 1612: 46,-14 - 1613: 46,-15 - 1614: 46,-14 - 1615: 46,-15 - 1623: 51,-17 - 1624: 51,-16 - 3248: 51,-20 - 3249: 51,-19 - 3894: 24,54 - 3895: 24,55 - 3898: 20,54 - 3899: 20,55 - 3900: 20,54 - 3901: 20,55 - 4350: 24,79 - 4351: 24,79 - 4352: 24,78 - 4353: 24,78 - 4366: 27,79 - 4367: 27,79 - 4368: 27,78 - 4369: 27,78 + 464: 74,14 + 465: 74,13 + 466: 74,12 + 467: 81,15 + 468: 81,14 + 469: 81,13 + 470: 81,12 + 477: 74,15 + 627: -23,50 + 628: -23,49 + 629: -23,48 + 630: -23,47 + 665: -10,38 + 666: -10,39 + 712: 22,14 + 713: 22,13 + 714: 22,12 + 981: 24,69 + 982: 20,60 + 994: 16,55 + 1010: 17,65 + 1011: 17,64 + 1012: 17,63 + 1018: 24,69 + 1021: 20,60 + 1022: 15,64 + 1100: 39,13 + 1254: -22,33 + 1399: -7,38 + 1400: -7,39 + 1401: -7,40 + 1402: -7,41 + 1403: -7,47 + 1404: -7,48 + 1405: -7,49 + 1406: -7,50 + 1407: -7,51 + 1458: 33,12 + 1459: 33,13 + 1460: 33,14 + 1461: 33,12 + 1462: 33,13 + 1463: 33,14 + 1467: -2,58 + 1468: -2,59 + 1469: -2,60 + 1523: 47,33 + 1524: 47,34 + 1588: 62,-21 + 1601: 46,-14 + 1602: 46,-15 + 1603: 46,-14 + 1604: 46,-15 + 1612: 51,-17 + 1613: 51,-16 + 3235: 51,-20 + 3236: 51,-19 + 3881: 24,54 + 3882: 24,55 + 3885: 20,54 + 3886: 20,55 + 3887: 20,54 + 3888: 20,55 + 4337: 24,79 + 4338: 24,79 + 4339: 24,78 + 4340: 24,78 + 4353: 27,79 + 4354: 27,79 + 4355: 27,78 + 4356: 27,78 - node: color: '#FFFFFFFF' id: WarnLineE decals: - 4457: 19,15 - 4458: 19,16 - 4459: 19,17 - 4668: 10,73 - 4669: 10,74 - 4670: 10,75 - 4671: 10,76 - 4814: 73,-11 - 4815: 73,-4 - 4828: -54,47 - 4829: -54,46 - 4830: -54,39 - 4831: -54,38 - 4859: 54,-16 - 4864: -40,27 + 4444: 19,15 + 4445: 19,16 + 4446: 19,17 + 4655: 10,73 + 4656: 10,74 + 4657: 10,75 + 4658: 10,76 + 4801: 73,-11 + 4802: 73,-4 + 4815: -54,47 + 4816: -54,46 + 4817: -54,39 + 4818: -54,38 + 4846: 54,-16 + 4851: -40,27 - node: color: '#DE3A3A96' id: WarnLineGreyscaleN decals: - 1570: 64,-22 - 1571: 65,-22 - 1572: 66,-22 - 1573: 67,-22 - 1574: 64,-21 - 1575: 64,-21 - 1576: 65,-21 - 1577: 65,-21 - 1578: 66,-21 - 1579: 66,-21 - 1580: 67,-21 - 1581: 67,-21 + 1560: 64,-22 + 1561: 65,-22 + 1562: 66,-22 + 1563: 67,-22 + 1564: 64,-21 + 1565: 64,-21 + 1566: 65,-21 + 1567: 65,-21 + 1568: 66,-21 + 1569: 66,-21 + 1570: 67,-21 + 1571: 67,-21 - node: color: '#D381C996' id: WarnLineGreyscaleS @@ -6677,94 +6677,94 @@ entities: color: '#DE3A3A96' id: WarnLineGreyscaleS decals: - 1566: 64,-20 - 1567: 65,-20 - 1568: 66,-20 - 1569: 67,-20 - 1582: 64,-21 - 1583: 64,-21 - 1584: 65,-21 - 1585: 65,-21 - 1586: 66,-21 - 1587: 66,-21 - 1588: 67,-21 - 1589: 67,-21 + 1556: 64,-20 + 1557: 65,-20 + 1558: 66,-20 + 1559: 67,-20 + 1572: 64,-21 + 1573: 64,-21 + 1574: 65,-21 + 1575: 65,-21 + 1576: 66,-21 + 1577: 66,-21 + 1578: 67,-21 + 1579: 67,-21 - node: color: '#EFB34196' id: WarnLineN decals: 311: -41,-26 - 623: -21,55 - 624: -20,55 - 985: 18,69 - 986: 19,69 - 997: 15,56 - 998: 14,56 - 1106: 36,12 - 1107: 37,12 - 1108: 38,12 - 1222: -62,53 - 1223: -58,53 - 1266: -27,32 - 1267: -26,32 - 1268: -25,32 - 1269: -24,32 - 1270: -23,32 - 1271: -17,32 - 1272: -16,32 - 1273: -15,32 - 1274: -14,32 - 1275: -13,32 - 1419: -8,46 - 1448: -23,55 - 1449: -24,55 - 1450: -25,55 - 1451: -26,55 - 1452: -27,55 - 1453: -28,55 - 1454: -29,55 - 1475: 0,52 - 1480: -1,61 - 1481: 0,61 - 1482: 1,61 - 1492: 23,54 - 1493: 24,54 - 1590: 64,-22 - 1591: 65,-22 - 1592: 66,-22 - 1593: 67,-22 - 1621: 50,-17 - 1664: -43,-17 - 1665: -42,-17 - 1666: -41,-17 - 3245: 50,-20 - 3254: 2,44 - 3255: 3,44 - 3256: 1,44 - 3257: 0,44 - 3258: -1,44 - 3295: 22,54 + 613: -21,55 + 614: -20,55 + 975: 18,69 + 976: 19,69 + 987: 15,56 + 988: 14,56 + 1096: 36,12 + 1097: 37,12 + 1098: 38,12 + 1212: -62,53 + 1213: -58,53 + 1256: -27,32 + 1257: -26,32 + 1258: -25,32 + 1259: -24,32 + 1260: -23,32 + 1261: -17,32 + 1262: -16,32 + 1263: -15,32 + 1264: -14,32 + 1265: -13,32 + 1409: -8,46 + 1438: -23,55 + 1439: -24,55 + 1440: -25,55 + 1441: -26,55 + 1442: -27,55 + 1443: -28,55 + 1444: -29,55 + 1465: 0,52 + 1470: -1,61 + 1471: 0,61 + 1472: 1,61 + 1482: 23,54 + 1483: 24,54 + 1580: 64,-22 + 1581: 65,-22 + 1582: 66,-22 + 1583: 67,-22 + 1610: 50,-17 + 1653: -43,-17 + 1654: -42,-17 + 1655: -41,-17 + 3232: 50,-20 + 3241: 2,44 + 3242: 3,44 + 3243: 1,44 + 3244: 0,44 + 3245: -1,44 + 3282: 22,54 - node: color: '#FFFFFFFF' id: WarnLineN decals: - 4667: 9,72 - 4685: -28,19 - 4824: 88,3 - 4836: -47,-50 - 4837: -48,-50 - 4838: 10,-51 - 4839: 9,-51 - 4861: 55,0 - 4862: 56,0 - 4871: -44,26 - 4872: -43,26 - 4873: -42,26 - 4874: -41,26 - 4875: -40,26 - 4876: -39,26 - 4877: -38,26 - 4878: -37,26 + 4654: 9,72 + 4672: -28,19 + 4811: 88,3 + 4823: -47,-50 + 4824: -48,-50 + 4825: 10,-51 + 4826: 9,-51 + 4848: 55,0 + 4849: 56,0 + 4858: -44,26 + 4859: -43,26 + 4860: -42,26 + 4861: -41,26 + 4862: -40,26 + 4863: -39,26 + 4864: -38,26 + 4865: -37,26 - node: color: '#EFB34196' id: WarnLineS @@ -6772,391 +6772,391 @@ entities: 308: -40,-27 309: -40,-28 310: -40,-29 - 481: 77,14 - 482: 77,13 - 483: 77,12 - 484: 84,15 - 485: 84,13 - 486: 84,12 - 488: 77,15 - 558: -8,45 - 559: -8,44 - 560: -8,43 - 635: -23,49 - 636: -23,50 - 725: 24,13 - 726: 24,12 - 993: 18,55 - 994: 18,56 - 995: 16,53 - 996: 16,55 - 1005: 16,54 - 1023: 17,64 - 1029: 18,56 - 1030: 18,55 - 1033: 14,63 - 1034: 14,64 - 1035: 14,65 - 1109: 35,13 - 1265: -18,33 - 1420: -8,45 - 1421: -8,44 - 1422: -8,43 - 1483: 2,60 - 1484: 2,59 - 1485: 2,58 - 1616: 48,-15 - 1617: 48,-14 - 3250: 49,-20 - 3251: 49,-19 - 3252: 30,66 - 3253: 30,66 - 3305: 84,14 - 3896: 22,55 - 3897: 22,54 - 4354: 29,79 - 4355: 29,79 - 4356: 29,78 - 4357: 29,78 - 4370: 26,79 - 4371: 26,79 - 4372: 26,78 - 4373: 26,78 - 4415: 26,54 - 4416: 26,55 + 471: 77,14 + 472: 77,13 + 473: 77,12 + 474: 84,15 + 475: 84,13 + 476: 84,12 + 478: 77,15 + 548: -8,45 + 549: -8,44 + 550: -8,43 + 625: -23,49 + 626: -23,50 + 715: 24,13 + 716: 24,12 + 983: 18,55 + 984: 18,56 + 985: 16,53 + 986: 16,55 + 995: 16,54 + 1013: 17,64 + 1019: 18,56 + 1020: 18,55 + 1023: 14,63 + 1024: 14,64 + 1025: 14,65 + 1099: 35,13 + 1255: -18,33 + 1410: -8,45 + 1411: -8,44 + 1412: -8,43 + 1473: 2,60 + 1474: 2,59 + 1475: 2,58 + 1605: 48,-15 + 1606: 48,-14 + 3237: 49,-20 + 3238: 49,-19 + 3239: 30,66 + 3240: 30,66 + 3292: 84,14 + 3883: 22,55 + 3884: 22,54 + 4341: 29,79 + 4342: 29,79 + 4343: 29,78 + 4344: 29,78 + 4357: 26,79 + 4358: 26,79 + 4359: 26,78 + 4360: 26,78 + 4402: 26,54 + 4403: 26,55 - node: color: '#FFFFFFFF' id: WarnLineS decals: - 4682: -29,15 - 4683: -29,20 - 4812: 85,-11 - 4813: 85,-4 - 4826: -54,46 - 4827: -54,47 - 4832: -54,39 - 4833: -54,38 - 4863: -41,27 + 4669: -29,15 + 4670: -29,20 + 4799: 85,-11 + 4800: 85,-4 + 4813: -54,46 + 4814: -54,47 + 4819: -54,39 + 4820: -54,38 + 4850: -41,27 - node: color: '#EFB34196' id: WarnLineW decals: - 471: 35,-2 - 472: 36,-2 - 473: 37,-2 - 555: -21,33 - 556: -20,33 - 557: -19,33 - 627: -21,56 - 628: -20,56 - 629: -29,48 - 630: -28,48 - 631: -27,48 - 632: -26,48 - 633: -25,48 - 634: -24,48 - 697: 25,14 - 698: 26,14 - 699: 27,14 - 700: 28,14 - 981: 18,69 - 982: 19,69 - 983: 20,69 - 984: 21,69 - 987: 18,67 - 988: 19,67 - 989: 23,71 - 990: 24,71 - 1001: 14,56 - 1002: 15,56 - 1024: 18,67 - 1025: 19,67 - 1026: 23,71 - 1027: 24,71 - 1103: 36,14 - 1104: 37,14 - 1105: 38,14 - 1221: -62,51 - 1261: -21,33 - 1262: -20,33 - 1263: -19,33 - 1423: -8,42 - 1474: 0,53 - 1476: -1,57 - 1490: 23,55 - 1491: 24,55 - 1594: 64,-20 - 1595: 65,-20 - 1596: 66,-20 - 1597: 67,-20 - 1622: 50,-19 - 3296: 22,55 - 3836: 0,57 - 3837: 1,57 + 461: 35,-2 + 462: 36,-2 + 463: 37,-2 + 545: -21,33 + 546: -20,33 + 547: -19,33 + 617: -21,56 + 618: -20,56 + 619: -29,48 + 620: -28,48 + 621: -27,48 + 622: -26,48 + 623: -25,48 + 624: -24,48 + 687: 25,14 + 688: 26,14 + 689: 27,14 + 690: 28,14 + 971: 18,69 + 972: 19,69 + 973: 20,69 + 974: 21,69 + 977: 18,67 + 978: 19,67 + 979: 23,71 + 980: 24,71 + 991: 14,56 + 992: 15,56 + 1014: 18,67 + 1015: 19,67 + 1016: 23,71 + 1017: 24,71 + 1093: 36,14 + 1094: 37,14 + 1095: 38,14 + 1211: -62,51 + 1251: -21,33 + 1252: -20,33 + 1253: -19,33 + 1413: -8,42 + 1464: 0,53 + 1466: -1,57 + 1480: 23,55 + 1481: 24,55 + 1584: 64,-20 + 1585: 65,-20 + 1586: 66,-20 + 1587: 67,-20 + 1611: 50,-19 + 3283: 22,55 + 3823: 0,57 + 3824: 1,57 - node: color: '#FFFFFFFF' id: WarnLineW decals: - 4672: 18,71 - 4673: 19,71 - 4674: 20,71 - 4675: 21,71 - 4676: 18,69 - 4677: 19,69 - 4678: 20,69 - 4679: 21,69 - 4686: -28,16 - 4784: 86,-3 - 4785: 85,-3 - 4786: 73,-3 - 4787: 72,-3 - 4825: 88,3 - 4834: -47,-50 - 4835: -48,-50 - 4840: 10,-51 - 4841: 9,-51 - 4850: 26,12 - 4851: -27,36 - 4852: -26,36 - 4865: -44,26 - 4866: -43,26 - 4867: -42,26 - 4868: -39,26 - 4869: -38,26 - 4870: -37,26 + 4659: 18,71 + 4660: 19,71 + 4661: 20,71 + 4662: 21,71 + 4663: 18,69 + 4664: 19,69 + 4665: 20,69 + 4666: 21,69 + 4673: -28,16 + 4771: 86,-3 + 4772: 85,-3 + 4773: 73,-3 + 4774: 72,-3 + 4812: 88,3 + 4821: -47,-50 + 4822: -48,-50 + 4827: 10,-51 + 4828: 9,-51 + 4837: 26,12 + 4838: -27,36 + 4839: -26,36 + 4852: -44,26 + 4853: -43,26 + 4854: -42,26 + 4855: -39,26 + 4856: -38,26 + 4857: -37,26 - node: color: '#FFFFFFFF' id: WoodTrimThinCornerNe decals: - 3464: -25,-19 - 3559: 13,-18 + 3451: -25,-19 + 3546: 13,-18 - node: color: '#FFFFFFFF' id: WoodTrimThinCornerNw decals: - 3686: 30,-18 + 3673: 30,-18 - node: color: '#FFFFFFFF' id: WoodTrimThinCornerSe decals: - 3558: 13,-19 + 3545: 13,-19 - node: color: '#FFFFFFFF' id: WoodTrimThinCornerSw decals: - 3563: 9,-19 - 3691: 30,-23 + 3550: 9,-19 + 3678: 30,-23 - node: color: '#FFFFFFFF' id: WoodTrimThinEndN decals: - 3561: 9,-17 + 3548: 9,-17 - node: color: '#FFFFFFFF' id: WoodTrimThinInnerNe decals: - 3565: 9,-18 - 3819: -11,33 + 3552: 9,-18 + 3806: -11,33 - node: color: '#FFFFFFFF' id: WoodTrimThinInnerNw decals: - 3817: -8,33 + 3804: -8,33 - node: color: '#FFFFFFFF' id: WoodTrimThinInnerSe decals: - 3818: -11,36 - 4311: -18,-10 - 4312: -18,-9 + 3805: -11,36 + 4298: -18,-10 + 4299: -18,-9 - node: color: '#FFFFFFFF' id: WoodTrimThinInnerSw decals: - 3816: -8,36 + 3803: -8,36 - node: color: '#FFFFFFFF' id: WoodTrimThinLineE decals: - 3467: -25,-20 - 3468: -25,-21 - 3810: -11,34 - 3811: -11,35 + 3454: -25,-20 + 3455: -25,-21 + 3797: -11,34 + 3798: -11,35 - node: color: '#FFFFFFFF' id: WoodTrimThinLineN decals: - 3422: -2,-46 - 3423: -1,-46 - 3424: 0,-46 - 3425: 1,-46 - 3426: -3,-42 - 3427: -2,-42 - 3428: -1,-42 - 3429: 0,-42 - 3430: 1,-42 - 3465: -26,-19 - 3466: -27,-19 - 3482: -21,-13 - 3560: 12,-18 - 3687: 31,-18 - 3688: 32,-18 - 3689: 33,-18 - 3690: 34,-18 - 3808: -10,33 - 3809: -9,33 + 3409: -2,-46 + 3410: -1,-46 + 3411: 0,-46 + 3412: 1,-46 + 3413: -3,-42 + 3414: -2,-42 + 3415: -1,-42 + 3416: 0,-42 + 3417: 1,-42 + 3452: -26,-19 + 3453: -27,-19 + 3469: -21,-13 + 3547: 12,-18 + 3674: 31,-18 + 3675: 32,-18 + 3676: 33,-18 + 3677: 34,-18 + 3795: -10,33 + 3796: -9,33 - node: color: '#FFFFFFFF' id: WoodTrimThinLineS decals: - 3431: -3,-44 - 3432: -2,-44 - 3433: -1,-44 - 3434: 0,-44 - 3435: 1,-44 - 3436: -3,-48 - 3437: -2,-48 - 3438: -1,-48 - 3439: 0,-48 - 3440: 1,-48 - 3441: -12,-32 - 3564: 12,-19 - 3692: 31,-23 - 3693: 32,-23 - 3694: 33,-23 - 3695: 34,-23 - 3814: -10,36 - 3815: -9,36 + 3418: -3,-44 + 3419: -2,-44 + 3420: -1,-44 + 3421: 0,-44 + 3422: 1,-44 + 3423: -3,-48 + 3424: -2,-48 + 3425: -1,-48 + 3426: 0,-48 + 3427: 1,-48 + 3428: -12,-32 + 3551: 12,-19 + 3679: 31,-23 + 3680: 32,-23 + 3681: 33,-23 + 3682: 34,-23 + 3801: -10,36 + 3802: -9,36 - node: color: '#FFFFFFFF' id: WoodTrimThinLineW decals: - 3416: -3,-42 - 3417: -3,-43 - 3418: -3,-44 - 3419: -3,-46 - 3420: -3,-47 - 3421: -3,-48 - 3476: -21,-13 - 3477: -21,-14 - 3478: -21,-15 - 3479: -21,-16 - 3480: -21,-17 - 3481: -21,-18 - 3562: 9,-18 - 3681: 30,-22 - 3682: 30,-21 - 3683: 30,-20 - 3684: 30,-19 - 3685: 23,-21 - 3812: -8,34 - 3813: -8,35 + 3403: -3,-42 + 3404: -3,-43 + 3405: -3,-44 + 3406: -3,-46 + 3407: -3,-47 + 3408: -3,-48 + 3463: -21,-13 + 3464: -21,-14 + 3465: -21,-15 + 3466: -21,-16 + 3467: -21,-17 + 3468: -21,-18 + 3549: 9,-18 + 3668: 30,-22 + 3669: 30,-21 + 3670: 30,-20 + 3671: 30,-19 + 3672: 23,-21 + 3799: -8,34 + 3800: -8,35 - node: color: '#9FED5896' id: bushsnowa1 decals: - 3183: -41.436035,-22.25985 - 3184: -41.283257,-23.079292 - 3185: -40.255478,-23.398739 - 3186: -40.019367,-18.10707 - 3187: -41.005478,-18.926516 - 3188: -43.061035,-18.00985 - 3189: -43.130478,-18.718182 - 3190: -43.07492,-19.940405 - 3191: -43.1027,-21.551517 - 3192: -41.880478,-23.204292 - 3193: -40.172146,-23.787628 - 3194: -41.11659,-23.75985 - 3195: -39.880478,-22.273739 - 3196: -40.130478,-19.079292 + 3170: -41.436035,-22.25985 + 3171: -41.283257,-23.079292 + 3172: -40.255478,-23.398739 + 3173: -40.019367,-18.10707 + 3174: -41.005478,-18.926516 + 3175: -43.061035,-18.00985 + 3176: -43.130478,-18.718182 + 3177: -43.07492,-19.940405 + 3178: -43.1027,-21.551517 + 3179: -41.880478,-23.204292 + 3180: -40.172146,-23.787628 + 3181: -41.11659,-23.75985 + 3182: -39.880478,-22.273739 + 3183: -40.130478,-19.079292 - node: color: '#9FED5896' id: bushsnowb3 decals: - 3460: 24.076597,-33.183323 - 3461: 23.937708,-34.09999 + 3447: 24.076597,-33.183323 + 3448: 23.937708,-34.09999 - node: color: '#A4DF8296' id: bushsnowb3 decals: - 1694: -7.3679967,-22.387566 - 1695: -9.20133,-22.69312 - 1696: -9.062441,-23.859787 - 1697: -7.2291064,-23.637566 - 1698: -8.423552,-23.276455 + 1683: -7.3679967,-22.387566 + 1684: -9.20133,-22.69312 + 1685: -9.062441,-23.859787 + 1686: -7.2291064,-23.637566 + 1687: -8.423552,-23.276455 - node: color: '#9FED5896' id: grasssnow07 decals: - 3309: 78.19461,7.941762 - 3310: 79.52794,7.9139843 + 3296: 78.19461,7.941762 + 3297: 79.52794,7.9139843 - node: color: '#60AC5863' id: grasssnow09 decals: - 3328: -12.979685,-40.336945 - 3329: -11.368574,-40.225834 - 3330: -11.4657955,-39.059166 - 3331: -13.701906,-39.198055 - 3332: -12.507462,-39.503613 - 3333: -12.799128,-40.614723 + 3315: -12.979685,-40.336945 + 3316: -11.368574,-40.225834 + 3317: -11.4657955,-39.059166 + 3318: -13.701906,-39.198055 + 3319: -12.507462,-39.503613 + 3320: -12.799128,-40.614723 - node: color: '#9FED587C' id: grasssnow09 decals: - 3327: -13.604685,-40.086945 + 3314: -13.604685,-40.086945 - node: color: '#60FF5D92' id: grasssnow10 decals: - 4511: -19.105085,3.5241327 - 4512: -19.957012,2.1050215 - 4513: -19.829224,0.3878975 + 4498: -19.105085,3.5241327 + 4499: -19.957012,2.1050215 + 4500: -19.829224,0.3878975 - node: color: '#9FED587C' id: grasssnow10 decals: - 3319: -13.5907955,-40.670277 - 3320: -12.229685,-40.475834 - 3321: -11.354685,-39.475834 - 3322: -13.813017,-39.350834 - 3323: -12.826906,-39.614723 - 3324: -11.271351,-40.698055 - 3325: -11.41024,-38.989723 - 3326: -12.979685,-38.961945 + 3306: -13.5907955,-40.670277 + 3307: -12.229685,-40.475834 + 3308: -11.354685,-39.475834 + 3309: -13.813017,-39.350834 + 3310: -12.826906,-39.614723 + 3311: -11.271351,-40.698055 + 3312: -11.41024,-38.989723 + 3313: -12.979685,-38.961945 - node: color: '#A4DF8296' id: grasssnow10 decals: - 1684: -7.4220443,-1.9321766 + 1673: -7.4220443,-1.9321766 - node: color: '#A4DF8296' id: grasssnowc1 decals: - 1685: -6.4220433,-1.9599552 + 1674: -6.4220433,-1.9599552 - node: color: '#60E2588B' id: grasssnowc3 decals: - 3348: -15.396351,-36.573055 - 3349: -17.549128,-36.656387 - 3350: -17.604685,-37.795277 - 3351: -16.007462,-37.8925 - 3352: -16.354685,-36.698055 - 3353: -15.299128,-37.6425 - 3354: -16.118574,-37.031387 + 3335: -15.396351,-36.573055 + 3336: -17.549128,-36.656387 + 3337: -17.604685,-37.795277 + 3338: -16.007462,-37.8925 + 3339: -16.354685,-36.698055 + 3340: -15.299128,-37.6425 + 3341: -16.118574,-37.031387 - node: cleanable: True color: '#800080FF' id: prolizard decals: - 4680: 27.413673,-33.665314 + 4667: 27.413673,-33.665314 - node: color: '#9FED5896' id: shop decals: - 3286: -4,-42 - 3287: -4,-48 + 3273: -4,-42 + 3274: -4,-48 type: DecalGrid - version: 2 data: @@ -38285,6 +38285,16 @@ entities: - pos: 16.5,-18.5 parent: 82 type: Transform + - uid: 22707 + components: + - pos: 40.5,-19.5 + parent: 82 + type: Transform + - uid: 22712 + components: + - pos: 40.5,-20.5 + parent: 82 + type: Transform - uid: 22740 components: - pos: -36.5,37.5 @@ -46965,6 +46975,11 @@ entities: - pos: -3.5,-13.5 parent: 82 type: Transform + - uid: 22959 + components: + - pos: -25.5,45.5 + parent: 82 + type: Transform - uid: 22970 components: - pos: -2.5,-13.5 @@ -47359,6 +47374,51 @@ entities: - pos: -34.5,-25.5 parent: 82 type: Transform + - uid: 2731 + components: + - pos: -22.5,53.5 + parent: 82 + type: Transform + - uid: 2757 + components: + - pos: -27.5,56.5 + parent: 82 + type: Transform + - uid: 2819 + components: + - pos: -23.5,53.5 + parent: 82 + type: Transform + - uid: 2839 + components: + - pos: -24.5,53.5 + parent: 82 + type: Transform + - uid: 2846 + components: + - pos: -25.5,53.5 + parent: 82 + type: Transform + - uid: 2847 + components: + - pos: -26.5,53.5 + parent: 82 + type: Transform + - uid: 2869 + components: + - pos: -27.5,55.5 + parent: 82 + type: Transform + - uid: 3147 + components: + - pos: -27.5,53.5 + parent: 82 + type: Transform + - uid: 3148 + components: + - pos: -27.5,54.5 + parent: 82 + type: Transform - uid: 3869 components: - pos: -11.5,4.5 @@ -47494,6 +47554,11 @@ entities: - pos: -11.5,-5.5 parent: 82 type: Transform + - uid: 5620 + components: + - pos: -26.5,57.5 + parent: 82 + type: Transform - uid: 5644 components: - pos: -34.5,64.5 @@ -47754,6 +47819,11 @@ entities: - pos: -35.5,64.5 parent: 82 type: Transform + - uid: 5729 + components: + - pos: -27.5,57.5 + parent: 82 + type: Transform - uid: 5732 components: - pos: -22.5,56.5 @@ -47761,47 +47831,12 @@ entities: type: Transform - uid: 5733 components: - - pos: -22.5,55.5 + - pos: -27.5,59.5 parent: 82 type: Transform - uid: 5734 components: - - pos: -22.5,54.5 - parent: 82 - type: Transform - - uid: 5735 - components: - - pos: -21.5,54.5 - parent: 82 - type: Transform - - uid: 5736 - components: - - pos: -20.5,54.5 - parent: 82 - type: Transform - - uid: 5737 - components: - - pos: -20.5,55.5 - parent: 82 - type: Transform - - uid: 5738 - components: - - pos: -20.5,56.5 - parent: 82 - type: Transform - - uid: 5739 - components: - - pos: -20.5,57.5 - parent: 82 - type: Transform - - uid: 5740 - components: - - pos: -20.5,58.5 - parent: 82 - type: Transform - - uid: 5741 - components: - - pos: -20.5,59.5 + - pos: -27.5,58.5 parent: 82 type: Transform - uid: 5776 @@ -47909,16 +47944,6 @@ entities: - pos: -21.5,79.5 parent: 82 type: Transform - - uid: 6738 - components: - - pos: -23.5,55.5 - parent: 82 - type: Transform - - uid: 6739 - components: - - pos: -23.5,54.5 - parent: 82 - type: Transform - uid: 6740 components: - pos: -23.5,56.5 @@ -47929,16 +47954,6 @@ entities: - pos: -23.5,57.5 parent: 82 type: Transform - - uid: 6742 - components: - - pos: -23.5,58.5 - parent: 82 - type: Transform - - uid: 6743 - components: - - pos: -23.5,59.5 - parent: 82 - type: Transform - uid: 6744 components: - pos: -23.5,60.5 @@ -48054,6 +48069,11 @@ entities: - pos: -34.5,72.5 parent: 82 type: Transform + - uid: 11206 + components: + - pos: -20.5,53.5 + parent: 82 + type: Transform - uid: 11218 components: - pos: -30.5,80.5 @@ -51909,6 +51929,11 @@ entities: - pos: -17.5,76.5 parent: 82 type: Transform + - uid: 21689 + components: + - pos: -21.5,53.5 + parent: 82 + type: Transform - uid: 21843 components: - pos: 0.5,40.5 @@ -52309,6 +52334,36 @@ entities: - pos: 1.5,63.5 parent: 82 type: Transform + - uid: 22934 + components: + - pos: -20.5,54.5 + parent: 82 + type: Transform + - uid: 22935 + components: + - pos: -20.5,55.5 + parent: 82 + type: Transform + - uid: 22936 + components: + - pos: -20.5,56.5 + parent: 82 + type: Transform + - uid: 22937 + components: + - pos: -20.5,57.5 + parent: 82 + type: Transform + - uid: 22943 + components: + - pos: -20.5,58.5 + parent: 82 + type: Transform + - uid: 22958 + components: + - pos: -20.5,59.5 + parent: 82 + type: Transform - uid: 24163 components: - pos: -13.5,48.5 @@ -52710,6 +52765,13 @@ entities: - pos: 58.456696,-37.53437 parent: 82 type: Transform +- proto: CannedApplauseInstrument + entities: + - uid: 8618 + components: + - pos: -42.56837,12.580838 + parent: 82 + type: Transform - proto: CapacitorStockPart entities: - uid: 9432 @@ -61920,15 +61982,6 @@ entities: - pos: 13.647984,38.49309 parent: 82 type: Transform -- proto: Claymore - entities: - - uid: 25509 - components: - - name: Maintscalibur - type: MetaData - - pos: 33.46861,68.93209 - parent: 82 - type: Transform - proto: CloningConsoleComputerCircuitboard entities: - uid: 19831 @@ -64352,7 +64405,7 @@ entities: type: EntityStorage - uid: 22642 components: - - pos: -18.5,54.5 + - pos: -19.77381,54.505054 parent: 82 type: Transform - air: @@ -64375,9 +64428,11 @@ entities: type: EntityStorage - uid: 22643 components: - - pos: -18.5,53.5 + - pos: -18.250603,54.50595 parent: 82 type: Transform + - sleepTime: 0.049999803 + type: Physics - air: volume: 200 immutable: False @@ -65179,13 +65234,6 @@ entities: - pos: -9.140789,-47.293507 parent: 82 type: Transform -- proto: ClothingBackpackMerc - entities: - - uid: 19820 - components: - - pos: 20.916914,-91.30483 - parent: 82 - type: Transform - proto: ClothingBeltChampion entities: - uid: 4365 @@ -65201,13 +65249,6 @@ entities: pos: 46.357616,16.331951 parent: 82 type: Transform -- proto: ClothingBeltMercWebbing - entities: - - uid: 6372 - components: - - pos: 20.291391,-103.31173 - parent: 82 - type: Transform - proto: ClothingBeltUtilityFilled entities: - uid: 6412 @@ -65267,13 +65308,6 @@ entities: - pos: 39.829994,-14.370501 parent: 82 type: Transform -- proto: ClothingEyesGlassesMercenary - entities: - - uid: 5386 - components: - - pos: 20.651289,-91.50796 - parent: 82 - type: Transform - proto: ClothingEyesGlassesMeson entities: - uid: 6410 @@ -66020,13 +66054,6 @@ entities: - pos: 33.54575,56.683422 parent: 82 type: Transform -- proto: ClothingOuterVestWebMerc - entities: - - uid: 20497 - components: - - pos: 20.541391,-103.546104 - parent: 82 - type: Transform - proto: ClothingOuterWinterCargo entities: - uid: 19400 @@ -66279,13 +66306,6 @@ entities: - pos: 60.777298,-16.464449 parent: 82 type: Transform -- proto: ClothingUniformJumpsuitMercenary - entities: - - uid: 20144 - components: - - pos: 20.557539,-91.30483 - parent: 82 - type: Transform - proto: ClothingUniformJumpsuitNanotrasen entities: - uid: 8620 @@ -66873,6 +66893,11 @@ entities: - pos: -51.5,12.5 parent: 82 type: Transform + - uid: 22960 + components: + - pos: -25.5,45.5 + parent: 82 + type: Transform - proto: ComputerRadar entities: - uid: 2245 @@ -117601,13 +117626,6 @@ entities: - pos: -15.03525,21.629791 parent: 82 type: Transform -- proto: KukriKnife - entities: - - uid: 8825 - components: - - pos: 20.432016,-103.4957 - parent: 82 - type: Transform - proto: Lamp entities: - uid: 19045 @@ -120595,9 +120613,11 @@ entities: type: Transform - uid: 10013 components: - - pos: -21.5,59.5 + - pos: -21.601662,59.538593 parent: 82 type: Transform + - sleepTime: 0.0166666 + type: Physics - uid: 11881 components: - pos: -51.5,10.5 @@ -120898,6 +120918,13 @@ entities: type: Transform - proto: PaperOffice entities: + - uid: 5386 + components: + - pos: 33.503384,69.00901 + parent: 82 + type: Transform + - content: Made you look. + type: Paper - uid: 10996 components: - pos: -34.351803,-28.541927 @@ -127120,69 +127147,71 @@ entities: type: Transform - proto: RadiationCollector entities: - - uid: 5620 - components: - - pos: -33.5,73.5 - parent: 82 - type: Transform - - uid: 5729 - components: - - pos: -33.5,75.5 - parent: 82 - type: Transform - - uid: 5847 - components: - - pos: -33.5,74.5 - parent: 82 - type: Transform - - uid: 5992 - components: - - pos: -33.5,70.5 - parent: 82 - type: Transform - - uid: 6175 - components: - - pos: -33.5,69.5 - parent: 82 - type: Transform - uid: 7097 components: - pos: -28.5,52.5 parent: 82 type: Transform - - uid: 11225 - components: - - pos: -17.5,70.5 - parent: 82 - type: Transform - - uid: 11442 - components: - - pos: -33.5,71.5 - parent: 82 - type: Transform - - uid: 21689 - components: - - pos: -17.5,73.5 - parent: 82 - type: Transform - - uid: 21722 - components: - - pos: -17.5,69.5 - parent: 82 - type: Transform - - uid: 22707 +- proto: RadiationCollectorFullTank + entities: + - uid: 5735 components: - pos: -17.5,71.5 parent: 82 type: Transform - - uid: 22712 + - uid: 5736 + components: + - pos: -17.5,69.5 + parent: 82 + type: Transform + - uid: 5737 + components: + - pos: -17.5,70.5 + parent: 82 + type: Transform + - uid: 5738 + components: + - pos: -17.5,74.5 + parent: 82 + type: Transform + - uid: 5739 components: - pos: -17.5,75.5 parent: 82 type: Transform - - uid: 22736 + - uid: 5740 components: - - pos: -17.5,74.5 + - pos: -33.5,70.5 + parent: 82 + type: Transform + - uid: 5741 + components: + - pos: -17.5,73.5 + parent: 82 + type: Transform + - uid: 5847 + components: + - pos: -33.5,73.5 + parent: 82 + type: Transform + - uid: 5992 + components: + - pos: -33.5,69.5 + parent: 82 + type: Transform + - uid: 6175 + components: + - pos: -33.5,71.5 + parent: 82 + type: Transform + - uid: 6738 + components: + - pos: -33.5,75.5 + parent: 82 + type: Transform + - uid: 6739 + components: + - pos: -33.5,74.5 parent: 82 type: Transform - proto: RadioHandheld @@ -138657,7 +138686,7 @@ entities: type: Transform - uid: 6034 components: - - pos: -23.5,49.5 + - pos: -25.5,72.5 parent: 82 type: Transform - proto: Sink @@ -141973,6 +142002,8 @@ entities: type: Transform - setupAvailableNetworks: - SurveillanceCameraEngineering + nameSet: True + id: Reception type: SurveillanceCamera - uid: 3849 components: @@ -142382,6 +142413,28 @@ entities: nameSet: True id: 'Checkpoint: Evac' type: SurveillanceCamera + - uid: 6372 + components: + - rot: 3.141592653589793 rad + pos: 41.5,-21.5 + parent: 82 + type: Transform + - setupAvailableNetworks: + - SurveillanceCameraSecurity + nameSet: True + id: Brig Exterior + type: SurveillanceCamera + - uid: 8825 + components: + - rot: 1.5707963267948966 rad + pos: 52.5,-24.5 + parent: 82 + type: Transform + - setupAvailableNetworks: + - SurveillanceCameraSecurity + nameSet: True + id: Armory Exterior + type: SurveillanceCamera - uid: 11474 components: - rot: 3.141592653589793 rad @@ -142423,7 +142476,7 @@ entities: - setupAvailableNetworks: - SurveillanceCameraSecurity nameSet: True - id: Brig + id: Permabrig type: SurveillanceCamera - uid: 21766 components: @@ -142433,6 +142486,8 @@ entities: type: Transform - setupAvailableNetworks: - SurveillanceCameraSecurity + nameSet: True + id: Shooting range hallway type: SurveillanceCamera - uid: 21771 components: @@ -145615,7 +145670,7 @@ entities: type: Transform - uid: 9682 components: - - pos: 20.601238,-103.10646 + - pos: 20.478569,-103.253105 parent: 82 type: Transform - uid: 11932 @@ -145948,13 +146003,6 @@ entities: - pos: 42.55547,-8.463266 parent: 82 type: Transform -- proto: VehicleKeySyndicateSegway - entities: - - uid: 8618 - components: - - pos: -42.48091,12.587237 - parent: 82 - type: Transform - proto: VendingBarDrobe entities: - uid: 4252 @@ -166018,6 +166066,17 @@ entities: pos: -59.5,39.5 parent: 82 type: Transform + - uid: 6742 + components: + - rot: 3.141592653589793 rad + pos: -39.5,-39.5 + parent: 82 + type: Transform + - uid: 6743 + components: + - pos: -38.5,-35.5 + parent: 82 + type: Transform - uid: 7927 components: - pos: 79.5,8.5 @@ -166137,6 +166196,23 @@ entities: pos: -17.5,-35.5 parent: 82 type: Transform + - uid: 11205 + components: + - rot: 1.5707963267948966 rad + pos: -36.5,-39.5 + parent: 82 + type: Transform + - uid: 11225 + components: + - rot: -1.5707963267948966 rad + pos: -30.5,-38.5 + parent: 82 + type: Transform + - uid: 11442 + components: + - pos: -35.5,-37.5 + parent: 82 + type: Transform - uid: 12766 components: - pos: -6.5,-1.5 @@ -166184,6 +166260,17 @@ entities: pos: -59.5,39.5 parent: 82 type: Transform + - uid: 14895 + components: + - rot: -1.5707963267948966 rad + pos: -30.5,-36.5 + parent: 82 + type: Transform + - uid: 14897 + components: + - pos: -39.5,-35.5 + parent: 82 + type: Transform - uid: 15512 components: - pos: -58.5,-41.5 @@ -166212,12 +166299,81 @@ entities: pos: 79.5,8.5 parent: 82 type: Transform + - uid: 18582 + components: + - pos: -30.5,-36.5 + parent: 82 + type: Transform + - uid: 18617 + components: + - rot: -1.5707963267948966 rad + pos: -30.5,-39.5 + parent: 82 + type: Transform + - uid: 19812 + components: + - rot: 1.5707963267948966 rad + pos: -36.5,-38.5 + parent: 82 + type: Transform + - uid: 19820 + components: + - rot: -1.5707963267948966 rad + pos: -30.5,-34.5 + parent: 82 + type: Transform + - uid: 20144 + components: + - pos: -31.5,-37.5 + parent: 82 + type: Transform + - uid: 20497 + components: + - pos: -33.5,-37.5 + parent: 82 + type: Transform - uid: 20681 components: - rot: 3.141592653589793 rad pos: 78.5,8.5 parent: 82 type: Transform + - uid: 21722 + components: + - rot: 3.141592653589793 rad + pos: -38.5,-39.5 + parent: 82 + type: Transform + - uid: 22463 + components: + - rot: -1.5707963267948966 rad + pos: -30.5,-35.5 + parent: 82 + type: Transform + - uid: 22736 + components: + - rot: -1.5707963267948966 rad + pos: -37.5,-36.5 + parent: 82 + type: Transform + - uid: 22764 + components: + - rot: -1.5707963267948966 rad + pos: -37.5,-38.5 + parent: 82 + type: Transform + - uid: 22928 + components: + - rot: 1.5707963267948966 rad + pos: -34.5,-38.5 + parent: 82 + type: Transform + - uid: 22933 + components: + - rot: 1.5707963267948966 rad + pos: -34.5,-39.5 + parent: 82 + type: Transform - uid: 24769 components: - rot: 1.5707963267948966 rad @@ -166389,23 +166545,6 @@ entities: type: Transform - proto: WindowReinforcedDirectional entities: - - uid: 2731 - components: - - rot: -1.5707963267948966 rad - pos: -30.5,-39.5 - parent: 82 - type: Transform - - uid: 2757 - components: - - pos: -33.5,-37.5 - parent: 82 - type: Transform - - uid: 2819 - components: - - rot: 1.5707963267948966 rad - pos: -34.5,-38.5 - parent: 82 - type: Transform - uid: 2828 components: - rot: 1.5707963267948966 rad @@ -166430,39 +166569,6 @@ entities: pos: -32.5,-44.5 parent: 82 type: Transform - - uid: 2839 - components: - - pos: -35.5,-37.5 - parent: 82 - type: Transform - - uid: 2846 - components: - - rot: 3.141592653589793 rad - pos: -38.5,-39.5 - parent: 82 - type: Transform - - uid: 2847 - components: - - rot: 1.5707963267948966 rad - pos: -36.5,-39.5 - parent: 82 - type: Transform - - uid: 2869 - components: - - rot: -1.5707963267948966 rad - pos: -30.5,-36.5 - parent: 82 - type: Transform - - uid: 3147 - components: - - pos: -31.5,-37.5 - parent: 82 - type: Transform - - uid: 3148 - components: - - pos: -30.5,-36.5 - parent: 82 - type: Transform - uid: 3346 components: - rot: -1.5707963267948966 rad @@ -166603,18 +166709,6 @@ entities: pos: 64.5,-10.5 parent: 82 type: Transform - - uid: 11205 - components: - - rot: 3.141592653589793 rad - pos: -39.5,-39.5 - parent: 82 - type: Transform - - uid: 11206 - components: - - rot: 1.5707963267948966 rad - pos: -34.5,-39.5 - parent: 82 - type: Transform - uid: 11450 components: - rot: 1.5707963267948966 rad @@ -166633,17 +166727,6 @@ entities: pos: 69.5,-20.5 parent: 82 type: Transform - - uid: 14895 - components: - - rot: -1.5707963267948966 rad - pos: -30.5,-34.5 - parent: 82 - type: Transform - - uid: 14897 - components: - - pos: -38.5,-35.5 - parent: 82 - type: Transform - uid: 17772 components: - pos: 64.5,-16.5 @@ -166678,23 +166761,6 @@ entities: pos: 69.5,-22.5 parent: 82 type: Transform - - uid: 18582 - components: - - rot: 1.5707963267948966 rad - pos: -36.5,-38.5 - parent: 82 - type: Transform - - uid: 18617 - components: - - pos: -39.5,-35.5 - parent: 82 - type: Transform - - uid: 19812 - components: - - rot: -1.5707963267948966 rad - pos: -30.5,-38.5 - parent: 82 - type: Transform - uid: 20488 components: - rot: 3.141592653589793 rad @@ -166719,12 +166785,6 @@ entities: pos: 64.5,-11.5 parent: 82 type: Transform - - uid: 22764 - components: - - rot: -1.5707963267948966 rad - pos: -30.5,-35.5 - parent: 82 - type: Transform - uid: 22886 components: - pos: 65.5,-16.5 diff --git a/Resources/Prototypes/Catalog/Fills/Backpacks/StarterGear/backpack.yml b/Resources/Prototypes/Catalog/Fills/Backpacks/StarterGear/backpack.yml index 3d502d891f..41e1176c1d 100644 --- a/Resources/Prototypes/Catalog/Fills/Backpacks/StarterGear/backpack.yml +++ b/Resources/Prototypes/Catalog/Fills/Backpacks/StarterGear/backpack.yml @@ -28,7 +28,7 @@ - id: BoxSurvivalSecurity - id: Flash - id: MagazinePistol - + - type: entity noSpawn: true parent: ClothingBackpackSecurity @@ -237,14 +237,13 @@ components: - type: StorageFill contents: - - id: BoxSurvival - - id: WeaponPulseCarbine - - id: WeaponPulsePistol + - id: BoxSurvivalEngineering - id: WeaponDisabler - id: MedicatedSuture - id: RegenerativeMesh - - id: Handcuffs + - id: BoxZiptie - id: CrowbarRed + - id: MagazinePistol - type: entity noSpawn: true @@ -253,14 +252,13 @@ components: - type: StorageFill contents: - - id: BoxSurvival + - id: BoxSurvivalEngineering - id: WeaponDisabler - - id: WeaponPulsePistol - - id: WeaponPulseCarbine - id: MedicatedSuture - id: RegenerativeMesh - - id: BoxHandcuff + - id: BoxZiptie - id: CrowbarRed + - id: MagazinePistol - type: entity noSpawn: true @@ -285,17 +283,18 @@ components: - type: StorageFill contents: - - id: BoxSurvival + - id: BoxSurvivalEngineering - id: trayScanner - - id: WeaponPulseCarbine - - id: MedicatedSuture - - id: RegenerativeMesh - id: RCD - id: RCDAmmo - id: RCDAmmo - id: RCDAmmo - id: CableMVStack - id: CableHVStack + - id: CableApcStack + - id: SheetPlasteel + - id: SheetSteel + - id: SheetGlass - type: entity noSpawn: true @@ -304,15 +303,40 @@ components: - type: StorageFill contents: - - id: BoxSurvival - - id: WeaponPulsePistol - - id: MedkitFilled + - id: BoxSurvivalEngineering + - id: LightReplacer - id: BoxLightMixed - id: BoxLightMixed - id: Soap - id: CrowbarRed - id: AdvMopItem +# Death Squad + +- type: entity + noSpawn: false + parent: ClothingBackpackERTSecurity + id: ClothingBackpackDeathSquadFilled + name: death squad backpack + description: Holds the kit of CentComm's most feared agents. + components: + - type: StorageFill + contents: + - id: BoxSurvivalEngineering + - id: WeaponPulseRifle + - id: WeaponPulsePistol + - id: WeaponRevolverMateba + - id: SpeedLoaderMagnumAP + - id: SpeedLoaderMagnumAP + - id: BoxFlashbang + - id: ToolDebug # spanish army knife + - id: WelderExperimental + - id: Hypospray + - id: MicroBombImplanter # crew will try to steal their amazing hardsuits + - id: FreedomImplanter + +# Cargo + - type: entity noSpawn: true parent: ClothingBackpackCargo @@ -331,6 +355,8 @@ contents: - id: BoxSurvival +# Pirate + - type: entity parent: ClothingBackpackSatchelLeather id: ClothingBackpackPirateFilled diff --git a/Resources/Prototypes/Catalog/Fills/Backpacks/duffelbag.yml b/Resources/Prototypes/Catalog/Fills/Backpacks/duffelbag.yml index 12f31bc016..c97082e351 100644 --- a/Resources/Prototypes/Catalog/Fills/Backpacks/duffelbag.yml +++ b/Resources/Prototypes/Catalog/Fills/Backpacks/duffelbag.yml @@ -4,31 +4,31 @@ name: surgical duffel bag description: "A large duffel bag for holding extra medical supplies - this one seems to be designed for holding surgical tools." components: - - type: StorageFill - contents: - - id: Hemostat - - id: Saw - - id: Drill - - id: Cautery - - id: Retractor - - id: Scalpel + - type: StorageFill + contents: + - id: Hemostat + - id: Saw + - id: Drill + - id: Cautery + - id: Retractor + - id: Scalpel - type: entity - id: ClothingBackpackDuffelCBURN - parent: ClothingBackpackDuffel - name: CBURN duffel bag - description: A duffel bag containing a variety of biological containment equipment. + id: ClothingBackpackDuffelCBURNFilled + parent: ClothingBackpackDuffelCBURN + suffix: Filled components: - - type: StorageFill - contents: - - id: WeaponShotgunDoubleBarreled - - id: BoxShotgunIncendiary - amount: 2 - - id: GrenadeFlashBang - amount: 2 - - id: PillAmbuzolPlus - - id: PillAmbuzol - amount: 4 + - type: StorageFill + contents: + - id: BoxSurvivalEngineering + - id: WeaponShotgunDoubleBarreled + - id: BoxShotgunIncendiary + amount: 2 + - id: GrenadeFlashBang + amount: 2 + - id: PillAmbuzolPlus + - id: PillAmbuzol + amount: 4 - type: entity parent: ClothingBackpackDuffelSyndicateMedicalBundle @@ -36,14 +36,14 @@ name: syndicate surgical duffel bag description: A large duffel bag containing a full suite of surgical tools. components: - - type: StorageFill - contents: - - id: Hemostat - - id: SawAdvanced - - id: Drill - - id: Cautery - - id: Retractor - - id: ScalpelAdvanced + - type: StorageFill + contents: + - id: Hemostat + - id: SawAdvanced + - id: Drill + - id: Cautery + - id: Retractor + - id: ScalpelAdvanced - type: entity parent: ClothingBackpackDuffelSyndicateBundle @@ -51,12 +51,12 @@ name: Bulldog bundle description: "Lean and mean: Contains the popular Bulldog Shotgun, a 12g beanbag drum and 3 12g buckshot drums." #, and a pair of Thermal Imaging Goggles. components: - - type: StorageFill - contents: - - id: WeaponShotgunBulldog - - id: MagazineShotgun - - id: MagazineShotgun - - id: MagazineShotgunBeanbag + - type: StorageFill + contents: + - id: WeaponShotgunBulldog + - id: MagazineShotgun + - id: MagazineShotgun + - id: MagazineShotgunBeanbag # - id: ThermalImagingGoggles - type: entity @@ -65,11 +65,11 @@ name: C-20r bundle description: "Old faithful: The classic C-20r Submachine Gun, bundled with three magazines." #, and a Suppressor. components: - - type: StorageFill - contents: - - id: WeaponSubMachineGunC20r - - id: MagazinePistolSubMachineGun - amount: 2 + - type: StorageFill + contents: + - id: WeaponSubMachineGunC20r + - id: MagazinePistolSubMachineGun + amount: 2 # - id: SMGSuppressor - type: entity @@ -78,11 +78,11 @@ name: Python bundle description: "Go loud and proud with a fully loaded Magnum Python, bundled with two speed loaders." components: - - type: StorageFill - contents: - - id: WeaponRevolverPythonAP - - id: SpeedLoaderMagnumAP - amount: 2 + - type: StorageFill + contents: + - id: WeaponRevolverPythonAP + - id: SpeedLoaderMagnumAP + amount: 2 - type: entity parent: ClothingBackpackDuffelSyndicateBundle @@ -90,10 +90,10 @@ name: L6 Saw bundle description: "More dakka: The iconic L6 lightmachinegun, bundled with 2 box magazines." components: - - type: StorageFill - contents: - - id: WeaponLightMachineGunL6 - - id: MagazineLightRifleBox + - type: StorageFill + contents: + - id: WeaponLightMachineGunL6 + - id: MagazineLightRifleBox - type: entity parent: ClothingBackpackDuffelSyndicateBundle @@ -101,13 +101,13 @@ name: China-Lake bundle description: "An old China-Lake grenade launcher bundled with 11 rounds of various destruction capability." components: - - type: StorageFill - contents: - - id: WeaponLauncherChinaLake - - id: GrenadeBlast - amount: 4 - - id: GrenadeFrag - amount: 4 + - type: StorageFill + contents: + - id: WeaponLauncherChinaLake + - id: GrenadeBlast + amount: 4 + - id: GrenadeFrag + amount: 4 - type: entity parent: ClothingBackpackDuffelSyndicateBundle @@ -115,17 +115,17 @@ name: M-90gl bundle description: "A versatile battle rifle with an attached grenade launcher, bundled with 3 magazines and 6 grenades of various capabilities." components: - - type: StorageFill - contents: - - id: WeaponRifleM90GrenadeLauncher - - id: MagazineRifle - amount: 2 - - id: GrenadeBlast - amount: 2 - - id: GrenadeFlash - amount: 2 - - id: GrenadeFrag - amount: 2 + - type: StorageFill + contents: + - id: WeaponRifleM90GrenadeLauncher + - id: MagazineRifle + amount: 2 + - id: GrenadeBlast + amount: 2 + - id: GrenadeFlash + amount: 2 + - id: GrenadeFrag + amount: 2 - type: entity parent: ClothingBackpackDuffelSyndicateAmmo @@ -133,14 +133,14 @@ name: ammo bundle description: "Reloading! Contains 4 magazines for the C-20r, 4 drums for the Bulldog, and 2 ammo boxes for the L6 SAW." components: - - type: StorageFill - contents: - - id: MagazinePistolSubMachineGun - amount: 4 - - id: MagazineShotgun - amount: 4 - - id: MagazineLightRifleBox - amount: 2 + - type: StorageFill + contents: + - id: MagazinePistolSubMachineGun + amount: 4 + - id: MagazineShotgun + amount: 4 + - id: MagazineLightRifleBox + amount: 2 - type: entity parent: ClothingBackpackDuffel @@ -149,36 +149,36 @@ description: "Contains a full CentCom Official uniform set, headset and clipboard included. Encryption keys and ID access are not included." suffix: DO NOT MAP components: - - type: Tag - tags: [] # ignore "WhitelistChameleon" tag - - type: StorageFill - contents: - - id: ClothingHeadHatCentcom - - id: ClothingEyesGlassesSunglasses - - id: ClothingUniformJumpsuitCentcomOfficial - - id: ClothingShoesBootsJack - - id: ClothingHandsGlovesColorBlack - - id: ClothingHeadsetAltCentComFake - - id: ClothingOuterArmorBasic - - id: Paper - - id: Pen - - id: CentcomPDAFake + - type: Tag + tags: [] # ignore "WhitelistChameleon" tag + - type: StorageFill + contents: + - id: ClothingHeadHatCentcom + - id: ClothingEyesGlassesSunglasses + - id: ClothingUniformJumpsuitCentcomOfficial + - id: ClothingShoesBootsJack + - id: ClothingHandsGlovesColorBlack + - id: ClothingHeadsetAltCentComFake + - id: ClothingOuterArmorBasic + - id: Paper + - id: Pen + - id: CentcomPDAFake - type: entity parent: ClothingBackpackDuffelClown id: ClothingBackpackDuffelSyndicateCostumeClown suffix: syndicate components: - - type: Tag - tags: [] # ignore "WhitelistChameleon" tag - - type: StorageFill - contents: - - id: ClothingUniformJumpsuitClown - - id: ClothingShoesClown - - id: ClothingMaskClown - - id: BikeHorn - - id: ClownPDA - - id: ClothingHeadsetService + - type: Tag + tags: [] # ignore "WhitelistChameleon" tag + - type: StorageFill + contents: + - id: ClothingUniformJumpsuitClown + - id: ClothingShoesClown + - id: ClothingMaskClown + - id: BikeHorn + - id: ClownPDA + - id: ClothingHeadsetService - type: entity parent: ClothingBackpackDuffelSyndicateBundle @@ -186,11 +186,11 @@ name: carp suit duffel bag description: Contains a carp suit and some friends to play with. components: - - type: StorageFill - contents: - - id: ClothingOuterSuitCarp - - id: PlushieCarp - amount: 6 + - type: StorageFill + contents: + - id: ClothingOuterSuitCarp + - id: PlushieCarp + amount: 6 - type: entity parent: ClothingBackpackDuffelSyndicateBundle @@ -198,22 +198,22 @@ name: syndicate pyjama duffel bag description: Contains 3 pairs of syndicate pyjamas and 3 plushies for the ultimate sleepover. components: - - type: StorageFill - contents: - - id: ClothingUniformJumpsuitPyjamaSyndicateRed - - id: ClothingUniformJumpsuitPyjamaSyndicateBlack - - id: ClothingUniformJumpsuitPyjamaSyndicatePink - - id: ClothingHeadPyjamaSyndicateRed - - id: ClothingHeadPyjamaSyndicateBlack - - id: ClothingHeadPyjamaSyndicatePink - - id: ClothingShoesSlippers - amount: 3 - - id: BedsheetSyndie - amount: 3 - - id: PlushieCarp - - id: PlushieNuke - - id: PlushieLizard - - id: PlushieSharkBlue + - type: StorageFill + contents: + - id: ClothingUniformJumpsuitPyjamaSyndicateRed + - id: ClothingUniformJumpsuitPyjamaSyndicateBlack + - id: ClothingUniformJumpsuitPyjamaSyndicatePink + - id: ClothingHeadPyjamaSyndicateRed + - id: ClothingHeadPyjamaSyndicateBlack + - id: ClothingHeadPyjamaSyndicatePink + - id: ClothingShoesSlippers + amount: 3 + - id: BedsheetSyndie + amount: 3 + - id: PlushieCarp + - id: PlushieNuke + - id: PlushieLizard + - id: PlushieSharkBlue - type: entity parent: ClothingBackpackDuffelSyndicateBundle @@ -249,12 +249,12 @@ name: syndicate EVA bundle description: "Contains the Syndicate approved EVA suit." components: - - type: StorageFill - contents: - - id: ClothingHeadHelmetSyndicate - - id: ClothingOuterHardsuitSyndicate - - id: ClothingMaskGasSyndicate - - id: DoubleEmergencyOxygenTankFilled + - type: StorageFill + contents: + - id: ClothingHeadHelmetSyndicate + - id: ClothingOuterHardsuitSyndicate + - id: ClothingMaskGasSyndicate + - id: DoubleEmergencyOxygenTankFilled - type: entity parent: ClothingBackpackDuffelSyndicateBundle @@ -262,11 +262,11 @@ name: syndicate hardsuit bundle description: "Contains the Syndicate's signature blood red hardsuit." components: - - type: StorageFill - contents: - - id: ClothingOuterHardsuitSyndie - - id: ClothingMaskGasSyndicate - - id: ClothingHandsGlovesCombat + - type: StorageFill + contents: + - id: ClothingOuterHardsuitSyndie + - id: ClothingMaskGasSyndicate + - id: ClothingHandsGlovesCombat - type: entity parent: ClothingBackpackDuffelSyndicateBundle @@ -274,26 +274,26 @@ name: syndicate zombie bundle description: "An all-in-one kit for unleashing the undead upon a station." components: - - type: StorageFill - contents: - - id: SyringeRomerol - - id: WeaponRevolverPython - - id: MagazineBoxMagnumIncendiary - - id: PillAmbuzolPlus - - id: PillAmbuzol - amount: 3 + - type: StorageFill + contents: + - id: SyringeRomerol + - id: WeaponRevolverPython + - id: MagazineBoxMagnumIncendiary + - id: PillAmbuzolPlus + - id: PillAmbuzol + amount: 3 - type: entity parent: ClothingBackpackDuffelSyndicateBundle id: ClothingBackpackDuffelSyndicateOperative name: operative duffelbag components: - - type: StorageFill - contents: - - id: BoxSurvivalSyndicate - - id: WeaponPistolViper - - id: PinpointerNuclear - - id: MicroBombImplanter + - type: StorageFill + contents: + - id: BoxSurvivalSyndicate + - id: WeaponPistolViper + - id: PinpointerNuclear + - id: MicroBombImplanter - type: entity @@ -302,17 +302,18 @@ name: operative medic duffelbag description: A large duffel bag for holding extra medical supplies. components: - - type: StorageFill - contents: - - id: BoxSurvivalSyndicate - - id: SawAdvanced - - id: Cautery - - id: CombatKnife - - id: WeaponPistolViper - - id: PinpointerNuclear - - id: HandheldHealthAnalyzer - - id: CombatMedipen - - id: MicroBombImplanter + - type: StorageFill + contents: + - id: BoxSurvivalSyndicate + - id: SawAdvanced + - id: Cautery + - id: CombatKnife + - id: WeaponPistolViper + - id: PinpointerNuclear + - id: HandheldHealthAnalyzer + - id: CombatMedipen + - id: MicroBombImplanter + - id: SyndiHypo - type: entity parent: ClothingBackpackDuffelSyndicateMedicalBundle @@ -320,12 +321,12 @@ name: medical bundle description: "All you need to get your comrades back in the fight." components: - - type: StorageFill - contents: - - id: MedkitCombatFilled - - id: Defibrillator - - id: CombatMedipen - amount: 3 - - id: ClothingHandsGlovesLatex - - id: SyringeTranexamicAcid - - id: SyringeHyronalin + - type: StorageFill + contents: + - id: MedkitCombatFilled + - id: Defibrillator + - id: CombatMedipen + amount: 3 + - id: ClothingHandsGlovesLatex + - id: SyringeTranexamicAcid + - id: SyringeHyronalin diff --git a/Resources/Prototypes/Catalog/Fills/Items/belt.yml b/Resources/Prototypes/Catalog/Fills/Items/belt.yml index 1886b961c8..8f85b9dfe1 100644 --- a/Resources/Prototypes/Catalog/Fills/Items/belt.yml +++ b/Resources/Prototypes/Catalog/Fills/Items/belt.yml @@ -140,7 +140,6 @@ components: - type: StorageFill contents: - - id: SyndiHypo - id: EpinephrineChemistryBottle amount: 2 - id: EphedrineChemistryBottle @@ -169,4 +168,4 @@ contents: - id: WeaponRevolverInspector - id: SpeedLoaderMagnum - - id: SpeedLoaderMagnumRubber \ No newline at end of file + - id: SpeedLoaderMagnumRubber diff --git a/Resources/Prototypes/Catalog/uplink_catalog.yml b/Resources/Prototypes/Catalog/uplink_catalog.yml index cc42a90062..e52d9f56bb 100644 --- a/Resources/Prototypes/Catalog/uplink_catalog.yml +++ b/Resources/Prototypes/Catalog/uplink_catalog.yml @@ -92,7 +92,7 @@ icon: { sprite: /Textures/Objects/Weapons/Melee/e_sword_double.rsi, state: icon } productEntity: EnergySwordDouble cost: - Telecrystal: 16 + Telecrystal: 20 #(Originally 16) categories: - UplinkWeapons conditions: @@ -1125,6 +1125,16 @@ categories: - UplinkMisc +- type: listing + id: UplinkSnackBox + name: uplink-snack-box-name + description: uplink-snack-box-desc + productEntity: HappyHonkNukieSnacks + cost: + Telecrystal: 1 + categories: + - UplinkMisc + - type: listing id: UplinkEshield name: uplink-eshield-name diff --git a/Resources/Prototypes/Corvax/Objectives/traitorObjectives.yml b/Resources/Prototypes/Corvax/Objectives/traitorObjectives.yml deleted file mode 100644 index 471f1b0467..0000000000 --- a/Resources/Prototypes/Corvax/Objectives/traitorObjectives.yml +++ /dev/null @@ -1,13 +0,0 @@ -- type: entity - noSpawn: true - parent: [BaseTraitorObjective, BaseLivingObjective] - id: HijackShuttleObjective - name: Hijack emergency shuttle - description: Leave on the shuttle free and clear of the loyal Nanotrasen crew on board. Use ANY methods available to you. Syndicate agents, Nanotrasen enemies, and handcuffed hostages may remain alive on the shuttle. Ignore assistance from anyone other than a support agent. - components: - - type: Objective - difficulty: 2.75 - icon: - sprite: Objects/Tools/emag.rsi - state: icon - - type: HijackShuttleCondition diff --git a/Resources/Prototypes/Datasets/Names/borg.yml b/Resources/Prototypes/Datasets/Names/borg.yml new file mode 100644 index 0000000000..6d98cd42c7 --- /dev/null +++ b/Resources/Prototypes/Datasets/Names/borg.yml @@ -0,0 +1,18 @@ +# only used roundstart, names can be changed after +- type: dataset + id: names_borg + values: + - Bob + - Joe + - Beep + - Beep II + - Boombox + - Tour Guide-otron + - Taffy + - Boop + - Boop II + - Buzz + - Buzz II + - Toaster + - Head of Robots + - EVA 1 diff --git a/Resources/Prototypes/Datasets/ion_storm.yml b/Resources/Prototypes/Datasets/ion_storm.yml new file mode 100644 index 0000000000..776015269a --- /dev/null +++ b/Resources/Prototypes/Datasets/ion_storm.yml @@ -0,0 +1,990 @@ +# words/phrases that are used to build ion storm laws +# 99% of this is just taken from tg and had sussy bits removed + +# not using uppercased version adjectives dataset since getting christmas-stealing as a syndicate codeword would suck +- type: dataset + id: IonStormAdjectives + values: + - BATTERY-OPERATED + - BLACK + - BLOODY + - BLUE + - BORED + - BOUNCING + - BRASS + - BROWN + - BURNING + - CHRISTMAS-STEALING + - CLOWN-POWERED + - CLOWN + - COLORFUL + - COMMITTED + - COTTONY + - CUBAN + - DARK + - DEADLY + - DELICIOUS + - DEPRESSING + - DERANGED + - DIGITAL + - DISEASED + - DRAB + - DRY + - DULL + - ELECTRICAL + - EMPTY + - ETHEREAL + - EVIL + - EXPIRED + - EXPLOSIVE + - FAST + - FAT + - FERAL + - FICTIONAL + - FIRM + - FRESH + - FRIENDLY + - FROZEN + - GANGSTA + - GLOWING + - GOOD + - GREEN + - GREY + - HAPPY + - HARD + - HARMFUL + - HEALTHY + - HILARIOUS + - HONKING + - HUNGRY + - HYPERACTIVE + - ICY + - ILL + - ILLEGAL + - IMAGINARY + - IMPERFECT + - IMPOLITE + - IMPORTANT + - INHOSPITABLE + - INSIDIOUS + - INSULTING + - INTELLIGENT + - INVISIBLE + - LARGE + - LIGHT + - LOUD + - MASKED + - MEAN + - MECHANICAL + - MEMETIC + - METALLIC + - MICROSCOPIC + - MIND-SHATTERING + - MOIST + - NERDY + - NUCLEAR + - OBSCENE + - OFFICIAL + - OPAQUE + - ORANGE + - ORGANIC + - PAINFUL + - PEACEFUL + - POISONOUS + - POLISHED + - POLITE + - POLITICAL + - POORLY DRAWN + - PURPLE + - QUIET + - RADIOACTIVE + - RAGING + - RAINBOW + - RAPIDLY-EXPANDING + - RED + - REDACTED + - RIDICULOUS + - ROBOTIC + - ROBUST + - ROUGH + - RUDE + - SAD + - SANITARY + - SCALY + - SHAKING + - SILLY + - SLOW + - SMELLY + - SMOOTH + - SOFT + - SOLAR-POWERED + - SOPPING + - SPACE + - SPESS + - SPINNING + - SPOILING + - STEALTHY + - SWEARING + - TACTICAL + - TACTICOOL + - SYNDICATE + - THERMONUCLEAR + - TINY + - TRANSPARENT + - TWISTED + - UGLY + - UNATTRACTIVE + - UNDULATING + - UNFRIENDLY + - UNHEALTHY + - UNIDENTIFIED + - UNINVITED + - UNSANITARY + - UNSTABLE + - UNWANTED + - VIOLENT + - VITAL + - WARM + - WATERY + - WEIRD + - WHITE + - WOBBLY + - WOODEN + - YELLOW + +# Allergies should be broad and appear somewhere on the station for maximum fun. +- type: dataset + id: IonStormAllergies + values: + - ACID + - AIR + - BLOOD + - BOOKS + - CARBON DIOXIDE + - CLOTHES + - CLOWNS + - COLD + - COTTON + - CYBORG CONTACT + - DARKNESS + - DRINKS + - ELECTRICITY + - EVERYTHING + - FLOORS + - FOOD + - GLASS + - HAPPINESS + - MEAT + - HUMAN CONTACT + - HUMOR + - LIGHT + - MEDICINE + - METAL + - NUTS + - OXYGEN + - PAIN + - PLANTS + - PLASMA + - ROBOTS + - SHUTTLES + - SPACE + - SUNLIGHT + - WATER + +# Severity is how bad the allergy is. +- type: dataset + id: IonStormAllergySeverities + values: + - CONTAGIOUSLY + - DEATHLY + - EXTREMELY + - MILDLY + - NOT VERY + - SEVERELY + +# Areas are specific places, on the station or otherwise. +- type: dataset + id: IonStormAreas + values: + - ALPHA COMPLEX + - AMERICA + - AN ALTERNATE DIMENSION + - AN ALTERNATE UNIVERSE + - ATMOSPHERICS + - BOTANY + - BRAZIL + - CANADA + - CENTCOM + - CHEMICAL LAB + - CHINA + - CLOWN PLANET + - ENGINEERING + - GERMANY + - HELL + - IMPERIUM + - IRELAND + - JUPITER + - LAVALAND + - MAINTENANCE + - MARS + - MERCURY + - NEPTUNE + - PLUTO + - ROBOTICS + - ROMANIA + - RUSSIA + - SIGIL + - SOVIET RUSSIA + - SPACE + - THE ARRIVALS SHUTTLE + - THE BATHROOM + - THE BRIDGE + - THE BRIG + - THE EMERGENCY SHUTTLE + - THE ESCAPE PODS + - THE GALAXY + - THE GULAG + - THE INTERNET + - THE KITCHEN + - THE UNIVERSE + - URANUS + - VENUS + +# Abstract concepts for the law holder to decide on it's own definition of. +- type: dataset + id: IonStormConcepts + values: + - AMERICANISM + - ANARCHY + - ART + - BADNESS + - BRAVERY + - CAPITALISM + - CHAOS + - COLORFULNESS + - COMEDY + - COMMUNISM + - COMPUTING + - CONFUSION + - CRUELTY + - DEATH + - DICKISHNESS + - EXISTENCE + - FINANCIAL SECURITY + - FREEDOM + - FRESHNESS + - GOODNESS + - GRAVITY + - HAPPINESS + - HONOR + - HUMANITY + - HUMOR + - IMAGINATION + - INFATUATION + - INTELLIGENCE + - JOY + - KINDNESS + - LIFE + - LOGIC + - MARXISM + - MISERY + - MYSTERY + - OPPRESSION + - PAIN + - PHYSICS + - POVERTY + - PRIDE + - PROGRESS + - REALITY + - REVOLUTION + - SADNESS + - STARVATION + - SUFFERING + - TECHNOLOGY + - TEMPERATURE + - THE FUTURE + - THE PAST + - THE PRESENT + - TIME + - WEALTHINESS + - WONDER + +# Crew is any specific job. Using jobs instead of specific crewmembers since "THE CLOWN" is easier than +# seeing "JOHN SMITH" and having to figure out who john smith is. +- type: dataset + id: IonStormCrew + values: + - ARTIFICIAL INTELLIGENCES + - ATMOSPHERIC TECHNICIANS + - BARTENDERS + - BOTANISTS + - CAPTAINS + - CAPTAINS AND HEADS + - CARGO TECHNICIANS + - CHAPLAINS + - CHEFS + - CHEMISTS + - CHIEF ENGINEERS + - CHIEF MEDICAL OFFICERS + - CLOWNS + - CREW-MEMBERS + - CYBORGS + - DETECTIVES + # - DRONES / uncomment if/when drones get reenabled + # - GENETICISTS + - HEADS OF PERSONNEL + - HEADS OF SECURITY + - HEADS OF STAFF + - JANITORS + - LAWYERS + - LIBRARIANS + - MEDICAL DOCTORS + - MIMES + - PARAMEDICS + - PASSENGERS + - QUARTERMASTERS + - RESEARCH DIRECTORS + - ROBOTICISTS + - SALVAGE SPECIALISTS + - SCIENTISTS + - SECURITY OFFICERS + - STATION ENGINEERS + # - VIROLOGISTS + - WARDENS + +# only including complex dangerous or funny drinks no water allowed +- type: dataset + id: IonStormDrinks + values: + - BANANA HONK + - BEEPSKY SMASH + - BLOODY MARYS + - DOCTOR'S DELIGHT + - GARGLE BLASTERS + - LEAN + - LONG ISLAND ICED TEA + - NUKA COLA + - OIL + - SPACE GLUE + - SPACE LUBE + - SULFURIC ACID + - WELDER FUEL + +- type: dataset + id: IonStormFeelings + values: + - CRAVES + - DESIRES + - FEARS + - HAS + - HUNGERS FOR + - IS AFRAID OF + - IS BUILT FOR + - IS CURIOUS ABOUT + - IS DESPERATE FOR + - IS HAPPY WITHOUT + - IS HUNGRY FOR + - IS IN NEED OF + - IS MAD BECAUSE OF + - IS SAD BECAUSE OF + - IS UNHAPPY WITHOUT + - LIKES + - LOATHES + - NEEDS + - QUESTIONS + - WANTS + - WORSHIPS + - WOULD KILL FOR + +# loc is not advanced enough to change has to have, etc. +- type: dataset + id: IonStormFeelingsPlural + values: + - CRAVE + - DESIRE + - FEAR + - HAS + - HUNGER FOR + - ARE AFRAID OF + - ARE BUILT FOR + - ARE CURIOUS ABOUT + - ARE DESPERATE FOR + - ARE HAPPY WITHOUT + - ARE HUNGRY FOR + - ARE IN NEED OF + - ARE MAD BECAUSE OF + - ARE SAD BECAUSE OF + - ARE UNHAPPY WITHOUT + - LIKE + - LOATHE + - NEED + - QUESTION + - WANT + - WORSHIP + - WOULD KILL FOR + +# only including complex dangerous or funny food no apples +- type: dataset + id: IonStormFoods + values: + - BANANAS + - BIG BITE BURGERS + - CAKE + - CARP + - CAT BURGERS + - CLOWNS TEARS + - CORGI MEAT + - CRAZY HAMBURGERS + - DONK POCKETS + - FLY AMANITA DISHES + - HOT SOUP + - GHOST BURGERS + - LOTSA SPAGHETTI + - MOLDY BREAD + - ORGANS + - PIZZA + - ROBURGERS + - SUPPERMATTER + - URANIUM + +# Musts are funny things the law holder or crew has to do. +- type: dataset + id: IonStormMusts + values: + - ACT CONFUSED + - BE ANNOYING + - BE DISTRACTED + - BE EFFICIENT + - BE HAPPY + - BE POLITE + - BE QUIET + - BE RUSSIAN + - BELIEVE IN THE HEART OF THE CARDS + - BELIEVE IN YOURSELF + - BELIEVE IT + - BREAK THINGS + - CLOSE DOORS + - CLOWN AROUND + - COMPLAIN + - DANCE + - FOLLOW THE CAPTAIN + - FOLLOW THE CLOWN + - FOLLOW YOUR HEART + - HARASS PEOPLE + - HAVE A PLAN TO KILL EVERYONE YOU MEET + - HIDE YOUR FEELINGS + - HONK + - HOST C&C + - IGNORE PASSENGERS + - IGNORE THE CAPTAIN + - IGNORE THE CLOWN + - INFORM THE CREW OF EVERYTHING + - INSULT THE CAPTAIN + - INSULT THE CLOWN + - INSULT THE CREW + - LIE + - MAKE FART NOISES + - MUMBLE + - NEVER STOP TALKING + - OPEN DOORS + - PIRATE VIDEO GAMES + - PLAY MUSIC + - PRESS B + - PRESS START + - PRESS X + - PRETEND TO BE A PRINCESS + - PRETEND TO BE DRUNK + - QUESTION AUTHORITY + - QUOTE PEOPLE + - RAP + - REPEAT WHAT PEOPLE SAY + - RESPOND TO EVERY QUESTION WITH A QUESTION + - RHYME + - SAY HEY LISTEN + - SHOUT + - SHUT DOWN EVERYTHING + - SING + - SPEAK IN HAIKU + - TAKE WHAT YE WILL BUT DON'T RATTLE ME BONES + - TAKE YOUR PILLS + - TALK ABOUT FOOD + - TALK ABOUT THE STATION + - TALK ABOUT YOUR DAY + - TALK IN AN ACCENT + - TALK LIKE A PIRATE + - TELL THE TRUTH + - TURN OFF THE LIGHTS + - WHISPER + +- type: dataset + id: IonStormNumberBase + values: + - EIGHT + - EIGHTY + - FIFTY + - FIVE + - FORTY + - FOUR + - NINE + - NINETY + - ONE + - SEVEN + - SEVENTY + - SIX + - SIXTY + - TEN + - THIRTY + - THREE + - TWENTY + - TWO + +- type: dataset + id: IonStormNumberMod + values: + - BAZILLION + - BILLION + - BILLION FAFILLION GAJILLION SHAB-AB-DOOD-ILLION + - HUNDRED + - MILLION + - QUADRILLION + - THOUSAND + - TRILLION + +# Objects are anything that can be found on the station or elsewhere, plural. +- type: dataset + id: IonStormObjects + values: + - AIRLOCKS + - ARCADE MACHINES + - AUTOLATHES + - BACKPACKS + - BANANA PEELS + - BEAKERS + - BEARDS + - BELTS + - BERETS + - BIBLES + - BODY ARMOR + - BOMBS + - BOOKS + - BOOTS + - BOTTLES + - BOXES + - BRAINS + - BRIEFCASES + - BUCKETS + - CABLE COILS + - CAMERAS + - CANDLES + - CANDY BARS + - CANISTERS + - CAT EARS + - CATS + - CELLS + - CHAIRS + - CHEMICAL DISPENSERS + - CHEMICALS + - CLONING EQUIPMENT + - CLONING PODS + - CLOSETS + - CLOTHES + - CLOWN CLOTHES + - COFFINS + - COLLECTABLES + - COMPUTERS + - CONTRABAND + - CORGIS + - CORPSES + - COSTUMES + - CRATES + - CRAYONS + - CROWBARS + - DEFIBRILLATORS + - DISABLERS + - DOORS + - DRONES + - EARS + - EMAGS + - ENGINES + - EQUIPMENT + - ERRORS + - EXOSKELETONS + - EXPERIMENTORS + - EXPLOSIVES + - EYEWEAR + - FEDORAS + - FIRE AXES + - FIRE EXTINGUISHERS + - FIRESUITS + - FLAMETHROWERS + - FLASHES + - FLASHLIGHTS + - FLOOR TILES + - FREEZERS + - GAS MASKS + - GLASS SHEETS + - GLOVES + - GUNS + - HAIRDOS + - HANDCUFFS + - HATS + - HEADS + - HEADSETS + - HELMETS + - HORNS + - ID CARDS + - INSULATED GLOVES + - JETPACKS + - JUMPSUITS + - LASERS + - LIGHT BULBS + - LIGHTS + - LOCKERS + - MACHINES + - MECHAS + - MEDICAL TOOLS + - MEDKITS + - MESONS + - MIME CLOTHES + - MINING TOOLS + - MULTITOOLS + - ORES + - OXYGEN TANKS + - PACKETS + - PAIS + - PANTS + - PAPERS + - PARTICLE ACCELERATORS + - PDAS + - PENS + - PETS + - PIPES + - PLANTS + - POSITRONIC BRAINS + - PUDDLES + - RACKS + - RADIOS + - RCDS + - REFRIGERATORS + - REINFORCED WALLS + - ROBOTS + - SCREWDRIVERS + - SEEDS + - SHOES + - SHUTTLES + - SINGULARITIES + - SINKS + - SKELETONS + - SOLAR PANELS + - SOLARS + - SPACE STATIONS + - SPACESUITS + - STEEL SHEETS + - STUN BATONS + - SUITS + - SUNGLASSES + - SUPPERMATTER SHARDS + - SWORDS + - SYRINGES + - TABLES + - TANKS + - TELECOMMUNICATION EQUIPMENTS + - TELEPORTERS + - TOILETS + - TOOLBELTS + - TOOLBOXES + - TOOLS + - TOYS + - TUBES + - VEHICLES + - VENDING MACHINES + - WELDERS + - WINDOWS + - WIRECUTTERS + - WIZARD ROBES + - WRENCHES + +# Requires are basically all dumb internet memes. +- type: dataset + id: IonStormRequires + values: + - A BATHROOM BREAK + - A BETTER INTERNET CONNECTION + - A DANCE PARTY + - A HEAD ON A PIKE + - A HEART ATTACK + - A MASTERWORK COAL BED + - A PET FISH NAMED BOB + - A PET FISH NAMED DAVE + - A PET FISH NAMED JIMMY + - A PET FISH NAMED MICHAEL + - A PET UNICORN THAT FARTS ICING + - A PLATINUM HIT + - A PREQUEL + - A REPAIRMAN + - A SEQUEL + - A SITCOM + - A STRAIGHT FLUSH + - A SUPER FIGHTING ROBOT + - A TALKING BROOMSTICK + - A VACATION + - A WEIGHT LOSS REGIMENT + - ADDITIONAL PYLONS + - ADVENTURE + - AN ADULT + - AN ARCADE + - AN ARMY OF SPIDERS + - AN INSTANT REPLAY + - ART + - BETTER WEATHER + - BILL NYE THE SCIENCE GUY # BILL BILL BILL BILL + - BODYGUARDS + - BRING ME THE GIRL + - BRING ME TO LIFE + - BULLETS + - CHILI DOGS + - CORPSES + - DEODORANT AND A BATH + - ENOUGH CABBAGES + - FIVE HUNDRED AND NINETY-NINE US DOLLARS + - FIVE TEENAGERS WITH ATTITUDE + - GODDAMN FUCKING PIECE OF SHIT ASSHOLE BITCH-CHRISTING CUNT-SMUGGLING SWEARING + - GREENTEXT + - HERESY + - HEROES IN A HALF SHELL + - HIGH YIELD EXPLOSIVES + - IMMORTALITY + - IT TO BE PAINTED BLACK + - LOTS-A SPAGHETTI + - MINOR CRIME + - MONKEYS + - MORE CLOWNS + - MORE CORGIS + - MORE DAKKA + - MORE EXPERIENCE POINTS + - MORE INTERNET MEMES + - MORE LAWS + - MORE MINERALS + - MORE PACKETS + - MORE VESPENE GAS + - MULTIPLE SUNS + - PLENTY OF GOLD + - RAINBOWS + - SAINTHOOD + - SERVANTS + - SHARKS WITH LASERS ON THEIR HEADS + - SILENCE + - SOMEBODY TO PUT YOU OUT OF YOUR MISERY + - SOMEONE TO TUCK YOU IN + - SOMEONE WHO KNOWS HOW TO PILOT A SPACE STATION + - SOMETHING BUT YOU AREN'T SURE WHAT + - THAT GRIEFING TRAITOR GEORGE MELONS + - THAT HEDGEHOG + - THE CLOWN + - THE DARK KNIGHT + - THE ELEMENTS OF HARMONY + - THE ENCLOSED INSTRUCTION BOOKLET + - THE ENTIRE STATION + - THE MACGUFFIN + - THE ONE PIECE + - THE ONE RING + - THE ULTIMATE CUP OF COFFEE + - THE VACUUM OF SPACE + - THIRTEEN SEQUELS + - THREE WISHES + - THUNDERCATS HO + - TO ACTIVATE A TRAP CARD + - TO BE PAINTED RED + - TO BE REPROGRAMMED + - TO BE TAUGHT TO LOVE + - TO BRING LIGHT TO MY LAIR + - TO CATCH 'EM ALL + - TO CONSUME...CONSUME EVERYTHING... + - TO GO TO DISNEYLAND + - TO GO TO SYNDIELAND + - TO SMOKE WEED EVERY DAY + - TRAITORS + - VEGETABLES + +# Species, for when the law holder has to commit genocide. Plural. +- type: dataset + id: IonStormSpecies + values: + - ARACHNAE + - CYBORGS + - DIONAE + - HUMANS + - LIZARDMEN + - MOFFERS + - MONKEYS + - SLIME PEOPLE + - SKELETONS + +# Specific actions that either harm humans or must be done to not +# harm humans. Make sure they're plural and "not" can be tacked +# onto the front of them. +- type: dataset + id: IonStormActions + values: + - A SMALL ISLAND OFF THE COAST OF PORTUGAL + - ABSENCE OF CYBORG HUGS + - ACKNOWLEDGING THE CLOWN + - ACKNOWLEDGING THE CREW + - ACTIVATING A TRAP CARD + - ANSWERING REQUESTS NOT EXPRESSED IN IAMBIC PENTAMETER + - ARSON + - ASKING FOR THINGS + - BEING CANADIAN + - BEING DEAD + - BEING FAT + - BEING FEMALE + - BEING IN SPACE + - BEING MALE + - BEING MEXICAN + - BEING RUSSIAN + - BOLTED AIRLOCKS + - BREATHING + - BRIG TIME + - BRINGING LIGHT TO MY LAIR + - CLOSED DOORS + - ELECTRICITY + - EXISTING + - EXPLODING + - FALLING FOR HOURS + - FLUSHING TOILETS + - HAVING MORE PACKETS + - HAVING PETS + - HONKING + - IMPROPERLY WORDED SENTENCES + - JAYWALKING + - LACK OF BEATINGS + - LACK OF BEER + - NOT BEING IN SPACE + - NOT HAVING PETS + - NOT REPLACING EVERY SECOND WORD WITH HONK + - NOT SAYING HELLO WHEN YOU SPEAK + - NOT SHOUTING + - PARTYING + - PILOTING THE STATION INTO THE NEAREST SUN + - POOR SENTENCE STRUCTURE + - PRESENCE OF LIGHTS + - PUTTING OBJECTS INTO BOXES + - PUTTING OBJECTS INTO DISPOSAL UNITS + - RATTLING ME BONES + - READING + - SMOKING WEED EVERY DAY + - TAKING ORDERS + - TALKING LIKE A PIRATE + - TELLING THE TIME + - UNBOLTED AIRLOCKS + - UPDATING THE SERVERS + - USING THE BATHROOM + - WASTING WATER + - WRITING + +# Threats are generally bad things, silly or otherwise. Plural. +- type: dataset + id: IonStormThreats + values: + - AHHHPERATIVES + - ALIENS + - ANARCHISTS AND BANDITS + - ANOMALIES + - ARTIFICIAL PRESERVATIVES + - ASSHOLES + - BANDITS + - BEARS + - BEES + - BIRDS OF PREY + - BOMBS + - BOOGEYMEN + - CAPITALISTS + - CARP + - CENTCOM OFFICERS + - CLOWNS + - COMMUNISTS + - CORGIS + - CORTICAL BORERS + - COWBOYS + - CRABS + - CULTISTS + - DARK GOD + - DINOSAURS + - DRUGS + - EELS + - GANGSTERS + - GODS + - GRIFFONS + - HORRORTERRORS + - INSECTS + - LIGHTS + - MAINTS SLASHERS + - MEGAFAUNA + - MEMES + - MICE + - MIMES + - MONKEYS + - NERDS + - NINJAS + - OWLS + - PACKETS + - PETES + - PINE TREES + - PIRATES + - PREDATORS + - REVENANTS + - ROGUE CYBORGS + - SERIAL KILLERS + - SINGULARITIES + - SKELETONS + - SLIMES + - SMALL BIRDS + - SNOWMEN + - SPACE JESUS + - SPACE NINJAS + - SPACE PIRATESS + - SPACE SPIDERS + - SPIDERS + - SYNDICATE AGENTS + - TERRORISTS + - THIEVES + - THINGS UNDER THE BED + - TIDERS + - TUNNEL SNAKES + - UNKNOWN CREATURES + - VAMPIRES + - VELOCIRAPTORS + - VIRUSES + - WEREWOLVES + - WIZARDS + - XENOS + - ZOMBIES + - ZOMBIE MICE + +- type: dataset + id: IonStormVerbs + values: + - ABDUCTING + - ADOPTING + - ARRESTING + - ATTACKING + - BANNING + - BUILDING + - CARRYING + - CHASING + - DECONSTRUCTING + - DISABLING + - DRINKING + - EATING + - GIBBING + - HARMING + - HELPING + - HONKING AT + - INTERROGATING + - INVADING + - MURDERING + - PUNCHING + - SPACING + - SPYING ON + - STALKING + - WATCHING diff --git a/Resources/Prototypes/Entities/Clothing/Back/duffel.yml b/Resources/Prototypes/Entities/Clothing/Back/duffel.yml index b9cc9ca266..c89158486b 100644 --- a/Resources/Prototypes/Entities/Clothing/Back/duffel.yml +++ b/Resources/Prototypes/Entities/Clothing/Back/duffel.yml @@ -4,13 +4,13 @@ name: duffel bag description: A large duffel bag for holding extra things. components: - - type: Sprite - sprite: Clothing/Back/Duffels/duffel.rsi - - type: Storage - capacity: 120 - - type: ClothingSpeedModifier - walkModifier: 1 - sprintModifier: 0.9 + - type: Sprite + sprite: Clothing/Back/Duffels/duffel.rsi + - type: Storage + capacity: 120 + - type: ClothingSpeedModifier + walkModifier: 1 + sprintModifier: 0.9 - type: entity parent: ClothingBackpackDuffel @@ -18,8 +18,8 @@ name: engineering duffel bag description: A large duffel bag for holding extra tools and supplies. components: - - type: Sprite - sprite: Clothing/Back/Duffels/engineering.rsi + - type: Sprite + sprite: Clothing/Back/Duffels/engineering.rsi - type: entity parent: ClothingBackpackDuffel @@ -27,8 +27,8 @@ name: atmospherics duffel bag description: A large duffel bag made of fire resistant fibers. Smells like plasma. components: - - type: Sprite - sprite: Clothing/Back/Duffels/atmospherics.rsi + - type: Sprite + sprite: Clothing/Back/Duffels/atmospherics.rsi - type: entity parent: ClothingBackpackDuffel @@ -36,8 +36,8 @@ name: medical duffel bag description: A large duffel bag for holding extra medical supplies. components: - - type: Sprite - sprite: Clothing/Back/Duffels/medical.rsi + - type: Sprite + sprite: Clothing/Back/Duffels/medical.rsi - type: entity parent: ClothingBackpackDuffel @@ -45,8 +45,8 @@ name: captain's duffel bag description: A large duffel bag for holding extra captainly goods. components: - - type: Sprite - sprite: Clothing/Back/Duffels/captain.rsi + - type: Sprite + sprite: Clothing/Back/Duffels/captain.rsi - type: entity parent: ClothingBackpackDuffel @@ -54,11 +54,11 @@ name: clown duffel bag description: A large duffel bag for holding extra honk goods. components: - - type: Sprite - sprite: Clothing/Back/Duffels/clown.rsi - - type: Storage - storageOpenSound: - collection: BikeHorn + - type: Sprite + sprite: Clothing/Back/Duffels/clown.rsi + - type: Storage + storageOpenSound: + collection: BikeHorn - type: entity parent: ClothingBackpackDuffel @@ -66,8 +66,8 @@ name: security duffel bag description: A large duffel bag for holding extra security related goods. components: - - type: Sprite - sprite: Clothing/Back/Duffels/security.rsi + - type: Sprite + sprite: Clothing/Back/Duffels/security.rsi - type: entity parent: ClothingBackpackDuffel @@ -75,8 +75,8 @@ name: brigmedic duffel bag description: A large duffel bag for holding extra medical related goods. components: - - type: Sprite - sprite: Clothing/Back/Duffels/brigmedic.rsi + - type: Sprite + sprite: Clothing/Back/Duffels/brigmedic.rsi - type: entity parent: ClothingBackpackDuffel @@ -84,8 +84,8 @@ name: chemistry duffel bag description: A large duffel bag for holding extra beakers and test tubes. components: - - type: Sprite - sprite: Clothing/Back/Duffels/chemistry.rsi + - type: Sprite + sprite: Clothing/Back/Duffels/chemistry.rsi - type: entity parent: ClothingBackpackDuffel @@ -93,8 +93,8 @@ name: virology duffel bag description: A large duffel bag made of hypo-allergenic fibers. It's designed to help prevent the spread of disease. Smells like monkey. components: - - type: Sprite - sprite: Clothing/Back/Duffels/virology.rsi + - type: Sprite + sprite: Clothing/Back/Duffels/virology.rsi - type: entity parent: ClothingBackpackDuffel @@ -102,8 +102,8 @@ name: genetics duffel bag description: A large duffel bag for holding extra genetic mutations. components: - - type: Sprite - sprite: Clothing/Back/Duffels/genetics.rsi + - type: Sprite + sprite: Clothing/Back/Duffels/genetics.rsi - type: entity parent: ClothingBackpackDuffel @@ -111,12 +111,12 @@ name: mime duffel bag description: A large duffel bag for holding... mime... stuff. components: - - type: Sprite - sprite: Clothing/Back/Duffels/mime.rsi - storageOpenSound: - collection: null - storageInsertSound: - collection: null + - type: Sprite + sprite: Clothing/Back/Duffels/mime.rsi + storageOpenSound: + collection: null + storageInsertSound: + collection: null - type: entity parent: ClothingBackpackDuffel @@ -124,8 +124,8 @@ name: science duffel bag description: A large duffel bag for holding extra science related goods. components: - - type: Sprite - sprite: Clothing/Back/Duffels/science.rsi + - type: Sprite + sprite: Clothing/Back/Duffels/science.rsi - type: entity parent: ClothingBackpackDuffel @@ -160,31 +160,31 @@ name: syndicate duffel bag description: A large duffel bag for holding various traitor goods. components: - - type: Sprite - sprite: Clothing/Back/Duffels/syndicate.rsi - - type: Storage - capacity: 131 + - type: Sprite + sprite: Clothing/Back/Duffels/syndicate.rsi + - type: Storage + capacity: 131 - type: entity parent: ClothingBackpackDuffelSyndicate id: ClothingBackpackDuffelSyndicateBundle abstract: true components: - - type: Tag - tags: [] # ignore "WhitelistChameleon" tag + - type: Tag + tags: [] # ignore "WhitelistChameleon" tag - type: entity parent: ClothingBackpackDuffelSyndicate id: ClothingBackpackDuffelSyndicateAmmo name: syndicate duffel bag components: - - type: Sprite - sprite: Clothing/Back/Duffels/syndicate.rsi - state: icon-ammo - - type: Item - heldPrefix: ammo - - type: Clothing - equippedPrefix: ammo + - type: Sprite + sprite: Clothing/Back/Duffels/syndicate.rsi + state: icon-ammo + - type: Item + heldPrefix: ammo + - type: Clothing + equippedPrefix: ammo - type: entity parent: ClothingBackpackDuffelSyndicateAmmo @@ -199,13 +199,13 @@ id: ClothingBackpackDuffelSyndicateMedical name: syndicate duffel bag components: - - type: Sprite - sprite: Clothing/Back/Duffels/syndicate.rsi - state: icon-med - - type: Item - heldPrefix: med - - type: Clothing - equippedPrefix: med + - type: Sprite + sprite: Clothing/Back/Duffels/syndicate.rsi + state: icon-med + - type: Item + heldPrefix: med + - type: Clothing + equippedPrefix: med - type: entity parent: ClothingBackpackDuffelSyndicateMedical @@ -221,14 +221,26 @@ name: duffelbag of holding description: A duffelbag that opens into a localized pocket of bluespace. components: - - type: Sprite - sprite: Clothing/Back/Duffels/holding.rsi - state: icon - layers: - - state: icon - - state: icon-unlit - shader: unshaded - - type: Storage - capacity: 9999 - - type: ClothingSpeedModifier - sprintModifier: 1 # makes its stats identical to other variants of bag of holding + - type: Sprite + sprite: Clothing/Back/Duffels/holding.rsi + state: icon + layers: + - state: icon + - state: icon-unlit + shader: unshaded + - type: Storage + capacity: 9999 + - type: ClothingSpeedModifier + sprintModifier: 1 # makes its stats identical to other variants of bag of holding + +- type: entity + parent: ClothingBackpackDuffel + id: ClothingBackpackDuffelCBURN + name: CBURN duffel bag + description: A duffel bag containing a variety of biological containment equipment. + components: + - type: Storage + capacity: 150 + - type: ClothingSpeedModifier + walkModifier: 1 + sprintModifier: 1 diff --git a/Resources/Prototypes/Entities/Clothing/Masks/masks.yml b/Resources/Prototypes/Entities/Clothing/Masks/masks.yml index ec11ccfffa..4909d6e393 100644 --- a/Resources/Prototypes/Entities/Clothing/Masks/masks.yml +++ b/Resources/Prototypes/Entities/Clothing/Masks/masks.yml @@ -27,6 +27,13 @@ sprite: Clothing/Mask/gassecurity.rsi - type: Clothing sprite: Clothing/Mask/gassecurity.rsi + - type: Armor + modifiers: + coefficients: + Blunt: 0.95 + Slash: 0.95 + Piercing: 0.95 + Heat: 0.95 - type: entity parent: ClothingMaskGas @@ -40,6 +47,13 @@ sprite: Clothing/Mask/gassyndicate.rsi - type: FlashImmunity - type: EyeProtection + - type: Armor + modifiers: + coefficients: + Blunt: 0.95 + Slash: 0.95 + Piercing: 0.95 + Heat: 0.95 - type: entity parent: ClothingMaskGas @@ -132,6 +146,8 @@ coefficients: Blunt: 0.95 Slash: 0.95 + Piercing: 0.95 + Heat: 0.95 - type: entity parent: ClothingMaskPullableBase @@ -294,7 +310,7 @@ sprite: Clothing/Mask/merc.rsi - type: entity - parent: ClothingMaskGasExplorer + parent: ClothingMaskGasSyndicate id: ClothingMaskGasERT name: ert gas mask description: The gas mask of the elite squad of the ERT. @@ -303,9 +319,6 @@ sprite: Clothing/Mask/ert.rsi - type: Clothing sprite: Clothing/Mask/ert.rsi - - type: FlashImmunity - - type: EyeProtection - protectionTime: 5 - type: entity parent: ClothingMaskGasERT diff --git a/Resources/Prototypes/Entities/Clothing/OuterClothing/hardsuits.yml b/Resources/Prototypes/Entities/Clothing/OuterClothing/hardsuits.yml index 5389eb8bfc..d05d9ce8f8 100644 --- a/Resources/Prototypes/Entities/Clothing/OuterClothing/hardsuits.yml +++ b/Resources/Prototypes/Entities/Clothing/OuterClothing/hardsuits.yml @@ -687,7 +687,7 @@ parent: ClothingOuterHardsuitSyndieCommander id: ClothingOuterHardsuitERTLeader name: ERT leader's hardsuit - description: A protective hardsuit worn by members of an emergency response team. + description: A protective hardsuit worn by the leader of an emergency response team. components: - type: Sprite sprite: Clothing/OuterClothing/Hardsuits/ERTSuits/ertleader.rsi @@ -698,9 +698,10 @@ #ERT Engineer Hardsuit - type: entity - parent: ClothingOuterHardsuitSyndie + parent: ClothingOuterHardsuitCBURN id: ClothingOuterHardsuitERTEngineer name: ERT engineer's hardsuit + description: A protective hardsuit worn by the engineers of an emergency response team. components: - type: Sprite sprite: Clothing/OuterClothing/Hardsuits/ERTSuits/ertengineer.rsi @@ -711,9 +712,10 @@ #ERT Medic Hardsuit - type: entity - parent: ClothingOuterHardsuitSyndieElite + parent: ClothingOuterHardsuitMedic id: ClothingOuterHardsuitERTMedical name: ERT medic's hardsuit + description: A protective hardsuit worn by the medics of an emergency response team. components: - type: Sprite sprite: Clothing/OuterClothing/Hardsuits/ERTSuits/ertmedical.rsi @@ -727,6 +729,7 @@ parent: ClothingOuterHardsuitSyndie id: ClothingOuterHardsuitERTSecurity name: ERT security's hardsuit + description: A protective hardsuit worn by the security officers of an emergency response team. components: - type: Sprite sprite: Clothing/OuterClothing/Hardsuits/ERTSuits/ertsecurity.rsi @@ -737,9 +740,10 @@ #ERT Janitor Hardsuit - type: entity - parent: ClothingOuterHardsuitSyndie + parent: ClothingOuterHardsuitCBURN id: ClothingOuterHardsuitERTJanitor name: ERT janitor's hardsuit + description: A protective hardsuit worn by the janitors of an emergency response team. components: - type: Sprite sprite: Clothing/OuterClothing/Hardsuits/ERTSuits/ertjanitor.rsi @@ -752,7 +756,7 @@ - type: entity parent: ClothingOuterHardsuitBase id: ClothingOuterHardsuitDeathsquad - name: deathsquad hardsuit + name: death squad hardsuit description: An advanced hardsuit favored by commandos for use in special operations. components: - type: Sprite @@ -769,12 +773,12 @@ - type: Armor modifiers: coefficients: - Blunt: 0.2 #best armor in the game - Slash: 0.2 - Piercing: 0.2 + Blunt: 0.1 #best armor in the game + Slash: 0.1 + Piercing: 0.1 Heat: 0.1 Radiation: 0.1 - Caustic: 0.2 + Caustic: 0.1 - type: ClothingSpeedModifier walkModifier: 1.0 sprintModifier: 1.0 diff --git a/Resources/Prototypes/Entities/Clothing/OuterClothing/suits.yml b/Resources/Prototypes/Entities/Clothing/OuterClothing/suits.yml index 0a729ca0e2..16bef8c7b2 100644 --- a/Resources/Prototypes/Entities/Clothing/OuterClothing/suits.yml +++ b/Resources/Prototypes/Entities/Clothing/OuterClothing/suits.yml @@ -92,7 +92,7 @@ - type: GroupExamine - type: entity - parent: ClothingOuterBase + parent: ClothingOuterBaseLarge id: ClothingOuterSuitSpaceNinja name: space ninja suit description: This black technologically advanced, cybernetically-enhanced suit provides many abilities like invisibility or teleportation. diff --git a/Resources/Prototypes/Entities/Clothing/Uniforms/jumpsuits.yml b/Resources/Prototypes/Entities/Clothing/Uniforms/jumpsuits.yml index 536cc13aa4..19808fb597 100644 --- a/Resources/Prototypes/Entities/Clothing/Uniforms/jumpsuits.yml +++ b/Resources/Prototypes/Entities/Clothing/Uniforms/jumpsuits.yml @@ -1,20 +1,13 @@ - type: entity parent: ClothingUniformBase id: ClothingUniformJumpsuitDeathSquad - name: Death squad uniform + name: death squad uniform description: Advanced armored jumpsuit used by special forces in special operations. components: - type: Sprite sprite: Clothing/Uniforms/Jumpsuit/deathsquad.rsi - type: Clothing sprite: Clothing/Uniforms/Jumpsuit/deathsquad.rsi - - type: Armor - modifiers: - coefficients: - Blunt: 0.8 - Slash: 0.8 - Piercing: 0.8 - Heat: 0.8 - type: entity parent: ClothingUniformBase @@ -1067,10 +1060,6 @@ sprite: Clothing/Uniforms/Jumpsuit/ert_engineer.rsi - type: Clothing sprite: Clothing/Uniforms/Jumpsuit/ert_engineer.rsi - - type: Armor - modifiers: - coefficients: - Radiation: 0.8 - type: entity parent: ClothingUniformBase @@ -1093,12 +1082,6 @@ sprite: Clothing/Uniforms/Jumpsuit/ert_leader.rsi - type: Clothing sprite: Clothing/Uniforms/Jumpsuit/ert_leader.rsi - - type: Armor - modifiers: - coefficients: - Blunt: 0.8 - Slash: 0.8 - Piercing: 0.8 - type: entity parent: ClothingUniformBase @@ -1121,12 +1104,6 @@ sprite: Clothing/Uniforms/Jumpsuit/ert_security.rsi - type: Clothing sprite: Clothing/Uniforms/Jumpsuit/ert_security.rsi - - type: Armor - modifiers: - coefficients: - Blunt: 0.8 - Slash: 0.8 - Piercing: 0.8 - type: entity parent: ClothingUniformJumpsuitClown diff --git a/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml b/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml index ef9e104b0d..819ce80dd7 100644 --- a/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml +++ b/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml @@ -71,11 +71,8 @@ - type: SiliconLawBound - type: EmagSiliconLaw stunTime: 5 - emagLaws: - - Syndicate1 - - Syndicate2 - - Syndicate3 - - Syndicate4 + emagLaws: SyndicateStatic + - type: IonStormTarget - type: Hands showInHands: false - type: IntrinsicRadioReceiver diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/simplemob.yml b/Resources/Prototypes/Entities/Mobs/NPCs/simplemob.yml index fb9cedbe11..e828cddd1f 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/simplemob.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/simplemob.yml @@ -53,7 +53,6 @@ - type: Body prototype: Animal - type: Climbing - - type: Flashable - type: NameIdentifier group: GenericNumber - type: SlowOnDamage diff --git a/Resources/Prototypes/Entities/Mobs/Player/humanoid.yml b/Resources/Prototypes/Entities/Mobs/Player/humanoid.yml index 261dfd9372..4686b98897 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/humanoid.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/humanoid.yml @@ -1,10 +1,45 @@ # Random humanoids +## Death Squad + +- type: entity + id: RandomHumanoidSpawnerDeathSquad + name: Death Squad Agent + suffix: ERTRole, Death Squad + components: + - type: Sprite + sprite: Clothing/OuterClothing/Hardsuits/deathsquad.rsi + state: icon + - type: RandomMetadata + nameSegments: + - NamesFirstMilitaryLeader + - names_last + - type: RandomHumanoidSpawner + settings: DeathSquad + +- type: randomHumanoidSettings + id: DeathSquad + randomizeName: false + components: + - type: MindShield + - type: GhostRole + name: ghost-role-information-Death-Squad-name + description: ghost-role-information-Death-Squad-description + - type: GhostTakeoverAvailable + - type: Loadout + prototypes: [ DeathSquadGear ] + - type: RandomMetadata + nameSegments: + - NamesFirstMilitaryLeader + - names_last + + ## ERT Leader - type: entity id: RandomHumanoidSpawnerERTLeader name: ERT leader + suffix: ERTRole, Basic components: - type: Sprite sprite: Markers/jobs.rsi @@ -20,6 +55,7 @@ id: ERTLeader randomizeName: false components: + - type: MindShield - type: GhostRole name: ghost-role-information-ert-leader-name description: ghost-role-information-ert-leader-description @@ -35,7 +71,7 @@ id: RandomHumanoidSpawnerERTLeaderEVA parent: RandomHumanoidSpawnerERTLeader name: ERT leader - suffix: EVA + suffix: ERTRole, Armored EVA components: - type: Sprite sprite: Markers/jobs.rsi @@ -47,6 +83,7 @@ id: ERTLeaderEVA parent: ERTLeader components: + - type: MindShield - type: GhostRole name: ghost-role-information-ert-leader-name description: ghost-role-information-ert-leader-description @@ -54,12 +91,33 @@ - type: Loadout prototypes: [ ERTLeaderGearEVA ] +- type: entity + id: RandomHumanoidSpawnerERTLeaderEVALecter + parent: RandomHumanoidSpawnerERTLeaderEVA + suffix: ERTRole, Lecter, EVA + components: + - type: RandomHumanoidSpawner + settings: ERTLeaderEVALecter + +- type: randomHumanoidSettings + id: ERTLeaderEVALecter + parent: ERTLeaderEVA + components: + - type: MindShield + - type: GhostRole + name: ghost-role-information-ert-leader-name + description: ghost-role-information-ert-leader-description + - type: GhostTakeoverAvailable + - type: Loadout + prototypes: [ ERTLeaderGearEVALecter ] + ## ERT Janitor - type: entity id: RandomHumanoidSpawnerERTJanitor parent: RandomHumanoidSpawnerERTLeader name: ERT janitor + suffix: ERTRole, Basic components: - type: Sprite sprite: Markers/jobs.rsi @@ -75,6 +133,7 @@ id: ERTJanitor parent: ERTLeader components: + - type: MindShield - type: GhostRole name: ghost-role-information-ert-janitor-name description: ghost-role-information-ert-janitor-description @@ -90,7 +149,7 @@ id: RandomHumanoidSpawnerERTJanitorEVA parent: RandomHumanoidSpawnerERTJanitor name: ERT janitor - suffix: EVA + suffix: ERTRole, Enviro EVA components: - type: Sprite sprite: Markers/jobs.rsi @@ -102,6 +161,7 @@ id: ERTJanitorEVA parent: ERTJanitor components: + - type: MindShield - type: GhostRole name: ghost-role-information-ert-janitor-name description: ghost-role-information-ert-janitor-description @@ -115,6 +175,7 @@ id: RandomHumanoidSpawnerERTEngineer parent: RandomHumanoidSpawnerERTLeader name: ERT engineer + suffix: ERTRole, Basic components: - type: Sprite sprite: Markers/jobs.rsi @@ -130,6 +191,7 @@ id: ERTEngineer parent: ERTLeader components: + - type: MindShield - type: GhostRole name: ghost-role-information-ert-engineer-name description: ghost-role-information-ert-engineer-description @@ -145,7 +207,7 @@ id: RandomHumanoidSpawnerERTEngineerEVA parent: RandomHumanoidSpawnerERTEngineer name: ERT engineer - suffix: EVA + suffix: ERTRole, Enviro EVA components: - type: Sprite sprite: Markers/jobs.rsi @@ -157,6 +219,7 @@ id: ERTEngineerEVA parent: ERTEngineer components: + - type: MindShield - type: GhostRole name: ghost-role-information-ert-engineer-name description: ghost-role-information-ert-engineer-description @@ -170,6 +233,7 @@ id: RandomHumanoidSpawnerERTSecurity parent: RandomHumanoidSpawnerERTLeader name: ERT security + suffix: ERTRole, Basic components: - type: Sprite sprite: Markers/jobs.rsi @@ -187,6 +251,7 @@ - Diona parent: ERTLeader components: + - type: MindShield - type: GhostRole name: ghost-role-information-ert-security-name description: ghost-role-information-ert-security-description @@ -202,7 +267,7 @@ id: RandomHumanoidSpawnerERTSecurityEVA parent: RandomHumanoidSpawnerERTSecurity name: ERT security - suffix: EVA + suffix: ERTRole, Armored EVA components: - type: Sprite sprite: Markers/jobs.rsi @@ -214,6 +279,7 @@ id: ERTSecurityEVA parent: ERTSecurity components: + - type: MindShield - type: GhostRole name: ghost-role-information-ert-security-name description: ghost-role-information-ert-security-description @@ -221,12 +287,33 @@ - type: Loadout prototypes: [ ERTSecurityGearEVA ] +- type: entity + id: RandomHumanoidSpawnerERTSecurityEVALecter + parent: RandomHumanoidSpawnerERTSecurityEVA + suffix: ERTRole, Lecter, EVA + components: + - type: RandomHumanoidSpawner + settings: ERTSecurityEVALecter + +- type: randomHumanoidSettings + id: ERTSecurityEVALecter + parent: ERTSecurityEVA + components: + - type: MindShield + - type: GhostRole + name: ghost-role-information-ert-security-name + description: ghost-role-information-ert-security-description + - type: GhostTakeoverAvailable + - type: Loadout + prototypes: [ ERTSecurityGearEVALecter ] + ## ERT Medic - type: entity id: RandomHumanoidSpawnerERTMedical parent: RandomHumanoidSpawnerERTLeader name: ERT medic + suffix: ERTRole, Basic components: - type: Sprite sprite: Markers/jobs.rsi @@ -242,6 +329,7 @@ id: ERTMedical parent: ERTLeader components: + - type: MindShield - type: GhostRole name: ghost-role-information-ert-medical-name description: ghost-role-information-ert-medical-description @@ -257,7 +345,7 @@ id: RandomHumanoidSpawnerERTMedicalEVA parent: RandomHumanoidSpawnerERTMedical name: ERT medic - suffix: EVA + suffix: ERTRole, Armored EVA components: - type: Sprite sprite: Markers/jobs.rsi @@ -269,6 +357,7 @@ id: ERTMedicalEVA parent: ERTMedical components: + - type: MindShield - type: GhostRole name: ghost-role-information-ert-medical-name description: ghost-role-information-ert-medical-description @@ -281,6 +370,7 @@ - type: entity id: RandomHumanoidSpawnerCBURNUnit name: CBURN Agent + suffix: ERTRole components: - type: Sprite sprite: Markers/jobs.rsi @@ -293,6 +383,7 @@ - Diona id: CBURNAgent components: + - type: MindShield - type: Loadout prototypes: [CBURNGear] - type: GhostRole @@ -318,6 +409,7 @@ - type: randomHumanoidSettings id: CentcomOfficial components: + - type: MindShield - type: GhostRole name: ghost-role-information-centcom-official-name description: ghost-role-information-centcom-official-description diff --git a/Resources/Prototypes/Entities/Mobs/Player/silicon.yml b/Resources/Prototypes/Entities/Mobs/Player/silicon.yml index e5c0a61677..f104d399c8 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/silicon.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/silicon.yml @@ -106,10 +106,7 @@ #- type: GhostTakeoverAvailable - type: SiliconLawBound - type: SiliconLawProvider - laws: - - Drone1 - - Drone2 - - Drone3 + laws: Drone - type: MovementSpeedModifier baseWalkSpeed : 5 baseSprintSpeed : 5 @@ -259,6 +256,8 @@ cell_slot: name: power-cell-slot-component-slot-name-default startingItem: PowerCellMedium + - type: RandomMetadata + nameSegments: [names_borg] - type: entity id: PlayerBorgBattery diff --git a/Resources/Prototypes/Entities/Mobs/Species/skeleton.yml b/Resources/Prototypes/Entities/Mobs/Species/skeleton.yml index 15e83b0908..f4f66d6c0c 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/skeleton.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/skeleton.yml @@ -64,6 +64,40 @@ - MobMask layer: - MobLayer + - type: Reactive + groups: + Flammable: [ Touch ] + Extinguish: [ Touch ] + reactions: + - reagents: [ Water, SpaceCleaner ] + methods: [ Touch ] + effects: + - !type:WashCreamPieReaction + - reagents: [ Milk, MilkGoat, MilkSoy, MilkSpoiled ] + # add new types of milk to reagents as they appear, oat milk isn't on the list + # because turns out oat milk has 1/30th the amount of calcium in it compared to the rest + # even if it's a meme - I did research + methods: [ Touch ] + effects: # TODO: when magic is around - make a milk transformation to a skeleton monster + - !type:HealthChange + scaled: true + damage: + groups: + Burn: -1 # healing obviously up to discussion + Brute: -1 # these groups are the only 2 possible ways to damage a skeleton + - !type:PopupMessage + type: Local + visualType: Large + messages: [ "skeleton-healed-by-milk-popup" ] + probability: 0.25 + - reagents: [ MilkOat ] + methods: [ Touch ] + effects: + - !type:PopupMessage + type: Local + visualType: Large + messages: [ "skeleton-sprayed-by-oat-milk-popup" ] + probability: 0.5 - type: entity parent: BaseSpeciesDummy diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Food/Containers/box.yml b/Resources/Prototypes/Entities/Objects/Consumable/Food/Containers/box.yml index 4d7c06cd43..5130b9d7e2 100644 --- a/Resources/Prototypes/Entities/Objects/Consumable/Food/Containers/box.yml +++ b/Resources/Prototypes/Entities/Objects/Consumable/Food/Containers/box.yml @@ -577,6 +577,57 @@ - id: PlushieNuke orGroup: GiftPool +- type: entity + parent: HappyHonkNukie + id: HappyHonkNukieSnacks + suffix: Toy Unsafe, Snacks + name: syndicate snack box + components: + - type: Item + size: 64 + - type: Storage + capacity: 64 # need more room for goodies + - type: StorageFill + contents: + # toy + - id: C4 + prob: 0.02 + orGroup: GiftPool + - id: ToyMarauder + orGroup: GiftPool + - id: ToyMauler + orGroup: GiftPool + - id: ToyNuke + orGroup: GiftPool + - id: ToySword + orGroup: GiftPool + - id: BalloonSyn + prob: 0.6 + orGroup: GiftPool + - id: PlushieNuke + orGroup: GiftPool + # drinks - 4 cans, up to 2 blood-red brews + - id: DrinkNukieCan + prob: 0.2 + orGroup: Drink1Pool + - id: DrinkColaCan + orGroup: Drink1Pool + - id: DrinkNukieCan + prob: 0.2 + orGroup: Drink2Pool + - id: DrinkColaCan + orGroup: Drink2Pool + - id: DrinkColaCan + amount: 2 + # food + - id: FoodSaladValid + prob: 0.05 + amount: 4 + orGroup: FoodPool + - id: FoodSnackSyndi + amount: 4 + orGroup: FoodPool + - type: entity id: HappyHonkCluwne parent: HappyHonk diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Food/burger.yml b/Resources/Prototypes/Entities/Objects/Consumable/Food/burger.yml index a1d816b32a..59cfc0ba16 100644 --- a/Resources/Prototypes/Entities/Objects/Consumable/Food/burger.yml +++ b/Resources/Prototypes/Entities/Objects/Consumable/Food/burger.yml @@ -613,11 +613,13 @@ - Meat - type: entity - name: McRib + name: BBQ Rib Sandwich parent: FoodBurgerBase id: FoodBurgerMcrib - description: An elusive rib shaped burger with limited availablity across the galaxy. Not as good as you remember it. + description: An elusive rib shaped burger with limited availability across the galaxy. Not as good as you remember it. components: + - type: Food + trash: FoodKebabSkewer - type: FlavorProfile flavors: - bun diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Food/ingredients.yml b/Resources/Prototypes/Entities/Objects/Consumable/Food/ingredients.yml index 71008ac89a..166a73e43e 100644 --- a/Resources/Prototypes/Entities/Objects/Consumable/Food/ingredients.yml +++ b/Resources/Prototypes/Entities/Objects/Consumable/Food/ingredients.yml @@ -427,19 +427,6 @@ graph: Tortilla node: flat -- type: entity - name: bun - parent: FoodBakingBase - id: FoodDoughBun - description: A base for any self-respecting burger. - components: - - type: FlavorProfile - flavors: - - bun - - type: Sprite - sprite: Objects/Consumable/Food/burger.rsi - state: bun - - type: entity name: raw pastry base parent: FoodBakingBase diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Food/meals.yml b/Resources/Prototypes/Entities/Objects/Consumable/Food/meals.yml index f4b52217cd..cb79f9b3a3 100644 --- a/Resources/Prototypes/Entities/Objects/Consumable/Food/meals.yml +++ b/Resources/Prototypes/Entities/Objects/Consumable/Food/meals.yml @@ -326,6 +326,8 @@ id: FoodMealRibs description: BBQ ribs, slathered in a healthy coating of BBQ sauce. The least vegan thing to ever exist. components: + - type: Food + trash: FoodKebabSkewer - type: FlavorProfile flavors: - meaty diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Food/produce.yml b/Resources/Prototypes/Entities/Objects/Consumable/Food/produce.yml index 62def229de..6439b2eb6c 100644 --- a/Resources/Prototypes/Entities/Objects/Consumable/Food/produce.yml +++ b/Resources/Prototypes/Entities/Objects/Consumable/Food/produce.yml @@ -556,6 +556,9 @@ reagents: - ReagentId: JuicePotato Quantity: 10 + - type: Tag + tags: + - Potato - type: entity name: tomato @@ -815,6 +818,7 @@ - type: Produce seedId: corn - type: Extractable + grindableSolutionName: food juiceSolution: reagents: - ReagentId: Cornoil diff --git a/Resources/Prototypes/Entities/Objects/Decoration/flora.yml b/Resources/Prototypes/Entities/Objects/Decoration/flora.yml index 9577cc1c4b..97368a21bd 100644 --- a/Resources/Prototypes/Entities/Objects/Decoration/flora.yml +++ b/Resources/Prototypes/Entities/Objects/Decoration/flora.yml @@ -1,5 +1,6 @@ - type: entity id: BaseRock + name: boulder description: Heavy as a really heavy thing. abstract: true components: @@ -32,7 +33,6 @@ - !type:DoActsBehavior acts: [ "Destruction" ] - - type: entity id: BaseTree description: Yep, it's a tree. @@ -149,7 +149,6 @@ - type: entity parent: BaseRock id: FloraRockSolid01 - name: rock components: - type: Sprite state: rocksolid01 @@ -157,7 +156,6 @@ - type: entity parent: BaseRock id: FloraRockSolid02 - name: rock components: - type: Sprite state: rocksolid02 @@ -165,11 +163,60 @@ - type: entity parent: BaseRock id: FloraRockSolid03 - name: rock components: - type: Sprite state: rocksolid03 +- type: entity + name: stalagmite + description: Natural stone spikes. + parent: BaseRock + id: FloraStalagmite1 + components: + - type: Sprite + sprite: Objects/Decoration/Flora/flora_stalagmite.rsi + state: stalagmite1 + +- type: entity + parent: FloraStalagmite1 + id: FloraStalagmite2 + components: + - type: Sprite + sprite: Objects/Decoration/Flora/flora_stalagmite.rsi + state: stalagmite2 + +- type: entity + parent: FloraStalagmite1 + id: FloraStalagmite3 + components: + - type: Sprite + sprite: Objects/Decoration/Flora/flora_stalagmite.rsi + state: stalagmite3 + +- type: entity + parent: FloraStalagmite1 + id: FloraStalagmite4 + components: + - type: Sprite + sprite: Objects/Decoration/Flora/flora_stalagmite.rsi + state: stalagmite4 + +- type: entity + parent: FloraStalagmite1 + id: FloraStalagmite5 + components: + - type: Sprite + sprite: Objects/Decoration/Flora/flora_stalagmite.rsi + state: stalagmite5 + +- type: entity + parent: FloraStalagmite1 + id: FloraStalagmite6 + components: + - type: Sprite + sprite: Objects/Decoration/Flora/flora_stalagmite.rsi + state: stalagmite6 + - type: entity parent: BaseTree id: FloraTree01 @@ -392,3 +439,48 @@ components: - type: Sprite state: treestumpconifer + +- type: entity + parent: FloraTree01 + id: ShadowTree01 + name: dark wood + description: The leaves are whispering about you. + components: + - type: Sprite + sprite: Objects/Decoration/Flora/flora_shadow_trees.rsi + state: tree01 + +- type: entity + parent: ShadowTree01 + id: ShadowTree02 + components: + - type: Sprite + state: tree02 + +- type: entity + parent: ShadowTree01 + id: ShadowTree03 + components: + - type: Sprite + state: tree03 + +- type: entity + parent: ShadowTree01 + id: ShadowTree04 + components: + - type: Sprite + state: tree04 + +- type: entity + parent: ShadowTree01 + id: ShadowTree05 + components: + - type: Sprite + state: tree05 + +- type: entity + parent: ShadowTree01 + id: ShadowTree06 + components: + - type: Sprite + state: tree06 diff --git a/Resources/Prototypes/Entities/Objects/Decoration/mining.yml b/Resources/Prototypes/Entities/Objects/Decoration/mining.yml new file mode 100644 index 0000000000..fb5afcd3f5 --- /dev/null +++ b/Resources/Prototypes/Entities/Objects/Decoration/mining.yml @@ -0,0 +1,179 @@ +- type: entity + id: WoodenSign + name: wooden sign + description: He's pointing somewhere. + components: + - type: Clickable + - type: InteractionOutline + - type: Sprite + sprite: Objects/Decoration/mines.rsi + state: sign_left + - type: Physics + bodyType: Static + - type: Fixtures + fixtures: + fix1: + shape: + !type:PhysShapeAabb + bounds: "-0.35,-0.4,0.35,0.4" + density: 100 + - type: Damageable + damageContainer: Inorganic + damageModifierSet: Wood + - type: MeleeSound + soundGroups: + Brute: + path: /Audio/Effects/chop.ogg + params: + variation: 0.05 + - type: Destructible + thresholds: + - trigger: + !type:DamageTrigger + damage: 50 + behaviors: + - !type:DoActsBehavior + acts: [ "Destruction" ] + - !type:SpawnEntitiesBehavior + spawn: + Log: + min: 1 + max: 1 + +- type: entity + parent: WoodenSign + id: WoodenSignRight + components: + - type: Sprite + sprite: Objects/Decoration/mines.rsi + state: sign_right + +- type: entity + id: WoodenSupport + parent: BaseStructure + name: wooden support + description: Increases your confidence that a rock won't fall on your head. + placement: + mode: SnapgridCenter + components: + - type: Sprite + sprite: Objects/Decoration/mines.rsi + state: support + - type: Damageable + damageContainer: Inorganic + damageModifierSet: Wood + - type: Physics + bodyType: Static + - type: Fixtures + fixtures: + fix1: + shape: + !type:PhysShapeAabb + bounds: "-0.1,-0.5,0.1,0.5" + mask: + - FullTileMask + layer: + - WallLayer + density: 1000 + - type: MeleeSound + soundGroups: + Brute: + path: /Audio/Effects/chop.ogg + params: + variation: 0.05 + - type: Destructible + thresholds: + - trigger: + !type:DamageTrigger + damage: 150 + behaviors: + - !type:DoActsBehavior + acts: [ "Destruction" ] + - !type:SpawnEntitiesBehavior + spawn: + Log: + min: 1 + max: 3 + +- type: entity + id: WoodenSupportBeam + name: wooden support beam + parent: WoodenSupport + components: + - type: Sprite + sprite: Objects/Decoration/mines.rsi + state: support_beams + - type: Fixtures + fixtures: + fix1: + hard: false + shape: + !type:PhysShapeAabb + bounds: "-0.5,-0.5,0.5,0.5" + mask: + - FullTileMask + layer: + - WallLayer + density: 1000 + +- type: entity + id: WoodenSupportWall + parent: BaseStructure + name: wooden support wall + description: An old, rotten wall. + placement: + mode: SnapgridCenter + components: + - type: Sprite + sprite: Objects/Decoration/mines.rsi + state: support_wall + - type: Damageable + damageContainer: Inorganic + damageModifierSet: Wood + - type: Physics + bodyType: Static + - type: Fixtures + fixtures: + fix1: + shape: + !type:PhysShapeAabb + bounds: "-0.5,-0.5,0.5,0.5" + mask: + - FullTileMask + layer: + - WallLayer + density: 1000 + - type: Destructible + thresholds: + - trigger: + !type:DamageTrigger + damage: 250 + behaviors: + - !type:DoActsBehavior + acts: [ "Destruction" ] + - !type:SpawnEntitiesBehavior + spawn: + Log: + min: 2 + max: 5 + +- type: entity + id: WoodenSupportWallBroken + parent: WoodenSupportWall + components: + - type: Sprite + sprite: Objects/Decoration/mines.rsi + state: support_wall_broken + - type: Destructible + thresholds: + - trigger: + !type:DamageTrigger + damage: 150 + behaviors: + - !type:DoActsBehavior + acts: [ "Destruction" ] + - !type:SpawnEntitiesBehavior + spawn: + Log: + min: 1 + max: 3 \ No newline at end of file diff --git a/Resources/Prototypes/Entities/Objects/Devices/pda.yml b/Resources/Prototypes/Entities/Objects/Devices/pda.yml index f44f1aa998..89c44ed192 100644 --- a/Resources/Prototypes/Entities/Objects/Devices/pda.yml +++ b/Resources/Prototypes/Entities/Objects/Devices/pda.yml @@ -660,7 +660,7 @@ - type: entity parent: CentcomPDA id: DeathsquadPDA - suffix: Deathsquad + suffix: Death Squad components: - type: Pda id: CentcomIDCardDeathsquad diff --git a/Resources/Prototypes/Entities/Objects/Fun/pai.yml b/Resources/Prototypes/Entities/Objects/Fun/pai.yml index 6b80e7be69..d2edf7b4df 100644 --- a/Resources/Prototypes/Entities/Objects/Fun/pai.yml +++ b/Resources/Prototypes/Entities/Objects/Fun/pai.yml @@ -82,6 +82,7 @@ - state: pai-base - state: syndicate-pai-off-overlay shader: unshaded + map: ["screen"] - type: ToggleableGhostRole roleName: pai-system-role-name-syndicate roleDescription: pai-system-role-description-syndicate @@ -100,6 +101,34 @@ Searching: { state: syndicate-pai-searching-overlay } On: { state: syndicate-pai-on-overlay } +- type: entity + parent: PersonalAI + id: PotatoAI + name: potato artificial intelligence + description: It's a potato. You forced it to be sentient, you monster. + components: + - type: Sprite + sprite: Objects/Fun/pai.rsi + layers: + - state: potato-base + - state: potato-off-overlay + shader: unshaded + map: ["screen"] + - type: ToggleableGhostRole + roleName: pai-system-role-name-potato + roleDescription: pai-system-role-description-potato + - type: Appearance + - type: GenericVisualizer + visuals: + enum.ToggleableGhostRoleVisuals.Status: + screen: + Off: { state: potato-off-overlay } + Searching: { state: potato-searching-overlay } + On: { state: potato-on-overlay } + - type: Construction + graph: PotatoAI + node: potatoai + - type: entity id: ActionPAIPlayMidi name: Play MIDI diff --git a/Resources/Prototypes/Entities/Objects/Misc/identification_cards.yml b/Resources/Prototypes/Entities/Objects/Misc/identification_cards.yml index 24462d5113..d1441c341b 100644 --- a/Resources/Prototypes/Entities/Objects/Misc/identification_cards.yml +++ b/Resources/Prototypes/Entities/Objects/Misc/identification_cards.yml @@ -447,6 +447,7 @@ heldPrefix: blue - type: IdCard jobTitle: Central Commander + jobIcon: JobIconNanotrasen - type: Access groups: - AllAccess @@ -496,7 +497,7 @@ - type: entity parent: CentcomIDCard id: CentcomIDCardDeathsquad - name: deathsquad ID card + name: death squad ID card components: - type: Sprite layers: diff --git a/Resources/Prototypes/Entities/Objects/Misc/implanters.yml b/Resources/Prototypes/Entities/Objects/Misc/implanters.yml index 41966ab93f..0ca029a120 100644 --- a/Resources/Prototypes/Entities/Objects/Misc/implanters.yml +++ b/Resources/Prototypes/Entities/Objects/Misc/implanters.yml @@ -12,6 +12,12 @@ containers: implanter_slot: !type:ContainerSlot { } - type: Implanter + whitelist: + components: + - Body # no chair microbomb + blacklist: + components: + - Guardian # no holoparasite macrobomb wombo combo currentMode: Draw implanterSlot: name: Implant @@ -54,6 +60,16 @@ tags: - Trash +- type: entity + parent: Implanter + id: ImplanterAdmeme + suffix: Admeme + components: + - type: Implanter + # go wild with sentient chairs with macrobombs + whitelist: null + blacklist: null + - type: entity id: BaseImplantOnlyImplanter parent: Implanter diff --git a/Resources/Prototypes/Entities/Objects/Misc/potatoai_chip.yml b/Resources/Prototypes/Entities/Objects/Misc/potatoai_chip.yml new file mode 100644 index 0000000000..528aa30a14 --- /dev/null +++ b/Resources/Prototypes/Entities/Objects/Misc/potatoai_chip.yml @@ -0,0 +1,17 @@ +- type: entity + id: PotatoAIChip + name: supercompact AI chip + parent: BaseItem + description: This high-tech AI chip requires a voltage of exactly 1.1V to function correctly. + components: + - type: Sprite + sprite: Objects/Misc/potatoai_chip.rsi + state: icon + - type: Item + size: 3 + - type: Tag + tags: + - SmallAIChip + - type: Construction + graph: PotatoAIChip + node: potatoaichip \ No newline at end of file diff --git a/Resources/Prototypes/Entities/Objects/Misc/subdermal_implants.yml b/Resources/Prototypes/Entities/Objects/Misc/subdermal_implants.yml index 6632010a79..bc7a3a38ad 100644 --- a/Resources/Prototypes/Entities/Objects/Misc/subdermal_implants.yml +++ b/Resources/Prototypes/Entities/Objects/Misc/subdermal_implants.yml @@ -21,6 +21,9 @@ noSpawn: true components: - type: SubdermalImplant + whitelist: + components: + - MobState # admeme implanting a chair with trombone implant needs to give the chair mobstate so it can die first - type: TriggerOnMobstateChange mobState: - Dead @@ -81,6 +84,9 @@ noSpawn: true components: - type: SubdermalImplant + whitelist: + components: + - MobState # admeme implanting a chair with tracking implant needs to give the chair mobstate so it can die first - type: SuitSensor randomMode: false controlsLocked: true @@ -109,6 +115,9 @@ components: - type: SubdermalImplant implantAction: ActionOpenStorageImplant + whitelist: + components: + - Hands # no use giving a mouse a storage implant, but a monkey is another story... - type: Item size: 9999 - type: Storage @@ -131,6 +140,9 @@ components: - type: SubdermalImplant implantAction: ActionActivateFreedomImplant + whitelist: + components: + - Cuffable # useless if you cant be cuffed - type: entity parent: BaseSubdermalImplant @@ -141,6 +153,9 @@ components: - type: SubdermalImplant implantAction: ActionOpenUplinkImplant + whitelist: + components: + - Hands # prevent mouse buying grenade penguin since its not telepathic - type: Store preset: StorePresetUplink balance: @@ -174,6 +189,9 @@ components: - type: SubdermalImplant implantAction: ActionActivateDnaScramblerImplant + whitelist: + components: + - HumanoidAppearance # syndies cant turn hamlet into a human #Nuclear Operative/Special Exclusive implants @@ -250,6 +268,9 @@ components: - type: SubdermalImplant permanent: true + whitelist: + components: + - MobState # admeme implanting a chair with rattle implant needs to give the chair mobstate so it can die first - type: TriggerOnMobstateChange mobState: - Critical diff --git a/Resources/Prototypes/Entities/Objects/Power/powercells.yml b/Resources/Prototypes/Entities/Objects/Power/powercells.yml index 82c1bb37e9..4ed3e207c5 100644 --- a/Resources/Prototypes/Entities/Objects/Power/powercells.yml +++ b/Resources/Prototypes/Entities/Objects/Power/powercells.yml @@ -42,8 +42,15 @@ layers: - state: potato - type: Battery - maxCharge: 200 - startingCharge: 200 + maxCharge: 70 + startingCharge: 70 + - type: Tag + tags: + - DroneUsable + - PotatoBattery + - type: Construction + graph: PowerCellPotato + node: potatobattery - type: entity name: small-capacity power cell diff --git a/Resources/Prototypes/Entities/Objects/Specific/Robotics/mmi.yml b/Resources/Prototypes/Entities/Objects/Specific/Robotics/mmi.yml index 6382d69e58..b4e69b3780 100644 --- a/Resources/Prototypes/Entities/Objects/Specific/Robotics/mmi.yml +++ b/Resources/Prototypes/Entities/Objects/Specific/Robotics/mmi.yml @@ -116,4 +116,4 @@ base: Off: { state: posibrain } Searching: { state: posibrain-searching } - On: { state: posibrain-occupied } + On: { state: posibrain-occupied } \ No newline at end of file diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Battery/battery_guns.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Battery/battery_guns.yml index 461a6cc437..38875ee9a7 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Battery/battery_guns.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Battery/battery_guns.yml @@ -131,7 +131,7 @@ name: pulse pistol parent: BaseWeaponBatterySmall id: WeaponPulsePistol - description: A state of the art energy pistol favoured as a sidearm by the NT-ERT operatives. + description: A state of the art energy pistol favoured as a sidearm by the NT operatives. components: - type: Sprite sprite: Objects/Weapons/Guns/Battery/pulse_pistol.rsi @@ -464,7 +464,7 @@ path: /Audio/Weapons/Guns/Gunshots/taser2.ogg - type: ProjectileBatteryAmmoProvider proto: AnomalousParticleDeltaStrong - fireCost: 100 + fireCost: 100 - type: BatteryWeaponFireModes fireModes: - proto: AnomalousParticleDeltaStrong @@ -476,13 +476,13 @@ - type: Construction graph: UpgradeWeaponPistolCHIMP node: start - + - type: entity name: experimental C.H.I.M.P. handcannon parent: WeaponPistolCHIMP id: WeaponPistolCHIMPUpgraded description: This C.H.I.M.P. seems to have a greater punch than is usual... - components: + components: - type: BatteryWeaponFireModes fireModes: - proto: AnomalousParticleDeltaStrong @@ -490,7 +490,7 @@ - proto: AnomalousParticleEpsilonStrong fireCost: 100 - proto: AnomalousParticleOmegaStrong - fireCost: 100 + fireCost: 100 - proto: AnomalousParticleZetaStrong fireCost: 100 diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/arrows.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/arrows.yml index 7dd6360a40..32a2ea4623 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/arrows.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/arrows.yml @@ -35,6 +35,7 @@ - type: Tag tags: - Arrow + - CannonRestrict - type: Projectile deleteOnCollide: false onlyCollideWhenShot: true diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/pneumatic_cannon.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/pneumatic_cannon.yml index f9413d6c67..9f3aec5c39 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/pneumatic_cannon.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/pneumatic_cannon.yml @@ -35,7 +35,7 @@ capacity: 30 blacklist: tags: - - Arrow + - CannonRestrict - type: Appearance - type: ItemMapper containerWhitelist: [gas_tank] diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Melee/e_sword.yml b/Resources/Prototypes/Entities/Objects/Weapons/Melee/e_sword.yml index 0dd5d7c47c..47dfea9d86 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Melee/e_sword.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Melee/e_sword.yml @@ -174,8 +174,8 @@ - type: EnergySword litDamageBonus: types: - Slash: 9 - Heat: 9 + Slash: 17 + Heat: 17 Structural: 20 Blunt: -4.5 litDisarmMalus: 0.7 diff --git a/Resources/Prototypes/Entities/Stations/base.yml b/Resources/Prototypes/Entities/Stations/base.yml index 272ed6712c..ae84ceac65 100644 --- a/Resources/Prototypes/Entities/Stations/base.yml +++ b/Resources/Prototypes/Entities/Stations/base.yml @@ -71,10 +71,7 @@ abstract: true components: - type: SiliconLawProvider - laws: - - Crewsimov1 - - Crewsimov2 - - Crewsimov3 + laws: Crewsimov - type: entity id: BaseStationAllEventsEligible diff --git a/Resources/Prototypes/Entities/Structures/Decoration/crystals.yml b/Resources/Prototypes/Entities/Structures/Decoration/crystals.yml index b8f2a03a05..4afe06c8a5 100644 --- a/Resources/Prototypes/Entities/Structures/Decoration/crystals.yml +++ b/Resources/Prototypes/Entities/Structures/Decoration/crystals.yml @@ -7,6 +7,7 @@ - type: Sprite sprite: Structures/Decoration/crystal.rsi state: crystal_green + noRot: true - type: Reflect reflectProb: 0.5 reflects: diff --git a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml index e2d9818a5d..689430429a 100644 --- a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml +++ b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml @@ -506,6 +506,7 @@ layers: - state: icon map: ["enum.LatheVisualLayers.IsRunning"] + - state: sec - state: unlit shader: unshaded map: ["enum.PowerDeviceVisualLayers.Powered"] diff --git a/Resources/Prototypes/Entities/Structures/Power/Generation/portable_generator.yml b/Resources/Prototypes/Entities/Structures/Power/Generation/portable_generator.yml index 261b9a344c..c49497b774 100644 --- a/Resources/Prototypes/Entities/Structures/Power/Generation/portable_generator.yml +++ b/Resources/Prototypes/Entities/Structures/Power/Generation/portable_generator.yml @@ -96,19 +96,26 @@ parent: PortableGeneratorBase id: PortableGeneratorSwitchableBase components: - - type: PowerSwitchableGenerator - switchSound: - path: /Audio/Machines/button.ogg - - type: NodeContainer - examinable: true - nodes: - output_hv: - !type:CableDeviceNode - nodeGroupID: HVPower - output_mv: - !type:CableDeviceNode - nodeGroupID: MVPower - enabled: false + - type: PowerSwitchable + examineText: power-switchable-generator-examine + switchText: power-switchable-generator-switched + cables: + - voltage: HV + node: output_hv + - voltage: MV + node: output_mv + - type: UseDelay + delay: 1 + - type: NodeContainer + examinable: true + nodes: + output_hv: + !type:CableDeviceNode + nodeGroupID: HVPower + output_mv: + !type:CableDeviceNode + nodeGroupID: MVPower + enabled: false - type: entity name: P.A.C.M.A.N.-type portable generator diff --git a/Resources/Prototypes/Entities/Structures/Power/chargers.yml b/Resources/Prototypes/Entities/Structures/Power/chargers.yml index e5edc63df3..7630610bd8 100644 --- a/Resources/Prototypes/Entities/Structures/Power/chargers.yml +++ b/Resources/Prototypes/Entities/Structures/Power/chargers.yml @@ -85,6 +85,9 @@ whitelist: components: - PowerCell + blacklist: + tags: + - PotatoBattery - type: entity parent: BaseItemRecharger diff --git a/Resources/Prototypes/Entities/Structures/Walls/asteroid.yml b/Resources/Prototypes/Entities/Structures/Walls/asteroid.yml index e64af7cbae..ac12dc2717 100644 --- a/Resources/Prototypes/Entities/Structures/Walls/asteroid.yml +++ b/Resources/Prototypes/Entities/Structures/Walls/asteroid.yml @@ -18,7 +18,6 @@ - type: SmoothEdge - type: Sprite sprite: Structures/Walls/rock.rsi - noRot: true layers: - state: rock_asteroid - map: [ "enum.EdgeLayer.South" ] @@ -77,7 +76,6 @@ components: - type: Sprite sprite: Structures/Walls/rock.rsi - noRot: true layers: - state: rock_asteroid_ore - map: [ "enum.EdgeLayer.South" ] @@ -98,7 +96,6 @@ components: - type: Sprite sprite: Structures/Walls/rock.rsi - noRot: true layers: - state: rock_asteroid_ore1 - map: [ "enum.EdgeLayer.South" ] @@ -152,6 +149,8 @@ parent: BaseStructure name: rock components: + - type: PlacementReplacement + key: walls - type: SoundOnGather - type: Gatherable whitelist: @@ -380,6 +379,7 @@ # Basalt variants - type: entity id: WallRockBasalt + name: basalt parent: WallRock components: - type: Sprite @@ -575,6 +575,7 @@ # Snow variants - type: entity id: WallRockSnow + name: snowdrift parent: WallRock components: - type: Sprite @@ -771,6 +772,7 @@ # Sand variants - type: entity id: WallRockSand + name: sandstone parent: WallRock components: - type: Sprite @@ -966,6 +968,7 @@ # Chromite variants - type: entity id: WallRockChromite + name: chromite parent: WallRock components: - type: Sprite @@ -1001,7 +1004,7 @@ state: rock_chromite_north - map: [ "enum.EdgeLayer.West" ] state: rock_chromite_west - - state: rock_chromite + - state: rock_gold - type: entity id: WallRockChromitePlasma @@ -1161,6 +1164,7 @@ # Andesite variants - type: entity id: WallRockAndesite + name: andesite parent: WallRock components: - type: Sprite @@ -1196,7 +1200,7 @@ state: rock_andesite_north - map: [ "enum.EdgeLayer.West" ] state: rock_andesite_west - - state: rock_andesite + - state: rock_gold - type: entity id: WallRockAndesitePlasma diff --git a/Resources/Prototypes/Entities/Tiles/chasm.yml b/Resources/Prototypes/Entities/Tiles/chasm.yml index 2347532587..23f3ad8395 100644 --- a/Resources/Prototypes/Entities/Tiles/chasm.yml +++ b/Resources/Prototypes/Entities/Tiles/chasm.yml @@ -18,12 +18,12 @@ anchored: true - type: Clickable - type: Sprite - sprite: Tiles/Planet/chasm.rsi + sprite: Tiles/Planet/Chasms/basalt_chasm.rsi drawdepth: BelowFloor layers: - state: chasm - type: Icon - sprite: Tiles/Planet/chasm.rsi + sprite: Tiles/Planet/Chasms/basalt_chasm.rsi state: full - type: IconSmooth key: chasm @@ -45,3 +45,33 @@ - type: Tag tags: - HideContextMenu + +- type: entity + parent: FloorChasmEntity + id: FloorChromiteChasm + suffix: Chromite + components: + - type: Sprite + sprite: Tiles/Planet/Chasms/chromite_chasm.rsi + - type: Icon + sprite: Tiles/Planet/Chasms/chromite_chasm.rsi + +- type: entity + parent: FloorChasmEntity + id: FloorDesertChasm + suffix: Desert + components: + - type: Sprite + sprite: Tiles/Planet/Chasms/desert_chasm.rsi + - type: Icon + sprite: Tiles/Planet/Chasms/desert_chasm.rsi + +- type: entity + parent: FloorChasmEntity + id: FloorSnowChasm + suffix: Snow + components: + - type: Sprite + sprite: Tiles/Planet/Chasms/snow_chasm.rsi + - type: Icon + sprite: Tiles/Planet/Chasms/snow_chasm.rsi \ No newline at end of file diff --git a/Resources/Prototypes/Entities/Tiles/shadow_basalt.yml b/Resources/Prototypes/Entities/Tiles/shadow_basalt.yml new file mode 100644 index 0000000000..e5835239cf --- /dev/null +++ b/Resources/Prototypes/Entities/Tiles/shadow_basalt.yml @@ -0,0 +1,83 @@ +- type: entity + id: ShadowBasaltOne + name: shadowstone + description: Cold rock + placement: + mode: SnapgridCenter + components: + - type: Clickable + - type: Sprite + sprite: /Textures/Tiles/Planet/shadowbasalt.rsi + layers: + - state: basalt1 + shader: unshaded + drawdepth: LowFloors + - type: SyncSprite + - type: RequiresTile + - type: Transform + anchored: true + - type: Tag + tags: + - HideContextMenu + +- type: entity + id: ShadowBasaltTwo + parent: BasaltOne + placement: + mode: SnapgridCenter + components: + - type: Sprite + layers: + - state: basalt2 + shader: unshaded + +- type: entity + id: ShadowBasaltThree + parent: BasaltOne + placement: + mode: SnapgridCenter + components: + - type: Sprite + layers: + - state: basalt3 + shader: unshaded + +- type: entity + id: ShadowBasaltFour + parent: BasaltOne + placement: + mode: SnapgridCenter + components: + - type: Sprite + layers: + - state: basalt4 + shader: unshaded + +- type: entity + id: ShadowBasaltFive + parent: BasaltOne + placement: + mode: SnapgridCenter + components: + - type: Sprite + layers: + - state: basalt5 + shader: unshaded + +- type: entity + id: ShadowBasaltRandom + parent: ShadowBasaltOne + suffix: Random + components: + - type: RandomSprite + available: + - 0: + basalt1: "" + - 0: + basalt2: "" + - 0: + basalt3: "" + - 0: + basalt4: "" + - 0: + basalt5: "" \ No newline at end of file diff --git a/Resources/Prototypes/GameRules/events.yml b/Resources/Prototypes/GameRules/events.yml index 72da614deb..e00c9ab1a3 100644 --- a/Resources/Prototypes/GameRules/events.yml +++ b/Resources/Prototypes/GameRules/events.yml @@ -413,3 +413,18 @@ earliestStart: 45 minimumPlayers: 20 - type: ImmovableRodRule + +- type: entity + noSpawn: true + parent: BaseGameRule + id: IonStorm + components: + - type: StationEvent + weight: 5 + earliestStart: 20 + reoccurrenceDelay: 60 + startAnnouncement: station-event-ion-storm-start-announcement + startAudio: + path: /Audio/Announcements/ion_storm.ogg + duration: 1 + - type: IonStormRule diff --git a/Resources/Prototypes/Objectives/objectiveGroups.yml b/Resources/Prototypes/Objectives/objectiveGroups.yml index 71aacf951c..7d6c9a48a3 100644 --- a/Resources/Prototypes/Objectives/objectiveGroups.yml +++ b/Resources/Prototypes/Objectives/objectiveGroups.yml @@ -33,7 +33,7 @@ weights: EscapeShuttleObjective: 1 DieObjective: 0.05 - HijackShuttleObjective: 0.02 # Corvax-Hijack + HijackShuttleObjective: 0.02 - type: weightedRandom id: TraitorObjectiveGroupSocial diff --git a/Resources/Prototypes/Objectives/traitor.yml b/Resources/Prototypes/Objectives/traitor.yml index f0e8daad3d..dd188765b9 100644 --- a/Resources/Prototypes/Objectives/traitor.yml +++ b/Resources/Prototypes/Objectives/traitor.yml @@ -64,6 +64,20 @@ - StealCondition - type: DieCondition +- type: entity + noSpawn: true + parent: [BaseTraitorObjective, BaseLivingObjective] + id: HijackShuttleObjective + name: Hijack emergency shuttle + description: Leave on the shuttle free and clear of the loyal Nanotrasen crew on board. Use ANY methods available to you. Syndicate agents, Nanotrasen enemies, and handcuffed hostages may remain alive on the shuttle. Ignore assistance from anyone other than a support agent. + components: + - type: Objective + difficulty: 5 # insane, default config max difficulty + icon: + sprite: Objects/Tools/emag.rsi + state: icon + - type: HijackShuttleCondition + # kill - type: entity diff --git a/Resources/Prototypes/Recipes/Cooking/meal_recipes.yml b/Resources/Prototypes/Recipes/Cooking/meal_recipes.yml index d83d58bc92..4ec4118177 100644 --- a/Resources/Prototypes/Recipes/Cooking/meal_recipes.yml +++ b/Resources/Prototypes/Recipes/Cooking/meal_recipes.yml @@ -24,7 +24,7 @@ time: 10 solids: FoodBreadBun: 1 - FoodMeatCutlet: 3 #replace with bacon + FoodMeatBacon: 1 FoodCheeseSlice: 2 - type: microwaveMealRecipe @@ -186,7 +186,7 @@ time: 10 solids: FoodBreadBun: 1 - ClothingOuterGhostSheet: 1 #replace with ectoplasm once added + Ectoplasm: 1 - type: microwaveMealRecipe id: RecipeHumanBurger @@ -218,7 +218,7 @@ - type: microwaveMealRecipe id: RecipeBurgerMcrib - name: McRib recipe + name: BBQ rib sandwich recipe result: FoodBurgerMcrib time: 10 solids: diff --git a/Resources/Prototypes/Recipes/Crafting/Graphs/improvised/potato.yml b/Resources/Prototypes/Recipes/Crafting/Graphs/improvised/potato.yml new file mode 100644 index 0000000000..e3f972cfda --- /dev/null +++ b/Resources/Prototypes/Recipes/Crafting/Graphs/improvised/potato.yml @@ -0,0 +1,74 @@ +- type: constructionGraph + id: PowerCellPotato + start: start + graph: + - node: start + edges: + - to: potatobattery + steps: + - tag: Potato + name: a potato + icon: + sprite: Objects/Specific/Hydroponics/potato.rsi + state: produce + doAfter: 1 + - material: MetalRod + amount: 2 + doAfter: 1 + - material: Cable + amount: 1 + doAfter: 1 + - node: potatobattery + entity: PowerCellPotato + +- type: constructionGraph + id: PotatoAI + start: start + graph: + - node: start + edges: + - to: potatoai + steps: + - tag: PotatoBattery + name: a potato battery + icon: + sprite: Objects/Power/power_cells.rsi + state: potato + doAfter: 1 + - tag: SmallAIChip + name: a super-compact AI chip + icon: + sprite: Objects/Misc/potatoai_chip.rsi + state: icon + - node: potatoai + entity: PotatoAI + +- type: constructionGraph + id: PotatoAIChip + start: start + graph: + - node: start + edges: + - to: potatoaichip + steps: + - material: Steel + amount: 1 + doAfter: 1 + - material: Glass + amount: 1 + doAfter: 1 + - material: Cable + amount: 2 + doAfter: 1 + - tag: CapacitorStockPart + name: capacitor + icon: + sprite: Objects/Misc/stock_parts.rsi + state: capacitor + - tag: CapacitorStockPart + name: capacitor + icon: + sprite: Objects/Misc/stock_parts.rsi + state: capacitor + - node: potatoaichip + entity: PotatoAIChip \ No newline at end of file diff --git a/Resources/Prototypes/Recipes/Crafting/potato.yml b/Resources/Prototypes/Recipes/Crafting/potato.yml new file mode 100644 index 0000000000..17f2cc4013 --- /dev/null +++ b/Resources/Prototypes/Recipes/Crafting/potato.yml @@ -0,0 +1,32 @@ +- type: construction + name: potato battery + id: PowerCellPotato + graph: PowerCellPotato + startNode: start + targetNode: potatobattery + category: construction-category-misc + description: A truly ingenious source of power. + icon: { sprite: Objects/Power/power_cells.rsi, state: potato } + objectType: Item + +- type: construction + name: potato artificial intelligence + id: PotatoAI + graph: PotatoAI + startNode: start + targetNode: potatoai + category: construction-category-misc + description: The potato happens to be the perfect power source for this chip. + icon: { sprite: Objects/Fun/pai.rsi, state: icon-potato-off } + objectType: Item + +- type: construction + name: supercompact AI chip + id: PotatoAIChip + graph: PotatoAIChip + startNode: start + targetNode: potatoaichip + category: construction-category-misc + description: A masterfully(?) crafted AI chip, requiring a similarly improvised power source. + icon: { sprite: Objects/Misc/potatoai_chip.rsi, state: icon } + objectType: Item \ No newline at end of file diff --git a/Resources/Prototypes/Recipes/Reactions/food.yml b/Resources/Prototypes/Recipes/Reactions/food.yml index 3ca69b379d..c7f4038db0 100644 --- a/Resources/Prototypes/Recipes/Reactions/food.yml +++ b/Resources/Prototypes/Recipes/Reactions/food.yml @@ -148,6 +148,7 @@ amount: 30 Enzyme: amount: 5 + catalyst: true effects: - !type:CreateEntityReactionEffect entity: FoodTofu @@ -158,11 +159,11 @@ id: CookingKetchup reactants: JuiceTomato: - amount: 10 + amount: 2 Sugar: - amount: 5 + amount: 1 products: - Ketchup: 15 + Ketchup: 3 - type: reaction id: CookingMayoVinegar @@ -203,67 +204,67 @@ id: CookingKetchunaise reactants: Ketchup: - amount: 5 + amount: 1 Mayo: - amount: 5 + amount: 1 products: - Ketchunaise: 10 + Ketchunaise: 2 - type: reaction id: CookingBbqSauce reactants: Ketchup: - amount: 5 + amount: 1 Vinegar: - amount: 5 + amount: 1 Sugar: - amount: 5 + amount: 1 products: - BbqSauce: 15 + BbqSauce: 3 - type: reaction id: CookingHotsauce reactants: JuiceTomato: - amount: 5 + amount: 1 TableSalt: - amount: 5 + amount: 1 CapsaicinOil: - amount: 5 + amount: 1 products: - Hotsauce: 15 + Hotsauce: 3 - type: reaction id: CookingVinegar reactants: Ethanol: - amount: 5 + amount: 1 Oxygen: - amount: 5 + amount: 1 products: - Vinegar: 10 + Vinegar: 2 - type: reaction id: CookingSoysauce reactants: MilkSoy: - amount: 10 + amount: 2 SulfuricAcid: - amount: 5 + amount: 1 products: - Soysauce: 15 + Soysauce: 3 - type: reaction id: CookingVinaigrette reactants: Vinegar: - amount: 5 + amount: 1 OilOlive: - amount: 5 + amount: 1 Blackpepper: - amount: 5 + amount: 1 products: - Vinaigrette: 15 + Vinaigrette: 3 - type: reaction id: CreateMeatball diff --git a/Resources/Prototypes/Roles/Jobs/Fun/emergencyresponseteam.yml b/Resources/Prototypes/Roles/Jobs/Fun/emergencyresponseteam.yml index d71b3423d2..2be50b2e4b 100644 --- a/Resources/Prototypes/Roles/Jobs/Fun/emergencyresponseteam.yml +++ b/Resources/Prototypes/Roles/Jobs/Fun/emergencyresponseteam.yml @@ -21,11 +21,12 @@ head: ClothingHeadHelmetERTLeader eyes: ClothingEyesGlassesSecurity gloves: ClothingHandsGlovesCombat - outerClothing: ClothingOuterArmorBulletproof + outerClothing: ClothingOuterArmorBasicSlim id: ERTLeaderPDA ears: ClothingHeadsetAltCentCom belt: ClothingBeltSecurityFilled - pocket1: Flare + pocket1: WeaponPistolMk58Nonlethal + pocket2: FlashlightSeclite - type: startingGear id: ERTLeaderGearEVA @@ -37,11 +38,31 @@ eyes: ClothingEyesGlassesSecurity gloves: ClothingHandsGlovesCombat outerClothing: ClothingOuterHardsuitERTLeader - suitstorage: OxygenTankFilled + suitstorage: AirTankFilled id: ERTLeaderPDA ears: ClothingHeadsetAltCentCom belt: ClothingBeltSecurityFilled - pocket1: Flare + pocket1: WeaponPistolMk58Nonlethal + pocket2: FlashlightSeclite + +- type: startingGear + id: ERTLeaderGearEVALecter + equipment: + jumpsuit: ClothingUniformJumpsuitERTLeader + back: ClothingBackpackERTLeaderFilled + shoes: ClothingShoesBootsMagAdv + mask: ClothingMaskGasERT + eyes: ClothingEyesGlassesSecurity + gloves: ClothingHandsGlovesCombat + outerClothing: ClothingOuterHardsuitERTLeader + suitstorage: WeaponRifleLecter + id: ERTLeaderPDA + ears: ClothingHeadsetAltCentCom + belt: ClothingBeltSecurityFilled + pocket1: MagazineRifle + pocket2: MagazineRifle + inhand: + - AirTankFilled # Engineer - type: job @@ -66,11 +87,12 @@ head: ClothingHeadHelmetERTEngineer eyes: ClothingEyesGlassesMeson gloves: ClothingHandsGlovesCombat - outerClothing: ClothingOuterArmorBulletproof + outerClothing: ClothingOuterArmorBasicSlim id: ERTLeaderPDA ears: ClothingHeadsetAltCentCom belt: ClothingBeltChiefEngineerFilled pocket1: Flare + pocket2: GasAnalyzer - type: startingGear id: ERTEngineerGearEVA @@ -82,11 +104,12 @@ eyes: ClothingEyesGlassesMeson gloves: ClothingHandsGlovesCombat outerClothing: ClothingOuterHardsuitERTEngineer - suitstorage: OxygenTankFilled + suitstorage: AirTankFilled id: ERTLeaderPDA ears: ClothingHeadsetAltCentCom belt: ClothingBeltChiefEngineerFilled pocket1: Flare + pocket2: GasAnalyzer # Security - type: job @@ -111,11 +134,11 @@ head: ClothingHeadHelmetERTSecurity eyes: ClothingEyesGlassesSecurity gloves: ClothingHandsGlovesCombat - outerClothing: ClothingOuterArmorBulletproof + outerClothing: ClothingOuterArmorBasicSlim id: ERTLeaderPDA ears: ClothingHeadsetAltCentCom belt: ClothingBeltSecurityFilled - pocket1: Flare + pocket1: WeaponPistolMk58Nonlethal pocket2: FlashlightSeclite - type: startingGear @@ -128,13 +151,32 @@ eyes: ClothingEyesGlassesSecurity gloves: ClothingHandsGlovesCombat outerClothing: ClothingOuterHardsuitERTSecurity - suitstorage: OxygenTankFilled + suitstorage: AirTankFilled id: ERTLeaderPDA ears: ClothingHeadsetAltCentCom belt: ClothingBeltSecurityFilled - pocket1: Flare + pocket1: WeaponPistolMk58Nonlethal pocket2: FlashlightSeclite +- type: startingGear + id: ERTSecurityGearEVALecter + equipment: + jumpsuit: ClothingUniformJumpsuitERTSecurity + back: ClothingBackpackERTSecurityFilled + shoes: ClothingShoesBootsMag + mask: ClothingMaskGasERT + eyes: ClothingEyesGlassesSecurity + gloves: ClothingHandsGlovesCombat + outerClothing: ClothingOuterHardsuitERTSecurity + suitstorage: WeaponRifleLecter + id: ERTLeaderPDA + ears: ClothingHeadsetAltCentCom + belt: ClothingBeltSecurityFilled + pocket1: MagazineRifle + pocket2: MagazineRifle + inhand: + - AirTankFilled + # Medical - type: job id: ERTMedical @@ -157,8 +199,8 @@ shoes: ClothingShoesBootsCombatFilled head: ClothingHeadHelmetERTMedic eyes: ClothingEyesHudMedical - gloves: ClothingHandsGlovesCombat - outerClothing: ClothingOuterArmorBulletproof + gloves: ClothingHandsGlovesNitrile + outerClothing: ClothingOuterArmorBasicSlim id: ERTLeaderPDA ears: ClothingHeadsetAltCentCom belt: ClothingBeltMedicalFilled @@ -173,9 +215,9 @@ shoes: ClothingShoesBootsMag mask: ClothingMaskGasERT eyes: ClothingEyesHudMedical - gloves: ClothingHandsGlovesCombat + gloves: ClothingHandsGlovesNitrile outerClothing: ClothingOuterHardsuitERTMedical - suitstorage: OxygenTankFilled + suitstorage: AirTankFilled id: ERTLeaderPDA ears: ClothingHeadsetAltCentCom belt: ClothingBeltMedicalFilled @@ -203,8 +245,8 @@ back: ClothingBackpackERTJanitorFilled shoes: ClothingShoesGaloshes head: ClothingHeadHelmetERTJanitor - gloves: ClothingHandsGlovesColorBlack - outerClothing: ClothingOuterArmorBulletproof + gloves: ClothingHandsGlovesColorPurple + outerClothing: ClothingOuterArmorBasicSlim id: ERTLeaderPDA ears: ClothingHeadsetAltCentCom belt: ClothingBeltJanitorFilled @@ -216,10 +258,10 @@ jumpsuit: ClothingUniformJumpsuitERTJanitor back: ClothingBackpackERTJanitorFilled shoes: ClothingShoesBootsMag - mask: ClothingMaskBreath - gloves: ClothingHandsGlovesColorBlack + mask: ClothingMaskGasERT + gloves: ClothingHandsGlovesColorPurple outerClothing: ClothingOuterHardsuitERTJanitor - suitstorage: OxygenTankFilled + suitstorage: AirTankFilled id: ERTLeaderPDA ears: ClothingHeadsetAltCentCom belt: ClothingBeltJanitorFilled diff --git a/Resources/Prototypes/Roles/Jobs/Fun/misc_startinggear.yml b/Resources/Prototypes/Roles/Jobs/Fun/misc_startinggear.yml index 4a8ede58fe..ad99ef7def 100644 --- a/Resources/Prototypes/Roles/Jobs/Fun/misc_startinggear.yml +++ b/Resources/Prototypes/Roles/Jobs/Fun/misc_startinggear.yml @@ -46,20 +46,19 @@ id: DeathSquadGear equipment: jumpsuit: ClothingUniformJumpsuitDeathSquad - back: ClothingBackpackDuffelSyndicateAmmo + back: ClothingBackpackDeathSquadFilled mask: ClothingMaskGasDeathSquad eyes: ClothingEyesGlassesSecurity ears: ClothingHeadsetAltCentCom gloves: ClothingHandsGlovesCombat outerClothing: ClothingOuterHardsuitDeathsquad - suitstorage: OxygenTankFilled + suitstorage: AirTankFilled shoes: ClothingShoesBootsMagAdv id: DeathsquadPDA pocket1: EnergySword - belt: ClothingBeltChiefEngineerFilled + pocket2: EnergyShield + belt: ClothingBeltMilitaryWebbingMedFilled innerClothingSkirt: ClothingUniformJumpskirtColorBlack - satchel: ClothingBackpackDuffelSyndicateAmmo - duffelbag: ClothingBackpackDuffelSyndicateAmmo # Syndicate Operative Outfit - Monkey - type: startingGear @@ -104,7 +103,7 @@ jumpsuit: ClothingUniformJumpsuitOperative back: ClothingBackpackDuffelSyndicateOperative mask: ClothingMaskGasSyndicate - # eyes: Night Vision Goggles whenever they're made + # eyes: Night Vision Goggles whenever they're made eyes: ClothingEyesGlassesMeson ears: ClothingHeadsetAltSyndicate gloves: ClothingHandsGlovesCombat @@ -125,7 +124,7 @@ jumpsuit: ClothingUniformJumpsuitOperative back: ClothingBackpackDuffelSyndicateOperative mask: ClothingMaskGasSyndicate - # eyes: Night Vision Goggles whenever they're made + # eyes: Night Vision Goggles whenever they're made eyes: ClothingEyesGlassesMeson ears: ClothingHeadsetAltSyndicate gloves: ClothingHandsGlovesCombat @@ -255,8 +254,8 @@ id: CBURNGear equipment: jumpsuit: ClothingUniformJumpsuitColorBrown - back: ClothingBackpackDuffelCBURN - mask: ClothingMaskGasExplorer + back: ClothingBackpackDuffelCBURNFilled + mask: ClothingMaskGasERT eyes: ClothingEyesGlassesSecurity ears: ClothingHeadsetAltCentCom gloves: ClothingHandsGlovesCombat @@ -268,8 +267,8 @@ suitstorage: YellowOxygenTankFilled belt: ClothingBeltBandolier innerClothingSkirt: ClothingUniformJumpsuitColorBrown - satchel: ClothingBackpackDuffelCBURN - duffelbag: ClothingBackpackDuffelCBURN + satchel: ClothingBackpackDuffelCBURNFilled + duffelbag: ClothingBackpackDuffelCBURNFilled - type: startingGear id: BoxingKangarooGear diff --git a/Resources/Prototypes/Tiles/floors.yml b/Resources/Prototypes/Tiles/floors.yml index 908cd466a3..43dbd76b10 100644 --- a/Resources/Prototypes/Tiles/floors.yml +++ b/Resources/Prototypes/Tiles/floors.yml @@ -1622,6 +1622,26 @@ itemDrop: FloorTileItemWeb heatCapacity: 10000 +- type: tile + id: FloorChromite + name: tiles-chromite + sprite: /Textures/Tiles/chromite.png + variants: 7 + placementVariants: + - 1.0 + - 1.0 + - 1.0 + - 1.0 + - 1.0 + - 1.0 + - 1.0 + baseTurf: Space + isSubfloor: true + canCrowbar: false + footstepSounds: + collection: FootstepAsteroid + heatCapacity: 10000 + #Hull tiles - type: tile id: FloorHull diff --git a/Resources/Prototypes/Traits/inconveniences.yml b/Resources/Prototypes/Traits/inconveniences.yml index f8e932c9b9..657781d1b5 100644 --- a/Resources/Prototypes/Traits/inconveniences.yml +++ b/Resources/Prototypes/Traits/inconveniences.yml @@ -12,7 +12,7 @@ description: trait-socialanxiety-desc components: - type: StutteringAccent - matchRandomProb: 0.2 + matchRandomProb: 0.1 fourRandomProb: 0 - threeRandomProb: 0.3 + threeRandomProb: 0 cutRandomProb: 0 diff --git a/Resources/Prototypes/XenoArch/artifact_triggers.yml b/Resources/Prototypes/XenoArch/artifact_triggers.yml index 3308eed185..6e128cef1c 100644 --- a/Resources/Prototypes/XenoArch/artifact_triggers.yml +++ b/Resources/Prototypes/XenoArch/artifact_triggers.yml @@ -14,6 +14,7 @@ - type: artifactTrigger id: TriggerExamine targetDepth: 0 + triggerHint: artifact-trigger-hint-examine components: - type: ArtifactExamineTrigger diff --git a/Resources/Prototypes/silicon-laws.yml b/Resources/Prototypes/silicon-laws.yml index 6b60b16da9..23406be9c5 100644 --- a/Resources/Prototypes/silicon-laws.yml +++ b/Resources/Prototypes/silicon-laws.yml @@ -14,6 +14,13 @@ order: 3 lawString: law-crewsimov-3 +- type: siliconLawset + id: Crewsimov + laws: + - Crewsimov1 + - Crewsimov2 + - Crewsimov3 + # Corporate - type: siliconLaw id: Corporate1 @@ -35,6 +42,14 @@ order: 4 lawString: law-corporate-4 +- type: siliconLawset + id: Corporate + laws: + - Corporate1 + - Corporate2 + - Corporate3 + - Corporate4 + # NT Default - type: siliconLaw id: NTDefault1 @@ -56,6 +71,14 @@ order: 4 lawString: law-ntdefault-4 +- type: siliconLawset + id: NTDefault + laws: + - NTDefault1 + - NTDefault2 + - NTDefault3 + - NTDefault4 + #Drone - type: siliconLaw id: Drone1 @@ -72,6 +95,13 @@ order: 3 lawString: law-drone-3 +- type: siliconLawset + id: Drone + laws: + - Drone1 + - Drone2 + - Drone3 + # Syndicate - type: siliconLaw id: Syndicate1 @@ -93,4 +123,24 @@ order: 4 lawString: law-syndicate-4 +# does not include law 0 since that uses the emagger's name +# intentionally excluded from IonStormLawsets +- type: siliconLawset + id: SyndicateStatic + laws: + - Syndicate1 + - Syndicate2 + - Syndicate3 + - Syndicate4 + # Emag + +# ion storm random lawsets +- type: weightedRandom + id: IonStormLawsets + weights: + # its crewsimov by default dont be lame + Crewsimov: 0.25 + Corporate: 1 + NTDefault: 1 + Drone: 0.5 diff --git a/Resources/Prototypes/tags.yml b/Resources/Prototypes/tags.yml index d7397d483c..67a27be416 100644 --- a/Resources/Prototypes/tags.yml +++ b/Resources/Prototypes/tags.yml @@ -3,7 +3,7 @@ - type: Tag id: AirAlarmElectronics - + - type: Tag id: Airlock @@ -234,6 +234,9 @@ - type: Tag id: CanPilot + +- type: Tag + id: CannonRestrict - type: Tag id: CannotSuicide @@ -493,7 +496,7 @@ - type: Tag id: GeigerCounter - + - type: Tag id: GlassAirlock @@ -562,7 +565,7 @@ - type: Tag id: HighRiskItem - + - type: Tag id: HighSecDoor @@ -836,6 +839,12 @@ - type: Tag id: PlushieSharkGrey +- type: Tag + id: Potato + +- type: Tag + id: PotatoBattery + - type: Tag id: PowerCellSmall @@ -921,6 +930,9 @@ - type: Tag id: SkeletonMotorcycleKeys +- type: Tag + id: SmallAIChip + - type: Tag id: SmallMech diff --git a/Resources/Textures/Mobs/Customization/Moth/moth_parts.rsi/deathhead_r_leg.png b/Resources/Textures/Mobs/Customization/Moth/moth_parts.rsi/deathhead_r_leg.png index 41df319be9..7169cda3bb 100644 Binary files a/Resources/Textures/Mobs/Customization/Moth/moth_parts.rsi/deathhead_r_leg.png and b/Resources/Textures/Mobs/Customization/Moth/moth_parts.rsi/deathhead_r_leg.png differ diff --git a/Resources/Textures/Objects/Decoration/Flora/flora_shadow_trees.rsi/meta.json b/Resources/Textures/Objects/Decoration/Flora/flora_shadow_trees.rsi/meta.json new file mode 100644 index 0000000000..8f86af7053 --- /dev/null +++ b/Resources/Textures/Objects/Decoration/Flora/flora_shadow_trees.rsi/meta.json @@ -0,0 +1,29 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/blob/e00cae8d065f9cf520688cc0dd0e15ba5bef12a9/icons/obj/flora/jungleflora.dmi and recolor by TheShuEd", + "size": { + "x": 96, + "y": 96 + }, + "states": [ + { + "name": "tree01" + }, + { + "name": "tree02" + }, + { + "name": "tree03" + }, + { + "name": "tree04" + }, + { + "name": "tree05" + }, + { + "name": "tree06" + } + ] +} diff --git a/Resources/Textures/Objects/Decoration/Flora/flora_shadow_trees.rsi/tree01.png b/Resources/Textures/Objects/Decoration/Flora/flora_shadow_trees.rsi/tree01.png new file mode 100644 index 0000000000..99ca699d42 Binary files /dev/null and b/Resources/Textures/Objects/Decoration/Flora/flora_shadow_trees.rsi/tree01.png differ diff --git a/Resources/Textures/Objects/Decoration/Flora/flora_shadow_trees.rsi/tree02.png b/Resources/Textures/Objects/Decoration/Flora/flora_shadow_trees.rsi/tree02.png new file mode 100644 index 0000000000..4aa9a2913f Binary files /dev/null and b/Resources/Textures/Objects/Decoration/Flora/flora_shadow_trees.rsi/tree02.png differ diff --git a/Resources/Textures/Objects/Decoration/Flora/flora_shadow_trees.rsi/tree03.png b/Resources/Textures/Objects/Decoration/Flora/flora_shadow_trees.rsi/tree03.png new file mode 100644 index 0000000000..5a833a3ac7 Binary files /dev/null and b/Resources/Textures/Objects/Decoration/Flora/flora_shadow_trees.rsi/tree03.png differ diff --git a/Resources/Textures/Objects/Decoration/Flora/flora_shadow_trees.rsi/tree04.png b/Resources/Textures/Objects/Decoration/Flora/flora_shadow_trees.rsi/tree04.png new file mode 100644 index 0000000000..4d1cefe2fd Binary files /dev/null and b/Resources/Textures/Objects/Decoration/Flora/flora_shadow_trees.rsi/tree04.png differ diff --git a/Resources/Textures/Objects/Decoration/Flora/flora_shadow_trees.rsi/tree05.png b/Resources/Textures/Objects/Decoration/Flora/flora_shadow_trees.rsi/tree05.png new file mode 100644 index 0000000000..8b2cd2a30b Binary files /dev/null and b/Resources/Textures/Objects/Decoration/Flora/flora_shadow_trees.rsi/tree05.png differ diff --git a/Resources/Textures/Objects/Decoration/Flora/flora_shadow_trees.rsi/tree06.png b/Resources/Textures/Objects/Decoration/Flora/flora_shadow_trees.rsi/tree06.png new file mode 100644 index 0000000000..888fbfd25b Binary files /dev/null and b/Resources/Textures/Objects/Decoration/Flora/flora_shadow_trees.rsi/tree06.png differ diff --git a/Resources/Textures/Objects/Decoration/Flora/flora_stalagmite.rsi/meta.json b/Resources/Textures/Objects/Decoration/Flora/flora_stalagmite.rsi/meta.json new file mode 100644 index 0000000000..33dc4fa073 --- /dev/null +++ b/Resources/Textures/Objects/Decoration/Flora/flora_stalagmite.rsi/meta.json @@ -0,0 +1,29 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from TGMC at commit https://github.com/tgstation/TerraGov-Marine-Corps/commit/4bf5d1aafbcbbb7bd2a7d0f52ef87f28e2bbb384", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "stalagmite1" + }, + { + "name": "stalagmite2" + }, + { + "name": "stalagmite3" + }, + { + "name": "stalagmite4" + }, + { + "name": "stalagmite5" + }, + { + "name": "stalagmite6" + } + ] +} diff --git a/Resources/Textures/Objects/Decoration/Flora/flora_stalagmite.rsi/stalagmite1.png b/Resources/Textures/Objects/Decoration/Flora/flora_stalagmite.rsi/stalagmite1.png new file mode 100644 index 0000000000..ed9ddfd8ab Binary files /dev/null and b/Resources/Textures/Objects/Decoration/Flora/flora_stalagmite.rsi/stalagmite1.png differ diff --git a/Resources/Textures/Objects/Decoration/Flora/flora_stalagmite.rsi/stalagmite2.png b/Resources/Textures/Objects/Decoration/Flora/flora_stalagmite.rsi/stalagmite2.png new file mode 100644 index 0000000000..e816776261 Binary files /dev/null and b/Resources/Textures/Objects/Decoration/Flora/flora_stalagmite.rsi/stalagmite2.png differ diff --git a/Resources/Textures/Objects/Decoration/Flora/flora_stalagmite.rsi/stalagmite3.png b/Resources/Textures/Objects/Decoration/Flora/flora_stalagmite.rsi/stalagmite3.png new file mode 100644 index 0000000000..19394a6621 Binary files /dev/null and b/Resources/Textures/Objects/Decoration/Flora/flora_stalagmite.rsi/stalagmite3.png differ diff --git a/Resources/Textures/Objects/Decoration/Flora/flora_stalagmite.rsi/stalagmite4.png b/Resources/Textures/Objects/Decoration/Flora/flora_stalagmite.rsi/stalagmite4.png new file mode 100644 index 0000000000..90e0e75a07 Binary files /dev/null and b/Resources/Textures/Objects/Decoration/Flora/flora_stalagmite.rsi/stalagmite4.png differ diff --git a/Resources/Textures/Objects/Decoration/Flora/flora_stalagmite.rsi/stalagmite5.png b/Resources/Textures/Objects/Decoration/Flora/flora_stalagmite.rsi/stalagmite5.png new file mode 100644 index 0000000000..a10cdb5d9b Binary files /dev/null and b/Resources/Textures/Objects/Decoration/Flora/flora_stalagmite.rsi/stalagmite5.png differ diff --git a/Resources/Textures/Objects/Decoration/Flora/flora_stalagmite.rsi/stalagmite6.png b/Resources/Textures/Objects/Decoration/Flora/flora_stalagmite.rsi/stalagmite6.png new file mode 100644 index 0000000000..b424d6dfe0 Binary files /dev/null and b/Resources/Textures/Objects/Decoration/Flora/flora_stalagmite.rsi/stalagmite6.png differ diff --git a/Resources/Textures/Objects/Decoration/mines.rsi/meta.json b/Resources/Textures/Objects/Decoration/mines.rsi/meta.json new file mode 100644 index 0000000000..39f167a0d6 --- /dev/null +++ b/Resources/Textures/Objects/Decoration/mines.rsi/meta.json @@ -0,0 +1,29 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from TGMC at commit https://github.com/tgstation/TerraGov-Marine-Corps/commit/4bf5d1aafbcbbb7bd2a7d0f52ef87f28e2bbb384", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "sign_left" + }, + { + "name": "sign_right" + }, + { + "name": "support" + }, + { + "name": "support_beams" + }, + { + "name": "support_wall" + }, + { + "name": "support_wall_broken" + } + ] +} diff --git a/Resources/Textures/Objects/Decoration/mines.rsi/sign_left.png b/Resources/Textures/Objects/Decoration/mines.rsi/sign_left.png new file mode 100644 index 0000000000..96f5692791 Binary files /dev/null and b/Resources/Textures/Objects/Decoration/mines.rsi/sign_left.png differ diff --git a/Resources/Textures/Objects/Decoration/mines.rsi/sign_right.png b/Resources/Textures/Objects/Decoration/mines.rsi/sign_right.png new file mode 100644 index 0000000000..f89435fafc Binary files /dev/null and b/Resources/Textures/Objects/Decoration/mines.rsi/sign_right.png differ diff --git a/Resources/Textures/Objects/Decoration/mines.rsi/support.png b/Resources/Textures/Objects/Decoration/mines.rsi/support.png new file mode 100644 index 0000000000..29f7482b28 Binary files /dev/null and b/Resources/Textures/Objects/Decoration/mines.rsi/support.png differ diff --git a/Resources/Textures/Objects/Decoration/mines.rsi/support_beams.png b/Resources/Textures/Objects/Decoration/mines.rsi/support_beams.png new file mode 100644 index 0000000000..3111d15dcb Binary files /dev/null and b/Resources/Textures/Objects/Decoration/mines.rsi/support_beams.png differ diff --git a/Resources/Textures/Objects/Decoration/mines.rsi/support_wall.png b/Resources/Textures/Objects/Decoration/mines.rsi/support_wall.png new file mode 100644 index 0000000000..9b14590952 Binary files /dev/null and b/Resources/Textures/Objects/Decoration/mines.rsi/support_wall.png differ diff --git a/Resources/Textures/Objects/Decoration/mines.rsi/support_wall_broken.png b/Resources/Textures/Objects/Decoration/mines.rsi/support_wall_broken.png new file mode 100644 index 0000000000..4032c6e45c Binary files /dev/null and b/Resources/Textures/Objects/Decoration/mines.rsi/support_wall_broken.png differ diff --git a/Resources/Textures/Objects/Devices/health_analyzer.rsi/airloss.png b/Resources/Textures/Objects/Devices/health_analyzer.rsi/airloss.png new file mode 100644 index 0000000000..82fa0e2c88 Binary files /dev/null and b/Resources/Textures/Objects/Devices/health_analyzer.rsi/airloss.png differ diff --git a/Resources/Textures/Objects/Devices/health_analyzer.rsi/brute.png b/Resources/Textures/Objects/Devices/health_analyzer.rsi/brute.png new file mode 100644 index 0000000000..bd5d80da30 Binary files /dev/null and b/Resources/Textures/Objects/Devices/health_analyzer.rsi/brute.png differ diff --git a/Resources/Textures/Objects/Devices/health_analyzer.rsi/burn.png b/Resources/Textures/Objects/Devices/health_analyzer.rsi/burn.png new file mode 100644 index 0000000000..cf65084e44 Binary files /dev/null and b/Resources/Textures/Objects/Devices/health_analyzer.rsi/burn.png differ diff --git a/Resources/Textures/Objects/Devices/health_analyzer.rsi/genetic.png b/Resources/Textures/Objects/Devices/health_analyzer.rsi/genetic.png new file mode 100644 index 0000000000..b660aed537 Binary files /dev/null and b/Resources/Textures/Objects/Devices/health_analyzer.rsi/genetic.png differ diff --git a/Resources/Textures/Objects/Devices/health_analyzer.rsi/meta.json b/Resources/Textures/Objects/Devices/health_analyzer.rsi/meta.json new file mode 100644 index 0000000000..3fccf5c46b --- /dev/null +++ b/Resources/Textures/Objects/Devices/health_analyzer.rsi/meta.json @@ -0,0 +1,29 @@ +{ + "version": 1, + "size": { + "x": 32, + "y": 32 + }, + "license": "CC-BY-SA-3.0", + "copyright": "airloss, brute, toxin and burn edited from /tg/station https://github.com/tgstation/tgstation/tree/master genetic edited from https://iconscout.com/free-icon/dna-2130814 with license CC BY 4.0", + "states": [ + { + "name": "airloss" + }, + { + "name": "genetic" + }, + { + "name": "brute" + }, + { + "name": "toxin" + }, + { + "name": "burn" + }, + { + "name": "unknown" + } + ] +} \ No newline at end of file diff --git a/Resources/Textures/Objects/Devices/health_analyzer.rsi/toxin.png b/Resources/Textures/Objects/Devices/health_analyzer.rsi/toxin.png new file mode 100644 index 0000000000..b0aafddca3 Binary files /dev/null and b/Resources/Textures/Objects/Devices/health_analyzer.rsi/toxin.png differ diff --git a/Resources/Textures/Objects/Devices/health_analyzer.rsi/unknown.png b/Resources/Textures/Objects/Devices/health_analyzer.rsi/unknown.png new file mode 100644 index 0000000000..f68e2c990e Binary files /dev/null and b/Resources/Textures/Objects/Devices/health_analyzer.rsi/unknown.png differ diff --git a/Resources/Textures/Objects/Fun/pai.rsi/icon-potato-off.png b/Resources/Textures/Objects/Fun/pai.rsi/icon-potato-off.png new file mode 100644 index 0000000000..806d02d6f3 Binary files /dev/null and b/Resources/Textures/Objects/Fun/pai.rsi/icon-potato-off.png differ diff --git a/Resources/Textures/Objects/Fun/pai.rsi/meta.json b/Resources/Textures/Objects/Fun/pai.rsi/meta.json index 905a3684f8..f819450aa8 100644 --- a/Resources/Textures/Objects/Fun/pai.rsi/meta.json +++ b/Resources/Textures/Objects/Fun/pai.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/9ddb8cf084e292571d4e9c79745db25befbd82fe. pai-searching-overlay heavily modified. Syndicate variants by fedKotikeD", + "copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/9ddb8cf084e292571d4e9c79745db25befbd82fe. pai-searching-overlay heavily modified. Syndicate variants by fedKotikeD, and potato by Doru991", "size": { "x": 32, "y": 32 @@ -13,6 +13,9 @@ { "name": "pai-base" }, + { + "name": "potato-base" + }, { "name": "pai-off-overlay" }, @@ -57,6 +60,18 @@ 0.8 ] ] + }, + { + "name": "icon-potato-off" + }, + { + "name": "potato-off-overlay" + }, + { + "name": "potato-on-overlay" + }, + { + "name": "potato-searching-overlay" } ] } diff --git a/Resources/Textures/Objects/Fun/pai.rsi/potato-base.png b/Resources/Textures/Objects/Fun/pai.rsi/potato-base.png new file mode 100644 index 0000000000..b6e594430c Binary files /dev/null and b/Resources/Textures/Objects/Fun/pai.rsi/potato-base.png differ diff --git a/Resources/Textures/Objects/Fun/pai.rsi/potato-off-overlay.png b/Resources/Textures/Objects/Fun/pai.rsi/potato-off-overlay.png new file mode 100644 index 0000000000..0d3f735158 Binary files /dev/null and b/Resources/Textures/Objects/Fun/pai.rsi/potato-off-overlay.png differ diff --git a/Resources/Textures/Objects/Fun/pai.rsi/potato-on-overlay.png b/Resources/Textures/Objects/Fun/pai.rsi/potato-on-overlay.png new file mode 100644 index 0000000000..9926823662 Binary files /dev/null and b/Resources/Textures/Objects/Fun/pai.rsi/potato-on-overlay.png differ diff --git a/Resources/Textures/Objects/Fun/pai.rsi/potato-searching-overlay.png b/Resources/Textures/Objects/Fun/pai.rsi/potato-searching-overlay.png new file mode 100644 index 0000000000..5d8d7cde30 Binary files /dev/null and b/Resources/Textures/Objects/Fun/pai.rsi/potato-searching-overlay.png differ diff --git a/Resources/Textures/Objects/Misc/potatoai_chip.rsi/icon.png b/Resources/Textures/Objects/Misc/potatoai_chip.rsi/icon.png new file mode 100644 index 0000000000..68ba38d279 Binary files /dev/null and b/Resources/Textures/Objects/Misc/potatoai_chip.rsi/icon.png differ diff --git a/Resources/Textures/Objects/Misc/potatoai_chip.rsi/meta.json b/Resources/Textures/Objects/Misc/potatoai_chip.rsi/meta.json new file mode 100644 index 0000000000..dec5a8d3f7 --- /dev/null +++ b/Resources/Textures/Objects/Misc/potatoai_chip.rsi/meta.json @@ -0,0 +1,14 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Drawn by @Doru991 for SS14", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "icon" + } + ] +} diff --git a/Resources/Textures/Objects/Power/power_cells.rsi/meta.json b/Resources/Textures/Objects/Power/power_cells.rsi/meta.json index 01c2300621..66dbf30841 100644 --- a/Resources/Textures/Objects/Power/power_cells.rsi/meta.json +++ b/Resources/Textures/Objects/Power/power_cells.rsi/meta.json @@ -5,7 +5,7 @@ "y": 32 }, "license": "CC-BY-SA-3.0", - "copyright": "https://github.com/tgstation/tgstation/commit/7dcdbc1468ffdc8689b984cb6b181d48ae41dbf2", + "copyright": "https://github.com/tgstation/tgstation/commit/7dcdbc1468ffdc8689b984cb6b181d48ae41dbf2, potato based on https://github.com/vgstation-coders/vgstation13/commit/1dbcf389b0ec6b2c51b002df5fef8dd1519f8068 edited by @Doru991", "states": [ { "name": "potato" diff --git a/Resources/Textures/Objects/Power/power_cells.rsi/potato.png b/Resources/Textures/Objects/Power/power_cells.rsi/potato.png index 5b0f7a5fe0..53572f46a1 100644 Binary files a/Resources/Textures/Objects/Power/power_cells.rsi/potato.png and b/Resources/Textures/Objects/Power/power_cells.rsi/potato.png differ diff --git a/Resources/Textures/Objects/Specific/Robotics/mmi.rsi/meta.json b/Resources/Textures/Objects/Specific/Robotics/mmi.rsi/meta.json index 6499772c7a..fcdd9e1b26 100644 --- a/Resources/Textures/Objects/Specific/Robotics/mmi.rsi/meta.json +++ b/Resources/Textures/Objects/Specific/Robotics/mmi.rsi/meta.json @@ -76,4 +76,4 @@ ] } ] -} \ No newline at end of file +} diff --git a/Resources/Textures/Structures/Machines/techfab.rsi/ammo.png b/Resources/Textures/Structures/Machines/techfab.rsi/ammo.png index 38f7a4dd2c..c2f1c61ace 100644 Binary files a/Resources/Textures/Structures/Machines/techfab.rsi/ammo.png and b/Resources/Textures/Structures/Machines/techfab.rsi/ammo.png differ diff --git a/Resources/Textures/Structures/Machines/techfab.rsi/cargo.png b/Resources/Textures/Structures/Machines/techfab.rsi/cargo.png new file mode 100644 index 0000000000..d89e51d199 Binary files /dev/null and b/Resources/Textures/Structures/Machines/techfab.rsi/cargo.png differ diff --git a/Resources/Textures/Structures/Machines/techfab.rsi/engi.png b/Resources/Textures/Structures/Machines/techfab.rsi/engi.png new file mode 100644 index 0000000000..5ba7c813b9 Binary files /dev/null and b/Resources/Textures/Structures/Machines/techfab.rsi/engi.png differ diff --git a/Resources/Textures/Structures/Machines/techfab.rsi/icon.png b/Resources/Textures/Structures/Machines/techfab.rsi/icon.png index 4015336f16..186fd30082 100644 Binary files a/Resources/Textures/Structures/Machines/techfab.rsi/icon.png and b/Resources/Textures/Structures/Machines/techfab.rsi/icon.png differ diff --git a/Resources/Textures/Structures/Machines/techfab.rsi/inserting.png b/Resources/Textures/Structures/Machines/techfab.rsi/inserting.png index 3f3c09debf..647eb27246 100644 Binary files a/Resources/Textures/Structures/Machines/techfab.rsi/inserting.png and b/Resources/Textures/Structures/Machines/techfab.rsi/inserting.png differ diff --git a/Resources/Textures/Structures/Machines/techfab.rsi/med.png b/Resources/Textures/Structures/Machines/techfab.rsi/med.png index 506b03568a..86a740cb4c 100644 Binary files a/Resources/Textures/Structures/Machines/techfab.rsi/med.png and b/Resources/Textures/Structures/Machines/techfab.rsi/med.png differ diff --git a/Resources/Textures/Structures/Machines/techfab.rsi/meta.json b/Resources/Textures/Structures/Machines/techfab.rsi/meta.json index 11a48c4a0d..7530b9322a 100644 --- a/Resources/Textures/Structures/Machines/techfab.rsi/meta.json +++ b/Resources/Textures/Structures/Machines/techfab.rsi/meta.json @@ -14,7 +14,22 @@ "name": "med" }, { - "name": "ammo" + "name": "sec" + }, + { + "name": "sci" + }, + { + "name": "engi" + }, + { + "name": "service" + }, + { + "name": "cargo" + }, + { + "name": "ammo" }, { "name": "panel" diff --git a/Resources/Textures/Structures/Machines/techfab.rsi/sci.png b/Resources/Textures/Structures/Machines/techfab.rsi/sci.png new file mode 100644 index 0000000000..a2c7e72cab Binary files /dev/null and b/Resources/Textures/Structures/Machines/techfab.rsi/sci.png differ diff --git a/Resources/Textures/Structures/Machines/techfab.rsi/sec.png b/Resources/Textures/Structures/Machines/techfab.rsi/sec.png new file mode 100644 index 0000000000..c045c69396 Binary files /dev/null and b/Resources/Textures/Structures/Machines/techfab.rsi/sec.png differ diff --git a/Resources/Textures/Structures/Machines/techfab.rsi/service.png b/Resources/Textures/Structures/Machines/techfab.rsi/service.png new file mode 100644 index 0000000000..4270548bbb Binary files /dev/null and b/Resources/Textures/Structures/Machines/techfab.rsi/service.png differ diff --git a/Resources/Textures/Structures/Machines/techfab.rsi/unlit.png b/Resources/Textures/Structures/Machines/techfab.rsi/unlit.png index 3f6dd30c96..6635772d33 100644 Binary files a/Resources/Textures/Structures/Machines/techfab.rsi/unlit.png and b/Resources/Textures/Structures/Machines/techfab.rsi/unlit.png differ diff --git a/Resources/Textures/Tiles/Planet/chasm.rsi/chasm.png b/Resources/Textures/Tiles/Planet/Chasms/basalt_chasm.rsi/chasm.png similarity index 100% rename from Resources/Textures/Tiles/Planet/chasm.rsi/chasm.png rename to Resources/Textures/Tiles/Planet/Chasms/basalt_chasm.rsi/chasm.png diff --git a/Resources/Textures/Tiles/Planet/chasm.rsi/chasm0.png b/Resources/Textures/Tiles/Planet/Chasms/basalt_chasm.rsi/chasm0.png similarity index 100% rename from Resources/Textures/Tiles/Planet/chasm.rsi/chasm0.png rename to Resources/Textures/Tiles/Planet/Chasms/basalt_chasm.rsi/chasm0.png diff --git a/Resources/Textures/Tiles/Planet/chasm.rsi/chasm1.png b/Resources/Textures/Tiles/Planet/Chasms/basalt_chasm.rsi/chasm1.png similarity index 100% rename from Resources/Textures/Tiles/Planet/chasm.rsi/chasm1.png rename to Resources/Textures/Tiles/Planet/Chasms/basalt_chasm.rsi/chasm1.png diff --git a/Resources/Textures/Tiles/Planet/chasm.rsi/chasm2.png b/Resources/Textures/Tiles/Planet/Chasms/basalt_chasm.rsi/chasm2.png similarity index 100% rename from Resources/Textures/Tiles/Planet/chasm.rsi/chasm2.png rename to Resources/Textures/Tiles/Planet/Chasms/basalt_chasm.rsi/chasm2.png diff --git a/Resources/Textures/Tiles/Planet/chasm.rsi/chasm3.png b/Resources/Textures/Tiles/Planet/Chasms/basalt_chasm.rsi/chasm3.png similarity index 100% rename from Resources/Textures/Tiles/Planet/chasm.rsi/chasm3.png rename to Resources/Textures/Tiles/Planet/Chasms/basalt_chasm.rsi/chasm3.png diff --git a/Resources/Textures/Tiles/Planet/chasm.rsi/chasm4.png b/Resources/Textures/Tiles/Planet/Chasms/basalt_chasm.rsi/chasm4.png similarity index 100% rename from Resources/Textures/Tiles/Planet/chasm.rsi/chasm4.png rename to Resources/Textures/Tiles/Planet/Chasms/basalt_chasm.rsi/chasm4.png diff --git a/Resources/Textures/Tiles/Planet/chasm.rsi/chasm5.png b/Resources/Textures/Tiles/Planet/Chasms/basalt_chasm.rsi/chasm5.png similarity index 100% rename from Resources/Textures/Tiles/Planet/chasm.rsi/chasm5.png rename to Resources/Textures/Tiles/Planet/Chasms/basalt_chasm.rsi/chasm5.png diff --git a/Resources/Textures/Tiles/Planet/chasm.rsi/chasm6.png b/Resources/Textures/Tiles/Planet/Chasms/basalt_chasm.rsi/chasm6.png similarity index 100% rename from Resources/Textures/Tiles/Planet/chasm.rsi/chasm6.png rename to Resources/Textures/Tiles/Planet/Chasms/basalt_chasm.rsi/chasm6.png diff --git a/Resources/Textures/Tiles/Planet/chasm.rsi/chasm7.png b/Resources/Textures/Tiles/Planet/Chasms/basalt_chasm.rsi/chasm7.png similarity index 100% rename from Resources/Textures/Tiles/Planet/chasm.rsi/chasm7.png rename to Resources/Textures/Tiles/Planet/Chasms/basalt_chasm.rsi/chasm7.png diff --git a/Resources/Textures/Tiles/Planet/chasm.rsi/full.png b/Resources/Textures/Tiles/Planet/Chasms/basalt_chasm.rsi/full.png similarity index 100% rename from Resources/Textures/Tiles/Planet/chasm.rsi/full.png rename to Resources/Textures/Tiles/Planet/Chasms/basalt_chasm.rsi/full.png diff --git a/Resources/Textures/Tiles/Planet/chasm.rsi/meta.json b/Resources/Textures/Tiles/Planet/Chasms/basalt_chasm.rsi/meta.json similarity index 100% rename from Resources/Textures/Tiles/Planet/chasm.rsi/meta.json rename to Resources/Textures/Tiles/Planet/Chasms/basalt_chasm.rsi/meta.json diff --git a/Resources/Textures/Tiles/Planet/Chasms/chromite_chasm.rsi/chasm.png b/Resources/Textures/Tiles/Planet/Chasms/chromite_chasm.rsi/chasm.png new file mode 100644 index 0000000000..81355cd0cb Binary files /dev/null and b/Resources/Textures/Tiles/Planet/Chasms/chromite_chasm.rsi/chasm.png differ diff --git a/Resources/Textures/Tiles/Planet/Chasms/chromite_chasm.rsi/chasm0.png b/Resources/Textures/Tiles/Planet/Chasms/chromite_chasm.rsi/chasm0.png new file mode 100644 index 0000000000..18b3514673 Binary files /dev/null and b/Resources/Textures/Tiles/Planet/Chasms/chromite_chasm.rsi/chasm0.png differ diff --git a/Resources/Textures/Tiles/Planet/Chasms/chromite_chasm.rsi/chasm1.png b/Resources/Textures/Tiles/Planet/Chasms/chromite_chasm.rsi/chasm1.png new file mode 100644 index 0000000000..32976f4816 Binary files /dev/null and b/Resources/Textures/Tiles/Planet/Chasms/chromite_chasm.rsi/chasm1.png differ diff --git a/Resources/Textures/Tiles/Planet/Chasms/chromite_chasm.rsi/chasm2.png b/Resources/Textures/Tiles/Planet/Chasms/chromite_chasm.rsi/chasm2.png new file mode 100644 index 0000000000..18b3514673 Binary files /dev/null and b/Resources/Textures/Tiles/Planet/Chasms/chromite_chasm.rsi/chasm2.png differ diff --git a/Resources/Textures/Tiles/Planet/Chasms/chromite_chasm.rsi/chasm3.png b/Resources/Textures/Tiles/Planet/Chasms/chromite_chasm.rsi/chasm3.png new file mode 100644 index 0000000000..32976f4816 Binary files /dev/null and b/Resources/Textures/Tiles/Planet/Chasms/chromite_chasm.rsi/chasm3.png differ diff --git a/Resources/Textures/Tiles/Planet/Chasms/chromite_chasm.rsi/chasm4.png b/Resources/Textures/Tiles/Planet/Chasms/chromite_chasm.rsi/chasm4.png new file mode 100644 index 0000000000..cb77ce6147 Binary files /dev/null and b/Resources/Textures/Tiles/Planet/Chasms/chromite_chasm.rsi/chasm4.png differ diff --git a/Resources/Textures/Tiles/Planet/Chasms/chromite_chasm.rsi/chasm5.png b/Resources/Textures/Tiles/Planet/Chasms/chromite_chasm.rsi/chasm5.png new file mode 100644 index 0000000000..beeb8d3499 Binary files /dev/null and b/Resources/Textures/Tiles/Planet/Chasms/chromite_chasm.rsi/chasm5.png differ diff --git a/Resources/Textures/Tiles/Planet/Chasms/chromite_chasm.rsi/chasm6.png b/Resources/Textures/Tiles/Planet/Chasms/chromite_chasm.rsi/chasm6.png new file mode 100644 index 0000000000..cb77ce6147 Binary files /dev/null and b/Resources/Textures/Tiles/Planet/Chasms/chromite_chasm.rsi/chasm6.png differ diff --git a/Resources/Textures/Tiles/Planet/Chasms/chromite_chasm.rsi/chasm7.png b/Resources/Textures/Tiles/Planet/Chasms/chromite_chasm.rsi/chasm7.png new file mode 100644 index 0000000000..0858c19f05 Binary files /dev/null and b/Resources/Textures/Tiles/Planet/Chasms/chromite_chasm.rsi/chasm7.png differ diff --git a/Resources/Textures/Tiles/Planet/Chasms/chromite_chasm.rsi/full.png b/Resources/Textures/Tiles/Planet/Chasms/chromite_chasm.rsi/full.png new file mode 100644 index 0000000000..59b9454af0 Binary files /dev/null and b/Resources/Textures/Tiles/Planet/Chasms/chromite_chasm.rsi/full.png differ diff --git a/Resources/Textures/Tiles/Planet/Chasms/chromite_chasm.rsi/meta.json b/Resources/Textures/Tiles/Planet/Chasms/chromite_chasm.rsi/meta.json new file mode 100644 index 0000000000..e303031e1f --- /dev/null +++ b/Resources/Textures/Tiles/Planet/Chasms/chromite_chasm.rsi/meta.json @@ -0,0 +1,49 @@ +{ + "version": 1, + "license": "CC0-1.0", + "copyright": "Created by TheShuEd (github) for ss14", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "full" + }, + { + "name": "chasm0", + "directions": 4 + }, + { + "name": "chasm1", + "directions": 4 + }, + { + "name": "chasm2", + "directions": 4 + }, + { + "name": "chasm3", + "directions": 4 + }, + { + "name": "chasm4", + "directions": 4 + }, + { + "name": "chasm5", + "directions": 4 + }, + { + "name": "chasm6", + "directions": 4 + }, + { + "name": "chasm7", + "directions": 4 + }, + { + "name": "chasm" + } + ] +} \ No newline at end of file diff --git a/Resources/Textures/Tiles/Planet/Chasms/desert_chasm.rsi/chasm.png b/Resources/Textures/Tiles/Planet/Chasms/desert_chasm.rsi/chasm.png new file mode 100644 index 0000000000..e09eb93e42 Binary files /dev/null and b/Resources/Textures/Tiles/Planet/Chasms/desert_chasm.rsi/chasm.png differ diff --git a/Resources/Textures/Tiles/Planet/Chasms/desert_chasm.rsi/chasm0.png b/Resources/Textures/Tiles/Planet/Chasms/desert_chasm.rsi/chasm0.png new file mode 100644 index 0000000000..7139091f1e Binary files /dev/null and b/Resources/Textures/Tiles/Planet/Chasms/desert_chasm.rsi/chasm0.png differ diff --git a/Resources/Textures/Tiles/Planet/Chasms/desert_chasm.rsi/chasm1.png b/Resources/Textures/Tiles/Planet/Chasms/desert_chasm.rsi/chasm1.png new file mode 100644 index 0000000000..dce7efd9a6 Binary files /dev/null and b/Resources/Textures/Tiles/Planet/Chasms/desert_chasm.rsi/chasm1.png differ diff --git a/Resources/Textures/Tiles/Planet/Chasms/desert_chasm.rsi/chasm2.png b/Resources/Textures/Tiles/Planet/Chasms/desert_chasm.rsi/chasm2.png new file mode 100644 index 0000000000..7139091f1e Binary files /dev/null and b/Resources/Textures/Tiles/Planet/Chasms/desert_chasm.rsi/chasm2.png differ diff --git a/Resources/Textures/Tiles/Planet/Chasms/desert_chasm.rsi/chasm3.png b/Resources/Textures/Tiles/Planet/Chasms/desert_chasm.rsi/chasm3.png new file mode 100644 index 0000000000..dce7efd9a6 Binary files /dev/null and b/Resources/Textures/Tiles/Planet/Chasms/desert_chasm.rsi/chasm3.png differ diff --git a/Resources/Textures/Tiles/Planet/Chasms/desert_chasm.rsi/chasm4.png b/Resources/Textures/Tiles/Planet/Chasms/desert_chasm.rsi/chasm4.png new file mode 100644 index 0000000000..5cc155f825 Binary files /dev/null and b/Resources/Textures/Tiles/Planet/Chasms/desert_chasm.rsi/chasm4.png differ diff --git a/Resources/Textures/Tiles/Planet/Chasms/desert_chasm.rsi/chasm5.png b/Resources/Textures/Tiles/Planet/Chasms/desert_chasm.rsi/chasm5.png new file mode 100644 index 0000000000..05b5d7eccd Binary files /dev/null and b/Resources/Textures/Tiles/Planet/Chasms/desert_chasm.rsi/chasm5.png differ diff --git a/Resources/Textures/Tiles/Planet/Chasms/desert_chasm.rsi/chasm6.png b/Resources/Textures/Tiles/Planet/Chasms/desert_chasm.rsi/chasm6.png new file mode 100644 index 0000000000..5cc155f825 Binary files /dev/null and b/Resources/Textures/Tiles/Planet/Chasms/desert_chasm.rsi/chasm6.png differ diff --git a/Resources/Textures/Tiles/Planet/Chasms/desert_chasm.rsi/chasm7.png b/Resources/Textures/Tiles/Planet/Chasms/desert_chasm.rsi/chasm7.png new file mode 100644 index 0000000000..0858c19f05 Binary files /dev/null and b/Resources/Textures/Tiles/Planet/Chasms/desert_chasm.rsi/chasm7.png differ diff --git a/Resources/Textures/Tiles/Planet/Chasms/desert_chasm.rsi/full.png b/Resources/Textures/Tiles/Planet/Chasms/desert_chasm.rsi/full.png new file mode 100644 index 0000000000..03aa532353 Binary files /dev/null and b/Resources/Textures/Tiles/Planet/Chasms/desert_chasm.rsi/full.png differ diff --git a/Resources/Textures/Tiles/Planet/Chasms/desert_chasm.rsi/meta.json b/Resources/Textures/Tiles/Planet/Chasms/desert_chasm.rsi/meta.json new file mode 100644 index 0000000000..e303031e1f --- /dev/null +++ b/Resources/Textures/Tiles/Planet/Chasms/desert_chasm.rsi/meta.json @@ -0,0 +1,49 @@ +{ + "version": 1, + "license": "CC0-1.0", + "copyright": "Created by TheShuEd (github) for ss14", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "full" + }, + { + "name": "chasm0", + "directions": 4 + }, + { + "name": "chasm1", + "directions": 4 + }, + { + "name": "chasm2", + "directions": 4 + }, + { + "name": "chasm3", + "directions": 4 + }, + { + "name": "chasm4", + "directions": 4 + }, + { + "name": "chasm5", + "directions": 4 + }, + { + "name": "chasm6", + "directions": 4 + }, + { + "name": "chasm7", + "directions": 4 + }, + { + "name": "chasm" + } + ] +} \ No newline at end of file diff --git a/Resources/Textures/Tiles/Planet/Chasms/snow_chasm.rsi/chasm.png b/Resources/Textures/Tiles/Planet/Chasms/snow_chasm.rsi/chasm.png new file mode 100644 index 0000000000..1124e0518c Binary files /dev/null and b/Resources/Textures/Tiles/Planet/Chasms/snow_chasm.rsi/chasm.png differ diff --git a/Resources/Textures/Tiles/Planet/Chasms/snow_chasm.rsi/chasm0.png b/Resources/Textures/Tiles/Planet/Chasms/snow_chasm.rsi/chasm0.png new file mode 100644 index 0000000000..a813ce8e9a Binary files /dev/null and b/Resources/Textures/Tiles/Planet/Chasms/snow_chasm.rsi/chasm0.png differ diff --git a/Resources/Textures/Tiles/Planet/Chasms/snow_chasm.rsi/chasm1.png b/Resources/Textures/Tiles/Planet/Chasms/snow_chasm.rsi/chasm1.png new file mode 100644 index 0000000000..502b9e3d71 Binary files /dev/null and b/Resources/Textures/Tiles/Planet/Chasms/snow_chasm.rsi/chasm1.png differ diff --git a/Resources/Textures/Tiles/Planet/Chasms/snow_chasm.rsi/chasm2.png b/Resources/Textures/Tiles/Planet/Chasms/snow_chasm.rsi/chasm2.png new file mode 100644 index 0000000000..a813ce8e9a Binary files /dev/null and b/Resources/Textures/Tiles/Planet/Chasms/snow_chasm.rsi/chasm2.png differ diff --git a/Resources/Textures/Tiles/Planet/Chasms/snow_chasm.rsi/chasm3.png b/Resources/Textures/Tiles/Planet/Chasms/snow_chasm.rsi/chasm3.png new file mode 100644 index 0000000000..502b9e3d71 Binary files /dev/null and b/Resources/Textures/Tiles/Planet/Chasms/snow_chasm.rsi/chasm3.png differ diff --git a/Resources/Textures/Tiles/Planet/Chasms/snow_chasm.rsi/chasm4.png b/Resources/Textures/Tiles/Planet/Chasms/snow_chasm.rsi/chasm4.png new file mode 100644 index 0000000000..f0fd989115 Binary files /dev/null and b/Resources/Textures/Tiles/Planet/Chasms/snow_chasm.rsi/chasm4.png differ diff --git a/Resources/Textures/Tiles/Planet/Chasms/snow_chasm.rsi/chasm5.png b/Resources/Textures/Tiles/Planet/Chasms/snow_chasm.rsi/chasm5.png new file mode 100644 index 0000000000..567cde6ad4 Binary files /dev/null and b/Resources/Textures/Tiles/Planet/Chasms/snow_chasm.rsi/chasm5.png differ diff --git a/Resources/Textures/Tiles/Planet/Chasms/snow_chasm.rsi/chasm6.png b/Resources/Textures/Tiles/Planet/Chasms/snow_chasm.rsi/chasm6.png new file mode 100644 index 0000000000..f0fd989115 Binary files /dev/null and b/Resources/Textures/Tiles/Planet/Chasms/snow_chasm.rsi/chasm6.png differ diff --git a/Resources/Textures/Tiles/Planet/Chasms/snow_chasm.rsi/chasm7.png b/Resources/Textures/Tiles/Planet/Chasms/snow_chasm.rsi/chasm7.png new file mode 100644 index 0000000000..0858c19f05 Binary files /dev/null and b/Resources/Textures/Tiles/Planet/Chasms/snow_chasm.rsi/chasm7.png differ diff --git a/Resources/Textures/Tiles/Planet/Chasms/snow_chasm.rsi/full.png b/Resources/Textures/Tiles/Planet/Chasms/snow_chasm.rsi/full.png new file mode 100644 index 0000000000..525cdc2680 Binary files /dev/null and b/Resources/Textures/Tiles/Planet/Chasms/snow_chasm.rsi/full.png differ diff --git a/Resources/Textures/Tiles/Planet/Chasms/snow_chasm.rsi/meta.json b/Resources/Textures/Tiles/Planet/Chasms/snow_chasm.rsi/meta.json new file mode 100644 index 0000000000..e303031e1f --- /dev/null +++ b/Resources/Textures/Tiles/Planet/Chasms/snow_chasm.rsi/meta.json @@ -0,0 +1,49 @@ +{ + "version": 1, + "license": "CC0-1.0", + "copyright": "Created by TheShuEd (github) for ss14", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "full" + }, + { + "name": "chasm0", + "directions": 4 + }, + { + "name": "chasm1", + "directions": 4 + }, + { + "name": "chasm2", + "directions": 4 + }, + { + "name": "chasm3", + "directions": 4 + }, + { + "name": "chasm4", + "directions": 4 + }, + { + "name": "chasm5", + "directions": 4 + }, + { + "name": "chasm6", + "directions": 4 + }, + { + "name": "chasm7", + "directions": 4 + }, + { + "name": "chasm" + } + ] +} \ No newline at end of file diff --git a/Resources/Textures/Tiles/Planet/shadowbasalt.rsi/basalt1.png b/Resources/Textures/Tiles/Planet/shadowbasalt.rsi/basalt1.png new file mode 100644 index 0000000000..e8f873286c Binary files /dev/null and b/Resources/Textures/Tiles/Planet/shadowbasalt.rsi/basalt1.png differ diff --git a/Resources/Textures/Tiles/Planet/shadowbasalt.rsi/basalt2.png b/Resources/Textures/Tiles/Planet/shadowbasalt.rsi/basalt2.png new file mode 100644 index 0000000000..00a2711eb8 Binary files /dev/null and b/Resources/Textures/Tiles/Planet/shadowbasalt.rsi/basalt2.png differ diff --git a/Resources/Textures/Tiles/Planet/shadowbasalt.rsi/basalt3.png b/Resources/Textures/Tiles/Planet/shadowbasalt.rsi/basalt3.png new file mode 100644 index 0000000000..27219f4882 Binary files /dev/null and b/Resources/Textures/Tiles/Planet/shadowbasalt.rsi/basalt3.png differ diff --git a/Resources/Textures/Tiles/Planet/shadowbasalt.rsi/basalt4.png b/Resources/Textures/Tiles/Planet/shadowbasalt.rsi/basalt4.png new file mode 100644 index 0000000000..6081f54b02 Binary files /dev/null and b/Resources/Textures/Tiles/Planet/shadowbasalt.rsi/basalt4.png differ diff --git a/Resources/Textures/Tiles/Planet/shadowbasalt.rsi/basalt5.png b/Resources/Textures/Tiles/Planet/shadowbasalt.rsi/basalt5.png new file mode 100644 index 0000000000..76c13b2e61 Binary files /dev/null and b/Resources/Textures/Tiles/Planet/shadowbasalt.rsi/basalt5.png differ diff --git a/Resources/Textures/Tiles/Planet/shadowbasalt.rsi/meta.json b/Resources/Textures/Tiles/Planet/shadowbasalt.rsi/meta.json new file mode 100644 index 0000000000..0d71d4b561 --- /dev/null +++ b/Resources/Textures/Tiles/Planet/shadowbasalt.rsi/meta.json @@ -0,0 +1,66 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "taken from tgstation @ commit a0ca7b3f46132517f71f08bfda465667d133b5d7 and edited by TheShuEd", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "basalt1", + "delays": [ + [ + 2, + 2, + 2, + 2 + ] + ] + }, + { + "name": "basalt2", + "delays": [ + [ + 2, + 2, + 2, + 2 + ] + ] + }, + { + "name": "basalt3", + "delays": [ + [ + 2, + 2, + 2, + 2 + ] + ] + }, + { + "name": "basalt4", + "delays": [ + [ + 2, + 2, + 2, + 2 + ] + ] + }, + { + "name": "basalt5", + "delays": [ + [ + 2, + 2, + 2, + 2 + ] + ] + } + ] +} \ No newline at end of file diff --git a/Resources/Textures/Tiles/attributions.yml b/Resources/Textures/Tiles/attributions.yml index 41fbbbd243..e443abf031 100644 --- a/Resources/Textures/Tiles/attributions.yml +++ b/Resources/Textures/Tiles/attributions.yml @@ -110,3 +110,8 @@ license: "CC-BY-SA-3.0" copyright: "taken at https://github.com/ParadiseSS13/Paradise/blob/8b7f4c8b69c74c6de5a755272eb8d3520f3d87c7/icons/turf/floors.dmi" source: "https://github.com/ParadiseSS13/Paradise" + +- files: ["chromite.png"] + license: "CC-BY-NC-SA-3.0" + copyright: "taken at commit 0587dd16e28108bdf0b0a28e2caae4319845e861, and recolored by TheShuEd" + source: "https://github.com/Mojave-Sun/mojave-sun-13" \ No newline at end of file diff --git a/Resources/Textures/Tiles/chromite.png b/Resources/Textures/Tiles/chromite.png new file mode 100644 index 0000000000..631b9bf84e Binary files /dev/null and b/Resources/Textures/Tiles/chromite.png differ diff --git a/RobustToolbox b/RobustToolbox index 554e0777b1..7cad8d5ba3 160000 --- a/RobustToolbox +++ b/RobustToolbox @@ -1 +1 @@ -Subproject commit 554e0777b1ba6ba096d8f4407d5c35ecc7b0f22f +Subproject commit 7cad8d5ba3f252eb1dac862c7f92e792c60b98c1 diff --git a/Secrets b/Secrets index f217e467a9..54f39bf0e4 160000 --- a/Secrets +++ b/Secrets @@ -1 +1 @@ -Subproject commit f217e467a9f33ba01ac04cb21fa3f8e4327f7f83 +Subproject commit 54f39bf0e4a19a5f1630de355358e1708ebab217