mirror of
https://github.com/space-syndicate/space-station-14.git
synced 2026-06-09 12:26:34 +02:00
merge remote wizden/master
This commit is contained in:
@@ -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 по усмотрению сопровождающего -->
|
||||
|
||||
|
||||
@@ -317,3 +317,6 @@ Resources/MapImages
|
||||
|
||||
# Direnv stuff
|
||||
.direnv/
|
||||
|
||||
# C# Dev Kit cache file
|
||||
*.lscache
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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<ItemComponent>(Server));
|
||||
///
|
||||
/// // Assert that the server-sided entity myEntity has an ItemComponent with a Size field equal to "Small"
|
||||
/// Assert.That(myEntity,
|
||||
/// Has
|
||||
/// .Comp<ItemComponent>(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);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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!
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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++)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
+3
-4
@@ -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
Reference in New Issue
Block a user