From f308a1b31e2f178badbb74d218d1bf83a830e5a0 Mon Sep 17 00:00:00 2001 From: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> Date: Mon, 29 May 2023 16:53:28 +1000 Subject: [PATCH] Fix cleanbots (#16922) --- .../Operators/Fluid/PickPuddleOperator.cs | 106 ------------------ Content.Server/NPC/NPCBlackboard.cs | 4 + .../Queries/Queries/NearbyComponentsQuery.cs | 9 -- .../NPC/Queries/Queries/PuddleFilter.cs | 6 + .../NPC/Systems/NPCUtilitySystem.cs | 35 +++++- Resources/Prototypes/NPCs/cleanbot.yml | 24 +++- Resources/Prototypes/NPCs/utility_queries.yml | 16 +++ 7 files changed, 75 insertions(+), 125 deletions(-) delete mode 100644 Content.Server/NPC/HTN/PrimitiveTasks/Operators/Fluid/PickPuddleOperator.cs delete mode 100644 Content.Server/NPC/Queries/Queries/NearbyComponentsQuery.cs create mode 100644 Content.Server/NPC/Queries/Queries/PuddleFilter.cs diff --git a/Content.Server/NPC/HTN/PrimitiveTasks/Operators/Fluid/PickPuddleOperator.cs b/Content.Server/NPC/HTN/PrimitiveTasks/Operators/Fluid/PickPuddleOperator.cs deleted file mode 100644 index ecce69ce38..0000000000 --- a/Content.Server/NPC/HTN/PrimitiveTasks/Operators/Fluid/PickPuddleOperator.cs +++ /dev/null @@ -1,106 +0,0 @@ -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Content.Server.Chemistry.EntitySystems; -using Content.Server.Fluids.EntitySystems; -using Content.Server.NPC.Pathfinding; -using Content.Shared.Fluids.Components; -using Robust.Shared.Map; - -namespace Content.Server.NPC.HTN.PrimitiveTasks.Operators.Fluid; - -/// -/// Picks a nearby evaporatable puddle. -/// -public sealed class PickPuddleOperator : HTNOperator -{ - // This is similar to PickAccessibleComponent however I have an idea on generic utility queries - // that can also be re-used for melee that needs further fleshing out. - - [Dependency] private readonly IComponentFactory _factory = default!; - [Dependency] private readonly IEntityManager _entManager = default!; - private PathfindingSystem _pathfinding = default!; - private EntityLookupSystem _lookup = default!; - - [DataField("rangeKey", required: true)] - public string RangeKey = string.Empty; - - [DataField("target")] public string Target = "Target"; - - [DataField("targetKey", required: true)] - public string TargetKey = string.Empty; - - /// - /// Where the pathfinding result will be stored (if applicable). This gets removed after execution. - /// - [DataField("pathfindKey")] - public string PathfindKey = NPCBlackboard.PathfindKey; - - public override void Initialize(IEntitySystemManager sysManager) - { - base.Initialize(sysManager); - _lookup = sysManager.GetEntitySystem(); - _pathfinding = sysManager.GetEntitySystem(); - } - - /// - [Obsolete("Obsolete")] - public override async Task<(bool Valid, Dictionary? Effects)> Plan(NPCBlackboard blackboard, - CancellationToken cancelToken) - { - var range = blackboard.GetValueOrDefault(RangeKey, _entManager); - var owner = blackboard.GetValue(NPCBlackboard.Owner); - - if (!blackboard.TryGetValue(NPCBlackboard.OwnerCoordinates, out var coordinates, _entManager)) - { - return (false, null); - } - - var targets = new List(); - var puddleSystem = _entManager.System(); - var solSystem = _entManager.System(); - - foreach (var comp in _lookup.GetComponentsInRange(coordinates, range)) - { - if (comp.Owner == owner || - !solSystem.TryGetSolution(comp.Owner, comp.SolutionName, out var puddleSolution) || - puddleSystem.CanFullyEvaporate(puddleSolution)) - { - continue; - } - - targets.Add((comp.Owner)); - } - - if (targets.Count == 0) - { - return (false, null); - } - - foreach (var target in targets) - { - var path = await _pathfinding.GetPath( - owner, - target, - 1f, - cancelToken, - flags: _pathfinding.GetFlags(blackboard)); - - if (path.Result != PathResult.Path) - { - return (false, null); - } - - var xform = _entManager.GetComponent(target); - - return (true, new Dictionary() - { - { Target, target }, - { TargetKey, xform.Coordinates }, - { PathfindKey, path} - }); - } - - return (false, null); - } -} diff --git a/Content.Server/NPC/NPCBlackboard.cs b/Content.Server/NPC/NPCBlackboard.cs index 4e8581efb2..f386fba21e 100644 --- a/Content.Server/NPC/NPCBlackboard.cs +++ b/Content.Server/NPC/NPCBlackboard.cs @@ -4,6 +4,7 @@ using Content.Server.Interaction; using Content.Shared.Access.Systems; using Content.Shared.ActionBlocker; using Content.Shared.Interaction; +using JetBrains.Annotations; using Robust.Shared.Utility; namespace Content.Server.NPC; @@ -60,6 +61,7 @@ public sealed class NPCBlackboard : IEnumerable> return dict; } + [Pure] public bool ContainsKey(string key) { return _blackboard.ContainsKey(key); @@ -68,6 +70,7 @@ public sealed class NPCBlackboard : IEnumerable> /// /// Get the blackboard data for a particular key. /// + [Pure] public T GetValue(string key) { return (T) _blackboard[key]; @@ -76,6 +79,7 @@ public sealed class NPCBlackboard : IEnumerable> /// /// Tries to get the blackboard data for a particular key. Returns default if not found /// + [Pure] public T? GetValueOrDefault(string key, IEntityManager entManager) { if (_blackboard.TryGetValue(key, out var value)) diff --git a/Content.Server/NPC/Queries/Queries/NearbyComponentsQuery.cs b/Content.Server/NPC/Queries/Queries/NearbyComponentsQuery.cs deleted file mode 100644 index c465f11fd2..0000000000 --- a/Content.Server/NPC/Queries/Queries/NearbyComponentsQuery.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Robust.Shared.Prototypes; - -namespace Content.Server.NPC.Queries.Queries; - -public sealed class NearbyComponentsQuery : UtilityQuery -{ - [DataField("components")] - public ComponentRegistry Component = default!; -} diff --git a/Content.Server/NPC/Queries/Queries/PuddleFilter.cs b/Content.Server/NPC/Queries/Queries/PuddleFilter.cs new file mode 100644 index 0000000000..65ebfda395 --- /dev/null +++ b/Content.Server/NPC/Queries/Queries/PuddleFilter.cs @@ -0,0 +1,6 @@ +namespace Content.Server.NPC.Queries.Queries; + +public sealed class PuddleFilter : UtilityQueryFilter +{ + +} diff --git a/Content.Server/NPC/Systems/NPCUtilitySystem.cs b/Content.Server/NPC/Systems/NPCUtilitySystem.cs index 0b00ab8c83..a9e93062e8 100644 --- a/Content.Server/NPC/Systems/NPCUtilitySystem.cs +++ b/Content.Server/NPC/Systems/NPCUtilitySystem.cs @@ -1,5 +1,7 @@ using System.Linq; +using Content.Server.Chemistry.EntitySystems; using Content.Server.Examine; +using Content.Server.Fluids.EntitySystems; using Content.Server.NPC.Queries; using Content.Server.NPC.Queries.Considerations; using Content.Server.NPC.Queries.Curves; @@ -8,8 +10,10 @@ using Content.Server.Nutrition.Components; using Content.Server.Nutrition.EntitySystems; using Content.Server.Storage.Components; using Content.Shared.Examine; +using Content.Shared.Fluids.Components; using Content.Shared.Mobs.Systems; using Robust.Server.Containers; +using Robust.Shared.Collections; using Robust.Shared.Prototypes; namespace Content.Server.NPC.Systems; @@ -23,9 +27,11 @@ public sealed class NPCUtilitySystem : EntitySystem [Dependency] private readonly ContainerSystem _container = default!; [Dependency] private readonly EntityLookupSystem _lookup = default!; [Dependency] private readonly FactionSystem _faction = default!; - [Dependency] private readonly MobStateSystem _mobState = default!; - [Dependency] private readonly SharedTransformSystem _transform = default!; [Dependency] private readonly FoodSystem _food = default!; + [Dependency] private readonly MobStateSystem _mobState = default!; + [Dependency] private readonly PuddleSystem _puddle = default!; + [Dependency] private readonly SharedTransformSystem _transform = default!; + [Dependency] private readonly SolutionContainerSystem _solutions = default!; /// /// Runs the UtilityQueryPrototype and returns the best-matching entities. @@ -269,10 +275,31 @@ public sealed class NPCUtilitySystem : EntitySystem private void Filter(NPCBlackboard blackboard, HashSet entities, UtilityQueryFilter filter) { - var owner = blackboard.GetValue(NPCBlackboard.Owner); - switch (filter) { + case PuddleFilter: + { + var puddleQuery = GetEntityQuery(); + + var toRemove = new ValueList(); + + foreach (var ent in entities) + { + if (!puddleQuery.TryGetComponent(ent, out var puddleComp) || + !_solutions.TryGetSolution(ent, puddleComp.SolutionName, out var sol) || + _puddle.CanFullyEvaporate(sol)) + { + toRemove.Add(ent); + } + } + + foreach (var ent in toRemove) + { + entities.Remove(ent); + } + + break; + } default: throw new NotImplementedException(); } diff --git a/Resources/Prototypes/NPCs/cleanbot.yml b/Resources/Prototypes/NPCs/cleanbot.yml index ca3835338a..60e8bdb8b6 100644 --- a/Resources/Prototypes/NPCs/cleanbot.yml +++ b/Resources/Prototypes/NPCs/cleanbot.yml @@ -12,18 +12,30 @@ branches: - tasks: - id: PickPuddlePrimitive - - id: MoveToAccessiblePrimitive - - id: InteractWithPrimitive + - id: MoveToCombatTargetPrimitive + - id: MopPrimitive - type: htnPrimitive id: PickPuddlePrimitive - operator: !type:PickPuddleOperator - rangeKey: BufferRange - targetKey: MovementTarget - component: Puddle + operator: !type:UtilityOperator + proto: NearbyPuddles - type: htnPrimitive id: SetIdleTimePrimitive operator: !type:SetFloatOperator targetKey: IdleTime amount: 3 + +- type: htnPrimitive + id: MopPrimitive + preconditions: + - !type:TargetInRangePrecondition + targetKey: CombatTarget + rangeKey: InteractRange + operator: !type:InteractWithOperator + targetKey: CombatTarget + services: + - !type:UtilityService + id: PuddleService + proto: NearbyPuddles + key: CombatTarget diff --git a/Resources/Prototypes/NPCs/utility_queries.yml b/Resources/Prototypes/NPCs/utility_queries.yml index 87eda1f9eb..7b804f6f37 100644 --- a/Resources/Prototypes/NPCs/utility_queries.yml +++ b/Resources/Prototypes/NPCs/utility_queries.yml @@ -35,6 +35,22 @@ - !type:TargetInLOSOrCurrentCon curve: !type:BoolCurve +- type: utilityQuery + id: NearbyPuddles + query: + - !type:ComponentQuery + components: + - type: Puddle + - !type:PuddleFilter + considerations: + - !type:TargetDistanceCon + curve: !type:PresetCurve + preset: TargetDistance + - !type:TargetAccessibleCon + curve: !type:BoolCurve + - !type:TargetInLOSOrCurrentCon + curve: !type:BoolCurve + - type: utilityQuery id: NearbyRangedTargets query: