From 73df3b15939e4c40ea58f1526ede5ce3bc3ed5ad Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Fri, 27 Jun 2025 01:27:23 +0200 Subject: [PATCH] Stop network serializing prototypes (#38602) * Stop network serializing prototypes Send the damn proto ID instead. * Fix sandbox violation --- .../Administration/AdminNameOverlay.cs | 45 ++++++++++++++----- .../Systems/AdminSystem.Overlay.cs | 5 ++- .../UI/Tabs/PlayerTab/PlayerTabEntry.xaml.cs | 15 ++++--- .../NetworkConfiguratorLinkMenu.xaml.cs | 10 +++-- .../Administration/Logs/AdminLogManager.cs | 6 ++- .../Administration/Systems/AdminSystem.cs | 6 +-- .../Systems/NetworkConfiguratorSystem.cs | 6 ++- .../EntitySystems/MumbleAccentSystem.cs | 10 ++++- .../Speech/EntitySystems/VocalSystem.cs | 16 +++++-- Content.Shared/Administration/PlayerInfo.cs | 3 +- .../Cargo/Prototypes/CargoBountyPrototype.cs | 2 +- .../Chat/Prototypes/EmoteSoundsPrototype.cs | 2 +- .../Prototypes/DamageContainerPrototype.cs | 1 - .../Damage/Prototypes/DamageGroupPrototype.cs | 1 - .../DeviceLinking/DevicePortPrototype.cs | 3 -- .../DeviceLinking/SharedDeviceLinkSystem.cs | 11 +++++ .../DeviceNetwork/DeviceFrequencyPrototype.cs | 1 - .../NetworkConfiguratorUserInterfaceState.cs | 8 ++-- Content.Shared/Mind/RoleTypePrototype.cs | 12 +++-- Content.Shared/Roles/AntagPrototype.cs | 1 - .../Silicons/Laws/SiliconLawPrototype.cs | 1 - .../Silicons/Laws/SiliconLawsetPrototype.cs | 2 +- .../Speech/Components/VocalComponent.cs | 2 +- Content.Shared/Store/CurrencyPrototype.cs | 2 +- Content.Shared/Store/ListingPrototype.cs | 3 +- .../Store/StoreCategoryPrototype.cs | 1 - .../Prototypes/StoryTemplatePrototype.cs | 2 +- .../VendingMachineInventoryPrototype.cs | 2 +- 28 files changed, 120 insertions(+), 59 deletions(-) diff --git a/Content.Client/Administration/AdminNameOverlay.cs b/Content.Client/Administration/AdminNameOverlay.cs index 0d424cbff0..abeed65732 100644 --- a/Content.Client/Administration/AdminNameOverlay.cs +++ b/Content.Client/Administration/AdminNameOverlay.cs @@ -1,3 +1,4 @@ +using System.Collections.Frozen; using System.Linq; using System.Numerics; using Content.Client.Administration.Systems; @@ -24,6 +25,7 @@ internal sealed class AdminNameOverlay : Overlay private readonly EntityLookupSystem _entityLookup; private readonly IUserInterfaceManager _userInterfaceManager; private readonly SharedRoleSystem _roles; + private readonly IPrototypeManager _prototypeManager; private readonly Font _font; private readonly Font _fontBold; private AdminOverlayAntagFormat _overlayFormat; @@ -36,8 +38,9 @@ internal sealed class AdminNameOverlay : Overlay private float _overlayMergeDistance; //TODO make this adjustable via GUI? - private readonly ProtoId[] _filter = - ["SoloAntagonist", "TeamAntagonist", "SiliconAntagonist", "FreeAgent"]; + private static readonly FrozenSet> Filter = + new ProtoId[] {"SoloAntagonist", "TeamAntagonist", "SiliconAntagonist", "FreeAgent"} + .ToFrozenSet(); private readonly string _antagLabelClassic = Loc.GetString("admin-overlay-antag-classic"); @@ -49,7 +52,8 @@ internal sealed class AdminNameOverlay : Overlay EntityLookupSystem entityLookup, IUserInterfaceManager userInterfaceManager, IConfigurationManager config, - SharedRoleSystem roles) + SharedRoleSystem roles, + IPrototypeManager prototypeManager) { _system = system; _entityManager = entityManager; @@ -57,6 +61,7 @@ internal sealed class AdminNameOverlay : Overlay _entityLookup = entityLookup; _userInterfaceManager = userInterfaceManager; _roles = roles; + _prototypeManager = prototypeManager; ZIndex = 200; // Setting these to a specific ttf would break the antag symbols _font = resourceCache.NotoStack(); @@ -125,6 +130,14 @@ internal sealed class AdminNameOverlay : Overlay foreach (var info in sortable.OrderBy(s => s.Item4.Y).ToList()) { var playerInfo = info.Item1; + var rolePrototype = playerInfo.RoleProto == null + ? null + : _prototypeManager.Index(playerInfo.RoleProto.Value); + + var roleName = Loc.GetString(rolePrototype?.Name ?? RoleTypePrototype.FallbackName); + var roleColor = rolePrototype?.Color ?? RoleTypePrototype.FallbackColor; + var roleSymbol = rolePrototype?.Symbol ?? RoleTypePrototype.FallbackSymbol; + var aabb = info.Item2; var entity = info.Item3; var screenCoordinatesCenter = info.Item4; @@ -209,7 +222,7 @@ internal sealed class AdminNameOverlay : Overlay switch (_overlaySymbolStyle) { case AdminOverlayAntagSymbolStyle.Specific: - symbol = playerInfo.RoleProto.Symbol; + symbol = roleSymbol; break; case AdminOverlayAntagSymbolStyle.Basic: symbol = Loc.GetString("player-tab-antag-prefix"); @@ -225,17 +238,17 @@ internal sealed class AdminNameOverlay : Overlay switch (_overlayFormat) { case AdminOverlayAntagFormat.Roletype: - color = playerInfo.RoleProto.Color; - symbol = _filter.Contains(playerInfo.RoleProto) ? symbol : string.Empty; - text = _filter.Contains(playerInfo.RoleProto) - ? Loc.GetString(playerInfo.RoleProto.Name).ToUpper() + color = roleColor; + symbol = IsFiltered(playerInfo.RoleProto) ? symbol : string.Empty; + text = IsFiltered(playerInfo.RoleProto) + ? roleName.ToUpper() : string.Empty; break; case AdminOverlayAntagFormat.Subtype: - color = playerInfo.RoleProto.Color; - symbol = _filter.Contains(playerInfo.RoleProto) ? symbol : string.Empty; - text = _filter.Contains(playerInfo.RoleProto) - ? _roles.GetRoleSubtypeLabel(playerInfo.RoleProto.Name, playerInfo.Subtype).ToUpper() + color = roleColor; + symbol = IsFiltered(playerInfo.RoleProto) ? symbol : string.Empty; + text = IsFiltered(playerInfo.RoleProto) + ? _roles.GetRoleSubtypeLabel(roleName, playerInfo.Subtype).ToUpper() : string.Empty; break; default: @@ -258,4 +271,12 @@ internal sealed class AdminNameOverlay : Overlay drawnOverlays.Add((screenCoordinatesCenter, currentOffset)); } } + + private static bool IsFiltered(ProtoId? roleProtoId) + { + if (roleProtoId == null) + return false; + + return Filter.Contains(roleProtoId.Value); + } } diff --git a/Content.Client/Administration/Systems/AdminSystem.Overlay.cs b/Content.Client/Administration/Systems/AdminSystem.Overlay.cs index a630df4521..e000bdc0ba 100644 --- a/Content.Client/Administration/Systems/AdminSystem.Overlay.cs +++ b/Content.Client/Administration/Systems/AdminSystem.Overlay.cs @@ -4,6 +4,7 @@ using Robust.Client.Graphics; using Robust.Client.ResourceManagement; using Robust.Client.UserInterface; using Robust.Shared.Configuration; +using Robust.Shared.Prototypes; namespace Content.Client.Administration.Systems { @@ -17,6 +18,7 @@ namespace Content.Client.Administration.Systems [Dependency] private readonly IUserInterfaceManager _userInterfaceManager = default!; [Dependency] private readonly IConfigurationManager _configurationManager = default!; [Dependency] private readonly SharedRoleSystem _roles = default!; + [Dependency] private readonly IPrototypeManager _proto = default!; private AdminNameOverlay _adminNameOverlay = default!; @@ -33,7 +35,8 @@ namespace Content.Client.Administration.Systems _entityLookup, _userInterfaceManager, _configurationManager, - _roles); + _roles, + _proto); _adminManager.AdminStatusUpdated += OnAdminStatusUpdated; } diff --git a/Content.Client/Administration/UI/Tabs/PlayerTab/PlayerTabEntry.xaml.cs b/Content.Client/Administration/UI/Tabs/PlayerTab/PlayerTabEntry.xaml.cs index 41e3fca761..6a2d939b4b 100644 --- a/Content.Client/Administration/UI/Tabs/PlayerTab/PlayerTabEntry.xaml.cs +++ b/Content.Client/Administration/UI/Tabs/PlayerTab/PlayerTabEntry.xaml.cs @@ -1,9 +1,11 @@ using Content.Shared.Administration; +using Content.Shared.Mind; using Content.Shared.Roles; using Robust.Client.AutoGenerated; using Robust.Client.Graphics; using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.XAML; +using Robust.Shared.Prototypes; namespace Content.Client.Administration.UI.Tabs.PlayerTab; @@ -11,6 +13,7 @@ namespace Content.Client.Administration.UI.Tabs.PlayerTab; public sealed partial class PlayerTabEntry : PanelContainer { [Dependency] private readonly IEntityManager _entMan = default!; + [Dependency] private readonly IPrototypeManager _prototype = default!; public PlayerTabEntry( PlayerInfo player, @@ -23,6 +26,8 @@ public sealed partial class PlayerTabEntry : PanelContainer RobustXamlLoader.Load(this); var roles = _entMan.System(); + var rolePrototype = player.RoleProto == null ? null : _prototype.Index(player.RoleProto.Value); + UsernameLabel.Text = player.Username; if (!player.Connected) UsernameLabel.StyleClasses.Add("Disabled"); @@ -57,19 +62,19 @@ public sealed partial class PlayerTabEntry : PanelContainer break; default: case AdminPlayerTabSymbolOption.Specific: - symbol = player.Antag ? player.RoleProto.Symbol : string.Empty; + symbol = player.Antag ? rolePrototype?.Symbol ?? RoleTypePrototype.FallbackSymbol : string.Empty; break; } CharacterLabel.Text = Loc.GetString("player-tab-character-name-antag-symbol", ("symbol", symbol), ("name", player.CharacterName)); if (player.Antag && colorAntags) - CharacterLabel.FontColorOverride = player.RoleProto.Color; + CharacterLabel.FontColorOverride = rolePrototype?.Color ?? RoleTypePrototype.FallbackColor; if (player.IdentityName != player.CharacterName) CharacterLabel.Text += $" [{player.IdentityName}]"; - var roletype = RoleTypeLabel.Text = Loc.GetString(player.RoleProto.Name); - var subtype = roles.GetRoleSubtypeLabel(player.RoleProto.Name, player.Subtype); + var roletype = RoleTypeLabel.Text = Loc.GetString(rolePrototype?.Name ?? RoleTypePrototype.FallbackName); + var subtype = roles.GetRoleSubtypeLabel(rolePrototype?.Name ?? RoleTypePrototype.FallbackName, player.Subtype); switch (roleSetting) { case AdminPlayerTabRoleTypeOption.RoleTypeSubtype: @@ -92,7 +97,7 @@ public sealed partial class PlayerTabEntry : PanelContainer } if (colorRoles) - RoleTypeLabel.FontColorOverride = player.RoleProto.Color; + RoleTypeLabel.FontColorOverride = rolePrototype?.Color ?? RoleTypePrototype.FallbackColor; BackgroundColorPanel.PanelOverride = styleBoxFlat; OverallPlaytimeLabel.Text = player.PlaytimeString; } diff --git a/Content.Client/NetworkConfigurator/NetworkConfiguratorLinkMenu.xaml.cs b/Content.Client/NetworkConfigurator/NetworkConfiguratorLinkMenu.xaml.cs index 8cdffd16af..c627dc2ce8 100644 --- a/Content.Client/NetworkConfigurator/NetworkConfiguratorLinkMenu.xaml.cs +++ b/Content.Client/NetworkConfigurator/NetworkConfiguratorLinkMenu.xaml.cs @@ -1,4 +1,5 @@ -using System.Numerics; +using System.Linq; +using System.Numerics; using Content.Client.UserInterface.Controls; using Content.Shared.DeviceLinking; using Content.Shared.DeviceNetwork; @@ -14,6 +15,8 @@ namespace Content.Client.NetworkConfigurator; [GenerateTypedNameReferences] public sealed partial class NetworkConfiguratorLinkMenu : FancyWindow { + private readonly IPrototypeManager _prototypeManager = null!; + private const string PanelBgColor = "#202023"; private readonly LinksRender _links; @@ -33,6 +36,7 @@ public sealed partial class NetworkConfiguratorLinkMenu : FancyWindow public NetworkConfiguratorLinkMenu() { RobustXamlLoader.Load(this); + IoCManager.InjectDependencies(this); var footerStyleBox = new StyleBoxFlat() { @@ -61,7 +65,7 @@ public sealed partial class NetworkConfiguratorLinkMenu : FancyWindow ButtonContainerRight.RemoveAllChildren(); _sources.Clear(); - _sources.AddRange(linkState.Sources); + _sources.AddRange(linkState.Sources.Select(s => _prototypeManager.Index(s))); _links.SourceButtons.Clear(); var i = 0; foreach (var source in _sources) @@ -73,7 +77,7 @@ public sealed partial class NetworkConfiguratorLinkMenu : FancyWindow } _sinks.Clear(); - _sinks.AddRange(linkState.Sinks); + _sinks.AddRange(linkState.Sinks.Select(s => _prototypeManager.Index(s))); _links.SinkButtons.Clear(); i = 0; foreach (var sink in _sinks) diff --git a/Content.Server/Administration/Logs/AdminLogManager.cs b/Content.Server/Administration/Logs/AdminLogManager.cs index 1d6ff13a5a..add51a7775 100644 --- a/Content.Server/Administration/Logs/AdminLogManager.cs +++ b/Content.Server/Administration/Logs/AdminLogManager.cs @@ -9,12 +9,14 @@ using Content.Shared.Administration.Logs; using Content.Shared.CCVar; using Content.Shared.Chat; using Content.Shared.Database; +using Content.Shared.Mind; using Content.Shared.Players.PlayTimeTracking; using Prometheus; using Robust.Shared; using Robust.Shared.Configuration; using Robust.Shared.Network; using Robust.Shared.Player; +using Robust.Shared.Prototypes; using Robust.Shared.Reflection; using Robust.Shared.Timing; @@ -33,6 +35,7 @@ public sealed partial class AdminLogManager : SharedAdminLogManager, IAdminLogMa [Dependency] private readonly ISharedPlayerManager _player = default!; [Dependency] private readonly ISharedPlaytimeManager _playtime = default!; [Dependency] private readonly ISharedChatManager _chat = default!; + [Dependency] private readonly IPrototypeManager _proto = default!; public const string SawmillId = "admin.logs"; @@ -330,7 +333,8 @@ public sealed partial class AdminLogManager : SharedAdminLogManager, IAdminLogMa var cachedInfo = adminSys.GetCachedPlayerInfo(new NetUserId(id)); if (cachedInfo != null && cachedInfo.Antag) { - var subtype = Loc.GetString(cachedInfo.Subtype ?? cachedInfo.RoleProto.Name); + var proto = cachedInfo.RoleProto == null ? null : _proto.Index(cachedInfo.RoleProto.Value); + var subtype = Loc.GetString(cachedInfo.Subtype ?? proto?.Name ?? RoleTypePrototype.FallbackName); logMessage = Loc.GetString( "admin-alert-antag-label", ("message", logMessage), diff --git a/Content.Server/Administration/Systems/AdminSystem.cs b/Content.Server/Administration/Systems/AdminSystem.cs index 0e5138ba96..95c6578a94 100644 --- a/Content.Server/Administration/Systems/AdminSystem.cs +++ b/Content.Server/Administration/Systems/AdminSystem.cs @@ -231,7 +231,7 @@ public sealed class AdminSystem : EntitySystem var antag = false; // Starting role, antagonist status and role type - RoleTypePrototype roleType = new(); + RoleTypePrototype? roleType = null; var startingRole = string.Empty; LocId? subtype = null; if (_minds.TryGetMind(session, out var mindId, out var mindComp) && mindComp is not null) @@ -244,7 +244,7 @@ public sealed class AdminSystem : EntitySystem subtype = mindComp.Subtype; } else - Log.Error($"{ToPrettyString(mindId)} has invalid Role Type '{mindComp.RoleType}'. Displaying '{Loc.GetString(roleType.Name)}' instead"); + Log.Error($"{ToPrettyString(mindId)} has invalid Role Type '{mindComp.RoleType}'. Displaying '{Loc.GetString(RoleTypePrototype.FallbackName)}' instead"); antag = _role.MindIsAntagonist(mindId); startingRole = _jobs.MindTryGetJobName(mindId); @@ -270,7 +270,7 @@ public sealed class AdminSystem : EntitySystem identityName, startingRole, antag, - roleType, + roleType?.ID, subtype, sortWeight, GetNetEntity(session?.AttachedEntity), diff --git a/Content.Server/DeviceNetwork/Systems/NetworkConfiguratorSystem.cs b/Content.Server/DeviceNetwork/Systems/NetworkConfiguratorSystem.cs index 6bcbe30456..e34929bd2e 100644 --- a/Content.Server/DeviceNetwork/Systems/NetworkConfiguratorSystem.cs +++ b/Content.Server/DeviceNetwork/Systems/NetworkConfiguratorSystem.cs @@ -18,6 +18,7 @@ using Robust.Server.Audio; using Robust.Server.GameObjects; using Robust.Shared.Audio; using Robust.Shared.Map.Events; +using Robust.Shared.Prototypes; using Robust.Shared.Timing; using Robust.Shared.Utility; @@ -496,14 +497,15 @@ public sealed class NetworkConfiguratorSystem : SharedNetworkConfiguratorSystem return; var sources = _deviceLinkSystem.GetSourcePorts(sourceUid, sourceComponent); - var sinks = _deviceLinkSystem.GetSinkPorts(sinkUid, sinkComponent); + var sinks = _deviceLinkSystem.GetSinkPortIds((sinkUid, sinkComponent)); var links = _deviceLinkSystem.GetLinks(sourceUid, sinkUid, sourceComponent); var defaults = _deviceLinkSystem.GetDefaults(sources); + var sourceIds = sources.Select(s => (ProtoId)s.ID).ToArray(); var sourceAddress = Resolve(sourceUid, ref sourceNetworkComponent, false) ? sourceNetworkComponent.Address : ""; var sinkAddress = Resolve(sinkUid, ref sinkNetworkComponent, false) ? sinkNetworkComponent.Address : ""; - var state = new DeviceLinkUserInterfaceState(sources, sinks, links, sourceAddress, sinkAddress, defaults); + var state = new DeviceLinkUserInterfaceState(sourceIds, sinks, links, sourceAddress, sinkAddress, defaults); _uiSystem.SetUiState(configuratorUid, NetworkConfiguratorUiKey.Link, state); } diff --git a/Content.Server/Speech/EntitySystems/MumbleAccentSystem.cs b/Content.Server/Speech/EntitySystems/MumbleAccentSystem.cs index 6b1af5c227..57469a25aa 100644 --- a/Content.Server/Speech/EntitySystems/MumbleAccentSystem.cs +++ b/Content.Server/Speech/EntitySystems/MumbleAccentSystem.cs @@ -2,6 +2,7 @@ using Content.Server.Chat.Systems; using Content.Server.Speech.Components; using Content.Shared.Chat.Prototypes; using Content.Shared.Speech.Components; +using Robust.Shared.Prototypes; namespace Content.Server.Speech.EntitySystems; @@ -9,6 +10,7 @@ public sealed class MumbleAccentSystem : EntitySystem { [Dependency] private readonly ChatSystem _chat = default!; [Dependency] private readonly ReplacementAccentSystem _replacement = default!; + [Dependency] private readonly IPrototypeManager _prototype = default!; public override void Initialize() { @@ -23,10 +25,14 @@ public sealed class MumbleAccentSystem : EntitySystem if (args.Handled || !args.Emote.Category.HasFlag(EmoteCategory.Vocal)) return; - if (TryComp(ent.Owner, out var vocalComp)) + if (TryComp(ent.Owner, out var vocalComp) && vocalComp.EmoteSounds is { } sounds) { // play a muffled version of the vocal emote - args.Handled = _chat.TryPlayEmoteSound(ent.Owner, vocalComp.EmoteSounds, args.Emote, ent.Comp.EmoteAudioParams); + args.Handled = _chat.TryPlayEmoteSound( + ent.Owner, + _prototype.Index(sounds), + args.Emote, + ent.Comp.EmoteAudioParams); } } diff --git a/Content.Server/Speech/EntitySystems/VocalSystem.cs b/Content.Server/Speech/EntitySystems/VocalSystem.cs index 14fac0bab8..fb88238288 100644 --- a/Content.Server/Speech/EntitySystems/VocalSystem.cs +++ b/Content.Server/Speech/EntitySystems/VocalSystem.cs @@ -64,8 +64,11 @@ public sealed class VocalSystem : EntitySystem return; } + if (component.EmoteSounds is not { } sounds) + return; + // just play regular sound based on emote proto - args.Handled = _chat.TryPlayEmoteSound(uid, component.EmoteSounds, args.Emote); + args.Handled = _chat.TryPlayEmoteSound(uid, _proto.Index(sounds), args.Emote); } private void OnScreamAction(EntityUid uid, VocalComponent component, ScreamActionEvent args) @@ -85,7 +88,10 @@ public sealed class VocalSystem : EntitySystem return true; } - return _chat.TryPlayEmoteSound(uid, component.EmoteSounds, component.ScreamId); + if (component.EmoteSounds is not { } sounds) + return false; + + return _chat.TryPlayEmoteSound(uid, _proto.Index(sounds), component.ScreamId); } private void LoadSounds(EntityUid uid, VocalComponent component, Sex? sex = null) @@ -97,6 +103,10 @@ public sealed class VocalSystem : EntitySystem if (!component.Sounds.TryGetValue(sex.Value, out var protoId)) return; - _proto.TryIndex(protoId, out component.EmoteSounds); + + if (!_proto.HasIndex(protoId)) + return; + + component.EmoteSounds = protoId; } } diff --git a/Content.Shared/Administration/PlayerInfo.cs b/Content.Shared/Administration/PlayerInfo.cs index 5164425347..0f8dd814a5 100644 --- a/Content.Shared/Administration/PlayerInfo.cs +++ b/Content.Shared/Administration/PlayerInfo.cs @@ -1,5 +1,6 @@ using Content.Shared.Mind; using Robust.Shared.Network; +using Robust.Shared.Prototypes; using Robust.Shared.Serialization; namespace Content.Shared.Administration; @@ -11,7 +12,7 @@ public sealed record PlayerInfo( string IdentityName, string StartingJob, bool Antag, - RoleTypePrototype RoleProto, + ProtoId? RoleProto, LocId? Subtype, int SortWeight, NetEntity? NetEntity, diff --git a/Content.Shared/Cargo/Prototypes/CargoBountyPrototype.cs b/Content.Shared/Cargo/Prototypes/CargoBountyPrototype.cs index 38ca2286ee..495ad14a9d 100644 --- a/Content.Shared/Cargo/Prototypes/CargoBountyPrototype.cs +++ b/Content.Shared/Cargo/Prototypes/CargoBountyPrototype.cs @@ -10,7 +10,7 @@ namespace Content.Shared.Cargo.Prototypes; /// that must be sold together in a labeled container in order /// to receive a monetary reward. /// -[Prototype, Serializable, NetSerializable] +[Prototype] public sealed partial class CargoBountyPrototype : IPrototype { /// diff --git a/Content.Shared/Chat/Prototypes/EmoteSoundsPrototype.cs b/Content.Shared/Chat/Prototypes/EmoteSoundsPrototype.cs index 73a3ba0bbf..4364e13d84 100644 --- a/Content.Shared/Chat/Prototypes/EmoteSoundsPrototype.cs +++ b/Content.Shared/Chat/Prototypes/EmoteSoundsPrototype.cs @@ -9,7 +9,7 @@ namespace Content.Shared.Chat.Prototypes; /// Sounds collection for each . /// Different entities may use different sounds collections. /// -[Prototype, Serializable, NetSerializable] +[Prototype] public sealed partial class EmoteSoundsPrototype : IPrototype { [IdDataField] diff --git a/Content.Shared/Damage/Prototypes/DamageContainerPrototype.cs b/Content.Shared/Damage/Prototypes/DamageContainerPrototype.cs index 836978dd03..95de0fb29d 100644 --- a/Content.Shared/Damage/Prototypes/DamageContainerPrototype.cs +++ b/Content.Shared/Damage/Prototypes/DamageContainerPrototype.cs @@ -13,7 +13,6 @@ namespace Content.Shared.Damage.Prototypes /// cref="DamageableComponent"/> should support. /// [Prototype] - [Serializable, NetSerializable] public sealed partial class DamageContainerPrototype : IPrototype { [ViewVariables] diff --git a/Content.Shared/Damage/Prototypes/DamageGroupPrototype.cs b/Content.Shared/Damage/Prototypes/DamageGroupPrototype.cs index 6df2138cd4..7615724467 100644 --- a/Content.Shared/Damage/Prototypes/DamageGroupPrototype.cs +++ b/Content.Shared/Damage/Prototypes/DamageGroupPrototype.cs @@ -12,7 +12,6 @@ namespace Content.Shared.Damage.Prototypes /// to change/get/set damage in a . /// [Prototype(2)] - [Serializable, NetSerializable] public sealed partial class DamageGroupPrototype : IPrototype { [IdDataField] public string ID { get; private set; } = default!; diff --git a/Content.Shared/DeviceLinking/DevicePortPrototype.cs b/Content.Shared/DeviceLinking/DevicePortPrototype.cs index d01f4d6d2a..bf062ddce4 100644 --- a/Content.Shared/DeviceLinking/DevicePortPrototype.cs +++ b/Content.Shared/DeviceLinking/DevicePortPrototype.cs @@ -7,7 +7,6 @@ namespace Content.Shared.DeviceLinking; /// /// A prototype for a device port, for use with device linking. /// -[Serializable, NetSerializable] public abstract class DevicePortPrototype { [IdDataField] @@ -28,13 +27,11 @@ public abstract class DevicePortPrototype } [Prototype] -[Serializable, NetSerializable] public sealed partial class SinkPortPrototype : DevicePortPrototype, IPrototype { } [Prototype] -[Serializable, NetSerializable] public sealed partial class SourcePortPrototype : DevicePortPrototype, IPrototype { /// diff --git a/Content.Shared/DeviceLinking/SharedDeviceLinkSystem.cs b/Content.Shared/DeviceLinking/SharedDeviceLinkSystem.cs index e51087fdf6..5d51bbc3e8 100644 --- a/Content.Shared/DeviceLinking/SharedDeviceLinkSystem.cs +++ b/Content.Shared/DeviceLinking/SharedDeviceLinkSystem.cs @@ -1,3 +1,4 @@ +using System.Linq; using Content.Shared.Administration.Logs; using Content.Shared.Database; using Content.Shared.DeviceLinking.Events; @@ -142,6 +143,11 @@ public abstract class SharedDeviceLinkSystem : EntitySystem } } + public ProtoId[] GetSourcePortIds(Entity source) + { + return source.Comp.Ports.ToArray(); + } + /// /// Retrieves the available ports from a source /// @@ -160,6 +166,11 @@ public abstract class SharedDeviceLinkSystem : EntitySystem return sourcePorts; } + public ProtoId[] GetSinkPortIds(Entity source) + { + return source.Comp.Ports.ToArray(); + } + /// /// Retrieves the available ports from a sink /// diff --git a/Content.Shared/DeviceNetwork/DeviceFrequencyPrototype.cs b/Content.Shared/DeviceNetwork/DeviceFrequencyPrototype.cs index 19ccb5e2fe..ac5b6eec18 100644 --- a/Content.Shared/DeviceNetwork/DeviceFrequencyPrototype.cs +++ b/Content.Shared/DeviceNetwork/DeviceFrequencyPrototype.cs @@ -7,7 +7,6 @@ namespace Content.Shared.DeviceNetwork; /// A named device network frequency. Useful for ensuring entity prototypes can communicate with each other. /// [Prototype] -[Serializable, NetSerializable] public sealed partial class DeviceFrequencyPrototype : IPrototype { [IdDataField] diff --git a/Content.Shared/DeviceNetwork/NetworkConfiguratorUserInterfaceState.cs b/Content.Shared/DeviceNetwork/NetworkConfiguratorUserInterfaceState.cs index 13000d00c9..4c02124487 100644 --- a/Content.Shared/DeviceNetwork/NetworkConfiguratorUserInterfaceState.cs +++ b/Content.Shared/DeviceNetwork/NetworkConfiguratorUserInterfaceState.cs @@ -29,16 +29,16 @@ public sealed class DeviceListUserInterfaceState : BoundUserInterfaceState [Serializable, NetSerializable] public sealed class DeviceLinkUserInterfaceState : BoundUserInterfaceState { - public readonly List Sources; - public readonly List Sinks; + public readonly ProtoId[] Sources; + public readonly ProtoId[] Sinks; public readonly HashSet<(ProtoId source, ProtoId sink)> Links; public readonly List<(string source, string sink)>? Defaults; public readonly string SourceAddress; public readonly string SinkAddress; public DeviceLinkUserInterfaceState( - List sources, - List sinks, + ProtoId[] sources, + ProtoId[] sinks, HashSet<(ProtoId source, ProtoId sink)> links, string sourceAddress, string sinkAddress, diff --git a/Content.Shared/Mind/RoleTypePrototype.cs b/Content.Shared/Mind/RoleTypePrototype.cs index 03f88ba751..690bd894a0 100644 --- a/Content.Shared/Mind/RoleTypePrototype.cs +++ b/Content.Shared/Mind/RoleTypePrototype.cs @@ -5,27 +5,31 @@ namespace Content.Shared.Mind; /// /// The core properties of Role Types /// -[Prototype, Serializable] +[Prototype] public sealed partial class RoleTypePrototype : IPrototype { [IdDataField] public string ID { get; private set; } = default!; + public static readonly LocId FallbackName = "role-type-crew-aligned-name"; + public const string FallbackSymbol = ""; + public static readonly Color FallbackColor = Color.FromHex("#eeeeee"); + /// /// The role's name as displayed on the UI. /// [DataField] - public LocId Name = "role-type-crew-aligned-name"; + public LocId Name = FallbackName; /// /// The role's displayed color. /// [DataField] - public Color Color = Color.FromHex("#eeeeee"); + public Color Color = FallbackColor; /// /// A symbol used to represent the role type. /// [DataField] - public string Symbol = string.Empty; + public string Symbol = FallbackSymbol; } diff --git a/Content.Shared/Roles/AntagPrototype.cs b/Content.Shared/Roles/AntagPrototype.cs index 3f5b2a1bd6..ff2712600a 100644 --- a/Content.Shared/Roles/AntagPrototype.cs +++ b/Content.Shared/Roles/AntagPrototype.cs @@ -8,7 +8,6 @@ namespace Content.Shared.Roles; /// Describes information for a single antag. /// [Prototype] -[Serializable, NetSerializable] public sealed partial class AntagPrototype : IPrototype { [ViewVariables] diff --git a/Content.Shared/Silicons/Laws/SiliconLawPrototype.cs b/Content.Shared/Silicons/Laws/SiliconLawPrototype.cs index 434f80e16e..d2bdf7d02b 100644 --- a/Content.Shared/Silicons/Laws/SiliconLawPrototype.cs +++ b/Content.Shared/Silicons/Laws/SiliconLawPrototype.cs @@ -78,7 +78,6 @@ public partial class SiliconLaw : IComparable, IEquatable [Prototype] -[Serializable, NetSerializable] public sealed partial class SiliconLawPrototype : SiliconLaw, IPrototype { /// diff --git a/Content.Shared/Silicons/Laws/SiliconLawsetPrototype.cs b/Content.Shared/Silicons/Laws/SiliconLawsetPrototype.cs index 49c618ef8c..a3861504e9 100644 --- a/Content.Shared/Silicons/Laws/SiliconLawsetPrototype.cs +++ b/Content.Shared/Silicons/Laws/SiliconLawsetPrototype.cs @@ -61,7 +61,7 @@ public sealed partial class SiliconLawset /// This is a prototype for a list. /// Cannot be used directly since it is a list of prototype ids rather than List. /// -[Prototype, Serializable, NetSerializable] +[Prototype] public sealed partial class SiliconLawsetPrototype : IPrototype { /// diff --git a/Content.Shared/Speech/Components/VocalComponent.cs b/Content.Shared/Speech/Components/VocalComponent.cs index a520da4354..0f62a39d45 100644 --- a/Content.Shared/Speech/Components/VocalComponent.cs +++ b/Content.Shared/Speech/Components/VocalComponent.cs @@ -49,5 +49,5 @@ public sealed partial class VocalComponent : Component /// [ViewVariables] [AutoNetworkedField] - public EmoteSoundsPrototype? EmoteSounds = null; + public ProtoId? EmoteSounds = null; } diff --git a/Content.Shared/Store/CurrencyPrototype.cs b/Content.Shared/Store/CurrencyPrototype.cs index 03cc59d2df..fdd113d3a2 100644 --- a/Content.Shared/Store/CurrencyPrototype.cs +++ b/Content.Shared/Store/CurrencyPrototype.cs @@ -11,7 +11,7 @@ namespace Content.Shared.Store; /// This is separate to the cargo ordering system. /// [Prototype] -[DataDefinition, Serializable, NetSerializable] +[DataDefinition] public sealed partial class CurrencyPrototype : IPrototype { [ViewVariables] diff --git a/Content.Shared/Store/ListingPrototype.cs b/Content.Shared/Store/ListingPrototype.cs index b68c5ffa0d..4d01f91c44 100644 --- a/Content.Shared/Store/ListingPrototype.cs +++ b/Content.Shared/Store/ListingPrototype.cs @@ -242,7 +242,6 @@ public partial class ListingData : IEquatable /// Defines a set item listing that is available in a store /// [Prototype] -[Serializable, NetSerializable] [DataDefinition] public sealed partial class ListingPrototype : ListingData, IPrototype { @@ -423,7 +422,7 @@ public sealed partial class ListingDataWithCostModifiers : ListingData /// how will be filled by respective system. /// [Prototype] -[DataDefinition, Serializable, NetSerializable] +[DataDefinition] public sealed partial class DiscountCategoryPrototype : IPrototype { [ViewVariables] diff --git a/Content.Shared/Store/StoreCategoryPrototype.cs b/Content.Shared/Store/StoreCategoryPrototype.cs index 5713ecd98a..fcf7ec3496 100644 --- a/Content.Shared/Store/StoreCategoryPrototype.cs +++ b/Content.Shared/Store/StoreCategoryPrototype.cs @@ -7,7 +7,6 @@ namespace Content.Shared.Store; /// Used to define different categories for a store. /// [Prototype] -[Serializable, NetSerializable, DataDefinition] public sealed partial class StoreCategoryPrototype : IPrototype { private string _name = string.Empty; diff --git a/Content.Shared/StoryGen/Prototypes/StoryTemplatePrototype.cs b/Content.Shared/StoryGen/Prototypes/StoryTemplatePrototype.cs index 38dab902e2..564a3f16d4 100644 --- a/Content.Shared/StoryGen/Prototypes/StoryTemplatePrototype.cs +++ b/Content.Shared/StoryGen/Prototypes/StoryTemplatePrototype.cs @@ -6,7 +6,7 @@ namespace Content.Shared.StoryGen; /// /// Prototype for a story template that can be filled in with words chosen from s. /// -[Serializable, Prototype] +[Prototype] public sealed partial class StoryTemplatePrototype : IPrototype { /// diff --git a/Content.Shared/VendingMachines/VendingMachineInventoryPrototype.cs b/Content.Shared/VendingMachines/VendingMachineInventoryPrototype.cs index b39e29aead..be4816b319 100644 --- a/Content.Shared/VendingMachines/VendingMachineInventoryPrototype.cs +++ b/Content.Shared/VendingMachines/VendingMachineInventoryPrototype.cs @@ -4,7 +4,7 @@ using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototy namespace Content.Shared.VendingMachines { - [Serializable, NetSerializable, Prototype] + [Prototype] public sealed partial class VendingMachineInventoryPrototype : IPrototype { [ViewVariables]