Merge remote-tracking branch 'refs/remotes/upstream/master' into ed-27-04-2024-displacement-upstream

# Conflicts:
#	Resources/Prototypes/Entities/Mobs/Customization/Markings/human_hair.yml
This commit is contained in:
Ed
2024-04-27 10:45:35 +03:00
471 changed files with 9993 additions and 9391 deletions

View File

@@ -2,6 +2,4 @@
namespace Content.Client.Access;
public sealed class IdCardSystem : SharedIdCardSystem
{
}
public sealed class IdCardSystem : SharedIdCardSystem;

View File

@@ -40,9 +40,9 @@ namespace Content.Client.Access.UI
SendMessage(new AgentIDCardJobChangedMessage(newJob));
}
public void OnJobIconChanged(string newJobIcon)
public void OnJobIconChanged(string newJobIconId)
{
SendMessage(new AgentIDCardJobIconChangedMessage(newJobIcon));
SendMessage(new AgentIDCardJobIconChangedMessage(newJobIconId));
}
/// <summary>
@@ -57,7 +57,7 @@ namespace Content.Client.Access.UI
_window.SetCurrentName(cast.CurrentName);
_window.SetCurrentJob(cast.CurrentJob);
_window.SetAllowedIcons(cast.Icons);
_window.SetAllowedIcons(cast.Icons, cast.CurrentJobIconId);
}
protected override void Dispose(bool disposing)

View File

@@ -38,7 +38,7 @@ namespace Content.Client.Access.UI
JobLineEdit.OnFocusExit += e => OnJobChanged?.Invoke(e.Text);
}
public void SetAllowedIcons(HashSet<string> icons)
public void SetAllowedIcons(HashSet<string> icons, string currentJobIconId)
{
IconGrid.DisposeAllChildren();
@@ -79,6 +79,10 @@ namespace Content.Client.Access.UI
jobIconButton.AddChild(jobIconTexture);
jobIconButton.OnPressed += _ => _bui.OnJobIconChanged(jobIcon.ID);
IconGrid.AddChild(jobIconButton);
if (jobIconId.Equals(currentJobIconId))
jobIconButton.Pressed = true;
i++;
}
}

View File

@@ -3,7 +3,7 @@ using Robust.Shared.GameStates;
namespace Content.Client.Administration.Components;
[RegisterComponent, NetworkedComponent]
[RegisterComponent]
public sealed partial class HeadstandComponent : SharedHeadstandComponent
{

View File

@@ -3,6 +3,5 @@ using Robust.Shared.GameStates;
namespace Content.Client.Administration.Components;
[NetworkedComponent, RegisterComponent]
public sealed partial class KillSignComponent : SharedKillSignComponent
{ }
[RegisterComponent]
public sealed partial class KillSignComponent : SharedKillSignComponent;

View File

@@ -11,6 +11,7 @@ public sealed class JukeboxSystem : SharedJukeboxSystem
[Dependency] private readonly IPrototypeManager _protoManager = default!;
[Dependency] private readonly AnimationPlayerSystem _animationPlayer = default!;
[Dependency] private readonly SharedAppearanceSystem _appearanceSystem = default!;
[Dependency] private readonly SharedUserInterfaceSystem _uiSystem = default!;
public override void Initialize()
{
@@ -35,13 +36,10 @@ public sealed class JukeboxSystem : SharedJukeboxSystem
var query = AllEntityQuery<JukeboxComponent, UserInterfaceComponent>();
while (query.MoveNext(out _, out var ui))
while (query.MoveNext(out var uid, out _, out var ui))
{
if (!ui.OpenInterfaces.TryGetValue(JukeboxUiKey.Key, out var baseBui) ||
baseBui is not JukeboxBoundUserInterface bui)
{
if (!_uiSystem.TryGetOpenUi<JukeboxBoundUserInterface>((uid, ui), JukeboxUiKey.Key, out var bui))
continue;
}
bui.PopulateMusic();
}
@@ -49,15 +47,9 @@ public sealed class JukeboxSystem : SharedJukeboxSystem
private void OnJukeboxAfterState(Entity<JukeboxComponent> ent, ref AfterAutoHandleStateEvent args)
{
if (!TryComp(ent, out UserInterfaceComponent? ui))
if (!_uiSystem.TryGetOpenUi<JukeboxBoundUserInterface>(ent.Owner, JukeboxUiKey.Key, out var bui))
return;
if (!ui.OpenInterfaces.TryGetValue(JukeboxUiKey.Key, out var baseBui) ||
baseBui is not JukeboxBoundUserInterface bui)
{
return;
}
bui.Reload();
}

View File

@@ -11,6 +11,7 @@ using Content.Shared.Item;
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Client.ResourceManagement;
using Robust.Shared.Serialization.Manager;
using Robust.Shared.Serialization.TypeSerializers.Implementations;
using Robust.Shared.Utility;
using static Robust.Client.GameObjects.SpriteComponent;
@@ -53,6 +54,7 @@ public sealed class ClientClothingSystem : ClothingSystem
};
[Dependency] private readonly IResourceCache _cache = default!;
[Dependency] private readonly ISerializationManager _serialization = default!;
[Dependency] private readonly InventorySystem _inventorySystem = default!;
public override void Initialize()
@@ -272,6 +274,7 @@ public sealed class ClientClothingSystem : ClothingSystem
// temporary, until layer draw depths get added. Basically: a layer with the key "slot" is being used as a
// bookmark to determine where in the list of layers we should insert the clothing layers.
bool slotLayerExists = sprite.LayerMapTryGet(slot, out var index);
var displacementData = inventory.Displacements.GetValueOrDefault(slot);
// add the new layers
foreach (var (key, layerData) in ev.Layers)
@@ -311,10 +314,29 @@ public sealed class ClientClothingSystem : ClothingSystem
// Sprite layer redactor when
// Sprite "redactor" just a week away.
if (slot == Jumpsuit)
layerData.Shader ??= "StencilDraw";
layerData.Shader ??= inventory.JumpsuitShader;
sprite.LayerSetData(index, layerData);
layer.Offset += slotDef.Offset;
if (displacementData != null)
{
var displacementKey = $"{key}-displacement";
if (!revealedLayers.Add(displacementKey))
{
Log.Warning($"Duplicate key for clothing visuals DISPLACEMENT: {displacementKey}.");
continue;
}
var displacementLayer = _serialization.CreateCopy(displacementData.Layer, notNullableOverride: true);
displacementLayer.CopyToShaderParameters!.LayerKey = key;
// Add before main layer for this item.
sprite.AddLayer(displacementLayer, index);
sprite.LayerMapSet(displacementKey, index);
revealedLayers.Add(displacementKey);
}
}
RaiseLocalEvent(equipment, new EquipmentVisualsUpdatedEvent(equipee, slot, revealedLayers), true);

View File

@@ -3,7 +3,5 @@ using Robust.Shared.GameStates;
namespace Content.Client.Extinguisher;
[NetworkedComponent, RegisterComponent]
public sealed partial class FireExtinguisherComponent : SharedFireExtinguisherComponent
{
}
[RegisterComponent]
public sealed partial class FireExtinguisherComponent : SharedFireExtinguisherComponent;

View File

@@ -7,7 +7,7 @@ using Content.Shared.GameWindow;
using JetBrains.Annotations;
using Robust.Client.Graphics;
using Robust.Client.State;
using Robust.Shared.Utility;
using Robust.Client.UserInterface;
namespace Content.Client.GameTicking.Managers
{
@@ -18,16 +18,11 @@ namespace Content.Client.GameTicking.Managers
[Dependency] private readonly IClientAdminManager _admin = default!;
[Dependency] private readonly IClyde _clyde = default!;
[Dependency] private readonly SharedMapSystem _map = default!;
[Dependency] private readonly IUserInterfaceManager _userInterfaceManager = default!;
[ViewVariables] private bool _initialized;
private Dictionary<NetEntity, Dictionary<string, uint?>> _jobsAvailable = new();
private Dictionary<NetEntity, string> _stationNames = new();
/// <summary>
/// The current round-end window. Could be used to support re-opening the window after closing it.
/// </summary>
private RoundEndSummaryWindow? _window;
[ViewVariables] public bool AreWeReady { get; private set; }
[ViewVariables] public bool IsGameStarted { get; private set; }
[ViewVariables] public string? RestartSound { get; private set; }
@@ -152,12 +147,7 @@ namespace Content.Client.GameTicking.Managers
// Force an update in the event of this song being the same as the last.
RestartSound = message.RestartSound;
// Don't open duplicate windows (mainly for replays).
if (_window?.RoundId == message.RoundId)
return;
//This is not ideal at all, but I don't see an immediately better fit anywhere else.
_window = new RoundEndSummaryWindow(message.GamemodeTitle, message.RoundEndText, message.RoundDuration, message.RoundId, message.AllPlayersEndInfo, EntityManager);
_userInterfaceManager.GetUIController<RoundEndSummaryUIController>().OpenRoundEndSummaryWindow(message);
}
}
}

View File

@@ -38,6 +38,7 @@ namespace Content.Client.Input
common.AddFunction(ContentKeyFunctions.ZoomIn);
common.AddFunction(ContentKeyFunctions.ResetZoom);
common.AddFunction(ContentKeyFunctions.InspectEntity);
common.AddFunction(ContentKeyFunctions.ToggleRoundEndSummaryWindow);
// Not in engine, because engine cannot check for sanbox/admin status before starting placement.
common.AddFunction(ContentKeyFunctions.EditorCopyObject);

View File

@@ -72,9 +72,6 @@ public sealed class MagicMirrorBoundUserInterface : BoundUserInterface
if (!disposing)
return;
if (_window != null)
_window.OnClose -= Close;
_window?.Dispose();
}
}

View File

@@ -0,0 +1,8 @@
using Content.Shared.MagicMirror;
namespace Content.Client.MagicMirror;
public sealed class MagicMirrorSystem : SharedMagicMirrorSystem
{
}

View File

@@ -88,6 +88,7 @@ public sealed class NetworkConfiguratorBoundUserInterface : BoundUserInterface
base.Dispose(disposing);
if (!disposing) return;
_linkMenu?.Dispose();
_listMenu?.Dispose();
_configurationMenu?.Dispose();
}

View File

@@ -215,6 +215,7 @@ namespace Content.Client.Options.UI.Tabs
AddButton(ContentKeyFunctions.OpenInventoryMenu);
AddButton(ContentKeyFunctions.OpenAHelp);
AddButton(ContentKeyFunctions.OpenActionsMenu);
AddButton(ContentKeyFunctions.ToggleRoundEndSummaryWindow);
AddButton(ContentKeyFunctions.OpenEntitySpawnWindow);
AddButton(ContentKeyFunctions.OpenSandboxWindow);
AddButton(ContentKeyFunctions.OpenTileSpawnWindow);

View File

@@ -21,7 +21,6 @@ namespace Content.Client.PDA
protected override void Open()
{
base.Open();
SendMessage(new PdaRequestUpdateInterfaceMessage());
_menu = new PdaMenu();
_menu.OpenCenteredLeft();
_menu.OnClose += Close;
@@ -32,17 +31,17 @@ namespace Content.Client.PDA
_menu.EjectIdButton.OnPressed += _ =>
{
SendMessage(new ItemSlotButtonPressedEvent(PdaComponent.PdaIdSlotId));
SendPredictedMessage(new ItemSlotButtonPressedEvent(PdaComponent.PdaIdSlotId));
};
_menu.EjectPenButton.OnPressed += _ =>
{
SendMessage(new ItemSlotButtonPressedEvent(PdaComponent.PdaPenSlotId));
SendPredictedMessage(new ItemSlotButtonPressedEvent(PdaComponent.PdaPenSlotId));
};
_menu.EjectPaiButton.OnPressed += _ =>
{
SendMessage(new ItemSlotButtonPressedEvent(PdaComponent.PdaPaiSlotId));
SendPredictedMessage(new ItemSlotButtonPressedEvent(PdaComponent.PdaPaiSlotId));
};
_menu.ActivateMusicButton.OnPressed += _ =>

View File

@@ -1,9 +1,6 @@
using Content.Shared.Paper;
using Robust.Shared.GameStates;
namespace Content.Client.Paper;
[NetworkedComponent, RegisterComponent]
public sealed partial class PaperComponent : SharedPaperComponent
{
}
[RegisterComponent]
public sealed partial class PaperComponent : SharedPaperComponent;

View File

@@ -0,0 +1,21 @@
using Content.Shared.Power.Components;
using Content.Shared.UserInterface;
using Content.Shared.Wires;
namespace Content.Client.Power;
public sealed class ActivatableUIRequiresPowerSystem : EntitySystem
{
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<ActivatableUIRequiresPowerComponent, ActivatableUIOpenAttemptEvent>(OnActivate);
}
private void OnActivate(EntityUid uid, ActivatableUIRequiresPowerComponent component, ActivatableUIOpenAttemptEvent args)
{
// Client can't predict the power properly at the moment so rely upon the server to do it.
args.Cancel();
}
}

View File

@@ -697,6 +697,20 @@ namespace Content.Client.Preferences.UI
var color = SkinColor.TintedHues(_rgbSkinColorSelector.Color);
CMarkings.CurrentSkinColor = color;
Profile = Profile.WithCharacterAppearance(Profile.Appearance.WithSkinColor(color));
break;
}
case HumanoidSkinColor.VoxFeathers:
{
if (!_rgbSkinColorContainer.Visible)
{
_skinColor.Visible = false;
_rgbSkinColorContainer.Visible = true;
}
var color = SkinColor.ClosestVoxColor(_rgbSkinColorSelector.Color);
CMarkings.CurrentSkinColor = color;
Profile = Profile.WithCharacterAppearance(Profile.Appearance.WithSkinColor(color));
break;
@@ -908,6 +922,18 @@ namespace Content.Client.Preferences.UI
_rgbSkinColorSelector.Color = Profile.Appearance.SkinColor;
break;
}
case HumanoidSkinColor.VoxFeathers:
{
if (!_rgbSkinColorContainer.Visible)
{
_skinColor.Visible = false;
_rgbSkinColorContainer.Visible = true;
}
_rgbSkinColorSelector.Color = SkinColor.ClosestVoxColor(Profile.Appearance.SkinColor);
break;
}
}
}

View File

@@ -198,6 +198,13 @@ public sealed partial class ReplaySpectatorSystem
if (args.Transform.MapUid != null || args.OldMapId == MapId.Nullspace)
return;
if (_spectatorData != null)
{
// Currently scrubbing/setting the replay tick
// the observer will get respawned once the state was applied
return;
}
// The entity being spectated from was moved to null-space.
// This was probably because they were spectating some entity in a client-side replay that left PVS range.
// Simple respawn the ghost.

View File

@@ -0,0 +1,51 @@
using Content.Client.GameTicking.Managers;
using Content.Shared.GameTicking;
using Content.Shared.Input;
using JetBrains.Annotations;
using Robust.Client.Input;
using Robust.Client.UserInterface.Controllers;
using Robust.Shared.Input.Binding;
using Robust.Shared.Player;
namespace Content.Client.RoundEnd;
[UsedImplicitly]
public sealed class RoundEndSummaryUIController : UIController,
IOnSystemLoaded<ClientGameTicker>
{
[Dependency] private readonly IInputManager _input = default!;
private RoundEndSummaryWindow? _window;
private void ToggleScoreboardWindow(ICommonSession? session = null)
{
if (_window == null)
return;
if (_window.IsOpen)
{
_window.Close();
}
else
{
_window.OpenCenteredRight();
_window.MoveToFront();
}
}
public void OpenRoundEndSummaryWindow(RoundEndMessageEvent message)
{
// Don't open duplicate windows (mainly for replays).
if (_window?.RoundId == message.RoundId)
return;
_window = new RoundEndSummaryWindow(message.GamemodeTitle, message.RoundEndText,
message.RoundDuration, message.RoundId, message.AllPlayersEndInfo, EntityManager);
}
public void OnSystemLoaded(ClientGameTicker system)
{
_input.SetInputCommand(ContentKeyFunctions.ToggleRoundEndSummaryWindow,
InputCmdHandler.FromDelegate(ToggleScoreboardWindow));
}
}

View File

@@ -2,7 +2,6 @@ using System.Linq;
using System.Numerics;
using Content.Client.Message;
using Content.Shared.GameTicking;
using Robust.Client.GameObjects;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls;
using Robust.Shared.Utility;

View File

@@ -17,6 +17,14 @@ public sealed class StorageBoundUserInterface : BoundUserInterface
_storage = _entManager.System<StorageSystem>();
}
protected override void Open()
{
base.Open();
if (_entManager.TryGetComponent<StorageComponent>(Owner, out var comp))
_storage.OpenStorageWindow((Owner, comp));
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
@@ -25,16 +33,5 @@ public sealed class StorageBoundUserInterface : BoundUserInterface
_storage.CloseStorageWindow(Owner);
}
protected override void ReceiveMessage(BoundUserInterfaceMessage message)
{
base.ReceiveMessage(message);
if (message is StorageModifyWindowMessage)
{
if (_entManager.TryGetComponent<StorageComponent>(Owner, out var comp))
_storage.OpenStorageWindow((Owner, comp));
}
}
}

View File

@@ -111,7 +111,7 @@ public sealed class StorageSystem : SharedStorageSystem
if (!Resolve(entity, ref entity.Comp, false))
return;
if (entity.Comp.OpenInterfaces.GetValueOrDefault(StorageComponent.StorageUiKey.Key) is not { } bui)
if (entity.Comp.ClientOpenInterfaces.GetValueOrDefault(StorageComponent.StorageUiKey.Key) is not { } bui)
return;
bui.Close();

View File

@@ -35,7 +35,7 @@ public sealed class StrippableSystem : SharedStrippableSystem
if (!TryComp(uid, out UserInterfaceComponent? uiComp))
return;
foreach (var ui in uiComp.OpenInterfaces.Values)
foreach (var ui in uiComp.ClientOpenInterfaces.Values)
{
if (ui is StrippableBoundUserInterface stripUi)
stripUi.DirtyMenu();

View File

@@ -117,8 +117,7 @@ namespace Content.Client.UserInterface.Systems.Alerts.Controls
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
_entityManager.DeleteEntity(_spriteViewEntity);
_entityManager.QueueDeleteEntity(_spriteViewEntity);
}
}

View File

@@ -97,7 +97,8 @@ public sealed partial class AlertsUI : UIWidget
}
else
{
if (existingAlertControl != null) AlertContainer.Children.Remove(existingAlertControl);
if (existingAlertControl != null)
AlertContainer.Children.Remove(existingAlertControl);
// this is a new alert + alert key or just a different alert with the same
// key, create the control and add it in the appropriate order

View File

@@ -22,6 +22,7 @@ public sealed class HandsUIController : UIController, IOnStateEntered<GameplaySt
[Dependency] private readonly IPlayerManager _player = default!;
[UISystemDependency] private readonly HandsSystem _handsSystem = default!;
[UISystemDependency] private readonly UseDelaySystem _useDelay = default!;
private readonly List<HandsContainer> _handsContainers = new();
private readonly Dictionary<string, int> _handContainerIndices = new();
@@ -450,15 +451,15 @@ public sealed class HandsUIController : UIController, IOnStateEntered<GameplaySt
foreach (var hand in container.GetButtons())
{
if (!_entities.TryGetComponent(hand.Entity, out UseDelayComponent? useDelay) ||
useDelay is not { DelayStartTime: var start, DelayEndTime: var end })
if (!_entities.TryGetComponent(hand.Entity, out UseDelayComponent? useDelay))
{
hand.CooldownDisplay.Visible = false;
continue;
}
var delay = _useDelay.GetLastEndingDelay((hand.Entity.Value, useDelay));
hand.CooldownDisplay.Visible = true;
hand.CooldownDisplay.FromTime(start, end);
hand.CooldownDisplay.FromTime(delay.StartTime, delay.EndTime);
}
}
}

View File

@@ -262,7 +262,7 @@ public sealed class StorageUIController : UIController, IOnSystemChanged<Storage
}
else if (args.Function == ContentKeyFunctions.ActivateItemInWorld)
{
_entity.EntityNetManager?.SendSystemNetworkMessage(
_entity.RaisePredictiveEvent(
new InteractInventorySlotEvent(_entity.GetNetEntity(control.Entity), altInteract: false));
args.Handle();
}