From 41d2d3ff82864896e6eebbe5b910652d26b0dbe5 Mon Sep 17 00:00:00 2001 From: Proximitron Date: Thu, 27 Aug 2026 16:56:02 +0200 Subject: [PATCH 01/17] Stable and tested version of the remote access system (remote grids) based at the moment entirely on shuttle remote consoles. --- .../BUI/ShuttleConsoleBoundUserInterface.cs | 27 ++++++ Content.Client/Shuttles/UI/NavScreen.xaml.cs | 15 ++++ .../Shuttles/UI/ShuttleConsoleWindow.xaml.cs | 13 +++ .../Silicons/StationAi/StationAiOverlay.cs | 7 +- .../Systems/StationLimitedNetworkSystem.cs | 19 +++- Content.Server/Holopad/HolopadSystem.cs | 27 +++--- .../Systems/ShuttleConsoleSystem.Drone.cs | 89 ++++++++++++++++++- .../Shuttles/Systems/ShuttleConsoleSystem.cs | 42 +++++++++ .../Silicons/StationAi/StationAiSystem.cs | 46 ++++------ .../Systems/SharedMoverController.Input.cs | 10 ++- .../StationAi/SharedStationAiSystem.Held.cs | 7 +- .../StationAi/SharedStationAiSystem.cs | 36 +++++++- .../_Starlight/Maps/GridAccessComponent.cs | 16 ++++ .../_Starlight/Maps/SharedGridAccessSystem.cs | 64 +++++++++++++ .../Entities/Structures/Machines/holopad.yml | 1 + 15 files changed, 366 insertions(+), 53 deletions(-) create mode 100644 Content.Shared/_Starlight/Maps/GridAccessComponent.cs create mode 100644 Content.Shared/_Starlight/Maps/SharedGridAccessSystem.cs diff --git a/Content.Client/Shuttles/BUI/ShuttleConsoleBoundUserInterface.cs b/Content.Client/Shuttles/BUI/ShuttleConsoleBoundUserInterface.cs index 35bfbbedfa01..aa35f7dfe0a8 100644 --- a/Content.Client/Shuttles/BUI/ShuttleConsoleBoundUserInterface.cs +++ b/Content.Client/Shuttles/BUI/ShuttleConsoleBoundUserInterface.cs @@ -6,16 +6,27 @@ using Robust.Client.UserInterface; using Robust.Shared.Map; +#region Starlight +using Content.Shared.Medical.CrewMonitoring; +using Content.Shared.Silicons.StationAi; +using Robust.Shared.Player; +#endregion Starlight + namespace Content.Client.Shuttles.BUI; [UsedImplicitly] public sealed class ShuttleConsoleBoundUserInterface : BoundUserInterface { + #region Starlight + [Dependency] private ISharedPlayerManager _playerManager = default!; + #endregion Starlight + [ViewVariables] private ShuttleConsoleWindow? _window; public ShuttleConsoleBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey) { + IoCManager.InjectDependencies(this); // Starlight } protected override void Open() @@ -27,6 +38,7 @@ protected override void Open() _window.RequestBeaconFTL += OnFTLBeaconRequest; _window.DockRequest += OnDockRequest; _window.UndockRequest += OnUndockRequest; + _window.RadarClicked += OnRadarClicked; // Starlight } private void OnUndockRequest(NetEntity entity) @@ -70,10 +82,25 @@ protected override void Dispose(bool disposing) if (disposing) { + // Starlight - start + if (_window != null) + _window.RadarClicked -= OnRadarClicked; + // Starlight - end _window?.DisposePopOut(); // Starlight: close the popout if exists } } + #region Starlight + private void OnRadarClicked(EntityCoordinates coordinates) + { + var local = _playerManager.LocalEntity; + if (local is null || !EntMan.HasComponent(local.Value)) + return; + + SendMessage(new CrewMonitoringWarpRequestMessage(EntMan.GetNetCoordinates(coordinates))); + } + #endregion Starlight + protected override void UpdateState(BoundUserInterfaceState state) { base.UpdateState(state); diff --git a/Content.Client/Shuttles/UI/NavScreen.xaml.cs b/Content.Client/Shuttles/UI/NavScreen.xaml.cs index fd6c09b52878..28debf8f08d7 100644 --- a/Content.Client/Shuttles/UI/NavScreen.xaml.cs +++ b/Content.Client/Shuttles/UI/NavScreen.xaml.cs @@ -19,6 +19,10 @@ public sealed partial class NavScreen : BoxContainer private EntityUid? _consoleEntity; // Entity of controlling console private EntityUid? _shuttleEntity; + #region Starlight + public event Action? OnRadarClick; + #endregion Starlight + public NavScreen() { RobustXamlLoader.Load(this); @@ -30,6 +34,10 @@ public NavScreen() DockToggle.OnToggled += OnDockTogglePressed; DockToggle.Pressed = NavRadar.ShowDocks; + + // Starlight - start + NavRadar.OnRadarClick += OnRadarClickPressed; + // Starlight - end } public void SetShuttle(EntityUid? shuttle) @@ -55,6 +63,13 @@ private void OnDockTogglePressed(BaseButton.ButtonEventArgs args) args.Button.Pressed = NavRadar.ShowDocks; } + #region Starlight + private void OnRadarClickPressed(EntityCoordinates coordinates) + { + OnRadarClick?.Invoke(coordinates); + } + #endregion + public void UpdateState(NavInterfaceState scc, DockingPortStates dockingPortStates) // Starlight: +dockingPortStates { NavRadar.UpdateState(scc, dockingPortStates); // Starlight: +dockingPortStates diff --git a/Content.Client/Shuttles/UI/ShuttleConsoleWindow.xaml.cs b/Content.Client/Shuttles/UI/ShuttleConsoleWindow.xaml.cs index fed15a581f4d..ae499c2ba3c4 100644 --- a/Content.Client/Shuttles/UI/ShuttleConsoleWindow.xaml.cs +++ b/Content.Client/Shuttles/UI/ShuttleConsoleWindow.xaml.cs @@ -27,6 +27,10 @@ public sealed partial class ShuttleConsoleWindow : PopOutFancyWindow, // Starlig public event Action? DockRequest; public event Action? UndockRequest; + #region Starlight + public event Action? RadarClicked; + #endregion Starlight + public ShuttleConsoleWindow() { RobustXamlLoader.Load(this); @@ -47,6 +51,8 @@ public ShuttleConsoleWindow() NavModeButton.Pressed = true; SetupMode(_mode); + NavContainer.OnRadarClick += OnRadarClick; // Starlight + MapContainer.RequestFTL += (coords, angle) => { RequestFTL?.Invoke(coords, angle); @@ -68,6 +74,13 @@ public ShuttleConsoleWindow() }; } + #region Starlight + private void OnRadarClick(EntityCoordinates coordinates) + { + RadarClicked?.Invoke(coordinates); + } + #endregion + private void ClearModes(ShuttleConsoleMode mode) { if (mode != ShuttleConsoleMode.Nav) diff --git a/Content.Client/Silicons/StationAi/StationAiOverlay.cs b/Content.Client/Silicons/StationAi/StationAiOverlay.cs index 38eed0758e93..964216cbb3b9 100644 --- a/Content.Client/Silicons/StationAi/StationAiOverlay.cs +++ b/Content.Client/Silicons/StationAi/StationAiOverlay.cs @@ -76,7 +76,7 @@ protected override void Draw(in OverlayDrawArgs args) // Check for cross-grid viewing (e.g., Abductor remote eye) BEFORE getting gridUid if (_entManager.TryGetComponent(playerEnt, out StationAiOverlayComponent? stationAiOverlay) - && stationAiOverlay.AllowCrossGrid + && (stationAiOverlay.AllowCrossGrid || _entManager.HasComponent(playerEnt)) && _entManager.TryGetComponent(playerEnt, out RelayInputMoverComponent? relay)) playerEnt = relay.RelayEntity; @@ -84,7 +84,10 @@ protected override void Draw(in OverlayDrawArgs args) _entManager.TryGetComponent(playerEnt, out TransformComponent? playerXform); var gridUid = playerXform?.GridUid - ?? (stationAiOverlay is { AllowCrossGrid: true } ? _lastGridUid : EntityUid.Invalid); + ?? (stationAiOverlay is { AllowCrossGrid: true } || + _entManager.HasComponent(_player.LocalEntity) + ? _lastGridUid + : EntityUid.Invalid); if (gridUid != EntityUid.Invalid) _lastGridUid = gridUid; diff --git a/Content.Server/DeviceNetwork/Systems/StationLimitedNetworkSystem.cs b/Content.Server/DeviceNetwork/Systems/StationLimitedNetworkSystem.cs index fbb8b2e35a0b..bc3370145376 100644 --- a/Content.Server/DeviceNetwork/Systems/StationLimitedNetworkSystem.cs +++ b/Content.Server/DeviceNetwork/Systems/StationLimitedNetworkSystem.cs @@ -1,6 +1,7 @@ using Content.Server.DeviceNetwork.Components; using Content.Server.Station.Systems; using Content.Shared.DeviceNetwork.Events; +using Content.Shared.Maps; using JetBrains.Annotations; using Robust.Shared.Map; @@ -13,6 +14,9 @@ namespace Content.Server.DeviceNetwork.Systems public sealed partial class StationLimitedNetworkSystem : EntitySystem { [Dependency] private StationSystem _stationSystem = default!; + #region Starlight + [Dependency] private SharedGridAccessSystem _gridAccess = default!; + #endregion public override void Initialize() { base.Initialize(); @@ -59,12 +63,25 @@ private void OnBeforePacketSent(EntityUid uid, StationLimitedNetworkComponent co if (!component.StationId.HasValue) TrySetStationId(uid, component); - if (!CheckStationId(args.Sender, component.AllowNonStationPackets, component.StationId)) + if (!CheckStationId(args.Sender, component.AllowNonStationPackets, component.StationId) && + !CanAccessSenderGrid(uid, args.Sender)) // Starlight: allow access if the sender and receiver are on grids that can access each other { args.Cancel(); } } + #region Starlight + private bool CanAccessSenderGrid(EntityUid receiver, EntityUid sender) + { + var receiverGrid = Transform(receiver).GridUid; + var senderGrid = Transform(sender).GridUid; + + return receiverGrid is { } targetGrid && senderGrid is { } sourceGrid && + (_gridAccess.CanAccess(sourceGrid, targetGrid) || + _gridAccess.CanAccess(targetGrid, sourceGrid)); + } + #endregion Starlight + /// /// Compares the station IDs of the sending and receiving network components. /// Returns false if either of them doesn't have a station ID or if their station ID isn't equal. diff --git a/Content.Server/Holopad/HolopadSystem.cs b/Content.Server/Holopad/HolopadSystem.cs index 1afd6c2ba17f..c9225badc376 100644 --- a/Content.Server/Holopad/HolopadSystem.cs +++ b/Content.Server/Holopad/HolopadSystem.cs @@ -105,6 +105,11 @@ private void OnHolopadStartNewCall(Entity source, ref HolopadS if (!TryComp(receiver, out var receiverTelephone)) return; + // Starlight - start + if (HasComp(args.Actor) && + !_stationAiSystem.CanAccessGrid(args.Actor, Transform(receiver).GridUid)) + return; + // Starlight - end LinkHolopadToUser(source, args.Actor); _telephoneSystem.CallTelephone((source, sourceTelephone), (receiver, receiverTelephone), args.Actor); } @@ -127,15 +132,6 @@ private void OnHolopadAnswerCall(Entity receiver, ref HolopadA if (_stationAiSystem.TryGetCore(args.Actor, out var stationAiCore)) _userInterfaceSystem.CloseUi(receiver.Owner, HolopadUiKey.AiRequestWindow, args.Actor); - // Try to warn the AI if the source of the call is out of its range - if (TryComp(stationAiCore, out var stationAiTelephone) && - TryComp(source, out var sourceTelephone) && - !_telephoneSystem.IsSourceInRangeOfReceiver((stationAiCore.Owner, stationAiTelephone), (source.Value.Owner, sourceTelephone))) - { - _popupSystem.PopupEntity(Loc.GetString("holopad-ai-is-unable-to-reach-holopad"), receiver, args.Actor); - return; - } - ActivateProjector(source.Value, args.Actor); } @@ -673,8 +669,18 @@ private void ActivateProjector(Entity entity, EntityUid user) var source = new Entity(stationAiCore, stationAiTelephone); + // Starlight - start + // We check if the AI has grid access. Normal projector call are range limited, not limited by grid access. The AI is special. + if (!_stationAiSystem.CanAccessGrid(user, Transform(entity).GridUid)) + { + _popupSystem.PopupEntity(Loc.GetString("holopad-ai-is-unable-to-activate-projector"), receiver, user); + return; + } + // Starlight - end + // Check if the AI is unable to activate the projector (unlikely this will ever pass; its just a safeguard) - if (!_telephoneSystem.IsSourceInRangeOfReceiver(source, receiver)) + if (!_telephoneSystem.IsTelephonePowered(source) || + !_telephoneSystem.IsTelephonePowered(receiver)) // Starlight: check replaced with sensible check based on power { _popupSystem.PopupEntity(Loc.GetString("holopad-ai-is-unable-to-activate-projector"), receiver, user); return; @@ -685,6 +691,7 @@ private void ActivateProjector(Entity entity, EntityUid user) var callOptions = new TelephoneCallOptions() { + IgnoreRange = true, // Starlight: we do check things in advance and have safeguards in place ForceConnect = true, MuteReceiver = true }; diff --git a/Content.Server/Shuttles/Systems/ShuttleConsoleSystem.Drone.cs b/Content.Server/Shuttles/Systems/ShuttleConsoleSystem.Drone.cs index eb5e11b8ebeb..a965822863b4 100644 --- a/Content.Server/Shuttles/Systems/ShuttleConsoleSystem.Drone.cs +++ b/Content.Server/Shuttles/Systems/ShuttleConsoleSystem.Drone.cs @@ -2,11 +2,24 @@ using Content.Server.Shuttles.Events; using Content.Shared.Station.Components; using Content.Shared.UserInterface; +using Content.Server.Power.Components; +using Content.Server.Power.EntitySystems; +using Content.Shared.Maps; namespace Content.Server.Shuttles.Systems; public sealed partial class ShuttleConsoleSystem { + #region Starlight + [Dependency] private SharedGridAccessSystem _gridAccess = default!; + private readonly Dictionary _remoteGridAccess = new(); + + private void OnDroneConsoleStartup(EntityUid uid, DroneConsoleComponent component, ComponentStartup args) + { + UpdateRemoteGridAccess(uid, component); + } + #endregion Starlight + /// /// Gets the drone console target if applicable otherwise returns itself. /// @@ -30,13 +43,17 @@ public void RefreshDroneConsoles() while (query.MoveNext(out var uid, out var comp)) { - comp.Entity = GetShuttleConsole(uid, comp); + // Starlight - start + UpdateRemoteGridAccess(uid, comp); + // Starlight - end } } private void OnDronePilotConsoleOpen(EntityUid uid, DroneConsoleComponent component, AfterActivatableUIOpenEvent args) { - component.Entity = GetShuttleConsole(uid); + // Starlight - start + UpdateRemoteGridAccess(uid, component); + // Starlight - end } private void OnDronePilotConsoleClose(EntityUid uid, DroneConsoleComponent component, BoundUIClosedEvent args) @@ -48,8 +65,74 @@ private void OnDronePilotConsoleClose(EntityUid uid, DroneConsoleComponent compo private void OnCargoGetConsole(EntityUid uid, DroneConsoleComponent component, ref ConsoleShuttleEvent args) { - args.Console = GetShuttleConsole(uid, component); + // Starlight - start + UpdateRemoteGridAccess(uid, component); + // Starlight - end + args.Console = component.Entity; + } + + #region Starlight + private void UpdateRemoteGridAccess(EntityUid uid, DroneConsoleComponent component) + { + // Starlight - start + var targetConsole = GetShuttleConsole(uid, component); + var sourceGrid = Transform(uid).GridUid; + var targetGrid = targetConsole is { } target + ? Transform(target).GridUid + : null; + + if (_remoteGridAccess.TryGetValue(uid, out var previous) && + (sourceGrid != previous.SourceGrid || targetGrid != previous.TargetGrid || + !IsConsoleOperational(uid) || targetConsole is not { } currentTarget || !IsConsoleOperational(currentTarget))) + { + RemoveRemoteGridAccess(uid); + } + + component.Entity = targetConsole; + + if (sourceGrid is not { } source || targetGrid is not { } targetUid || + targetConsole is not { } console || + !IsConsoleOperational(uid) || !IsConsoleOperational(console)) + { + return; + } + + if (_remoteGridAccess.ContainsKey(uid)) + return; + + _gridAccess.AddAccessibleGrid(source, targetUid); + _remoteGridAccess[uid] = (source, targetUid); + // Starlight - end + } + + private void RemoveRemoteGridAccess(EntityUid uid) + { + // Starlight - start + if (!_remoteGridAccess.Remove(uid, out var access)) + return; + + foreach (var other in _remoteGridAccess.Values) + { + if (other != access) + continue; + + return; + } + + _gridAccess.RemoveAccessibleGrid(access.SourceGrid, access.TargetGrid); + // Starlight - end + } + + private bool IsConsoleOperational(EntityUid uid) + { + // Starlight - start + return TryComp(uid, out _) && + MetaData(uid).EntityLifeStage < EntityLifeStage.Terminating && + Transform(uid).Anchored && + this.IsPowered(uid, EntityManager); + // Starlight - end } + #endregion Starlight /// /// Gets the relevant shuttle console to proxy from the drone console. diff --git a/Content.Server/Shuttles/Systems/ShuttleConsoleSystem.cs b/Content.Server/Shuttles/Systems/ShuttleConsoleSystem.cs index 401a7513334a..ed121fa1edbb 100644 --- a/Content.Server/Shuttles/Systems/ShuttleConsoleSystem.cs +++ b/Content.Server/Shuttles/Systems/ShuttleConsoleSystem.cs @@ -29,6 +29,9 @@ using Content.Server._Starlight.Shuttles.Components; using Content.Shared._Starlight.Shuttles.Components; using Content.Shared._Starlight.Shuttles.BUIStates; +using Content.Shared.Medical.CrewMonitoring; +using Content.Shared.Silicons.StationAi; +using Content.Server.Silicons.StationAi; namespace Content.Server.Shuttles.Systems; @@ -48,6 +51,7 @@ public sealed partial class ShuttleConsoleSystem : SharedShuttleConsoleSystem [Dependency] private ILogManager _log = default!; [Dependency] private RadarLaserSystem _laserSystem = default!; // _Starlight [Dependency] private IGameTiming _timing = default!; // _Starlight + [Dependency] private StationAiSystem _stationAiSystem = default!; // Starlight #region Starlight // Periodic blip/laser update @@ -86,11 +90,18 @@ public override void Initialize() SubscribeLocalEvent(OnConsoleShutdown); SubscribeLocalEvent(OnConsolePowerChange); SubscribeLocalEvent(OnConsoleAnchorChange); + // Starlight - start + SubscribeLocalEvent(OnDroneConsoleStartup); + // Starlight - end SubscribeLocalEvent(OnConsoleUIOpenAttempt); Subs.BuiEvents(ShuttleConsoleUiKey.Key, subs => { subs.Event(OnBeaconFTLMessage); subs.Event(OnPositionFTLMessage); + subs.Event((uid, component, args) => + { + HandleWarpRequest(args); + }); // Starlight subs.Event(OnConsoleUIClose); }); @@ -98,6 +109,10 @@ public override void Initialize() SubscribeLocalEvent(OnDronePilotConsoleOpen); Subs.BuiEvents(ShuttleConsoleUiKey.Key, subs => { + subs.Event((uid, component, args) => + { + HandleWarpRequest(args); + }); // Starlight subs.Event(OnDronePilotConsoleClose); }); @@ -187,6 +202,26 @@ private void OnConsoleUIOpenAttempt(EntityUid uid, ShuttleConsoleComponent compo TryPilot(args.User, uid); } + #region Starlight + private void HandleWarpRequest(CrewMonitoringWarpRequestMessage args) + { + if (args.Actor is not { Valid: true } actor || !HasComp(actor)) + return; + + EntityCoordinates coordinates; + try + { + coordinates = GetCoordinates(args.Coordinates); + } + catch + { + return; + } + + _stationAiSystem.TryWarpEyeToCoordinates(actor, coordinates); + } + #endregion + private void OnConsoleAnchorChange(EntityUid uid, ShuttleConsoleComponent component, ref AnchorStateChangedEvent args) { @@ -200,6 +235,9 @@ private void OnConsolePowerChange(EntityUid uid, ShuttleConsoleComponent compone DockingInterfaceState? dockState = null; DockingPortStates? dockingPortStates = null; // Starlight UpdateState(uid, ref dockState, ref dockingPortStates); // Starlight + // Starlight - start + RefreshDroneConsoles(); + // Starlight - end } private bool TryPilot(EntityUid user, EntityUid uid) @@ -414,6 +452,10 @@ protected override void HandlePilotShutdown(EntityUid uid, PilotComponent compon private void OnConsoleShutdown(EntityUid uid, ShuttleConsoleComponent component, ComponentShutdown args) { ClearPilots(component); + // Starlight - start + RemoveRemoteGridAccess(uid); + RefreshDroneConsoles(); + // Starlight - end } public void AddPilot(EntityUid uid, EntityUid entity, ShuttleConsoleComponent component) diff --git a/Content.Server/Silicons/StationAi/StationAiSystem.cs b/Content.Server/Silicons/StationAi/StationAiSystem.cs index c136705bf205..aeaaeef6f9ee 100644 --- a/Content.Server/Silicons/StationAi/StationAiSystem.cs +++ b/Content.Server/Silicons/StationAi/StationAiSystem.cs @@ -199,11 +199,12 @@ private void OnStationAiWarpRequest(StationAiWarpRequestEvent msg, EntitySession return; } - var aiStation = _station.GetOwningStation(coreEntity.Owner); var targets = new List(); - CollectCrewWarpTargets(actor, aiStation, targets); - CollectLocationWarpTargets(actor, aiStation, coreEntity.Comp.RemoteEntity, targets); + // Starlight - start + CollectCrewWarpTargets(actor, targets); + CollectLocationWarpTargets(actor, coreEntity.Comp.RemoteEntity, targets); + // Starlight - end if (targets.Count == 0) _warpSawmill.Debug($"No warp targets available for Station AI {Name(actor)} ({actor})."); @@ -233,7 +234,7 @@ private void OnStationAiWarpToTarget(StationAiWarpToTargetEvent msg, EntitySessi /// /// Populates the warp target buffer with crew members whose suit sensors are broadcasting coordinates. /// - private void CollectCrewWarpTargets(EntityUid actor, EntityUid? aiStation, List buffer) + private void CollectCrewWarpTargets(EntityUid actor, List buffer) { var processed = new HashSet(); var enumerator = EntityQueryEnumerator(); @@ -257,12 +258,10 @@ private void CollectCrewWarpTargets(EntityUid actor, EntityUid? aiStation, List< if (!HasComp(ownerUid)) continue; - if (aiStation is { } station) - { - var ownerStation = _station.GetOwningStation(ownerUid); - if (ownerStation != station) - continue; - } + // Starlight - start + if (!CanAccessGrid(actor, Transform(ownerUid).GridUid)) + continue; + // Starlight - end // Don't show crew members outside of camera view if (_aiVision.IsOutsideCameraViewCached(ownerUid)) // starlight @@ -276,7 +275,7 @@ private void CollectCrewWarpTargets(EntityUid actor, EntityUid? aiStation, List< } } - private void CollectLocationWarpTargets(EntityUid actor, EntityUid? aiStation, EntityUid? remoteEntity, List buffer) + private void CollectLocationWarpTargets(EntityUid actor, EntityUid? remoteEntity, List buffer) { var query = AllEntityQuery(); @@ -296,15 +295,13 @@ private void CollectLocationWarpTargets(EntityUid actor, EntityUid? aiStation, E continue; // Starlight End - if (aiStation is { } station) + // Starlight - start + if (!CanAccessGrid(actor, Transform(uid).GridUid)) { - var warpStation = _station.GetOwningStation(uid); - if (warpStation != station) - { - _warpSawmill.Debug($"Skipping warp point {Name(uid)} ({uid}) outside AI station {station}."); - continue; - } + _warpSawmill.Debug($"Skipping warp point {Name(uid)} ({uid}) outside AI grid access list."); + continue; } + // Starlight - end var name = warp.Location ?? Name(uid); buffer.Add(new StationAiWarpTarget(GetNetEntity(uid), name, StationAiWarpTargetType.Location)); @@ -349,15 +346,10 @@ bool Fail() if (!_map.TryFindGridAt(mapCoordinates, out var gridUid, out _)) return Fail(); - var aiStation = _station.GetOwningStation(coreUid); - - if (aiStation != null) - { - var targetStation = _station.GetOwningStation(gridUid); - - if (targetStation != aiStation) - return Fail(); - } + // Starlight - start + if (!CanAccessGrid(user, gridUid)) + return Fail(); + // Starlight - end var targetCoords = _xforms.ToCoordinates((gridUid, Transform(gridUid)), mapCoordinates); diff --git a/Content.Shared/Movement/Systems/SharedMoverController.Input.cs b/Content.Shared/Movement/Systems/SharedMoverController.Input.cs index 4158dca64133..106d92d66a37 100644 --- a/Content.Shared/Movement/Systems/SharedMoverController.Input.cs +++ b/Content.Shared/Movement/Systems/SharedMoverController.Input.cs @@ -1,4 +1,4 @@ -using System.Numerics; +using System.Numerics; using System.Security.Cryptography; using Content.Shared._Starlight.Actions.Handlers; using Content.Shared.Alert; @@ -12,6 +12,7 @@ using Robust.Shared.Input.Binding; using Robust.Shared.Map.Components; using Robust.Shared.Physics; +using Robust.Shared.Physics.Components; using Robust.Shared.Player; using Robust.Shared.Prototypes; using Robust.Shared.Serialization; @@ -330,8 +331,11 @@ private void OnInputParentChange(Entity entity, ref EntPare private void OnAnchorState(Entity entity, ref AnchorStateChangedEvent args) { - if (!args.Anchored) - PhysicsSystem.SetBodyType(entity, BodyType.KinematicController); + if (args.Anchored || EntityManager.IsQueuedForDeletion(entity.Owner) || + !TryComp(entity.Owner, out _)) + return; // Starlight: cleaner checks that prevent a lot of exceptions + + PhysicsSystem.TrySetBodyType(entity, BodyType.KinematicController); // Starlight: we use try instead of set because sometimes its not available yet and causes exceptions } private void HandleDirChange(EntityUid entity, Direction dir, ushort subTick, bool state) diff --git a/Content.Shared/Silicons/StationAi/SharedStationAiSystem.Held.cs b/Content.Shared/Silicons/StationAi/SharedStationAiSystem.Held.cs index 6991c349abdf..49e64c451d3a 100644 --- a/Content.Shared/Silicons/StationAi/SharedStationAiSystem.Held.cs +++ b/Content.Shared/Silicons/StationAi/SharedStationAiSystem.Held.cs @@ -188,10 +188,11 @@ private void OnTargetVerbs(Entity ent, ref GetVerbs return; } - // Starlight Start - if (_vision.IsOutsideCameraViewCached(args.Target)) + // Starlight - start + if (!CanAccessGrid(args.User, Transform(args.Target).GridUid) || + _vision.IsOutsideCameraViewCached(args.Target)) return; - // Starlight End + // Starlight - end var user = args.User; var target = args.Target; diff --git a/Content.Shared/Silicons/StationAi/SharedStationAiSystem.cs b/Content.Shared/Silicons/StationAi/SharedStationAiSystem.cs index 917901699992..adaebbf17c22 100644 --- a/Content.Shared/Silicons/StationAi/SharedStationAiSystem.cs +++ b/Content.Shared/Silicons/StationAi/SharedStationAiSystem.cs @@ -45,6 +45,7 @@ using Content.Shared.DeviceLinking; using Content.Shared._Starlight; using Content.Shared.NameModifier.EntitySystems; +using Content.Shared.Maps; #endregion Starlight namespace Content.Shared.Silicons.StationAi; @@ -75,6 +76,9 @@ public abstract partial class SharedStationAiSystem : EntitySystem [Dependency] private SharedTransformSystem _xforms = default!; [Dependency] private SharedUserInterfaceSystem _uiSystem = default!; [Dependency] private StationAiVisionSystem _vision = default!; + #region Starlight + [Dependency] private SharedGridAccessSystem _gridAccess = default!; + #endregion Starlight [Dependency] private IPrototypeManager _protoManager = default!; [Dependency] private MobStateSystem _mobState = default!; [Dependency] private SharedDeviceLinkSystem _deviceLinkSystem = default!; // Starlight @@ -193,6 +197,22 @@ private void OnAiAccessible(Entity ent, ref Accessibl args.Accessible = true; } + #region Starlight + /// + /// Returns whether the grid containing the AI core can access the target grid. + /// + public bool CanAccessGrid(EntityUid user, EntityUid? targetGrid) + { + if (targetGrid is not { } target || !HasComp(target)) + return false; + + if (!TryGetCore(user, out var core) || core.Comp is null) + return false; + + var sourceGrid = Transform(core.Owner).GridUid; + return sourceGrid is { } source && _gridAccess.CanAccess(source, target); + } + #endregion private void OnAiMenu(Entity ent, ref MenuVisibilityEvent args) { @@ -210,11 +230,12 @@ private void OnAiBuiCheck(Entity ent, ref BoundUser //// Similar to the inrange check but more optimised so server doesn't die. var targetXform = Transform(args.Target); - // No cross-grid - if (targetXform.GridUid != args.Actor.Comp.GridUid) + // Starlight - start + if (!CanAccessGrid(args.Actor, targetXform.GridUid)) { return; } + // Starlight - end // //if (!_broadphaseQuery.TryComp(targetXform.GridUid, out var broadphase) || !_gridQuery.TryComp(targetXform.GridUid, out var grid)) //{ @@ -248,8 +269,15 @@ private void OnAiInRange(Entity ent, ref InRangeOverr var targetXform = Transform(target); - // No cross-grid - if (targetXform.GridUid != Transform(args.User).GridUid && !ent.Comp.AllowCrossGrid) + // Starlight the AI can access remote grids in some situation + if (HasComp(args.User)) + { + // Starlight - start + if (!CanAccessGrid(args.User, targetXform.GridUid)) + return; + // Starlight - end + } + else if (targetXform.GridUid != Transform(args.User).GridUid && !ent.Comp.AllowCrossGrid) { return; } diff --git a/Content.Shared/_Starlight/Maps/GridAccessComponent.cs b/Content.Shared/_Starlight/Maps/GridAccessComponent.cs new file mode 100644 index 000000000000..6900609e3e81 --- /dev/null +++ b/Content.Shared/_Starlight/Maps/GridAccessComponent.cs @@ -0,0 +1,16 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared.Maps; + +/// +/// Describes which grids can be accessed from this grid. +/// +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +public sealed partial class GridAccessComponent : Component +{ + /// + /// Grids accessible from this grid. The owning grid is always included. + /// + [DataField, AutoNetworkedField] + public HashSet AccessibleGrids = new(); +} diff --git a/Content.Shared/_Starlight/Maps/SharedGridAccessSystem.cs b/Content.Shared/_Starlight/Maps/SharedGridAccessSystem.cs new file mode 100644 index 000000000000..048742eb0705 --- /dev/null +++ b/Content.Shared/_Starlight/Maps/SharedGridAccessSystem.cs @@ -0,0 +1,64 @@ +using Robust.Shared.Map; +using Robust.Shared.Map.Components; + +namespace Content.Shared.Maps; + +/// +/// Manages access from one map grid to other map grids. +/// +public sealed class SharedGridAccessSystem : EntitySystem +{ + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(OnGridInitialize); + } + + /// + /// Returns whether can be accessed from . + /// + public bool CanAccess(EntityUid sourceGrid, EntityUid targetGrid) => + TryComp(sourceGrid, out var access) && + access.AccessibleGrids.Contains(targetGrid); + + /// + /// Adds a grid to the access list of another grid. + /// + public bool AddAccessibleGrid(EntityUid sourceGrid, EntityUid targetGrid) + { + if (!HasComp(sourceGrid) || !HasComp(targetGrid)) + return false; + + var access = EnsureComp(sourceGrid); + if (!access.AccessibleGrids.Add(targetGrid)) + return false; + + Dirty(sourceGrid, access); + return true; + } + + /// + /// Removes a grid from the access list of another grid. A grid always retains access to itself. + /// + public bool RemoveAccessibleGrid(EntityUid sourceGrid, EntityUid targetGrid) + { + if (sourceGrid == targetGrid || !TryComp(sourceGrid, out var access)) + return false; + + if (!access.AccessibleGrids.Remove(targetGrid)) + return false; + + Dirty(sourceGrid, access); + return true; + } + + private void OnGridInitialize(GridInitializeEvent ev) + { + if (!HasComp(ev.EntityUid)) + return; + + var access = EnsureComp(ev.EntityUid); + if (access.AccessibleGrids.Add(ev.EntityUid)) + Dirty(ev.EntityUid, access); + } +} diff --git a/Resources/Prototypes/Entities/Structures/Machines/holopad.yml b/Resources/Prototypes/Entities/Structures/Machines/holopad.yml index f82610f0556b..2ec952d101e1 100644 --- a/Resources/Prototypes/Entities/Structures/Machines/holopad.yml +++ b/Resources/Prototypes/Entities/Structures/Machines/holopad.yml @@ -118,6 +118,7 @@ - type: Telephone transmissionRange: Map compatibleRanges: + - Grid # Starlight for SharedGridAccessSystem - Map - Unlimited ignoreTelephonesOnSameGrid: true From e192230c3c40d5e4ddc2414685329e80fe0ebc9c Mon Sep 17 00:00:00 2001 From: Proximitron Date: Thu, 27 Aug 2026 17:44:33 +0200 Subject: [PATCH 02/17] Cleanup for access of the camera system (to ensure cameras, even if present, are not usable by the AI on non-remote grids) --- .../Silicons/StationAi/StationAiOverlay.cs | 9 ++++++++- .../StationAi/StationAiVisionSystem.cs | 18 ++++++++++++++++-- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/Content.Client/Silicons/StationAi/StationAiOverlay.cs b/Content.Client/Silicons/StationAi/StationAiOverlay.cs index 964216cbb3b9..39f86a721e62 100644 --- a/Content.Client/Silicons/StationAi/StationAiOverlay.cs +++ b/Content.Client/Silicons/StationAi/StationAiOverlay.cs @@ -83,6 +83,13 @@ protected override void Draw(in OverlayDrawArgs args) _entManager.TryGetComponent(playerEnt, out StationAiOverlayComponent? relayStationAiOverlay); _entManager.TryGetComponent(playerEnt, out TransformComponent? playerXform); + // We try to figure out where the AI is even coming from to make sure we don't render cameras for remote grids without access + EntityUid? sourceGrid = null; + var stationAiSystem = _entManager.System(); + if (_player.LocalEntity is EntityUid localEntity) + if (stationAiSystem.TryGetCore(localEntity, out var core) && core.Comp is not null) + sourceGrid = _entManager.GetComponent(core.Owner).GridUid; + var gridUid = playerXform?.GridUid ?? (stationAiOverlay is { AllowCrossGrid: true } || _entManager.HasComponent(_player.LocalEntity) @@ -116,7 +123,7 @@ protected override void Draw(in OverlayDrawArgs args) _visibleTiles.Clear(); // Starlight - start _visibleTileTags.Clear(); - _entManager.System().GetView((gridUid, broadphase, grid), worldBounds, _visibleTiles, _visibleTileTags); + _entManager.System().GetView((gridUid, broadphase, grid), worldBounds, _visibleTiles, _visibleTileTags, sourceGrid: sourceGrid); // Starlight - end } diff --git a/Content.Shared/Silicons/StationAi/StationAiVisionSystem.cs b/Content.Shared/Silicons/StationAi/StationAiVisionSystem.cs index c0fad779622a..40357680f2c8 100644 --- a/Content.Shared/Silicons/StationAi/StationAiVisionSystem.cs +++ b/Content.Shared/Silicons/StationAi/StationAiVisionSystem.cs @@ -1,5 +1,6 @@ using Content.Shared.Power.EntitySystems; using Content.Shared.StationAi; +using Content.Shared.Maps; using Robust.Shared.Map.Components; using Robust.Shared.Physics; using Robust.Shared.Threading; @@ -20,7 +21,11 @@ public sealed partial class StationAiVisionSystem : EntitySystem [Dependency] private SharedMapSystem _maps = default!; [Dependency] private SharedTransformSystem _xforms = default!; [Dependency] private SharedPowerReceiverSystem _power = default!; - [Dependency] private IGameTiming _timing = default!; // STARLIGHT + + #region Starlight + [Dependency] private SharedGridAccessSystem _gridAccess = default!; + [Dependency] private IGameTiming _timing = default!; + #endregion private SeedJob _seedJob; private ViewJob _job; @@ -264,7 +269,7 @@ private bool IsOccluded(Entity grid, Vect /// /// How much to expand the bounds before to find vision intersecting it. Makes this the largest vision size + 1 tile. /// Starlight: added visibleTileTags - public void GetView(Entity grid, Box2Rotated worldBounds, HashSet visibleTiles, Dictionary> visibleTileTags, float expansionSize = 8.5f) + public void GetView(Entity grid, Box2Rotated worldBounds, HashSet visibleTiles, Dictionary> visibleTileTags, float expansionSize = 8.5f, EntityUid? sourceGrid = null) { _viewportTiles.Clear(); // Starlight - start @@ -288,6 +293,15 @@ public void GetView(Entity grid, Box2Rota if (!seed.Comp.Enabled) continue; + // Starlight - start + // Ensure we only render for grids we have access to + if (sourceGrid is { } source && Transform(seed.Owner).GridUid is { } seedGrid && + !_gridAccess.CanAccess(source, seedGrid)) + { + continue; + } + // Starlight - end + if (seed.Comp.NeedsPower && !_power.IsPowered(seed.Owner)) continue; From 4fc6737e0900114087664af076269574cace2ed0 Mon Sep 17 00:00:00 2001 From: Proximitron Date: Thu, 27 Aug 2026 18:25:08 +0200 Subject: [PATCH 03/17] Trying to reformat it? --- .../Systems/StationLimitedNetworkSystem.cs | 4 +--- .../Systems/ShuttleConsoleSystem.Drone.cs | 19 ++++++++----------- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/Content.Server/DeviceNetwork/Systems/StationLimitedNetworkSystem.cs b/Content.Server/DeviceNetwork/Systems/StationLimitedNetworkSystem.cs index bc3370145376..555267a73de5 100644 --- a/Content.Server/DeviceNetwork/Systems/StationLimitedNetworkSystem.cs +++ b/Content.Server/DeviceNetwork/Systems/StationLimitedNetworkSystem.cs @@ -76,9 +76,7 @@ private bool CanAccessSenderGrid(EntityUid receiver, EntityUid sender) var receiverGrid = Transform(receiver).GridUid; var senderGrid = Transform(sender).GridUid; - return receiverGrid is { } targetGrid && senderGrid is { } sourceGrid && - (_gridAccess.CanAccess(sourceGrid, targetGrid) || - _gridAccess.CanAccess(targetGrid, sourceGrid)); + return receiverGrid is { } targetGrid && senderGrid is { } sourceGrid && (_gridAccess.CanAccess(sourceGrid, targetGrid) || _gridAccess.CanAccess(targetGrid, sourceGrid)); } #endregion Starlight diff --git a/Content.Server/Shuttles/Systems/ShuttleConsoleSystem.Drone.cs b/Content.Server/Shuttles/Systems/ShuttleConsoleSystem.Drone.cs index a965822863b4..bdf1f64ff642 100644 --- a/Content.Server/Shuttles/Systems/ShuttleConsoleSystem.Drone.cs +++ b/Content.Server/Shuttles/Systems/ShuttleConsoleSystem.Drone.cs @@ -13,7 +13,7 @@ public sealed partial class ShuttleConsoleSystem #region Starlight [Dependency] private SharedGridAccessSystem _gridAccess = default!; private readonly Dictionary _remoteGridAccess = new(); - + private void OnDroneConsoleStartup(EntityUid uid, DroneConsoleComponent component, ComponentStartup args) { UpdateRemoteGridAccess(uid, component); @@ -77,13 +77,11 @@ private void UpdateRemoteGridAccess(EntityUid uid, DroneConsoleComponent compone // Starlight - start var targetConsole = GetShuttleConsole(uid, component); var sourceGrid = Transform(uid).GridUid; - var targetGrid = targetConsole is { } target - ? Transform(target).GridUid - : null; + var targetGrid = targetConsole is { } target ? Transform(target).GridUid : null; - if (_remoteGridAccess.TryGetValue(uid, out var previous) && - (sourceGrid != previous.SourceGrid || targetGrid != previous.TargetGrid || - !IsConsoleOperational(uid) || targetConsole is not { } currentTarget || !IsConsoleOperational(currentTarget))) + if (_remoteGridAccess.TryGetValue(uid, out var previous) + && (sourceGrid != previous.SourceGrid || targetGrid != previous.TargetGrid + || !IsConsoleOperational(uid) || targetConsole is not { } currentTarget || !IsConsoleOperational(currentTarget))) { RemoveRemoteGridAccess(uid); } @@ -126,10 +124,9 @@ private void RemoveRemoteGridAccess(EntityUid uid) private bool IsConsoleOperational(EntityUid uid) { // Starlight - start - return TryComp(uid, out _) && - MetaData(uid).EntityLifeStage < EntityLifeStage.Terminating && - Transform(uid).Anchored && - this.IsPowered(uid, EntityManager); + return TryComp(uid, out _) + && MetaData(uid).EntityLifeStage < EntityLifeStage.Terminating + && Transform(uid).Anchored && this.IsPowered(uid, EntityManager); // Starlight - end } #endregion Starlight From 5ac70c9035433f1a3f4ddedafa93e918d7be74b2 Mon Sep 17 00:00:00 2001 From: Floximo Date: Thu, 27 Aug 2026 18:26:17 +0200 Subject: [PATCH 04/17] Taking suggestion to remove region Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- Content.Client/Shuttles/BUI/ShuttleConsoleBoundUserInterface.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/Content.Client/Shuttles/BUI/ShuttleConsoleBoundUserInterface.cs b/Content.Client/Shuttles/BUI/ShuttleConsoleBoundUserInterface.cs index aa35f7dfe0a8..8a11618ef4d8 100644 --- a/Content.Client/Shuttles/BUI/ShuttleConsoleBoundUserInterface.cs +++ b/Content.Client/Shuttles/BUI/ShuttleConsoleBoundUserInterface.cs @@ -6,11 +6,9 @@ using Robust.Client.UserInterface; using Robust.Shared.Map; -#region Starlight using Content.Shared.Medical.CrewMonitoring; using Content.Shared.Silicons.StationAi; using Robust.Shared.Player; -#endregion Starlight namespace Content.Client.Shuttles.BUI; From 39d538864db1c034a839d9fd9bbf36ae493d8c16 Mon Sep 17 00:00:00 2001 From: Proximitron Date: Thu, 27 Aug 2026 18:39:35 +0200 Subject: [PATCH 05/17] Cleanup as required by validators --- .../BUI/ShuttleConsoleBoundUserInterface.cs | 4 --- .../Shuttles/UI/ShuttleConsoleWindow.xaml.cs | 1 - .../Systems/StationLimitedNetworkSystem.cs | 2 +- .../Systems/ShuttleConsoleSystem.Drone.cs | 3 +- .../Silicons/StationAi/StationAiSystem.cs | 33 ++++++++++++++----- .../StationAi/SharedStationAiSystem.Held.cs | 2 -- .../StationAi/SharedStationAiSystem.cs | 5 +-- .../StationAi/StationAiVisionSystem.cs | 2 +- .../_Starlight/Maps/GridAccessComponent.cs | 2 +- .../_Starlight/Maps/SharedGridAccessSystem.cs | 3 +- 10 files changed, 31 insertions(+), 26 deletions(-) diff --git a/Content.Client/Shuttles/BUI/ShuttleConsoleBoundUserInterface.cs b/Content.Client/Shuttles/BUI/ShuttleConsoleBoundUserInterface.cs index aa35f7dfe0a8..e03db60d926c 100644 --- a/Content.Client/Shuttles/BUI/ShuttleConsoleBoundUserInterface.cs +++ b/Content.Client/Shuttles/BUI/ShuttleConsoleBoundUserInterface.cs @@ -3,14 +3,10 @@ using Content.Shared.Shuttles.BUIStates; using Content.Shared.Shuttles.Events; using JetBrains.Annotations; -using Robust.Client.UserInterface; using Robust.Shared.Map; - -#region Starlight using Content.Shared.Medical.CrewMonitoring; using Content.Shared.Silicons.StationAi; using Robust.Shared.Player; -#endregion Starlight namespace Content.Client.Shuttles.BUI; diff --git a/Content.Client/Shuttles/UI/ShuttleConsoleWindow.xaml.cs b/Content.Client/Shuttles/UI/ShuttleConsoleWindow.xaml.cs index ae499c2ba3c4..c33dd0ece301 100644 --- a/Content.Client/Shuttles/UI/ShuttleConsoleWindow.xaml.cs +++ b/Content.Client/Shuttles/UI/ShuttleConsoleWindow.xaml.cs @@ -1,7 +1,6 @@ using System.Numerics; using Content.Client._Starlight.UserInterface; // Starlight using Content.Client.Computer; -using Content.Client.UserInterface.Controls; using Content.Shared.Shuttles.BUIStates; using Robust.Client.AutoGenerated; using Robust.Client.UserInterface; // Starlight diff --git a/Content.Server/DeviceNetwork/Systems/StationLimitedNetworkSystem.cs b/Content.Server/DeviceNetwork/Systems/StationLimitedNetworkSystem.cs index 555267a73de5..3a9c965a42d6 100644 --- a/Content.Server/DeviceNetwork/Systems/StationLimitedNetworkSystem.cs +++ b/Content.Server/DeviceNetwork/Systems/StationLimitedNetworkSystem.cs @@ -1,7 +1,7 @@ using Content.Server.DeviceNetwork.Components; using Content.Server.Station.Systems; using Content.Shared.DeviceNetwork.Events; -using Content.Shared.Maps; +using Content.Shared._Starlight.Maps; using JetBrains.Annotations; using Robust.Shared.Map; diff --git a/Content.Server/Shuttles/Systems/ShuttleConsoleSystem.Drone.cs b/Content.Server/Shuttles/Systems/ShuttleConsoleSystem.Drone.cs index bdf1f64ff642..6b9e3a142731 100644 --- a/Content.Server/Shuttles/Systems/ShuttleConsoleSystem.Drone.cs +++ b/Content.Server/Shuttles/Systems/ShuttleConsoleSystem.Drone.cs @@ -2,9 +2,8 @@ using Content.Server.Shuttles.Events; using Content.Shared.Station.Components; using Content.Shared.UserInterface; -using Content.Server.Power.Components; using Content.Server.Power.EntitySystems; -using Content.Shared.Maps; +using Content.Shared._Starlight.Maps; namespace Content.Server.Shuttles.Systems; diff --git a/Content.Server/Silicons/StationAi/StationAiSystem.cs b/Content.Server/Silicons/StationAi/StationAiSystem.cs index aeaaeef6f9ee..ad61b7629639 100644 --- a/Content.Server/Silicons/StationAi/StationAiSystem.cs +++ b/Content.Server/Silicons/StationAi/StationAiSystem.cs @@ -37,25 +37,17 @@ using Robust.Shared.Player; using Robust.Shared.Prototypes; using static Content.Server.Chat.Systems.ChatSystem; - -#region Starlight using Content.Server.Medical.SuitSensors; using Content.Shared.Follower.Components; using Content.Shared.Follower; using Content.Shared.Humanoid; -using Content.Shared.Intellicard; using Content.Shared.Medical.SuitSensor; using Content.Shared.Medical.SuitSensors; using Content.Shared.Mobs.Components; using Content.Shared.Warps; -using Content.Shared._Starlight.Silicons.Borgs; -using Robust.Shared.Localization; -using Robust.Shared.Log; using Robust.Shared.Map; -using System.Collections.Generic; using Content.Shared._Starlight.StationAi; using Content.Shared.Tag; -#endregion Starlight namespace Content.Server.Silicons.StationAi; @@ -227,6 +219,12 @@ private void OnStationAiWarpToTarget(StationAiWarpToTargetEvent msg, EntitySessi return; } + if (!CanAccessGrid(actor, Transform(target).GridUid)) + { + _warpSawmill.Debug($"Station AI {Name(actor)} ({actor}) attempted to warp to inaccessible target {Name(target)} ({target})."); + return; + } + if (!TryWarpEyeToEntity(actor, target)) _warpSawmill.Debug($"Station AI {Name(actor)} ({actor}) warp to {Name(target)} ({target}) rejected by TryWarpEyeToEntity."); } @@ -385,6 +383,12 @@ bool Fail() var remoteXform = Transform(remoteEye); + if (!CanAccessGrid(user, Transform(target).GridUid)) + { + StopFollowingTarget(remoteEye, target); + return Fail(); + } + if ((TryComp(target, out WarpPointComponent? warp) && warp.Follow) || HasComp(target)) { var orbit = !HasComp(user); @@ -410,6 +414,19 @@ bool Fail() return TryWarpEyeToCoordinates(user, Transform(target).Coordinates, popupOnFailure); } + private void StopFollowingTarget(EntityUid remoteEye, EntityUid target) + { + if (_activeFollowTargets.TryGetValue(target, out var follower) && follower == remoteEye) + _activeFollowTargets.Remove(target); + + if (!HasComp(remoteEye)) + return; + + var parent = Transform(remoteEye).ParentUid; + if (parent == target) + _followerSystem.StopFollowingEntity(remoteEye, target); + } + private void OnSuitSensorModeChanged(Entity ent, ref SuitSensorModeChangedEvent args) { if (args.Mode == SuitSensorMode.SensorCords) diff --git a/Content.Shared/Silicons/StationAi/SharedStationAiSystem.Held.cs b/Content.Shared/Silicons/StationAi/SharedStationAiSystem.Held.cs index 49e64c451d3a..c5e3096577f8 100644 --- a/Content.Shared/Silicons/StationAi/SharedStationAiSystem.Held.cs +++ b/Content.Shared/Silicons/StationAi/SharedStationAiSystem.Held.cs @@ -6,9 +6,7 @@ using Robust.Shared.Serialization; using Robust.Shared.Utility; using System.Diagnostics.CodeAnalysis; -#region Starlight using Content.Shared._Starlight.StationAi; -#endregion namespace Content.Shared.Silicons.StationAi; diff --git a/Content.Shared/Silicons/StationAi/SharedStationAiSystem.cs b/Content.Shared/Silicons/StationAi/SharedStationAiSystem.cs index adaebbf17c22..c7470fef7b3f 100644 --- a/Content.Shared/Silicons/StationAi/SharedStationAiSystem.cs +++ b/Content.Shared/Silicons/StationAi/SharedStationAiSystem.cs @@ -34,8 +34,6 @@ using Robust.Shared.Serialization; using Robust.Shared.Timing; using Robust.Shared.Utility; - -#region Starlight using Content.Shared._Starlight.Silicons.Borgs; using Content.Shared.Silicons.Borgs.Components; using Content.Shared._Starlight.TextToSpeech; @@ -45,8 +43,7 @@ using Content.Shared.DeviceLinking; using Content.Shared._Starlight; using Content.Shared.NameModifier.EntitySystems; -using Content.Shared.Maps; -#endregion Starlight +using Content.Shared._Starlight.Maps; namespace Content.Shared.Silicons.StationAi; diff --git a/Content.Shared/Silicons/StationAi/StationAiVisionSystem.cs b/Content.Shared/Silicons/StationAi/StationAiVisionSystem.cs index 40357680f2c8..bdba70cb8eaf 100644 --- a/Content.Shared/Silicons/StationAi/StationAiVisionSystem.cs +++ b/Content.Shared/Silicons/StationAi/StationAiVisionSystem.cs @@ -1,6 +1,6 @@ using Content.Shared.Power.EntitySystems; using Content.Shared.StationAi; -using Content.Shared.Maps; +using Content.Shared._Starlight.Maps; using Robust.Shared.Map.Components; using Robust.Shared.Physics; using Robust.Shared.Threading; diff --git a/Content.Shared/_Starlight/Maps/GridAccessComponent.cs b/Content.Shared/_Starlight/Maps/GridAccessComponent.cs index 6900609e3e81..152be961ca28 100644 --- a/Content.Shared/_Starlight/Maps/GridAccessComponent.cs +++ b/Content.Shared/_Starlight/Maps/GridAccessComponent.cs @@ -1,6 +1,6 @@ using Robust.Shared.GameStates; -namespace Content.Shared.Maps; +namespace Content.Shared._Starlight.Maps; /// /// Describes which grids can be accessed from this grid. diff --git a/Content.Shared/_Starlight/Maps/SharedGridAccessSystem.cs b/Content.Shared/_Starlight/Maps/SharedGridAccessSystem.cs index 048742eb0705..75f8e79b88c8 100644 --- a/Content.Shared/_Starlight/Maps/SharedGridAccessSystem.cs +++ b/Content.Shared/_Starlight/Maps/SharedGridAccessSystem.cs @@ -1,7 +1,6 @@ -using Robust.Shared.Map; using Robust.Shared.Map.Components; -namespace Content.Shared.Maps; +namespace Content.Shared._Starlight.Maps; /// /// Manages access from one map grid to other map grids. From 58f535ee48e75573918042f1246ed4566a6bb424 Mon Sep 17 00:00:00 2001 From: Proximitron Date: Thu, 27 Aug 2026 19:08:23 +0200 Subject: [PATCH 06/17] Cleanup to make very sure we don't accept only specific uid's of the right type --- .../Systems/StationLimitedNetworkSystem.cs | 2 +- Content.Server/Holopad/HolopadSystem.cs | 4 +-- .../Systems/ShuttleConsoleSystem.Drone.cs | 8 ++--- .../Silicons/StationAi/StationAiSystem.cs | 10 +++--- .../StationAi/SharedStationAiSystem.Held.cs | 2 +- .../StationAi/SharedStationAiSystem.cs | 12 ++++--- .../StationAi/StationAiVisionSystem.cs | 2 +- .../_Starlight/Maps/SharedGridAccessSystem.cs | 36 ++++++++++++------- 8 files changed, 44 insertions(+), 32 deletions(-) diff --git a/Content.Server/DeviceNetwork/Systems/StationLimitedNetworkSystem.cs b/Content.Server/DeviceNetwork/Systems/StationLimitedNetworkSystem.cs index 3a9c965a42d6..f39560dbc7dd 100644 --- a/Content.Server/DeviceNetwork/Systems/StationLimitedNetworkSystem.cs +++ b/Content.Server/DeviceNetwork/Systems/StationLimitedNetworkSystem.cs @@ -76,7 +76,7 @@ private bool CanAccessSenderGrid(EntityUid receiver, EntityUid sender) var receiverGrid = Transform(receiver).GridUid; var senderGrid = Transform(sender).GridUid; - return receiverGrid is { } targetGrid && senderGrid is { } sourceGrid && (_gridAccess.CanAccess(sourceGrid, targetGrid) || _gridAccess.CanAccess(targetGrid, sourceGrid)); + return receiverGrid is { } targetGrid && senderGrid is { } sourceGrid && (_gridAccess.CanAccess((sourceGrid, null), (targetGrid, null)) || _gridAccess.CanAccess((targetGrid, null), (sourceGrid, null))); } #endregion Starlight diff --git a/Content.Server/Holopad/HolopadSystem.cs b/Content.Server/Holopad/HolopadSystem.cs index c9225badc376..ac7113cb29e8 100644 --- a/Content.Server/Holopad/HolopadSystem.cs +++ b/Content.Server/Holopad/HolopadSystem.cs @@ -107,7 +107,7 @@ private void OnHolopadStartNewCall(Entity source, ref HolopadS // Starlight - start if (HasComp(args.Actor) && - !_stationAiSystem.CanAccessGrid(args.Actor, Transform(receiver).GridUid)) + !_stationAiSystem.CanAccessGrid((args.Actor, null), Transform(receiver).GridUid)) return; // Starlight - end LinkHolopadToUser(source, args.Actor); @@ -671,7 +671,7 @@ private void ActivateProjector(Entity entity, EntityUid user) // Starlight - start // We check if the AI has grid access. Normal projector call are range limited, not limited by grid access. The AI is special. - if (!_stationAiSystem.CanAccessGrid(user, Transform(entity).GridUid)) + if (!_stationAiSystem.CanAccessGrid((user, userAiHeld), Transform(entity).GridUid)) { _popupSystem.PopupEntity(Loc.GetString("holopad-ai-is-unable-to-activate-projector"), receiver, user); return; diff --git a/Content.Server/Shuttles/Systems/ShuttleConsoleSystem.Drone.cs b/Content.Server/Shuttles/Systems/ShuttleConsoleSystem.Drone.cs index 6b9e3a142731..cd3124afa7c0 100644 --- a/Content.Server/Shuttles/Systems/ShuttleConsoleSystem.Drone.cs +++ b/Content.Server/Shuttles/Systems/ShuttleConsoleSystem.Drone.cs @@ -97,7 +97,7 @@ targetConsole is not { } console || if (_remoteGridAccess.ContainsKey(uid)) return; - _gridAccess.AddAccessibleGrid(source, targetUid); + _gridAccess.AddAccessibleGrid((source, null), (targetUid, null)); _remoteGridAccess[uid] = (source, targetUid); // Starlight - end } @@ -116,16 +116,14 @@ private void RemoveRemoteGridAccess(EntityUid uid) return; } - _gridAccess.RemoveAccessibleGrid(access.SourceGrid, access.TargetGrid); + _gridAccess.RemoveAccessibleGrid((access.SourceGrid, null), (access.TargetGrid, null)); // Starlight - end } private bool IsConsoleOperational(EntityUid uid) { // Starlight - start - return TryComp(uid, out _) - && MetaData(uid).EntityLifeStage < EntityLifeStage.Terminating - && Transform(uid).Anchored && this.IsPowered(uid, EntityManager); + return TryComp(uid, out _) && MetaData(uid).EntityLifeStage < EntityLifeStage.Terminating && Transform(uid).Anchored && this.IsPowered(uid, EntityManager); // Starlight - end } #endregion Starlight diff --git a/Content.Server/Silicons/StationAi/StationAiSystem.cs b/Content.Server/Silicons/StationAi/StationAiSystem.cs index ad61b7629639..3d828f39a50c 100644 --- a/Content.Server/Silicons/StationAi/StationAiSystem.cs +++ b/Content.Server/Silicons/StationAi/StationAiSystem.cs @@ -219,7 +219,7 @@ private void OnStationAiWarpToTarget(StationAiWarpToTargetEvent msg, EntitySessi return; } - if (!CanAccessGrid(actor, Transform(target).GridUid)) + if (!CanAccessGrid((actor, null), Transform(target).GridUid)) { _warpSawmill.Debug($"Station AI {Name(actor)} ({actor}) attempted to warp to inaccessible target {Name(target)} ({target})."); return; @@ -257,7 +257,7 @@ private void CollectCrewWarpTargets(EntityUid actor, List b continue; // Starlight - start - if (!CanAccessGrid(actor, Transform(ownerUid).GridUid)) + if (!CanAccessGrid((actor, null), Transform(ownerUid).GridUid)) continue; // Starlight - end @@ -294,7 +294,7 @@ private void CollectLocationWarpTargets(EntityUid actor, EntityUid? remoteEntity // Starlight End // Starlight - start - if (!CanAccessGrid(actor, Transform(uid).GridUid)) + if (!CanAccessGrid((actor, null), Transform(uid).GridUid)) { _warpSawmill.Debug($"Skipping warp point {Name(uid)} ({uid}) outside AI grid access list."); continue; @@ -345,7 +345,7 @@ bool Fail() return Fail(); // Starlight - start - if (!CanAccessGrid(user, gridUid)) + if (!CanAccessGrid((user, null), gridUid)) return Fail(); // Starlight - end @@ -383,7 +383,7 @@ bool Fail() var remoteXform = Transform(remoteEye); - if (!CanAccessGrid(user, Transform(target).GridUid)) + if (!CanAccessGrid((user, null), Transform(target).GridUid)) { StopFollowingTarget(remoteEye, target); return Fail(); diff --git a/Content.Shared/Silicons/StationAi/SharedStationAiSystem.Held.cs b/Content.Shared/Silicons/StationAi/SharedStationAiSystem.Held.cs index c5e3096577f8..662de9c69503 100644 --- a/Content.Shared/Silicons/StationAi/SharedStationAiSystem.Held.cs +++ b/Content.Shared/Silicons/StationAi/SharedStationAiSystem.Held.cs @@ -187,7 +187,7 @@ private void OnTargetVerbs(Entity ent, ref GetVerbs } // Starlight - start - if (!CanAccessGrid(args.User, Transform(args.Target).GridUid) || + if (!CanAccessGrid((args.User, null), Transform(args.Target).GridUid) || _vision.IsOutsideCameraViewCached(args.Target)) return; // Starlight - end diff --git a/Content.Shared/Silicons/StationAi/SharedStationAiSystem.cs b/Content.Shared/Silicons/StationAi/SharedStationAiSystem.cs index c7470fef7b3f..bd7df1723877 100644 --- a/Content.Shared/Silicons/StationAi/SharedStationAiSystem.cs +++ b/Content.Shared/Silicons/StationAi/SharedStationAiSystem.cs @@ -198,16 +198,18 @@ private void OnAiAccessible(Entity ent, ref Accessibl /// /// Returns whether the grid containing the AI core can access the target grid. /// - public bool CanAccessGrid(EntityUid user, EntityUid? targetGrid) + public bool CanAccessGrid(Entity user, EntityUid? targetGrid) { + Resolve(user, ref user.Comp); + if (targetGrid is not { } target || !HasComp(target)) return false; - if (!TryGetCore(user, out var core) || core.Comp is null) + if (user.Comp is null || !TryGetCore(user.Owner, out var core) || core.Comp is null) return false; var sourceGrid = Transform(core.Owner).GridUid; - return sourceGrid is { } source && _gridAccess.CanAccess(source, target); + return sourceGrid is { } source && _gridAccess.CanAccess((source, null), (target, null)); } #endregion @@ -228,7 +230,7 @@ private void OnAiBuiCheck(Entity ent, ref BoundUser var targetXform = Transform(args.Target); // Starlight - start - if (!CanAccessGrid(args.Actor, targetXform.GridUid)) + if (!CanAccessGrid((args.Actor, null), targetXform.GridUid)) { return; } @@ -270,7 +272,7 @@ private void OnAiInRange(Entity ent, ref InRangeOverr if (HasComp(args.User)) { // Starlight - start - if (!CanAccessGrid(args.User, targetXform.GridUid)) + if (!CanAccessGrid((args.User, null), targetXform.GridUid)) return; // Starlight - end } diff --git a/Content.Shared/Silicons/StationAi/StationAiVisionSystem.cs b/Content.Shared/Silicons/StationAi/StationAiVisionSystem.cs index bdba70cb8eaf..f4fd2dc51515 100644 --- a/Content.Shared/Silicons/StationAi/StationAiVisionSystem.cs +++ b/Content.Shared/Silicons/StationAi/StationAiVisionSystem.cs @@ -296,7 +296,7 @@ public void GetView(Entity grid, Box2Rota // Starlight - start // Ensure we only render for grids we have access to if (sourceGrid is { } source && Transform(seed.Owner).GridUid is { } seedGrid && - !_gridAccess.CanAccess(source, seedGrid)) + !_gridAccess.CanAccess((source, null), (seedGrid, null))) { continue; } diff --git a/Content.Shared/_Starlight/Maps/SharedGridAccessSystem.cs b/Content.Shared/_Starlight/Maps/SharedGridAccessSystem.cs index 75f8e79b88c8..c042cf55ed5c 100644 --- a/Content.Shared/_Starlight/Maps/SharedGridAccessSystem.cs +++ b/Content.Shared/_Starlight/Maps/SharedGridAccessSystem.cs @@ -16,38 +16,50 @@ public override void Initialize() /// /// Returns whether can be accessed from . /// - public bool CanAccess(EntityUid sourceGrid, EntityUid targetGrid) => - TryComp(sourceGrid, out var access) && - access.AccessibleGrids.Contains(targetGrid); + public bool CanAccess(Entity sourceGrid, Entity targetGrid) + { + Resolve(sourceGrid, ref sourceGrid.Comp); + Resolve(targetGrid, ref targetGrid.Comp); + + return TryComp(sourceGrid.Owner, out var access) && + access.AccessibleGrids.Contains(targetGrid.Owner); + } /// /// Adds a grid to the access list of another grid. /// - public bool AddAccessibleGrid(EntityUid sourceGrid, EntityUid targetGrid) + public bool AddAccessibleGrid(Entity sourceGrid, Entity targetGrid) { - if (!HasComp(sourceGrid) || !HasComp(targetGrid)) + Resolve(sourceGrid, ref sourceGrid.Comp); + Resolve(targetGrid, ref targetGrid.Comp); + + if (sourceGrid.Comp is null || targetGrid.Comp is null) return false; - var access = EnsureComp(sourceGrid); - if (!access.AccessibleGrids.Add(targetGrid)) + var access = EnsureComp(sourceGrid.Owner); + if (!access.AccessibleGrids.Add(targetGrid.Owner)) return false; - Dirty(sourceGrid, access); + Dirty(sourceGrid.Owner, access); return true; } /// /// Removes a grid from the access list of another grid. A grid always retains access to itself. /// - public bool RemoveAccessibleGrid(EntityUid sourceGrid, EntityUid targetGrid) + public bool RemoveAccessibleGrid(Entity sourceGrid, Entity targetGrid) { - if (sourceGrid == targetGrid || !TryComp(sourceGrid, out var access)) + Resolve(sourceGrid, ref sourceGrid.Comp); + Resolve(targetGrid, ref targetGrid.Comp); + + if (sourceGrid.Owner == targetGrid.Owner || sourceGrid.Comp is null || targetGrid.Comp is null || + !TryComp(sourceGrid.Owner, out var access)) return false; - if (!access.AccessibleGrids.Remove(targetGrid)) + if (!access.AccessibleGrids.Remove(targetGrid.Owner)) return false; - Dirty(sourceGrid, access); + Dirty(sourceGrid.Owner, access); return true; } From 527b2b32fce9e984f2a89bf57e14077d6b06ffaf Mon Sep 17 00:00:00 2001 From: Proximitron Date: Thu, 27 Aug 2026 19:20:51 +0200 Subject: [PATCH 07/17] Making EditorConfig check happy by putting that on a single line --- Content.Shared/_Starlight/Maps/SharedGridAccessSystem.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Content.Shared/_Starlight/Maps/SharedGridAccessSystem.cs b/Content.Shared/_Starlight/Maps/SharedGridAccessSystem.cs index c042cf55ed5c..b956429b9e1c 100644 --- a/Content.Shared/_Starlight/Maps/SharedGridAccessSystem.cs +++ b/Content.Shared/_Starlight/Maps/SharedGridAccessSystem.cs @@ -21,8 +21,7 @@ public bool CanAccess(Entity sourceGrid, Entity(sourceGrid.Owner, out var access) && - access.AccessibleGrids.Contains(targetGrid.Owner); + return TryComp(sourceGrid.Owner, out var access) && access.AccessibleGrids.Contains(targetGrid.Owner); } /// From 205bb78a1b4aaeabfcf658bc25bd00ad6d210e77 Mon Sep 17 00:00:00 2001 From: Proximitron Date: Thu, 27 Aug 2026 19:50:38 +0200 Subject: [PATCH 08/17] Comments and cleaner deauthorization (i don't believe it is nessesary, but now i have to test again) --- .../Shuttles/Systems/ShuttleConsoleSystem.Drone.cs | 3 +++ Content.Server/Silicons/StationAi/StationAiSystem.cs | 8 ++++++++ 2 files changed, 11 insertions(+) diff --git a/Content.Server/Shuttles/Systems/ShuttleConsoleSystem.Drone.cs b/Content.Server/Shuttles/Systems/ShuttleConsoleSystem.Drone.cs index cd3124afa7c0..be1d90a6d8a2 100644 --- a/Content.Server/Shuttles/Systems/ShuttleConsoleSystem.Drone.cs +++ b/Content.Server/Shuttles/Systems/ShuttleConsoleSystem.Drone.cs @@ -59,7 +59,10 @@ private void OnDronePilotConsoleClose(EntityUid uid, DroneConsoleComponent compo { // Only if last person closed UI. if (!_ui.IsUiOpen(uid, args.UiKey)) + { component.Entity = null; + _remoteGridAccess.Remove(uid); // We only remove the access to the remote grid, not changing grid access + } } private void OnCargoGetConsole(EntityUid uid, DroneConsoleComponent component, ref ConsoleShuttleEvent args) diff --git a/Content.Server/Silicons/StationAi/StationAiSystem.cs b/Content.Server/Silicons/StationAi/StationAiSystem.cs index 3d828f39a50c..7536458547f9 100644 --- a/Content.Server/Silicons/StationAi/StationAiSystem.cs +++ b/Content.Server/Silicons/StationAi/StationAiSystem.cs @@ -306,6 +306,10 @@ private void CollectLocationWarpTargets(EntityUid actor, EntityUid? remoteEntity } } + /// + /// Attempts to warp the AI's remote eye to the specified coordinates. + /// The AI must have grid access to the grid containing the coordinates; returns false when access is denied. + /// public bool TryWarpEyeToCoordinates(EntityUid user, EntityCoordinates coordinates, bool popupOnFailure = true) { bool Fail() @@ -359,6 +363,10 @@ bool Fail() return true; } + /// + /// Attempts to warp the AI's remote eye to the specified entity. + /// The AI must have grid access to the grid containing the entity; returns false when access is denied. + /// public bool TryWarpEyeToEntity(EntityUid user, EntityUid target, bool popupOnFailure = true) { bool Fail() From 726be64c60fc26e1747935a972c91663296f0cbb Mon Sep 17 00:00:00 2001 From: Proximitron Date: Sun, 30 Aug 2026 21:48:45 +0200 Subject: [PATCH 09/17] Same code, tested again, as partials. --- Content.Client/Content.Client.csproj | 1 + .../BUI/ShuttleConsoleBoundUserInterface.cs | 16 ++++--------- Content.Client/Shuttles/UI/NavScreen.xaml.cs | 16 +++---------- .../Shuttles/UI/ShuttleConsoleWindow.xaml.cs | 24 +++++++------------ .../_Starlight/Shuttles/UI/NavScreen.cs | 18 ++++++++++++++ .../Shuttles/UI/ShuttleConsoleWindow.cs | 18 ++++++++++++++ .../Systems/StationLimitedNetworkSystem.cs | 14 ----------- .../Systems/StationLimitedNetworkSystem.cs | 19 +++++++++++++++ .../StationAi/SharedStationAiSystem.cs | 23 ------------------ .../SharedStationAiSystem.GridAccess.cs | 23 ++++++++++++++++++ 10 files changed, 95 insertions(+), 77 deletions(-) create mode 100644 Content.Client/_Starlight/Shuttles/UI/NavScreen.cs create mode 100644 Content.Client/_Starlight/Shuttles/UI/ShuttleConsoleWindow.cs create mode 100644 Content.Server/_Starlight/DeviceNetwork/Systems/StationLimitedNetworkSystem.cs create mode 100644 Content.Shared/_Starlight/Silicons/StationAi/SharedStationAiSystem.GridAccess.cs diff --git a/Content.Client/Content.Client.csproj b/Content.Client/Content.Client.csproj index 5d4759867cb1..3dc700f8ae2e 100644 --- a/Content.Client/Content.Client.csproj +++ b/Content.Client/Content.Client.csproj @@ -27,6 +27,7 @@ + diff --git a/Content.Client/Shuttles/BUI/ShuttleConsoleBoundUserInterface.cs b/Content.Client/Shuttles/BUI/ShuttleConsoleBoundUserInterface.cs index e03db60d926c..ede70aceaa76 100644 --- a/Content.Client/Shuttles/BUI/ShuttleConsoleBoundUserInterface.cs +++ b/Content.Client/Shuttles/BUI/ShuttleConsoleBoundUserInterface.cs @@ -1,5 +1,5 @@ -using Content.Client._Starlight.UserInterface; // Starlight using Content.Client.Shuttles.UI; +using Content.Client._Starlight.UserInterface; using Content.Shared.Shuttles.BUIStates; using Content.Shared.Shuttles.Events; using JetBrains.Annotations; @@ -13,28 +13,26 @@ namespace Content.Client.Shuttles.BUI; [UsedImplicitly] public sealed class ShuttleConsoleBoundUserInterface : BoundUserInterface { - #region Starlight [Dependency] private ISharedPlayerManager _playerManager = default!; - #endregion Starlight [ViewVariables] private ShuttleConsoleWindow? _window; public ShuttleConsoleBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey) { - IoCManager.InjectDependencies(this); // Starlight + IoCManager.InjectDependencies(this); } protected override void Open() { base.Open(); - _window = this.CreatePopOutableWindow(EntMan); // Starlight: popout support + _window = this.CreatePopOutableWindow(EntMan); + _window.RadarClicked += OnRadarClicked; _window.RequestFTL += OnFTLRequest; _window.RequestBeaconFTL += OnFTLBeaconRequest; _window.DockRequest += OnDockRequest; _window.UndockRequest += OnUndockRequest; - _window.RadarClicked += OnRadarClicked; // Starlight } private void OnUndockRequest(NetEntity entity) @@ -78,15 +76,12 @@ protected override void Dispose(bool disposing) if (disposing) { - // Starlight - start if (_window != null) _window.RadarClicked -= OnRadarClicked; - // Starlight - end - _window?.DisposePopOut(); // Starlight: close the popout if exists + _window?.DisposePopOut(); } } - #region Starlight private void OnRadarClicked(EntityCoordinates coordinates) { var local = _playerManager.LocalEntity; @@ -95,7 +90,6 @@ private void OnRadarClicked(EntityCoordinates coordinates) SendMessage(new CrewMonitoringWarpRequestMessage(EntMan.GetNetCoordinates(coordinates))); } - #endregion Starlight protected override void UpdateState(BoundUserInterfaceState state) { diff --git a/Content.Client/Shuttles/UI/NavScreen.xaml.cs b/Content.Client/Shuttles/UI/NavScreen.xaml.cs index 28debf8f08d7..9e455fb04f5c 100644 --- a/Content.Client/Shuttles/UI/NavScreen.xaml.cs +++ b/Content.Client/Shuttles/UI/NavScreen.xaml.cs @@ -19,9 +19,7 @@ public sealed partial class NavScreen : BoxContainer private EntityUid? _consoleEntity; // Entity of controlling console private EntityUid? _shuttleEntity; - #region Starlight - public event Action? OnRadarClick; - #endregion Starlight + partial void InitializeStarlight(); // Starlight public NavScreen() { @@ -35,9 +33,8 @@ public NavScreen() DockToggle.OnToggled += OnDockTogglePressed; DockToggle.Pressed = NavRadar.ShowDocks; - // Starlight - start - NavRadar.OnRadarClick += OnRadarClickPressed; - // Starlight - end + InitializeStarlight(); // Starlight + } public void SetShuttle(EntityUid? shuttle) @@ -63,13 +60,6 @@ private void OnDockTogglePressed(BaseButton.ButtonEventArgs args) args.Button.Pressed = NavRadar.ShowDocks; } - #region Starlight - private void OnRadarClickPressed(EntityCoordinates coordinates) - { - OnRadarClick?.Invoke(coordinates); - } - #endregion - public void UpdateState(NavInterfaceState scc, DockingPortStates dockingPortStates) // Starlight: +dockingPortStates { NavRadar.UpdateState(scc, dockingPortStates); // Starlight: +dockingPortStates diff --git a/Content.Client/Shuttles/UI/ShuttleConsoleWindow.xaml.cs b/Content.Client/Shuttles/UI/ShuttleConsoleWindow.xaml.cs index c33dd0ece301..630c7d6eb1f7 100644 --- a/Content.Client/Shuttles/UI/ShuttleConsoleWindow.xaml.cs +++ b/Content.Client/Shuttles/UI/ShuttleConsoleWindow.xaml.cs @@ -1,9 +1,10 @@ using System.Numerics; -using Content.Client._Starlight.UserInterface; // Starlight +using Content.Client._Starlight.UserInterface; using Content.Client.Computer; +using Content.Shared._Starlight.Shuttles.BUIStates; using Content.Shared.Shuttles.BUIStates; using Robust.Client.AutoGenerated; -using Robust.Client.UserInterface; // Starlight +using Robust.Client.UserInterface; using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.XAML; using Robust.Shared.Map; @@ -11,12 +12,14 @@ namespace Content.Client.Shuttles.UI; [GenerateTypedNameReferences] -public sealed partial class ShuttleConsoleWindow : PopOutFancyWindow, // Starlight: popout support +public sealed partial class ShuttleConsoleWindow : PopOutFancyWindow, IComputerWindow { [Dependency] private IEntityManager _entManager = default!; - protected override Control Control => RootContainer; // Starlight: popout support + protected override Control Control => RootContainer; + + partial void InitializeStarlight(); // Starlight private ShuttleConsoleMode _mode = ShuttleConsoleMode.Nav; @@ -26,10 +29,6 @@ public sealed partial class ShuttleConsoleWindow : PopOutFancyWindow, // Starlig public event Action? DockRequest; public event Action? UndockRequest; - #region Starlight - public event Action? RadarClicked; - #endregion Starlight - public ShuttleConsoleWindow() { RobustXamlLoader.Load(this); @@ -50,7 +49,7 @@ public ShuttleConsoleWindow() NavModeButton.Pressed = true; SetupMode(_mode); - NavContainer.OnRadarClick += OnRadarClick; // Starlight + InitializeStarlight(); // Starlight MapContainer.RequestFTL += (coords, angle) => { @@ -73,13 +72,6 @@ public ShuttleConsoleWindow() }; } - #region Starlight - private void OnRadarClick(EntityCoordinates coordinates) - { - RadarClicked?.Invoke(coordinates); - } - #endregion - private void ClearModes(ShuttleConsoleMode mode) { if (mode != ShuttleConsoleMode.Nav) diff --git a/Content.Client/_Starlight/Shuttles/UI/NavScreen.cs b/Content.Client/_Starlight/Shuttles/UI/NavScreen.cs new file mode 100644 index 000000000000..8609b7a5cd21 --- /dev/null +++ b/Content.Client/_Starlight/Shuttles/UI/NavScreen.cs @@ -0,0 +1,18 @@ +using Robust.Shared.Map; + +namespace Content.Client.Shuttles.UI; + +public sealed partial class NavScreen +{ + public event Action? OnRadarClick; + + partial void InitializeStarlight() + { + NavRadar.OnRadarClick += OnRadarClickPressed; + } + + private void OnRadarClickPressed(EntityCoordinates coordinates) + { + OnRadarClick?.Invoke(coordinates); + } +} diff --git a/Content.Client/_Starlight/Shuttles/UI/ShuttleConsoleWindow.cs b/Content.Client/_Starlight/Shuttles/UI/ShuttleConsoleWindow.cs new file mode 100644 index 000000000000..49cf94b37de5 --- /dev/null +++ b/Content.Client/_Starlight/Shuttles/UI/ShuttleConsoleWindow.cs @@ -0,0 +1,18 @@ +using Robust.Shared.Map; + +namespace Content.Client.Shuttles.UI; + +public sealed partial class ShuttleConsoleWindow +{ + public event Action? RadarClicked; + + partial void InitializeStarlight() + { + NavContainer.OnRadarClick += OnRadarClick; + } + + private void OnRadarClick(EntityCoordinates coordinates) + { + RadarClicked?.Invoke(coordinates); + } +} diff --git a/Content.Server/DeviceNetwork/Systems/StationLimitedNetworkSystem.cs b/Content.Server/DeviceNetwork/Systems/StationLimitedNetworkSystem.cs index f39560dbc7dd..2857e24ab1ea 100644 --- a/Content.Server/DeviceNetwork/Systems/StationLimitedNetworkSystem.cs +++ b/Content.Server/DeviceNetwork/Systems/StationLimitedNetworkSystem.cs @@ -1,7 +1,6 @@ using Content.Server.DeviceNetwork.Components; using Content.Server.Station.Systems; using Content.Shared.DeviceNetwork.Events; -using Content.Shared._Starlight.Maps; using JetBrains.Annotations; using Robust.Shared.Map; @@ -14,9 +13,6 @@ namespace Content.Server.DeviceNetwork.Systems public sealed partial class StationLimitedNetworkSystem : EntitySystem { [Dependency] private StationSystem _stationSystem = default!; - #region Starlight - [Dependency] private SharedGridAccessSystem _gridAccess = default!; - #endregion public override void Initialize() { base.Initialize(); @@ -70,16 +66,6 @@ private void OnBeforePacketSent(EntityUid uid, StationLimitedNetworkComponent co } } - #region Starlight - private bool CanAccessSenderGrid(EntityUid receiver, EntityUid sender) - { - var receiverGrid = Transform(receiver).GridUid; - var senderGrid = Transform(sender).GridUid; - - return receiverGrid is { } targetGrid && senderGrid is { } sourceGrid && (_gridAccess.CanAccess((sourceGrid, null), (targetGrid, null)) || _gridAccess.CanAccess((targetGrid, null), (sourceGrid, null))); - } - #endregion Starlight - /// /// Compares the station IDs of the sending and receiving network components. /// Returns false if either of them doesn't have a station ID or if their station ID isn't equal. diff --git a/Content.Server/_Starlight/DeviceNetwork/Systems/StationLimitedNetworkSystem.cs b/Content.Server/_Starlight/DeviceNetwork/Systems/StationLimitedNetworkSystem.cs new file mode 100644 index 000000000000..0a83f9337e1c --- /dev/null +++ b/Content.Server/_Starlight/DeviceNetwork/Systems/StationLimitedNetworkSystem.cs @@ -0,0 +1,19 @@ +using Content.Shared._Starlight.Maps; +using Robust.Shared.Map; + +namespace Content.Server.DeviceNetwork.Systems; + +public sealed partial class StationLimitedNetworkSystem +{ + [Dependency] private SharedGridAccessSystem _gridAccess = default!; + + private bool CanAccessSenderGrid(EntityUid receiver, EntityUid sender) + { + var receiverGrid = Transform(receiver).GridUid; + var senderGrid = Transform(sender).GridUid; + + return receiverGrid is { } targetGrid && senderGrid is { } sourceGrid && + (_gridAccess.CanAccess((sourceGrid, null), (targetGrid, null)) || + _gridAccess.CanAccess((targetGrid, null), (sourceGrid, null))); + } +} diff --git a/Content.Shared/Silicons/StationAi/SharedStationAiSystem.cs b/Content.Shared/Silicons/StationAi/SharedStationAiSystem.cs index bd7df1723877..358da236ff17 100644 --- a/Content.Shared/Silicons/StationAi/SharedStationAiSystem.cs +++ b/Content.Shared/Silicons/StationAi/SharedStationAiSystem.cs @@ -43,7 +43,6 @@ using Content.Shared.DeviceLinking; using Content.Shared._Starlight; using Content.Shared.NameModifier.EntitySystems; -using Content.Shared._Starlight.Maps; namespace Content.Shared.Silicons.StationAi; @@ -73,9 +72,6 @@ public abstract partial class SharedStationAiSystem : EntitySystem [Dependency] private SharedTransformSystem _xforms = default!; [Dependency] private SharedUserInterfaceSystem _uiSystem = default!; [Dependency] private StationAiVisionSystem _vision = default!; - #region Starlight - [Dependency] private SharedGridAccessSystem _gridAccess = default!; - #endregion Starlight [Dependency] private IPrototypeManager _protoManager = default!; [Dependency] private MobStateSystem _mobState = default!; [Dependency] private SharedDeviceLinkSystem _deviceLinkSystem = default!; // Starlight @@ -194,25 +190,6 @@ private void OnAiAccessible(Entity ent, ref Accessibl args.Accessible = true; } - #region Starlight - /// - /// Returns whether the grid containing the AI core can access the target grid. - /// - public bool CanAccessGrid(Entity user, EntityUid? targetGrid) - { - Resolve(user, ref user.Comp); - - if (targetGrid is not { } target || !HasComp(target)) - return false; - - if (user.Comp is null || !TryGetCore(user.Owner, out var core) || core.Comp is null) - return false; - - var sourceGrid = Transform(core.Owner).GridUid; - return sourceGrid is { } source && _gridAccess.CanAccess((source, null), (target, null)); - } - #endregion - private void OnAiMenu(Entity ent, ref MenuVisibilityEvent args) { args.Visibility &= ~MenuVisibility.NoFov; diff --git a/Content.Shared/_Starlight/Silicons/StationAi/SharedStationAiSystem.GridAccess.cs b/Content.Shared/_Starlight/Silicons/StationAi/SharedStationAiSystem.GridAccess.cs new file mode 100644 index 000000000000..3494692ce14a --- /dev/null +++ b/Content.Shared/_Starlight/Silicons/StationAi/SharedStationAiSystem.GridAccess.cs @@ -0,0 +1,23 @@ +using Content.Shared._Starlight.Maps; +using Robust.Shared.Map.Components; + +namespace Content.Shared.Silicons.StationAi; + +public abstract partial class SharedStationAiSystem +{ + [Dependency] private SharedGridAccessSystem _gridAccess = default!; + + public bool CanAccessGrid(Entity user, EntityUid? targetGrid) + { + Resolve(user, ref user.Comp); + + if (targetGrid is not { } target || !HasComp(target)) + return false; + + if (user.Comp is null || !TryGetCore(user.Owner, out var core) || core.Comp is null) + return false; + + var sourceGrid = Transform(core.Owner).GridUid; + return sourceGrid is { } source && _gridAccess.CanAccess((source, null), (target, null)); + } +} From 77c1774a6ba34adf2a2bc9dfd3dbfd501dba876b Mon Sep 17 00:00:00 2001 From: Proximitron Date: Sun, 30 Aug 2026 21:57:44 +0200 Subject: [PATCH 10/17] // ReSharper disable CheckNamespace --- .../Shuttles/BUI/ShuttleConsoleBoundUserInterface.cs | 1 + Content.Client/Shuttles/UI/NavScreen.xaml.cs | 1 + Content.Client/Shuttles/UI/ShuttleConsoleWindow.xaml.cs | 1 + Content.Client/_Starlight/Shuttles/UI/NavScreen.cs | 2 ++ .../_Starlight/Shuttles/UI/ShuttleConsoleWindow.cs | 2 ++ .../DeviceNetwork/Systems/StationLimitedNetworkSystem.cs | 5 ++--- .../Silicons/StationAi/SharedStationAiSystem.GridAccess.cs | 2 ++ 7 files changed, 11 insertions(+), 3 deletions(-) diff --git a/Content.Client/Shuttles/BUI/ShuttleConsoleBoundUserInterface.cs b/Content.Client/Shuttles/BUI/ShuttleConsoleBoundUserInterface.cs index ede70aceaa76..98a725316845 100644 --- a/Content.Client/Shuttles/BUI/ShuttleConsoleBoundUserInterface.cs +++ b/Content.Client/Shuttles/BUI/ShuttleConsoleBoundUserInterface.cs @@ -1,3 +1,4 @@ +// ReSharper disable CheckNamespace using Content.Client.Shuttles.UI; using Content.Client._Starlight.UserInterface; using Content.Shared.Shuttles.BUIStates; diff --git a/Content.Client/Shuttles/UI/NavScreen.xaml.cs b/Content.Client/Shuttles/UI/NavScreen.xaml.cs index 9e455fb04f5c..95bd050b467a 100644 --- a/Content.Client/Shuttles/UI/NavScreen.xaml.cs +++ b/Content.Client/Shuttles/UI/NavScreen.xaml.cs @@ -1,3 +1,4 @@ +// ReSharper disable CheckNamespace using System.Numerics; using Content.Shared._Starlight.Shuttles.BUIStates; using Content.Shared.Shuttles.BUIStates; diff --git a/Content.Client/Shuttles/UI/ShuttleConsoleWindow.xaml.cs b/Content.Client/Shuttles/UI/ShuttleConsoleWindow.xaml.cs index 630c7d6eb1f7..c4934abbbdea 100644 --- a/Content.Client/Shuttles/UI/ShuttleConsoleWindow.xaml.cs +++ b/Content.Client/Shuttles/UI/ShuttleConsoleWindow.xaml.cs @@ -1,3 +1,4 @@ +// ReSharper disable CheckNamespace using System.Numerics; using Content.Client._Starlight.UserInterface; using Content.Client.Computer; diff --git a/Content.Client/_Starlight/Shuttles/UI/NavScreen.cs b/Content.Client/_Starlight/Shuttles/UI/NavScreen.cs index 8609b7a5cd21..6af5a813dd21 100644 --- a/Content.Client/_Starlight/Shuttles/UI/NavScreen.cs +++ b/Content.Client/_Starlight/Shuttles/UI/NavScreen.cs @@ -1,3 +1,5 @@ +// ReSharper disable CheckNamespace + using Robust.Shared.Map; namespace Content.Client.Shuttles.UI; diff --git a/Content.Client/_Starlight/Shuttles/UI/ShuttleConsoleWindow.cs b/Content.Client/_Starlight/Shuttles/UI/ShuttleConsoleWindow.cs index 49cf94b37de5..a54c9f93949b 100644 --- a/Content.Client/_Starlight/Shuttles/UI/ShuttleConsoleWindow.cs +++ b/Content.Client/_Starlight/Shuttles/UI/ShuttleConsoleWindow.cs @@ -1,3 +1,5 @@ +// ReSharper disable CheckNamespace + using Robust.Shared.Map; namespace Content.Client.Shuttles.UI; diff --git a/Content.Server/_Starlight/DeviceNetwork/Systems/StationLimitedNetworkSystem.cs b/Content.Server/_Starlight/DeviceNetwork/Systems/StationLimitedNetworkSystem.cs index 0a83f9337e1c..a742dcb72bea 100644 --- a/Content.Server/_Starlight/DeviceNetwork/Systems/StationLimitedNetworkSystem.cs +++ b/Content.Server/_Starlight/DeviceNetwork/Systems/StationLimitedNetworkSystem.cs @@ -1,3 +1,4 @@ +// ReSharper disable CheckNamespace using Content.Shared._Starlight.Maps; using Robust.Shared.Map; @@ -12,8 +13,6 @@ private bool CanAccessSenderGrid(EntityUid receiver, EntityUid sender) var receiverGrid = Transform(receiver).GridUid; var senderGrid = Transform(sender).GridUid; - return receiverGrid is { } targetGrid && senderGrid is { } sourceGrid && - (_gridAccess.CanAccess((sourceGrid, null), (targetGrid, null)) || - _gridAccess.CanAccess((targetGrid, null), (sourceGrid, null))); + return receiverGrid is { } targetGrid && senderGrid is { } sourceGrid && (_gridAccess.CanAccess((sourceGrid, null), (targetGrid, null)) || _gridAccess.CanAccess((targetGrid, null), (sourceGrid, null))); } } diff --git a/Content.Shared/_Starlight/Silicons/StationAi/SharedStationAiSystem.GridAccess.cs b/Content.Shared/_Starlight/Silicons/StationAi/SharedStationAiSystem.GridAccess.cs index 3494692ce14a..a114c525c49f 100644 --- a/Content.Shared/_Starlight/Silicons/StationAi/SharedStationAiSystem.GridAccess.cs +++ b/Content.Shared/_Starlight/Silicons/StationAi/SharedStationAiSystem.GridAccess.cs @@ -1,3 +1,5 @@ +// ReSharper disable CheckNamespace + using Content.Shared._Starlight.Maps; using Robust.Shared.Map.Components; From 58a4f112ebe6e429a9a07cca26947fbd8f5dd4c7 Mon Sep 17 00:00:00 2001 From: Floximo Date: Wed, 2 Sep 2026 14:49:22 +0200 Subject: [PATCH 11/17] Update Content.Server/Silicons/StationAi/StationAiSystem.cs Co-authored-by: mack.wtf --- Content.Server/Silicons/StationAi/StationAiSystem.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Content.Server/Silicons/StationAi/StationAiSystem.cs b/Content.Server/Silicons/StationAi/StationAiSystem.cs index 7536458547f9..7187371c970e 100644 --- a/Content.Server/Silicons/StationAi/StationAiSystem.cs +++ b/Content.Server/Silicons/StationAi/StationAiSystem.cs @@ -193,10 +193,8 @@ private void OnStationAiWarpRequest(StationAiWarpRequestEvent msg, EntitySession var targets = new List(); - // Starlight - start - CollectCrewWarpTargets(actor, targets); - CollectLocationWarpTargets(actor, coreEntity.Comp.RemoteEntity, targets); - // Starlight - end + CollectCrewWarpTargets(actor, targets); // Starlight + CollectLocationWarpTargets(actor, coreEntity.Comp.RemoteEntity, targets); // Starlight if (targets.Count == 0) _warpSawmill.Debug($"No warp targets available for Station AI {Name(actor)} ({actor})."); From 762ae7030f84bb52127448a34c82be847caf0767 Mon Sep 17 00:00:00 2001 From: Floximo Date: Wed, 2 Sep 2026 14:50:00 +0200 Subject: [PATCH 12/17] Update Content.Server/Shuttles/Systems/ShuttleConsoleSystem.Drone.cs Co-authored-by: mack.wtf --- Content.Server/Shuttles/Systems/ShuttleConsoleSystem.Drone.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Content.Server/Shuttles/Systems/ShuttleConsoleSystem.Drone.cs b/Content.Server/Shuttles/Systems/ShuttleConsoleSystem.Drone.cs index be1d90a6d8a2..45520d4abd90 100644 --- a/Content.Server/Shuttles/Systems/ShuttleConsoleSystem.Drone.cs +++ b/Content.Server/Shuttles/Systems/ShuttleConsoleSystem.Drone.cs @@ -42,9 +42,7 @@ public void RefreshDroneConsoles() while (query.MoveNext(out var uid, out var comp)) { - // Starlight - start - UpdateRemoteGridAccess(uid, comp); - // Starlight - end + UpdateRemoteGridAccess(uid, comp); // Starlight } } From 8fd9a50d122868ff2854a58a400a7e52b9a5734f Mon Sep 17 00:00:00 2001 From: Floximo Date: Wed, 2 Sep 2026 14:50:18 +0200 Subject: [PATCH 13/17] Update Content.Shared/Silicons/StationAi/SharedStationAiSystem.cs Co-authored-by: mack.wtf --- Content.Shared/Silicons/StationAi/SharedStationAiSystem.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Content.Shared/Silicons/StationAi/SharedStationAiSystem.cs b/Content.Shared/Silicons/StationAi/SharedStationAiSystem.cs index 4a47f5bcbfe4..8b5de2c91125 100644 --- a/Content.Shared/Silicons/StationAi/SharedStationAiSystem.cs +++ b/Content.Shared/Silicons/StationAi/SharedStationAiSystem.cs @@ -209,7 +209,7 @@ private void OnAiBuiCheck(Entity ent, ref BoundUser var targetXform = Transform(args.Target); // Starlight - start - if (!CanAccessGrid((args.Actor, null), targetXform.GridUid)) + if (!CanAccessGrid((args.Actor, null), targetXform.GridUid)) // Starlight { return; } From ec252981fd6627496ef1312d1057e529d40678f0 Mon Sep 17 00:00:00 2001 From: Floximo Date: Wed, 2 Sep 2026 14:52:06 +0200 Subject: [PATCH 14/17] Add comment for popout support in ShuttleConsole UI Added comment for popout support in window creation. --- Content.Client/Shuttles/BUI/ShuttleConsoleBoundUserInterface.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Content.Client/Shuttles/BUI/ShuttleConsoleBoundUserInterface.cs b/Content.Client/Shuttles/BUI/ShuttleConsoleBoundUserInterface.cs index 98a725316845..e61c46b57aff 100644 --- a/Content.Client/Shuttles/BUI/ShuttleConsoleBoundUserInterface.cs +++ b/Content.Client/Shuttles/BUI/ShuttleConsoleBoundUserInterface.cs @@ -27,7 +27,7 @@ public ShuttleConsoleBoundUserInterface(EntityUid owner, Enum uiKey) : base(owne protected override void Open() { base.Open(); - _window = this.CreatePopOutableWindow(EntMan); + _window = this.CreatePopOutableWindow(EntMan); // Starlight: popout support _window.RadarClicked += OnRadarClicked; _window.RequestFTL += OnFTLRequest; From 7e4d2c8b0bc553d00d3d03d39f667efe21ad6d38 Mon Sep 17 00:00:00 2001 From: Floximo Date: Wed, 2 Sep 2026 14:52:55 +0200 Subject: [PATCH 15/17] Clarify popout disposal in Dispose method Added comment to clarify the purpose of disposing the popout. --- Content.Client/Shuttles/BUI/ShuttleConsoleBoundUserInterface.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Content.Client/Shuttles/BUI/ShuttleConsoleBoundUserInterface.cs b/Content.Client/Shuttles/BUI/ShuttleConsoleBoundUserInterface.cs index e61c46b57aff..937f470da010 100644 --- a/Content.Client/Shuttles/BUI/ShuttleConsoleBoundUserInterface.cs +++ b/Content.Client/Shuttles/BUI/ShuttleConsoleBoundUserInterface.cs @@ -79,7 +79,7 @@ protected override void Dispose(bool disposing) { if (_window != null) _window.RadarClicked -= OnRadarClicked; - _window?.DisposePopOut(); + _window?.DisposePopOut(); // Starlight: close the popout if exists } } From 9bda76951b3cc685644e0c646944efa675f495da Mon Sep 17 00:00:00 2001 From: Floximo Date: Wed, 2 Sep 2026 18:45:53 +0200 Subject: [PATCH 16/17] Update Content.Server/Silicons/StationAi/StationAiSystem.cs Co-authored-by: mack.wtf --- Content.Server/Silicons/StationAi/StationAiSystem.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Content.Server/Silicons/StationAi/StationAiSystem.cs b/Content.Server/Silicons/StationAi/StationAiSystem.cs index 7187371c970e..a43a58ece170 100644 --- a/Content.Server/Silicons/StationAi/StationAiSystem.cs +++ b/Content.Server/Silicons/StationAi/StationAiSystem.cs @@ -304,10 +304,6 @@ private void CollectLocationWarpTargets(EntityUid actor, EntityUid? remoteEntity } } - /// - /// Attempts to warp the AI's remote eye to the specified coordinates. - /// The AI must have grid access to the grid containing the coordinates; returns false when access is denied. - /// public bool TryWarpEyeToCoordinates(EntityUid user, EntityCoordinates coordinates, bool popupOnFailure = true) { bool Fail() From 7811501cfa0792ad7eafd39a4eb891feb4d514d9 Mon Sep 17 00:00:00 2001 From: Proximitron Date: Wed, 2 Sep 2026 19:09:11 +0200 Subject: [PATCH 17/17] Fix to starlight comments --- .../Shuttles/Systems/ShuttleConsoleSystem.Drone.cs | 14 ++------------ .../Silicons/StationAi/StationAiSystem.cs | 6 +----- 2 files changed, 3 insertions(+), 17 deletions(-) diff --git a/Content.Server/Shuttles/Systems/ShuttleConsoleSystem.Drone.cs b/Content.Server/Shuttles/Systems/ShuttleConsoleSystem.Drone.cs index 45520d4abd90..8883e28821b9 100644 --- a/Content.Server/Shuttles/Systems/ShuttleConsoleSystem.Drone.cs +++ b/Content.Server/Shuttles/Systems/ShuttleConsoleSystem.Drone.cs @@ -48,9 +48,7 @@ public void RefreshDroneConsoles() private void OnDronePilotConsoleOpen(EntityUid uid, DroneConsoleComponent component, AfterActivatableUIOpenEvent args) { - // Starlight - start - UpdateRemoteGridAccess(uid, component); - // Starlight - end + UpdateRemoteGridAccess(uid, component); // Starlight } private void OnDronePilotConsoleClose(EntityUid uid, DroneConsoleComponent component, BoundUIClosedEvent args) @@ -65,16 +63,13 @@ private void OnDronePilotConsoleClose(EntityUid uid, DroneConsoleComponent compo private void OnCargoGetConsole(EntityUid uid, DroneConsoleComponent component, ref ConsoleShuttleEvent args) { - // Starlight - start - UpdateRemoteGridAccess(uid, component); - // Starlight - end + UpdateRemoteGridAccess(uid, component); // Starlight args.Console = component.Entity; } #region Starlight private void UpdateRemoteGridAccess(EntityUid uid, DroneConsoleComponent component) { - // Starlight - start var targetConsole = GetShuttleConsole(uid, component); var sourceGrid = Transform(uid).GridUid; var targetGrid = targetConsole is { } target ? Transform(target).GridUid : null; @@ -100,12 +95,10 @@ targetConsole is not { } console || _gridAccess.AddAccessibleGrid((source, null), (targetUid, null)); _remoteGridAccess[uid] = (source, targetUid); - // Starlight - end } private void RemoveRemoteGridAccess(EntityUid uid) { - // Starlight - start if (!_remoteGridAccess.Remove(uid, out var access)) return; @@ -118,14 +111,11 @@ private void RemoveRemoteGridAccess(EntityUid uid) } _gridAccess.RemoveAccessibleGrid((access.SourceGrid, null), (access.TargetGrid, null)); - // Starlight - end } private bool IsConsoleOperational(EntityUid uid) { - // Starlight - start return TryComp(uid, out _) && MetaData(uid).EntityLifeStage < EntityLifeStage.Terminating && Transform(uid).Anchored && this.IsPowered(uid, EntityManager); - // Starlight - end } #endregion Starlight diff --git a/Content.Server/Silicons/StationAi/StationAiSystem.cs b/Content.Server/Silicons/StationAi/StationAiSystem.cs index a43a58ece170..d006980b3e49 100644 --- a/Content.Server/Silicons/StationAi/StationAiSystem.cs +++ b/Content.Server/Silicons/StationAi/StationAiSystem.cs @@ -217,7 +217,7 @@ private void OnStationAiWarpToTarget(StationAiWarpToTargetEvent msg, EntitySessi return; } - if (!CanAccessGrid((actor, null), Transform(target).GridUid)) + if (!CanAccessGrid((actor, null), Transform(target).GridUid)) // Starlight { _warpSawmill.Debug($"Station AI {Name(actor)} ({actor}) attempted to warp to inaccessible target {Name(target)} ({target})."); return; @@ -357,10 +357,6 @@ bool Fail() return true; } - /// - /// Attempts to warp the AI's remote eye to the specified entity. - /// The AI must have grid access to the grid containing the entity; returns false when access is denied. - /// public bool TryWarpEyeToEntity(EntityUid user, EntityUid target, bool popupOnFailure = true) { bool Fail()