* Recipe stuff.

* Lathe GUI and stuff

* god dammit

* Lathe menu works, yay.

* EventArgs henk

* Some work

* SS14 -> Robust

* More SS14 -> Robust

* Lathe materials

* Lathe works, Lathe GUI, Queue GUI, etc

too many changes to name them here

* Remove materials button, add ViewVariables and update lathe on connect

* Add Autolathe RSI

* Adds new recipes, fixes a few bugs.

* Remove unused ScrollContainers

* Use same delegate for spawn.

* Removes client-side LatheComponent in favor of BoundUserInterface

* Remove GetMaterial and TryGetMaterial

* Use auto-properties in a few places.

* Adds LatheDatabase, and a bunch of other changes

* Remove useless log.

* Remove lathetype from prototypes.

* Turns Storage, Lathe and Database into autoproperties

* Remove Hacked property from LatheRecipePrototype

* Remove unneeded dependency injection from components

* Refactors LatheDatabaseComponent to use ComponentState

* Refactors MaterialStorageComponent to use ComponentState

* Oopsie

* Another oopsie

* Last oopsie, I hope

* Fix missing Close call.
This commit is contained in:
Víctor Aguilera Puerto
2019-04-26 15:51:05 +02:00
committed by Pieter-Jan Briers
parent 092539ae59
commit fe0414eda7
37 changed files with 1580 additions and 13 deletions

View File

@@ -74,9 +74,13 @@
<Compile Include="GameObjects\Components\Items\ClothingComponentState.cs" />
<Compile Include="GameObjects\Components\Items\ItemComponentState.cs" />
<Compile Include="GameObjects\Components\Markers\SharedSpawnPointComponent.cs" />
<Compile Include="GameObjects\Components\Materials\MaterialComponent.cs" />
<Compile Include="GameObjects\Components\Mobs\SharedCameraRecoilComponent.cs" />
<Compile Include="GameObjects\Components\Power\PowerShared.cs" />
<Compile Include="GameObjects\Components\Power\SharedPowerCellComponent.cs" />
<Compile Include="GameObjects\Components\Research\SharedLatheComponent.cs" />
<Compile Include="GameObjects\Components\Research\SharedLatheDatabaseComponent.cs" />
<Compile Include="GameObjects\Components\Research\SharedMaterialStorageComponent.cs" />
<Compile Include="GameObjects\Components\Sound\SharedSoundComponent.cs" />
<Compile Include="GameObjects\Components\Storage\SharedStorageComponent.cs" />
<Compile Include="GameObjects\Components\Weapons\Ranged\SharedBallisticMagazineComponent.cs" />
@@ -90,6 +94,7 @@
<Compile Include="Interfaces\ISharedNotifyManager.cs" />
<Compile Include="GameObjects\Verb.cs" />
<Compile Include="Maps\ContentTileDefinition.cs" />
<Compile Include="Materials\Material.cs" />
<Compile Include="Physics\CollisionGroup.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="GameObjects\Components\Items\SharedHandsComponent.cs" />
@@ -100,6 +105,7 @@
<ItemGroup>
<None Include="app.config" />
<Compile Include="Input\ContentKeyFunctions.cs" />
<Compile Include="Research\LatheRecipePrototype.cs" />
<Compile Include="SharedGameTicker.cs" />
<Compile Include="SharedNotifyManager.cs" />
<Compile Include="Utility\ContentHelpers.cs" />

View File

@@ -0,0 +1,87 @@
using System.Collections.Generic;
using Content.Shared.Materials;
using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.Reflection;
using Robust.Shared.Interfaces.Serialization;
using Robust.Shared.IoC;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
using Robust.Shared.Utility;
namespace Content.Shared.GameObjects.Components.Materials
{
/// <summary>
/// Component to store data such as "this object is made out of steel".
/// This is not a storage system for say smelteries.
/// </summary>
public class MaterialComponent : Component
{
public const string SerializationCache = "mat";
public override string Name => "Material";
public Dictionary<object, Material> MaterialTypes => _materialTypes;
private Dictionary<object, Material> _materialTypes;
public override void ExposeData(ObjectSerializer serializer)
{
base.ExposeData(serializer);
// TODO: Writing.
if (!serializer.Reading)
{
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>();
int index = 0;
foreach (var entry in list)
{
var proto = protoMan.Index<MaterialPrototype>(entry.Value);
_materialTypes[entry.Key] = proto.Material;
index++;
}
}
serializer.SetCacheData(SerializationCache, _materialTypes.ShallowClone());
}
class MaterialDataEntry : IExposeData
{
public object Key;
public string Value;
public void ExposeData(ObjectSerializer serializer)
{
if (!serializer.Reading)
{
return;
}
var refl = IoCManager.Resolve<IReflectionManager>();
Value = serializer.ReadDataField<string>("mat");
var key = serializer.ReadDataField<string>("key");
if (refl.TryParseEnumReference(key, out var @enum))
{
Key = @enum;
return;
}
Key = key;
}
}
}
public enum MaterialKeys
{
Stack,
}
}

View File

@@ -0,0 +1,116 @@
using System;
using System.Collections.Generic;
using Content.Shared.Materials;
using Content.Shared.Research;
using Mono.Cecil;
using Robust.Shared.GameObjects;
using Robust.Shared.GameObjects.Components.UserInterface;
using Robust.Shared.IoC;
using Robust.Shared.Log;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
using Robust.Shared.Utility;
using Robust.Shared.ViewVariables;
namespace Content.Shared.GameObjects.Components.Research
{
public class SharedLatheComponent : Component
{
public override string Name => "Lathe";
public override uint? NetID => ContentNetIDs.LATHE;
#pragma warning disable CS0649
[Dependency]
protected IPrototypeManager _prototypeManager;
#pragma warning restore
public bool CanProduce(LatheRecipePrototype recipe, int quantity = 1)
{
if (!Owner.TryGetComponent(out SharedMaterialStorageComponent storage)
|| !Owner.TryGetComponent(out SharedLatheDatabaseComponent database)) return false;
if (!database.Contains(recipe)) return false;
foreach (var (material, amount) in recipe.RequiredMaterials)
{
if (storage[material] <= (amount * quantity)) return false;
}
return true;
}
public bool CanProduce(string ID, int quantity = 1)
{
return _prototypeManager.TryIndex(ID, out LatheRecipePrototype recipe) && CanProduce(recipe, quantity);
}
/// <summary>
/// Sent to the server to sync material storage and the recipe queue.
/// </summary>
[Serializable, NetSerializable]
public class LatheSyncRequestMessage : BoundUserInterfaceMessage
{
public LatheSyncRequestMessage()
{
}
}
/// <summary>
/// Sent to the client when the lathe is producing a recipe.
/// </summary>
[Serializable, NetSerializable]
public class LatheProducingRecipeMessage : BoundUserInterfaceMessage
{
public readonly string ID;
public LatheProducingRecipeMessage(string id)
{
ID = id;
}
}
/// <summary>
/// Sent to the client when the lathe stopped/finished producing a recipe.
/// </summary>
[Serializable, NetSerializable]
public class LatheStoppedProducingRecipeMessage : BoundUserInterfaceMessage
{
public LatheStoppedProducingRecipeMessage()
{
}
}
/// <summary>
/// Sent to the client to let it know about the recipe queue.
/// </summary>
[Serializable, NetSerializable]
public class LatheFullQueueMessage : BoundUserInterfaceMessage
{
public readonly Queue<string> Recipes;
public LatheFullQueueMessage(Queue<string> recipes)
{
Recipes = recipes;
}
}
/// <summary>
/// Sent to the server when a client queues a new recipe.
/// </summary>
[Serializable, NetSerializable]
public class LatheQueueRecipeMessage : BoundUserInterfaceMessage
{
public readonly string ID;
public readonly int Quantity;
public LatheQueueRecipeMessage(string id, int quantity)
{
ID = id;
Quantity = quantity;
}
}
[NetSerializable, Serializable]
public enum LatheUiKey
{
Key,
}
}
}

View File

@@ -0,0 +1,107 @@
using System;
using System.Collections;
using System.Collections.Generic;
using Content.Shared.Research;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Log;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
namespace Content.Shared.GameObjects.Components.Research
{
public class SharedLatheDatabaseComponent : Component, IEnumerable<LatheRecipePrototype>
{
public override string Name => "LatheDatabase";
public sealed override uint? NetID => ContentNetIDs.LATHE_DATABASE;
public sealed override Type StateType => typeof(LatheDatabaseState);
private List<LatheRecipePrototype> _recipes = new List<LatheRecipePrototype>();
/// <summary>
/// Removes all recipes from the database if it's not static.
/// </summary>
/// <returns>Whether it could clear the database or not.</returns>
public virtual void Clear()
{
_recipes.Clear();
}
/// <summary>
/// Adds a recipe to the database if it's not static.
/// </summary>
/// <param name="recipe">The recipe to be added.</param>
/// <returns>Whether it could be added or not</returns>
public virtual void AddRecipe(LatheRecipePrototype recipe)
{
_recipes.Add(recipe);
}
/// <summary>
/// Removes a recipe from the database if it's not static.
/// </summary>
/// <param name="recipe">The recipe to be removed.</param>
/// <returns>Whether it could be removed or not</returns>
public virtual bool RemoveRecipe(LatheRecipePrototype recipe)
{
return _recipes.Remove(recipe);
}
/// <summary>
/// Returns whether the database contains the recipe or not.
/// </summary>
/// <param name="recipe">The recipe to check</param>
/// <returns>Whether the database contained the recipe or not.</returns>
public virtual bool Contains(LatheRecipePrototype recipe)
{
return _recipes.Contains(recipe);
}
/// <summary>
/// Returns whether the database contains the recipe or not.
/// </summary>
/// <param name="id">The recipe id to check</param>
/// <returns>Whether the database contained the recipe or not.</returns>
public virtual bool Contains(string id)
{
foreach (var recipe in _recipes)
{
if (recipe.ID == id) return true;
}
return false;
}
public override void ExposeData(ObjectSerializer serializer)
{
base.ExposeData(serializer);
var recipes = serializer.ReadDataField("recipes", new List<string>());
var prototypeManager = IoCManager.Resolve<IPrototypeManager>();
foreach (var id in recipes)
{
if (!prototypeManager.TryIndex(id, out LatheRecipePrototype recipe)) continue;
_recipes.Add(recipe);
}
}
public IEnumerator<LatheRecipePrototype> GetEnumerator()
{
return _recipes.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
[NetSerializable, Serializable]
public class LatheDatabaseState : ComponentState
{
public readonly List<string> Recipes;
public LatheDatabaseState(List<string> recipes) : base(ContentNetIDs.LATHE_DATABASE)
{
Recipes = recipes;
}
}
}

View File

@@ -0,0 +1,78 @@
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;
namespace Content.Shared.GameObjects.Components.Research
{
public class SharedMaterialStorageComponent : Component, IEnumerable<KeyValuePair<string, int>>
{
[ViewVariables]
protected virtual Dictionary<string, int> Storage { get; set; }
public override string Name => "MaterialStorage";
public sealed override uint? NetID => ContentNetIDs.MATERIAL_STORAGE;
public sealed override Type StateType => typeof(MaterialStorageState);
public int this[string ID]
{
get
{
if (!Storage.ContainsKey(ID))
return 0;
return Storage[ID];
}
}
public int this[Material material]
{
get
{
var ID = material.ID;
if (!Storage.ContainsKey(ID))
return 0;
return Storage[ID];
}
}
/// <summary>
/// The total volume of material stored currently.
/// </summary>
[ViewVariables] public int CurrentAmount
{
get
{
var value = 0;
foreach (var amount in Storage.Values)
{
value += amount;
}
return value;
}
}
public IEnumerator<KeyValuePair<string, int>> GetEnumerator()
{
return Storage.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
[NetSerializable, Serializable]
public class MaterialStorageState : ComponentState
{
public readonly Dictionary<string, int> Storage;
public MaterialStorageState(Dictionary<string, int> storage) : base(ContentNetIDs.MATERIAL_STORAGE)
{
Storage = storage;
}
}
}

View File

@@ -18,5 +18,8 @@
public const uint ITEM = 1013;
public const uint CLOTHING = 1014;
public const uint ENTITYSTORAGE = 1015;
public const uint LATHE = 1016;
public const uint LATHE_DATABASE = 1017;
public const uint MATERIAL_STORAGE = 1018;
}
}

View File

@@ -0,0 +1,131 @@
using Robust.Shared.Interfaces.Serialization;
using Robust.Shared.IoC;
using Robust.Shared.Maths;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
using Robust.Shared.Utility;
using YamlDotNet.RepresentationModel;
namespace Content.Shared.Materials
{
/// <summary>
/// Materials are read-only storage for the properties of specific materials.
/// Properties should be intrinsic (or at least as much is necessary for game purposes).
/// </summary>
public class Material : IExposeData
{
public string Name => _name;
private string _name = "unobtanium";
public Color Color => _color;
private Color _color = Color.Gray;
/// <summary>
/// Volumetric mass density, in kg.m^-3.
/// </summary>
public double Density => _density;
private double _density = 1;
/// <summary>
/// Electrical resistivity, NOT resistance.
/// Unit is ohm-meter (Ω⋅m).
/// </summary>
public double ElectricResistivity => _electricResistivity;
private double _electricResistivity = 1;
/// <summary>
/// Thermal conductivity, in W.m-1.K-1
/// </summary>
public double ThermalConductivity => _thermalConductivity;
private double _thermalConductivity = 1;
/// <summary>
/// Specific heat, in J.kg-1.K-1
/// </summary>
public double SpecificHeat => _specificHeat;
private double _specificHeat = 1;
/// <summary>
/// Controls how durable the material is.
/// Basically how slowly it degrades.
/// </summary>
public double Durability => _durability;
private double _durability = 1;
/// <summary>
/// Multiplier for how much this resists damage.
/// So higher means armor is more effective, for example.
/// </summary>
public double Hardness => _hardness;
private double _hardness = 1;
/// <summary>
/// Multiplier that determines damage on sharpness-based weapons like knives.
/// Higher means more damage is done.
/// </summary>
public double SharpDamage => _sharpDamage;
private double _sharpDamage = 1;
/// <summary>
/// Multiplier that determines damage on blunt-based weapons like clubs.
/// Higher means more damage is done.
/// </summary>
public double BluntDamage => _bluntDamage;
private double _bluntDamage = 1;
/// <summary>
/// An icon used to represent the material in graphic interfaces.
/// </summary>
public SpriteSpecifier Icon => _icon;
private SpriteSpecifier _icon = SpriteSpecifier.Invalid;
public string ID
{
get
{
var prototypeManager = IoCManager.Resolve<IPrototypeManager>();
foreach (var prototype in prototypeManager.EnumeratePrototypes<MaterialPrototype>())
{
if (prototype.Material == this) return prototype.ID;
}
return null;
}
}
public void ExposeData(ObjectSerializer serializer)
{
serializer.DataField(ref _name, "name", "unobtanium", alwaysWrite: true);
serializer.DataField(ref _color, "color", Color.Gray, alwaysWrite: true);
// All default material params are initialized to 1 because
// I'm too lazy to figure out for which that's necessary to prevent divisions by zero in case left out.
serializer.DataField(ref _density, "density", 1, alwaysWrite: true);
serializer.DataField(ref _electricResistivity, "electricresistivity", 1, alwaysWrite: true);
serializer.DataField(ref _thermalConductivity, "thermalconductivity", 1, alwaysWrite: true);
serializer.DataField(ref _specificHeat, "specificheat", 1, alwaysWrite: true);
serializer.DataField(ref _durability, "durability", 1, alwaysWrite: true);
serializer.DataField(ref _hardness, "hardness", 1, alwaysWrite: true);
serializer.DataField(ref _sharpDamage, "sharpdamage", 1, alwaysWrite: true);
serializer.DataField(ref _bluntDamage, "bluntdamage", 1, alwaysWrite: true);
serializer.DataField(ref _icon, "icon", SpriteSpecifier.Invalid, alwaysWrite: true);
}
}
[Prototype("material")]
public class MaterialPrototype : IPrototype, IIndexedPrototype
{
public string ID { get; private set; }
public Material Material { get; private set; }
public void LoadFrom(YamlMappingNode mapping)
{
ID = mapping["id"].AsString();
var ser = YamlObjectSerializer.NewReader(mapping);
Material = new Material();
Material.ExposeData(ser);
}
}
}

View File

@@ -0,0 +1,100 @@
using System;
using System.Collections.Generic;
using Content.Shared.GameObjects.Components.Research;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
using Robust.Shared.Utility;
using YamlDotNet.RepresentationModel;
namespace Content.Shared.Research
{
[NetSerializable, Serializable, Prototype("latheRecipe")]
public class LatheRecipePrototype : IPrototype, IIndexedPrototype
{
private string _name;
private string _id;
private SpriteSpecifier _icon;
private string _description;
private string _result;
private int _completeTime;
private Dictionary<string, int> _requiredMaterials;
public string ID => _id;
/// <summary>
/// Name displayed in the lathe GUI.
/// </summary>
public string Name
{
get
{
if (_name.Trim().Length != 0) return _name;
var protoMan = IoCManager.Resolve<IPrototypeManager>();
if (protoMan == null) return _description;
protoMan.TryIndex(_result, out EntityPrototype prototype);
if (prototype?.Name != null)
_name = prototype.Name;
return _name;
}
}
/// <summary>
/// Short description displayed in the lathe GUI.
/// </summary>
public string Description
{
get
{
if (_description.Trim().Length != 0) return _description;
var protoMan = IoCManager.Resolve<IPrototypeManager>();
if (protoMan == null) return _description;
protoMan.TryIndex(_result, out EntityPrototype prototype);
if (prototype?.Description != null)
_description = prototype.Description;
return _description;
}
}
/// <summary>
/// Texture path used in the lathe GUI.
/// </summary>
public SpriteSpecifier Icon => _icon;
/// <summary>
/// The prototype name of the resulting entity when the recipe is printed.
/// </summary>
public string Result => _result;
/// <summary>
/// The materials required to produce this recipe.
/// Takes a material ID as string.
/// </summary>
public Dictionary<string, int> RequiredMaterials
{
get => _requiredMaterials;
private set => _requiredMaterials = value;
}
/// <summary>
/// How many milliseconds it'll take for the lathe to finish this recipe.
/// Might lower depending on the lathe's upgrade level.
/// </summary>
public int CompleteTime => _completeTime;
public void LoadFrom(YamlMappingNode mapping)
{
var serializer = YamlObjectSerializer.NewReader(mapping);
serializer.DataField(ref _name, "name", string.Empty);
serializer.DataField(ref _id, "id", string.Empty);
serializer.DataField(ref _description, "description", string.Empty);
serializer.DataField(ref _icon, "icon", SpriteSpecifier.Invalid);
serializer.DataField(ref _result, "result", null);
serializer.DataField(ref _completeTime, "completetime", 2500);
serializer.DataField(ref _requiredMaterials, "materials", new Dictionary<string, int>());
}
}
}

View File

@@ -0,0 +1,65 @@
using SS14.Shared.Prototypes;
using SS14.Shared.Serialization;
using SS14.Shared.Utility;
using YamlDotNet.RepresentationModel;
namespace Content.Shared.Research
{
[Prototype("latheRecipe")]
public class LatheRecipePrototype : IPrototype, IIndexedPrototype
{
private string _name;
private string _id;
private SpriteSpecifier _icon;
private string _description;
private string _result;
private bool _hacked;
private string _latheType;
public string ID => _id;
/// <summary>
/// Name displayed in the lathe GUI.
/// </summary>
public string Name => _name;
/// <summary>
/// Short description displayed in the lathe GUI.
/// </summary>
public string Description => _description;
/// <summary>
/// Texture path used in the lathe GUI.
/// </summary>
public SpriteSpecifier Icon => _icon;
/// <summary>
/// The prototype name of the resulting entity when the recipe is printed.
/// </summary>
public string Result => _result;
/// <summary>
/// Whether the lathe should be hacked to unlock this recipe.
/// </summary>
public bool Hacked => _hacked;
/// <summary>
/// The type of lathe that'll print this recipe.
/// TODO: Replace with an enum before merging, henk!
/// </summary>
public string LatheType => _latheType;
public void LoadFrom(YamlMappingNode mapping)
{
var serializer = YamlObjectSerializer.NewReader(mapping);
_name = serializer.ReadDataField<string>("name");
serializer.DataField(ref _id, "id", string.Empty);
serializer.DataField(ref _description, "description", string.Empty);
serializer.DataField(ref _icon, "icon", SpriteSpecifier.Invalid);
serializer.DataField(ref _result, "result", null);
serializer.DataField(ref _hacked, "hacked", false);
serializer.DataField(ref _latheType, "lathetype", "default");
}
}
}