* 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

@@ -1,86 +0,0 @@
using System.Collections.Generic;
using Content.Server.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.Server.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";
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,152 @@
using System.Collections.Generic;
using Content.Server.GameObjects.Components.Stack;
using Content.Server.GameObjects.EntitySystems;
using Content.Shared.GameObjects.Components.Materials;
using Content.Shared.GameObjects.Components.Research;
using Content.Shared.Research;
using Robust.Server.GameObjects.Components.UserInterface;
using Robust.Server.Interfaces.GameObjects;
using Robust.Shared.GameObjects.Components.UserInterface;
using Robust.Shared.IoC;
using Robust.Shared.Prototypes;
using Robust.Shared.Timers;
using Robust.Shared.Utility;
using Robust.Shared.ViewVariables;
namespace Content.Server.GameObjects.Components.Research
{
public class LatheComponent : SharedLatheComponent, IAttackHand, IAttackBy, IActivate
{
public const int VolumePerSheet = 3750;
private BoundUserInterface _userInterface;
[ViewVariables]
public Queue<LatheRecipePrototype> Queue { get; } = new Queue<LatheRecipePrototype>();
[ViewVariables]
public bool Producing { get; private set; } = false;
private LatheRecipePrototype _producingRecipe = null;
public override void Initialize()
{
base.Initialize();
_userInterface = Owner.GetComponent<ServerUserInterfaceComponent>().GetBoundUserInterface(LatheUiKey.Key);
_userInterface.OnReceiveMessage += UserInterfaceOnOnReceiveMessage;
}
private void UserInterfaceOnOnReceiveMessage(BoundUserInterfaceMessage message)
{
switch (message)
{
case LatheQueueRecipeMessage msg:
_prototypeManager.TryIndex(msg.ID, out LatheRecipePrototype recipe);
if (recipe != null)
for (var i = 0; i < msg.Quantity; i++)
{
Queue.Enqueue(recipe);
_userInterface.SendMessage(new LatheFullQueueMessage(GetIDQueue()));
}
break;
case LatheSyncRequestMessage msg:
if (!Owner.TryGetComponent(out MaterialStorageComponent storage)) return;
_userInterface.SendMessage(new LatheFullQueueMessage(GetIDQueue()));
if (_producingRecipe != null)
_userInterface.SendMessage(new LatheProducingRecipeMessage(_producingRecipe.ID));
break;
}
}
internal bool Produce(LatheRecipePrototype recipe)
{
if (Producing || !CanProduce(recipe) || !Owner.TryGetComponent(out MaterialStorageComponent storage)) return false;
_userInterface.SendMessage(new LatheFullQueueMessage(GetIDQueue()));
Producing = true;
_producingRecipe = recipe;
foreach (var (material, amount) in recipe.RequiredMaterials)
{
// This should always return true, otherwise CanProduce fucked up.
storage.RemoveMaterial(material, amount);
}
_userInterface.SendMessage(new LatheProducingRecipeMessage(recipe.ID));
Timer.Spawn(recipe.CompleteTime, () =>
{
Producing = false;
_producingRecipe = null;
Owner.EntityManager.TrySpawnEntityAt(recipe.Result, Owner.Transform.GridPosition, out var entity);
_userInterface.SendMessage(new LatheStoppedProducingRecipeMessage());
});
return true;
}
void IActivate.Activate(ActivateEventArgs eventArgs)
{
if (!eventArgs.User.TryGetComponent(out IActorComponent actor))
return;
_userInterface.Open(actor.playerSession);
return;
}
bool IAttackHand.AttackHand(AttackHandEventArgs eventArgs)
{
if (!eventArgs.User.TryGetComponent(out IActorComponent actor))
return false;
_userInterface.Open(actor.playerSession);
return true;
}
bool IAttackBy.AttackBy(AttackByEventArgs eventArgs)
{
if (!Owner.TryGetComponent(out MaterialStorageComponent storage)
|| !eventArgs.AttackWith.TryGetComponent(out MaterialComponent material)) return false;
var multiplier = 1;
if (eventArgs.AttackWith.TryGetComponent(out StackComponent stack)) multiplier = stack.Count;
var totalAmount = 0;
// Check if it can insert all materials.
foreach (var mat in material.MaterialTypes.Values)
{
// TODO: Change how MaterialComponent works so this is not hard-coded.
if (!storage.CanInsertMaterial(mat.ID, VolumePerSheet * multiplier)) return false;
totalAmount += VolumePerSheet * multiplier;
}
// Check if it can take ALL of the material's volume.
if (storage.CanTakeAmount(totalAmount)) return false;
foreach (var mat in material.MaterialTypes.Values)
{
storage.InsertMaterial(mat.ID, VolumePerSheet * multiplier);
}
eventArgs.AttackWith.Delete();
return false;
}
private Queue<string> GetIDQueue()
{
var queue = new Queue<string>();
foreach (var recipePrototype in Queue)
{
queue.Enqueue(recipePrototype.ID);
}
return queue;
}
}
}

View File

@@ -0,0 +1,60 @@
using System.Collections.Generic;
using Content.Shared.GameObjects.Components.Research;
using Content.Shared.Research;
using Robust.Shared.GameObjects;
using Robust.Shared.Serialization;
namespace Content.Server.GameObjects.Components.Research
{
public class LatheDatabaseComponent : SharedLatheDatabaseComponent
{
/// <summary>
/// Whether new recipes can be added to this database or not.
/// </summary>
public bool Static => _static;
private bool _static = false;
public override ComponentState GetComponentState()
{
return new LatheDatabaseState(GetRecipeIdList());
}
public override void ExposeData(ObjectSerializer serializer)
{
base.ExposeData(serializer);
serializer.DataField(ref _static, "static", false);
}
public override void Clear()
{
if (Static) return;
Dirty();
}
public override void AddRecipe(LatheRecipePrototype recipe)
{
if (Static) return;
Dirty();
}
public override bool RemoveRecipe(LatheRecipePrototype recipe)
{
if (Static || !base.RemoveRecipe(recipe)) return false;
Dirty();
return true;
}
private List<string> GetRecipeIdList()
{
var list = new List<string>();
foreach (var recipe in this)
{
list.Add(recipe.ID);
}
return list;
}
}
}

View File

@@ -0,0 +1,83 @@
using System.Collections.Generic;
using Content.Shared.GameObjects.Components.Research;
using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.Network;
using Robust.Shared.Serialization;
namespace Content.Server.GameObjects.Components.Research
{
public class MaterialStorageComponent : SharedMaterialStorageComponent
{
protected override Dictionary<string, int> Storage { get; set; } = new Dictionary<string, int>();
/// <summary>
/// How much material the storage can store in total.
/// </summary>
public int StorageLimit => _storageLimit;
private int _storageLimit;
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);
}
public override void ExposeData(ObjectSerializer serializer)
{
base.ExposeData(serializer);
serializer.DataField(ref _storageLimit, "StorageLimit", -1);
}
}
}

View File

@@ -0,0 +1,26 @@
using Content.Server.GameObjects.Components.Research;
using Robust.Shared.GameObjects;
using Robust.Shared.GameObjects.Systems;
namespace Content.Server.GameObjects.EntitySystems
{
public class LatheSystem : EntitySystem
{
public override void Initialize()
{
EntityQuery = new TypeEntityQuery(typeof(LatheComponent));
}
public override void Update(float frameTime)
{
foreach (var entity in RelevantEntities)
{
var comp = entity.GetComponent<LatheComponent>();
if (comp.Producing == false && comp.Queue.Count > 0)
{
comp.Produce(comp.Queue.Dequeue());
}
}
}
}
}