feat: replace PlayerChat hook with Harmony patch on command dispatch
This commit is contained in:
@@ -0,0 +1,48 @@
|
|||||||
|
using System;
|
||||||
|
using HarmonyLib;
|
||||||
|
using Vintagestory.API.Common;
|
||||||
|
using Vintagestory.API.Server;
|
||||||
|
using Vintagestory.Common;
|
||||||
|
|
||||||
|
namespace CommandHook;
|
||||||
|
|
||||||
|
[HarmonyPatch(typeof(ChatCommandApi))]
|
||||||
|
public static class ChatCommandApiPatch
|
||||||
|
{
|
||||||
|
[HarmonyPatch(
|
||||||
|
"Execute",
|
||||||
|
new[] { typeof(string), typeof(TextCommandCallingArgs), typeof(Action<TextCommandResult>) }
|
||||||
|
)]
|
||||||
|
[HarmonyPrefix]
|
||||||
|
public static bool Prefix(
|
||||||
|
string commandName,
|
||||||
|
TextCommandCallingArgs args,
|
||||||
|
ref Action<TextCommandResult> onCommandComplete
|
||||||
|
)
|
||||||
|
{
|
||||||
|
var system = CommandHookModSystem.Instance;
|
||||||
|
if (system == null)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
var sender = args.Caller.Player as IServerPlayer;
|
||||||
|
var data = new CommandData(sender, "/" + commandName);
|
||||||
|
|
||||||
|
if (system.FireBefore(commandName, ref data))
|
||||||
|
{
|
||||||
|
onCommandComplete?.Invoke(
|
||||||
|
new TextCommandResult { Status = EnumCommandStatus.Deferred }
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var original = onCommandComplete;
|
||||||
|
onCommandComplete = result =>
|
||||||
|
{
|
||||||
|
original?.Invoke(result);
|
||||||
|
var afterData = data;
|
||||||
|
system.FireAfter(commandName, ref afterData, result);
|
||||||
|
};
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,35 +1,48 @@
|
|||||||
using System.Collections.Frozen;
|
using System.Collections.Frozen;
|
||||||
|
using HarmonyLib;
|
||||||
using Vintagestory.API.Common;
|
using Vintagestory.API.Common;
|
||||||
using Vintagestory.API.Datastructures;
|
|
||||||
using Vintagestory.API.Server;
|
using Vintagestory.API.Server;
|
||||||
|
|
||||||
namespace CommandHook;
|
namespace CommandHook;
|
||||||
|
|
||||||
public class CommandHookModSystem : ModSystem
|
public class CommandHookModSystem : ModSystem
|
||||||
{
|
{
|
||||||
|
internal static CommandHookModSystem? Instance;
|
||||||
|
|
||||||
private FrozenDictionary<string, FrozenDictionary<string, CommandRegistration>> registrations =
|
private FrozenDictionary<string, FrozenDictionary<string, CommandRegistration>> registrations =
|
||||||
FrozenDictionary<string, FrozenDictionary<string, CommandRegistration>>.Empty;
|
FrozenDictionary<string, FrozenDictionary<string, CommandRegistration>>.Empty;
|
||||||
|
|
||||||
|
private Harmony? harmony;
|
||||||
|
|
||||||
public override bool ShouldLoad(EnumAppSide forSide) => forSide == EnumAppSide.Server;
|
public override bool ShouldLoad(EnumAppSide forSide) => forSide == EnumAppSide.Server;
|
||||||
|
|
||||||
public override void StartServerSide(ICoreServerAPI api)
|
public override void StartServerSide(ICoreServerAPI api)
|
||||||
{
|
{
|
||||||
|
Instance = this;
|
||||||
|
harmony = new Harmony(Mod.Info.ModID);
|
||||||
|
harmony.PatchAll();
|
||||||
Mod.Logger.Notification("Loaded");
|
Mod.Logger.Notification("Loaded");
|
||||||
api.Event.PlayerChat += OnPlayerChat;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnPlayerChat(
|
public override void Dispose()
|
||||||
IServerPlayer player,
|
|
||||||
int channelId,
|
|
||||||
ref string message,
|
|
||||||
ref string data,
|
|
||||||
BoolRef consumed
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
if (!message.StartsWith('/'))
|
harmony?.UnpatchAll(Mod.Info.ModID);
|
||||||
return;
|
Instance = null;
|
||||||
|
}
|
||||||
|
|
||||||
var cmdData = new CommandData(player, message);
|
public bool FireBefore(string commandName, ref CommandData data)
|
||||||
// TODO dispatch
|
{
|
||||||
|
if (registrations.TryGetValue(commandName, out var mods))
|
||||||
|
foreach (var (_, reg) in mods)
|
||||||
|
reg.Before?.Invoke(ref data);
|
||||||
|
|
||||||
|
return data.Cancel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void FireAfter(string commandName, ref CommandData data, TextCommandResult result)
|
||||||
|
{
|
||||||
|
if (registrations.TryGetValue(commandName, out var mods))
|
||||||
|
foreach (var (_, reg) in mods)
|
||||||
|
reg.After?.Invoke(ref data, result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user