Lathe Refactor and ECS (#11201)
* lathe and material storage refactor * materialStorage ECS it kinda sus tho * beginning the lathe shitcode dive * couple lathe visuals and lathe system * lathe changes and such * dynamic lathe databases * rewrote internal logic on to ui * da newI * material display clientside * misc ui changes * component state handling and various other things * moar * Update Content.Shared/Lathe/LatheComponent.cs Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> * first volley of sloth review * more fixes * losin' my mind * all da changes * test fix and other review Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com>
This commit is contained in:
@@ -1,41 +0,0 @@
|
||||
using Content.Shared.Lathe;
|
||||
using Content.Shared.Research.Prototypes;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List;
|
||||
using Robust.Shared.Audio;
|
||||
|
||||
namespace Content.Server.Lathe.Components
|
||||
{
|
||||
[RegisterComponent]
|
||||
public sealed class LatheComponent : SharedLatheComponent
|
||||
{
|
||||
/// <summary>
|
||||
/// The lathe's construction queue
|
||||
/// </summary>
|
||||
[DataField("queue", customTypeSerializer: typeof(PrototypeIdListSerializer<LatheRecipePrototype>))]
|
||||
public List<string> Queue { get; } = new();
|
||||
// TODO queue serializer.
|
||||
|
||||
/// <summary>
|
||||
/// How long the inserting animation will play
|
||||
/// </summary>
|
||||
[ViewVariables]
|
||||
public float InsertionTime = 0.79f; // 0.01 off for animation timing
|
||||
/// <summary>
|
||||
/// Update accumulator for the insertion time
|
||||
/// </suummary>
|
||||
[DataField("insertionAccumulator")]
|
||||
public float InsertionAccumulator = 0f;
|
||||
|
||||
/// <summary>
|
||||
/// The sound that plays when the lathe is producing an item, if any
|
||||
/// </summary>
|
||||
[DataField("producingSound")]
|
||||
public SoundSpecifier? ProducingSound;
|
||||
|
||||
/// <summmary>
|
||||
/// The lathe's UI.
|
||||
/// </summary>
|
||||
[ViewVariables] public BoundUserInterface? UserInterface;
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
using Content.Shared.Lathe;
|
||||
using Content.Shared.Research.Prototypes;
|
||||
|
||||
namespace Content.Server.Lathe.Components
|
||||
{
|
||||
[RegisterComponent]
|
||||
[ComponentReference(typeof(SharedLatheDatabaseComponent))]
|
||||
public sealed class LatheDatabaseComponent : SharedLatheDatabaseComponent
|
||||
{
|
||||
/// <summary>
|
||||
/// Whether new recipes can be added to this database or not.
|
||||
/// </summary>
|
||||
[ViewVariables]
|
||||
[DataField("static")]
|
||||
public bool Static { get; private set; } = false;
|
||||
|
||||
public override ComponentState GetComponentState()
|
||||
{
|
||||
return new LatheDatabaseState(GetRecipeIdList());
|
||||
}
|
||||
|
||||
public override void Clear()
|
||||
{
|
||||
if (Static) return;
|
||||
base.Clear();
|
||||
Dirty();
|
||||
}
|
||||
|
||||
public override void AddRecipe(LatheRecipePrototype recipe)
|
||||
{
|
||||
if (Static) return;
|
||||
base.AddRecipe(recipe);
|
||||
Dirty();
|
||||
}
|
||||
|
||||
public override bool RemoveRecipe(LatheRecipePrototype recipe)
|
||||
{
|
||||
if (Static || !base.RemoveRecipe(recipe)) return false;
|
||||
Dirty();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@ namespace Content.Server.Lathe.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// For EntityQuery to keep track of which lathes are inserting
|
||||
/// <summary>
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
public sealed class LatheInsertingComponent : Component
|
||||
{
|
||||
|
||||
@@ -1,24 +1,15 @@
|
||||
using Content.Shared.Research.Prototypes;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
namespace Content.Server.Lathe.Components;
|
||||
|
||||
namespace Content.Server.Lathe.Components
|
||||
/// <summary>
|
||||
/// For EntityQuery to keep track of which lathes are producing
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
public sealed class LatheProducingComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// For EntityQuery to keep track of which lathes are producing
|
||||
/// <summary>
|
||||
[RegisterComponent]
|
||||
public sealed class LatheProducingComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// The recipe the lathe is currently producing
|
||||
/// </summary>
|
||||
[DataField("recipe", required:true, customTypeSerializer:typeof(PrototypeIdSerializer<LatheRecipePrototype>))]
|
||||
public string? Recipe;
|
||||
|
||||
/// <summary>
|
||||
/// Remaining production time, in seconds.
|
||||
/// </summary>
|
||||
[DataField("timeRemaining", required: true)]
|
||||
public float TimeRemaining;
|
||||
}
|
||||
/// How much production time has passed, in seconds.
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public float AccumulatedTime;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,110 +0,0 @@
|
||||
using Content.Shared.Lathe;
|
||||
using Content.Shared.Whitelist;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List;
|
||||
using Content.Shared.Materials;
|
||||
using Robust.Shared.Audio;
|
||||
|
||||
namespace Content.Server.Lathe.Components
|
||||
{
|
||||
[RegisterComponent]
|
||||
[ComponentReference(typeof(SharedMaterialStorageComponent))]
|
||||
public sealed class MaterialStorageComponent : SharedMaterialStorageComponent
|
||||
{
|
||||
[ViewVariables]
|
||||
protected override Dictionary<string, int> Storage { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// How much material the storage can store in total.
|
||||
/// </summary>
|
||||
[ViewVariables]
|
||||
public int StorageLimit => _storageLimit;
|
||||
[DataField("StorageLimit")]
|
||||
private int _storageLimit = -1;
|
||||
|
||||
/// <summary>
|
||||
/// Whitelist for specifying the kind of items that can be insert into this entity.
|
||||
/// </summary>
|
||||
[ViewVariables]
|
||||
[DataField("whitelist")]
|
||||
public EntityWhitelist? EntityWhitelist;
|
||||
|
||||
/// <summary>
|
||||
/// Whitelist generated on runtime for what specific materials can be inserted into this entity.
|
||||
/// </summary>
|
||||
[ViewVariables]
|
||||
[DataField("materialWhiteList", customTypeSerializer: typeof(PrototypeIdListSerializer<MaterialPrototype>))]
|
||||
public List<string> MaterialWhiteList = new();
|
||||
|
||||
/// <summary>
|
||||
/// The sound that plays when inserting an item into the storage
|
||||
/// </summary>
|
||||
[DataField("insertingSound")]
|
||||
public SoundSpecifier? InsertingSound;
|
||||
|
||||
public override ComponentState GetComponentState()
|
||||
{
|
||||
return new MaterialStorageState(Storage);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the storage can take a volume of material without surpassing its own limits.
|
||||
/// </summary>
|
||||
/// <param name="amount">The volume of material</param>
|
||||
/// <returns></returns>
|
||||
public bool CanTakeAmount(int amount)
|
||||
{
|
||||
return CurrentAmount + amount <= StorageLimit;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if it can insert a material.
|
||||
/// </summary>
|
||||
/// <param name="id">Material ID</param>
|
||||
/// <param name="amount">How much to insert</param>
|
||||
/// <returns>Whether it can insert the material or not.</returns>
|
||||
public bool CanInsertMaterial(string id, int amount)
|
||||
{
|
||||
return (CanTakeAmount(amount) || StorageLimit < 0) && (!Storage.ContainsKey(id) || Storage[id] + amount >= 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inserts material into the storage.
|
||||
/// </summary>
|
||||
/// <param name="id">Material ID</param>
|
||||
/// <param name="amount">How much to insert</param>
|
||||
/// <returns>Whether it inserted it or not.</returns>
|
||||
public bool InsertMaterial(string id, int amount)
|
||||
{
|
||||
if (!CanInsertMaterial(id, amount)) return false;
|
||||
|
||||
if (!Storage.ContainsKey(id))
|
||||
Storage.Add(id, 0);
|
||||
|
||||
Storage[id] += amount;
|
||||
|
||||
Dirty();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes material from the storage.
|
||||
/// </summary>
|
||||
/// <param name="id">Material ID</param>
|
||||
/// <param name="amount">How much to remove</param>
|
||||
/// <returns>Whether it removed it or not.</returns>
|
||||
public bool RemoveMaterial(string id, int amount)
|
||||
{
|
||||
return InsertMaterial(id, -amount);
|
||||
}
|
||||
|
||||
// forgive me I needed to write a crumb of e/c code to not go fucking insane i swear i will ecs this entire shitty fucking system one day
|
||||
public int GetMaterialAmount(string id)
|
||||
{
|
||||
if (!Storage.TryGetValue(id, out var amount))
|
||||
return 0;
|
||||
|
||||
return amount;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
using System.Linq;
|
||||
using Content.Server.Research.Components;
|
||||
using Content.Shared.Lathe;
|
||||
using Content.Shared.Research.Prototypes;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server.Lathe.Components
|
||||
{
|
||||
[RegisterComponent]
|
||||
[ComponentReference(typeof(SharedLatheDatabaseComponent))]
|
||||
public sealed class ProtolatheDatabaseComponent : SharedProtolatheDatabaseComponent
|
||||
{
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
|
||||
public override ComponentState GetComponentState()
|
||||
{
|
||||
return new ProtolatheDatabaseState(GetRecipeIdList());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds unlocked recipes from technologies to the database.
|
||||
/// </summary>
|
||||
public void Sync()
|
||||
{
|
||||
if (!IoCManager.Resolve<IEntityManager>().TryGetComponent(Owner, out TechnologyDatabaseComponent? database)) return;
|
||||
|
||||
foreach (var technology in database.Technologies)
|
||||
{
|
||||
foreach (var id in technology.UnlockedRecipes)
|
||||
{
|
||||
var recipe = (LatheRecipePrototype) _prototypeManager.Index(typeof(LatheRecipePrototype), id);
|
||||
UnlockRecipe(recipe);
|
||||
}
|
||||
}
|
||||
|
||||
Dirty();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unlocks a recipe but only if it's one of the allowed recipes on this protolathe.
|
||||
/// </summary>
|
||||
/// <param name="recipe">The recipe</param>
|
||||
/// <returns>Whether it could add it or not.</returns>
|
||||
public bool UnlockRecipe(LatheRecipePrototype recipe)
|
||||
{
|
||||
if (!ProtolatheRecipes.Contains(recipe)) return false;
|
||||
|
||||
AddRecipe(recipe);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user