Predict ReactionMixerSystem (#41218)
* predict * documentation * review
This commit is contained in:
parent
2692b91189
commit
4f4945d8c6
|
|
@ -1,81 +0,0 @@
|
|||
using Content.Shared.Chemistry.Components;
|
||||
using Content.Shared.Chemistry.Reaction;
|
||||
using Content.Shared.DoAfter;
|
||||
using Content.Shared.IdentityManagement;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Nutrition.EntitySystems;
|
||||
using Content.Shared.Chemistry.EntitySystems;
|
||||
using Content.Server.Popups;
|
||||
|
||||
namespace Content.Server.Chemistry.EntitySystems;
|
||||
|
||||
public sealed partial class ReactionMixerSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly PopupSystem _popup = default!;
|
||||
[Dependency] private readonly SharedSolutionContainerSystem _solutionContainers = default!;
|
||||
[Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<ReactionMixerComponent, AfterInteractEvent>(OnAfterInteract, before: [typeof(IngestionSystem)]);
|
||||
SubscribeLocalEvent<ReactionMixerComponent, ShakeEvent>(OnShake);
|
||||
SubscribeLocalEvent<ReactionMixerComponent, ReactionMixDoAfterEvent>(OnDoAfter);
|
||||
}
|
||||
|
||||
private void OnAfterInteract(Entity<ReactionMixerComponent> entity, ref AfterInteractEvent args)
|
||||
{
|
||||
if (!args.Target.HasValue || !args.CanReach || !entity.Comp.MixOnInteract)
|
||||
return;
|
||||
|
||||
if (!MixAttempt(entity, args.Target.Value, out _))
|
||||
return;
|
||||
|
||||
var doAfterArgs = new DoAfterArgs(EntityManager, args.User, entity.Comp.TimeToMix, new ReactionMixDoAfterEvent(), entity, args.Target.Value, entity);
|
||||
|
||||
_doAfterSystem.TryStartDoAfter(doAfterArgs);
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
private void OnDoAfter(Entity<ReactionMixerComponent> entity, ref ReactionMixDoAfterEvent args)
|
||||
{
|
||||
//Do again to get the solution again
|
||||
if (!MixAttempt(entity, args.Target!.Value, out var solution))
|
||||
return;
|
||||
|
||||
_popup.PopupEntity(Loc.GetString(entity.Comp.MixMessage, ("mixed", Identity.Entity(args.Target!.Value, EntityManager)), ("mixer", Identity.Entity(entity.Owner, EntityManager))), args.User, args.User);
|
||||
|
||||
_solutionContainers.UpdateChemicals(solution!.Value, true, entity.Comp);
|
||||
|
||||
var afterMixingEvent = new AfterMixingEvent(entity, args.Target!.Value);
|
||||
RaiseLocalEvent(entity, afterMixingEvent);
|
||||
}
|
||||
|
||||
private void OnShake(Entity<ReactionMixerComponent> entity, ref ShakeEvent args)
|
||||
{
|
||||
if (!MixAttempt(entity, entity, out var solution))
|
||||
return;
|
||||
|
||||
_solutionContainers.UpdateChemicals(solution!.Value, true, entity.Comp);
|
||||
|
||||
var afterMixingEvent = new AfterMixingEvent(entity, entity);
|
||||
RaiseLocalEvent(entity, afterMixingEvent);
|
||||
}
|
||||
|
||||
private bool MixAttempt(EntityUid ent, EntityUid target, out Entity<SolutionComponent>? solution)
|
||||
{
|
||||
solution = null;
|
||||
var mixAttemptEvent = new MixingAttemptEvent(ent);
|
||||
RaiseLocalEvent(ent, ref mixAttemptEvent);
|
||||
if (mixAttemptEvent.Cancelled)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!_solutionContainers.TryGetMixableSolution(target, out solution, out _))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,48 +1,43 @@
|
|||
using Content.Shared.Chemistry.Components;
|
||||
using Content.Shared.DoAfter;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared.Chemistry.Reaction;
|
||||
|
||||
[RegisterComponent]
|
||||
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
|
||||
public sealed partial class ReactionMixerComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// A list of IDs for categories of reactions that can be mixed (i.e. HOLY for a bible, DRINK for a spoon)
|
||||
/// A list of IDs for categories of reactions that can be mixed (i.e. HOLY for a bible, DRINK for a spoon).
|
||||
/// </summary>
|
||||
[ViewVariables]
|
||||
[DataField]
|
||||
public List<ProtoId<MixingCategoryPrototype>> ReactionTypes = default!;
|
||||
[DataField, AutoNetworkedField]
|
||||
public List<ProtoId<MixingCategoryPrototype>> ReactionTypes = new();
|
||||
|
||||
/// <summary>
|
||||
/// A string which identifies the string to be sent when successfully mixing a solution
|
||||
/// The popup message when successfully mixing a solution.
|
||||
/// </summary>
|
||||
[ViewVariables]
|
||||
[DataField]
|
||||
[DataField, AutoNetworkedField]
|
||||
public LocId MixMessage = "default-mixing-success";
|
||||
|
||||
/// <summary>
|
||||
/// Defines if interacting is enough to mix with this component
|
||||
/// Defines if interacting is enough to mix with this component.
|
||||
/// </summary>
|
||||
[ViewVariables]
|
||||
[DataField]
|
||||
[DataField, AutoNetworkedField]
|
||||
public bool MixOnInteract = true;
|
||||
|
||||
/// <summary>
|
||||
/// How long it takes to mix with this
|
||||
/// How long it takes to mix with this.
|
||||
/// </summary>
|
||||
[ViewVariables]
|
||||
[DataField]
|
||||
[DataField, AutoNetworkedField]
|
||||
public TimeSpan TimeToMix = TimeSpan.Zero;
|
||||
}
|
||||
|
||||
[ByRefEvent]
|
||||
public record struct MixingAttemptEvent(EntityUid Mixed, bool Cancelled = false);
|
||||
|
||||
[ByRefEvent]
|
||||
public readonly record struct AfterMixingEvent(EntityUid Mixed, EntityUid Mixer);
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed partial class ReactionMixDoAfterEvent : SimpleDoAfterEvent
|
||||
{
|
||||
}
|
||||
public sealed partial class ReactionMixDoAfterEvent : SimpleDoAfterEvent;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,109 @@
|
|||
using Content.Shared.Chemistry.Components;
|
||||
using Content.Shared.DoAfter;
|
||||
using Content.Shared.IdentityManagement;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Nutrition.EntitySystems;
|
||||
using Content.Shared.Chemistry.EntitySystems;
|
||||
using Content.Shared.Popups;
|
||||
|
||||
namespace Content.Shared.Chemistry.Reaction;
|
||||
|
||||
public sealed partial class ReactionMixerSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly SharedPopupSystem _popup = default!;
|
||||
[Dependency] private readonly SharedSolutionContainerSystem _solutionContainer = default!;
|
||||
[Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<ReactionMixerComponent, AfterInteractEvent>(OnAfterInteract, before: [typeof(IngestionSystem)]);
|
||||
SubscribeLocalEvent<ReactionMixerComponent, ShakeEvent>(OnShake);
|
||||
SubscribeLocalEvent<ReactionMixerComponent, ReactionMixDoAfterEvent>(OnDoAfter);
|
||||
}
|
||||
|
||||
private void OnAfterInteract(Entity<ReactionMixerComponent> ent, ref AfterInteractEvent args)
|
||||
{
|
||||
if (!args.Target.HasValue || !args.CanReach || !ent.Comp.MixOnInteract)
|
||||
return;
|
||||
|
||||
if (!CanMix(ent.AsNullable(), args.Target.Value))
|
||||
return;
|
||||
|
||||
var doAfterArgs = new DoAfterArgs(EntityManager, args.User, ent.Comp.TimeToMix, new ReactionMixDoAfterEvent(), ent, args.Target.Value, ent);
|
||||
|
||||
_doAfter.TryStartDoAfter(doAfterArgs);
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
private void OnDoAfter(Entity<ReactionMixerComponent> ent, ref ReactionMixDoAfterEvent args)
|
||||
{
|
||||
if (args.Target == null)
|
||||
return;
|
||||
|
||||
if (!TryMix(ent.AsNullable(), args.Target.Value))
|
||||
return;
|
||||
|
||||
_popup.PopupClient(
|
||||
Loc.GetString(
|
||||
ent.Comp.MixMessage,
|
||||
("mixed", Identity.Entity(args.Target.Value, EntityManager)),
|
||||
("mixer", Identity.Entity(ent.Owner, EntityManager))),
|
||||
args.User,
|
||||
args.User);
|
||||
}
|
||||
|
||||
private void OnShake(Entity<ReactionMixerComponent> ent, ref ShakeEvent args)
|
||||
{
|
||||
TryMix(ent.AsNullable(), ent);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if given reaction mixer is able to mix the solution inside the target entity, false otherwise.
|
||||
/// </summary>
|
||||
/// <param name="ent">The reaction mixer used to cause the reaction.</param>
|
||||
/// <param name="target">The target solution container with a <see cref="MixableSolutionComponent"/>.</param>
|
||||
public bool CanMix(Entity<ReactionMixerComponent?> ent, EntityUid target)
|
||||
{
|
||||
if (!Resolve(ent, ref ent.Comp, false)) // The used entity needs the component to be able to mix a solution
|
||||
return false;
|
||||
|
||||
var mixAttemptEvent = new MixingAttemptEvent(ent);
|
||||
RaiseLocalEvent(ent, ref mixAttemptEvent);
|
||||
if (mixAttemptEvent.Cancelled)
|
||||
return false;
|
||||
|
||||
if (!_solutionContainer.TryGetMixableSolution(target, out _, out _))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to mix the solution inside the target entity using the given reaction mixer.
|
||||
/// </summary>
|
||||
/// <param name="ent">The reaction mixer used to cause the reaction.</param>
|
||||
/// <param name="target">The target solution container with a <see cref="MixableSolutionComponent"/>.</param>
|
||||
/// <returns>If the reaction mixer was able to mix the solution. This does not necessarily mean a reaction took place.</returns>
|
||||
public bool TryMix(Entity<ReactionMixerComponent?> ent, EntityUid target)
|
||||
{
|
||||
if (!Resolve(ent, ref ent.Comp, false))
|
||||
return false;
|
||||
|
||||
var mixAttemptEvent = new MixingAttemptEvent(ent);
|
||||
RaiseLocalEvent(ent, ref mixAttemptEvent);
|
||||
if (mixAttemptEvent.Cancelled)
|
||||
return false;
|
||||
|
||||
if (!_solutionContainer.TryGetMixableSolution(target, out var solutionEnt, out _))
|
||||
return false;
|
||||
|
||||
_solutionContainer.UpdateChemicals(solutionEnt.Value, true, ent.Comp);
|
||||
|
||||
var afterMixingEvent = new AfterMixingEvent(ent, target);
|
||||
RaiseLocalEvent(ent, ref afterMixingEvent);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue