Predict passive welding fuel consumption (#38876)
* predict welding fuel consumption * autopaused * review Co-authored-by: ArtisticRoomba <145879011+ArtisticRoomba@users.noreply.github.com> --------- Co-authored-by: ArtisticRoomba <145879011+ArtisticRoomba@users.noreply.github.com>
This commit is contained in:
@@ -1,47 +1,5 @@
|
|||||||
using Content.Shared.Chemistry.Components.SolutionManager;
|
using Content.Shared.Tools.Systems;
|
||||||
using Content.Shared.FixedPoint;
|
|
||||||
using Content.Shared.Tools.Components;
|
|
||||||
|
|
||||||
using SharedToolSystem = Content.Shared.Tools.Systems.SharedToolSystem;
|
|
||||||
|
|
||||||
namespace Content.Server.Tools;
|
namespace Content.Server.Tools;
|
||||||
|
|
||||||
public sealed class ToolSystem : SharedToolSystem
|
public sealed class ToolSystem : SharedToolSystem;
|
||||||
{
|
|
||||||
public override void Update(float frameTime)
|
|
||||||
{
|
|
||||||
base.Update(frameTime);
|
|
||||||
|
|
||||||
UpdateWelders(frameTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
//todo move to shared once you can remove reagents from shared without it freaking out.
|
|
||||||
private void UpdateWelders(float frameTime)
|
|
||||||
{
|
|
||||||
var query = EntityQueryEnumerator<WelderComponent, SolutionContainerManagerComponent>();
|
|
||||||
while (query.MoveNext(out var uid, out var welder, out var solutionContainer))
|
|
||||||
{
|
|
||||||
if (!welder.Enabled)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
welder.WelderTimer += frameTime;
|
|
||||||
|
|
||||||
if (welder.WelderTimer < welder.WelderUpdateTimer)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!SolutionContainerSystem.TryGetSolution((uid, solutionContainer), welder.FuelSolutionName, out var solutionComp, out var solution))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
SolutionContainerSystem.RemoveReagent(solutionComp.Value, welder.FuelReagent, welder.FuelConsumption * welder.WelderTimer);
|
|
||||||
|
|
||||||
if (solution.GetTotalPrototypeQuantity(welder.FuelReagent) <= FixedPoint2.Zero)
|
|
||||||
{
|
|
||||||
ItemToggle.Toggle(uid, predicted: false);
|
|
||||||
}
|
|
||||||
|
|
||||||
Dirty(uid, welder);
|
|
||||||
welder.WelderTimer -= welder.WelderUpdateTimer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,58 +1,76 @@
|
|||||||
using Content.Shared.Chemistry.Components;
|
|
||||||
using Content.Shared.Chemistry.Reagent;
|
using Content.Shared.Chemistry.Reagent;
|
||||||
using Content.Shared.FixedPoint;
|
using Content.Shared.FixedPoint;
|
||||||
using Content.Shared.Tools.Systems;
|
using Content.Shared.Tools.Systems;
|
||||||
using Robust.Shared.Audio;
|
using Robust.Shared.Audio;
|
||||||
using Robust.Shared.GameStates;
|
using Robust.Shared.GameStates;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
|
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
|
||||||
|
|
||||||
namespace Content.Shared.Tools.Components;
|
namespace Content.Shared.Tools.Components;
|
||||||
|
|
||||||
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState(true), Access(typeof(SharedToolSystem))]
|
/// <summary>
|
||||||
|
/// Handles fuel consumption for the tool and allows it to explode welding fuel tanks.
|
||||||
|
/// </summary>
|
||||||
|
/// <summary>
|
||||||
|
/// TODO: De-hardcode welder bombing.
|
||||||
|
/// </summary>
|
||||||
|
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState(true), AutoGenerateComponentPause]
|
||||||
|
[Access(typeof(SharedToolSystem))]
|
||||||
public sealed partial class WelderComponent : Component
|
public sealed partial class WelderComponent : Component
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Is the welder currently enabled?
|
||||||
|
/// </summary>
|
||||||
[DataField, AutoNetworkedField]
|
[DataField, AutoNetworkedField]
|
||||||
public bool Enabled;
|
public bool Enabled;
|
||||||
|
|
||||||
[DataField]
|
/// <summary>
|
||||||
public float WelderTimer;
|
/// Timestamp for the next update loop update.
|
||||||
|
/// </summary>
|
||||||
|
[DataField(customTypeSerializer: typeof(TimeOffsetSerializer))]
|
||||||
|
[AutoNetworkedField, AutoPausedField]
|
||||||
|
public TimeSpan NextUpdate;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Name of <see cref="FuelSolution"/>.
|
/// Delay between updates.
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public TimeSpan WelderUpdateTimer = TimeSpan.FromSeconds(1);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Name of the fuel solution.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField]
|
[DataField]
|
||||||
public string FuelSolutionName = "Welder";
|
public string FuelSolutionName = "Welder";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Reagent that will be used as fuel for welding.
|
/// Reagent that will be used as fuel for welding.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField]
|
[DataField]
|
||||||
public ProtoId<ReagentPrototype> FuelReagent = "WeldingFuel";
|
public ProtoId<ReagentPrototype> FuelReagent = "WeldingFuel";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Fuel consumption per second while the welder is active.
|
/// Fuel consumption per second while the welder is active.
|
||||||
|
/// In u/s
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField, AutoNetworkedField]
|
[DataField, AutoNetworkedField]
|
||||||
public FixedPoint2 FuelConsumption = FixedPoint2.New(1.0f);
|
public FixedPoint2 FuelConsumption = FixedPoint2.New(1.0f);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A fuel amount to be consumed when the welder goes from being unlit to being lit.
|
/// A fuel amount to be consumed when the welder goes from being unlit to being lit.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField, AutoNetworkedField]
|
[DataField, AutoNetworkedField]
|
||||||
public FixedPoint2 FuelLitCost = FixedPoint2.New(0.5f);
|
public FixedPoint2 FuelLitCost = FixedPoint2.New(0.5f);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sound played when refilling the welder.
|
/// Sound played when refilling the welder.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField]
|
[DataField]
|
||||||
public SoundSpecifier WelderRefill = new SoundPathSpecifier("/Audio/Effects/refill.ogg");
|
public SoundSpecifier WelderRefill = new SoundPathSpecifier("/Audio/Effects/refill.ogg");
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether the item is safe to refill while lit without exploding the tank.
|
/// Whether the item is safe to refill while lit without exploding the tank.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField]
|
[DataField]
|
||||||
public bool TankSafe;
|
public bool TankSafe;
|
||||||
|
|
||||||
[DataField]
|
|
||||||
public float WelderUpdateTimer = 1f;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,13 +17,16 @@ public abstract partial class SharedToolSystem
|
|||||||
|
|
||||||
public void InitializeWelder()
|
public void InitializeWelder()
|
||||||
{
|
{
|
||||||
|
SubscribeLocalEvent<WelderComponent, MapInitEvent>(OnWelderInit);
|
||||||
SubscribeLocalEvent<WelderComponent, ExaminedEvent>(OnWelderExamine);
|
SubscribeLocalEvent<WelderComponent, ExaminedEvent>(OnWelderExamine);
|
||||||
SubscribeLocalEvent<WelderComponent, AfterInteractEvent>(OnWelderAfterInteract);
|
SubscribeLocalEvent<WelderComponent, AfterInteractEvent>(OnWelderAfterInteract);
|
||||||
|
|
||||||
SubscribeLocalEvent<WelderComponent, ToolUseAttemptEvent>((uid, comp, ev) => {
|
SubscribeLocalEvent<WelderComponent, ToolUseAttemptEvent>((uid, comp, ev) =>
|
||||||
|
{
|
||||||
CanCancelWelderUse((uid, comp), ev.User, ev.Fuel, ev);
|
CanCancelWelderUse((uid, comp), ev.User, ev.Fuel, ev);
|
||||||
});
|
});
|
||||||
SubscribeLocalEvent<WelderComponent, DoAfterAttemptEvent<ToolDoAfterEvent>>((uid, comp, ev) => {
|
SubscribeLocalEvent<WelderComponent, DoAfterAttemptEvent<ToolDoAfterEvent>>((uid, comp, ev) =>
|
||||||
|
{
|
||||||
CanCancelWelderUse((uid, comp), ev.Event.User, ev.Event.Fuel, ev);
|
CanCancelWelderUse((uid, comp), ev.Event.User, ev.Event.Fuel, ev);
|
||||||
});
|
});
|
||||||
SubscribeLocalEvent<WelderComponent, ToolDoAfterEvent>(OnWelderDoAfter);
|
SubscribeLocalEvent<WelderComponent, ToolDoAfterEvent>(OnWelderDoAfter);
|
||||||
@@ -71,6 +74,12 @@ public abstract partial class SharedToolSystem
|
|||||||
return (fuelSolution.GetTotalPrototypeQuantity(welder.FuelReagent), fuelSolution.MaxVolume);
|
return (fuelSolution.GetTotalPrototypeQuantity(welder.FuelReagent), fuelSolution.MaxVolume);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnWelderInit(Entity<WelderComponent> ent, ref MapInitEvent args)
|
||||||
|
{
|
||||||
|
ent.Comp.NextUpdate = _timing.CurTime + ent.Comp.WelderUpdateTimer;
|
||||||
|
Dirty(ent);
|
||||||
|
}
|
||||||
|
|
||||||
private void OnWelderExamine(Entity<WelderComponent> entity, ref ExaminedEvent args)
|
private void OnWelderExamine(Entity<WelderComponent> entity, ref ExaminedEvent args)
|
||||||
{
|
{
|
||||||
using (args.PushGroup(nameof(WelderComponent)))
|
using (args.PushGroup(nameof(WelderComponent)))
|
||||||
@@ -169,7 +178,8 @@ public abstract partial class SharedToolSystem
|
|||||||
|
|
||||||
private void OnActivateAttempt(Entity<WelderComponent> entity, ref ItemToggleActivateAttemptEvent args)
|
private void OnActivateAttempt(Entity<WelderComponent> entity, ref ItemToggleActivateAttemptEvent args)
|
||||||
{
|
{
|
||||||
if (args.User != null && !_actionBlocker.CanComplexInteract(args.User.Value)) {
|
if (args.User != null && !_actionBlocker.CanComplexInteract(args.User.Value))
|
||||||
|
{
|
||||||
args.Cancelled = true;
|
args.Cancelled = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -191,9 +201,34 @@ public abstract partial class SharedToolSystem
|
|||||||
|
|
||||||
private void OnDeactivateAttempt(Entity<WelderComponent> entity, ref ItemToggleDeactivateAttemptEvent args)
|
private void OnDeactivateAttempt(Entity<WelderComponent> entity, ref ItemToggleDeactivateAttemptEvent args)
|
||||||
{
|
{
|
||||||
if (args.User != null && !_actionBlocker.CanComplexInteract(args.User.Value)) {
|
if (args.User != null && !_actionBlocker.CanComplexInteract(args.User.Value))
|
||||||
|
{
|
||||||
args.Cancelled = true;
|
args.Cancelled = true;
|
||||||
return;
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateWelders()
|
||||||
|
{
|
||||||
|
var query = EntityQueryEnumerator<WelderComponent, SolutionContainerManagerComponent>();
|
||||||
|
var curTime = _timing.CurTime;
|
||||||
|
while (query.MoveNext(out var uid, out var welder, out var solutionContainer))
|
||||||
|
{
|
||||||
|
if (curTime < welder.NextUpdate)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
welder.NextUpdate += welder.WelderUpdateTimer;
|
||||||
|
Dirty(uid, welder);
|
||||||
|
|
||||||
|
if (!welder.Enabled)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!SolutionContainerSystem.TryGetSolution((uid, solutionContainer), welder.FuelSolutionName, out var solutionComp, out var solution))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
SolutionContainerSystem.RemoveReagent(solutionComp.Value, welder.FuelReagent, welder.FuelConsumption * welder.WelderUpdateTimer.TotalSeconds);
|
||||||
|
|
||||||
|
if (solution.GetTotalPrototypeQuantity(welder.FuelReagent) <= FixedPoint2.Zero)
|
||||||
|
ItemToggle.Toggle(uid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,12 +12,14 @@ using Robust.Shared.Audio.Systems;
|
|||||||
using Robust.Shared.Map;
|
using Robust.Shared.Map;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
using Robust.Shared.Serialization;
|
using Robust.Shared.Serialization;
|
||||||
|
using Robust.Shared.Timing;
|
||||||
using Robust.Shared.Utility;
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
namespace Content.Shared.Tools.Systems;
|
namespace Content.Shared.Tools.Systems;
|
||||||
|
|
||||||
public abstract partial class SharedToolSystem : EntitySystem
|
public abstract partial class SharedToolSystem : EntitySystem
|
||||||
{
|
{
|
||||||
|
[Dependency] private readonly IGameTiming _timing = default!;
|
||||||
[Dependency] private readonly IMapManager _mapManager = default!;
|
[Dependency] private readonly IMapManager _mapManager = default!;
|
||||||
[Dependency] private readonly IPrototypeManager _protoMan = default!;
|
[Dependency] private readonly IPrototypeManager _protoMan = default!;
|
||||||
[Dependency] protected readonly ISharedAdminLogManager AdminLogger = default!;
|
[Dependency] protected readonly ISharedAdminLogManager AdminLogger = default!;
|
||||||
@@ -263,6 +265,13 @@ public abstract partial class SharedToolSystem : EntitySystem
|
|||||||
return !beforeAttempt.Cancelled;
|
return !beforeAttempt.Cancelled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void Update(float frameTime)
|
||||||
|
{
|
||||||
|
base.Update(frameTime);
|
||||||
|
|
||||||
|
UpdateWelders();
|
||||||
|
}
|
||||||
|
|
||||||
#region DoAfterEvents
|
#region DoAfterEvents
|
||||||
|
|
||||||
[Serializable, NetSerializable]
|
[Serializable, NetSerializable]
|
||||||
|
|||||||
Reference in New Issue
Block a user