Serialization v3 content PR (#3491)

* serv3 in shared pt 1

* beginning of deepclone api

* progress in implementing ideepclone & serv3 in content

* adds target

* its cant hurt you it cant hurt you

* more changes to content.server

* adds dataclasses

* almost there

* renamed & edited entry

* finishes refactoring content to use serv3

* gasmixture runtimes, next: reagentunit

* fucin hell that was an annoying one

* adds flags

* fixes some yaml errors

* removes comment

* fixes generic components for now

* removes todo
actually clones values my god paul
fixes bug involving resolving custom data classes from other proj
renames dataclass
fixes spritecomp
adds WithFormat.Constants support

* adds deepclone to ResistanceSet

* adds a bunch of deepclone implementations
adds a deepclone analyzer (TODO)
adds a deep clone fallback for classes & structs

* fixes a bunch of runtimes

* adds deepclone to entityuid

* adds generator to sln

* gets rid of warnings

* fixes

* argh

* componentdata refactors

* more deepclone impl

* heck me i reworked all of content deepclone

* renames custom dataclasstarget

* misc

* reworks prototypes

* deepclone nuke

* renamed customdataclass attribute

* fixes everything

* misc fixed

* the killcommit

* getting there

* changed yamlfieldattribute namespace

* adds back iselfserialize

* renames everything to data(field/definition)

* ouch

* Fix most errors on content

* Fix more errors in content

* Fix some components

* work on tests

* fixes some customdataclasses

* fuggin shit

* yes

* yeas

* Remove data classes

* Data field naming fixes

* arg

* Git resetti RobustToolbox

* Merge fixes

* General fixes

* Fix startup serialization errors

* Fix DamageContainerPrototype when supported classes or types are null

* Implement construction graph step type serializer

* Fix up construction serialization

* Fix up construction serialization part 2

* Fix null list in technology database component

* Fix body serialization

* Fix entity storage serialization

* Fix actions serialization

* Fix AI serialization

* Fix reaction serialization

* Fix body serialization

* Fix grid atmosphere serialization

* Rename IServ3Manager to ISerializationManager

* Convert every non generic serializer to the new format, general fixes

* Serialization and body system fix

* pushinheritance fix

* Update all prototypes to have a parent and have consistent id/parent properties

* Merge fixes

* smh my head

* cuddling slaps

* Content commit for engine PR

* stuff

* more fixes

* argh

* yes even you are fixed

* changelog fixes

* fixes seeds

* argh

* Test fixes

* Add writing for alert order prototype

* Fix alert order writing

* FIX

* its been alot ok

* Fix the rest of the visualizers

* Fix server alerts component tests

* Fix alert prototype tests not using the read value

* Fix alert prototype tests initializing serialization multiple times

* THIS IS AN AMERICAN CODEBASE GOD BLESS THE USA

* Add ImplicitDataDefinitionForInheritors to IMechanismBehavior
Fixes the behaviors not being found

* Fix NRE in strap component
Good night to the 1 buckle optimization

* Fix clothing component slot flags serialization tag

* Fix body component in all components test

* Merge fixes

* ffs

* Make construction graph prototype use serialization hooks

* human yaml linted

* a

* Do the thing for construction

* stuff

* a

* monke see yaml linter

* LINT HARDER

* Remove redundant todo

* yes

* Add skip hook argument to readers and copiers

* we gamin

* test/datafield fixes

* adds more verbose validation

* moves linter to action

* Improve construction graph step type serializer error message

* Fix ammo box component NRE

* gamin

* some updates to the linter

* yes

* removes that test

* misc fixes

* array fix
priority fix
misc fixes

* adds proper info the validation

* adds alwaysrelevant usa

* Make yaml linter take half as long to run (~50% less)

* Make yaml linter 5 times faster (~80% less execution time)

* based vera being based

* fixes mapsaving

* warning cleanup & moves surpressor

* removes old msbuild targets

* Revert "Make yaml linter 5 times faster (~80% less execution time)"

This reverts commit 3e6091359a26252c3e98828199553de668031c63.

* Add -nowarn to yaml linter run configuration

* Improve yaml linter message feedback

* Make dependencies an argument instead of a property on the serialization manager

* yamllinting slaps

* Clean up type serializers

* Move yaml linter code to its own method

* Fix yaml errors

* Change yaml linter action name and remove -nowarn

* yaml linter please shut

* Git resetti robust toolbox

Co-authored-by: Paul <ritter.paul1+git@googlemail.com>
Co-authored-by: DrSmugleaf <DrSmugleaf@users.noreply.github.com>
This commit is contained in:
Paul Ritter
2021-03-05 01:08:38 +01:00
committed by GitHub
parent 05d4d9692c
commit 5c50b1f6ed
545 changed files with 4547 additions and 6650 deletions

View File

@@ -2,14 +2,15 @@
using Content.Shared.GameObjects.Components.Body.Mechanism;
using Content.Shared.GameObjects.Components.Body.Part;
using Robust.Shared.GameObjects;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.Manager.Attributes;
namespace Content.Shared.GameObjects.Components.Body.Behavior
{
/// <summary>
/// Gives functionality to a <see cref="IMechanism"/> when added to it.
/// </summary>
public interface IMechanismBehavior : IExposeData
[ImplicitDataDefinitionForInheritors]
public interface IMechanismBehavior
{
/// <summary>
/// The body that owns the <see cref="IBodyPart"/> in which the

View File

@@ -4,16 +4,16 @@ using System.Collections.Generic;
using System.Linq;
using Content.Shared.GameObjects.Components.Body.Behavior;
using Content.Shared.GameObjects.Components.Body.Part;
using Content.Shared.Interfaces;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Log;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.Utility;
namespace Content.Shared.GameObjects.Components.Body.Mechanism
{
public abstract class SharedMechanismComponent : Component, IMechanism
public abstract class SharedMechanismComponent : Component, IMechanism, ISerializationHooks
{
public override string Name => "Mechanism";
@@ -22,6 +22,9 @@ namespace Content.Shared.GameObjects.Components.Body.Mechanism
protected int IdHash;
protected IEntity? PerformerCache;
private IBodyPart? _part;
[DataField("behaviors", serverOnly: true)] private HashSet<IMechanismBehavior> _behaviorTypes = new();
private readonly Dictionary<Type, IMechanismBehavior> _behaviors = new();
public IBody? Body => Part?.Body;
@@ -67,65 +70,40 @@ namespace Content.Shared.GameObjects.Components.Body.Mechanism
public IReadOnlyDictionary<Type, IMechanismBehavior> Behaviors => _behaviors;
public int MaxDurability { get; set; }
[DataField("maxDurability")] public int MaxDurability { get; set; } = 10;
public int CurrentDurability { get; set; }
[DataField("currentDurability")] public int CurrentDurability { get; set; } = 10;
public int DestroyThreshold { get; set; }
[DataField("destroyThreshold")] public int DestroyThreshold { get; set; } = -10;
// TODO BODY: Surgery description and adding a message to the examine tooltip of the entity that owns this mechanism
// TODO BODY
public int Resistance { get; set; }
[DataField("resistance")] public int Resistance { get; set; } = 0;
// TODO BODY OnSizeChanged
public int Size { get; set; }
[DataField("size")] public int Size { get; set; } = 1;
public BodyPartCompatibility Compatibility { get; set; }
[DataField("compatibility")]
public BodyPartCompatibility Compatibility { get; set; } = BodyPartCompatibility.Universal;
public override void ExposeData(ObjectSerializer serializer)
void ISerializationHooks.BeforeSerialization()
{
base.ExposeData(serializer);
_behaviorTypes = _behaviors.Values.ToHashSet();
}
serializer.DataField(this, m => m.MaxDurability, "maxDurability", 10);
serializer.DataField(this, m => m.CurrentDurability, "currentDurability", MaxDurability);
serializer.DataField(this, m => m.DestroyThreshold, "destroyThreshold", -MaxDurability);
serializer.DataField(this, m => m.Resistance, "resistance", 0);
serializer.DataField(this, m => m.Size, "size", 1);
serializer.DataField(this, m => m.Compatibility, "compatibility", BodyPartCompatibility.Universal);
var moduleManager = IoCManager.Resolve<IModuleManager>();
if (moduleManager.IsServerModule)
void ISerializationHooks.AfterDeserialization()
{
foreach (var behavior in _behaviorTypes)
{
serializer.DataReadWriteFunction(
"behaviors",
null!,
behaviors =>
{
if (behaviors == null)
{
return;
}
var type = behavior.GetType();
foreach (var behavior in behaviors)
{
var type = behavior.GetType();
if (!_behaviors.TryAdd(type, behavior))
{
Logger.Warning($"Duplicate behavior in {nameof(SharedMechanismComponent)}: {type}.");
continue;
}
if (!_behaviors.TryAdd(type, behavior))
{
Logger.Warning($"Duplicate behavior in {nameof(SharedMechanismComponent)} for entity {Owner.Name}: {type}.");
continue;
}
IoCManager.InjectDependencies(behavior);
}
},
() => _behaviors.Values.ToList());
IoCManager.InjectDependencies(behavior);
}
}

View File

@@ -1,6 +1,6 @@
#nullable enable
#nullable enable
using Robust.Shared.GameObjects;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.Manager.Attributes;
namespace Content.Shared.GameObjects.Components.Body.Part.Property
{
@@ -15,13 +15,7 @@ namespace Content.Shared.GameObjects.Components.Body.Part.Property
/// <summary>
/// Whether this property is currently active.
/// </summary>
public bool Active { get; set; }
public override void ExposeData(ObjectSerializer serializer)
{
base.ExposeData(serializer);
serializer.DataField(this, b => b.Active, "active", true);
}
[DataField("active")]
public bool Active { get; set; } = true;
}
}

View File

@@ -1,6 +1,6 @@
#nullable enable
#nullable enable
using Robust.Shared.GameObjects;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.Manager.Attributes;
namespace Content.Shared.GameObjects.Components.Body.Part.Property
{
@@ -15,13 +15,7 @@ namespace Content.Shared.GameObjects.Components.Body.Part.Property
/// <summary>
/// Current distance in tiles.
/// </summary>
public float Distance { get; set; }
public override void ExposeData(ObjectSerializer serializer)
{
base.ExposeData(serializer);
serializer.DataField(this, e => e.Distance, "distance", 3f);
}
[DataField("distance")]
public float Distance { get; set; } = 3f;
}
}

View File

@@ -1,6 +1,6 @@
#nullable enable
#nullable enable
using Robust.Shared.GameObjects;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.Manager.Attributes;
namespace Content.Shared.GameObjects.Components.Body.Part.Property
{
@@ -15,13 +15,7 @@ namespace Content.Shared.GameObjects.Components.Body.Part.Property
/// <summary>
/// Speed in tiles per second.
/// </summary>
public float Speed { get; set; }
public override void ExposeData(ObjectSerializer serializer)
{
base.ExposeData(serializer);
serializer.DataField(this, l => l.Speed, "speed", 2.6f);
}
[DataField("speed")]
public float Speed { get; set; } = 2.6f;
}
}

View File

@@ -9,6 +9,7 @@ using Robust.Shared.IoC;
using Robust.Shared.Map;
using Robust.Shared.Players;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.Utility;
using Robust.Shared.ViewVariables;
@@ -23,6 +24,7 @@ namespace Content.Shared.GameObjects.Components.Body.Part
private IBody? _body;
// TODO BODY Remove
[DataField("mechanisms")]
private List<string> _mechanismIds = new();
public IReadOnlyList<string> MechanismIds => _mechanismIds;
@@ -55,8 +57,11 @@ namespace Content.Shared.GameObjects.Components.Body.Part
}
}
[ViewVariables] public BodyPartType PartType { get; private set; }
[ViewVariables] public int Size { get; private set; }
[ViewVariables]
[DataField("partType")]
public BodyPartType PartType { get; private set; } = BodyPartType.Other;
[ViewVariables] [DataField("size")] public int Size { get; private set; } = 1;
[ViewVariables] public int SizeUsed { get; private set; }
@@ -69,7 +74,8 @@ namespace Content.Shared.GameObjects.Components.Body.Part
/// attach between types.
/// </summary>
[ViewVariables]
public BodyPartCompatibility Compatibility { get; private set; }
[DataField("compatibility")]
public BodyPartCompatibility Compatibility { get; private set; } = BodyPartCompatibility.Universal;
/// <summary>
/// Set of all <see cref="IMechanism"/> currently inside this
@@ -84,10 +90,12 @@ namespace Content.Shared.GameObjects.Components.Body.Part
/// If the last vital body part is removed creature dies
/// </summary>
[ViewVariables]
public bool IsVital { get; private set; }
[DataField("vital")]
public bool IsVital { get; private set; } = false;
[ViewVariables]
public BodyPartSymmetry Symmetry { get; private set; }
[DataField("symmetry")]
public BodyPartSymmetry Symmetry { get; private set; } = BodyPartSymmetry.None;
[ViewVariables]
public ISurgeryData? SurgeryDataComponent => Owner.GetComponentOrNull<ISurgeryData>();
@@ -116,25 +124,6 @@ namespace Content.Shared.GameObjects.Components.Body.Part
Dirty();
}
public override void ExposeData(ObjectSerializer serializer)
{
base.ExposeData(serializer);
// TODO BODY serialize any changed properties?
serializer.DataField(this, b => b.PartType, "partType", BodyPartType.Other);
serializer.DataField(this, b => b.Size, "size", 1);
serializer.DataField(this, b => b.Compatibility, "compatibility", BodyPartCompatibility.Universal);
serializer.DataField(this, b => b.IsVital, "vital", false);
serializer.DataField(this, b => b.Symmetry, "symmetry", BodyPartSymmetry.None);
serializer.DataField(ref _mechanismIds, "mechanisms", new List<string>());
}
public override ComponentState GetComponentState(ICommonSession player)
{
var mechanismIds = new EntityUid[_mechanisms.Count];

View File

@@ -4,8 +4,8 @@ using System.Collections.Generic;
using Content.Shared.GameObjects.Components.Body.Part;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.ViewVariables;
using YamlDotNet.RepresentationModel;
namespace Content.Shared.GameObjects.Components.Body.Preset
{
@@ -16,22 +16,21 @@ namespace Content.Shared.GameObjects.Components.Body.Preset
[Serializable, NetSerializable]
public class BodyPresetPrototype : IPrototype
{
private string _id = string.Empty;
private string _name = string.Empty;
[ViewVariables]
[field: DataField("id", required: true)]
public string ID { get; } = default!;
[ViewVariables]
[field: DataField("parent")]
public string? Parent { get; }
[DataField("partIDs")]
private Dictionary<string, string> _partIDs = new();
[ViewVariables] public string ID => _id;
[ViewVariables] public string Name => _name;
[ViewVariables]
[field: DataField("name")]
public string Name { get; } = string.Empty;
[ViewVariables] public Dictionary<string, string> PartIDs => new(_partIDs);
public virtual void LoadFrom(YamlMappingNode mapping)
{
var serializer = YamlObjectSerializer.NewReader(mapping);
serializer.DataField(ref _id, "id", string.Empty);
serializer.DataField(ref _name, "name", string.Empty);
serializer.DataField(ref _partIDs, "partIDs", new Dictionary<string, string>());
}
}
}

View File

@@ -16,13 +16,14 @@ using Robust.Shared.IoC;
using Robust.Shared.Players;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.Utility;
using Robust.Shared.ViewVariables;
namespace Content.Shared.GameObjects.Components.Body
{
// TODO BODY Damage methods for collections of IDamageableComponents
public abstract class SharedBodyComponent : Component, IBody
public abstract class SharedBodyComponent : Component, IBody, ISerializationHooks
{
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
@@ -30,15 +31,20 @@ namespace Content.Shared.GameObjects.Components.Body
public override uint? NetID => ContentNetIDs.BODY;
[DataField("centerSlot", required: true)]
private string? _centerSlot;
private Dictionary<string, string> _partIds = new();
private readonly Dictionary<string, IBodyPart> _parts = new();
[ViewVariables] public string? TemplateName { get; private set; }
[ViewVariables]
[DataField("template", required: true)]
public string? TemplateName { get; private set; }
[ViewVariables] public string? PresetName { get; private set; }
[ViewVariables]
[DataField("preset", required: true)]
public string? PresetName { get; private set; }
[ViewVariables]
public Dictionary<string, BodyPartType> Slots { get; private set; } = new();
@@ -56,6 +62,62 @@ namespace Content.Shared.GameObjects.Components.Body
[ViewVariables] public IReadOnlyDictionary<string, string> PartIDs => _partIds;
public override void Initialize()
{
base.Initialize();
// TODO BODY BeforeDeserialization
// TODO BODY Move to template or somewhere else
if (TemplateName != null)
{
var template = _prototypeManager.Index<BodyTemplatePrototype>(TemplateName);
Connections = template.Connections;
Slots = template.Slots;
_centerSlot = template.CenterSlot;
}
if (PresetName != null)
{
var preset = _prototypeManager.Index<BodyPresetPrototype>(PresetName);
_partIds = preset.PartIDs;
}
// Our prototypes don't force the user to define a BodyPart connection twice. E.g. Head: Torso v.s. Torso: Head.
// The user only has to do one. We want it to be that way in the code, though, so this cleans that up.
var cleanedConnections = new Dictionary<string, List<string>>();
foreach (var targetSlotName in Slots.Keys)
{
var tempConnections = new List<string>();
foreach (var (slotName, slotConnections) in Connections)
{
if (slotName == targetSlotName)
{
foreach (var connection in slotConnections)
{
if (!tempConnections.Contains(connection))
{
tempConnections.Add(connection);
}
}
}
else if (slotConnections.Contains(targetSlotName))
{
tempConnections.Add(slotName);
}
}
if (tempConnections.Count > 0)
{
cleanedConnections.Add(targetSlotName, tempConnections);
}
}
Connections = cleanedConnections;
}
protected virtual bool CanAddPart(string slot, IBodyPart part)
{
if (!HasSlot(slot) || !_parts.TryAdd(slot, part))
@@ -537,122 +599,6 @@ namespace Content.Shared.GameObjects.Components.Body
return Parts.ElementAt(index);
}
public override void ExposeData(ObjectSerializer serializer)
{
base.ExposeData(serializer);
serializer.DataReadWriteFunction(
"template",
null,
name =>
{
if (string.IsNullOrEmpty(name))
{
return;
}
var template = _prototypeManager.Index<BodyTemplatePrototype>(name);
Connections = template.Connections;
Slots = template.Slots;
_centerSlot = template.CenterSlot;
TemplateName = name;
},
() => TemplateName);
serializer.DataReadWriteFunction(
"preset",
null,
name =>
{
if (string.IsNullOrEmpty(name))
{
return;
}
var preset = _prototypeManager.Index<BodyPresetPrototype>(name);
_partIds = preset.PartIDs;
},
() => PresetName);
serializer.DataReadWriteFunction(
"connections",
new Dictionary<string, List<string>>(),
connections =>
{
foreach (var (from, to) in connections)
{
Connections.GetOrNew(from).AddRange(to);
}
},
() => Connections);
serializer.DataReadWriteFunction(
"slots",
new Dictionary<string, BodyPartType>(),
slots =>
{
foreach (var (part, type) in slots)
{
Slots[part] = type;
}
},
() => Slots);
// TODO BODY Move to template or somewhere else
serializer.DataReadWriteFunction(
"centerSlot",
null,
slot => _centerSlot = slot,
() => _centerSlot);
serializer.DataReadWriteFunction(
"partIds",
new Dictionary<string, string>(),
partIds =>
{
foreach (var (slot, part) in partIds)
{
_partIds[slot] = part;
}
},
() => _partIds);
// Our prototypes don't force the user to define a BodyPart connection twice. E.g. Head: Torso v.s. Torso: Head.
// The user only has to do one. We want it to be that way in the code, though, so this cleans that up.
var cleanedConnections = new Dictionary<string, List<string>>();
foreach (var targetSlotName in Slots.Keys)
{
var tempConnections = new List<string>();
foreach (var (slotName, slotConnections) in Connections)
{
if (slotName == targetSlotName)
{
foreach (var connection in slotConnections)
{
if (!tempConnections.Contains(connection))
{
tempConnections.Add(connection);
}
}
}
else if (slotConnections.Contains(targetSlotName))
{
tempConnections.Add(slotName);
}
}
if (tempConnections.Count > 0)
{
cleanedConnections.Add(targetSlotName, tempConnections);
}
}
Connections = cleanedConnections;
}
public override ComponentState GetComponentState(ICommonSession player)
{
var parts = new (string slot, EntityUid partId)[_parts.Count];

View File

@@ -1,12 +1,11 @@
#nullable enable
using System;
using System.Collections.Generic;
using System.Linq;
using Content.Shared.GameObjects.Components.Body.Part;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.ViewVariables;
using YamlDotNet.RepresentationModel;
namespace Content.Shared.GameObjects.Components.Body.Template
{
@@ -15,50 +14,58 @@ namespace Content.Shared.GameObjects.Components.Body.Template
/// </summary>
[Prototype("bodyTemplate")]
[Serializable, NetSerializable]
public class BodyTemplatePrototype : IPrototype
public class BodyTemplatePrototype : IPrototype, ISerializationHooks
{
private string _id = string.Empty;
private string _name = string.Empty;
private string _centerSlot = string.Empty;
[DataField("slots")]
private Dictionary<string, BodyPartType> _slots = new();
private Dictionary<string, List<string>> _connections = new();
[DataField("connections")]
private Dictionary<string, List<string>> _rawConnections = new();
[DataField("layers")]
private Dictionary<string, string> _layers = new();
[DataField("mechanismLayers")]
private Dictionary<string, string> _mechanismLayers = new();
[ViewVariables] public string ID => _id;
[ViewVariables] public string Name => _name;
[ViewVariables] public string CenterSlot => _centerSlot;
[ViewVariables] public Dictionary<string, BodyPartType> Slots => new(_slots);
[ViewVariables]
[field: DataField("id", required: true)]
public string ID { get; } = default!;
[ViewVariables]
public Dictionary<string, List<string>> Connections =>
_connections.ToDictionary(x => x.Key, x => x.Value.ToList());
[field: DataField("parent")]
public string? Parent { get; }
[ViewVariables] public Dictionary<string, string> Layers => new(_layers);
[ViewVariables]
[field: DataField("name")]
public string Name { get; } = string.Empty;
[ViewVariables] public Dictionary<string, string> MechanismLayers => new(_mechanismLayers);
[ViewVariables]
[field: DataField("centerSlot")]
public string CenterSlot { get; } = string.Empty;
public virtual void LoadFrom(YamlMappingNode mapping)
[ViewVariables]
public Dictionary<string, BodyPartType> Slots => new(_slots);
[ViewVariables]
public Dictionary<string, List<string>> Connections { get; set; } = new();
[ViewVariables]
public Dictionary<string, string> Layers => new(_layers);
[ViewVariables]
public Dictionary<string, string> MechanismLayers => new(_mechanismLayers);
void ISerializationHooks.AfterDeserialization()
{
var serializer = YamlObjectSerializer.NewReader(mapping);
serializer.DataField(ref _id, "id", string.Empty);
serializer.DataField(ref _name, "name", string.Empty);
serializer.DataField(ref _centerSlot, "centerSlot", string.Empty);
serializer.DataField(ref _slots, "slots", new Dictionary<string, BodyPartType>());
serializer.DataField(ref _connections, "connections", new Dictionary<string, List<string>>());
serializer.DataField(ref _layers, "layers", new Dictionary<string, string>());
serializer.DataField(ref _mechanismLayers, "mechanismLayers", new Dictionary<string, string>());
//Our prototypes don't force the user to define a BodyPart connection twice. E.g. Head: Torso v.s. Torso: Head.
//The user only has to do one. We want it to be that way in the code, though, so this cleans that up.
var cleanedConnections = new Dictionary<string, List<string>>();
foreach (var targetSlotName in _slots.Keys)
{
var tempConnections = new List<string>();
foreach (var (slotName, slotConnections) in _connections)
foreach (var (slotName, slotConnections) in _rawConnections)
{
if (slotName == targetSlotName)
{
@@ -82,7 +89,7 @@ namespace Content.Shared.GameObjects.Components.Body.Template
}
}
_connections = cleanedConnections;
Connections = cleanedConnections;
}
}
}

View File

@@ -8,6 +8,7 @@ using Content.Shared.Interfaces.GameObjects.Components;
using Robust.Shared.GameObjects;
using Robust.Shared.Physics;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.ViewVariables;
namespace Content.Shared.GameObjects.Components.Buckle
@@ -24,14 +25,8 @@ namespace Content.Shared.GameObjects.Components.Buckle
/// The range from which this entity can buckle to a <see cref="SharedStrapComponent"/>.
/// </summary>
[ViewVariables]
public float Range { get; protected set; }
public override void ExposeData(ObjectSerializer serializer)
{
base.ExposeData(serializer);
serializer.DataField(this, x => x.Range, "range", SharedInteractionSystem.InteractionRange / 1.4f);
}
[DataField("range")]
public float Range { get; protected set; } = SharedInteractionSystem.InteractionRange / 1.4f;
/// <summary>
/// True if the entity is buckled, false otherwise.

View File

@@ -7,21 +7,52 @@ using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.Manager.Attributes;
namespace Content.Shared.GameObjects.Components.Cargo
{
public class SharedGalacticMarketComponent : Component, IEnumerable<CargoProductPrototype>
public class SharedGalacticMarketComponent : Component, IEnumerable<CargoProductPrototype>, ISerializationHooks
{
public sealed override string Name => "GalacticMarket";
public sealed override uint? NetID => ContentNetIDs.GALACTIC_MARKET;
protected List<CargoProductPrototype> _products = new();
[DataField("products")]
protected List<string> _productIds = new();
protected readonly List<CargoProductPrototype> _products = new();
/// <summary>
/// A read-only list of products.
/// </summary>
public IReadOnlyList<CargoProductPrototype> Products => _products;
void ISerializationHooks.AfterDeserialization()
{
var prototypeManager = IoCManager.Resolve<IPrototypeManager>();
_productIds.Clear();
foreach (var id in _productIds)
{
if (!prototypeManager.TryIndex(id, out CargoProductPrototype? product))
{
continue;
}
_products.Add(product);
}
}
void ISerializationHooks.BeforeSerialization()
{
_productIds = new List<string>();
foreach (var product in _products)
{
_productIds.Add(product.ID);
}
}
public IEnumerator<CargoProductPrototype> GetEnumerator()
{
return _products.GetEnumerator();
@@ -52,7 +83,7 @@ namespace Content.Shared.GameObjects.Components.Cargo
/// <returns>A list of product IDs</returns>
public List<string> GetProductIdList()
{
List<string> productIds = new List<string>();
var productIds = new List<string>();
foreach (var product in _products)
{
@@ -61,31 +92,6 @@ namespace Content.Shared.GameObjects.Components.Cargo
return productIds;
}
public override void ExposeData(ObjectSerializer serializer)
{
base.ExposeData(serializer);
serializer.DataReadWriteFunction(
"products",
new List<string>(),
products =>
{
var prototypeManager = IoCManager.Resolve<IPrototypeManager>();
_products.Clear();
foreach (var id in products)
{
if (!prototypeManager.TryIndex(id, out CargoProductPrototype? product))
{
continue;
}
_products.Add(product);
}
},
GetProductIdList);
}
}
[Serializable, NetSerializable]

View File

@@ -3,7 +3,8 @@ using System;
using System.Collections.Generic;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
using YamlDotNet.RepresentationModel;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.ViewVariables;
namespace Content.Shared.GameObjects.Components.Chemistry.ReagentDispenser
{
@@ -16,18 +17,17 @@ namespace Content.Shared.GameObjects.Components.Chemistry.ReagentDispenser
[Serializable, NetSerializable, Prototype("reagentDispenserInventory")]
public class ReagentDispenserInventoryPrototype : IPrototype
{
private string _id = string.Empty;
[DataField("inventory")]
private List<string> _inventory = new();
public string ID => _id;
[ViewVariables]
[field: DataField("id", required: true)]
public string ID { get; } = default!;
[ViewVariables]
[field: DataField("parent")]
public string? Parent { get; }
public List<string> Inventory => _inventory;
public void LoadFrom(YamlMappingNode mapping)
{
var serializer = YamlObjectSerializer.NewReader(mapping);
serializer.DataField(ref _id, "id", string.Empty);
serializer.DataField(ref _inventory, "inventory", new List<string>());
}
}
}

View File

@@ -11,6 +11,7 @@ using Robust.Shared.Maths;
using Robust.Shared.Players;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.Utility;
using Robust.Shared.ViewVariables;
@@ -27,12 +28,14 @@ namespace Content.Shared.GameObjects.Components.Chemistry
public sealed override uint? NetID => ContentNetIDs.SOLUTION;
[ViewVariables]
[DataField("contents")]
public Solution Solution { get; private set; } = new();
public IReadOnlyList<Solution.ReagentQuantity> ReagentList => Solution.Contents;
[ViewVariables(VVAccess.ReadWrite)]
public ReagentUnit MaxVolume { get; set; }
[DataField("maxVol")]
public ReagentUnit MaxVolume { get; set; } = ReagentUnit.Zero;
[ViewVariables]
public ReagentUnit CurrentVolume => Solution.TotalVolume;
@@ -50,9 +53,11 @@ namespace Content.Shared.GameObjects.Components.Chemistry
/// If reactions will be checked for when adding reagents to the container.
/// </summary>
[ViewVariables(VVAccess.ReadWrite)]
public bool CanReact { get; set; }
[DataField("canReact")]
public bool CanReact { get; set; } = true;
[ViewVariables(VVAccess.ReadWrite)]
[DataField("caps")]
public SolutionContainerCaps Capabilities { get; set; }
public bool CanExamineContents => Capabilities.HasCap(SolutionContainerCaps.CanExamine);
@@ -65,17 +70,6 @@ namespace Content.Shared.GameObjects.Components.Chemistry
public bool CanRefill => Capabilities.HasCap(SolutionContainerCaps.Refillable);
public bool CanDrain => Capabilities.HasCap(SolutionContainerCaps.Drainable);
public override void ExposeData(ObjectSerializer serializer)
{
base.ExposeData(serializer);
serializer.DataField(this, x => x.CanReact, "canReact", true);
serializer.DataField(this, x => x.MaxVolume, "maxVol", ReagentUnit.New(0));
serializer.DataField(this, x => x.Solution, "contents", new Solution());
serializer.DataField(this, x => x.Capabilities, "caps", SolutionContainerCaps.None);
serializer.DataField(this, x => x.MaxSpillRefill, "maxSpillRefill", MaxVolume / ReagentUnit.New(4));
}
public void RemoveAllSolution()
{
if (CurrentVolume == 0)
@@ -215,6 +209,8 @@ namespace Content.Shared.GameObjects.Components.Chemistry
ReagentUnit ISolutionInteractionsComponent.InjectSpaceAvailable => EmptyVolume;
ReagentUnit ISolutionInteractionsComponent.DrawAvailable => CurrentVolume;
ReagentUnit ISolutionInteractionsComponent.DrainAvailable => CurrentVolume;
[DataField("maxSpillRefill")]
public ReagentUnit MaxSpillRefill { get; set; }
void ISolutionInteractionsComponent.Refill(Solution solution)

View File

@@ -12,6 +12,7 @@ using Robust.Shared.IoC;
using Robust.Shared.Players;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.ViewVariables;
namespace Content.Shared.GameObjects.Components.Damage
@@ -22,27 +23,31 @@ namespace Content.Shared.GameObjects.Components.Damage
/// </summary>
[RegisterComponent]
[ComponentReference(typeof(IDamageableComponent))]
public class DamageableComponent : Component, IDamageableComponent, IRadiationAct
public class DamageableComponent : Component, IDamageableComponent, IRadiationAct, ISerializationHooks
{
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
// TODO define these in yaml?
public const string DefaultDamageContainer = "metallicDamageContainer";
public const string DefaultResistanceSet = "defaultResistances";
public override string Name => "Damageable";
public override uint? NetID => ContentNetIDs.DAMAGEABLE;
// TODO define these in yaml?
public const string DefaultResistanceSet = "defaultResistances";
public const string DefaultDamageContainer = "metallicDamageContainer";
private readonly Dictionary<DamageType, int> _damageList = DamageTypeExtensions.ToNewDictionary();
private readonly HashSet<DamageType> _supportedTypes = new();
private readonly HashSet<DamageClass> _supportedClasses = new();
[DataField("flags")]
private DamageFlag _flags;
// TODO DAMAGE Use as default values, specify overrides in a separate property through yaml for better (de)serialization
[ViewVariables] public string DamageContainerId { get; set; } = default!;
[DataField("resistances")] public string ResistanceSetId = DefaultResistanceSet;
[ViewVariables] private ResistanceSet Resistances { get; set; } = default!;
// TODO DAMAGE Use as default values, specify overrides in a separate property through yaml for better (de)serialization
[ViewVariables] [DataField("damageContainer")] public string DamageContainerId { get; set; } = DefaultDamageContainer;
[ViewVariables] private ResistanceSet Resistances { get; set; } = new();
// TODO DAMAGE Cache this
[ViewVariables] public int TotalDamage => _damageList.Values.Sum();
@@ -93,70 +98,24 @@ namespace Content.Shared.GameObjects.Components.Damage
return _supportedTypes.Contains(type);
}
public override void ExposeData(ObjectSerializer serializer)
public override void Initialize()
{
base.ExposeData(serializer);
base.Initialize();
serializer.DataReadWriteFunction(
"flags",
new List<DamageFlag>(),
flags =>
{
var result = DamageFlag.None;
foreach (var flag in flags)
{
result |= flag;
}
Flags = result;
},
() =>
{
var writeFlags = new List<DamageFlag>();
if (Flags == DamageFlag.None)
{
return writeFlags;
}
foreach (var flag in (DamageFlag[]) Enum.GetValues(typeof(DamageFlag)))
{
if ((Flags & flag) == flag)
{
writeFlags.Add(flag);
}
}
return writeFlags;
});
var prototypeManager = IoCManager.Resolve<IPrototypeManager>();
// TODO DAMAGE Serialize damage done and resistance changes
serializer.DataReadWriteFunction(
"damageContainer",
DefaultDamageContainer,
prototype =>
{
var damagePrototype = _prototypeManager.Index<DamageContainerPrototype>(prototype);
var damagePrototype = prototypeManager.Index<DamageContainerPrototype>(DamageContainerId);
_supportedClasses.Clear();
_supportedTypes.Clear();
_supportedClasses.Clear();
_supportedTypes.Clear();
DamageContainerId = damagePrototype.ID;
_supportedClasses.UnionWith(damagePrototype.SupportedClasses);
_supportedTypes.UnionWith(damagePrototype.SupportedTypes);
},
() => DamageContainerId);
DamageContainerId = damagePrototype.ID;
_supportedClasses.UnionWith(damagePrototype.SupportedClasses);
_supportedTypes.UnionWith(damagePrototype.SupportedTypes);
serializer.DataReadWriteFunction(
"resistances",
DefaultResistanceSet,
prototype =>
{
var resistancePrototype = _prototypeManager.Index<ResistanceSetPrototype>(prototype);
Resistances = new ResistanceSet(resistancePrototype);
},
() => Resistances.ID);
var resistancePrototype = prototypeManager.Index<ResistanceSetPrototype>(ResistanceSetId);
Resistances = new ResistanceSet(resistancePrototype);
}
protected override void Startup()

View File

@@ -1,12 +1,13 @@
#nullable enable
using System;
using System.Collections.Generic;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Serialization;
using Robust.Shared.ViewVariables;
using Robust.Shared.Physics;
using System.Collections.Generic;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.Timing;
using Robust.Shared.ViewVariables;
namespace Content.Shared.GameObjects.Components.Doors
{
@@ -52,19 +53,27 @@ namespace Content.Shared.GameObjects.Components.Doors
/// <summary>
/// Closing time until impassable.
/// </summary>
protected TimeSpan CloseTimeOne;
[DataField("closeTimeOne")]
protected TimeSpan CloseTimeOne = TimeSpan.FromSeconds(0.4f);
/// <summary>
/// Closing time until fully closed.
/// </summary>
protected TimeSpan CloseTimeTwo;
[DataField("closeTimeTwo")]
protected TimeSpan CloseTimeTwo = TimeSpan.FromSeconds(0.2f);
/// <summary>
/// Opening time until passable.
/// </summary>
protected TimeSpan OpenTimeOne;
[DataField("openTimeOne")]
protected TimeSpan OpenTimeOne = TimeSpan.FromSeconds(0.4f);
/// <summary>
/// Opening time until fully open.
/// </summary>
protected TimeSpan OpenTimeTwo;
[DataField("openTimeTwo")]
protected TimeSpan OpenTimeTwo = TimeSpan.FromSeconds(0.2f);
/// <summary>
/// Time to finish denying.
/// </summary>
@@ -85,42 +94,9 @@ namespace Content.Shared.GameObjects.Components.Doors
/// </summary>
protected List<EntityUid> CurrentlyCrushing = new();
public override void ExposeData(ObjectSerializer serializer)
{
base.ExposeData(serializer);
serializer.DataReadWriteFunction(
"closeTimeOne",
0.4f,
seconds => CloseTimeOne = TimeSpan.FromSeconds(seconds),
() => CloseTimeOne.TotalSeconds);
serializer.DataReadWriteFunction(
"closeTimeTwo",
0.2f,
seconds => CloseTimeTwo = TimeSpan.FromSeconds(seconds),
() => CloseTimeTwo.TotalSeconds);
serializer.DataReadWriteFunction(
"openTimeOne",
0.4f,
seconds => OpenTimeOne = TimeSpan.FromSeconds(seconds),
() => OpenTimeOne.TotalSeconds);
serializer.DataReadWriteFunction(
"openTimeTwo",
0.2f,
seconds => OpenTimeTwo = TimeSpan.FromSeconds(seconds),
() => OpenTimeTwo.TotalSeconds);
}
protected void SetAppearance(DoorVisualState state)
{
if (AppearanceComponent != null)
{
AppearanceComponent.SetData(DoorVisuals.VisualState, state);
}
AppearanceComponent?.SetData(DoorVisuals.VisualState, state);
}
// stops us colliding with people we're crushing, to prevent hitbox clipping and jank

View File

@@ -4,7 +4,9 @@ using Content.Shared.GameObjects.Components.Movement;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Reflection;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.Utility;
using Robust.Shared.ViewVariables;
using static Content.Shared.GameObjects.Components.Inventory.EquipmentSlotDefines;
@@ -25,15 +27,9 @@ namespace Content.Shared.GameObjects.Components.Inventory
protected Inventory InventoryInstance { get; private set; }
[ViewVariables]
[DataField("Template")]
private string _templateName = "HumanInventory"; //stored for serialization purposes
public override void ExposeData(ObjectSerializer serializer)
{
base.ExposeData(serializer);
serializer.DataField(ref _templateName, "Template", "HumanInventory");
}
public override void Initialize()
{
base.Initialize();

View File

@@ -5,7 +5,7 @@ using Robust.Shared.IoC;
using Robust.Shared.Prototypes;
using Robust.Shared.Reflection;
using Robust.Shared.Serialization;
using Robust.Shared.Utility;
using Robust.Shared.Serialization.Manager.Attributes;
namespace Content.Shared.GameObjects.Components.Materials
{
@@ -14,66 +14,51 @@ namespace Content.Shared.GameObjects.Components.Materials
/// This is not a storage system for say smelteries.
/// </summary>
[RegisterComponent]
public class MaterialComponent : Component
public class MaterialComponent : Component, ISerializationHooks
{
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
public const string SerializationCache = "mat";
public override string Name => "Material";
public Dictionary<object, Material> MaterialTypes => _materialTypes;
private Dictionary<object, Material> _materialTypes;
[DataField("materials")] private List<MaterialDataEntry> _materials = new();
public override void ExposeData(ObjectSerializer serializer)
public IEnumerable<KeyValuePair<object, MaterialPrototype>> MaterialTypes
{
base.ExposeData(serializer);
// TODO: Writing.
if (serializer.Writing)
get
{
return;
}
if (serializer.TryGetCacheData(SerializationCache, out Dictionary<object, Material> cached))
{
_materialTypes = cached.ShallowClone();
return;
}
_materialTypes = new Dictionary<object, Material>();
if (serializer.TryReadDataField("materials", out List<MaterialDataEntry> list))
{
var protoMan = IoCManager.Resolve<IPrototypeManager>();
foreach (var entry in list)
foreach (var entry in _materials)
{
var proto = protoMan.Index<MaterialPrototype>(entry.Value);
_materialTypes[entry.Key] = proto.Material;
var prototype = _prototypeManager.Index<MaterialPrototype>(entry.Value);
yield return new KeyValuePair<object, MaterialPrototype>(entry.Key, prototype);
}
}
serializer.SetCacheData(SerializationCache, _materialTypes.ShallowClone());
}
class MaterialDataEntry : IExposeData
[DataDefinition]
public class MaterialDataEntry : ISerializationHooks
{
public object Key;
[DataField("key")]
public string StringKey;
[DataField("mat")]
public string Value;
void IExposeData.ExposeData(ObjectSerializer serializer)
void ISerializationHooks.AfterDeserialization()
{
if (serializer.Writing)
{
return;
}
var refl = IoCManager.Resolve<IReflectionManager>();
Value = serializer.ReadDataField<string>("mat");
var key = serializer.ReadDataField<string>("key");
if (refl.TryParseEnumReference(key, out var @enum))
if (refl.TryParseEnumReference(StringKey, out var @enum))
{
Key = @enum;
return;
}
Key = key;
Key = StringKey;
}
}
}

View File

@@ -6,7 +6,6 @@ using Robust.Shared.Serialization;
namespace Content.Shared.GameObjects.Components.Medical
{
public class SharedCloningPodComponent : Component
{
public override string Name => "CloningPod";

View File

@@ -1,6 +1,8 @@
#nullable enable
using Robust.Shared.GameObjects;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.ViewVariables;
namespace Content.Shared.GameObjects.Components.Mobs
@@ -14,6 +16,7 @@ namespace Content.Shared.GameObjects.Components.Mobs
public override string Name => "Examiner";
[ViewVariables(VVAccess.ReadWrite)]
[DataField("DoRangeCheck")]
private bool _doRangeCheck = true;
/// <summary>
@@ -21,12 +24,5 @@ namespace Content.Shared.GameObjects.Components.Mobs
/// If false, the user can theoretically examine from infinitely far away.
/// </summary>
public bool DoRangeCheck => _doRangeCheck;
public override void ExposeData(ObjectSerializer serializer)
{
base.ExposeData(serializer);
serializer.DataField(ref _doRangeCheck, "DoRangeCheck", true);
}
}
}

View File

@@ -8,6 +8,7 @@ using Content.Shared.Interfaces.GameObjects.Components;
using Robust.Shared.GameObjects;
using Robust.Shared.Log;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.Manager.Attributes;
namespace Content.Shared.GameObjects.Components.Mobs
{
@@ -50,23 +51,25 @@ namespace Content.Shared.GameObjects.Components.Mobs
public IEntity? Holder { get; private set; }
// cached actions component of the holder, since we'll need to access it frequently
private SharedActionsComponent? _holderActionsComponent;
private List<ItemActionConfig> _actionConfigs = new();
// State of all actions provided by this item.
private readonly Dictionary<ItemActionType, ActionState> _actions = new();
public override void ExposeData(ObjectSerializer serializer)
[DataField("actions")]
private List<ItemActionConfig> _actionConfigs
{
base.ExposeData(serializer);
serializer.DataField(ref _actionConfigs,"actions", new List<ItemActionConfig>());
foreach (var actionConfig in _actionConfigs)
get => internalActionConfigs;
set
{
GrantOrUpdate(actionConfig.ActionType, actionConfig.Enabled, false, null);
internalActionConfigs = value;
foreach (var actionConfig in value)
{
GrantOrUpdate(actionConfig.ActionType, actionConfig.Enabled, false, null);
}
}
}
// State of all actions provided by this item.
private readonly Dictionary<ItemActionType, ActionState> _actions = new();
private List<ItemActionConfig> internalActionConfigs = new ();
protected override void Startup()
{
base.Startup();
@@ -226,22 +229,23 @@ namespace Content.Shared.GameObjects.Components.Mobs
/// <summary>
/// Configuration for an item action provided by an item.
/// </summary>
public class ItemActionConfig : IExposeData
[DataDefinition]
public class ItemActionConfig : ISerializationHooks
{
public ItemActionType ActionType { get; private set; }
[DataField("actionType", required: true)]
public ItemActionType ActionType { get; private set; } = ItemActionType.Error;
/// <summary>
/// Whether action is initially enabled on this item. Defaults to true.
/// </summary>
public bool Enabled { get; private set; }
public bool Enabled { get; private set; } = true;
void IExposeData.ExposeData(ObjectSerializer serializer)
void ISerializationHooks.AfterDeserialization()
{
serializer.DataField(this, x => x.ActionType, "actionType", ItemActionType.Error);
if (ActionType == ItemActionType.Error)
{
Logger.ErrorS("action", "invalid or missing actionType");
}
serializer.DataField(this, x => x.Enabled, "enabled", true);
}
}
}

View File

@@ -10,6 +10,7 @@ using Robust.Shared.Map;
using Robust.Shared.Players;
using Robust.Shared.Serialization;
using Robust.Shared.Timing;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.ViewVariables;
namespace Content.Shared.GameObjects.Components.Mobs
@@ -46,7 +47,8 @@ namespace Content.Shared.GameObjects.Components.Mobs
/// of the status of the entity.
/// </summary>
public IEnumerable<ActionType> InnateActions => _innateActions ?? Enumerable.Empty<ActionType>();
private List<ActionType>? _innateActions;
[DataField("innateActions")]
private List<ActionType>? _innateActions = null;
// entries are removed from this if they are at the initial state (not enabled, no cooldown, toggled off).
@@ -63,11 +65,6 @@ namespace Content.Shared.GameObjects.Components.Mobs
private Dictionary<EntityUid, Dictionary<ItemActionType, ActionState>> _itemActions =
new();
public override void ExposeData(ObjectSerializer serializer)
{
base.ExposeData(serializer);
serializer.DataField(ref _innateActions,"innateActions", null);
}
protected override void Startup()
{
foreach (var actionType in InnateActions)

View File

@@ -7,8 +7,10 @@ using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using Content.Shared.Interfaces.GameObjects.Components;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
using Robust.Shared.Timing;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.ViewVariables;
namespace Content.Shared.GameObjects.Components.Mobs
@@ -31,17 +33,26 @@ namespace Content.Shared.GameObjects.Components.Mobs
(TimeSpan.FromSeconds(Math.Max(StunnedTimer, Math.Max(KnockdownTimer, SlowdownTimer))));
private bool _canHelp = true;
[DataField("stunCap")]
protected float _stunCap = 20f;
[DataField("knockdownCap")]
protected float _knockdownCap = 20f;
[DataField("slowdownCap")]
protected float _slowdownCap = 20f;
private float _helpKnockdownRemove = 1f;
[DataField("helpInterval")]
private float _helpInterval = 1f;
protected float StunnedTimer;
protected float KnockdownTimer;
protected float SlowdownTimer;
private string _stunAlertId = string.Empty;
[DataField("stunAlertId")] private string _stunAlertId = "stun";
protected CancellationTokenSource StatusRemoveCancellation = new();
@@ -203,19 +214,6 @@ namespace Content.Shared.GameObjects.Components.Mobs
StatusRemoveCancellation = new CancellationTokenSource();
}
public override void ExposeData(ObjectSerializer serializer)
{
base.ExposeData(serializer);
serializer.DataField(ref _stunCap, "stunCap", 20f);
serializer.DataField(ref _knockdownCap, "knockdownCap", 20f);
serializer.DataField(ref _slowdownCap, "slowdownCap", 20f);
serializer.DataField(ref _helpInterval, "helpInterval", 1f);
serializer.DataField(ref _helpKnockdownRemove, "helpKnockdownRemove", 1f);
serializer.DataField(ref _stunAlertId, "stunAlertId",
"stun");
}
protected virtual void OnInteractHand() { }
bool IInteractHand.InteractHand(InteractHandEventArgs eventArgs)

View File

@@ -1,14 +1,14 @@
#nullable enable
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using Robust.Shared.GameObjects;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.Manager.Attributes;
namespace Content.Shared.GameObjects.Components.Mobs.Speech
{
[RegisterComponent]
public class SharedEmotingComponent : Component, IActionBlocker
{
private bool _enabled = true;
[DataField("enabled")] private bool _enabled = true;
public override string Name => "Emoting";
public bool Enabled
@@ -23,12 +23,5 @@ namespace Content.Shared.GameObjects.Components.Mobs.Speech
}
bool IActionBlocker.CanEmote() => Enabled;
public override void ExposeData(ObjectSerializer serializer)
{
base.ExposeData(serializer);
serializer.DataField(this, x => x.Enabled, "enabled", true);
}
}
}

View File

@@ -1,7 +1,7 @@
#nullable enable
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using Robust.Shared.GameObjects;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.Manager.Attributes;
namespace Content.Shared.GameObjects.Components.Mobs.Speech
{
@@ -11,9 +11,11 @@ namespace Content.Shared.GameObjects.Components.Mobs.Speech
[RegisterComponent]
public class SharedSpeechComponent : Component, IActionBlocker
{
private bool _enabled = true;
public override string Name => "Speech";
[DataField("enabled")]
private bool _enabled = true;
public bool Enabled
{
get => _enabled;
@@ -26,12 +28,5 @@ namespace Content.Shared.GameObjects.Components.Mobs.Speech
}
bool IActionBlocker.CanSpeak() => Enabled;
public override void ExposeData(ObjectSerializer serializer)
{
base.ExposeData(serializer);
serializer.DataField(this, x => x.Enabled, "enabled", true);
}
}
}

View File

@@ -1,9 +1,10 @@
#nullable enable
using Robust.Shared.GameObjects;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.Manager.Attributes;
namespace Content.Shared.GameObjects.Components.Mobs.State
{
[ImplicitDataDefinitionForInheritors]
public abstract class BaseMobState : IMobState
{
protected abstract DamageState DamageState { get; }
@@ -34,8 +35,6 @@ namespace Content.Shared.GameObjects.Components.Mobs.State
public virtual void UpdateState(IEntity entity, int threshold) { }
public virtual void ExposeData(ObjectSerializer serializer) { }
public virtual bool CanInteract()
{
return true;

View File

@@ -1,7 +1,6 @@
#nullable enable
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using Robust.Shared.GameObjects;
using Robust.Shared.Serialization;
namespace Content.Shared.GameObjects.Components.Mobs.State
{
@@ -10,7 +9,7 @@ namespace Content.Shared.GameObjects.Components.Mobs.State
/// (i.e. Normal, Critical, Dead) and what effects to apply upon entering or
/// exiting the state.
/// </summary>
public interface IMobState : IExposeData, IActionBlocker
public interface IMobState : IActionBlocker
{
bool IsAlive();

View File

@@ -9,6 +9,7 @@ using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using Robust.Shared.GameObjects;
using Robust.Shared.Players;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.ViewVariables;
namespace Content.Shared.GameObjects.Components.Mobs.State
@@ -29,12 +30,12 @@ namespace Content.Shared.GameObjects.Components.Mobs.State
/// States that this <see cref="SharedMobStateComponent"/> mapped to
/// the amount of damage at which they are triggered.
/// A threshold is reached when the total damage of an entity is equal
/// A threshold is reached when the total damage of an entity is equal
/// to or higher than the int key, but lower than the next threshold.
/// Ordered from lowest to highest.
/// </summary>
[ViewVariables]
private SortedDictionary<int, IMobState> _lowestToHighestStates = default!;
[DataField("thresholds")]
private readonly SortedDictionary<int, IMobState> _lowestToHighestStates = default!;
// TODO Remove Nullability?
[ViewVariables]
@@ -45,20 +46,6 @@ namespace Content.Shared.GameObjects.Components.Mobs.State
public IEnumerable<KeyValuePair<int, IMobState>> _highestToLowestStates => _lowestToHighestStates.Reverse();
public override void ExposeData(ObjectSerializer serializer)
{
base.ExposeData(serializer);
serializer.DataReadWriteFunction(
"thresholds",
new Dictionary<int, IMobState>(),
thresholds =>
{
_lowestToHighestStates = new SortedDictionary<int, IMobState>(thresholds);
},
() => new Dictionary<int, IMobState>(_lowestToHighestStates));
}
protected override void Startup()
{
base.Startup();

View File

@@ -1,7 +1,9 @@
#nullable enable
#nullable enable
using Robust.Shared.Containers;
using Robust.Shared.GameObjects;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.ViewVariables;
namespace Content.Shared.GameObjects.Components.Movement
@@ -37,9 +39,12 @@ namespace Content.Shared.GameObjects.Components.Movement
}
[ViewVariables(VVAccess.ReadWrite)]
public float BaseWalkSpeed { get; set; }
[DataField("baseWalkSpeed")]
public float BaseWalkSpeed { get; set; } = 4;
[ViewVariables(VVAccess.ReadWrite)]
public float BaseSprintSpeed { get; set; }
[DataField("baseSprintSpeed")]
public float BaseSprintSpeed { get; set; } = 7;
[ViewVariables]
public float CurrentWalkSpeed => WalkSpeedModifier * BaseWalkSpeed;
@@ -65,14 +70,6 @@ namespace Content.Shared.GameObjects.Components.Movement
}
}
public override void ExposeData(ObjectSerializer serializer)
{
base.ExposeData(serializer);
serializer.DataField(this, p => p.BaseWalkSpeed, "baseWalkSpeed", 4);
serializer.DataField(this, p => p.BaseSprintSpeed, "baseSprintSpeed", 7);
}
/// <summary>
/// Recalculate movement speed with current modifiers, or return early if no change
/// </summary>

View File

@@ -2,12 +2,12 @@
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.Interfaces.GameObjects.Components;
using Robust.Shared.GameObjects;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.ViewVariables;
namespace Content.Shared.GameObjects.Components.Movement
{
public interface IClimbable { };
public interface IClimbable { }
public abstract class SharedClimbableComponent : Component, IClimbable, IDragDropOn
{
@@ -16,14 +16,7 @@ namespace Content.Shared.GameObjects.Components.Movement
/// <summary>
/// The range from which this entity can be climbed.
/// </summary>
[ViewVariables]
protected float Range;
public override void ExposeData(ObjectSerializer serializer)
{
base.ExposeData(serializer);
serializer.DataField(ref Range, "range", SharedInteractionSystem.InteractionRange / 1.4f);
}
[ViewVariables] [DataField("range")] protected float Range = SharedInteractionSystem.InteractionRange / 1.4f;
public virtual bool CanDragDropOn(DragDropEventArgs eventArgs)
{

View File

@@ -8,13 +8,13 @@ using Content.Shared.Physics;
using Robust.Shared.Containers;
using Robust.Shared.GameObjects;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.ViewVariables;
namespace Content.Shared.GameObjects.Components.Movement
{
public abstract class SharedSlipperyComponent : Component, ICollideBehavior
{
public sealed override string Name => "Slippery";
/// <summary>
@@ -27,31 +27,36 @@ namespace Content.Shared.GameObjects.Components.Movement
/// How many seconds the mob will be paralyzed for.
/// </summary>
[ViewVariables(VVAccess.ReadWrite)]
public virtual float ParalyzeTime { get; set; } = 2f;
[DataField("paralyzeTime")]
public virtual float ParalyzeTime { get; set; } = 3f;
/// <summary>
/// Percentage of shape intersection for a slip to occur.
/// </summary>
[ViewVariables(VVAccess.ReadWrite)]
[DataField("intersectPercentage")]
public virtual float IntersectPercentage { get; set; } = 0.3f;
/// <summary>
/// Entities will only be slipped if their speed exceeds this limit.
/// </summary>
[ViewVariables(VVAccess.ReadWrite)]
public virtual float RequiredSlipSpeed { get; set; } = 0f;
[DataField("requiredSlipSpeed")]
public virtual float RequiredSlipSpeed { get; set; } = 0.1f;
/// <summary>
/// The entity's speed will be multiplied by this to slip it forwards.
/// </summary>
[ViewVariables(VVAccess.ReadWrite)]
[DataField("launchForwardsMultiplier")]
public virtual float LaunchForwardsMultiplier { get; set; } = 1f;
/// <summary>
/// Whether or not this component will try to slip entities.
/// </summary>
[ViewVariables(VVAccess.ReadWrite)]
public virtual bool Slippery { get; set; }
[DataField("slippery")]
public virtual bool Slippery { get; set; } = true;
private bool TrySlip(IEntity entity)
{
@@ -140,17 +145,6 @@ namespace Content.Shared.GameObjects.Components.Movement
shape.CollisionMask = (int) CollisionGroup.None;
}
}
public override void ExposeData(ObjectSerializer serializer)
{
base.ExposeData(serializer);
serializer.DataField(this, x => x.ParalyzeTime, "paralyzeTime", 3f);
serializer.DataField(this, x => x.IntersectPercentage, "intersectPercentage", 0.3f);
serializer.DataField(this, x => x.RequiredSlipSpeed, "requiredSlipSpeed", 0.1f);
serializer.DataField(this, x => x.LaunchForwardsMultiplier, "launchForwardsMultiplier", 1f);
serializer.DataField(this, x => x.Slippery, "slippery", true);
}
}
[Serializable, NetSerializable]

View File

@@ -7,16 +7,44 @@ using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.Manager.Attributes;
namespace Content.Shared.GameObjects.Components.Research
{
public class SharedLatheDatabaseComponent : Component, IEnumerable<LatheRecipePrototype>
public class SharedLatheDatabaseComponent : Component, IEnumerable<LatheRecipePrototype>, ISerializationHooks
{
public override string Name => "LatheDatabase";
public override uint? NetID => ContentNetIDs.LATHE_DATABASE;
[DataField("recipes")] private List<string> _recipeIds = new();
private readonly List<LatheRecipePrototype> _recipes = new();
void ISerializationHooks.BeforeSerialization()
{
var list = new List<string>();
foreach (var recipe in _recipes)
{
list.Add(recipe.ID);
}
_recipeIds = list;
}
void ISerializationHooks.AfterDeserialization()
{
var prototypeManager = IoCManager.Resolve<IPrototypeManager>();
foreach (var id in _recipeIds)
{
if (prototypeManager.TryIndex(id, out LatheRecipePrototype? recipe))
{
_recipes.Add(recipe);
}
}
}
/// <summary>
/// Removes all recipes from the database if it's not static.
/// </summary>
@@ -33,7 +61,7 @@ namespace Content.Shared.GameObjects.Components.Research
/// <returns>Whether it could be added or not</returns>
public virtual void AddRecipe(LatheRecipePrototype recipe)
{
if(!Contains(recipe))
if (!Contains(recipe))
_recipes.Add(recipe);
}
@@ -71,29 +99,6 @@ namespace Content.Shared.GameObjects.Components.Research
return false;
}
public override void ExposeData(ObjectSerializer serializer)
{
base.ExposeData(serializer);
serializer.DataReadWriteFunction(
"recipes",
new List<string>(),
recipes =>
{
var prototypeManager = IoCManager.Resolve<IPrototypeManager>();
foreach (var id in recipes)
{
if (prototypeManager.TryIndex(id, out LatheRecipePrototype? recipe))
{
_recipes.Add(recipe);
}
}
},
GetRecipeIdList);
}
public List<string> GetRecipeIdList()
{
var list = new List<string>();

View File

@@ -2,6 +2,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
using Content.Shared.Materials;
using Robust.Shared.GameObjects;
using Robust.Shared.Serialization;
using Robust.Shared.ViewVariables;
@@ -10,11 +11,12 @@ namespace Content.Shared.GameObjects.Components.Research
{
public class SharedMaterialStorageComponent : Component, IEnumerable<KeyValuePair<string, int>>
{
[ViewVariables]
protected virtual Dictionary<string, int> Storage { get; set; } = new();
public override string Name => "MaterialStorage";
public sealed override uint? NetID => ContentNetIDs.MATERIAL_STORAGE;
[ViewVariables]
protected virtual Dictionary<string, int> Storage { get; set; } = new();
public int this[string ID]
{
get
@@ -25,6 +27,17 @@ namespace Content.Shared.GameObjects.Components.Research
}
}
public int this[MaterialPrototype material]
{
get
{
var ID = material.ID;
if (!Storage.ContainsKey(ID))
return 0;
return Storage[ID];
}
}
/// <summary>
/// The total volume of material stored currently.
/// </summary>

View File

@@ -6,59 +6,33 @@ using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.Manager.Attributes;
namespace Content.Shared.GameObjects.Components.Research
{
[ComponentReference(typeof(SharedLatheDatabaseComponent))]
public class SharedProtolatheDatabaseComponent : SharedLatheDatabaseComponent
public class SharedProtolatheDatabaseComponent : SharedLatheDatabaseComponent, ISerializationHooks
{
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
public override string Name => "ProtolatheDatabase";
public sealed override uint? NetID => ContentNetIDs.PROTOLATHE_DATABASE;
private readonly List<LatheRecipePrototype> _protolatheRecipes = new();
[DataField("protolatherecipes")] private List<string> _recipeIds = new();
/// <summary>
/// A full list of recipes this protolathe can print.
/// </summary>
public List<LatheRecipePrototype> ProtolatheRecipes => _protolatheRecipes;
public override void ExposeData(ObjectSerializer serializer)
public IEnumerable<LatheRecipePrototype> ProtolatheRecipes
{
base.ExposeData(serializer);
serializer.DataReadWriteFunction(
"protolatherecipes",
new List<string>(),
recipes =>
{
var prototypeManager = IoCManager.Resolve<IPrototypeManager>();
foreach (var id in recipes)
{
if (prototypeManager.TryIndex(id, out LatheRecipePrototype? recipe))
{
_protolatheRecipes.Add(recipe);
}
}
},
GetProtolatheRecipeIdList);
}
/// <summary>
/// Returns a list of the allowed protolathe recipe IDs.
/// </summary>
/// <returns>A list of recipe IDs allowed</returns>
public List<string> GetProtolatheRecipeIdList()
{
var list = new List<string>();
foreach (var recipe in ProtolatheRecipes)
get
{
list.Add(recipe.ID);
foreach (var id in _recipeIds)
{
yield return _prototypeManager.Index<LatheRecipePrototype>(id);
}
}
return list;
}
}

View File

@@ -7,14 +7,17 @@ using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.Manager.Attributes;
namespace Content.Shared.GameObjects.Components.Research
{
public class SharedTechnologyDatabaseComponent : Component, IEnumerable<TechnologyPrototype>
public class SharedTechnologyDatabaseComponent : Component, IEnumerable<TechnologyPrototype>, ISerializationHooks
{
public override string Name => "TechnologyDatabase";
public override uint? NetID => ContentNetIDs.TECHNOLOGY_DATABASE;
[DataField("technologies")] private List<string> _technologyIds = new();
protected List<TechnologyPrototype> _technologies = new();
/// <summary>
@@ -22,6 +25,31 @@ namespace Content.Shared.GameObjects.Components.Research
/// </summary>
public IReadOnlyList<TechnologyPrototype> Technologies => _technologies;
void ISerializationHooks.BeforeSerialization()
{
var techIds = new List<string>();
foreach (var tech in _technologies)
{
techIds.Add(tech.ID);
}
_technologyIds = techIds;
}
void ISerializationHooks.AfterDeserialization()
{
var prototypeManager = IoCManager.Resolve<IPrototypeManager>();
foreach (var id in _technologyIds)
{
if (prototypeManager.TryIndex(id, out TechnologyPrototype? tech))
{
_technologies.Add(tech);
}
}
}
public IEnumerator<TechnologyPrototype> GetEnumerator()
{
return Technologies.GetEnumerator();
@@ -79,27 +107,6 @@ namespace Content.Shared.GameObjects.Components.Research
}
return true;
}
public override void ExposeData(ObjectSerializer serializer)
{
base.ExposeData(serializer);
serializer.DataReadWriteFunction(
"technologies",
new List<string>(),
techs =>
{
var prototypeManager = IoCManager.Resolve<IPrototypeManager>();
foreach (var id in techs)
{
if (prototypeManager.TryIndex(id, out TechnologyPrototype? tech))
{
_technologies.Add(tech);
}
}
}, GetTechnologyIdList);
}
}
[Serializable, NetSerializable]

View File

@@ -1,11 +1,12 @@
#nullable enable
#nullable enable
using System;
using System.Collections.Generic;
using Robust.Shared.GameObjects;
using Robust.Shared.Maths;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
using System;
using System.Collections.Generic;
using YamlDotNet.RepresentationModel;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.ViewVariables;
namespace Content.Shared.GameObjects.Components
{
@@ -15,6 +16,8 @@ namespace Content.Shared.GameObjects.Components
public override uint? NetID => ContentNetIDs.CRAYONS;
public string SelectedState { get; set; } = string.Empty;
[DataField("color")]
protected string _color = "white";
[Serializable, NetSerializable]
@@ -74,21 +77,16 @@ namespace Content.Shared.GameObjects.Components
[Serializable, NetSerializable, Prototype("crayonDecal")]
public class CrayonDecalPrototype : IPrototype
{
public string ID { get; private set; } = string.Empty;
[ViewVariables]
[field: DataField("id", required: true)]
public string ID { get; } = default!;
private string _spritePath = string.Empty;
public string SpritePath => _spritePath;
[ViewVariables]
[field: DataField("parent")]
public string? Parent { get; }
private List<string> _decals = new();
public List<string> Decals => _decals;
[field: DataField("spritePath")] public string SpritePath { get; } = string.Empty;
public void LoadFrom(YamlMappingNode mapping)
{
var serializer = YamlObjectSerializer.NewReader(mapping);
serializer.DataField(this, x => x.ID, "id", string.Empty);
serializer.DataField(ref _spritePath, "spritePath", string.Empty);
serializer.DataField(ref _decals, "decals", new List<string>());
}
[field: DataField("decals")] public List<string> Decals { get; } = new();
}
}

View File

@@ -2,6 +2,7 @@
using System;
using Robust.Shared.GameObjects;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.ViewVariables;
namespace Content.Shared.GameObjects.Components
@@ -29,53 +30,47 @@ namespace Content.Shared.GameObjects.Components
protected ExpendableLightState CurrentState { get; set; }
[ViewVariables]
[DataField("turnOnBehaviourID")]
protected string TurnOnBehaviourID { get; set; } = string.Empty;
[ViewVariables]
[DataField("fadeOutBehaviourID")]
protected string FadeOutBehaviourID { get; set; } = string.Empty;
[ViewVariables]
protected float GlowDuration { get; set; }
[DataField("glowDuration")]
protected float GlowDuration { get; set; } = 60 * 15f;
[ViewVariables]
protected float FadeOutDuration { get; set; }
[DataField("fadeOutDuration")]
protected float FadeOutDuration { get; set; } = 60 * 5f;
[ViewVariables]
[DataField("spentDesc")]
protected string SpentDesc { get; set; } = string.Empty;
[ViewVariables]
[DataField("spentName")]
protected string SpentName { get; set; } = string.Empty;
[ViewVariables]
[DataField("iconStateSpent")]
protected string IconStateSpent { get; set; } = string.Empty;
[ViewVariables]
[DataField("iconStateOn")]
protected string IconStateLit { get; set; } = string.Empty;
[ViewVariables]
[DataField("litSound")]
protected string LitSound { get; set; } = string.Empty;
[ViewVariables]
[DataField("loopedSound")]
protected string LoopedSound { get; set; } = string.Empty;
[ViewVariables]
[DataField("dieSound")]
protected string DieSound { get; set; } = string.Empty;
public override void ExposeData(ObjectSerializer serializer)
{
base.ExposeData(serializer);
serializer.DataField(this, x => x.TurnOnBehaviourID, "turnOnBehaviourID", string.Empty);
serializer.DataField(this, x => x.FadeOutBehaviourID, "fadeOutBehaviourID", string.Empty);
serializer.DataField(this, x => x.GlowDuration, "glowDuration", 60 * 15f);
serializer.DataField(this, x => x.FadeOutDuration, "fadeOutDuration", 60 * 5f);
serializer.DataField(this, x => x.SpentName, "spentName", string.Empty);
serializer.DataField(this, x => x.SpentDesc, "spentDesc", string.Empty);
serializer.DataField(this, x => x.IconStateLit, "iconStateOn", string.Empty);
serializer.DataField(this, x => x.IconStateSpent, "iconStateSpent", string.Empty);
serializer.DataField(this, x => x.LitSound, "litSound", string.Empty);
serializer.DataField(this, x => x.LoopedSound, "loopedSound", string.Empty);
serializer.DataField(this, x => x.DieSound, "dieSound", string.Empty);
}
}
}

View File

@@ -6,11 +6,12 @@ using Robust.Shared.Log;
using Robust.Shared.Players;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.ViewVariables;
namespace Content.Shared.GameObjects.Components
{
public abstract class SharedStackComponent : Component
public abstract class SharedStackComponent : Component, ISerializationHooks
{
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
@@ -19,8 +20,11 @@ namespace Content.Shared.GameObjects.Components
public sealed override string Name => "Stack";
public sealed override uint? NetID => ContentNetIDs.STACK;
private int _count;
private int _maxCount;
[DataField("count")]
private int _count = 30;
[DataField("max")]
private int _maxCount = 30;
[ViewVariables(VVAccess.ReadWrite)]
public virtual int Count
@@ -51,35 +55,12 @@ namespace Content.Shared.GameObjects.Components
[ViewVariables] public int AvailableSpace => MaxCount - Count;
[ViewVariables] public string StackTypeId { get; private set; } = string.Empty;
[ViewVariables]
[field: DataField("stackType")]
public string StackTypeId { get; } = string.Empty;
public StackPrototype StackType => _prototypeManager.Index<StackPrototype>(StackTypeId);
public override void ExposeData(ObjectSerializer serializer)
{
serializer.DataFieldCached(ref _maxCount, "max", 30);
serializer.DataFieldCached(ref _count, "count", MaxCount);
if (serializer.Writing)
{
return;
}
if (serializer.TryGetCacheData(SerializationCache, out string stackType))
{
StackTypeId = stackType;
return;
}
serializer.DataFieldCached(ref stackType, "stackType", string.Empty);
if (!string.IsNullOrEmpty(stackType))
{
serializer.SetCacheData(SerializationCache, stackType);
StackTypeId = stackType;
}
}
protected override void Startup()
{
base.Startup();

View File

@@ -3,6 +3,7 @@ using System;
using Robust.Shared.Audio;
using Robust.Shared.GameObjects;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.Manager.Attributes;
namespace Content.Shared.GameObjects.Components.Sound
{
@@ -73,49 +74,43 @@ namespace Content.Shared.GameObjects.Components.Sound
}
[Serializable, NetSerializable]
public class ScheduledSound : IExposeData
[DataDefinition]
public class ScheduledSound
{
public string Filename = "";
[DataField("fileName")]
public string Filename = string.Empty;
/// <summary>
/// The parameters to play the sound with.
/// </summary>
[DataField("audioparams")]
public AudioParams? AudioParams;
/// <summary>
/// Delay in milliseconds before playing the sound,
/// and delay between repetitions if Times is not 0.
/// </summary>
public uint Delay = 0;
[DataField("delay")]
public uint Delay;
/// <summary>
/// Maximum number of milliseconds to add to the delay randomly.
/// Useful for random ambience noises. Generated value differs from client to client.
/// </summary>
public uint RandomDelay = 0;
[DataField("randomdelay")]
public uint RandomDelay;
/// <summary>
/// How many times to repeat the sound. If it's 0, it will play the sound once.
/// If it's less than 0, it will repeat the sound indefinitely.
/// If it's greater than 0, it will play the sound n+1 times.
/// </summary>
public int Times = 0;
[DataField("times")]
public int Times;
/// <summary>
/// Whether the sound will play or not.
/// </summary>
public bool Play = true;
void IExposeData.ExposeData(ObjectSerializer serializer)
{
if (serializer.Writing)
return;
Filename = serializer.ReadDataField("filename", "");
Delay = serializer.ReadDataField("delay", 0u);
RandomDelay = serializer.ReadDataField("randomdelay", 0u);
Times = serializer.ReadDataField("times", 0);
AudioParams = serializer.ReadDataField("audioparams", Robust.Shared.Audio.AudioParams.Default);
}
}
}

View File

@@ -1,7 +1,9 @@
#nullable enable
using System;
using Robust.Shared.GameObjects;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.Manager.Attributes;
namespace Content.Shared.GameObjects.Components.Storage
{
@@ -10,14 +12,7 @@ namespace Content.Shared.GameObjects.Components.Storage
public override string Name => "Storable";
public override uint? NetID => ContentNetIDs.STORABLE;
public virtual int Size { get; set; }
public override void ExposeData(ObjectSerializer serializer)
{
base.ExposeData(serializer);
serializer.DataField(this, s => s.Size, "size", 1);
}
[DataField("size")] public virtual int Size { get; set; } = 1;
}
[Serializable, NetSerializable]

View File

@@ -7,39 +7,30 @@ using Robust.Shared.IoC;
using Robust.Shared.Players;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.ViewVariables;
namespace Content.Shared.GameObjects.Components.Tag
{
[RegisterComponent]
public class TagComponent : Component
public class TagComponent : Component, ISerializationHooks
{
public override string Name => "Tag";
[ViewVariables]
[DataField("tags")]
private readonly HashSet<string> _tags = new();
public IReadOnlySet<string> Tags => _tags;
public override void ExposeData(ObjectSerializer serializer)
public override void Initialize()
{
base.ExposeData(serializer);
base.Initialize();
serializer.DataReadWriteFunction(
"tags",
null!,
(ids) =>
{
_tags.Clear();
if (ids == null)
{
return;
}
AddTags(ids);
},
() => _tags);
foreach (var tag in _tags)
{
GetTagOrThrow(tag);
}
}
public override ComponentState GetComponentState(ICommonSession player)

View File

@@ -2,57 +2,53 @@
using System;
using Robust.Shared.Maths;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.ViewVariables;
using YamlDotNet.RepresentationModel;
namespace Content.Shared.GameObjects.Components.Weapons.Melee
{
[Prototype("MeleeWeaponAnimation")]
public sealed class MeleeWeaponAnimationPrototype : IPrototype
{
private string _prototype = "WeaponArc";
private string _state = string.Empty;
private string _id = string.Empty;
private Vector4 _colorDelta;
private Vector4 _color;
private TimeSpan _length;
private float _speed;
private float _width;
private WeaponArcType _arcType;
[ViewVariables]
[field: DataField("id", required: true)]
public string ID { get; } = default!;
[ViewVariables] public string ID => _id;
[ViewVariables] public string State => _state;
[ViewVariables] public string Prototype => _prototype;
[ViewVariables] public TimeSpan Length => _length;
[ViewVariables] public float Speed => _speed;
[ViewVariables] public Vector4 Color => _color;
[ViewVariables] public Vector4 ColorDelta => _colorDelta;
[ViewVariables] public WeaponArcType ArcType => _arcType;
[ViewVariables] public float Width => _width;
[ViewVariables]
[field: DataField("parent")]
public string? Parent { get; }
public void LoadFrom(YamlMappingNode mapping)
{
var serializer = YamlObjectSerializer.NewReader(mapping);
[ViewVariables]
[field: DataField("state")]
public string State { get; } = string.Empty;
serializer.DataField(ref _prototype, "prototype", "WeaponArc");
serializer.DataField(ref _state, "state", string.Empty);
serializer.DataField(ref _id, "id", string.Empty);
serializer.DataField(ref _colorDelta, "colorDelta", Vector4.Zero);
serializer.DataField(ref _color, "color", new Vector4(1, 1, 1, 1));
if (serializer.TryReadDataField("length", out float length))
{
_length = TimeSpan.FromSeconds(length);
}
else
{
_length = TimeSpan.FromSeconds(0.5f);
}
[ViewVariables]
[field: DataField("prototype")]
public string Prototype { get; } = "WeaponArc";
serializer.DataField(ref _speed, "speed", 1);
serializer.DataField(ref _arcType, "arcType", WeaponArcType.Slash);
serializer.DataField(ref _width, "width", 90);
}
[ViewVariables]
[field: DataField("length")]
public TimeSpan Length { get; } = TimeSpan.FromSeconds(0.5f);
[ViewVariables]
[field: DataField("speed")]
public float Speed { get; } = 1;
[ViewVariables]
[field: DataField("color")]
public Vector4 Color { get; } = new(1,1,1,1);
[ViewVariables]
[field: DataField("colorDelta")]
public Vector4 ColorDelta { get; } = Vector4.Zero;
[ViewVariables]
[field: DataField("arcType")]
public WeaponArcType ArcType { get; } = WeaponArcType.Slash;
[ViewVariables]
[field: DataField("width")]
public float Width { get; } = 90;
}
public enum WeaponArcType