Merge branch 'master' into 2020-08-31-click-attack

This commit is contained in:
Víctor Aguilera Puerto
2020-09-02 15:12:17 +02:00
committed by GitHub
299 changed files with 42728 additions and 31895 deletions

View File

@@ -0,0 +1,45 @@
using Content.Shared.GameObjects.Components;
using JetBrains.Annotations;
using Robust.Client.GameObjects.Components.UserInterface;
namespace Content.Client.GameObjects.Components
{
[UsedImplicitly]
public class AcceptCloningBoundUserInterface : BoundUserInterface
{
public AcceptCloningBoundUserInterface(ClientUserInterfaceComponent owner, object uiKey) : base(owner, uiKey)
{
}
private AcceptCloningWindow _window;
protected override void Open()
{
base.Open();
_window = new AcceptCloningWindow();
_window.OnClose += Close;
_window.DenyButton.OnPressed += _ => _window.Close();
_window.ConfirmButton.OnPressed += _ =>
{
SendMessage(
new SharedAcceptCloningComponent.UiButtonPressedMessage(
SharedAcceptCloningComponent.UiButton.Accept));
_window.Close();
};
_window.OpenCentered();
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (disposing)
{
_window?.Dispose();
}
}
}
}

View File

@@ -0,0 +1,50 @@
#nullable enable
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls;
using Robust.Shared.Localization;
namespace Content.Client.GameObjects.Components
{
public sealed class AcceptCloningWindow : SS14Window
{
public readonly Button DenyButton;
public readonly Button ConfirmButton;
public AcceptCloningWindow()
{
Title = Loc.GetString("Cloning Machine");
Contents.AddChild(new VBoxContainer
{
Children =
{
new VBoxContainer
{
Children =
{
(new Label
{
Text = Loc.GetString("You are being cloned! Transfer your soul to the clone body?")
}),
new HBoxContainer
{
Children =
{
(ConfirmButton = new Button
{
Text = Loc.GetString("Yes"),
}),
(DenyButton = new Button
{
Text = Loc.GetString("No"),
})
}
},
}
},
}
});
}
}
}

View File

@@ -2,6 +2,7 @@
using System.Linq;
using Content.Client.GameObjects.Components.Mobs;
using Content.Client.UserInterface;
using Content.Shared.GameObjects.Components.Mobs;
using Content.Shared.Input;
using Robust.Client.GameObjects;
using Robust.Client.Interfaces.Input;

View File

@@ -1,8 +1,10 @@
#nullable enable
using Content.Client.GameObjects.Components.Disposal;
using Content.Client.GameObjects.Components.MedicalScanner;
using Content.Client.Interfaces.GameObjects.Components.Interaction;
using Content.Shared.GameObjects.Components.Body;
using Content.Shared.GameObjects.Components.Damage;
using Content.Shared.GameObjects.Components.Medical;
using Robust.Client.Interfaces.GameObjects.Components;
using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.GameObjects;
@@ -21,7 +23,13 @@ namespace Content.Client.GameObjects.Components.Body
public bool ClientCanDropOn(CanDropEventArgs eventArgs)
{
return eventArgs.Target.HasComponent<DisposalUnitComponent>();
if (
eventArgs.Target.HasComponent<DisposalUnitComponent>()||
eventArgs.Target.HasComponent<MedicalScannerComponent>())
{
return true;
}
return false;
}
public bool ClientCanDrag(CanDragEventArgs eventArgs)

View File

@@ -0,0 +1,60 @@
using System;
using System.Collections.Generic;
using Content.Shared.GameObjects.Components.Medical;
using JetBrains.Annotations;
using Robust.Client.GameObjects.Components.UserInterface;
using Robust.Shared.GameObjects;
using Robust.Shared.GameObjects.Components.UserInterface;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
using static Content.Shared.GameObjects.Components.Medical.SharedCloningPodComponent;
namespace Content.Client.GameObjects.Components.CloningPod
{
[UsedImplicitly]
public class CloningPodBoundUserInterface : BoundUserInterface
{
public CloningPodBoundUserInterface(ClientUserInterfaceComponent owner, object uiKey) : base(owner, uiKey)
{
}
private CloningPodWindow _window;
protected override void Open()
{
base.Open();
_window = new CloningPodWindow(new Dictionary<int, string>());
_window.OnClose += Close;
_window.CloneButton.OnPressed += _ =>
{
if (_window.SelectedScan != null)
{
SendMessage(new CloningPodUiButtonPressedMessage(UiButton.Clone, (int) _window.SelectedScan));
}
};
_window.EjectButton.OnPressed += _ =>
{
SendMessage(new CloningPodUiButtonPressedMessage(UiButton.Eject, null));
};
_window.OpenCentered();
}
protected override void UpdateState(BoundUserInterfaceState state)
{
base.UpdateState(state);
_window.Populate((CloningPodBoundUserInterfaceState) state);
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (disposing)
{
_window?.Dispose();
}
}
}
}

View File

@@ -0,0 +1,41 @@
using System;
using Content.Shared.GameObjects.Components.Medical;
using Robust.Client.GameObjects;
using Robust.Client.Interfaces.GameObjects.Components;
using static Content.Shared.GameObjects.Components.Medical.SharedCloningPodComponent;
using static Content.Shared.GameObjects.Components.Medical.SharedCloningPodComponent.CloningPodStatus;
namespace Content.Client.GameObjects.Components.CloningPod
{
public class CloningPodVisualizer : AppearanceVisualizer
{
public override void OnChangeData(AppearanceComponent component)
{
base.OnChangeData(component);
var sprite = component.Owner.GetComponent<ISpriteComponent>();
if (!component.TryGetData(CloningPodVisuals.Status, out CloningPodStatus status)) return;
sprite.LayerSetState(CloningPodVisualLayers.Machine, StatusToMachineStateId(status));
}
private string StatusToMachineStateId(CloningPodStatus status)
{
//TODO: implement NoMind for if the mind is not yet in the body
//TODO: Find a use for GORE POD
switch (status)
{
case Cloning: return "pod_1";
case NoMind: return "pod_e";
case Gore: return "pod_g";
case Idle: return "pod_0";
default:
throw new ArgumentOutOfRangeException(nameof(status), status, "unknown CloningPodStatus");
}
}
public enum CloningPodVisualLayers
{
Machine,
}
}
}

View File

@@ -0,0 +1,442 @@
#nullable enable
using System;
using System.Collections.Generic;
using System.Diagnostics;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls;
using Robust.Shared.Localization;
using Robust.Shared.Maths;
using Robust.Shared.Timing;
using Robust.Shared.Utility;
using Robust.Shared.Localization;
using static Content.Shared.GameObjects.Components.Medical.SharedCloningPodComponent;
namespace Content.Client.GameObjects.Components.CloningPod
{
public sealed class CloningPodWindow : SS14Window
{
private Dictionary<int, string> _scanManager;
private readonly VBoxContainer _mainVBox;
private readonly ScanListContainer _scanList;
private readonly LineEdit _searchBar;
private readonly Button _clearButton;
public readonly Button CloneButton;
public readonly Button EjectButton;
private readonly CloningScanButton _measureButton;
private CloningScanButton? _selectedButton;
private Label _progressLabel;
private readonly ProgressBar _cloningProgressBar;
private Label _mindState;
protected override Vector2 ContentsMinimumSize => _mainVBox?.CombinedMinimumSize ?? Vector2.Zero;
private CloningPodBoundUserInterfaceState _lastUpdate = null!;
// List of scans that are visible based on current filter criteria.
private readonly Dictionary<int, string> _filteredScans = new Dictionary<int, string>();
// The indices of the visible scans last time UpdateVisibleScans was ran.
// This is inclusive, so end is the index of the last scan, not right after it.
private (int start, int end) _lastScanIndices;
public int? SelectedScan;
protected override Vector2? CustomSize => (250, 300);
public CloningPodWindow(
Dictionary<int, string> scanManager)
{
_scanManager = scanManager;
Title = Loc.GetString("Cloning Machine");
Contents.AddChild(_mainVBox = new VBoxContainer
{
Children =
{
new HBoxContainer
{
Children =
{
(_searchBar = new LineEdit
{
SizeFlagsHorizontal = SizeFlags.FillExpand,
PlaceHolder = Loc.GetString("Search")
}),
(_clearButton = new Button
{
Disabled = true,
Text = Loc.GetString("Clear"),
})
}
},
new ScrollContainer
{
CustomMinimumSize = new Vector2(200.0f, 0.0f),
SizeFlagsVertical = SizeFlags.FillExpand,
Children =
{
(_scanList = new ScanListContainer())
}
},
new VBoxContainer
{
Children =
{
(CloneButton = new Button
{
Text = Loc.GetString("Clone")
})
}
},
(_measureButton = new CloningScanButton {Visible = false}),
(_cloningProgressBar = new ProgressBar
{
CustomMinimumSize = (200, 20),
SizeFlagsHorizontal = SizeFlags.Fill,
MinValue = 0,
MaxValue = 10,
Page = 0,
Value = 0.5f,
Children =
{
(_progressLabel = new Label())
}
}),
(EjectButton = new Button
{
Text = Loc.GetString("Eject Body")
}),
new HBoxContainer
{
Children =
{
new Label()
{
Text = Loc.GetString("Neural Interface: ")
},
(_mindState = new Label()
{
Text = Loc.GetString("No Activity"),
FontColorOverride = Color.Red
}),
}
}
}
});
_searchBar.OnTextChanged += OnSearchBarTextChanged;
_clearButton.OnPressed += OnClearButtonPressed;
BuildEntityList();
_searchBar.GrabKeyboardFocus();
}
public void Populate(CloningPodBoundUserInterfaceState state)
{
//Ignore useless updates or we can't interact with the UI
//TODO: come up with a better comparision, probably write a comparator because '.Equals' doesn't work
if (_lastUpdate == null || _lastUpdate.MindIdName.Count != state.MindIdName.Count)
{
_scanManager = state.MindIdName;
BuildEntityList();
_lastUpdate = state;
}
var percentage = state.Progress / _cloningProgressBar.MaxValue * 100;
_progressLabel.Text = $"{percentage:0}%";
_cloningProgressBar.Value = state.Progress;
_mindState.Text = Loc.GetString(state.MindPresent ? "Consciousness Detected" : "No Activity");
_mindState.FontColorOverride = state.MindPresent ? Color.Green : Color.Red;
}
private void OnSearchBarTextChanged(LineEdit.LineEditEventArgs args)
{
BuildEntityList(args.Text);
_clearButton.Disabled = string.IsNullOrEmpty(args.Text);
}
private void OnClearButtonPressed(BaseButton.ButtonEventArgs args)
{
_searchBar.Clear();
BuildEntityList("");
}
private void BuildEntityList(string? searchStr = null)
{
_filteredScans.Clear();
_scanList.RemoveAllChildren();
// Reset last scan indices so it automatically updates the entire list.
_lastScanIndices = (0, -1);
_scanList.RemoveAllChildren();
_selectedButton = null;
searchStr = searchStr?.ToLowerInvariant();
foreach (var scan in _scanManager)
{
if (searchStr != null && !_doesScanMatchSearch(scan.Value, searchStr))
{
continue;
}
_filteredScans.Add(scan.Key, scan.Value);
}
//TODO: set up sort
//_filteredScans.Sort((a, b) => string.Compare(a.ToString(), b.ToString(), StringComparison.Ordinal));
_scanList.TotalItemCount = _filteredScans.Count;
}
private void UpdateVisibleScans()
{
// Update visible buttons in the scan list.
// Calculate index of first scan to render based on current scroll.
var height = _measureButton.CombinedMinimumSize.Y + ScanListContainer.Separation;
var offset = -_scanList.Position.Y;
var startIndex = (int) Math.Floor(offset / height);
_scanList.ItemOffset = startIndex;
var (prevStart, prevEnd) = _lastScanIndices;
// Calculate index of final one.
var endIndex = startIndex - 1;
var spaceUsed = -height; // -height instead of 0 because else it cuts off the last button.
while (spaceUsed < _scanList.Parent!.Height)
{
spaceUsed += height;
endIndex += 1;
}
endIndex = Math.Min(endIndex, _filteredScans.Count - 1);
if (endIndex == prevEnd && startIndex == prevStart)
{
// Nothing changed so bye.
return;
}
_lastScanIndices = (startIndex, endIndex);
// Delete buttons at the start of the list that are no longer visible (scrolling down).
for (var i = prevStart; i < startIndex && i <= prevEnd; i++)
{
var control = (CloningScanButton) _scanList.GetChild(0);
DebugTools.Assert(control.Index == i);
_scanList.RemoveChild(control);
}
// Delete buttons at the end of the list that are no longer visible (scrolling up).
for (var i = prevEnd; i > endIndex && i >= prevStart; i--)
{
var control = (CloningScanButton) _scanList.GetChild(_scanList.ChildCount - 1);
DebugTools.Assert(control.Index == i);
_scanList.RemoveChild(control);
}
var array = _filteredScans.ToArray();
// Create buttons at the start of the list that are now visible (scrolling up).
for (var i = Math.Min(prevStart - 1, endIndex); i >= startIndex; i--)
{
InsertEntityButton(array[i], true, i);
}
// Create buttons at the end of the list that are now visible (scrolling down).
for (var i = Math.Max(prevEnd + 1, startIndex); i <= endIndex; i++)
{
InsertEntityButton(array[i], false, i);
}
}
// Create a spawn button and insert it into the start or end of the list.
private void InsertEntityButton(KeyValuePair<int, string> scan, bool insertFirst, int index)
{
var button = new CloningScanButton
{
Scan = scan.Value,
Id = scan.Key,
Index = index // We track this index purely for debugging.
};
button.ActualButton.OnToggled += OnItemButtonToggled;
var entityLabelText = scan.Value;
button.EntityLabel.Text = entityLabelText;
if (scan.Key == SelectedScan)
{
_selectedButton = button;
_selectedButton.ActualButton.Pressed = true;
}
//TODO: replace with body's face
/*var tex = IconComponent.GetScanIcon(scan, resourceCache);
var rect = button.EntityTextureRect;
if (tex != null)
{
rect.Texture = tex.Default;
}
else
{
rect.Dispose();
}
rect.Dispose();
*/
_scanList.AddChild(button);
if (insertFirst)
{
button.SetPositionInParent(0);
}
}
private static bool _doesScanMatchSearch(string scan, string searchStr)
{
return scan.ToLowerInvariant().Contains(searchStr);
}
private void OnItemButtonToggled(BaseButton.ButtonToggledEventArgs args)
{
var item = (CloningScanButton) args.Button.Parent!;
if (_selectedButton == item)
{
_selectedButton = null;
SelectedScan = null;
return;
}
else if (_selectedButton != null)
{
_selectedButton.ActualButton.Pressed = false;
}
_selectedButton = null;
SelectedScan = null;
_selectedButton = item;
SelectedScan = item.Id;
}
protected override void FrameUpdate(FrameEventArgs args)
{
base.FrameUpdate(args);
UpdateVisibleScans();
}
private class ScanListContainer : Container
{
// Quick and dirty container to do virtualization of the list.
// Basically, get total item count and offset to put the current buttons at.
// Get a constant minimum height and move the buttons in the list up to match the scrollbar.
private int _totalItemCount;
private int _itemOffset;
public int TotalItemCount
{
get => _totalItemCount;
set
{
_totalItemCount = value;
MinimumSizeChanged();
}
}
public int ItemOffset
{
get => _itemOffset;
set
{
_itemOffset = value;
UpdateLayout();
}
}
public const float Separation = 2;
protected override Vector2 CalculateMinimumSize()
{
if (ChildCount == 0)
{
return Vector2.Zero;
}
var first = GetChild(0);
var (minX, minY) = first.CombinedMinimumSize;
return (minX, minY * TotalItemCount + (TotalItemCount - 1) * Separation);
}
protected override void LayoutUpdateOverride()
{
if (ChildCount == 0)
{
return;
}
var first = GetChild(0);
var height = first.CombinedMinimumSize.Y;
var offset = ItemOffset * height + (ItemOffset - 1) * Separation;
foreach (var child in Children)
{
FitChildInBox(child, UIBox2.FromDimensions(0, offset, Width, height));
offset += Separation + height;
}
}
}
[DebuggerDisplay("cloningbutton {" + nameof(Index) + "}")]
private class CloningScanButton : Control
{
public string Scan { get; set; } = default!;
public int Id { get; set; }
public Button ActualButton { get; private set; }
public Label EntityLabel { get; private set; }
public TextureRect EntityTextureRect { get; private set; }
public int Index { get; set; }
public CloningScanButton()
{
AddChild(ActualButton = new Button
{
SizeFlagsHorizontal = SizeFlags.FillExpand,
SizeFlagsVertical = SizeFlags.FillExpand,
ToggleMode = true,
});
AddChild(new HBoxContainer
{
Children =
{
(EntityTextureRect = new TextureRect
{
CustomMinimumSize = (32, 32),
SizeFlagsHorizontal = SizeFlags.ShrinkCenter,
SizeFlagsVertical = SizeFlags.ShrinkCenter,
Stretch = TextureRect.StretchMode.KeepAspectCentered,
CanShrink = true
}),
(EntityLabel = new Label
{
SizeFlagsVertical = SizeFlags.ShrinkCenter,
SizeFlagsHorizontal = SizeFlags.FillExpand,
Text = "",
ClipText = true
})
}
});
}
}
}
}

View File

@@ -0,0 +1,41 @@
using Content.Shared.GameObjects.Components;
using Robust.Client.GameObjects;
using Robust.Client.Interfaces.GameObjects.Components;
namespace Content.Client.GameObjects.Components
{
public class ExtinguisherCabinetVisualizer : AppearanceVisualizer
{
private string _prefix;
public override void OnChangeData(AppearanceComponent component)
{
base.OnChangeData(component);
var sprite = component.Owner.GetComponent<ISpriteComponent>();
if (component.TryGetData(ExtinguisherCabinetVisuals.IsOpen, out bool isOpen))
{
if (isOpen)
{
if (component.TryGetData(ExtinguisherCabinetVisuals.ContainsExtinguisher, out bool contains))
{
if (contains)
{
sprite.LayerSetState(0, "extinguisher_full");
}
else
{
sprite.LayerSetState(0, "extinguisher_empty");
}
}
}
else
{
sprite.LayerSetState(0, "extinguisher_closed");
}
}
}
}
}

View File

@@ -0,0 +1,13 @@
using Content.Shared.GameObjects.Components.Medical;
using Robust.Shared.GameObjects;
namespace Content.Client.GameObjects.Components.MedicalScanner
{
[RegisterComponent]
[ComponentReference(typeof(SharedMedicalScannerComponent))]
public class MedicalScannerComponent : SharedMedicalScannerComponent
{
}
}

View File

@@ -12,6 +12,11 @@ namespace Content.Client.GameObjects.Components.MedicalScanner
{
base.OnChangeData(component);
if (component.Owner.Deleted)
{
return;
}
var sprite = component.Owner.GetComponent<ISpriteComponent>();
if (!component.TryGetData(MedicalScannerVisuals.Status, out MedicalScannerStatus status)) return;
sprite.LayerSetState(MedicalScannerVisualLayers.Machine, StatusToMachineStateId(status));

View File

@@ -24,7 +24,7 @@ namespace Content.Client.GameObjects.Components.MedicalScanner
{
(ScanButton = new Button
{
Text = "Scan and Save DNA"
Text = Loc.GetString("Scan and Save DNA")
}),
(_diagnostics = new Label
{

View File

@@ -18,8 +18,7 @@ namespace Content.Client.GameObjects.Components.Observer
private GhostGui _gui;
[ViewVariables(VVAccess.ReadOnly)]
public bool CanReturnToBody { get; private set; } = true;
[ViewVariables(VVAccess.ReadOnly)] public bool CanReturnToBody { get; private set; } = true;
private bool _isAttached;
@@ -51,7 +50,8 @@ namespace Content.Client.GameObjects.Components.Observer
base.Initialize();
if (Owner.TryGetComponent(out SpriteComponent component))
component.Visible = _playerManager.LocalPlayer.ControlledEntity?.HasComponent<GhostComponent>() ?? false;
component.Visible =
_playerManager.LocalPlayer.ControlledEntity?.HasComponent<GhostComponent>() ?? false;
}
public override void HandleMessage(ComponentMessage message, IComponent component)
@@ -98,7 +98,6 @@ namespace Content.Client.GameObjects.Components.Observer
{
_gui?.Update();
}
}
}
}

View File

@@ -9,6 +9,7 @@
"Breakable",
"Pickaxe",
"Interactable",
"CloningPod",
"Destructible",
"Temperature",
"Explosive",
@@ -58,7 +59,6 @@
"AccessReader",
"IdCardConsole",
"Airlock",
"MedicalScanner",
"WirePlacer",
"Drink",
"Food",
@@ -172,6 +172,9 @@
"SignalTransmitter",
"SignalButton",
"SignalLinker",
"ExtinguisherCabinet",
"ExtinguisherCabinetFilled",
"FireExtinguisher",
};
}
}

View File

@@ -57,7 +57,7 @@ namespace Content.Client
}
await using var file =
_resourceManager.UserData.Open(BaseScreenshotPath / $"{filename}.png", FileMode.CreateNew, FileAccess.Read, FileShare.None);
_resourceManager.UserData.Open(BaseScreenshotPath / $"{filename}.png", FileMode.CreateNew, FileAccess.Write, FileShare.None);
await Task.Run(() =>
{

View File

@@ -2,12 +2,14 @@ using Content.Client.GameObjects.Components.Observer;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
namespace Content.Client.UserInterface
{
public class GhostGui : Control
{
public Button ReturnToBody = new Button(){Text = "Return to body"};
public readonly Button ReturnToBody = new Button() {Text = Loc.GetString("Return to body")};
private GhostComponent _owner;
public GhostGui(GhostComponent owner)

View File

@@ -66,7 +66,7 @@ namespace Content.Client.UserInterface.Suspicion
_ => throw new ArgumentException($"Invalid number of allies: {role.Allies.Count}")
};
role.Owner.PopupMessage(role.Owner, message);
role.Owner.PopupMessage(message);
}
private bool TryGetComponent(out SuspicionRoleComponent suspicion)

View File

@@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using NUnit.Framework;
using Robust.Server.Interfaces.Maps;
using Robust.Server.Interfaces.Timing;
using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.GameObjects;
@@ -25,11 +24,13 @@ namespace Content.IntegrationTests.Tests
{
var server = StartServerDummyTicker();
await server.WaitIdleAsync();
var mapMan = server.ResolveDependency<IMapManager>();
var mapManager = server.ResolveDependency<IMapManager>();
var entityMan = server.ResolveDependency<IEntityManager>();
var prototypeMan = server.ResolveDependency<IPrototypeManager>();
var mapLoader = server.ResolveDependency<IMapLoader>();
var pauseMan = server.ResolveDependency<IPauseManager>();
var pauseManager = server.ResolveDependency<IPauseManager>();
var tileDefinitionManager = server.ResolveDependency<ITileDefinitionManager>();
var prototypes = new List<EntityPrototype>();
IMapGrid grid = default;
IEntity testEntity;
@@ -37,9 +38,25 @@ namespace Content.IntegrationTests.Tests
//Build up test environment
server.Post(() =>
{
var mapId = mapMan.CreateMap();
pauseMan.AddUninitializedMap(mapId);
grid = mapLoader.LoadBlueprint(mapId, "Maps/stationstation.yml");
// Create a one tile grid to stave off the grid 0 monsters
var mapId = mapManager.CreateMap();
pauseManager.AddUninitializedMap(mapId);
var gridId = new GridId(1);
if (!mapManager.TryGetGrid(gridId, out grid))
{
grid = mapManager.CreateGrid(mapId, gridId);
}
var tileDefinition = tileDefinitionManager["underplating"];
var tile = new Tile(tileDefinition.TileId);
var coordinates = new GridCoordinates(0, 0, gridId);
grid.SetTile(coordinates, tile);
pauseManager.DoMapInitialize(mapId);
});
server.Assert(() =>

View File

@@ -0,0 +1,102 @@
using System.Threading.Tasks;
using Content.Server.GameObjects.Components.Fluids;
using Content.Shared.Chemistry;
using NUnit.Framework;
using Robust.Server.Interfaces.Timing;
using Robust.Shared.Interfaces.Map;
using Robust.Shared.Map;
namespace Content.IntegrationTests.Tests.Fluids
{
[TestFixture]
[TestOf(typeof(PuddleComponent))]
public class PuddleTest : ContentIntegrationTest
{
[Test]
public async Task TilePuddleTest()
{
var server = StartServerDummyTicker();
await server.WaitIdleAsync();
var mapManager = server.ResolveDependency<IMapManager>();
var pauseManager = server.ResolveDependency<IPauseManager>();
var tileDefinitionManager = server.ResolveDependency<ITileDefinitionManager>();
GridCoordinates coordinates = default;
// Build up test environment
server.Post(() =>
{
// Create a one tile grid to spill onto
var mapId = mapManager.CreateMap();
pauseManager.AddUninitializedMap(mapId);
var gridId = new GridId(1);
if (!mapManager.TryGetGrid(gridId, out var grid))
{
grid = mapManager.CreateGrid(mapId, gridId);
}
var tileDefinition = tileDefinitionManager["underplating"];
var tile = new Tile(tileDefinition.TileId);
coordinates = new GridCoordinates(0, 0, gridId);
grid.SetTile(coordinates, tile);
pauseManager.DoMapInitialize(mapId);
});
await server.WaitIdleAsync();
server.Assert(() =>
{
var solution = new Solution("water", ReagentUnit.New(20));
var puddle = solution.SpillAt(coordinates, "PuddleSmear");
Assert.NotNull(puddle);
});
await server.WaitIdleAsync();
}
[Test]
public async Task SpaceNoPuddleTest()
{
var server = StartServerDummyTicker();
await server.WaitIdleAsync();
var mapManager = server.ResolveDependency<IMapManager>();
var pauseManager = server.ResolveDependency<IPauseManager>();
// Build up test environment
server.Post(() =>
{
var mapId = mapManager.CreateMap();
pauseManager.AddUninitializedMap(mapId);
var gridId = new GridId(1);
if (!mapManager.GridExists(gridId))
{
mapManager.CreateGrid(mapId, gridId);
}
});
await server.WaitIdleAsync();
server.Assert(() =>
{
var gridId = new GridId(1);
var coordinates = new GridCoordinates(0, 0, gridId);
var solution = new Solution("water", ReagentUnit.New(20));
var puddle = solution.SpillAt(coordinates, "PuddleSmear");
Assert.Null(puddle);
});
await server.WaitIdleAsync();
}
}
}

View File

@@ -0,0 +1,60 @@
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using NUnit.Framework;
using Robust.Shared.Interfaces.Resources;
using Robust.Shared.Utility;
using YamlDotNet.RepresentationModel;
namespace Content.IntegrationTests.Tests
{
[TestFixture]
public class PostMapInitTest : ContentIntegrationTest
{
public readonly string[] SkippedMaps =
{
"/Maps/Pathfinding/simple.yml"
};
[Test]
public async Task NoSavedPostMapInitTest()
{
var server = StartServerDummyTicker();
await server.WaitIdleAsync();
var resourceManager = server.ResolveDependency<IResourceManager>();
var mapFolder = new ResourcePath("/Maps");
var maps = resourceManager
.ContentFindFiles(mapFolder)
.Where(filePath => filePath.Extension == "yml" && !filePath.Filename.StartsWith("."))
.ToArray();
foreach (var map in maps)
{
var rootedPath = map.ToRootedPath();
if (SkippedMaps.Contains(rootedPath.ToString()))
{
continue;
}
if (!resourceManager.TryContentFileRead(rootedPath, out var fileStream))
{
Assert.Fail($"Map not found: {rootedPath}");
}
using var reader = new StreamReader(fileStream);
var yamlStream = new YamlStream();
yamlStream.Load(reader);
var root = yamlStream.Documents[0].RootNode;
var meta = root["meta"];
var postMapInit = meta["postmapinit"].AsBool();
Assert.False(postMapInit);
}
}
}
}

View File

@@ -0,0 +1,39 @@
#nullable enable
using Robust.Server.Interfaces.Console;
using Robust.Server.Interfaces.Player;
using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.IoC;
namespace Content.Server.Administration
{
public class DeleteEntitiesWithId : IClientCommand
{
public string Command => "deleteewi";
public string Description => "Deletes entities with the specified prototype ID.";
public string Help => $"Usage: {Command} <prototypeID>";
public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args)
{
if (args.Length != 1)
{
shell.SendText(player, Help);
return;
}
var id = args[0].ToLower();
var entityManager = IoCManager.Resolve<IEntityManager>();
var query = new PredicateEntityQuery(e => e.Prototype?.ID.ToLower() == id);
var entities = entityManager.GetEntities(query);
var i = 0;
foreach (var entity in entities)
{
entity.Delete();
i++;
}
shell.SendText(player, $"Deleted all entities with id {id}. Occurrences: {i}");
}
}
}

View File

@@ -1,7 +1,7 @@
using Content.Server.GameObjects.Components.Chemistry;
using Content.Server.Interfaces;
using Content.Shared.Chemistry;
using Content.Shared.GameObjects.Components;
using Content.Shared.Interfaces;
using Content.Shared.Interfaces.GameObjects.Components;
using Robust.Server.GameObjects;
using Robust.Server.GameObjects.EntitySystems;
@@ -13,13 +13,11 @@ using Robust.Shared.Localization;
using Robust.Shared.Maths;
using Robust.Shared.Serialization;
namespace Content.Server.Atmos
{
[RegisterComponent]
public class GasSprayerComponent : Component, IAfterInteract
{
[Dependency] private readonly IServerNotifyManager _notifyManager = default!;
[Dependency] private readonly IServerEntityManager _serverEntityManager = default!;
//TODO: create a function that can create a gas based on a solution mix
@@ -48,7 +46,7 @@ namespace Content.Server.Atmos
if (tank.Solution.GetReagentQuantity(_fuelType) == 0)
{
_notifyManager.PopupMessage(Owner, eventArgs.User,
Owner.PopupMessage(eventArgs.User,
Loc.GetString("{0:theName} is out of {1}!", Owner, _fuelName));
}
else

View File

@@ -36,7 +36,7 @@ namespace Content.Server.Body
{
private IBodyManagerComponent? _body;
private readonly HashSet<Mechanism> _mechanisms = new HashSet<Mechanism>();
private readonly HashSet<IMechanism> _mechanisms = new HashSet<IMechanism>();
public BodyPart(BodyPartPrototype data)
{
@@ -146,11 +146,11 @@ namespace Content.Server.Body
public BodyPartCompatibility Compatibility { get; private set; }
/// <summary>
/// Set of all <see cref="Mechanism"/> currently inside this
/// Set of all <see cref="IMechanism"/> currently inside this
/// <see cref="IBodyPart"/>.
/// </summary>
[ViewVariables]
public IReadOnlyCollection<Mechanism> Mechanisms => _mechanisms;
public IReadOnlyCollection<IMechanism> Mechanisms => _mechanisms;
/// <summary>
/// This method is called by
@@ -258,7 +258,7 @@ namespace Content.Server.Body
return SurgeryData.CanAttachBodyPart(part);
}
public bool CanInstallMechanism(Mechanism mechanism)
public bool CanInstallMechanism(IMechanism mechanism)
{
return SizeUsed + mechanism.Size <= Size &&
SurgeryData.CanInstallMechanism(mechanism);
@@ -275,7 +275,7 @@ namespace Content.Server.Body
/// True if successful, false if there was an error
/// (e.g. not enough room in <see cref="IBodyPart"/>).
/// </returns>
private bool TryInstallMechanism(Mechanism mechanism)
private bool TryInstallMechanism(IMechanism mechanism)
{
if (!CanInstallMechanism(mechanism))
{
@@ -308,7 +308,7 @@ namespace Content.Server.Body
return true;
}
public bool TryDropMechanism(IEntity dropLocation, Mechanism mechanismTarget,
public bool TryDropMechanism(IEntity dropLocation, IMechanism mechanismTarget,
[NotNullWhen(true)] out DroppedMechanismComponent dropped)
{
dropped = null!;
@@ -331,16 +331,16 @@ namespace Content.Server.Body
}
/// <summary>
/// Tries to destroy the given <see cref="Mechanism"/> in this
/// Tries to destroy the given <see cref="IMechanism"/> in this
/// <see cref="IBodyPart"/>. Does NOT spawn a dropped entity.
/// </summary>
/// <summary>
/// Tries to destroy the given <see cref="Mechanism"/> in this
/// Tries to destroy the given <see cref="IMechanism"/> in this
/// <see cref="IBodyPart"/>.
/// </summary>
/// <param name="mechanismTarget">The mechanism to destroy.</param>
/// <returns>True if successful, false otherwise.</returns>
public bool DestroyMechanism(Mechanism mechanismTarget)
public bool DestroyMechanism(IMechanism mechanismTarget)
{
if (!RemoveMechanism(mechanismTarget))
{
@@ -365,7 +365,7 @@ namespace Content.Server.Body
return SurgeryData.PerformSurgery(toolType, target, surgeon, performer);
}
private void AddMechanism(Mechanism mechanism)
private void AddMechanism(IMechanism mechanism)
{
DebugTools.AssertNotNull(mechanism);
@@ -402,7 +402,7 @@ namespace Content.Server.Body
/// </summary>
/// <param name="mechanism">The mechanism to remove.</param>
/// <returns>True if it was removed, false otherwise.</returns>
private bool RemoveMechanism(Mechanism mechanism)
private bool RemoveMechanism(IMechanism mechanism)
{
DebugTools.AssertNotNull(mechanism);

View File

@@ -54,12 +54,12 @@ namespace Content.Server.Body
int CurrentDurability { get; }
/// <summary>
/// Collection of all <see cref="Mechanism"/>s currently inside this
/// Collection of all <see cref="IMechanism"/>s currently inside this
/// <see cref="IBodyPart"/>.
/// To add and remove from this list see <see cref="AddMechanism"/> and
/// <see cref="RemoveMechanism"/>
/// </summary>
IReadOnlyCollection<Mechanism> Mechanisms { get; }
IReadOnlyCollection<IMechanism> Mechanisms { get; }
/// <summary>
/// Path to the RSI that represents this <see cref="IBodyPart"/>.
@@ -109,23 +109,23 @@ namespace Content.Server.Body
bool CanAttachPart(IBodyPart part);
/// <summary>
/// Checks if a <see cref="Mechanism"/> can be installed on this
/// Checks if a <see cref="IMechanism"/> can be installed on this
/// <see cref="IBodyPart"/>.
/// </summary>
/// <returns>True if it can be installed, false otherwise.</returns>
bool CanInstallMechanism(Mechanism mechanism);
bool CanInstallMechanism(IMechanism mechanism);
/// <summary>
/// Tries to remove the given <see cref="Mechanism"/> reference from
/// Tries to remove the given <see cref="IMechanism"/> reference from
/// this <see cref="IBodyPart"/>.
/// </summary>
/// <returns>
/// The newly spawned <see cref="DroppedMechanismComponent"/>, or null
/// if there was an error in spawning the entity or removing the mechanism.
/// </returns>
bool TryDropMechanism(IEntity dropLocation, Mechanism mechanismTarget,
bool TryDropMechanism(IEntity dropLocation, IMechanism mechanismTarget,
[NotNullWhen(true)] out DroppedMechanismComponent dropped);
bool DestroyMechanism(Mechanism mechanism);
bool DestroyMechanism(IMechanism mechanism);
}
}

View File

@@ -0,0 +1,103 @@
#nullable enable
using System.Collections.Generic;
using Content.Server.Body.Mechanisms.Behaviors;
using Content.Server.GameObjects.Components.Body;
using Content.Shared.GameObjects.Components.Body;
namespace Content.Server.Body.Mechanisms
{
public interface IMechanism
{
string Id { get; }
string Name { get; set; }
/// <summary>
/// Professional description of the <see cref="IMechanism"/>.
/// </summary>
string Description { get; set; }
/// <summary>
/// The message to display upon examining a mob with this Mechanism installed.
/// If the string is empty (""), no message will be displayed.
/// </summary>
string ExamineMessage { get; set; }
// TODO: Make RSI properties sane
/// <summary>
/// Path to the RSI that represents this <see cref="IMechanism"/>.
/// </summary>
string RSIPath { get; set; }
/// <summary>
/// RSI state that represents this <see cref="IMechanism"/>.
/// </summary>
string RSIState { get; set; }
/// <summary>
/// Max HP of this <see cref="IMechanism"/>.
/// </summary>
int MaxDurability { get; set; }
/// <summary>
/// Current HP of this <see cref="IMechanism"/>.
/// </summary>
int CurrentDurability { get; set; }
/// <summary>
/// At what HP this <see cref="IMechanism"/> is completely destroyed.
/// </summary>
int DestroyThreshold { get; set; }
/// <summary>
/// Armor of this <see cref="IMechanism"/> against attacks.
/// </summary>
int Resistance { get; set; }
/// <summary>
/// Determines a handful of things - mostly whether this
/// <see cref="IMechanism"/> can fit into a <see cref="IBodyPart"/>.
/// </summary>
// TODO: OnSizeChanged
int Size { get; set; }
/// <summary>
/// What kind of <see cref="IBodyPart"/> this <see cref="IMechanism"/> can be
/// easily installed into.
/// </summary>
BodyPartCompatibility Compatibility { get; set; }
IReadOnlyList<MechanismBehavior> Behaviors { get; }
IBodyManagerComponent? Body { get; }
IBodyPart? Part { get; set; }
void EnsureInitialize();
void InstalledIntoBody();
void RemovedFromBody(IBodyManagerComponent old);
/// <summary>
/// This method is called by <see cref="IBodyPart.PreMetabolism"/> before
/// <see cref="MetabolismComponent.Update"/> is called.
/// </summary>
void PreMetabolism(float frameTime);
/// <summary>
/// This method is called by <see cref="IBodyPart.PostMetabolism"/> after
/// <see cref="MetabolismComponent.Update"/> is called.
/// </summary>
void PostMetabolism(float frameTime);
void AddBehavior(MechanismBehavior behavior);
/// <summary>
/// Removes a behavior from this mechanism.
/// </summary>
/// <param name="behavior">The behavior to remove.</param>
/// <returns>True if it was removed, false otherwise.</returns>
bool RemoveBehavior(MechanismBehavior behavior);
}
}

View File

@@ -16,7 +16,7 @@ namespace Content.Server.Body.Mechanisms
/// This includes livers, eyes, cameras, brains, explosive implants,
/// binary communicators, and other things.
/// </summary>
public class Mechanism
public class Mechanism : IMechanism
{
private IBodyPart? _part;
@@ -29,7 +29,7 @@ namespace Content.Server.Body.Mechanisms
ExamineMessage = null!;
RSIPath = null!;
RSIState = null!;
Behaviors = new List<MechanismBehavior>();
_behaviors = new List<MechanismBehavior>();
}
[ViewVariables] private bool Initialized { get; set; }
@@ -40,74 +40,29 @@ namespace Content.Server.Body.Mechanisms
[ViewVariables] public string Name { get; set; }
/// <summary>
/// Professional description of the <see cref="Mechanism"/>.
/// </summary>
[ViewVariables]
public string Description { get; set; }
[ViewVariables] public string Description { get; set; }
/// <summary>
/// The message to display upon examining a mob with this Mechanism installed.
/// If the string is empty (""), no message will be displayed.
/// </summary>
[ViewVariables]
public string ExamineMessage { get; set; }
[ViewVariables] public string ExamineMessage { get; set; }
/// <summary>
/// Path to the RSI that represents this <see cref="Mechanism"/>.
/// </summary>
[ViewVariables]
public string RSIPath { get; set; }
[ViewVariables] public string RSIPath { get; set; }
/// <summary>
/// RSI state that represents this <see cref="Mechanism"/>.
/// </summary>
[ViewVariables]
public string RSIState { get; set; }
[ViewVariables] public string RSIState { get; set; }
/// <summary>
/// Max HP of this <see cref="Mechanism"/>.
/// </summary>
[ViewVariables]
public int MaxDurability { get; set; }
[ViewVariables] public int MaxDurability { get; set; }
/// <summary>
/// Current HP of this <see cref="Mechanism"/>.
/// </summary>
[ViewVariables]
public int CurrentDurability { get; set; }
[ViewVariables] public int CurrentDurability { get; set; }
/// <summary>
/// At what HP this <see cref="Mechanism"/> is completely destroyed.
/// </summary>
[ViewVariables]
public int DestroyThreshold { get; set; }
[ViewVariables] public int DestroyThreshold { get; set; }
/// <summary>
/// Armor of this <see cref="Mechanism"/> against attacks.
/// </summary>
[ViewVariables]
public int Resistance { get; set; }
[ViewVariables] public int Resistance { get; set; }
/// <summary>
/// Determines a handful of things - mostly whether this
/// <see cref="Mechanism"/> can fit into a <see cref="IBodyPart"/>.
/// </summary>
[ViewVariables]
public int Size { get; set; }
[ViewVariables] public int Size { get; set; }
/// <summary>
/// What kind of <see cref="IBodyPart"/> this <see cref="Mechanism"/> can be
/// easily installed into.
/// </summary>
[ViewVariables]
public BodyPartCompatibility Compatibility { get; set; }
[ViewVariables] public BodyPartCompatibility Compatibility { get; set; }
/// <summary>
/// The behaviors that this <see cref="Mechanism"/> performs.
/// </summary>
[ViewVariables]
private List<MechanismBehavior> Behaviors { get; }
private readonly List<MechanismBehavior> _behaviors;
[ViewVariables] public IReadOnlyList<MechanismBehavior> Behaviors => _behaviors;
public IBodyManagerComponent? Body => Part?.Body;
@@ -167,7 +122,7 @@ namespace Content.Server.Body.Mechanisms
Size = data.Size;
Compatibility = data.Compatibility;
foreach (var behavior in Behaviors.ToArray())
foreach (var behavior in _behaviors.ToArray())
{
RemoveBehavior(behavior);
}
@@ -210,10 +165,6 @@ namespace Content.Server.Body.Mechanisms
}
}
/// <summary>
/// This method is called by <see cref="IBodyPart.PreMetabolism"/> before
/// <see cref="MetabolismComponent.Update"/> is called.
/// </summary>
public void PreMetabolism(float frameTime)
{
foreach (var behavior in Behaviors)
@@ -222,10 +173,6 @@ namespace Content.Server.Body.Mechanisms
}
}
/// <summary>
/// This method is called by <see cref="IBodyPart.PostMetabolism"/> after
/// <see cref="MetabolismComponent.Update"/> is called.
/// </summary>
public void PostMetabolism(float frameTime)
{
foreach (var behavior in Behaviors)
@@ -234,16 +181,21 @@ namespace Content.Server.Body.Mechanisms
}
}
private void AddBehavior(MechanismBehavior behavior)
public void AddBehavior(MechanismBehavior behavior)
{
Behaviors.Add(behavior);
_behaviors.Add(behavior);
behavior.Initialize(this);
}
private bool RemoveBehavior(MechanismBehavior behavior)
public bool RemoveBehavior(MechanismBehavior behavior)
{
behavior.Remove();
return Behaviors.Remove(behavior);
if (_behaviors.Remove(behavior))
{
behavior.Remove();
return true;
}
return false;
}
}
}

View File

@@ -17,7 +17,7 @@ namespace Content.Server.Body.Surgery
[UsedImplicitly]
public class BiologicalSurgeryData : SurgeryData
{
private readonly List<Mechanism> _disconnectedOrgans = new List<Mechanism>();
private readonly List<IMechanism> _disconnectedOrgans = new List<IMechanism>();
private bool _skinOpened;
private bool _skinRetracted;
@@ -118,7 +118,7 @@ namespace Content.Server.Body.Surgery
return toReturn;
}
public override bool CanInstallMechanism(Mechanism mechanism)
public override bool CanInstallMechanism(IMechanism mechanism)
{
return _skinOpened && _vesselsClamped && _skinRetracted;
}
@@ -131,7 +131,7 @@ namespace Content.Server.Body.Surgery
private void OpenSkinSurgery(IBodyPartContainer container, ISurgeon surgeon, IEntity performer)
{
performer.PopupMessage(performer, Loc.GetString("Cut open the skin..."));
performer.PopupMessage(Loc.GetString("Cut open the skin..."));
// TODO do_after: Delay
_skinOpened = true;
@@ -139,7 +139,7 @@ namespace Content.Server.Body.Surgery
private void ClampVesselsSurgery(IBodyPartContainer container, ISurgeon surgeon, IEntity performer)
{
performer.PopupMessage(performer, Loc.GetString("Clamp the vessels..."));
performer.PopupMessage(Loc.GetString("Clamp the vessels..."));
// TODO do_after: Delay
_vesselsClamped = true;
@@ -147,7 +147,7 @@ namespace Content.Server.Body.Surgery
private void RetractSkinSurgery(IBodyPartContainer container, ISurgeon surgeon, IEntity performer)
{
performer.PopupMessage(performer, Loc.GetString("Retract the skin..."));
performer.PopupMessage(Loc.GetString("Retract the skin..."));
// TODO do_after: Delay
_skinRetracted = true;
@@ -155,7 +155,7 @@ namespace Content.Server.Body.Surgery
private void CauterizeIncisionSurgery(IBodyPartContainer container, ISurgeon surgeon, IEntity performer)
{
performer.PopupMessage(performer, Loc.GetString("Cauterize the incision..."));
performer.PopupMessage(Loc.GetString("Cauterize the incision..."));
// TODO do_after: Delay
_skinOpened = false;
@@ -170,7 +170,7 @@ namespace Content.Server.Body.Surgery
return;
}
var toSend = new List<Mechanism>();
var toSend = new List<IMechanism>();
foreach (var mechanism in Parent.Mechanisms)
{
if (!_disconnectedOrgans.Contains(mechanism))
@@ -185,7 +185,7 @@ namespace Content.Server.Body.Surgery
}
}
private void LoosenOrganSurgeryCallback(Mechanism target, IBodyPartContainer container, ISurgeon surgeon,
private void LoosenOrganSurgeryCallback(IMechanism target, IBodyPartContainer container, ISurgeon surgeon,
IEntity performer)
{
if (target == null || !Parent.Mechanisms.Contains(target))
@@ -193,7 +193,7 @@ namespace Content.Server.Body.Surgery
return;
}
performer.PopupMessage(performer, Loc.GetString("Loosen the organ..."));
performer.PopupMessage(Loc.GetString("Loosen the organ..."));
// TODO do_after: Delay
_disconnectedOrgans.Add(target);
@@ -216,7 +216,7 @@ namespace Content.Server.Body.Surgery
}
}
private void RemoveOrganSurgeryCallback(Mechanism target, IBodyPartContainer container, ISurgeon surgeon,
private void RemoveOrganSurgeryCallback(IMechanism target, IBodyPartContainer container, ISurgeon surgeon,
IEntity performer)
{
if (target == null || !Parent.Mechanisms.Contains(target))
@@ -224,7 +224,7 @@ namespace Content.Server.Body.Surgery
return;
}
performer.PopupMessage(performer, Loc.GetString("Remove the organ..."));
performer.PopupMessage(Loc.GetString("Remove the organ..."));
// TODO do_after: Delay
Parent.TryDropMechanism(performer, target, out _);
@@ -240,7 +240,7 @@ namespace Content.Server.Body.Surgery
}
var bmTarget = (BodyManagerComponent) container;
performer.PopupMessage(performer, Loc.GetString("Saw off the limb!"));
performer.PopupMessage(Loc.GetString("Saw off the limb!"));
// TODO do_after: Delay
bmTarget.DisconnectBodyPart(Parent, true);

View File

@@ -13,7 +13,7 @@ namespace Content.Server.Body.Surgery
public interface ISurgeon
{
public delegate void MechanismRequestCallback(
Mechanism target,
IMechanism target,
IBodyPartContainer container,
ISurgeon surgeon,
IEntity performer);
@@ -29,6 +29,6 @@ namespace Content.Server.Body.Surgery
/// This function is called in that scenario, and it is expected that you call the callback with one mechanism from the
/// provided list.
/// </summary>
public void RequestMechanism(IEnumerable<Mechanism> options, MechanismRequestCallback callback);
public void RequestMechanism(IEnumerable<IMechanism> options, MechanismRequestCallback callback);
}
}

View File

@@ -38,10 +38,10 @@ namespace Content.Server.Body.Surgery
public abstract string GetDescription(IEntity target);
/// <summary>
/// Returns whether a <see cref="Mechanism"/> can be installed into the
/// Returns whether a <see cref="IMechanism"/> can be installed into the
/// <see cref="IBodyPart"/> this <see cref="SurgeryData"/> represents.
/// </summary>
public abstract bool CanInstallMechanism(Mechanism mechanism);
public abstract bool CanInstallMechanism(IMechanism mechanism);
/// <summary>
/// Returns whether the given <see cref="IBodyPart"/> can be connected to the

View File

@@ -5,7 +5,6 @@ using Content.Server.GameObjects.Components.Items.Storage;
using Content.Server.GameObjects.Components.Observer;
using Content.Server.Interfaces.Chat;
using Content.Server.Interfaces.GameObjects;
using Content.Server.Interfaces;
using Content.Server.Observer;
using Content.Server.Players;
using Content.Server.Utility;
@@ -120,7 +119,6 @@ namespace Content.Server.Chat
internal class SuicideCommand : IClientCommand
{
[Dependency] private readonly IPlayerManager _playerManager = default!;
[Dependency] private readonly IServerNotifyManager _notifyManager = default!;
public string Command => "suicide";

View File

@@ -2,11 +2,11 @@
using System.Collections.Generic;
using System.Linq;
using Content.Server.GameObjects.Components.Items.Storage;
using Content.Server.Interfaces;
using Content.Server.Interfaces.GameObjects.Components.Items;
using Content.Server.Utility;
using Content.Shared.Access;
using Content.Shared.GameObjects.Components.Access;
using Content.Shared.Interfaces;
using Content.Shared.Interfaces.GameObjects.Components;
using Robust.Server.GameObjects.Components.Container;
using Robust.Server.GameObjects.Components.UserInterface;
@@ -25,7 +25,6 @@ namespace Content.Server.GameObjects.Components.Access
[ComponentReference(typeof(IActivate))]
public class IdCardConsoleComponent : SharedIdCardConsoleComponent, IActivate
{
[Dependency] private readonly IServerNotifyManager _notifyManager = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
private ContainerSlot _privilegedIdContainer = default!;
@@ -132,7 +131,7 @@ namespace Content.Server.GameObjects.Components.Access
{
if (!user.TryGetComponent(out IHandsComponent? hands))
{
_notifyManager.PopupMessage(Owner.Transform.GridPosition, user, Loc.GetString("You have no hands."));
Owner.PopupMessage(user, Loc.GetString("You have no hands."));
return;
}
@@ -161,7 +160,7 @@ namespace Content.Server.GameObjects.Components.Access
if (!hands.Drop(hands.ActiveHand, container))
{
_notifyManager.PopupMessage(Owner.Transform.GridPosition, user, Loc.GetString("You can't let go of the ID card!"));
Owner.PopupMessage(user, Loc.GetString("You can't let go of the ID card!"));
return;
}
UpdateUserInterface();

View File

@@ -4,7 +4,6 @@ using Content.Shared.Interfaces;
using Robust.Shared.GameObjects;
using Robust.Shared.GameObjects.Systems;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Content.Server.GameObjects.EntitySystems.DoAfter;
using Robust.Shared.ViewVariables;
@@ -22,7 +21,6 @@ using Robust.Shared.Maths;
using System;
using System.Collections.Generic;
using Content.Shared.Utility;
using Serilog;
using Content.Server.GameObjects.Components.GUI;
namespace Content.Server.GameObjects.Components.ActionBlocking
@@ -30,9 +28,6 @@ namespace Content.Server.GameObjects.Components.ActionBlocking
[RegisterComponent]
public class CuffableComponent : SharedCuffableComponent
{
[Dependency]
private readonly ISharedNotifyManager _notifyManager;
/// <summary>
/// How many of this entity's hands are currently cuffed.
/// </summary>
@@ -231,13 +226,13 @@ namespace Content.Server.GameObjects.Components.ActionBlocking
if (!isOwner && !ActionBlockerSystem.CanInteract(user))
{
user.PopupMessage(user, Loc.GetString("You can't do that!"));
user.PopupMessage(Loc.GetString("You can't do that!"));
return;
}
if (!isOwner && user.InRangeUnobstructed(Owner, _interactRange))
{
user.PopupMessage(user, Loc.GetString("You are too far away to remove the cuffs."));
user.PopupMessage(Loc.GetString("You are too far away to remove the cuffs."));
return;
}
@@ -247,7 +242,7 @@ namespace Content.Server.GameObjects.Components.ActionBlocking
return;
}
user.PopupMessage(user, Loc.GetString("You start removing the cuffs."));
user.PopupMessage(Loc.GetString("You start removing the cuffs."));
var audio = EntitySystem.Get<AudioSystem>();
audio.PlayFromEntity(isOwner ? cuff.StartBreakoutSound : cuff.StartUncuffSound, Owner);
@@ -292,29 +287,29 @@ namespace Content.Server.GameObjects.Components.ActionBlocking
if (CuffedHandCount == 0)
{
_notifyManager.PopupMessage(user, user, Loc.GetString("You successfully remove the cuffs."));
user.PopupMessage(Loc.GetString("You successfully remove the cuffs."));
if (!isOwner)
{
_notifyManager.PopupMessage(user, Owner, Loc.GetString("{0:theName} uncuffs your hands.", user));
user.PopupMessage(Owner, Loc.GetString("{0:theName} uncuffs your hands.", user));
}
}
else
{
if (!isOwner)
{
_notifyManager.PopupMessage(user, user, Loc.GetString("You successfully remove the cuffs. {0} of {1:theName}'s hands remain cuffed.", CuffedHandCount, user));
_notifyManager.PopupMessage(user, Owner, Loc.GetString("{0:theName} removes your cuffs. {1} of your hands remain cuffed.", user, CuffedHandCount));
user.PopupMessage(Loc.GetString("You successfully remove the cuffs. {0} of {1:theName}'s hands remain cuffed.", CuffedHandCount, user));
user.PopupMessage(Owner, Loc.GetString("{0:theName} removes your cuffs. {1} of your hands remain cuffed.", user, CuffedHandCount));
}
else
{
_notifyManager.PopupMessage(user, user, Loc.GetString("You successfully remove the cuffs. {0} of your hands remain cuffed.", CuffedHandCount));
user.PopupMessage(Loc.GetString("You successfully remove the cuffs. {0} of your hands remain cuffed.", CuffedHandCount));
}
}
}
else
{
_notifyManager.PopupMessage(user, user, Loc.GetString("You fail to remove the cuffs."));
user.PopupMessage(Loc.GetString("You fail to remove the cuffs."));
}
return;

View File

@@ -23,9 +23,6 @@ namespace Content.Server.GameObjects.Components.ActionBlocking
[RegisterComponent]
public class HandcuffComponent : SharedHandcuffComponent, IAfterInteract
{
[Dependency]
private readonly ISharedNotifyManager _notifyManager;
/// <summary>
/// The time it takes to apply a <see cref="CuffedComponent"/> to an entity.
/// </summary>
@@ -161,36 +158,36 @@ namespace Content.Server.GameObjects.Components.ActionBlocking
if (eventArgs.Target == eventArgs.User)
{
_notifyManager.PopupMessage(eventArgs.User, eventArgs.User, Loc.GetString("You can't cuff yourself!"));
eventArgs.User.PopupMessage(Loc.GetString("You can't cuff yourself!"));
return;
}
if (Broken)
{
_notifyManager.PopupMessage(eventArgs.User, eventArgs.User, Loc.GetString("The cuffs are broken!"));
eventArgs.User.PopupMessage(Loc.GetString("The cuffs are broken!"));
return;
}
if (!eventArgs.Target.TryGetComponent<HandsComponent>(out var hands))
{
_notifyManager.PopupMessage(eventArgs.User, eventArgs.User, Loc.GetString("{0:theName} has no hands!", eventArgs.Target));
eventArgs.User.PopupMessage(Loc.GetString("{0:theName} has no hands!", eventArgs.Target));
return;
}
if (cuffed.CuffedHandCount == hands.Count)
{
_notifyManager.PopupMessage(eventArgs.User, eventArgs.User, Loc.GetString("{0:theName} has no free hands to handcuff!", eventArgs.Target));
eventArgs.User.PopupMessage(Loc.GetString("{0:theName} has no free hands to handcuff!", eventArgs.Target));
return;
}
if (!eventArgs.InRangeUnobstructed(_interactRange, ignoreInsideBlocker: true))
{
_notifyManager.PopupMessage(eventArgs.User, eventArgs.User, Loc.GetString("You are too far away to use the cuffs!"));
eventArgs.User.PopupMessage(Loc.GetString("You are too far away to use the cuffs!"));
return;
}
_notifyManager.PopupMessage(eventArgs.User, eventArgs.User, Loc.GetString("You start cuffing {0:theName}.", eventArgs.Target));
_notifyManager.PopupMessage(eventArgs.User, eventArgs.Target, Loc.GetString("{0:theName} starts cuffing you!", eventArgs.User));
eventArgs.User.PopupMessage(Loc.GetString("You start cuffing {0:theName}.", eventArgs.Target));
eventArgs.User.PopupMessage(eventArgs.Target, Loc.GetString("{0:theName} starts cuffing you!", eventArgs.User));
_audioSystem.PlayFromEntity(StartCuffSound, Owner);
TryUpdateCuff(eventArgs.User, eventArgs.Target, cuffed);
@@ -222,8 +219,8 @@ namespace Content.Server.GameObjects.Components.ActionBlocking
if (result != DoAfterStatus.Cancelled)
{
_audioSystem.PlayFromEntity(EndCuffSound, Owner);
_notifyManager.PopupMessage(user, user, Loc.GetString("You successfully cuff {0:theName}.", target));
_notifyManager.PopupMessage(target, target, Loc.GetString("You have been cuffed by {0:theName}!", user));
user.PopupMessage(Loc.GetString("You successfully cuff {0:theName}.", target));
target.PopupMessage(Loc.GetString("You have been cuffed by {0:theName}!", user));
if (user.TryGetComponent<HandsComponent>(out var hands))
{
@@ -237,8 +234,8 @@ namespace Content.Server.GameObjects.Components.ActionBlocking
}
else
{
user.PopupMessage(user, Loc.GetString("You were interrupted while cuffing {0:theName}!", target));
target.PopupMessage(target, Loc.GetString("You interrupt {0:theName} while they are cuffing you!", user));
user.PopupMessage(Loc.GetString("You were interrupted while cuffing {0:theName}!", target));
target.PopupMessage(Loc.GetString("You interrupt {0:theName} while they are cuffing you!", user));
}
}
}

View File

@@ -1,12 +1,12 @@
#nullable enable
using System.Collections.Generic;
using Content.Server.GameObjects.EntitySystems;
using Content.Server.Interfaces;
using Content.Server.Interfaces.GameObjects.Components.Items;
using Content.Server.Utility;
using Content.Shared.Atmos;
using Content.Shared.GameObjects.Components;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.Interfaces;
using Content.Shared.Interfaces.GameObjects.Components;
using Robust.Server.GameObjects.Components.UserInterface;
using Robust.Server.Interfaces.GameObjects;
@@ -24,7 +24,6 @@ namespace Content.Server.GameObjects.Components.Atmos
[RegisterComponent]
public class GasAnalyzerComponent : SharedGasAnalyzerComponent, IAfterInteract, IDropped, IUse
{
[Dependency] private readonly IServerNotifyManager _notifyManager = default!;
[Dependency] private readonly IMapManager _mapManager = default!;
private GasAnalyzerDanger _pressureDanger;
@@ -207,17 +206,14 @@ namespace Content.Server.GameObjects.Components.Atmos
if (!player.TryGetComponent(out IHandsComponent? handsComponent))
{
_notifyManager.PopupMessage(Owner.Transform.GridPosition, player,
Loc.GetString("You have no hands."));
Owner.PopupMessage(player, Loc.GetString("You have no hands."));
return;
}
var activeHandEntity = handsComponent.GetActiveHand?.Owner;
if (activeHandEntity == null || !activeHandEntity.TryGetComponent(out GasAnalyzerComponent? gasAnalyzer))
{
_notifyManager.PopupMessage(serverMsg.Session.AttachedEntity,
serverMsg.Session.AttachedEntity,
Loc.GetString("You need a Gas Analyzer in your hand!"));
serverMsg.Session.AttachedEntity.PopupMessage(Loc.GetString("You need a Gas Analyzer in your hand!"));
return;
}
@@ -231,7 +227,7 @@ namespace Content.Server.GameObjects.Components.Atmos
{
if (!eventArgs.CanReach)
{
_notifyManager.PopupMessage(eventArgs.User, eventArgs.User, Loc.GetString("You can't reach there!"));
eventArgs.User.PopupMessage(Loc.GetString("You can't reach there!"));
return;
}

View File

@@ -32,6 +32,8 @@ namespace Content.Server.GameObjects.Components.Atmos
public class GridAtmosphereComponent : Component, IGridAtmosphereComponent
{
[Robust.Shared.IoC.Dependency] private IMapManager _mapManager = default!;
[Robust.Shared.IoC.Dependency] private ITileDefinitionManager _tileDefinitionManager = default!;
[Robust.Shared.IoC.Dependency] private IServerEntityManager _serverEntityManager = default!;
/// <summary>
/// Check current execution time every n instances processed.
@@ -162,14 +164,13 @@ namespace Content.Server.GameObjects.Components.Atmos
var mapGrid = mapGridComponent.Grid;
var tile = mapGrid.GetTileRef(indices).Tile;
var tileDefinitionManager = IoCManager.Resolve<ITileDefinitionManager>();
var tileDef = (ContentTileDefinition)tileDefinitionManager[tile.TypeId];
var tileDef = (ContentTileDefinition) _tileDefinitionManager[tile.TypeId];
var underplating = tileDefinitionManager["underplating"];
var underplating = _tileDefinitionManager["underplating"];
mapGrid.SetTile(indices, new Tile(underplating.TileId));
//Actually spawn the relevant tile item at the right position and give it some offset to the corner.
var tileItem = IoCManager.Resolve<IServerEntityManager>().SpawnEntity(tileDef.ItemDropPrototypeName, new GridCoordinates(indices.X, indices.Y, mapGrid));
var tileItem = _serverEntityManager.SpawnEntity(tileDef.ItemDropPrototypeName, new GridCoordinates(indices.X, indices.Y, mapGrid));
tileItem.Transform.WorldPosition += (0.2f, 0.2f);
}

View File

@@ -1,18 +1,17 @@
#nullable enable
using System.Collections.Generic;
using System.Linq;
using Content.Shared.Interfaces;
using Content.Shared.Interfaces.GameObjects.Components;
using Content.Server.Body;
using Content.Server.Utility;
using Content.Shared.Body.Surgery;
using Content.Shared.Interfaces;
using Robust.Server.GameObjects;
using Robust.Server.GameObjects.Components.UserInterface;
using Robust.Server.Interfaces.GameObjects;
using Robust.Server.Interfaces.Player;
using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Robust.Shared.ViewVariables;
@@ -24,8 +23,6 @@ namespace Content.Server.GameObjects.Components.Body
[RegisterComponent]
public class DroppedBodyPartComponent : Component, IAfterInteract, IBodyPartContainer
{
[Dependency] private readonly ISharedNotifyManager _sharedNotifyManager = default!;
private readonly Dictionary<int, object> _optionsCache = new Dictionary<int, object>();
private BodyManagerComponent? _bodyManagerComponentCache;
private int _idHash;
@@ -121,7 +118,7 @@ namespace Content.Server.GameObjects.Components.Body
}
else // If surgery cannot be performed, show message saying so.
{
_sharedNotifyManager.PopupMessage(eventArgs.Target, eventArgs.User,
eventArgs.Target.PopupMessage(eventArgs.User,
Loc.GetString("You see no way to install {0:theName}.", Owner));
}
}
@@ -147,7 +144,7 @@ namespace Content.Server.GameObjects.Components.Body
// TODO: sanity checks to see whether user is in range, user is still able-bodied, target is still the same, etc etc
if (!_optionsCache.TryGetValue(key, out var targetObject))
{
_sharedNotifyManager.PopupMessage(_bodyManagerComponentCache.Owner, _performerCache,
_bodyManagerComponentCache.Owner.PopupMessage(_performerCache,
Loc.GetString("You see no useful way to attach {0:theName} anymore.", Owner));
}
@@ -163,10 +160,7 @@ namespace Content.Server.GameObjects.Components.Body
message = Loc.GetString("You can't attach it!");
}
_sharedNotifyManager.PopupMessage(
_bodyManagerComponentCache.Owner,
_performerCache,
message);
_bodyManagerComponentCache.Owner.PopupMessage(_performerCache, message);
}
private void OpenSurgeryUI(IPlayerSession session)

View File

@@ -28,7 +28,6 @@ namespace Content.Server.GameObjects.Components.Body
[RegisterComponent]
public class DroppedMechanismComponent : Component, IAfterInteract
{
[Dependency] private readonly ISharedNotifyManager _sharedNotifyManager = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
public sealed override string Name => "DroppedMechanism";
@@ -41,7 +40,7 @@ namespace Content.Server.GameObjects.Components.Body
private IEntity? _performerCache;
[ViewVariables] public Mechanism ContainedMechanism { get; private set; } = default!;
[ViewVariables] public IMechanism ContainedMechanism { get; private set; } = default!;
[ViewVariables] private BoundUserInterface? UserInterface => Owner.GetUIOrNull(GenericSurgeryUiKey.Key);
@@ -67,8 +66,7 @@ namespace Content.Server.GameObjects.Components.Body
if (!droppedBodyPart.ContainedBodyPart.TryInstallDroppedMechanism(this))
{
_sharedNotifyManager.PopupMessage(eventArgs.Target, eventArgs.User,
Loc.GetString("You can't fit it in!"));
eventArgs.Target.PopupMessage(eventArgs.User, Loc.GetString("You can't fit it in!"));
}
}
}
@@ -83,7 +81,7 @@ namespace Content.Server.GameObjects.Components.Body
}
}
public void InitializeDroppedMechanism(Mechanism data)
public void InitializeDroppedMechanism(IMechanism data)
{
ContainedMechanism = data;
Owner.Name = Loc.GetString(ContainedMechanism.Name);
@@ -141,7 +139,7 @@ namespace Content.Server.GameObjects.Components.Body
}
else // If surgery cannot be performed, show message saying so.
{
_sharedNotifyManager.PopupMessage(eventArgs.Target, eventArgs.User,
eventArgs.Target.PopupMessage(eventArgs.User,
Loc.GetString("You see no way to install the {0}.", Owner.Name));
}
}
@@ -167,7 +165,7 @@ namespace Content.Server.GameObjects.Components.Body
// TODO: sanity checks to see whether user is in range, user is still able-bodied, target is still the same, etc etc
if (!_optionsCache.TryGetValue(key, out var targetObject))
{
_sharedNotifyManager.PopupMessage(_bodyManagerComponentCache.Owner, _performerCache,
_bodyManagerComponentCache.Owner.PopupMessage(_performerCache,
Loc.GetString("You see no useful way to use the {0} anymore.", Owner.Name));
return;
}
@@ -177,10 +175,7 @@ namespace Content.Server.GameObjects.Components.Body
? Loc.GetString("You jam the {0} inside {1:them}.", ContainedMechanism.Name, _performerCache)
: Loc.GetString("You can't fit it in!");
_sharedNotifyManager.PopupMessage(
_bodyManagerComponentCache.Owner,
_performerCache,
message);
_bodyManagerComponentCache.Owner.PopupMessage(_performerCache, message);
// TODO: {1:theName}
}

View File

@@ -16,7 +16,6 @@ using Robust.Server.Interfaces.GameObjects;
using Robust.Server.Interfaces.Player;
using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Robust.Shared.Log;
using Robust.Shared.Serialization;
@@ -34,8 +33,6 @@ namespace Content.Server.GameObjects.Components.Body
[RegisterComponent]
public class SurgeryToolComponent : Component, ISurgeon, IAfterInteract
{
[Dependency] private readonly ISharedNotifyManager _sharedNotifyManager = default!;
public override string Name => "SurgeryTool";
public override uint? NetID => ContentNetIDs.SURGERY;
@@ -131,7 +128,7 @@ namespace Content.Server.GameObjects.Components.Body
public float BaseOperationTime { get => _baseOperateTime; set => _baseOperateTime = value; }
public void RequestMechanism(IEnumerable<Mechanism> options, ISurgeon.MechanismRequestCallback callback)
public void RequestMechanism(IEnumerable<IMechanism> options, ISurgeon.MechanismRequestCallback callback)
{
var toSend = new Dictionary<string, int>();
foreach (var mechanism in options)
@@ -233,7 +230,7 @@ namespace Content.Server.GameObjects.Components.Body
/// <summary>
/// Called after the client chooses from a list of possible
/// <see cref="Mechanism"/> to choose from.
/// <see cref="IMechanism"/> to choose from.
/// </summary>
private void HandleReceiveMechanism(int key)
{
@@ -254,27 +251,13 @@ namespace Content.Server.GameObjects.Components.Body
private void SendNoUsefulWayToUsePopup()
{
if (_bodyManagerComponentCache == null)
{
return;
}
_sharedNotifyManager.PopupMessage(
_bodyManagerComponentCache.Owner,
_performerCache,
_bodyManagerComponentCache?.Owner.PopupMessage(_performerCache,
Loc.GetString("You see no useful way to use {0:theName}.", Owner));
}
private void SendNoUsefulWayToUseAnymorePopup()
{
if (_bodyManagerComponentCache == null)
{
return;
}
_sharedNotifyManager.PopupMessage(
_bodyManagerComponentCache.Owner,
_performerCache,
_bodyManagerComponentCache?.Owner.PopupMessage(_performerCache,
Loc.GetString("You see no useful way to use {0:theName} anymore.", Owner));
}

View File

@@ -6,12 +6,12 @@ using Content.Server.GameObjects.Components.Mobs;
using Content.Server.GameObjects.Components.Mobs.State;
using Content.Server.GameObjects.Components.Strap;
using Content.Server.GameObjects.EntitySystems;
using Content.Server.Interfaces;
using Content.Shared.GameObjects.Components.Buckle;
using Content.Shared.GameObjects.Components.Mobs;
using Content.Shared.GameObjects.Components.Strap;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.Verbs;
using Content.Shared.Interfaces;
using Content.Shared.Interfaces.GameObjects.Components;
using Content.Shared.Utility;
using Robust.Server.GameObjects;
@@ -38,7 +38,6 @@ namespace Content.Server.GameObjects.Components.Buckle
[Dependency] private readonly IEntityManager _entityManager = default!;
[Dependency] private readonly IEntitySystemManager _entitySystem = default!;
[Dependency] private readonly IGameTiming _gameTiming = default!;
[Dependency] private readonly IServerNotifyManager _notifyManager = default!;
[Dependency] private readonly IMapManager _mapManager = default!;
private int _size;
@@ -163,7 +162,7 @@ namespace Content.Server.GameObjects.Components.Buckle
}
}
private bool CanBuckle(IEntity user, IEntity to, [MaybeNullWhen(false)] out StrapComponent strap)
private bool CanBuckle(IEntity? user, IEntity to, [MaybeNullWhen(false)] out StrapComponent strap)
{
strap = null;
@@ -174,18 +173,16 @@ namespace Content.Server.GameObjects.Components.Buckle
if (!ActionBlockerSystem.CanInteract(user))
{
_notifyManager.PopupMessage(user, user,
Loc.GetString("You can't do that!"));
user.PopupMessage(Loc.GetString("You can't do that!"));
return false;
}
if (!to.TryGetComponent(out strap))
{
_notifyManager.PopupMessage(Owner, user,
Loc.GetString(Owner == user
? "You can't buckle yourself there!"
: "You can't buckle {0:them} there!", Owner));
var message = Loc.GetString(Owner == user
? "You can't buckle yourself there!"
: "You can't buckle {0:them} there!", Owner);
Owner.PopupMessage(user, message);
return false;
}
@@ -195,8 +192,7 @@ namespace Content.Server.GameObjects.Components.Buckle
if (!Owner.InRangeUnobstructed(strap, _range, predicate: Ignored, popup: true))
{
_notifyManager.PopupMessage(strap.Owner, user,
Loc.GetString("You can't reach there!"));
strap.Owner.PopupMessage(user, Loc.GetString("You can't reach there!"));
return false;
}
@@ -208,7 +204,7 @@ namespace Content.Server.GameObjects.Components.Buckle
if (!ContainerHelpers.TryGetContainer(strap.Owner, out var strapContainer) ||
ownerContainer != strapContainer)
{
_notifyManager.PopupMessage(strap.Owner, user, Loc.GetString("You can't reach there!"));
strap.Owner.PopupMessage(user, Loc.GetString("You can't reach there!"));
return false;
}
@@ -216,18 +212,16 @@ namespace Content.Server.GameObjects.Components.Buckle
if (!user.HasComponent<HandsComponent>())
{
_notifyManager.PopupMessage(user, user,
Loc.GetString("You don't have hands!"));
user.PopupMessage(Loc.GetString("You don't have hands!"));
return false;
}
if (Buckled)
{
_notifyManager.PopupMessage(Owner, user,
Loc.GetString(Owner == user
? "You are already buckled in!"
: "{0:They} are already buckled in!", Owner));
var message = Loc.GetString(Owner == user
? "You are already buckled in!"
: "{0:They} are already buckled in!", Owner);
Owner.PopupMessage(user, message);
return false;
}
@@ -237,10 +231,10 @@ namespace Content.Server.GameObjects.Components.Buckle
{
if (parent == user.Transform)
{
_notifyManager.PopupMessage(Owner, user,
Loc.GetString(Owner == user
? "You can't buckle yourself there!"
: "You can't buckle {0:them} there!", Owner));
var message = Loc.GetString(Owner == user
? "You can't buckle yourself there!"
: "You can't buckle {0:them} there!", Owner);
Owner.PopupMessage(user, message);
return false;
}
@@ -250,10 +244,10 @@ namespace Content.Server.GameObjects.Components.Buckle
if (!strap.HasSpace(this))
{
_notifyManager.PopupMessage(Owner, user,
Loc.GetString(Owner == user
? "You can't fit there!"
: "{0:They} can't fit there!", Owner));
var message = Loc.GetString(Owner == user
? "You can't fit there!"
: "{0:They} can't fit there!", Owner);
Owner.PopupMessage(user, message);
return false;
}
@@ -284,10 +278,10 @@ namespace Content.Server.GameObjects.Components.Buckle
if (!strap.TryAdd(this))
{
_notifyManager.PopupMessage(Owner, user,
Loc.GetString(Owner == user
? "You can't buckle yourself there!"
: "You can't buckle {0:them} there!", Owner));
var message = Loc.GetString(Owner == user
? "You can't buckle yourself there!"
: "You can't buckle {0:them} there!", Owner);
Owner.PopupMessage(user, message);
return false;
}
@@ -338,8 +332,7 @@ namespace Content.Server.GameObjects.Components.Buckle
if (!ActionBlockerSystem.CanInteract(user))
{
_notifyManager.PopupMessage(user, user,
Loc.GetString("You can't do that!"));
user.PopupMessage(Loc.GetString("You can't do that!"));
return false;
}

View File

@@ -7,13 +7,14 @@ using Content.Server.GameObjects.Components.GUI;
using Content.Server.GameObjects.Components.Items.Storage;
using Content.Server.GameObjects.Components.Power.ApcNetComponents;
using Content.Server.GameObjects.EntitySystems;
using Content.Server.Interfaces;
using Content.Server.Interfaces.GameObjects.Components.Items;
using Content.Server.Utility;
using Content.Shared.Chemistry;
using Content.Shared.GameObjects.Components.Chemistry.ChemMaster;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.Interfaces;
using Content.Shared.Interfaces.GameObjects.Components;
using Content.Shared.Utility;
using Robust.Server.GameObjects.Components.Container;
using Robust.Server.GameObjects.Components.UserInterface;
using Robust.Server.GameObjects.EntitySystems;
@@ -22,11 +23,7 @@ using Robust.Shared.Audio;
using Robust.Shared.GameObjects;
using Robust.Shared.GameObjects.Systems;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.Random;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Robust.Shared.Maths;
using Robust.Shared.Random;
using Robust.Shared.Serialization;
using Robust.Shared.ViewVariables;
@@ -43,8 +40,6 @@ namespace Content.Server.GameObjects.Components.Chemistry
[ComponentReference(typeof(IInteractUsing))]
public class ChemMasterComponent : SharedChemMasterComponent, IActivate, IInteractUsing, ISolutionChange
{
[Dependency] private readonly IServerNotifyManager _notifyManager = default!;
[ViewVariables] private ContainerSlot _beakerContainer = default!;
[ViewVariables] private string _packPrototypeId = "";
@@ -272,8 +267,6 @@ namespace Content.Server.GameObjects.Components.Chemistry
private void TryCreatePackage(IEntity user, UiAction action, int pillAmount, int bottleAmount)
{
var random = IoCManager.Resolve<IRobustRandom>();
if (BufferSolution.CurrentVolume == 0)
return;
@@ -302,15 +295,12 @@ namespace Content.Server.GameObjects.Components.Chemistry
hands.PutInHand(item);
continue;
}
}
//Put it on the floor
bottle.Transform.GridPosition = user.Transform.GridPosition;
//Give it an offset
var x_negative = random.Prob(0.5f) ? -1 : 1;
var y_negative = random.Prob(0.5f) ? -1 : 1;
bottle.Transform.LocalPosition += new Vector2(random.NextFloat() * 0.2f * x_negative, random.NextFloat() * 0.2f * y_negative);
bottle.RandomOffset(0.2f);
}
}
@@ -345,9 +335,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
//Put it on the floor
pill.Transform.GridPosition = user.Transform.GridPosition;
//Give it an offset
var x_negative = random.Prob(0.5f) ? -1 : 1;
var y_negative = random.Prob(0.5f) ? -1 : 1;
pill.Transform.LocalPosition += new Vector2(random.NextFloat() * 0.2f * x_negative, random.NextFloat() * 0.2f * y_negative);
pill.RandomOffset(0.2f);
}
}
@@ -367,8 +355,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
if (!args.User.TryGetComponent(out IHandsComponent? hands))
{
_notifyManager.PopupMessage(Owner.Transform.GridPosition, args.User,
Loc.GetString("You have no hands."));
Owner.PopupMessage(args.User, Loc.GetString("You have no hands."));
return;
}
@@ -390,15 +377,13 @@ namespace Content.Server.GameObjects.Components.Chemistry
{
if (!args.User.TryGetComponent(out IHandsComponent? hands))
{
_notifyManager.PopupMessage(Owner.Transform.GridPosition, args.User,
Loc.GetString("You have no hands."));
Owner.PopupMessage(args.User, Loc.GetString("You have no hands."));
return true;
}
if (hands.GetActiveHand == null)
{
_notifyManager.PopupMessage(Owner.Transform.GridPosition, args.User,
Loc.GetString("You have nothing on your hand."));
Owner.PopupMessage(args.User, Loc.GetString("You have nothing on your hand."));
return false;
}
@@ -407,14 +392,12 @@ namespace Content.Server.GameObjects.Components.Chemistry
{
if (HasBeaker)
{
_notifyManager.PopupMessage(Owner.Transform.GridPosition, args.User,
Loc.GetString("This ChemMaster already has a container in it."));
Owner.PopupMessage(args.User, Loc.GetString("This ChemMaster already has a container in it."));
}
else if ((solution.Capabilities & SolutionCaps.FitsInDispenser) == 0) //Close enough to a chem master...
{
//If it can't fit in the chem master, don't put it in. For example, buckets and mop buckets can't fit.
_notifyManager.PopupMessage(Owner.Transform.GridPosition, args.User,
Loc.GetString("That can't fit in the ChemMaster."));
Owner.PopupMessage(args.User, Loc.GetString("That can't fit in the ChemMaster."));
}
else
{
@@ -424,8 +407,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
}
else
{
_notifyManager.PopupMessage(Owner.Transform.GridPosition, args.User,
Loc.GetString("You can't put this in the ChemMaster."));
Owner.PopupMessage(args.User, Loc.GetString("You can't put this in the ChemMaster."));
}
return true;
@@ -435,7 +417,6 @@ namespace Content.Server.GameObjects.Components.Chemistry
private void ClickSound()
{
EntitySystem.Get<AudioSystem>().PlayFromEntity("/Audio/Machines/machine_switch.ogg", Owner, AudioParams.Default.WithVolume(-2f));
}
}

View File

@@ -1,14 +1,13 @@
#nullable enable
using System;
using Content.Server.GameObjects.Components.Body.Circulatory;
using Content.Server.Interfaces;
using Content.Shared.Chemistry;
using Content.Shared.GameObjects.Components.Chemistry;
using Content.Shared.Interfaces;
using Content.Shared.Interfaces.GameObjects.Components;
using Content.Shared.Utility;
using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Robust.Shared.Serialization;
using Robust.Shared.ViewVariables;
@@ -23,8 +22,6 @@ namespace Content.Server.GameObjects.Components.Chemistry
[RegisterComponent]
public class InjectorComponent : SharedInjectorComponent, IAfterInteract, IUse
{
[Dependency] private readonly IServerNotifyManager _notifyManager = default!;
/// <summary>
/// Whether or not the injector is able to draw from containers or if it's a single use
/// device that can only inject.
@@ -100,7 +97,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
throw new ArgumentOutOfRangeException();
}
_notifyManager.PopupMessage(Owner, user, Loc.GetString(msg));
Owner.PopupMessage(user, Loc.GetString(msg));
Dirty();
}
@@ -165,8 +162,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
var realTransferAmount = ReagentUnit.Min(_transferAmount, targetBloodstream.EmptyVolume);
if (realTransferAmount <= 0)
{
_notifyManager.PopupMessage(Owner.Transform.GridPosition, user,
Loc.GetString("Container full."));
Owner.PopupMessage(user, Loc.GetString("Container full."));
return;
}
@@ -177,8 +173,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
return;
}
_notifyManager.PopupMessage(Owner.Transform.GridPosition, user,
Loc.GetString("Injected {0}u", removedSolution.TotalVolume));
Owner.PopupMessage(user, Loc.GetString("Injected {0}u", removedSolution.TotalVolume));
Dirty();
}
@@ -194,8 +189,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
var realTransferAmount = ReagentUnit.Min(_transferAmount, targetSolution.EmptyVolume);
if (realTransferAmount <= 0)
{
_notifyManager.PopupMessage(Owner.Transform.GridPosition, user,
Loc.GetString("Container full."));
Owner.PopupMessage(user, Loc.GetString("Container full."));
return;
}
@@ -206,8 +200,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
return;
}
_notifyManager.PopupMessage(Owner.Transform.GridPosition, user,
Loc.GetString("Injected {0}u", removedSolution.TotalVolume));
Owner.PopupMessage(user, Loc.GetString("Injected {0}u", removedSolution.TotalVolume));
Dirty();
}
@@ -223,8 +216,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
var realTransferAmount = ReagentUnit.Min(_transferAmount, targetSolution.CurrentVolume);
if (realTransferAmount <= 0)
{
_notifyManager.PopupMessage(Owner.Transform.GridPosition, user,
Loc.GetString("Container empty"));
Owner.PopupMessage(user, Loc.GetString("Container empty"));
return;
}
@@ -235,8 +227,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
return;
}
_notifyManager.PopupMessage(Owner.Transform.GridPosition, user,
Loc.GetString("Drew {0}u", removedSolution.TotalVolume));
Owner.PopupMessage(user, Loc.GetString("Drew {0}u", removedSolution.TotalVolume));
Dirty();
}

View File

@@ -1,9 +1,8 @@
using System.Threading.Tasks;
using Content.Server.Interfaces;
using Content.Shared.Chemistry;
using Content.Shared.Interfaces;
using Content.Shared.Interfaces.GameObjects.Components;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Robust.Shared.Serialization;
using Robust.Shared.ViewVariables;
@@ -19,8 +18,6 @@ namespace Content.Server.GameObjects.Components.Chemistry
[RegisterComponent]
class PourableComponent : Component, IInteractUsing
{
[Dependency] private readonly IServerNotifyManager _notifyManager = default!;
public override string Name => "Pourable";
private ReagentUnit _transferAmount;
@@ -87,8 +84,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
var realTransferAmount = ReagentUnit.Min(fromPourable.TransferAmount, toSolution.EmptyVolume);
if (realTransferAmount <= 0) //Special message if container is full
{
_notifyManager.PopupMessage(Owner.Transform.GridPosition, eventArgs.User,
Loc.GetString("Container is full"));
Owner.PopupMessage(eventArgs.User, Loc.GetString("Container is full"));
return false;
}
@@ -97,8 +93,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
if (!toSolution.TryAddSolution(removedSolution))
return false;
_notifyManager.PopupMessage(Owner.Transform.GridPosition, eventArgs.User,
Loc.GetString("Transferred {0}u", removedSolution.TotalVolume));
Owner.PopupMessage(eventArgs.User, Loc.GetString("Transferred {0}u", removedSolution.TotalVolume));
return true;
}

View File

@@ -6,12 +6,12 @@ using Content.Server.GameObjects.Components.GUI;
using Content.Server.GameObjects.Components.Items.Storage;
using Content.Server.GameObjects.Components.Power.ApcNetComponents;
using Content.Server.GameObjects.EntitySystems;
using Content.Server.Interfaces;
using Content.Server.Interfaces.GameObjects.Components.Items;
using Content.Server.Utility;
using Content.Shared.Chemistry;
using Content.Shared.GameObjects.Components.Chemistry.ReagentDispenser;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.Interfaces;
using Content.Shared.Interfaces.GameObjects.Components;
using Robust.Server.GameObjects.Components.Container;
using Robust.Server.GameObjects.Components.UserInterface;
@@ -40,7 +40,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
[ComponentReference(typeof(IInteractUsing))]
public class ReagentDispenserComponent : SharedReagentDispenserComponent, IActivate, IInteractUsing, ISolutionChange
{
[Dependency] private readonly IServerNotifyManager _notifyManager = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[ViewVariables] private ContainerSlot _beakerContainer = default!;
[ViewVariables] private string _packPrototypeId = "";
@@ -99,8 +99,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
{
if (string.IsNullOrEmpty(_packPrototypeId)) return;
var prototypeManager = IoCManager.Resolve<IPrototypeManager>();
if (!prototypeManager.TryIndex(_packPrototypeId, out ReagentDispenserInventoryPrototype packPrototype))
if (!_prototypeManager.TryIndex(_packPrototypeId, out ReagentDispenserInventoryPrototype packPrototype))
{
return;
}
@@ -280,8 +279,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
if (!args.User.TryGetComponent(out IHandsComponent? hands))
{
_notifyManager.PopupMessage(Owner.Transform.GridPosition, args.User,
Loc.GetString("You have no hands."));
Owner.PopupMessage(args.User, Loc.GetString("You have no hands."));
return;
}
@@ -303,15 +301,13 @@ namespace Content.Server.GameObjects.Components.Chemistry
{
if (!args.User.TryGetComponent(out IHandsComponent? hands))
{
_notifyManager.PopupMessage(Owner.Transform.GridPosition, args.User,
Loc.GetString("You have no hands."));
Owner.PopupMessage(args.User, Loc.GetString("You have no hands."));
return true;
}
if (hands.GetActiveHand == null)
{
_notifyManager.PopupMessage(Owner.Transform.GridPosition, args.User,
Loc.GetString("You have nothing on your hand."));
Owner.PopupMessage(args.User, Loc.GetString("You have nothing on your hand."));
return false;
}
@@ -320,14 +316,12 @@ namespace Content.Server.GameObjects.Components.Chemistry
{
if (HasBeaker)
{
_notifyManager.PopupMessage(Owner.Transform.GridPosition, args.User,
Loc.GetString("This dispenser already has a container in it."));
Owner.PopupMessage(args.User, Loc.GetString("This dispenser already has a container in it."));
}
else if ((solution.Capabilities & SolutionCaps.FitsInDispenser) == 0)
{
//If it can't fit in the dispenser, don't put it in. For example, buckets and mop buckets can't fit.
_notifyManager.PopupMessage(Owner.Transform.GridPosition, args.User,
Loc.GetString("That can't fit in the dispenser."));
Owner.PopupMessage(args.User, Loc.GetString("That can't fit in the dispenser."));
}
else
{
@@ -337,8 +331,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
}
else
{
_notifyManager.PopupMessage(Owner.Transform.GridPosition, args.User,
Loc.GetString("You can't put this in the dispenser."));
Owner.PopupMessage(args.User, Loc.GetString("You can't put this in the dispenser."));
}
return true;
@@ -348,11 +341,8 @@ namespace Content.Server.GameObjects.Components.Chemistry
private void ClickSound()
{
EntitySystem.Get<AudioSystem>().PlayFromEntity("/Audio/Machines/machine_switch.ogg", Owner, AudioParams.Default.WithVolume(-2f));
}
}
}

View File

@@ -76,7 +76,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
foreach (var tile in tiles)
{
var pos = tile.GridIndices.ToGridCoordinates(_mapManager, tile.GridIndex);
SpillHelper.SpillAt(pos, contents.SplitSolution(amount), "PuddleSmear", false); //make non PuddleSmear?
contents.SplitSolution(amount).SpillAt(pos, "PuddleSmear", false); // TODO: Make non PuddleSmear?
}
}

View File

@@ -10,6 +10,7 @@ using Content.Shared.GameObjects.Components.Conveyor;
using Content.Shared.GameObjects.Components.Interactable;
using Content.Shared.Interfaces.GameObjects.Components;
using Content.Shared.Physics;
using Content.Shared.Utility;
using Robust.Server.GameObjects;
using Robust.Shared.Containers;
using Robust.Shared.GameObjects;
@@ -170,7 +171,7 @@ namespace Content.Server.GameObjects.Components.Conveyor
Owner.AddComponent<ItemComponent>();
_group?.RemoveConveyor(this);
Owner.Transform.WorldPosition += (_random.NextFloat() * 0.4f - 0.2f, _random.NextFloat() * 0.4f - 0.2f);
Owner.RandomOffset(0.2f);
return true;
}

View File

@@ -81,7 +81,7 @@ namespace Content.Server.GameObjects.Components.Conveyor
}
_group.AddConveyor(conveyor);
user?.PopupMessage(user, Loc.GetString("Conveyor linked."));
user?.PopupMessage(Loc.GetString("Conveyor linked."));
}
/// <summary>

View File

@@ -1,5 +1,4 @@
#nullable enable
using Content.Server.Interfaces;
using Content.Server.Interfaces.GameObjects.Components.Items;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.Interfaces.GameObjects.Components;
@@ -11,13 +10,13 @@ using Robust.Shared.GameObjects;
using Robust.Shared.GameObjects.Components;
using Robust.Shared.GameObjects.Systems;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Robust.Shared.Maths;
using Robust.Shared.ViewVariables;
using System;
using System.Collections.Generic;
using Content.Server.Utility;
using Content.Shared.Interfaces;
using static Content.Shared.GameObjects.Components.Disposal.SharedDisposalRouterComponent;
namespace Content.Server.GameObjects.Components.Disposal
@@ -27,7 +26,6 @@ namespace Content.Server.GameObjects.Components.Disposal
[ComponentReference(typeof(IDisposalTubeComponent))]
public class DisposalRouterComponent : DisposalJunctionComponent, IActivate
{
[Dependency] private readonly IServerNotifyManager _notifyManager = default!;
public override string Name => "DisposalRouter";
[ViewVariables]
@@ -160,8 +158,7 @@ namespace Content.Server.GameObjects.Components.Disposal
if (!args.User.TryGetComponent(out IHandsComponent? hands))
{
_notifyManager.PopupMessage(Owner.Transform.GridPosition, args.User,
Loc.GetString("You have no hands."));
Owner.PopupMessage(args.User, Loc.GetString("You have no hands."));
return;
}

View File

@@ -1,8 +1,8 @@
#nullable enable
using Content.Server.Interfaces;
using Content.Server.Interfaces.GameObjects.Components.Items;
using Content.Server.Utility;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.Interfaces;
using Content.Shared.Interfaces.GameObjects.Components;
using Robust.Server.GameObjects.Components.UserInterface;
using Robust.Server.GameObjects.EntitySystems;
@@ -12,7 +12,6 @@ using Robust.Shared.GameObjects;
using Robust.Shared.GameObjects.Components;
using Robust.Shared.GameObjects.Systems;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Robust.Shared.Maths;
using Robust.Shared.ViewVariables;
@@ -25,7 +24,6 @@ namespace Content.Server.GameObjects.Components.Disposal
[ComponentReference(typeof(IDisposalTubeComponent))]
public class DisposalTaggerComponent : DisposalTransitComponent, IActivate
{
[Dependency] private readonly IServerNotifyManager _notifyManager = default!;
public override string Name => "DisposalTagger";
[ViewVariables(VVAccess.ReadWrite)]
@@ -128,8 +126,7 @@ namespace Content.Server.GameObjects.Components.Disposal
if (!args.User.TryGetComponent(out IHandsComponent? hands))
{
_notifyManager.PopupMessage(Owner.Transform.GridPosition, args.User,
Loc.GetString("You have no hands."));
Owner.PopupMessage(args.User, Loc.GetString("You have no hands."));
return;
}

View File

@@ -8,13 +8,13 @@ using Content.Server.GameObjects.Components.GUI;
using Content.Server.GameObjects.Components.Items.Storage;
using Content.Server.GameObjects.Components.Power.ApcNetComponents;
using Content.Server.GameObjects.EntitySystems.DoAfter;
using Content.Server.Interfaces;
using Content.Server.Interfaces.GameObjects.Components.Items;
using Content.Server.Utility;
using Content.Shared.GameObjects.Components.Body;
using Content.Shared.GameObjects.Components.Disposal;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.Verbs;
using Content.Shared.Interfaces;
using Content.Shared.Interfaces.GameObjects.Components;
using Robust.Server.GameObjects;
using Robust.Server.GameObjects.Components.Container;
@@ -43,7 +43,6 @@ namespace Content.Server.GameObjects.Components.Disposal
[ComponentReference(typeof(IInteractUsing))]
public class DisposalUnitComponent : SharedDisposalUnitComponent, IInteractHand, IInteractUsing, IDragDropOn
{
[Dependency] private readonly IServerNotifyManager _notifyManager = default!;
[Dependency] private readonly IGameTiming _gameTiming = default!;
public override string Name => "DisposalUnit";
@@ -614,15 +613,13 @@ namespace Content.Server.GameObjects.Components.Disposal
{
if (!ActionBlockerSystem.CanInteract(eventArgs.User))
{
_notifyManager.PopupMessage(Owner.Transform.GridPosition, eventArgs.User,
Loc.GetString("You can't do that!"));
Owner.PopupMessage(eventArgs.User, Loc.GetString("You can't do that!"));
return false;
}
if (ContainerHelpers.IsInContainer(eventArgs.User))
{
_notifyManager.PopupMessage(Owner.Transform.GridPosition, eventArgs.User,
Loc.GetString("You can't reach there!"));
Owner.PopupMessage(eventArgs.User, Loc.GetString("You can't reach there!"));
return false;
}
@@ -633,8 +630,7 @@ namespace Content.Server.GameObjects.Components.Disposal
if (!eventArgs.User.HasComponent<IHandsComponent>())
{
_notifyManager.PopupMessage(Owner.Transform.GridPosition, eventArgs.User,
Loc.GetString("You have no hands!"));
Owner.PopupMessage(eventArgs.User, Loc.GetString("You have no hands!"));
return false;
}

View File

@@ -8,6 +8,7 @@ using Content.Server.GameObjects.Components.VendingMachines;
using Content.Server.Interfaces;
using Content.Shared.GameObjects.Components.Doors;
using Content.Shared.GameObjects.Components.Interactable;
using Content.Shared.Interfaces;
using Content.Shared.Interfaces.GameObjects.Components;
using Robust.Server.GameObjects;
using Robust.Server.GameObjects.EntitySystems;
@@ -438,16 +439,14 @@ namespace Content.Server.GameObjects.Components.Doors
{
if (IsBolted())
{
var notify = IoCManager.Resolve<IServerNotifyManager>();
notify.PopupMessage(Owner, eventArgs.User,
Owner.PopupMessage(eventArgs.User,
Loc.GetString("The airlock's bolts prevent it from being forced!"));
return false;
}
if (IsPowered())
{
var notify = IoCManager.Resolve<IServerNotifyManager>();
notify.PopupMessage(Owner, eventArgs.User, Loc.GetString("The powered motors block your efforts!"));
Owner.PopupMessage(eventArgs.User, Loc.GetString("The powered motors block your efforts!"));
return false;
}

View File

@@ -0,0 +1,128 @@
using System.Threading.Tasks;
using Content.Server.GameObjects.Components.GUI;
using Content.Server.GameObjects.Components.Items;
using Content.Server.GameObjects.Components.Items.Storage;
using Content.Server.Interfaces.GameObjects.Components.Items;
using Content.Shared.Audio;
using Content.Shared.GameObjects.Components;
using Content.Shared.Interfaces;
using Content.Shared.Interfaces.GameObjects.Components;
using Robust.Server.GameObjects;
using Robust.Server.GameObjects.Components.Container;
using Robust.Server.GameObjects.EntitySystems;
using Robust.Shared.GameObjects;
using Robust.Shared.GameObjects.Systems;
using Robust.Shared.Localization;
using Robust.Shared.Serialization;
using Robust.Shared.ViewVariables;
namespace Content.Server.GameObjects.Components
{
[RegisterComponent]
[ComponentReference(typeof(IActivate))]
public class ExtinguisherCabinetComponent : Component, IInteractUsing, IInteractHand, IActivate
{
public override string Name => "ExtinguisherCabinet";
private bool _opened = false;
private string _doorSound;
[ViewVariables] protected ContainerSlot ItemContainer;
[ViewVariables] public string DoorSound => _doorSound;
public override void Initialize()
{
base.Initialize();
ItemContainer =
ContainerManagerComponent.Ensure<ContainerSlot>("extinguisher_cabinet", Owner, out _);
}
public override void ExposeData(ObjectSerializer serializer)
{
base.ExposeData(serializer);
serializer.DataField(ref _doorSound, "doorSound", "/Audio/Machines/machine_switch.ogg");
}
async Task<bool> IInteractUsing.InteractUsing(InteractUsingEventArgs eventArgs)
{
if (!_opened)
{
_opened = true;
ClickLatchSound();
}
else
{
if (ItemContainer.ContainedEntity != null || !eventArgs.Using.HasComponent<FireExtinguisherComponent>())
{
return false;
}
var handsComponent = eventArgs.User.GetComponent<IHandsComponent>();
if (!handsComponent.Drop(eventArgs.Using, ItemContainer))
{
return false;
}
}
UpdateVisuals();
return true;
}
bool IInteractHand.InteractHand(InteractHandEventArgs eventArgs)
{
if (_opened)
{
if (ItemContainer.ContainedEntity == null)
{
_opened = false;
ClickLatchSound();
}
else if (eventArgs.User.TryGetComponent(out HandsComponent hands))
{
Owner.PopupMessage(eventArgs.User,
Loc.GetString("You take {0:extinguisherName} from the {1:cabinetName}", ItemContainer.ContainedEntity.Name, Owner.Name));
hands.PutInHandOrDrop(ItemContainer.ContainedEntity.GetComponent<ItemComponent>());
}
else if (ItemContainer.Remove(ItemContainer.ContainedEntity))
{
ItemContainer.ContainedEntity.Transform.GridPosition = Owner.Transform.GridPosition;
}
}
else
{
_opened = true;
ClickLatchSound();
}
UpdateVisuals();
return true;
}
void IActivate.Activate(ActivateEventArgs eventArgs)
{
_opened = !_opened;
ClickLatchSound();
UpdateVisuals();
}
private void UpdateVisuals()
{
if (Owner.TryGetComponent(out AppearanceComponent appearance))
{
appearance.SetData(ExtinguisherCabinetVisuals.IsOpen, _opened);
appearance.SetData(ExtinguisherCabinetVisuals.ContainsExtinguisher, ItemContainer.ContainedEntity != null);
}
}
private void ClickLatchSound()
{
EntitySystem.Get<AudioSystem>() // Don't have original click, this sounds close
.PlayFromEntity(DoorSound, Owner, AudioHelpers.WithVariation(0.15f));
}
}
}

View File

@@ -0,0 +1,19 @@
using Content.Shared.Interfaces.GameObjects.Components;
using Robust.Shared.GameObjects;
using Robust.Shared.ViewVariables;
namespace Content.Server.GameObjects.Components
{
[RegisterComponent]
public class ExtinguisherCabinetFilledComponent : ExtinguisherCabinetComponent
{
public override string Name => "ExtinguisherCabinetFilled";
public override void Initialize()
{
base.Initialize();
ItemContainer.Insert(Owner.EntityManager.SpawnEntity("FireExtinguisher", Owner.Transform.GridPosition));
}
}
}

View File

@@ -41,7 +41,7 @@ namespace Content.Server.GameObjects.Components.Fluids
// Need this as when we split the component's owner may be deleted
var entityLocation = component.Owner.Transform.GridPosition;
var solution = solutionComponent.SplitSolution(solutionComponent.CurrentVolume);
SpillHelper.SpillAt(entityLocation, solution, "PuddleSmear");
solution.SpillAt(entityLocation, "PuddleSmear");
}
}
}

View File

@@ -80,7 +80,7 @@ namespace Content.Server.GameObjects.Components.Fluids
if (eventArgs.Target == null)
{
// Drop the liquid on the mop on to the ground
SpillHelper.SpillAt(eventArgs.ClickLocation, contents.SplitSolution(CurrentVolume), "PuddleSmear");
contents.SplitSolution(CurrentVolume).SpillAt(eventArgs.ClickLocation, "PuddleSmear");
return;
}
@@ -116,7 +116,7 @@ namespace Content.Server.GameObjects.Components.Fluids
if (puddleCleaned) //After cleaning the puddle, make a new puddle with solution from the mop as a "wet floor". Then evaporate it slowly.
{
SpillHelper.SpillAt(eventArgs.ClickLocation, contents.SplitSolution(transferAmount), "PuddleSmear");
contents.SplitSolution(transferAmount).SpillAt(eventArgs.ClickLocation, "PuddleSmear");
}
else
{

View File

@@ -6,7 +6,9 @@ using Content.Server.GameObjects.Components.Chemistry;
using Content.Server.GameObjects.Components.Movement;
using Content.Shared.Chemistry;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.Maps;
using Content.Shared.Physics;
using Content.Shared.Utility;
using Robust.Server.GameObjects;
using Robust.Server.GameObjects.EntitySystems;
using Robust.Server.Interfaces.GameObjects;
@@ -41,12 +43,13 @@ namespace Content.Server.GameObjects.Components.Fluids
// Small puddles will evaporate after a set delay
// TODO: 'leaves fluidtracks', probably in a separate component for stuff like gibb chunks?;
// TODO: Add stuff like slipping -> probably in a separate component (for stuff like bananas)
// based on behaviour (e.g. someone being punched vs slashed with a sword would have different blood sprite)
// to check for low volumes for evaporation or whatever
[Dependency] private readonly IMapManager _mapManager = default!;
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly IEntityManager _entityManager = default!;
public override string Name => "Puddle";
@@ -132,8 +135,7 @@ namespace Content.Server.GameObjects.Components.Fluids
// Random sprite state set server-side so it's consistent across all clients
_spriteComponent = Owner.EnsureComponent<SpriteComponent>();
var robustRandom = IoCManager.Resolve<IRobustRandom>();
var randomVariant = robustRandom.Next(0, _spriteVariants - 1);
var randomVariant = _random.Next(0, _spriteVariants - 1);
if (_spriteComponent.BaseRSIPath != null)
{
@@ -338,43 +340,6 @@ namespace Content.Server.GameObjects.Components.Fluids
}
}
// TODO: Move the below to SnapGrid?
/// <summary>
/// Will yield a random direction until none are left
/// </summary>
/// <returns></returns>
private static IEnumerable<Direction> RandomDirections()
{
var directions = new[]
{
Direction.East,
Direction.SouthEast,
Direction.South,
Direction.SouthWest,
Direction.West,
Direction.NorthWest,
Direction.North,
Direction.NorthEast,
};
var robustRandom = IoCManager.Resolve<IRobustRandom>();
var n = directions.Length;
while (n > 1)
{
n--;
var k = robustRandom.Next(n + 1);
var value = directions[k];
directions[k] = directions[n];
directions[n] = value;
}
foreach (var direction in directions)
{
yield return direction;
}
}
/// <summary>
/// Tries to get an adjacent coordinate to overflow to, unless it is blocked by a wall on the
/// same tile or the tile is empty
@@ -389,9 +354,13 @@ namespace Content.Server.GameObjects.Components.Fluids
var mapGrid = _mapManager.GetGrid(Owner.Transform.GridID);
if (!Owner.Transform.GridPosition.Offset(direction).TryGetTileRef(out var tile))
{
return false;
}
// If space return early, let that spill go out into the void
var tileRef = mapGrid.GetTileRef(Owner.Transform.GridPosition.Offset(direction.ToVec()));
if (tileRef.Tile.IsEmpty)
if (tile.Value.Tile.IsEmpty)
{
return false;
}
@@ -419,8 +388,7 @@ namespace Content.Server.GameObjects.Components.Fluids
if (puddle == default)
{
var grid = _snapGrid.DirectionToGrid(direction);
var entityManager = IoCManager.Resolve<IEntityManager>();
puddle = () => entityManager.SpawnEntity(Owner.Prototype.ID, grid).GetComponent<PuddleComponent>();
puddle = () => _entityManager.SpawnEntity(Owner.Prototype.ID, grid).GetComponent<PuddleComponent>();
}
return true;
@@ -432,7 +400,7 @@ namespace Content.Server.GameObjects.Components.Fluids
/// <returns>Enumerable of the puddles found or to be created</returns>
private IEnumerable<Func<PuddleComponent>> GetAllAdjacentOverflow()
{
foreach (var direction in RandomDirections())
foreach (var direction in SharedDirectionExtensions.RandomDirections())
{
if (TryGetAdjacentOverflow(direction, out var puddle))
{

View File

@@ -0,0 +1,128 @@
#nullable enable
using System.Diagnostics.CodeAnalysis;
using Content.Shared.Chemistry;
using Robust.Server.Interfaces.GameObjects;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.Map;
using Robust.Shared.IoC;
using Robust.Shared.Map;
namespace Content.Server.GameObjects.Components.Fluids
{
public static class SpillExtensions
{
/// <summary>
/// Spills the specified solution at the entity's location if possible.
/// </summary>
/// <param name="entity">
/// The entity to use as a location to spill the solution at.
/// </param>
/// <param name="solution">Initial solution for the prototype.</param>
/// <param name="prototype">The prototype to use.</param>
/// <param name="sound">Play the spill sound.</param>
/// <returns>The puddle if one was created, null otherwise.</returns>
public static PuddleComponent? SpillAt(this Solution solution, IEntity entity, string prototype, bool sound = true)
{
var coordinates = entity.Transform.GridPosition;
return solution.SpillAt(coordinates, prototype, sound);
}
/// <summary>
/// Spills the specified solution at the entity's location if possible.
/// </summary>
/// <param name="entity">
/// The entity to use as a location to spill the solution at.
/// </param>
/// <param name="solution">Initial solution for the prototype.</param>
/// <param name="prototype">The prototype to use.</param>
/// <param name="puddle">The puddle if one was created, null otherwise.</param>
/// <param name="sound">Play the spill sound.</param>
/// <returns>True if a puddle was created, false otherwise.</returns>
public static bool TrySpillAt(this Solution solution, IEntity entity, string prototype, [NotNullWhen(true)] out PuddleComponent? puddle, bool sound = true)
{
puddle = solution.SpillAt(entity, prototype, sound);
return puddle != null;
}
/// <summary>
/// Spills solution at the specified grid coordinates.
/// </summary>
/// <param name="solution">Initial solution for the prototype.</param>
/// <param name="coordinates">The coordinates to spill the solution at.</param>
/// <param name="prototype">The prototype to use.</param>
/// <param name="sound">Whether or not to play the spill sound.</param>
/// <returns>The puddle if one was created, null otherwise.</returns>
public static PuddleComponent? SpillAt(this Solution solution, GridCoordinates coordinates, string prototype, bool sound = true)
{
if (solution.TotalVolume == 0)
{
return null;
}
var mapManager = IoCManager.Resolve<IMapManager>();
var entityManager = IoCManager.Resolve<IEntityManager>();
var serverEntityManager = IoCManager.Resolve<IServerEntityManager>();
var mapGrid = mapManager.GetGrid(coordinates.GridID);
// If space return early, let that spill go out into the void
var tileRef = mapGrid.GetTileRef(coordinates);
if (tileRef.Tile.IsEmpty)
{
return null;
}
// Get normalized co-ordinate for spill location and spill it in the centre
// TODO: Does SnapGrid or something else already do this?
var spillTileMapGrid = mapManager.GetGrid(coordinates.GridID);
var spillTileRef = spillTileMapGrid.GetTileRef(coordinates).GridIndices;
var spillGridCoords = spillTileMapGrid.GridTileToLocal(spillTileRef);
var spilt = false;
foreach (var spillEntity in entityManager.GetEntitiesAt(spillTileMapGrid.ParentMapId, spillGridCoords.Position))
{
if (!spillEntity.TryGetComponent(out PuddleComponent? puddleComponent))
{
continue;
}
if (!puddleComponent.TryAddSolution(solution, sound))
{
continue;
}
spilt = true;
break;
}
// Did we add to an existing puddle
if (spilt)
{
return null;
}
var puddle = serverEntityManager.SpawnEntity(prototype, spillGridCoords);
var newPuddleComponent = puddle.GetComponent<PuddleComponent>();
newPuddleComponent.TryAddSolution(solution, sound);
return newPuddleComponent;
}
/// <summary>
/// Spills the specified solution at the entity's location if possible.
/// </summary>
/// <param name="coordinates">The coordinates to spill the solution at.</param>
/// <param name="solution">Initial solution for the prototype.</param>
/// <param name="prototype">The prototype to use.</param>
/// <param name="puddle">The puddle if one was created, null otherwise.</param>
/// <param name="sound">Play the spill sound.</param>
/// <returns>True if a puddle was created, false otherwise.</returns>
public static bool TrySpillAt(this Solution solution, GridCoordinates coordinates, string prototype, [NotNullWhen(true)] out PuddleComponent? puddle, bool sound = true)
{
puddle = solution.SpillAt(coordinates, prototype, sound);
return puddle != null;
}
}
}

View File

@@ -1,94 +0,0 @@
#nullable enable
using Content.Shared.Chemistry;
using Robust.Server.Interfaces.GameObjects;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.Map;
using Robust.Shared.IoC;
using Robust.Shared.Map;
namespace Content.Server.GameObjects.Components.Fluids
{
public static class SpillHelper
{
/// <summary>
/// Spills the specified solution at the entity's location if possible.
/// </summary>
/// <param name="entity">Entity location to spill at</param>
/// <param name="solution">Initial solution for the prototype</param>
/// <param name="prototype">Prototype to use</param>
/// <param name="sound">Play the spill sound</param>
internal static void SpillAt(IEntity entity, Solution solution, string prototype, bool sound = true)
{
var entityLocation = entity.Transform.GridPosition;
SpillAt(entityLocation, solution, prototype, sound);
}
// Other functions will be calling this one
/// <summary>
/// Spills solution at the specified grid co-ordinates
/// </summary>
/// <param name="gridCoordinates"></param>
/// <param name="solution">Initial solution for the prototype</param>
/// <param name="prototype">Prototype to use</param>
/// <param name="sound">Play the spill sound</param>
internal static PuddleComponent? SpillAt(GridCoordinates gridCoordinates, Solution solution, string prototype, bool sound = true)
{
if (solution.TotalVolume == 0)
{
return null;
}
var mapManager = IoCManager.Resolve<IMapManager>();
var entityManager = IoCManager.Resolve<IEntityManager>();
var serverEntityManager = IoCManager.Resolve<IServerEntityManager>();
var mapGrid = mapManager.GetGrid(gridCoordinates.GridID);
// If space return early, let that spill go out into the void
var tileRef = mapGrid.GetTileRef(gridCoordinates);
if (tileRef.Tile.IsEmpty)
{
return null;
}
// Get normalized co-ordinate for spill location and spill it in the centre
// TODO: Does SnapGrid or something else already do this?
var spillTileMapGrid = mapManager.GetGrid(gridCoordinates.GridID);
var spillTileRef = spillTileMapGrid.GetTileRef(gridCoordinates).GridIndices;
var spillGridCoords = spillTileMapGrid.GridTileToLocal(spillTileRef);
var spilt = false;
foreach (var spillEntity in entityManager.GetEntitiesAt(spillTileMapGrid.ParentMapId, spillGridCoords.Position))
{
if (!spillEntity.TryGetComponent(out PuddleComponent? puddleComponent))
{
continue;
}
if (!puddleComponent.TryAddSolution(solution, sound))
{
continue;
}
spilt = true;
break;
}
// Did we add to an existing puddle
if (spilt)
{
return null;
}
var puddle = serverEntityManager.SpawnEntity(prototype, spillGridCoords);
var newPuddleComponent = puddle.GetComponent<PuddleComponent>();
newPuddleComponent.TryAddSolution(solution, sound);
return newPuddleComponent;
}
}
}

View File

@@ -1,6 +1,6 @@
using Content.Server.GameObjects.Components.Chemistry;
using Content.Server.Interfaces;
using Content.Shared.Chemistry;
using Content.Shared.Interfaces;
using Content.Shared.Interfaces.GameObjects.Components;
using Robust.Server.GameObjects.EntitySystems;
using Robust.Server.Interfaces.GameObjects;
@@ -17,7 +17,6 @@ namespace Content.Server.GameObjects.Components.Fluids
[RegisterComponent]
class SprayComponent : Component, IAfterInteract
{
[Dependency] private readonly IServerNotifyManager _notifyManager = default!;
[Dependency] private readonly IServerEntityManager _serverEntityManager = default!;
public override string Name => "Spray";
@@ -71,7 +70,7 @@ namespace Content.Server.GameObjects.Components.Fluids
{
if (CurrentVolume <= 0)
{
_notifyManager.PopupMessage(Owner, eventArgs.User, Loc.GetString("It's empty!"));
Owner.PopupMessage(eventArgs.User, Loc.GetString("It's empty!"));
return;
}

View File

@@ -3,12 +3,11 @@ using System.Collections.Generic;
using System.Linq;
using Content.Server.GameObjects.Components.Items.Clothing;
using Content.Server.GameObjects.Components.Items.Storage;
using Content.Server.GameObjects.EntitySystems;
using Content.Server.GameObjects.EntitySystems.Click;
using Content.Server.Interfaces;
using Content.Server.Interfaces.GameObjects;
using Content.Shared.GameObjects.Components.Inventory;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.Interfaces;
using Robust.Server.GameObjects.Components.Container;
using Robust.Shared.Containers;
using Robust.Shared.GameObjects;
@@ -29,7 +28,6 @@ namespace Content.Server.GameObjects.Components.GUI
public class InventoryComponent : SharedInventoryComponent, IExAct, IEffectBlocker, IPressureProtection
{
[Dependency] private readonly IEntitySystemManager _entitySystemManager = default!;
[Dependency] private readonly IServerNotifyManager _serverNotifyManager = default!;
[ViewVariables]
private readonly Dictionary<Slots, ContainerSlot> _slotContainers = new Dictionary<Slots, ContainerSlot>();
@@ -432,7 +430,7 @@ namespace Content.Server.GameObjects.Components.GUI
hands.PutInHand(clothing);
if (reason != null)
_serverNotifyManager.PopupMessageCursor(Owner, reason);
Owner.PopupMessageCursor(reason);
}
}
break;

View File

@@ -1,15 +1,14 @@
#nullable enable
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using Content.Server.GameObjects.Components.ActionBlocking;
using Content.Server.GameObjects.Components.Items.Storage;
using Content.Server.GameObjects.EntitySystems.DoAfter;
using Content.Server.Interfaces;
using Content.Server.Utility;
using Content.Shared.GameObjects.Components.GUI;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.Verbs;
using Content.Shared.Interfaces;
using Content.Shared.Interfaces.GameObjects.Components;
using Robust.Server.GameObjects.Components.UserInterface;
using Robust.Server.Interfaces.GameObjects;
@@ -17,7 +16,6 @@ using Robust.Server.Interfaces.Player;
using Robust.Shared.GameObjects;
using Robust.Shared.GameObjects.Systems;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Robust.Shared.ViewVariables;
using static Content.Shared.GameObjects.Components.Inventory.EquipmentSlotDefines;
@@ -27,11 +25,9 @@ namespace Content.Server.GameObjects.Components.GUI
[RegisterComponent]
public sealed class StrippableComponent : SharedStrippableComponent, IDragDrop
{
[Dependency] private readonly IServerNotifyManager _notifyManager = default!;
public const float StripDelay = 2f;
[ViewVariables]
[ViewVariables]
private BoundUserInterface? UserInterface => Owner.GetUIOrNull(StrippingUiKey.Key);
public override void Initialize()
@@ -46,7 +42,7 @@ namespace Content.Server.GameObjects.Components.GUI
Owner.EnsureComponent<InventoryComponent>();
Owner.EnsureComponent<HandsComponent>();
Owner.EnsureComponent<CuffableComponent>();
if (Owner.TryGetComponent(out CuffableComponent? cuffed))
{
cuffed.OnCuffedStateChanged += UpdateSubscribed;
@@ -104,7 +100,7 @@ namespace Content.Server.GameObjects.Components.GUI
private Dictionary<EntityUid, string> GetHandcuffs()
{
var dictionary = new Dictionary<EntityUid, string>();
if (!Owner.TryGetComponent(out CuffableComponent? cuffed))
{
return dictionary;
@@ -173,13 +169,13 @@ namespace Content.Server.GameObjects.Components.GUI
if (item == null)
{
_notifyManager.PopupMessageCursor(user, Loc.GetString("You aren't holding anything!"));
user.PopupMessageCursor(Loc.GetString("You aren't holding anything!"));
return false;
}
if (!userHands.CanDrop(userHands.ActiveHand!))
{
_notifyManager.PopupMessageCursor(user, Loc.GetString("You can't drop that!"));
user.PopupMessageCursor(Loc.GetString("You can't drop that!"));
return false;
}
@@ -188,13 +184,13 @@ namespace Content.Server.GameObjects.Components.GUI
if (inventory.TryGetSlotItem(slot, out ItemComponent _))
{
_notifyManager.PopupMessageCursor(user, Loc.GetString("{0:They} already {0:have} something there!", Owner));
user.PopupMessageCursor(Loc.GetString("{0:They} already {0:have} something there!", Owner));
return false;
}
if (!inventory.CanEquip(slot, item, false))
{
_notifyManager.PopupMessageCursor(user, Loc.GetString("{0:They} cannot equip that there!", Owner));
user.PopupMessageCursor(Loc.GetString("{0:They} cannot equip that there!", Owner));
return false;
}
@@ -238,13 +234,13 @@ namespace Content.Server.GameObjects.Components.GUI
if (item == null)
{
_notifyManager.PopupMessageCursor(user, Loc.GetString("You aren't holding anything!"));
user.PopupMessageCursor(Loc.GetString("You aren't holding anything!"));
return false;
}
if (!userHands.CanDrop(userHands.ActiveHand!))
{
_notifyManager.PopupMessageCursor(user, Loc.GetString("You can't drop that!"));
user.PopupMessageCursor(Loc.GetString("You can't drop that!"));
return false;
}
@@ -253,13 +249,13 @@ namespace Content.Server.GameObjects.Components.GUI
if (hands.TryGetItem(hand, out var _))
{
_notifyManager.PopupMessageCursor(user, Loc.GetString("{0:They} already {0:have} something there!", Owner));
user.PopupMessageCursor(Loc.GetString("{0:They} already {0:have} something there!", Owner));
return false;
}
if (!hands.CanPutInHand(item, hand, false))
{
_notifyManager.PopupMessageCursor(user, Loc.GetString("{0:They} cannot put that there!", Owner));
user.PopupMessageCursor(Loc.GetString("{0:They} cannot put that there!", Owner));
return false;
}
@@ -304,13 +300,13 @@ namespace Content.Server.GameObjects.Components.GUI
if (!inventory.TryGetSlotItem(slot, out ItemComponent itemToTake))
{
_notifyManager.PopupMessageCursor(user, Loc.GetString("{0:They} {0:have} nothing there!", Owner));
user.PopupMessageCursor(Loc.GetString("{0:They} {0:have} nothing there!", Owner));
return false;
}
if (!inventory.CanUnequip(slot, false))
{
_notifyManager.PopupMessageCursor(user, Loc.GetString("{0:They} cannot unequip that!", Owner));
user.PopupMessageCursor(Loc.GetString("{0:They} cannot unequip that!", Owner));
return false;
}
@@ -355,13 +351,13 @@ namespace Content.Server.GameObjects.Components.GUI
if (!hands.TryGetItem(hand, out var heldItem))
{
_notifyManager.PopupMessageCursor(user, Loc.GetString("{0:They} {0:have} nothing there!", Owner));
user.PopupMessageCursor(Loc.GetString("{0:They} {0:have} nothing there!", Owner));
return false;
}
if (!hands.CanDrop(hand, false))
{
_notifyManager.PopupMessageCursor(user, Loc.GetString("{0:They} cannot drop that!", Owner));
user.PopupMessageCursor(Loc.GetString("{0:They} cannot drop that!", Owner));
return false;
}

View File

@@ -8,6 +8,7 @@ using Content.Server.Utility;
using Content.Shared.GameObjects.Components.Gravity;
using Content.Shared.GameObjects.Components.Interactable;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.Interfaces;
using Content.Shared.Interfaces.GameObjects.Components;
using Robust.Server.GameObjects;
using Robust.Server.GameObjects.Components.UserInterface;
@@ -111,9 +112,8 @@ namespace Content.Server.GameObjects.Components.Gravity
breakable.FixAllDamage();
_intact = true;
var notifyManager = IoCManager.Resolve<IServerNotifyManager>();
notifyManager.PopupMessage(Owner, eventArgs.User, Loc.GetString("You repair {0:theName} with {1:theName}", Owner, eventArgs.Using));
Owner.PopupMessage(eventArgs.User,
Loc.GetString("You repair {0:theName} with {1:theName}", Owner, eventArgs.Using));
return true;
}

View File

@@ -3,11 +3,10 @@ using System;
using System.Linq;
using Content.Server.GameObjects.Components.Mobs;
using Content.Server.GameObjects.EntitySystems;
using Content.Server.Interfaces;
using Content.Server.Mobs;
using Content.Server.Utility;
using Content.Shared.GameObjects.Components.Instruments;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.Interfaces;
using Content.Shared.Interfaces.GameObjects.Components;
using Robust.Server.GameObjects;
using Robust.Server.GameObjects.Components.UserInterface;
@@ -38,7 +37,6 @@ namespace Content.Server.GameObjects.Components.Instruments
IUse,
IThrown
{
[Dependency] private readonly IServerNotifyManager _notifyManager = default!;
[Dependency] private readonly IGameTiming _gameTiming = default!;
private static readonly TimeSpan OneSecAgo = TimeSpan.FromSeconds(-1);
@@ -166,11 +164,11 @@ namespace Content.Server.GameObjects.Components.Instruments
switch (_laggedBatches)
{
case (int) (MaxMidiLaggedBatches * (1 / 3d)) + 1:
_notifyManager.PopupMessage(Owner, InstrumentPlayer.AttachedEntity,
Owner.PopupMessage(InstrumentPlayer.AttachedEntity,
"Your fingers are beginning to a cramp a little!");
break;
case (int) (MaxMidiLaggedBatches * (2 / 3d)) + 1:
_notifyManager.PopupMessage(Owner, InstrumentPlayer.AttachedEntity,
Owner.PopupMessage(InstrumentPlayer.AttachedEntity,
"Your fingers are seriously cramping up!");
break;
}
@@ -333,7 +331,7 @@ namespace Content.Server.GameObjects.Components.Instruments
InstrumentPlayer = null;
_notifyManager.PopupMessage(Owner, mob, "Your fingers cramp up from playing!");
Owner.PopupMessage(mob, "Your fingers cramp up from playing!");
}
_timer += delta;

View File

@@ -17,7 +17,6 @@ using Robust.Server.Interfaces.GameObjects;
using Robust.Shared.GameObjects;
using Robust.Shared.GameObjects.Systems;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Robust.Shared.Utility;
using Robust.Shared.ViewVariables;
@@ -31,8 +30,6 @@ namespace Content.Server.GameObjects.Components.Interactable
internal sealed class HandheldLightComponent : SharedHandheldLightComponent, IUse, IExamine, IInteractUsing,
IMapInit
{
[Dependency] private readonly ISharedNotifyManager _notifyManager = default!;
[ViewVariables(VVAccess.ReadWrite)] public float Wattage { get; set; } = 10;
[ViewVariables] private ContainerSlot _cellContainer = default!;
@@ -152,7 +149,7 @@ namespace Content.Server.GameObjects.Components.Interactable
{
EntitySystem.Get<AudioSystem>().PlayFromEntity("/Audio/Machines/button.ogg", Owner);
_notifyManager.PopupMessage(Owner, user, Loc.GetString("Cell missing..."));
Owner.PopupMessage(user, Loc.GetString("Cell missing..."));
return;
}
@@ -162,7 +159,7 @@ namespace Content.Server.GameObjects.Components.Interactable
if (Wattage > cell.CurrentCharge)
{
EntitySystem.Get<AudioSystem>().PlayFromEntity("/Audio/Machines/button.ogg", Owner);
_notifyManager.PopupMessage(Owner, user, Loc.GetString("Dead cell..."));
Owner.PopupMessage(user, Loc.GetString("Dead cell..."));
return;
}

View File

@@ -5,7 +5,6 @@ using Content.Server.Atmos;
using Content.Server.GameObjects.Components.Chemistry;
using Content.Server.GameObjects.Components.Items.Storage;
using Content.Server.GameObjects.EntitySystems;
using Content.Server.Interfaces;
using Content.Server.Interfaces.Chat;
using Content.Server.Interfaces.GameObjects;
using Content.Server.Utility;
@@ -15,7 +14,6 @@ using Content.Shared.GameObjects.Components.Interactable;
using Content.Shared.Interfaces.GameObjects.Components;
using Content.Shared.Interfaces;
using Robust.Server.GameObjects;
using Robust.Server.Interfaces.Player;
using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.IoC;
@@ -33,8 +31,6 @@ namespace Content.Server.GameObjects.Components.Interactable
public class WelderComponent : ToolComponent, IExamine, IUse, ISuicideAct, ISolutionChange
{
[Dependency] private readonly IEntitySystemManager _entitySystemManager = default!;
[Dependency] private readonly IServerNotifyManager _notifyManager = default!;
[Dependency] private readonly IPlayerManager _playerManager = default!;
public override string Name => "Welder";
public override uint? NetID => ContentNetIDs.WELDER;
@@ -108,7 +104,7 @@ namespace Content.Server.GameObjects.Components.Interactable
if (!CanWeld(DefaultFuelCost))
{
_notifyManager.PopupMessage(target, user, "Can't weld!");
target.PopupMessage(user, "Can't weld!");
return false;
}
@@ -137,13 +133,13 @@ namespace Content.Server.GameObjects.Components.Interactable
{
if (!WelderLit)
{
if(!silent) _notifyManager.PopupMessage(Owner, user, Loc.GetString("The welder is turned off!"));
if(!silent) Owner.PopupMessage(user, Loc.GetString("The welder is turned off!"));
return false;
}
if (!CanWeld(value))
{
if(!silent) _notifyManager.PopupMessage(Owner, user, Loc.GetString("The welder does not have enough fuel for that!"));
if(!silent) Owner.PopupMessage(user, Loc.GetString("The welder does not have enough fuel for that!"));
return false;
}
@@ -192,7 +188,7 @@ namespace Content.Server.GameObjects.Components.Interactable
if (!CanLitWelder())
{
_notifyManager.PopupMessage(Owner, user, Loc.GetString("The welder has no fuel left!"));
Owner.PopupMessage(user, Loc.GetString("The welder has no fuel left!"));
return false;
}

View File

@@ -2,13 +2,12 @@
using System.Collections.Generic;
using Content.Server.GameObjects.Components.GUI;
using Content.Server.GameObjects.Components.Items.Storage;
using Content.Server.Interfaces;
using Content.Shared.GameObjects;
using Content.Shared.GameObjects.Components.Items;
using Content.Shared.Interfaces;
using Content.Shared.Interfaces.GameObjects.Components;
using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Serialization;
using static Content.Shared.GameObjects.Components.Inventory.EquipmentSlotDefines;
@@ -20,8 +19,6 @@ namespace Content.Server.GameObjects.Components.Items.Clothing
[ComponentReference(typeof(IItemComponent))]
public class ClothingComponent : ItemComponent, IUse
{
[Dependency] private readonly IServerNotifyManager _serverNotifyManager = default!;
public override string Name => "Clothing";
public override uint? NetID => ContentNetIDs.CLOTHING;
@@ -112,7 +109,7 @@ namespace Content.Server.GameObjects.Components.Items.Clothing
if (!inv.Equip(slot, this, true, out var reason))
{
if (reason != null)
_serverNotifyManager.PopupMessage(Owner, user, reason);
Owner.PopupMessage(user, reason);
return false;
}

View File

@@ -0,0 +1,14 @@
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.Interfaces.GameObjects.Components;
using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.Random;
using Robust.Shared.Prototypes;
namespace Content.Server.GameObjects.Components.Items
{
[RegisterComponent]
public class FireExtinguisherComponent : Component
{
public override string Name => "FireExtinguisher";
}
}

View File

@@ -1,10 +1,9 @@
using System;
using Content.Server.Interfaces;
using Content.Server.Interfaces.GameObjects.Components.Items;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.Interfaces;
using Content.Shared.Interfaces.GameObjects.Components;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Robust.Shared.Serialization;
using Robust.Shared.Utility;
@@ -15,8 +14,6 @@ namespace Content.Server.GameObjects.Components.Items.RCD
[RegisterComponent]
public class RCDAmmoComponent : Component, IAfterInteract, IExamine
{
[Dependency] private IServerNotifyManager _serverNotifyManager = default!;
public override string Name => "RCDAmmo";
//How much ammo we refill
@@ -43,17 +40,16 @@ namespace Content.Server.GameObjects.Components.Items.RCD
if (rcdComponent.maxAmmo - rcdComponent._ammo < refillAmmo)
{
_serverNotifyManager.PopupMessage(rcdComponent.Owner, eventArgs.User, "The RCD is full!");
rcdComponent.Owner.PopupMessage(eventArgs.User, Loc.GetString("The RCD is full!"));
return;
}
rcdComponent._ammo = Math.Min(rcdComponent.maxAmmo, rcdComponent._ammo + refillAmmo);
_serverNotifyManager.PopupMessage(rcdComponent.Owner, eventArgs.User, "You refill the RCD.");
rcdComponent.Owner.PopupMessage(eventArgs.User, Loc.GetString("You refill the RCD."));
//Deleting a held item causes a lot of errors
hands.Drop(Owner, false);
Owner.Delete();
}
}
}

View File

@@ -1,9 +1,8 @@
using System;
using System.Threading;
using Content.Server.GameObjects.EntitySystems.DoAfter;
using Content.Server.Interfaces;
using Content.Server.Utility;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.Interfaces;
using Content.Shared.Interfaces.GameObjects.Components;
using Content.Shared.Maps;
using Content.Shared.Utility;
@@ -30,7 +29,6 @@ namespace Content.Server.GameObjects.Components.Items.RCD
[Dependency] private readonly IEntitySystemManager _entitySystemManager = default!;
[Dependency] private readonly IMapManager _mapManager = default!;
[Dependency] private readonly IServerEntityManager _serverEntityManager = default!;
[Dependency] private readonly IServerNotifyManager _serverNotifyManager = default!;
public override string Name => "RCD";
private RcdMode _mode = 0; //What mode are we on? Can be floors, walls, deconstruct.
@@ -86,12 +84,12 @@ namespace Content.Server.GameObjects.Components.Items.RCD
int mode = (int) _mode; //Firstly, cast our RCDmode mode to an int (enums are backed by ints anyway by default)
mode = (++mode) % _modes.Length; //Then, do a rollover on the value so it doesnt hit an invalid state
_mode = (RcdMode) mode; //Finally, cast the newly acquired int mode to an RCDmode so we can use it.
_serverNotifyManager.PopupMessage(Owner, eventArgs.User, $"The RCD is now set to {this._mode} mode."); //Prints an overhead message above the RCD
Owner.PopupMessage(eventArgs.User, Loc.GetString("The RCD is now set to {0} mode.", _mode)); //Prints an overhead message above the RCD
}
public void Examine(FormattedMessage message, bool inDetailsRange)
{
message.AddMarkup(Loc.GetString("It's currently on {0} mode, and holds {1} charges.",_mode.ToString(), this._ammo));
message.AddMarkup(Loc.GetString("It's currently on {0} mode, and holds {1} charges.",_mode.ToString(), _ammo));
}
public async void AfterInteract(AfterInteractEventArgs eventArgs)
@@ -159,7 +157,7 @@ namespace Content.Server.GameObjects.Components.Items.RCD
//Less expensive checks first. Failing those ones, we need to check that the tile isn't obstructed.
if (_ammo <= 0)
{
_serverNotifyManager.PopupMessage(Owner, eventArgs.User, $"The RCD is out of ammo!");
Owner.PopupMessage(eventArgs.User, Loc.GetString("The RCD is out of ammo!"));
return false;
}
@@ -180,7 +178,7 @@ namespace Content.Server.GameObjects.Components.Items.RCD
case RcdMode.Floors:
if (!tile.Tile.IsEmpty)
{
_serverNotifyManager.PopupMessage(Owner, eventArgs.User, $"You can only build a floor on space!");
Owner.PopupMessage(eventArgs.User, Loc.GetString("You can only build a floor on space!"));
return false;
}
@@ -195,13 +193,13 @@ namespace Content.Server.GameObjects.Components.Items.RCD
//They tried to decon a turf but the turf is blocked
if (eventArgs.Target == null && tile.IsBlockedTurf(true))
{
_serverNotifyManager.PopupMessage(Owner, eventArgs.User, $"That tile is obstructed!");
Owner.PopupMessage(eventArgs.User, Loc.GetString("That tile is obstructed!"));
return false;
}
//They tried to decon a non-turf but it's not in the whitelist
if (eventArgs.Target != null && !eventArgs.Target.TryGetComponent(out RCDDeconstructWhitelist rcd_decon))
{
_serverNotifyManager.PopupMessage(Owner, eventArgs.User, $"You can't deconstruct that!");
Owner.PopupMessage(eventArgs.User, Loc.GetString("You can't deconstruct that!"));
return false;
}
@@ -210,25 +208,25 @@ namespace Content.Server.GameObjects.Components.Items.RCD
case RcdMode.Walls:
if (tile.Tile.IsEmpty)
{
_serverNotifyManager.PopupMessage(Owner, eventArgs.User, $"Cannot build a wall on space!");
Owner.PopupMessage(eventArgs.User, Loc.GetString("You cannot build a wall on space!"));
return false;
}
if (tile.IsBlockedTurf(true))
{
_serverNotifyManager.PopupMessage(Owner, eventArgs.User, $"That tile is obstructed!");
Owner.PopupMessage(eventArgs.User, Loc.GetString("That tile is obstructed!"));
return false;
}
return true;
case RcdMode.Airlock:
if (tile.Tile.IsEmpty)
{
_serverNotifyManager.PopupMessage(Owner, eventArgs.User, $"Cannot build an airlock on space!");
Owner.PopupMessage(eventArgs.User, Loc.GetString("Cannot build an airlock on space!"));
return false;
}
if (tile.IsBlockedTurf(true))
{
_serverNotifyManager.PopupMessage(Owner, eventArgs.User, $"That tile is obstructed!");
Owner.PopupMessage(eventArgs.User, Loc.GetString("That tile is obstructed!"));
return false;
}
return true;

View File

@@ -4,10 +4,7 @@ using System.Threading.Tasks;
using Content.Server.GameObjects.Components.Body;
using Content.Server.GameObjects.Components.GUI;
using Content.Server.GameObjects.Components.Interactable;
using Content.Server.GameObjects.Components.Mobs;
using Content.Server.GameObjects.EntitySystems;
using Content.Shared.GameObjects.Components.Interactable;
using Content.Shared.GameObjects.Components.Mobs;
using Content.Shared.GameObjects.Components.Storage;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.Verbs;
@@ -35,6 +32,8 @@ namespace Content.Server.GameObjects.Components.Items.Storage
[ComponentReference(typeof(IStorageComponent))]
public class EntityStorageComponent : Component, IActivate, IStorageComponent, IInteractUsing, IDestroyAct, IActionBlocker, IExAct
{
[Dependency] private readonly IGameTiming _gameTiming = default!;
public override string Name => "EntityStorage";
private const float MaxSize = 1.0f; // maximum width or height of an entity allowed inside the storage.
@@ -301,14 +300,13 @@ namespace Content.Server.GameObjects.Components.Items.Storage
case RelayMovementEntityMessage msg:
if (msg.Entity.HasComponent<HandsComponent>())
{
var timing = IoCManager.Resolve<IGameTiming>();
if (timing.CurTime <
if (_gameTiming.CurTime <
_lastInternalOpenAttempt + InternalOpenAttemptDelay)
{
break;
}
_lastInternalOpenAttempt = timing.CurTime;
_lastInternalOpenAttempt = _gameTiming.CurTime;
TryOpenStorage(msg.Entity);
}
break;

View File

@@ -13,7 +13,6 @@ namespace Content.Server.GameObjects.Components.Items.Storage.Fill
void IMapInit.MapInit()
{
var storage = Owner.GetComponent<IStorageComponent>();
var random = IoCManager.Resolve<IRobustRandom>();
void Spawn(string prototype)
{

View File

@@ -126,8 +126,7 @@ namespace Content.Server.GameObjects.Components.Items.Storage
{
if (!reader.IsAllowed(user))
{
IoCManager.Resolve<IServerNotifyManager>()
.PopupMessage(Owner, user, Loc.GetString("Access denied"));
Owner.PopupMessage(user, Loc.GetString("Access denied"));
return true;
}
}

View File

@@ -12,7 +12,6 @@ using Content.Server.GameObjects.Components.GUI;
using Content.Server.GameObjects.Components.Items.Storage;
using Content.Server.GameObjects.Components.Power.ApcNetComponents;
using Content.Server.GameObjects.EntitySystems;
using Content.Server.Interfaces;
using Content.Server.Interfaces.Chat;
using Content.Server.Interfaces.GameObjects;
using Content.Server.Utility;
@@ -27,7 +26,6 @@ using Robust.Server.GameObjects.Components.Container;
using Robust.Server.GameObjects.Components.UserInterface;
using Robust.Server.GameObjects.EntitySystems;
using Robust.Server.Interfaces.GameObjects;
using Robust.Server.Interfaces.Player;
using Robust.Shared.Audio;
using Robust.Shared.GameObjects.Systems;
using Content.Shared.GameObjects.Components.Body;
@@ -44,8 +42,6 @@ namespace Content.Server.GameObjects.Components.Kitchen
{
[Dependency] private readonly IEntityManager _entityManager = default!;
[Dependency] private readonly RecipeManager _recipeManager = default!;
[Dependency] private readonly IServerNotifyManager _notifyManager = default!;
[Dependency] private readonly IPlayerManager _playerManager = default!;
#region YAMLSERIALIZE
private int _cookTimeDefault;
@@ -206,8 +202,7 @@ namespace Content.Server.GameObjects.Components.Kitchen
{
if (!Powered)
{
_notifyManager.PopupMessage(Owner.Transform.GridPosition, eventArgs.User,
Loc.GetString("It has no power!"));
Owner.PopupMessage(eventArgs.User, Loc.GetString("It has no power!"));
return false;
}
@@ -215,7 +210,7 @@ namespace Content.Server.GameObjects.Components.Kitchen
if (itemEntity == null)
{
eventArgs.User.PopupMessage(eventArgs.User, Loc.GetString("You have no active hand!"));
eventArgs.User.PopupMessage(Loc.GetString("You have no active hand!"));
return false;
}
@@ -236,8 +231,7 @@ namespace Content.Server.GameObjects.Components.Kitchen
var realTransferAmount = ReagentUnit.Min(attackPourable.TransferAmount, solution.EmptyVolume);
if (realTransferAmount <= 0) //Special message if container is full
{
_notifyManager.PopupMessage(Owner.Transform.GridPosition, eventArgs.User,
Loc.GetString("Container is full"));
Owner.PopupMessage(eventArgs.User, Loc.GetString("Container is full"));
return false;
}
@@ -248,15 +242,14 @@ namespace Content.Server.GameObjects.Components.Kitchen
return false;
}
_notifyManager.PopupMessage(Owner.Transform.GridPosition, eventArgs.User,
Loc.GetString("Transferred {0}u", removedSolution.TotalVolume));
Owner.PopupMessage(eventArgs.User, Loc.GetString("Transferred {0}u", removedSolution.TotalVolume));
return true;
}
if (!itemEntity.TryGetComponent(typeof(ItemComponent), out var food))
{
_notifyManager.PopupMessage(Owner, eventArgs.User, "That won't work!");
Owner.PopupMessage(eventArgs.User, "That won't work!");
return false;
}

View File

@@ -63,7 +63,7 @@ namespace Content.Server.GameObjects.Components.MachineLinking
{
if (transmitter == null)
{
user.PopupMessage(user, Loc.GetString("Signal not set."));
user.PopupMessage(Loc.GetString("Signal not set."));
return false;
}

View File

@@ -0,0 +1,235 @@
#nullable enable
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Content.Server.GameObjects.Components.Mobs;
using Content.Server.GameObjects.Components.Observer;
using Content.Server.GameObjects.Components.Power.ApcNetComponents;
using Content.Server.GameObjects.EntitySystems;
using Content.Server.Interfaces;
using Content.Server.Mobs;
using Content.Server.Utility;
using Content.Shared.GameObjects.Components.Damage;
using Content.Shared.GameObjects.Components.Medical;
using Content.Shared.Interfaces.GameObjects.Components;
using Content.Shared.Preferences;
using Robust.Server.GameObjects;
using Robust.Server.GameObjects.Components.Container;
using Robust.Server.GameObjects.Components.UserInterface;
using Robust.Server.Interfaces.GameObjects;
using Robust.Server.Interfaces.Player;
using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Maths;
using Robust.Shared.Network;
using Robust.Shared.Serialization;
using Robust.Shared.ViewVariables;
namespace Content.Server.GameObjects.Components.Medical
{
[RegisterComponent]
[ComponentReference(typeof(IActivate))]
public class CloningPodComponent : SharedCloningPodComponent, IActivate
{
[Dependency] private readonly IServerPreferencesManager _prefsManager = null!;
[Dependency] private readonly IEntityManager _entityManager = null!;
[Dependency] private readonly IPlayerManager _playerManager = null!;
[ViewVariables]
private bool Powered => !Owner.TryGetComponent(out PowerReceiverComponent? receiver) || receiver.Powered;
[ViewVariables]
private BoundUserInterface? UserInterface =>
Owner.GetUIOrNull(CloningPodUIKey.Key);
private ContainerSlot _bodyContainer = default!;
private Mind? _capturedMind;
private CloningPodStatus _status;
private float _cloningProgress = 0;
private float _cloningTime;
public override void ExposeData(ObjectSerializer serializer)
{
base.ExposeData(serializer);
serializer.DataField(ref _cloningTime, "cloningTime", 10f);
}
public override void Initialize()
{
base.Initialize();
if (UserInterface != null)
{
UserInterface.OnReceiveMessage += OnUiReceiveMessage;
}
_bodyContainer = ContainerManagerComponent.Ensure<ContainerSlot>($"{Name}-bodyContainer", Owner);
//TODO: write this so that it checks for a change in power events for GORE POD cases
var newState = GetUserInterfaceState();
UserInterface?.SetState(newState);
UpdateUserInterface();
Owner.EntityManager.EventBus.SubscribeEvent<GhostComponent.GhostReturnMessage>(EventSource.Local, this,
HandleGhostReturn);
}
public void Update(float frametime)
{
if (_bodyContainer.ContainedEntity != null &&
Powered)
{
_cloningProgress += frametime;
_cloningProgress = MathHelper.Clamp(_cloningProgress, 0f, _cloningTime);
}
if (_cloningProgress >= _cloningTime &&
_bodyContainer.ContainedEntity != null &&
_capturedMind?.Session.AttachedEntity == _bodyContainer.ContainedEntity &&
Powered)
{
_bodyContainer.Remove(_bodyContainer.ContainedEntity);
_capturedMind = null;
_cloningProgress = 0f;
_status = CloningPodStatus.Idle;
UpdateAppearance();
}
UpdateUserInterface();
}
public override void OnRemove()
{
if (UserInterface != null)
{
UserInterface.OnReceiveMessage -= OnUiReceiveMessage;
}
Owner.EntityManager.EventBus.UnsubscribeEvent<GhostComponent.GhostReturnMessage>(EventSource.Local, this);
base.OnRemove();
}
private void UpdateUserInterface()
{
if (!Powered) return;
UserInterface?.SetState(GetUserInterfaceState());
}
private CloningPodBoundUserInterfaceState GetUserInterfaceState()
{
return new CloningPodBoundUserInterfaceState(CloningSystem.getIdToUser(), _cloningProgress,
(_status == CloningPodStatus.Cloning));
}
private void UpdateAppearance()
{
if (Owner.TryGetComponent(out AppearanceComponent? appearance))
{
appearance.SetData(CloningPodVisuals.Status, _status);
}
}
public void Activate(ActivateEventArgs eventArgs)
{
if (!Powered ||
!eventArgs.User.TryGetComponent(out IActorComponent? actor))
{
return;
}
UserInterface?.Open(actor.playerSession);
}
private async void OnUiReceiveMessage(ServerBoundUserInterfaceMessage obj)
{
if (!(obj.Message is CloningPodUiButtonPressedMessage message)) return;
switch (message.Button)
{
case UiButton.Clone:
if (message.ScanId == null) return;
if (_bodyContainer.ContainedEntity != null ||
!CloningSystem.Minds.TryGetValue(message.ScanId.Value, out var mind))
{
return;
}
var dead =
mind.OwnedEntity.TryGetComponent<IDamageableComponent>(out var damageable) &&
damageable.CurrentDamageState == DamageState.Dead;
if (!dead) return;
var mob = _entityManager.SpawnEntity("HumanMob_Content", Owner.Transform.MapPosition);
var client = _playerManager
.GetPlayersBy(x => x.SessionId == mind.SessionId).First();
mob.GetComponent<HumanoidAppearanceComponent>()
.UpdateFromProfile(GetPlayerProfileAsync(client.Name).Result);
mob.Name = GetPlayerProfileAsync(client.Name).Result.Name;
_bodyContainer.Insert(mob);
_capturedMind = mind;
Owner.EntityManager.EventBus.RaiseEvent(EventSource.Local,
new CloningStartedMessage(_capturedMind));
_status = CloningPodStatus.NoMind;
UpdateAppearance();
break;
case UiButton.Eject:
if (_bodyContainer.ContainedEntity == null || _cloningProgress < _cloningTime) break;
_bodyContainer.Remove(_bodyContainer.ContainedEntity!);
_capturedMind = null;
_cloningProgress = 0f;
_status = CloningPodStatus.Idle;
UpdateAppearance();
break;
default:
throw new ArgumentOutOfRangeException();
}
}
public class CloningStartedMessage : EntitySystemMessage
{
public CloningStartedMessage(Mind capturedMind)
{
CapturedMind = capturedMind;
}
public Mind CapturedMind { get; }
}
private async Task<HumanoidCharacterProfile> GetPlayerProfileAsync(string username)
{
return (HumanoidCharacterProfile) (await _prefsManager.GetPreferencesAsync(username))
.SelectedCharacter;
}
private void HandleGhostReturn(GhostComponent.GhostReturnMessage message)
{
if (message.Sender == _capturedMind)
{
//If the captured mind is in a ghost, we want to get rid of it.
_capturedMind.VisitingEntity?.Delete();
//Transfer the mind to the new mob
_capturedMind.TransferTo(_bodyContainer.ContainedEntity);
_status = CloningPodStatus.Cloning;
UpdateAppearance();
}
}
}
}

View File

@@ -1,9 +1,14 @@
#nullable enable
using System;
using System.Collections.Generic;
using System.Linq;
using Content.Server.GameObjects.Components.Body;
using Content.Server.GameObjects.Components.Mobs;
using Content.Server.GameObjects.Components.Power.ApcNetComponents;
using Content.Server.GameObjects.EntitySystems;
using Content.Server.Players;
using Content.Server.Utility;
using Content.Shared.Damage;
using Content.Shared.GameObjects.Components.Damage;
using Content.Shared.GameObjects.Components.Medical;
using Content.Shared.GameObjects.EntitySystems;
@@ -13,21 +18,24 @@ using Robust.Server.GameObjects;
using Robust.Server.GameObjects.Components.Container;
using Robust.Server.GameObjects.Components.UserInterface;
using Robust.Server.Interfaces.GameObjects;
using Robust.Server.Interfaces.Player;
using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Maths;
using Content.Shared.Damage;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Robust.Shared.Maths;
using Robust.Shared.ViewVariables;
namespace Content.Server.GameObjects.Components.Medical
{
[RegisterComponent]
[ComponentReference(typeof(IActivate))]
public class MedicalScannerComponent : SharedMedicalScannerComponent, IActivate
public class MedicalScannerComponent : SharedMedicalScannerComponent, IActivate, IDragDropOn
{
private ContainerSlot _bodyContainer = default!;
private readonly Vector2 _ejectOffset = new Vector2(-0.5f, 0f);
[Dependency] private readonly IPlayerManager _playerManager = null!;
public bool IsOccupied => _bodyContainer.ContainedEntity != null;
[ViewVariables]
@@ -68,13 +76,12 @@ namespace Content.Server.GameObjects.Components.Medical
if (Owner.TryGetComponent(out AppearanceComponent? appearance))
{
appearance?.SetData(MedicalScannerVisuals.Status, MedicalScannerStatus.Open);
};
}
return EmptyUIState;
}
if (!body.TryGetComponent(out IDamageableComponent? damageable) ||
damageable.CurrentDamageState == DamageState.Dead)
if (!body.TryGetComponent(out IDamageableComponent? damageable))
{
return EmptyUIState;
}
@@ -82,7 +89,14 @@ namespace Content.Server.GameObjects.Components.Medical
var classes = new Dictionary<DamageClass, int>(damageable.DamageClasses);
var types = new Dictionary<DamageType, int>(damageable.DamageTypes);
return new MedicalScannerBoundUserInterfaceState(body.Uid, classes, types, CloningSystem.HasUid(body.Uid));
if (_bodyContainer.ContainedEntity?.Uid == null)
{
return new MedicalScannerBoundUserInterfaceState(body.Uid, classes, types, true);
}
return new MedicalScannerBoundUserInterfaceState(body.Uid, classes, types,
CloningSystem.HasDnaScan(_bodyContainer.ContainedEntity.GetComponent<MindComponent>().Mind));
}
private void UpdateUserInterface()
@@ -207,22 +221,41 @@ namespace Content.Server.GameObjects.Components.Medical
private void OnUiReceiveMessage(ServerBoundUserInterfaceMessage obj)
{
if (!(obj.Message is UiButtonPressedMessage message))
{
return;
}
if (!(obj.Message is UiButtonPressedMessage message)) return;
switch (message.Button)
{
case UiButton.ScanDNA:
if (_bodyContainer.ContainedEntity != null)
{
CloningSystem.AddToScannedUids(_bodyContainer.ContainedEntity.Uid);
//TODO: Show a 'ERROR: Body is completely devoid of soul' if no Mind owns the entity.
CloningSystem.AddToDnaScans(_playerManager
.GetPlayersBy(playerSession =>
{
var mindOwnedMob = playerSession.ContentData()?.Mind?.OwnedEntity;
return mindOwnedMob != null && mindOwnedMob ==
_bodyContainer.ContainedEntity;
}).Single()
.ContentData()
?.Mind);
}
break;
default:
throw new ArgumentOutOfRangeException();
}
}
public bool CanDragDropOn(DragDropEventArgs eventArgs)
{
return eventArgs.Dropped.HasComponent<BodyManagerComponent>();
}
public bool DragDropOn(DragDropEventArgs eventArgs)
{
_bodyContainer.Insert(eventArgs.Dropped);
return true;
}
}
}

View File

@@ -1,9 +1,16 @@
#nullable enable
using System;
using Content.Server.GameObjects.Components.Body;
using Content.Server.GameObjects.Components.Medical;
using Content.Server.GameObjects.Components.Observer;
using Content.Server.Interfaces.GameTicking;
using Content.Server.Mobs;
using Content.Server.Utility;
using Content.Shared.GameObjects.Components;
using Content.Shared.GameObjects.Components.Damage;
using Content.Shared.GameObjects.Components.Mobs;
using Content.Shared.GameObjects.EntitySystems;
using Robust.Server.GameObjects.Components.UserInterface;
using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.Map;
@@ -14,6 +21,7 @@ using Robust.Shared.Serialization;
using Robust.Shared.Timers;
using Robust.Shared.Utility;
using Robust.Shared.ViewVariables;
using Serilog.Debugging;
namespace Content.Server.GameObjects.Components.Mobs
{
@@ -50,6 +58,45 @@ namespace Content.Server.GameObjects.Components.Mobs
set => _showExamineInfo = value;
}
[ViewVariables]
private BoundUserInterface? UserInterface =>
Owner.GetUIOrNull(SharedAcceptCloningComponent.AcceptCloningUiKey.Key);
public override void Initialize()
{
base.Initialize();
Owner.EntityManager.EventBus.SubscribeEvent<CloningPodComponent.CloningStartedMessage>(
EventSource.Local, this,
HandleCloningStartedMessage);
if (UserInterface != null)
{
UserInterface.OnReceiveMessage += OnUiAcceptCloningMessage;
}
}
private void HandleCloningStartedMessage(CloningPodComponent.CloningStartedMessage ev)
{
if (ev.CapturedMind == Mind)
{
UserInterface?.Open(Mind.Session);
}
}
private void OnUiAcceptCloningMessage(ServerBoundUserInterfaceMessage obj)
{
if (!(obj.Message is SharedAcceptCloningComponent.UiButtonPressedMessage message)) return;
Owner.EntityManager.EventBus.RaiseEvent(EventSource.Local, new GhostComponent.GhostReturnMessage(Mind));
}
public override void OnRemove()
{
base.OnRemove();
Owner.EntityManager.EventBus.UnsubscribeEvent<CloningPodComponent.CloningStartedMessage>(EventSource.Local, this);
if (UserInterface != null) UserInterface.OnReceiveMessage -= OnUiAcceptCloningMessage;
}
/// <summary>
/// Don't call this unless you know what the hell you're doing.
/// Use <see cref="Mind.TransferTo(IEntity)"/> instead.
@@ -133,13 +180,19 @@ namespace Content.Server.GameObjects.Components.Mobs
if (!HasMind)
{
message.AddMarkup(!dead
? $"[color=red]" + Loc.GetString("{0:They} {0:are} totally catatonic. The stresses of life in deep-space must have been too much for {0:them}. Any recovery is unlikely.", Owner) + "[/color]"
? $"[color=red]" +
Loc.GetString(
"{0:They} {0:are} totally catatonic. The stresses of life in deep-space must have been too much for {0:them}. Any recovery is unlikely.",
Owner) + "[/color]"
: $"[color=purple]" + Loc.GetString("{0:Their} soul has departed.", Owner) + "[/color]");
}
else if (Mind?.Session == null)
{
if(!dead)
message.AddMarkup("[color=yellow]" + Loc.GetString("{0:They} {0:have} a blank, absent-minded stare and appears completely unresponsive to anything. {0:They} may snap out of it soon.", Owner) + "[/color]");
if (!dead)
message.AddMarkup("[color=yellow]" +
Loc.GetString(
"{0:They} {0:have} a blank, absent-minded stare and appears completely unresponsive to anything. {0:They} may snap out of it soon.",
Owner) + "[/color]");
}
}
}

View File

@@ -115,7 +115,7 @@ namespace Content.Server.GameObjects.Components.Mobs
hands.StopPull();
break;
default:
player.PopupMessage(player, msg.Effect.ToString());
player.PopupMessage(msg.Effect.ToString());
break;
}

View File

@@ -9,12 +9,14 @@ namespace Content.Server.GameObjects.Components.Mobs.Speech
[RegisterComponent]
public class OwOAccentComponent : Component, IAccentComponent
{
[Dependency] private readonly IRobustRandom _random;
public override string Name => "OwOAccent";
private static readonly IReadOnlyList<string> Faces = new List<string>{
" (・`ω´・)", " ;;w;;", " owo", " UwU", " >w<", " ^w^"
}.AsReadOnly();
private string RandomFace => IoCManager.Resolve<IRobustRandom>().Pick(Faces);
private string RandomFace => _random.Pick(Faces);
private static readonly Dictionary<string, string> SpecialWords = new Dictionary<string, string>
{
@@ -23,7 +25,7 @@ namespace Content.Server.GameObjects.Components.Mobs.Speech
public string Accentuate(string message)
{
foreach ((var word,var repl) in SpecialWords)
foreach (var (word, repl) in SpecialWords)
{
message = message.Replace(word, repl);
}

View File

@@ -19,6 +19,9 @@ namespace Content.Server.GameObjects.Components.Movement
[RegisterComponent, ComponentReference(typeof(IMoverComponent))]
public class AiControllerComponent : Component, IMoverComponent
{
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly IGameTicker _gameTicker = default!;
private string? _logicName;
private float _visionRadius;
@@ -36,7 +39,7 @@ namespace Content.Server.GameObjects.Components.Movement
}
public AiLogicProcessor? Processor { get; set; }
[ViewVariables(VVAccess.ReadWrite)]
public string? StartingGearPrototype { get; set; }
@@ -61,13 +64,13 @@ namespace Content.Server.GameObjects.Components.Movement
protected override void Startup()
{
base.Startup();
if (StartingGearPrototype != null)
{
var startingGear = IoCManager.Resolve<IPrototypeManager>().Index<StartingGearPrototype>(StartingGearPrototype);
IoCManager.Resolve<IGameTicker>().EquipStartingGear(Owner, startingGear);
var startingGear = _prototypeManager.Index<StartingGearPrototype>(StartingGearPrototype);
_gameTicker.EquipStartingGear(Owner, startingGear);
}
}
/// <inheritdoc />
@@ -77,7 +80,7 @@ namespace Content.Server.GameObjects.Components.Movement
serializer.DataField(ref _logicName, "logic", null);
serializer.DataReadWriteFunction(
"startingGear",
"startingGear",
null,
startingGear => StartingGearPrototype = startingGear,
() => StartingGearPrototype);

View File

@@ -73,7 +73,7 @@ namespace Content.Server.GameObjects.Components.Movement
canVault = CanVault(eventArgs.User, eventArgs.Dropped, eventArgs.Target, out reason);
if (!canVault)
eventArgs.User.PopupMessage(eventArgs.User, reason);
eventArgs.User.PopupMessage(reason);
return canVault;
}

View File

@@ -130,13 +130,13 @@ namespace Content.Server.GameObjects.Components.Nutrition
if (!Opened)
{
target.PopupMessage(target, Loc.GetString("Open it first!"));
target.PopupMessage(Loc.GetString("Open it first!"));
return false;
}
if (_contents.CurrentVolume.Float() <= 0)
{
target.PopupMessage(target, Loc.GetString("It's empty!"));
target.PopupMessage(Loc.GetString("It's empty!"));
return false;
}
@@ -151,14 +151,14 @@ namespace Content.Server.GameObjects.Components.Nutrition
{
if (_useSound == null) return false;
EntitySystem.Get<AudioSystem>().PlayFromEntity(_useSound, target, AudioParams.Default.WithVolume(-2f));
target.PopupMessage(target, Loc.GetString("Slurp"));
target.PopupMessage(Loc.GetString("Slurp"));
UpdateAppearance();
return true;
}
//Stomach was full or can't handle whatever solution we have.
_contents.TryAddSolution(split);
target.PopupMessage(target, Loc.GetString("You've had enough {0}!", Owner.Name));
target.PopupMessage(Loc.GetString("You've had enough {0}!", Owner.Name));
return false;
}
@@ -172,7 +172,7 @@ namespace Content.Server.GameObjects.Components.Nutrition
Opened = true;
var solution = component.SplitSolution(component.CurrentVolume);
SpillHelper.SpillAt(Owner, solution, "PuddleSmear");
solution.SpillAt(Owner, "PuddleSmear");
EntitySystem.Get<AudioSystem>().PlayFromEntity(_burstSound, Owner,
AudioParams.Default.WithVolume(-4));

View File

@@ -90,7 +90,7 @@ namespace Content.Server.GameObjects.Components.Nutrition
{
if (_utensilsNeeded != UtensilType.None)
{
eventArgs.User.PopupMessage(eventArgs.User, Loc.GetString("You need to use a {0} to eat that!", _utensilsNeeded));
eventArgs.User.PopupMessage(Loc.GetString("You need to use a {0} to eat that!", _utensilsNeeded));
return false;
}
@@ -122,7 +122,7 @@ namespace Content.Server.GameObjects.Components.Nutrition
if (UsesRemaining <= 0)
{
user.PopupMessage(user, Loc.GetString("{0:TheName} is empty!", Owner));
user.PopupMessage(Loc.GetString("{0:TheName} is empty!", Owner));
return false;
}

View File

@@ -6,7 +6,6 @@ using Content.Shared.GameObjects.Components.Damage;
using Content.Shared.GameObjects.Components.Mobs;
using Content.Shared.GameObjects.Components.Movement;
using Content.Shared.GameObjects.Components.Nutrition;
using JetBrains.Annotations;
using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.Random;
using Robust.Shared.IoC;
@@ -19,6 +18,8 @@ namespace Content.Server.GameObjects.Components.Nutrition
[RegisterComponent]
public sealed class HungerComponent : SharedHungerComponent
{
[Dependency] private readonly IRobustRandom _random = default!;
// Base stuff
[ViewVariables(VVAccess.ReadWrite)]
public float BaseDecayRate
@@ -141,7 +142,7 @@ namespace Content.Server.GameObjects.Components.Nutrition
{
base.Startup();
// Similar functionality to SS13. Should also stagger people going to the chef.
_currentHunger = IoCManager.Resolve<IRobustRandom>().Next(
_currentHunger = _random.Next(
(int)_hungerThresholds[HungerThreshold.Peckish] + 10,
(int)_hungerThresholds[HungerThreshold.Okay] - 1);
_currentHungerThreshold = GetHungerThreshold(_currentHunger);

View File

@@ -6,7 +6,6 @@ using Content.Shared.GameObjects.Components.Damage;
using Content.Shared.GameObjects.Components.Mobs;
using Content.Shared.GameObjects.Components.Movement;
using Content.Shared.GameObjects.Components.Nutrition;
using JetBrains.Annotations;
using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.Random;
using Robust.Shared.IoC;
@@ -19,6 +18,8 @@ namespace Content.Server.GameObjects.Components.Nutrition
[RegisterComponent]
public sealed class ThirstComponent : SharedThirstComponent
{
[Dependency] private readonly IRobustRandom _random = default!;
// Base stuff
[ViewVariables(VVAccess.ReadWrite)]
public float BaseDecayRate
@@ -136,7 +137,7 @@ namespace Content.Server.GameObjects.Components.Nutrition
protected override void Startup()
{
base.Startup();
_currentThirst = IoCManager.Resolve<IRobustRandom>().Next(
_currentThirst = _random.Next(
(int)ThirstThresholds[ThirstThreshold.Thirsty] + 10,
(int)ThirstThresholds[ThirstThreshold.Okay] - 1);
_currentThirstThreshold = GetThirstThreshold(_currentThirst);

View File

@@ -1,4 +1,6 @@
using Content.Server.Players;
using Content.Server.GameObjects.Components.Mobs;
using Content.Server.Mobs;
using Content.Server.Players;
using Content.Shared.GameObjects.Components.Observer;
using Robust.Server.GameObjects;
using Robust.Server.GameObjects.Components;
@@ -31,7 +33,7 @@ namespace Content.Server.GameObjects.Components.Observer
{
base.Initialize();
Owner.EnsureComponent<VisibilityComponent>().Layer = (int)VisibilityFlags.Ghost;
Owner.EnsureComponent<VisibilityComponent>().Layer = (int) VisibilityFlags.Ghost;
}
public override ComponentState GetComponentState() => new GhostComponentState(CanReturnToBody);
@@ -43,18 +45,19 @@ namespace Content.Server.GameObjects.Components.Observer
switch (message)
{
case PlayerAttachedMsg msg:
msg.NewPlayer.VisibilityMask |= (int)VisibilityFlags.Ghost;
msg.NewPlayer.VisibilityMask |= (int) VisibilityFlags.Ghost;
Dirty();
break;
case PlayerDetachedMsg msg:
msg.OldPlayer.VisibilityMask &= ~(int)VisibilityFlags.Ghost;
msg.OldPlayer.VisibilityMask &= ~(int) VisibilityFlags.Ghost;
break;
default:
break;
}
}
public override void HandleNetworkMessage(ComponentMessage message, INetChannel netChannel, ICommonSession session = null)
public override void HandleNetworkMessage(ComponentMessage message, INetChannel netChannel,
ICommonSession session = null)
{
base.HandleNetworkMessage(message, netChannel, session);
@@ -67,10 +70,29 @@ namespace Content.Server.GameObjects.Components.Observer
actor.playerSession.ContentData().Mind.UnVisit();
Owner.Delete();
}
break;
case ReturnToCloneComponentMessage reenter:
if (Owner.TryGetComponent(out VisitingMindComponent mind))
{
Owner.EntityManager.EventBus.RaiseEvent(EventSource.Local, new GhostReturnMessage(mind.Mind));
}
break;
default:
break;
}
}
public class GhostReturnMessage : EntitySystemMessage
{
public GhostReturnMessage(Mind sender)
{
Sender = sender;
}
public Mind Sender { get; }
}
}
}

View File

@@ -5,7 +5,6 @@ using Content.Server.GameObjects.Components.NodeContainer;
using Content.Server.GameObjects.Components.NodeContainer.NodeGroups;
using Content.Server.GameObjects.Components.Power.ApcNetComponents;
using Content.Server.GameObjects.Components.Power.PowerNetComponents;
using Content.Server.Interfaces;
using Content.Server.Interfaces.GameObjects.Components.Items;
using Content.Server.Utility;
using Content.Shared.GameObjects.Components.Power.AME;
@@ -20,11 +19,11 @@ using Robust.Shared.Audio;
using Robust.Shared.GameObjects;
using Robust.Shared.GameObjects.Systems;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Robust.Shared.ViewVariables;
using System.Linq;
using System.Threading.Tasks;
using Content.Shared.Interfaces;
namespace Content.Server.GameObjects.Components.Power.AME
{
@@ -33,8 +32,6 @@ namespace Content.Server.GameObjects.Components.Power.AME
[ComponentReference(typeof(IInteractUsing))]
public class AMEControllerComponent : SharedAMEControllerComponent, IActivate, IInteractUsing
{
[Dependency] private readonly IServerNotifyManager _notifyManager = default!;
[ViewVariables] private BoundUserInterface? UserInterface => Owner.GetUIOrNull(AMEControllerUiKey.Key);
[ViewVariables] private bool _injecting;
[ViewVariables] public int InjectionAmount;
@@ -117,8 +114,7 @@ namespace Content.Server.GameObjects.Components.Power.AME
if (!args.User.TryGetComponent(out IHandsComponent? hands))
{
_notifyManager.PopupMessage(Owner.Transform.GridPosition, args.User,
Loc.GetString("You have no hands."));
Owner.PopupMessage(args.User, Loc.GetString("You have no hands."));
return;
}
@@ -328,15 +324,13 @@ namespace Content.Server.GameObjects.Components.Power.AME
{
if (!args.User.TryGetComponent(out IHandsComponent? hands))
{
_notifyManager.PopupMessage(Owner.Transform.GridPosition, args.User,
Loc.GetString("You have no hands."));
Owner.PopupMessage(args.User, Loc.GetString("You have no hands."));
return true;
}
if (hands.GetActiveHand == null)
{
_notifyManager.PopupMessage(Owner.Transform.GridPosition, args.User,
Loc.GetString("You have nothing on your hand."));
Owner.PopupMessage(args.User, Loc.GetString("You have nothing on your hand."));
return false;
}
@@ -345,22 +339,19 @@ namespace Content.Server.GameObjects.Components.Power.AME
{
if (HasJar)
{
_notifyManager.PopupMessage(Owner.Transform.GridPosition, args.User,
Loc.GetString("The controller already has a jar loaded."));
Owner.PopupMessage(args.User, Loc.GetString("The controller already has a jar loaded."));
}
else
{
_jarSlot.Insert(activeHandEntity);
_notifyManager.PopupMessage(Owner.Transform.GridPosition, args.User,
Loc.GetString("You insert the jar into the fuel slot."));
Owner.PopupMessage(args.User, Loc.GetString("You insert the jar into the fuel slot."));
UpdateUserInterface();
}
}
else
{
_notifyManager.PopupMessage(Owner.Transform.GridPosition, args.User,
Loc.GetString("You can't put that in the controller..."));
Owner.PopupMessage(args.User, Loc.GetString("You can't put that in the controller..."));
}
return true;

View File

@@ -1,5 +1,4 @@
using Content.Server.GameObjects.Components.Interactable;
using Content.Server.Interfaces;
using Content.Server.Interfaces.GameObjects.Components.Items;
using Content.Shared.GameObjects.Components.Interactable;
using Content.Shared.Interfaces.GameObjects.Components;
@@ -10,6 +9,7 @@ using Robust.Shared.Interfaces.Map;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
using System.Threading.Tasks;
using Content.Shared.Interfaces;
namespace Content.Server.GameObjects.Components.Power.AME
{
@@ -19,15 +19,14 @@ namespace Content.Server.GameObjects.Components.Power.AME
{
[Dependency] private readonly IMapManager _mapManager = default!;
[Dependency] private readonly IServerEntityManager _serverEntityManager = default!;
[Dependency] private readonly IServerNotifyManager _notifyManager = default!;
public override string Name => "AMEPart";
async Task<bool> IInteractUsing.InteractUsing(InteractUsingEventArgs args)
{
if (!args.User.TryGetComponent(out IHandsComponent hands))
{
_notifyManager.PopupMessage(Owner.Transform.GridPosition, args.User,
Loc.GetString("You have no hands."));
Owner.PopupMessage(args.User, Loc.GetString("You have no hands."));
return true;
}

View File

@@ -24,6 +24,9 @@ namespace Content.Server.GameObjects.Components.Power.ApcNetComponents
[RegisterComponent]
public class PowerProviderComponent : BaseApcNetComponent, IPowerProvider
{
[Dependency] private readonly IMapManager _mapManager = default!;
[Dependency] private readonly IServerEntityManager _serverEntityManager;
public override string Name => "PowerProvider";
/// <summary>
@@ -91,14 +94,13 @@ namespace Content.Server.GameObjects.Components.Power.ApcNetComponents
private List<PowerReceiverComponent> FindAvailableReceivers()
{
var mapManager = IoCManager.Resolve<IMapManager>();
var nearbyEntities = IoCManager.Resolve<IServerEntityManager>()
var nearbyEntities = _serverEntityManager
.GetEntitiesInRange(Owner, PowerTransferRange);
return nearbyEntities.Select(entity => entity.TryGetComponent<PowerReceiverComponent>(out var receiver) ? receiver : null)
.Where(receiver => receiver != null)
.Where(receiver => receiver.Connectable)
.Where(receiver => receiver.NeedsProvider)
.Where(receiver => receiver.Owner.Transform.GridPosition.Distance(mapManager, Owner.Transform.GridPosition) < Math.Min(PowerTransferRange, receiver.PowerReceptionRange))
.Where(receiver => receiver.Owner.Transform.GridPosition.Distance(_mapManager, Owner.Transform.GridPosition) < Math.Min(PowerTransferRange, receiver.PowerReceptionRange))
.ToList();
}

View File

@@ -21,6 +21,9 @@ namespace Content.Server.GameObjects.Components.Power.ApcNetComponents
[RegisterComponent]
public class PowerReceiverComponent : Component, IExamine
{
[Dependency] private readonly IServerEntityManager _serverEntityManager = default!;
[Dependency] private readonly IMapManager _mapManager = default!;
public override string Name => "PowerReceiver";
public event EventHandler<PowerStateEventArgs> OnPowerStateChanged;
@@ -116,16 +119,16 @@ namespace Content.Server.GameObjects.Components.Power.ApcNetComponents
private bool TryFindAvailableProvider(out IPowerProvider foundProvider)
{
var nearbyEntities = IoCManager.Resolve<IServerEntityManager>()
var nearbyEntities = _serverEntityManager
.GetEntitiesInRange(Owner, PowerReceptionRange);
var mapManager = IoCManager.Resolve<IMapManager>();
foreach (var entity in nearbyEntities)
{
if (entity.TryGetComponent<PowerProviderComponent>(out var provider))
{
if (provider.Connectable)
{
var distanceToProvider = provider.Owner.Transform.GridPosition.Distance(mapManager, Owner.Transform.GridPosition);
var distanceToProvider = provider.Owner.Transform.GridPosition.Distance(_mapManager, Owner.Transform.GridPosition);
if (distanceToProvider < Math.Min(PowerReceptionRange, provider.PowerTransferRange))
{
foundProvider = provider;

View File

@@ -4,7 +4,6 @@ using Content.Server.GameObjects.Components.GUI;
using Content.Server.GameObjects.Components.Items.Storage;
using Content.Server.GameObjects.Components.Mobs;
using Content.Server.GameObjects.EntitySystems;
using Content.Server.Interfaces;
using Content.Shared.GameObjects.Components.Damage;
using Content.Shared.Damage;
using Content.Shared.Interfaces.GameObjects.Components;
@@ -32,6 +31,8 @@ namespace Content.Server.GameObjects.Components.Power.ApcNetComponents.PowerRece
[RegisterComponent]
public class PoweredLightComponent : Component, IInteractHand, IInteractUsing, IMapInit, ISignalReceiver
{
[Dependency] private IGameTiming _gameTiming = default!;
public override string Name => "PoweredLight";
private static readonly TimeSpan _thunkDelay = TimeSpan.FromSeconds(2);
@@ -41,6 +42,7 @@ namespace Content.Server.GameObjects.Components.Power.ApcNetComponents.PowerRece
private LightBulbType BulbType = LightBulbType.Tube;
[ViewVariables] private ContainerSlot _lightBulbContainer;
[ViewVariables]
private LightBulbComponent LightBulb
{
@@ -63,8 +65,7 @@ namespace Content.Server.GameObjects.Components.Power.ApcNetComponents.PowerRece
case BeginDeconstructCompMsg msg:
if (!msg.BlockDeconstruct && !(_lightBulbContainer.ContainedEntity is null))
{
var notifyManager = IoCManager.Resolve<IServerNotifyManager>();
notifyManager.PopupMessage(Owner, msg.User, "Remove the bulb.");
Owner.PopupMessage(msg.User, Loc.GetString("Remove the bulb."));
msg.BlockDeconstruct = true;
}
break;
@@ -211,7 +212,7 @@ namespace Content.Server.GameObjects.Components.Power.ApcNetComponents.PowerRece
sprite.LayerSetState(0, "on");
light.Enabled = true;
light.Color = LightBulb.Color;
var time = IoCManager.Resolve<IGameTiming>().CurTime;
var time = _gameTiming.CurTime;
if (time > _lastThunk + _thunkDelay)
{
_lastThunk = time;

View File

@@ -22,6 +22,8 @@ namespace Content.Server.GameObjects.Components.Projectiles
[RegisterComponent]
public class HitscanComponent : Component
{
[Dependency] private readonly IGameTiming _gameTiming = default!;
public override string Name => "Hitscan";
public CollisionGroup CollisionMask => (CollisionGroup) _collisionMask;
private int _collisionMask;
@@ -60,7 +62,7 @@ namespace Content.Server.GameObjects.Components.Projectiles
public void FireEffects(IEntity user, float distance, Angle angle, IEntity hitEntity = null)
{
var effectSystem = EntitySystem.Get<EffectSystem>();
_startTime = IoCManager.Resolve<IGameTiming>().CurTime;
_startTime = _gameTiming.CurTime;
_deathTime = _startTime + TimeSpan.FromSeconds(1);
var afterEffect = AfterEffects(user.Transform.GridPosition, angle, distance, 1.0f);

View File

@@ -1,6 +1,7 @@
using Content.Server.GameObjects.EntitySystems;
using Content.Server.Interfaces;
using Content.Server.Interfaces.Chat;
using Content.Shared.Interfaces;
using Content.Shared.Interfaces.GameObjects.Components;
using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.GameObjects;
@@ -13,7 +14,7 @@ namespace Content.Server.GameObjects.Components
class RadioComponent : Component, IUse, IListen
{
[Dependency] private readonly IEntitySystemManager _entitySystemManager = default!;
[Dependency] private readonly IServerNotifyManager _notifyManager = default!;
[Dependency] private readonly IChatManager _chatManager = default!;
public override string Name => "Radio";
@@ -51,8 +52,7 @@ namespace Content.Server.GameObjects.Components
public void Speaker(string message)
{
var chat = IoCManager.Resolve<IChatManager>();
chat.EntitySay(Owner, message);
_chatManager.EntitySay(Owner, message);
}
public bool UseEntity(UseEntityEventArgs eventArgs)
@@ -60,11 +60,11 @@ namespace Content.Server.GameObjects.Components
RadioOn = !RadioOn;
if(RadioOn)
{
_notifyManager.PopupMessage(Owner, eventArgs.User, "The radio is now on.");
Owner.PopupMessage(eventArgs.User, "The radio is now on.");
}
else
{
_notifyManager.PopupMessage(Owner, eventArgs.User, "The radio is now off.");
Owner.PopupMessage(eventArgs.User, "The radio is now off.");
}
return true;
}

View File

@@ -10,6 +10,8 @@ namespace Content.Server.GameObjects.Components.Research
[ComponentReference(typeof(SharedLatheDatabaseComponent))]
public class ProtolatheDatabaseComponent : SharedProtolatheDatabaseComponent
{
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
public override string Name => "ProtolatheDatabase";
public override ComponentState GetComponentState()
@@ -24,13 +26,11 @@ namespace Content.Server.GameObjects.Components.Research
{
if (!Owner.TryGetComponent(out TechnologyDatabaseComponent database)) return;
var prototypeManager = IoCManager.Resolve<IPrototypeManager>();
foreach (var technology in database.Technologies)
{
foreach (var id in technology.UnlockedRecipes)
{
var recipe = (LatheRecipePrototype)prototypeManager.Index(typeof(LatheRecipePrototype), id);
var recipe = (LatheRecipePrototype) _prototypeManager.Index(typeof(LatheRecipePrototype), id);
UnlockRecipe(recipe);
}
}

View File

@@ -57,8 +57,7 @@ namespace Content.Server.GameObjects.Components.Research
switch (message.Message)
{
case ConsoleUnlockTechnologyMessage msg:
var protoMan = IoCManager.Resolve<IPrototypeManager>();
if (!protoMan.TryIndex(msg.Id, out TechnologyPrototype tech)) break;
if (!_prototypeManager.TryIndex(msg.Id, out TechnologyPrototype tech)) break;
if (client.Server == null) break;
if (!client.Server.CanUnlockTechnology(tech)) break;
if (client.Server.UnlockTechnology(tech))

View File

@@ -1,11 +1,10 @@
#nullable enable
using Content.Server.Interfaces;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.Verbs;
using Content.Shared.Interfaces;
using Robust.Shared.GameObjects;
using Robust.Shared.GameObjects.Components;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Robust.Shared.Serialization;
@@ -14,8 +13,6 @@ namespace Content.Server.GameObjects.Components.Rotatable
[RegisterComponent]
public class FlippableComponent : Component
{
[Dependency] private readonly IServerNotifyManager _notifyManager = default!;
public override string Name => "Flippable";
private string? _entity;
@@ -25,7 +22,7 @@ namespace Content.Server.GameObjects.Components.Rotatable
if (Owner.TryGetComponent(out ICollidableComponent? collidable) &&
collidable.Anchored)
{
_notifyManager.PopupMessage(Owner.Transform.GridPosition, user, Loc.GetString("It's stuck."));
Owner.PopupMessage(user, Loc.GetString("It's stuck."));
return;
}

View File

@@ -1,10 +1,9 @@
using Content.Server.Interfaces;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.Verbs;
using Content.Shared.Interfaces;
using Robust.Shared.GameObjects;
using Robust.Shared.GameObjects.Components;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Robust.Shared.Maths;
@@ -13,8 +12,6 @@ namespace Content.Server.GameObjects.Components.Rotatable
[RegisterComponent]
public class RotatableComponent : Component
{
[Dependency] private readonly IServerNotifyManager _notifyManager = default!;
public override string Name => "Rotatable";
private void TryRotate(IEntity user, Angle angle)
@@ -23,7 +20,7 @@ namespace Content.Server.GameObjects.Components.Rotatable
{
if (collidable.Anchored)
{
_notifyManager.PopupMessage(Owner.Transform.GridPosition, user, Loc.GetString("It's stuck."));
Owner.PopupMessage(user, Loc.GetString("It's stuck."));
return;
}
}

View File

@@ -5,7 +5,6 @@ using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.Interfaces;
using Content.Shared.Interfaces.GameObjects.Components;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Robust.Shared.Map;
using Robust.Shared.Timers;
@@ -19,8 +18,6 @@ namespace Content.Server.GameObjects.Components.Stack
[RegisterComponent]
public class StackComponent : SharedStackComponent, IInteractUsing, IExamine
{
[Dependency] private readonly ISharedNotifyManager _sharedNotifyManager = default!;
private bool _throwIndividually = false;
public override int Count
@@ -82,20 +79,19 @@ namespace Content.Server.GameObjects.Components.Stack
if (toTransfer > 0)
{
_sharedNotifyManager.PopupMessage(popupPos, eventArgs.User, $"+{toTransfer}");
popupPos.PopupMessage(eventArgs.User, $"+{toTransfer}");
if (stack.AvailableSpace == 0)
{
Timer.Spawn(300, () => _sharedNotifyManager.PopupMessage(popupPos, eventArgs.User, "Stack is now full."));
Timer.Spawn(300, () => popupPos.PopupMessage(eventArgs.User, "Stack is now full."));
}
return true;
}
else if (toTransfer == 0 && stack.AvailableSpace == 0)
{
_sharedNotifyManager.PopupMessage(popupPos, eventArgs.User, "Stack is already full.");
popupPos.PopupMessage(eventArgs.User, "Stack is already full.");
}
}
return false;

View File

@@ -15,12 +15,15 @@ namespace Content.Server.GameObjects.Components.StationEvents
[RegisterComponent]
public sealed class RadiationPulseComponent : SharedRadiationPulseComponent
{
[Dependency] private readonly IGameTiming _gameTiming = default!;
[Dependency] private readonly IRobustRandom _random = default!;
private const float MinPulseLifespan = 0.8f;
private const float MaxPulseLifespan = 2.5f;
public float DPS => _dps;
private float _dps;
private TimeSpan _endTime;
public override void ExposeData(ObjectSerializer serializer)
@@ -33,15 +36,15 @@ namespace Content.Server.GameObjects.Components.StationEvents
{
base.Initialize();
var currentTime = IoCManager.Resolve<IGameTiming>().CurTime;
var currentTime = _gameTiming.CurTime;
var duration =
TimeSpan.FromSeconds(
IoCManager.Resolve<IRobustRandom>().NextFloat() * (MaxPulseLifespan - MinPulseLifespan) +
_random.NextFloat() * (MaxPulseLifespan - MinPulseLifespan) +
MinPulseLifespan);
_endTime = currentTime + duration;
Timer.Spawn(duration,
Timer.Spawn(duration,
() =>
{
if (!Owner.Deleted)
@@ -59,4 +62,4 @@ namespace Content.Server.GameObjects.Components.StationEvents
return new RadiationPulseMessage(_endTime);
}
}
}
}

View File

@@ -7,7 +7,6 @@ using Content.Shared.Interfaces.GameObjects.Components;
using Content.Shared.Utility;
using Robust.Server.GameObjects;
using Robust.Shared.GameObjects;
using Robust.Shared.GameObjects.Systems;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Localization;
using Robust.Shared.Serialization;

View File

@@ -32,6 +32,7 @@ namespace Content.Server.GameObjects.Components.VendingMachines
public class VendingMachineComponent : SharedVendingMachineComponent, IActivate, IExamine, IBreakAct, IWires
{
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
private bool _ejecting;
private TimeSpan _animationDuration = TimeSpan.Zero;
@@ -77,8 +78,7 @@ namespace Content.Server.GameObjects.Components.VendingMachines
private void InitializeFromPrototype()
{
if (string.IsNullOrEmpty(_packPrototypeId)) { return; }
var prototypeManger = IoCManager.Resolve<IPrototypeManager>();
if (!prototypeManger.TryIndex(_packPrototypeId, out VendingMachineInventoryPrototype packPrototype))
if (!_prototypeManager.TryIndex(_packPrototypeId, out VendingMachineInventoryPrototype packPrototype))
{
return;
}

View File

@@ -12,13 +12,14 @@ namespace Content.Server.GameObjects.Components.Weapon
[RegisterComponent]
public sealed class FlashableComponent : SharedFlashableComponent
{
[Dependency] private readonly IGameTiming _gameTiming = default!;
private double _duration;
private TimeSpan _lastFlash;
public void Flash(double duration)
{
var timing = IoCManager.Resolve<IGameTiming>();
_lastFlash = timing.CurTime;
_lastFlash = _gameTiming.CurTime;
_duration = duration;
Dirty();
}

Some files were not shown because too many files have changed in this diff Show More