serv4 + submodule update (#12740)

Co-authored-by: DrSmugleaf <DrSmugleaf@users.noreply.github.com>
This commit is contained in:
Paul Ritter
2022-11-27 19:25:55 +01:00
committed by GitHub
parent 7608c24b63
commit 3884c4d3db
46 changed files with 230 additions and 302 deletions

View File

@@ -1,44 +0,0 @@
using Robust.Shared.Serialization.Manager;
using Robust.Shared.Serialization.Markdown;
using Robust.Shared.Serialization.Markdown.Validation;
using Robust.Shared.Serialization.Markdown.Value;
using Robust.Shared.Serialization.TypeSerializers.Interfaces;
namespace Content.Client.CartridgeLoader;
/// <summary>
/// Boilerplate serializer for defining the ui fragment used for a cartridge in yaml
/// </summary>
/// <example>
/// This is an example from the yaml definition from the notekeeper ui
/// <code>
/// - type: CartridgeUi
/// ui: !type:NotekeeperUi
/// </code>
/// </example>
public sealed class CartridgeUISerializer : ITypeSerializer<CartridgeUI, ValueDataNode>
{
public ValidationNode Validate(ISerializationManager serializationManager, ValueDataNode node,
IDependencyCollection dependencies, ISerializationContext? context = null)
{
return serializationManager.ValidateNode<CartridgeUI>(node, context);
}
public CartridgeUI Read(ISerializationManager serializationManager, ValueDataNode node, IDependencyCollection dependencies,
bool skipHook, ISerializationContext? context = null, CartridgeUI? value = default)
{
return serializationManager.Read(node, context, skipHook, value);
}
public CartridgeUI Copy(ISerializationManager serializationManager, CartridgeUI source, CartridgeUI target, bool skipHook,
ISerializationContext? context = null)
{
return serializationManager.Copy(source, context, skipHook);
}
public DataNode Write(ISerializationManager serializationManager, CartridgeUI value, IDependencyCollection dependencies,
bool alwaysWrite = false, ISerializationContext? context = null)
{
return serializationManager.WriteValue(value, alwaysWrite, context);
}
}

View File

@@ -9,6 +9,6 @@ namespace Content.Client.CartridgeLoader;
[RegisterComponent] [RegisterComponent]
public sealed class CartridgeUiComponent : Component public sealed class CartridgeUiComponent : Component
{ {
[DataField("ui", true, customTypeSerializer: typeof(CartridgeUISerializer))] [DataField("ui", true)]
public CartridgeUI? Ui = default; public CartridgeUI? Ui = default;
} }

View File

@@ -11,9 +11,10 @@ namespace Content.Client.Gravity
[DataField("spritemap")] [DataField("spritemap")]
private Dictionary<string, string> _rawSpriteMap private Dictionary<string, string> _rawSpriteMap
{ {
get => _spriteMap.ToDictionary(x => x.Value.ToString().ToLower(), x => x.Value); get => _spriteMap.ToDictionary(x => x.Key.ToString().ToLower(), x => x.Value);
set set
{ {
_spriteMap.Clear();
// Get Sprites for each status // Get Sprites for each status
foreach (var status in (GravityGeneratorStatus[]) Enum.GetValues(typeof(GravityGeneratorStatus))) foreach (var status in (GravityGeneratorStatus[]) Enum.GetValues(typeof(GravityGeneratorStatus)))
{ {

View File

@@ -1,37 +1,25 @@
using System.Collections.Generic;
using System.Linq; using System.Linq;
using Content.Shared.Singularity.Components; using Content.Shared.Singularity.Components;
using JetBrains.Annotations; using JetBrains.Annotations;
using Robust.Client.GameObjects; using Robust.Client.GameObjects;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.Manager.Attributes;
namespace Content.Client.ParticleAccelerator namespace Content.Client.ParticleAccelerator
{ {
[UsedImplicitly] [UsedImplicitly]
[DataDefinition] [DataDefinition]
public sealed class ParticleAcceleratorPartVisualizer : AppearanceVisualizer, ISerializationHooks public sealed class ParticleAcceleratorPartVisualizer : AppearanceVisualizer
{ {
[DataField("baseState", required: true)] [DataField("baseState", required: true)]
private string? _baseState; private string _baseState = default!;
private Dictionary<ParticleAcceleratorVisualState, string> _states = new(); private static readonly Dictionary<ParticleAcceleratorVisualState, string> StatesSuffixes = new()
void ISerializationHooks.AfterDeserialization()
{ {
if (_baseState == null) {ParticleAcceleratorVisualState.Powered, "p"},
{ {ParticleAcceleratorVisualState.Level0, "p0"},
return; {ParticleAcceleratorVisualState.Level1, "p1"},
} {ParticleAcceleratorVisualState.Level2, "p2"},
{ParticleAcceleratorVisualState.Level3, "p3"},
_states.Add(ParticleAcceleratorVisualState.Powered, _baseState + "p"); };
_states.Add(ParticleAcceleratorVisualState.Level0, _baseState + "p0");
_states.Add(ParticleAcceleratorVisualState.Level1, _baseState + "p1");
_states.Add(ParticleAcceleratorVisualState.Level2, _baseState + "p2");
_states.Add(ParticleAcceleratorVisualState.Level3, _baseState + "p3");
}
[Obsolete("Subscribe to your component being initialised instead.")] [Obsolete("Subscribe to your component being initialised instead.")]
public override void InitializeEntity(EntityUid entity) public override void InitializeEntity(EntityUid entity)
@@ -63,7 +51,7 @@ namespace Content.Client.ParticleAccelerator
if (state != ParticleAcceleratorVisualState.Unpowered) if (state != ParticleAcceleratorVisualState.Unpowered)
{ {
sprite.LayerSetVisible(ParticleAcceleratorVisualLayers.Unlit, true); sprite.LayerSetVisible(ParticleAcceleratorVisualLayers.Unlit, true);
sprite.LayerSetState(ParticleAcceleratorVisualLayers.Unlit, _states[state]); sprite.LayerSetState(ParticleAcceleratorVisualLayers.Unlit, _baseState + StatesSuffixes[state]);
} }
else else
{ {

View File

@@ -12,8 +12,8 @@ namespace Content.Client.Trigger
{ {
private const string AnimationKey = "priming_animation"; private const string AnimationKey = "priming_animation";
[DataField("countdown_sound", required: false)] [DataField("countdown_sound")]
private SoundSpecifier _countdownSound = default!; private SoundSpecifier? _countdownSound;
private Animation PrimingAnimation = default!; private Animation PrimingAnimation = default!;

View File

@@ -18,16 +18,31 @@ namespace Content.IntegrationTests.Tests.Chemistry
[Test] [Test]
public void DeserializeNullTest() public void DeserializeNullTest()
{ {
var node = new ValueDataNode("null"); var node = ValueDataNode.Null();
var unit = Serialization.Read<FixedPoint2?>(node); var unit = Serialization.Read<FixedPoint2?>(node);
Assert.That(unit, Is.Null); Assert.That(unit, Is.Null);
} }
[Test]
public void SerializeNullTest()
{
var node = Serialization.WriteValue<FixedPoint2?>(null);
Assert.That(node.IsNull);
}
[Test]
public void SerializeNullableValueTest()
{
var node = Serialization.WriteValue<FixedPoint2?>(FixedPoint2.New(2.5f));
Assert.That(node is ValueDataNode);
Assert.That(((ValueDataNode)node).Value, Is.EqualTo("2.5"));
}
[Test] [Test]
public void DeserializeNullDefinitionTest() public void DeserializeNullDefinitionTest()
{ {
var node = new MappingDataNode().Add("unit", "null"); var node = new MappingDataNode().Add("unit", ValueDataNode.Null());
var definition = Serialization.Read<FixedPoint2TestDefinition>(node); var definition = Serialization.Read<FixedPoint2TestDefinition>(node);
Assert.That(definition.Unit, Is.Null); Assert.That(definition.Unit, Is.Null);

View File

@@ -213,18 +213,14 @@ public sealed class PrototypeSaveTest
} }
private sealed class TestEntityUidContext : ISerializationContext, private sealed class TestEntityUidContext : ISerializationContext,
ITypeSerializer<EntityUid, ValueDataNode>, ITypeSerializer<EntityUid, ValueDataNode>
ITypeReaderWriter<EntityUid, ValueDataNode>
{ {
public Dictionary<(Type, Type), object> TypeReaders { get; } public SerializationManager.SerializerProvider SerializerProvider { get; }
public Dictionary<Type, object> TypeWriters { get; }
public Dictionary<Type, object> TypeCopiers => TypeWriters;
public Dictionary<(Type, Type), object> TypeValidators => TypeReaders;
public TestEntityUidContext() public TestEntityUidContext()
{ {
TypeReaders = new() { { (typeof(EntityUid), typeof(ValueDataNode)), this } }; SerializerProvider = new();
TypeWriters = new() { { typeof(EntityUid), this } }; SerializerProvider.RegisterSerializer(this);
} }
ValidationNode ITypeValidator<EntityUid, ValueDataNode>.Validate(ISerializationManager serializationManager, ValidationNode ITypeValidator<EntityUid, ValueDataNode>.Validate(ISerializationManager serializationManager,
@@ -245,16 +241,9 @@ public sealed class PrototypeSaveTest
ValueDataNode node, ValueDataNode node,
IDependencyCollection dependencies, IDependencyCollection dependencies,
bool skipHook, bool skipHook,
ISerializationContext? context, EntityUid _) ISerializationContext? context, ISerializationManager.InstantiationDelegate<EntityUid>? instanceProvider = null)
{ {
return EntityUid.Invalid; return EntityUid.Invalid;
} }
public EntityUid Copy(ISerializationManager serializationManager, EntityUid source, EntityUid target,
bool skipHook,
ISerializationContext? context = null)
{
return new((int) source);
}
} }
} }

View File

@@ -6,7 +6,7 @@ using Robust.Shared.Serialization.TypeSerializers.Interfaces;
namespace Content.Server.Atmos.Serialization; namespace Content.Server.Atmos.Serialization;
public sealed class TileAtmosCollectionSerializer : ITypeSerializer<Dictionary<Vector2i, TileAtmosphere>, MappingDataNode> public sealed class TileAtmosCollectionSerializer : ITypeSerializer<Dictionary<Vector2i, TileAtmosphere>, MappingDataNode>, ITypeCopier<Dictionary<Vector2i, TileAtmosphere>>
{ {
public ValidationNode Validate(ISerializationManager serializationManager, MappingDataNode node, public ValidationNode Validate(ISerializationManager serializationManager, MappingDataNode node,
IDependencyCollection dependencies, ISerializationContext? context = null) IDependencyCollection dependencies, ISerializationContext? context = null)
@@ -14,8 +14,10 @@ public sealed class TileAtmosCollectionSerializer : ITypeSerializer<Dictionary<V
return serializationManager.ValidateNode<TileAtmosData>(node, context); return serializationManager.ValidateNode<TileAtmosData>(node, context);
} }
public Dictionary<Vector2i, TileAtmosphere> Read(ISerializationManager serializationManager, MappingDataNode node, IDependencyCollection dependencies, public Dictionary<Vector2i, TileAtmosphere> Read(ISerializationManager serializationManager, MappingDataNode node,
bool skipHook, ISerializationContext? context = null, Dictionary<Vector2i, TileAtmosphere>? value = default) IDependencyCollection dependencies,
bool skipHook, ISerializationContext? context = null,
ISerializationManager.InstantiationDelegate<Dictionary<Vector2i, TileAtmosphere>>? instanceProvider = null)
{ {
var data = serializationManager.Read<TileAtmosData>(node, context, skipHook); var data = serializationManager.Read<TileAtmosData>(node, context, skipHook);
var tiles = new Dictionary<Vector2i, TileAtmosphere>(); var tiles = new Dictionary<Vector2i, TileAtmosphere>();
@@ -72,13 +74,6 @@ public sealed class TileAtmosCollectionSerializer : ITypeSerializer<Dictionary<V
}, alwaysWrite, context); }, alwaysWrite, context);
} }
public Dictionary<Vector2i, TileAtmosphere> Copy(ISerializationManager serializationManager, Dictionary<Vector2i, TileAtmosphere> source, Dictionary<Vector2i, TileAtmosphere> target, bool skipHook,
ISerializationContext? context = null)
{
serializationManager.Copy(source, ref target, context, skipHook);
return target;
}
[DataDefinition] [DataDefinition]
private struct TileAtmosData private struct TileAtmosData
{ {
@@ -86,4 +81,20 @@ public sealed class TileAtmosCollectionSerializer : ITypeSerializer<Dictionary<V
[DataField("tiles")] public Dictionary<Vector2i, int>? TilesUniqueMixes; [DataField("tiles")] public Dictionary<Vector2i, int>? TilesUniqueMixes;
} }
public void CopyTo(ISerializationManager serializationManager, Dictionary<Vector2i, TileAtmosphere> source, ref Dictionary<Vector2i, TileAtmosphere> target, bool skipHook,
ISerializationContext? context = null)
{
target.Clear();
foreach (var (key, val) in source)
{
target.Add(key,
new TileAtmosphere(
val.GridIndex,
val.GridIndices,
val.Air?.Clone(),
val.Air?.Immutable ?? false,
val.Space));
}
}
} }

View File

@@ -2,7 +2,6 @@ using Content.Server.Storage.Components;
using Content.Shared.Storage; using Content.Shared.Storage;
using Robust.Shared.Prototypes; using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.Manager; using Robust.Shared.Serialization.Manager;
using Robust.Shared.Serialization.Markdown;
using Robust.Shared.Serialization.Markdown.Mapping; using Robust.Shared.Serialization.Markdown.Mapping;
using Robust.Shared.Serialization.Markdown.Sequence; using Robust.Shared.Serialization.Markdown.Sequence;
using Robust.Shared.Serialization.Markdown.Validation; using Robust.Shared.Serialization.Markdown.Validation;
@@ -36,7 +35,7 @@ public sealed class ContainerFillComponent : Component
// all of this exists just to validate prototype ids. // all of this exists just to validate prototype ids.
// it would be nice if you could specify only a type validator and not have to re-implement everything else. // it would be nice if you could specify only a type validator and not have to re-implement everything else.
// or a dictionary serializer that accepts a custom type serializer for the dictionary values // or a dictionary serializer that accepts a custom type serializer for the dictionary values
public sealed class ContainerFillSerializer : ITypeSerializer<Dictionary<string, List<string>>, MappingDataNode> public sealed class ContainerFillSerializer : ITypeValidator<Dictionary<string, List<string>>, MappingDataNode>
{ {
private static PrototypeIdListSerializer<EntityPrototype> ListSerializer => new(); private static PrototypeIdListSerializer<EntityPrototype> ListSerializer => new();
@@ -61,35 +60,4 @@ public sealed class ContainerFillSerializer : ITypeSerializer<Dictionary<string,
return new ValidatedMappingNode(mapping); return new ValidatedMappingNode(mapping);
} }
public Dictionary<string, List<string>> Copy(
ISerializationManager serializationManager,
Dictionary<string, List<string>> source,
Dictionary<string, List<string>> target,
bool skipHook,
ISerializationContext? context = null)
{
serializationManager.Copy(source, ref target, context, skipHook);
return target;
}
public Dictionary<string, List<string>> Read(
ISerializationManager serializationManager,
MappingDataNode node,
IDependencyCollection dependencies,
bool skipHook,
ISerializationContext? context = null,
Dictionary<string, List<string>>? value = null)
{
return serializationManager.Read(node, context, skipHook, value);
}
public DataNode Write(ISerializationManager serializationManager,
Dictionary<string, List<string>> value,
IDependencyCollection dependencies,
bool alwaysWrite = false,
ISerializationContext? context = null)
{
return serializationManager.WriteValue(value, alwaysWrite, context);
}
} }

View File

@@ -1,3 +1,4 @@
using System.Threading;
using Content.Server.Body.Systems; using Content.Server.Body.Systems;
using Content.Server.Chat.Systems; using Content.Server.Chat.Systems;
using Content.Server.Disease.Components; using Content.Server.Disease.Components;
@@ -21,7 +22,6 @@ using Robust.Shared.Prototypes;
using Robust.Shared.Random; using Robust.Shared.Random;
using Robust.Shared.Serialization.Manager; using Robust.Shared.Serialization.Manager;
using Robust.Shared.Utility; using Robust.Shared.Utility;
using System.Threading;
namespace Content.Server.Disease namespace Content.Server.Disease
{ {
@@ -384,7 +384,7 @@ namespace Content.Server.Disease
return; return;
} }
var freshDisease = _serializationManager.Copy(addedDisease); var freshDisease = _serializationManager.CreateCopy(addedDisease);
if (freshDisease == null) return; if (freshDisease == null) return;

View File

@@ -1,6 +1,5 @@
using Content.Server.NodeContainer; using Content.Server.NodeContainer;
using Content.Server.NodeContainer.Nodes; using Content.Server.NodeContainer.Nodes;
using Robust.Shared.Map;
using Robust.Shared.Map.Components; using Robust.Shared.Map.Components;
namespace Content.Server.Electrocution namespace Content.Server.Electrocution
@@ -11,7 +10,7 @@ namespace Content.Server.Electrocution
[DataField("cable")] [DataField("cable")]
public EntityUid CableEntity; public EntityUid CableEntity;
[DataField("node")] [DataField("node")]
public string NodeName = default!; public string? NodeName;
public override IEnumerable<Node> GetReachableNodes(TransformComponent xform, public override IEnumerable<Node> GetReachableNodes(TransformComponent xform,
EntityQuery<NodeContainerComponent> nodeQuery, EntityQuery<NodeContainerComponent> nodeQuery,

View File

@@ -9,6 +9,5 @@ public sealed class EnsnareableComponent : SharedEnsnareableComponent
/// <summary> /// <summary>
/// The container where the <see cref="EnsnaringComponent"/> entity will be stored /// The container where the <see cref="EnsnaringComponent"/> entity will be stored
/// </summary> /// </summary>
[DataField("container")]
public Container Container = default!; public Container Container = default!;
} }

View File

@@ -1,43 +1,38 @@
using System.Linq; using System.Linq;
using Content.Server.Administration.Commands;
using Content.Server.CharacterAppearance.Components; using Content.Server.CharacterAppearance.Components;
using Content.Server.Chat.Managers; using Content.Server.Chat.Managers;
using Content.Server.GameTicking.Rules.Components;
using Content.Server.GameTicking.Rules.Configurations; using Content.Server.GameTicking.Rules.Configurations;
using Content.Server.Ghost.Roles.Components; using Content.Server.Ghost.Roles.Components;
using Content.Server.Ghost.Roles.Events; using Content.Server.Ghost.Roles.Events;
using Content.Server.Humanoid.Systems;
using Content.Server.Mind.Components; using Content.Server.Mind.Components;
using Content.Server.NPC.Systems;
using Content.Server.Nuke; using Content.Server.Nuke;
using Content.Server.Preferences.Managers;
using Content.Server.RoundEnd; using Content.Server.RoundEnd;
using Content.Server.Shuttles.Components; using Content.Server.Shuttles.Components;
using Content.Server.Shuttles.Systems; using Content.Server.Shuttles.Systems;
using Content.Server.Spawners.Components; using Content.Server.Spawners.Components;
using Content.Server.Station.Components;
using Content.Server.Station.Systems; using Content.Server.Station.Systems;
using Content.Shared.MobState; using Content.Server.Traitor;
using Content.Shared.Dataset; using Content.Shared.Dataset;
using Content.Shared.MobState;
using Content.Shared.MobState.Components;
using Content.Shared.Nuke;
using Content.Shared.Preferences;
using Content.Shared.Roles; using Content.Shared.Roles;
using Robust.Server.GameObjects;
using Robust.Server.Maps; using Robust.Server.Maps;
using Robust.Server.Player; using Robust.Server.Player;
using Robust.Shared.Configuration;
using Robust.Shared.Map; using Robust.Shared.Map;
using Robust.Shared.Player;
using Robust.Shared.Prototypes; using Robust.Shared.Prototypes;
using Robust.Shared.Random; using Robust.Shared.Random;
using Robust.Shared.Utility; using Robust.Shared.Utility;
using Content.Server.Traitor;
using Content.Shared.MobState.Components;
using System.Data;
using Content.Server.GameTicking.Rules.Components;
using Content.Server.Station.Components;
using Content.Shared.Chat;
using Content.Shared.Nuke;
using Robust.Server.GameObjects;
using Content.Server.NPC.Components;
using Content.Server.NPC.Systems;
using Content.Server.Traitor.Uplink;
using Robust.Shared.Audio;
using Robust.Shared.Configuration;
using Robust.Shared.Player;
using Content.Server.Administration.Commands;
using Content.Server.Humanoid.Systems;
using Content.Shared.Preferences;
using Content.Server.Preferences.Managers;
namespace Content.Server.GameTicking.Rules; namespace Content.Server.GameTicking.Rules;
@@ -846,7 +841,7 @@ public sealed class NukeopsRuleSystem : GameRuleSystem
var query = EntityQuery<NukeOperativeComponent, MindComponent>(true); var query = EntityQuery<NukeOperativeComponent, MindComponent>(true);
foreach (var (_, mindComp) in query) foreach (var (_, mindComp) in query)
{ {
if (mindComp.Mind?.TryGetSession(out var session) == true) if (mindComp.Mind != null && mindComp.Mind.TryGetSession(out var session) == true)
_operativePlayers.Add(session); _operativePlayers.Add(session);
} }

View File

@@ -56,7 +56,7 @@ public sealed class RandomHumanoidSystem : EntitySystem
foreach (var entry in prototype.Components.Values) foreach (var entry in prototype.Components.Values)
{ {
var comp = (Component) _serialization.Copy(entry.Component); var comp = (Component) _serialization.CreateCopy(entry.Component);
comp.Owner = humanoid; comp.Owner = humanoid;
EntityManager.AddComponent(humanoid, comp, true); EntityManager.AddComponent(humanoid, comp, true);
} }

View File

@@ -27,7 +27,7 @@ namespace Content.Server.Jobs
component.Owner = mob; component.Owner = mob;
var temp = (object) component; var temp = (object) component;
serializationManager.Copy(data.Component, ref temp); serializationManager.CopyTo(data.Component, ref temp);
entityManager.AddComponent(mob, (Component)temp!); entityManager.AddComponent(mob, (Component)temp!);
} }
} }

View File

@@ -39,10 +39,12 @@ public sealed class HTNTaskListSerializer : ITypeSerializer<List<string>, Sequen
return new ValidatedSequenceNode(list); return new ValidatedSequenceNode(list);
} }
public List<string> Read(ISerializationManager serializationManager, SequenceDataNode node, IDependencyCollection dependencies, public List<string> Read(ISerializationManager serializationManager, SequenceDataNode node,
bool skipHook, ISerializationContext? context = null, List<string>? value = default) IDependencyCollection dependencies,
bool skipHook, ISerializationContext? context = null,
ISerializationManager.InstantiationDelegate<List<string>>? instanceProvider = null)
{ {
value ??= new List<string>(); var value = instanceProvider != null ? instanceProvider() : new List<string>();
foreach (var data in node.Sequence) foreach (var data in node.Sequence)
{ {
var mapping = (MappingDataNode) data; var mapping = (MappingDataNode) data;
@@ -72,15 +74,4 @@ public sealed class HTNTaskListSerializer : ITypeSerializer<List<string>, Sequen
return sequence; return sequence;
} }
public List<string> Copy(ISerializationManager serializationManager, List<string> source, List<string> target, bool skipHook,
ISerializationContext? context = null)
{
target.Clear();
target.EnsureCapacity(source.Capacity);
// Tasks are just prototypes soooo?
target.AddRange(source);
return target;
}
} }

View File

@@ -45,10 +45,12 @@ public sealed class NPCBlackboardSerializer : ITypeReader<NPCBlackboard, Mapping
return new ValidatedSequenceNode(validated); return new ValidatedSequenceNode(validated);
} }
public NPCBlackboard Read(ISerializationManager serializationManager, MappingDataNode node, IDependencyCollection dependencies, public NPCBlackboard Read(ISerializationManager serializationManager, MappingDataNode node,
bool skipHook, ISerializationContext? context = null, NPCBlackboard? value = default) IDependencyCollection dependencies,
bool skipHook, ISerializationContext? context = null,
ISerializationManager.InstantiationDelegate<NPCBlackboard>? instanceProvider = null)
{ {
value ??= new NPCBlackboard(); var value = instanceProvider != null ? instanceProvider() : new NPCBlackboard();
if (node.Count > 0) if (node.Count > 0)
{ {

View File

@@ -19,8 +19,14 @@ namespace Content.Server.NodeContainer
return (T) Nodes[identifier]; return (T) Nodes[identifier];
} }
public bool TryGetNode<T>(string identifier, [NotNullWhen(true)] out T? node) where T : Node public bool TryGetNode<T>(string? identifier, [NotNullWhen(true)] out T? node) where T : Node
{ {
if (identifier == null)
{
node = null;
return false;
}
if (Nodes.TryGetValue(identifier, out var n) && n is T t) if (Nodes.TryGetValue(identifier, out var n) && n is T t)
{ {
node = t; node = t;

View File

@@ -9,7 +9,6 @@ using Content.Shared.Payload.Components;
using Content.Shared.Tag; using Content.Shared.Tag;
using Robust.Shared.Containers; using Robust.Shared.Containers;
using Robust.Shared.Serialization.Manager; using Robust.Shared.Serialization.Manager;
using Robust.Shared.Serialization.Markdown.Validation;
using Robust.Shared.Utility; using Robust.Shared.Utility;
namespace Content.Server.Payload.EntitySystems; namespace Content.Server.Payload.EntitySystems;
@@ -100,7 +99,7 @@ public sealed class PayloadSystem : EntitySystem
component.Owner = uid; component.Owner = uid;
var temp = (object) component; var temp = (object) component;
_serializationManager.Copy(data.Component, ref temp); _serializationManager.CopyTo(data.Component, ref temp);
EntityManager.AddComponent(uid, (Component)temp!); EntityManager.AddComponent(uid, (Component)temp!);
trigger.GrantedComponents.Add(registration.Type); trigger.GrantedComponents.Add(registration.Type);

View File

@@ -1,7 +1,7 @@
using Content.Shared.Radio; using Content.Shared.Radio;
using Content.Shared.Salvage;
using Robust.Shared.GameStates; using Robust.Shared.GameStates;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
using Content.Shared.Salvage;
namespace Content.Server.Salvage namespace Content.Server.Salvage
{ {
@@ -66,6 +66,7 @@ namespace Content.Server.Salvage
public int PreviousCharge = 5; public int PreviousCharge = 5;
} }
[CopyByRef]
public record struct MagnetState(MagnetStateType StateType, TimeSpan Until) public record struct MagnetState(MagnetStateType StateType, TimeSpan Until)
{ {
public static readonly MagnetState Inactive = new (MagnetStateType.Inactive, TimeSpan.Zero); public static readonly MagnetState Inactive = new (MagnetStateType.Inactive, TimeSpan.Zero);

View File

@@ -38,7 +38,7 @@ public sealed class TraitSystem : EntitySystem
// Add all components required by the prototype // Add all components required by the prototype
foreach (var entry in traitPrototype.Components.Values) foreach (var entry in traitPrototype.Components.Values)
{ {
var comp = (Component) _serializationManager.Copy(entry.Component); var comp = (Component) _serializationManager.CreateCopy(entry.Component);
comp.Owner = args.Mob; comp.Owner = args.Mob;
EntityManager.AddComponent(args.Mob, comp); EntityManager.AddComponent(args.Mob, comp);
} }

View File

@@ -180,7 +180,7 @@ public sealed partial class ArtifactSystem
comp.Owner = uid; comp.Owner = uid;
var temp = (object) comp; var temp = (object) comp;
_serialization.Copy(entry.Component, ref temp); _serialization.CopyTo(entry.Component, ref temp);
EntityManager.AddComponent(uid, (Component) temp!, true); EntityManager.AddComponent(uid, (Component) temp!, true);
} }

View File

@@ -16,7 +16,7 @@ public sealed class BodyComponent : Component, IDraggable
public readonly string? Prototype; public readonly string? Prototype;
[DataField("root")] [DataField("root")]
public BodyPartSlot Root = default!; public BodyPartSlot? Root;
[DataField("gibSound")] [DataField("gibSound")]
public SoundSpecifier GibSound = new SoundCollectionSpecifier("gib"); public SoundSpecifier GibSound = new SoundCollectionSpecifier("gib");

View File

@@ -7,10 +7,10 @@ namespace Content.Shared.Body.Components;
[Serializable, NetSerializable] [Serializable, NetSerializable]
public sealed class BodyComponentState : ComponentState public sealed class BodyComponentState : ComponentState
{ {
public readonly BodyPartSlot Root; public readonly BodyPartSlot? Root;
public readonly SoundSpecifier GibSound; public readonly SoundSpecifier GibSound;
public BodyComponentState(BodyPartSlot root, SoundSpecifier gibSound) public BodyComponentState(BodyPartSlot? root, SoundSpecifier gibSound)
{ {
Root = root; Root = root;
GibSound = gibSound; GibSound = gibSound;

View File

@@ -125,8 +125,10 @@ public sealed class BodyPrototypeSerializer : ITypeReader<BodyPrototype, Mapping
return new ValidatedSequenceNode(nodes); return new ValidatedSequenceNode(nodes);
} }
public BodyPrototype Read(ISerializationManager serializationManager, MappingDataNode node, IDependencyCollection dependencies, public BodyPrototype Read(ISerializationManager serializationManager, MappingDataNode node,
bool skipHook, ISerializationContext? context = null, BodyPrototype? value = default) IDependencyCollection dependencies,
bool skipHook, ISerializationContext? context = null,
ISerializationManager.InstantiationDelegate<BodyPrototype>? instanceProvider = null)
{ {
var id = node.Get<ValueDataNode>("id").Value; var id = node.Get<ValueDataNode>("id").Value;
var name = node.Get<ValueDataNode>("name").Value; var name = node.Get<ValueDataNode>("name").Value;

View File

@@ -125,7 +125,7 @@ public partial class SharedBodySystem
{ {
if (id == null || if (id == null ||
!Resolve(id.Value, ref body, false) || !Resolve(id.Value, ref body, false) ||
!TryComp(body.Root.Child, out BodyPartComponent? part)) !TryComp(body.Root?.Child, out BodyPartComponent? part))
yield break; yield break;
yield return (body.Root.Child.Value, part); yield return (body.Root.Child.Value, part);
@@ -155,7 +155,7 @@ public partial class SharedBodySystem
if (bodyId == null || !Resolve(bodyId.Value, ref body, false)) if (bodyId == null || !Resolve(bodyId.Value, ref body, false))
yield break; yield break;
foreach (var slot in GetPartAllSlots(body.Root.Child)) foreach (var slot in GetPartAllSlots(body.Root?.Child))
{ {
yield return slot; yield return slot;
} }

View File

@@ -37,5 +37,5 @@ public sealed class ReactiveReagentEffectEntry
[DataField("groups", readOnly: true, serverOnly: true, [DataField("groups", readOnly: true, serverOnly: true,
customTypeSerializer:typeof(PrototypeIdDictionarySerializer<HashSet<ReactionMethod>, ReactiveGroupPrototype>))] customTypeSerializer:typeof(PrototypeIdDictionarySerializer<HashSet<ReactionMethod>, ReactiveGroupPrototype>))]
public Dictionary<string, HashSet<ReactionMethod>> ReactiveGroups { get; } = default!; public Dictionary<string, HashSet<ReactionMethod>>? ReactiveGroups { get; }
} }

View File

@@ -42,7 +42,8 @@ namespace Content.Shared.Construction.Steps
MappingDataNode node, MappingDataNode node,
IDependencyCollection dependencies, IDependencyCollection dependencies,
bool skipHook, bool skipHook,
ISerializationContext? context = null, ConstructionGraphStep? _ = null) ISerializationContext? context = null,
ISerializationManager.InstantiationDelegate<ConstructionGraphStep>? instanceProvider = null)
{ {
var type = GetType(node) ?? var type = GetType(node) ??
throw new ArgumentException( throw new ArgumentException(

View File

@@ -43,7 +43,7 @@ namespace Content.Shared.Damage
/// <remarks> /// <remarks>
/// If this data-field is specified, this allows damageable components to be initialized with non-zero damage. /// If this data-field is specified, this allows damageable components to be initialized with non-zero damage.
/// </remarks> /// </remarks>
[DataField("damage")] [DataField("damage", readOnly: true)] //todo remove this readonly when implementing writing to damagespecifier
public DamageSpecifier Damage = new(); public DamageSpecifier Damage = new();
/// <summary> /// <summary>

View File

@@ -1,10 +1,8 @@
using Content.Shared.Damage.Prototypes;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Dictionary;
using Robust.Shared.Utility;
using System.Linq;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
using Content.Shared.Damage.Prototypes;
using Content.Shared.FixedPoint; using Content.Shared.FixedPoint;
using Robust.Shared.Prototypes;
using Robust.Shared.Utility;
namespace Content.Shared.Damage namespace Content.Shared.Damage
{ {
@@ -18,31 +16,13 @@ namespace Content.Shared.Damage
[DataDefinition] [DataDefinition]
public sealed class DamageSpecifier : IEquatable<DamageSpecifier> public sealed class DamageSpecifier : IEquatable<DamageSpecifier>
{ {
[JsonPropertyName("types")]
[DataField("types", customTypeSerializer: typeof(PrototypeIdDictionarySerializer<FixedPoint2, DamageTypePrototype>))]
private readonly Dictionary<string,FixedPoint2>? _damageTypeDictionary;
[JsonPropertyName("groups")]
[DataField("groups", customTypeSerializer: typeof(PrototypeIdDictionarySerializer<FixedPoint2, DamageGroupPrototype>))]
private readonly Dictionary<string, FixedPoint2>? _damageGroupDictionary;
/// <summary> /// <summary>
/// Main DamageSpecifier dictionary. Most DamageSpecifier functions exist to somehow modifying this. /// Main DamageSpecifier dictionary. Most DamageSpecifier functions exist to somehow modifying this.
/// </summary> /// </summary>
[JsonIgnore] [JsonIgnore]
[ViewVariables(VVAccess.ReadWrite)] [ViewVariables(VVAccess.ReadWrite)]
public Dictionary<string, FixedPoint2> DamageDict [IncludeDataField(customTypeSerializer: typeof(DamageSpecifierDictionarySerializer), readOnly: true)]
{ public Dictionary<string, FixedPoint2> DamageDict { get; set; } = new();
get
{
if (_damageDict == null)
DeserializeDamage();
return _damageDict!;
}
set => _damageDict = value;
}
[JsonIgnore]
private Dictionary<string, FixedPoint2>? _damageDict;
/// <summary> /// <summary>
/// Sum of the damage values. /// Sum of the damage values.
@@ -88,56 +68,19 @@ namespace Content.Shared.Damage
/// </summary> /// </summary>
public DamageSpecifier(DamageGroupPrototype group, FixedPoint2 value) public DamageSpecifier(DamageGroupPrototype group, FixedPoint2 value)
{ {
_damageGroupDictionary = new() { { group.ID, value } };
}
#endregion constructors
/// <summary>
/// Combines the damage group and type datafield dictionaries FixedPoint2o a single damage dictionary.
/// </summary>
public void DeserializeDamage()
{
// Add all the damage types by just copying the type dictionary (if it is not null).
if (_damageTypeDictionary != null)
{
_damageDict = new(_damageTypeDictionary);
}
else
{
_damageDict = new();
}
if (_damageGroupDictionary == null)
return;
// Then resolve damage groups and add them
var prototypeManager = IoCManager.Resolve<IPrototypeManager>();
foreach (var entry in _damageGroupDictionary)
{
if (!prototypeManager.TryIndex<DamageGroupPrototype>(entry.Key, out var group))
{
// This can happen if deserialized before prototypes are loaded.
Logger.Error($"Unknown damage group given to DamageSpecifier: {entry.Key}");
continue;
}
// Simply distribute evenly (except for rounding). // Simply distribute evenly (except for rounding).
// We do this by reducing remaining the # of types and damage every loop. // We do this by reducing remaining the # of types and damage every loop.
var remainingTypes = group.DamageTypes.Count; var remainingTypes = group.DamageTypes.Count;
var remainingDamage = entry.Value; var remainingDamage = value;
foreach (var damageType in group.DamageTypes) foreach (var damageType in group.DamageTypes)
{ {
var damage = remainingDamage / FixedPoint2.New(remainingTypes); var damage = remainingDamage / FixedPoint2.New(remainingTypes);
if (!_damageDict.TryAdd(damageType, damage)) DamageDict.Add(damageType, damage);
{
// Key already exists, add values
_damageDict[damageType] += damage;
}
remainingDamage -= damage; remainingDamage -= damage;
remainingTypes -= 1; remainingTypes -= 1;
} }
} }
} #endregion constructors
/// <summary> /// <summary>
/// Reduce (or increase) damages by applying a damage modifier set. /// Reduce (or increase) damages by applying a damage modifier set.

View File

@@ -0,0 +1,80 @@
using Content.Shared.Damage.Prototypes;
using Content.Shared.FixedPoint;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.Manager;
using Robust.Shared.Serialization.Markdown.Mapping;
using Robust.Shared.Serialization.Markdown.Validation;
using Robust.Shared.Serialization.Markdown.Value;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Dictionary;
using Robust.Shared.Serialization.TypeSerializers.Interfaces;
namespace Content.Shared.Damage;
//todo writing
public sealed class DamageSpecifierDictionarySerializer : ITypeReader<Dictionary<string, FixedPoint2>, MappingDataNode>
{
private ITypeValidator<Dictionary<string, FixedPoint2>, MappingDataNode> _damageTypeSerializer = new PrototypeIdDictionarySerializer<FixedPoint2, DamageTypePrototype>();
private ITypeValidator<Dictionary<string, FixedPoint2>, MappingDataNode> _damageGroupSerializer = new PrototypeIdDictionarySerializer<FixedPoint2, DamageGroupPrototype>();
public ValidationNode Validate(ISerializationManager serializationManager, MappingDataNode node,
IDependencyCollection dependencies, ISerializationContext? context = null)
{
var vals = new Dictionary<ValidationNode, ValidationNode>();
if (node.TryGet<MappingDataNode>("types", out var typesNode))
{
vals.Add(new ValidatedValueNode(new ValueDataNode("types")), _damageTypeSerializer.Validate(serializationManager, typesNode, dependencies, context));
}
if (node.TryGet<MappingDataNode>("groups", out var groupsNode))
{
vals.Add(new ValidatedValueNode(new ValueDataNode("groups")), _damageGroupSerializer.Validate(serializationManager, groupsNode, dependencies, context));
}
return new ValidatedMappingNode(vals);
}
public Dictionary<string, FixedPoint2> Read(ISerializationManager serializationManager, MappingDataNode node, IDependencyCollection dependencies,
bool skipHook, ISerializationContext? context = null, ISerializationManager.InstantiationDelegate<Dictionary<string, FixedPoint2>>? instanceProvider = null)
{
var dict = instanceProvider != null ? instanceProvider() : new();
// Add all the damage types by just copying the type dictionary (if it is not null).
if (node.TryGet("types", out var typesNode))
{
serializationManager.Read(typesNode, instanceProvider: () => dict);
}
if (!node.TryGet("groups", out var groupsNode))
return dict;
// Then resolve damage groups and add them
var prototypeManager = dependencies.Resolve<IPrototypeManager>();
foreach (var entry in serializationManager.Read<Dictionary<string, FixedPoint2>>(groupsNode))
{
if (!prototypeManager.TryIndex<DamageGroupPrototype>(entry.Key, out var group))
{
// This can happen if deserialized before prototypes are loaded.
// i made this a warning bc it was failing tests -paul
dependencies.Resolve<ILogManager>().RootSawmill.Error($"Unknown damage group given to DamageSpecifier: {entry.Key}");
continue;
}
// Simply distribute evenly (except for rounding).
// We do this by reducing remaining the # of types and damage every loop.
var remainingTypes = group.DamageTypes.Count;
var remainingDamage = entry.Value;
foreach (var damageType in group.DamageTypes)
{
var damage = remainingDamage / FixedPoint2.New(remainingTypes);
if (!dict.TryAdd(damageType, damage))
{
// Key already exists, add values
dict[damageType] += damage;
}
remainingDamage -= damage;
remainingTypes -= 1;
}
}
return dict;
}
}

View File

@@ -11,7 +11,7 @@ namespace Content.Shared.Damage.Prototypes
/// These groups can be used to specify supported damage types of a <see cref="DamageContainerPrototype"/>, or /// These groups can be used to specify supported damage types of a <see cref="DamageContainerPrototype"/>, or
/// to change/get/set damage in a <see cref="DamageableComponent"/>. /// to change/get/set damage in a <see cref="DamageableComponent"/>.
/// </remarks> /// </remarks>
[Prototype("damageGroup")] [Prototype("damageGroup", 2)]
[Serializable, NetSerializable] [Serializable, NetSerializable]
public sealed class DamageGroupPrototype : IPrototype public sealed class DamageGroupPrototype : IPrototype
{ {

View File

@@ -15,10 +15,12 @@ namespace Content.Shared.Decals
return serializationManager.ValidateNode<Dictionary<Vector2i, Dictionary<uint, Decal>>>(node, context); return serializationManager.ValidateNode<Dictionary<Vector2i, Dictionary<uint, Decal>>>(node, context);
} }
public DecalGridComponent.DecalGridChunkCollection Read(ISerializationManager serializationManager, MappingDataNode node, public DecalGridComponent.DecalGridChunkCollection Read(ISerializationManager serializationManager,
IDependencyCollection dependencies, bool skipHook, ISerializationContext? context = null, DecalGridComponent.DecalGridChunkCollection? _ = null) MappingDataNode node,
IDependencyCollection dependencies, bool skipHook, ISerializationContext? context = null,
ISerializationManager.InstantiationDelegate<DecalGridComponent.DecalGridChunkCollection>? _ = default)
{ {
var dictionary = serializationManager.Read<Dictionary<Vector2i, Dictionary<uint, Decal>>>(node, context, skipHook: skipHook); var dictionary = serializationManager.Read<Dictionary<Vector2i, Dictionary<uint, Decal>>>(node, context, skipHook);
var uids = new SortedSet<uint>(); var uids = new SortedSet<uint>();
var uidChunkMap = new Dictionary<uint, Vector2i>(); var uidChunkMap = new Dictionary<uint, Vector2i>();
@@ -57,13 +59,5 @@ namespace Content.Shared.Decals
{ {
return serializationManager.WriteValue(value.ChunkCollection, alwaysWrite, context); return serializationManager.WriteValue(value.ChunkCollection, alwaysWrite, context);
} }
public DecalGridComponent.DecalGridChunkCollection Copy(ISerializationManager serializationManager, DecalGridComponent.DecalGridChunkCollection source,
DecalGridComponent.DecalGridChunkCollection target, bool skipHook, ISerializationContext? context = null)
{
var dict = target.ChunkCollection;
serializationManager.Copy(source.ChunkCollection, ref dict, context, skipHook);
return new DecalGridComponent.DecalGridChunkCollection(dict) {NextUid = source.NextUid};
}
} }
} }

View File

@@ -7,6 +7,7 @@ namespace Content.Shared.Decals
[DataField("chunkCollection", serverOnly: true)] [DataField("chunkCollection", serverOnly: true)]
public DecalGridChunkCollection ChunkCollection = new(new ()); public DecalGridChunkCollection ChunkCollection = new(new ());
[DataRecord]
public record DecalGridChunkCollection(Dictionary<Vector2i, Dictionary<uint, Decal>> ChunkCollection) public record DecalGridChunkCollection(Dictionary<Vector2i, Dictionary<uint, Decal>> ChunkCollection)
{ {
public uint NextUid; public uint NextUid;

View File

@@ -8,7 +8,7 @@ namespace Content.Shared.FixedPoint
/// Represents a quantity of something, to a precision of 0.01. /// Represents a quantity of something, to a precision of 0.01.
/// To enforce this level of precision, floats are shifted by 2 decimal points, rounded, and converted to an int. /// To enforce this level of precision, floats are shifted by 2 decimal points, rounded, and converted to an int.
/// </summary> /// </summary>
[Serializable] [Serializable, CopyByRef]
public struct FixedPoint2 : ISelfSerialize, IComparable<FixedPoint2>, IEquatable<FixedPoint2>, IFormattable public struct FixedPoint2 : ISelfSerialize, IComparable<FixedPoint2>, IEquatable<FixedPoint2>, IFormattable
{ {
private int _value; private int _value;

View File

@@ -1,8 +1,4 @@
using System.Linq;
using Content.Shared.Humanoid.Prototypes; using Content.Shared.Humanoid.Prototypes;
using Content.Shared.Preferences;
using Robust.Shared.Enums;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization; using Robust.Shared.Serialization;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
@@ -15,13 +11,13 @@ public abstract class SharedHumanoidComponent : Component
/// base humanoid to spawn, etc. /// base humanoid to spawn, etc.
/// </summary> /// </summary>
[DataField("species", customTypeSerializer: typeof(PrototypeIdSerializer<SpeciesPrototype>))] [DataField("species", customTypeSerializer: typeof(PrototypeIdSerializer<SpeciesPrototype>))]
public string Species { get; set; } = default!; public string Species { get; set; } = string.Empty;
/// <summary> /// <summary>
/// The initial profile and base layers to apply to this humanoid. /// The initial profile and base layers to apply to this humanoid.
/// </summary> /// </summary>
[DataField("initial", customTypeSerializer: typeof(PrototypeIdSerializer<HumanoidProfilePrototype>))] [DataField("initial", customTypeSerializer: typeof(PrototypeIdSerializer<HumanoidProfilePrototype>))]
public string Initial { get; } = default!; public string? Initial { get; }
/// <summary> /// <summary>
/// Skin color of this humanoid. /// Skin color of this humanoid.

View File

@@ -36,7 +36,6 @@
- Aria - Aria
- Bro - Bro
- Fox - Fox
- Null
- Samurai - Samurai
- Eater - Eater
- Ryu - Ryu

View File

@@ -1,7 +1,7 @@
- type: entity - type: entity
id: RandomSnacks id: RandomSnacks
name: random snack spawner name: random snack spawner
#suffix: #suffix: ""
parent: MarkerBase parent: MarkerBase
placement: placement:
mode: AlignTileAny mode: AlignTileAny

View File

@@ -2,7 +2,7 @@
name: space dragon name: space dragon
parent: SimpleSpaceMobBase parent: SimpleSpaceMobBase
id: MobDragon id: MobDragon
suffix: suffix: ""
description: A flying leviathan, loosely related to space carps. description: A flying leviathan, loosely related to space carps.
components: components:
- type: GhostTakeoverAvailable - type: GhostTakeoverAvailable

View File

@@ -103,7 +103,7 @@
- type: entity - type: entity
id: Poweredlight id: Poweredlight
description: "A light fixture. Draws power and produces light when equipped with a light tube." description: "A light fixture. Draws power and produces light when equipped with a light tube."
suffix: suffix: ""
parent: PoweredlightEmpty parent: PoweredlightEmpty
components: components:
- type: Sprite - type: Sprite
@@ -273,7 +273,7 @@
- type: entity - type: entity
id: PoweredSmallLight id: PoweredSmallLight
suffix: suffix: ""
parent: PoweredSmallLightEmpty parent: PoweredSmallLightEmpty
components: components:
- type: Sprite - type: Sprite
@@ -290,7 +290,7 @@
name: emergency light name: emergency light
description: A small light with an internal battery that turns on as soon as it stops receiving any power. Nanotrasen technology allows it to adapt its color to alert crew to the conditions of the station. description: A small light with an internal battery that turns on as soon as it stops receiving any power. Nanotrasen technology allows it to adapt its color to alert crew to the conditions of the station.
parent: AlwaysPoweredWallLight parent: AlwaysPoweredWallLight
suffix: suffix: ""
components: components:
- type: PointLight - type: PointLight
enabled: false enabled: false

View File

@@ -105,7 +105,7 @@
id: PoweredLightPostSmall id: PoweredLightPostSmall
name: post light name: post light
description: "A light fixture. Draws power and produces light when equipped with a light tube." description: "A light fixture. Draws power and produces light when equipped with a light tube."
suffix: suffix: ""
parent: PoweredLightPostSmallEmpty parent: PoweredLightPostSmallEmpty
components: components:
- type: Sprite - type: Sprite

View File

@@ -123,8 +123,6 @@
transmitFrequencyId: MailingUnit transmitFrequencyId: MailingUnit
- type: WiredNetworkConnection - type: WiredNetworkConnection
- type: Configuration - type: Configuration
config:
tag:
- type: Appearance - type: Appearance
visuals: visuals:
- type: DisposalUnitVisualizer - type: DisposalUnitVisualizer

View File

@@ -84,7 +84,7 @@
- type: entity - type: entity
id: GhostBox id: GhostBox
parent: StealthBox parent: StealthBox
suffix: suffix: ""
name: ghost box name: ghost box
description: Beware! description: Beware!
components: components:

View File

@@ -19,7 +19,6 @@
- type: startingGear - type: startingGear
id: AtmosphericTechnicianGear id: AtmosphericTechnicianGear
equipment: equipment:
head:
jumpsuit: ClothingUniformJumpsuitAtmos jumpsuit: ClothingUniformJumpsuitAtmos
back: ClothingBackpackEngineeringFilled back: ClothingBackpackEngineeringFilled
shoes: ClothingShoesColorWhite shoes: ClothingShoesColorWhite

View File

@@ -25,7 +25,6 @@
ears: ClothingHeadsetAltCommand ears: ClothingHeadsetAltCommand
belt: ClothingBeltSecurityWebbing belt: ClothingBeltSecurityWebbing
pocket1: Flare pocket1: Flare
pocket2:
- type: startingGear - type: startingGear
id: ERTLeaderGearEVA id: ERTLeaderGearEVA
@@ -42,7 +41,6 @@
ears: ClothingHeadsetAltCommand ears: ClothingHeadsetAltCommand
belt: ClothingBeltSecurityFilled belt: ClothingBeltSecurityFilled
pocket1: Flare pocket1: Flare
pocket2:
# Engineer # Engineer
- type: job - type: job
@@ -71,7 +69,6 @@
ears: ClothingHeadsetAltCommand ears: ClothingHeadsetAltCommand
belt: ClothingBeltChiefEngineerFilled belt: ClothingBeltChiefEngineerFilled
pocket1: Flare pocket1: Flare
pocket2:
- type: startingGear - type: startingGear
id: ERTEngineerGearEVA id: ERTEngineerGearEVA
@@ -116,7 +113,6 @@
ears: ClothingHeadsetAltCommand ears: ClothingHeadsetAltCommand
belt: ClothingBeltSecurityWebbing belt: ClothingBeltSecurityWebbing
pocket1: Flare pocket1: Flare
pocket2:
- type: startingGear - type: startingGear
id: ERTSecurityGearEVA id: ERTSecurityGearEVA
@@ -206,7 +202,6 @@
ears: ClothingHeadsetAltCommand ears: ClothingHeadsetAltCommand
belt: ClothingBeltJanitorFilled belt: ClothingBeltJanitorFilled
pocket1: Flare pocket1: Flare
pocket2:
- type: startingGear - type: startingGear
id: ERTJanitorGearEVA id: ERTJanitorGearEVA