2021-10-07 13:01:27 +02:00
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
2022-01-30 14:48:18 +11:00
|
|
|
using System.Threading;
|
2021-10-07 13:01:27 +02:00
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
using Content.Server.Atmos.EntitySystems;
|
2021-10-29 13:40:15 +01:00
|
|
|
using Content.Server.Chemistry.EntitySystems;
|
2021-10-07 13:01:27 +02:00
|
|
|
using Content.Server.DoAfter;
|
|
|
|
|
using Content.Server.Popups;
|
|
|
|
|
using Content.Server.Tools.Components;
|
|
|
|
|
using Content.Shared.ActionBlocker;
|
|
|
|
|
using Content.Shared.Audio;
|
|
|
|
|
using Robust.Shared.Audio;
|
|
|
|
|
using Robust.Shared.GameObjects;
|
|
|
|
|
using Robust.Shared.IoC;
|
2022-01-30 14:48:18 +11:00
|
|
|
using Robust.Shared.Map;
|
2021-10-07 13:01:27 +02:00
|
|
|
using Robust.Shared.Player;
|
|
|
|
|
using Robust.Shared.Prototypes;
|
|
|
|
|
|
|
|
|
|
namespace Content.Server.Tools
|
|
|
|
|
{
|
2022-02-16 00:23:23 -07:00
|
|
|
public sealed partial class ToolSystem : EntitySystem
|
2021-10-07 13:01:27 +02:00
|
|
|
{
|
2022-01-30 14:48:18 +11:00
|
|
|
[Dependency] private readonly ITileDefinitionManager _tileDefinitionManager = default!;
|
|
|
|
|
[Dependency] private readonly IMapManager _mapManager = default!;
|
2021-10-07 13:01:27 +02:00
|
|
|
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
|
|
|
|
[Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
|
|
|
|
|
[Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!;
|
|
|
|
|
[Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!;
|
|
|
|
|
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public override void Initialize()
|
|
|
|
|
{
|
|
|
|
|
base.Initialize();
|
|
|
|
|
|
2022-01-30 14:48:18 +11:00
|
|
|
InitializeTilePrying();
|
2021-10-07 13:01:27 +02:00
|
|
|
InitializeWelders();
|
|
|
|
|
InitializeMultipleTools();
|
2021-10-28 11:21:43 +02:00
|
|
|
|
|
|
|
|
SubscribeLocalEvent<ToolDoAfterComplete>(OnDoAfterComplete);
|
|
|
|
|
SubscribeLocalEvent<ToolDoAfterCancelled>(OnDoAfterCancelled);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void OnDoAfterComplete(ToolDoAfterComplete ev)
|
|
|
|
|
{
|
|
|
|
|
// Actually finish the tool use! Depending on whether that succeeds or not, either event will be broadcast.
|
2021-10-30 19:27:06 +02:00
|
|
|
if(ToolFinishUse(ev.Uid, ev.UserUid, ev.Fuel))
|
2022-01-19 11:17:46 +13:00
|
|
|
{
|
|
|
|
|
if (ev.EventTarget != null)
|
|
|
|
|
RaiseLocalEvent(ev.EventTarget.Value, ev.CompletedEvent, false);
|
|
|
|
|
else
|
|
|
|
|
RaiseLocalEvent(ev.CompletedEvent);
|
|
|
|
|
}
|
2021-10-30 19:27:06 +02:00
|
|
|
else if(ev.CancelledEvent != null)
|
2022-01-19 11:17:46 +13:00
|
|
|
{
|
|
|
|
|
if (ev.EventTarget != null)
|
|
|
|
|
RaiseLocalEvent(ev.EventTarget.Value, ev.CancelledEvent, false);
|
|
|
|
|
else
|
|
|
|
|
RaiseLocalEvent(ev.CancelledEvent);
|
|
|
|
|
}
|
2021-10-28 11:21:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void OnDoAfterCancelled(ToolDoAfterCancelled ev)
|
|
|
|
|
{
|
2022-01-19 11:17:46 +13:00
|
|
|
if (ev.EventTarget != null)
|
|
|
|
|
RaiseLocalEvent(ev.EventTarget.Value, ev.Event, false);
|
|
|
|
|
else
|
|
|
|
|
RaiseLocalEvent(ev.Event);
|
2021-10-07 13:01:27 +02:00
|
|
|
}
|
|
|
|
|
|
ConstructionGL2 Part 1: ECSification, events and steps. (#5017)
- Completely rewrited the `ConstructionComponent` logic to be ECS, *without* looking too much at the original implementation.
- The original implementation was dirty and unmaintainable, whereas this new implementation is much cleaner, well-organized and maintainable. I've made sure to leave many comments around, explaining what everything does.
- Construction now has a framework for handling events other than `InteractUsing`.
- This means that you can now have CGL steps for things other than inserting items, using tools...
- Construction no longer uses `async` everywhere for `DoAfter`s. Instead it uses events.
- Construction event handling occurs in the `ConstructionSystem` update tick, instead of on event handlers.
- This ensures we can delete/modify entities without worrying about "collection modified while enumerating" exceptions.
- This also means the construction update tick is where all the fun happens, meaning it'll show up on our metrics and give us an idea of how expensive it is/how much tick time is spent in construction.
- `IGraphCondition` and `IGraphAction` have been refactored to take in `EntityUid`, `IEntityManager`, and to not be async.
- Removes nested steps, as they made maintainability significantly worse, and nothing used them yet.
- This fixes #4892 and fixes #4857
Please note, this leaves many things unchanged, as my idea is to split this into multiple PRs. Some unchanged things:
- Initial construction code is the same. In the future, it'll probably use dummy entities.
- Client-side guided steps are the same. In the future, the server will generate the guided steps and send them to clients as needed, caching these in both the server and client to save cycles and bandwidth.
- No new construction graph steps... Yet! :eyes:
2021-10-26 16:38:03 +02:00
|
|
|
/// <summary>
|
|
|
|
|
/// Whether a tool entity has the specified quality or not.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public bool HasQuality(EntityUid uid, string quality, ToolComponent? tool = null)
|
|
|
|
|
{
|
|
|
|
|
return Resolve(uid, ref tool, false) && tool.Qualities.Contains(quality);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Whether a tool entity has all specified qualities or not.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public bool HasAllQualities(EntityUid uid, IEnumerable<string> qualities, ToolComponent? tool = null)
|
|
|
|
|
{
|
|
|
|
|
return Resolve(uid, ref tool, false) && tool.Qualities.ContainsAll(qualities);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Sync version of UseTool.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="tool">The tool entity.</param>
|
|
|
|
|
/// <param name="user">The entity using the tool.</param>
|
|
|
|
|
/// <param name="target">Optionally, a target to use the tool on.</param>
|
|
|
|
|
/// <param name="fuel">An optional amount of fuel or energy to consume-</param>
|
|
|
|
|
/// <param name="doAfterDelay">A doAfter delay in seconds.</param>
|
|
|
|
|
/// <param name="toolQualitiesNeeded">The tool qualities needed to use the tool.</param>
|
2022-01-19 11:17:46 +13:00
|
|
|
/// <param name="doAfterCompleteEvent">An event to raise once the doAfter is completed successfully.</param>
|
|
|
|
|
/// <param name="doAfterCancelledEvent">An event to raise once the doAfter is canceled.</param>
|
|
|
|
|
/// <param name="doAfterEventTarget">Where to direct the do-after events. If null, events are broadcast</param>
|
ConstructionGL2 Part 1: ECSification, events and steps. (#5017)
- Completely rewrited the `ConstructionComponent` logic to be ECS, *without* looking too much at the original implementation.
- The original implementation was dirty and unmaintainable, whereas this new implementation is much cleaner, well-organized and maintainable. I've made sure to leave many comments around, explaining what everything does.
- Construction now has a framework for handling events other than `InteractUsing`.
- This means that you can now have CGL steps for things other than inserting items, using tools...
- Construction no longer uses `async` everywhere for `DoAfter`s. Instead it uses events.
- Construction event handling occurs in the `ConstructionSystem` update tick, instead of on event handlers.
- This ensures we can delete/modify entities without worrying about "collection modified while enumerating" exceptions.
- This also means the construction update tick is where all the fun happens, meaning it'll show up on our metrics and give us an idea of how expensive it is/how much tick time is spent in construction.
- `IGraphCondition` and `IGraphAction` have been refactored to take in `EntityUid`, `IEntityManager`, and to not be async.
- Removes nested steps, as they made maintainability significantly worse, and nothing used them yet.
- This fixes #4892 and fixes #4857
Please note, this leaves many things unchanged, as my idea is to split this into multiple PRs. Some unchanged things:
- Initial construction code is the same. In the future, it'll probably use dummy entities.
- Client-side guided steps are the same. In the future, the server will generate the guided steps and send them to clients as needed, caching these in both the server and client to save cycles and bandwidth.
- No new construction graph steps... Yet! :eyes:
2021-10-26 16:38:03 +02:00
|
|
|
/// <param name="doAfterCheck">An optional check to perform for the doAfter.</param>
|
|
|
|
|
/// <param name="toolComponent">The tool component.</param>
|
2022-01-30 14:48:18 +11:00
|
|
|
/// <param name="cancelToken">Token to provide to do_after for cancelling</param>
|
ConstructionGL2 Part 1: ECSification, events and steps. (#5017)
- Completely rewrited the `ConstructionComponent` logic to be ECS, *without* looking too much at the original implementation.
- The original implementation was dirty and unmaintainable, whereas this new implementation is much cleaner, well-organized and maintainable. I've made sure to leave many comments around, explaining what everything does.
- Construction now has a framework for handling events other than `InteractUsing`.
- This means that you can now have CGL steps for things other than inserting items, using tools...
- Construction no longer uses `async` everywhere for `DoAfter`s. Instead it uses events.
- Construction event handling occurs in the `ConstructionSystem` update tick, instead of on event handlers.
- This ensures we can delete/modify entities without worrying about "collection modified while enumerating" exceptions.
- This also means the construction update tick is where all the fun happens, meaning it'll show up on our metrics and give us an idea of how expensive it is/how much tick time is spent in construction.
- `IGraphCondition` and `IGraphAction` have been refactored to take in `EntityUid`, `IEntityManager`, and to not be async.
- Removes nested steps, as they made maintainability significantly worse, and nothing used them yet.
- This fixes #4892 and fixes #4857
Please note, this leaves many things unchanged, as my idea is to split this into multiple PRs. Some unchanged things:
- Initial construction code is the same. In the future, it'll probably use dummy entities.
- Client-side guided steps are the same. In the future, the server will generate the guided steps and send them to clients as needed, caching these in both the server and client to save cycles and bandwidth.
- No new construction graph steps... Yet! :eyes:
2021-10-26 16:38:03 +02:00
|
|
|
/// <returns>Whether initially, using the tool succeeded. If there's a doAfter delay, you'll need to listen to
|
|
|
|
|
/// the <see cref="doAfterCompleteEvent"/> and <see cref="doAfterCancelledEvent"/> being broadcast
|
|
|
|
|
/// to see whether using the tool succeeded or not. If the <see cref="doAfterDelay"/> is zero,
|
|
|
|
|
/// this simply returns whether using the tool succeeded or not.</returns>
|
2022-01-30 14:48:18 +11:00
|
|
|
public bool UseTool(
|
|
|
|
|
EntityUid tool,
|
|
|
|
|
EntityUid user,
|
|
|
|
|
EntityUid? target,
|
|
|
|
|
float fuel,
|
|
|
|
|
float doAfterDelay,
|
|
|
|
|
IEnumerable<string> toolQualitiesNeeded,
|
|
|
|
|
object? doAfterCompleteEvent = null,
|
|
|
|
|
object? doAfterCancelledEvent = null,
|
|
|
|
|
EntityUid? doAfterEventTarget = null,
|
|
|
|
|
Func<bool>? doAfterCheck = null,
|
|
|
|
|
ToolComponent? toolComponent = null,
|
|
|
|
|
CancellationToken? cancelToken = null)
|
2021-10-07 13:01:27 +02:00
|
|
|
{
|
2021-10-07 23:08:16 +02:00
|
|
|
// No logging here, after all that'd mean the caller would need to check if the component is there or not.
|
|
|
|
|
if (!Resolve(tool, ref toolComponent, false))
|
2021-10-07 13:01:27 +02:00
|
|
|
return false;
|
|
|
|
|
|
ConstructionGL2 Part 1: ECSification, events and steps. (#5017)
- Completely rewrited the `ConstructionComponent` logic to be ECS, *without* looking too much at the original implementation.
- The original implementation was dirty and unmaintainable, whereas this new implementation is much cleaner, well-organized and maintainable. I've made sure to leave many comments around, explaining what everything does.
- Construction now has a framework for handling events other than `InteractUsing`.
- This means that you can now have CGL steps for things other than inserting items, using tools...
- Construction no longer uses `async` everywhere for `DoAfter`s. Instead it uses events.
- Construction event handling occurs in the `ConstructionSystem` update tick, instead of on event handlers.
- This ensures we can delete/modify entities without worrying about "collection modified while enumerating" exceptions.
- This also means the construction update tick is where all the fun happens, meaning it'll show up on our metrics and give us an idea of how expensive it is/how much tick time is spent in construction.
- `IGraphCondition` and `IGraphAction` have been refactored to take in `EntityUid`, `IEntityManager`, and to not be async.
- Removes nested steps, as they made maintainability significantly worse, and nothing used them yet.
- This fixes #4892 and fixes #4857
Please note, this leaves many things unchanged, as my idea is to split this into multiple PRs. Some unchanged things:
- Initial construction code is the same. In the future, it'll probably use dummy entities.
- Client-side guided steps are the same. In the future, the server will generate the guided steps and send them to clients as needed, caching these in both the server and client to save cycles and bandwidth.
- No new construction graph steps... Yet! :eyes:
2021-10-26 16:38:03 +02:00
|
|
|
if (!ToolStartUse(tool, user, fuel, toolQualitiesNeeded, toolComponent))
|
2021-10-07 13:01:27 +02:00
|
|
|
return false;
|
|
|
|
|
|
ConstructionGL2 Part 1: ECSification, events and steps. (#5017)
- Completely rewrited the `ConstructionComponent` logic to be ECS, *without* looking too much at the original implementation.
- The original implementation was dirty and unmaintainable, whereas this new implementation is much cleaner, well-organized and maintainable. I've made sure to leave many comments around, explaining what everything does.
- Construction now has a framework for handling events other than `InteractUsing`.
- This means that you can now have CGL steps for things other than inserting items, using tools...
- Construction no longer uses `async` everywhere for `DoAfter`s. Instead it uses events.
- Construction event handling occurs in the `ConstructionSystem` update tick, instead of on event handlers.
- This ensures we can delete/modify entities without worrying about "collection modified while enumerating" exceptions.
- This also means the construction update tick is where all the fun happens, meaning it'll show up on our metrics and give us an idea of how expensive it is/how much tick time is spent in construction.
- `IGraphCondition` and `IGraphAction` have been refactored to take in `EntityUid`, `IEntityManager`, and to not be async.
- Removes nested steps, as they made maintainability significantly worse, and nothing used them yet.
- This fixes #4892 and fixes #4857
Please note, this leaves many things unchanged, as my idea is to split this into multiple PRs. Some unchanged things:
- Initial construction code is the same. In the future, it'll probably use dummy entities.
- Client-side guided steps are the same. In the future, the server will generate the guided steps and send them to clients as needed, caching these in both the server and client to save cycles and bandwidth.
- No new construction graph steps... Yet! :eyes:
2021-10-26 16:38:03 +02:00
|
|
|
if (doAfterDelay > 0f)
|
|
|
|
|
{
|
2022-01-30 14:48:18 +11:00
|
|
|
var doAfterArgs = new DoAfterEventArgs(user, doAfterDelay / toolComponent.SpeedModifier, cancelToken ?? default, target)
|
ConstructionGL2 Part 1: ECSification, events and steps. (#5017)
- Completely rewrited the `ConstructionComponent` logic to be ECS, *without* looking too much at the original implementation.
- The original implementation was dirty and unmaintainable, whereas this new implementation is much cleaner, well-organized and maintainable. I've made sure to leave many comments around, explaining what everything does.
- Construction now has a framework for handling events other than `InteractUsing`.
- This means that you can now have CGL steps for things other than inserting items, using tools...
- Construction no longer uses `async` everywhere for `DoAfter`s. Instead it uses events.
- Construction event handling occurs in the `ConstructionSystem` update tick, instead of on event handlers.
- This ensures we can delete/modify entities without worrying about "collection modified while enumerating" exceptions.
- This also means the construction update tick is where all the fun happens, meaning it'll show up on our metrics and give us an idea of how expensive it is/how much tick time is spent in construction.
- `IGraphCondition` and `IGraphAction` have been refactored to take in `EntityUid`, `IEntityManager`, and to not be async.
- Removes nested steps, as they made maintainability significantly worse, and nothing used them yet.
- This fixes #4892 and fixes #4857
Please note, this leaves many things unchanged, as my idea is to split this into multiple PRs. Some unchanged things:
- Initial construction code is the same. In the future, it'll probably use dummy entities.
- Client-side guided steps are the same. In the future, the server will generate the guided steps and send them to clients as needed, caching these in both the server and client to save cycles and bandwidth.
- No new construction graph steps... Yet! :eyes:
2021-10-26 16:38:03 +02:00
|
|
|
{
|
|
|
|
|
ExtraCheck = doAfterCheck,
|
|
|
|
|
BreakOnDamage = true,
|
|
|
|
|
BreakOnStun = true,
|
|
|
|
|
BreakOnTargetMove = true,
|
|
|
|
|
BreakOnUserMove = true,
|
|
|
|
|
NeedHand = true,
|
2022-01-19 11:17:46 +13:00
|
|
|
BroadcastFinishedEvent = doAfterCompleteEvent != null ? new ToolDoAfterComplete(doAfterCompleteEvent, doAfterCancelledEvent, tool, user, fuel, doAfterEventTarget) : null,
|
|
|
|
|
BroadcastCancelledEvent = doAfterCancelledEvent != null ? new ToolDoAfterCancelled(doAfterCancelledEvent, doAfterEventTarget) : null,
|
ConstructionGL2 Part 1: ECSification, events and steps. (#5017)
- Completely rewrited the `ConstructionComponent` logic to be ECS, *without* looking too much at the original implementation.
- The original implementation was dirty and unmaintainable, whereas this new implementation is much cleaner, well-organized and maintainable. I've made sure to leave many comments around, explaining what everything does.
- Construction now has a framework for handling events other than `InteractUsing`.
- This means that you can now have CGL steps for things other than inserting items, using tools...
- Construction no longer uses `async` everywhere for `DoAfter`s. Instead it uses events.
- Construction event handling occurs in the `ConstructionSystem` update tick, instead of on event handlers.
- This ensures we can delete/modify entities without worrying about "collection modified while enumerating" exceptions.
- This also means the construction update tick is where all the fun happens, meaning it'll show up on our metrics and give us an idea of how expensive it is/how much tick time is spent in construction.
- `IGraphCondition` and `IGraphAction` have been refactored to take in `EntityUid`, `IEntityManager`, and to not be async.
- Removes nested steps, as they made maintainability significantly worse, and nothing used them yet.
- This fixes #4892 and fixes #4857
Please note, this leaves many things unchanged, as my idea is to split this into multiple PRs. Some unchanged things:
- Initial construction code is the same. In the future, it'll probably use dummy entities.
- Client-side guided steps are the same. In the future, the server will generate the guided steps and send them to clients as needed, caching these in both the server and client to save cycles and bandwidth.
- No new construction graph steps... Yet! :eyes:
2021-10-26 16:38:03 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
_doAfterSystem.DoAfter(doAfterArgs);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ToolFinishUse(tool, user, fuel, toolComponent);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// This is hilariously long.
|
|
|
|
|
/// <inheritdoc cref="UseTool(Robust.Shared.GameObjects.EntityUid,Robust.Shared.GameObjects.EntityUid,System.Nullable{Robust.Shared.GameObjects.EntityUid},float,float,System.Collections.Generic.IEnumerable{string},Robust.Shared.GameObjects.EntityUid,object,object,System.Func{bool}?,Content.Server.Tools.Components.ToolComponent?)"/>
|
|
|
|
|
public bool UseTool(EntityUid tool, EntityUid user, EntityUid? target, float fuel,
|
2022-01-19 11:17:46 +13:00
|
|
|
float doAfterDelay, string toolQualityNeeded, object doAfterCompleteEvent, object doAfterCancelledEvent, EntityUid? doAfterEventTarget = null,
|
ConstructionGL2 Part 1: ECSification, events and steps. (#5017)
- Completely rewrited the `ConstructionComponent` logic to be ECS, *without* looking too much at the original implementation.
- The original implementation was dirty and unmaintainable, whereas this new implementation is much cleaner, well-organized and maintainable. I've made sure to leave many comments around, explaining what everything does.
- Construction now has a framework for handling events other than `InteractUsing`.
- This means that you can now have CGL steps for things other than inserting items, using tools...
- Construction no longer uses `async` everywhere for `DoAfter`s. Instead it uses events.
- Construction event handling occurs in the `ConstructionSystem` update tick, instead of on event handlers.
- This ensures we can delete/modify entities without worrying about "collection modified while enumerating" exceptions.
- This also means the construction update tick is where all the fun happens, meaning it'll show up on our metrics and give us an idea of how expensive it is/how much tick time is spent in construction.
- `IGraphCondition` and `IGraphAction` have been refactored to take in `EntityUid`, `IEntityManager`, and to not be async.
- Removes nested steps, as they made maintainability significantly worse, and nothing used them yet.
- This fixes #4892 and fixes #4857
Please note, this leaves many things unchanged, as my idea is to split this into multiple PRs. Some unchanged things:
- Initial construction code is the same. In the future, it'll probably use dummy entities.
- Client-side guided steps are the same. In the future, the server will generate the guided steps and send them to clients as needed, caching these in both the server and client to save cycles and bandwidth.
- No new construction graph steps... Yet! :eyes:
2021-10-26 16:38:03 +02:00
|
|
|
Func<bool>? doAfterCheck = null, ToolComponent? toolComponent = null)
|
|
|
|
|
{
|
|
|
|
|
return UseTool(tool, user, target, fuel, doAfterDelay, new[] { toolQualityNeeded },
|
2022-01-19 11:17:46 +13:00
|
|
|
doAfterCompleteEvent, doAfterCancelledEvent, doAfterEventTarget, doAfterCheck, toolComponent);
|
ConstructionGL2 Part 1: ECSification, events and steps. (#5017)
- Completely rewrited the `ConstructionComponent` logic to be ECS, *without* looking too much at the original implementation.
- The original implementation was dirty and unmaintainable, whereas this new implementation is much cleaner, well-organized and maintainable. I've made sure to leave many comments around, explaining what everything does.
- Construction now has a framework for handling events other than `InteractUsing`.
- This means that you can now have CGL steps for things other than inserting items, using tools...
- Construction no longer uses `async` everywhere for `DoAfter`s. Instead it uses events.
- Construction event handling occurs in the `ConstructionSystem` update tick, instead of on event handlers.
- This ensures we can delete/modify entities without worrying about "collection modified while enumerating" exceptions.
- This also means the construction update tick is where all the fun happens, meaning it'll show up on our metrics and give us an idea of how expensive it is/how much tick time is spent in construction.
- `IGraphCondition` and `IGraphAction` have been refactored to take in `EntityUid`, `IEntityManager`, and to not be async.
- Removes nested steps, as they made maintainability significantly worse, and nothing used them yet.
- This fixes #4892 and fixes #4857
Please note, this leaves many things unchanged, as my idea is to split this into multiple PRs. Some unchanged things:
- Initial construction code is the same. In the future, it'll probably use dummy entities.
- Client-side guided steps are the same. In the future, the server will generate the guided steps and send them to clients as needed, caching these in both the server and client to save cycles and bandwidth.
- No new construction graph steps... Yet! :eyes:
2021-10-26 16:38:03 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Async version of UseTool.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="tool">The tool entity.</param>
|
|
|
|
|
/// <param name="user">The entity using the tool.</param>
|
|
|
|
|
/// <param name="target">Optionally, a target to use the tool on.</param>
|
|
|
|
|
/// <param name="fuel">An optional amount of fuel or energy to consume-</param>
|
|
|
|
|
/// <param name="doAfterDelay">A doAfter delay in seconds.</param>
|
|
|
|
|
/// <param name="toolQualitiesNeeded">The tool qualities needed to use the tool.</param>
|
|
|
|
|
/// <param name="doAfterCheck">An optional check to perform for the doAfter.</param>
|
|
|
|
|
/// <param name="toolComponent">The tool component.</param>
|
|
|
|
|
/// <returns>Whether using the tool succeeded or not.</returns>
|
|
|
|
|
public async Task<bool> UseTool(EntityUid tool, EntityUid user, EntityUid? target, float fuel,
|
|
|
|
|
float doAfterDelay, IEnumerable<string> toolQualitiesNeeded, Func<bool>? doAfterCheck = null,
|
|
|
|
|
ToolComponent? toolComponent = null)
|
|
|
|
|
{
|
|
|
|
|
// No logging here, after all that'd mean the caller would need to check if the component is there or not.
|
|
|
|
|
if (!Resolve(tool, ref toolComponent, false))
|
|
|
|
|
return false;
|
2021-10-07 13:01:27 +02:00
|
|
|
|
ConstructionGL2 Part 1: ECSification, events and steps. (#5017)
- Completely rewrited the `ConstructionComponent` logic to be ECS, *without* looking too much at the original implementation.
- The original implementation was dirty and unmaintainable, whereas this new implementation is much cleaner, well-organized and maintainable. I've made sure to leave many comments around, explaining what everything does.
- Construction now has a framework for handling events other than `InteractUsing`.
- This means that you can now have CGL steps for things other than inserting items, using tools...
- Construction no longer uses `async` everywhere for `DoAfter`s. Instead it uses events.
- Construction event handling occurs in the `ConstructionSystem` update tick, instead of on event handlers.
- This ensures we can delete/modify entities without worrying about "collection modified while enumerating" exceptions.
- This also means the construction update tick is where all the fun happens, meaning it'll show up on our metrics and give us an idea of how expensive it is/how much tick time is spent in construction.
- `IGraphCondition` and `IGraphAction` have been refactored to take in `EntityUid`, `IEntityManager`, and to not be async.
- Removes nested steps, as they made maintainability significantly worse, and nothing used them yet.
- This fixes #4892 and fixes #4857
Please note, this leaves many things unchanged, as my idea is to split this into multiple PRs. Some unchanged things:
- Initial construction code is the same. In the future, it'll probably use dummy entities.
- Client-side guided steps are the same. In the future, the server will generate the guided steps and send them to clients as needed, caching these in both the server and client to save cycles and bandwidth.
- No new construction graph steps... Yet! :eyes:
2021-10-26 16:38:03 +02:00
|
|
|
if (!ToolStartUse(tool, user, fuel, toolQualitiesNeeded, toolComponent))
|
2021-10-07 13:01:27 +02:00
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
if (doAfterDelay > 0f)
|
|
|
|
|
{
|
|
|
|
|
var doAfterArgs = new DoAfterEventArgs(user, doAfterDelay / toolComponent.SpeedModifier, default, target)
|
|
|
|
|
{
|
|
|
|
|
ExtraCheck = doAfterCheck,
|
|
|
|
|
BreakOnDamage = true,
|
|
|
|
|
BreakOnStun = true,
|
|
|
|
|
BreakOnTargetMove = true,
|
|
|
|
|
BreakOnUserMove = true,
|
|
|
|
|
NeedHand = true,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var result = await _doAfterSystem.WaitDoAfter(doAfterArgs);
|
|
|
|
|
|
|
|
|
|
if (result == DoAfterStatus.Cancelled)
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
ConstructionGL2 Part 1: ECSification, events and steps. (#5017)
- Completely rewrited the `ConstructionComponent` logic to be ECS, *without* looking too much at the original implementation.
- The original implementation was dirty and unmaintainable, whereas this new implementation is much cleaner, well-organized and maintainable. I've made sure to leave many comments around, explaining what everything does.
- Construction now has a framework for handling events other than `InteractUsing`.
- This means that you can now have CGL steps for things other than inserting items, using tools...
- Construction no longer uses `async` everywhere for `DoAfter`s. Instead it uses events.
- Construction event handling occurs in the `ConstructionSystem` update tick, instead of on event handlers.
- This ensures we can delete/modify entities without worrying about "collection modified while enumerating" exceptions.
- This also means the construction update tick is where all the fun happens, meaning it'll show up on our metrics and give us an idea of how expensive it is/how much tick time is spent in construction.
- `IGraphCondition` and `IGraphAction` have been refactored to take in `EntityUid`, `IEntityManager`, and to not be async.
- Removes nested steps, as they made maintainability significantly worse, and nothing used them yet.
- This fixes #4892 and fixes #4857
Please note, this leaves many things unchanged, as my idea is to split this into multiple PRs. Some unchanged things:
- Initial construction code is the same. In the future, it'll probably use dummy entities.
- Client-side guided steps are the same. In the future, the server will generate the guided steps and send them to clients as needed, caching these in both the server and client to save cycles and bandwidth.
- No new construction graph steps... Yet! :eyes:
2021-10-26 16:38:03 +02:00
|
|
|
return ToolFinishUse(tool, user, fuel, toolComponent);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// This is hilariously long.
|
|
|
|
|
/// <inheritdoc cref="UseTool(Robust.Shared.GameObjects.EntityUid,Robust.Shared.GameObjects.EntityUid,System.Nullable{Robust.Shared.GameObjects.EntityUid},float,float,System.Collections.Generic.IEnumerable{string},Robust.Shared.GameObjects.EntityUid,object,object,System.Func{bool}?,Content.Server.Tools.Components.ToolComponent?)"/>
|
|
|
|
|
public Task<bool> UseTool(EntityUid tool, EntityUid user, EntityUid? target, float fuel,
|
|
|
|
|
float doAfterDelay, string toolQualityNeeded, Func<bool>? doAfterCheck = null,
|
|
|
|
|
ToolComponent? toolComponent = null)
|
|
|
|
|
{
|
|
|
|
|
return UseTool(tool, user, target, fuel, doAfterDelay, new [] {toolQualityNeeded}, doAfterCheck, toolComponent);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private bool ToolStartUse(EntityUid tool, EntityUid user, float fuel, IEnumerable<string> toolQualitiesNeeded, ToolComponent? toolComponent = null)
|
|
|
|
|
{
|
|
|
|
|
if (!Resolve(tool, ref toolComponent))
|
|
|
|
|
return false;
|
|
|
|
|
|
2022-02-15 17:06:52 +13:00
|
|
|
if (!toolComponent.Qualities.ContainsAll(toolQualitiesNeeded))
|
ConstructionGL2 Part 1: ECSification, events and steps. (#5017)
- Completely rewrited the `ConstructionComponent` logic to be ECS, *without* looking too much at the original implementation.
- The original implementation was dirty and unmaintainable, whereas this new implementation is much cleaner, well-organized and maintainable. I've made sure to leave many comments around, explaining what everything does.
- Construction now has a framework for handling events other than `InteractUsing`.
- This means that you can now have CGL steps for things other than inserting items, using tools...
- Construction no longer uses `async` everywhere for `DoAfter`s. Instead it uses events.
- Construction event handling occurs in the `ConstructionSystem` update tick, instead of on event handlers.
- This ensures we can delete/modify entities without worrying about "collection modified while enumerating" exceptions.
- This also means the construction update tick is where all the fun happens, meaning it'll show up on our metrics and give us an idea of how expensive it is/how much tick time is spent in construction.
- `IGraphCondition` and `IGraphAction` have been refactored to take in `EntityUid`, `IEntityManager`, and to not be async.
- Removes nested steps, as they made maintainability significantly worse, and nothing used them yet.
- This fixes #4892 and fixes #4857
Please note, this leaves many things unchanged, as my idea is to split this into multiple PRs. Some unchanged things:
- Initial construction code is the same. In the future, it'll probably use dummy entities.
- Client-side guided steps are the same. In the future, the server will generate the guided steps and send them to clients as needed, caching these in both the server and client to save cycles and bandwidth.
- No new construction graph steps... Yet! :eyes:
2021-10-26 16:38:03 +02:00
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
var beforeAttempt = new ToolUseAttemptEvent(fuel, user);
|
|
|
|
|
RaiseLocalEvent(tool, beforeAttempt, false);
|
|
|
|
|
|
|
|
|
|
return !beforeAttempt.Cancelled;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private bool ToolFinishUse(EntityUid tool, EntityUid user, float fuel, ToolComponent? toolComponent = null)
|
|
|
|
|
{
|
|
|
|
|
if (!Resolve(tool, ref toolComponent))
|
|
|
|
|
return false;
|
|
|
|
|
|
2021-10-07 13:01:27 +02:00
|
|
|
var afterAttempt = new ToolUseFinishAttemptEvent(fuel, user);
|
|
|
|
|
RaiseLocalEvent(tool, afterAttempt, false);
|
|
|
|
|
|
|
|
|
|
if (afterAttempt.Cancelled)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
if (toolComponent.UseSound != null)
|
|
|
|
|
PlayToolSound(tool, toolComponent);
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void PlayToolSound(EntityUid uid, ToolComponent? tool = null)
|
|
|
|
|
{
|
|
|
|
|
if (!Resolve(uid, ref tool))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (tool.UseSound is not {} sound)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
// Pass tool.Owner to Filter.Pvs to avoid a TryGetEntity call.
|
|
|
|
|
SoundSystem.Play(Filter.Pvs(tool.Owner), sound.GetSound(), uid,
|
|
|
|
|
AudioHelpers.WithVariation(0.175f).WithVolume(-5f));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void Update(float frameTime)
|
|
|
|
|
{
|
|
|
|
|
base.Update(frameTime);
|
|
|
|
|
|
|
|
|
|
UpdateWelders(frameTime);
|
|
|
|
|
}
|
2021-10-28 11:21:43 +02:00
|
|
|
|
2022-02-16 00:23:23 -07:00
|
|
|
private sealed class ToolDoAfterComplete : EntityEventArgs
|
2021-10-28 11:21:43 +02:00
|
|
|
{
|
|
|
|
|
public readonly object CompletedEvent;
|
2021-10-30 19:27:06 +02:00
|
|
|
public readonly object? CancelledEvent;
|
2021-10-28 11:21:43 +02:00
|
|
|
public readonly EntityUid Uid;
|
|
|
|
|
public readonly EntityUid UserUid;
|
|
|
|
|
public readonly float Fuel;
|
2022-01-19 11:17:46 +13:00
|
|
|
public readonly EntityUid? EventTarget;
|
2021-10-28 11:21:43 +02:00
|
|
|
|
2022-01-19 11:17:46 +13:00
|
|
|
public ToolDoAfterComplete(object completedEvent, object? cancelledEvent, EntityUid uid, EntityUid userUid, float fuel, EntityUid? eventTarget = null)
|
2021-10-28 11:21:43 +02:00
|
|
|
{
|
|
|
|
|
CompletedEvent = completedEvent;
|
|
|
|
|
Uid = uid;
|
|
|
|
|
UserUid = userUid;
|
|
|
|
|
Fuel = fuel;
|
|
|
|
|
CancelledEvent = cancelledEvent;
|
2022-01-19 11:17:46 +13:00
|
|
|
EventTarget = eventTarget;
|
2021-10-28 11:21:43 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-16 00:23:23 -07:00
|
|
|
private sealed class ToolDoAfterCancelled : EntityEventArgs
|
2021-10-28 11:21:43 +02:00
|
|
|
{
|
|
|
|
|
public readonly object Event;
|
2022-01-19 11:17:46 +13:00
|
|
|
public readonly EntityUid? EventTarget;
|
2021-10-28 11:21:43 +02:00
|
|
|
|
2022-01-19 11:17:46 +13:00
|
|
|
public ToolDoAfterCancelled(object @event, EntityUid? eventTarget = null)
|
2021-10-28 11:21:43 +02:00
|
|
|
{
|
|
|
|
|
Event = @event;
|
2022-01-19 11:17:46 +13:00
|
|
|
EventTarget = eventTarget;
|
2021-10-28 11:21:43 +02:00
|
|
|
}
|
|
|
|
|
}
|
2021-10-07 13:01:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Attempt event called *before* any do afters to see if the tool usage should succeed or not.
|
|
|
|
|
/// You can change the fuel consumption by changing the Fuel property.
|
|
|
|
|
/// </summary>
|
2022-02-16 00:23:23 -07:00
|
|
|
public sealed class ToolUseAttemptEvent : CancellableEntityEventArgs
|
2021-10-07 13:01:27 +02:00
|
|
|
{
|
|
|
|
|
public float Fuel { get; set; }
|
|
|
|
|
public EntityUid User { get; }
|
|
|
|
|
|
|
|
|
|
public ToolUseAttemptEvent(float fuel, EntityUid user)
|
|
|
|
|
{
|
|
|
|
|
Fuel = fuel;
|
|
|
|
|
User = user;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Attempt event called *after* any do afters to see if the tool usage should succeed or not.
|
|
|
|
|
/// You can use this event to consume any fuel needed.
|
|
|
|
|
/// </summary>
|
2022-02-16 00:23:23 -07:00
|
|
|
public sealed class ToolUseFinishAttemptEvent : CancellableEntityEventArgs
|
2021-10-07 13:01:27 +02:00
|
|
|
{
|
|
|
|
|
public float Fuel { get; }
|
|
|
|
|
public EntityUid User { get; }
|
|
|
|
|
|
|
|
|
|
public ToolUseFinishAttemptEvent(float fuel, EntityUid user)
|
|
|
|
|
{
|
|
|
|
|
Fuel = fuel;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|