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]
public sealed class CartridgeUiComponent : Component
{
[DataField("ui", true, customTypeSerializer: typeof(CartridgeUISerializer))]
[DataField("ui", true)]
public CartridgeUI? Ui = default;
}

View File

@@ -11,9 +11,10 @@ namespace Content.Client.Gravity
[DataField("spritemap")]
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
{
_spriteMap.Clear();
// Get Sprites for each status
foreach (var status in (GravityGeneratorStatus[]) Enum.GetValues(typeof(GravityGeneratorStatus)))
{

View File

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

View File

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

View File

@@ -18,16 +18,31 @@ namespace Content.IntegrationTests.Tests.Chemistry
[Test]
public void DeserializeNullTest()
{
var node = new ValueDataNode("null");
var node = ValueDataNode.Null();
var unit = Serialization.Read<FixedPoint2?>(node);
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]
public void DeserializeNullDefinitionTest()
{
var node = new MappingDataNode().Add("unit", "null");
var node = new MappingDataNode().Add("unit", ValueDataNode.Null());
var definition = Serialization.Read<FixedPoint2TestDefinition>(node);
Assert.That(definition.Unit, Is.Null);

View File

@@ -213,18 +213,14 @@ public sealed class PrototypeSaveTest
}
private sealed class TestEntityUidContext : ISerializationContext,
ITypeSerializer<EntityUid, ValueDataNode>,
ITypeReaderWriter<EntityUid, ValueDataNode>
ITypeSerializer<EntityUid, ValueDataNode>
{
public Dictionary<(Type, Type), object> TypeReaders { get; }
public Dictionary<Type, object> TypeWriters { get; }
public Dictionary<Type, object> TypeCopiers => TypeWriters;
public Dictionary<(Type, Type), object> TypeValidators => TypeReaders;
public SerializationManager.SerializerProvider SerializerProvider { get; }
public TestEntityUidContext()
{
TypeReaders = new() { { (typeof(EntityUid), typeof(ValueDataNode)), this } };
TypeWriters = new() { { typeof(EntityUid), this } };
SerializerProvider = new();
SerializerProvider.RegisterSerializer(this);
}
ValidationNode ITypeValidator<EntityUid, ValueDataNode>.Validate(ISerializationManager serializationManager,
@@ -245,16 +241,9 @@ public sealed class PrototypeSaveTest
ValueDataNode node,
IDependencyCollection dependencies,
bool skipHook,
ISerializationContext? context, EntityUid _)
ISerializationContext? context, ISerializationManager.InstantiationDelegate<EntityUid>? instanceProvider = null)
{
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;
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,
IDependencyCollection dependencies, ISerializationContext? context = null)
@@ -14,8 +14,10 @@ public sealed class TileAtmosCollectionSerializer : ITypeSerializer<Dictionary<V
return serializationManager.ValidateNode<TileAtmosData>(node, context);
}
public Dictionary<Vector2i, TileAtmosphere> Read(ISerializationManager serializationManager, MappingDataNode node, IDependencyCollection dependencies,
bool skipHook, ISerializationContext? context = null, Dictionary<Vector2i, TileAtmosphere>? value = default)
public Dictionary<Vector2i, TileAtmosphere> Read(ISerializationManager serializationManager, MappingDataNode node,
IDependencyCollection dependencies,
bool skipHook, ISerializationContext? context = null,
ISerializationManager.InstantiationDelegate<Dictionary<Vector2i, TileAtmosphere>>? instanceProvider = null)
{
var data = serializationManager.Read<TileAtmosData>(node, context, skipHook);
var tiles = new Dictionary<Vector2i, TileAtmosphere>();
@@ -72,13 +74,6 @@ public sealed class TileAtmosCollectionSerializer : ITypeSerializer<Dictionary<V
}, 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]
private struct TileAtmosData
{
@@ -86,4 +81,20 @@ public sealed class TileAtmosCollectionSerializer : ITypeSerializer<Dictionary<V
[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 Robust.Shared.Prototypes;
using Robust.Shared.Serialization.Manager;
using Robust.Shared.Serialization.Markdown;
using Robust.Shared.Serialization.Markdown.Mapping;
using Robust.Shared.Serialization.Markdown.Sequence;
using Robust.Shared.Serialization.Markdown.Validation;
@@ -36,7 +35,7 @@ public sealed class ContainerFillComponent : Component
// 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.
// 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();
@@ -61,35 +60,4 @@ public sealed class ContainerFillSerializer : ITypeSerializer<Dictionary<string,
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.Chat.Systems;
using Content.Server.Disease.Components;
@@ -21,7 +22,6 @@ using Robust.Shared.Prototypes;
using Robust.Shared.Random;
using Robust.Shared.Serialization.Manager;
using Robust.Shared.Utility;
using System.Threading;
namespace Content.Server.Disease
{
@@ -384,7 +384,7 @@ namespace Content.Server.Disease
return;
}
var freshDisease = _serializationManager.Copy(addedDisease);
var freshDisease = _serializationManager.CreateCopy(addedDisease);
if (freshDisease == null) return;

View File

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

View File

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

View File

@@ -1,43 +1,38 @@
using System.Linq;
using Content.Server.Administration.Commands;
using Content.Server.CharacterAppearance.Components;
using Content.Server.Chat.Managers;
using Content.Server.GameTicking.Rules.Components;
using Content.Server.GameTicking.Rules.Configurations;
using Content.Server.Ghost.Roles.Components;
using Content.Server.Ghost.Roles.Events;
using Content.Server.Humanoid.Systems;
using Content.Server.Mind.Components;
using Content.Server.NPC.Systems;
using Content.Server.Nuke;
using Content.Server.Preferences.Managers;
using Content.Server.RoundEnd;
using Content.Server.Shuttles.Components;
using Content.Server.Shuttles.Systems;
using Content.Server.Spawners.Components;
using Content.Server.Station.Components;
using Content.Server.Station.Systems;
using Content.Shared.MobState;
using Content.Server.Traitor;
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 Robust.Server.GameObjects;
using Robust.Server.Maps;
using Robust.Server.Player;
using Robust.Shared.Configuration;
using Robust.Shared.Map;
using Robust.Shared.Player;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
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;
@@ -846,7 +841,7 @@ public sealed class NukeopsRuleSystem : GameRuleSystem
var query = EntityQuery<NukeOperativeComponent, MindComponent>(true);
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);
}

View File

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

View File

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

View File

@@ -39,10 +39,12 @@ public sealed class HTNTaskListSerializer : ITypeSerializer<List<string>, Sequen
return new ValidatedSequenceNode(list);
}
public List<string> Read(ISerializationManager serializationManager, SequenceDataNode node, IDependencyCollection dependencies,
bool skipHook, ISerializationContext? context = null, List<string>? value = default)
public List<string> Read(ISerializationManager serializationManager, SequenceDataNode node,
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)
{
var mapping = (MappingDataNode) data;
@@ -72,15 +74,4 @@ public sealed class HTNTaskListSerializer : ITypeSerializer<List<string>, Sequen
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);
}
public NPCBlackboard Read(ISerializationManager serializationManager, MappingDataNode node, IDependencyCollection dependencies,
bool skipHook, ISerializationContext? context = null, NPCBlackboard? value = default)
public NPCBlackboard Read(ISerializationManager serializationManager, MappingDataNode node,
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)
{

View File

@@ -19,8 +19,14 @@ namespace Content.Server.NodeContainer
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)
{
node = t;

View File

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

View File

@@ -1,7 +1,7 @@
using Content.Shared.Radio;
using Content.Shared.Salvage;
using Robust.Shared.GameStates;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
using Content.Shared.Salvage;
namespace Content.Server.Salvage
{
@@ -66,6 +66,7 @@ namespace Content.Server.Salvage
public int PreviousCharge = 5;
}
[CopyByRef]
public record struct MagnetState(MagnetStateType StateType, TimeSpan Until)
{
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
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;
EntityManager.AddComponent(args.Mob, comp);
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -37,5 +37,5 @@ public sealed class ReactiveReagentEffectEntry
[DataField("groups", readOnly: true, serverOnly: true,
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,
IDependencyCollection dependencies,
bool skipHook,
ISerializationContext? context = null, ConstructionGraphStep? _ = null)
ISerializationContext? context = null,
ISerializationManager.InstantiationDelegate<ConstructionGraphStep>? instanceProvider = null)
{
var type = GetType(node) ??
throw new ArgumentException(

View File

@@ -43,7 +43,7 @@ namespace Content.Shared.Damage
/// <remarks>
/// If this data-field is specified, this allows damageable components to be initialized with non-zero damage.
/// </remarks>
[DataField("damage")]
[DataField("damage", readOnly: true)] //todo remove this readonly when implementing writing to damagespecifier
public DamageSpecifier Damage = new();
/// <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 Content.Shared.Damage.Prototypes;
using Content.Shared.FixedPoint;
using Robust.Shared.Prototypes;
using Robust.Shared.Utility;
namespace Content.Shared.Damage
{
@@ -18,31 +16,13 @@ namespace Content.Shared.Damage
[DataDefinition]
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>
/// Main DamageSpecifier dictionary. Most DamageSpecifier functions exist to somehow modifying this.
/// </summary>
[JsonIgnore]
[ViewVariables(VVAccess.ReadWrite)]
public Dictionary<string, FixedPoint2> DamageDict
{
get
{
if (_damageDict == null)
DeserializeDamage();
return _damageDict!;
}
set => _damageDict = value;
}
[JsonIgnore]
private Dictionary<string, FixedPoint2>? _damageDict;
[IncludeDataField(customTypeSerializer: typeof(DamageSpecifierDictionarySerializer), readOnly: true)]
public Dictionary<string, FixedPoint2> DamageDict { get; set; } = new();
/// <summary>
/// Sum of the damage values.
@@ -88,56 +68,19 @@ namespace Content.Shared.Damage
/// </summary>
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).
// We do this by reducing remaining the # of types and damage every loop.
var remainingTypes = group.DamageTypes.Count;
var remainingDamage = entry.Value;
var remainingDamage = value;
foreach (var damageType in group.DamageTypes)
{
var damage = remainingDamage / FixedPoint2.New(remainingTypes);
if (!_damageDict.TryAdd(damageType, damage))
{
// Key already exists, add values
_damageDict[damageType] += damage;
}
DamageDict.Add(damageType, damage);
remainingDamage -= damage;
remainingTypes -= 1;
}
}
}
#endregion constructors
/// <summary>
/// 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
/// to change/get/set damage in a <see cref="DamageableComponent"/>.
/// </remarks>
[Prototype("damageGroup")]
[Prototype("damageGroup", 2)]
[Serializable, NetSerializable]
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);
}
public DecalGridComponent.DecalGridChunkCollection Read(ISerializationManager serializationManager, MappingDataNode node,
IDependencyCollection dependencies, bool skipHook, ISerializationContext? context = null, DecalGridComponent.DecalGridChunkCollection? _ = null)
public DecalGridComponent.DecalGridChunkCollection Read(ISerializationManager serializationManager,
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 uidChunkMap = new Dictionary<uint, Vector2i>();
@@ -57,13 +59,5 @@ namespace Content.Shared.Decals
{
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)]
public DecalGridChunkCollection ChunkCollection = new(new ());
[DataRecord]
public record DecalGridChunkCollection(Dictionary<Vector2i, Dictionary<uint, Decal>> ChunkCollection)
{
public uint NextUid;

View File

@@ -8,7 +8,7 @@ namespace Content.Shared.FixedPoint
/// 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.
/// </summary>
[Serializable]
[Serializable, CopyByRef]
public struct FixedPoint2 : ISelfSerialize, IComparable<FixedPoint2>, IEquatable<FixedPoint2>, IFormattable
{
private int _value;

View File

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

View File

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

View File

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

View File

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

View File

@@ -103,7 +103,7 @@
- type: entity
id: Poweredlight
description: "A light fixture. Draws power and produces light when equipped with a light tube."
suffix:
suffix: ""
parent: PoweredlightEmpty
components:
- type: Sprite
@@ -273,7 +273,7 @@
- type: entity
id: PoweredSmallLight
suffix:
suffix: ""
parent: PoweredSmallLightEmpty
components:
- type: Sprite
@@ -290,7 +290,7 @@
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.
parent: AlwaysPoweredWallLight
suffix:
suffix: ""
components:
- type: PointLight
enabled: false

View File

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

View File

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

View File

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

View File

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

View File

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