diff --git a/Content.IntegrationTests/PoolManager.cs b/Content.IntegrationTests/PoolManager.cs index 9c25c15417..8e2d2d3453 100644 --- a/Content.IntegrationTests/PoolManager.cs +++ b/Content.IntegrationTests/PoolManager.cs @@ -53,7 +53,7 @@ public static class PoolManager (CCVars.NPCMaxUpdates.Name, "999999"), (CVars.ThreadParallelCount.Name, "1"), (CCVars.GameRoleTimers.Name, "false"), - (CCVars.CargoShuttles.Name, "false"), + (CCVars.GridFill.Name, "false"), (CCVars.ArrivalsShuttles.Name, "false"), (CCVars.EmergencyShuttleEnabled.Name, "false"), (CCVars.ProcgenPreload.Name, "false"), diff --git a/Content.IntegrationTests/Tests/CargoTest.cs b/Content.IntegrationTests/Tests/CargoTest.cs index 617e89b7d2..ed011aa530 100644 --- a/Content.IntegrationTests/Tests/CargoTest.cs +++ b/Content.IntegrationTests/Tests/CargoTest.cs @@ -63,8 +63,6 @@ public sealed class CargoTest var entManager = server.ResolveDependency(); var mapManager = server.ResolveDependency(); var protoManager = server.ResolveDependency(); - var cfg = server.ResolveDependency(); - await server.WaitPost(() => cfg.SetCVar(CCVars.DisableGridFill, true)); await server.WaitAssertion(() => { @@ -106,7 +104,6 @@ public sealed class CargoTest mapManager.DeleteMap(mapId); }); - await server.WaitPost(() => cfg.SetCVar(CCVars.DisableGridFill, false)); await pairTracker.CleanReturnAsync(); } diff --git a/Content.IntegrationTests/Tests/EntityTest.cs b/Content.IntegrationTests/Tests/EntityTest.cs index dd6ebe0653..50ab2eb400 100644 --- a/Content.IntegrationTests/Tests/EntityTest.cs +++ b/Content.IntegrationTests/Tests/EntityTest.cs @@ -27,15 +27,12 @@ namespace Content.IntegrationTests.Tests await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true, Destructive = true}); var server = pairTracker.Pair.Server; - IEntityManager entityMan = null; - var cfg = server.ResolveDependency(); - await server.WaitPost(() => cfg.SetCVar(CCVars.DisableGridFill, true)); + var entityMan = server.ResolveDependency(); + var mapManager = server.ResolveDependency(); + var prototypeMan = server.ResolveDependency(); await server.WaitPost(() => { - entityMan = IoCManager.Resolve(); - var mapManager = IoCManager.Resolve(); - var prototypeMan = IoCManager.Resolve(); var protoIds = prototypeMan .EnumeratePrototypes() .Where(p=>!p.Abstract) @@ -65,7 +62,6 @@ namespace Content.IntegrationTests.Tests Assert.That(entityMan.EntityCount, Is.Zero); }); - await server.WaitPost(() => cfg.SetCVar(CCVars.DisableGridFill, false)); await pairTracker.CleanReturnAsync(); } @@ -75,16 +71,13 @@ namespace Content.IntegrationTests.Tests await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true, Destructive = true}); var server = pairTracker.Pair.Server; var map = await PoolManager.CreateTestMap(pairTracker); - IEntityManager entityMan = null; - var cfg = server.ResolveDependency(); - await server.WaitPost(() => cfg.SetCVar(CCVars.DisableGridFill, true)); + var entityMan = server.ResolveDependency(); + var prototypeMan = server.ResolveDependency(); await server.WaitPost(() => { - entityMan = IoCManager.Resolve(); - var prototypeMan = IoCManager.Resolve(); var protoIds = prototypeMan .EnumeratePrototypes() .Where(p=>!p.Abstract) @@ -109,7 +102,6 @@ namespace Content.IntegrationTests.Tests Assert.That(entityMan.EntityCount, Is.Zero); }); - await server.WaitPost(() => cfg.SetCVar(CCVars.DisableGridFill, false)); await pairTracker.CleanReturnAsync(); } @@ -129,7 +121,6 @@ namespace Content.IntegrationTests.Tests var mapManager = server.ResolveDependency(); var sEntMan = server.ResolveDependency(); - await server.WaitPost(() => cfg.SetCVar(CCVars.DisableGridFill, true)); Assert.That(cfg.GetCVar(CVars.NetPVS), Is.False); var protoIds = prototypeMan @@ -178,7 +169,6 @@ namespace Content.IntegrationTests.Tests Assert.That(sEntMan.EntityCount, Is.Zero); }); - await server.WaitPost(() => cfg.SetCVar(CCVars.DisableGridFill, false)); await pairTracker.CleanReturnAsync(); } diff --git a/Content.IntegrationTests/Tests/GameRules/StartEndGameRulesTest.cs b/Content.IntegrationTests/Tests/GameRules/StartEndGameRulesTest.cs index 6b60022438..4309311b8c 100644 --- a/Content.IntegrationTests/Tests/GameRules/StartEndGameRulesTest.cs +++ b/Content.IntegrationTests/Tests/GameRules/StartEndGameRulesTest.cs @@ -27,7 +27,7 @@ public sealed class StartEndGameRulesTest await server.WaitIdleAsync(); var gameTicker = server.ResolveDependency().GetEntitySystem(); var cfg = server.ResolveDependency(); - Assert.That(cfg.GetCVar(CCVars.DisableGridFill), Is.False); + Assert.That(cfg.GetCVar(CCVars.GridFill), Is.False); await server.WaitAssertion(() => { diff --git a/Content.IntegrationTests/Tests/PostMapInitTest.cs b/Content.IntegrationTests/Tests/PostMapInitTest.cs index 23b85b9959..a415a04e69 100644 --- a/Content.IntegrationTests/Tests/PostMapInitTest.cs +++ b/Content.IntegrationTests/Tests/PostMapInitTest.cs @@ -58,7 +58,7 @@ namespace Content.IntegrationTests.Tests var mapLoader = server.ResolveDependency().GetEntitySystem(); var mapManager = server.ResolveDependency(); var cfg = server.ResolveDependency(); - Assert.That(cfg.GetCVar(CCVars.DisableGridFill), Is.False); + Assert.That(cfg.GetCVar(CCVars.GridFill), Is.False); await server.WaitPost(() => { @@ -188,7 +188,7 @@ namespace Content.IntegrationTests.Tests var shuttleSystem = entManager.EntitySysManager.GetEntitySystem(); var xformQuery = entManager.GetEntityQuery(); var cfg = server.ResolveDependency(); - Assert.That(cfg.GetCVar(CCVars.DisableGridFill), Is.False); + Assert.That(cfg.GetCVar(CCVars.GridFill), Is.False); await server.WaitPost(() => { @@ -352,7 +352,7 @@ namespace Content.IntegrationTests.Tests var mapLoader = server.ResolveDependency().GetEntitySystem(); var mapManager = server.ResolveDependency(); var cfg = server.ResolveDependency(); - Assert.That(cfg.GetCVar(CCVars.DisableGridFill), Is.False); + Assert.That(cfg.GetCVar(CCVars.GridFill), Is.False); await server.WaitPost(() => { diff --git a/Content.IntegrationTests/Tests/SaveLoadMapTest.cs b/Content.IntegrationTests/Tests/SaveLoadMapTest.cs index 5fda54fb51..07d335eb67 100644 --- a/Content.IntegrationTests/Tests/SaveLoadMapTest.cs +++ b/Content.IntegrationTests/Tests/SaveLoadMapTest.cs @@ -29,7 +29,7 @@ namespace Content.IntegrationTests.Tests var xformSystem = sEntities.EntitySysManager.GetEntitySystem(); var resManager = server.ResolveDependency(); var cfg = server.ResolveDependency(); - Assert.That(cfg.GetCVar(CCVars.DisableGridFill), Is.False); + Assert.That(cfg.GetCVar(CCVars.GridFill), Is.False); await server.WaitAssertion(() => { diff --git a/Content.IntegrationTests/Tests/SaveLoadSaveTest.cs b/Content.IntegrationTests/Tests/SaveLoadSaveTest.cs index 206b3072fb..eeb35f6a68 100644 --- a/Content.IntegrationTests/Tests/SaveLoadSaveTest.cs +++ b/Content.IntegrationTests/Tests/SaveLoadSaveTest.cs @@ -28,7 +28,7 @@ namespace Content.IntegrationTests.Tests var mapLoader = server.ResolveDependency().GetEntitySystem(); var mapManager = server.ResolveDependency(); var cfg = server.ResolveDependency(); - Assert.That(cfg.GetCVar(CCVars.DisableGridFill), Is.False); + Assert.That(cfg.GetCVar(CCVars.GridFill), Is.False); await server.WaitPost(() => { @@ -97,7 +97,7 @@ namespace Content.IntegrationTests.Tests MapId mapId = default; var cfg = server.ResolveDependency(); - Assert.That(cfg.GetCVar(CCVars.DisableGridFill), Is.False); + Assert.That(cfg.GetCVar(CCVars.GridFill), Is.False); // Load bagel.yml as uninitialized map, and save it to ensure it's up to date. server.Post(() => @@ -178,7 +178,7 @@ namespace Content.IntegrationTests.Tests var mapManager = server.ResolveDependency(); var userData = server.ResolveDependency().UserData; var cfg = server.ResolveDependency(); - Assert.That(cfg.GetCVar(CCVars.DisableGridFill), Is.False); + Assert.That(cfg.GetCVar(CCVars.GridFill), Is.False); MapId mapId = default; const string fileA = "/load tick load a.yml"; diff --git a/Content.Server/Cargo/Components/CargoPilotConsoleComponent.cs b/Content.Server/Cargo/Components/CargoPilotConsoleComponent.cs deleted file mode 100644 index 6b7ccfcf16..0000000000 --- a/Content.Server/Cargo/Components/CargoPilotConsoleComponent.cs +++ /dev/null @@ -1,15 +0,0 @@ -using Content.Server.Shuttles.Components; - -namespace Content.Server.Cargo.Components; - -/// -/// Lets you remotely control the cargo shuttle. -/// -[RegisterComponent] -public sealed class CargoPilotConsoleComponent : Component -{ - /// - /// that we're proxied into. - /// - public EntityUid? Entity; -} diff --git a/Content.Server/Cargo/Components/StationCargoOrderDatabaseComponent.cs b/Content.Server/Cargo/Components/StationCargoOrderDatabaseComponent.cs index 318274893c..5ec104ac5c 100644 --- a/Content.Server/Cargo/Components/StationCargoOrderDatabaseComponent.cs +++ b/Content.Server/Cargo/Components/StationCargoOrderDatabaseComponent.cs @@ -24,9 +24,7 @@ public sealed class StationCargoOrderDatabaseComponent : Component /// public int NumOrdersCreated; - [DataField("cargoShuttleProto", customTypeSerializer:typeof(PrototypeIdSerializer))] - public string? CargoShuttleProto = "CargoShuttle"; - + // TODO: Can probably dump this /// /// The cargo shuttle assigned to this station. /// diff --git a/Content.Server/Cargo/Systems/CargoSystem.Shuttle.cs b/Content.Server/Cargo/Systems/CargoSystem.Shuttle.cs index f104a84ed8..9226627d4a 100644 --- a/Content.Server/Cargo/Systems/CargoSystem.Shuttle.cs +++ b/Content.Server/Cargo/Systems/CargoSystem.Shuttle.cs @@ -1,5 +1,6 @@ using System.Linq; using Content.Server.Cargo.Components; +using Content.Server.Shuttle.Components; using Content.Server.Shuttles.Components; using Content.Server.Shuttles.Events; using Content.Server.UserInterface; @@ -30,35 +31,21 @@ namespace Content.Server.Cargo.Systems; public sealed partial class CargoSystem { /* - * Handles cargo shuttle mechanics, including cargo shuttle consoles. + * Handles cargo shuttle mechanics. */ [Dependency] private readonly IComponentFactory _factory = default!; - [Dependency] private readonly IConfigurationManager _configManager = default!; [Dependency] private readonly IMapManager _mapManager = default!; [Dependency] private readonly IRobustRandom _random = default!; [Dependency] private readonly IPrototypeManager _prototypeManager = default!; [Dependency] private readonly EntityLookupSystem _lookup = default!; - [Dependency] private readonly MapLoaderSystem _map = default!; [Dependency] private readonly PricingSystem _pricing = default!; - [Dependency] private readonly SharedTransformSystem _transform = default!; [Dependency] private readonly ShuttleConsoleSystem _console = default!; [Dependency] private readonly StackSystem _stack = default!; public MapId? CargoMap { get; private set; } - private int _index; - - /// - /// Whether cargo shuttles are enabled at all. Mainly used to disable cargo shuttle loading for performance reasons locally. - /// - private bool _enabled; - private void InitializeShuttle() { - _enabled = _configManager.GetCVar(CCVars.CargoShuttles); - // Don't want to immediately call this as shuttles will get setup in the natural course of things. - _configManager.OnValueChanged(CCVars.CargoShuttles, SetCargoShuttleEnabled); - SubscribeLocalEvent(OnCargoFTLStarted); SubscribeLocalEvent(OnCargoFTLCompleted); SubscribeLocalEvent(OnCargoFTLTag); @@ -69,12 +56,6 @@ public sealed partial class CargoSystem SubscribeLocalEvent(OnPalletAppraise); SubscribeLocalEvent(OnPalletUIOpen); - SubscribeLocalEvent(OnCargoGetConsole); - SubscribeLocalEvent(OnCargoPilotConsoleOpen); - SubscribeLocalEvent(OnCargoPilotConsoleClose); - - SubscribeLocalEvent(OnCargoOrderStartup); - SubscribeLocalEvent(OnRoundRestart); } @@ -88,90 +69,20 @@ public sealed partial class CargoSystem args.Tag = "DockCargo"; } - private void ShutdownShuttle() - { - _configManager.UnsubValueChanged(CCVars.CargoShuttles, SetCargoShuttleEnabled); - } - - private void SetCargoShuttleEnabled(bool value) - { - if (_enabled == value) - return; - - _enabled = value; - - if (value) - { - Setup(); - - var query = AllEntityQuery(); - - while (query.MoveNext(out var stationUid, out var station)) - { - AddShuttle(stationUid, station); - } - } - else - { - CleanupShuttle(); - } - } - - #region Cargo Pilot Console - - private void OnCargoPilotConsoleOpen(EntityUid uid, CargoPilotConsoleComponent component, AfterActivatableUIOpenEvent args) - { - component.Entity = GetShuttleConsole(uid); - } - - private void OnCargoPilotConsoleClose(EntityUid uid, CargoPilotConsoleComponent component, BoundUIClosedEvent args) - { - component.Entity = null; - } - - private void OnCargoGetConsole(EntityUid uid, CargoPilotConsoleComponent component, ref ConsoleShuttleEvent args) - { - args.Console = GetShuttleConsole(uid); - } - - private EntityUid? GetShuttleConsole(EntityUid uid) - { - var stationUid = _station.GetOwningStation(uid); - - if (!TryComp(stationUid, out var orderDatabase) || - !TryComp(orderDatabase.Shuttle, out var shuttle)) - { - return null; - } - - return GetShuttleConsole(orderDatabase.Shuttle.Value, shuttle); - } - - #endregion - #region Console - private void UpdateCargoShuttleConsoles(CargoShuttleComponent component) + private void UpdateCargoShuttleConsoles(EntityUid shuttleUid, CargoShuttleComponent component) { // Update pilot consoles that are already open. - var pilotConsoleQuery = AllEntityQuery(); - - while (pilotConsoleQuery.MoveNext(out var uid, out var console)) - { - var stationUid = _station.GetOwningStation(uid); - if (stationUid == null || stationUid != component.Station) - continue; - - console.Entity = GetShuttleConsole(stationUid.Value); - } + _console.RefreshDroneConsoles(); // Update order consoles. var shuttleConsoleQuery = AllEntityQuery(); - while (shuttleConsoleQuery.MoveNext(out var uid, out var console)) + while (shuttleConsoleQuery.MoveNext(out var uid, out _)) { var stationUid = _station.GetOwningStation(uid); - if (stationUid != component.Station) + if (stationUid != shuttleUid) continue; UpdateShuttleState(uid, stationUid); @@ -245,21 +156,6 @@ public sealed partial class CargoSystem #region Shuttle - public EntityUid? GetShuttleConsole(EntityUid uid, CargoShuttleComponent component) - { - var query = AllEntityQuery(); - - while (query.MoveNext(out var cUid, out var comp, out var xform)) - { - if (xform.ParentUid != uid) - continue; - - return cUid; - } - - return null; - } - /// /// Returns the orders that can fit on the cargo shuttle. /// @@ -331,50 +227,6 @@ public sealed partial class CargoSystem #region Station - private void OnCargoOrderStartup(EntityUid uid, StationCargoOrderDatabaseComponent component, ComponentStartup args) - { - if (!_enabled) - return; - - // Stations get created first but if any are added at runtime then do this. - AddShuttle(uid, component); - } - - private void AddShuttle(EntityUid stationUid, StationCargoOrderDatabaseComponent component) - { - Setup(); - - if (CargoMap == null || - component.Shuttle != null || - component.CargoShuttleProto == null) - { - return; - } - - var prototype = _protoMan.Index(component.CargoShuttleProto); - var possibleNames = _protoMan.Index(prototype.NameDataset).Values; - var name = _random.Pick(possibleNames); - - if (!_map.TryLoad(CargoMap.Value, prototype.Path.ToString(), out var gridList)) - { - _sawmill.Error($"Could not load the cargo shuttle!"); - return; - } - var shuttleUid = gridList[0]; - var xform = Transform(shuttleUid); - MetaData(shuttleUid).EntityName = name; - - // TODO: Something better like a bounds check. - _transform.SetLocalPosition(xform, xform.LocalPosition + 100 * _index); - var comp = EnsureComp(shuttleUid); - comp.Station = stationUid; - - component.Shuttle = shuttleUid; - UpdateCargoShuttleConsoles(comp); - _index++; - _sawmill.Info($"Added cargo shuttle to {ToPrettyString(shuttleUid)}"); - } - private void SellPallets(EntityUid gridUid, out double amount) { GetPalletGoods(gridUid, out var toSell, out amount); @@ -480,7 +332,7 @@ public sealed partial class CargoSystem private void OnCargoFTLStarted(EntityUid uid, CargoShuttleComponent component, ref FTLStartedEvent args) { - var stationUid = component.Station; + var stationUid = _station.GetOwningStation(uid); // Called if (CargoMap == null || @@ -492,7 +344,7 @@ public sealed partial class CargoSystem AddCargoContents(uid, component, orderDatabase); UpdateOrders(orderDatabase); - UpdateCargoShuttleConsoles(component); + UpdateCargoShuttleConsoles(uid, component); } private void OnCargoFTLCompleted(EntityUid uid, CargoShuttleComponent component, ref FTLCompletedEvent args) @@ -502,7 +354,7 @@ public sealed partial class CargoSystem if (xform.MapID != CargoMap) return; - var stationUid = component.Station; + var stationUid = _station.GetOwningStation(uid); if (TryComp(stationUid, out var bank)) { @@ -515,10 +367,11 @@ public sealed partial class CargoSystem private void OnRoundRestart(RoundRestartCleanupEvent ev) { - CleanupShuttle(); + CleanupCargoShuttle(); + SetupCargoShuttle(); } - private void CleanupShuttle() + private void CleanupCargoShuttle() { if (CargoMap == null || !_mapManager.MapExists(CargoMap.Value)) { @@ -535,7 +388,9 @@ public sealed partial class CargoSystem while (query.MoveNext(out var uid, out var comp)) { - if (TryComp(comp.Station, out var station)) + var stationUid = _station.GetOwningStation(uid); + + if (TryComp(uid, out var station)) { station.Shuttle = null; } @@ -543,9 +398,9 @@ public sealed partial class CargoSystem } } - private void Setup() + private void SetupCargoShuttle() { - if (!_enabled || CargoMap != null && _mapManager.MapExists(CargoMap.Value)) + if (CargoMap != null && _mapManager.MapExists(CargoMap.Value)) { return; } @@ -564,13 +419,6 @@ public sealed partial class CargoSystem MetaData(mapUid).EntityName = $"Trading post {_random.Next(1000):000}"; - var query = AllEntityQuery(); - - while (query.MoveNext(out var uid, out var comp)) - { - AddShuttle(uid, comp); - } - _console.RefreshShuttleConsoles(); } } diff --git a/Content.Server/Cargo/Systems/CargoSystem.cs b/Content.Server/Cargo/Systems/CargoSystem.cs index 10ada53ccd..244e1ac1b5 100644 --- a/Content.Server/Cargo/Systems/CargoSystem.cs +++ b/Content.Server/Cargo/Systems/CargoSystem.cs @@ -27,8 +27,7 @@ public sealed partial class CargoSystem : SharedCargoSystem public override void Shutdown() { base.Shutdown(); - ShutdownShuttle(); - CleanupShuttle(); + CleanupCargoShuttle(); } public override void Update(float frameTime) @@ -39,19 +38,21 @@ public sealed partial class CargoSystem : SharedCargoSystem } [PublicAPI] - public void UpdateBankAccount(StationBankAccountComponent component, int balanceAdded) + public void UpdateBankAccount(EntityUid uid, StationBankAccountComponent component, int balanceAdded) { component.Balance += balanceAdded; - // TODO: Code bad - foreach (var comp in EntityQuery()) - { - if (!_uiSystem.IsUiOpen(comp.Owner, CargoConsoleUiKey.Orders)) continue; + var query = EntityQueryEnumerator(); - var station = _station.GetOwningStation(comp.Owner); - if (station != component.Owner) + while (query.MoveNext(out var oUid, out var oComp)) + { + if (!_uiSystem.IsUiOpen(oUid, CargoConsoleUiKey.Orders)) continue; - UpdateOrderState(comp, station); + var station = _station.GetOwningStation(oUid); + if (station != uid) + continue; + + UpdateOrderState(oComp, station); } } } diff --git a/Content.Server/Physics/Controllers/MoverController.cs b/Content.Server/Physics/Controllers/MoverController.cs index a0b8932c8e..5157c4bc9b 100644 --- a/Content.Server/Physics/Controllers/MoverController.cs +++ b/Content.Server/Physics/Controllers/MoverController.cs @@ -1,4 +1,5 @@ using Content.Server.Cargo.Components; +using Content.Server.Shuttle.Components; using Content.Server.Shuttles.Components; using Content.Server.Shuttles.Systems; using Content.Shared.Movement.Components; @@ -254,7 +255,7 @@ namespace Content.Server.Physics.Controllers var consoleEnt = pilot.Console?.Owner; // TODO: This is terrible. Just make a new mover and also make it remote piloting + device networks - if (TryComp(consoleEnt, out var cargoConsole)) + if (TryComp(consoleEnt, out var cargoConsole)) { consoleEnt = cargoConsole.Entity; } diff --git a/Content.Server/Salvage/Expeditions/SalvageShuttleComponent.cs b/Content.Server/Salvage/Expeditions/SalvageShuttleComponent.cs new file mode 100644 index 0000000000..067d7d2482 --- /dev/null +++ b/Content.Server/Salvage/Expeditions/SalvageShuttleComponent.cs @@ -0,0 +1,10 @@ +namespace Content.Server.Salvage.Expeditions; + +/// +/// Added to salvage shuttle. Used for drone control. +/// +[RegisterComponent] +public sealed class SalvageShuttleComponent : Component +{ + +} diff --git a/Content.Server/Shuttle/Components/DroneConsoleComponent.cs b/Content.Server/Shuttle/Components/DroneConsoleComponent.cs new file mode 100644 index 0000000000..933dc358d0 --- /dev/null +++ b/Content.Server/Shuttle/Components/DroneConsoleComponent.cs @@ -0,0 +1,21 @@ +using Content.Server.Shuttles.Components; +using Robust.Shared.Prototypes; + +namespace Content.Server.Shuttle.Components; + +// Primo shitcode +/// +/// Lets you remotely control a shuttle. +/// +[RegisterComponent] +public sealed class DroneConsoleComponent : Component +{ + [DataField("components", required: true)] + public ComponentRegistry Components = default!; + + /// + /// that we're proxied into. + /// + [DataField("entity")] + public EntityUid? Entity; +} diff --git a/Content.Server/Shuttles/Components/GridSpawnComponent.cs b/Content.Server/Shuttles/Components/GridSpawnComponent.cs new file mode 100644 index 0000000000..0311f2c1c7 --- /dev/null +++ b/Content.Server/Shuttles/Components/GridSpawnComponent.cs @@ -0,0 +1,13 @@ +using Content.Server.Shuttles.Systems; +using Robust.Shared.Utility; + +namespace Content.Server.Shuttles.Components; + +/// +/// Similar to except spawns the grid near to the station. +/// +[RegisterComponent, Access(typeof(ShuttleSystem))] +public sealed class GridSpawnComponent : Component +{ + [DataField("paths", required: true)] public List Paths = new(); +} diff --git a/Content.Server/Shuttles/Events/ConsoleShuttleEvent.cs b/Content.Server/Shuttles/Events/ConsoleShuttleEvent.cs index bd96387b28..dfc49152cc 100644 --- a/Content.Server/Shuttles/Events/ConsoleShuttleEvent.cs +++ b/Content.Server/Shuttles/Events/ConsoleShuttleEvent.cs @@ -8,5 +8,8 @@ namespace Content.Server.Shuttles.Events; [ByRefEvent] public struct ConsoleShuttleEvent { + /// + /// Console that we proxy into. + /// public EntityUid? Console; } diff --git a/Content.Server/Shuttles/Systems/ShuttleConsoleSystem.Drone.cs b/Content.Server/Shuttles/Systems/ShuttleConsoleSystem.Drone.cs new file mode 100644 index 0000000000..b9c29cb02b --- /dev/null +++ b/Content.Server/Shuttles/Systems/ShuttleConsoleSystem.Drone.cs @@ -0,0 +1,75 @@ +using Content.Server.Shuttle.Components; +using Content.Server.Shuttles.Components; +using Content.Server.Shuttles.Events; +using Content.Server.Station.Components; +using Content.Server.UserInterface; + +namespace Content.Server.Shuttles.Systems; + +public sealed partial class ShuttleConsoleSystem +{ + /// + /// Refreshes all drone console entities. + /// + public void RefreshDroneConsoles() + { + var query = AllEntityQuery(); + + while (query.MoveNext(out var uid, out var comp)) + { + comp.Entity = GetShuttleConsole(uid, comp); + } + } + + private void OnDronePilotConsoleOpen(EntityUid uid, DroneConsoleComponent component, AfterActivatableUIOpenEvent args) + { + component.Entity = GetShuttleConsole(uid); + } + + private void OnDronePilotConsoleClose(EntityUid uid, DroneConsoleComponent component, BoundUIClosedEvent args) + { + component.Entity = null; + } + + private void OnCargoGetConsole(EntityUid uid, DroneConsoleComponent component, ref ConsoleShuttleEvent args) + { + args.Console = GetShuttleConsole(uid, component); + } + + /// + /// Gets the relevant shuttle console to proxy from the drone console. + /// + private EntityUid? GetShuttleConsole(EntityUid uid, DroneConsoleComponent? component = null) + { + if (!Resolve(uid, ref component)) + return null; + + var stationUid = _station.GetOwningStation(uid); + + if (stationUid == null) + return null; + + // I know this sucks but needs device linking or something idunno + var query = AllEntityQuery(); + + while (query.MoveNext(out var cUid, out _, out var xform)) + { + if (xform.GridUid == null || + !TryComp(xform.GridUid, out var member) || + member.Station != stationUid) + { + continue; + } + + foreach (var compType in component.Components.Values) + { + if (!HasComp(xform.GridUid, compType.Component.GetType())) + continue; + + return cUid; + } + } + + return null; + } +} diff --git a/Content.Server/Shuttles/Systems/ShuttleConsoleSystem.cs b/Content.Server/Shuttles/Systems/ShuttleConsoleSystem.cs index 2b96f9d13f..c3c49018de 100644 --- a/Content.Server/Shuttles/Systems/ShuttleConsoleSystem.cs +++ b/Content.Server/Shuttles/Systems/ShuttleConsoleSystem.cs @@ -1,7 +1,9 @@ using Content.Server.Power.Components; using Content.Server.Power.EntitySystems; +using Content.Server.Shuttle.Components; using Content.Server.Shuttles.Components; using Content.Server.Shuttles.Events; +using Content.Server.Station.Systems; using Content.Server.UserInterface; using Content.Shared.ActionBlocker; using Content.Shared.Alert; @@ -21,13 +23,14 @@ using Robust.Shared.Utility; namespace Content.Server.Shuttles.Systems; -public sealed class ShuttleConsoleSystem : SharedShuttleConsoleSystem +public sealed partial class ShuttleConsoleSystem : SharedShuttleConsoleSystem { [Dependency] private readonly IGameTiming _timing = default!; [Dependency] private readonly ActionBlockerSystem _blocker = default!; [Dependency] private readonly AlertsSystem _alertsSystem = default!; [Dependency] private readonly SharedPopupSystem _popup = default!; [Dependency] private readonly ShuttleSystem _shuttle = default!; + [Dependency] private readonly StationSystem _station = default!; [Dependency] private readonly TagSystem _tags = default!; [Dependency] private readonly UserInterfaceSystem _ui = default!; @@ -42,6 +45,10 @@ public sealed class ShuttleConsoleSystem : SharedShuttleConsoleSystem SubscribeLocalEvent(OnDestinationMessage); SubscribeLocalEvent(OnConsoleUIClose); + SubscribeLocalEvent(OnCargoGetConsole); + SubscribeLocalEvent(OnDronePilotConsoleOpen); + SubscribeLocalEvent(OnDronePilotConsoleClose); + SubscribeLocalEvent(OnDock); SubscribeLocalEvent(OnUndock); diff --git a/Content.Server/Shuttles/Systems/ShuttleSystem.GridFill.cs b/Content.Server/Shuttles/Systems/ShuttleSystem.GridFill.cs index 7b4c33fef6..4d53647c9e 100644 --- a/Content.Server/Shuttles/Systems/ShuttleSystem.GridFill.cs +++ b/Content.Server/Shuttles/Systems/ShuttleSystem.GridFill.cs @@ -1,5 +1,7 @@ using Content.Server.Shuttles.Components; using Content.Server.Station.Components; +using Content.Server.Station.Events; +using Content.Shared.Cargo.Components; using Content.Shared.CCVar; namespace Content.Server.Shuttles.Systems; @@ -8,11 +10,88 @@ public sealed partial class ShuttleSystem { private void InitializeGridFills() { + SubscribeLocalEvent(OnGridSpawnPostInit); SubscribeLocalEvent(OnGridFillMapInit); + + _cfg.OnValueChanged(CCVars.GridFill, OnGridFillChange); + } + + private void ShutdownGridFills() + { + _cfg.UnsubValueChanged(CCVars.GridFill, OnGridFillChange); + } + + private void OnGridFillChange(bool obj) + { + // If you're doing this on live then god help you, + if (obj) + { + var query = AllEntityQuery(); + + while (query.MoveNext(out var uid, out var comp)) + { + GridSpawns(uid, comp); + } + } + } + + private void OnGridSpawnPostInit(EntityUid uid, GridSpawnComponent component, ref StationPostInitEvent args) + { + GridSpawns(uid, component); + } + + private void GridSpawns(EntityUid uid, GridSpawnComponent component) + { + if (!_cfg.GetCVar(CCVars.GridFill)) + return; + + if (!TryComp(uid, out var data)) + { + return; + } + + var targetGrid = _station.GetLargestGrid(data); + + if (targetGrid == null) + return; + + // Spawn on a dummy map and try to FTL if possible, otherwise dump it. + var mapId = _mapManager.CreateMap(); + var valid = true; + + foreach (var path in component.Paths) + { + if (_loader.TryLoad(mapId, path.ToString(), out var ent) && ent.Count == 1) + { + if (TryComp(ent[0], out var shuttle)) + { + TryFTLProximity(ent[0], shuttle, targetGrid.Value); + _station.AddGridToStation(uid, ent[0]); + } + else + { + valid = false; + } + } + else + { + valid = false; + } + + if (!valid) + { + _sawmill.Error($"Error loading gridspawn for {ToPrettyString(uid)} / {path}"); + } + } + + _mapManager.DeleteMap(mapId); } private void OnGridFillMapInit(EntityUid uid, GridFillComponent component, MapInitEvent args) { + if (!_cfg.GetCVar(CCVars.GridFill)) + return; + if (!TryComp(uid, out var dock) || !TryComp(uid, out var xform) || xform.GridUid == null) @@ -20,9 +99,6 @@ public sealed partial class ShuttleSystem return; } - if (_cfg.GetCVar(CCVars.DisableGridFill)) - return; - // Spawn on a dummy map and try to dock if possible, otherwise dump it. var mapId = _mapManager.CreateMap(); var valid = false; diff --git a/Content.Server/Shuttles/Systems/ShuttleSystem.cs b/Content.Server/Shuttles/Systems/ShuttleSystem.cs index 30f3a829c5..2ca053f8cd 100644 --- a/Content.Server/Shuttles/Systems/ShuttleSystem.cs +++ b/Content.Server/Shuttles/Systems/ShuttleSystem.cs @@ -67,6 +67,13 @@ public sealed partial class ShuttleSystem : SharedShuttleSystem SubscribeLocalEvent(OnGridFixtureChange); } + public override void Shutdown() + { + base.Shutdown(); + ShutdownGridFills(); + } + + public override void Update(float frameTime) { base.Update(frameTime); diff --git a/Content.Server/Station/Events/StationPostInitEvent.cs b/Content.Server/Station/Events/StationPostInitEvent.cs new file mode 100644 index 0000000000..a4e55fafb2 --- /dev/null +++ b/Content.Server/Station/Events/StationPostInitEvent.cs @@ -0,0 +1,7 @@ +namespace Content.Server.Station.Events; + +/// +/// Raised directed on a station after it has been initialized. +/// +[ByRefEvent] +public readonly record struct StationPostInitEvent; diff --git a/Content.Server/Station/Systems/StationSystem.cs b/Content.Server/Station/Systems/StationSystem.cs index c951fb1ccd..ff2446eeb6 100644 --- a/Content.Server/Station/Systems/StationSystem.cs +++ b/Content.Server/Station/Systems/StationSystem.cs @@ -2,6 +2,7 @@ using System.Linq; using Content.Server.Chat.Systems; using Content.Server.GameTicking; using Content.Server.Station.Components; +using Content.Server.Station.Events; using Content.Shared.CCVar; using Content.Shared.Station; using JetBrains.Annotations; @@ -304,6 +305,9 @@ public sealed class StationSystem : EntitySystem AddGridToStation(station, grid, null, data, name); } + var ev = new StationPostInitEvent(); + RaiseLocalEvent(station, ref ev); + return station; } diff --git a/Content.Shared/CCVar/CCVars.cs b/Content.Shared/CCVar/CCVars.cs index a3c64b415a..eee95cd2fe 100644 --- a/Content.Shared/CCVar/CCVars.cs +++ b/Content.Shared/CCVar/CCVars.cs @@ -1096,17 +1096,11 @@ namespace Content.Shared.CCVar public static readonly CVarDef ArrivalsReturns = CVarDef.Create("shuttle.arrivals_returns", false, CVar.SERVERONLY); - /// - /// Whether cargo shuttles are enabled. - /// - public static readonly CVarDef CargoShuttles = - CVarDef.Create("shuttle.cargo", true, CVar.SERVERONLY); - /// /// Whether to automatically spawn escape shuttles. /// - public static readonly CVarDef DisableGridFill = - CVarDef.Create("shuttle.disable_grid_fill", false, CVar.SERVERONLY); + public static readonly CVarDef GridFill = + CVarDef.Create("shuttle.grid_fill", true, CVar.SERVERONLY); /* * Emergency diff --git a/Content.Shared/Cargo/Components/CargoShuttleComponent.cs b/Content.Shared/Cargo/Components/CargoShuttleComponent.cs index b6d503a756..6e1ed3c9f1 100644 --- a/Content.Shared/Cargo/Components/CargoShuttleComponent.cs +++ b/Content.Shared/Cargo/Components/CargoShuttleComponent.cs @@ -1,4 +1,4 @@ -using Robust.Shared.Map; +using Robust.Shared.GameStates; using Robust.Shared.Prototypes; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; @@ -7,15 +7,9 @@ namespace Content.Shared.Cargo.Components; /// /// Present on cargo shuttles to provide metadata such as preventing spam calling. /// -[RegisterComponent, Access(typeof(SharedCargoSystem))] +[RegisterComponent, NetworkedComponent, Access(typeof(SharedCargoSystem))] public sealed class CargoShuttleComponent : Component { - /// - /// The assigned station for this cargo shuttle. - /// - [DataField("station")] - public EntityUid? Station; - /// /// The paper-type prototype to spawn with the order information. /// diff --git a/Content.Shared/Cargo/Prototypes/CargoShuttlePrototype.cs b/Content.Shared/Cargo/Prototypes/CargoShuttlePrototype.cs deleted file mode 100644 index b740c3a0f9..0000000000 --- a/Content.Shared/Cargo/Prototypes/CargoShuttlePrototype.cs +++ /dev/null @@ -1,20 +0,0 @@ -using Content.Shared.Dataset; -using Robust.Shared.Prototypes; -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; -using Robust.Shared.Utility; - -namespace Content.Shared.Cargo.Prototypes; - -[Prototype("cargoShuttle")] -public sealed class CargoShuttlePrototype : IPrototype -{ - [ViewVariables] - [IdDataField] - public string ID { get; } = default!; - - [DataField("path")] - public ResPath Path = default!; - - [DataField("nameDataset", customTypeSerializer:typeof(PrototypeIdSerializer))] - public string NameDataset = "CargoShuttleNames"; -} diff --git a/Resources/ConfigPresets/Build/development.toml b/Resources/ConfigPresets/Build/development.toml index 9bf50765e3..1d8f02f0ac 100644 --- a/Resources/ConfigPresets/Build/development.toml +++ b/Resources/ConfigPresets/Build/development.toml @@ -17,8 +17,7 @@ expedition_cooldown = 30.0 expedition_failed_cooldown = 30.0 [shuttle] -# Wastes startup time +grid_fill = false auto_call_time = 0 -cargo = false emergency = false arrivals = false diff --git a/Resources/Maps/Shuttles/cargo.yml b/Resources/Maps/Shuttles/cargo.yml index e1a1c39cf1..9433124bfe 100644 --- a/Resources/Maps/Shuttles/cargo.yml +++ b/Resources/Maps/Shuttles/cargo.yml @@ -14,6 +14,7 @@ entities: - uid: 173 components: - type: MetaData + name: Cargo shuttle - pos: 2.2710133,-2.4148211 parent: invalid type: Transform @@ -37,10 +38,10 @@ entities: fixedRotation: False bodyType: Dynamic type: Physics - - gravityShakeSound: !type:SoundPathSpecifier path: /Audio/Effects/alert.ogg type: Gravity + - type: CargoShuttle - chunkCollection: version: 2 nodes: diff --git a/Resources/Maps/Shuttles/mining.yml b/Resources/Maps/Shuttles/mining.yml index bcbd226521..135e138cb4 100644 --- a/Resources/Maps/Shuttles/mining.yml +++ b/Resources/Maps/Shuttles/mining.yml @@ -37,7 +37,7 @@ entities: fixedRotation: False bodyType: Dynamic type: Physics - + - type: SalvageShuttle - gravityShakeSound: !type:SoundPathSpecifier path: /Audio/Effects/alert.ogg type: Gravity diff --git a/Resources/Prototypes/Catalog/Fills/Lockers/heads.yml b/Resources/Prototypes/Catalog/Fills/Lockers/heads.yml index e34f95b324..d80fad39e8 100644 --- a/Resources/Prototypes/Catalog/Fills/Lockers/heads.yml +++ b/Resources/Prototypes/Catalog/Fills/Lockers/heads.yml @@ -19,6 +19,7 @@ - id: CargoRequestComputerCircuitboard - id: CargoShuttleComputerCircuitboard - id: CargoShuttleConsoleCircuitboard + - id: SalvageShuttleConsoleCircuitboard - id: CigPackGreen prob: 0.50 - id: DoorRemoteCargo @@ -59,7 +60,7 @@ - id: WeaponAntiqueLaser - id: JetpackCaptainFilled - id: MedalCase - + - type: entity id: LockerCaptainFilled suffix: Filled diff --git a/Resources/Prototypes/Datasets/Names/cargo_shuttle.yml b/Resources/Prototypes/Datasets/Names/cargo_shuttle.yml index 85a95273f8..97ad423ed1 100644 --- a/Resources/Prototypes/Datasets/Names/cargo_shuttle.yml +++ b/Resources/Prototypes/Datasets/Names/cargo_shuttle.yml @@ -1,5 +1,5 @@ - type: dataset - id: CargoShuttleNames + id: ShuttleNames values: - A Shuttle Will Not Occur - Big Money Shuttle @@ -8,4 +8,4 @@ - Shootel - Shuttle McShuttleface - ShuttleShuttle - - Urist McShuttle \ No newline at end of file + - Urist McShuttle diff --git a/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/computer.yml b/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/computer.yml index 7acf33c448..0a5f99f134 100644 --- a/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/computer.yml +++ b/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/computer.yml @@ -103,12 +103,21 @@ - type: entity parent: BaseComputerCircuitboard id: CargoShuttleConsoleCircuitboard - name: supply shuttle console board + name: cargo shuttle console board description: A computer printed circuit board for a cargo shuttle console. components: - type: ComputerBoard prototype: ComputerShuttleCargo +- type: entity + parent: BaseComputerCircuitboard + id: SalvageShuttleConsoleCircuitboard + name: salvage shuttle console board + description: A computer printed circuit board for a salvage shuttle console. + components: + - type: ComputerBoard + prototype: ComputerShuttleSalvage + - type: entity parent: BaseComputerCircuitboard id: SurveillanceCameraMonitorCircuitboard diff --git a/Resources/Prototypes/Entities/Stations/base.yml b/Resources/Prototypes/Entities/Stations/base.yml index da5dc6d301..add77dc0db 100644 --- a/Resources/Prototypes/Entities/Stations/base.yml +++ b/Resources/Prototypes/Entities/Stations/base.yml @@ -31,6 +31,15 @@ components: - type: StationArrivals +- type: entity + id: BaseStationShuttles + abstract: true + components: + - type: GridSpawn + paths: + - /Maps/Shuttles/cargo.yml + - /Maps/Shuttles/mining.yml + - type: entity id: BaseStationCentcomm abstract: true diff --git a/Resources/Prototypes/Entities/Stations/nanotrasen.yml b/Resources/Prototypes/Entities/Stations/nanotrasen.yml index 6e1e339d17..89e9b7c132 100644 --- a/Resources/Prototypes/Entities/Stations/nanotrasen.yml +++ b/Resources/Prototypes/Entities/Stations/nanotrasen.yml @@ -14,6 +14,7 @@ - BaseStationJobsSpawning - BaseStationRecords - BaseStationArrivals + - BaseStationShuttles - BaseStationCentcomm - BaseStationEvacuation - BaseStationAlertLevels diff --git a/Resources/Prototypes/Entities/Structures/Machines/Computers/computers.yml b/Resources/Prototypes/Entities/Structures/Machines/Computers/computers.yml index b2bd2c5d1b..a06fc8f401 100644 --- a/Resources/Prototypes/Entities/Structures/Machines/Computers/computers.yml +++ b/Resources/Prototypes/Entities/Structures/Machines/Computers/computers.yml @@ -129,7 +129,9 @@ state: shuttle - map: ["computerLayerKeys"] state: generic_keys - - type: CargoPilotConsole + - type: DroneConsole + components: + - type: CargoShuttle - type: RadarConsole maxRange: 256 - type: PointLight @@ -139,6 +141,34 @@ - type: Computer board: CargoShuttleConsoleCircuitboard +- type: entity + parent: BaseComputerShuttle + id: ComputerShuttleSalvage + name: salvage shuttle console + description: Used to pilot the salvage shuttle. + components: + - type: Sprite + layers: + - map: ["computerLayerBody"] + state: computer + - map: ["computerLayerKeyboard"] + state: generic_keyboard + - map: ["computerLayerScreen"] + state: shuttle + - map: ["computerLayerKeys"] + state: generic_keys + - type: DroneConsole + components: + - type: SalvageShuttle + - type: RadarConsole + maxRange: 256 + - type: PointLight + radius: 1.5 + energy: 1.6 + color: "#c94242" + - type: Computer + board: SalvageShuttleConsoleCircuitboard + - type: entity parent: BaseComputer id: ComputerIFF diff --git a/Resources/Prototypes/shuttles.yml b/Resources/Prototypes/shuttles.yml deleted file mode 100644 index 8acfd263ed..0000000000 --- a/Resources/Prototypes/shuttles.yml +++ /dev/null @@ -1,4 +0,0 @@ -# Cargo -- type: cargoShuttle - id: CargoShuttle - path: /Maps/Shuttles/cargo.yml