2023-10-01 21:46:09 +01:00
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.
2024-03-19 12:09:00 +02:00
BreakOnMove = true ,
2023-10-01 21:46:09 +01:00
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 { }