diff --git a/Content.Client/Cargo/CargoConsoleBoundUserInterface.cs b/Content.Client/Cargo/BUI/CargoOrderConsoleBoundUserInterface.cs
similarity index 55%
rename from Content.Client/Cargo/CargoConsoleBoundUserInterface.cs
rename to Content.Client/Cargo/BUI/CargoOrderConsoleBoundUserInterface.cs
index ac03a59fe9..1d9f4a4cf5 100644
--- a/Content.Client/Cargo/CargoConsoleBoundUserInterface.cs
+++ b/Content.Client/Cargo/BUI/CargoOrderConsoleBoundUserInterface.cs
@@ -1,45 +1,46 @@
-using Content.Client.Cargo.Components;
using Content.Client.Cargo.UI;
+using Content.Shared.Access.Systems;
using Content.Shared.Cargo;
+using Content.Shared.Cargo.BUI;
using Content.Shared.Cargo.Components;
+using Content.Shared.Cargo.Events;
+using Content.Shared.Cargo.Prototypes;
using Robust.Client.GameObjects;
-using Robust.Shared.GameObjects;
-using Robust.Shared.IoC;
-using Robust.Shared.ViewVariables;
-using static Content.Shared.Cargo.Components.SharedCargoConsoleComponent;
+using Robust.Client.Player;
+using Robust.Shared.Prototypes;
using static Robust.Client.UserInterface.Controls.BaseButton;
-namespace Content.Client.Cargo
+namespace Content.Client.Cargo.BUI
{
- public sealed class CargoConsoleBoundUserInterface : BoundUserInterface
+ public sealed class CargoOrderConsoleBoundUserInterface : BoundUserInterface
{
[ViewVariables]
private CargoConsoleMenu? _menu;
+ ///
+ /// This is the separate popup window for individual orders.
+ ///
[ViewVariables]
private CargoConsoleOrderMenu? _orderMenu;
[ViewVariables]
- public CargoOrderDatabaseComponent? Orders { get; private set; }
-
- [ViewVariables]
- public bool RequestOnly { get; private set; }
-
- [ViewVariables]
- public int BankId { get; private set; }
-
- [ViewVariables]
- public string? BankName { get; private set; }
+ public string? AccountName { get; private set; }
[ViewVariables]
public int BankBalance { get; private set; }
[ViewVariables]
- public (int CurrentCapacity, int MaxCapacity) ShuttleCapacity { get; private set; }
+ public int OrderCapacity { get; private set; }
+ [ViewVariables]
+ public int OrderCount { get; private set; }
+
+ ///
+ /// Currently selected product
+ ///
private CargoProductPrototype? _product;
- public CargoConsoleBoundUserInterface(ClientUserInterfaceComponent owner, object uiKey) : base(owner, uiKey)
+ public CargoOrderConsoleBoundUserInterface(ClientUserInterfaceComponent owner, object uiKey) : base(owner, uiKey)
{
}
@@ -47,30 +48,29 @@ namespace Content.Client.Cargo
{
base.Open();
- var entMan = IoCManager.Resolve();
- if (!entMan.TryGetComponent(Owner.Owner, out CargoOrderDatabaseComponent? orders)) return;
+ var entityManager = IoCManager.Resolve();
+ var sysManager = entityManager.EntitySysManager;
+ var spriteSystem = sysManager.GetEntitySystem();
+ _menu = new CargoConsoleMenu(IoCManager.Resolve(), spriteSystem);
+ var localPlayer = IoCManager.Resolve()?.LocalPlayer?.ControlledEntity;
- Orders = orders;
+ string orderRequester;
+
+ if (entityManager.TryGetComponent(localPlayer, out var metadata))
+ orderRequester = metadata.EntityName;
+ else
+ orderRequester = string.Empty;
- _menu = new CargoConsoleMenu(this);
_orderMenu = new CargoConsoleOrderMenu();
_menu.OnClose += Close;
- _menu.Populate();
-
- Orders.OnDatabaseUpdated += _menu.PopulateOrders;
-
- _menu.CallShuttleButton.OnPressed += (_) =>
- {
- SendMessage(new CargoConsoleShuttleMessage());
- };
_menu.OnItemSelected += (args) =>
{
if (args.Button.Parent is not CargoProductRow row)
return;
_product = row.Product;
- _orderMenu.Requester.Text = "";
+ _orderMenu.Requester.Text = orderRequester;
_orderMenu.Reason.Text = "";
_orderMenu.Amount.Value = 1;
_orderMenu.OpenCentered();
@@ -86,7 +86,15 @@ namespace Content.Client.Cargo
};
_menu.OpenCentered();
+ }
+ private void Populate(List orders)
+ {
+ if (_menu == null) return;
+
+ _menu.PopulateProducts();
+ _menu.PopulateCategories();
+ _menu.PopulateOrders(orders);
}
protected override void UpdateState(BoundUserInterfaceState state)
@@ -95,17 +103,16 @@ namespace Content.Client.Cargo
if (state is not CargoConsoleInterfaceState cState)
return;
- if (RequestOnly != cState.RequestOnly)
- {
- RequestOnly = cState.RequestOnly;
- _menu?.UpdateRequestOnly();
- }
- BankId = cState.BankId;
- BankName = cState.BankName;
- BankBalance = cState.BankBalance;
- ShuttleCapacity = cState.ShuttleCapacity;
- _menu?.UpdateCargoCapacity();
- _menu?.UpdateBankData();
+
+ OrderCapacity = cState.Capacity;
+ OrderCount = cState.Count;
+ BankBalance = cState.Balance;
+
+ AccountName = cState.Name;
+
+ Populate(cState.Orders);
+ _menu?.UpdateCargoCapacity(OrderCount, OrderCapacity);
+ _menu?.UpdateBankData(AccountName, BankBalance);
}
protected override void Dispose(bool disposing)
@@ -114,11 +121,6 @@ namespace Content.Client.Cargo
if (!disposing) return;
- if (Orders != null && _menu != null)
- {
- Orders.OnDatabaseUpdated -= _menu.PopulateOrders;
- }
-
_menu?.Dispose();
_orderMenu?.Dispose();
}
@@ -126,7 +128,7 @@ namespace Content.Client.Cargo
private bool AddOrder()
{
int orderAmt = _orderMenu?.Amount.Value ?? 0;
- if (orderAmt < 1 || orderAmt > ShuttleCapacity.MaxCapacity)
+ if (orderAmt < 1 || orderAmt > OrderCapacity)
{
return false;
}
@@ -153,11 +155,12 @@ namespace Content.Client.Cargo
if (args.Button.Parent?.Parent is not CargoOrderRow row || row.Order == null)
return;
- if (ShuttleCapacity.CurrentCapacity == ShuttleCapacity.MaxCapacity)
+ if (OrderCount >= OrderCapacity)
return;
SendMessage(new CargoConsoleApproveOrderMessage(row.Order.OrderNumber));
- _menu?.UpdateCargoCapacity();
+ // Most of the UI isn't predicted anyway so.
+ // _menu?.UpdateCargoCapacity(OrderCount + row.Order.Amount, OrderCapacity);
}
}
}
diff --git a/Content.Client/Cargo/BUI/CargoShuttleConsoleBoundUserInterface.cs b/Content.Client/Cargo/BUI/CargoShuttleConsoleBoundUserInterface.cs
new file mode 100644
index 0000000000..6dd3df5f6e
--- /dev/null
+++ b/Content.Client/Cargo/BUI/CargoShuttleConsoleBoundUserInterface.cs
@@ -0,0 +1,57 @@
+using Content.Client.Cargo.UI;
+using Content.Shared.Cargo.BUI;
+using Content.Shared.Cargo.Events;
+using Robust.Client.GameObjects;
+using Robust.Shared.Prototypes;
+using Robust.Shared.Timing;
+
+namespace Content.Client.Cargo.BUI;
+
+public sealed class CargoShuttleConsoleBoundUserInterface : BoundUserInterface
+{
+ private CargoShuttleMenu? _menu;
+
+ public CargoShuttleConsoleBoundUserInterface(ClientUserInterfaceComponent owner, object uiKey) : base(owner, uiKey) {}
+
+ protected override void Open()
+ {
+ base.Open();
+ _menu = new CargoShuttleMenu(IoCManager.Resolve(), IoCManager.Resolve(), EntitySystem.Get());
+
+ _menu.ShuttleCallRequested += OnShuttleCall;
+ _menu.ShuttleRecallRequested += OnShuttleRecall;
+ _menu.OnClose += Close;
+
+ _menu.OpenCentered();
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ base.Dispose(disposing);
+ if (disposing)
+ {
+ _menu?.Dispose();
+ }
+ }
+
+ private void OnShuttleRecall()
+ {
+ SendMessage(new CargoRecallShuttleMessage());
+ }
+
+ private void OnShuttleCall()
+ {
+ SendMessage(new CargoCallShuttleMessage());
+ }
+
+ protected override void UpdateState(BoundUserInterfaceState state)
+ {
+ base.UpdateState(state);
+ if (state is not CargoShuttleConsoleBoundUserInterfaceState cargoState) return;
+ _menu?.SetAccountName(cargoState.AccountName);
+ _menu?.SetShuttleName(cargoState.ShuttleName);
+ _menu?.SetShuttleETA(cargoState.ShuttleETA);
+ _menu?.SetOrders(cargoState.Orders);
+ _menu?.SetCanRecall(cargoState.CanRecall);
+ }
+}
diff --git a/Content.Client/Cargo/Components/CargoOrderDatabaseComponent.cs b/Content.Client/Cargo/Components/CargoOrderDatabaseComponent.cs
deleted file mode 100644
index 5279e6dc0e..0000000000
--- a/Content.Client/Cargo/Components/CargoOrderDatabaseComponent.cs
+++ /dev/null
@@ -1,56 +0,0 @@
-using System;
-using System.Collections.Generic;
-using Content.Shared.Cargo;
-using Content.Shared.Cargo.Components;
-using Robust.Shared.GameObjects;
-
-namespace Content.Client.Cargo.Components
-{
- [RegisterComponent]
- public sealed class CargoOrderDatabaseComponent : SharedCargoOrderDatabaseComponent
- {
- private readonly List _orders = new();
-
- public IReadOnlyList Orders => _orders;
- ///
- /// Event called when the database is updated.
- ///
- public event Action? OnDatabaseUpdated;
-
- // TODO add account selector menu
-
- ///
- /// Removes all orders from the database.
- ///
- public void Clear()
- {
- _orders.Clear();
- }
-
- ///
- /// Adds an order to the database.
- ///
- /// The order to be added.
- public void AddOrder(CargoOrderData order)
- {
- if (!_orders.Contains(order))
- _orders.Add(order);
- }
-
- public override void HandleComponentState(ComponentState? curState, ComponentState? nextState)
- {
- base.HandleComponentState(curState, nextState);
- if (curState is not CargoOrderDatabaseState state)
- return;
- Clear();
- if (state.Orders == null)
- return;
- foreach (var order in state.Orders)
- {
- AddOrder(order);
- }
-
- OnDatabaseUpdated?.Invoke();
- }
- }
-}
diff --git a/Content.Client/Cargo/CargoSystem.Telepad.cs b/Content.Client/Cargo/Systems/CargoSystem.Telepad.cs
similarity index 98%
rename from Content.Client/Cargo/CargoSystem.Telepad.cs
rename to Content.Client/Cargo/Systems/CargoSystem.Telepad.cs
index 6074d637ac..4d73caacb2 100644
--- a/Content.Client/Cargo/CargoSystem.Telepad.cs
+++ b/Content.Client/Cargo/Systems/CargoSystem.Telepad.cs
@@ -3,7 +3,7 @@ using Robust.Client.Animations;
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
-namespace Content.Client.Cargo;
+namespace Content.Client.Cargo.Systems;
public sealed partial class CargoSystem
{
diff --git a/Content.Client/Cargo/CargoSystem.cs b/Content.Client/Cargo/Systems/CargoSystem.cs
similarity index 88%
rename from Content.Client/Cargo/CargoSystem.cs
rename to Content.Client/Cargo/Systems/CargoSystem.cs
index ce26dc7ecf..3ffb0636d0 100644
--- a/Content.Client/Cargo/CargoSystem.cs
+++ b/Content.Client/Cargo/Systems/CargoSystem.cs
@@ -1,7 +1,7 @@
using Content.Shared.Cargo;
using Robust.Client.GameObjects;
-namespace Content.Client.Cargo;
+namespace Content.Client.Cargo.Systems;
public sealed partial class CargoSystem : SharedCargoSystem
{
diff --git a/Content.Client/Cargo/UI/CargoConsoleMenu.xaml b/Content.Client/Cargo/UI/CargoConsoleMenu.xaml
index 9b92e43091..5262f43d6b 100644
--- a/Content.Client/Cargo/UI/CargoConsoleMenu.xaml
+++ b/Content.Client/Cargo/UI/CargoConsoleMenu.xaml
@@ -1,7 +1,8 @@
-
+
-
-
-
-
-
-
-
-
-
+
diff --git a/Content.Client/Cargo/UI/CargoConsoleMenu.xaml.cs b/Content.Client/Cargo/UI/CargoConsoleMenu.xaml.cs
index dac0b70d86..ccda7d6467 100644
--- a/Content.Client/Cargo/UI/CargoConsoleMenu.xaml.cs
+++ b/Content.Client/Cargo/UI/CargoConsoleMenu.xaml.cs
@@ -1,31 +1,24 @@
-using System;
-using System.Collections.Generic;
-using Content.Client.Stylesheets;
+using System.Linq;
+using Content.Client.UserInterface;
using Content.Shared.Cargo;
+using Content.Shared.Cargo.Prototypes;
using Robust.Client.AutoGenerated;
-using Robust.Client.Graphics;
+using Robust.Client.GameObjects;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls;
using Robust.Client.UserInterface.XAML;
using Robust.Client.Utility;
-using Robust.Shared.IoC;
using Robust.Shared.Prototypes;
-using Robust.Shared.Localization;
-using Robust.Shared.Log;
-using Robust.Shared.Maths;
using Robust.Shared.Utility;
using static Robust.Client.UserInterface.Controls.BaseButton;
-using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.Cargo.UI
{
[GenerateTypedNameReferences]
- public sealed partial class CargoConsoleMenu : DefaultWindow
+ public sealed partial class CargoConsoleMenu : FancyWindow
{
- [Dependency]
- private IPrototypeManager _prototypeManager = default!;
-
- public CargoConsoleBoundUserInterface Owner { get; private set; }
+ private IPrototypeManager _protoManager;
+ private SpriteSystem _spriteSystem;
public event Action? OnItemSelected;
public event Action? OnOrderApproved;
@@ -34,25 +27,18 @@ namespace Content.Client.Cargo.UI
private readonly List _categoryStrings = new();
private string? _category;
- public CargoConsoleMenu(CargoConsoleBoundUserInterface owner)
+ public CargoConsoleMenu(IPrototypeManager protoManager, SpriteSystem spriteSystem)
{
RobustXamlLoader.Load(this);
- IoCManager.InjectDependencies(this);
- Owner = owner;
+ _protoManager = protoManager;
+ _spriteSystem = spriteSystem;
- Title = Loc.GetString(Owner.RequestOnly
- ? "cargo-console-menu-request-only-title"
- : "cargo-console-menu-title");
+ Title = Loc.GetString("cargo-console-menu-title");
- CallShuttleButton.OnPressed += OnCallShuttleButtonPressed;
SearchBar.OnTextChanged += OnSearchBarTextChanged;
Categories.OnItemSelected += OnCategoryItemSelected;
}
- private void OnCallShuttleButtonPressed(ButtonEventArgs args)
- {
- }
-
private void OnCategoryItemSelected(OptionButton.ItemSelectedEventArgs args)
{
SetCategoryText(args.Id);
@@ -70,7 +56,7 @@ namespace Content.Client.Cargo.UI
Categories.SelectId(id);
}
- public IEnumerable ProductPrototypes => _prototypeManager.EnumeratePrototypes();
+ public IEnumerable ProductPrototypes => _protoManager.EnumeratePrototypes();
///
/// Populates the list of products that will actually be shown, using the current filters.
@@ -78,9 +64,12 @@ namespace Content.Client.Cargo.UI
public void PopulateProducts()
{
Products.RemoveAllChildren();
+ var products = ProductPrototypes.ToList();
+ products.Sort((x, y) =>
+ string.Compare(x.Name, y.Name, StringComparison.Ordinal));
var search = SearchBar.Text.Trim().ToLowerInvariant();
- foreach (var prototype in ProductPrototypes)
+ foreach (var prototype in products)
{
// if no search or category
// else if search
@@ -94,7 +83,7 @@ namespace Content.Client.Cargo.UI
Product = prototype,
ProductName = { Text = prototype.Name },
PointCost = { Text = prototype.PointCost.ToString() },
- Icon = { Texture = prototype.Icon.Frame0() },
+ Icon = { Texture = _spriteSystem.Frame0(prototype.Icon) },
};
button.MainButton.OnPressed += args =>
{
@@ -132,31 +121,20 @@ namespace Content.Client.Cargo.UI
///
/// Populates the list of orders and requests.
///
- public void PopulateOrders()
+ public void PopulateOrders(IEnumerable orders)
{
- Orders.RemoveAllChildren();
- Requests.RemoveAllChildren();
+ Orders.DisposeAllChildren();
+ Requests.DisposeAllChildren();
- if (Owner.Orders == null)
+ foreach (var order in orders)
{
- return;
- }
-
- foreach (var order in Owner.Orders.Orders)
- {
- if (!_prototypeManager.TryIndex(order.ProductId, out CargoProductPrototype? product))
- {
- DebugTools.Assert(false);
- Logger.ErrorS("cargo", $"Unable to find product name for {order.ProductId}");
- continue;
- }
-
+ var product = _protoManager.Index(order.ProductId);
var productName = product.Name;
var row = new CargoOrderRow
{
Order = order,
- Icon = { Texture = product.Icon.Frame0() },
+ Icon = { Texture = _spriteSystem.Frame0(product.Icon) },
ProductName =
{
Text = Loc.GetString(
@@ -177,43 +155,23 @@ namespace Content.Client.Cargo.UI
}
else
{
- if (Owner.RequestOnly)
- row.Approve.Visible = false;
- else
- row.Approve.OnPressed += (args) => { OnOrderApproved?.Invoke(args); };
+ // TODO: Disable based on access.
+ row.Approve.OnPressed += (args) => { OnOrderApproved?.Invoke(args); };
Requests.AddChild(row);
}
}
}
- public void Populate()
+ public void UpdateCargoCapacity(int count, int capacity)
{
- PopulateProducts();
- PopulateCategories();
- PopulateOrders();
+ // TODO: Rename + Loc.
+ ShuttleCapacityLabel.Text = $"{count}/{capacity}";
}
- public void UpdateCargoCapacity()
+ public void UpdateBankData(string name, int points)
{
- ShuttleCapacityLabel.Text = $"{Owner.ShuttleCapacity.CurrentCapacity}/{Owner.ShuttleCapacity.MaxCapacity}";
- }
-
- public void UpdateBankData()
- {
- AccountNameLabel.Text = Owner.BankName;
- PointsLabel.Text = Owner.BankBalance.ToString();
- }
-
- ///
- /// Show/Hide Call Shuttle button and Approve buttons
- ///
- public void UpdateRequestOnly()
- {
- CallShuttleButton.Visible = !Owner.RequestOnly;
- foreach (CargoOrderRow row in Requests.Children)
- {
- row.Approve.Visible = !Owner.RequestOnly;
- }
+ AccountNameLabel.Text = name;
+ PointsLabel.Text = points.ToString();
}
}
}
diff --git a/Content.Client/Cargo/UI/CargoProductRow.xaml.cs b/Content.Client/Cargo/UI/CargoProductRow.xaml.cs
index 0f3796dac2..5afa7633a5 100644
--- a/Content.Client/Cargo/UI/CargoProductRow.xaml.cs
+++ b/Content.Client/Cargo/UI/CargoProductRow.xaml.cs
@@ -1,4 +1,5 @@
using Content.Shared.Cargo;
+using Content.Shared.Cargo.Prototypes;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
diff --git a/Content.Client/Cargo/UI/CargoShuttleMenu.xaml b/Content.Client/Cargo/UI/CargoShuttleMenu.xaml
new file mode 100644
index 0000000000..5d5d0cbf88
--- /dev/null
+++ b/Content.Client/Cargo/UI/CargoShuttleMenu.xaml
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Content.Client/Cargo/UI/CargoShuttleMenu.xaml.cs b/Content.Client/Cargo/UI/CargoShuttleMenu.xaml.cs
new file mode 100644
index 0000000000..0319d1b03b
--- /dev/null
+++ b/Content.Client/Cargo/UI/CargoShuttleMenu.xaml.cs
@@ -0,0 +1,128 @@
+using Content.Client.UserInterface;
+using Content.Shared.Cargo;
+using Content.Shared.Cargo.Prototypes;
+using Robust.Client.AutoGenerated;
+using Robust.Client.GameObjects;
+using Robust.Client.Graphics;
+using Robust.Client.UserInterface.Controls;
+using Robust.Client.UserInterface.XAML;
+using Robust.Shared.Prototypes;
+using Robust.Shared.Timing;
+
+namespace Content.Client.Cargo.UI
+{
+ [GenerateTypedNameReferences]
+ public sealed partial class CargoShuttleMenu : FancyWindow
+ {
+ private readonly IGameTiming _timing;
+ private readonly IPrototypeManager _protoManager;
+ private readonly SpriteSystem _spriteSystem;
+
+ public Action? ShuttleCallRequested;
+ public Action? ShuttleRecallRequested;
+
+ private TimeSpan? _shuttleEta;
+
+ public CargoShuttleMenu(IGameTiming timing, IPrototypeManager protoManager, SpriteSystem spriteSystem)
+ {
+ RobustXamlLoader.Load(this);
+ _timing = timing;
+ _protoManager = protoManager;
+ _spriteSystem = spriteSystem;
+ ShuttleCallButton.OnPressed += OnCallPressed;
+ ShuttleRecallButton.OnPressed += OnRecallPressed;
+ Title = Loc.GetString("cargo-shuttle-console-menu-title");
+ }
+
+ public void SetAccountName(string name)
+ {
+ AccountNameLabel.Text = name;
+ }
+
+ public void SetShuttleName(string name)
+ {
+ ShuttleNameLabel.Text = name;
+ }
+
+ public void SetShuttleETA(TimeSpan? eta)
+ {
+ _shuttleEta = eta;
+
+ if (eta == null)
+ {
+ ShuttleCallButton.Visible = false;
+ ShuttleRecallButton.Visible = true;
+ }
+ else
+ {
+ ShuttleRecallButton.Visible = false;
+ ShuttleCallButton.Visible = true;
+ ShuttleCallButton.Disabled = true;
+ }
+ }
+
+ private void OnRecallPressed(BaseButton.ButtonEventArgs obj)
+ {
+ ShuttleRecallRequested?.Invoke();
+ }
+
+ private void OnCallPressed(BaseButton.ButtonEventArgs obj)
+ {
+ ShuttleCallRequested?.Invoke();
+ }
+
+ public void SetOrders(List orders)
+ {
+ Orders.DisposeAllChildren();
+
+ foreach (var order in orders)
+ {
+ var product = _protoManager.Index(order.ProductId);
+ var productName = product.Name;
+
+ var row = new CargoOrderRow
+ {
+ Order = order,
+ Icon = { Texture = _spriteSystem.Frame0(product.Icon) },
+ ProductName =
+ {
+ Text = Loc.GetString(
+ "cargo-console-menu-populate-orders-cargo-order-row-product-name-text",
+ ("productName", productName),
+ ("orderAmount", order.Amount),
+ ("orderRequester", order.Requester))
+ },
+ Description = {Text = Loc.GetString("cargo-console-menu-order-reason-description",
+ ("reason", order.Reason))}
+ };
+
+ row.Approve.Visible = false;
+ row.Cancel.Visible = false;
+
+ Orders.AddChild(row);
+ }
+ }
+
+ public void SetCanRecall(bool canRecall)
+ {
+ ShuttleRecallButton.Disabled = !canRecall;
+ }
+
+ protected override void Draw(DrawingHandleScreen handle)
+ {
+ base.Draw(handle);
+
+ var remaining = _shuttleEta - _timing.CurTime;
+
+ if (remaining == null || remaining <= TimeSpan.Zero)
+ {
+ ShuttleStatusLabel.Text = $"Available";
+ ShuttleCallButton.Disabled = false;
+ }
+ else
+ {
+ ShuttleStatusLabel.Text = $"Available in: {remaining.Value.TotalSeconds:0.0}";
+ }
+ }
+ }
+}
diff --git a/Content.Client/Cargo/UI/GalacticBankSelectionMenu.cs b/Content.Client/Cargo/UI/GalacticBankSelectionMenu.cs
deleted file mode 100644
index b742676829..0000000000
--- a/Content.Client/Cargo/UI/GalacticBankSelectionMenu.cs
+++ /dev/null
@@ -1,45 +0,0 @@
-using Robust.Client.UserInterface.Controls;
-using Robust.Client.UserInterface.CustomControls;
-using Robust.Shared.IoC;
-using Robust.Shared.Localization;
-
-namespace Content.Client.Cargo.UI
-{
- public sealed class GalacticBankSelectionMenu : DefaultWindow
- {
- private readonly ItemList _accounts;
- private int _accountCount;
- private string[] _accountNames = System.Array.Empty();
- private int[] _accountIds = System.Array.Empty();
- private int _selectedAccountId = -1;
-
- public GalacticBankSelectionMenu(CargoConsoleBoundUserInterface owner)
- {
- MinSize = SetSize = (300, 300);
- IoCManager.InjectDependencies(this);
-
- Title = Loc.GetString("galactic-bank-selection-menu-title");
-
- _accounts = new ItemList { SelectMode = ItemList.ItemListSelectMode.Single };
-
- Contents.AddChild(_accounts);
- }
-
- public void Populate(int accountCount, string[] accountNames, int[] accountIds, int selectedAccountId)
- {
- _accountCount = accountCount;
- _accountNames = accountNames;
- _accountIds = accountIds;
- _selectedAccountId = selectedAccountId;
-
- _accounts.Clear();
- for (var i = 0; i < _accountCount; i++)
- {
- var id = _accountIds[i];
- _accounts.AddItem($"ID: {id} || {_accountNames[i]}");
- if (id == _selectedAccountId)
- _accounts[id].Selected = true;
- }
- }
- }
-}
diff --git a/Content.Client/Entry/EntryPoint.cs b/Content.Client/Entry/EntryPoint.cs
index f2aa214e14..8bec3815e2 100644
--- a/Content.Client/Entry/EntryPoint.cs
+++ b/Content.Client/Entry/EntryPoint.cs
@@ -74,7 +74,6 @@ namespace Content.Client.Entry
factory.RegisterClass();
factory.RegisterClass();
factory.RegisterClass();
- factory.RegisterClass();
factory.RegisterClass();
factory.RegisterClass();
factory.RegisterClass();
diff --git a/Content.Client/Shuttles/BUI/RadarConsoleBoundUserInterface.cs b/Content.Client/Shuttles/BUI/RadarConsoleBoundUserInterface.cs
index 4c5b4edea8..0c2e8bc726 100644
--- a/Content.Client/Shuttles/BUI/RadarConsoleBoundUserInterface.cs
+++ b/Content.Client/Shuttles/BUI/RadarConsoleBoundUserInterface.cs
@@ -24,6 +24,7 @@ public sealed class RadarConsoleBoundUserInterface : BoundUserInterface
base.UpdateState(state);
if (state is not RadarConsoleBoundInterfaceState cState) return;
+ _window?.SetMatrix(cState.Coordinates, cState.Angle);
_window?.UpdateState(cState);
}
}
diff --git a/Content.Client/Shuttles/BUI/ShuttleConsoleBoundUserInterface.cs b/Content.Client/Shuttles/BUI/ShuttleConsoleBoundUserInterface.cs
index cb60508c31..0b8b83acc9 100644
--- a/Content.Client/Shuttles/BUI/ShuttleConsoleBoundUserInterface.cs
+++ b/Content.Client/Shuttles/BUI/ShuttleConsoleBoundUserInterface.cs
@@ -65,6 +65,8 @@ public sealed class ShuttleConsoleBoundUserInterface : BoundUserInterface
{
base.UpdateState(state);
if (state is not ShuttleConsoleBoundInterfaceState cState) return;
+
+ _window?.SetMatrix(cState.Coordinates, cState.Angle);
_window?.UpdateState(cState);
}
}
diff --git a/Content.Client/Shuttles/Systems/DockingSystem.cs b/Content.Client/Shuttles/Systems/DockingSystem.cs
index 61f0b8d06c..143f0a971b 100644
--- a/Content.Client/Shuttles/Systems/DockingSystem.cs
+++ b/Content.Client/Shuttles/Systems/DockingSystem.cs
@@ -2,20 +2,4 @@ using Content.Shared.Shuttles.Events;
namespace Content.Client.Shuttles.Systems;
-public sealed class DockingSystem : EntitySystem
-{
- public void StartAutodock(EntityUid uid)
- {
- RaiseNetworkEvent(new AutodockRequestMessage {Entity = uid});
- }
-
- public void StopAutodock(EntityUid uid)
- {
- RaiseNetworkEvent(new StopAutodockRequestMessage() {Entity = uid});
- }
-
- public void Undock(EntityUid uid)
- {
- RaiseNetworkEvent(new UndockRequestMessage() {Entity = uid});
- }
-}
+public sealed class DockingSystem : EntitySystem {}
diff --git a/Content.Client/Shuttles/UI/DockingControl.cs b/Content.Client/Shuttles/UI/DockingControl.cs
index dfa5023a8a..2c37f62357 100644
--- a/Content.Client/Shuttles/UI/DockingControl.cs
+++ b/Content.Client/Shuttles/UI/DockingControl.cs
@@ -31,6 +31,9 @@ public class DockingControl : Control
public EntityUid? ViewedDock;
public EntityUid? GridEntity;
+ public EntityCoordinates? Coordinates;
+ public Angle? Angle;
+
///
/// Stored by GridID then by docks
///
@@ -69,11 +72,12 @@ public class DockingControl : Control
handle.DrawLine((MidPoint, MidPoint) - aExtent, (MidPoint, MidPoint) + aExtent, gridLines);
}
- if (!_entManager.TryGetComponent(ViewedDock, out var xform) ||
+ if (Coordinates == null ||
+ Angle == null ||
!_entManager.TryGetComponent(GridEntity, out var gridXform)) return;
- var rotation = Matrix3.CreateRotation(xform.LocalRotation);
- var matrix = Matrix3.CreateTranslation(-xform.LocalPosition);
+ var rotation = Matrix3.CreateRotation(Angle.Value);
+ var matrix = Matrix3.CreateTranslation(-Coordinates.Value.Position);
// Draw the fixtures around the dock before drawing it
if (_entManager.TryGetComponent(GridEntity, out var fixtures))
@@ -128,7 +132,7 @@ public class DockingControl : Control
ScalePosition(rotation.Transform(new Vector2(0.5f, -0.5f)))), Color.Green);
// Draw nearby grids
- var worldPos = gridXform.WorldMatrix.Transform(xform.LocalPosition);
+ var worldPos = gridXform.WorldMatrix.Transform(Coordinates.Value.Position);
var gridInvMatrix = gridXform.InvWorldMatrix;
Matrix3.Multiply(in gridInvMatrix, in matrix, out var invMatrix);
diff --git a/Content.Client/Shuttles/UI/RadarConsoleWindow.xaml.cs b/Content.Client/Shuttles/UI/RadarConsoleWindow.xaml.cs
index 7274cc23c8..4a297a2a88 100644
--- a/Content.Client/Shuttles/UI/RadarConsoleWindow.xaml.cs
+++ b/Content.Client/Shuttles/UI/RadarConsoleWindow.xaml.cs
@@ -3,6 +3,7 @@ using Content.Client.UserInterface;
using Content.Shared.Shuttles.BUIStates;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.XAML;
+using Robust.Shared.Map;
namespace Content.Client.Shuttles.UI;
@@ -19,4 +20,9 @@ public sealed partial class RadarConsoleWindow : FancyWindow,
{
RadarScreen.UpdateState(scc);
}
+
+ public void SetMatrix(EntityCoordinates? coordinates, Angle? angle)
+ {
+ RadarScreen.SetMatrix(coordinates, angle);
+ }
}
diff --git a/Content.Client/Shuttles/UI/RadarControl.cs b/Content.Client/Shuttles/UI/RadarControl.cs
index eda8fb08d8..adf69b03cb 100644
--- a/Content.Client/Shuttles/UI/RadarControl.cs
+++ b/Content.Client/Shuttles/UI/RadarControl.cs
@@ -25,9 +25,11 @@ public sealed class RadarControl : Control
private const float GridLinesDistance = 32f;
///
- /// Entity used to transform all of the radar objects.
+ /// Used to transform all of the radar objects. Typically is a shuttle console parented to a grid.
///
- private EntityUid? _entity;
+ private EntityCoordinates? _coordinates;
+
+ private Angle? _rotation;
private float _radarMinRange = 64f;
private float _radarMaxRange = 256f;
@@ -61,6 +63,12 @@ public sealed class RadarControl : Control
MinSize = (SizeFull, SizeFull);
}
+ public void SetMatrix(EntityCoordinates? coordinates, Angle? angle)
+ {
+ _coordinates = coordinates;
+ _rotation = angle;
+ }
+
public void UpdateState(RadarConsoleBoundInterfaceState ls)
{
_radarMaxRange = ls.MaxRange;
@@ -74,7 +82,6 @@ public sealed class RadarControl : Control
if (_radarMaxRange < _radarMinRange)
_radarMinRange = _radarMaxRange;
- _entity = ls.Entity;
_docks.Clear();
foreach (var state in ls.Docks)
@@ -109,7 +116,7 @@ public sealed class RadarControl : Control
handle.DrawCircle((MidPoint, MidPoint), ScaledMinimapRadius, Color.Black);
// No data
- if (_entity == null)
+ if (_coordinates == null || _rotation == null)
{
Clear();
return;
@@ -135,8 +142,8 @@ public sealed class RadarControl : Control
var xformQuery = _entManager.GetEntityQuery();
var fixturesQuery = _entManager.GetEntityQuery();
var bodyQuery = _entManager.GetEntityQuery();
- var xform = xformQuery.GetComponent(_entity.Value);
- var mapPosition = xform.MapPosition;
+
+ var mapPosition = _coordinates.Value.ToMap(_entManager);
if (mapPosition.MapId == MapId.Nullspace)
{
@@ -144,28 +151,30 @@ public sealed class RadarControl : Control
return;
}
- // Can also use ourGridBody.LocalCenter
- var offset = xform.Coordinates.Position;
- var offsetMatrix = Matrix3.CreateTranslation(-offset);
+ var offset = _coordinates.Value.Position;
Matrix3 matrix;
// Draw our grid in detail
- var ourGridId = xform.GridUid;
+ var ourGridId = _coordinates.Value.GetGridUid(_entManager);
if (ourGridId != null)
{
- matrix = xform.InvWorldMatrix;
+ var offsetMatrix = Matrix3.CreateInverseTransform(offset.X, offset.Y, (float) _rotation.Value.Theta);
var ourGridFixtures = fixturesQuery.GetComponent(ourGridId.Value);
// Draw our grid; use non-filled boxes so it doesn't look awful.
DrawGrid(handle, offsetMatrix, ourGridFixtures, Color.Yellow);
DrawDocks(handle, ourGridId.Value, offsetMatrix);
+
+ var ourGridMatrix = xformQuery.GetComponent(ourGridId.Value).InvWorldMatrix;
+
+ Matrix3.Multiply(in ourGridMatrix, in offsetMatrix, out matrix);
}
else
{
matrix = Matrix3.CreateTranslation(-offset);
}
- var invertedPosition = xform.Coordinates.Position - offset;
+ var invertedPosition = _coordinates.Value.Position - offset;
invertedPosition.Y = -invertedPosition.Y;
// Don't need to transform the InvWorldMatrix again as it's already offset to its position.
diff --git a/Content.Client/Shuttles/UI/ShuttleConsoleWindow.xaml.cs b/Content.Client/Shuttles/UI/ShuttleConsoleWindow.xaml.cs
index 4a2d945889..0a52fa33ae 100644
--- a/Content.Client/Shuttles/UI/ShuttleConsoleWindow.xaml.cs
+++ b/Content.Client/Shuttles/UI/ShuttleConsoleWindow.xaml.cs
@@ -7,6 +7,7 @@ using Robust.Client.Graphics;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
+using Robust.Shared.Map;
using Robust.Shared.Utility;
namespace Content.Client.Shuttles.UI;
@@ -17,10 +18,7 @@ public sealed partial class ShuttleConsoleWindow : FancyWindow,
{
private readonly IEntityManager _entManager;
- ///
- /// EntityUid of the open console.
- ///
- private EntityUid? _entity;
+ private EntityUid? _shuttleUid;
///
/// Currently selected dock button for camera.
@@ -84,9 +82,14 @@ public sealed partial class ShuttleConsoleWindow : FancyWindow,
UndockPressed?.Invoke(DockingScreen.ViewedDock.Value);
}
+ public void SetMatrix(EntityCoordinates? coordinates, Angle? angle)
+ {
+ _shuttleUid = coordinates?.EntityId;
+ RadarScreen.SetMatrix(coordinates, angle);
+ }
+
public void UpdateState(ShuttleConsoleBoundInterfaceState scc)
{
- _entity = scc.Entity;
UpdateDocks(scc.Docks);
RadarScreen.UpdateState(scc);
MaxRadarRange.Text = $"{scc.MaxRange:0}";
@@ -110,21 +113,16 @@ public sealed partial class ShuttleConsoleWindow : FancyWindow,
DockPorts.DisposeAllChildren();
DockingScreen.Docks = _docks;
- if (!_entManager.TryGetComponent(_entity, out var xform)
- || !xform.GridUid.HasValue)
- {
- // TODO: Show Placeholder
- return;
- }
- if (_docks.TryGetValue(xform.GridUid.Value, out var gridDocks))
+ // TODO: Show Placeholder
+ if (_shuttleUid != null && _docks.TryGetValue(_shuttleUid.Value, out var gridDocks))
{
var index = 1;
foreach (var state in gridDocks)
{
- var ent = state.Entity;
- var pressed = ent == DockingScreen.ViewedDock;
+ var pressed = state.Entity == DockingScreen.ViewedDock;
+
string suffix;
if (state.Connected)
@@ -143,21 +141,26 @@ public sealed partial class ShuttleConsoleWindow : FancyWindow,
Pressed = pressed,
};
- button.OnMouseEntered += args => OnDockMouseEntered(args, ent);
- button.OnMouseExited += args => OnDockMouseExited(args, ent);
- button.OnToggled += args => OnDockToggled(args, ent);
+ if (pressed)
+ {
+ _selectedDock = button;
+ }
+
+ button.OnMouseEntered += args => OnDockMouseEntered(args, state);
+ button.OnMouseExited += args => OnDockMouseExited(args, state);
+ button.OnToggled += args => OnDockToggled(args, state);
DockPorts.AddChild(button);
index++;
}
}
}
- private void OnDockMouseEntered(GUIMouseHoverEventArgs obj, EntityUid uid)
+ private void OnDockMouseEntered(GUIMouseHoverEventArgs obj, DockingInterfaceState state)
{
- RadarScreen.HighlightedDock = uid;
+ RadarScreen.HighlightedDock = state.Entity;
}
- private void OnDockMouseExited(GUIMouseHoverEventArgs obj, EntityUid uid)
+ private void OnDockMouseExited(GUIMouseHoverEventArgs obj, DockingInterfaceState state)
{
RadarScreen.HighlightedDock = null;
}
@@ -165,10 +168,18 @@ public sealed partial class ShuttleConsoleWindow : FancyWindow,
///
/// Shows a docking camera instead of radar screen.
///
- private void OnDockToggled(BaseButton.ButtonEventArgs obj, EntityUid ent)
+ private void OnDockToggled(BaseButton.ButtonEventArgs obj, DockingInterfaceState state)
{
+ var ent = state.Entity;
+
if (_selectedDock != null)
{
+ // If it got untoggled via other means then we'll stop viewing the old dock.
+ if (DockingScreen.ViewedDock != null && DockingScreen.ViewedDock != state.Entity)
+ {
+ StopAutodockPressed?.Invoke(DockingScreen.ViewedDock.Value);
+ }
+
_selectedDock.Pressed = false;
_selectedDock = null;
}
@@ -187,15 +198,23 @@ public sealed partial class ShuttleConsoleWindow : FancyWindow,
}
else
{
- // DebugTools.Assert(DockingScreen.ViewedDock == null);
- _entManager.TryGetComponent(_entity, out var xform);
+ if (_shuttleUid != null)
+ {
+ DockingScreen.Coordinates = state.Coordinates;
+ DockingScreen.Angle = state.Angle;
+ }
+ else
+ {
+ DockingScreen.Coordinates = null;
+ DockingScreen.Angle = null;
+ }
UndockButton.Disabled = false;
RadarScreen.Visible = false;
DockingScreen.Visible = true;
DockingScreen.ViewedDock = ent;
StartAutodockPressed?.Invoke(ent);
- DockingScreen.GridEntity = xform?.GridUid;
+ DockingScreen.GridEntity = _shuttleUid;
_selectedDock = obj.Button;
}
}
@@ -215,9 +234,8 @@ public sealed partial class ShuttleConsoleWindow : FancyWindow,
{
base.Draw(handle);
- if (!_entManager.TryGetComponent(_entity, out var entXform) ||
- !_entManager.TryGetComponent(entXform.GridUid, out var gridBody) ||
- !_entManager.TryGetComponent(entXform.GridUid, out var gridXform))
+ if (!_entManager.TryGetComponent(_shuttleUid, out var gridBody) ||
+ !_entManager.TryGetComponent(_shuttleUid, out var gridXform))
{
return;
}
diff --git a/Content.IntegrationTests/Tests/CargoTest.cs b/Content.IntegrationTests/Tests/CargoTest.cs
new file mode 100644
index 0000000000..4ce1d3a720
--- /dev/null
+++ b/Content.IntegrationTests/Tests/CargoTest.cs
@@ -0,0 +1,39 @@
+using System.Threading.Tasks;
+using Content.Server.Cargo.Systems;
+using Content.Shared.Cargo.Prototypes;
+using NUnit.Framework;
+using Robust.Shared.GameObjects;
+using Robust.Shared.Map;
+using Robust.Shared.Maths;
+using Robust.Shared.Prototypes;
+
+namespace Content.IntegrationTests.Tests;
+
+[TestFixture]
+public sealed class CargoTest
+{
+ [Test]
+ public async Task NoArbitrage()
+ {
+ await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings() {NoClient = true});
+ var server = pairTracker.Pair.Server;
+
+ var entManager = server.ResolveDependency();
+ var mapManager = server.ResolveDependency();
+ var protoManager = server.ResolveDependency();
+ var pricing = server.ResolveDependency().GetEntitySystem();
+
+ await server.WaitAssertion(() =>
+ {
+ var mapId = mapManager.CreateMap();
+
+ foreach (var proto in protoManager.EnumeratePrototypes())
+ {
+ var ent = entManager.SpawnEntity(proto.Product, new MapCoordinates(Vector2.Zero, mapId));
+ var price = pricing.GetPrice(ent);
+
+ Assert.That(price, Is.LessThan(proto.PointCost), $"Found arbitrage on {proto.ID} cargo product!");
+ }
+ });
+ }
+}
diff --git a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Commands.cs b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Commands.cs
index 585160ee47..149ce7e353 100644
--- a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Commands.cs
+++ b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Commands.cs
@@ -57,8 +57,6 @@ public sealed partial class AtmosphereSystem
mixtures[5].AdjustMoles(Gas.Plasma, Atmospherics.MolesCellGasMiner);
mixtures[5].Temperature = 5000f;
- var entMan = IoCManager.Resolve();
-
foreach (var gid in args)
{
if(!EntityUid.TryParse(gid, out var euid))
diff --git a/Content.Server/Cargo/CargoBankAccount.cs b/Content.Server/Cargo/CargoBankAccount.cs
deleted file mode 100644
index 3dbe7da5c1..0000000000
--- a/Content.Server/Cargo/CargoBankAccount.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-namespace Content.Server.Cargo
-{
- public sealed class CargoBankAccount : ICargoBankAccount
- {
- [ViewVariables]
- public int Id { get; }
- [ViewVariables]
- public string Name { get; }
-
- private int _balance;
- [ViewVariables(VVAccess.ReadWrite)]
- public int Balance
- {
- get => _balance;
- set
- {
- if (_balance == value)
- return;
- _balance = value;
- OnBalanceChange?.Invoke();
- }
- }
-
- public event Action? OnBalanceChange;
-
- public CargoBankAccount(int id, string name, int balance)
- {
- Id = id;
- Name = name;
- Balance = balance;
- }
- }
-}
diff --git a/Content.Server/Cargo/CargoOrderDatabase.cs b/Content.Server/Cargo/CargoOrderDatabase.cs
deleted file mode 100644
index fdf517a265..0000000000
--- a/Content.Server/Cargo/CargoOrderDatabase.cs
+++ /dev/null
@@ -1,129 +0,0 @@
-using System.Diagnostics.CodeAnalysis;
-using System.Linq;
-using Content.Shared.Cargo;
-
-namespace Content.Server.Cargo
-{
- public sealed class CargoOrderDatabase
- {
- private readonly Dictionary _orders = new();
- private int _orderNumber = 0;
-
- public CargoOrderDatabase(int id)
- {
- Id = id;
- CurrentOrderSize = 0;
- MaxOrderSize = 20;
- }
-
- public int Id { get; private set; }
- public int CurrentOrderSize { get; private set; }
- public int MaxOrderSize { get; private set; }
-
- ///
- /// Removes all orders from the database.
- ///
- public void Clear()
- {
- _orders.Clear();
- }
-
- ///
- /// Returns a list of all orders.
- ///
- /// A list of orders
- public List GetOrders()
- {
- return _orders.Values.ToList();
- }
-
- public bool TryGetOrder(int id, [NotNullWhen(true)] out CargoOrderData? order)
- {
- return _orders.TryGetValue(id, out order);
- }
-
- public List SpliceApproved()
- {
- var orders = _orders.Values.Where(order => order.Approved).ToList();
- foreach (var order in orders)
- _orders.Remove(order.OrderNumber);
- return orders;
- }
-
- ///
- /// Adds an order to the database.
- ///
- /// The person who requested the item.
- /// The reason the product was requested.
- /// The ID of the product requested.
- /// The amount of the products requested.
- /// The ID of the bank account paying for the order.
- /// Whether the order will be bought when the orders are processed.
- public void AddOrder(string requester, string reason, string productId, int amount, int payingAccountId)
- {
- var order = new CargoOrderData(_orderNumber, requester, reason, productId, amount, payingAccountId);
- if (Contains(order))
- return;
- _orders.Add(_orderNumber, order);
- _orderNumber += 1;
- }
-
- ///
- /// Removes an order from the database.
- ///
- /// The order to be removed.
- /// Whether it could be removed or not
- public bool RemoveOrder(int orderNumber)
- {
- return _orders.Remove(orderNumber);
- }
-
- ///
- /// Approves an order in the database.
- ///
- /// The order to be approved.
- public bool ApproveOrder(string approver, int orderNumber)
- {
- if (CurrentOrderSize == MaxOrderSize ||
- !_orders.TryGetValue(orderNumber, out var order) ||
- order.Approved)
- {
- return false;
- }
- else if (CurrentOrderSize + order.Amount > MaxOrderSize)
- {
- AddOrder(
- order.Requester,
- Loc.GetString("cargo-order-database-order-overflow-message", ("placeholder", order.Reason.Replace(" (Overflow)", string.Empty))),
- order.ProductId,
- order.Amount - MaxOrderSize - CurrentOrderSize, order.PayingAccountId);
-
- order.Amount = MaxOrderSize - CurrentOrderSize;
- }
-
- order.Approved = true;
- order.Approver = approver;
-
- CurrentOrderSize += order.Amount;
- return true;
- }
-
- ///
- /// Returns whether the database contains the order or not.
- ///
- /// The order to check
- /// Whether the database contained the order or not.
- public bool Contains(CargoOrderData order)
- {
- return _orders.ContainsValue(order);
- }
-
- ///
- /// Clears the current order capacity. This allows more orders to be processed and is invoked after an order is dispatched.
- ///
- public void ClearOrderCapacity()
- {
- CurrentOrderSize = 0;
- }
- }
-}
diff --git a/Content.Server/Cargo/Components/CargoConsoleComponent.cs b/Content.Server/Cargo/Components/CargoConsoleComponent.cs
deleted file mode 100644
index 890b8ac3ca..0000000000
--- a/Content.Server/Cargo/Components/CargoConsoleComponent.cs
+++ /dev/null
@@ -1,205 +0,0 @@
-using Content.Server.Cargo.Systems;
-using Content.Server.Power.Components;
-using Content.Server.UserInterface;
-using Content.Shared.Cargo;
-using Content.Shared.Cargo.Components;
-using Content.Shared.Sound;
-using Content.Server.MachineLinking.Components;
-using Content.Shared.MachineLinking;
-using Robust.Server.GameObjects;
-using Robust.Shared.Audio;
-using Robust.Shared.Player;
-using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
-
-namespace Content.Server.Cargo.Components
-{
- [RegisterComponent]
- public sealed class CargoConsoleComponent : SharedCargoConsoleComponent
- {
- [Dependency] private readonly IEntityManager _entMan = default!;
-
- private CargoBankAccount? _bankAccount;
-
- [ViewVariables]
- public CargoBankAccount? BankAccount
- {
- get => _bankAccount;
- private set
- {
- if (_bankAccount == value)
- {
- return;
- }
-
- if (_bankAccount != null)
- {
- _bankAccount.OnBalanceChange -= UpdateUIState;
- }
-
- _bankAccount = value;
-
- if (value != null)
- {
- value.OnBalanceChange += UpdateUIState;
- }
-
- UpdateUIState();
- }
- }
-
- [DataField("requestOnly")]
- private bool _requestOnly = false;
-
- [DataField("errorSound")]
- private SoundSpecifier _errorSound = new SoundPathSpecifier("/Audio/Effects/error.ogg");
-
- private bool Powered => !_entMan.TryGetComponent(Owner, out ApcPowerReceiverComponent? receiver) || receiver.Powered;
- private CargoSystem _cargoConsoleSystem = default!;
-
- [ViewVariables] private BoundUserInterface? UserInterface => Owner.GetUIOrNull(CargoConsoleUiKey.Key);
-
- [DataField("senderPort", customTypeSerializer: typeof(PrototypeIdSerializer))]
- public string SenderPort = "OrderSender";
-
- protected override void Initialize()
- {
- base.Initialize();
-
- Owner.EnsureComponentWarn(out CargoOrderDatabaseComponent _);
-
- if (UserInterface != null)
- {
- UserInterface.OnReceiveMessage += UserInterfaceOnOnReceiveMessage;
- }
-
- _cargoConsoleSystem = EntitySystem.Get();
- BankAccount = _cargoConsoleSystem.StationAccount;
- }
-
- protected override void OnRemove()
- {
- if (UserInterface != null)
- {
- UserInterface.OnReceiveMessage -= UserInterfaceOnOnReceiveMessage;
- }
-
- base.OnRemove();
- }
-
- private void UserInterfaceOnOnReceiveMessage(ServerBoundUserInterfaceMessage serverMsg)
- {
- if (!_entMan.TryGetComponent(Owner, out CargoOrderDatabaseComponent? orders))
- {
- return;
- }
-
- var message = serverMsg.Message;
- if (orders.Database == null)
- return;
- if (!Powered)
- return;
- switch (message)
- {
- case CargoConsoleAddOrderMessage msg:
- {
- if (msg.Amount <= 0 || _bankAccount == null)
- {
- break;
- }
-
- if (!_cargoConsoleSystem.AddOrder(orders.Database.Id, msg.Requester, msg.Reason, msg.ProductId,
- msg.Amount, _bankAccount.Id))
- {
- SoundSystem.Play(_errorSound.GetSound(), Filter.Pvs(Owner), Owner, AudioParams.Default);
- }
- break;
- }
- case CargoConsoleRemoveOrderMessage msg:
- {
- _cargoConsoleSystem.RemoveOrder(orders.Database.Id, msg.OrderNumber);
- break;
- }
- case CargoConsoleApproveOrderMessage msg:
- {
- if (_requestOnly ||
- !orders.Database.TryGetOrder(msg.OrderNumber, out var order) ||
- _bankAccount == null)
- {
- break;
- }
-
- if (msg.Session.AttachedEntity is not {Valid: true} player)
- break;
-
- PrototypeManager.TryIndex(order.ProductId, out CargoProductPrototype? product);
- if (product == null!)
- break;
- var capacity = _cargoConsoleSystem.GetCapacity(orders.Database.Id);
- if (
- (capacity.CurrentCapacity == capacity.MaxCapacity
- || capacity.CurrentCapacity + order.Amount > capacity.MaxCapacity
- || !_cargoConsoleSystem.CheckBalance(_bankAccount.Id, (-product.PointCost) * order.Amount)
- || !_cargoConsoleSystem.ApproveOrder(Owner, player, orders.Database.Id, msg.OrderNumber)
- || !_cargoConsoleSystem.ChangeBalance(_bankAccount.Id, (-product.PointCost) * order.Amount))
- )
- {
- SoundSystem.Play(_errorSound.GetSound(), Filter.Pvs(Owner), Owner, AudioParams.Default);
- break;
- }
-
- UpdateUIState();
- break;
- }
- case CargoConsoleShuttleMessage _:
- {
- // Jesus fucking christ Glass
- //var approvedOrders = _cargoOrderDataManager.RemoveAndGetApprovedFrom(orders.Database);
- //orders.Database.ClearOrderCapacity();
-
- // TODO replace with shuttle code
- EntityUid? cargoTelepad = null;
-
- if (_entMan.TryGetComponent(Owner, out var transmitter) &&
- transmitter.Outputs.TryGetValue(SenderPort, out var telepad) &&
- telepad.Count > 0)
- {
- // use most recent link
- var pad = telepad[^1].Uid;
- if (_entMan.HasComponent(pad) &&
- _entMan.TryGetComponent(pad, out var powerReceiver) &&
- powerReceiver.Powered)
- cargoTelepad = pad;
- }
-
- if (cargoTelepad != null)
- {
- if (_entMan.TryGetComponent(cargoTelepad.Value, out var telepadComponent))
- {
- var approvedOrders = _cargoConsoleSystem.RemoveAndGetApprovedOrders(orders.Database.Id);
- orders.Database.ClearOrderCapacity();
- foreach (var order in approvedOrders)
- {
- _cargoConsoleSystem.QueueTeleport(telepadComponent, order);
- }
- }
- }
- break;
- }
- }
- }
-
- private void UpdateUIState()
- {
- if (_bankAccount == null || !_entMan.EntityExists(Owner))
- {
- return;
- }
-
- var id = _bankAccount.Id;
- var name = _bankAccount.Name;
- var balance = _bankAccount.Balance;
- var capacity = _cargoConsoleSystem.GetCapacity(id);
- UserInterface?.SetState(new CargoConsoleInterfaceState(_requestOnly, id, name, balance, capacity));
- }
- }
-}
diff --git a/Content.Server/Cargo/Components/CargoOrderConsoleComponent.cs b/Content.Server/Cargo/Components/CargoOrderConsoleComponent.cs
new file mode 100644
index 0000000000..8e1687427e
--- /dev/null
+++ b/Content.Server/Cargo/Components/CargoOrderConsoleComponent.cs
@@ -0,0 +1,17 @@
+using Content.Shared.Sound;
+
+namespace Content.Server.Cargo.Components
+{
+ ///
+ /// Handles sending order requests to cargo. Doesn't handle orders themselves via shuttle or telepads.
+ ///
+ [RegisterComponent]
+ public sealed class CargoOrderConsoleComponent : Component
+ {
+ [DataField("soundError")] public SoundSpecifier ErrorSound =
+ new SoundPathSpecifier("/Audio/Effects/Cargo/buzz_sigh.ogg");
+
+ [DataField("soundConfirm")]
+ public SoundSpecifier ConfirmSound = new SoundPathSpecifier("/Audio/Effects/Cargo/ping.ogg");
+ }
+}
diff --git a/Content.Server/Cargo/Components/CargoOrderDatabaseComponent.cs b/Content.Server/Cargo/Components/CargoOrderDatabaseComponent.cs
deleted file mode 100644
index 10489ec406..0000000000
--- a/Content.Server/Cargo/Components/CargoOrderDatabaseComponent.cs
+++ /dev/null
@@ -1,26 +0,0 @@
-using Content.Server.Cargo.Systems;
-using Content.Shared.Cargo.Components;
-
-namespace Content.Server.Cargo.Components
-{
- [RegisterComponent]
- public sealed class CargoOrderDatabaseComponent : SharedCargoOrderDatabaseComponent
- {
- public CargoOrderDatabase? Database { get; set; }
- public bool ConnectedToDatabase => Database != null;
-
- protected override void Initialize()
- {
- base.Initialize();
-
- Database = EntitySystem.Get().StationOrderDatabase;
- }
-
- public override ComponentState GetComponentState()
- {
- if (!ConnectedToDatabase)
- return new CargoOrderDatabaseState(null);
- return new CargoOrderDatabaseState(Database?.GetOrders());
- }
- }
-}
diff --git a/Content.Server/Cargo/Components/CargoPalletComponent.cs b/Content.Server/Cargo/Components/CargoPalletComponent.cs
new file mode 100644
index 0000000000..24fd2eda9e
--- /dev/null
+++ b/Content.Server/Cargo/Components/CargoPalletComponent.cs
@@ -0,0 +1,7 @@
+namespace Content.Server.Cargo.Components;
+
+///
+/// Any entities intersecting when a shuttle is recalled will be sold.
+///
+[RegisterComponent]
+public sealed class CargoPalletComponent : Component {}
diff --git a/Content.Server/Cargo/Components/CargoPilotConsoleComponent.cs b/Content.Server/Cargo/Components/CargoPilotConsoleComponent.cs
new file mode 100644
index 0000000000..6b7ccfcf16
--- /dev/null
+++ b/Content.Server/Cargo/Components/CargoPilotConsoleComponent.cs
@@ -0,0 +1,15 @@
+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/CargoShuttleConsoleComponent.cs b/Content.Server/Cargo/Components/CargoShuttleConsoleComponent.cs
new file mode 100644
index 0000000000..a7ff0185cf
--- /dev/null
+++ b/Content.Server/Cargo/Components/CargoShuttleConsoleComponent.cs
@@ -0,0 +1,10 @@
+using Content.Shared.Sound;
+
+namespace Content.Server.Cargo.Components;
+
+[RegisterComponent]
+public sealed class CargoShuttleConsoleComponent : Component
+{
+ [ViewVariables(VVAccess.ReadWrite), DataField("soundDeny")]
+ public SoundSpecifier DenySound = new SoundPathSpecifier("/Audio/Effects/Cargo/buzz_two.ogg");
+}
diff --git a/Content.Server/Cargo/Components/CargoTelepadComponent.cs b/Content.Server/Cargo/Components/CargoTelepadComponent.cs
index 00a6e4c5c3..1b946d1693 100644
--- a/Content.Server/Cargo/Components/CargoTelepadComponent.cs
+++ b/Content.Server/Cargo/Components/CargoTelepadComponent.cs
@@ -15,7 +15,7 @@ namespace Content.Server.Cargo.Components
public sealed class CargoTelepadComponent : SharedCargoTelepadComponent
{
[DataField("delay")]
- public float Delay = 20f;
+ public float Delay = 45f;
///
/// How much time we've accumulated until next teleport.
@@ -24,9 +24,6 @@ namespace Content.Server.Cargo.Components
[DataField("accumulator")]
public float Accumulator = 0f;
- [ViewVariables]
- public readonly Stack TeleportQueue = new();
-
[ViewVariables]
public CargoTelepadState CurrentState = CargoTelepadState.Unpowered;
diff --git a/Content.Server/Cargo/Components/StationBankAccountComponent.cs b/Content.Server/Cargo/Components/StationBankAccountComponent.cs
new file mode 100644
index 0000000000..a2d56b3fd8
--- /dev/null
+++ b/Content.Server/Cargo/Components/StationBankAccountComponent.cs
@@ -0,0 +1,19 @@
+using Content.Shared.Cargo;
+
+namespace Content.Server.Cargo.Components;
+
+///
+/// Added to the abstract representation of a station to track its money.
+///
+[RegisterComponent, Access(typeof(SharedCargoSystem))]
+public sealed class StationBankAccountComponent : Component
+{
+ [ViewVariables(VVAccess.ReadWrite), DataField("balance")]
+ public int Balance = 2000;
+
+ ///
+ /// How much the bank balance goes up per second, every Delay period. Rounded down when multiplied.
+ ///
+ [ViewVariables(VVAccess.ReadWrite), DataField("increasePerSecond")]
+ public int IncreasePerSecond = 10;
+}
diff --git a/Content.Server/Cargo/Components/StationCargoOrderDatabaseComponent.cs b/Content.Server/Cargo/Components/StationCargoOrderDatabaseComponent.cs
new file mode 100644
index 0000000000..a3e5ab644d
--- /dev/null
+++ b/Content.Server/Cargo/Components/StationCargoOrderDatabaseComponent.cs
@@ -0,0 +1,33 @@
+using Content.Shared.Cargo;
+
+namespace Content.Server.Cargo.Components;
+
+///
+/// Stores all of cargo orders for a particular station.
+///
+[RegisterComponent]
+public sealed class StationCargoOrderDatabaseComponent : Component
+{
+ ///
+ /// Maximum amount of orders a station is allowed, approved or not.
+ ///
+ [ViewVariables(VVAccess.ReadWrite), DataField("capacity")]
+ public int Capacity = 20;
+
+ [ViewVariables(VVAccess.ReadWrite), DataField("orders")]
+ public Dictionary Orders = new();
+
+ ///
+ /// Tracks the next order index available.
+ ///
+ public int Index;
+
+ [ViewVariables, DataField("cargoShuttleProto")]
+ public string? CargoShuttleProto = "CargoShuttle";
+
+ ///
+ /// The cargo shuttle assigned to this station.
+ ///
+ [ViewVariables, DataField("shuttle")]
+ public EntityUid? Shuttle;
+}
diff --git a/Content.Server/Cargo/ICargoBankAccount.cs b/Content.Server/Cargo/ICargoBankAccount.cs
deleted file mode 100644
index d7a22448ac..0000000000
--- a/Content.Server/Cargo/ICargoBankAccount.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-namespace Content.Server.Cargo
-{
- public interface ICargoBankAccount
- {
- int Id { get; }
- string Name { get; }
- int Balance { get; }
- public event Action OnBalanceChange;
- }
-}
diff --git a/Content.Server/Cargo/Systems/CargoSystem.Console.cs b/Content.Server/Cargo/Systems/CargoSystem.Console.cs
deleted file mode 100644
index 3659d5f9b8..0000000000
--- a/Content.Server/Cargo/Systems/CargoSystem.Console.cs
+++ /dev/null
@@ -1,240 +0,0 @@
-using System.Diagnostics.CodeAnalysis;
-using Content.Server.Access.Systems;
-using Content.Server.Cargo.Components;
-using Content.Server.MachineLinking.System;
-using Content.Shared.Access.Components;
-using Content.Shared.Access.Systems;
-using Content.Shared.Cargo;
-using Content.Shared.GameTicking;
-
-namespace Content.Server.Cargo.Systems
-{
- public sealed partial class CargoSystem
- {
- ///
- /// How much time to wait (in seconds) before increasing bank accounts balance.
- ///
- private const float Delay = 10f;
- ///
- /// How many points to give to every bank account every seconds.
- ///
- private const int PointIncrease = 150;
-
- ///
- /// Keeps track of how much time has elapsed since last balance increase.
- ///
- private float _timer;
- ///
- /// Stores all bank accounts.
- ///
- private readonly Dictionary _accountsDict = new();
-
- private readonly Dictionary _databasesDict = new();
- ///
- /// Used to assign IDs to bank accounts. Incremental counter.
- ///
- private int _accountIndex;
- ///
- /// Enumeration of all bank accounts.
- ///
- public IEnumerable BankAccounts => _accountsDict.Values;
- ///
- /// The station's bank account.
- ///
- public CargoBankAccount StationAccount => GetBankAccount(0);
-
- public CargoOrderDatabase StationOrderDatabase => GetOrderDatabase(0);
-
- [Dependency] private readonly IdCardSystem _idCardSystem = default!;
- [Dependency] private readonly AccessReaderSystem _accessReaderSystem = default!;
- [Dependency] private readonly SignalLinkerSystem _linker = default!;
-
- private void InitializeConsole()
- {
- SubscribeLocalEvent(OnInit);
- SubscribeLocalEvent(Reset);
- Reset();
- }
- private void OnInit(EntityUid uid, CargoConsoleComponent console, ComponentInit args)
- {
- _linker.EnsureTransmitterPorts(uid, console.SenderPort);
- }
-
- private void Reset(RoundRestartCleanupEvent ev)
- {
- Reset();
- }
-
- private void Reset()
- {
- _accountsDict.Clear();
- _databasesDict.Clear();
- _timer = 0;
- _accountIndex = 0;
-
- CreateBankAccount("Space Station 14", 1000);
- CreateOrderDatabase(0);
- }
-
- private void UpdateConsole(float frameTime)
- {
- _timer += frameTime;
-
- while (_timer > Delay)
- {
- _timer -= Delay;
-
- foreach (var account in BankAccounts)
- {
- account.Balance += PointIncrease;
- }
- }
- }
-
- ///
- /// Creates a new bank account.
- ///
- public void CreateBankAccount(string name, int balance)
- {
- var account = new CargoBankAccount(_accountIndex, name, balance);
- _accountsDict.Add(_accountIndex, account);
- _accountIndex += 1;
- }
-
- public void CreateOrderDatabase(int id)
- {
- _databasesDict.Add(id, new CargoOrderDatabase(id));
- }
-
- ///
- /// Returns the bank account associated with the given ID.
- ///
- public CargoBankAccount GetBankAccount(int id)
- {
- return _accountsDict[id];
- }
-
- public CargoOrderDatabase GetOrderDatabase(int id)
- {
- return _databasesDict[id];
- }
-
- ///
- /// Returns whether the account exists, eventually passing the account in the out parameter.
- ///
- public bool TryGetBankAccount(int id, [NotNullWhen(true)] out CargoBankAccount? account)
- {
- return _accountsDict.TryGetValue(id, out account);
- }
-
- public bool TryGetOrderDatabase(int id, [NotNullWhen(true)] out CargoOrderDatabase? database)
- {
- return _databasesDict.TryGetValue(id, out database);
- }
- ///
- /// Verifies if there is enough money in the account's balance to pay the amount.
- /// Returns false if there's no account associated with the given ID
- /// or if the balance would end up being negative.
- ///
- public bool CheckBalance(int id, int amount)
- {
- if (!TryGetBankAccount(id, out var account))
- {
- return false;
- }
-
- if (account.Balance + amount < 0)
- {
- return false;
- }
-
- return true;
- }
- ///
- /// Attempts to change the given account's balance.
- /// Returns false if there's no account associated with the given ID
- /// or if the balance would end up being negative.
- ///
- public bool ChangeBalance(int id, int amount)
- {
- if (!TryGetBankAccount(id, out var account))
- {
- return false;
- }
-
- account.Balance += amount;
- return true;
- }
-
- public bool AddOrder(int id, string requester, string reason, string productId, int amount, int payingAccountId)
- {
- if (amount < 1 || !TryGetOrderDatabase(id, out var database) || amount > database.MaxOrderSize)
- {
- return false;
- }
-
- database.AddOrder(requester, reason, productId, amount, payingAccountId);
- SyncComponentsWithId(id);
- return true;
- }
-
- public bool RemoveOrder(int id, int orderNumber)
- {
- if (!TryGetOrderDatabase(id, out var database))
- return false;
- database.RemoveOrder(orderNumber);
- SyncComponentsWithId(id);
- return true;
- }
-
- public bool ApproveOrder(EntityUid uid, EntityUid approver, int id, int orderNumber, AccessReaderComponent? reader = null)
- {
- // does the approver have permission to approve orders?
- if (Resolve(uid, ref reader) && !_accessReaderSystem.IsAllowed(approver, reader))
- return false;
-
- // get the approver's name
- _idCardSystem.TryFindIdCard(approver, out var idCard);
- var approverName = idCard?.FullName ?? string.Empty;
-
- if (!TryGetOrderDatabase(id, out var database))
- return false;
-
- if (!database.TryGetOrder(orderNumber, out var order))
- return false;
-
- if (!database.ApproveOrder(approverName, orderNumber))
- return false;
-
- SyncComponentsWithId(id);
- return true;
- }
-
- public List RemoveAndGetApprovedOrders(int id)
- {
- if (!TryGetOrderDatabase(id, out var database))
- return new List();
- var approvedOrders = database.SpliceApproved();
- SyncComponentsWithId(id);
- return approvedOrders;
- }
-
- public (int CurrentCapacity, int MaxCapacity) GetCapacity(int id)
- {
- if (!TryGetOrderDatabase(id, out var database))
- return (0,0);
- return (database.CurrentOrderSize, database.MaxOrderSize);
- }
-
- private void SyncComponentsWithId(int id)
- {
- foreach (var comp in EntityManager.EntityQuery(true))
- {
- if (comp.Database == null || comp.Database.Id != id)
- continue;
-
- Dirty(comp);
- }
- }
- }
-}
diff --git a/Content.Server/Cargo/Systems/CargoSystem.Orders.cs b/Content.Server/Cargo/Systems/CargoSystem.Orders.cs
new file mode 100644
index 0000000000..ccee28f087
--- /dev/null
+++ b/Content.Server/Cargo/Systems/CargoSystem.Orders.cs
@@ -0,0 +1,324 @@
+using System.Linq;
+using Content.Server.Access.Systems;
+using Content.Server.Cargo.Components;
+using Content.Server.MachineLinking.System;
+using Content.Server.Popups;
+using Content.Server.Station.Systems;
+using Content.Shared.Access.Systems;
+using Content.Shared.Cargo;
+using Content.Shared.Cargo.BUI;
+using Content.Shared.Cargo.Events;
+using Content.Shared.Cargo.Prototypes;
+using Content.Shared.GameTicking;
+using Robust.Server.GameObjects;
+using Robust.Shared.Audio;
+using Robust.Shared.Player;
+using Robust.Shared.Players;
+
+namespace Content.Server.Cargo.Systems
+{
+ public sealed partial class CargoSystem
+ {
+ ///
+ /// How much time to wait (in seconds) before increasing bank accounts balance.
+ ///
+ private const int Delay = 10;
+
+ ///
+ /// Keeps track of how much time has elapsed since last balance increase.
+ ///
+ private float _timer;
+
+ [Dependency] private readonly IdCardSystem _idCardSystem = default!;
+ [Dependency] private readonly AccessReaderSystem _accessReaderSystem = default!;
+ [Dependency] private readonly SignalLinkerSystem _linker = default!;
+ [Dependency] private readonly PopupSystem _popup = default!;
+ [Dependency] private readonly StationSystem _station = default!;
+ [Dependency] private readonly UserInterfaceSystem _uiSystem = default!;
+
+ private void InitializeConsole()
+ {
+ SubscribeLocalEvent(OnAddOrderMessage);
+ SubscribeLocalEvent(OnRemoveOrderMessage);
+ SubscribeLocalEvent(OnApproveOrderMessage);
+ SubscribeLocalEvent(OnOrderUIOpened);
+ SubscribeLocalEvent(OnInit);
+ SubscribeLocalEvent(Reset);
+ Reset();
+ }
+
+ private void OnInit(EntityUid uid, CargoOrderConsoleComponent orderConsole, ComponentInit args)
+ {
+ var station = _station.GetOwningStation(uid);
+ UpdateOrderState(orderConsole, station);
+ }
+
+ private void Reset(RoundRestartCleanupEvent ev)
+ {
+ Reset();
+ }
+
+ private void Reset()
+ {
+ _timer = 0;
+ }
+
+ private void UpdateConsole(float frameTime)
+ {
+ _timer += frameTime;
+
+ while (_timer > Delay)
+ {
+ _timer -= Delay;
+
+ foreach (var account in EntityQuery())
+ {
+ account.Balance += account.IncreasePerSecond * Delay;
+ }
+
+ foreach (var comp in EntityQuery())
+ {
+ if (!_uiSystem.IsUiOpen(comp.Owner, CargoConsoleUiKey.Orders)) continue;
+
+ var station = _station.GetOwningStation(comp.Owner);
+ UpdateOrderState(comp, station);
+ }
+ }
+ }
+
+ #region Interface
+
+ private void OnApproveOrderMessage(EntityUid uid, CargoOrderConsoleComponent component, CargoConsoleApproveOrderMessage args)
+ {
+ if (args.Session.AttachedEntity is not {Valid: true} player)
+ return;
+
+ if (!_accessReaderSystem.IsAllowed(player, uid))
+ {
+ ConsolePopup(args.Session, Loc.GetString("cargo-console-order-not-allowed"));
+ PlayDenySound(uid, component);
+ return;
+ }
+
+ var orderDatabase = GetOrderDatabase(component);
+ var bankAccount = GetBankAccount(component);
+
+ // No station to deduct from.
+ if (orderDatabase == null || bankAccount == null)
+ {
+ ConsolePopup(args.Session, Loc.GetString("cargo-console-station-not-found"));
+ PlayDenySound(uid, component);
+ return;
+ }
+
+ // No order to approve?
+ if (!orderDatabase.Orders.TryGetValue(args.OrderNumber, out var order) ||
+ order.Approved) return;
+
+ // Invalid order
+ if (!_protoMan.TryIndex(order.ProductId, out var product))
+ {
+ ConsolePopup(args.Session, Loc.GetString("cargo-console-invalid-product"));
+ PlayDenySound(uid, component);
+ return;
+ }
+
+ var amount = GetOrderCount(orderDatabase);
+ var capacity = orderDatabase.Capacity;
+
+ // Too many orders, avoid them getting spammed in the UI.
+ if (amount >= capacity)
+ {
+ ConsolePopup(args.Session, Loc.GetString("cargo-console-too-many"));
+ PlayDenySound(uid, component);
+ return;
+ }
+
+ // Cap orders so someone can't spam thousands.
+ var orderAmount = Math.Min(capacity - amount, order.Amount);
+
+ if (orderAmount != order.Amount)
+ {
+ order.Amount = orderAmount;
+ ConsolePopup(args.Session, Loc.GetString("cargo-console-snip-snip"));
+ PlayDenySound(uid, component);
+ }
+
+ var cost = product.PointCost * order.Amount;
+
+ // Not enough balance
+ if (cost > bankAccount.Balance)
+ {
+ ConsolePopup(args.Session, Loc.GetString("cargo-console-insufficient-funds", ("cost", cost)));
+ PlayDenySound(uid, component);
+ return;
+ }
+
+ order.Approved = true;
+ _idCardSystem.TryFindIdCard(player, out var idCard);
+ order.Approver = idCard?.FullName ?? string.Empty;
+
+
+ SoundSystem.Play(component.ConfirmSound.GetSound(), Filter.Pvs(uid, entityManager: EntityManager), uid);
+
+ DeductFunds(bankAccount, cost);
+ UpdateOrders(orderDatabase);
+ }
+
+ private void OnRemoveOrderMessage(EntityUid uid, CargoOrderConsoleComponent component, CargoConsoleRemoveOrderMessage args)
+ {
+ var orderDatabase = GetOrderDatabase(component);
+ if (orderDatabase == null) return;
+ RemoveOrder(orderDatabase, args.OrderNumber);
+ }
+
+ private void OnAddOrderMessage(EntityUid uid, CargoOrderConsoleComponent component, CargoConsoleAddOrderMessage args)
+ {
+ if (args.Amount <= 0)
+ return;
+
+ var bank = GetBankAccount(component);
+ if (bank == null) return;
+ var orderDatabase = GetOrderDatabase(component);
+ if (orderDatabase == null) return;
+
+ var data = GetOrderData(args, GetNextIndex(orderDatabase));
+
+ if (!TryAddOrder(orderDatabase, data))
+ {
+ PlayDenySound(uid, component);
+ return;
+ }
+ }
+
+ private void OnOrderUIOpened(EntityUid uid, CargoOrderConsoleComponent component, BoundUIOpenedEvent args)
+ {
+ var station = _station.GetOwningStation(uid);
+ UpdateOrderState(component, station);
+ }
+
+ #endregion
+
+ private void UpdateOrderState(CargoOrderConsoleComponent component, EntityUid? station)
+ {
+ if (station == null ||
+ !TryComp(station, out var orderDatabase) ||
+ !TryComp(station, out var bankAccount)) return;
+
+ var state = new CargoConsoleInterfaceState(
+ MetaData(station.Value).EntityName,
+ GetOrderCount(orderDatabase),
+ orderDatabase.Capacity,
+ bankAccount.Balance,
+ orderDatabase.Orders.Values.ToList());
+
+ _uiSystem.GetUiOrNull(component.Owner, CargoConsoleUiKey.Orders)?.SetState(state);
+ }
+
+ private void ConsolePopup(ICommonSession session, string text)
+ {
+ _popup.PopupCursor(text, Filter.SinglePlayer(session));
+ }
+
+ private void PlayDenySound(EntityUid uid, CargoOrderConsoleComponent component)
+ {
+ SoundSystem.Play(component.ErrorSound.GetSound(), Filter.Pvs(uid, entityManager: EntityManager), uid);
+ }
+
+ private CargoOrderData GetOrderData(CargoConsoleAddOrderMessage args, int index)
+ {
+ return new CargoOrderData(index, args.Requester, args.Reason, args.ProductId, args.Amount);
+ }
+
+ private int GetOrderCount(StationCargoOrderDatabaseComponent component)
+ {
+ var amount = 0;
+
+ foreach (var (_, order) in component.Orders)
+ {
+ if (!order.Approved) continue;
+ amount += order.Amount;
+ }
+
+ return amount;
+ }
+
+ ///
+ /// Updates all of the cargo-related consoles for a particular station.
+ /// This should be called whenever orders change.
+ ///
+ private void UpdateOrders(StationCargoOrderDatabaseComponent component)
+ {
+ // Order added so all consoles need updating.
+ foreach (var comp in EntityQuery(true))
+ {
+ var station = _station.GetOwningStation(component.Owner);
+ if (station != component.Owner) continue;
+
+ UpdateOrderState(comp, station);
+ }
+
+ foreach (var comp in EntityQuery(true))
+ {
+ var station = _station.GetOwningStation(component.Owner);
+ if (station != component.Owner) continue;
+
+ UpdateShuttleState(comp, station);
+ }
+ }
+
+ public bool TryAddOrder(StationCargoOrderDatabaseComponent component, CargoOrderData data)
+ {
+ component.Orders.Add(data.OrderNumber, data);
+ UpdateOrders(component);
+ return true;
+ }
+
+ private int GetNextIndex(StationCargoOrderDatabaseComponent component)
+ {
+ var index = component.Index;
+ component.Index++;
+ return index;
+ }
+
+ public void RemoveOrder(StationCargoOrderDatabaseComponent component, int index)
+ {
+ if (!component.Orders.Remove(index)) return;
+ UpdateOrders(component);
+ }
+
+ public void ClearOrders(StationCargoOrderDatabaseComponent component)
+ {
+ if (component.Orders.Count == 0) return;
+
+ component.Orders.Clear();
+ Dirty(component);
+ }
+
+ private void DeductFunds(StationBankAccountComponent component, int amount)
+ {
+ component.Balance = Math.Max(0, component.Balance - amount);
+ Dirty(component);
+ }
+
+ #region Station
+
+ private StationBankAccountComponent? GetBankAccount(CargoOrderConsoleComponent component)
+ {
+ var station = _station.GetOwningStation(component.Owner);
+
+ TryComp(station, out var bankComponent);
+ return bankComponent;
+ }
+
+ private StationCargoOrderDatabaseComponent? GetOrderDatabase(CargoOrderConsoleComponent component)
+ {
+ var station = _station.GetOwningStation(component.Owner);
+
+ TryComp(station, out var orderComponent);
+ return orderComponent;
+ }
+
+ #endregion
+ }
+}
diff --git a/Content.Server/Cargo/Systems/CargoSystem.Shuttle.cs b/Content.Server/Cargo/Systems/CargoSystem.Shuttle.cs
new file mode 100644
index 0000000000..3f1bc47d1e
--- /dev/null
+++ b/Content.Server/Cargo/Systems/CargoSystem.Shuttle.cs
@@ -0,0 +1,528 @@
+using System.Diagnostics.CodeAnalysis;
+using System.Linq;
+using Content.Server.Cargo.Components;
+using Content.Server.GameTicking.Events;
+using Content.Server.Shuttles.Components;
+using Content.Server.Shuttles.Events;
+using Content.Server.UserInterface;
+using Content.Shared.Cargo;
+using Content.Shared.Cargo.BUI;
+using Content.Shared.Cargo.Components;
+using Content.Shared.Cargo.Events;
+using Content.Shared.Cargo.Prototypes;
+using Content.Shared.Dataset;
+using Content.Shared.GameTicking;
+using Content.Shared.MobState.Components;
+using Robust.Server.GameObjects;
+using Robust.Server.Maps;
+using Robust.Shared.Audio;
+using Robust.Shared.Map;
+using Robust.Shared.Player;
+using Robust.Shared.Random;
+using Robust.Shared.Timing;
+using Robust.Shared.Utility;
+
+namespace Content.Server.Cargo.Systems;
+
+public sealed partial class CargoSystem
+{
+ /*
+ * Handles cargo shuttle mechanics, including cargo shuttle consoles.
+ */
+
+ [Dependency] private readonly IGameTiming _timing = default!;
+ [Dependency] private readonly IMapLoader _loader = default!;
+ [Dependency] private readonly IMapManager _mapManager = default!;
+ [Dependency] private readonly IRobustRandom _random = default!;
+ [Dependency] private readonly EntityLookupSystem _lookup = default!;
+ [Dependency] private readonly PricingSystem _pricing = default!;
+
+ public MapId? CargoMap { get; private set; }
+
+ private const float ShuttleRecallRange = 100f;
+
+ ///
+ /// Minimum mass a grid needs to be to block a shuttle recall.
+ ///
+ private const float ShuttleCallMassThreshold = 300f;
+
+ private const float CallOffset = 50f;
+
+ private int _index;
+
+ private void InitializeShuttle()
+ {
+ SubscribeLocalEvent(OnCargoShuttleMove);
+ SubscribeLocalEvent(OnCargoShuttleConsoleStartup);
+ SubscribeLocalEvent(OnCargoShuttleCall);
+ SubscribeLocalEvent(RecallCargoShuttle);
+
+ SubscribeLocalEvent(OnCargoGetConsole);
+ SubscribeLocalEvent(OnCargoPilotConsoleOpen);
+ SubscribeLocalEvent(OnCargoPilotConsoleClose);
+
+ SubscribeLocalEvent(OnCargoOrderStartup);
+
+ SubscribeLocalEvent(OnRoundRestart);
+ }
+
+ #region Cargo Pilot Console
+
+ private void OnCargoPilotConsoleOpen(EntityUid uid, CargoPilotConsoleComponent component, AfterActivatableUIOpenEvent args)
+ {
+ component.Entity = GetShuttleConsole(component);
+ }
+
+ 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(component);
+ }
+
+ private EntityUid? GetShuttleConsole(CargoPilotConsoleComponent component)
+ {
+ var stationUid = _station.GetOwningStation(component.Owner);
+
+ if (!TryComp(stationUid, out var orderDatabase) ||
+ !TryComp(orderDatabase.Shuttle, out var shuttle)) return null;
+
+ return GetShuttleConsole(shuttle);
+ }
+
+ #endregion
+
+ #region Console
+
+ private void UpdateShuttleCargoConsoles(CargoShuttleComponent component)
+ {
+ foreach (var console in EntityQuery(true))
+ {
+ var stationUid = _station.GetOwningStation(console.Owner);
+ if (stationUid != component.Station) continue;
+ UpdateShuttleState(console, stationUid);
+ }
+ }
+
+ private void OnCargoShuttleConsoleStartup(EntityUid uid, CargoShuttleConsoleComponent component, ComponentStartup args)
+ {
+ var station = _station.GetOwningStation(uid);
+ UpdateShuttleState(component, station);
+ }
+
+ private void UpdateShuttleState(CargoShuttleConsoleComponent component, EntityUid? station = null)
+ {
+ TryComp(station, out var orderDatabase);
+ TryComp(orderDatabase?.Shuttle, out var shuttle);
+
+ var orders = GetProjectedOrders(orderDatabase, shuttle);
+ var shuttleName = orderDatabase?.Shuttle != null ? MetaData(orderDatabase.Shuttle.Value).EntityName : string.Empty;
+
+ // TODO: Loc
+ _uiSystem.GetUiOrNull(component.Owner, CargoConsoleUiKey.Shuttle)?.SetState(
+ new CargoShuttleConsoleBoundUserInterfaceState(
+ station != null ? MetaData(station.Value).EntityName : Loc.GetString("cargo-shuttle-console-station-unknown"),
+ string.IsNullOrEmpty(shuttleName) ? Loc.GetString("cargo-shuttle-console-shuttle-not-found") : shuttleName,
+ CanRecallShuttle(shuttle?.Owner, out _),
+ shuttle?.NextCall,
+ orders));
+ }
+
+ #endregion
+
+ #region Shuttle
+
+ public EntityUid? GetShuttleConsole(CargoShuttleComponent component)
+ {
+ foreach (var (comp, xform) in EntityQuery(true))
+ {
+ if (xform.ParentUid != component.Owner) continue;
+ return comp.Owner;
+ }
+
+ return null;
+ }
+
+ private void OnCargoShuttleMove(EntityUid uid, CargoShuttleComponent component, ref MoveEvent args)
+ {
+ if (component.Station == null) return;
+
+ var oldCanRecall = component.CanRecall;
+
+ // Check if we can update the recall status.
+ var canRecall = CanRecallShuttle(uid, out _, args.Component);
+ if (oldCanRecall == canRecall) return;
+
+ component.CanRecall = canRecall;
+ _sawmill.Debug($"Updated CanRecall for {ToPrettyString(uid)}");
+ UpdateShuttleCargoConsoles(component);
+ }
+
+ ///
+ /// Returns the orders that can fit on the cargo shuttle.
+ ///
+ private List GetProjectedOrders(
+ StationCargoOrderDatabaseComponent? component = null,
+ CargoShuttleComponent? shuttle = null)
+ {
+ var orders = new List();
+
+ if (component == null || shuttle == null || component.Orders.Count == 0)
+ return orders;
+
+ var space = GetCargoSpace(shuttle);
+
+ if (space == 0) return orders;
+
+ var indices = component.Orders.Keys.ToList();
+ indices.Sort();
+ var amount = 0;
+
+ foreach (var index in indices)
+ {
+ var order = component.Orders[index];
+ if (!order.Approved) continue;
+
+ var cappedAmount = Math.Min(space - amount, order.Amount);
+ amount += cappedAmount;
+ DebugTools.Assert(amount <= space);
+
+ if (cappedAmount < order.Amount)
+ {
+ var reducedOrder = new CargoOrderData(order.OrderNumber, order.Requester, order.Reason, order.ProductId,
+ cappedAmount);
+
+ orders.Add(reducedOrder);
+ break;
+ }
+
+ orders.Add(order);
+
+ if (amount == space) break;
+ }
+
+ return orders;
+ }
+
+ ///
+ /// Get the amount of space the cargo shuttle can fit for orders.
+ ///
+ private int GetCargoSpace(CargoShuttleComponent component)
+ {
+ var space = GetCargoPallets(component).Count;
+ return space;
+ }
+
+ private List GetCargoPallets(CargoShuttleComponent component)
+ {
+ var pads = new List();
+
+ foreach (var (comp, compXform) in EntityQuery(true))
+ {
+ if (compXform.ParentUid != component.Owner ||
+ !compXform.Anchored) continue;
+
+ pads.Add(comp);
+ }
+
+ return pads;
+ }
+
+ #endregion
+
+ #region Station
+
+ private void OnCargoOrderStartup(EntityUid uid, StationCargoOrderDatabaseComponent component, ComponentStartup args)
+ {
+ // Stations get created first but if any are added at runtime then do this.
+ AddShuttle(component);
+ }
+
+ private void AddShuttle(StationCargoOrderDatabaseComponent component)
+ {
+ Setup();
+
+ if (CargoMap == null || component.Shuttle != null) return;
+
+ if (component.CargoShuttleProto != null)
+ {
+ var prototype = _protoMan.Index(component.CargoShuttleProto);
+ var possibleNames = _protoMan.Index(prototype.NameDataset).Values;
+ var name = _random.Pick(possibleNames);
+
+ var (_, gridId) = _loader.LoadBlueprint(CargoMap.Value, prototype.Path.ToString());
+ var shuttleUid = _mapManager.GetGridEuid(gridId!.Value);
+ var xform = Transform(shuttleUid);
+ MetaData(shuttleUid).EntityName = name;
+
+ // TODO: Something better like a bounds check.
+ xform.LocalPosition += 100 * _index;
+ var comp = EnsureComp(shuttleUid);
+ comp.Station = component.Owner;
+ comp.Coordinates = xform.Coordinates;
+
+ component.Shuttle = shuttleUid;
+ comp.NextCall = _timing.CurTime + TimeSpan.FromSeconds(comp.Cooldown);
+ UpdateShuttleCargoConsoles(comp);
+ _index++;
+ _sawmill.Info($"Added cargo shuttle to {ToPrettyString(shuttleUid)}");
+ }
+ }
+
+ private void SellPallets(CargoShuttleComponent component, StationBankAccountComponent bank)
+ {
+ double amount = 0;
+ var toSell = new HashSet();
+ var xformQuery = GetEntityQuery();
+
+ foreach (var pallet in GetCargoPallets(component))
+ {
+ // Containers should already get the sell price of their children so can skip those.
+ foreach (var ent in _lookup.GetEntitiesIntersecting(pallet.Owner, LookupFlags.Anchored))
+ {
+ // Don't re-sell anything, sell anything anchored (e.g. light fixtures), or anything blacklisted
+ // (e.g. players).
+ if (toSell.Contains(ent) ||
+ (xformQuery.TryGetComponent(ent, out var xform) && xform.Anchored)) continue;
+
+ var price = _pricing.GetPrice(ent);
+ if (price == 0) continue;
+ toSell.Add(ent);
+ amount += price;
+ }
+ }
+
+ bank.Balance += (int) amount;
+ _sawmill.Debug($"Cargo sold {toSell.Count} entities for {amount}");
+
+ foreach (var ent in toSell)
+ {
+ Del(ent);
+ }
+ }
+
+ private void SendToCargoMap(EntityUid uid, CargoShuttleComponent? component = null)
+ {
+ if (!Resolve(uid, ref component))
+ return;
+
+ component.NextCall = _timing.CurTime + TimeSpan.FromSeconds(component.Cooldown);
+ Transform(uid).Coordinates = component.Coordinates;
+ DebugTools.Assert(MetaData(uid).EntityPaused);
+
+ UpdateShuttleCargoConsoles(component);
+ _sawmill.Info($"Stashed cargo shuttle {ToPrettyString(uid)}");
+ }
+
+ ///
+ /// Retrieves a shuttle for delivery.
+ ///
+ public void CallShuttle(StationCargoOrderDatabaseComponent orderDatabase)
+ {
+ if (!TryComp(orderDatabase.Shuttle, out var shuttle) ||
+ !TryComp(orderDatabase.Owner, out var xform)) return;
+
+ // Already called / not available
+ if (shuttle.NextCall == null || _timing.CurTime < shuttle.NextCall)
+ return;
+
+ shuttle.NextCall = null;
+
+ // Find a valid free area nearby to spawn in on
+ var center = new Vector2();
+ var minRadius = 0f;
+ Box2? aabb = null;
+
+ foreach (var grid in _mapManager.GetAllMapGrids(xform.MapID))
+ {
+ aabb = aabb?.Union(grid.WorldAABB) ?? grid.WorldAABB;
+ }
+
+ if (aabb != null)
+ {
+ center = aabb.Value.Center;
+ minRadius = MathF.Max(aabb.Value.Width, aabb.Value.Height);
+ }
+
+ var offset = 0f;
+ if (TryComp(orderDatabase.Shuttle, out var shuttleGrid))
+ {
+ var bounds = shuttleGrid.Grid.LocalAABB;
+ offset = MathF.Max(bounds.Width, bounds.Height) / 2f;
+ }
+
+ Transform(shuttle.Owner).Coordinates = new EntityCoordinates(xform.ParentUid,
+ center + _random.NextVector2(minRadius + offset, minRadius + CallOffset + offset));
+ DebugTools.Assert(!MetaData(shuttle.Owner).EntityPaused);
+
+ AddCargoContents(shuttle, orderDatabase);
+ UpdateOrders(orderDatabase);
+ UpdateShuttleCargoConsoles(shuttle);
+
+ _sawmill.Info($"Retrieved cargo shuttle {ToPrettyString(shuttle.Owner)} from {ToPrettyString(orderDatabase.Owner)}");
+ }
+
+ private void AddCargoContents(CargoShuttleComponent component, StationCargoOrderDatabaseComponent orderDatabase)
+ {
+ var xformQuery = GetEntityQuery();
+ var orders = GetProjectedOrders(orderDatabase, component);
+
+ var pads = GetCargoPallets(component);
+ DebugTools.Assert(orders.Sum(o => o.Amount) <= pads.Count);
+
+ for (var i = 0; i < orders.Count; i++)
+ {
+ var order = orders[i];
+
+ Spawn(_protoMan.Index(order.ProductId).Product,
+ new EntityCoordinates(component.Owner, xformQuery.GetComponent(_random.PickAndTake(pads).Owner).LocalPosition));
+ order.Amount--;
+
+ if (order.Amount == 0)
+ {
+ orders.RemoveSwap(i);
+ orderDatabase.Orders.Remove(order.OrderNumber);
+ i--;
+ }
+ else
+ {
+ orderDatabase.Orders[order.OrderNumber] = order;
+ }
+ }
+ }
+
+ public bool CanRecallShuttle(EntityUid? uid, [NotNullWhen(false)] out string? reason, TransformComponent? xform = null)
+ {
+ reason = null;
+
+ if (!TryComp(uid, out var grid) ||
+ !Resolve(uid.Value, ref xform)) return true;
+
+ var bounds = grid.Grid.WorldAABB.Enlarged(ShuttleRecallRange);
+ var bodyQuery = GetEntityQuery();
+
+ foreach (var other in _mapManager.FindGridsIntersecting(xform.MapID, bounds))
+ {
+ if (grid.GridIndex == other.Index ||
+ !bodyQuery.TryGetComponent(other.GridEntityId, out var body) ||
+ body.Mass < ShuttleCallMassThreshold) continue;
+
+ reason = Loc.GetString("cargo-shuttle-console-proximity");
+ return false;
+ }
+
+ return true;
+ }
+
+ private void RecallCargoShuttle(EntityUid uid, CargoShuttleConsoleComponent component, CargoRecallShuttleMessage args)
+ {
+ var player = args.Session.AttachedEntity;
+
+ if (player == null) return;
+
+ var stationUid = _station.GetOwningStation(component.Owner);
+
+ if (!TryComp(stationUid, out var orderDatabase) ||
+ !TryComp(stationUid, out var bank)) return;
+
+ if (!TryComp(orderDatabase.Shuttle, out var shuttle))
+ {
+ _popup.PopupEntity($"No cargo shuttle found!", args.Entity, Filter.Entities(args.Entity));
+ return;
+ }
+
+ if (!CanRecallShuttle(shuttle.Owner, out var reason))
+ {
+ _popup.PopupEntity(reason, args.Entity, Filter.Entities(args.Entity));
+ return;
+ }
+
+ if (IsBlocked(shuttle))
+ {
+ _popup.PopupEntity(Loc.GetString("cargo-shuttle-console-organics"), player.Value, Filter.Entities(player.Value));
+ SoundSystem.Play(component.DenySound.GetSound(), Filter.Pvs(uid, entityManager: EntityManager), uid);
+ return;
+ };
+
+ SellPallets(shuttle, bank);
+
+ SendToCargoMap(orderDatabase.Shuttle.Value);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ private bool IsBlocked(CargoShuttleComponent component)
+ {
+ // TODO: Would be good to rate-limit this on the console.
+ var mobQuery = GetEntityQuery();
+ var xformQuery = GetEntityQuery();
+
+ return FoundOrganics(component.Owner, mobQuery, xformQuery);
+ }
+
+ private bool FoundOrganics(EntityUid uid, EntityQuery mobQuery, EntityQuery xformQuery)
+ {
+ var xform = xformQuery.GetComponent(uid);
+ var childEnumerator = xform.ChildEnumerator;
+
+ while (childEnumerator.MoveNext(out var child))
+ {
+ if (mobQuery.HasComponent(child.Value) ||
+ FoundOrganics(child.Value, mobQuery, xformQuery)) return true;
+ }
+
+ return false;
+ }
+
+ private void OnCargoShuttleCall(EntityUid uid, CargoShuttleConsoleComponent component, CargoCallShuttleMessage args)
+ {
+ var stationUid = _station.GetOwningStation(args.Entity);
+ if (!TryComp(stationUid, out var orderDatabase)) return;
+ CallShuttle(orderDatabase);
+ }
+
+ #endregion
+
+ private void OnRoundRestart(RoundRestartCleanupEvent ev)
+ {
+ Cleanup();
+ }
+
+ private void Cleanup()
+ {
+ if (CargoMap == null || !_mapManager.MapExists(CargoMap.Value))
+ {
+ CargoMap = null;
+ DebugTools.Assert(!EntityQuery().Any());
+ return;
+ }
+
+ _mapManager.DeleteMap(CargoMap.Value);
+ CargoMap = null;
+
+ // Shuttle may not have been in the cargo dimension (e.g. on the station map) so need to delete.
+ foreach (var comp in EntityQuery())
+ {
+ QueueDel(comp.Owner);
+ }
+ }
+
+ private void Setup()
+ {
+ if (CargoMap != null && _mapManager.MapExists(CargoMap.Value)) return;
+
+ // It gets mapinit which is okay... buuutt we still want it paused to avoid power draining.
+ CargoMap = _mapManager.CreateMap();
+ _mapManager.SetMapPaused(CargoMap!.Value, true);
+
+ foreach (var comp in EntityQuery(true))
+ {
+ AddShuttle(comp);
+ }
+ }
+}
diff --git a/Content.Server/Cargo/Systems/CargoSystem.Telepad.cs b/Content.Server/Cargo/Systems/CargoSystem.Telepad.cs
index a773f05394..1316ec4531 100644
--- a/Content.Server/Cargo/Systems/CargoSystem.Telepad.cs
+++ b/Content.Server/Cargo/Systems/CargoSystem.Telepad.cs
@@ -1,9 +1,12 @@
+using System.Linq;
using Content.Server.Cargo.Components;
using Content.Server.Labels.Components;
using Content.Server.Paper;
using Content.Server.Power.Components;
using Content.Shared.Cargo;
+using Content.Shared.Cargo.Prototypes;
using Robust.Shared.Audio;
+using Robust.Shared.Collections;
using Robust.Shared.Player;
namespace Content.Server.Cargo.Systems;
@@ -27,7 +30,7 @@ public sealed partial class CargoSystem
// Don't EntityQuery for it as it's not required.
TryComp(comp.Owner, out var appearance);
- if (comp.CurrentState == CargoTelepadState.Unpowered || comp.TeleportQueue.Count <= 0)
+ if (comp.CurrentState == CargoTelepadState.Unpowered)
{
comp.CurrentState = CargoTelepadState.Idle;
appearance?.SetData(CargoTelepadVisuals.State, CargoTelepadState.Idle);
@@ -45,14 +48,44 @@ public sealed partial class CargoSystem
continue;
}
- var product = comp.TeleportQueue.Pop();
+ var station = _station.GetOwningStation(comp.Owner);
+
+ if (!TryComp(station, out var orderDatabase) ||
+ orderDatabase.Orders.Count == 0)
+ {
+ comp.Accumulator += comp.Delay;
+ continue;
+ }
+
+ var orderIndices = new ValueList();
+
+ foreach (var (oIndex, oOrder) in orderDatabase.Orders)
+ {
+ if (!oOrder.Approved) continue;
+ orderIndices.Add(oIndex);
+ }
+
+ if (orderIndices.Count == 0)
+ {
+ comp.Accumulator += comp.Delay;
+ continue;
+ }
+
+ orderIndices.Sort();
+ var index = orderIndices[0];
+ var order = orderDatabase.Orders[index];
+ order.Amount--;
+
+ if (order.Amount <= 0)
+ orderDatabase.Orders.Remove(index);
SoundSystem.Play(comp.TeleportSound.GetSound(), Filter.Pvs(comp.Owner), comp.Owner, AudioParams.Default.WithVolume(-8f));
- SpawnProduct(comp, product);
+ SpawnProduct(comp, order);
+ UpdateOrders(orderDatabase);
comp.CurrentState = CargoTelepadState.Teleporting;
appearance?.SetData(CargoTelepadVisuals.State, CargoTelepadState.Teleporting);
- comp.Accumulator = comp.Delay;
+ comp.Accumulator += comp.Delay;
}
}
@@ -87,14 +120,6 @@ public sealed partial class CargoSystem
SetEnabled(component);
}
- public void QueueTeleport(CargoTelepadComponent component, CargoOrderData order)
- {
- for (var i = 0; i < order.Amount; i++)
- {
- component.TeleportQueue.Push(order);
- }
- }
-
///
/// Spawn the product and a piece of paper. Attempt to attach the paper to the product.
///
diff --git a/Content.Server/Cargo/Systems/CargoSystem.cs b/Content.Server/Cargo/Systems/CargoSystem.cs
index fa5427e887..f675d05f25 100644
--- a/Content.Server/Cargo/Systems/CargoSystem.cs
+++ b/Content.Server/Cargo/Systems/CargoSystem.cs
@@ -1,4 +1,7 @@
+using Content.Server.Cargo.Components;
+using Content.Server.Station.Systems;
using Content.Shared.Cargo;
+using Content.Shared.Cargo.Components;
using Content.Shared.Containers.ItemSlots;
using Robust.Shared.Prototypes;
@@ -9,11 +12,28 @@ public sealed partial class CargoSystem : SharedCargoSystem
[Dependency] private readonly IPrototypeManager _protoMan = default!;
[Dependency] private readonly ItemSlotsSystem _slots = default!;
+ private ISawmill _sawmill = default!;
+
public override void Initialize()
{
base.Initialize();
+ _sawmill = Logger.GetSawmill("cargo");
InitializeConsole();
+ InitializeShuttle();
InitializeTelepad();
+ SubscribeLocalEvent(OnStationInit);
+ }
+
+ public override void Shutdown()
+ {
+ base.Shutdown();
+ Cleanup();
+ }
+
+ private void OnStationInit(StationInitializedEvent ev)
+ {
+ EnsureComp(ev.Station);
+ EnsureComp(ev.Station);
}
public override void Update(float frameTime)
diff --git a/Content.Server/GameTicking/Rules/NukeopsRuleSystem.cs b/Content.Server/GameTicking/Rules/NukeopsRuleSystem.cs
index c3d5810925..dacf5aeb0b 100644
--- a/Content.Server/GameTicking/Rules/NukeopsRuleSystem.cs
+++ b/Content.Server/GameTicking/Rules/NukeopsRuleSystem.cs
@@ -187,17 +187,26 @@ public sealed class NukeopsRuleSystem : GameRuleSystem
// TODO: Make this a prototype
var map = "/Maps/infiltrator.yml";
- var aabbs = _stationSystem.Stations.SelectMany(x =>
- Comp(x).Grids.Select(x => _mapManager.GetGridComp(x).Grid.WorldAABB)).ToArray();
- var aabb = aabbs[0];
- for (int i = 1; i < aabbs.Length; i++)
+ var center = new Vector2();
+ var minRadius = 0f;
+ Box2? aabb = null;
+
+ foreach (var uid in _stationSystem.Stations)
{
- aabb.Union(aabbs[i]);
+ var grid = Comp(uid).Grid;
+
+ aabb = aabb?.Union(grid.WorldAABB) ?? grid.WorldAABB;
+ }
+
+ if (aabb != null)
+ {
+ center = aabb.Value.Center;
+ minRadius = MathF.Max(aabb.Value.Width, aabb.Value.Height);
}
var (_, gridId) = _mapLoader.LoadBlueprint(GameTicker.DefaultMap, map, new MapLoadOptions
{
- Offset = aabb.Center + MathF.Max(aabb.Height / 2f, aabb.Width / 2f) * 2.5f
+ Offset = center + MathF.Max(minRadius, minRadius) + 1000f,
});
if (!gridId.HasValue)
diff --git a/Content.Server/Gravity/EntitySystems/WeightlessSystem.cs b/Content.Server/Gravity/EntitySystems/WeightlessSystem.cs
index cf86734ad0..14d1c7c952 100644
--- a/Content.Server/Gravity/EntitySystems/WeightlessSystem.cs
+++ b/Content.Server/Gravity/EntitySystems/WeightlessSystem.cs
@@ -42,6 +42,9 @@ namespace Content.Server.Gravity.EntitySystems
if (_mapManager.TryGetGrid(xform.GridUid, out var grid))
{
+ var alerts = _alerts.GetOrNew(xform.GridUid.Value);
+ alerts.Add(status);
+
if (EntityManager.GetComponent(grid.GridEntityId).Enabled)
{
RemoveWeightless(status.Owner);
@@ -51,6 +54,10 @@ namespace Content.Server.Gravity.EntitySystems
AddWeightless(status.Owner);
}
}
+ else
+ {
+ AddWeightless(status.Owner);
+ }
}
public void RemoveAlert(AlertsComponent status)
diff --git a/Content.Server/Physics/Controllers/MoverController.cs b/Content.Server/Physics/Controllers/MoverController.cs
index f29fc79566..a0d99f2c52 100644
--- a/Content.Server/Physics/Controllers/MoverController.cs
+++ b/Content.Server/Physics/Controllers/MoverController.cs
@@ -1,3 +1,4 @@
+using Content.Server.Cargo.Components;
using Content.Server.Shuttles.Components;
using Content.Server.Shuttles.Systems;
using Content.Shared.Vehicle.Components;
@@ -61,9 +62,18 @@ namespace Content.Server.Physics.Controllers
var newPilots = new Dictionary>();
// We just mark off their movement and the shuttle itself does its own movement
- foreach (var (pilot, mover, xform) in EntityManager.EntityQuery())
+ foreach (var (pilot, mover) in EntityManager.EntityQuery())
{
- if (pilot.Console == null) continue;
+ 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))
+ {
+ consoleEnt = cargoConsole.Entity;
+ }
+
+ if (!TryComp(consoleEnt, out var xform)) continue;
+
_excludedMobs.Add(mover.Owner);
var gridId = xform.GridUid;
diff --git a/Content.Server/Shuttles/Events/ConsoleShuttleEvent.cs b/Content.Server/Shuttles/Events/ConsoleShuttleEvent.cs
new file mode 100644
index 0000000000..bd96387b28
--- /dev/null
+++ b/Content.Server/Shuttles/Events/ConsoleShuttleEvent.cs
@@ -0,0 +1,12 @@
+using Content.Server.Shuttles.Components;
+
+namespace Content.Server.Shuttles.Events;
+
+///
+/// Raised on a when it's trying to get its shuttle console to pilot.
+///
+[ByRefEvent]
+public struct ConsoleShuttleEvent
+{
+ public EntityUid? Console;
+}
diff --git a/Content.Server/Shuttles/Systems/RadarConsoleSystem.cs b/Content.Server/Shuttles/Systems/RadarConsoleSystem.cs
index 3d2e6c0025..eac8d07ff6 100644
--- a/Content.Server/Shuttles/Systems/RadarConsoleSystem.cs
+++ b/Content.Server/Shuttles/Systems/RadarConsoleSystem.cs
@@ -23,7 +23,16 @@ public sealed class RadarConsoleSystem : SharedRadarConsoleSystem
protected override void UpdateState(RadarConsoleComponent component)
{
- var radarState = new RadarConsoleBoundInterfaceState(component.MaxRange, component.Owner, new List());
+ var xform = Transform(component.Owner);
+
+ var onGrid = xform.ParentUid == xform.GridUid;
+
+ var radarState = new RadarConsoleBoundInterfaceState(
+ component.MaxRange,
+ onGrid ? xform.Coordinates : null,
+ onGrid ? xform.LocalRotation : null,
+ new List());
+
_uiSystem.GetUiOrNull(component.Owner, RadarConsoleUiKey.Key)?.SetState(radarState);
}
}
diff --git a/Content.Server/Shuttles/Systems/ShuttleConsoleSystem.cs b/Content.Server/Shuttles/Systems/ShuttleConsoleSystem.cs
index 6eb8649509..3780453ee8 100644
--- a/Content.Server/Shuttles/Systems/ShuttleConsoleSystem.cs
+++ b/Content.Server/Shuttles/Systems/ShuttleConsoleSystem.cs
@@ -1,3 +1,4 @@
+using Content.Server.Cargo.Components;
using Content.Server.Power.Components;
using Content.Server.Power.EntitySystems;
using Content.Server.Shuttles.Components;
@@ -5,6 +6,7 @@ using Content.Server.Shuttles.Events;
using Content.Server.UserInterface;
using Content.Shared.ActionBlocker;
using Content.Shared.Alert;
+using Content.Shared.Light;
using Content.Shared.Popups;
using Content.Shared.Shuttles.BUIStates;
using Content.Shared.Shuttles.Components;
@@ -136,15 +138,29 @@ namespace Content.Server.Shuttles.Systems
///
private void OnModeRequest(EntityUid uid, ShuttleConsoleComponent component, ShuttleModeRequestMessage args)
{
+ var consoleUid = uid;
+
+ if (TryComp(uid, out var cargoPilot) && cargoPilot.Entity != null)
+ {
+ consoleUid = cargoPilot.Entity.Value;
+ }
+
if (args.Session.AttachedEntity is not { } player ||
!TryComp(player, out var pilot) ||
- !TryComp(player, out var xform) ||
- pilot.Console is not ShuttleConsoleComponent console) return;
+ !TryComp(consoleUid, out var console) ||
+ !TryComp(consoleUid, out var consoleXform)) return;
- if (!console.SubscribedPilots.Contains(pilot) ||
- !TryComp(xform.GridUid, out var shuttle)) return;
+ // Can't check console pilots as it may be remotely piloted!
+ if (!component.SubscribedPilots.Contains(pilot) ||
+ !TryComp(consoleXform.GridUid, out var shuttle)) return;
SetShuttleMode(args.Mode, console, shuttle);
+ UpdateState(component);
+
+ if (uid != consoleUid)
+ {
+ UpdateState(console);
+ }
}
///
@@ -159,7 +175,6 @@ namespace Content.Server.Shuttles.Systems
!consoleXform.Anchored ||
consoleXform.GridID != Transform(shuttleComponent.Owner).GridID)
{
- UpdateState(consoleComponent);
return;
}
@@ -174,8 +189,6 @@ namespace Content.Server.Shuttles.Systems
default:
throw new ArgumentOutOfRangeException();
}
-
- UpdateState(consoleComponent);
}
///
@@ -205,10 +218,21 @@ namespace Content.Server.Shuttles.Systems
private void UpdateState(ShuttleConsoleComponent component, List? docks = null)
{
- TryComp(component.Owner, out var radar);
+ EntityUid? entity = component.Owner;
+
+ var getShuttleEv = new ConsoleShuttleEvent
+ {
+ Console = entity,
+ };
+
+ RaiseLocalEvent(entity.Value, ref getShuttleEv, false);
+ entity = getShuttleEv.Console;
+
+ TryComp(entity, out var consoleXform);
+ TryComp(entity, out var radar);
var range = radar?.MaxRange ?? 0f;
- TryComp(Transform(component.Owner).GridUid, out var shuttle);
+ TryComp(consoleXform?.GridUid, out var shuttle);
var mode = shuttle?.Mode ?? ShuttleMode.Cruise;
docks ??= GetAllDocks();
@@ -217,7 +241,8 @@ namespace Content.Server.Shuttles.Systems
?.SetState(new ShuttleConsoleBoundInterfaceState(
mode,
range,
- component.Owner,
+ consoleXform?.Coordinates,
+ consoleXform?.LocalRotation,
docks));
}
diff --git a/Content.Shared/Cargo/BUI/CargoConsoleInterfaceState.cs b/Content.Shared/Cargo/BUI/CargoConsoleInterfaceState.cs
new file mode 100644
index 0000000000..a1e61772cd
--- /dev/null
+++ b/Content.Shared/Cargo/BUI/CargoConsoleInterfaceState.cs
@@ -0,0 +1,22 @@
+using Robust.Shared.Serialization;
+
+namespace Content.Shared.Cargo.BUI;
+
+[NetSerializable, Serializable]
+public sealed class CargoConsoleInterfaceState : BoundUserInterfaceState
+{
+ public string Name;
+ public int Count;
+ public int Capacity;
+ public int Balance;
+ public List Orders;
+
+ public CargoConsoleInterfaceState(string name, int count, int capacity, int balance, List orders)
+ {
+ Name = name;
+ Count = count;
+ Capacity = capacity;
+ Balance = balance;
+ Orders = orders;
+ }
+}
\ No newline at end of file
diff --git a/Content.Shared/Cargo/BUI/CargoShuttleConsoleBoundUserInterfaceState.cs b/Content.Shared/Cargo/BUI/CargoShuttleConsoleBoundUserInterfaceState.cs
new file mode 100644
index 0000000000..75e0aee60f
--- /dev/null
+++ b/Content.Shared/Cargo/BUI/CargoShuttleConsoleBoundUserInterfaceState.cs
@@ -0,0 +1,41 @@
+using Robust.Shared.Serialization;
+
+namespace Content.Shared.Cargo.BUI;
+
+[Serializable, NetSerializable]
+public sealed class CargoShuttleConsoleBoundUserInterfaceState : BoundUserInterfaceState
+{
+ public string AccountName;
+ public string ShuttleName;
+
+ // Unfortunately shuttles have essentially 3 states so can't just use a nullable var for it:
+ // 1. stowed
+ // 2. called but not recallable
+ // 3. called and recallable
+ // The reason we have 2 is so people don't spam the recall button in the UI.
+ public bool CanRecall;
+
+ ///
+ /// When the shuttle is expected to be usable.
+ ///
+ public TimeSpan? ShuttleETA;
+
+ ///
+ /// List of orders expected on the delivery.
+ ///
+ public List Orders;
+
+ public CargoShuttleConsoleBoundUserInterfaceState(
+ string accountName,
+ string shuttleName,
+ bool canRecall,
+ TimeSpan? shuttleETA,
+ List orders)
+ {
+ AccountName = accountName;
+ ShuttleName = shuttleName;
+ CanRecall = canRecall;
+ ShuttleETA = shuttleETA;
+ Orders = orders;
+ }
+}
diff --git a/Content.Shared/Cargo/CargoOrderData.cs b/Content.Shared/Cargo/CargoOrderData.cs
index 62e4594127..38ebe195fa 100644
--- a/Content.Shared/Cargo/CargoOrderData.cs
+++ b/Content.Shared/Cargo/CargoOrderData.cs
@@ -12,18 +12,16 @@ namespace Content.Shared.Cargo
public string Reason;
public string ProductId;
public int Amount;
- public int PayingAccountId;
public bool Approved;
public string Approver = string.Empty;
- public CargoOrderData(int orderNumber, string requester, string reason, string productId, int amount, int payingAccountId)
+ public CargoOrderData(int orderNumber, string requester, string reason, string productId, int amount)
{
OrderNumber = orderNumber;
Requester = requester;
Reason = reason;
ProductId = productId;
Amount = amount;
- PayingAccountId = payingAccountId;
}
}
}
diff --git a/Content.Shared/Cargo/Components/CargoShuttleComponent.cs b/Content.Shared/Cargo/Components/CargoShuttleComponent.cs
new file mode 100644
index 0000000000..5a428ce985
--- /dev/null
+++ b/Content.Shared/Cargo/Components/CargoShuttleComponent.cs
@@ -0,0 +1,31 @@
+using Robust.Shared.Map;
+
+namespace Content.Shared.Cargo.Components;
+
+///
+/// Present on cargo shuttles to provide metadata such as preventing spam calling.
+///
+[RegisterComponent, Access(typeof(SharedCargoSystem))]
+public sealed class CargoShuttleComponent : Component
+{
+ [ViewVariables(VVAccess.ReadWrite), DataField("nextCall")]
+ public TimeSpan? NextCall;
+
+ [ViewVariables(VVAccess.ReadWrite), DataField("cooldown")]
+ public float Cooldown = 45f;
+
+ [ViewVariables]
+ public bool CanRecall;
+
+ ///
+ /// The shuttle's assigned coordinates on the cargo map.
+ ///
+ [ViewVariables]
+ public EntityCoordinates Coordinates;
+
+ ///
+ /// The assigned station for this cargo shuttle.
+ ///
+ [ViewVariables, DataField("station")]
+ public EntityUid? Station;
+}
diff --git a/Content.Shared/Cargo/Components/SharedCargoConsoleComponent.cs b/Content.Shared/Cargo/Components/SharedCargoConsoleComponent.cs
deleted file mode 100644
index 19a2114207..0000000000
--- a/Content.Shared/Cargo/Components/SharedCargoConsoleComponent.cs
+++ /dev/null
@@ -1,95 +0,0 @@
-using Robust.Shared.Prototypes;
-using Robust.Shared.Serialization;
-
-namespace Content.Shared.Cargo.Components
-{
- [Virtual]
- public class SharedCargoConsoleComponent : Component
- {
- [Dependency] protected readonly IPrototypeManager PrototypeManager = default!;
-
- ///
- /// Sends away or requests shuttle
- ///
- [Serializable, NetSerializable]
- public sealed class CargoConsoleShuttleMessage : BoundUserInterfaceMessage
- {
- public CargoConsoleShuttleMessage()
- {
- }
- }
-
- ///
- /// Add order to database.
- ///
- [Serializable, NetSerializable]
- public sealed class CargoConsoleAddOrderMessage : BoundUserInterfaceMessage
- {
- public string Requester;
- public string Reason;
- public string ProductId;
- public int Amount;
-
- public CargoConsoleAddOrderMessage(string requester, string reason, string productId, int amount)
- {
- Requester = requester;
- Reason = reason;
- ProductId = productId;
- Amount = amount;
- }
- }
-
- ///
- /// Remove order from database.
- ///
- [Serializable, NetSerializable]
- public sealed class CargoConsoleRemoveOrderMessage : BoundUserInterfaceMessage
- {
- public int OrderNumber;
-
- public CargoConsoleRemoveOrderMessage(int orderNumber)
- {
- OrderNumber = orderNumber;
- }
- }
-
- ///
- /// Set order in database as approved.
- ///
- [Serializable, NetSerializable]
- public sealed class CargoConsoleApproveOrderMessage : BoundUserInterfaceMessage
- {
- public int OrderNumber;
-
- public CargoConsoleApproveOrderMessage(int orderNumber)
- {
- OrderNumber = orderNumber;
- }
- }
-
- [NetSerializable, Serializable]
- public enum CargoConsoleUiKey
- {
- Key
- }
- }
-
- [NetSerializable, Serializable]
- public sealed class CargoConsoleInterfaceState : BoundUserInterfaceState
- {
- public readonly bool RequestOnly;
- public readonly int BankId;
- public readonly string BankName;
- public readonly int BankBalance;
- public readonly (int CurrentCapacity, int MaxCapacity) ShuttleCapacity;
-
- public CargoConsoleInterfaceState(bool requestOnly, int bankId, string bankName, int bankBalance, (int CurrentCapacity, int MaxCapacity) shuttleCapacity)
- {
- RequestOnly = requestOnly;
- BankId = bankId;
- BankName = bankName;
- BankBalance = bankBalance;
- ShuttleCapacity = shuttleCapacity;
- }
- }
-}
diff --git a/Content.Shared/Cargo/Components/SharedCargoOrderDatabaseComponent.cs b/Content.Shared/Cargo/Components/SharedCargoOrderDatabaseComponent.cs
deleted file mode 100644
index c1a7e4b468..0000000000
--- a/Content.Shared/Cargo/Components/SharedCargoOrderDatabaseComponent.cs
+++ /dev/null
@@ -1,21 +0,0 @@
-using Robust.Shared.GameStates;
-using Robust.Shared.Serialization;
-
-namespace Content.Shared.Cargo.Components
-{
- [NetworkedComponent()]
- public abstract class SharedCargoOrderDatabaseComponent : Component
- {
- }
-
- [NetSerializable, Serializable]
- public sealed class CargoOrderDatabaseState : ComponentState
- {
- public readonly List? Orders;
-
- public CargoOrderDatabaseState(List? orders)
- {
- Orders = orders;
- }
- }
-}
diff --git a/Content.Shared/Cargo/Events/CargoCallShuttleMessage.cs b/Content.Shared/Cargo/Events/CargoCallShuttleMessage.cs
new file mode 100644
index 0000000000..e06b388596
--- /dev/null
+++ b/Content.Shared/Cargo/Events/CargoCallShuttleMessage.cs
@@ -0,0 +1,12 @@
+using Robust.Shared.Serialization;
+
+namespace Content.Shared.Cargo.Events;
+
+///
+/// Raised on a cargo console requesting the cargo shuttle.
+///
+[Serializable, NetSerializable]
+public sealed class CargoCallShuttleMessage : BoundUserInterfaceMessage
+{
+
+}
diff --git a/Content.Shared/Cargo/Events/CargoConsoleAddOrderMessage.cs b/Content.Shared/Cargo/Events/CargoConsoleAddOrderMessage.cs
new file mode 100644
index 0000000000..5044ef121c
--- /dev/null
+++ b/Content.Shared/Cargo/Events/CargoConsoleAddOrderMessage.cs
@@ -0,0 +1,23 @@
+using Robust.Shared.Serialization;
+
+namespace Content.Shared.Cargo.Events;
+
+///
+/// Add order to database.
+///
+[Serializable, NetSerializable]
+public sealed class CargoConsoleAddOrderMessage : BoundUserInterfaceMessage
+{
+ public string Requester;
+ public string Reason;
+ public string ProductId;
+ public int Amount;
+
+ public CargoConsoleAddOrderMessage(string requester, string reason, string productId, int amount)
+ {
+ Requester = requester;
+ Reason = reason;
+ ProductId = productId;
+ Amount = amount;
+ }
+}
\ No newline at end of file
diff --git a/Content.Shared/Cargo/Events/CargoConsoleApproveOrderMessage.cs b/Content.Shared/Cargo/Events/CargoConsoleApproveOrderMessage.cs
new file mode 100644
index 0000000000..4e580dd8ac
--- /dev/null
+++ b/Content.Shared/Cargo/Events/CargoConsoleApproveOrderMessage.cs
@@ -0,0 +1,17 @@
+using Robust.Shared.Serialization;
+
+namespace Content.Shared.Cargo.Events;
+
+///
+/// Set order in database as approved.
+///
+[Serializable, NetSerializable]
+public sealed class CargoConsoleApproveOrderMessage : BoundUserInterfaceMessage
+{
+ public int OrderNumber;
+
+ public CargoConsoleApproveOrderMessage(int orderNumber)
+ {
+ OrderNumber = orderNumber;
+ }
+}
\ No newline at end of file
diff --git a/Content.Shared/Cargo/Events/CargoConsoleRemoveOrderMessage.cs b/Content.Shared/Cargo/Events/CargoConsoleRemoveOrderMessage.cs
new file mode 100644
index 0000000000..9a7a842fbe
--- /dev/null
+++ b/Content.Shared/Cargo/Events/CargoConsoleRemoveOrderMessage.cs
@@ -0,0 +1,17 @@
+using Robust.Shared.Serialization;
+
+namespace Content.Shared.Cargo.Events;
+
+///
+/// Remove order from database.
+///
+[Serializable, NetSerializable]
+public sealed class CargoConsoleRemoveOrderMessage : BoundUserInterfaceMessage
+{
+ public int OrderNumber;
+
+ public CargoConsoleRemoveOrderMessage(int orderNumber)
+ {
+ OrderNumber = orderNumber;
+ }
+}
\ No newline at end of file
diff --git a/Content.Shared/Cargo/Events/CargoRecallShuttleMessage.cs b/Content.Shared/Cargo/Events/CargoRecallShuttleMessage.cs
new file mode 100644
index 0000000000..041ddebe79
--- /dev/null
+++ b/Content.Shared/Cargo/Events/CargoRecallShuttleMessage.cs
@@ -0,0 +1,12 @@
+using Robust.Shared.Serialization;
+
+namespace Content.Shared.Cargo.Events;
+
+///
+/// Raised on a client request cargo shuttle recall
+///
+[Serializable, NetSerializable]
+public sealed class CargoRecallShuttleMessage : BoundUserInterfaceMessage
+{
+
+}
diff --git a/Content.Shared/Cargo/CargoProductPrototype.cs b/Content.Shared/Cargo/Prototypes/CargoProductPrototype.cs
similarity index 97%
rename from Content.Shared/Cargo/CargoProductPrototype.cs
rename to Content.Shared/Cargo/Prototypes/CargoProductPrototype.cs
index 7cad752b40..63bb301047 100644
--- a/Content.Shared/Cargo/CargoProductPrototype.cs
+++ b/Content.Shared/Cargo/Prototypes/CargoProductPrototype.cs
@@ -3,7 +3,7 @@ using Robust.Shared.Serialization;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
using Robust.Shared.Utility;
-namespace Content.Shared.Cargo
+namespace Content.Shared.Cargo.Prototypes
{
[NetSerializable, Serializable, Prototype("cargoProduct")]
public sealed class CargoProductPrototype : IPrototype
@@ -13,7 +13,7 @@ namespace Content.Shared.Cargo
[DataField("description")] private string _description = string.Empty;
[ViewVariables]
- [IdDataFieldAttribute]
+ [IdDataField]
public string ID { get; } = default!;
///
diff --git a/Content.Shared/Cargo/Prototypes/CargoShuttlePrototype.cs b/Content.Shared/Cargo/Prototypes/CargoShuttlePrototype.cs
new file mode 100644
index 0000000000..8dac2a98b0
--- /dev/null
+++ b/Content.Shared/Cargo/Prototypes/CargoShuttlePrototype.cs
@@ -0,0 +1,20 @@
+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!;
+
+ [ViewVariables, DataField("path")]
+ public ResourcePath Path = default!;
+
+ [ViewVariables, DataField("nameDataset", customTypeSerializer:typeof(PrototypeIdSerializer))]
+ public string NameDataset = "CargoShuttleNames";
+}
diff --git a/Content.Shared/Cargo/SharedCargoSystem.cs b/Content.Shared/Cargo/SharedCargoSystem.cs
index 1931c0b95e..2e2546dadb 100644
--- a/Content.Shared/Cargo/SharedCargoSystem.cs
+++ b/Content.Shared/Cargo/SharedCargoSystem.cs
@@ -2,6 +2,14 @@ using Robust.Shared.Serialization;
namespace Content.Shared.Cargo;
+[NetSerializable, Serializable]
+public enum CargoConsoleUiKey : byte
+{
+ Orders,
+ Shuttle,
+ Telepad
+}
+
public abstract class SharedCargoSystem : EntitySystem {}
[Serializable, NetSerializable]
diff --git a/Content.Shared/Shuttles/BUIStates/RadarConsoleBoundInterfaceState.cs b/Content.Shared/Shuttles/BUIStates/RadarConsoleBoundInterfaceState.cs
index 550c6d28f1..bb16f9bdbc 100644
--- a/Content.Shared/Shuttles/BUIStates/RadarConsoleBoundInterfaceState.cs
+++ b/Content.Shared/Shuttles/BUIStates/RadarConsoleBoundInterfaceState.cs
@@ -8,16 +8,28 @@ namespace Content.Shared.Shuttles.BUIStates;
public class RadarConsoleBoundInterfaceState : BoundUserInterfaceState
{
public readonly float MaxRange;
- public readonly EntityUid? Entity;
+
+ ///
+ /// The relevant coordinates to base the radar around.
+ ///
+ public EntityCoordinates? Coordinates;
+
+ ///
+ /// The relevant rotation to rotate the angle around.
+ ///
+ public Angle? Angle;
+
public readonly List Docks;
public RadarConsoleBoundInterfaceState(
float maxRange,
- EntityUid? entity,
+ EntityCoordinates? coordinates,
+ Angle? angle,
List docks)
{
MaxRange = maxRange;
- Entity = entity;
+ Coordinates = coordinates;
+ Angle = angle;
Docks = docks;
}
}
diff --git a/Content.Shared/Shuttles/BUIStates/ShuttleConsoleBoundInterfaceState.cs b/Content.Shared/Shuttles/BUIStates/ShuttleConsoleBoundInterfaceState.cs
index d210fd5bb6..bad69c5f66 100644
--- a/Content.Shared/Shuttles/BUIStates/ShuttleConsoleBoundInterfaceState.cs
+++ b/Content.Shared/Shuttles/BUIStates/ShuttleConsoleBoundInterfaceState.cs
@@ -12,8 +12,9 @@ public sealed class ShuttleConsoleBoundInterfaceState : RadarConsoleBoundInterfa
public ShuttleConsoleBoundInterfaceState(
ShuttleMode mode,
float maxRange,
- EntityUid? entity,
- List docks) : base(maxRange, entity, docks)
+ EntityCoordinates? coordinates,
+ Angle? angle,
+ List docks) : base(maxRange, coordinates, angle, docks)
{
Mode = mode;
}
diff --git a/Content.Shared/Shuttles/Components/RadarConsoleComponent.cs b/Content.Shared/Shuttles/Components/RadarConsoleComponent.cs
index 92d51ab607..4e20a8b5f8 100644
--- a/Content.Shared/Shuttles/Components/RadarConsoleComponent.cs
+++ b/Content.Shared/Shuttles/Components/RadarConsoleComponent.cs
@@ -17,5 +17,5 @@ public sealed class RadarConsoleComponent : Component
}
[ViewVariables, DataField("maxRange")]
- public float MaxRange = 120f;
+ public float MaxRange = 256f;
}
diff --git a/Resources/Audio/Effects/Cargo/buzz_sigh.ogg b/Resources/Audio/Effects/Cargo/buzz_sigh.ogg
new file mode 100644
index 0000000000..109c196e2c
Binary files /dev/null and b/Resources/Audio/Effects/Cargo/buzz_sigh.ogg differ
diff --git a/Resources/Audio/Effects/Cargo/buzz_two.ogg b/Resources/Audio/Effects/Cargo/buzz_two.ogg
new file mode 100644
index 0000000000..3f79e2a0e9
Binary files /dev/null and b/Resources/Audio/Effects/Cargo/buzz_two.ogg differ
diff --git a/Resources/Audio/Effects/Cargo/licenses.txt b/Resources/Audio/Effects/Cargo/licenses.txt
new file mode 100644
index 0000000000..113b586912
--- /dev/null
+++ b/Resources/Audio/Effects/Cargo/licenses.txt
@@ -0,0 +1,7 @@
+The following sounds are taken from TGstation github (licensed under CC by 3.0):
+
+ buzz_sigh.ogg from https://github.com/tgstation/tgstation/tree/d6f15fb717e7c047f8befefabb4b7735b3c39a84/sound
+
+ buzz_two.ogg from https://github.com/tgstation/tgstation/tree/d6f15fb717e7c047f8befefabb4b7735b3c39a84/sound
+
+ ping.ogg from https://github.com/tgstation/tgstation/tree/d6f15fb717e7c047f8befefabb4b7735b3c39a84/sound
diff --git a/Resources/Audio/Effects/Cargo/ping.ogg b/Resources/Audio/Effects/Cargo/ping.ogg
new file mode 100644
index 0000000000..3f8a27cfcd
Binary files /dev/null and b/Resources/Audio/Effects/Cargo/ping.ogg differ
diff --git a/Resources/Audio/Effects/error.ogg b/Resources/Audio/Effects/error.ogg
deleted file mode 100644
index 4d7188e251..0000000000
Binary files a/Resources/Audio/Effects/error.ogg and /dev/null differ
diff --git a/Resources/Locale/en-US/cargo/cargo-console-component.ftl b/Resources/Locale/en-US/cargo/cargo-console-component.ftl
new file mode 100644
index 0000000000..f145522c14
--- /dev/null
+++ b/Resources/Locale/en-US/cargo/cargo-console-component.ftl
@@ -0,0 +1,43 @@
+## UI
+cargo-console-menu-title = Cargo request console
+cargo-console-menu-account-name-label = Account name:{" "}
+cargo-console-menu-account-name-none-text = None
+cargo-console-menu-shuttle-name-label = Shuttle name:{" "}
+cargo-console-menu-shuttle-name-none-text = None
+cargo-console-menu-points-label = Points:{" "}
+cargo-console-menu-shuttle-status-label = Shuttle status:{" "}
+cargo-console-menu-shuttle-status-away-text = Away
+cargo-console-menu-order-capacity-label = Order capacity:{" "}
+cargo-console-menu-call-shuttle-button = Activate telepad
+cargo-console-menu-permissions-button = Permissions
+cargo-console-menu-categories-label = Categories:{" "}
+cargo-console-menu-search-bar-placeholder = Search
+cargo-console-menu-requests-label = Requests
+cargo-console-menu-orders-label = Orders
+cargo-console-menu-order-reason-description = Reasons: {$reason}
+cargo-console-menu-populate-categories-all-text = All
+cargo-console-menu-populate-orders-cargo-order-row-product-name-text = {$productName} (x{$orderAmount}) by {$orderRequester}
+cargo-console-menu-cargo-order-row-approve-button = Approve
+cargo-console-menu-cargo-order-row-cancel-button = Cancel
+
+# Orders
+cargo-console-order-not-allowed = Access not allowed
+cargo-console-station-not-found = No available station
+cargo-console-invalid-product = Invalid product ID
+cargo-console-too-many = Too many approved orders
+cargo-console-snip-snip = Order trimmed to capacity
+cargo-console-insufficient-funds = Insufficient funds (require {$cost})
+
+cargo-console-paper-print-name = Order #{$orderNumber}
+cargo-console-paper-print-text =
+ Order #{$orderNumber}
+ Requested by: {$requester}
+ Reason: {$reason}
+ Approved by: {$approver}
+
+# Cargo shuttle console
+cargo-shuttle-console-menu-title = Cargo shuttle console
+cargo-shuttle-console-station-unknown = Unknown
+cargo-shuttle-console-shuttle-not-found = Not found
+cargo-shuttle-console-proximity = Too close to nearby objects
+cargo-shuttle-console-organics = Detected organic lifeforms on the shuttle
diff --git a/Resources/Locale/en-US/cargo/components/cargo-console-order-component.ftl b/Resources/Locale/en-US/cargo/cargo-console-order-component.ftl
similarity index 100%
rename from Resources/Locale/en-US/cargo/components/cargo-console-order-component.ftl
rename to Resources/Locale/en-US/cargo/cargo-console-order-component.ftl
diff --git a/Resources/Locale/en-US/cargo/components/cargo-order-database-component.ftl b/Resources/Locale/en-US/cargo/cargo-order-database-component.ftl
similarity index 100%
rename from Resources/Locale/en-US/cargo/components/cargo-order-database-component.ftl
rename to Resources/Locale/en-US/cargo/cargo-order-database-component.ftl
diff --git a/Resources/Locale/en-US/cargo/components/cargo-console-component.ftl b/Resources/Locale/en-US/cargo/components/cargo-console-component.ftl
deleted file mode 100644
index 32bce89169..0000000000
--- a/Resources/Locale/en-US/cargo/components/cargo-console-component.ftl
+++ /dev/null
@@ -1,27 +0,0 @@
-## UI
-cargo-console-menu-request-only-title = Cargo Request Console
-cargo-console-menu-title = Cargo Shuttle Console
-cargo-console-menu-account-name-label = Account Name:{" "}
-cargo-console-menu-account-name-none-text = None
-cargo-console-menu-points-label = Points:{" "}
-cargo-console-menu-shuttle-status-label = Shuttle Status:{" "}
-cargo-console-menu-shuttle-status-away-text = Away
-cargo-console-menu-order-capacity-label = Order Capacity:{" "}
-cargo-console-menu-call-shuttle-button = Activate Telepad
-cargo-console-menu-permissions-button = Permissions
-cargo-console-menu-categories-label = Categories:{" "}
-cargo-console-menu-search-bar-placeholder = Search
-cargo-console-menu-requests-label = Requests
-cargo-console-menu-orders-label = Orders
-cargo-console-menu-order-reason-description = Reasons: {$reason}
-cargo-console-menu-populate-categories-all-text = All
-cargo-console-menu-populate-orders-cargo-order-row-product-name-text = {$productName} (x{$orderAmount}) by {$orderRequester}
-cargo-console-menu-cargo-order-row-approve-button = Approve
-cargo-console-menu-cargo-order-row-cancel-button = Cancel
-
-cargo-console-paper-print-name = Order #{$orderNumber}
-cargo-console-paper-print-text =
- Order #{$orderNumber}
- Requested by: {$requester}
- Reason: {$reason}
- Approved by: {$approver}
diff --git a/Resources/Locale/en-US/cargo/galactic-bank-selection-menu.ftl b/Resources/Locale/en-US/cargo/galactic-bank-selection-menu.ftl
deleted file mode 100644
index 76b54eaddf..0000000000
--- a/Resources/Locale/en-US/cargo/galactic-bank-selection-menu.ftl
+++ /dev/null
@@ -1 +0,0 @@
-galactic-bank-selection-menu-title = Galactic Bank Selection
\ No newline at end of file
diff --git a/Resources/Locale/en-US/cargo/components/price-gun-component.ftl b/Resources/Locale/en-US/cargo/price-gun-component.ftl
similarity index 100%
rename from Resources/Locale/en-US/cargo/components/price-gun-component.ftl
rename to Resources/Locale/en-US/cargo/price-gun-component.ftl
diff --git a/Resources/Maps/Salvage/stationstation.yml b/Resources/Maps/Salvage/stationstation.yml
index 060e405f3f..105707e209 100644
--- a/Resources/Maps/Salvage/stationstation.yml
+++ b/Resources/Maps/Salvage/stationstation.yml
@@ -2603,7 +2603,7 @@ entities:
parent: 179
type: Transform
- uid: 326
- type: ComputerSupplyRequest
+ type: ComputerCargoOrders
components:
- pos: 0.5,-5.5
parent: 179
@@ -2613,7 +2613,7 @@ entities:
ents: []
type: ContainerContainer
- uid: 327
- type: ComputerSupplyOrdering
+ type: ComputerCargoOrders
components:
- pos: 0.5,0.5
parent: 179
diff --git a/Resources/Maps/atlas.yml b/Resources/Maps/atlas.yml
index c9a6622adf..dcbccc5cc9 100644
--- a/Resources/Maps/atlas.yml
+++ b/Resources/Maps/atlas.yml
@@ -16554,7 +16554,7 @@ entities:
parent: 30
type: Transform
- uid: 1172
- type: ComputerSupplyOrdering
+ type: ComputerCargoOrders
components:
- rot: -1.5707963267948966 rad
pos: -21.5,15.5
@@ -16678,7 +16678,7 @@ entities:
parent: 30
type: Transform
- uid: 1184
- type: cargoTelepad
+ type: CargoTelepad
components:
- pos: -21.5,16.5
parent: 30
@@ -43132,14 +43132,11 @@ entities:
parent: 30
type: Transform
- uid: 4712
- type: ComputerSupplyRequest
+ type: ComputerCargoOrders
components:
- pos: -35.5,17.5
parent: 30
type: Transform
- - outputs:
- OrderSender: []
- type: SignalTransmitter
- containers:
board: !type:Container
ents: []
@@ -49808,14 +49805,11 @@ entities:
parent: 30
type: Transform
- uid: 5603
- type: ComputerSupplyRequest
+ type: ComputerCargoOrders
components:
- pos: -27.5,17.5
parent: 30
type: Transform
- - outputs:
- OrderSender: []
- type: SignalTransmitter
- containers:
board: !type:Container
ents: []
@@ -51445,7 +51439,7 @@ entities:
parent: 30
type: Transform
- uid: 5833
- type: ComputerSupplyOrdering
+ type: ComputerCargoOrders
components:
- pos: -28.5,21.5
parent: 30
diff --git a/Resources/Maps/bagel.yml b/Resources/Maps/bagel.yml
index 48e0e0f0e2..a02b4e185e 100644
--- a/Resources/Maps/bagel.yml
+++ b/Resources/Maps/bagel.yml
@@ -119308,14 +119308,11 @@ entities:
parent: 60
type: Transform
- uid: 13084
- type: ComputerSupplyRequest
+ type: ComputerCargoOrders
components:
- pos: 43.5,10.5
parent: 60
type: Transform
- - outputs:
- OrderSender: []
- type: SignalTransmitter
- containers:
board: !type:Container
ents: []
@@ -119382,7 +119379,7 @@ entities:
parent: 60
type: Transform
- uid: 13095
- type: ComputerSupplyOrdering
+ type: ComputerCargoOrders
components:
- rot: 1.5707963267948966 rad
pos: 43.5,14.5
@@ -120078,15 +120075,12 @@ entities:
uid: 13173
type: SignalReceiver
- uid: 13172
- type: ComputerSupplyRequest
+ type: ComputerCargoOrders
components:
- rot: -1.5707963267948966 rad
pos: 56.5,13.5
parent: 60
type: Transform
- - outputs:
- OrderSender: []
- type: SignalTransmitter
- containers:
board: !type:Container
ents: []
@@ -153756,7 +153750,7 @@ entities:
- color: '#0335FCFF'
type: AtmosPipeColor
- uid: 17876
- type: cargoTelepad
+ type: CargoTelepad
components:
- pos: 50.5,11.5
parent: 60
@@ -162231,7 +162225,7 @@ entities:
ents: []
type: ContainerContainer
- uid: 19004
- type: ComputerSupplyOrdering
+ type: ComputerCargoOrders
components:
- pos: 49.5,11.5
parent: 60
@@ -162509,15 +162503,12 @@ entities:
parent: 60
type: Transform
- uid: 19043
- type: ComputerSupplyRequest
+ type: ComputerCargoOrders
components:
- rot: -1.5707963267948966 rad
pos: 41.5,3.5
parent: 60
type: Transform
- - outputs:
- OrderSender: []
- type: SignalTransmitter
- containers:
board: !type:Container
ents: []
diff --git a/Resources/Maps/barratry.yml b/Resources/Maps/barratry.yml
index fa00b0ae17..29f5c07a4e 100644
--- a/Resources/Maps/barratry.yml
+++ b/Resources/Maps/barratry.yml
@@ -44158,7 +44158,7 @@ entities:
uid: 9045
type: SignalReceiver
- uid: 3558
- type: cargoTelepad
+ type: CargoTelepad
components:
- pos: -32.5,-13.5
parent: 106
@@ -44235,7 +44235,7 @@ entities:
parent: 106
type: Transform
- uid: 3564
- type: ComputerSupplyRequest
+ type: ComputerCargoOrders
components:
- rot: 3.141592653589793 rad
pos: -31.5,-18.5
@@ -44245,9 +44245,6 @@ entities:
board: !type:Container
ents: []
type: ContainerContainer
- - outputs:
- OrderSender: []
- type: SignalTransmitter
- uid: 3565
type: FirelockEdge
components:
@@ -46747,7 +46744,7 @@ entities:
ents: []
type: ContainerContainer
- uid: 3905
- type: ComputerSupplyOrdering
+ type: ComputerCargoOrders
components:
- rot: 1.5707963267948966 rad
pos: -31.5,-13.5
@@ -46785,7 +46782,7 @@ entities:
parent: 106
type: Transform
- uid: 3910
- type: ComputerSupplyRequest
+ type: ComputerCargoOrders
components:
- rot: 1.5707963267948966 rad
pos: -38.5,-12.5
@@ -46795,9 +46792,6 @@ entities:
board: !type:Container
ents: []
type: ContainerContainer
- - outputs:
- OrderSender: []
- type: SignalTransmitter
- uid: 3911
type: Table
components:
diff --git a/Resources/Maps/cargo_shuttle.yml b/Resources/Maps/cargo_shuttle.yml
new file mode 100644
index 0000000000..bc42835507
--- /dev/null
+++ b/Resources/Maps/cargo_shuttle.yml
@@ -0,0 +1,2011 @@
+meta:
+ format: 2
+ name: DemoStation
+ author: Space-Wizards
+ postmapinit: false
+tilemap:
+ 0: space
+ 1: FloorArcadeBlue
+ 2: FloorArcadeBlue2
+ 3: FloorArcadeRed
+ 4: FloorAsteroidIronsand1
+ 5: FloorAsteroidIronsand2
+ 6: FloorAsteroidIronsand3
+ 7: FloorAsteroidIronsand4
+ 8: FloorBoxing
+ 9: FloorCarpetClown
+ 10: FloorCarpetOffice
+ 11: FloorEighties
+ 12: FloorGrassJungle
+ 13: FloorGym
+ 14: FloorMetalDiamond
+ 15: FloorShuttleBlue
+ 16: FloorShuttleOrange
+ 17: FloorShuttlePurple
+ 18: FloorShuttleRed
+ 19: FloorShuttleWhite
+ 20: floor_asteroid_coarse_sand0
+ 21: floor_asteroid_coarse_sand1
+ 22: floor_asteroid_coarse_sand2
+ 23: floor_asteroid_coarse_sand_dug
+ 24: floor_asteroid_sand
+ 25: floor_asteroid_tile
+ 26: floor_bar
+ 27: floor_blue
+ 28: floor_blue_circuit
+ 29: floor_clown
+ 30: floor_dark
+ 31: floor_elevator_shaft
+ 32: floor_freezer
+ 33: floor_glass
+ 34: floor_gold
+ 35: floor_grass
+ 36: floor_green_circuit
+ 37: floor_hydro
+ 38: floor_kitchen
+ 39: floor_laundry
+ 40: floor_lino
+ 41: floor_mime
+ 42: floor_mono
+ 43: floor_reinforced
+ 44: floor_rglass
+ 45: floor_rock_vault
+ 46: floor_showroom
+ 47: floor_silver
+ 48: floor_snow
+ 49: floor_steel
+ 50: floor_steel_dirty
+ 51: floor_techmaint
+ 52: floor_white
+ 53: floor_wood
+ 54: lattice
+ 55: plating
+grids:
+- settings:
+ chunksize: 16
+ tilesize: 1
+ chunks:
+ - ind: -1,0
+ tiles: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADEAAAAxAAAAMQAAADEAAAAxAAAAMQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAxAAAAMQAAADEAAAAxAAAAMQAAADEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANwAAADEAAAAxAAAAMQAAADEAAAAxAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADEAAAAxAAAAMQAAADEAAAAxAAAAMQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAxAAAAMQAAADEAAAAxAAAAMQAAADEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANwAAADEAAAAxAAAAMQAAADEAAAAxAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADcAAAA3AAAAMQAAADEAAAAxAAAANwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3AAAANwAAABMAAAAPAAAAEwAAADcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANwAAADcAAAA3AAAADwAAADcAAAA3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3AAAANwAAADcAAAA3AAAANwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
+ - ind: 0,0
+ tiles: MQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
+ - ind: -1,-1
+ tiles: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADcAAAA3AAAANwAAADcAAAA3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADcAAAA3AAAANwAAADcAAAA3AAAANwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3AAAANwAAADcAAAA3AAAANwAAADcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANwAAADcAAAAzAAAANwAAADMAAAA3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADcAAAAxAAAAMQAAADEAAAAxAAAAMQAAAA==
+ - ind: 0,-1
+ tiles: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
+entities:
+- uid: 0
+ components:
+ - pos: 2.2710133,-2.4148211
+ parent: null
+ type: Transform
+ - index: 0
+ type: MapGrid
+ - angularDamping: 100
+ linearDamping: 50
+ fixedRotation: False
+ bodyType: Dynamic
+ type: Physics
+ - fixtures: []
+ type: Fixtures
+ - gravityShakeSound: !type:SoundPathSpecifier
+ path: /Audio/Effects/alert.ogg
+ type: Gravity
+ - chunkCollection:
+ -1,0:
+ 0:
+ color: '#FFFFFFFF'
+ id: Bot
+ coordinates: -5,5
+ 1:
+ color: '#FFFFFFFF'
+ id: Bot
+ coordinates: -4,5
+ 2:
+ color: '#FFFFFFFF'
+ id: Bot
+ coordinates: -2,5
+ 3:
+ color: '#FFFFFFFF'
+ id: Bot
+ coordinates: -1,5
+ 8:
+ color: '#FFFFFFFF'
+ id: Bot
+ coordinates: -1,2
+ 9:
+ color: '#FFFFFFFF'
+ id: Bot
+ coordinates: -2,2
+ 10:
+ color: '#FFFFFFFF'
+ id: Bot
+ coordinates: -4,2
+ 11:
+ color: '#FFFFFFFF'
+ id: Bot
+ coordinates: -5,2
+ 12:
+ angle: -1.5707963267948966 rad
+ color: '#FFFFFFFF'
+ id: Arrows
+ coordinates: -5,1
+ 13:
+ angle: -1.5707963267948966 rad
+ color: '#FFFFFFFF'
+ id: Arrows
+ coordinates: -5,3
+ 14:
+ angle: 1.5707963267948966 rad
+ color: '#FFFFFFFF'
+ id: Arrows
+ coordinates: -1,1
+ 15:
+ angle: 1.5707963267948966 rad
+ color: '#FFFFFFFF'
+ id: Arrows
+ coordinates: -1,3
+ 16:
+ color: '#A4610696'
+ id: CheckerNWSE
+ coordinates: -3,0
+ 17:
+ color: '#A4610696'
+ id: CheckerNWSE
+ coordinates: -3,1
+ 18:
+ color: '#A4610696'
+ id: CheckerNWSE
+ coordinates: -3,2
+ 19:
+ color: '#A4610696'
+ id: CheckerNWSE
+ coordinates: -3,3
+ 20:
+ color: '#A4610696'
+ id: CheckerNWSE
+ coordinates: -3,4
+ 21:
+ color: '#A4610696'
+ id: QuarterTileOverlayGreyscale180
+ coordinates: -3,5
+ -1,-1:
+ 4:
+ color: '#FFFFFFFF'
+ id: Bot
+ coordinates: -1,-1
+ 5:
+ color: '#FFFFFFFF'
+ id: Bot
+ coordinates: -2,-1
+ 6:
+ color: '#FFFFFFFF'
+ id: Bot
+ coordinates: -4,-1
+ 7:
+ color: '#FFFFFFFF'
+ id: Bot
+ coordinates: -5,-1
+ 22:
+ color: '#A4610696'
+ id: QuarterTileOverlayGreyscale
+ coordinates: -3,-1
+ type: DecalGrid
+ - tiles:
+ -5,-2: 0
+ -5,-1: 0
+ -4,-10: 0
+ -4,-4: 0
+ -4,-3: 0
+ -3,-11: 0
+ -3,-8: 1
+ -3,-7: 1
+ -3,-6: 1
+ -2,-11: 0
+ -2,-9: 1
+ -2,-8: 1
+ -2,-7: 1
+ -2,-6: 1
+ -2,-5: 1
+ -2,-4: 1
+ -2,-3: 1
+ -2,-1: 1
+ -1,-11: 0
+ -1,-9: 1
+ -1,-8: 1
+ -1,-7: 1
+ -1,-6: 1
+ -1,-5: 1
+ -1,-4: 1
+ -1,-3: 1
+ -1,-1: 1
+ -5,5: 0
+ -5,6: 0
+ -5,7: 0
+ -4,1: 1
+ -4,2: 1
+ -4,3: 1
+ -4,7: 0
+ -4,8: 0
+ -4,9: 0
+ -3,12: 0
+ -3,13: 0
+ -3,14: 0
+ -2,0: 1
+ -2,1: 1
+ -2,2: 1
+ -2,3: 1
+ -2,4: 1
+ -2,5: 1
+ -2,7: 1
+ -2,8: 1
+ -2,9: 1
+ -2,10: 1
+ -1,0: 1
+ -1,1: 1
+ -1,2: 1
+ -1,3: 1
+ -1,4: 1
+ -1,5: 1
+ -1,7: 1
+ -1,8: 1
+ -1,9: 1
+ -1,10: 1
+ -1,12: 1
+ -1,13: 1
+ -1,14: 1
+ 0,-11: 0
+ 0,-9: 1
+ 0,-8: 1
+ 0,-7: 1
+ 0,-6: 1
+ 0,-5: 1
+ 0,-4: 1
+ 0,-3: 1
+ 1,-11: 0
+ 1,-9: 1
+ 1,-8: 1
+ 1,-7: 1
+ 1,-6: 1
+ 1,-5: 1
+ 1,-4: 1
+ 1,-3: 1
+ 1,-1: 1
+ 2,-11: 0
+ 2,-9: 1
+ 2,-8: 1
+ 2,-7: 1
+ 2,-6: 1
+ 2,-5: 1
+ 2,-4: 1
+ 2,-3: 1
+ 2,-1: 1
+ 3,-11: 0
+ 3,-9: 1
+ 3,-8: 1
+ 3,-7: 1
+ 3,-6: 1
+ 3,-5: 1
+ 3,-4: 1
+ 3,-3: 1
+ 3,-1: 1
+ 4,-11: 0
+ 4,-8: 1
+ 4,-7: 1
+ 4,-6: 1
+ 5,-10: 0
+ 5,-4: 0
+ 5,-3: 0
+ 6,-2: 0
+ 6,-1: 0
+ 0,7: 1
+ 0,8: 1
+ 0,9: 1
+ 0,10: 1
+ 0,12: 1
+ 0,13: 1
+ 0,14: 1
+ 0,15: 1
+ 1,0: 1
+ 1,1: 1
+ 1,2: 1
+ 1,3: 1
+ 1,4: 1
+ 1,5: 1
+ 1,7: 1
+ 1,8: 1
+ 1,9: 1
+ 1,10: 1
+ 1,12: 1
+ 1,13: 1
+ 1,14: 1
+ 1,15: 1
+ 2,0: 1
+ 2,1: 1
+ 2,2: 1
+ 2,3: 1
+ 2,4: 1
+ 2,5: 1
+ 2,7: 1
+ 2,8: 1
+ 2,9: 1
+ 2,10: 1
+ 2,12: 1
+ 2,13: 1
+ 2,14: 1
+ 3,0: 1
+ 3,1: 1
+ 3,2: 1
+ 3,3: 1
+ 3,4: 1
+ 3,5: 1
+ 3,7: 1
+ 3,8: 1
+ 3,9: 1
+ 3,10: 1
+ 4,12: 0
+ 4,13: 0
+ 4,14: 0
+ 5,1: 1
+ 5,2: 1
+ 5,3: 1
+ 5,7: 0
+ 5,8: 0
+ 5,9: 0
+ 6,1: 1
+ 6,2: 1
+ 6,3: 1
+ 6,5: 0
+ 6,6: 0
+ 6,7: 0
+ 0,17: 0
+ 1,17: 0
+ 2,17: 0
+ 3,16: 0
+ -2,16: 0
+ -1,17: 0
+ -4,-9: 1
+ -4,-8: 1
+ -4,-7: 1
+ -4,-6: 1
+ -4,-5: 1
+ -3,-10: 1
+ -3,-9: 1
+ -3,-5: 1
+ -3,-4: 1
+ -3,-3: 1
+ -3,-2: 1
+ -3,-1: 1
+ -2,-10: 1
+ -2,-2: 1
+ -1,-10: 1
+ -1,-2: 1
+ -5,0: 1
+ -5,1: 1
+ -5,2: 1
+ -5,3: 1
+ -5,4: 1
+ -4,0: 1
+ -4,4: 1
+ -3,0: 1
+ -3,1: 1
+ -3,2: 1
+ -3,3: 1
+ -3,4: 1
+ -3,5: 1
+ -3,6: 1
+ -3,7: 1
+ -3,8: 1
+ -3,9: 1
+ -3,10: 1
+ -3,11: 1
+ -2,6: 1
+ -2,11: 1
+ -2,12: 1
+ -2,13: 1
+ -2,14: 1
+ -2,15: 1
+ -1,6: 1
+ -1,11: 1
+ -1,15: 1
+ 0,-10: 1
+ 0,-2: 1
+ 0,-1: 1
+ 1,-10: 1
+ 1,-2: 1
+ 2,-10: 1
+ 2,-2: 1
+ 3,-10: 1
+ 3,-2: 1
+ 4,-10: 1
+ 4,-9: 1
+ 4,-5: 1
+ 4,-4: 1
+ 4,-3: 1
+ 4,-2: 1
+ 4,-1: 1
+ 5,-9: 1
+ 5,-8: 1
+ 5,-7: 1
+ 5,-6: 1
+ 5,-5: 1
+ 0,0: 1
+ 0,1: 1
+ 0,2: 1
+ 0,3: 1
+ 0,4: 1
+ 0,5: 1
+ 0,6: 1
+ 0,11: 1
+ 1,6: 1
+ 1,11: 1
+ 2,6: 1
+ 2,11: 1
+ 2,15: 1
+ 3,6: 1
+ 3,11: 1
+ 3,12: 1
+ 3,13: 1
+ 3,14: 1
+ 3,15: 1
+ 4,0: 1
+ 4,1: 1
+ 4,2: 1
+ 4,3: 1
+ 4,4: 1
+ 4,5: 1
+ 4,6: 1
+ 4,7: 1
+ 4,8: 1
+ 4,9: 1
+ 4,10: 1
+ 4,11: 1
+ 5,0: 1
+ 5,4: 1
+ 6,0: 1
+ 6,4: 1
+ 0,16: 1
+ 1,16: 1
+ 2,16: 1
+ -1,16: 1
+ -6,0: 1
+ -6,1: 1
+ -6,2: 1
+ -6,3: 1
+ -6,4: 1
+ -6,5: 1
+ -6,6: 1
+ -6,7: 1
+ -6,8: 1
+ -5,8: 1
+ -5,9: 1
+ -4,5: 1
+ -4,6: 1
+ -6,-4: 1
+ -6,-3: 1
+ -6,-2: 1
+ -6,-1: 1
+ -5,-5: 1
+ -5,-4: 1
+ -5,-3: 1
+ -4,-2: 1
+ -4,-1: 1
+ uniqueMixes:
+ - volume: 2500
+ immutable: True
+ moles:
+ - 0
+ - 0
+ - 0
+ - 0
+ - 0
+ - 0
+ - 0
+ - 0
+ - volume: 2500
+ temperature: 293.15
+ moles:
+ - 21.824879
+ - 82.10312
+ - 0
+ - 0
+ - 0
+ - 0
+ - 0
+ - 0
+ type: GridAtmosphere
+- uid: 1
+ type: BlastDoor
+ components:
+ - pos: 0.5,4.5
+ parent: 0
+ type: Transform
+ - inputs:
+ Open: []
+ Close: []
+ Toggle:
+ - port: Pressed
+ uid: 57
+ type: SignalReceiver
+- uid: 2
+ type: BlastDoor
+ components:
+ - pos: -5.5,4.5
+ parent: 0
+ type: Transform
+ - inputs:
+ Open: []
+ Close: []
+ Toggle:
+ - port: Pressed
+ uid: 56
+ type: SignalReceiver
+- uid: 3
+ type: BlastDoor
+ components:
+ - pos: -5.5,0.5
+ parent: 0
+ type: Transform
+ - inputs:
+ Open: []
+ Close: []
+ Toggle:
+ - port: Pressed
+ uid: 55
+ type: SignalReceiver
+- uid: 4
+ type: WallShuttle
+ components:
+ - pos: -5.5,8.5
+ parent: 0
+ type: Transform
+- uid: 5
+ type: WallShuttle
+ components:
+ - pos: -4.5,8.5
+ parent: 0
+ type: Transform
+- uid: 6
+ type: WallShuttle
+ components:
+ - pos: -0.5,8.5
+ parent: 0
+ type: Transform
+- uid: 7
+ type: WallShuttle
+ components:
+ - pos: 0.5,8.5
+ parent: 0
+ type: Transform
+- uid: 8
+ type: WallShuttle
+ components:
+ - pos: -0.5,-3.5
+ parent: 0
+ type: Transform
+- uid: 9
+ type: WallShuttle
+ components:
+ - pos: 0.5,-3.5
+ parent: 0
+ type: Transform
+- uid: 10
+ type: WallShuttle
+ components:
+ - pos: -4.5,-3.5
+ parent: 0
+ type: Transform
+- uid: 11
+ type: WallShuttle
+ components:
+ - pos: -5.5,-3.5
+ parent: 0
+ type: Transform
+- uid: 12
+ type: Thruster
+ components:
+ - rot: -1.5707963267948966 rad
+ pos: 0.5,-2.5
+ parent: 0
+ type: Transform
+ - enabled: False
+ type: AmbientSound
+- uid: 13
+ type: Thruster
+ components:
+ - rot: -1.5707963267948966 rad
+ pos: 0.5,7.5
+ parent: 0
+ type: Transform
+ - enabled: False
+ type: AmbientSound
+- uid: 14
+ type: Thruster
+ components:
+ - rot: 1.5707963267948966 rad
+ pos: -5.5,7.5
+ parent: 0
+ type: Transform
+ - enabled: False
+ type: AmbientSound
+- uid: 15
+ type: Thruster
+ components:
+ - rot: 1.5707963267948966 rad
+ pos: -5.5,-2.5
+ parent: 0
+ type: Transform
+ - enabled: False
+ type: AmbientSound
+- uid: 16
+ type: WallShuttle
+ components:
+ - pos: -0.5,-1.5
+ parent: 0
+ type: Transform
+- uid: 17
+ type: WallShuttle
+ components:
+ - pos: -0.5,-2.5
+ parent: 0
+ type: Transform
+- uid: 18
+ type: WallShuttle
+ components:
+ - pos: -4.5,-1.5
+ parent: 0
+ type: Transform
+- uid: 19
+ type: WallShuttle
+ components:
+ - pos: 0.5,-1.5
+ parent: 0
+ type: Transform
+- uid: 20
+ type: WallShuttle
+ components:
+ - pos: -4.5,-2.5
+ parent: 0
+ type: Transform
+- uid: 21
+ type: WallShuttle
+ components:
+ - pos: -5.5,-1.5
+ parent: 0
+ type: Transform
+- uid: 22
+ type: WallShuttle
+ components:
+ - pos: -0.5,7.5
+ parent: 0
+ type: Transform
+- uid: 23
+ type: WallShuttle
+ components:
+ - pos: -0.5,6.5
+ parent: 0
+ type: Transform
+- uid: 24
+ type: WallShuttle
+ components:
+ - pos: 0.5,6.5
+ parent: 0
+ type: Transform
+- uid: 25
+ type: WallShuttle
+ components:
+ - pos: -4.5,7.5
+ parent: 0
+ type: Transform
+- uid: 26
+ type: WallShuttle
+ components:
+ - pos: -4.5,6.5
+ parent: 0
+ type: Transform
+- uid: 27
+ type: WallShuttle
+ components:
+ - pos: -5.5,6.5
+ parent: 0
+ type: Transform
+- uid: 28
+ type: WallShuttle
+ components:
+ - pos: -5.5,-0.5
+ parent: 0
+ type: Transform
+- uid: 29
+ type: WallShuttle
+ components:
+ - pos: -5.5,5.5
+ parent: 0
+ type: Transform
+- uid: 30
+ type: WallShuttle
+ components:
+ - pos: 0.5,5.5
+ parent: 0
+ type: Transform
+- uid: 31
+ type: WallShuttle
+ components:
+ - pos: 0.5,-0.5
+ parent: 0
+ type: Transform
+- uid: 32
+ type: WallShuttle
+ components:
+ - pos: 0.5,2.5
+ parent: 0
+ type: Transform
+- uid: 33
+ type: WallShuttle
+ components:
+ - pos: -5.5,2.5
+ parent: 0
+ type: Transform
+- uid: 34
+ type: TwoWayLever
+ components:
+ - pos: -3.5,1.5
+ parent: 0
+ type: Transform
+ - outputs:
+ Left:
+ - port: Forward
+ uid: 43
+ - port: Forward
+ uid: 42
+ - port: Forward
+ uid: 41
+ Right:
+ - port: Reverse
+ uid: 43
+ - port: Reverse
+ uid: 42
+ - port: Reverse
+ uid: 41
+ Middle:
+ - port: Off
+ uid: 43
+ - port: Off
+ uid: 42
+ - port: Off
+ uid: 41
+ type: SignalTransmitter
+- uid: 35
+ type: TwoWayLever
+ components:
+ - pos: -1.5,1.5
+ parent: 0
+ type: Transform
+ - outputs:
+ Left:
+ - port: Forward
+ uid: 46
+ - port: Forward
+ uid: 45
+ - port: Forward
+ uid: 44
+ Right:
+ - port: Reverse
+ uid: 46
+ - port: Reverse
+ uid: 45
+ - port: Reverse
+ uid: 44
+ Middle:
+ - port: Off
+ uid: 46
+ - port: Off
+ uid: 45
+ - port: Off
+ uid: 44
+ type: SignalTransmitter
+- uid: 36
+ type: TwoWayLever
+ components:
+ - pos: -1.5,3.5
+ parent: 0
+ type: Transform
+ - outputs:
+ Left:
+ - port: Forward
+ uid: 38
+ - port: Forward
+ uid: 39
+ - port: Forward
+ uid: 40
+ Right:
+ - port: Reverse
+ uid: 38
+ - port: Reverse
+ uid: 39
+ - port: Reverse
+ uid: 40
+ Middle:
+ - port: Off
+ uid: 38
+ - port: Off
+ uid: 39
+ - port: Off
+ uid: 40
+ type: SignalTransmitter
+- uid: 37
+ type: TwoWayLever
+ components:
+ - pos: -3.5,3.5
+ parent: 0
+ type: Transform
+ - outputs:
+ Left:
+ - port: Forward
+ uid: 49
+ - port: Forward
+ uid: 48
+ - port: Forward
+ uid: 47
+ Right:
+ - port: Reverse
+ uid: 49
+ - port: Reverse
+ uid: 48
+ - port: Reverse
+ uid: 47
+ Middle:
+ - port: Off
+ uid: 49
+ - port: Off
+ uid: 48
+ - port: Off
+ uid: 47
+ type: SignalTransmitter
+- uid: 38
+ type: ConveyorBelt
+ components:
+ - rot: 1.5707963267948966 rad
+ pos: 0.5,4.5
+ parent: 0
+ type: Transform
+ - inputs:
+ Reverse:
+ - port: Right
+ uid: 36
+ Forward:
+ - port: Left
+ uid: 36
+ Off:
+ - port: Middle
+ uid: 36
+ type: SignalReceiver
+- uid: 39
+ type: ConveyorBelt
+ components:
+ - rot: 1.5707963267948966 rad
+ pos: -0.5,4.5
+ parent: 0
+ type: Transform
+ - inputs:
+ Reverse:
+ - port: Right
+ uid: 36
+ Forward:
+ - port: Left
+ uid: 36
+ Off:
+ - port: Middle
+ uid: 36
+ type: SignalReceiver
+- uid: 40
+ type: ConveyorBelt
+ components:
+ - rot: 1.5707963267948966 rad
+ pos: -1.5,4.5
+ parent: 0
+ type: Transform
+ - inputs:
+ Reverse:
+ - port: Right
+ uid: 36
+ Forward:
+ - port: Left
+ uid: 36
+ Off:
+ - port: Middle
+ uid: 36
+ type: SignalReceiver
+- uid: 41
+ type: ConveyorBelt
+ components:
+ - rot: 1.5707963267948966 rad
+ pos: -5.5,0.5
+ parent: 0
+ type: Transform
+ - inputs:
+ Reverse:
+ - port: Right
+ uid: 34
+ Forward:
+ - port: Left
+ uid: 34
+ Off:
+ - port: Middle
+ uid: 34
+ type: SignalReceiver
+- uid: 42
+ type: ConveyorBelt
+ components:
+ - rot: 1.5707963267948966 rad
+ pos: -4.5,0.5
+ parent: 0
+ type: Transform
+ - inputs:
+ Reverse:
+ - port: Right
+ uid: 34
+ Forward:
+ - port: Left
+ uid: 34
+ Off:
+ - port: Middle
+ uid: 34
+ type: SignalReceiver
+- uid: 43
+ type: ConveyorBelt
+ components:
+ - rot: 1.5707963267948966 rad
+ pos: -3.5,0.5
+ parent: 0
+ type: Transform
+ - inputs:
+ Reverse:
+ - port: Right
+ uid: 34
+ Forward:
+ - port: Left
+ uid: 34
+ Off:
+ - port: Middle
+ uid: 34
+ type: SignalReceiver
+- uid: 44
+ type: ConveyorBelt
+ components:
+ - rot: -1.5707963267948966 rad
+ pos: -1.5,0.5
+ parent: 0
+ type: Transform
+ - inputs:
+ Reverse:
+ - port: Right
+ uid: 35
+ Forward:
+ - port: Left
+ uid: 35
+ Off:
+ - port: Middle
+ uid: 35
+ type: SignalReceiver
+- uid: 45
+ type: ConveyorBelt
+ components:
+ - rot: -1.5707963267948966 rad
+ pos: -0.5,0.5
+ parent: 0
+ type: Transform
+ - inputs:
+ Reverse:
+ - port: Right
+ uid: 35
+ Forward:
+ - port: Left
+ uid: 35
+ Off:
+ - port: Middle
+ uid: 35
+ type: SignalReceiver
+- uid: 46
+ type: ConveyorBelt
+ components:
+ - rot: -1.5707963267948966 rad
+ pos: 0.5,0.5
+ parent: 0
+ type: Transform
+ - inputs:
+ Reverse:
+ - port: Right
+ uid: 35
+ Forward:
+ - port: Left
+ uid: 35
+ Off:
+ - port: Middle
+ uid: 35
+ type: SignalReceiver
+- uid: 47
+ type: ConveyorBelt
+ components:
+ - rot: -1.5707963267948966 rad
+ pos: -3.5,4.5
+ parent: 0
+ type: Transform
+ - inputs:
+ Reverse:
+ - port: Right
+ uid: 37
+ Forward:
+ - port: Left
+ uid: 37
+ Off:
+ - port: Middle
+ uid: 37
+ type: SignalReceiver
+- uid: 48
+ type: ConveyorBelt
+ components:
+ - rot: -1.5707963267948966 rad
+ pos: -4.5,4.5
+ parent: 0
+ type: Transform
+ - inputs:
+ Reverse:
+ - port: Right
+ uid: 37
+ Forward:
+ - port: Left
+ uid: 37
+ Off:
+ - port: Middle
+ uid: 37
+ type: SignalReceiver
+- uid: 49
+ type: ConveyorBelt
+ components:
+ - rot: -1.5707963267948966 rad
+ pos: -5.5,4.5
+ parent: 0
+ type: Transform
+ - inputs:
+ Reverse:
+ - port: Right
+ uid: 37
+ Forward:
+ - port: Left
+ uid: 37
+ Off:
+ - port: Middle
+ uid: 37
+ type: SignalReceiver
+- uid: 50
+ type: AirlockExternalGlassShuttleLocked
+ components:
+ - rot: -1.5707963267948966 rad
+ pos: -5.5,3.5
+ parent: 0
+ type: Transform
+ - fixtures:
+ - shape: !type:PolygonShape
+ vertices:
+ - 0.49,-0.49
+ - 0.49,0.49
+ - -0.49,0.49
+ - -0.49,-0.49
+ mask:
+ - Impassable
+ - MidImpassable
+ - HighImpassable
+ - LowImpassable
+ - InteractImpassable
+ layer:
+ - MidImpassable
+ - HighImpassable
+ - BulletImpassable
+ - InteractImpassable
+ - Opaque
+ mass: 100
+ - shape: !type:PhysShapeCircle
+ position: 0,-0.5
+ radius: 0.2
+ hard: False
+ id: docking
+ type: Fixtures
+- uid: 51
+ type: AirlockExternalGlassShuttleLocked
+ components:
+ - rot: 1.5707963267948966 rad
+ pos: 0.5,1.5
+ parent: 0
+ type: Transform
+ - fixtures:
+ - shape: !type:PolygonShape
+ vertices:
+ - 0.49,-0.49
+ - 0.49,0.49
+ - -0.49,0.49
+ - -0.49,-0.49
+ mask:
+ - Impassable
+ - MidImpassable
+ - HighImpassable
+ - LowImpassable
+ - InteractImpassable
+ layer:
+ - MidImpassable
+ - HighImpassable
+ - BulletImpassable
+ - InteractImpassable
+ - Opaque
+ mass: 100
+ - shape: !type:PhysShapeCircle
+ position: 0,-0.5
+ radius: 0.2
+ hard: False
+ id: docking
+ type: Fixtures
+- uid: 52
+ type: AirlockExternalGlassShuttleLocked
+ components:
+ - rot: 1.5707963267948966 rad
+ pos: 0.5,3.5
+ parent: 0
+ type: Transform
+ - fixtures:
+ - shape: !type:PolygonShape
+ vertices:
+ - 0.49,-0.49
+ - 0.49,0.49
+ - -0.49,0.49
+ - -0.49,-0.49
+ mask:
+ - Impassable
+ - MidImpassable
+ - HighImpassable
+ - LowImpassable
+ - InteractImpassable
+ layer:
+ - MidImpassable
+ - HighImpassable
+ - BulletImpassable
+ - InteractImpassable
+ - Opaque
+ mass: 100
+ - shape: !type:PhysShapeCircle
+ position: 0,-0.5
+ radius: 0.2
+ hard: False
+ id: docking
+ type: Fixtures
+- uid: 53
+ type: AirlockExternalGlassShuttleLocked
+ components:
+ - rot: -1.5707963267948966 rad
+ pos: -5.5,1.5
+ parent: 0
+ type: Transform
+ - fixtures:
+ - shape: !type:PolygonShape
+ vertices:
+ - 0.49,-0.49
+ - 0.49,0.49
+ - -0.49,0.49
+ - -0.49,-0.49
+ mask:
+ - Impassable
+ - MidImpassable
+ - HighImpassable
+ - LowImpassable
+ - InteractImpassable
+ layer:
+ - MidImpassable
+ - HighImpassable
+ - BulletImpassable
+ - InteractImpassable
+ - Opaque
+ mass: 100
+ - shape: !type:PhysShapeCircle
+ position: 0,-0.5
+ radius: 0.2
+ hard: False
+ id: docking
+ type: Fixtures
+- uid: 54
+ type: BlastDoor
+ components:
+ - pos: 0.5,0.5
+ parent: 0
+ type: Transform
+ - inputs:
+ Open: []
+ Close: []
+ Toggle:
+ - port: Pressed
+ uid: 58
+ type: SignalReceiver
+- uid: 55
+ type: SignalButton
+ components:
+ - pos: -5.5,-0.5
+ parent: 0
+ type: Transform
+ - fixtures: []
+ type: Fixtures
+ - outputs:
+ Pressed:
+ - port: Toggle
+ uid: 3
+ type: SignalTransmitter
+- uid: 56
+ type: SignalButton
+ components:
+ - pos: -5.5,5.5
+ parent: 0
+ type: Transform
+ - fixtures: []
+ type: Fixtures
+ - outputs:
+ Pressed:
+ - port: Toggle
+ uid: 2
+ type: SignalTransmitter
+- uid: 57
+ type: SignalButton
+ components:
+ - pos: 0.5,5.5
+ parent: 0
+ type: Transform
+ - fixtures: []
+ type: Fixtures
+ - outputs:
+ Pressed:
+ - port: Toggle
+ uid: 1
+ type: SignalTransmitter
+- uid: 58
+ type: SignalButton
+ components:
+ - pos: 0.5,-0.5
+ parent: 0
+ type: Transform
+ - fixtures: []
+ type: Fixtures
+ - outputs:
+ Pressed:
+ - port: Toggle
+ uid: 54
+ type: SignalTransmitter
+- uid: 59
+ type: Thruster
+ components:
+ - pos: -4.5,9.5
+ parent: 0
+ type: Transform
+ - enabled: False
+ type: AmbientSound
+- uid: 60
+ type: Thruster
+ components:
+ - pos: -0.5,9.5
+ parent: 0
+ type: Transform
+ - enabled: False
+ type: AmbientSound
+- uid: 61
+ type: Thruster
+ components:
+ - rot: 3.141592653589793 rad
+ pos: -0.5,-4.5
+ parent: 0
+ type: Transform
+ - enabled: False
+ type: AmbientSound
+- uid: 62
+ type: Thruster
+ components:
+ - rot: 3.141592653589793 rad
+ pos: -4.5,-4.5
+ parent: 0
+ type: Transform
+ - enabled: False
+ type: AmbientSound
+- uid: 63
+ type: WallShuttle
+ components:
+ - pos: -3.5,-4.5
+ parent: 0
+ type: Transform
+- uid: 64
+ type: WallShuttle
+ components:
+ - pos: -2.5,-4.5
+ parent: 0
+ type: Transform
+- uid: 65
+ type: WallShuttle
+ components:
+ - pos: -1.5,-4.5
+ parent: 0
+ type: Transform
+- uid: 66
+ type: WallShuttle
+ components:
+ - pos: -3.5,-3.5
+ parent: 0
+ type: Transform
+- uid: 67
+ type: WallShuttle
+ components:
+ - pos: -1.5,-3.5
+ parent: 0
+ type: Transform
+- uid: 68
+ type: ReinforcedWindow
+ components:
+ - pos: -3.5,8.5
+ parent: 0
+ type: Transform
+- uid: 69
+ type: ReinforcedWindow
+ components:
+ - pos: -3.5,9.5
+ parent: 0
+ type: Transform
+- uid: 70
+ type: ReinforcedWindow
+ components:
+ - pos: -2.5,9.5
+ parent: 0
+ type: Transform
+- uid: 71
+ type: ReinforcedWindow
+ components:
+ - pos: -1.5,9.5
+ parent: 0
+ type: Transform
+- uid: 72
+ type: ReinforcedWindow
+ components:
+ - pos: -1.5,8.5
+ parent: 0
+ type: Transform
+- uid: 73
+ type: Grille
+ components:
+ - pos: -3.5,8.5
+ parent: 0
+ type: Transform
+- uid: 74
+ type: Grille
+ components:
+ - pos: -3.5,9.5
+ parent: 0
+ type: Transform
+- uid: 75
+ type: Grille
+ components:
+ - pos: -2.5,9.5
+ parent: 0
+ type: Transform
+- uid: 76
+ type: Grille
+ components:
+ - pos: -1.5,9.5
+ parent: 0
+ type: Transform
+- uid: 77
+ type: Grille
+ components:
+ - pos: -1.5,8.5
+ parent: 0
+ type: Transform
+- uid: 78
+ type: ComputerShuttle
+ components:
+ - pos: -2.5,8.5
+ parent: 0
+ type: Transform
+ - containers:
+ board: !type:Container
+ ents: []
+ type: ContainerContainer
+- uid: 79
+ type: APCHyperCapacity
+ components:
+ - pos: -0.5,6.5
+ parent: 0
+ type: Transform
+- uid: 80
+ type: CableHV
+ components:
+ - pos: -1.5,-2.5
+ parent: 0
+ type: Transform
+- uid: 81
+ type: CableHV
+ components:
+ - pos: -2.5,-2.5
+ parent: 0
+ type: Transform
+- uid: 82
+ type: CableTerminal
+ components:
+ - rot: 3.141592653589793 rad
+ pos: -2.5,-3.5
+ parent: 0
+ type: Transform
+- uid: 83
+ type: GeneratorUranium
+ components:
+ - pos: -2.5,-3.5
+ parent: 0
+ type: Transform
+ - containers:
+ - machine_parts
+ - machine_board
+ type: Construction
+- uid: 84
+ type: SMESBasic
+ components:
+ - pos: -2.5,-2.5
+ parent: 0
+ type: Transform
+ - containers:
+ - machine_parts
+ - machine_board
+ type: Construction
+- uid: 85
+ type: SubstationBasic
+ components:
+ - pos: -1.5,-2.5
+ parent: 0
+ type: Transform
+ - containers:
+ - machine_parts
+ - machine_board
+ type: Construction
+- uid: 86
+ type: CableHV
+ components:
+ - pos: -2.5,-3.5
+ parent: 0
+ type: Transform
+- uid: 87
+ type: CableMV
+ components:
+ - pos: -1.5,-2.5
+ parent: 0
+ type: Transform
+- uid: 88
+ type: CableMV
+ components:
+ - pos: -1.5,-1.5
+ parent: 0
+ type: Transform
+- uid: 89
+ type: CableMV
+ components:
+ - pos: -2.5,-1.5
+ parent: 0
+ type: Transform
+- uid: 90
+ type: CableMV
+ components:
+ - pos: -2.5,-0.5
+ parent: 0
+ type: Transform
+- uid: 91
+ type: CableMV
+ components:
+ - pos: -2.5,0.5
+ parent: 0
+ type: Transform
+- uid: 92
+ type: CableMV
+ components:
+ - pos: -2.5,1.5
+ parent: 0
+ type: Transform
+- uid: 93
+ type: CableMV
+ components:
+ - pos: -2.5,2.5
+ parent: 0
+ type: Transform
+- uid: 94
+ type: CableMV
+ components:
+ - pos: -2.5,3.5
+ parent: 0
+ type: Transform
+- uid: 95
+ type: CableMV
+ components:
+ - pos: -2.5,4.5
+ parent: 0
+ type: Transform
+- uid: 96
+ type: CableMV
+ components:
+ - pos: -2.5,5.5
+ parent: 0
+ type: Transform
+- uid: 97
+ type: CableMV
+ components:
+ - pos: -2.5,6.5
+ parent: 0
+ type: Transform
+- uid: 98
+ type: CableMV
+ components:
+ - pos: -1.5,6.5
+ parent: 0
+ type: Transform
+- uid: 99
+ type: CableMV
+ components:
+ - pos: -0.5,6.5
+ parent: 0
+ type: Transform
+- uid: 100
+ type: CableApcExtension
+ components:
+ - pos: -0.5,6.5
+ parent: 0
+ type: Transform
+- uid: 101
+ type: CableApcExtension
+ components:
+ - pos: -1.5,6.5
+ parent: 0
+ type: Transform
+- uid: 102
+ type: CableApcExtension
+ components:
+ - pos: -2.5,6.5
+ parent: 0
+ type: Transform
+- uid: 103
+ type: CableApcExtension
+ components:
+ - pos: -2.5,5.5
+ parent: 0
+ type: Transform
+- uid: 104
+ type: CableApcExtension
+ components:
+ - pos: -2.5,8.5
+ parent: 0
+ type: Transform
+- uid: 105
+ type: CableApcExtension
+ components:
+ - pos: -3.5,8.5
+ parent: 0
+ type: Transform
+- uid: 106
+ type: CableApcExtension
+ components:
+ - pos: -1.5,8.5
+ parent: 0
+ type: Transform
+- uid: 107
+ type: CableApcExtension
+ components:
+ - pos: -3.5,6.5
+ parent: 0
+ type: Transform
+- uid: 108
+ type: CableApcExtension
+ components:
+ - pos: -3.5,7.5
+ parent: 0
+ type: Transform
+- uid: 109
+ type: CableApcExtension
+ components:
+ - pos: -2.5,4.5
+ parent: 0
+ type: Transform
+- uid: 110
+ type: CableApcExtension
+ components:
+ - pos: -2.5,3.5
+ parent: 0
+ type: Transform
+- uid: 111
+ type: CableApcExtension
+ components:
+ - pos: -2.5,2.5
+ parent: 0
+ type: Transform
+- uid: 112
+ type: CableApcExtension
+ components:
+ - pos: -2.5,1.5
+ parent: 0
+ type: Transform
+- uid: 113
+ type: CableApcExtension
+ components:
+ - pos: -2.5,0.5
+ parent: 0
+ type: Transform
+- uid: 114
+ type: CableApcExtension
+ components:
+ - pos: -2.5,-0.5
+ parent: 0
+ type: Transform
+- uid: 115
+ type: CableApcExtension
+ components:
+ - pos: -2.5,-1.5
+ parent: 0
+ type: Transform
+- uid: 116
+ type: CableApcExtension
+ components:
+ - pos: -1.5,-4.5
+ parent: 0
+ type: Transform
+- uid: 117
+ type: CableApcExtension
+ components:
+ - pos: -1.5,-1.5
+ parent: 0
+ type: Transform
+- uid: 118
+ type: CableApcExtension
+ components:
+ - pos: -1.5,-2.5
+ parent: 0
+ type: Transform
+- uid: 119
+ type: CableApcExtension
+ components:
+ - pos: -2.5,-4.5
+ parent: 0
+ type: Transform
+- uid: 120
+ type: CableApcExtension
+ components:
+ - pos: -1.5,-3.5
+ parent: 0
+ type: Transform
+- uid: 121
+ type: CableApcExtension
+ components:
+ - pos: -3.5,-4.5
+ parent: 0
+ type: Transform
+- uid: 122
+ type: CableApcExtension
+ components:
+ - pos: -3.5,-3.5
+ parent: 0
+ type: Transform
+- uid: 123
+ type: CableApcExtension
+ components:
+ - pos: -4.5,7.5
+ parent: 0
+ type: Transform
+- uid: 124
+ type: CableApcExtension
+ components:
+ - pos: -0.5,7.5
+ parent: 0
+ type: Transform
+- uid: 125
+ type: CableApcExtension
+ components:
+ - pos: -1.5,3.5
+ parent: 0
+ type: Transform
+- uid: 126
+ type: CableApcExtension
+ components:
+ - pos: -0.5,3.5
+ parent: 0
+ type: Transform
+- uid: 127
+ type: CableApcExtension
+ components:
+ - pos: -1.5,1.5
+ parent: 0
+ type: Transform
+- uid: 128
+ type: CableApcExtension
+ components:
+ - pos: -0.5,1.5
+ parent: 0
+ type: Transform
+- uid: 129
+ type: CableApcExtension
+ components:
+ - pos: -3.5,1.5
+ parent: 0
+ type: Transform
+- uid: 130
+ type: CableApcExtension
+ components:
+ - pos: -4.5,1.5
+ parent: 0
+ type: Transform
+- uid: 131
+ type: CableApcExtension
+ components:
+ - pos: -3.5,3.5
+ parent: 0
+ type: Transform
+- uid: 132
+ type: CableApcExtension
+ components:
+ - pos: -4.5,3.5
+ parent: 0
+ type: Transform
+- uid: 133
+ type: CableHV
+ components:
+ - pos: -3.5,-2.5
+ parent: 0
+ type: Transform
+- uid: 134
+ type: GeneratorUranium
+ components:
+ - pos: -3.5,-2.5
+ parent: 0
+ type: Transform
+ - containers:
+ - machine_parts
+ - machine_board
+ type: Construction
+- uid: 135
+ type: CableTerminal
+ components:
+ - rot: 1.5707963267948966 rad
+ pos: -3.5,-2.5
+ parent: 0
+ type: Transform
+- uid: 136
+ type: CableHV
+ components:
+ - pos: -2.5,-1.5
+ parent: 0
+ type: Transform
+- uid: 137
+ type: CableTerminal
+ components:
+ - pos: -2.5,-1.5
+ parent: 0
+ type: Transform
+- uid: 138
+ type: GeneratorUranium
+ components:
+ - pos: -2.5,-1.5
+ parent: 0
+ type: Transform
+ - containers:
+ - machine_parts
+ - machine_board
+ type: Construction
+- uid: 139
+ type: WindowReinforcedDirectional
+ components:
+ - rot: 3.141592653589793 rad
+ pos: -3.5,6.5
+ parent: 0
+ type: Transform
+- uid: 140
+ type: Gyroscope
+ components:
+ - pos: -3.5,-1.5
+ parent: 0
+ type: Transform
+ - enabled: False
+ type: AmbientSound
+- uid: 141
+ type: ChairPilotSeat
+ components:
+ - rot: 3.141592653589793 rad
+ pos: -2.5,7.5
+ parent: 0
+ type: Transform
+- uid: 142
+ type: WindowReinforcedDirectional
+ components:
+ - rot: 3.141592653589793 rad
+ pos: -1.5,6.5
+ parent: 0
+ type: Transform
+- uid: 143
+ type: TableReinforced
+ components:
+ - pos: -3.5,7.5
+ parent: 0
+ type: Transform
+- uid: 144
+ type: TableReinforced
+ components:
+ - pos: -1.5,7.5
+ parent: 0
+ type: Transform
+- uid: 145
+ type: WindoorSecureCargoLocked
+ components:
+ - rot: 3.141592653589793 rad
+ pos: -2.5,6.5
+ parent: 0
+ type: Transform
+- uid: 146
+ type: GravityGeneratorMini
+ components:
+ - pos: -1.5,-1.5
+ parent: 0
+ type: Transform
+ - enabled: False
+ type: AmbientSound
+ - powerLoad: 500
+ type: ApcPowerReceiver
+ - radius: 2.5
+ type: PointLight
+- uid: 147
+ type: Poweredlight
+ components:
+ - rot: -1.5707963267948966 rad
+ pos: -0.5,2.5
+ parent: 0
+ type: Transform
+ - powerLoad: 0
+ type: ApcPowerReceiver
+ - inputs:
+ On: []
+ Off: []
+ Toggle: []
+ type: SignalReceiver
+- uid: 148
+ type: Poweredlight
+ components:
+ - rot: 1.5707963267948966 rad
+ pos: -4.5,2.5
+ parent: 0
+ type: Transform
+ - powerLoad: 0
+ type: ApcPowerReceiver
+ - inputs:
+ On: []
+ Off: []
+ Toggle: []
+ type: SignalReceiver
+- uid: 149
+ type: Poweredlight
+ components:
+ - rot: 1.5707963267948966 rad
+ pos: -3.5,7.5
+ parent: 0
+ type: Transform
+ - powerLoad: 0
+ type: ApcPowerReceiver
+ - inputs:
+ On: []
+ Off: []
+ Toggle: []
+ type: SignalReceiver
+- uid: 150
+ type: Poweredlight
+ components:
+ - rot: -1.5707963267948966 rad
+ pos: -1.5,7.5
+ parent: 0
+ type: Transform
+ - powerLoad: 0
+ type: ApcPowerReceiver
+ - inputs:
+ On: []
+ Off: []
+ Toggle: []
+ type: SignalReceiver
+- uid: 151
+ type: CargoPallet
+ components:
+ - pos: -4.5,5.5
+ parent: 0
+ type: Transform
+ - canCollide: False
+ type: Physics
+- uid: 152
+ type: CargoPallet
+ components:
+ - pos: -3.5,5.5
+ parent: 0
+ type: Transform
+ - canCollide: False
+ type: Physics
+- uid: 153
+ type: CargoPallet
+ components:
+ - pos: -1.5,5.5
+ parent: 0
+ type: Transform
+ - canCollide: False
+ type: Physics
+- uid: 154
+ type: CargoPallet
+ components:
+ - pos: -0.5,5.5
+ parent: 0
+ type: Transform
+ - canCollide: False
+ type: Physics
+- uid: 155
+ type: CargoPallet
+ components:
+ - pos: -0.5,2.5
+ parent: 0
+ type: Transform
+ - canCollide: False
+ type: Physics
+- uid: 156
+ type: CargoPallet
+ components:
+ - pos: -1.5,2.5
+ parent: 0
+ type: Transform
+ - canCollide: False
+ type: Physics
+- uid: 157
+ type: CargoPallet
+ components:
+ - pos: -1.5,-0.5
+ parent: 0
+ type: Transform
+ - canCollide: False
+ type: Physics
+- uid: 158
+ type: CargoPallet
+ components:
+ - pos: -0.5,-0.5
+ parent: 0
+ type: Transform
+ - canCollide: False
+ type: Physics
+- uid: 159
+ type: CargoPallet
+ components:
+ - pos: -3.5,2.5
+ parent: 0
+ type: Transform
+ - canCollide: False
+ type: Physics
+- uid: 160
+ type: CargoPallet
+ components:
+ - pos: -4.5,2.5
+ parent: 0
+ type: Transform
+ - canCollide: False
+ type: Physics
+- uid: 161
+ type: CargoPallet
+ components:
+ - pos: -4.5,-0.5
+ parent: 0
+ type: Transform
+ - canCollide: False
+ type: Physics
+- uid: 162
+ type: CargoPallet
+ components:
+ - pos: -3.5,-0.5
+ parent: 0
+ type: Transform
+ - canCollide: False
+ type: Physics
+- uid: 163
+ type: CableApcExtension
+ components:
+ - pos: -4.5,-3.5
+ parent: 0
+ type: Transform
+...
diff --git a/Resources/Maps/delta.yml b/Resources/Maps/delta.yml
index f704a903fc..c19fad5055 100644
--- a/Resources/Maps/delta.yml
+++ b/Resources/Maps/delta.yml
@@ -37669,7 +37669,7 @@ entities:
stash: !type:ContainerSlot {}
type: ContainerContainer
- uid: 437
- type: ComputerSupplyRequest
+ type: ComputerCargoOrders
components:
- rot: 1.5707963267948966 rad
pos: -13.5,0.5
@@ -37679,11 +37679,8 @@ entities:
board: !type:Container
ents: []
type: ContainerContainer
- - outputs:
- OrderSender: []
- type: SignalTransmitter
- uid: 438
- type: ComputerSupplyOrdering
+ type: ComputerCargoOrders
components:
- rot: 1.5707963267948966 rad
pos: -13.5,-0.5
@@ -42175,7 +42172,7 @@ entities:
ItemCabinet: !type:ContainerSlot {}
type: ContainerContainer
- uid: 1056
- type: ComputerSupplyOrdering
+ type: ComputerCargoOrders
components:
- pos: -8.5,16.5
parent: 60
@@ -42188,7 +42185,7 @@ entities:
OrderSender: []
type: SignalTransmitter
- uid: 1057
- type: ComputerSupplyRequest
+ type: ComputerCargoOrders
components:
- pos: -7.5,16.5
parent: 60
@@ -42197,9 +42194,6 @@ entities:
board: !type:Container
ents: []
type: ContainerContainer
- - outputs:
- OrderSender: []
- type: SignalTransmitter
- uid: 1058
type: CableApcExtension
components:
@@ -48619,7 +48613,7 @@ entities:
parent: 60
type: Transform
- uid: 1949
- type: ComputerSupplyRequest
+ type: ComputerCargoOrders
components:
- pos: -18.5,-32.5
parent: 60
@@ -48628,9 +48622,6 @@ entities:
board: !type:Container
ents: []
type: ContainerContainer
- - outputs:
- OrderSender: []
- type: SignalTransmitter
- uid: 1950
type: PosterLegitNanotrasenLogo
components:
@@ -107866,7 +107857,7 @@ entities:
parent: 60
type: Transform
- uid: 10252
- type: ComputerSupplyRequest
+ type: ComputerCargoOrders
components:
- pos: -29.5,43.5
parent: 60
@@ -107875,9 +107866,6 @@ entities:
board: !type:Container
ents: []
type: ContainerContainer
- - outputs:
- OrderSender: []
- type: SignalTransmitter
- uid: 10253
type: CableApcExtension
components:
@@ -150182,7 +150170,7 @@ entities:
stash: !type:ContainerSlot {}
type: ContainerContainer
- uid: 16392
- type: ComputerSupplyRequest
+ type: ComputerCargoOrders
components:
- rot: -1.5707963267948966 rad
pos: 10.5,31.5
@@ -150192,9 +150180,6 @@ entities:
board: !type:Container
ents: []
type: ContainerContainer
- - outputs:
- OrderSender: []
- type: SignalTransmitter
- uid: 16393
type: TableReinforced
components:
@@ -150860,7 +150845,7 @@ entities:
ents: []
type: ContainerContainer
- uid: 16487
- type: ComputerSupplyOrdering
+ type: ComputerCargoOrders
components:
- rot: 1.5707963267948966 rad
pos: 8.5,33.5
@@ -152007,7 +151992,7 @@ entities:
parent: 60
type: Transform
- uid: 16645
- type: ComputerSupplyOrdering
+ type: ComputerCargoOrders
components:
- pos: 18.5,39.5
parent: 60
@@ -152022,7 +152007,7 @@ entities:
uid: 16646
type: SignalTransmitter
- uid: 16646
- type: cargoTelepad
+ type: CargoTelepad
components:
- pos: 18.5,40.5
parent: 60
@@ -152975,7 +152960,7 @@ entities:
parent: 60
type: Transform
- uid: 16775
- type: ComputerSupplyRequest
+ type: ComputerCargoOrders
components:
- pos: -1.5,49.5
parent: 60
@@ -152984,9 +152969,6 @@ entities:
board: !type:Container
ents: []
type: ContainerContainer
- - outputs:
- OrderSender: []
- type: SignalTransmitter
- uid: 16776
type: AirlockGlass
components:
@@ -154312,7 +154294,7 @@ entities:
uid: 30426
type: SignalReceiver
- uid: 16949
- type: ComputerSupplyOrdering
+ type: ComputerCargoOrders
components:
- rot: -1.5707963267948966 rad
pos: 25.5,48.5
@@ -155451,7 +155433,7 @@ entities:
parent: 60
type: Transform
- uid: 17120
- type: ComputerSupplyOrdering
+ type: ComputerCargoOrders
components:
- rot: -1.5707963267948966 rad
pos: 29.5,37.5
@@ -219233,7 +219215,7 @@ entities:
- color: '#0313FFFF'
type: AtmosPipeColor
- uid: 25752
- type: ComputerSupplyRequest
+ type: ComputerCargoOrders
components:
- rot: 3.141592653589793 rad
pos: 31.5,-26.5
@@ -219243,9 +219225,6 @@ entities:
board: !type:Container
ents: []
type: ContainerContainer
- - outputs:
- OrderSender: []
- type: SignalTransmitter
- uid: 25753
type: GasPipeTJunction
components:
@@ -281207,15 +281186,12 @@ entities:
ents: []
type: ContainerContainer
- uid: 33379
- type: ComputerSupplyRequest
+ type: ComputerCargoOrders
components:
- rot: -1.5707963267948966 rad
pos: 48.5,-2.5
parent: 60
type: Transform
- - outputs:
- OrderSender: []
- type: SignalTransmitter
- containers:
board: !type:Container
ents: []
diff --git a/Resources/Maps/marathon.yml b/Resources/Maps/marathon.yml
index 2e181fedc2..4fe49016b0 100644
--- a/Resources/Maps/marathon.yml
+++ b/Resources/Maps/marathon.yml
@@ -84441,7 +84441,7 @@ entities:
parent: 30
type: Transform
- uid: 8497
- type: ComputerSupplyRequest
+ type: ComputerCargoOrders
components:
- rot: 1.5707963267948966 rad
pos: 15.5,0.5
@@ -84451,11 +84451,8 @@ entities:
board: !type:Container
ents: []
type: ContainerContainer
- - outputs:
- OrderSender: []
- type: SignalTransmitter
- uid: 8498
- type: ComputerSupplyOrdering
+ type: ComputerCargoOrders
components:
- rot: 1.5707963267948966 rad
pos: 15.5,1.5
@@ -107377,7 +107374,7 @@ entities:
parent: 30
type: Transform
- uid: 11627
- type: ComputerSupplyOrdering
+ type: ComputerCargoOrders
components:
- pos: 24.5,2.5
parent: 30
@@ -108154,7 +108151,7 @@ entities:
uid: 8465
type: SignalTransmitter
- uid: 11718
- type: ComputerSupplyOrdering
+ type: ComputerCargoOrders
components:
- pos: 26.5,-3.5
parent: 30
@@ -108167,7 +108164,7 @@ entities:
OrderSender: []
type: SignalTransmitter
- uid: 11719
- type: cargoTelepad
+ type: CargoTelepad
components:
- pos: 26.5,-4.5
parent: 30
diff --git a/Resources/Maps/nss_pillar.yml b/Resources/Maps/nss_pillar.yml
index f0ae08b09e..ffb8857d32 100644
--- a/Resources/Maps/nss_pillar.yml
+++ b/Resources/Maps/nss_pillar.yml
@@ -28403,7 +28403,7 @@ entities:
parent: 130
type: Transform
- uid: 1171
- type: ComputerSupplyRequest
+ type: ComputerCargoOrders
components:
- pos: -30.5,-7.5
parent: 130
@@ -28412,9 +28412,6 @@ entities:
board: !type:Container
ents: []
type: ContainerContainer
- - outputs:
- OrderSender: []
- type: SignalTransmitter
- uid: 1172
type: Grille
components:
@@ -39959,7 +39956,7 @@ entities:
parent: 130
type: Transform
- uid: 2885
- type: ComputerSupplyOrdering
+ type: ComputerCargoOrders
components:
- rot: 3.141592653589793 rad
pos: -34.5,-16.5
@@ -40285,7 +40282,7 @@ entities:
parent: 130
type: Transform
- uid: 2933
- type: ComputerSupplyOrdering
+ type: ComputerCargoOrders
components:
- rot: 3.141592653589793 rad
pos: -35.5,-12.5
@@ -59257,7 +59254,7 @@ entities:
- canCollide: False
type: Physics
- uid: 5637
- type: cargoTelepad
+ type: CargoTelepad
components:
- pos: -34.5,-17.5
parent: 130
diff --git a/Resources/Maps/packedstation.yml b/Resources/Maps/packedstation.yml
index 4950333d92..000bab935a 100644
--- a/Resources/Maps/packedstation.yml
+++ b/Resources/Maps/packedstation.yml
@@ -28883,7 +28883,7 @@ entities:
charger-slot: !type:ContainerSlot {}
type: ContainerContainer
- uid: 2135
- type: ComputerSupplyOrdering
+ type: ComputerCargoOrders
components:
- rot: -1.5707963267948966 rad
pos: 13.5,30.5
@@ -28897,7 +28897,7 @@ entities:
OrderSender: []
type: SignalTransmitter
- uid: 2136
- type: ComputerSupplyRequest
+ type: ComputerCargoOrders
components:
- pos: 20.5,23.5
parent: 2
@@ -28906,9 +28906,6 @@ entities:
board: !type:Container
ents: []
type: ContainerContainer
- - outputs:
- OrderSender: []
- type: SignalTransmitter
- uid: 2137
type: CableHV
components:
@@ -94282,7 +94279,7 @@ entities:
parent: 2
type: Transform
- uid: 11095
- type: cargoTelepad
+ type: CargoTelepad
components:
- pos: 11.5,24.5
parent: 2
@@ -94293,7 +94290,7 @@ entities:
OrderReceiver: []
type: SignalReceiver
- uid: 11096
- type: ComputerSupplyOrdering
+ type: ComputerCargoOrders
components:
- pos: 11.5,25.5
parent: 2
diff --git a/Resources/Maps/packedstationxmas.yml b/Resources/Maps/packedstationxmas.yml
index 4e33216d3c..8b801d8f4a 100644
--- a/Resources/Maps/packedstationxmas.yml
+++ b/Resources/Maps/packedstationxmas.yml
@@ -22581,7 +22581,7 @@ entities:
charger-slot: !type:ContainerSlot {}
type: ContainerContainer
- uid: 2157
- type: ComputerSupplyOrdering
+ type: ComputerCargoOrders
components:
- pos: 13.5,30.5
parent: 0
@@ -22594,7 +22594,7 @@ entities:
OrderSender: []
type: SignalTransmitter
- uid: 2158
- type: ComputerSupplyOrdering
+ type: ComputerCargoOrders
components:
- pos: 20.5,23.5
parent: 0
@@ -87928,7 +87928,7 @@ entities:
parent: 0
type: Transform
- uid: 11133
- type: cargoTelepad
+ type: CargoTelepad
components:
- pos: 11.5,24.5
parent: 0
@@ -87939,7 +87939,7 @@ entities:
OrderReceiver: []
type: SignalReceiver
- uid: 11134
- type: ComputerSupplyOrdering
+ type: ComputerCargoOrders
components:
- pos: 11.5,25.5
parent: 0
diff --git a/Resources/Maps/saltern.yml b/Resources/Maps/saltern.yml
index 2c40685839..733bdc9220 100644
--- a/Resources/Maps/saltern.yml
+++ b/Resources/Maps/saltern.yml
@@ -23263,7 +23263,7 @@ entities:
ents: []
type: ContainerContainer
- uid: 1771
- type: ComputerSupplyRequest
+ type: ComputerCargoOrders
components:
- pos: 27.5,10.5
parent: 852
@@ -23272,9 +23272,6 @@ entities:
board: !type:Container
ents: []
type: ContainerContainer
- - outputs:
- OrderSender: []
- type: SignalTransmitter
- uid: 1772
type: LockerQuarterMasterFilled
components:
@@ -32620,16 +32617,13 @@ entities:
parent: 852
type: Transform
- uid: 3115
- type: cargoTelepad
+ type: CargoTelepad
components:
- pos: 20.5,10.5
parent: 852
type: Transform
- canCollide: False
type: Physics
- - inputs:
- OrderReceiver: []
- type: SignalReceiver
- uid: 3116
type: GasVentPump
components:
@@ -41694,7 +41688,7 @@ entities:
parent: 852
type: Transform
- uid: 4309
- type: ComputerSupplyRequest
+ type: ComputerCargoOrders
components:
- rot: -1.5707963267948966 rad
pos: 16.5,9.5
@@ -41704,9 +41698,6 @@ entities:
board: !type:Container
ents: []
type: ContainerContainer
- - outputs:
- OrderSender: []
- type: SignalTransmitter
- uid: 4310
type: CableApcExtension
components:
@@ -56953,7 +56944,7 @@ entities:
parent: 852
type: Transform
- uid: 6251
- type: ComputerSupplyOrdering
+ type: ComputerCargoOrders
components:
- rot: 1.5707963267948966 rad
pos: 21.5,10.5
@@ -56963,9 +56954,6 @@ entities:
board: !type:Container
ents: []
type: ContainerContainer
- - outputs:
- OrderSender: []
- type: SignalTransmitter
- uid: 6252
type: TableReinforced
components:
diff --git a/Resources/Maps/splitstation.yml b/Resources/Maps/splitstation.yml
index d5a37fef70..7bea442a25 100644
--- a/Resources/Maps/splitstation.yml
+++ b/Resources/Maps/splitstation.yml
@@ -70993,7 +70993,7 @@ entities:
parent: 69
type: Transform
- uid: 6473
- type: ComputerSupplyRequest
+ type: ComputerCargoOrders
components:
- rot: 3.141592653589793 rad
pos: 13.5,-70.5
@@ -71003,9 +71003,6 @@ entities:
board: !type:Container
ents: []
type: ContainerContainer
- - outputs:
- OrderSender: []
- type: SignalTransmitter
- uid: 6474
type: AirlockGlass
components:
@@ -186003,7 +186000,7 @@ entities:
- canCollide: False
type: Physics
- uid: 21911
- type: cargoTelepad
+ type: CargoTelepad
components:
- pos: 21.5,-71.5
parent: 69
@@ -186116,7 +186113,7 @@ entities:
ents: []
type: ContainerContainer
- uid: 21928
- type: ComputerSupplyOrdering
+ type: ComputerCargoOrders
components:
- rot: 1.5707963267948966 rad
pos: 22.5,-71.5
diff --git a/Resources/Maps/ssreach.yml b/Resources/Maps/ssreach.yml
index 6cd8fad41b..720c845d03 100644
--- a/Resources/Maps/ssreach.yml
+++ b/Resources/Maps/ssreach.yml
@@ -20161,7 +20161,7 @@ entities:
parent: 4
type: Transform
- uid: 1961
- type: ComputerSupplyOrdering
+ type: ComputerCargoOrders
components:
- pos: 6.5,8.5
parent: 4
@@ -20177,7 +20177,7 @@ entities:
parent: 4
type: Transform
- uid: 1963
- type: cargoTelepad
+ type: CargoTelepad
components:
- pos: 6.5,9.5
parent: 4
diff --git a/Resources/Maps/waystation.yml b/Resources/Maps/waystation.yml
index ad841c741d..4f0a35e354 100644
--- a/Resources/Maps/waystation.yml
+++ b/Resources/Maps/waystation.yml
@@ -18704,7 +18704,7 @@ entities:
parent: 82
type: Transform
- uid: 592
- type: cargoTelepad
+ type: CargoTelepad
components:
- pos: 14.5,43.5
parent: 82
@@ -33056,7 +33056,7 @@ entities:
parent: 82
type: Transform
- uid: 2222
- type: ComputerSupplyRequest
+ type: ComputerCargoOrders
components:
- pos: 16.5,33.5
parent: 82
@@ -33065,9 +33065,6 @@ entities:
board: !type:Container
ents: []
type: ContainerContainer
- - outputs:
- OrderSender: []
- type: SignalTransmitter
- uid: 2223
type: WallSolid
components:
@@ -33856,7 +33853,7 @@ entities:
parent: 82
type: Transform
- uid: 2312
- type: ComputerSupplyOrdering
+ type: ComputerCargoOrders
components:
- pos: 10.5,36.5
parent: 82
@@ -33978,7 +33975,7 @@ entities:
parent: 82
type: Transform
- uid: 2326
- type: ComputerSupplyOrdering
+ type: ComputerCargoOrders
components:
- rot: -1.5707963267948966 rad
pos: 17.5,36.5
@@ -68591,7 +68588,7 @@ entities:
ents: []
type: ContainerContainer
- uid: 6330
- type: ComputerSupplyOrdering
+ type: ComputerCargoOrders
components:
- pos: 28.5,-35.5
parent: 82
diff --git a/Resources/Prototypes/Catalog/Cargo/cargo_materials.yml b/Resources/Prototypes/Catalog/Cargo/cargo_materials.yml
index ccb90e32c4..0d77430557 100644
--- a/Resources/Prototypes/Catalog/Cargo/cargo_materials.yml
+++ b/Resources/Prototypes/Catalog/Cargo/cargo_materials.yml
@@ -9,7 +9,7 @@
cost: 2000
category: Materials
group: market
-
+
- type: cargoProduct
name: "fuel tank crate"
id: MaterialCrateFuelTank
@@ -78,7 +78,7 @@
sprite: Objects/Materials/Sheets/other.rsi
state: plasma_3
product: CrateMaterialPlasma
- cost: 4500
+ cost: 5000
category: Materials
group: market
diff --git a/Resources/Prototypes/Datasets/Names/cargo_shuttle.yml b/Resources/Prototypes/Datasets/Names/cargo_shuttle.yml
new file mode 100644
index 0000000000..85a95273f8
--- /dev/null
+++ b/Resources/Prototypes/Datasets/Names/cargo_shuttle.yml
@@ -0,0 +1,11 @@
+- type: dataset
+ id: CargoShuttleNames
+ values:
+ - A Shuttle Will Not Occur
+ - Big Money Shuttle
+ - Engine Change
+ - Ships-the-Cargo
+ - Shootel
+ - Shuttle McShuttleface
+ - ShuttleShuttle
+ - Urist McShuttle
\ No newline at end of file
diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml b/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml
index e3962d3525..eb9b54bfb4 100644
--- a/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml
+++ b/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml
@@ -114,6 +114,8 @@
- type: Bloodstream
bloodMaxVolume: 0.1
- type: NoSlip
+ - type: MobPrice
+ price: 50
- type: entity
name: bee
@@ -331,6 +333,8 @@
- type: Bloodstream
bloodMaxVolume: 0.1
- type: NoSlip
+ - type: MobPrice
+ price: 50
- type: entity
name: cow
@@ -822,7 +826,8 @@
bloodMaxVolume: 50
- type: DiseaseCarrier #The other class lab animal and disease vector
- type: CanEscapeInventory
-
+ - type: MobPrice
+ price: 50
- type: entity
parent: MobMouse
diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/pets.yml b/Resources/Prototypes/Entities/Mobs/NPCs/pets.yml
index c2a1d97ece..75c30eed30 100644
--- a/Resources/Prototypes/Entities/Mobs/NPCs/pets.yml
+++ b/Resources/Prototypes/Entities/Mobs/NPCs/pets.yml
@@ -50,6 +50,8 @@
- type: SentienceTarget
flavorKind: corgi
- type: Puller
+ - type: MobPrice
+ price: 200
- type: entity
name: corrupted corgi
@@ -272,6 +274,8 @@
- type: Grammar
attributes:
gender: epicene
+ - type: MobPrice
+ price: 200
- type: entity
name: Runtime
diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/simplemob.yml b/Resources/Prototypes/Entities/Mobs/NPCs/simplemob.yml
index 843da2c8d7..5f2d74f658 100644
--- a/Resources/Prototypes/Entities/Mobs/NPCs/simplemob.yml
+++ b/Resources/Prototypes/Entities/Mobs/NPCs/simplemob.yml
@@ -204,4 +204,6 @@
Heat : 1 #per second, scales with temperature & other constants
- type: Bloodstream
bloodMaxVolume: 150
+ - type: MobPrice
+ price: 150
diff --git a/Resources/Prototypes/Entities/Mobs/Player/admin_ghost.yml b/Resources/Prototypes/Entities/Mobs/Player/admin_ghost.yml
index 636aed8c31..cd40922738 100644
--- a/Resources/Prototypes/Entities/Mobs/Player/admin_ghost.yml
+++ b/Resources/Prototypes/Entities/Mobs/Player/admin_ghost.yml
@@ -44,8 +44,8 @@
type: CommunicationsConsoleBoundUserInterface
- key: enum.RadarConsoleUiKey.Key
type: RadarConsoleBoundUserInterface
- - key: enum.CargoConsoleUiKey.Key
- type: CargoConsoleBoundUserInterface
+ - key: enum.CargoConsoleUiKey.Orders
+ type: CargoOrderConsoleBoundUserInterface
- key: enum.CrewMonitoringUIKey.Key
type: CrewMonitoringBoundUserInterface
- type: IntrinsicUI
@@ -77,7 +77,7 @@
keywords: [ "AI", "console", "interface" ]
priority: -10
event: !type:ToggleIntrinsicUIEvent
- - key: enum.CargoConsoleUiKey.Key
+ - key: enum.CargoConsoleUiKey.Orders
toggleAction:
name: action-name-show-cargo-console
description: action-description-show-cargo-console
@@ -100,8 +100,7 @@
title: communicationsconsole-announcement-title-centcom
color: "#228b22"
- type: RadarConsole
- - type: CargoConsole
- - type: CargoOrderDatabase
+ - type: CargoOrderConsole
- type: CrewMonitoringConsole
snap: false
precision: 3
diff --git a/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/computer.yml b/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/computer.yml
index acd0644bd1..bbd1615c52 100644
--- a/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/computer.yml
+++ b/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/computer.yml
@@ -57,7 +57,7 @@
description: A computer printed circuit board for a supply ordering console
components:
- type: ComputerBoard
- prototype: ComputerSupplyOrdering
+ prototype: ComputerCargoOrders
- type: StaticPrice
price: 750
@@ -68,7 +68,7 @@
description: A computer printed circuit board for a supply request console
components:
- type: ComputerBoard
- prototype: ComputerSupplyRequest
+ prototype: ComputerCargoOrders
- type: entity
parent: BaseComputerCircuitboard
diff --git a/Resources/Prototypes/Entities/Objects/Specific/Cargo/cargo_pallet.yml b/Resources/Prototypes/Entities/Objects/Specific/Cargo/cargo_pallet.yml
new file mode 100644
index 0000000000..3f446e3a73
--- /dev/null
+++ b/Resources/Prototypes/Entities/Objects/Specific/Cargo/cargo_pallet.yml
@@ -0,0 +1,12 @@
+- type: entity
+ id: CargoPallet
+ name: cargo pallet
+ description: Designates valid items to sell to Centcomm when a shuttle is recalled.
+ parent: BaseStructure
+ components:
+ - type: CargoPallet
+ - type: Sprite
+ netsync: false
+ layers:
+ - texture: Structures/catwalk.rsi/catwalk_preview.png
+ - type: CollideOnAnchor
diff --git a/Resources/Prototypes/Entities/Structures/Machines/Computers/computers.yml b/Resources/Prototypes/Entities/Structures/Machines/Computers/computers.yml
index 2c8bae918e..1d4730e5d4 100644
--- a/Resources/Prototypes/Entities/Structures/Machines/Computers/computers.yml
+++ b/Resources/Prototypes/Entities/Structures/Machines/Computers/computers.yml
@@ -62,7 +62,26 @@
key: syndie_key
screen: syndishuttle
- type: RadarConsole
- maxRange: 512
+ maxRange: 1536
+ - type: PointLight
+ radius: 1.5
+ energy: 1.6
+ color: "#c94242"
+
+- type: entity
+ parent: ComputerShuttleBase
+ id: ComputerShuttleCargo
+ name: cargo shuttle console
+ description: Used to pilot the cargo shuttle.
+ components:
+ - type: Appearance
+ visuals:
+ - type: ComputerVisualizer
+ key: generic_key
+ screen: shuttle
+ - type: CargoPilotConsole
+ - type: RadarConsole
+ maxRange: 256
- type: PointLight
radius: 1.5
energy: 1.6
@@ -388,25 +407,24 @@
color: "#e6e227"
- type: entity
- id: ComputerSupplyOrdering
+ id: ComputerCargoShuttle
parent: ComputerBase
- name: Cargo ordering computer
- description: Used to order supplies, approve requests, and control the shuttle.
+ name: cargo shuttle computer
+ description: Used to order the shuttle.
components:
- type: Appearance
visuals:
- type: ComputerVisualizer
key: tech_key
screen: supply
- - type: CargoConsole
- - type: CargoOrderDatabase
+ - type: CargoShuttleConsole
- type: ActivatableUI
- key: enum.CargoConsoleUiKey.Key
+ key: enum.CargoConsoleUiKey.Shuttle
- type: ActivatableUIRequiresPower
- type: UserInterface
interfaces:
- - key: enum.CargoConsoleUiKey.Key
- type: CargoConsoleBoundUserInterface
+ - key: enum.CargoConsoleUiKey.Shuttle
+ type: CargoShuttleConsoleBoundUserInterface
- type: Computer
board: SupplyComputerCircuitboard
- type: PointLight
@@ -417,24 +435,32 @@
access: [["Cargo"]]
- type: entity
- id: ComputerSupplyRequest
- parent: ComputerSupplyOrdering
+ id: ComputerCargoOrders
+ parent: ComputerBase
name: cargo request computer
- description: Used to request supplies from cargo.
+ description: Used to order supplies and approve requests.
components:
- type: Appearance
visuals:
- type: ComputerVisualizer
key: tech_key
screen: request
- - type: CargoConsole
- requestOnly: true
+ - type: CargoOrderConsole
+ - type: ActivatableUI
+ key: enum.CargoConsoleUiKey.Orders
+ - type: ActivatableUIRequiresPower
+ - type: UserInterface
+ interfaces:
+ - key: enum.CargoConsoleUiKey.Orders
+ type: CargoOrderConsoleBoundUserInterface
- type: Computer
- board: SupplyRequestComputerCircuitboard
+ board: SupplyComputerCircuitboard
- type: PointLight
radius: 1.5
energy: 1.6
color: "#b89f25"
+ - type: AccessReader
+ access: [["Cargo"]]
- type: entity
parent: ComputerBase
diff --git a/Resources/Prototypes/Entities/Structures/Shuttles/thrusters.yml b/Resources/Prototypes/Entities/Structures/Shuttles/thrusters.yml
index a8032b9f6d..ddd22a5aff 100644
--- a/Resources/Prototypes/Entities/Structures/Shuttles/thrusters.yml
+++ b/Resources/Prototypes/Entities/Structures/Shuttles/thrusters.yml
@@ -118,3 +118,28 @@
autoRot: true
offset: "0, 0.1" # shine from the top, not bottom of the computer
color: "#4246b3"
+
+- type: entity
+ id: DebugGyroscope
+ parent: Gyroscope
+ name: gyroscope
+ suffix: DEBUG
+ description: Increases the shuttle's potential angular rotation.
+ components:
+ - type: Thruster
+ requireSpace: false
+ - type: ApcPowerReceiver
+ needsPower: false
+ powerLoad: 0
+ - type: Sprite
+ sprite: Structures/Shuttles/thruster.rsi
+ layers:
+ - state: base
+ map: ["enum.ThrusterVisualLayers.Base"]
+ - state: thrust
+ map: ["enum.ThrusterVisualLayers.ThrustOn"]
+ shader: unshaded
+ - state: thrust_burn_unshaded
+ map: ["enum.ThrusterVisualLayers.ThrustingUnshaded"]
+ shader: unshaded
+ offset: 0, 1
diff --git a/Resources/Prototypes/Entities/Structures/cargo_console.yml b/Resources/Prototypes/Entities/Structures/cargo_console.yml
new file mode 100644
index 0000000000..282882a963
--- /dev/null
+++ b/Resources/Prototypes/Entities/Structures/cargo_console.yml
@@ -0,0 +1,51 @@
+- type: entity
+ id: CargoTelepad
+ parent: BaseStructureDynamic
+ name: cargo telepad
+ components:
+ - type: InteractionOutline
+ - type: Physics
+ bodyType: Static
+ - type: Transform
+ anchored: true
+ noRot: true
+ - type: Fixtures
+ fixtures:
+ - shape:
+ !type:PhysShapeAabb
+ bounds: "-0.45,-0.45,0.45,0.00"
+ mass: 25
+ mask:
+ - MachineMask
+ - type: Sprite
+ netsync: false
+ sprite: Structures/cargo_telepad.rsi
+ drawdepth: FloorObjects
+ layers:
+ - state: offline
+ map: [ "enum.CargoTelepadLayers.Base" ]
+ - state: idle
+ map: [ "enum.CargoTelepadLayers.Beam" ]
+ shader: unshaded
+ - type: Damageable
+ damageContainer: Inorganic
+ damageModifierSet: Metallic
+ - type: Destructible
+ thresholds:
+ - trigger:
+ !type:DamageTrigger
+ damage: 75
+ behaviors:
+ - !type:SpawnEntitiesBehavior
+ spawn:
+ SheetSteel1:
+ min: 1
+ max: 1
+ - !type:DoActsBehavior
+ acts: [ "Destruction" ]
+ - type: ApcPowerReceiver
+ powerLoad: 1000 # TODO if we keep this make it spike power draw when teleporting
+ - type: ExtensionCableReceiver
+ - type: CargoTelepad
+ - type: Appearance
+ - type: CollideOnAnchor
diff --git a/Resources/Prototypes/Entities/Structures/cargo_telepad.yml b/Resources/Prototypes/Entities/Structures/cargo_telepad.yml
deleted file mode 100644
index 6938c45e4b..0000000000
--- a/Resources/Prototypes/Entities/Structures/cargo_telepad.yml
+++ /dev/null
@@ -1,52 +0,0 @@
-- type: entity
- id: cargoTelepad
- parent: BaseStructureDynamic
- name: cargo telepad
- description: 'Temporary cargo delivery for developing Nanotrasen stations! Warning: destroying this while goods are in transit will lose them forever!'
- components:
- - type: InteractionOutline
- - type: Physics
- bodyType: Static
- - type: Transform
- anchored: true
- noRot: true
- - type: Fixtures
- fixtures:
- - shape:
- !type:PhysShapeAabb
- bounds: "-0.45,-0.45,0.45,0.00"
- mass: 25
- mask:
- - MachineMask
- - type: Sprite
- netsync: false
- sprite: Structures/cargo_telepad.rsi
- drawdepth: FloorObjects
- layers:
- - state: offline
- map: ["enum.CargoTelepadLayers.Base"]
- - state: idle
- map: [ "enum.CargoTelepadLayers.Beam" ]
- shader: unshaded
- - type: Damageable
- damageContainer: Inorganic
- damageModifierSet: Metallic
- - type: Destructible
- thresholds:
- - trigger:
- !type:DamageTrigger
- damage: 75
- behaviors:
- - !type:SpawnEntitiesBehavior
- spawn:
- SheetSteel1:
- min: 1
- max: 1
- - !type:DoActsBehavior
- acts: ["Destruction"]
- - type: ApcPowerReceiver
- powerLoad: 1000 # TODO if we keep this make it spike power draw when teleporting
- - type: ExtensionCableReceiver
- - type: CargoTelepad
- - type: Appearance
- - type: CollideOnAnchor
diff --git a/Resources/Prototypes/shuttles.yml b/Resources/Prototypes/shuttles.yml
new file mode 100644
index 0000000000..e59e1762a9
--- /dev/null
+++ b/Resources/Prototypes/shuttles.yml
@@ -0,0 +1,4 @@
+# Cargo
+- type: cargoShuttle
+ id: CargoShuttle
+ path: /Maps/cargo_shuttle.yml