-- MonoMod.Hook replacement.
This commit is contained in:
@@ -9,7 +9,6 @@ using System.Diagnostics.CodeAnalysis;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
using Barotrauma.IO;
|
using Barotrauma.IO;
|
||||||
using Barotrauma.LuaCs.Events;
|
|
||||||
using Barotrauma.Steam;
|
using Barotrauma.Steam;
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using OneOf.Types;
|
using OneOf.Types;
|
||||||
|
|||||||
@@ -30,10 +30,21 @@ namespace Barotrauma
|
|||||||
// == startup
|
// == startup
|
||||||
_servicesProvider = SetupServicesProvider();
|
_servicesProvider = SetupServicesProvider();
|
||||||
_runStateMachine = SetupStateMachine();
|
_runStateMachine = SetupStateMachine();
|
||||||
|
_servicesProvider.GetService<EventPatchingService>();
|
||||||
_servicesProvider.GetService<HarmonyEventPatchesService>();
|
|
||||||
|
|
||||||
SubscribeToLuaCsEvents();
|
SubscribeToLuaCsEvents();
|
||||||
|
PatchEventMethods();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PatchEventMethods()
|
||||||
|
{
|
||||||
|
if (_servicesProvider.TryGetService<EventPatchingService>(out var svc))
|
||||||
|
{
|
||||||
|
svc.GenerateMethodHooks();
|
||||||
|
Logger.LogDebug($"Patched methods.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger.LogError($"Failed to find {nameof(EventPatchingService)}");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SubscribeToLuaCsEvents()
|
private void SubscribeToLuaCsEvents()
|
||||||
@@ -185,7 +196,7 @@ namespace Barotrauma
|
|||||||
servicesProvider.RegisterServiceType<IConfigService, ConfigService>(ServiceLifetime.Singleton);
|
servicesProvider.RegisterServiceType<IConfigService, ConfigService>(ServiceLifetime.Singleton);
|
||||||
servicesProvider.RegisterServiceType<INetworkingService, NetworkingService>(ServiceLifetime.Singleton);
|
servicesProvider.RegisterServiceType<INetworkingService, NetworkingService>(ServiceLifetime.Singleton);
|
||||||
servicesProvider.RegisterServiceType<INetworkIdProvider, NetworkingIdProvider>(ServiceLifetime.Transient);
|
servicesProvider.RegisterServiceType<INetworkIdProvider, NetworkingIdProvider>(ServiceLifetime.Transient);
|
||||||
servicesProvider.RegisterServiceType<HarmonyEventPatchesService, HarmonyEventPatchesService>(ServiceLifetime.Singleton);
|
servicesProvider.RegisterServiceType<EventPatchingService, EventPatchingService>(ServiceLifetime.Singleton);
|
||||||
|
|
||||||
// Extension/Sub Services
|
// Extension/Sub Services
|
||||||
servicesProvider.RegisterServiceType<IAssemblyLoaderService.IFactory, AssemblyLoader.Factory>(ServiceLifetime.Transient);
|
servicesProvider.RegisterServiceType<IAssemblyLoaderService.IFactory, AssemblyLoader.Factory>(ServiceLifetime.Transient);
|
||||||
|
|||||||
@@ -0,0 +1,191 @@
|
|||||||
|
using Barotrauma.LuaCs;
|
||||||
|
using Barotrauma.LuaCs.Events;
|
||||||
|
using Barotrauma.Networking;
|
||||||
|
using HarmonyLib;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.Immutable;
|
||||||
|
using System.Reflection;
|
||||||
|
using MonoMod.RuntimeDetour;
|
||||||
|
using static Barotrauma.ContentPackageManager;
|
||||||
|
|
||||||
|
namespace Barotrauma.LuaCs;
|
||||||
|
|
||||||
|
|
||||||
|
internal class EventPatchingService : IService
|
||||||
|
{
|
||||||
|
public bool IsDisposed { get; private set; }
|
||||||
|
private static EventPatchingService _instance;
|
||||||
|
private IEventService _eventService;
|
||||||
|
private ILoggerService _loggerService;
|
||||||
|
/// <summary>
|
||||||
|
/// Key: Original Method, Value: Active Hook.
|
||||||
|
/// </summary>
|
||||||
|
private readonly ConcurrentDictionary<MethodInfo, Hook> _runtimeHooks = new();
|
||||||
|
|
||||||
|
#region METHODINFO
|
||||||
|
|
||||||
|
private static readonly MethodInfo Screen_Select_Orig =
|
||||||
|
typeof(Screen).GetMethod(nameof(Screen.Select), BindingFlags.Instance | BindingFlags.Public);
|
||||||
|
|
||||||
|
private static readonly MethodInfo EnabledPackages_SetCore_Orig =
|
||||||
|
typeof(ContentPackageManager.EnabledPackages).GetMethod(nameof(ContentPackageManager.EnabledPackages.SetCore),
|
||||||
|
BindingFlags.Static | BindingFlags.Public);
|
||||||
|
|
||||||
|
private static readonly MethodInfo EnabledPackages_SetRegular_Orig =
|
||||||
|
typeof(ContentPackageManager.EnabledPackages).GetMethod(nameof(ContentPackageManager.EnabledPackages.SetRegular),
|
||||||
|
BindingFlags.Static | BindingFlags.Public);
|
||||||
|
|
||||||
|
private static readonly MethodInfo Character_Create_Orig =
|
||||||
|
AccessTools.DeclaredMethod(typeof(Character),
|
||||||
|
nameof(Character.Create), new []
|
||||||
|
{
|
||||||
|
typeof(CharacterPrefab),
|
||||||
|
typeof(Vector2),
|
||||||
|
typeof(string),
|
||||||
|
typeof(CharacterInfo),
|
||||||
|
typeof(ushort),
|
||||||
|
typeof(bool),
|
||||||
|
typeof(bool),
|
||||||
|
typeof(bool),
|
||||||
|
typeof(RagdollParams),
|
||||||
|
typeof(bool)
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
public EventPatchingService(IEventService eventService, ILoggerService loggerService)
|
||||||
|
{
|
||||||
|
_eventService = eventService;
|
||||||
|
_loggerService = loggerService;
|
||||||
|
_instance = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GenerateMethodHooks()
|
||||||
|
{
|
||||||
|
IService.CheckDisposed(this);
|
||||||
|
|
||||||
|
if (!_runtimeHooks.IsEmpty)
|
||||||
|
{
|
||||||
|
_loggerService.LogError($"{nameof(GenerateMethodHooks)}: Hooks are already active!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_runtimeHooks.TryAdd(Screen_Select_Orig, new Hook(
|
||||||
|
Screen_Select_Orig,
|
||||||
|
this.Screen_Select_Post
|
||||||
|
));
|
||||||
|
|
||||||
|
_runtimeHooks.TryAdd(EnabledPackages_SetCore_Orig, new Hook(
|
||||||
|
EnabledPackages_SetCore_Orig,
|
||||||
|
typeof(EventPatchingService).GetMethod(nameof(EnabledPackages_SetCore_Post))
|
||||||
|
));
|
||||||
|
|
||||||
|
_runtimeHooks.TryAdd(EnabledPackages_SetRegular_Orig, new Hook(
|
||||||
|
EnabledPackages_SetRegular_Orig,
|
||||||
|
typeof(EventPatchingService).GetMethod(nameof(EnabledPackages_SetRegular_Post))
|
||||||
|
));
|
||||||
|
|
||||||
|
_runtimeHooks.TryAdd(Character_Create_Orig, new Hook(
|
||||||
|
Character_Create_Orig,
|
||||||
|
this.Character_Create_Post
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CoroutineManager_Update_Post()
|
||||||
|
{
|
||||||
|
_eventService.PublishEvent<IEventUpdate>(x => x.OnUpdate(Timing.TotalTime));
|
||||||
|
_loggerService.ProcessLogs();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Screen_Select_Post(Action<Screen> orig, Screen src)
|
||||||
|
{
|
||||||
|
orig(src);
|
||||||
|
_eventService.PublishEvent<IEventScreenSelected>(x => x.OnScreenSelected(Screen.Selected));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PackageSource_Refresh_Post()
|
||||||
|
{
|
||||||
|
_eventService.PublishEvent<IEventAllPackageListChanged>(x => x.OnAllPackageListChanged(ContentPackageManager.CorePackages, ContentPackageManager.RegularPackages));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ContentPackageManager_Init_Post()
|
||||||
|
{
|
||||||
|
_eventService.PublishEvent<IEventAllPackageListChanged>(x => x.OnAllPackageListChanged(ContentPackageManager.CorePackages, ContentPackageManager.RegularPackages));
|
||||||
|
_eventService.PublishEvent<IEventEnabledPackageListChanged>(sub => sub.OnEnabledPackageListChanged(EnabledPackages.Core, EnabledPackages.Regular));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void EnabledPackages_SetCore_Post(Action<CorePackage> orig, CorePackage newCore)
|
||||||
|
{
|
||||||
|
orig(newCore);
|
||||||
|
_instance?._eventService.PublishEvent<IEventEnabledPackageListChanged>(sub => sub.OnEnabledPackageListChanged(EnabledPackages.Core, EnabledPackages.Regular));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void EnabledPackages_SetRegular_Post(Action<IReadOnlyList<RegularPackage>> orig, IReadOnlyList<RegularPackage> newRegular)
|
||||||
|
{
|
||||||
|
orig(newRegular);
|
||||||
|
_instance?._eventService.PublishEvent<IEventEnabledPackageListChanged>(sub => sub.OnEnabledPackageListChanged(EnabledPackages.Core, EnabledPackages.Regular));
|
||||||
|
}
|
||||||
|
|
||||||
|
#if CLIENT
|
||||||
|
public void GameClient_ReadDataMessage_Pre(IReadMessage inc)
|
||||||
|
{
|
||||||
|
ServerPacketHeader header = (ServerPacketHeader)inc.ReadByte();
|
||||||
|
_eventService.PublishEvent<IEventServerRawNetMessageReceived>(x => x.OnReceivedServerNetMessage(inc, header));
|
||||||
|
inc.BitPosition -= 8; // rewind so the game can read the message
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SubEditorScreen_Selected_Post(Screen __instance)
|
||||||
|
{
|
||||||
|
_eventService.PublishEvent<IEventScreenSelected>(x => x.OnScreenSelected(__instance));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PlayerInput_Update_Pre(double deltaTime)
|
||||||
|
{
|
||||||
|
_eventService.PublishEvent<IEventKeyUpdate>(x => x.OnKeyUpdate(deltaTime));
|
||||||
|
}
|
||||||
|
#elif SERVER
|
||||||
|
public void GameServer_ReadDataMessage_Pre(NetworkConnection sender, IReadMessage inc)
|
||||||
|
{
|
||||||
|
ClientPacketHeader header = (ClientPacketHeader)inc.ReadByte();
|
||||||
|
_eventService.PublishEvent<IEventClientRawNetMessageReceived>(x => x.OnReceivedClientNetMessage(inc, header, sender));
|
||||||
|
inc.BitPosition -= 8; // rewind so the game can read the message
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Character.Create(), Line 1411.
|
||||||
|
public Character Character_Create_Post(Func<CharacterPrefab, Vector2, string, CharacterInfo, ushort, bool, bool, bool, RagdollParams, bool, Character> orig,
|
||||||
|
CharacterPrefab prefab, Vector2 position, string seed,
|
||||||
|
CharacterInfo characterInfo = null, ushort id = Entity.NullEntityID,
|
||||||
|
bool isRemotePlayer = false, bool hasAi = true, bool createNetworkEvent = true,
|
||||||
|
RagdollParams ragdoll = null, bool spawnInitialItems = true)
|
||||||
|
{
|
||||||
|
Character result = orig(prefab, position, seed, characterInfo, id, isRemotePlayer, hasAi, createNetworkEvent,
|
||||||
|
ragdoll, spawnInitialItems);
|
||||||
|
_eventService.PublishEvent<IEventCharacterCreated>(x => x.OnCharacterCreated(result));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Character_GiveJobItems_Post(Character __instance, WayPoint spawnPoint, bool isPvPMode)
|
||||||
|
{
|
||||||
|
_eventService.PublishEvent<IEventGiveCharacterJobItems>(x => x.OnGiveCharacterJobItems(__instance, spawnPoint, isPvPMode));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Affliction_Update_Post(Affliction __instance, CharacterHealth characterHealth, Limb targetLimb, float deltaTime)
|
||||||
|
{
|
||||||
|
_eventService.PublishEvent<IEventAfflictionUpdate>(x => x.OnAfflictionUpdate(__instance, characterHealth, targetLimb, deltaTime));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
IsDisposed = true;
|
||||||
|
foreach (var runtimeHook in _runtimeHooks)
|
||||||
|
{
|
||||||
|
runtimeHook.Value.Dispose();
|
||||||
|
}
|
||||||
|
_runtimeHooks.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
-132
@@ -1,132 +0,0 @@
|
|||||||
using Barotrauma.LuaCs;
|
|
||||||
using Barotrauma.LuaCs.Events;
|
|
||||||
using Barotrauma.Networking;
|
|
||||||
using HarmonyLib;
|
|
||||||
using Microsoft.Xna.Framework;
|
|
||||||
using System;
|
|
||||||
using static Barotrauma.ContentPackageManager;
|
|
||||||
|
|
||||||
namespace Barotrauma.LuaCs;
|
|
||||||
|
|
||||||
[HarmonyPatch]
|
|
||||||
internal class HarmonyEventPatchesService : IService
|
|
||||||
{
|
|
||||||
public bool IsDisposed { get; private set; }
|
|
||||||
|
|
||||||
private static IEventService _eventService;
|
|
||||||
private static ILoggerService _loggerService;
|
|
||||||
private readonly Harmony Harmony;
|
|
||||||
|
|
||||||
public HarmonyEventPatchesService(IEventService eventService, ILoggerService loggerService)
|
|
||||||
{
|
|
||||||
_eventService = eventService;
|
|
||||||
_loggerService = loggerService;
|
|
||||||
Harmony = new Harmony("LuaCsForBarotrauma.Events");
|
|
||||||
Harmony.PatchAll(typeof(HarmonyEventPatchesService));
|
|
||||||
}
|
|
||||||
|
|
||||||
[HarmonyPatch(typeof(CoroutineManager), nameof(CoroutineManager.Update)), HarmonyPostfix]
|
|
||||||
public static void CoroutineManager_Update_Post()
|
|
||||||
{
|
|
||||||
_eventService.PublishEvent<IEventUpdate>(x => x.OnUpdate(Timing.TotalTime));
|
|
||||||
_loggerService.ProcessLogs();
|
|
||||||
}
|
|
||||||
|
|
||||||
[HarmonyPatch(typeof(Screen), nameof(Screen.Select)), HarmonyPostfix]
|
|
||||||
public static void Screen_Selected_Post(Screen __instance)
|
|
||||||
{
|
|
||||||
_eventService.PublishEvent<IEventScreenSelected>(x => x.OnScreenSelected(__instance));
|
|
||||||
}
|
|
||||||
|
|
||||||
[HarmonyPatch(typeof(ContentPackageManager.PackageSource), nameof(ContentPackageManager.PackageSource.Refresh)), HarmonyPostfix]
|
|
||||||
public static void PackageSource_Refresh_Post()
|
|
||||||
{
|
|
||||||
_eventService.PublishEvent<IEventAllPackageListChanged>(x => x.OnAllPackageListChanged(ContentPackageManager.CorePackages, ContentPackageManager.RegularPackages));
|
|
||||||
}
|
|
||||||
|
|
||||||
[HarmonyPatch(typeof(ContentPackageManager), nameof(ContentPackageManager.Init)), HarmonyPostfix]
|
|
||||||
public static void ContentPackageManager_Init_Post()
|
|
||||||
{
|
|
||||||
_eventService.PublishEvent<IEventAllPackageListChanged>(x => x.OnAllPackageListChanged(ContentPackageManager.CorePackages, ContentPackageManager.RegularPackages));
|
|
||||||
_eventService.PublishEvent<IEventEnabledPackageListChanged>(sub => sub.OnEnabledPackageListChanged(EnabledPackages.Core, EnabledPackages.Regular));
|
|
||||||
}
|
|
||||||
|
|
||||||
[HarmonyPatch(typeof(ContentPackageManager.EnabledPackages), nameof(ContentPackageManager.EnabledPackages.SetCore)), HarmonyPostfix]
|
|
||||||
public static void EnabledPackages_SetCore_Post()
|
|
||||||
{
|
|
||||||
_eventService.PublishEvent<IEventEnabledPackageListChanged>(sub => sub.OnEnabledPackageListChanged(EnabledPackages.Core, EnabledPackages.Regular));
|
|
||||||
}
|
|
||||||
|
|
||||||
[HarmonyPatch(typeof(ContentPackageManager.EnabledPackages), nameof(ContentPackageManager.EnabledPackages.SetRegular)), HarmonyPostfix]
|
|
||||||
public static void EnabledPackages_SetRegular_Post()
|
|
||||||
{
|
|
||||||
_eventService.PublishEvent<IEventEnabledPackageListChanged>(sub => sub.OnEnabledPackageListChanged(EnabledPackages.Core, EnabledPackages.Regular));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if CLIENT
|
|
||||||
[HarmonyPatch(typeof(GameClient), "ReadDataMessage"), HarmonyPrefix]
|
|
||||||
public static void GameClient_ReadDataMessage_Pre(IReadMessage inc)
|
|
||||||
{
|
|
||||||
ServerPacketHeader header = (ServerPacketHeader)inc.ReadByte();
|
|
||||||
_eventService.PublishEvent<IEventServerRawNetMessageReceived>(x => x.OnReceivedServerNetMessage(inc, header));
|
|
||||||
inc.BitPosition -= 8; // rewind so the game can read the message
|
|
||||||
}
|
|
||||||
|
|
||||||
[HarmonyPatch(typeof(SubEditorScreen), nameof(SubEditorScreen.Select), new Type[] { }), HarmonyPostfix]
|
|
||||||
public static void SubEditorScreen_Selected_Post(Screen __instance)
|
|
||||||
{
|
|
||||||
_eventService.PublishEvent<IEventScreenSelected>(x => x.OnScreenSelected(__instance));
|
|
||||||
}
|
|
||||||
|
|
||||||
[HarmonyPatch(typeof(PlayerInput), nameof(PlayerInput.Update)), HarmonyPrefix]
|
|
||||||
public static void PlayerInput_Update_Pre(double deltaTime)
|
|
||||||
{
|
|
||||||
_eventService.PublishEvent<IEventKeyUpdate>(x => x.OnKeyUpdate(deltaTime));
|
|
||||||
}
|
|
||||||
#elif SERVER
|
|
||||||
[HarmonyPatch(typeof(GameServer), "ReadDataMessage"), HarmonyPrefix]
|
|
||||||
public static void GameServer_ReadDataMessage_Pre(NetworkConnection sender, IReadMessage inc)
|
|
||||||
{
|
|
||||||
ClientPacketHeader header = (ClientPacketHeader)inc.ReadByte();
|
|
||||||
_eventService.PublishEvent<IEventClientRawNetMessageReceived>(x => x.OnReceivedClientNetMessage(inc, header, sender));
|
|
||||||
inc.BitPosition -= 8; // rewind so the game can read the message
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
[HarmonyPatch(typeof(Character), nameof(Character.Create), new[] {
|
|
||||||
typeof(CharacterPrefab),
|
|
||||||
typeof(Vector2),
|
|
||||||
typeof(string),
|
|
||||||
typeof(CharacterInfo),
|
|
||||||
typeof(ushort),
|
|
||||||
typeof(bool),
|
|
||||||
typeof(bool),
|
|
||||||
typeof(bool),
|
|
||||||
typeof(RagdollParams),
|
|
||||||
typeof(bool)
|
|
||||||
}), HarmonyPostfix]
|
|
||||||
public static void Character_Create_Post(Character __result)
|
|
||||||
{
|
|
||||||
_eventService.PublishEvent<IEventCharacterCreated>(x => x.OnCharacterCreated(__result));
|
|
||||||
}
|
|
||||||
|
|
||||||
[HarmonyPatch(typeof(Character), nameof(Character.GiveJobItems)), HarmonyPostfix]
|
|
||||||
public static void Character_GiveJobItems_Post(Character __instance, WayPoint spawnPoint, bool isPvPMode)
|
|
||||||
{
|
|
||||||
_eventService.PublishEvent<IEventGiveCharacterJobItems>(x => x.OnGiveCharacterJobItems(__instance, spawnPoint, isPvPMode));
|
|
||||||
}
|
|
||||||
|
|
||||||
[HarmonyPatch(typeof(Affliction), nameof(Affliction.Update)), HarmonyPostfix]
|
|
||||||
public static void Affliction_Update_Post(Affliction __instance, CharacterHealth characterHealth, Limb targetLimb, float deltaTime)
|
|
||||||
{
|
|
||||||
_eventService.PublishEvent<IEventAfflictionUpdate>(x => x.OnAfflictionUpdate(__instance, characterHealth, targetLimb, deltaTime));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
Harmony.UnpatchSelf();
|
|
||||||
IsDisposed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user