Sericulture fixes (#19193)
* redone * I FUCKING HATE SPAWNING STUFF IN SHARED * inheritdoc * owo * fly broken wings * From a server event to just an event. * more info * a comment and a different comment * Partial * Emo's requested changes. * wuh * head ache * they call me mean names (laugh track)
This commit is contained in:
8
Content.Client/Sericulture/SericultureSystem.cs
Normal file
8
Content.Client/Sericulture/SericultureSystem.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
using Content.Shared.Sericulture;
|
||||||
|
|
||||||
|
namespace Content.Client.Sericulture;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <inheritdoc/>
|
||||||
|
/// </summary>
|
||||||
|
public sealed partial class SericultureSystem : SharedSericultureSystem { }
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
using Robust.Shared.Prototypes;
|
|
||||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
|
||||||
|
|
||||||
namespace Content.Server.Sericulture;
|
|
||||||
|
|
||||||
[RegisterComponent]
|
|
||||||
public sealed partial class SericultureComponent : Component
|
|
||||||
{
|
|
||||||
[DataField("popupText")]
|
|
||||||
public string PopupText = "sericulture-failure-hunger";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// What will be produced at the end of the action.
|
|
||||||
/// </summary>
|
|
||||||
[DataField("entityProduced", required: true)]
|
|
||||||
public string EntityProduced = "";
|
|
||||||
|
|
||||||
[DataField("action", customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
|
|
||||||
public string Action = "ActionSericulture";
|
|
||||||
|
|
||||||
[DataField("actionEntity")] public EntityUid? ActionEntity;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// How long will it take to make.
|
|
||||||
/// </summary>
|
|
||||||
[DataField("productionLength", required: true), ViewVariables(VVAccess.ReadWrite)]
|
|
||||||
public float ProductionLength = 0;
|
|
||||||
|
|
||||||
[DataField("hungerCost"), ViewVariables(VVAccess.ReadWrite)]
|
|
||||||
public float HungerCost = 0f;
|
|
||||||
}
|
|
||||||
@@ -1,89 +1,7 @@
|
|||||||
using Content.Server.Actions;
|
|
||||||
using Content.Server.DoAfter;
|
|
||||||
using Content.Server.Popups;
|
|
||||||
using Content.Server.Stack;
|
|
||||||
using Content.Shared.DoAfter;
|
|
||||||
using Content.Shared.Nutrition.Components;
|
|
||||||
using Content.Shared.Nutrition.EntitySystems;
|
|
||||||
using Content.Shared.Sericulture;
|
using Content.Shared.Sericulture;
|
||||||
|
|
||||||
namespace Content.Server.Sericulture;
|
namespace Content.Server.Sericulture;
|
||||||
|
|
||||||
public sealed partial class SericultureSystem : EntitySystem
|
public sealed partial class SericultureSystem : SharedSericultureSystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly ActionsSystem _actionsSystem = default!;
|
|
||||||
[Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
|
|
||||||
[Dependency] private readonly HungerSystem _hungerSystem = default!;
|
|
||||||
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
|
||||||
[Dependency] private readonly StackSystem _stackSystem = default!;
|
|
||||||
|
|
||||||
public override void Initialize()
|
|
||||||
{
|
|
||||||
base.Initialize();
|
|
||||||
|
|
||||||
SubscribeLocalEvent<SericultureComponent, MapInitEvent>(OnCompMapInit);
|
|
||||||
SubscribeLocalEvent<SericultureComponent, ComponentShutdown>(OnCompRemove);
|
|
||||||
SubscribeLocalEvent<SericultureComponent, SericultureActionEvent>(OnSericultureStart);
|
|
||||||
SubscribeLocalEvent<SericultureComponent, SericultureDoAfterEvent>(OnSericultureDoAfter);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnCompMapInit(EntityUid uid, SericultureComponent comp, MapInitEvent args)
|
|
||||||
{
|
|
||||||
_actionsSystem.AddAction(uid, ref comp.ActionEntity, comp.Action, uid);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnCompRemove(EntityUid uid, SericultureComponent comp, ComponentShutdown args)
|
|
||||||
{
|
|
||||||
_actionsSystem.RemoveAction(uid, comp.ActionEntity);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnSericultureStart(EntityUid uid, SericultureComponent comp, SericultureActionEvent args)
|
|
||||||
{
|
|
||||||
if (IsHungry(uid))
|
|
||||||
{
|
|
||||||
_popupSystem.PopupEntity(Loc.GetString(comp.PopupText), uid, uid);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var doAfter = new DoAfterArgs(EntityManager, uid, comp.ProductionLength, new SericultureDoAfterEvent(), uid)
|
|
||||||
{
|
|
||||||
BreakOnUserMove = true,
|
|
||||||
BlockDuplicate = true,
|
|
||||||
BreakOnDamage = true,
|
|
||||||
CancelDuplicate = true,
|
|
||||||
};
|
|
||||||
|
|
||||||
_doAfterSystem.TryStartDoAfter(doAfter);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnSericultureDoAfter(EntityUid uid, SericultureComponent comp, SericultureDoAfterEvent args)
|
|
||||||
{
|
|
||||||
if (args.Cancelled || args.Handled || comp.Deleted)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (IsHungry(uid))
|
|
||||||
{
|
|
||||||
_popupSystem.PopupEntity(Loc.GetString(comp.PopupText), uid, uid);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_hungerSystem.ModifyHunger(uid, -comp.HungerCost);
|
|
||||||
|
|
||||||
var newEntity = Spawn(comp.EntityProduced, Transform(uid).Coordinates);
|
|
||||||
|
|
||||||
_stackSystem.TryMergeToHands(newEntity, uid);
|
|
||||||
|
|
||||||
args.Repeat = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool IsHungry(EntityUid uid, HungerComponent? comp = null)
|
|
||||||
{
|
|
||||||
if (!Resolve(uid, ref comp))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (_hungerSystem.GetHungerThreshold(comp) <= HungerThreshold.Peckish)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -173,6 +173,17 @@ public sealed class HungerSystem : EntitySystem
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A check that returns if the entity is below a hunger threshold.
|
||||||
|
/// </summary>
|
||||||
|
public bool IsHungerBelowState(EntityUid uid, HungerThreshold threshold, float? food = null, HungerComponent? comp = null)
|
||||||
|
{
|
||||||
|
if (!Resolve(uid, ref comp))
|
||||||
|
return false; // It's never going to go hungry, so it's probably fine to assume that it's not... you know, hungry.
|
||||||
|
|
||||||
|
return GetHungerThreshold(comp, food) < threshold;
|
||||||
|
}
|
||||||
|
|
||||||
private bool GetMovementThreshold(HungerThreshold threshold)
|
private bool GetMovementThreshold(HungerThreshold threshold)
|
||||||
{
|
{
|
||||||
switch (threshold)
|
switch (threshold)
|
||||||
|
|||||||
66
Content.Shared/Sericulture/SericultureComponent.cs
Normal file
66
Content.Shared/Sericulture/SericultureComponent.cs
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
using Content.Shared.Nutrition.Components;
|
||||||
|
using Robust.Shared.GameStates;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||||
|
|
||||||
|
namespace Content.Shared.Sericulture;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Should be applied to any mob that you want to be able to produce any material with an action and the cost of hunger.
|
||||||
|
/// TODO: Probably adjust this to utilize organs?
|
||||||
|
/// </summary>
|
||||||
|
[RegisterComponent, NetworkedComponent, Access(typeof(SharedSericultureSystem))]
|
||||||
|
public sealed partial class SericultureComponent : Component
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The text that pops up whenever sericulture fails for not having enough hunger.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("popupText")]
|
||||||
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
[AutoNetworkedField]
|
||||||
|
public string PopupText = "sericulture-failure-hunger";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// What will be produced at the end of the action.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("entityProduced", required: true, customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
|
||||||
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
[AutoNetworkedField]
|
||||||
|
public string EntityProduced = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The entity needed to actually preform sericulture. This will be granted (and removed) upon the entity's creation.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("action", required: true, customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
|
||||||
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
[AutoNetworkedField]
|
||||||
|
public string Action = string.Empty;
|
||||||
|
|
||||||
|
[AutoNetworkedField]
|
||||||
|
[DataField("actionEntity")]
|
||||||
|
public EntityUid? ActionEntity;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// How long will it take to make.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("productionLength")]
|
||||||
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
[AutoNetworkedField]
|
||||||
|
public float ProductionLength = 3f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This will subtract (not add, don't get this mixed up) from the current hunger of the mob doing sericulture.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("hungerCost")]
|
||||||
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
[AutoNetworkedField]
|
||||||
|
public float HungerCost = 5f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The lowest hunger threshold that this mob can be in before it's allowed to spin silk.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("minHungerThreshold")]
|
||||||
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
[AutoNetworkedField]
|
||||||
|
public HungerThreshold MinHungerThreshold = HungerThreshold.Okay;
|
||||||
|
}
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
using Content.Shared.Actions;
|
|
||||||
using Content.Shared.DoAfter;
|
|
||||||
using Robust.Shared.Serialization;
|
|
||||||
|
|
||||||
namespace Content.Shared.Sericulture;
|
|
||||||
|
|
||||||
[Serializable, NetSerializable]
|
|
||||||
public sealed partial class SericultureDoAfterEvent : SimpleDoAfterEvent { }
|
|
||||||
|
|
||||||
public sealed partial class SericultureActionEvent : InstantActionEvent { }
|
|
||||||
109
Content.Shared/Sericulture/SericultureSystem.cs
Normal file
109
Content.Shared/Sericulture/SericultureSystem.cs
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
using Content.Shared.Actions;
|
||||||
|
using Content.Shared.DoAfter;
|
||||||
|
using Content.Shared.Nutrition.EntitySystems;
|
||||||
|
using Robust.Shared.Serialization;
|
||||||
|
using Content.Shared.Popups;
|
||||||
|
using Robust.Shared.Network;
|
||||||
|
using Content.Shared.Nutrition.Components;
|
||||||
|
using Content.Shared.Stacks;
|
||||||
|
|
||||||
|
namespace Content.Shared.Sericulture;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Allows mobs to produce materials with <see cref="SericultureComponent"/>.
|
||||||
|
/// </summary>
|
||||||
|
public abstract partial class SharedSericultureSystem : EntitySystem
|
||||||
|
{
|
||||||
|
// Managers
|
||||||
|
[Dependency] private readonly INetManager _netManager = default!;
|
||||||
|
|
||||||
|
// Systems
|
||||||
|
[Dependency] private readonly SharedActionsSystem _actionsSystem = default!;
|
||||||
|
[Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
|
||||||
|
[Dependency] private readonly HungerSystem _hungerSystem = default!;
|
||||||
|
[Dependency] private readonly SharedPopupSystem _popupSystem = default!;
|
||||||
|
[Dependency] private readonly SharedStackSystem _stackSystem = default!;
|
||||||
|
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
|
||||||
|
SubscribeLocalEvent<SericultureComponent, MapInitEvent>(OnMapInit);
|
||||||
|
SubscribeLocalEvent<SericultureComponent, ComponentShutdown>(OnCompRemove);
|
||||||
|
SubscribeLocalEvent<SericultureComponent, SericultureActionEvent>(OnSericultureStart);
|
||||||
|
SubscribeLocalEvent<SericultureComponent, SericultureDoAfterEvent>(OnSericultureDoAfter);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Giveths the action to preform sericulture on the entity
|
||||||
|
/// </summary>
|
||||||
|
private void OnMapInit(EntityUid uid, SericultureComponent comp, MapInitEvent args)
|
||||||
|
{
|
||||||
|
_actionsSystem.AddAction(uid, ref comp.ActionEntity, comp.Action);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Takeths away the action to preform sericulture from the entity.
|
||||||
|
/// </summary>
|
||||||
|
private void OnCompRemove(EntityUid uid, SericultureComponent comp, ComponentShutdown args)
|
||||||
|
{
|
||||||
|
_actionsSystem.RemoveAction(uid, comp.ActionEntity);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnSericultureStart(EntityUid uid, SericultureComponent comp, SericultureActionEvent args)
|
||||||
|
{
|
||||||
|
if (TryComp<HungerComponent>(uid, out var hungerComp)
|
||||||
|
&& _hungerSystem.IsHungerBelowState(uid, comp.MinHungerThreshold, hungerComp.CurrentHunger - comp.HungerCost, hungerComp))
|
||||||
|
{
|
||||||
|
_popupSystem.PopupClient(Loc.GetString(comp.PopupText), uid, uid);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var doAfter = new DoAfterArgs(EntityManager, uid, comp.ProductionLength, new SericultureDoAfterEvent(), uid)
|
||||||
|
{ // I'm not sure if more things should be put here, but imo ideally it should probably be set in the component/YAML. Not sure if this is currently possible.
|
||||||
|
BreakOnUserMove = true,
|
||||||
|
BlockDuplicate = true,
|
||||||
|
BreakOnDamage = true,
|
||||||
|
CancelDuplicate = true,
|
||||||
|
};
|
||||||
|
|
||||||
|
_doAfterSystem.TryStartDoAfter(doAfter);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void OnSericultureDoAfter(EntityUid uid, SericultureComponent comp, SericultureDoAfterEvent args)
|
||||||
|
{
|
||||||
|
if (args.Cancelled || args.Handled || comp.Deleted)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (TryComp<HungerComponent>(uid, out var hungerComp) // A check, just incase the doafter is somehow performed when the entity is not in the right hunger state.
|
||||||
|
&& _hungerSystem.IsHungerBelowState(uid, comp.MinHungerThreshold, hungerComp.CurrentHunger - comp.HungerCost, hungerComp))
|
||||||
|
{
|
||||||
|
_popupSystem.PopupClient(Loc.GetString(comp.PopupText), uid, uid);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_hungerSystem.ModifyHunger(uid, -comp.HungerCost);
|
||||||
|
|
||||||
|
if (!_netManager.IsClient) // Have to do this because spawning stuff in shared is CBT.
|
||||||
|
{
|
||||||
|
var newEntity = Spawn(comp.EntityProduced, Transform(uid).Coordinates);
|
||||||
|
|
||||||
|
_stackSystem.TryMergeToHands(newEntity, uid);
|
||||||
|
}
|
||||||
|
|
||||||
|
args.Repeat = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Should be relayed upon using the action.
|
||||||
|
/// </summary>
|
||||||
|
public sealed partial class SericultureActionEvent : InstantActionEvent { }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Is relayed at the end of the sericulturing doafter.
|
||||||
|
/// </summary>
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public sealed partial class SericultureDoAfterEvent : SimpleDoAfterEvent { }
|
||||||
|
|
||||||
Reference in New Issue
Block a user