#if UNITY_EDITOR using System.Collections.Generic; using ProjectM.Simulation; using Unity.Entities; using Unity.NetCode; namespace ProjectM.Server { /// /// Editor-only debug hook (mirrors ProjectM.Client.DebugInputInjectionSystem's static-poke pattern) /// for driving the server-authoritative modifier stack from MCP execute_code. Because modifiers are /// server-authoritative, a client-side append would be stomped by the next snapshot, so this runs in /// the SERVER world: the change flows back through the snapshot and is prediction-correct on the /// client. In-editor single-process only (client + server worlds in one process). Poke from execute_code: /// DebugModifierInjectionSystem.AddModifier((byte)StatTarget.Damage, (byte)ModOp.Flat, 50f); /// DebugModifierInjectionSystem.AddModifier((byte)StatTarget.MoveSpeed, (byte)ModOp.PercentAdd, 0.5f); /// DebugModifierInjectionSystem.ClearModifiers(); /// All applied to the first player on the next server tick. /// [WorldSystemFilter(WorldSystemFilterFlags.ServerSimulation)] public partial class DebugModifierInjectionSystem : SystemBase { struct PendingModifier { public byte Target; public byte Op; public float Value; } static readonly List s_Pending = new List(); static bool s_Clear; /// Queue a modifier to append to the first player on the next server tick. public static void AddModifier(byte target, byte op, float value) { s_Pending.Add(new PendingModifier { Target = target, Op = op, Value = value }); } /// Clear the first player's whole modifier stack on the next server tick. public static void ClearModifiers() => s_Clear = true; protected override void OnUpdate() { if (s_Pending.Count == 0 && !s_Clear) return; Entity player = Entity.Null; foreach (var (tag, e) in SystemAPI.Query>().WithAll().WithEntityAccess()) { player = e; break; } if (player == Entity.Null) return; if (s_Clear) { EntityManager.GetBuffer(player).Clear(); s_Clear = false; } if (s_Pending.Count > 0) { var buffer = EntityManager.GetBuffer(player); for (int i = 0; i < s_Pending.Count; i++) { var m = s_Pending[i]; buffer.Add(new StatModifier { Target = m.Target, Op = m.Op, Value = m.Value, SourceId = 0u }); } s_Pending.Clear(); } } } } #endif