merge remote wizden/master

This commit is contained in:
Dmitry
2026-05-21 15:29:28 +07:00
233 changed files with 5391 additions and 3113 deletions
+6
View File
@@ -9,6 +9,11 @@
## Технические детали
<!-- Краткое описание изменений в коде для облегчения проверки. -->
## Test plan
<!--
Describe how you tested the pull request, and how someone reviewing this PR can test it themselves.
-->
## Медиа
<!-- Прикрепите медиафайлы, если PR вносит изменения в игру (одежда, предметы, механики и т.д.).
Небольшие исправления/рефакторинг освобождаются от этого требования. -->
@@ -16,6 +21,7 @@
## Требования
<!-- Подтвердите следующее, поставив X в скобках без пробелов [X]: -->
- [ ] Я прочитал(а) и следую [Рекомендациям по оформлению Pull Request и Changelog](https://docs.spacestation14.com/en/general-development/codebase-info/pull-request-guidelines.html).
- [ ] I have tested this pull request and written instructions on how to test it
- [ ] Я добавил(а) медиафайлы к этому PR или он не требует демонстрации в игре.
<!-- Вы должны понимать, что несоблюдение вышеуказанного может привести к закрытию вашего PR по усмотрению сопровождающего -->
+3
View File
@@ -317,3 +317,6 @@ Resources/MapImages
# Direnv stuff
.direnv/
# C# Dev Kit cache file
*.lscache
+1 -1
View File
@@ -262,7 +262,7 @@ namespace Content.Client.Actions
SetIcon(actionId, new SpriteSpecifier.EntityPrototype(id));
SetEvent(actionId, new StartPlacementActionEvent()
{
PlacementOption = "SnapgridCenter",
PlacementOption = proto.PlacementMode,
EntityType = id
});
_metaData.SetEntityName(actionId, proto.Name);
@@ -1,5 +1,5 @@
using Content.Shared.Cargo;
using Content.Client.Cargo.UI;
using Content.Shared.Cargo;
using Content.Shared.Cargo.BUI;
using Content.Shared.Cargo.Components;
using Content.Shared.Cargo.Events;
@@ -7,15 +7,15 @@ using Content.Shared.Cargo.Prototypes;
using Content.Shared.IdentityManagement;
using Robust.Client.GameObjects;
using Robust.Client.Player;
using Robust.Shared.Utility;
using Robust.Shared.Prototypes;
using static Robust.Client.UserInterface.Controls.BaseButton;
using Robust.Shared.Utility;
namespace Content.Client.Cargo.BUI
{
public sealed class CargoOrderConsoleBoundUserInterface : BoundUserInterface
public sealed partial class CargoOrderConsoleBoundUserInterface(EntityUid owner, Enum uiKey) : BoundUserInterface(owner, uiKey)
{
private readonly SharedCargoSystem _cargoSystem;
[Dependency] private SharedCargoSystem _cargoSystem = default!;
[Dependency] private IdentitySystem _identity = default!;
[ViewVariables]
private CargoConsoleMenu? _menu;
@@ -44,11 +44,6 @@ namespace Content.Client.Cargo.BUI
[ViewVariables]
private CargoProductPrototype? _product;
public CargoOrderConsoleBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey)
{
_cargoSystem = EntMan.System<SharedCargoSystem>();
}
protected override void Open()
{
base.Open();
@@ -59,12 +54,9 @@ namespace Content.Client.Cargo.BUI
var localPlayer = dependencies.Resolve<IPlayerManager>().LocalEntity;
var description = new FormattedMessage();
string orderRequester;
var orderRequester = Loc.GetString("cargo-console-paper-approver-default");
if (EntMan.EntityExists(localPlayer))
orderRequester = Identity.Name(localPlayer.Value, EntMan);
else
orderRequester = string.Empty;
orderRequester = _identity.GetIdentityShortInfo(localPlayer.Value, Owner) ?? orderRequester;
_orderMenu = new CargoConsoleOrderMenu();
@@ -142,6 +134,11 @@ namespace Content.Client.Cargo.BUI
return;
_menu.ProductCatalogue = cState.Products;
_menu.ShuttleCapacityLabel.Text = Loc.GetString(
"cargo-console-menu-order-capacity-number",
("count", OrderCount),
("capacity", OrderCapacity)
);
_menu?.UpdateStation(station);
Populate(cState.Orders);
@@ -52,7 +52,8 @@
<PanelContainer StyleClasses="LowDivider" Margin="0 -2 0 -1"/>
<Label Name="ShuttleCapacityLabel"
Text="0/20"
Text="0/0"
Access="Public"
Margin="4 0"/>
</GridContainer>
+3 -4
View File
@@ -1,6 +1,5 @@
<controls:FancyWindow xmlns="https://spacestation14.io"
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
xmlns:gfx="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client"
Resizable="False"
MaxSize="400 800"
MinSize="400 150">
@@ -10,7 +9,7 @@
<!-- Header text -->
<controls:StripeBack>
<PanelContainer>
<RichTextLabel Name="EmergencyBroadcastText" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="10 10 10 10" ReservesSpace="False"/>
<RichTextLabel Text="{Loc 'holopad-window-emergency-broadcast-in-progress'}" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="10 10 10 10" ReservesSpace="False"/>
</PanelContainer>
</controls:StripeBack>
@@ -52,8 +51,8 @@
<controls:StripeBack>
<PanelContainer>
<BoxContainer Orientation="Vertical">
<RichTextLabel Name="SubtitleText" HorizontalAlignment="Center" Margin="0 5 0 0"/>
<RichTextLabel Name="OptionsText" HorizontalAlignment="Center" Margin="0 0 0 5"/>
<RichTextLabel Text="{Loc 'holopad-window-subtitle'}" HorizontalAlignment="Center" Margin="0 5 0 0"/>
<RichTextLabel Text="{Loc 'holopad-window-options'}" HorizontalAlignment="Center" Margin="0 0 0 5"/>
</BoxContainer>
</PanelContainer>
</controls:StripeBack>
+75 -68
View File
@@ -10,7 +10,6 @@ using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Timing;
using Robust.Shared.Utility;
using System.Linq;
namespace Content.Client.Holopad;
@@ -19,22 +18,18 @@ public sealed partial class HolopadWindow : FancyWindow
{
[Dependency] private IEntityManager _entManager = default!;
[Dependency] private IPlayerManager _playerManager = default!;
[Dependency] private ILogManager _logManager = default!;
[Dependency] private IGameTiming _timing = default!;
private readonly SharedHolopadSystem _holopadSystem = default!;
private readonly SharedTelephoneSystem _telephoneSystem = default!;
private readonly AccessReaderSystem _accessReaderSystem = default!;
private readonly PopupSystem _popupSystem = default!;
private readonly ISawmill _sawmill = default!;
private EntityUid? _owner = null;
private HolopadUiKey _currentUiKey;
private TelephoneState _currentState;
private TelephoneState _previousState;
private TimeSpan _buttonUnlockTime;
private float _updateTimer = 0.25f;
private const float UpdateTime = 0.25f;
private TimeSpan _buttonUnlockDelay = TimeSpan.FromSeconds(0.5f);
private string _currentSearch = string.Empty;
public event Action<NetEntity>? SendHolopadStartNewCallMessageAction;
public event Action? SendHolopadAnswerCallMessageAction;
@@ -43,6 +38,9 @@ public sealed partial class HolopadWindow : FancyWindow
public event Action? SendHolopadActivateProjectorMessageAction;
public event Action? SendHolopadRequestStationAiMessageAction;
private TimeSpan _updateDelay = TimeSpan.FromSeconds(0.25f);
private TimeSpan _nextUpdate;
public HolopadWindow()
{
RobustXamlLoader.Load(this);
@@ -52,8 +50,7 @@ public sealed partial class HolopadWindow : FancyWindow
_telephoneSystem = _entManager.System<SharedTelephoneSystem>();
_accessReaderSystem = _entManager.System<AccessReaderSystem>();
_popupSystem = _entManager.System<PopupSystem>();
_buttonUnlockTime = _timing.CurTime + _buttonUnlockDelay;
_sawmill = _logManager.GetSawmill("Holopad");
// Assign button actions
AnswerCallButton.OnPressed += args => { OnHolopadAnswerCallMessage(); };
@@ -78,10 +75,6 @@ public sealed partial class HolopadWindow : FancyWindow
{
BackgroundColor = new Color(82, 82, 82),
};
EmergencyBroadcastText.SetMessage(FormattedMessage.FromMarkupOrThrow(Loc.GetString("holopad-window-emergency-broadcast-in-progress")));
SubtitleText.SetMessage(FormattedMessage.FromMarkupOrThrow(Loc.GetString("holopad-window-subtitle")));
OptionsText.SetMessage(FormattedMessage.FromMarkupOrThrow(Loc.GetString("holopad-window-options")));
}
#region: Button actions
@@ -166,16 +159,28 @@ public sealed partial class HolopadWindow : FancyWindow
public void UpdateState(Dictionary<NetEntity, string> holopads)
{
if (_owner == null || !_entManager.TryGetComponent<TelephoneComponent>(_owner.Value, out var telephone))
if (!_entManager.TryGetComponent<TelephoneComponent>(_owner, out var telephone))
return;
// Caller ID text
var callerId = _telephoneSystem.GetFormattedCallerIdForEntity(telephone.LastCallerId.Item1, telephone.LastCallerId.Item2, Color.LightGray, "Default", 11);
var holoapdId = _telephoneSystem.GetFormattedDeviceIdForEntity(telephone.LastCallerId.Item3, Color.LightGray, "Default", 11);
// Caller and holopad ID text
var callerId = _telephoneSystem.GetFormattedCallerIdForEntity(telephone.LastCallerId?.CallerId, telephone.LastCallerId?.CallerJob, Color.LightGray, "Default", 11);
var holopadId = _telephoneSystem.GetFormattedDeviceIdForEntity(telephone.LastCallerId?.DeviceId, Color.LightGray, "Default", 11);
CallerIdText.SetMessage(FormattedMessage.FromMarkupPermissive(callerId));
HolopadIdText.SetMessage(FormattedMessage.FromMarkupPermissive(holoapdId));
LockOutIdText.SetMessage(FormattedMessage.FromMarkupPermissive(callerId));
if (!FormattedMessage.TryFromMarkup(callerId, out var callerIdMsg))
{
callerIdMsg = FormattedMessage.FromMarkupPermissive(callerId);
_sawmill.Error($"CallerId markup text was incorrectly formatted: {callerIdMsg}");
}
if (!FormattedMessage.TryFromMarkup(holopadId, out var holopadIdMsg))
{
holopadIdMsg = FormattedMessage.FromMarkupPermissive(holopadId);
_sawmill.Error($"HolopadId markup text was incorrectly formatted: {holopadIdMsg}");
}
CallerIdText.SetMessage(callerIdMsg);
LockOutIdText.SetMessage(callerIdMsg);
HolopadIdText.SetMessage(holopadIdMsg);
// Sort holopads alphabetically
var holopadArray = holopads.ToArray();
@@ -183,7 +188,9 @@ public sealed partial class HolopadWindow : FancyWindow
// Clear excess children from the contact list
while (ContactsList.ChildCount > holopadArray.Length)
{
ContactsList.RemoveChild(ContactsList.GetChild(ContactsList.ChildCount - 1));
}
// Make / update required children
for (int i = 0; i < holopadArray.Length; i++)
@@ -213,55 +220,57 @@ public sealed partial class HolopadWindow : FancyWindow
private void UpdateAppearance()
{
if (_owner == null || !_entManager.TryGetComponent<TelephoneComponent>(_owner.Value, out var telephone))
if (!_entManager.TryGetComponent<TelephoneComponent>(_owner, out var telephone))
return;
if (_owner == null || !_entManager.TryGetComponent<HolopadComponent>(_owner.Value, out var holopad))
if (!_entManager.TryGetComponent<HolopadComponent>(_owner, out var holopad))
return;
var hasBroadcastAccess = !_holopadSystem.IsHolopadBroadcastOnCoolDown((_owner.Value, holopad));
var broadcastOnCooldown = _holopadSystem.IsHolopadBroadcastOnCoolDown((_owner.Value, holopad));
var localPlayer = _playerManager.LocalSession?.AttachedEntity;
// Update container visibility
ControlsLockOutContainer.Visible = _holopadSystem.IsHolopadControlLocked((_owner.Value, holopad), localPlayer);
ControlsContainer.Visible = !ControlsLockOutContainer.Visible;
// Temporarily disable the interface buttons when the call state changes to prevent any misclicks
if (_currentState != telephone.CurrentState)
// Update contact button visibility
if (SearchLineEdit.Text != _currentSearch)
{
_previousState = _currentState;
_currentState = telephone.CurrentState;
_buttonUnlockTime = _timing.CurTime + _buttonUnlockDelay;
_currentSearch = SearchLineEdit.Text;
foreach (var child in ContactsList.Children)
{
if (child is not HolopadContactButton contactButton)
continue;
var passesFilter = string.IsNullOrEmpty(SearchLineEdit.Text) ||
contactButton.Text?.Contains(SearchLineEdit.Text, StringComparison.CurrentCultureIgnoreCase) == true;
contactButton.Visible = passesFilter;
}
}
var lockButtons = _timing.CurTime < _buttonUnlockTime;
// Make / update required children
foreach (var child in ContactsList.Children)
// Update timers
if (ControlsContainer.Visible)
{
if (child is not HolopadContactButton contactButton)
continue;
var cooldown = _holopadSystem.GetHolopadBroadcastCoolDown((_owner.Value, holopad));
var cooldownString = $"{cooldown.Minutes:00}:{cooldown.Seconds:00}";
var passesFilter = string.IsNullOrEmpty(SearchLineEdit.Text) ||
contactButton.Text?.Contains(SearchLineEdit.Text, StringComparison.CurrentCultureIgnoreCase) == true;
contactButton.Visible = passesFilter;
contactButton.Disabled = (_currentState != TelephoneState.Idle || lockButtons);
StartBroadcastButton.Text = broadcastOnCooldown
? Loc.GetString("holopad-window-emergency-broadcast-with-countdown", ("countdown", cooldownString))
: Loc.GetString("holopad-window-emergency-broadcast");
}
// Update control text
var cooldown = _holopadSystem.GetHolopadBroadcastCoolDown((_owner.Value, holopad));
var cooldownString = $"{cooldown.Minutes:00}:{cooldown.Seconds:00}";
if (ControlsLockOutContainer.Visible)
{
var lockout = _holopadSystem.GetHolopadControlLockedPeriod((_owner.Value, holopad));
var lockoutString = $"{lockout.Minutes:00}:{lockout.Seconds:00}";
StartBroadcastButton.Text = _holopadSystem.IsHolopadBroadcastOnCoolDown((_owner.Value, holopad)) ?
Loc.GetString("holopad-window-emergency-broadcast-with-countdown", ("countdown", cooldownString)) :
Loc.GetString("holopad-window-emergency-broadcast");
LockOutCountDownText.Text = Loc.GetString("holopad-window-controls-unlock-countdown", ("countdown", lockoutString));
}
var lockout = _holopadSystem.GetHolopadControlLockedPeriod((_owner.Value, holopad));
var lockoutString = $"{lockout.Minutes:00}:{lockout.Seconds:00}";
LockOutCountDownText.Text = Loc.GetString("holopad-window-controls-unlock-countdown", ("countdown", lockoutString));
switch (_currentState)
// Update call status text
switch (telephone.CurrentState)
{
case TelephoneState.Idle:
CallStatusText.Text = Loc.GetString("holopad-window-no-calls-in-progress"); break;
@@ -277,7 +286,7 @@ public sealed partial class HolopadWindow : FancyWindow
CallStatusText.Text = Loc.GetString("holopad-window-call-in-progress"); break;
case TelephoneState.EndingCall:
if (_previousState == TelephoneState.Calling || _previousState == TelephoneState.Idle)
if (telephone.PreviousState == TelephoneState.Calling || telephone.PreviousState == TelephoneState.Idle)
CallStatusText.Text = Loc.GetString("holopad-window-call-rejected");
else
CallStatusText.Text = Loc.GetString("holopad-window-call-ending");
@@ -285,31 +294,29 @@ public sealed partial class HolopadWindow : FancyWindow
}
// Update control disability
AnswerCallButton.Disabled = (_currentState != TelephoneState.Ringing || lockButtons);
EndCallButton.Disabled = (_currentState == TelephoneState.Idle || _currentState == TelephoneState.EndingCall || lockButtons);
StartBroadcastButton.Disabled = (_currentState != TelephoneState.Idle || !hasBroadcastAccess || lockButtons);
RequestStationAiButton.Disabled = (_currentState != TelephoneState.Idle || lockButtons);
ActivateProjectorButton.Disabled = (_currentState != TelephoneState.Idle || lockButtons);
AnswerCallButton.Disabled = telephone.CurrentState is not TelephoneState.Ringing;
EndCallButton.Disabled = telephone.CurrentState is TelephoneState.Idle or TelephoneState.EndingCall;
StartBroadcastButton.Disabled = telephone.CurrentState is not TelephoneState.Idle || broadcastOnCooldown;
RequestStationAiButton.Disabled = telephone.CurrentState is not TelephoneState.Idle;
ActivateProjectorButton.Disabled = telephone.CurrentState is not TelephoneState.Idle;
// Update control visibility
FetchingAvailableHolopadsContainer.Visible = (ContactsList.ChildCount == 0);
ActiveCallControlsContainer.Visible = (_currentState != TelephoneState.Idle || _currentUiKey == HolopadUiKey.AiRequestWindow);
FetchingAvailableHolopadsContainer.Visible = ContactsList.ChildCount == 0;
ActiveCallControlsContainer.Visible = telephone.CurrentState is not TelephoneState.Idle || _currentUiKey is HolopadUiKey.AiRequestWindow;
CallPlacementControlsContainer.Visible = !ActiveCallControlsContainer.Visible;
CallerIdContainer.Visible = (_currentState == TelephoneState.Ringing);
AnswerCallButton.Visible = (_currentState == TelephoneState.Ringing);
CallerIdContainer.Visible = telephone.CurrentState is TelephoneState.Ringing;
AnswerCallButton.Visible = telephone.CurrentState is TelephoneState.Ringing;
}
protected override void FrameUpdate(FrameEventArgs args)
{
base.FrameUpdate(args);
_updateTimer += args.DeltaSeconds;
if (_timing.CurTime < _nextUpdate)
return;
if (_updateTimer >= UpdateTime)
{
_updateTimer -= UpdateTime;
UpdateAppearance();
}
_nextUpdate = _timing.CurTime + _updateDelay;
UpdateAppearance();
}
private sealed class HolopadContactButton : Button
+57 -39
View File
@@ -1,52 +1,70 @@
<Control xmlns="https://spacestation14.io"
xmlns:pllax="clr-namespace:Content.Client.Parallax"
xmlns:clog="clr-namespace:Content.Client.Changelog">
xmlns:clog="clr-namespace:Content.Client.Changelog"
xmlns:system="clr-namespace:System;assembly=System.Runtime">
<pllax:ParallaxControl
ParallaxPrototype="TrainStation"
Name="BackgroundParallax"
SpeedX="5"
SpeedY="20"
ScaleX="3"
ScaleY="3"/>
ScaleY="3" />
<BoxContainer Name="VBox"
Orientation="Vertical"
HorizontalAlignment="Center"
VerticalAlignment="Center"
HorizontalExpand="True"
VerticalExpand="True"
StyleIdentifier="mainMenuVBox"
SeparationOverride="3">
<TextureRect Name="Logo"
Stretch="KeepCentered"/>
<GridContainer Columns="2">
<Label Text="{Loc 'main-menu-username-label'}" />
<LineEdit Name="UsernameBox"
Access="Public"
PlaceHolder="{Loc 'main-menu-username-text'}"
HorizontalExpand="True" />
<Label Text="{Loc 'main-menu-address-label'}"/>
<LineEdit Name="AddressBox"
Access="Public"
Text="localhost"
PlaceHolder="server address:port"
HorizontalExpand="True" />
</GridContainer>
<Button Name="DirectConnectButton"
Access="Public"
Text="{Loc 'main-menu-direct-connect-button'}"
TextAlign="Center"
StyleIdentifier="mainMenu"/>
<Button Name="OptionsButton"
Access="Public"
Text="{Loc 'main-menu-options-button'}"
TextAlign="Center"
StyleIdentifier="mainMenu"/>
<Button Name="QuitButton"
Access="Public"
Text="{Loc 'main-menu-quit-button'}"
TextAlign="Center"
StyleIdentifier="mainMenu"/>
<clog:ChangelogButton
Name="ChangelogButton"
Access="Public"/>
VerticalExpand="True">
<PanelContainer StyleClasses="BackgroundPanel">
<BoxContainer Orientation="Vertical"
HorizontalAlignment="Center"
VerticalAlignment="Center"
HorizontalExpand="True"
VerticalExpand="True"
StyleIdentifier="mainMenuVBox"
Margin="4 16">
<TextureRect Name="Logo"
Stretch="KeepCentered" />
<GridContainer Columns="2" Margin="0 4">
<Label Text="{Loc 'main-menu-username-label'}" />
<LineEdit Name="UsernameBox"
Access="Public"
PlaceHolder="{Loc 'main-menu-username-text'}"
HorizontalExpand="True" />
<Label Text="{Loc 'main-menu-address-label'}" />
<LineEdit Name="AddressBox"
Access="Public"
Text="localhost"
PlaceHolder="server address:port"
HorizontalExpand="True" />
</GridContainer>
<Button Name="DirectConnectButton"
Access="Public"
Text="{Loc 'main-menu-direct-connect-button'}"
TextAlign="Center"
StyleClasses="OpenLeft"
StyleIdentifier="mainMenu" />
<clog:ChangelogButton
Name="ChangelogButton"
StyleIdentifier="mainMenu"
StyleClasses="OpenBoth"
Access="Public" />
<Button Name="OptionsButton"
Access="Public"
Text="{Loc 'main-menu-options-button'}"
TextAlign="Center"
StyleClasses="OpenBoth"
StyleIdentifier="mainMenu" />
<Button Name="QuitButton"
Access="Public"
Text="{Loc 'main-menu-quit-button'}"
TextAlign="Center"
StyleIdentifier="mainMenu">
<Control.StyleClasses>
<system:String>negative</system:String>
<system:String>OpenRight</system:String>
</Control.StyleClasses>
</Button>
</BoxContainer>
</PanelContainer>
</BoxContainer>
</Control>
@@ -1,21 +1,43 @@
using Robust.Client.AutoGenerated;
using Content.Client.Parallax.Data;
using Robust.Client.AutoGenerated;
using Robust.Client.ResourceManagement;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared;
using Robust.Shared.Configuration;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
namespace Content.Client.MainMenu.UI;
[GenerateTypedNameReferences]
public sealed partial class MainMenuControl : Control
{
[Dependency] private IRobustRandom _random = default!;
public const string StyleIdentifierMainMenu = "mainMenu";
public const string StyleIdentifierMainMenuVBox = "mainMenuVBox";
private static readonly ProtoId<ParallaxPrototype>[] Parallaxes =
[
"Wizard",
"TrainStation",
"PlasmaStation",
"AmberStation",
"FastSpace",
"AspidParallax",
"OriginStation",
"Default",
"Sky",
"KettleStation",
"BagelStation",
"ExoStation",
];
public MainMenuControl(IResourceCache resCache, IConfigurationManager configMan)
{
IoCManager.InjectDependencies(this);
RobustXamlLoader.Load(this);
LayoutContainer.SetAnchorPreset(this, LayoutContainer.LayoutPreset.Wide);
@@ -25,6 +47,10 @@ public sealed partial class MainMenuControl : Control
LayoutContainer.SetMarginTop(VBox, 30);
LayoutContainer.SetGrowHorizontal(VBox, LayoutContainer.GrowDirection.Begin);
// I don't just enumerate them all as there's some hideous parallaxes, and it's easier
// to update an allowlist than to randomly get an ugly one to fix a blocklist.
BackgroundParallax.ParallaxPrototype = _random.Pick(Parallaxes).Id;
var logoTexture = resCache.GetResource<TextureResource>("/Textures/Logo/logo.png");
Logo.Texture = logoTexture;
@@ -1,9 +1,7 @@
using System.Numerics;
using Content.Shared.CCVar;
using Content.Shared.Movement.Components;
using Content.Shared.Movement.Systems;
using Robust.Client.Player;
using Robust.Shared.Physics.Components;
using Robust.Shared.Timing;
namespace Content.Client.Movement.Systems;
+23 -12
View File
@@ -1,22 +1,33 @@
<ui1:EscapeMenu xmlns="https://spacestation14.io"
xmlns:changelog="clr-namespace:Content.Client.Changelog"
xmlns:ui="clr-namespace:Content.Client.Voting.UI"
xmlns:ui1="clr-namespace:Content.Client.Options.UI"
Title="{Loc 'ui-escape-title'}"
Resizable="False">
xmlns:changelog="clr-namespace:Content.Client.Changelog"
xmlns:ui="clr-namespace:Content.Client.Voting.UI"
xmlns:ui1="clr-namespace:Content.Client.Options.UI"
xmlns:system="clr-namespace:System;assembly=System.Runtime"
Title="{Loc 'ui-escape-title'}"
Resizable="False">
<BoxContainer Orientation="Vertical" SeparationOverride="4" MinWidth="150">
<ui:VoteCallMenuButton />
<PanelContainer StyleClasses="LowDivider" Margin="0 2.5 0 2.5" />
<Button Access="Public" Name="RulesButton" Text="{Loc 'ui-escape-rules'}" />
<Button Access="Public" Name="GuidebookButton" Text="{Loc 'ui-escape-guidebook'}" />
<Button Access="Public" Name="WikiButton" Text="{Loc 'ui-escape-wiki'}" />
<changelog:ChangelogButton Access="Public" Name="ChangelogButton" />
<Button Access="Public" Name="FeedbackButton" Text="{Loc 'ui-escape-feedback'}"/>
<Button Access="Public" Name="RulesButton" Text="{Loc 'ui-escape-rules'}" StyleClasses="OpenLeft" />
<Button Access="Public" Name="GuidebookButton" Text="{Loc 'ui-escape-guidebook'}" StyleClasses="OpenBoth" />
<Button Access="Public" Name="WikiButton" Text="{Loc 'ui-escape-wiki'}" StyleClasses="OpenBoth" />
<changelog:ChangelogButton Access="Public" Name="ChangelogButton" StyleClasses="OpenBoth"/>
<Button Access="Public" Name="FeedbackButton" Text="{Loc 'ui-escape-feedback'}" StyleClasses="OpenRight"/>
<PanelContainer StyleClasses="LowDivider" Margin="0 2.5 0 2.5" />
<Button Access="Public" Name="OptionsButton" Text="{Loc 'ui-escape-options'}" />
<PanelContainer StyleClasses="LowDivider" Margin="0 2.5 0 2.5" />
<Button Access="Public" Name="DisconnectButton" Text="{Loc 'ui-escape-disconnect'}" />
<Button Access="Public" Name="QuitButton" Text="{Loc 'ui-escape-quit'}" StyleClasses="ButtonColorRed" />
<Button Access="Public" Name="DisconnectButton" Text="{Loc 'ui-escape-disconnect'}">
<Control.StyleClasses>
<system:String>negative</system:String>
<system:String>OpenLeft</system:String>
</Control.StyleClasses>
</Button>
<Button Access="Public" Name="QuitButton" Text="{Loc 'ui-escape-quit'}">
<Control.StyleClasses>
<system:String>negative</system:String>
<system:String>OpenRight</system:String>
</Control.StyleClasses>
</Button>
</BoxContainer>
</ui1:EscapeMenu>
@@ -7,6 +7,7 @@
<Label Text="{Loc 'ui-options-accessability-header-visuals'}"
StyleClasses="LabelKeyText"/>
<CheckBox Name="ReducedMotionCheckBox" Text="{Loc 'ui-options-reduced-motion'}" />
<CheckBox Name="DisableAiStaticCheckBox" Text="{Loc 'ui-options-disable-ai-static'}" />
<CheckBox Name="EnableColorNameCheckBox" Text="{Loc 'ui-options-enable-color-name'}" />
<CheckBox Name="ColorblindFriendlyCheckBox" Text="{Loc 'ui-options-colorblind-friendly'}" />
<ui:OptionSlider Name="ScreenShakeIntensitySlider" Title="{Loc 'ui-options-screen-shake-intensity'}" />
@@ -15,6 +15,7 @@ public sealed partial class AccessibilityTab : Control
Control.AddOptionCheckBox(CCVars.ChatEnableColorName, EnableColorNameCheckBox);
Control.AddOptionCheckBox(CCVars.AccessibilityColorblindFriendly, ColorblindFriendlyCheckBox);
Control.AddOptionCheckBox(CCVars.ReducedMotion, ReducedMotionCheckBox);
Control.AddOptionCheckBox(CCVars.DisableAiStatic, DisableAiStaticCheckBox);
Control.AddOptionPercentSlider(CCVars.ScreenShakeIntensity, ScreenShakeIntensitySlider);
Control.AddOptionPercentSlider(CCVars.ChatWindowOpacity, ChatWindowOpacitySlider);
Control.AddOptionPercentSlider(CCVars.SpeechBubbleTextOpacity, SpeechBubbleTextOpacitySlider);
@@ -1,8 +1,10 @@
using System.Numerics;
using Content.Client.Graphics;
using Content.Shared.CCVar;
using Content.Shared.Silicons.StationAi;
using Robust.Client.Graphics;
using Robust.Client.Player;
using Robust.Shared.Configuration;
using Robust.Shared.Enums;
using Robust.Shared.Map.Components;
using Robust.Shared.Physics;
@@ -14,10 +16,12 @@ namespace Content.Client.Silicons.StationAi;
public sealed partial class StationAiOverlay : Overlay
{
private static readonly ProtoId<ShaderPrototype> CameraStaticShader = "CameraStatic";
private static readonly ProtoId<ShaderPrototype> CameraStaticAccessibleShader = "CameraStaticAccessible";
private static readonly ProtoId<ShaderPrototype> StencilMaskShader = "StencilMask";
private static readonly ProtoId<ShaderPrototype> StencilDrawShader = "StencilDraw";
[Dependency] private IClyde _clyde = default!;
[Dependency] private IConfigurationManager _cfg = default!;
[Dependency] private IEntityManager _entManager = default!;
[Dependency] private IGameTiming _timing = default!;
[Dependency] private IPlayerManager _player = default!;
@@ -29,12 +33,20 @@ public sealed partial class StationAiOverlay : Overlay
private readonly OverlayResourceCache<CachedResources> _resources = new();
private ProtoId<ShaderPrototype> _activeShader = CameraStaticShader;
private float _updateRate = 1f / 30f;
private float _accumulator;
public StationAiOverlay()
{
IoCManager.InjectDependencies(this);
_cfg.OnValueChanged(CCVars.DisableAiStatic, OnAiStaticChanged, invokeImmediately: true);
}
private void OnAiStaticChanged(bool toggle)
{
_activeShader = toggle ? CameraStaticAccessibleShader : CameraStaticShader;
}
protected override void Draw(in OverlayDrawArgs args)
@@ -97,7 +109,7 @@ public sealed partial class StationAiOverlay : Overlay
() =>
{
worldHandle.SetTransform(invMatrix);
var shader = _proto.Index(CameraStaticShader).Instance();
var shader = _proto.Index(_activeShader).Instance();
worldHandle.UseShader(shader);
worldHandle.DrawRect(worldBounds, Color.White);
},
@@ -239,11 +239,15 @@ public abstract class RadialMenuButtonBase : BaseButton
/// <inheritdoc />
protected override void KeyBindUp(GUIBoundKeyEventArgs args)
{
if (args.Function == EngineKeyFunctions.UIClick
|| args.Function == ContentKeyFunctions.AltActivateItemInWorld)
{
if (args.Function.IsClickOrAltClick())
base.KeyBindUp(args);
}
}
/// <inheritdoc />
protected override void KeyBindDown(GUIBoundKeyEventArgs args)
{
if (args.Function.IsClickOrAltClick())
base.KeyBindDown(args);
}
}
@@ -285,11 +289,15 @@ public sealed class RadialMenuContextualCentralTextureButton : TextureButton
/// <inheritdoc />
protected override void KeyBindUp(GUIBoundKeyEventArgs args)
{
if (args.Function == EngineKeyFunctions.UIClick
|| args.Function == ContentKeyFunctions.AltActivateItemInWorld)
{
if (args.Function.IsClickOrAltClick())
base.KeyBindUp(args);
}
}
/// <inheritdoc />
protected override void KeyBindDown(GUIBoundKeyEventArgs args)
{
if (args.Function.IsClickOrAltClick())
base.KeyBindDown(args);
}
}
@@ -684,3 +692,12 @@ public class RadialMenuButtonWithSector : RadialMenuButton, IRadialMenuItemWithS
return new Angle(angleSectorFrom).EqualsApprox(new Angle(angleSectorTo));
}
}
static file class RadialMenuButtonsHelpers
{
public static bool IsClickOrAltClick(this BoundKeyFunction function)
{
return function == EngineKeyFunctions.UIClick
|| function == ContentKeyFunctions.AltActivateItemInWorld;
}
}
@@ -250,6 +250,7 @@ public abstract partial class GameTest
catch (Exception)
{
_pairDestroyed = true;
Assert.Fail();
throw;
}
finally
@@ -20,12 +20,14 @@ public static class CompConstraintExtensions
{
extension(Has)
{
/// <inheritdoc cref="extension(ConstraintExpression).Comp{T}"/>
public static ResolvableConstraintExpression Comp<T>(IIntegrationInstance instance)
where T : IComponent
{
return new ConstraintExpression().Comp<T>(instance);
}
/// <inheritdoc cref="extension(ConstraintExpression).Comp(Type, IIntegrationInstance)"/>
public static ResolvableConstraintExpression Comp(Type t, IIntegrationInstance instance)
{
return new ConstraintExpression().Comp(t, instance);
@@ -34,12 +36,52 @@ public static class CompConstraintExtensions
extension(ConstraintExpression expr)
{
/// <summary>
/// Returns a new constraint which will either test for the existence of a <typeparamref name="T"/>
/// on the entity being tested or apply any following constraint to that component.
/// </summary>
/// <typeparam name="T">The component Type to check for.</typeparam>
/// <param name="instance">The <see cref="IIntegrationInstance"/> (i.e. Server or Client) on which to perform the test.</param>
/// <example>
/// <code>
/// // Assert that the server-sided entity myEntity has an ItemComponent on the server.
/// Assert.That(myEntity, Has.Comp&lt;ItemComponent&gt;(Server));
///
/// // Assert that the server-sided entity myEntity has an ItemComponent with a Size field equal to "Small"
/// Assert.That(myEntity,
/// Has
/// .Comp&lt;ItemComponent&gt;(Server)
/// .Property(nameof(ItemComponent.Size))
/// .EqualTo("Small")
/// );
/// </code>
/// </example>
public ResolvableConstraintExpression Comp<T>(IIntegrationInstance instance)
where T : IComponent
{
return expr.Append(new CompOperator(typeof(T), instance));
}
/// <summary>
/// Returns a new constraint which will either test for the existence of a component of the specified type
/// on the entity being tested or apply any following constraint to that component.
/// </summary>
/// <param name="t">The Type of the component to check for.</param>
/// <param name="instance">The <see cref="IIntegrationInstance"/> (i.e. Server or Client) on which to perform the test.</param>
/// <example>
/// <code>
/// // Assert that the server-sided entity myEntity has an ItemComponent on the server.
/// Assert.That(myEntity, Has.Comp(typeof(ItemComponent), Server));
///
/// // Assert that the server-sided entity myEntity has an ItemComponent with a Size field equal to "Small"
/// Assert.That(myEntity,
/// Has
/// .Comp(typeof(ItemComponent), Server)
/// .Property(nameof(ItemComponent.Size))
/// .EqualTo("Small")
/// );
/// </code>
/// </example>
public ResolvableConstraintExpression Comp(Type t, IIntegrationInstance instance)
{
return expr.Append(new CompOperator(t, instance));
@@ -56,36 +56,43 @@ public static class LifeStageConstraintExtensions
{
extension(Is)
{
/// <inheritdoc cref="extension(ConstraintExpression).LifeStage"/>
public static LifeStageConstraint LifeStage(EntityLifeStage stage, IIntegrationInstance instance)
{
return new LifeStageConstraint(stage, instance);
}
/// <inheritdoc cref="extension(ConstraintExpression).PreInit"/>
public static LifeStageConstraint PreInit(IIntegrationInstance instance)
{
return Is.LifeStage(EntityLifeStage.PreInit, instance);
}
/// <inheritdoc cref="extension(ConstraintExpression).Initializing"/>
public static LifeStageConstraint Initializing(IIntegrationInstance instance)
{
return Is.LifeStage(EntityLifeStage.Initializing, instance);
}
/// <inheritdoc cref="extension(ConstraintExpression).Initialized"/>
public static LifeStageConstraint Initialized(IIntegrationInstance instance)
{
return Is.LifeStage(EntityLifeStage.Initialized, instance);
}
/// <inheritdoc cref="extension(ConstraintExpression).MapInitialized"/>
public static LifeStageConstraint MapInitialized(IIntegrationInstance instance)
{
return Is.LifeStage(EntityLifeStage.MapInitialized, instance);
}
/// <inheritdoc cref="extension(ConstraintExpression).Terminating"/>
public static LifeStageConstraint Terminating(IIntegrationInstance instance)
{
return Is.LifeStage(EntityLifeStage.Terminating, instance);
}
/// <inheritdoc cref="extension(ConstraintExpression).Deleted"/>
public static LifeStageConstraint Deleted(IIntegrationInstance instance)
{
return Is.LifeStage(EntityLifeStage.Deleted, instance);
@@ -94,6 +101,17 @@ public static class LifeStageConstraintExtensions
extension(ConstraintExpression expr)
{
/// <summary>
/// Returns a new constraint that checks if the entity is in the given lifestage.
/// </summary>
/// <param name="stage">The <see cref="EntityLifeStage"/> to check for.</param>
/// <param name="instance">The <see cref="IIntegrationInstance"/> (i.e. Server or Client) on which to perform the test.</param>
/// <example>
/// <code>
/// // Assert that the server-sided entity myEntity is MapInitialized.
/// Assert.That(myEntity, Is.LifeStage(EntityLifeStage.MapInitialized, Server));
/// </code>
/// </example>
public LifeStageConstraint LifeStage(EntityLifeStage stage, IIntegrationInstance instance)
{
var c = new LifeStageConstraint(stage, instance);
@@ -103,31 +121,91 @@ public static class LifeStageConstraintExtensions
return c;
}
/// <summary>
/// Returns a new constraint that checks if the entity is in the PreInit lifestage.
/// </summary>
/// <param name="instance">The <see cref="IIntegrationInstance"/> (i.e. Server or Client) on which to perform the test.</param>
/// <example>
/// <code>
/// // Assert that the server-sided entity myEntity has not yet been initialized.
/// Assert.That(myEntity, Is.PreInit(Server));
/// </code>
/// </example>
public LifeStageConstraint PreInit(IIntegrationInstance instance)
{
return expr.LifeStage(EntityLifeStage.PreInit, instance);
}
/// <summary>
/// Returns a new constraint that checks if the entity is in the Intializing lifestage.
/// </summary>
/// <param name="instance">The <see cref="IIntegrationInstance"/> (i.e. Server or Client) on which to perform the test.</param>
/// <example>
/// <code>
/// // Assert that the server-sided entity myEntity is Initializing.
/// Assert.That(myEntity, Is.Initializing(Server));
/// </code>
/// </example>
public LifeStageConstraint Initializing(IIntegrationInstance instance)
{
return expr.LifeStage(EntityLifeStage.Initializing, instance);
}
/// <summary>
/// Returns a new constraint that checks if the entity is in the Initialized lifestage.
/// </summary>
/// <param name="instance">The <see cref="IIntegrationInstance"/> (i.e. Server or Client) on which to perform the test.</param>
/// <example>
/// <code>
/// // Assert that the server-sided entity myEntity is Initialized.
/// Assert.That(myEntity, Is.Initialized(Server));
/// </code>
/// </example>
public LifeStageConstraint Initialized(IIntegrationInstance instance)
{
return expr.LifeStage(EntityLifeStage.Initialized, instance);
}
/// <summary>
/// Returns a new constraint that checks if the entity is in the MapInitialized lifestage.
/// </summary>
/// <param name="instance">The <see cref="IIntegrationInstance"/> (i.e. Server or Client) on which to perform the test.</param>
/// <example>
/// <code>
/// // Assert that the server-sided entity myEntity is MapInitialized.
/// Assert.That(myEntity, Is.MapInitialized(Server));
/// </code>
/// </example>
public LifeStageConstraint MapInitialized(IIntegrationInstance instance)
{
return expr.LifeStage(EntityLifeStage.MapInitialized, instance);
}
/// <summary>
/// Returns a new constraint that checks if the entity is in the Terminating lifestage.
/// </summary>
/// <param name="instance">The <see cref="IIntegrationInstance"/> (i.e. Server or Client) on which to perform the test.</param>
/// <example>
/// <code>
/// // Assert that the server-sided entity myEntity is Terminating.
/// Assert.That(myEntity, Is.Terminating(Server));
/// </code>
/// </example>
public LifeStageConstraint Terminating(IIntegrationInstance instance)
{
return expr.LifeStage(EntityLifeStage.Terminating, instance);
}
/// <summary>
/// Returns a new constraint that checks if the entity is in the Deleted lifestage.
/// </summary>
/// <param name="instance">The <see cref="IIntegrationInstance"/> (i.e. Server or Client) on which to perform the test.</param>
/// <example>
/// <code>
/// // Assert that the server-sided entity myEntity is Deleted.
/// Assert.That(myEntity, Is.Deleted(Server));
/// </code>
/// </example>
public LifeStageConstraint Deleted(IIntegrationInstance instance)
{
return expr.LifeStage(EntityLifeStage.Deleted, instance);
@@ -2,13 +2,13 @@
using System.Collections.Generic;
using System.Linq;
using Content.IntegrationTests.Fixtures;
using Content.IntegrationTests.Fixtures.Attributes;
using Content.Server.Administration.Logs;
using Content.Server.Database;
using Content.Server.GameTicking;
using Content.Shared.Administration.Logs;
using Content.Shared.Database;
using Robust.Server.Player;
using Robust.Shared.GameObjects;
namespace Content.IntegrationTests.Tests.Administration.Logs;
@@ -23,29 +23,28 @@ public sealed class AddTests : GameTest
Connected = true
};
[SidedDependency(Side.Server)] private readonly IAdminLogManager _sAdminLogManager = null!;
[SidedDependency(Side.Server)] private readonly IServerDbManager _sDbManager = null!;
[SidedDependency(Side.Server)] private readonly GameTicker _sGameTicker = null!;
[SidedDependency(Side.Server)] private readonly IPlayerManager _sPlayerManager = null!;
[Test]
public async Task AddAndGetSingleLog()
{
var pair = Pair;
var server = pair.Server;
var sEntities = server.ResolveDependency<IEntityManager>();
var sAdminLogSystem = server.ResolveDependency<IAdminLogManager>();
var guid = Guid.NewGuid();
await pair.CreateTestMap();
var coordinates = pair.TestMap!.GridCoords;
await server.WaitPost(() =>
await Pair.CreateTestMap();
var coordinates = Pair.TestMap!.GridCoords;
await Server.WaitPost(() =>
{
var entity = sEntities.SpawnEntity(null, coordinates);
var entity = SSpawnAtPosition(null, coordinates);
sAdminLogSystem.Add(LogType.Unknown, $"{entity:Entity} test log: {guid}");
_sAdminLogManager.Add(LogType.Unknown, $"{entity:Entity} test log: {guid}");
});
await PoolManager.WaitUntil(server, async () =>
await PoolManager.WaitUntil(Server, async () =>
{
var logs = sAdminLogSystem.CurrentRoundJson(new LogFilter
var logs = _sAdminLogManager.CurrentRoundJson(new LogFilter
{
Search = guid.ToString()
});
@@ -69,32 +68,22 @@ public sealed class AddTests : GameTest
[Test]
public async Task AddAndGetUnformattedLog()
{
var pair = Pair;
var server = pair.Server;
var sDatabase = server.ResolveDependency<IServerDbManager>();
var sEntities = server.ResolveDependency<IEntityManager>();
var sSystems = server.ResolveDependency<IEntitySystemManager>();
var sAdminLogSystem = server.ResolveDependency<IAdminLogManager>();
var sGamerTicker = sSystems.GetEntitySystem<GameTicker>();
var guid = Guid.NewGuid();
var testMap = await pair.CreateTestMap();
var testMap = await Pair.CreateTestMap();
var coordinates = testMap.GridCoords;
await server.WaitPost(() =>
await Server.WaitPost(() =>
{
var entity = sEntities.SpawnEntity(null, coordinates);
var entity = SSpawnAtPosition(null, coordinates);
sAdminLogSystem.Add(LogType.Unknown, $"{entity} test log: {guid}");
_sAdminLogManager.Add(LogType.Unknown, $"{entity} test log: {guid}");
});
SharedAdminLog log = default;
await PoolManager.WaitUntil(server, async () =>
await PoolManager.WaitUntil(Server, async () =>
{
var logs = await sAdminLogSystem.CurrentRoundLogs(new LogFilter
var logs = await _sAdminLogManager.CurrentRoundLogs(new LogFilter
{
Search = guid.ToString()
});
@@ -110,12 +99,12 @@ public sealed class AddTests : GameTest
var filter = new LogFilter
{
Round = sGamerTicker.RoundId,
Round = _sGameTicker.RoundId,
Search = log.Message,
Types = new HashSet<LogType> { log.Type },
};
await foreach (var json in sDatabase.GetAdminLogsJson(filter))
await foreach (var json in _sDbManager.GetAdminLogsJson(filter))
{
var root = json.RootElement;
@@ -133,27 +122,21 @@ public sealed class AddTests : GameTest
[TestCase(500)]
public async Task BulkAddLogs(int amount)
{
var pair = Pair;
var server = pair.Server;
var sEntities = server.ResolveDependency<IEntityManager>();
var sAdminLogSystem = server.ResolveDependency<IAdminLogManager>();
var testMap = await pair.CreateTestMap();
var testMap = await Pair.CreateTestMap();
var coordinates = testMap.GridCoords;
await server.WaitPost(() =>
await Server.WaitPost(() =>
{
var entity = sEntities.SpawnEntity(null, coordinates);
var entity = SSpawnAtPosition(null, coordinates);
for (var i = 0; i < amount; i++)
{
sAdminLogSystem.Add(LogType.Unknown, $"{entity:Entity} test log.");
_sAdminLogManager.Add(LogType.Unknown, $"{entity:Entity} test log.");
}
});
await PoolManager.WaitUntil(server, async () =>
await PoolManager.WaitUntil(Server, async () =>
{
var messages = await sAdminLogSystem.CurrentRoundLogs();
var messages = await _sAdminLogManager.CurrentRoundLogs();
return messages.Count >= amount;
});
}
@@ -161,28 +144,22 @@ public sealed class AddTests : GameTest
[Test]
public async Task AddPlayerSessionLog()
{
var pair = Pair;
var server = pair.Server;
var sPlayers = server.ResolveDependency<IPlayerManager>();
var sAdminLogSystem = server.ResolveDependency<IAdminLogManager>();
Guid playerGuid = default;
await server.WaitPost(() =>
await Server.WaitPost(() =>
{
var player = sPlayers.Sessions.First();
var player = _sPlayerManager.Sessions.First();
playerGuid = player.UserId;
Assert.DoesNotThrow(() =>
{
sAdminLogSystem.Add(LogType.Unknown, $"{player:Player} test log.");
_sAdminLogManager.Add(LogType.Unknown, $"{player:Player} test log.");
});
});
await PoolManager.WaitUntil(server, async () =>
await PoolManager.WaitUntil(Server, async () =>
{
var logs = await sAdminLogSystem.CurrentRoundLogs();
var logs = await _sAdminLogManager.CurrentRoundLogs();
if (logs.Count == 0)
{
return false;
@@ -196,24 +173,18 @@ public sealed class AddTests : GameTest
[Test]
public async Task DuplicatePlayerDoesNotThrowTest()
{
var pair = Pair;
var server = pair.Server;
var sPlayers = server.ResolveDependency<IPlayerManager>();
var sAdminLogSystem = server.ResolveDependency<IAdminLogManager>();
var guid = Guid.NewGuid();
await server.WaitPost(() =>
await Server.WaitPost(() =>
{
var player = sPlayers.Sessions.Single();
var player = _sPlayerManager.Sessions.Single();
sAdminLogSystem.Add(LogType.Unknown, $"{player} {player} test log: {guid}");
_sAdminLogManager.Add(LogType.Unknown, $"{player} {player} test log: {guid}");
});
await PoolManager.WaitUntil(server, async () =>
await PoolManager.WaitUntil(Server, async () =>
{
var logs = await sAdminLogSystem.CurrentRoundLogs(new LogFilter
var logs = await _sAdminLogManager.CurrentRoundLogs(new LogFilter
{
Search = guid.ToString()
});
@@ -230,25 +201,18 @@ public sealed class AddTests : GameTest
[Test]
public async Task DuplicatePlayerIdDoesNotThrowTest()
{
var pair = Pair;
var server = pair.Server;
var sPlayers = server.ResolveDependency<IPlayerManager>();
var sAdminLogSystem = server.ResolveDependency<IAdminLogManager>();
var guid = Guid.NewGuid();
await server.WaitPost(() =>
await Server.WaitPost(() =>
{
var player = sPlayers.Sessions.Single();
var player = _sPlayerManager.Sessions.Single();
sAdminLogSystem.Add(LogType.Unknown, $"{player:first} {player:second} test log: {guid}");
_sAdminLogManager.Add(LogType.Unknown, $"{player:first} {player:second} test log: {guid}");
});
await PoolManager.WaitUntil(server, async () =>
await PoolManager.WaitUntil(Server, async () =>
{
var logs = await sAdminLogSystem.CurrentRoundLogs(new LogFilter
var logs = await _sAdminLogManager.CurrentRoundLogs(new LogFilter
{
Search = guid.ToString()
});
@@ -272,35 +236,30 @@ public sealed class PreRoundAddTests : GameTest
AdminLogsEnabled = true
};
[SidedDependency(Side.Server)] private readonly IAdminLogManager _sAdminLogManager = null!;
[SidedDependency(Side.Server)] private readonly IServerDbManager _sDbManager = null!;
[SidedDependency(Side.Server)] private readonly GameTicker _sGameTicker = null!;
[Test]
public async Task PreRoundAddAndGetSingle()
{
var pair = Pair;
var server = pair.Server;
var sDatabase = server.ResolveDependency<IServerDbManager>();
var sSystems = server.ResolveDependency<IEntitySystemManager>();
var sAdminLogSystem = server.ResolveDependency<IAdminLogManager>();
var sGamerTicker = sSystems.GetEntitySystem<GameTicker>();
var guid = Guid.NewGuid();
await server.WaitPost(() =>
await Server.WaitPost(() =>
{
sAdminLogSystem.Add(LogType.Unknown, $"test log: {guid}");
_sAdminLogManager.Add(LogType.Unknown, $"test log: {guid}");
});
await server.WaitPost(() =>
await Server.WaitPost(() =>
{
sGamerTicker.StartRound(true);
_sGameTicker.StartRound(true);
});
SharedAdminLog log = default;
await PoolManager.WaitUntil(server, async () =>
await PoolManager.WaitUntil(Server, async () =>
{
var logs = await sAdminLogSystem.CurrentRoundLogs(new LogFilter
var logs = await _sAdminLogManager.CurrentRoundLogs(new LogFilter
{
Search = guid.ToString()
});
@@ -316,12 +275,12 @@ public sealed class PreRoundAddTests : GameTest
var filter = new LogFilter
{
Round = sGamerTicker.RoundId,
Round = _sGameTicker.RoundId,
Search = log.Message,
Types = new HashSet<LogType> { log.Type },
};
await foreach (var json in sDatabase.GetAdminLogsJson(filter))
await foreach (var json in _sDbManager.GetAdminLogsJson(filter))
{
var root = json.RootElement;
@@ -0,0 +1,86 @@
using Content.Server.Atmos.Piping.Trinary.Components;
using Content.Shared.Atmos.Components;
using Content.Shared.Atmos.Piping.Binary.Components;
using Robust.Shared.Utility;
namespace Content.IntegrationTests.Tests.Atmos;
/// <summary>
/// Test for ensuring that atmospherics components deserialize and spawn with settings applied.
/// </summary>
[TestFixture]
public sealed class AtmosMapLoadSettingsTest : AtmosTest
{
// These values correspond to settings in the test map.
private const float PumpSetting = 180f;
private const float MixerMainSetting = 0.1f;
private const float MixerSideSetting = 0.9f;
/// <summary>
/// Test map containing saved atmos components.
/// </summary>
protected override ResPath? TestMapPath => new("Maps/Test/Atmospherics/load_atmos_test_room.yml");
/// <summary>
/// Test to verify that the settings have been properly applied.
/// </summary>
[Test]
public async Task TestMapLoading()
{
await Server.WaitAssertion(() =>
{
var volumePumpQuery = SEntMan.EntityQueryEnumerator<GasVolumePumpComponent>();
while (volumePumpQuery.MoveNext(out var volumePump))
{
using (Assert.EnterMultipleScope())
{
Assert.That(volumePump.Enabled, Is.True, "Volume pump did not load enabled!");
Assert.That(
volumePump.TransferRate,
Is.EqualTo(PumpSetting),
"Volume pump did not load correct setting!"
);
}
}
var pressurePumpQuery = SEntMan.EntityQueryEnumerator<GasPressurePumpComponent>();
while (pressurePumpQuery.MoveNext(out var pressurePump))
{
using (Assert.EnterMultipleScope())
{
Assert.That(pressurePump.Enabled, Is.True, "Pressure pump did not load enabled!");
Assert.That(
pressurePump.TargetPressure,
Is.EqualTo(PumpSetting),
"Pressure pump did not load correct setting!"
);
}
}
var mixerQuery = SEntMan.EntityQueryEnumerator<GasMixerComponent>();
while (mixerQuery.MoveNext(out var mixer))
{
using (Assert.EnterMultipleScope())
{
Assert.That(mixer.Enabled, Is.True, "Mixer did not load enabled!");
Assert.That(
mixer.TargetPressure,
Is.EqualTo(PumpSetting),
"Mixer pump did not load correct setting!"
);
Assert.That(
mixer.InletOneConcentration,
Is.EqualTo(MixerMainSetting),
"Mixer split did not load correct setting!"
);
Assert.That(
mixer.InletTwoConcentration,
Is.EqualTo(MixerSideSetting),
"Mixer split did not load correct setting!"
);
}
}
});
}
}
@@ -44,6 +44,9 @@ public sealed class SharedGasSpecificHeatsTest
_sAtmos = _sEntMan.System<Content.Server.Atmos.EntitySystems.AtmosphereSystem>();
_cAtmos = _cEntMan.System<AtmosphereSystem>();
// ensure that client and server atmos are fully inited otherwise arrays might not agree
await _pair.ReallyBeIdle(1);
}
[TearDown]
@@ -0,0 +1,495 @@
using Content.IntegrationTests.Tests.Interaction;
using Content.Shared.Hands.EntitySystems;
using Content.Shared.Inventory.VirtualItem;
using Content.Shared.Item;
using Content.Shared.Wieldable;
using Content.Shared.Wieldable.Components;
namespace Content.IntegrationTests.Tests.Hands;
[TestOf(typeof(MultiHandedItemComponent))]
[TestOf(typeof(WieldableComponent))]
public abstract class BaseMultiHandedItemTest : InteractionTest
{
protected SharedHandsSystem CHands = default!;
protected SharedHandsSystem SHands = default!;
protected SharedWieldableSystem SWieldable = default!;
protected const string Dummy1 = "DummyOneHanded";
protected const string Dummy2 = "DummyTwoHanded";
protected const string Dummy3 = "DummyThreeHanded";
protected const string Dummy4 = "DummyFourHanded";
protected const string Crowbar1 = "CrowbarOneHanded";
protected const string Crowbar2 = "CrowbarTwoHanded";
protected const string Crowbar3 = "CrowbarThreeHanded";
protected const string CrowbarWield1 = "CrowbarWieldableOneHanded";
protected const string CrowbarWield2 = "CrowbarWieldableTwoHanded";
protected const string CrowbarWield3 = "CrowbarWieldableThreeHanded";
[TestPrototypes]
private const string TestPrototypes = @$"
- type: entity
id: {Dummy1}
name: Urist McOneHand
components:
- type: DoAfter
- type: Hands
hands:
hand_right:
location: Right
sortedHands:
- hand_right
- type: ComplexInteraction
- type: MindContainer
- type: Puller
- type: entity
parent: {Dummy1}
id: {Dummy2}
name: Urist McTwoHands
components:
- type: Hands
hands:
hand_right:
location: Right
hand_left:
location: Left
sortedHands:
- hand_right
- hand_left
- type: entity
parent: {Dummy1}
id: {Dummy3}
name: Urist McThreeHands
components:
- type: Hands
hands:
hand_right:
location: Right
hand_middle:
location: Middle
hand_left:
location: Left
sortedHands:
- hand_right
- hand_middle
- hand_left
- type: entity
parent: {Dummy1}
id: {Dummy4}
name: Urist McFourHands
components:
- type: Hands
hands:
hand_right1:
location: Right
hand_right2:
location: Right
hand_left1:
location: Left
hand_left2:
location: Left
sortedHands:
- hand_right1
- hand_right2
- hand_left1
- hand_left2
- type: entity
parent: BaseItem
id: {Crowbar1}
components:
- type: Sprite
sprite: Objects/Tools/crowbar.rsi
state: icon
- type: entity
parent: {Crowbar1}
id: {Crowbar2}
components:
- type: MultiHandedItem
handsNeeded: 2
- type: entity
parent: {Crowbar1}
id: {Crowbar3}
components:
- type: MultiHandedItem
handsNeeded: 3
- type: entity
parent: {Crowbar1}
id: {CrowbarWield1}
components:
- type: Wieldable
freeHandsRequired: 0
- type: entity
parent: {Crowbar1}
id: {CrowbarWield2}
components:
- type: Wieldable
freeHandsRequired: 1
- type: entity
parent: {Crowbar1}
id: {CrowbarWield3}
components:
- type: Wieldable
freeHandsRequired: 2
";
[SetUp]
public override async Task Setup()
{
await base.Setup();
CHands = CEntMan.System<SharedHandsSystem>();
SHands = SEntMan.System<SharedHandsSystem>();
SWieldable = SEntMan.System<SharedWieldableSystem>();
}
protected async Task AssertHandItems(int hands, int freeHands, int items, int virtualItems)
{
await RunTicks(3);
await Server.WaitAssertion(() =>
{
var itemCount = 0;
var virtualItemCount = 0;
foreach (var item in SHands.EnumerateHeld(SPlayer))
{
itemCount++;
if (SEntMan.HasComponent<VirtualItemComponent>(item))
virtualItemCount++;
}
Assert.Multiple(() =>
{
Assert.That(SHands.GetHandCount(SPlayer), Is.EqualTo(hands));
Assert.That(SHands.CountFreeHands(SPlayer), Is.EqualTo(freeHands));
Assert.That(itemCount, Is.EqualTo(items));
Assert.That(virtualItemCount, Is.EqualTo(virtualItems));
});
});
await Client.WaitAssertion(() =>
{
var itemCount = 0;
var virtualItemCount = 0;
foreach (var item in CHands.EnumerateHeld(CPlayer))
{
itemCount++;
if (CEntMan.HasComponent<VirtualItemComponent>(item))
virtualItemCount++;
}
Assert.Multiple(() =>
{
Assert.That(CHands.GetHandCount(CPlayer), Is.EqualTo(hands));
Assert.That(CHands.CountFreeHands(CPlayer), Is.EqualTo(freeHands));
Assert.That(itemCount, Is.EqualTo(items));
Assert.That(virtualItemCount, Is.EqualTo(virtualItems));
});
});
}
}
// we need a separate fixture for each hand amount so that we can override the PlayerPrototype
public sealed class OneHandedItemTestFixture : BaseMultiHandedItemTest
{
protected override string PlayerPrototype => Dummy1;
/// <summary>
/// Tries out a few possible combinations for using multi-handed and wieldable items while having one hand.
/// This does not cover all possible scenarios, so if something breaks at some point then add it here as well.
/// </summary>
[Test]
public async Task OneHandedItemTest()
{
// Start with one empty hand
await AssertHandItems(1, 1, 0, 0);
// We can pick up a one-handed item with one hand
await SpawnTarget(Crowbar1);
await Pickup();
await SwapHands(); // does nothing but we try anyways
await AssertHandItems(1, 0, 1, 0);
// We cannot pick up a second item
await SpawnTarget(Crowbar1);
await Server.WaitAssertion(() =>
{
Assert.That(SHands.TryPickupAnyHand(SPlayer, STarget.Value), Is.False);
});
await AssertHandItems(1, 0, 1, 0);
// We can drop our current item to free up the hand
await Drop();
await AssertHandItems(1, 1, 0, 0);
// We cannot pick up a multi-handed item
await SpawnTarget(Crowbar2);
await Server.WaitAssertion(() =>
{
Assert.That(SHands.TryPickupAnyHand(SPlayer, STarget.Value), Is.False);
});
await AssertHandItems(1, 1, 0, 0);
// Spawn a wieldable Crowbar that does not need extra hands, pick it up, wield it
await SpawnTarget(CrowbarWield1);
await Pickup();
await AssertHandItems(1, 0, 1, 0);
await Server.WaitAssertion(() =>
{
Assert.That(SWieldable.TryWield(STarget.Value, SPlayer), Is.True);
});
await AssertHandItems(1, 0, 1, 0);
// Drop the wielded item
await Drop();
await AssertHandItems(1, 1, 0, 0);
// Spawn a wieldable Crowbar that needs extra hands, pick it up, fail to wield it
await SpawnTarget(CrowbarWield2);
await Pickup();
await AssertHandItems(1, 0, 1, 0);
await Server.WaitAssertion(() =>
{
Assert.That(SWieldable.TryWield(STarget.Value, SPlayer), Is.False);
});
await AssertHandItems(1, 0, 1, 0);
// Drop the unwielded item
await Drop();
await AssertHandItems(1, 1, 0, 0);
}
}
public sealed class TwoHandedItemTestFixture : BaseMultiHandedItemTest
{
protected override string PlayerPrototype => Dummy2;
/// <summary>
/// Tries out a few possible combinations for using multi-handed and wieldable items while having two hands.
/// This does not cover all possible scenarios, so if something breaks at some point then add it here as well.
/// </summary>
[Test]
public async Task TwoHandedItemTest()
{
// Start with two empty hands
await AssertHandItems(2, 2, 0, 0);
// We can pick up a one-handed item with one hand
await SpawnTarget(Crowbar1);
await Pickup();
await SwapHands();
await AssertHandItems(2, 1, 1, 0);
// We can pick up another one-handed item with the second hand
await SpawnTarget(Crowbar1);
await Pickup();
await SwapHands();
await AssertHandItems(2, 0, 2, 0);
// We cannot pick up a third item
await SpawnTarget(Crowbar1);
await Server.WaitAssertion(() =>
{
Assert.That(SHands.TryPickupAnyHand(SPlayer, STarget.Value), Is.False);
});
await AssertHandItems(2, 0, 2, 0);
// Drop all items
await DropAll();
await AssertHandItems(2, 2, 0, 0);
// We can pick up a two-handed item with two hands
await SpawnTarget(Crowbar2);
await Pickup();
await SwapHands();
await AssertHandItems(2, 0, 2, 1);
// We cannot pick up a second item
await SpawnTarget(Crowbar1);
await Server.WaitAssertion(() =>
{
Assert.That(SHands.TryPickupAnyHand(SPlayer, STarget.Value), Is.False);
});
await AssertHandItems(2, 0, 2, 1);
// Drop all items
await DropAll();
await AssertHandItems(2, 2, 0, 0);
// We can pick up a one-handed item with one hand
var handOneItem = await SpawnTarget(Crowbar1);
await Pickup();
await SwapHands();
await AssertHandItems(2, 1, 1, 0);
// We cannot pick up a two-handed item with only one free hand
await SpawnTarget(Crowbar2);
await Server.WaitAssertion(() =>
{
Assert.That(SHands.TryPickupAnyHand(SPlayer, STarget.Value), Is.False);
});
await AssertHandItems(2, 1, 1, 0);
// We can pick up a one handed wieldable item
await SpawnTarget(CrowbarWield1);
await Pickup();
await AssertHandItems(2, 0, 2, 0);
// We can wield the one-handed wieldable item without dropping other items
await Server.WaitAssertion(() =>
{
Assert.That(SWieldable.TryWield(STarget.Value, SPlayer), Is.True);
});
Assert.That(SHands.IsHolding(SPlayer, ToServer(handOneItem)), Is.True);
await AssertHandItems(2, 0, 2, 0);
// Drop it and pick up a two-handed wieldable item
await Drop();
await AssertHandItems(2, 1, 1, 0);
await SpawnTarget(CrowbarWield2);
await Pickup();
await AssertHandItems(2, 0, 2, 0);
// We can wield the two-handed wieldable item, but drop the item in the other hand while doing so
await Server.WaitAssertion(() =>
{
Assert.That(SWieldable.TryWield(STarget.Value, SPlayer), Is.True);
});
Assert.That(SHands.IsHolding(SPlayer, ToServer(handOneItem)), Is.False);
await AssertHandItems(2, 0, 2, 1);
// Drop the wielded item
await Drop();
await AssertHandItems(2, 2, 0, 0);
// We cannot pick up a three-handed item
await SpawnTarget(Crowbar3);
await Server.WaitAssertion(() =>
{
Assert.That(SHands.TryPickupAnyHand(SPlayer, STarget.Value), Is.False);
});
await AssertHandItems(2, 2, 0, 0);
// We can pick up a three-handed wieldable item
await SpawnTarget(CrowbarWield3);
await Server.WaitAssertion(() =>
{
Assert.That(SHands.TryPickupAnyHand(SPlayer, STarget.Value), Is.True);
});
await AssertHandItems(2, 1, 1, 0);
// But we cannot wield it
await Server.WaitAssertion(() =>
{
Assert.That(SWieldable.TryWield(STarget.Value, SPlayer), Is.False);
});
await AssertHandItems(2, 1, 1, 0);
}
}
public sealed class ThreeHandedItemTestFixture : BaseMultiHandedItemTest
{
protected override string PlayerPrototype => Dummy3;
/// <summary>
/// Tries out a few possible combinations for using multi-handed and wieldable items while having three hands.
/// This does not cover all possible scenarios, so if something breaks at some point then add it here as well.
/// </summary>
[Test]
public async Task ThreeHandedItemTest()
{
// Start with three empty hands
await AssertHandItems(3, 3, 0, 0);
// We can pick up a three-handed item
await SpawnTarget(Crowbar3);
await Pickup();
await AssertHandItems(3, 0, 3, 2);
// Drop it
await Drop();
await AssertHandItems(3, 3, 0, 0);
// We can pick up a two-handed wieldable item
var handOneItem = await SpawnTarget(CrowbarWield2);
await Pickup();
await AssertHandItems(3, 2, 1, 0);
// And we can wield it
await Server.WaitAssertion(() =>
{
Assert.That(SWieldable.TryWield(STarget.Value, SPlayer), Is.True);
});
await AssertHandItems(3, 1, 2, 1);
// We can pick up a second two-handed wieldable item
await SwapHands();
await SwapHands();
await SpawnTarget(CrowbarWield2);
await Pickup();
await AssertHandItems(3, 0, 3, 1);
// And wielding it drops the first item
await Server.WaitAssertion(() =>
{
Assert.That(SWieldable.TryWield(STarget.Value, SPlayer), Is.True);
});
Assert.That(SHands.IsHolding(SPlayer, ToServer(handOneItem)), Is.False);
await AssertHandItems(3, 1, 2, 1);
}
}
public sealed class FourHandedItemTestFixture : BaseMultiHandedItemTest
{
protected override string PlayerPrototype => Dummy4;
/// <summary>
/// Tries out a few possible combinations for using multi-handed and wieldable items while having four hands.
/// This does not cover all possible scenarios, so if something breaks at some point then add it here as well.
/// </summary>
[Test]
public async Task FourHandedItemTest()
{
// Start with four empty hands
await AssertHandItems(4, 4, 0, 0);
// We can wield two two-handed wieldable items at the same time
await SpawnTarget(CrowbarWield2);
await Pickup();
await AssertHandItems(4, 3, 1, 0);
await Server.WaitAssertion(() =>
{
Assert.That(SWieldable.TryWield(STarget.Value, SPlayer), Is.True);
});
await AssertHandItems(4, 2, 2, 1);
await SwapHands();
await SwapHands();
await SpawnTarget(CrowbarWield2);
await Pickup();
await AssertHandItems(4, 1, 3, 1);
await Server.WaitAssertion(() =>
{
Assert.That(SWieldable.TryWield(STarget.Value, SPlayer), Is.True);
});
await AssertHandItems(4, 0, 4, 2);
// Drop the first item
await Drop();
await AssertHandItems(4, 2, 2, 1);
// Drop the second item
await SwapHands();
await SwapHands();
await Drop();
await AssertHandItems(4, 4, 0, 0);
}
}
@@ -1,5 +1,7 @@
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using Content.IntegrationTests.Fixtures;
using Content.IntegrationTests.Fixtures.Attributes;
using Content.IntegrationTests.Utility;
using Content.Shared.Body;
using Content.Shared.Humanoid;
@@ -21,10 +23,10 @@ public sealed class HumanoidProfileTests : GameTest
private static readonly ProtoId<SpeciesPrototype> Vox = "Vox";
private static string[] _species = GameDataScrounger.PrototypesOfKind<SpeciesPrototype>();
private BodySystem _bodySystem;
private HumanoidProfileSystem _humanoidProfile;
private MarkingManager _markingManager;
private SharedVisualBodySystem _visualBody;
[SidedDependency(Side.Server)] private BodySystem _bodySystem = default!;
[SidedDependency(Side.Server)] private HumanoidProfileSystem _humanoidProfile = default!;
[SidedDependency(Side.Server)] private MarkingManager _markingManager = default!;
[SidedDependency(Side.Server)] private SharedVisualBodySystem _visualBody = default!;
[Test]
public async Task EnsureValidLoading()
@@ -36,17 +38,15 @@ public sealed class HumanoidProfileTests : GameTest
await server.WaitAssertion(() =>
{
var entityManager = server.ResolveDependency<IEntityManager>();
var humanoidProfile = entityManager.System<HumanoidProfileSystem>();
var human = entityManager.Spawn(BaseSpecies);
humanoidProfile.ApplyProfileTo(human,
LoadDependencies(out var body, out var humanoidComponent);
_humanoidProfile.ApplyProfileTo(body,
new HumanoidCharacterProfile()
.WithSex(Sex.Female)
.WithAge(67)
.WithGender(Gender.Neuter)
.WithSpecies(Vox));
var humanoidComponent = entityManager.GetComponent<HumanoidProfileComponent>(human);
var voiceComponent = entityManager.GetComponent<VocalComponent>(human);
var voiceComponent = SEntMan.GetComponent<VocalComponent>(body);
Assert.That(humanoidComponent.Age, Is.EqualTo(67));
Assert.That(humanoidComponent.Sex, Is.EqualTo(Sex.Female));
@@ -71,6 +71,7 @@ public sealed class HumanoidProfileTests : GameTest
await server.WaitAssertion(() =>
{
LoadDependencies(out var body, out var humanoidComponent);
var profile = HumanoidCharacterProfile.Random();
_humanoidProfile.ApplyProfileTo(body, profile);
_visualBody.ApplyProfileTo(body, profile);
@@ -91,17 +92,17 @@ public sealed class HumanoidProfileTests : GameTest
{
LoadDependencies(out var body, out var humanoidComponent);
var proto = Server.ProtoMan.Index<SpeciesPrototype>(species);
var proto = SProtoMan.Index<SpeciesPrototype>(species);
var profile = HumanoidCharacterProfile.RandomWithSpecies(species);
_humanoidProfile.ApplyProfileTo(body, profile);
_visualBody.ApplyProfileTo(body, profile);
Assert.That(humanoidComponent.Age, Is.LessThanOrEqualTo(proto.MaxAge));
Assert.That(humanoidComponent.Age, Is.GreaterThanOrEqualTo(proto.MinAge));
Assert.That(proto.Sexes.Contains(humanoidComponent.Sex), Is.True);
Assert.That(humanoidComponent.Species, Is.EqualTo(species));
Assert.That(humanoidComponent.Age, Is.LessThanOrEqualTo(proto.MaxAge), $"Expected age is above the maximum age limit! Current: {humanoidComponent.Age} Max: {proto.MaxAge}");
Assert.That(humanoidComponent.Age, Is.GreaterThanOrEqualTo(proto.MinAge), $"Expected age is below the minimum age limit! Current: {humanoidComponent.Age} Min: {proto.MinAge}");
Assert.That(proto.Sexes.Contains(humanoidComponent.Sex), Is.True, $"Character has sex not found in the species prototype! Current: {humanoidComponent.Sex}");
Assert.That(humanoidComponent.Species, Is.EqualTo(species), $"Species does not match! Expected: {species} Current: {humanoidComponent.Species}");
var strategy = Server.ProtoMan.Index(proto.SkinColoration).Strategy;
Assert.That(strategy.VerifySkinColor(profile.Appearance.SkinColor), Is.True);
Assert.That(strategy.VerifySkinColor(profile.Appearance.SkinColor, out var reason), Is.True, $"Failed to verify the skin color from strategy {strategy}. Reason: {reason}");
AssertValidProfile((body, humanoidComponent), profile);
});
@@ -109,29 +110,24 @@ public sealed class HumanoidProfileTests : GameTest
private void LoadDependencies(out EntityUid body, out HumanoidProfileComponent humanoidComponent)
{
var entityManager = Server.ResolveDependency<IEntityManager>();
_humanoidProfile = entityManager.System<HumanoidProfileSystem>();
_markingManager = Server.ResolveDependency<MarkingManager>();
_visualBody = entityManager.System<SharedVisualBodySystem>();
_bodySystem = entityManager.System<BodySystem>();
body = entityManager.Spawn(BaseSpecies);
humanoidComponent = entityManager.GetComponent<HumanoidProfileComponent>(body);
body = SEntMan.Spawn(BaseSpecies);
humanoidComponent = SEntMan.GetComponent<HumanoidProfileComponent>(body);
}
private void AssertValidProfile(Entity<HumanoidProfileComponent> body, HumanoidCharacterProfile profile)
{
_bodySystem.TryGetOrgansWithComponent<VisualOrganComponent>(body.Owner, out var organs);
foreach (var (_, visualOrgan) in organs)
foreach (var (uid, visualOrgan) in organs)
{
Assert.That(visualOrgan.Profile.Sex, Is.EqualTo(profile.Sex));
Assert.That(visualOrgan.Profile.EyeColor, Is.EqualTo(profile.Appearance.EyeColor));
Assert.That(visualOrgan.Profile.SkinColor, Is.EqualTo(profile.Appearance.SkinColor));
Assert.That(visualOrgan.Profile.Sex, Is.EqualTo(profile.Sex), $"Organ {uid} has invalid sex appearance! Expected: {profile.Sex} Current: {visualOrgan.Profile.Sex}");
Assert.That(visualOrgan.Profile.EyeColor, Is.EqualTo(profile.Appearance.EyeColor), $"Organ {uid} has invalid eye color! Expected: {profile.Appearance.EyeColor} Current: {visualOrgan.Profile.EyeColor}");
Assert.That(visualOrgan.Profile.SkinColor, Is.EqualTo(profile.Appearance.SkinColor), $"Organ {uid} has invalid skin color! Expected: {profile.Appearance.SkinColor} Current: {visualOrgan.Profile.SkinColor}");
}
_bodySystem.TryGetOrgansWithComponent<VisualOrganMarkingsComponent>(body.Owner, out var markings);
foreach (var (_, markingOrgan) in markings)
foreach (var (uid, markingOrgan) in markings)
{
// Needed to avoid access restrictions
var data = markingOrgan.MarkingData;
@@ -143,9 +139,9 @@ public sealed class HumanoidProfileTests : GameTest
{
var markingProto = Server.ProtoMan.Index(marking.MarkingId);
Assert.That(markingProto.Sprites.Count, Is.EqualTo(marking.MarkingColors.Count));
Assert.That(_markingManager.CanBeApplied(data.Group, profile.Sex, markingProto), Is.True);
Assert.That(data.Layers.Contains(markingProto.BodyPart), Is.True);
Assert.That(markingProto.Sprites.Count, Is.EqualTo(marking.MarkingColors.Count), $"Organ {uid} has invald amount of marking sprites! Expected: {marking.MarkingColors.Count} Current: {markingProto.Sprites.Count}");
Assert.That(_markingManager.CanBeApplied(data.Group, profile.Sex, markingProto), Is.True, $"Marking {markingProto.ID} cannot be applied to group {data.Group.Id} with sex {profile.Sex}");
Assert.That(data.Layers.Contains(markingProto.BodyPart), Is.True, $"Organ {uid} marking visual layers do not contain an entry for {markingProto.BodyPart}");
if (!markingProto.ForcedColoring && groupProto.Appearances.GetValueOrDefault(markingProto.BodyPart)?.MatchSkin != true)
freeMarkings.Add(marking);
@@ -172,7 +168,7 @@ public sealed class HumanoidProfileTests : GameTest
Is.EqualTo(MarkingColoring.GetMarkingLayerColors(markingProto, profile.Appearance.SkinColor, profile.Appearance.EyeColor, markingOrgan.AppliedMarkings)));
if (markingProto.SexRestriction != null)
Assert.That(markingProto.SexRestriction, Is.EqualTo(profile.Sex));
Assert.That(markingProto.SexRestriction, Is.EqualTo(profile.Sex), $"Marking {markingProto.ID} has invalid sex restriction! Expected: {profile.Sex} Current: {markingProto.SexRestriction}");
}
}
}
@@ -259,6 +259,7 @@ public abstract partial class InteractionTest
/// <summary>
/// Drops the currently held entity.
/// Causes an error if no entity was held.
/// </summary>
protected async Task Drop()
{
@@ -277,6 +278,36 @@ public abstract partial class InteractionTest
Assert.That(HandSys.GetActiveItem((ToServer(Player), Hands)), Is.Null);
}
/// <summary>
/// Drops all currently held entities.
/// Does nothing if no entity was held.
/// </summary>
protected async Task DropAll()
{
await Server.WaitPost(() =>
{
HandSys.DropAll((ToServer(Player), Hands));
});
await RunTicks(1);
// make sure that all hands are empty
Assert.That(HandSys.GetEmptyHandCount((ToServer(Player), Hands)), Is.EqualTo(HandSys.GetHandCount((ToServer(Player), Hands))));
}
/// <summary>
/// Swaps the current hand.
/// </summary>
protected async Task SwapHands(bool reverse = false)
{
await Server.WaitPost(() =>
{
HandSys.SwapHands((ToServer(Player), Hands), reverse: reverse);
});
await RunTicks(1);
}
#region Interact
/// <summary>
@@ -2,55 +2,61 @@ using System.Linq;
using Content.IntegrationTests.Fixtures;
using Content.Shared.Containers.ItemSlots;
using Content.Shared.Whitelist;
using Robust.Shared.GameObjects;
using Robust.Shared.Prototypes;
namespace Content.IntegrationTests.Tests.Utility
{
[TestFixture]
[TestOf(typeof(EntityWhitelist))]
public sealed class EntityWhitelistTest : GameTest
{
private const string InvalidComponent = "Sprite";
private const string ValidComponent = "Physics";
private const string WhitelistProtoId = "WhitelistDummy";
private const string ValidComponentProtoId = "ValidComponentDummy";
private const string WhitelistTestValidTagProtoId = "WhitelistTestValidTagDummy";
private const string InvalidComponentProtoId = "InvalidComponentDummy";
private const string WhitelistTestInvalidTagProtoId = "WhitelistTestInvalidTagDummy";
[TestPrototypes]
private const string Prototypes = $@"
- type: Tag
id: WhitelistTestValidTag
- type: Tag
id: WhitelistTestInvalidTag
- type: entity
id: WhitelistDummy
id: {WhitelistProtoId}
components:
- type: ItemSlots
slots:
slotName:
whitelist:
prototypes:
- ValidPrototypeDummy
components:
- {ValidComponent}
tags:
- WhitelistTestValidTag
- type: entity
id: InvalidComponentDummy
id: {InvalidComponentProtoId}
components:
- type: {InvalidComponent}
- type: entity
id: WhitelistTestInvalidTagDummy
id: {WhitelistTestInvalidTagProtoId}
components:
- type: Tag
tags:
- WhitelistTestInvalidTag
- type: entity
id: ValidComponentDummy
id: {ValidComponentProtoId}
components:
- type: {ValidComponent}
- type: entity
id: WhitelistTestValidTagDummy
id: {WhitelistTestValidTagProtoId}
components:
- type: Tag
tags:
@@ -70,11 +76,17 @@ namespace Content.IntegrationTests.Tests.Utility
await server.WaitAssertion(() =>
{
var validComponent = sEntities.SpawnEntity("ValidComponentDummy", mapCoordinates);
var WhitelistTestValidTag = sEntities.SpawnEntity("WhitelistTestValidTagDummy", mapCoordinates);
var prototypeManager = server.ResolveDependency<IPrototypeManager>();
var invalidComponent = sEntities.SpawnEntity("InvalidComponentDummy", mapCoordinates);
var WhitelistTestInvalidTag = sEntities.SpawnEntity("WhitelistTestInvalidTagDummy", mapCoordinates);
var validComponentProto = prototypeManager.Index(ValidComponentProtoId);
var whitelistTestValidTagProto = prototypeManager.Index(WhitelistTestValidTagProtoId);
var invalidComponentProto = prototypeManager.Index(InvalidComponentProtoId);
var whitelistTestInvalidTagProto = prototypeManager.Index(WhitelistTestInvalidTagProtoId);
var validComponentUid = sEntities.SpawnEntity(ValidComponentProtoId, mapCoordinates);
var whitelistTestValidTagUid = sEntities.SpawnEntity(WhitelistTestValidTagProtoId, mapCoordinates);
var invalidComponentUid = sEntities.SpawnEntity(InvalidComponentProtoId, mapCoordinates);
var whitelistTestInvalidTagUid = sEntities.SpawnEntity(WhitelistTestInvalidTagProtoId, mapCoordinates);
// Test instantiated on its own
var whitelistInst = new EntityWhitelist
@@ -85,15 +97,25 @@ namespace Content.IntegrationTests.Tests.Utility
Assert.Multiple(() =>
{
Assert.That(sys.IsValid(whitelistInst, validComponent), Is.True);
Assert.That(sys.IsValid(whitelistInst, WhitelistTestValidTag), Is.True);
Assert.That(sys.IsValid(whitelistInst, validComponentUid), Is.True);
Assert.That(sys.IsValid(whitelistInst, validComponentProto), Is.True);
Assert.That(sys.IsValid(whitelistInst, ValidComponentProtoId), Is.True);
Assert.That(sys.IsValid(whitelistInst, invalidComponent), Is.False);
Assert.That(sys.IsValid(whitelistInst, WhitelistTestInvalidTag), Is.False);
Assert.That(sys.IsValid(whitelistInst, whitelistTestValidTagUid), Is.True);
Assert.That(sys.IsValid(whitelistInst, whitelistTestValidTagProto), Is.True);
Assert.That(sys.IsValid(whitelistInst, WhitelistTestValidTagProtoId), Is.True);
Assert.That(sys.IsValid(whitelistInst, invalidComponentUid), Is.False);
Assert.That(sys.IsValid(whitelistInst, invalidComponentProto), Is.False);
Assert.That(sys.IsValid(whitelistInst, InvalidComponentProtoId), Is.False);
Assert.That(sys.IsValid(whitelistInst, whitelistTestInvalidTagUid), Is.False);
Assert.That(sys.IsValid(whitelistInst, whitelistTestInvalidTagProto), Is.False);
Assert.That(sys.IsValid(whitelistInst, WhitelistTestInvalidTagProtoId), Is.False);
});
// Test from serialized
var dummy = sEntities.SpawnEntity("WhitelistDummy", mapCoordinates);
var dummy = sEntities.SpawnEntity(WhitelistProtoId, mapCoordinates);
var whitelistSer = sEntities.GetComponent<ItemSlotsComponent>(dummy).Slots.Values.First().Whitelist;
Assert.That(whitelistSer, Is.Not.Null);
@@ -105,11 +127,21 @@ namespace Content.IntegrationTests.Tests.Utility
Assert.Multiple(() =>
{
Assert.That(sys.IsValid(whitelistSer, validComponent), Is.True);
Assert.That(sys.IsValid(whitelistSer, WhitelistTestValidTag), Is.True);
Assert.That(sys.IsValid(whitelistSer, validComponentUid), Is.True);
Assert.That(sys.IsValid(whitelistSer, validComponentProto), Is.True);
Assert.That(sys.IsValid(whitelistSer, ValidComponentProtoId), Is.True);
Assert.That(sys.IsValid(whitelistSer, invalidComponent), Is.False);
Assert.That(sys.IsValid(whitelistSer, WhitelistTestInvalidTag), Is.False);
Assert.That(sys.IsValid(whitelistSer, whitelistTestValidTagUid), Is.True);
Assert.That(sys.IsValid(whitelistSer, whitelistTestValidTagProto), Is.True);
Assert.That(sys.IsValid(whitelistSer, WhitelistTestValidTagProtoId), Is.True);
Assert.That(sys.IsValid(whitelistSer, invalidComponentUid), Is.False);
Assert.That(sys.IsValid(whitelistSer, invalidComponentProto), Is.False);
Assert.That(sys.IsValid(whitelistSer, InvalidComponentProtoId), Is.False);
Assert.That(sys.IsValid(whitelistSer, whitelistTestInvalidTagUid), Is.False);
Assert.That(sys.IsValid(whitelistSer, whitelistTestInvalidTagProto), Is.False);
Assert.That(sys.IsValid(whitelistSer, WhitelistTestInvalidTagProtoId), Is.False);
});
});
}
+199 -235
View File
@@ -1,5 +1,6 @@
using System.Linq;
using Content.IntegrationTests.Fixtures;
using Content.IntegrationTests.Fixtures.Attributes;
using Content.Shared.Xenoarchaeology.Artifact;
using Content.Shared.Xenoarchaeology.Artifact.Components;
using Robust.Shared.GameObjects;
@@ -7,12 +8,21 @@ using Robust.Shared.GameObjects;
namespace Content.IntegrationTests.Tests;
[TestFixture]
[TestOf(typeof(SharedXenoArtifactSystem))]
public sealed class XenoArtifactTest : GameTest
{
private const string TestArtifact = "TestArtifact";
private const string TestArtifactNode = "TestArtifactNode";
private const string TestGenArtifactFlat = "TestGenArtifactFlat";
private const string TestGenArtifactTall = "TestGenArtifactTall";
private const string TestGenArtifactFull = "TestGenArtifactFull";
[SidedDependency(Side.Server)] private SharedXenoArtifactSystem _sArtifactSystem = null!;
[TestPrototypes]
private const string Prototypes = @"
private const string Prototypes = $@"
- type: entity
id: TestArtifact
id: {TestArtifact}
parent: BaseXenoArtifact
name: artifact
components:
@@ -22,7 +32,7 @@ public sealed class XenoArtifactTest : GameTest
tableId: XenoArtifactEffectsDefaultTable
- type: entity
id: TestGenArtifactFlat
id: {TestGenArtifactFlat}
parent: BaseXenoArtifact
name: artifact
components:
@@ -41,7 +51,7 @@ public sealed class XenoArtifactTest : GameTest
tableId: XenoArtifactEffectsDefaultTable
- type: entity
id: TestGenArtifactTall
id: {TestGenArtifactTall}
parent: BaseXenoArtifact
name: artifact
components:
@@ -60,7 +70,7 @@ public sealed class XenoArtifactTest : GameTest
tableId: XenoArtifactEffectsDefaultTable
- type: entity
id: TestGenArtifactFull
id: {TestGenArtifactFull}
name: artifact
components:
- type: XenoArtifact
@@ -78,7 +88,7 @@ public sealed class XenoArtifactTest : GameTest
tableId: XenoArtifactEffectsDefaultTable
- type: entity
id: TestArtifactNode
id: {TestArtifactNode}
name: artifact node
components:
- type: XenoArtifactNode
@@ -89,314 +99,268 @@ public sealed class XenoArtifactTest : GameTest
/// Checks that adding nodes and edges properly adds them into the adjacency matrix
/// </summary>
[Test]
[Description("Checks that adding nodes and edges properly adds them into the adjacency matrix")]
[RunOnSide(Side.Server)]
public async Task XenoArtifactAddNodeTest()
{
var pair = Pair;
var server = pair.Server;
var artifactUid = SSpawn(TestArtifact);
var artifactEnt = (artifactUid, comp: SComp<XenoArtifactComponent>(artifactUid));
var entManager = server.ResolveDependency<IEntityManager>();
var artifactSystem = entManager.System<SharedXenoArtifactSystem>();
// Create 3 nodes
Assert.That(_sArtifactSystem.AddNode(artifactEnt, TestArtifactNode, out var node1, false));
Assert.That(_sArtifactSystem.AddNode(artifactEnt, TestArtifactNode, out var node2, false));
Assert.That(_sArtifactSystem.AddNode(artifactEnt, TestArtifactNode, out var node3, false));
await server.WaitPost(() =>
{
var artifactUid = entManager.Spawn("TestArtifact");
var artifactEnt = (artifactUid, comp: entManager.GetComponent<XenoArtifactComponent>(artifactUid));
Assert.That(_sArtifactSystem.GetAllNodeIndices(artifactEnt).Count(), Is.EqualTo(3));
// Create 3 nodes
Assert.That(artifactSystem.AddNode(artifactEnt, "TestArtifactNode", out var node1, false));
Assert.That(artifactSystem.AddNode(artifactEnt, "TestArtifactNode", out var node2, false));
Assert.That(artifactSystem.AddNode(artifactEnt, "TestArtifactNode", out var node3, false));
// Add connection from 1 -> 2 and 2-> 3
_sArtifactSystem.AddEdge(artifactEnt, node1!.Value, node2!.Value, false);
_sArtifactSystem.AddEdge(artifactEnt, node2!.Value, node3!.Value, false);
Assert.That(artifactSystem.GetAllNodeIndices(artifactEnt).Count(), Is.EqualTo(3));
// Assert that successors and direct successors are counted correctly for node 1.
Assert.That(_sArtifactSystem.GetDirectSuccessorNodes(artifactEnt, node1!.Value), Has.Count.EqualTo(1));
Assert.That(_sArtifactSystem.GetSuccessorNodes(artifactEnt, node1!.Value), Has.Count.EqualTo(2));
// Assert that we didn't somehow get predecessors on node 1.
Assert.That(_sArtifactSystem.GetDirectPredecessorNodes(artifactEnt, node1!.Value), Is.Empty);
Assert.That(_sArtifactSystem.GetPredecessorNodes(artifactEnt, node1!.Value), Is.Empty);
// Add connection from 1 -> 2 and 2-> 3
artifactSystem.AddEdge(artifactEnt, node1!.Value, node2!.Value, false);
artifactSystem.AddEdge(artifactEnt, node2!.Value, node3!.Value, false);
// Assert that successors and direct successors are counted correctly for node 2.
Assert.That(_sArtifactSystem.GetDirectSuccessorNodes(artifactEnt, node2!.Value), Has.Count.EqualTo(1));
Assert.That(_sArtifactSystem.GetSuccessorNodes(artifactEnt, node2!.Value), Has.Count.EqualTo(1));
// Assert that predecessors and direct predecessors are counted correctly for node 2.
Assert.That(_sArtifactSystem.GetDirectPredecessorNodes(artifactEnt, node2!.Value), Has.Count.EqualTo(1));
Assert.That(_sArtifactSystem.GetPredecessorNodes(artifactEnt, node2!.Value), Has.Count.EqualTo(1));
// Assert that successors and direct successors are counted correctly for node 1.
Assert.That(artifactSystem.GetDirectSuccessorNodes(artifactEnt, node1!.Value).Count, Is.EqualTo(1));
Assert.That(artifactSystem.GetSuccessorNodes(artifactEnt, node1!.Value).Count, Is.EqualTo(2));
// Assert that we didn't somehow get predecessors on node 1.
Assert.That(artifactSystem.GetDirectPredecessorNodes(artifactEnt, node1!.Value), Is.Empty);
Assert.That(artifactSystem.GetPredecessorNodes(artifactEnt, node1!.Value), Is.Empty);
// Assert that successors and direct successors are counted correctly for node 2.
Assert.That(artifactSystem.GetDirectSuccessorNodes(artifactEnt, node2!.Value), Has.Count.EqualTo(1));
Assert.That(artifactSystem.GetSuccessorNodes(artifactEnt, node2!.Value), Has.Count.EqualTo(1));
// Assert that predecessors and direct predecessors are counted correctly for node 2.
Assert.That(artifactSystem.GetDirectPredecessorNodes(artifactEnt, node2!.Value), Has.Count.EqualTo(1));
Assert.That(artifactSystem.GetPredecessorNodes(artifactEnt, node2!.Value), Has.Count.EqualTo(1));
// Assert that successors and direct successors are counted correctly for node 3.
Assert.That(artifactSystem.GetDirectSuccessorNodes(artifactEnt, node3!.Value), Is.Empty);
Assert.That(artifactSystem.GetSuccessorNodes(artifactEnt, node3!.Value), Is.Empty);
// Assert that predecessors and direct predecessors are counted correctly for node 3.
Assert.That(artifactSystem.GetDirectPredecessorNodes(artifactEnt, node3!.Value), Has.Count.EqualTo(1));
Assert.That(artifactSystem.GetPredecessorNodes(artifactEnt, node3!.Value), Has.Count.EqualTo(2));
});
// Assert that successors and direct successors are counted correctly for node 3.
Assert.That(_sArtifactSystem.GetDirectSuccessorNodes(artifactEnt, node3!.Value), Is.Empty);
Assert.That(_sArtifactSystem.GetSuccessorNodes(artifactEnt, node3!.Value), Is.Empty);
// Assert that predecessors and direct predecessors are counted correctly for node 3.
Assert.That(_sArtifactSystem.GetDirectPredecessorNodes(artifactEnt, node3!.Value), Has.Count.EqualTo(1));
Assert.That(_sArtifactSystem.GetPredecessorNodes(artifactEnt, node3!.Value), Has.Count.EqualTo(2));
}
/// <summary>
/// Checks to make sure that removing nodes properly cleans up all connections.
/// </summary>
[Test]
[Description("Checks to make sure that removing nodes properly cleans up all connections.")]
[RunOnSide(Side.Server)]
public async Task XenoArtifactRemoveNodeTest()
{
var pair = Pair;
var server = pair.Server;
var artifactUid = SSpawn(TestArtifact);
var artifactEnt = (artifactUid, comp: SComp<XenoArtifactComponent>(artifactUid));
var entManager = server.ResolveDependency<IEntityManager>();
var artifactSystem = entManager.System<SharedXenoArtifactSystem>();
// Create 3 nodes
Assert.That(_sArtifactSystem.AddNode(artifactEnt, TestArtifactNode, out var node1, false));
Assert.That(_sArtifactSystem.AddNode(artifactEnt, TestArtifactNode, out var node2, false));
Assert.That(_sArtifactSystem.AddNode(artifactEnt, TestArtifactNode, out var node3, false));
Assert.That(_sArtifactSystem.AddNode(artifactEnt, TestArtifactNode, out var node4, false));
Assert.That(_sArtifactSystem.AddNode(artifactEnt, TestArtifactNode, out var node5, false));
await server.WaitPost(() =>
{
var artifactUid = entManager.Spawn("TestArtifact");
var artifactEnt = (artifactUid, comp: entManager.GetComponent<XenoArtifactComponent>(artifactUid));
Assert.That(_sArtifactSystem.GetAllNodeIndices(artifactEnt).Count(), Is.EqualTo(5));
// Create 3 nodes
Assert.That(artifactSystem.AddNode(artifactEnt, "TestArtifactNode", out var node1, false));
Assert.That(artifactSystem.AddNode(artifactEnt, "TestArtifactNode", out var node2, false));
Assert.That(artifactSystem.AddNode(artifactEnt, "TestArtifactNode", out var node3, false));
Assert.That(artifactSystem.AddNode(artifactEnt, "TestArtifactNode", out var node4, false));
Assert.That(artifactSystem.AddNode(artifactEnt, "TestArtifactNode", out var node5, false));
// Add connection: 1 -> 2 -> 3 -> 4 -> 5
_sArtifactSystem.AddEdge(artifactEnt, node1!.Value, node2!.Value, false);
_sArtifactSystem.AddEdge(artifactEnt, node2!.Value, node3!.Value, false);
_sArtifactSystem.AddEdge(artifactEnt, node3!.Value, node4!.Value, false);
_sArtifactSystem.AddEdge(artifactEnt, node4!.Value, node5!.Value, false);
Assert.That(artifactSystem.GetAllNodeIndices(artifactEnt).Count(), Is.EqualTo(5));
// Make sure we have a continuous connection between the two ends of the graph.
Assert.That(_sArtifactSystem.GetSuccessorNodes(artifactEnt, node1.Value), Has.Count.EqualTo(4));
Assert.That(_sArtifactSystem.GetPredecessorNodes(artifactEnt, node5.Value), Has.Count.EqualTo(4));
// Add connection: 1 -> 2 -> 3 -> 4 -> 5
artifactSystem.AddEdge(artifactEnt, node1!.Value, node2!.Value, false);
artifactSystem.AddEdge(artifactEnt, node2!.Value, node3!.Value, false);
artifactSystem.AddEdge(artifactEnt, node3!.Value, node4!.Value, false);
artifactSystem.AddEdge(artifactEnt, node4!.Value, node5!.Value, false);
// Remove the node and make sure it's no longer in the artifact.
Assert.That(_sArtifactSystem.RemoveNode(artifactEnt, node3!.Value, false));
Assert.That(_sArtifactSystem.TryGetIndex(artifactEnt, node3!.Value, out _), Is.False, "Node 3 still present in artifact.");
// Make sure we have a continuous connection between the two ends of the graph.
Assert.That(artifactSystem.GetSuccessorNodes(artifactEnt, node1.Value), Has.Count.EqualTo(4));
Assert.That(artifactSystem.GetPredecessorNodes(artifactEnt, node5.Value), Has.Count.EqualTo(4));
// Remove the node and make sure it's no longer in the artifact.
Assert.That(artifactSystem.RemoveNode(artifactEnt, node3!.Value, false));
Assert.That(artifactSystem.TryGetIndex(artifactEnt, node3!.Value, out _), Is.False, "Node 3 still present in artifact.");
// Check to make sure that we got rid of all the connections.
Assert.That(artifactSystem.GetSuccessorNodes(artifactEnt, node2!.Value), Is.Empty);
Assert.That(artifactSystem.GetPredecessorNodes(artifactEnt, node4!.Value), Is.Empty);
});
// Check to make sure that we got rid of all the connections.
Assert.That(_sArtifactSystem.GetSuccessorNodes(artifactEnt, node2!.Value), Is.Empty);
Assert.That(_sArtifactSystem.GetPredecessorNodes(artifactEnt, node4!.Value), Is.Empty);
}
/// <summary>
/// Sets up series of linked nodes and ensures that resizing the adjacency matrix doesn't disturb the connections
/// </summary>
[Test]
[Description("Sets up series of linked nodes and ensures that resizing the adjacency matrix doesn't disturb the connections")]
[RunOnSide(Side.Server)]
public async Task XenoArtifactResizeTest()
{
var pair = Pair;
var server = pair.Server;
var artifactUid = SSpawn(TestArtifact);
var artifactEnt = (artifactUid, comp: SComp<XenoArtifactComponent>(artifactUid));
var entManager = server.ResolveDependency<IEntityManager>();
var artifactSystem = entManager.System<SharedXenoArtifactSystem>();
// Create 3 nodes
Assert.That(_sArtifactSystem.AddNode(artifactEnt, TestArtifactNode, out var node1, false));
Assert.That(_sArtifactSystem.AddNode(artifactEnt, TestArtifactNode, out var node2, false));
Assert.That(_sArtifactSystem.AddNode(artifactEnt, TestArtifactNode, out var node3, false));
await server.WaitPost(() =>
{
var artifactUid = entManager.Spawn("TestArtifact");
var artifactEnt = (artifactUid, comp: entManager.GetComponent<XenoArtifactComponent>(artifactUid));
// Add connection: 1 -> 2 -> 3
_sArtifactSystem.AddEdge(artifactEnt, node1!.Value, node2!.Value, false);
_sArtifactSystem.AddEdge(artifactEnt, node2!.Value, node3!.Value, false);
// Create 3 nodes
Assert.That(artifactSystem.AddNode(artifactEnt, "TestArtifactNode", out var node1, false));
Assert.That(artifactSystem.AddNode(artifactEnt, "TestArtifactNode", out var node2, false));
Assert.That(artifactSystem.AddNode(artifactEnt, "TestArtifactNode", out var node3, false));
// Make sure our connection is set up
Assert.That(_sArtifactSystem.NodeHasEdge(artifactEnt, node1.Value, node2.Value));
Assert.That(_sArtifactSystem.NodeHasEdge(artifactEnt, node2.Value, node3.Value));
Assert.That(_sArtifactSystem.NodeHasEdge(artifactEnt, node2.Value, node1.Value), Is.False);
Assert.That(_sArtifactSystem.NodeHasEdge(artifactEnt, node3.Value, node2.Value), Is.False);
Assert.That(_sArtifactSystem.NodeHasEdge(artifactEnt, node1.Value, node3.Value), Is.False);
Assert.That(_sArtifactSystem.NodeHasEdge(artifactEnt, node3.Value, node1.Value), Is.False);
// Add connection: 1 -> 2 -> 3
artifactSystem.AddEdge(artifactEnt, node1!.Value, node2!.Value, false);
artifactSystem.AddEdge(artifactEnt, node2!.Value, node3!.Value, false);
Assert.That(_sArtifactSystem.GetIndex(artifactEnt, node1!.Value), Is.Zero);
Assert.That(_sArtifactSystem.GetIndex(artifactEnt, node2!.Value), Is.EqualTo(1));
Assert.That(_sArtifactSystem.GetIndex(artifactEnt, node3!.Value), Is.EqualTo(2));
// Make sure our connection is set up
Assert.That(artifactSystem.NodeHasEdge(artifactEnt, node1.Value, node2.Value));
Assert.That(artifactSystem.NodeHasEdge(artifactEnt, node2.Value, node3.Value));
Assert.That(artifactSystem.NodeHasEdge(artifactEnt, node2.Value, node1.Value), Is.False);
Assert.That(artifactSystem.NodeHasEdge(artifactEnt, node3.Value, node2.Value), Is.False);
Assert.That(artifactSystem.NodeHasEdge(artifactEnt, node1.Value, node3.Value), Is.False);
Assert.That(artifactSystem.NodeHasEdge(artifactEnt, node3.Value, node1.Value), Is.False);
// Add a new node, resizing the original adjacency matrix and array.
Assert.That(_sArtifactSystem.AddNode(artifactEnt, TestArtifactNode, out var node4));
Assert.That(artifactSystem.GetIndex(artifactEnt, node1!.Value), Is.EqualTo(0));
Assert.That(artifactSystem.GetIndex(artifactEnt, node2!.Value), Is.EqualTo(1));
Assert.That(artifactSystem.GetIndex(artifactEnt, node3!.Value), Is.EqualTo(2));
// Check that our connections haven't changed.
Assert.That(_sArtifactSystem.NodeHasEdge(artifactEnt, node1.Value, node2.Value));
Assert.That(_sArtifactSystem.NodeHasEdge(artifactEnt, node2.Value, node3.Value));
Assert.That(_sArtifactSystem.NodeHasEdge(artifactEnt, node2.Value, node1.Value), Is.False);
Assert.That(_sArtifactSystem.NodeHasEdge(artifactEnt, node3.Value, node2.Value), Is.False);
Assert.That(_sArtifactSystem.NodeHasEdge(artifactEnt, node1.Value, node3.Value), Is.False);
Assert.That(_sArtifactSystem.NodeHasEdge(artifactEnt, node3.Value, node1.Value), Is.False);
// Add a new node, resizing the original adjacency matrix and array.
Assert.That(artifactSystem.AddNode(artifactEnt, "TestArtifactNode", out var node4));
// Has our array shifted any when we resized?
Assert.That(_sArtifactSystem.GetIndex(artifactEnt, node1!.Value), Is.Zero);
Assert.That(_sArtifactSystem.GetIndex(artifactEnt, node2!.Value), Is.EqualTo(1));
Assert.That(_sArtifactSystem.GetIndex(artifactEnt, node3!.Value), Is.EqualTo(2));
// Check that our connections haven't changed.
Assert.That(artifactSystem.NodeHasEdge(artifactEnt, node1.Value, node2.Value));
Assert.That(artifactSystem.NodeHasEdge(artifactEnt, node2.Value, node3.Value));
Assert.That(artifactSystem.NodeHasEdge(artifactEnt, node2.Value, node1.Value), Is.False);
Assert.That(artifactSystem.NodeHasEdge(artifactEnt, node3.Value, node2.Value), Is.False);
Assert.That(artifactSystem.NodeHasEdge(artifactEnt, node1.Value, node3.Value), Is.False);
Assert.That(artifactSystem.NodeHasEdge(artifactEnt, node3.Value, node1.Value), Is.False);
// Has our array shifted any when we resized?
Assert.That(artifactSystem.GetIndex(artifactEnt, node1!.Value), Is.EqualTo(0));
Assert.That(artifactSystem.GetIndex(artifactEnt, node2!.Value), Is.EqualTo(1));
Assert.That(artifactSystem.GetIndex(artifactEnt, node3!.Value), Is.EqualTo(2));
// Check that 4 didn't somehow end up with connections
Assert.That(artifactSystem.GetPredecessorNodes(artifactEnt, node4!.Value), Is.Empty);
Assert.That(artifactSystem.GetSuccessorNodes(artifactEnt, node4!.Value), Is.Empty);
});
// Check that 4 didn't somehow end up with connections
Assert.That(_sArtifactSystem.GetPredecessorNodes(artifactEnt, node4!.Value), Is.Empty);
Assert.That(_sArtifactSystem.GetSuccessorNodes(artifactEnt, node4!.Value), Is.Empty);
}
/// <summary>
/// Checks if removing a node and adding a new node into its place in the adjacency matrix doesn't accidentally retain extra data.
/// </summary>
[Test]
[Description("Checks if removing a node and adding a new node into its place in the adjacency matrix doesn't accidentally retain extra data.")]
[RunOnSide(Side.Server)]
public async Task XenoArtifactReplaceTest()
{
var pair = Pair;
var server = pair.Server;
var artifactUid = SSpawn(TestArtifact);
var artifactEnt = (artifactUid, Comp: SComp<XenoArtifactComponent>(artifactUid));
var entManager = server.ResolveDependency<IEntityManager>();
var artifactSystem = entManager.System<SharedXenoArtifactSystem>();
// Create 3 nodes
Assert.That(_sArtifactSystem.AddNode(artifactEnt, TestArtifactNode, out var node1, false));
Assert.That(_sArtifactSystem.AddNode(artifactEnt, TestArtifactNode, out var node2, false));
Assert.That(_sArtifactSystem.AddNode(artifactEnt, TestArtifactNode, out var node3, false));
await server.WaitPost(() =>
{
var artifactUid = entManager.Spawn("TestArtifact");
var artifactEnt = (artifactUid, comp: entManager.GetComponent<XenoArtifactComponent>(artifactUid));
// Add connection: 1 -> 2 -> 3
_sArtifactSystem.AddEdge(artifactEnt, node1!.Value, node2!.Value, false);
_sArtifactSystem.AddEdge(artifactEnt, node2!.Value, node3!.Value, false);
// Create 3 nodes
Assert.That(artifactSystem.AddNode(artifactEnt, "TestArtifactNode", out var node1, false));
Assert.That(artifactSystem.AddNode(artifactEnt, "TestArtifactNode", out var node2, false));
Assert.That(artifactSystem.AddNode(artifactEnt, "TestArtifactNode", out var node3, false));
// Make sure our connection is set up
Assert.That(_sArtifactSystem.NodeHasEdge(artifactEnt, node1.Value, node2.Value));
Assert.That(_sArtifactSystem.NodeHasEdge(artifactEnt, node2.Value, node3.Value));
// Add connection: 1 -> 2 -> 3
artifactSystem.AddEdge(artifactEnt, node1!.Value, node2!.Value, false);
artifactSystem.AddEdge(artifactEnt, node2!.Value, node3!.Value, false);
// Remove middle node, severing connections
_sArtifactSystem.RemoveNode(artifactEnt, node2!.Value, false);
// Make sure our connection is set up
Assert.That(artifactSystem.NodeHasEdge(artifactEnt, node1.Value, node2.Value));
Assert.That(artifactSystem.NodeHasEdge(artifactEnt, node2.Value, node3.Value));
// Make sure our connection are properly severed.
Assert.That(_sArtifactSystem.GetSuccessorNodes(artifactEnt, node1.Value), Is.Empty);
Assert.That(_sArtifactSystem.GetPredecessorNodes(artifactEnt, node3.Value), Is.Empty);
// Remove middle node, severing connections
artifactSystem.RemoveNode(artifactEnt, node2!.Value, false);
// Make sure our matrix is 3x3
Assert.That(artifactEnt.Comp.NodeAdjacencyMatrixRows, Is.EqualTo(3));
Assert.That(artifactEnt.Comp.NodeAdjacencyMatrixColumns, Is.EqualTo(3));
// Make sure our connection are properly severed.
Assert.That(artifactSystem.GetSuccessorNodes(artifactEnt, node1.Value), Is.Empty);
Assert.That(artifactSystem.GetPredecessorNodes(artifactEnt, node3.Value), Is.Empty);
Assert.That(_sArtifactSystem.AddNode(artifactEnt, TestArtifactNode, out var node4, false));
// Make sure our matrix is 3x3
Assert.That(artifactEnt.Item2.NodeAdjacencyMatrixRows, Is.EqualTo(3));
Assert.That(artifactEnt.Item2.NodeAdjacencyMatrixColumns, Is.EqualTo(3));
// Make sure that adding in a new node didn't add a new slot but instead re-used the middle slot.
Assert.That(artifactEnt.Comp.NodeAdjacencyMatrixRows, Is.EqualTo(3));
Assert.That(artifactEnt.Comp.NodeAdjacencyMatrixColumns, Is.EqualTo(3));
Assert.That(artifactSystem.AddNode(artifactEnt, "TestArtifactNode", out var node4, false));
// Make sure that adding in a new node didn't add a new slot but instead re-used the middle slot.
Assert.That(artifactEnt.Item2.NodeAdjacencyMatrixRows, Is.EqualTo(3));
Assert.That(artifactEnt.Item2.NodeAdjacencyMatrixColumns, Is.EqualTo(3));
// Ensure that all connections are still severed
Assert.That(artifactSystem.GetSuccessorNodes(artifactEnt, node1.Value), Is.Empty);
Assert.That(artifactSystem.GetPredecessorNodes(artifactEnt, node3.Value), Is.Empty);
Assert.That(artifactSystem.GetSuccessorNodes(artifactEnt, node4!.Value), Is.Empty);
Assert.That(artifactSystem.GetPredecessorNodes(artifactEnt, node4!.Value), Is.Empty);
});
// Ensure that all connections are still severed
Assert.That(_sArtifactSystem.GetSuccessorNodes(artifactEnt, node1.Value), Is.Empty);
Assert.That(_sArtifactSystem.GetPredecessorNodes(artifactEnt, node3.Value), Is.Empty);
Assert.That(_sArtifactSystem.GetSuccessorNodes(artifactEnt, node4!.Value), Is.Empty);
Assert.That(_sArtifactSystem.GetPredecessorNodes(artifactEnt, node4!.Value), Is.Empty);
}
/// <summary>
/// Checks if the active nodes are properly detected.
/// </summary>
[Test]
[Description("Checks if the active nodes are properly detected.")]
[RunOnSide(Side.Server)]
public async Task XenoArtifactBuildActiveNodesTest()
{
var pair = Pair;
var server = pair.Server;
var artifactUid = SSpawn(TestArtifact);
Entity<XenoArtifactComponent> artifactEnt = (artifactUid, SComp<XenoArtifactComponent>(artifactUid));
var entManager = server.ResolveDependency<IEntityManager>();
var artifactSystem = entManager.System<SharedXenoArtifactSystem>();
Assert.That(_sArtifactSystem.AddNode(artifactEnt, TestArtifactNode, out var node1, false));
Assert.That(_sArtifactSystem.AddNode(artifactEnt, TestArtifactNode, out var node2, false));
Assert.That(_sArtifactSystem.AddNode(artifactEnt, TestArtifactNode, out var node3, false));
Assert.That(_sArtifactSystem.AddNode(artifactEnt, TestArtifactNode, out var node4, false));
Assert.That(_sArtifactSystem.AddNode(artifactEnt, TestArtifactNode, out var node5, false));
Assert.That(_sArtifactSystem.AddNode(artifactEnt, TestArtifactNode, out var node6, false));
Assert.That(_sArtifactSystem.AddNode(artifactEnt, TestArtifactNode, out var node7, false));
Assert.That(_sArtifactSystem.AddNode(artifactEnt, TestArtifactNode, out var node8, false));
await server.WaitPost(() =>
{
var artifactUid = entManager.Spawn("TestArtifact");
Entity<XenoArtifactComponent> artifactEnt = (artifactUid, entManager.GetComponent<XenoArtifactComponent>(artifactUid));
// /----( 6 )
// /----[*3 ]-/----( 7 )----( 8 )
// /
// / /----[*5 ]
// [ 1 ]--/----[ 2 ]--/----( 4 )
// Diagram of the example generation. Nodes in [brackets] are unlocked, nodes in (braces) are locked
// and nodes with an *asterisk are supposed to be active.
_sArtifactSystem.AddEdge(artifactEnt, node1!.Value, node2!.Value, false);
_sArtifactSystem.AddEdge(artifactEnt, node1!.Value, node3!.Value, false);
Assert.That(artifactSystem.AddNode(artifactEnt, "TestArtifactNode", out var node1, false));
Assert.That(artifactSystem.AddNode(artifactEnt, "TestArtifactNode", out var node2, false));
Assert.That(artifactSystem.AddNode(artifactEnt, "TestArtifactNode", out var node3, false));
Assert.That(artifactSystem.AddNode(artifactEnt, "TestArtifactNode", out var node4, false));
Assert.That(artifactSystem.AddNode(artifactEnt, "TestArtifactNode", out var node5, false));
Assert.That(artifactSystem.AddNode(artifactEnt, "TestArtifactNode", out var node6, false));
Assert.That(artifactSystem.AddNode(artifactEnt, "TestArtifactNode", out var node7, false));
Assert.That(artifactSystem.AddNode(artifactEnt, "TestArtifactNode", out var node8, false));
_sArtifactSystem.AddEdge(artifactEnt, node2!.Value, node4!.Value, false);
_sArtifactSystem.AddEdge(artifactEnt, node2!.Value, node5!.Value, false);
// /----( 6 )
// /----[*3 ]-/----( 7 )----( 8 )
// /
// / /----[*5 ]
// [ 1 ]--/----[ 2 ]--/----( 4 )
// Diagram of the example generation. Nodes in [brackets] are unlocked, nodes in (braces) are locked
// and nodes with an *asterisk are supposed to be active.
artifactSystem.AddEdge(artifactEnt, node1!.Value, node2!.Value, false);
artifactSystem.AddEdge(artifactEnt, node1!.Value, node3!.Value, false);
_sArtifactSystem.AddEdge(artifactEnt, node3!.Value, node6!.Value, false);
_sArtifactSystem.AddEdge(artifactEnt, node3!.Value, node7!.Value, false);
artifactSystem.AddEdge(artifactEnt, node2!.Value, node4!.Value, false);
artifactSystem.AddEdge(artifactEnt, node2!.Value, node5!.Value, false);
_sArtifactSystem.AddEdge(artifactEnt, node7!.Value, node8!.Value, false);
artifactSystem.AddEdge(artifactEnt, node3!.Value, node6!.Value, false);
artifactSystem.AddEdge(artifactEnt, node3!.Value, node7!.Value, false);
_sArtifactSystem.SetNodeUnlocked(node1!.Value);
_sArtifactSystem.SetNodeUnlocked(node2!.Value);
_sArtifactSystem.SetNodeUnlocked(node3!.Value);
_sArtifactSystem.SetNodeUnlocked(node5!.Value);
artifactSystem.AddEdge(artifactEnt, node7!.Value, node8!.Value, false);
artifactSystem.SetNodeUnlocked(node1!.Value);
artifactSystem.SetNodeUnlocked(node2!.Value);
artifactSystem.SetNodeUnlocked(node3!.Value);
artifactSystem.SetNodeUnlocked(node5!.Value);
NetEntity[] expectedActiveNodes =
[
entManager.GetNetEntity(node3!.Value.Owner),
entManager.GetNetEntity(node5!.Value.Owner)
];
Assert.That(artifactEnt.Comp.CachedActiveNodes, Is.SupersetOf(expectedActiveNodes));
Assert.That(artifactEnt.Comp.CachedActiveNodes, Has.Count.EqualTo(expectedActiveNodes.Length));
});
NetEntity[] expectedActiveNodes =
[
SEntMan.GetNetEntity(node3!.Value.Owner),
SEntMan.GetNetEntity(node5!.Value.Owner)
];
Assert.That(artifactEnt.Comp.CachedActiveNodes, Is.SupersetOf(expectedActiveNodes));
Assert.That(artifactEnt.Comp.CachedActiveNodes, Has.Count.EqualTo(expectedActiveNodes.Length));
}
[Test]
[RunOnSide(Side.Server)]
public async Task XenoArtifactGenerateSegmentsTest()
{
var pair = Pair;
var server = pair.Server;
var artifact1Uid = SSpawn(TestGenArtifactFlat);
Entity<XenoArtifactComponent> artifact1Ent = (artifact1Uid, SComp<XenoArtifactComponent>(artifact1Uid));
var entManager = server.ResolveDependency<IEntityManager>();
var artifactSystem = entManager.System<SharedXenoArtifactSystem>();
var segments1 = _sArtifactSystem.GetSegments(artifact1Ent);
Assert.That(segments1, Has.Count.EqualTo(2));
Assert.That(segments1[0], Has.Count.EqualTo(1));
Assert.That(segments1[1], Has.Count.EqualTo(1));
await server.WaitPost(() =>
{
var artifact1Uid = entManager.Spawn("TestGenArtifactFlat");
Entity<XenoArtifactComponent> artifact1Ent = (artifact1Uid, entManager.GetComponent<XenoArtifactComponent>(artifact1Uid));
var artifact2Uid = SSpawn(TestGenArtifactTall);
Entity<XenoArtifactComponent> artifact2Ent = (artifact2Uid, SComp<XenoArtifactComponent>(artifact2Uid));
var segments1 = artifactSystem.GetSegments(artifact1Ent);
Assert.That(segments1.Count, Is.EqualTo(2));
Assert.That(segments1[0].Count, Is.EqualTo(1));
Assert.That(segments1[1].Count, Is.EqualTo(1));
var segments2 = _sArtifactSystem.GetSegments(artifact2Ent);
Assert.That(segments2, Has.Count.EqualTo(1));
Assert.That(segments2[0], Has.Count.EqualTo(2));
var artifact2Uid = entManager.Spawn("TestGenArtifactTall");
Entity<XenoArtifactComponent> artifact2Ent = (artifact2Uid, entManager.GetComponent<XenoArtifactComponent>(artifact2Uid));
var artifact3Uid = SSpawn(TestGenArtifactFull);
Entity<XenoArtifactComponent> artifact3Ent = (artifact3Uid, SComp<XenoArtifactComponent>(artifact3Uid));
var segments2 = artifactSystem.GetSegments(artifact2Ent);
Assert.That(segments2.Count, Is.EqualTo(1));
Assert.That(segments2[0].Count, Is.EqualTo(2));
var artifact3Uid = entManager.Spawn("TestGenArtifactFull");
Entity<XenoArtifactComponent> artifact3Ent = (artifact3Uid, entManager.GetComponent<XenoArtifactComponent>(artifact3Uid));
var segments3 = artifactSystem.GetSegments(artifact3Ent);
Assert.That(segments3.Count, Is.EqualTo(1));
Assert.That(segments3.Sum(x => x.Count), Is.EqualTo(6));
var nodesDepths = segments3[0].Select(x => x.Comp.Depth).ToArray();
Assert.That(nodesDepths.Distinct().Count(), Is.EqualTo(3));
var grouped = nodesDepths.ToLookup(x => x);
Assert.That(grouped[0].Count(), Is.EqualTo(2));
Assert.That(grouped[1].Count(), Is.GreaterThanOrEqualTo(2)); // tree is attempting sometimes to get wider (so it will look like a tree)
Assert.That(grouped[2].Count(), Is.LessThanOrEqualTo(2)); // maintain same width or, if we used 3 nodes on previous layer - we only have 1 left!
});
var segments3 = _sArtifactSystem.GetSegments(artifact3Ent);
Assert.That(segments3, Has.Count.EqualTo(1));
Assert.That(segments3.Sum(x => x.Count), Is.EqualTo(6));
var nodesDepths = segments3[0].Select(x => x.Comp.Depth).ToArray();
Assert.That(nodesDepths.Distinct().Count(), Is.EqualTo(3));
var grouped = nodesDepths.ToLookup(x => x);
Assert.That(grouped[0].Count(), Is.EqualTo(2));
Assert.That(grouped[1].Count(), Is.GreaterThanOrEqualTo(2)); // tree is attempting sometimes to get wider (so it will look like a tree)
Assert.That(grouped[2].Count(), Is.LessThanOrEqualTo(2)); // maintain same width or, if we used 3 nodes on previous layer - we only have 1 left!
}
}
-1
View File
@@ -4,7 +4,6 @@ using Content.Server.Ame.EntitySystems;
using Content.Server.Chat.Managers;
using Content.Server.Explosion.EntitySystems;
using Content.Server.NodeContainer.NodeGroups;
using Content.Server.NodeContainer.Nodes;
using Content.Shared.NodeContainer;
using Content.Shared.NodeContainer.NodeGroups;
using Robust.Server.GameObjects;
@@ -22,6 +22,7 @@ public sealed partial class AnomalySystem
{
[Dependency] private SharedMapSystem _mapSystem = default!;
[Dependency] private SharedTransformSystem _transform = default!;
[Dependency] private EntityQuery<PhysicsComponent> _physicsQuery = default!;
private void InitializeGenerator()
{
@@ -106,13 +107,12 @@ public sealed partial class AnomalySystem
}
// don't spawn inside of solid objects
var physQuery = GetEntityQuery<PhysicsComponent>();
var valid = true;
// TODO: This should be using static lookup.
foreach (var ent in _mapSystem.GetAnchoredEntities(grid, gridComp, tile))
{
if (!physQuery.TryGetComponent(ent, out var body))
if (!_physicsQuery.TryGetComponent(ent, out var body))
continue;
if (body.BodyType != BodyType.Static ||
!body.Hard ||
@@ -30,8 +30,7 @@ public sealed partial class BluespaceAnomalySystem : EntitySystem
private void OnPulse(EntityUid uid, BluespaceAnomalyComponent component, ref AnomalyPulseEvent args)
{
var xformQuery = GetEntityQuery<TransformComponent>();
var xform = xformQuery.GetComponent(uid);
var xform = Transform(uid);
var range = component.MaxShuffleRadius * args.Severity * args.PowerModifier;
// get a list of all entities in range with the MobStateComponent
// we filter out those inside a container
@@ -42,7 +41,7 @@ public sealed partial class BluespaceAnomalySystem : EntitySystem
var coords = new ValueList<Vector2>();
foreach (var ent in allEnts)
{
if (xformQuery.TryGetComponent(ent, out var allXform))
if (TryComp(ent, out TransformComponent? allXform))
coords.Add(_xform.GetWorldPosition(allXform));
}
@@ -3,7 +3,6 @@ using Content.Shared.Anomaly.Components;
using Content.Shared.Anomaly.Effects;
using Content.Shared.Anomaly.Effects.Components;
using Robust.Shared.Map.Components;
using Robust.Shared.Physics.Components;
using Robust.Shared.Random;
namespace Content.Server.Anomaly.Effects;
@@ -14,13 +13,9 @@ public sealed partial class EntityAnomalySystem : SharedEntityAnomalySystem
[Dependency] private IRobustRandom _random = default!;
[Dependency] private SharedMapSystem _mapSystem = default!;
private EntityQuery<PhysicsComponent> _physicsQuery;
/// <inheritdoc/>
public override void Initialize()
{
_physicsQuery = GetEntityQuery<PhysicsComponent>();
SubscribeLocalEvent<EntitySpawnAnomalyComponent, AnomalyPulseEvent>(OnPulse);
SubscribeLocalEvent<EntitySpawnAnomalyComponent, AnomalySupercriticalEvent>(OnSupercritical);
SubscribeLocalEvent<EntitySpawnAnomalyComponent, AnomalyStabilityChangedEvent>(OnStabilityChanged);
@@ -18,15 +18,12 @@ public sealed partial class InjectionAnomalySystem : EntitySystem
[Dependency] private EntityLookupSystem _lookup = default!;
[Dependency] private SharedSolutionContainerSystem _solutionContainer = default!;
[Dependency] private TransformSystem _transform = default!;
private EntityQuery<InjectableSolutionComponent> _injectableQuery;
[Dependency] private EntityQuery<InjectableSolutionComponent> _injectableQuery = default!;
public override void Initialize()
{
SubscribeLocalEvent<InjectionAnomalyComponent, AnomalyPulseEvent>(OnPulse);
SubscribeLocalEvent<InjectionAnomalyComponent, AnomalySupercriticalEvent>(OnSupercritical, before: new[] { typeof(SharedSolutionContainerSystem) });
_injectableQuery = GetEntityQuery<InjectableSolutionComponent>();
}
private void OnPulse(Entity<InjectionAnomalyComponent> entity, ref AnomalyPulseEvent args)
@@ -45,8 +42,7 @@ public sealed partial class InjectionAnomalySystem : EntitySystem
return;
//We get all the entity in the radius into which the reagent will be injected.
var xformQuery = GetEntityQuery<TransformComponent>();
var xform = xformQuery.GetComponent(entity);
var xform = Transform(entity);
var allEnts = _lookup.GetEntitiesInRange<InjectableSolutionComponent>(_transform.GetMapCoordinates(entity, xform: xform), injectRadius)
.Select(x => x.Owner).ToList();
@@ -21,9 +21,7 @@ public sealed partial class ProjectileAnomalySystem : EntitySystem
[Dependency] private IMapManager _mapManager = default!;
[Dependency] private GunSystem _gunSystem = default!;
[Dependency] private SharedMapSystem _map = default!;
private EntityQuery<TransformComponent> _xFormQuery;
private EntityQuery<MobStateComponent> _mobQuery;
[Dependency] private EntityQuery<MobStateComponent> _mobStateQuery = default!;
/// <summary> Pre-allocated collection for calculating entities in range. </summary>
private readonly HashSet<EntityUid> _inRange = new();
@@ -32,9 +30,6 @@ public sealed partial class ProjectileAnomalySystem : EntitySystem
{
SubscribeLocalEvent<ProjectileAnomalyComponent, AnomalyPulseEvent>(OnPulse);
SubscribeLocalEvent<ProjectileAnomalyComponent, AnomalySupercriticalEvent>(OnSupercritical);
_xFormQuery = GetEntityQuery<TransformComponent>();
_mobQuery = GetEntityQuery<MobStateComponent>();
}
private void OnPulse(EntityUid uid, ProjectileAnomalyComponent component, ref AnomalyPulseEvent args)
@@ -51,7 +46,7 @@ public sealed partial class ProjectileAnomalySystem : EntitySystem
{
var projectileCount = (int)MathF.Round(MathHelper.Lerp(component.MinProjectiles, component.MaxProjectiles, severity));
var xform = _xFormQuery.GetComponent(uid);
var xform = Transform(uid);
_inRange.Clear();
_lookup.GetEntitiesInRange(uid, component.ProjectileRange * severity, _inRange, LookupFlags.Dynamic);
@@ -62,7 +57,7 @@ public sealed partial class ProjectileAnomalySystem : EntitySystem
var priority = new List<EntityUid>();
foreach (var entity in _inRange)
{
if (_mobQuery.HasComponent(entity))
if (_mobStateQuery.HasComponent(entity))
priority.Add(entity);
}
@@ -74,7 +69,7 @@ public sealed partial class ProjectileAnomalySystem : EntitySystem
? _random.PickAndTake(priority)
: _random.Pick(_inRange);
var targetXForm= _xFormQuery.GetComponent(target);
var targetXForm = Transform(target);
var targetCoords = targetXForm.Coordinates.Offset(_random.NextVector2(0.5f));
ShootProjectile(
@@ -126,7 +126,6 @@ namespace Content.Server.Atmos.EntitySystems
public void InvalidatePosition(Entity<MapGridComponent?> grid, Vector2i pos)
{
var query = GetEntityQuery<AirtightComponent>();
_explosionSystem.UpdateAirtightMap(grid, pos, grid);
_atmosphereSystem.InvalidateTile(grid.Owner, pos);
}
@@ -7,7 +7,6 @@ using Content.Shared.Atmos.EntitySystems;
using Content.Shared.Atmos.Reactions;
using JetBrains.Annotations;
using Robust.Shared.Map.Components;
using Robust.Shared.Prototypes;
using Robust.Shared.Utility;
namespace Content.Server.Atmos.EntitySystems;
@@ -29,7 +28,7 @@ public partial class AtmosphereSystem
[PublicAPI]
public bool HasAtmosphere(EntityUid gridUid)
{
return _atmosQuery.HasComponent(gridUid);
return _gridAtmosQuery.HasComponent(gridUid);
}
/// <summary>
@@ -95,7 +94,7 @@ public partial class AtmosphereSystem
[PublicAPI]
public void InvalidateTile(Entity<GridAtmosphereComponent?> entity, Vector2i tile)
{
if (_atmosQuery.Resolve(entity.Owner, ref entity.Comp, false))
if (_gridAtmosQuery.Resolve(entity.Owner, ref entity.Comp, false))
entity.Comp.InvalidatedCoords.Add(tile);
}
@@ -181,7 +180,7 @@ public partial class AtmosphereSystem
var handled = false;
// If we've been passed a grid, try to let it handle it.
if (grid is { } gridEnt && _atmosQuery.Resolve(gridEnt, ref gridEnt.Comp1))
if (grid is { } gridEnt && _gridAtmosQuery.Resolve(gridEnt, ref gridEnt.Comp1))
{
if (excite)
Resolve(gridEnt, ref gridEnt.Comp2);
@@ -244,7 +243,7 @@ public partial class AtmosphereSystem
{
// If we've been passed a grid, try to let it handle it.
if (grid is { } gridEnt
&& _atmosQuery.Resolve(gridEnt, ref gridEnt.Comp1, false)
&& _gridAtmosQuery.Resolve(gridEnt, ref gridEnt.Comp1, false)
&& gridEnt.Comp1.Tiles.TryGetValue(gridTile, out var tile))
{
if (excite)
@@ -440,7 +439,7 @@ public partial class AtmosphereSystem
Vector2i tile,
AtmosDirection directions = AtmosDirection.All)
{
if (!_atmosQuery.Resolve(grid, ref grid.Comp, false))
if (!_gridAtmosQuery.Resolve(grid, ref grid.Comp, false))
return false;
if (!grid.Comp.Tiles.TryGetValue(tile, out var atmosTile))
@@ -463,7 +462,7 @@ public partial class AtmosphereSystem
[PublicAPI]
public AtmosDirection GetAirflowDirections(Entity<GridAtmosphereComponent?> grid, Vector2i tile)
{
if (!_atmosQuery.Resolve(grid, ref grid.Comp, false))
if (!_gridAtmosQuery.Resolve(grid, ref grid.Comp, false))
return AtmosDirection.Invalid;
if (!grid.Comp.Tiles.TryGetValue(tile, out var atmosTile))
@@ -486,7 +485,7 @@ public partial class AtmosphereSystem
[PublicAPI]
public bool IsTileSpace(Entity<GridAtmosphereComponent?>? grid, Entity<MapAtmosphereComponent?>? map, Vector2i tile)
{
if (grid is { } gridEnt && _atmosQuery.Resolve(gridEnt, ref gridEnt.Comp, false)
if (grid is { } gridEnt && _gridAtmosQuery.Resolve(gridEnt, ref gridEnt.Comp, false)
&& gridEnt.Comp.Tiles.TryGetValue(tile, out var tileAtmos))
{
return tileAtmos.Space;
@@ -541,7 +540,7 @@ public partial class AtmosphereSystem
public TileMixtureEnumerator GetAdjacentTileMixtures(Entity<GridAtmosphereComponent?> grid, Vector2i tile, bool includeBlocked = false, bool excite = false)
{
// TODO ATMOS includeBlocked and excite parameters are unhandled currently.
if (!_atmosQuery.Resolve(grid, ref grid.Comp, false))
if (!_gridAtmosQuery.Resolve(grid, ref grid.Comp, false))
return TileMixtureEnumerator.Empty;
return !grid.Comp.Tiles.TryGetValue(tile, out var atmosTile)
@@ -572,7 +571,7 @@ public partial class AtmosphereSystem
EntityUid? sparkSourceUid = null,
bool soh = false)
{
if (!_atmosQuery.Resolve(grid, ref grid.Comp, false))
if (!_gridAtmosQuery.Resolve(grid, ref grid.Comp, false))
return;
if (grid.Comp.Tiles.TryGetValue(tile, out var atmosTile))
@@ -600,7 +599,7 @@ public partial class AtmosphereSystem
EntityUid? sparkSourceUid = null,
bool soh = false)
{
if (!_atmosQuery.TryGetComponent(tile.GridIndex, out var atmos))
if (!_gridAtmosQuery.TryGetComponent(tile.GridIndex, out var atmos))
return;
DebugTools.Assert(atmos.Tiles.TryGetValue(tile.GridIndices, out var tmp) && tmp == tile);
@@ -644,7 +643,7 @@ public partial class AtmosphereSystem
[PublicAPI]
public bool AddPipeNet(Entity<GridAtmosphereComponent?> grid, PipeNet pipeNet)
{
return _atmosQuery.Resolve(grid, ref grid.Comp, false) && grid.Comp.PipeNets.Add(pipeNet);
return _gridAtmosQuery.Resolve(grid, ref grid.Comp, false) && grid.Comp.PipeNets.Add(pipeNet);
}
/// <summary>
@@ -664,7 +663,7 @@ public partial class AtmosphereSystem
RaiseLocalEvent(ref ev);
}
return _atmosQuery.Resolve(grid, ref grid.Comp, false) && grid.Comp.PipeNets.Remove(pipeNet);
return _gridAtmosQuery.Resolve(grid, ref grid.Comp, false) && grid.Comp.PipeNets.Remove(pipeNet);
}
/// <summary>
@@ -679,7 +678,7 @@ public partial class AtmosphereSystem
DebugTools.Assert(device.Comp.JoinedGrid == null);
DebugTools.Assert(Transform(device).GridUid == grid);
if (!_atmosQuery.Resolve(grid, ref grid.Comp, false))
if (!_gridAtmosQuery.Resolve(grid, ref grid.Comp, false))
return false;
if (!grid.Comp.AtmosDevices.Add(device))
@@ -699,7 +698,7 @@ public partial class AtmosphereSystem
{
DebugTools.Assert(device.Comp.JoinedGrid == grid);
if (!_atmosQuery.Resolve(grid, ref grid.Comp, false))
if (!_gridAtmosQuery.Resolve(grid, ref grid.Comp, false))
return false;
if (!grid.Comp.AtmosDevices.Remove(device))
@@ -732,7 +731,7 @@ public partial class AtmosphereSystem
// Entity should be on the grid it's being added to.
Debug.Assert(xform.GridUid == grid.Owner);
if (!_atmosQuery.Resolve(grid, ref grid.Comp, false))
if (!_gridAtmosQuery.Resolve(grid, ref grid.Comp, false))
return false;
if (grid.Comp.DeltaPressureEntityLookup.ContainsKey(ent.Owner))
@@ -759,7 +758,7 @@ public partial class AtmosphereSystem
[PublicAPI]
public bool TryRemoveDeltaPressureEntity(Entity<GridAtmosphereComponent?> grid, Entity<DeltaPressureComponent> ent)
{
if (!_atmosQuery.Resolve(grid, ref grid.Comp, false))
if (!_gridAtmosQuery.Resolve(grid, ref grid.Comp, false))
return false;
if (!grid.Comp.DeltaPressureEntityLookup.TryGetValue(ent.Owner, out var index))
@@ -797,7 +796,7 @@ public partial class AtmosphereSystem
public bool IsDeltaPressureEntityInList(Entity<GridAtmosphereComponent?> grid, Entity<DeltaPressureComponent> ent)
{
// Dict and list must be in sync - deep-fried if we aren't.
if (!_atmosQuery.Resolve(grid, ref grid.Comp, false))
if (!_gridAtmosQuery.Resolve(grid, ref grid.Comp, false))
return false;
var contains = grid.Comp.DeltaPressureEntityLookup.ContainsKey(ent.Owner);
@@ -13,6 +13,7 @@ namespace Content.Server.Atmos.EntitySystems;
public sealed partial class AtmosphereSystem
{
[Dependency] private IConsoleHost _consoleHost = default!;
[Dependency] private EntityQuery<AtmosFixMarkerComponent> _atmosFixMarkerQuery = default!;
private void InitializeCommands()
{
@@ -113,7 +114,6 @@ public sealed partial class AtmosphereSystem
RebuildGridTiles(grid);
var query = GetEntityQuery<AtmosFixMarkerComponent>();
foreach (var (indices, tile) in ent.Comp1.Tiles.ToArray())
{
if (tile.Air is not {Immutable: false} air)
@@ -124,7 +124,7 @@ public sealed partial class AtmosphereSystem
var enumerator = _mapSystem.GetAnchoredEntitiesEnumerator(grid, grid, indices);
while (enumerator.MoveNext(out var entUid))
{
if (query.TryComp(entUid, out var marker))
if (_atmosFixMarkerQuery.TryComp(entUid, out var marker))
mixtureId = marker.Mode;
}
@@ -14,6 +14,9 @@ namespace Content.Server.Atmos.EntitySystems
{
public sealed partial class AtmosphereSystem
{
[Dependency] private EntityQuery<PhysicsComponent> _physicsQuery = default!;
[Dependency] private EntityQuery<MovedByPressureComponent> _movedByPressureQuery = default!;
private static readonly ProtoId<SoundCollectionPrototype> DefaultSpaceWindSounds = "SpaceWind";
private const int SpaceWindSoundCooldownCycles = 75;
@@ -100,7 +103,7 @@ namespace Content.Server.Atmos.EntitySystems
_activePressures.Add((uid, component));
}
private void HighPressureMovements(Entity<GridAtmosphereComponent> gridAtmosphere, TileAtmosphere tile, EntityQuery<PhysicsComponent> bodies, EntityQuery<TransformComponent> xforms, EntityQuery<MovedByPressureComponent> pressureQuery, EntityQuery<MetaDataComponent> metas)
private void HighPressureMovements(Entity<GridAtmosphereComponent> gridAtmosphere, TileAtmosphere tile)
{
// TODO ATMOS finish this
@@ -156,12 +159,12 @@ namespace Content.Server.Atmos.EntitySystems
{
// Ideally containers would have their own EntityQuery internally or something given recursively it may need to slam GetComp<T> anyway.
// Also, don't care about static bodies (but also due to collisionwakestate can't query dynamic directly atm).
if (!bodies.TryGetComponent(entity, out var body) ||
!pressureQuery.TryGetComponent(entity, out var pressure) ||
if (!_physicsQuery.TryGetComponent(entity, out var body) ||
!_movedByPressureQuery.TryGetComponent(entity, out var pressure) ||
!pressure.Enabled)
continue;
if (_containers.IsEntityInContainer(entity, metas.GetComponent(entity))) continue;
if (_containers.IsEntityInContainer(entity)) continue;
var pressureMovements = EnsureComp<MovedByPressureComponent>(entity);
if (pressure.LastHighPressureMovementAirCycle < gridAtmosphere.Comp.UpdateCounter)
@@ -174,7 +177,7 @@ namespace Content.Server.Atmos.EntitySystems
tile.PressureDirection, 0,
tile.PressureSpecificTarget != null ? _mapSystem.ToCenterCoordinates(tile.GridIndex, tile.PressureSpecificTarget.GridIndices) : EntityCoordinates.Invalid,
gridWorldRotation,
xforms.GetComponent(entity),
Transform(entity),
body);
}
}
@@ -395,14 +395,9 @@ namespace Content.Server.Atmos.EntitySystems
// Note: This is still processed even if space wind is turned off since this handles playing the sounds.
var number = 0;
var bodies = GetEntityQuery<PhysicsComponent>();
var xforms = GetEntityQuery<TransformComponent>();
var metas = GetEntityQuery<MetaDataComponent>();
var pressureQuery = GetEntityQuery<MovedByPressureComponent>();
while (atmosphere.CurrentRunTiles.TryDequeue(out var tile))
{
HighPressureMovements(ent, tile, bodies, xforms, pressureQuery, metas);
HighPressureMovements(ent, tile);
tile.PressureDifference = 0f;
tile.LastPressureDirection = tile.PressureDirection;
tile.PressureDirection = AtmosDirection.Invalid;
@@ -42,13 +42,14 @@ public sealed partial class AtmosphereSystem : SharedAtmosphereSystem
[Dependency] public PuddleSystem Puddle = default!;
[Dependency] private DamageableSystem _damage = default!;
[Dependency] private EntityQuery<GridAtmosphereComponent> _gridAtmosQuery = default!;
[Dependency] private EntityQuery<MapAtmosphereComponent> _mapAtmosQuery = default!;
[Dependency] private EntityQuery<AirtightComponent> _airtightQuery = default!;
[Dependency] private EntityQuery<FirelockComponent> _firelockQuery = default!;
private const float ExposedUpdateDelay = 1f;
private float _exposedTimer = 0f;
private EntityQuery<GridAtmosphereComponent> _atmosQuery;
private EntityQuery<MapAtmosphereComponent> _mapAtmosQuery;
private EntityQuery<AirtightComponent> _airtightQuery;
private EntityQuery<FirelockComponent> _firelockQuery;
private HashSet<EntityUid> _entSet = new();
private string[] _burntDecals = [];
@@ -65,11 +66,6 @@ public sealed partial class AtmosphereSystem : SharedAtmosphereSystem
InitializeGridAtmosphere();
InitializeMap();
_atmosQuery = GetEntityQuery<GridAtmosphereComponent>();
_mapAtmosQuery = GetEntityQuery<MapAtmosphereComponent>();
_airtightQuery = GetEntityQuery<AirtightComponent>();
_firelockQuery = GetEntityQuery<FirelockComponent>();
SubscribeLocalEvent<TileChangedEvent>(OnTileChanged);
SubscribeLocalEvent<PrototypesReloadedEventArgs>(OnPrototypesReloaded);
@@ -51,8 +51,8 @@ namespace Content.Server.Atmos.EntitySystems
[Dependency] private IRobustRandom _random = default!;
[Dependency] private IGameTiming _timing = default!;
private EntityQuery<InventoryComponent> _inventoryQuery;
private EntityQuery<PhysicsComponent> _physicsQuery;
[Dependency] private EntityQuery<InventoryComponent> _inventoryQuery = default!;
[Dependency] private EntityQuery<PhysicsComponent> _physicsQuery = default!;
private static readonly TimeSpan UpdateTime = TimeSpan.FromSeconds(1);
@@ -62,9 +62,6 @@ namespace Content.Server.Atmos.EntitySystems
{
UpdatesAfter.Add(typeof(AtmosphereSystem));
_inventoryQuery = GetEntityQuery<InventoryComponent>();
_physicsQuery = GetEntityQuery<PhysicsComponent>();
SubscribeLocalEvent<FlammableComponent, MapInitEvent>(OnMapInit);
SubscribeLocalEvent<FlammableComponent, InteractUsingEvent>(OnInteractUsing);
SubscribeLocalEvent<FlammableComponent, StartCollideEvent>(OnCollide);
@@ -1,4 +1,3 @@
using Content.Server.Atmos.Components;
using Content.Shared.Atmos;
using Content.Shared.Atmos.Components;
using Content.Shared.Atmos.EntitySystems;
@@ -33,6 +32,9 @@ namespace Content.Server.Atmos.EntitySystems
[Robust.Shared.IoC.Dependency] private AtmosphereSystem _atmosphereSystem = default!;
[Robust.Shared.IoC.Dependency] private ChunkingSystem _chunkingSys = default!;
[Robust.Shared.IoC.Dependency] private EntityQuery<MapGridComponent> _mapGridQuery = default!;
[Robust.Shared.IoC.Dependency] private EntityQuery<GasTileOverlayComponent> _gasTileOverlayQuery = default!;
/// <summary>
/// Per-tick cache of sessions.
/// </summary>
@@ -57,16 +59,11 @@ namespace Content.Server.Atmos.EntitySystems
private float _updateInterval;
private int _thresholds;
private EntityQuery<MapGridComponent> _gridQuery;
private EntityQuery<GasTileOverlayComponent> _query;
public override void Initialize()
{
base.Initialize();
_query = GetEntityQuery<GasTileOverlayComponent>();
_gridQuery = GetEntityQuery<MapGridComponent>();
_updateJob = new UpdatePlayerJob()
{
EntManager = EntityManager,
@@ -77,7 +74,7 @@ namespace Content.Server.Atmos.EntitySystems
MapManager = _mapManager,
ChunkViewerPool = _chunkViewerPool,
LastSentChunks = _lastSentChunks,
GridQuery = _gridQuery,
GridQuery = _mapGridQuery,
};
_playerManager.PlayerStatusChanged += OnPlayerStatusChanged;
@@ -136,7 +133,7 @@ namespace Content.Server.Atmos.EntitySystems
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Invalidate(Entity<GasTileOverlayComponent?> grid, Vector2i index)
{
if (_query.Resolve(grid.Owner, ref grid.Comp))
if (_gasTileOverlayQuery.Resolve(grid.Owner, ref grid.Comp))
grid.Comp.InvalidTiles.Add(index);
}
@@ -1,6 +1,5 @@
using System.Linq;
using Content.Server.Atmos.Components;
using Content.Server.NodeContainer;
using Content.Server.NodeContainer.Nodes;
using Content.Server.Popups;
using Content.Shared.Atmos;
@@ -21,17 +20,15 @@ public sealed partial class PipeRestrictOverlapSystem : EntitySystem
[Dependency] private MapSystem _map = default!;
[Dependency] private PopupSystem _popup = default!;
[Dependency] private TransformSystem _xform = default!;
[Dependency] private EntityQuery<NodeContainerComponent> _nodeContainerQuery = default!;
private readonly List<EntityUid> _anchoredEntities = new();
private EntityQuery<NodeContainerComponent> _nodeContainerQuery;
/// <inheritdoc/>
public override void Initialize()
{
SubscribeLocalEvent<PipeRestrictOverlapComponent, AnchorStateChangedEvent>(OnAnchorStateChanged);
SubscribeLocalEvent<PipeRestrictOverlapComponent, AnchorAttemptEvent>(OnAnchorAttempt);
_nodeContainerQuery = GetEntityQuery<NodeContainerComponent>();
}
private void OnAnchorStateChanged(Entity<PipeRestrictOverlapComponent> ent, ref AnchorStateChangedEvent args)
@@ -45,6 +45,7 @@ public sealed partial class AirAlarmSystem : EntitySystem
[Dependency] private DeviceListSystem _deviceList = default!;
[Dependency] private PopupSystem _popup = default!;
[Dependency] private UserInterfaceSystem _ui = default!;
[Dependency] private EntityQuery<DeviceNetworkComponent> _deviceNetworkQuery = default!;
#region Device Network API
@@ -193,10 +194,9 @@ public sealed partial class AirAlarmSystem : EntitySystem
private void OnDeviceListUpdate(EntityUid uid, AirAlarmComponent component, DeviceListUpdateEvent args)
{
var query = GetEntityQuery<DeviceNetworkComponent>();
foreach (var device in args.OldDevices)
{
if (!query.TryGetComponent(device, out var deviceNet))
if (!_deviceNetworkQuery.TryGetComponent(device, out var deviceNet))
{
continue;
}
@@ -19,6 +19,7 @@ public sealed partial class FireAlarmSystem : EntitySystem
[Dependency] private SharedInteractionSystem _interactionSystem = default!;
[Dependency] private AccessReaderSystem _access = default!;
[Dependency] private IConfigurationManager _configManager = default!;
[Dependency] private EntityQuery<DeviceNetworkComponent> _deviceNetworkQuery = default!;
public override void Initialize()
{
@@ -29,10 +30,9 @@ public sealed partial class FireAlarmSystem : EntitySystem
private void OnDeviceListSync(EntityUid uid, FireAlarmComponent component, DeviceListUpdateEvent args)
{
var query = GetEntityQuery<DeviceNetworkComponent>();
foreach (var device in args.OldDevices)
{
if (!query.TryGetComponent(device, out var deviceNet))
if (!_deviceNetworkQuery.TryGetComponent(device, out var deviceNet))
{
continue;
}
@@ -112,6 +112,12 @@ namespace Content.Server.Atmos.Piping.EntitySystems
private void OnDeviceParentChanged(Entity<AtmosDeviceComponent> ent, ref EntParentChangedMessage args)
{
// Event is raised when a map is loaded in. Since this event mutates comp.Enabled,
// it will overwrite whatever saved value it had
// (so devices saved as enabled will just be disabled).
if (args.OldParent is null)
return;
RejoinAtmosphere(ent);
}
@@ -14,14 +14,9 @@ public sealed partial class InternalsSystem : SharedInternalsSystem
[Dependency] private GasTankSystem _gasTank = default!;
[Dependency] private RespiratorSystem _respirator = default!;
private EntityQuery<InternalsComponent> _internalsQuery;
public override void Initialize()
{
base.Initialize();
_internalsQuery = GetEntityQuery<InternalsComponent>();
SubscribeLocalEvent<InternalsComponent, InhaleLocationEvent>(OnInhaleLocation);
SubscribeLocalEvent<InternalsComponent, StartingGearEquippedEvent>(OnStartingGear);
}
@@ -17,7 +17,6 @@ using Robust.Server.Containers;
using Robust.Shared.Containers;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
using Robust.Shared.Timing;
using Robust.Shared.Utility;
namespace Content.Server.Cargo.Systems;
@@ -28,11 +27,11 @@ public sealed partial class CargoSystem
[Dependency] private NameIdentifierSystem _nameIdentifier = default!;
[Dependency] private EntityWhitelistSystem _whitelistSys = default!;
private static readonly ProtoId<NameIdentifierGroupPrototype> BountyNameIdentifierGroup = "Bounty";
[Dependency] private EntityQuery<StackComponent> _stackQuery = default!;
[Dependency] private EntityQuery<ContainerManagerComponent> _containerManagerQuery = default!;
[Dependency] private EntityQuery<CargoBountyLabelComponent> _cargoBountyLabelQuery = default!;
private EntityQuery<StackComponent> _stackQuery;
private EntityQuery<ContainerManagerComponent> _containerQuery;
private EntityQuery<CargoBountyLabelComponent> _bountyLabelQuery;
private static readonly ProtoId<NameIdentifierGroupPrototype> BountyNameIdentifierGroup = "Bounty";
private void InitializeBounty()
{
@@ -42,10 +41,6 @@ public sealed partial class CargoSystem
SubscribeLocalEvent<CargoBountyLabelComponent, PriceCalculationEvent>(OnGetBountyPrice);
SubscribeLocalEvent<EntitySoldEvent>(OnSold);
SubscribeLocalEvent<StationCargoBountyDatabaseComponent, MapInitEvent>(OnMapInit);
_stackQuery = GetEntityQuery<StackComponent>();
_containerQuery = GetEntityQuery<ContainerManagerComponent>();
_bountyLabelQuery = GetEntityQuery<CargoBountyLabelComponent>();
}
private void OnBountyConsoleOpened(EntityUid uid, CargoBountyConsoleComponent component, BoundUIOpenedEvent args)
@@ -196,7 +191,7 @@ public sealed partial class CargoSystem
{
labelEnt = null;
labelComp = null;
if (!_containerQuery.TryGetComponent(uid, out var containerMan))
if (!_containerManagerQuery.TryGetComponent(uid, out var containerMan))
return false;
// make sure this label was actually applied to a crate.
@@ -204,7 +199,7 @@ public sealed partial class CargoSystem
return false;
if (container.ContainedEntities.FirstOrNull() is not { } label ||
!_bountyLabelQuery.TryGetComponent(label, out var component))
!_cargoBountyLabelQuery.TryGetComponent(label, out var component))
return false;
labelEnt = label;
@@ -377,7 +372,7 @@ public sealed partial class CargoSystem
{
foreach (var ent in container.ContainedEntities)
{
if (_bountyLabelQuery.HasComponent(ent))
if (_cargoBountyLabelQuery.HasComponent(ent))
continue;
var children = GetBountyEntities(ent);
@@ -297,7 +297,7 @@ namespace Content.Server.Cargo.Systems
{
foreach (var gridUid in data.Grids)
{
if (!_tradeQuery.HasComponent(gridUid))
if (!_tradeStationQuery.HasComponent(gridUid))
continue;
ents.Add(gridUid);
@@ -6,7 +6,6 @@ using Content.Shared.Cargo.Components;
using Content.Shared.Cargo.Events;
using Content.Shared.Cargo.Prototypes;
using Content.Shared.CCVar;
using Content.Shared.HijackBeacon;
using Robust.Shared.Audio;
using Robust.Shared.Prototypes;
@@ -169,13 +168,13 @@ public sealed partial class CargoSystem
// - anything anchored (e.g. light fixtures)
// - anything blacklisted (e.g. players).
if (toSell.Contains(ent) ||
_xformQuery.TryGetComponent(ent, out var xform) &&
(xform.Anchored || !CanSell(ent, xform)))
TryComp(ent, out TransformComponent? xform) &&
(xform.Anchored || !CanSell(ent)))
{
continue;
}
if (_blacklistQuery.HasComponent(ent))
if (_cargoSellBlacklistQuery.HasComponent(ent))
continue;
var price = _pricing.GetPrice(ent);
@@ -187,9 +186,9 @@ public sealed partial class CargoSystem
}
}
private bool CanSell(EntityUid uid, TransformComponent xform)
private bool CanSell(EntityUid uid)
{
if (_mobQuery.HasComponent(uid))
if (_mobStateQuery.HasComponent(uid))
{
return false;
}
@@ -197,13 +196,14 @@ public sealed partial class CargoSystem
var complete = IsBountyComplete(uid, out var bountyEntities);
// Recursively check for mobs at any point.
var xform = Transform(uid);
var children = xform.ChildEnumerator;
while (children.MoveNext(out var child))
{
if (complete && bountyEntities.Contains(child))
continue;
if (!CanSell(child, _xformQuery.GetComponent(child)))
if (!CanSell(child))
return false;
}
+3 -10
View File
@@ -42,10 +42,9 @@ public sealed partial class CargoSystem : SharedCargoSystem
[Dependency] private RadioSystem _radio = default!;
[Dependency] private IdentitySystem _identity = default!;
private EntityQuery<TransformComponent> _xformQuery;
private EntityQuery<CargoSellBlacklistComponent> _blacklistQuery;
private EntityQuery<MobStateComponent> _mobQuery;
private EntityQuery<TradeStationComponent> _tradeQuery;
[Dependency] private EntityQuery<CargoSellBlacklistComponent> _cargoSellBlacklistQuery = default!;
[Dependency] private EntityQuery<MobStateComponent> _mobStateQuery = default!;
[Dependency] private EntityQuery<TradeStationComponent> _tradeStationQuery = default!;
private HashSet<EntityUid> _setEnts = new();
private List<EntityUid> _listEnts = new();
@@ -54,12 +53,6 @@ public sealed partial class CargoSystem : SharedCargoSystem
public override void Initialize()
{
base.Initialize();
_xformQuery = GetEntityQuery<TransformComponent>();
_blacklistQuery = GetEntityQuery<CargoSellBlacklistComponent>();
_mobQuery = GetEntityQuery<MobStateComponent>();
_tradeQuery = GetEntityQuery<TradeStationComponent>();
InitializeConsole();
InitializeShuttle();
InitializeTelepad();
+2 -2
View File
@@ -28,6 +28,7 @@ public sealed partial class SuicideSystem : EntitySystem
[Dependency] private SharedPopupSystem _popup = default!;
[Dependency] private GhostSystem _ghostSystem = default!;
[Dependency] private SharedSuicideSystem _suicide = default!;
[Dependency] private EntityQuery<ItemComponent> _itemQuery = default!;
private static readonly ProtoId<TagPrototype> CannotSuicideTag = "CannotSuicide";
@@ -132,11 +133,10 @@ public sealed partial class SuicideSystem : EntitySystem
// Try to suicide by nearby entities, like Microwaves or Crematoriums, by raising an event on it
// Returns upon being handled by any entity
var itemQuery = GetEntityQuery<ItemComponent>();
foreach (var entity in _entityLookupSystem.GetEntitiesInRange(victim, 1, LookupFlags.Approximate | LookupFlags.Static))
{
// Skip any nearby items that can be picked up, we already checked the active held item above
if (itemQuery.HasComponent(entity))
if (_itemQuery.HasComponent(entity))
continue;
RaiseLocalEvent(entity, suicideByEnvironmentEvent);
+4 -6
View File
@@ -21,7 +21,6 @@ using Content.Shared.Players;
using Content.Shared.Players.RateLimiting;
using Content.Shared.Radio;
using Content.Shared.Station.Components;
using Content.Shared.Whitelist;
using Robust.Server.Player;
using Robust.Shared.Audio;
using Robust.Shared.Audio.Systems;
@@ -58,6 +57,7 @@ public sealed partial class ChatSystem : SharedChatSystem
[Dependency] private SharedAudioSystem _audio = default!;
[Dependency] private ReplacementAccentSystem _wordreplacement = default!;
[Dependency] private ExamineSystemShared _examineSystem = default!;
[Dependency] private EntityQuery<GhostHearingComponent> _ghostHearingQuery = default!;
// Corvax-TTS-Start: Moved from Server to Shared
// public const int VoiceRange = 10; // how far voice goes in world units
@@ -801,10 +801,8 @@ public sealed partial class ChatSystem : SharedChatSystem
// TODO proper speech occlusion
var recipients = new Dictionary<ICommonSession, ICChatRecipientData>();
var ghostHearing = GetEntityQuery<GhostHearingComponent>();
var xforms = GetEntityQuery<TransformComponent>();
var transformSource = xforms.GetComponent(source);
var transformSource = Transform(source);
var sourceMapId = transformSource.MapID;
var sourceCoords = transformSource.Coordinates;
@@ -813,12 +811,12 @@ public sealed partial class ChatSystem : SharedChatSystem
if (player.AttachedEntity is not { Valid: true } playerEntity)
continue;
var transformEntity = xforms.GetComponent(playerEntity);
var transformEntity = Transform(playerEntity);
if (transformEntity.MapID != sourceMapId)
continue;
var observer = ghostHearing.HasComponent(playerEntity);
var observer = _ghostHearingQuery.HasComponent(playerEntity);
// even if they are a ghost hearer, in some situations we still need the range
if (sourceCoords.TryDistance(EntityManager, transformEntity.Coordinates, out var distance) && distance < voiceGetRange)
@@ -34,8 +34,8 @@ public sealed partial class CleanTileReaction : ITileReaction
FixedPoint2 ITileReaction.TileReact(TileRef tile,
ReagentPrototype reagent,
FixedPoint2 reactVolume,
IEntityManager entityManager
, List<ReagentData>? data)
IEntityManager entityManager,
List<ReagentData>? data)
{
var entities = entityManager.System<EntityLookupSystem>().GetLocalEntitiesIntersecting(tile, 0f).ToArray();
var puddleQuery = entityManager.GetEntityQuery<PuddleComponent>();
+1 -6
View File
@@ -1,5 +1,3 @@
using System.Linq;
using Content.Shared.Decals;
using Microsoft.Extensions.ObjectPool;
using Robust.Shared;
using Robust.Shared.Configuration;
@@ -22,14 +20,11 @@ public sealed partial class ChunkingSystem : EntitySystem
[Dependency] private IMapManager _mapManager = default!;
[Dependency] private SharedTransformSystem _transform = default!;
private EntityQuery<TransformComponent> _xformQuery;
private Box2 _baseViewBounds;
public override void Initialize()
{
base.Initialize();
_xformQuery = GetEntityQuery<TransformComponent>();
Subs.CVar(_configurationManager, CVars.NetMaxUpdateRange, OnPvsRangeChanged, true);
}
@@ -67,7 +62,7 @@ public sealed partial class ChunkingSystem : EntitySystem
int chunkSize,
float viewEnlargement)
{
if (!_xformQuery.TryGetComponent(viewer, out var xform))
if (!TryComp(viewer, out TransformComponent? xform))
return;
var pos = _transform.GetWorldPosition(xform);
@@ -88,8 +88,7 @@ namespace Content.Server.Construction.Conditions
var examineName = constructionSys.GetExamineName(info);
args.PushMarkup(Loc.GetString("construction-condition-machine-frame-required-element-entry",
("amount", info.Amount),
("elementName", examineName))
+ "\n");
("elementName", examineName)));
}
return true;
@@ -1,5 +1,4 @@
using Content.Server.DeviceLinking.Components;
using Content.Server.NodeContainer;
using Content.Server.Power.EntitySystems;
using Content.Server.Power.Nodes;
using Content.Server.Power.NodeGroups;
@@ -26,16 +25,10 @@ public sealed partial class PowerSensorSystem : EntitySystem
[Dependency] private SharedToolSystem _tool = default!;
[Dependency] private UseDelaySystem _useDelay = default!;
private EntityQuery<NodeContainerComponent> _nodeQuery;
private EntityQuery<TransformComponent> _xformQuery;
public override void Initialize()
{
base.Initialize();
_nodeQuery = GetEntityQuery<NodeContainerComponent>();
_xformQuery = GetEntityQuery<TransformComponent>();
SubscribeLocalEvent<PowerSensorComponent, ComponentInit>(OnInit);
SubscribeLocalEvent<PowerSensorComponent, ExaminedEvent>(OnExamined);
SubscribeLocalEvent<PowerSensorComponent, InteractUsingEvent>(OnInteractUsing);
@@ -99,7 +92,7 @@ public sealed partial class PowerSensorSystem : EntitySystem
var deviceNode = (CableDeviceNode) nodeContainer.Nodes[cable.Node];
// update state based on the power stats retrieved from the selected power network
var xform = _xformQuery.GetComponent(uid);
var xform = Transform(uid);
if (!TryComp(xform.GridUid, out MapGridComponent? grid))
return;
@@ -11,6 +11,7 @@ namespace Content.Server.DeviceNetwork.Systems;
public sealed partial class DeviceListSystem : SharedDeviceListSystem
{
[Dependency] private NetworkConfiguratorSystem _configurator = default!;
[Dependency] private EntityQuery<DeviceNetworkComponent> _deviceNetworkQuery = default!;
public override void Initialize()
{
@@ -28,10 +29,9 @@ public sealed partial class DeviceListSystem : SharedDeviceListSystem
_configurator.OnDeviceListShutdown(conf, (uid, component));
}
var query = GetEntityQuery<DeviceNetworkComponent>();
foreach (var device in component.Devices)
{
if (query.TryGetComponent(device, out var comp))
if (_deviceNetworkQuery.TryGetComponent(device, out var comp))
comp.DeviceLists.Remove(uid);
}
component.Devices.Clear();
@@ -125,7 +125,6 @@ public sealed partial class DeviceListSystem : SharedDeviceListSystem
private void OnMapSave(BeforeSerializationEvent ev)
{
List<EntityUid> toRemove = new();
var query = GetEntityQuery<TransformComponent>();
var enumerator = AllEntityQuery<DeviceListComponent, TransformComponent>();
while (enumerator.MoveNext(out var uid, out var device, out var xform))
{
@@ -134,7 +133,7 @@ public sealed partial class DeviceListSystem : SharedDeviceListSystem
foreach (var ent in device.Devices)
{
if (!query.TryGetComponent(ent, out var linkedXform))
if (!TryComp(ent, out TransformComponent? linkedXform))
{
// Entity was deleted.
// TODO remove these on deletion instead of on-save.
@@ -190,7 +189,6 @@ public sealed partial class DeviceListSystem : SharedDeviceListSystem
return DeviceListUpdateResult.TooManyDevices;
}
var query = GetEntityQuery<DeviceNetworkComponent>();
var oldDevices = deviceList.Devices.ToList();
foreach (var device in oldDevices)
{
@@ -198,13 +196,13 @@ public sealed partial class DeviceListSystem : SharedDeviceListSystem
continue;
deviceList.Devices.Remove(device);
if (query.TryGetComponent(device, out var comp))
if (_deviceNetworkQuery.TryGetComponent(device, out var comp))
comp.DeviceLists.Remove(uid);
}
foreach (var device in newDevices)
{
if (!query.TryGetComponent(device, out var comp))
if (!_deviceNetworkQuery.TryGetComponent(device, out var comp))
continue;
if (!deviceList.Devices.Add(device))
@@ -37,6 +37,7 @@ public sealed partial class NetworkConfiguratorSystem : SharedNetworkConfigurato
[Dependency] private SharedAppearanceSystem _appearanceSystem = default!;
[Dependency] private IGameTiming _gameTiming = default!;
[Dependency] private IAdminLogManager _adminLogger = default!;
[Dependency] private EntityQuery<DeviceNetworkComponent> _deviceNetworkQuery = default!;
public override void Initialize()
{
@@ -632,10 +633,9 @@ public sealed partial class NetworkConfiguratorSystem : SharedNetworkConfigurato
private void ClearDevices(EntityUid uid, NetworkConfiguratorComponent component)
{
var query = GetEntityQuery<DeviceNetworkComponent>();
foreach (var device in component.Devices.Values)
{
if (query.TryGetComponent(device, out var comp))
if (_deviceNetworkQuery.TryGetComponent(device, out var comp))
comp.Configurators.Remove(uid);
}
@@ -794,10 +794,9 @@ public sealed partial class NetworkConfiguratorSystem : SharedNetworkConfigurato
ClearDevices(uid, component);
var query = GetEntityQuery<DeviceNetworkComponent>();
foreach (var (addr, device) in _deviceListSystem.GetDeviceList(component.ActiveDeviceList.Value))
{
if (query.TryGetComponent(device, out var comp))
if (_deviceNetworkQuery.TryGetComponent(device, out var comp))
{
component.Devices.Add(addr, device);
comp.Configurators.Add(uid);
+15 -22
View File
@@ -2,7 +2,6 @@ using Content.Server.Atmos.Components;
using Content.Server.Atmos.EntitySystems;
using Content.Server.Atmos.Monitor.Components;
using Content.Server.Atmos.Monitor.Systems;
using Content.Server.Power.Components;
using Content.Server.Power.EntitySystems;
using Content.Server.Shuttles.Components;
using Content.Shared.Atmos;
@@ -24,7 +23,10 @@ namespace Content.Server.Doors.Systems
[Dependency] private SharedMapSystem _mapping = default!;
[Dependency] private PointLightSystem _pointLight = default!;
private EntityQuery<AtmosAlarmableComponent> _atmosAlarmQuery;
[Dependency] private EntityQuery<AtmosAlarmableComponent> _atmosAlarmQuery = default!;
[Dependency] private EntityQuery<AirtightComponent> _airtightQuery = default!;
[Dependency] private EntityQuery<AppearanceComponent> _appearanceQuery = default!;
[Dependency] private EntityQuery<PointLightComponent> _pointLightQuery = default!;
private const int UpdateInterval = 30;
private int _accumulatedTicks;
@@ -35,8 +37,6 @@ namespace Content.Server.Doors.Systems
SubscribeLocalEvent<FirelockComponent, AtmosAlarmEvent>(OnAtmosAlarm);
SubscribeLocalEvent<FirelockComponent, PowerChangedEvent>(PowerChanged);
_atmosAlarmQuery = GetEntityQuery<AtmosAlarmableComponent>();
}
private void PowerChanged(EntityUid uid, FirelockComponent component, ref PowerChangedEvent args)
@@ -53,10 +53,6 @@ namespace Content.Server.Doors.Systems
_accumulatedTicks = 0;
var airtightQuery = GetEntityQuery<AirtightComponent>();
var appearanceQuery = GetEntityQuery<AppearanceComponent>();
var xformQuery = GetEntityQuery<TransformComponent>();
var pointLightQuery = GetEntityQuery<PointLightComponent>();
var query = EntityQueryEnumerator<FirelockComponent, DoorComponent>();
while (query.MoveNext(out var uid, out var firelock, out var door))
@@ -77,11 +73,10 @@ namespace Content.Server.Doors.Systems
continue;
}
if (airtightQuery.TryGetComponent(uid, out var airtight)
&& xformQuery.TryGetComponent(uid, out var xform)
&& appearanceQuery.TryGetComponent(uid, out var appearance))
if (_airtightQuery.TryGetComponent(uid, out var airtight)
&& _appearanceQuery.TryGetComponent(uid, out var appearance))
{
var (pressure, fire) = CheckPressureAndFire(uid, firelock, xform, airtight, airtightQuery);
var (pressure, fire) = CheckPressureAndFire(uid, firelock, airtight);
_appearance.SetData(uid, DoorVisuals.ClosedLights, fire || pressure, appearance);
firelock.Temperature = fire;
firelock.Pressure = pressure;
@@ -89,7 +84,7 @@ namespace Content.Server.Doors.Systems
_appearance.SetData(uid, FirelockVisuals.TemperatureWarning, fire, appearance);
Dirty(uid, firelock);
if (pointLightQuery.TryComp(uid, out var pointLight))
if (_pointLightQuery.TryComp(uid, out var pointLight))
{
_pointLight.SetEnabled(uid, fire | pressure, pointLight);
}
@@ -118,18 +113,15 @@ namespace Content.Server.Doors.Systems
public (bool Pressure, bool Fire) CheckPressureAndFire(EntityUid uid, FirelockComponent firelock)
{
var query = GetEntityQuery<AirtightComponent>();
if (query.TryGetComponent(uid, out AirtightComponent? airtight))
return CheckPressureAndFire(uid, firelock, Transform(uid), airtight, query);
if (_airtightQuery.TryGetComponent(uid, out AirtightComponent? airtight))
return CheckPressureAndFire(uid, firelock, airtight);
return (false, false);
}
public (bool Pressure, bool Fire) CheckPressureAndFire(
EntityUid uid,
FirelockComponent firelock,
TransformComponent xform,
AirtightComponent airtight,
EntityQuery<AirtightComponent> airtightQuery)
AirtightComponent airtight)
{
if (!airtight.AirBlocked)
return (false, false);
@@ -140,6 +132,7 @@ namespace Content.Server.Doors.Systems
return (false, false);
}
var xform = Transform(uid);
if (!HasComp<GridAtmosphereComponent>(xform.ParentUid))
return (false, false);
@@ -190,7 +183,7 @@ namespace Content.Server.Doors.Systems
{
// Is there some airtight entity blocking this direction? If yes, don't include this direction in the
// pressure differential
if (HasAirtightBlocker(_mapping.GetAnchoredEntities(xform.ParentUid, grid, adjacentPos), dir.GetOpposite(), airtightQuery))
if (HasAirtightBlocker(_mapping.GetAnchoredEntities(xform.ParentUid, grid, adjacentPos), dir.GetOpposite()))
continue;
var p = gas.Pressure;
@@ -233,11 +226,11 @@ namespace Content.Server.Doors.Systems
return (holdingPressure, holdingFire);
}
private bool HasAirtightBlocker(IEnumerable<EntityUid> enumerable, AtmosDirection dir, EntityQuery<AirtightComponent> airtightQuery)
private bool HasAirtightBlocker(IEnumerable<EntityUid> enumerable, AtmosDirection dir)
{
foreach (var ent in enumerable)
{
if (!airtightQuery.TryGetComponent(ent, out var airtight) || !airtight.AirBlocked)
if (!_airtightQuery.TryGetComponent(ent, out var airtight) || !airtight.AirBlocked)
continue;
if ((airtight.AirBlockedDirection & dir) == dir)
+3 -6
View File
@@ -8,7 +8,6 @@ using Content.Shared.Dragon;
using Content.Shared.Gibbing;
using Content.Shared.Maps;
using Content.Shared.Mind;
using Content.Shared.Mind.Components;
using Content.Shared.Mobs;
using Content.Shared.Mobs.Systems;
using Content.Shared.Movement.Systems;
@@ -36,7 +35,7 @@ public sealed partial class DragonSystem : EntitySystem
[Dependency] private GibbingSystem _gibbing = default!;
[Dependency] private SmokeSystem _smoke = default!;
private EntityQuery<CarpRiftsConditionComponent> _objQuery;
[Dependency] private EntityQuery<CarpRiftsConditionComponent> _carpRiftsConditionQuery = default!;
/// <summary>
/// Minimum distance between 2 rifts allowed.
@@ -54,8 +53,6 @@ public sealed partial class DragonSystem : EntitySystem
{
base.Initialize();
_objQuery = GetEntityQuery<CarpRiftsConditionComponent>();
SubscribeLocalEvent<DragonComponent, MapInitEvent>(OnInit);
SubscribeLocalEvent<DragonComponent, ComponentShutdown>(OnShutdown);
SubscribeLocalEvent<DragonComponent, DragonSpawnRiftActionEvent>(OnSpawnRift);
@@ -244,7 +241,7 @@ public sealed partial class DragonSystem : EntitySystem
foreach (var objId in mind.Objectives)
{
if (_objQuery.TryGetComponent(objId, out var obj))
if (_carpRiftsConditionQuery.TryGetComponent(objId, out var obj))
{
_carpRifts.ResetRifts(objId, obj);
break;
@@ -265,7 +262,7 @@ public sealed partial class DragonSystem : EntitySystem
foreach (var objId in mind.Objectives)
{
if (_objQuery.TryGetComponent(objId, out var obj))
if (_carpRiftsConditionQuery.TryGetComponent(objId, out var obj))
{
_carpRifts.RiftCharged(objId, obj);
break;
@@ -1,8 +1,6 @@
using System.Numerics;
using Content.Shared.Atmos;
using Content.Shared.Explosion;
using Content.Shared.Explosion.Components;
using Content.Shared.Explosion.EntitySystems;
using Robust.Shared.Map;
using Robust.Shared.Map.Components;
@@ -102,9 +100,8 @@ public sealed partial class ExplosionSystem
continue;
}
var xforms = GetEntityQuery<TransformComponent>();
var xform = xforms.GetComponent(gridToTransform);
var (_, gridWorldRotation, gridWorldMatrix, invGridWorldMatrid) = _transformSystem.GetWorldPositionRotationMatrixWithInv(xform, xforms);
var xform = Transform(gridToTransform);
var (_, gridWorldRotation, gridWorldMatrix, invGridWorldMatrid) = _transformSystem.GetWorldPositionRotationMatrixWithInv(xform);
var localEpicentre = (Vector2i) Vector2.Transform(epicentre.Position, invGridWorldMatrid);
var matrix = offsetMatrix * gridWorldMatrix * targetMatrix;
@@ -681,13 +681,6 @@ sealed class Explosion
/// </summary>
private readonly Dictionary<Entity<MapGridComponent>, List<(Vector2i, Tile)>> _tileUpdateDict = new();
// Entity Queries
private readonly EntityQuery<TransformComponent> _xformQuery;
private readonly EntityQuery<PhysicsComponent> _physicsQuery;
private readonly EntityQuery<DamageableComponent> _damageQuery;
private readonly EntityQuery<ProjectileComponent> _projectileQuery;
private readonly EntityQuery<TagComponent> _tagQuery;
/// <summary>
/// Total area that the explosion covers.
/// </summary>
@@ -753,12 +746,6 @@ sealed class Explosion
_entMan = entMan;
_damageable = damageable;
_xformQuery = entMan.GetEntityQuery<TransformComponent>();
_physicsQuery = entMan.GetEntityQuery<PhysicsComponent>();
_damageQuery = entMan.GetEntityQuery<DamageableComponent>();
_tagQuery = entMan.GetEntityQuery<TagComponent>();
_projectileQuery = entMan.GetEntityQuery<ProjectileComponent>();
if (spaceData != null)
{
var mapUid = mapSystem.GetMap(epicenter.MapId);
@@ -59,15 +59,14 @@ public sealed partial class ExplosionSystem : SharedExplosionSystem
[Dependency] private DestructibleSystem _destructibleSystem = default!;
[Dependency] private AtmosphereSystem _atmosphere = default!;
private EntityQuery<FlammableComponent> _flammableQuery;
private EntityQuery<PhysicsComponent> _physicsQuery;
private EntityQuery<ProjectileComponent> _projectileQuery;
private EntityQuery<ActorComponent> _actorQuery;
private EntityQuery<DestructibleComponent> _destructibleQuery;
private EntityQuery<DamageableComponent> _damageableQuery;
[Dependency] private EntityQuery<FlammableComponent> _flammableQuery = default!;
[Dependency] private EntityQuery<PhysicsComponent> _physicsQuery = default!;
[Dependency] private EntityQuery<ActorComponent> _actorQuery = default!;
[Dependency] private EntityQuery<DestructibleComponent> _destructibleQuery = default!;
[Dependency] private EntityQuery<DamageableComponent> _damageableQuery = default!;
[Dependency] private EntityQuery<InjurableComponent> _injurableQuery = default!;
private EntityQuery<AirtightComponent> _airtightQuery;
private EntityQuery<TileHistoryComponent> _tileHistoryQuery;
[Dependency] private EntityQuery<AirtightComponent> _airtightQuery = default!;
[Dependency] private EntityQuery<TileHistoryComponent> _tileHistoryQuery = default!;
/// <summary>
/// "Tile-size" for space when there are no nearby grids to use as a reference.
@@ -103,15 +102,6 @@ public sealed partial class ExplosionSystem : SharedExplosionSystem
InitAirtightMap();
InitVisuals();
_flammableQuery = GetEntityQuery<FlammableComponent>();
_physicsQuery = GetEntityQuery<PhysicsComponent>();
_projectileQuery = GetEntityQuery<ProjectileComponent>();
_actorQuery = GetEntityQuery<ActorComponent>();
_destructibleQuery = GetEntityQuery<DestructibleComponent>();
_damageableQuery = GetEntityQuery<DamageableComponent>();
_airtightQuery = GetEntityQuery<AirtightComponent>();
_tileHistoryQuery = GetEntityQuery<TileHistoryComponent>();
_prototypeManager.PrototypesReloaded += ReloadExplosionPrototypes;
}
@@ -37,7 +37,8 @@ public sealed partial class PuddleSystem : SharedPuddleSystem
[Dependency] private SharedTransformSystem _transform = default!;
[Dependency] private TurfSystem _turf = default!;
private EntityQuery<PuddleComponent> _puddleQuery;
[Dependency] private EntityQuery<PuddleComponent> _puddleQuery = default!;
[Dependency] private EntityQuery<EvaporationSparkleComponent> _evaporationSparklesQuery = default!;
/*
* TODO: Need some sort of way to do blood slash / vomit solution spill on its own
@@ -49,8 +50,6 @@ public sealed partial class PuddleSystem : SharedPuddleSystem
{
base.Initialize();
_puddleQuery = GetEntityQuery<PuddleComponent>();
SubscribeLocalEvent<PuddleComponent, SpreadNeighborsEvent>(OnPuddleSpread);
SubscribeLocalEvent<PuddleComponent, SlipEvent>(OnPuddleSlip);
}
@@ -151,7 +150,7 @@ public sealed partial class PuddleSystem : SharedPuddleSystem
break;
}
// If there is nothing left to overflow from our tile, then we'll stop this tile being a active spreader
// If there is nothing left to overflow from our tile, then we'll stop this tile being an active spreader
if (overflow.Volume == FixedPoint2.Zero)
{
RemCompDeferred<ActiveEdgeSpreaderComponent>(entity);
@@ -517,19 +516,17 @@ public sealed partial class PuddleSystem : SharedPuddleSystem
// Get normalized co-ordinate for spill location and spill it in the centre
// TODO: Does SnapGrid or something else already do this?
var anchored = _map.GetAnchoredEntitiesEnumerator(gridId, mapGrid, tileRef.GridIndices);
var puddleQuery = GetEntityQuery<PuddleComponent>();
var sparklesQuery = GetEntityQuery<EvaporationSparkleComponent>();
while (anchored.MoveNext(out var ent))
{
// If there's existing sparkles then delete it
if (sparklesQuery.TryGetComponent(ent, out var sparkles))
if (_evaporationSparklesQuery.TryGetComponent(ent, out var sparkles))
{
QueueDel(ent.Value);
continue;
}
if (!puddleQuery.TryGetComponent(ent, out var puddle))
if (!_puddleQuery.TryGetComponent(ent, out var puddle))
continue;
if (TryAddSolution(ent.Value, solution, sound, puddleComponent: puddle))
@@ -565,11 +562,9 @@ public sealed partial class PuddleSystem : SharedPuddleSystem
return false;
var anc = _map.GetAnchoredEntitiesEnumerator(tile.GridUid, grid, tile.GridIndices);
var puddleQuery = GetEntityQuery<PuddleComponent>();
while (anc.MoveNext(out var ent))
{
if (!puddleQuery.HasComponent(ent.Value))
if (!_puddleQuery.HasComponent(ent.Value))
continue;
puddleUid = ent.Value;
@@ -1,6 +1,5 @@
using Content.Server.Administration.Logs;
using Content.Server.Body.Systems;
using Content.Shared.EntityEffects.Effects;
using Content.Server.Spreader;
using Content.Shared.Body.Components;
using Content.Shared.Chemistry;
@@ -45,17 +44,14 @@ public sealed partial class SmokeSystem : EntitySystem
[Dependency] private SharedPhysicsSystem _physics = default!;
[Dependency] private SharedSolutionContainerSystem _solutionContainerSystem = default!;
private EntityQuery<SmokeComponent> _smokeQuery;
private EntityQuery<SmokeAffectedComponent> _smokeAffectedQuery;
[Dependency] private EntityQuery<SmokeComponent> _smokeQuery = default!;
[Dependency] private EntityQuery<SmokeAffectedComponent> _smokeAffectedQuery = default!;
/// <inheritdoc/>
public override void Initialize()
{
base.Initialize();
_smokeQuery = GetEntityQuery<SmokeComponent>();
_smokeAffectedQuery = GetEntityQuery<SmokeAffectedComponent>();
SubscribeLocalEvent<SmokeComponent, StartCollideEvent>(OnStartCollide);
SubscribeLocalEvent<SmokeComponent, EndCollideEvent>(OnEndCollide);
SubscribeLocalEvent<SmokeComponent, ReactionAttemptEvent>(OnReactionAttempt);
@@ -165,12 +161,10 @@ public sealed partial class SmokeSystem : EntitySystem
// We have no more neighbours to spread to. So instead we will randomly distribute our volume to neighbouring smoke tiles.
var smokeQuery = GetEntityQuery<SmokeComponent>();
_random.Shuffle(args.Neighbors);
foreach (var neighbor in args.Neighbors)
{
if (!smokeQuery.TryGetComponent(neighbor, out var smoke))
if (!_smokeQuery.TryGetComponent(neighbor, out var smoke))
continue;
smoke.SpreadAmount++;
@@ -49,7 +49,7 @@ public sealed partial class SpraySystem : SharedSpraySystem
args.Handled = true;
var targetMapPos = _transform.GetMapCoordinates(GetEntityQuery<TransformComponent>().GetComponent(args.Target));
var targetMapPos = _transform.GetMapCoordinates(Transform(args.Target));
Spray(entity, targetMapPos, args.User);
}
@@ -104,8 +104,7 @@ public sealed partial class SpraySystem : SharedSpraySystem
return;
}
var xformQuery = GetEntityQuery<TransformComponent>();
var sprayerXform = xformQuery.GetComponent(entity);
var sprayerXform = Transform(entity);
var sprayerMapPos = _transform.GetMapCoordinates(sprayerXform);
var clickMapPos = mapcoord;
@@ -149,7 +148,7 @@ public sealed partial class SpraySystem : SharedSpraySystem
// Spawn the vapor cloud onto the grid/map the user is present on. Offset the start position based on how far the target destination is.
var vaporPos = sprayerMapPos.Offset(distance < 1 ? quarter : threeQuarters);
var vapor = Spawn(entity.Comp.SprayedPrototype, vaporPos);
var vaporXform = xformQuery.GetComponent(vapor);
var vaporXform = Transform(vapor);
_transform.SetWorldRotation(vaporXform, rotation);
@@ -4,7 +4,6 @@ using System.Numerics;
using Content.Server.Administration.Managers;
using Content.Server.Administration.Systems;
using Content.Server.GameTicking.Events;
using Content.Server.Ghost;
using Content.Server.Spawners.Components;
using Content.Server.Speech.Components;
using Content.Server.Station.Components;
@@ -460,15 +459,13 @@ namespace Content.Server.GameTicking
_possiblePositions.Add(transform.Coordinates);
}
var metaQuery = GetEntityQuery<MetaDataComponent>();
// Fallback to a random grid.
if (_possiblePositions.Count == 0)
{
var query = AllEntityQuery<MapGridComponent>();
while (query.MoveNext(out var uid, out var grid))
{
if (!metaQuery.TryGetComponent(uid, out var meta) || meta.EntityPaused || TerminatingOrDeleted(uid))
if (!TryComp(uid, out MetaDataComponent? meta) || meta.EntityPaused || TerminatingOrDeleted(uid))
{
continue;
}
@@ -507,7 +504,7 @@ namespace Content.Server.GameTicking
{
var mapUid = _map.GetMapOrInvalid(map);
if (!metaQuery.TryGetComponent(mapUid, out var meta)
if (!TryComp(mapUid, out MetaDataComponent? meta)
|| meta.EntityPaused
|| TerminatingOrDeleted(mapUid))
{
@@ -17,16 +17,15 @@ using Content.Shared.GameTicking.Components;
using Content.Shared.Humanoid;
using Content.Shared.IdentityManagement;
using Content.Shared.Mind.Components;
using Content.Shared.Mindshield.Components;
using Content.Shared.Mobs;
using Content.Shared.Mobs.Components;
using Content.Shared.Mobs.Systems;
using Content.Shared.NPC.Prototypes;
using Content.Shared.NPC.Systems;
using Content.Shared.Revolutionary;
using Content.Shared.Revolutionary.Components;
using Content.Shared.Roles.Components;
using Content.Shared.Stunnable;
using Content.Shared.Zombies;
using Robust.Shared.Prototypes;
using Robust.Shared.Timing;
using Content.Shared.Cuffs.Components;
@@ -142,17 +141,20 @@ public sealed partial class RevolutionaryRuleSystem : GameRuleSystem<Revolutiona
if (!_mind.TryGetMind(ev.Target, out var mindId, out var mind) && !alwaysConvertible)
return;
if (HasComp<RevolutionaryComponent>(ev.Target) ||
HasComp<MindShieldComponent>(ev.Target) ||
!HasComp<HumanoidProfileComponent>(ev.Target) &&
if (!HasComp<HumanoidProfileComponent>(ev.Target) &&
!alwaysConvertible ||
!_mobState.IsAlive(ev.Target) ||
HasComp<ZombieComponent>(ev.Target) ||
!HasComp<RevolutionaryConverterComponent>(ev.Used))
{
return;
}
var attemptConvertEv = new AttemptConvertRevolutionaryEvent();
RaiseLocalEvent(ev.Target, ref attemptConvertEv);
if (attemptConvertEv.Cancelled)
return;
_npcFaction.AddFaction(ev.Target, RevolutionaryNpcFaction);
var revComp = EnsureComp<RevolutionaryComponent>(ev.Target);
@@ -35,6 +35,7 @@ public sealed partial class ZombieRuleSystem : GameRuleSystem<ZombieRuleComponen
[Dependency] private SharedRoleSystem _roles = default!;
[Dependency] private StationSystem _station = default!;
[Dependency] private ZombieSystem _zombie = default!;
[Dependency] private EntityQuery<ZombieComponent> _zombieQuery = default!;
public override void Initialize()
{
@@ -198,13 +199,12 @@ public sealed partial class ZombieRuleSystem : GameRuleSystem<ZombieRuleComponen
}
var players = AllEntityQuery<HumanoidProfileComponent, ActorComponent, MobStateComponent, TransformComponent>();
var zombers = GetEntityQuery<ZombieComponent>();
while (players.MoveNext(out var uid, out _, out _, out var mob, out var xform))
{
if (!_mobState.IsAlive(uid, mob))
continue;
if (zombers.HasComponent(uid))
if (_zombieQuery.HasComponent(uid))
continue;
if (!includeOffStation && !stationGrids.Contains(xform.GridUid ?? EntityUid.Invalid))
+2 -5
View File
@@ -68,8 +68,8 @@ namespace Content.Server.Ghost
[Dependency] private NameModifierSystem _nameMod = default!;
[Dependency] private GhostSpriteStateSystem _ghostState = default!;
private EntityQuery<GhostComponent> _ghostQuery;
private EntityQuery<PhysicsComponent> _physicsQuery;
[Dependency] private EntityQuery<GhostComponent> _ghostQuery = default!;
[Dependency] private EntityQuery<PhysicsComponent> _physicsQuery = default!;
private static readonly ProtoId<TagPrototype> AllowGhostShownByEventTag = "AllowGhostShownByEvent";
private static readonly ProtoId<DamageTypePrototype> AsphyxiationDamageType = "Asphyxiation";
@@ -78,9 +78,6 @@ namespace Content.Server.Ghost
{
base.Initialize();
_ghostQuery = GetEntityQuery<GhostComponent>();
_physicsQuery = GetEntityQuery<PhysicsComponent>();
SubscribeLocalEvent<GhostComponent, ComponentStartup>(OnGhostStartup);
SubscribeLocalEvent<GhostComponent, MapInitEvent>(OnMapInit);
SubscribeLocalEvent<GhostComponent, ComponentShutdown>(OnGhostShutdown);
@@ -622,8 +622,7 @@ public sealed partial class GhostRoleSystem : EntitySystem
/// </summary>
public int GetGhostRoleCount()
{
var metaQuery = GetEntityQuery<MetaDataComponent>();
return _ghostRoles.Count(pair => metaQuery.GetComponent(pair.Value.Owner).EntityPaused == false);
return _ghostRoles.Count(pair => MetaData(pair.Value.Owner).EntityPaused == false);
}
/// <summary>
@@ -635,11 +634,10 @@ public sealed partial class GhostRoleSystem : EntitySystem
public GhostRoleInfo[] GetGhostRolesInfo(ICommonSession? player)
{
var roles = new List<GhostRoleInfo>();
var metaQuery = GetEntityQuery<MetaDataComponent>();
foreach (var (id, (uid, role)) in _ghostRoles)
{
if (metaQuery.GetComponent(uid).EntityPaused)
if (MetaData(uid).EntityPaused)
continue;
+1 -4
View File
@@ -32,8 +32,7 @@ namespace Content.Server.Hands.Systems
[Dependency] private SharedTransformSystem _transformSystem = default!;
[Dependency] private PullingSystem _pullingSystem = default!;
[Dependency] private ThrowingSystem _throwingSystem = default!;
private EntityQuery<PhysicsComponent> _physicsQuery;
[Dependency] private EntityQuery<PhysicsComponent> _physicsQuery = default!;
/// <summary>
/// Items dropped when the holder falls down will be launched in
@@ -57,8 +56,6 @@ namespace Content.Server.Hands.Systems
CommandBinds.Builder
.Bind(ContentKeyFunctions.ThrowItemInHand, new PointerInputCmdHandler(HandleThrowItem))
.Register<HandsSystem>();
_physicsQuery = GetEntityQuery<PhysicsComponent>();
}
public override void Shutdown()
+71 -38
View File
@@ -42,9 +42,7 @@ public sealed partial class HolopadSystem : SharedHolopadSystem
[Dependency] private IGameTiming _timing = default!;
[Dependency] private PvsOverrideSystem _pvs = default!;
[Dependency] private SharedPowerStateSystem _powerState = default!;
private float _updateTimer = 1.0f;
private const float UpdateTime = 1.0f;
[Dependency] private MetaDataSystem _meta = default!;
public override void Initialize()
{
@@ -79,10 +77,10 @@ public sealed partial class HolopadSystem : SharedHolopadSystem
SubscribeLocalEvent<HolopadUserComponent, JumpToCoreEvent>(OnJumpToCore);
SubscribeLocalEvent<HolopadComponent, GetVerbsEvent<AlternativeVerb>>(AddToggleProjectorVerb);
SubscribeLocalEvent<HolopadComponent, EntRemovedFromContainerMessage>(OnAiRemove);
SubscribeLocalEvent<HolopadComponent, EntParentChangedMessage>(OnParentChanged);
SubscribeLocalEvent<HolopadComponent, MapUidChangedEvent>(OnMapUidChanged);
SubscribeLocalEvent<HolopadComponent, PowerChangedEvent>(OnPowerChanged);
SubscribeLocalEvent<HolopadComponent, AnchorStateChangedEvent>(OnAnchorChanged);
SubscribeLocalEvent<HolopadUserComponent, MobStateChangedEvent>(OnMobStateChanged);
}
#region: Holopad UI bound user interface messages
@@ -263,6 +261,8 @@ public sealed partial class HolopadSystem : SharedHolopadSystem
SetHolopadAmbientState(holopad, this.IsPowered(holopad, EntityManager));
break;
}
UpdateUIState(holopad);
}
private void OnHoloCallCommenced(Entity<HolopadComponent> source, ref TelephoneCallCommencedEvent args)
@@ -315,7 +315,7 @@ public sealed partial class HolopadSystem : SharedHolopadSystem
if (receiverHolopad.Comp.Hologram == null)
continue;
_appearanceSystem.SetData(receiverHolopad.Comp.Hologram.Value.Owner, TypingIndicatorVisuals.State, ev.State);
_appearanceSystem.SetData(receiverHolopad.Comp.Hologram.Value, TypingIndicatorVisuals.State, ev.State);
}
}
}
@@ -328,6 +328,8 @@ public sealed partial class HolopadSystem : SharedHolopadSystem
{
if (entity.Comp.User != null)
LinkHolopadToUser(entity, entity.Comp.User.Value);
_meta.AddFlag(entity, MetaDataFlags.ExtraTransformEvents);
}
private void OnHolopadUserInit(Entity<HolopadUserComponent> entity, ref ComponentInit args)
@@ -343,6 +345,7 @@ public sealed partial class HolopadSystem : SharedHolopadSystem
ShutDownHolopad(entity);
SetHolopadAmbientState(entity, false);
UpdateAllUIStates();
}
private void OnHolopadUserShutdown(Entity<HolopadUserComponent> entity, ref ComponentShutdown args)
@@ -444,15 +447,25 @@ public sealed partial class HolopadSystem : SharedHolopadSystem
_telephoneSystem.EndTelephoneCalls((entity, entityTelephone));
}
private void OnParentChanged(Entity<HolopadComponent> entity, ref EntParentChangedMessage args)
private void OnMapUidChanged(Entity<HolopadComponent> entity, ref MapUidChangedEvent args)
{
UpdateHolopadControlLockoutStartTime(entity);
UpdateAllUIStates();
}
private void OnPowerChanged(Entity<HolopadComponent> entity, ref PowerChangedEvent args)
{
if (args.Powered)
{
UpdateHolopadControlLockoutStartTime(entity);
}
UpdateAllUIStates();
}
private void OnAnchorChanged(Entity<HolopadComponent> entity, ref AnchorStateChangedEvent args)
{
UpdateAllUIStates();
}
private void OnMobStateChanged(Entity<HolopadUserComponent> ent, ref MobStateChangedEvent args)
@@ -472,27 +485,37 @@ public sealed partial class HolopadSystem : SharedHolopadSystem
{
base.Update(frameTime);
_updateTimer += frameTime;
if (_updateTimer >= UpdateTime)
var query = AllEntityQuery<HolopadUserComponent, TransformComponent>();
while (query.MoveNext(out var uid, out var holopadUser, out var xform))
{
_updateTimer -= UpdateTime;
if (HasComp<IgnoreUIRangeComponent>(uid))
continue;
var query = AllEntityQuery<HolopadComponent, TelephoneComponent, TransformComponent>();
while (query.MoveNext(out var uid, out var holopad, out var telephone, out var xform))
foreach (var holopad in holopadUser.LinkedHolopads)
{
UpdateUIState((uid, holopad), telephone);
if (holopad.User != null &&
!HasComp<IgnoreUIRangeComponent>(holopad.User) &&
!_xformSystem.InRange((holopad.User.Value, Transform(holopad.User.Value)), (uid, xform), telephone.ListeningRange))
if (TryComp<TelephoneComponent>(holopad, out var telephone) &&
!_xformSystem.InRange((holopad.Owner, Transform(holopad)), (uid, xform), telephone.ListeningRange))
{
UnlinkHolopadFromUser((uid, holopad), holopad.User.Value);
UnlinkHolopadFromUser(holopad, (uid, holopadUser));
}
}
}
}
public void UpdateAllUIStates()
{
var querySources = AllEntityQuery<HolopadComponent, TelephoneComponent, UserInterfaceComponent>();
while (querySources.MoveNext(out var uid, out var holopad, out var telephone, out var ui))
{
var uiKey = HasComp<StationAiCoreComponent>(uid) ? HolopadUiKey.AiActionWindow : HolopadUiKey.InteractionWindow;
if (!_userInterfaceSystem.IsUiOpen((uid, ui), uiKey))
continue;
UpdateUIState((uid, holopad), telephone);
}
}
public void UpdateUIState(Entity<HolopadComponent> entity, TelephoneComponent? telephone = null)
{
if (!Resolve(entity.Owner, ref telephone, false))
@@ -571,23 +594,26 @@ public sealed partial class HolopadSystem : SharedHolopadSystem
return;
}
if (!TryComp<HolopadUserComponent>(user, out var holopadUser))
holopadUser = AddComp<HolopadUserComponent>(user.Value);
var holopadUser = EnsureComp<HolopadUserComponent>(user.Value);
var userEnt = (user.Value, holopadUser);
if (user != entity.Comp.User?.Owner)
if (user != entity.Comp.User)
{
// Removes the old user from the holopad
UnlinkHolopadFromUser(entity, entity.Comp.User);
if (TryComp<HolopadUserComponent>(entity.Comp.User, out var oldHolopadUser))
{
UnlinkHolopadFromUser(entity, (entity.Comp.User.Value, oldHolopadUser));
}
// Assigns the new user in their place
holopadUser.LinkedHolopads.Add(entity);
entity.Comp.User = (user.Value, holopadUser);
holopadUser?.LinkedHolopads.Add(entity);
entity.Comp.User = user.Value;
}
// Add the new user to PVS and sync their appearance with any
// holopads connected to the one they are using
_pvs.AddGlobalOverride(user.Value);
SyncHolopadHologramAppearanceWithTarget(entity, entity.Comp.User);
SyncHolopadHologramAppearanceWithTarget(entity, userEnt);
}
private void UnlinkHolopadFromUser(Entity<HolopadComponent> entity, Entity<HolopadUserComponent>? user)
@@ -611,14 +637,14 @@ public sealed partial class HolopadSystem : SharedHolopadSystem
{
foreach (var linkedHolopad in GetLinkedHolopads(entity))
{
if (linkedHolopad.Comp.Hologram == null)
if (!TryComp<HolopadHologramComponent>(linkedHolopad.Comp.Hologram, out var holopadHologram))
continue;
if (user == null)
_appearanceSystem.SetData(linkedHolopad.Comp.Hologram.Value.Owner, TypingIndicatorVisuals.State, false);
_appearanceSystem.SetData(linkedHolopad.Comp.Hologram.Value, TypingIndicatorVisuals.State, false);
linkedHolopad.Comp.Hologram.Value.Comp.LinkedEntity = user;
Dirty(linkedHolopad.Comp.Hologram.Value);
holopadHologram.LinkedEntity = user;
Dirty(linkedHolopad.Comp.Hologram.Value, holopadHologram);
}
}
@@ -626,8 +652,8 @@ public sealed partial class HolopadSystem : SharedHolopadSystem
{
entity.Comp.ControlLockoutOwner = null;
if (entity.Comp.Hologram != null)
DeleteHologram(entity.Comp.Hologram.Value, entity);
if (TryComp<HolopadHologramComponent>(entity.Comp.Hologram, out var holopadHologram))
DeleteHologram((entity.Comp.Hologram.Value, holopadHologram), entity);
// Check if the associated holopad user is an AI
if (HasComp<StationAiHeldComponent>(entity.Comp.User) &&
@@ -643,9 +669,9 @@ public sealed partial class HolopadSystem : SharedHolopadSystem
_telephoneSystem.EndTelephoneCalls((stationAiCore.Owner, stationAiCoreTelephone));
}
}
else
else if (TryComp<HolopadUserComponent>(entity.Comp.User, out var holopadUser))
{
UnlinkHolopadFromUser(entity, entity.Comp.User);
UnlinkHolopadFromUser(entity, (entity.Comp.User.Value, holopadUser));
}
Dirty(entity);
@@ -749,14 +775,16 @@ public sealed partial class HolopadSystem : SharedHolopadSystem
// Lock out the controls of all involved holopads for a set duration
source.Comp.ControlLockoutOwner = user;
source.Comp.ControlLockoutStartTime = _timing.CurTime;
source.Comp.ControlLockoutEndTime = _timing.CurTime + source.Comp.ControlLockoutDuration;
source.Comp.ControlLockoutCoolDownEndTime = _timing.CurTime + source.Comp.ControlLockoutCoolDown;
Dirty(source);
foreach (var receiver in GetLinkedHolopads(source))
{
receiver.Comp.ControlLockoutOwner = user;
receiver.Comp.ControlLockoutStartTime = _timing.CurTime;
receiver.Comp.ControlLockoutEndTime = _timing.CurTime + source.Comp.ControlLockoutDuration;
receiver.Comp.ControlLockoutCoolDownEndTime = _timing.CurTime + source.Comp.ControlLockoutCoolDown;
Dirty(receiver);
}
@@ -796,15 +824,20 @@ public sealed partial class HolopadSystem : SharedHolopadSystem
if (!_telephoneSystem.IsSourceInRangeOfReceiver(sourceTelephoneEntity, receiverTelephoneEntity))
continue;
if (receiverHolopad.ControlLockoutStartTime > source.Comp.ControlLockoutStartTime)
if (receiverHolopad.ControlLockoutEndTime > source.Comp.ControlLockoutEndTime ||
receiverHolopad.ControlLockoutCoolDownEndTime > source.Comp.ControlLockoutCoolDownEndTime)
{
source.Comp.ControlLockoutStartTime = receiverHolopad.ControlLockoutStartTime;
source.Comp.ControlLockoutEndTime = receiverHolopad.ControlLockoutEndTime;
source.Comp.ControlLockoutCoolDownEndTime = receiverHolopad.ControlLockoutCoolDownEndTime;
isDirty = true;
}
}
if (isDirty)
{
Dirty(source);
}
}
private void SetHolopadAmbientState(Entity<HolopadComponent> entity, bool isEnabled)
+11 -18
View File
@@ -1,7 +1,6 @@
using System.Linq;
using Content.Server.Administration;
using Content.Server.Administration.Logs;
using Content.Server.Interaction;
using Content.Server.Popups;
using Content.Server.Stunnable;
using Content.Shared.Administration;
@@ -10,7 +9,6 @@ using Content.Shared.Database;
using Content.Shared.Examine;
using Content.Shared.Instruments;
using Content.Shared.Instruments.UI;
using Content.Shared.Physics;
using Content.Shared.Popups;
using JetBrains.Annotations;
using Robust.Server.GameObjects;
@@ -19,9 +17,7 @@ using Robust.Shared.Collections;
using Robust.Shared.Configuration;
using Robust.Shared.Console;
using Robust.Shared.GameStates;
using Robust.Shared.Player;
using Robust.Shared.Timing;
using Robust.Shared.Utility;
namespace Content.Server.Instruments;
@@ -36,7 +32,10 @@ public sealed partial class InstrumentSystem : SharedInstrumentSystem
[Dependency] private PopupSystem _popup = default!;
[Dependency] private TransformSystem _transform = default!;
[Dependency] private ExamineSystemShared _examineSystem = default!;
[Dependency] private IAdminLogManager _admingLogSystem = default!;
[Dependency] private IAdminLogManager _adminLogSystem = default!;
[Dependency] private EntityQuery<InstrumentComponent> _instrumentQuery = default!;
[Dependency] private EntityQuery<ActiveInstrumentComponent> _activeInstrumentQuery = default!;
private const float MaxInstrumentBandRange = 10f;
@@ -170,7 +169,7 @@ public sealed partial class InstrumentSystem : SharedInstrumentSystem
.Where(t => t != null)
.Select(t => t!.ToString()));
_admingLogSystem.Add(
_adminLogSystem.Add(
LogType.Instrument,
LogImpact.Low,
$"{ToPrettyString(args.SenderSession.AttachedEntity)} set the midi channels for {ToPrettyString(uid)} to {tracksString}");
@@ -271,13 +270,10 @@ public sealed partial class InstrumentSystem : SharedInstrumentSystem
public (NetEntity, string)[] GetBands(EntityUid uid)
{
var metadataQuery = GetEntityQuery<MetaDataComponent>();
if (Deleted(uid))
return Array.Empty<(NetEntity, string)>();
var list = new ValueList<(NetEntity, string)>();
var instrumentQuery = GetEntityQuery<InstrumentComponent>();
if (!TryComp(uid, out InstrumentComponent? originInstrument)
|| originInstrument.InstrumentPlayer is not {} originPlayer)
@@ -291,7 +287,7 @@ public sealed partial class InstrumentSystem : SharedInstrumentSystem
continue;
// Don't grab puppet instruments.
if (!instrumentQuery.TryGetComponent(entity, out var instrument) || instrument.Master != null)
if (!_instrumentQuery.TryGetComponent(entity, out var instrument) || instrument.Master != null)
continue;
// We want to use the instrument player's name.
@@ -303,8 +299,8 @@ public sealed partial class InstrumentSystem : SharedInstrumentSystem
if (!_examineSystem.InRangeUnOccluded(uid, entity, MaxInstrumentBandRange, e => e == playerUid || e == originPlayer))
continue;
if (!metadataQuery.TryGetComponent(playerUid, out var playerMetadata)
|| !metadataQuery.TryGetComponent(entity, out var metadata))
if (!TryComp(playerUid, out MetaDataComponent? playerMetadata)
|| !TryComp(entity, out MetaDataComponent? metadata))
continue;
list.Add((GetNetEntity(entity), $"{playerMetadata.EntityName} - {metadata.EntityName}"));
@@ -427,9 +423,6 @@ public sealed partial class InstrumentSystem : SharedInstrumentSystem
_bandRequestQueue.Clear();
}
var activeQuery = GetEntityQuery<ActiveInstrumentComponent>();
var transformQuery = GetEntityQuery<TransformComponent>();
var query = AllEntityQuery<ActiveInstrumentComponent, InstrumentComponent>();
while (query.MoveNext(out var uid, out _, out var instrument))
{
@@ -441,15 +434,15 @@ public sealed partial class InstrumentSystem : SharedInstrumentSystem
continue;
}
var masterActive = activeQuery.CompOrNull(master);
_activeInstrumentQuery.TryComp(master, out var masterActive);
if (masterActive == null)
{
Clean(uid, instrument);
continue;
}
var trans = transformQuery.GetComponent(uid);
var masterTrans = transformQuery.GetComponent(master);
var trans = Transform(uid);
var masterTrans = Transform(master);
if (!_transform.InRange(masterTrans.Coordinates, trans.Coordinates, 10f))
{
Clean(uid, instrument);
@@ -1,5 +1,4 @@
using System.Linq;
using Content.Server.Light.Components;
using Content.Shared.Examine;
using Content.Shared.Interaction;
using Content.Shared.Light.EntitySystems;
@@ -7,7 +6,6 @@ using Content.Shared.Light.Components;
using Content.Shared.Popups;
using Content.Shared.Storage;
using JetBrains.Annotations;
using Robust.Shared.Audio;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Containers;
@@ -44,10 +42,9 @@ public sealed partial class LightReplacerSystem : SharedLightReplacerSystem
args.PushMarkup(Loc.GetString("comp-light-replacer-has-lights"));
var groups = new Dictionary<string, int>();
var metaQuery = GetEntityQuery<MetaDataComponent>();
foreach (var bulb in component.InsertedBulbs.ContainedEntities)
{
var metaData = metaQuery.GetComponent(bulb);
var metaData = MetaData(bulb);
groups[metaData.EntityName] = groups.GetValueOrDefault(metaData.EntityName) + 1;
}
@@ -8,13 +8,11 @@ namespace Content.Server.Light.EntitySystems;
public sealed partial class RoofSystem : SharedRoofSystem
{
[Dependency] private SharedMapSystem _maps = default!;
private EntityQuery<MapGridComponent> _gridQuery;
[Dependency] private EntityQuery<MapGridComponent> _mapGridQuery = default!;
public override void Initialize()
{
base.Initialize();
_gridQuery = GetEntityQuery<MapGridComponent>();
SubscribeLocalEvent<SetRoofComponent, ComponentStartup>(OnFlagStartup);
}
@@ -22,7 +20,7 @@ public sealed partial class RoofSystem : SharedRoofSystem
{
var xform = Transform(ent.Owner);
if (_gridQuery.TryComp(xform.GridUid, out var grid))
if (_mapGridQuery.TryComp(xform.GridUid, out var grid))
{
var index = _maps.LocalToTile(xform.GridUid.Value, grid, xform.Coordinates);
SetRoof((xform.GridUid.Value, grid, null), index, ent.Comp.Value);
-73
View File
@@ -1,73 +0,0 @@
using Content.Shared.Hands;
using Content.Shared.Hands.EntitySystems;
using Content.Shared.IdentityManagement;
using Content.Shared.Item;
using Content.Shared.Lube;
using Content.Shared.NameModifier.EntitySystems;
using Content.Shared.Popups;
using Content.Shared.Throwing;
using Robust.Shared.Random;
namespace Content.Server.Lube;
public sealed partial class LubedSystem : EntitySystem
{
[Dependency] private ThrowingSystem _throwing = default!;
[Dependency] private IRobustRandom _random = default!;
[Dependency] private SharedTransformSystem _transform = default!;
[Dependency] private SharedPopupSystem _popup = default!;
[Dependency] private NameModifierSystem _nameMod = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<LubedComponent, ComponentInit>(OnInit);
SubscribeLocalEvent<LubedComponent, BeforeGettingEquippedHandEvent>(OnHandPickUp);
SubscribeLocalEvent<LubedComponent, RefreshNameModifiersEvent>(OnRefreshNameModifiers);
}
private void OnInit(EntityUid uid, LubedComponent component, ComponentInit args)
{
_nameMod.RefreshNameModifiers(uid);
}
/// <remarks>
/// Note to whoever makes this predicted—there is a mispredict here that
/// would be nice to keep! If this is in shared, the client will predict
/// this and not run the pickup animation in <see cref="SharedHandsSystem"/>
/// which would (probably) make this effect look less funny. You will
/// probably want to either tweak <see cref="BeforeGettingEquippedHandEvent"/>
/// to be able to cancel but still run the animation or something—we do want
/// the event to run before the animation for stuff like
/// <see cref="MultiHandedItemSystem.OnBeforeEquipped"/>.
/// </remarks>
private void OnHandPickUp(Entity<LubedComponent> ent, ref BeforeGettingEquippedHandEvent args)
{
if (args.Cancelled)
return;
if (ent.Comp.SlipsLeft <= 0)
{
RemComp<LubedComponent>(ent);
_nameMod.RefreshNameModifiers(ent.Owner);
return;
}
ent.Comp.SlipsLeft--;
args.Cancelled = true;
_transform.SetCoordinates(ent, Transform(args.User).Coordinates);
_transform.AttachToGridOrMap(ent);
_throwing.TryThrow(ent, _random.NextVector2(), ent.Comp.SlipStrength);
_popup.PopupEntity(Loc.GetString("lube-slip", ("target", Identity.Entity(ent, EntityManager))),
args.User,
args.User,
PopupType.MediumCaution);
}
private void OnRefreshNameModifiers(Entity<LubedComponent> entity, ref RefreshNameModifiersEvent args)
{
args.AddModifier("lubed-name-prefix");
}
}
@@ -5,6 +5,7 @@ using Content.Server.Roles;
using Content.Shared.Database;
using Content.Shared.Implants;
using Content.Shared.Mindshield.Components;
using Content.Shared.Revolutionary;
using Content.Shared.Revolutionary.Components;
using Content.Shared.Roles.Components;
using Robust.Shared.Containers;
@@ -28,6 +29,7 @@ public sealed partial class MindShieldSystem : EntitySystem
SubscribeLocalEvent<MindShieldImplantComponent, ImplantImplantedEvent>(OnImplantImplanted);
SubscribeLocalEvent<MindShieldImplantComponent, ImplantRemovedEvent>(OnImplantRemoved);
SubscribeLocalEvent<MindShieldComponent, AttemptConvertRevolutionaryEvent>(OnAttemptConvert);
}
private void OnImplantImplanted(Entity<MindShieldImplantComponent> ent, ref ImplantImplantedEvent ev)
@@ -59,5 +61,10 @@ public sealed partial class MindShieldSystem : EntitySystem
{
RemComp<MindShieldComponent>(args.Implanted);
}
private void OnAttemptConvert(Entity<MindShieldComponent> ent, ref AttemptConvertRevolutionaryEvent args)
{
args.Cancelled = true;
}
}
@@ -6,14 +6,13 @@ using Robust.Shared.Player;
namespace Content.Server.Movement.Systems;
public sealed class MobCollisionSystem : SharedMobCollisionSystem
public sealed partial class MobCollisionSystem : SharedMobCollisionSystem
{
private EntityQuery<ActorComponent> _actorQuery;
[Dependency] private EntityQuery<ActorComponent> _actorQuery = default!;
public override void Initialize()
{
base.Initialize();
_actorQuery = GetEntityQuery<ActorComponent>();
SubscribeLocalEvent<MobCollisionComponent, MobCollisionMessage>(OnServerMobCollision);
}
@@ -7,9 +7,7 @@ using Content.Shared.Gravity;
using Content.Shared.Input;
using Content.Shared.Movement.Pulling.Components;
using Content.Shared.Movement.Pulling.Events;
using Content.Shared.Movement.Pulling.Systems;
using Content.Shared.Rotatable;
using Robust.Server.Physics;
using Robust.Shared.Containers;
using Robust.Shared.Input.Binding;
using Robust.Shared.Map;
@@ -61,6 +59,10 @@ public sealed partial class PullController : VirtualController
[Dependency] private SharedGravitySystem _gravity = default!;
[Dependency] private SharedTransformSystem _transformSystem = default!;
[Dependency] private EntityQuery<PhysicsComponent> _physicsQuery = default!;
[Dependency] private EntityQuery<PullableComponent> _pullableQuery = default!;
[Dependency] private EntityQuery<PullerComponent> _pullerQuery = default!;
/// <summary>
/// If distance between puller and pulled entity lower that this threshold,
/// pulled entity will not change its rotation.
@@ -76,22 +78,12 @@ public sealed partial class PullController : VirtualController
/// </summary>
private const float ThresholdRotAngle = 22.5f;
private EntityQuery<PhysicsComponent> _physicsQuery;
private EntityQuery<PullableComponent> _pullableQuery;
private EntityQuery<PullerComponent> _pullerQuery;
private EntityQuery<TransformComponent> _xformQuery;
public override void Initialize()
{
CommandBinds.Builder
.Bind(ContentKeyFunctions.MovePulledObject, new PointerInputCmdHandler(OnRequestMovePulledObject))
.Register<PullController>();
_physicsQuery = GetEntityQuery<PhysicsComponent>();
_pullableQuery = GetEntityQuery<PullableComponent>();
_pullerQuery = GetEntityQuery<PullerComponent>();
_xformQuery = GetEntityQuery<TransformComponent>();
UpdatesAfter.Add(typeof(MoverController));
SubscribeLocalEvent<PullMovingComponent, PullStoppedMessage>(OnPullStop);
SubscribeLocalEvent<ActivePullerComponent, MoveEvent>(OnPullerMove);
@@ -202,8 +194,8 @@ public sealed partial class PullController : VirtualController
if (!rotatable.RotateWhilePulling)
return;
var pulledXform = _xformQuery.GetComponent(pulled);
var pullerXform = _xformQuery.GetComponent(puller);
var pulledXform = Transform(pulled);
var pullerXform = Transform(puller);
var pullerData = TransformSystem.GetWorldPositionRotation(pullerXform);
var pulledData = TransformSystem.GetWorldPositionRotation(pulledXform);
@@ -245,7 +237,7 @@ public sealed partial class PullController : VirtualController
if (pullable.Puller is not {Valid: true} puller)
continue;
var pullerXform = _xformQuery.Get(puller);
var pullerXform = Transform(puller);
var pullerPosition = TransformSystem.GetMapCoordinates(pullerXform);
var movingTo = TransformSystem.ToMapCoordinates(mover.MovingTo);
@@ -305,7 +297,7 @@ public sealed partial class PullController : VirtualController
// if the puller is weightless or can't move, then we apply the inverse impulse (Newton's third law).
// doing it under gravity produces an unsatisfying wiggling when pulling.
// If player can't move, assume they are on a chair and we need to prevent pull-moving.
if (_gravity.IsWeightless(puller) && pullerXform.Comp.GridUid == null || !_actionBlockerSystem.CanMove(puller))
if (_gravity.IsWeightless(puller) && pullerXform.GridUid == null || !_actionBlockerSystem.CanMove(puller))
{
PhysicsSystem.WakeBody(puller);
PhysicsSystem.ApplyLinearImpulse(puller, -impulse);
@@ -40,6 +40,6 @@ public sealed partial class WieldedPrecondition : HTNPrecondition
return false;
var wieldableSystem = _entManager.System<SharedWieldableSystem>();
return wieldableSystem.CanWield(heldEntity.Value, wieldable, owner, quiet: true);
return wieldableSystem.CanWield((heldEntity.Value, wieldable), owner, quiet: true);
}
}
@@ -38,7 +38,7 @@ public sealed partial class WieldOperator : HTNOperator
if (wieldable.Wielded)
return HTNOperatorStatus.Failed;
return wieldableSystem.TryWield(weaponUid.Value, wieldable, owner)
return wieldableSystem.TryWield((weaponUid.Value, wieldable), owner)
? HTNOperatorStatus.Finished
: HTNOperatorStatus.Failed;
}
@@ -46,7 +46,7 @@ public sealed partial class WieldOperator : HTNOperator
if (!wieldable.Wielded)
return HTNOperatorStatus.Failed;
return wieldableSystem.TryUnwield(weaponUid.Value, wieldable, owner)
return wieldableSystem.TryUnwield((weaponUid.Value, wieldable), owner)
? HTNOperatorStatus.Finished
: HTNOperatorStatus.Failed;
}
@@ -96,7 +96,7 @@ public sealed partial class PathfindingSystem
// TODO: Dump all this shit and just do it live it's probably fast enough.
if (comp.DirtyChunks.Count == 0 ||
curTime < comp.NextUpdate ||
!_gridQuery.TryGetComponent(uid, out var mapGridComp))
!_mapGridQuery.TryGetComponent(uid, out var mapGridComp))
{
continue;
}
@@ -272,7 +272,7 @@ public sealed partial class PathfindingSystem
{
if (!_fixturesQuery.TryGetComponent(ev.Sender, out var fixtures) ||
!IsBodyRelevant(fixtures) ||
_gridQuery.HasComponent(ev.Sender))
_mapGridQuery.HasComponent(ev.Sender))
{
return;
}
@@ -441,7 +441,7 @@ public sealed partial class PathfindingSystem
continue;
}
var xform = _xformQuery.GetComponent(ent);
var xform = Transform(ent);
if (xform.ParentUid != grid.Owner ||
_maps.LocalToTile(grid.Owner, grid.Comp, xform.Coordinates) != tilePos)
@@ -494,7 +494,7 @@ public sealed partial class PathfindingSystem
}
if (!intersects ||
!_xformQuery.TryGetComponent(ent, out var xform))
!TryComp(ent, out TransformComponent? xform))
{
continue;
}
@@ -513,7 +513,7 @@ public sealed partial class PathfindingSystem
if (!colliding)
continue;
if (_accessQuery.HasComponent(ent))
if (_accessReaderQuery.HasComponent(ent))
{
flags |= PathfindingBreadcrumbFlag.Access;
}
@@ -53,6 +53,13 @@ namespace Content.Server.NPC.Pathfinding
[Dependency] private SharedPhysicsSystem _physics = default!;
[Dependency] private SharedTransformSystem _transform = default!;
[Dependency] private EntityQuery<AccessReaderComponent> _accessReaderQuery = default!;
[Dependency] private EntityQuery<DestructibleComponent> _destructibleQuery = default!;
[Dependency] private EntityQuery<DoorComponent> _doorQuery = default!;
[Dependency] private EntityQuery<ClimbableComponent> _climbableQuery = default!;
[Dependency] private EntityQuery<FixturesComponent> _fixturesQuery = default!;
[Dependency] private EntityQuery<MapGridComponent> _mapGridQuery = default!;
private readonly Dictionary<ICommonSession, PathfindingDebugMode> _subscribedSessions = new();
[ViewVariables]
@@ -68,26 +75,9 @@ namespace Content.Server.NPC.Pathfinding
private int _portalIndex;
private readonly Dictionary<int, PathPortal> _portals = new();
private EntityQuery<AccessReaderComponent> _accessQuery;
private EntityQuery<DestructibleComponent> _destructibleQuery;
private EntityQuery<DoorComponent> _doorQuery;
private EntityQuery<ClimbableComponent> _climbableQuery;
private EntityQuery<FixturesComponent> _fixturesQuery;
private EntityQuery<MapGridComponent> _gridQuery;
private EntityQuery<TransformComponent> _xformQuery;
public override void Initialize()
{
base.Initialize();
_accessQuery = GetEntityQuery<AccessReaderComponent>();
_destructibleQuery = GetEntityQuery<DestructibleComponent>();
_doorQuery = GetEntityQuery<DoorComponent>();
_climbableQuery = GetEntityQuery<ClimbableComponent>();
_fixturesQuery = GetEntityQuery<FixturesComponent>();
_gridQuery = GetEntityQuery<MapGridComponent>();
_xformQuery = GetEntityQuery<TransformComponent>();
_playerManager.PlayerStatusChanged += OnPlayerChange;
InitializeGrid();
SubscribeNetworkEvent<RequestPathfindingDebugMessage>(OnBreadcrumbs);
@@ -3,7 +3,6 @@ using Content.Server.NPC.Components;
using Content.Shared.CombatMode;
using Content.Shared.NPC;
using Robust.Shared.Map;
using Robust.Shared.Physics.Components;
using Robust.Shared.Random;
namespace Content.Server.NPC.Systems;
@@ -38,25 +37,22 @@ public sealed partial class NPCCombatSystem
private void UpdateMelee(float frameTime)
{
var combatQuery = GetEntityQuery<CombatModeComponent>();
var xformQuery = GetEntityQuery<TransformComponent>();
var physicsQuery = GetEntityQuery<PhysicsComponent>();
var curTime = _timing.CurTime;
var query = EntityQueryEnumerator<NPCMeleeCombatComponent, ActiveNPCComponent>();
while (query.MoveNext(out var uid, out var comp, out _))
{
if (!combatQuery.TryGetComponent(uid, out var combat) || !combat.IsInCombatMode)
if (!_combatQuery.TryGetComponent(uid, out var combat) || !combat.IsInCombatMode)
{
RemComp<NPCMeleeCombatComponent>(uid);
continue;
}
Attack(uid, comp, curTime, physicsQuery, xformQuery);
Attack(uid, comp, curTime);
}
}
private void Attack(EntityUid uid, NPCMeleeCombatComponent component, TimeSpan curTime, EntityQuery<PhysicsComponent> physicsQuery, EntityQuery<TransformComponent> xformQuery)
private void Attack(EntityUid uid, NPCMeleeCombatComponent component, TimeSpan curTime)
{
component.Status = CombatStatus.Normal;
@@ -66,8 +62,8 @@ public sealed partial class NPCCombatSystem
return;
}
if (!xformQuery.TryGetComponent(uid, out var xform) ||
!xformQuery.TryGetComponent(component.Target, out var targetXform))
if (!TryComp(uid, out TransformComponent? xform) ||
!TryComp(component.Target, out TransformComponent? targetXform))
{
component.Status = CombatStatus.TargetUnreachable;
return;
@@ -105,7 +101,7 @@ public sealed partial class NPCCombatSystem
return;
if (_random.Prob(component.MissChance) &&
physicsQuery.TryGetComponent(component.Target, out var targetPhysics) &&
_physicsQuery.TryGetComponent(component.Target, out var targetPhysics) &&
targetPhysics.LinearVelocity.LengthSquared() != 0f)
{
_melee.AttemptLightAttackMiss(uid, weaponUid, weapon, targetXform.Coordinates.Offset(_random.NextVector2(0.5f)));
@@ -14,11 +14,11 @@ public sealed partial class NPCCombatSystem
[Dependency] private SharedCombatModeSystem _combat = default!;
[Dependency] private RotateToFaceSystem _rotate = default!;
private EntityQuery<CombatModeComponent> _combatQuery;
private EntityQuery<NPCSteeringComponent> _steeringQuery;
private EntityQuery<RechargeBasicEntityAmmoComponent> _rechargeQuery;
private EntityQuery<PhysicsComponent> _physicsQuery;
private EntityQuery<TransformComponent> _xformQuery;
[Dependency] private EntityQuery<CombatModeComponent> _combatQuery = default!;
[Dependency] private EntityQuery<NPCSteeringComponent> _steeringQuery = default!;
[Dependency] private EntityQuery<RechargeBasicEntityAmmoComponent> _rechargeQuery = default!;
[Dependency] private EntityQuery<PhysicsComponent> _physicsQuery = default!;
[Dependency] private EntityQuery<TransformComponent> _xformQuery = default!;
// TODO: Don't predict for hitscan
private const float ShootSpeed = 20f;
@@ -30,12 +30,6 @@ public sealed partial class NPCCombatSystem
private void InitializeRanged()
{
_combatQuery = GetEntityQuery<CombatModeComponent>();
_physicsQuery = GetEntityQuery<PhysicsComponent>();
_rechargeQuery = GetEntityQuery<RechargeBasicEntityAmmoComponent>();
_steeringQuery = GetEntityQuery<NPCSteeringComponent>();
_xformQuery = GetEntityQuery<TransformComponent>();
SubscribeLocalEvent<NPCRangedCombatComponent, ComponentStartup>(OnRangedStartup);
SubscribeLocalEvent<NPCRangedCombatComponent, ComponentShutdown>(OnRangedShutdown);
}
+3 -11
View File
@@ -1,14 +1,10 @@
using System.Numerics;
using Content.Server.NPC.Components;
using Content.Server.NPC.Events;
using Content.Server.NPC.HTN.PrimitiveTasks.Operators.Combat;
using Content.Server.Weapons.Melee;
using Content.Shared.NPC;
using Content.Shared.Weapons.Melee;
using Robust.Shared.Collections;
using Robust.Shared.Map.Components;
using Robust.Shared.Physics.Components;
using Robust.Shared.Physics.Systems;
using Robust.Shared.Random;
using Robust.Shared.Timing;
@@ -23,17 +19,13 @@ public sealed partial class NPCJukeSystem : EntitySystem
[Dependency] private SharedMapSystem _mapSystem = default!;
[Dependency] private SharedTransformSystem _transform = default!;
private EntityQuery<NPCMeleeCombatComponent> _npcMeleeQuery;
private EntityQuery<NPCRangedCombatComponent> _npcRangedQuery;
private EntityQuery<PhysicsComponent> _physicsQuery;
[Dependency] private EntityQuery<NPCMeleeCombatComponent> _npcMeleeQuery = default!;
[Dependency] private EntityQuery<NPCRangedCombatComponent> _npcRangedQuery = default!;
[Dependency] private EntityQuery<PhysicsComponent> _physicsQuery = default!;
public override void Initialize()
{
base.Initialize();
_npcMeleeQuery = GetEntityQuery<NPCMeleeCombatComponent>();
_npcRangedQuery = GetEntityQuery<NPCRangedCombatComponent>();
_physicsQuery = GetEntityQuery<PhysicsComponent>();
SubscribeLocalEvent<NPCJukeComponent, NPCSteeringEvent>(OnJukeSteering);
}
@@ -1,18 +1,15 @@
using Content.Server.Destructible;
using Content.Server.NPC.Components;
using Content.Server.NPC.Pathfinding;
using Content.Shared.Climbing;
using Content.Shared.CombatMode;
using Content.Shared.DoAfter;
using Content.Shared.Doors.Components;
using Content.Shared.NPC;
using Robust.Shared.Map.Components;
using Robust.Shared.Physics;
using Robust.Shared.Physics.Components;
using Robust.Shared.Utility;
using ClimbableComponent = Content.Shared.Climbing.Components.ClimbableComponent;
using ClimbingComponent = Content.Shared.Climbing.Components.ClimbingComponent;
using Robust.Shared.Random;
namespace Content.Server.NPC.Systems;
@@ -37,6 +34,9 @@ public sealed partial class NPCSteeringSystem
* Also need to make sure it picks nearest obstacle path so it starts smashing in front of it.
*/
[Dependency] private EntityQuery<DoorComponent> _doorQuery = default!;
[Dependency] private EntityQuery<ClimbableComponent> _climbableQuery = default!;
[Dependency] private EntityQuery<DestructibleComponent> _destructibleQuery = default!;
private SteeringObstacleStatus TryHandleFlags(EntityUid uid, NPCSteeringComponent component, PathPoly poly)
{
@@ -84,12 +84,10 @@ public sealed partial class NPCSteeringSystem
// Just walk into it stupid
if (isDoor && !isAccessRequired)
{
var doorQuery = GetEntityQuery<DoorComponent>();
// ... At least if it's not a bump open.
foreach (var ent in obstacleEnts)
{
if (!doorQuery.TryGetComponent(ent, out var door))
if (!_doorQuery.TryGetComponent(ent, out var door))
continue;
if (!door.BumpOpen && (component.Flags & PathFlags.Interact) != 0x0)
@@ -107,12 +105,10 @@ public sealed partial class NPCSteeringSystem
if ((component.Flags & PathFlags.Prying) != 0x0 && isDoor)
{
var doorQuery = GetEntityQuery<DoorComponent>();
// Get the relevant obstacle
foreach (var ent in obstacleEnts)
{
if (doorQuery.TryGetComponent(ent, out var door) && door.State != DoorState.Open)
if (_doorQuery.TryGetComponent(ent, out var door) && door.State != DoorState.Open)
{
// TODO: Use the verb.
@@ -141,12 +137,10 @@ public sealed partial class NPCSteeringSystem
return SteeringObstacleStatus.Continuing;
}
var climbableQuery = GetEntityQuery<ClimbableComponent>();
// Get the relevant obstacle
foreach (var ent in obstacleEnts)
{
if (climbableQuery.TryGetComponent(ent, out var table) &&
if (_climbableQuery.TryGetComponent(ent, out var table) &&
_climb.CanVault(table, uid, uid, out _) &&
_climb.TryClimb(uid, uid, ent, out id, table, climbing))
{
@@ -165,8 +159,6 @@ public sealed partial class NPCSteeringSystem
if (_melee.TryGetWeapon(uid, out _, out var meleeWeapon) && meleeWeapon.NextAttack <= _timing.CurTime && TryComp<CombatModeComponent>(uid, out var combatMode))
{
_combat.SetInCombatMode(uid, true, combatMode);
var destructibleQuery = GetEntityQuery<DestructibleComponent>();
// TODO: This is a hack around grilles and windows.
_random.Shuffle(obstacleEnts);
var attackResult = false;
@@ -174,7 +166,7 @@ public sealed partial class NPCSteeringSystem
foreach (var ent in obstacleEnts)
{
// TODO: Validate we can damage it
if (destructibleQuery.HasComponent(ent))
if (_destructibleQuery.HasComponent(ent))
{
attackResult = _melee.AttemptLightAttack(uid, uid, meleeWeapon, ent);
break;
@@ -68,11 +68,11 @@ public sealed partial class NPCSteeringSystem : SharedNPCSteeringSystem
[Dependency] private SharedTransformSystem _transform = default!;
[Dependency] private SharedCombatModeSystem _combat = default!;
private EntityQuery<FixturesComponent> _fixturesQuery;
private EntityQuery<MovementSpeedModifierComponent> _modifierQuery;
private EntityQuery<NpcFactionMemberComponent> _factionQuery;
private EntityQuery<PhysicsComponent> _physicsQuery;
private EntityQuery<TransformComponent> _xformQuery;
[Dependency] private EntityQuery<FixturesComponent> _fixturesQuery = default!;
[Dependency] private EntityQuery<MovementSpeedModifierComponent> _modifierQuery = default!;
[Dependency] private EntityQuery<NpcFactionMemberComponent> _factionQuery = default!;
[Dependency] private EntityQuery<PhysicsComponent> _physicsQuery = default!;
[Dependency] private EntityQuery<TransformComponent> _xformQuery = default!;
private ObjectPool<HashSet<EntityUid>> _entSetPool =
new DefaultObjectPool<HashSet<EntityUid>>(new SetPolicy<EntityUid>());
@@ -99,11 +99,6 @@ public sealed partial class NPCSteeringSystem : SharedNPCSteeringSystem
base.Initialize();
Log.Level = LogLevel.Info;
_fixturesQuery = GetEntityQuery<FixturesComponent>();
_modifierQuery = GetEntityQuery<MovementSpeedModifierComponent>();
_factionQuery = GetEntityQuery<NpcFactionMemberComponent>();
_physicsQuery = GetEntityQuery<PhysicsComponent>();
_xformQuery = GetEntityQuery<TransformComponent>();
for (var i = 0; i < InterestDirections; i++)
{
+3 -12
View File
@@ -60,9 +60,7 @@ public sealed partial class NPCUtilitySystem : EntitySystem
[Dependency] private TurretTargetSettingsSystem _turretTargetSettings = default!;
[Dependency] private DamageableSystem _damageable = default!;
[Dependency] private SharedStealthSystem _stealth = default!;
private EntityQuery<PuddleComponent> _puddleQuery;
private EntityQuery<TransformComponent> _xformQuery;
[Dependency] private EntityQuery<PuddleComponent> _puddleQuery = default!;
private ObjectPool<HashSet<EntityUid>> _entPool =
new DefaultObjectPool<HashSet<EntityUid>>(new SetPolicy<EntityUid>(), 256);
@@ -72,13 +70,6 @@ public sealed partial class NPCUtilitySystem : EntitySystem
private HashSet<Entity<IComponent>> _entitySet = new();
private List<EntityPrototype.ComponentRegistryEntry> _compTypes = new();
public override void Initialize()
{
base.Initialize();
_puddleQuery = GetEntityQuery<PuddleComponent>();
_xformQuery = GetEntityQuery<TransformComponent>();
}
/// <summary>
/// Runs the UtilityQueryPrototype and returns the best-matching entities.
/// </summary>
@@ -429,7 +420,7 @@ public sealed partial class NPCUtilitySystem : EntitySystem
if (compQuery.Components.Count == 0)
return;
var mapPos = _transform.GetMapCoordinates(owner, xform: _xformQuery.GetComponent(owner));
var mapPos = _transform.GetMapCoordinates(owner, xform: Transform(owner));
_compTypes.Clear();
var i = -1;
EntityPrototype.ComponentRegistryEntry compZero = default!;
@@ -507,7 +498,7 @@ public sealed partial class NPCUtilitySystem : EntitySystem
private void RecursiveAdd(EntityUid uid, HashSet<EntityUid> entities)
{
// TODO: Probably need a recursive struct enumerator on engine.
var xform = _xformQuery.GetComponent(uid);
var xform = Transform(uid);
var enumerator = xform.ChildEnumerator;
entities.Add(uid);
@@ -33,7 +33,6 @@ public sealed partial class SpaceNinjaSystem : SharedSpaceNinjaSystem
{
base.Initialize();
SubscribeLocalEvent<SpaceNinjaComponent, EmaggedSomethingEvent>(OnDoorjack);
SubscribeLocalEvent<SpaceNinjaComponent, ResearchStolenEvent>(OnResearchStolen);
SubscribeLocalEvent<SpaceNinjaComponent, ThreatCalledInEvent>(OnThreatCalledIn);
SubscribeLocalEvent<SpaceNinjaComponent, CriminalRecordsHackedEvent>(OnCriminalRecordsHacked);
@@ -113,23 +112,6 @@ public sealed partial class SpaceNinjaSystem : SharedSpaceNinjaSystem
return GetNinjaBattery(user, out var uid, out var battery) && _battery.TryUseCharge((uid.Value, battery), charge);
}
/// <summary>
/// Increment greentext when emagging a door.
/// </summary>
private void OnDoorjack(EntityUid uid, SpaceNinjaComponent comp, ref EmaggedSomethingEvent args)
{
// incase someone lets ninja emag non-doors double check it here
if (!HasComp<DoorComponent>(args.Target))
return;
// this popup is serverside since door emag logic is serverside (power funnies)
Popup.PopupEntity(Loc.GetString("ninja-doorjack-success", ("target", Identity.Entity(args.Target, EntityManager))), uid, uid, PopupType.Medium);
// handle greentext
if (_mind.TryGetObjectiveComp<DoorjackConditionComponent>(uid, out var obj))
obj.DoorsJacked++;
}
/// <summary>
/// Add to greentext when stealing technologies.
/// </summary>
@@ -16,7 +16,7 @@ namespace Content.Server.NodeContainer.EntitySystems
public sealed partial class NodeContainerSystem : SharedNodeContainerSystem
{
[Dependency] private NodeGroupSystem _nodeGroupSystem = default!;
private EntityQuery<NodeContainerComponent> _query;
[Dependency] private EntityQuery<NodeContainerComponent> _nodeContainerQuery = default!;
public override void Initialize()
{
@@ -29,8 +29,6 @@ namespace Content.Server.NodeContainer.EntitySystems
SubscribeLocalEvent<NodeContainerComponent, ReAnchorEvent>(OnReAnchor);
SubscribeLocalEvent<NodeContainerComponent, MoveEvent>(OnMoveEvent);
SubscribeLocalEvent<NodeContainerComponent, ExaminedEvent>(OnExamine);
_query = GetEntityQuery<NodeContainerComponent>();
}
public bool TryGetNode<T>(NodeContainerComponent component, string? identifier, [NotNullWhen(true)] out T? node) where T : Node
@@ -53,7 +51,7 @@ namespace Content.Server.NodeContainer.EntitySystems
public bool TryGetNode<T>(Entity<NodeContainerComponent?> ent, string identifier, [NotNullWhen(true)] out T? node) where T : Node
{
if (_query.Resolve(ent, ref ent.Comp, false)
if (_nodeContainerQuery.Resolve(ent, ref ent.Comp, false)
&& ent.Comp.Nodes.TryGetValue(identifier, out var n)
&& n is T t)
{
@@ -74,7 +72,7 @@ namespace Content.Server.NodeContainer.EntitySystems
where T1 : Node
where T2 : Node
{
if (_query.Resolve(ent, ref ent.Comp, false)
if (_nodeContainerQuery.Resolve(ent, ref ent.Comp, false)
&& ent.Comp.Nodes.TryGetValue(id1, out var n1)
&& n1 is T1 t1
&& ent.Comp.Nodes.TryGetValue(id2, out var n2)
@@ -102,7 +100,7 @@ namespace Content.Server.NodeContainer.EntitySystems
where T2 : Node
where T3 : Node
{
if (_query.Resolve(ent, ref ent.Comp, false)
if (_nodeContainerQuery.Resolve(ent, ref ent.Comp, false)
&& ent.Comp.Nodes.TryGetValue(id1, out var n1)
&& n1 is T1 t1
&& ent.Comp.Nodes.TryGetValue(id2, out var n2)
@@ -25,6 +25,8 @@ namespace Content.Server.NodeContainer.EntitySystems
[Dependency] private IAdminManager _adminManager = default!;
[Dependency] private INodeGroupFactory _nodeGroupFactory = default!;
[Dependency] private ILogManager _logManager = default!;
[Dependency] private EntityQuery<NodeContainerComponent> _nodeContainerQuery = default!;
[Dependency] private EntityQuery<TransformComponent> _xformQuery = default!;
private readonly List<int> _visDeletes = new();
private readonly List<BaseNodeGroup> _visSends = new();
@@ -166,9 +168,6 @@ namespace Content.Server.NodeContainer.EntitySystems
var sw = Stopwatch.StartNew();
var xformQuery = GetEntityQuery<TransformComponent>();
var nodeQuery = GetEntityQuery<NodeContainerComponent>();
foreach (var toRemove in _toRemove)
{
if (toRemove.NodeGroup == null)
@@ -214,7 +213,7 @@ namespace Content.Server.NodeContainer.EntitySystems
// based on position & anchored neighbours However, here more than one node could be attached to the
// same parent. So there is probably a better way of doing this.
foreach (var compatible in GetCompatibleNodes(node, xformQuery, nodeQuery))
foreach (var compatible in GetCompatibleNodes(node))
{
ClearReachableIfNecessary(compatible);
@@ -346,20 +345,20 @@ namespace Content.Server.NodeContainer.EntitySystems
return allNodes;
}
private IEnumerable<Node> GetCompatibleNodes(Node node, EntityQuery<TransformComponent> xformQuery, EntityQuery<NodeContainerComponent> nodeQuery)
private IEnumerable<Node> GetCompatibleNodes(Node node)
{
var xform = xformQuery.GetComponent(node.Owner);
var xform = Transform(node.Owner);
Entity<MapGridComponent>? gridEnt = TryComp<MapGridComponent>(xform.GridUid, out var grid) ? (xform.GridUid.Value, grid) : null;
if (!node.Connectable(EntityManager, xform))
yield break;
foreach (var reachable in node.GetReachableNodes((node.Owner, xform), nodeQuery, xformQuery, gridEnt, EntityManager))
foreach (var reachable in node.GetReachableNodes((node.Owner, xform), _nodeContainerQuery, _xformQuery, gridEnt, EntityManager))
{
DebugTools.Assert(reachable != node, "GetReachableNodes() should not include self.");
if (reachable.NodeGroupID == node.NodeGroupID
&& reachable.Connectable(EntityManager, xformQuery.GetComponent(reachable.Owner)))
&& reachable.Connectable(EntityManager, Transform(reachable.Owner)))
{
yield return reachable;
}
@@ -5,11 +5,7 @@ namespace Content.Server.Objectives.Components;
/// <summary>
/// Objective condition that requires the player to be a ninja and have doorjacked at least a random number of airlocks.
/// Requires <see cref="NumberObjectiveComponent"/> to function.
/// Requires <see cref="NumberObjectiveComponent"/> and <see cref="CounterConditionComponent"/> to function.
/// </summary>
[RegisterComponent, Access(typeof(NinjaConditionsSystem), typeof(SharedSpaceNinjaSystem))]
public sealed partial class DoorjackConditionComponent : Component
{
[DataField("doorsJacked"), ViewVariables(VVAccess.ReadWrite)]
public int DoorsJacked;
}
[RegisterComponent]
public sealed partial class DoorjackConditionComponent : Component;
@@ -0,0 +1,44 @@
using Content.Server.Objectives.Components;
using Content.Shared.Doors.Components;
using Content.Shared.IdentityManagement;
using Content.Shared.Mind;
using Content.Shared.Ninja.Components;
using Content.Shared.Ninja.Systems;
using Content.Shared.Popups;
namespace Content.Server.Objectives.Systems;
public sealed partial class DoorJackObjectiveConditionSystem : EntitySystem
{
[Dependency] private SharedPopupSystem _popupSystem = default!;
[Dependency] private SharedMindSystem _mind = default!;
[Dependency] private CounterConditionSystem _counterCondition = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<SpaceNinjaComponent, EmaggedSomethingEvent>(OnDoorjack);
}
private void OnDoorjack(EntityUid uid, SpaceNinjaComponent comp, ref EmaggedSomethingEvent args)
{
// incase someone lets ninja emag non-doors double check it here
if (!HasComp<DoorComponent>(args.Target))
return;
if (!_mind.TryGetMind(uid, out var mindUid, out var mind))
return;
// this popup is serverside since door emag logic is serverside (power funnies)
_popupSystem.PopupEntity(
Loc.GetString("ninja-doorjack-success", ("target", Identity.Entity(args.Target, EntityManager))),
uid,
uid,
PopupType.Medium);
foreach (var obj in _mind.EnumerateObjectives<DoorjackConditionComponent>((mindUid, mind)))
{
_counterCondition.IncreaseCount(obj);
}
}
}
@@ -19,6 +19,9 @@ public sealed partial class HijackShuttleConditionSystem : EntitySystem
[Dependency] private SharedRoleSystem _role = default!;
[Dependency] private MobStateSystem _mobState = default!;
[Dependency] private EntityQuery<HumanoidProfileComponent> _humanoidsQuery = default!;
[Dependency] private EntityQuery<CuffableComponent> _cuffableQuery = default!;
public override void Initialize()
{
base.Initialize();
@@ -61,9 +64,6 @@ public sealed partial class HijackShuttleConditionSystem : EntitySystem
private bool IsShuttleHijacked(EntityUid shuttleGridId, EntityUid mindId)
{
var gridPlayers = Filter.BroadcastGrid(shuttleGridId).Recipients;
var humanoids = GetEntityQuery<HumanoidProfileComponent>();
var cuffable = GetEntityQuery<CuffableComponent>();
EntityQuery<MobStateComponent>();
var agentOnShuttle = false;
foreach (var player in gridPlayers)
@@ -78,7 +78,7 @@ public sealed partial class HijackShuttleConditionSystem : EntitySystem
continue;
}
var isHumanoid = humanoids.HasComponent(player.AttachedEntity.Value);
var isHumanoid = _humanoidsQuery.HasComponent(player.AttachedEntity.Value);
if (!isHumanoid) // Only humanoids count as enemies
continue;
@@ -91,7 +91,7 @@ public sealed partial class HijackShuttleConditionSystem : EntitySystem
continue;
var isPersonCuffed =
cuffable.TryGetComponent(player.AttachedEntity.Value, out var cuffed)
_cuffableQuery.TryGetComponent(player.AttachedEntity.Value, out var cuffed)
&& cuffed.CuffedHandCount > 0;
if (isPersonCuffed) // Allow handcuffed
continue;
@@ -24,15 +24,12 @@ public sealed partial class MailFraudObjectiveSystem : EntitySystem
if (_fingerprintReader.IsAllowed(ent.Owner, args.User, out var _, showPopup: false, checkGloves: false))
return; //cutting open your own letter
if (!_mind.TryGetMind(args.User, out _, out var mind))
if (!_mind.TryGetMind(args.User, out var mindUid, out var mind))
return;
foreach (var obj in mind.Objectives)
foreach (var obj in _mind.EnumerateObjectives<MailFraudConditionComponent>((mindUid, mind)))
{
if (HasComp<MailFraudConditionComponent>(obj))
{
_counterCondition.IncreaseCount(obj);
}
_counterCondition.IncreaseCount(obj);
}
}
}
@@ -22,30 +22,12 @@ public sealed partial class NinjaConditionsSystem : EntitySystem
public override void Initialize()
{
SubscribeLocalEvent<DoorjackConditionComponent, ObjectiveGetProgressEvent>(OnDoorjackGetProgress);
SubscribeLocalEvent<SpiderChargeConditionComponent, RequirementCheckEvent>(OnSpiderChargeRequirementCheck);
SubscribeLocalEvent<SpiderChargeConditionComponent, ObjectiveAfterAssignEvent>(OnSpiderChargeAfterAssign);
SubscribeLocalEvent<StealResearchConditionComponent, ObjectiveGetProgressEvent>(OnStealResearchGetProgress);
}
// doorjack
private void OnDoorjackGetProgress(EntityUid uid, DoorjackConditionComponent comp, ref ObjectiveGetProgressEvent args)
{
args.Progress = DoorjackProgress(comp, _number.GetTarget(uid));
}
private float DoorjackProgress(DoorjackConditionComponent comp, int target)
{
// prevent divide-by-zero
if (target == 0)
return 1f;
return MathF.Min(comp.DoorsJacked / (float) target, 1f);
}
// spider charge
private void OnSpiderChargeRequirementCheck(EntityUid uid, SpiderChargeConditionComponent comp, ref RequirementCheckEvent args)
{
@@ -24,8 +24,7 @@ public sealed partial class StealConditionSystem : EntitySystem
[Dependency] private SharedInteractionSystem _interaction = default!;
[Dependency] private SharedObjectivesSystem _objectives = default!;
[Dependency] private EntityLookupSystem _lookup = default!;
private EntityQuery<ContainerManagerComponent> _containerQuery;
[Dependency] private EntityQuery<ContainerManagerComponent> _containerQuery = default!;
private HashSet<Entity<TransformComponent>> _nearestEnts = new();
private HashSet<EntityUid> _countedItems = new();
@@ -34,8 +33,6 @@ public sealed partial class StealConditionSystem : EntitySystem
{
base.Initialize();
_containerQuery = GetEntityQuery<ContainerManagerComponent>();
SubscribeLocalEvent<StealConditionComponent, ObjectiveAssignedEvent>(OnAssigned);
SubscribeLocalEvent<StealConditionComponent, ObjectiveAfterAssignEvent>(OnAfterAssign);
SubscribeLocalEvent<StealConditionComponent, ObjectiveGetProgressEvent>(OnGetProgress);
+5 -15
View File
@@ -1,15 +1,11 @@
using System.Linq;
using System.Numerics;
using System.Threading.Tasks;
using Content.Server.Atmos;
using Content.Server.Atmos.Components;
using Content.Server.Atmos.EntitySystems;
using Content.Server.Decals;
using Content.Server.Ghost.Roles.Components;
using Content.Server.Shuttles.Events;
using Content.Server.Shuttles.Systems;
using Content.Shared.Atmos;
using Content.Shared.Decals;
using Content.Shared.Ghost;
using Content.Shared.Gravity;
using Content.Shared.Light.Components;
@@ -53,10 +49,10 @@ public sealed partial class BiomeSystem : SharedBiomeSystem
[Dependency] private ShuttleSystem _shuttles = default!;
[Dependency] private TagSystem _tags = default!;
private EntityQuery<BiomeComponent> _biomeQuery;
private EntityQuery<FixturesComponent> _fixturesQuery;
private EntityQuery<GhostComponent> _ghostQuery;
private EntityQuery<TransformComponent> _xformQuery;
[Dependency] private EntityQuery<BiomeComponent> _biomeQuery = default!;
[Dependency] private EntityQuery<FixturesComponent> _fixturesQuery = default!;
[Dependency] private EntityQuery<GhostComponent> _ghostQuery = default!;
[Dependency] private EntityQuery<TransformComponent> _xformQuery = default!;
private readonly HashSet<EntityUid> _handledEntities = new();
private const float DefaultLoadRange = 16f;
@@ -85,10 +81,6 @@ public sealed partial class BiomeSystem : SharedBiomeSystem
{
base.Initialize();
Log.Level = LogLevel.Debug;
_biomeQuery = GetEntityQuery<BiomeComponent>();
_fixturesQuery = GetEntityQuery<FixturesComponent>();
_ghostQuery = GetEntityQuery<GhostComponent>();
_xformQuery = GetEntityQuery<TransformComponent>();
SubscribeLocalEvent<BiomeComponent, MapInitEvent>(OnBiomeMapInit);
SubscribeLocalEvent<FTLStartedEvent>(OnFTLStarted);
SubscribeLocalEvent<ShuttleFlattenEvent>(OnShuttleFlatten);
@@ -924,11 +916,9 @@ public sealed partial class BiomeSystem : SharedBiomeSystem
// Ideally any entities that aren't modified just get deleted and re-generated later
// This is because if we want to save the map (e.g. persistent server) it makes the file much smaller
// and also if the map is enormous will make stuff like physics broadphase much faster
var xformQuery = GetEntityQuery<TransformComponent>();
foreach (var (ent, tile) in component.LoadedEntities[chunk])
{
if (Deleted(ent) || !xformQuery.TryGetComponent(ent, out var xform))
if (Deleted(ent) || !TryComp(ent, out TransformComponent? xform))
{
modified.Add(tile);
continue;
@@ -14,8 +14,7 @@ public sealed partial class ParticleAcceleratorSystem
if (!Resolve(uid, ref emitter))
return;
var xformQuery = GetEntityQuery<TransformComponent>();
if (!xformQuery.TryGetComponent(uid, out var xform))
if (!TryComp(uid, out TransformComponent? xform))
{
Log.Error("ParticleAccelerator attempted to emit a particle without (having) a transform from which to base its initial position and orientation.");
return;
@@ -23,12 +22,12 @@ public sealed partial class ParticleAcceleratorSystem
var emitted = Spawn(emitter.EmittedPrototype, xform.Coordinates);
if (xformQuery.TryGetComponent(emitted, out var particleXform))
if (TryComp(emitted, out TransformComponent? particleXform))
_transformSystem.SetLocalRotation(emitted, xform.LocalRotation, particleXform);
if (TryComp<PhysicsComponent>(emitted, out var particlePhys))
{
var angle = _transformSystem.GetWorldRotation(uid, xformQuery);
var angle = _transformSystem.GetWorldRotation(uid);
_physicsSystem.SetBodyStatus(emitted, particlePhys, BodyStatus.InAir);
var velocity = angle.ToWorldVec() * 20f;

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