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

@@ -1,22 +1,15 @@
#nullable enable
using Robust.Shared.Localization;
using Robust.Shared.Serialization;
using Robust.Shared.Localization;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.Utility;
namespace Content.Shared.Construction
{
public abstract class ArbitraryInsertConstructionGraphStep : EntityInsertConstructionGraphStep
{
public string Name { get; private set; } = string.Empty;
public SpriteSpecifier Icon { get; private set; } = SpriteSpecifier.Invalid;
[DataField("name")] public string Name { get; private set; } = string.Empty;
public override void ExposeData(ObjectSerializer serializer)
{
base.ExposeData(serializer);
serializer.DataField(this, x => x.Icon, "icon", SpriteSpecifier.Invalid);
serializer.DataField(this, x => x.Name, "name", string.Empty);
}
[DataField("icon")] public SpriteSpecifier Icon { get; private set; } = SpriteSpecifier.Invalid;
public override void DoExamine(FormattedMessage message, bool inDetailsRange)
{

View File

@@ -1,21 +1,15 @@
#nullable enable
using Robust.Shared.GameObjects;
using Robust.Shared.Localization;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.Utility;
namespace Content.Shared.Construction
{
[DataDefinition]
public class ComponentConstructionGraphStep : ArbitraryInsertConstructionGraphStep
{
public string Component { get; private set; } = string.Empty;
public override void ExposeData(ObjectSerializer serializer)
{
base.ExposeData(serializer);
serializer.DataField(this, x => x.Component, "component", string.Empty);
}
[field: DataField("component")] public string Component { get; } = string.Empty;
public override bool EntityValid(IEntity entity)
{

View File

@@ -5,15 +5,14 @@ using JetBrains.Annotations;
using Robust.Shared.GameObjects;
using Robust.Shared.Map;
using Robust.Shared.Maths;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.Manager.Attributes;
namespace Content.Shared.Construction.ConstructionConditions
{
[UsedImplicitly]
[DataDefinition]
public class LowWallInTile : IConstructionCondition
{
void IExposeData.ExposeData(ObjectSerializer serializer) { }
public bool Condition(IEntity user, EntityCoordinates location, Direction direction)
{
var lowWall = false;

View File

@@ -5,15 +5,14 @@ using JetBrains.Annotations;
using Robust.Shared.GameObjects;
using Robust.Shared.Map;
using Robust.Shared.Maths;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.Manager.Attributes;
namespace Content.Shared.Construction.ConstructionConditions
{
[UsedImplicitly]
[DataDefinition]
public class NoWindowsInTile : IConstructionCondition
{
void IExposeData.ExposeData(ObjectSerializer serializer) { }
public bool Condition(IEntity user, EntityCoordinates location, Direction direction)
{
foreach (var entity in location.GetEntitiesInTile(true))

View File

@@ -4,21 +4,16 @@ using JetBrains.Annotations;
using Robust.Shared.GameObjects;
using Robust.Shared.Map;
using Robust.Shared.Maths;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.Manager.Attributes;
namespace Content.Shared.Construction.ConstructionConditions
{
[UsedImplicitly]
[DataDefinition]
public class TileNotBlocked : IConstructionCondition
{
private bool _filterMobs = false;
private bool _failIfSpace = true;
void IExposeData.ExposeData(ObjectSerializer serializer)
{
serializer.DataField(ref _filterMobs, "filterMobs", false);
serializer.DataField(ref _failIfSpace, "failIfSpace", true);
}
[DataField("filterMobs")] private bool _filterMobs = false;
[DataField("failIfSpace")] private bool _failIfSpace = true;
public bool Condition(IEntity user, EntityCoordinates location, Direction direction)
{

View File

@@ -1,24 +1,19 @@
#nullable enable
using System.Collections.Generic;
using Content.Shared.Maps;
using JetBrains.Annotations;
using Robust.Shared.GameObjects;
using Robust.Shared.Map;
using Robust.Shared.Maths;
using Robust.Shared.Serialization;
using System.Collections.Generic;
using Robust.Shared.GameObjects;
using Robust.Shared.Serialization.Manager.Attributes;
namespace Content.Shared.Construction.ConstructionConditions
{
[UsedImplicitly]
[DataDefinition]
public class TileType : IConstructionCondition
{
public List<string> TargetTiles { get; private set; } = new();
void IExposeData.ExposeData(ObjectSerializer serializer)
{
serializer.DataField(this, x => x.TargetTiles, "targets", new List<string>());
}
[DataField("targets")] public List<string> TargetTiles { get; private set; } = new();
public bool Condition(IEntity user, EntityCoordinates location, Direction direction)
{

View File

@@ -1,22 +1,21 @@
#nullable enable
using System.Linq;
using Content.Shared.GameObjects.Components.Tag;
using Content.Shared.Physics;
using JetBrains.Annotations;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Map;
using Robust.Shared.Maths;
using Robust.Shared.Serialization;
using System.Linq;
using Robust.Shared.GameObjects;
using Robust.Shared.Physics;
using Robust.Shared.Serialization.Manager.Attributes;
namespace Content.Shared.Construction.ConstructionConditions
{
[UsedImplicitly]
[DataDefinition]
public class WallmountCondition : IConstructionCondition
{
void IExposeData.ExposeData(ObjectSerializer serializer) { }
public bool Condition(IEntity user, EntityCoordinates location, Direction direction)
{
var entManager = IoCManager.Resolve<IEntityManager>();

View File

@@ -1,23 +1,26 @@
#nullable enable
using System;
using System.Collections.Generic;
using Content.Shared.Interfaces;
using Robust.Shared.IoC;
using Robust.Shared.Serialization;
using Robust.Shared.Utility;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.ViewVariables;
using YamlDotNet.RepresentationModel;
namespace Content.Shared.Construction
{
[Serializable]
public class ConstructionGraphEdge : IExposeData
[DataDefinition]
public class ConstructionGraphEdge
{
[DataField("steps")]
private List<ConstructionGraphStep> _steps = new();
[DataField("conditions", serverOnly: true)]
private List<IEdgeCondition> _conditions = new();
[DataField("completed", serverOnly: true)]
private List<IGraphAction> _completed = new();
[ViewVariables]
[DataField("to")]
public string Target { get; private set; } = string.Empty;
[ViewVariables]
@@ -28,91 +31,5 @@ namespace Content.Shared.Construction
[ViewVariables]
public IReadOnlyList<ConstructionGraphStep> Steps => _steps;
void IExposeData.ExposeData(ObjectSerializer serializer)
{
InternalExposeData(serializer);
}
private void InternalExposeData(ObjectSerializer serializer)
{
var moduleManager = IoCManager.Resolve<IModuleManager>();
serializer.DataField(this, x => x.Target, "to", string.Empty);
if (!moduleManager.IsServerModule) return;
serializer.DataField(ref _conditions, "conditions", new List<IEdgeCondition>());
serializer.DataField(ref _completed, "completed", new List<IGraphAction>());
}
public void LoadFrom(YamlMappingNode mapping)
{
var serializer = YamlObjectSerializer.NewReader(mapping);
InternalExposeData(serializer);
if (!mapping.TryGetNode("steps", out YamlSequenceNode? stepsMapping)) return;
foreach (var yamlNode in stepsMapping)
{
var stepMapping = (YamlMappingNode) yamlNode;
_steps.Add(LoadStep(stepMapping));
}
}
public static ConstructionGraphStep LoadStep(YamlMappingNode mapping)
{
var stepSerializer = YamlObjectSerializer.NewReader(mapping);
if (mapping.TryGetNode("material", out _))
{
var material = new MaterialConstructionGraphStep();
material.ExposeData(stepSerializer);
return material;
}
if (mapping.TryGetNode("tool", out _))
{
var tool = new ToolConstructionGraphStep();
tool.ExposeData(stepSerializer);
return tool;
}
if (mapping.TryGetNode("prototype", out _))
{
var prototype = new PrototypeConstructionGraphStep();
prototype.ExposeData(stepSerializer);
return prototype;
}
if (mapping.TryGetNode("component", out _))
{
var component = new ComponentConstructionGraphStep();
component.ExposeData(stepSerializer);
return component;
}
if (mapping.TryGetNode("tag", out _))
{
var tags = new TagConstructionGraphStep();
tags.ExposeData(stepSerializer);
return tags;
}
if (mapping.TryGetNode("allTags", out _) || mapping.TryGetNode("anyTags", out _))
{
var tags = new MultipleTagsConstructionGraphStep();
tags.ExposeData(stepSerializer);
return tags;
}
if(mapping.TryGetNode("steps", out _))
{
var nested = new NestedConstructionGraphStep();
nested.ExposeData(stepSerializer);
nested.LoadFrom(mapping);
return nested;
}
throw new ArgumentException("Tried to convert invalid YAML node mapping to ConstructionGraphStep!");
}
}
}

View File

@@ -1,22 +1,22 @@
using System;
using System.Collections.Generic;
using Content.Shared.Interfaces;
using Robust.Shared.IoC;
using Robust.Shared.Serialization;
using Robust.Shared.Utility;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.ViewVariables;
using YamlDotNet.RepresentationModel;
using ObjectSerializer = Robust.Shared.Serialization.ObjectSerializer;
namespace Content.Shared.Construction
{
[Serializable]
[DataDefinition]
public class ConstructionGraphNode
{
[DataField("actions", serverOnly: true)]
private List<IGraphAction> _actions = new();
[DataField("edges")]
private List<ConstructionGraphEdge> _edges = new();
[ViewVariables]
[DataField("node")]
public string Name { get; private set; }
[ViewVariables]
@@ -26,34 +26,9 @@ namespace Content.Shared.Construction
public IReadOnlyList<IGraphAction> Actions => _actions;
[ViewVariables]
[DataField("entity")]
public string Entity { get; private set; }
public void ExposeData(ObjectSerializer serializer)
{
var moduleManager = IoCManager.Resolve<IModuleManager>();
serializer.DataField(this, x => x.Name, "node", string.Empty);
serializer.DataField(this, x => x.Entity, "entity",string.Empty);
if (!moduleManager.IsServerModule) return;
serializer.DataField(ref _actions, "actions", new List<IGraphAction>());
}
public void LoadFrom(YamlMappingNode mapping)
{
var serializer = YamlObjectSerializer.NewReader(mapping);
ExposeData(serializer);
if (!mapping.TryGetNode("edges", out YamlSequenceNode edgesMapping)) return;
foreach (var yamlNode in edgesMapping)
{
var edgeMapping = (YamlMappingNode) yamlNode;
var edge = new ConstructionGraphEdge();
edge.LoadFrom(edgeMapping);
_edges.Add(edge);
}
}
public ConstructionGraphEdge GetEdge(string target)
{
foreach (var edge in _edges)

View File

@@ -3,43 +3,41 @@ using System.Collections.Generic;
using System.IO;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
using Robust.Shared.Utility;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.ViewVariables;
using YamlDotNet.RepresentationModel;
namespace Content.Shared.Construction
{
[Prototype("constructionGraph")]
public class ConstructionGraphPrototype : IPrototype
public class ConstructionGraphPrototype : IPrototype, ISerializationHooks
{
private readonly Dictionary<string, ConstructionGraphNode> _nodes = new();
private readonly Dictionary<ValueTuple<string, string>, ConstructionGraphNode[]> _paths = new();
private readonly Dictionary<string, Dictionary<ConstructionGraphNode, ConstructionGraphNode>> _pathfinding = new();
[ViewVariables]
public string ID { get; private set; }
[field: DataField("id", required: true)]
public string ID { get; } = default!;
[field: DataField("parent")] public string Parent { get; }
[ViewVariables]
public string Start { get; private set; }
[field: DataField("start")]
public string Start { get; }
[DataField("graph", priority: 0)]
private List<ConstructionGraphNode> _graph = new();
[ViewVariables]
public IReadOnlyDictionary<string, ConstructionGraphNode> Nodes => _nodes;
public void LoadFrom(YamlMappingNode mapping)
void ISerializationHooks.AfterDeserialization()
{
var serializer = YamlObjectSerializer.NewReader(mapping);
_nodes.Clear();
serializer.DataField(this, x => x.ID, "id", string.Empty);
serializer.DataField(this, x => x.Start, "start", string.Empty);
if (!mapping.TryGetNode("graph", out YamlSequenceNode graphMapping)) return;
foreach (var yamlNode in graphMapping)
foreach (var graphNode in _graph)
{
var childMapping = (YamlMappingNode) yamlNode;
var node = new ConstructionGraphNode();
node.LoadFrom(childMapping);
_nodes[node.Name] = node;
_nodes[graphNode.Name] = graphNode;
}
if(string.IsNullOrEmpty(Start) || !_nodes.ContainsKey(Start))

View File

@@ -1,29 +1,21 @@
#nullable enable
using System;
using System.Collections.Generic;
using Content.Shared.Interfaces;
using Robust.Shared.IoC;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.Utility;
namespace Content.Shared.Construction
{
[Serializable]
public abstract class ConstructionGraphStep : IExposeData
[ImplicitDataDefinitionForInheritors]
public abstract class ConstructionGraphStep
{
private List<IGraphAction> _completed = new();
public float DoAfter { get; private set; }
[DataField("completed", serverOnly: true)] private List<IGraphAction> _completed = new();
[DataField("doAfter")] public float DoAfter { get; private set; }
public IReadOnlyList<IGraphAction> Completed => _completed;
public virtual void ExposeData(ObjectSerializer serializer)
{
var moduleManager = IoCManager.Resolve<IModuleManager>();
serializer.DataField(this, x => x.DoAfter, "doAfter", 0f);
if (!moduleManager.IsServerModule) return;
serializer.DataField(ref _completed, "completed", new List<IGraphAction>());
}
public abstract void DoExamine(FormattedMessage message, bool inDetailsRange);
}
}

View File

@@ -0,0 +1,76 @@
#nullable enable
using System;
using Robust.Shared.IoC;
using Robust.Shared.Serialization.Manager;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.Serialization.Manager.Result;
using Robust.Shared.Serialization.Markdown;
using Robust.Shared.Serialization.Markdown.Validation;
using Robust.Shared.Serialization.TypeSerializers.Interfaces;
namespace Content.Shared.Construction
{
[TypeSerializer]
public class ConstructionGraphStepTypeSerializer : ITypeReader<ConstructionGraphStep, MappingDataNode>
{
private Type? GetType(MappingDataNode node)
{
if (node.HasNode("material"))
{
return typeof(MaterialConstructionGraphStep);
}
else if (node.HasNode("tool"))
{
return typeof(ToolConstructionGraphStep);
}
else if (node.HasNode("prototype"))
{
return typeof(PrototypeConstructionGraphStep);
}
else if (node.HasNode("component"))
{
return typeof(ComponentConstructionGraphStep);
}
else if (node.HasNode("tag"))
{
return typeof(TagConstructionGraphStep);
}
else if (node.HasNode("allTags") || node.HasNode("anyTags"))
{
return typeof(MultipleTagsConstructionGraphStep);
}
else if (node.HasNode("steps"))
{
return typeof(NestedConstructionGraphStep);
}
else
{
return null;
}
}
public DeserializationResult Read(ISerializationManager serializationManager,
MappingDataNode node,
IDependencyCollection dependencies,
bool skipHook,
ISerializationContext? context = null)
{
var type = GetType(node) ??
throw new ArgumentException(
"Tried to convert invalid YAML node mapping to ConstructionGraphStep!");
return serializationManager.Read(type, node, context, skipHook);
}
public ValidationNode Validate(ISerializationManager serializationManager, MappingDataNode node,
IDependencyCollection dependencies,
ISerializationContext? context = null)
{
var type = GetType(node);
if (type == null) return new ErrorNode(node, "No construction graph step type found.", true);
return serializationManager.ValidateNode(type, node, context);
}
}
}

View File

@@ -1,85 +1,81 @@
#nullable enable
using System.Collections.Generic;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.Utility;
using YamlDotNet.RepresentationModel;
using Robust.Shared.ViewVariables;
namespace Content.Shared.Construction
{
[Prototype("construction")]
public class ConstructionPrototype : IPrototype
{
private List<IConstructionCondition> _conditions = new();
[DataField("conditions")] private List<IConstructionCondition> _conditions = new();
/// <summary>
/// Friendly name displayed in the construction GUI.
/// </summary>
public string Name { get; private set; } = string.Empty;
[field: DataField("name")]
public string Name { get; } = string.Empty;
/// <summary>
/// "Useful" description displayed in the construction GUI.
/// </summary>
public string Description { get; private set; } = string.Empty;
[field: DataField("description")]
public string Description { get; } = string.Empty;
/// <summary>
/// The <see cref="ConstructionGraphPrototype"/> this construction will be using.
/// </summary>
public string Graph { get; private set; } = string.Empty;
[field: DataField("graph")]
public string Graph { get; } = string.Empty;
/// <summary>
/// The target <see cref="ConstructionGraphNode"/> this construction will guide the user to.
/// </summary>
public string TargetNode { get; private set; } = string.Empty;
[field: DataField("targetNode")]
public string TargetNode { get; } = string.Empty;
/// <summary>
/// The starting <see cref="ConstructionGraphNode"/> this construction will start at.
/// </summary>
public string StartNode { get; private set; } = string.Empty;
[field: DataField("startNode")]
public string StartNode { get; } = string.Empty;
/// <summary>
/// Texture path inside the construction GUI.
/// </summary>
public SpriteSpecifier Icon { get; private set; } = SpriteSpecifier.Invalid;
[field: DataField("icon")]
public SpriteSpecifier Icon { get; } = SpriteSpecifier.Invalid;
/// <summary>
/// If you can start building or complete steps on impassable terrain.
/// </summary>
[DataField("canBuildInImpassable")]
public bool CanBuildInImpassable { get; private set; }
public string Category { get; private set; } = string.Empty;
[DataField("category")] public string Category { get; private set; } = string.Empty;
public ConstructionType Type { get; private set; } = ConstructionType.Structure;
[DataField("objectType")] public ConstructionType Type { get; private set; } = ConstructionType.Structure;
public string ID { get; private set; } = string.Empty;
[ViewVariables]
[field: DataField("id", required: true)]
public string ID { get; } = default!;
public string PlacementMode { get; private set; } = "PlaceFree";
[ViewVariables]
[field: DataField("parent")]
public string? Parent { get; }
[field: DataField("placementMode")]
public string PlacementMode { get; } = "PlaceFree";
/// <summary>
/// Whether this construction can be constructed rotated or not.
/// </summary>
public bool CanRotate { get; private set; }
[field: DataField("canRotate")]
public bool CanRotate { get; } = true;
public IReadOnlyList<IConstructionCondition> Conditions => _conditions;
public void LoadFrom(YamlMappingNode mapping)
{
var ser = YamlObjectSerializer.NewReader(mapping);
Name = ser.ReadDataField<string>("name");
ser.DataField(this, x => x.ID, "id", string.Empty);
ser.DataField(this, x => x.Graph, "graph", string.Empty);
ser.DataField(this, x => x.TargetNode, "targetNode", string.Empty);
ser.DataField(this, x => x.StartNode, "startNode", string.Empty);
ser.DataField(this, x => x.Description, "description", string.Empty);
ser.DataField(this, x => x.Icon, "icon", SpriteSpecifier.Invalid);
ser.DataField(this, x => x.Type, "objectType", ConstructionType.Structure);
ser.DataField(this, x => x.PlacementMode, "placementMode", "PlaceFree");
ser.DataField(this, x => x.CanBuildInImpassable, "canBuildInImpassable", false);
ser.DataField(this, x => x.Category, "category", string.Empty);
ser.DataField(this, x => x.CanRotate, "canRotate", true);
ser.DataField(ref _conditions, "conditions", new List<IConstructionCondition>());
}
}
public enum ConstructionType

View File

@@ -1,19 +1,13 @@
#nullable enable
using Robust.Shared.GameObjects;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.Manager.Attributes;
namespace Content.Shared.Construction
{
[ImplicitDataDefinitionForInheritors]
public abstract class EntityInsertConstructionGraphStep : ConstructionGraphStep
{
public string Store { get; private set; } = string.Empty;
public override void ExposeData(ObjectSerializer serializer)
{
base.ExposeData(serializer);
serializer.DataField(this, x => x.Store, "store", string.Empty);
}
[field: DataField("store")] public string Store { get; } = string.Empty;
public abstract bool EntityValid(IEntity entity);
}

View File

@@ -1,11 +1,10 @@
using Robust.Shared.GameObjects;
using Robust.Shared.Map;
using Robust.Shared.Maths;
using Robust.Shared.Serialization;
namespace Content.Shared.Construction
{
public interface IConstructionCondition : IExposeData
public interface IConstructionCondition
{
bool Condition(IEntity user, EntityCoordinates location, Direction direction);
}

View File

@@ -1,12 +1,11 @@
#nullable enable
using System.Threading.Tasks;
using Robust.Shared.GameObjects;
using Robust.Shared.Serialization;
using Robust.Shared.Utility;
namespace Content.Shared.Construction
{
public interface IEdgeCondition : IExposeData
public interface IEdgeCondition
{
Task<bool> Condition(IEntity entity);
bool DoExamine(IEntity entity, FormattedMessage message, bool inExamineRange) { return false; }

View File

@@ -1,11 +1,10 @@
#nullable enable
using System.Threading.Tasks;
using Robust.Shared.GameObjects;
using Robust.Shared.Serialization;
namespace Content.Shared.Construction
{
public interface IGraphAction : IExposeData
public interface IGraphAction
{
Task PerformAction(IEntity entity, IEntity? user);
}

View File

@@ -1,37 +1,28 @@
#nullable enable
using System.Diagnostics.CodeAnalysis;
using Content.Shared.GameObjects.Components;
using Content.Shared.Materials;
using Content.Shared.Stacks;
using JetBrains.Annotations;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.Utility;
namespace Content.Shared.Construction
{
[DataDefinition]
public class MaterialConstructionGraphStep : EntityInsertConstructionGraphStep
{
// TODO: Make this use the material system.
// TODO TODO: Make the material system not shit.
private string MaterialPrototypeId { get; [UsedImplicitly] set; } = default!;
[field: DataField("material")] public string MaterialPrototypeId { get; } = "Steel";
[field: DataField("amount")] public int Amount { get; } = 1;
public StackPrototype MaterialPrototype =>
IoCManager.Resolve<IPrototypeManager>().Index<StackPrototype>(MaterialPrototypeId);
public int Amount { get; private set; }
public override void ExposeData(ObjectSerializer serializer)
{
base.ExposeData(serializer);
serializer.DataField(this, x => x.MaterialPrototypeId, "material", "Steel");
serializer.DataField(this, x => x.Amount, "amount", 1);
}
public override void DoExamine(FormattedMessage message, bool inDetailsRange)
{
message.AddMarkup(Loc.GetString("Next, add [color=yellow]{0}x[/color] [color=cyan]{1}[/color].", Amount, MaterialPrototype.Name));

View File

@@ -1,24 +1,18 @@
#nullable enable
using System.Collections;
using System.Collections.Generic;
using Content.Shared.GameObjects.Components.Tag;
using Robust.Shared.GameObjects;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.Manager.Attributes;
namespace Content.Shared.Construction
{
public class MultipleTagsConstructionGraphStep : ArbitraryInsertConstructionGraphStep
{
private List<string>? _allTags = null;
private List<string>? _anyTags = null;
[DataField("allTags")]
private List<string>? _allTags;
public override void ExposeData(ObjectSerializer serializer)
{
base.ExposeData(serializer);
serializer.DataField(ref _allTags, "allTags", null);
serializer.DataField(ref _anyTags, "anyTags", null);
}
[DataField("anyTags")]
private List<string>? _anyTags;
private static bool IsNullOrEmpty<T>(ICollection<T>? list)
{

View File

@@ -1,36 +1,23 @@
#nullable enable
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.Utility;
using YamlDotNet.RepresentationModel;
namespace Content.Shared.Construction
{
public class NestedConstructionGraphStep : ConstructionGraphStep
[DataDefinition]
public class NestedConstructionGraphStep : ConstructionGraphStep, ISerializationHooks
{
public List<List<ConstructionGraphStep>> Steps { get; private set; } = new();
[DataField("steps")] public List<List<ConstructionGraphStep>> Steps { get; private set; } = new();
public void LoadFrom(YamlMappingNode mapping)
void ISerializationHooks.AfterDeserialization()
{
if (!mapping.TryGetNode("steps", out YamlSequenceNode? steps)) return;
foreach (var node in steps)
if (Steps.Any(inner => inner.Any(step => step is NestedConstructionGraphStep)))
{
var sequence = (YamlSequenceNode) node;
var list = new List<ConstructionGraphStep>();
foreach (var innerNode in sequence)
{
var stepNode = (YamlMappingNode) innerNode;
var step = ConstructionGraphEdge.LoadStep(stepNode);
if(step is NestedConstructionGraphStep)
throw new InvalidDataException("Can't have nested construction steps inside nested construction steps!");
list.Add(step);
}
Steps.Add(list);
throw new InvalidDataException("Can't have nested construction steps inside nested construction steps!");
}
}

View File

@@ -1,21 +1,15 @@
#nullable enable
using Robust.Shared.GameObjects;
using Robust.Shared.Localization;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.Utility;
namespace Content.Shared.Construction
{
[DataDefinition]
public class PrototypeConstructionGraphStep : ArbitraryInsertConstructionGraphStep
{
public string Prototype { get; private set; } = string.Empty;
public override void ExposeData(ObjectSerializer serializer)
{
base.ExposeData(serializer);
serializer.DataField(this, x => x.Prototype, "prototype", string.Empty);
}
[field: DataField("prototype")] public string Prototype { get; } = string.Empty;
public override bool EntityValid(IEntity entity)
{

View File

@@ -1,22 +1,16 @@
#nullable enable
using System.Collections.Generic;
using Content.Shared.GameObjects.Components.Tag;
using Robust.Shared.GameObjects;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.Manager.Attributes;
namespace Content.Shared.Construction
{
[DataDefinition]
public class TagConstructionGraphStep : ArbitraryInsertConstructionGraphStep
{
[DataField("tag")]
private string? _tag = null;
public override void ExposeData(ObjectSerializer serializer)
{
base.ExposeData(serializer);
serializer.DataField(ref _tag, "tag", null);
}
public override bool EntityValid(IEntity entity)
{
return !string.IsNullOrEmpty(_tag) && entity.HasTag(_tag);

View File

@@ -1,25 +1,19 @@
#nullable enable
using Content.Shared.GameObjects.Components.Interactable;
using Robust.Shared.Localization;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.Utility;
namespace Content.Shared.Construction
{
[DataDefinition]
public class ToolConstructionGraphStep : ConstructionGraphStep
{
public ToolQuality Tool { get; private set; }
public float Fuel { get; private set; }
public string ExamineOverride { get; private set; } = string.Empty;
[field: DataField("tool")] public ToolQuality Tool { get; } = ToolQuality.None;
public override void ExposeData(ObjectSerializer serializer)
{
base.ExposeData(serializer);
[field: DataField("fuel")] public float Fuel { get; } = 10;
serializer.DataField(this, x => x.Tool, "tool", ToolQuality.None);
serializer.DataField(this, x => x.Fuel, "fuel", 10f); // Default fuel cost.
serializer.DataField(this, x => x.ExamineOverride, "examine", string.Empty);
}
[field: DataField("examine")] public string ExamineOverride { get; } = string.Empty;
public override void DoExamine(FormattedMessage message, bool inDetailsRange)
{