From 3e73fb9ea2dc8c62e324c7329fc0d70dd668fdb5 Mon Sep 17 00:00:00 2001 From: starlight Date: Mon, 1 Jun 2026 02:23:15 +0200 Subject: [PATCH] Make HTN planning budget configurable via cvar --- Content.Server/NPC/HTN/HTNSystem.cs | 14 +++++++++++++- .../_Starlight/NPC/HTN/AdjustableJobQueue.cs | 13 +++++++++++++ Content.Shared/CCVar/CCVars.NPC.cs | 9 +++++++++ 3 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 Content.Server/_Starlight/NPC/HTN/AdjustableJobQueue.cs diff --git a/Content.Server/NPC/HTN/HTNSystem.cs b/Content.Server/NPC/HTN/HTNSystem.cs index 7bfe43299865..18fe751f849c 100644 --- a/Content.Server/NPC/HTN/HTNSystem.cs +++ b/Content.Server/NPC/HTN/HTNSystem.cs @@ -2,6 +2,11 @@ using System.Text; using System.Threading; using Content.Server.Administration.Managers; +// Starlight start +using Content.Server._Starlight.NPC.HTN; +using Content.Shared.CCVar; +using Robust.Shared.Configuration; +// Starlight end using Robust.Shared.CPUJob.JobQueues; using Robust.Shared.CPUJob.JobQueues.Queues; using Content.Server.NPC.HTN.PrimitiveTasks; @@ -22,8 +27,11 @@ public sealed class HTNSystem : EntitySystem [Dependency] private readonly IPrototypeManager _prototypeManager = default!; [Dependency] private readonly NPCSystem _npc = default!; [Dependency] private readonly NPCUtilitySystem _utility = default!; + [Dependency] private readonly IConfigurationManager _cfg = default!; // Starlight - private readonly JobQueue _planQueue = new(0.004); + // Starlight start - HTN plan budget is cvar-driven (npc.htn_plan_budget) instead of a hardcoded 0.004 + private readonly AdjustableJobQueue _planQueue = new(0.004); + // Starlight end private readonly HashSet _subscribers = new(); @@ -40,6 +48,10 @@ public override void Initialize() SubscribeNetworkEvent(OnHTNMessage); SubscribeLocalEvent(OnPrototypeLoad); OnLoad(); + + // Starlight + Subs.CVar(_cfg, CCVars.NPCHTNPlanBudget, value => _planQueue.SetMaxTime(value), true); + // Starlight end } private void OnHTNMessage(RequestHTNMessage msg, EntitySessionEventArgs args) diff --git a/Content.Server/_Starlight/NPC/HTN/AdjustableJobQueue.cs b/Content.Server/_Starlight/NPC/HTN/AdjustableJobQueue.cs new file mode 100644 index 000000000000..af44733cc20d --- /dev/null +++ b/Content.Server/_Starlight/NPC/HTN/AdjustableJobQueue.cs @@ -0,0 +1,13 @@ +using Robust.Shared.CPUJob.JobQueues.Queues; + +namespace Content.Server._Starlight.NPC.HTN; + +public sealed class AdjustableJobQueue(double maxTime) : JobQueue +{ + private double _maxTime = maxTime; + + public override double MaxTime => _maxTime; + + public void SetMaxTime(double maxTime) + => _maxTime = maxTime; +} diff --git a/Content.Shared/CCVar/CCVars.NPC.cs b/Content.Shared/CCVar/CCVars.NPC.cs index f0d5520195d0..71dde6fe2a9d 100644 --- a/Content.Shared/CCVar/CCVars.NPC.cs +++ b/Content.Shared/CCVar/CCVars.NPC.cs @@ -13,4 +13,13 @@ public sealed partial class CCVars /// Should NPCs pathfind when steering. For debug purposes. /// public static readonly CVarDef NPCPathfinding = CVarDef.Create("npc.pathfinding", true); + + // Starlight start + /// + /// Per-tick wall-clock budget (seconds) the HTN planner is allowed to spend running plan jobs. + /// Lower it to cap NPC planning cost under load. Was a hardcoded 0.004 (4ms) in HTNSystem. + /// + public static readonly CVarDef NPCHTNPlanBudget = + CVarDef.Create("npc.htn_plan_budget", 0.004f, CVar.SERVERONLY); + // Starlight end }