diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameMain.cs b/Barotrauma/BarotraumaClient/ClientSource/GameMain.cs index 2dc46b3d7..b37ca5668 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GameMain.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GameMain.cs @@ -297,6 +297,8 @@ namespace Barotrauma MainThread = Thread.CurrentThread; Window.FileDropped += OnFileDropped; + + LuaCs.GetType(); } public static void ExecuteAfterContentFinishedLoading(Action action) @@ -1051,9 +1053,6 @@ namespace Barotrauma SoundManager?.Update(); - LuaCs.EventService.PublishEvent(sub => sub.OnUpdate(Timing.Step)); - LuaCs.Logger.ProcessLogs(); - Timing.Accumulator -= Timing.Step; updateCount++; diff --git a/Barotrauma/BarotraumaClient/ClientSource/LuaCs/Services/NetworkingService.cs b/Barotrauma/BarotraumaClient/ClientSource/LuaCs/Services/NetworkingService.cs index 578e5c50f..4cde8a52b 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/LuaCs/Services/NetworkingService.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/LuaCs/Services/NetworkingService.cs @@ -7,11 +7,11 @@ using System.Collections.Generic; namespace Barotrauma.LuaCs; -partial class NetworkingService : INetworkingService, IEventConnectedToServer, IEventServerRawNetMessageReceived +partial class NetworkingService : INetworkingService, IEventServerConnected, IEventServerRawNetMessageReceived { private ConcurrentDictionary> receiveQueue = new(); - public void OnConnectedToServer() + public void OnServerConnected() { SendSyncMessage(); } diff --git a/Barotrauma/BarotraumaClient/ClientSource/PlayerInput.cs b/Barotrauma/BarotraumaClient/ClientSource/PlayerInput.cs index d3aa62499..593627a43 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/PlayerInput.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/PlayerInput.cs @@ -495,8 +495,6 @@ namespace Barotrauma allowInput = true; } - GameMain.LuaCs.Hook.Call("keyUpdate", deltaTime); - oldMouseState = mouseState; mouseState = latestMouseState; UpdateVariable(); diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/SubEditorScreen.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/SubEditorScreen.cs index d7b368980..8fb3e79a9 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Screens/SubEditorScreen.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/SubEditorScreen.cs @@ -1532,8 +1532,6 @@ namespace Barotrauma public override void Select() { Select(enableAutoSave: true); - - GameMain.LuaCs.EventService.PublishEvent(sub => sub.OnScreenSelected(this)); } public void Select(bool enableAutoSave = true) diff --git a/Barotrauma/BarotraumaServer/ServerSource/GameMain.cs b/Barotrauma/BarotraumaServer/ServerSource/GameMain.cs index b438e9af6..c875eed2f 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/GameMain.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/GameMain.cs @@ -114,6 +114,8 @@ namespace Barotrauma GameScreen = new GameScreen(); MainThread = Thread.CurrentThread; + + LuaCs.GetType(); } public void Init() @@ -364,9 +366,6 @@ namespace Barotrauma TaskPool.Update(); CoroutineManager.Update(paused: false, (float)Timing.Step); - LuaCs.EventService.PublishEvent(sub => sub.OnUpdate(Timing.Step)); - LuaCs.Logger.ProcessLogs(); - performanceCounterTimer.Stop(); if (GameMain.LuaCs.PerformanceCounter.EnablePerformanceCounter) { diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/Character.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/Character.cs index af94426d0..46ee0b105 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/Character.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/Character.cs @@ -1433,8 +1433,6 @@ namespace Barotrauma } #endif - GameMain.LuaCs.Hook.Call("character.created", new object[] { newCharacter }); - return newCharacter; } @@ -1889,7 +1887,6 @@ namespace Barotrauma } } info.Job?.GiveJobItems(this, isPvPMode, spawnPoint); - GameMain.LuaCs.Hook.Call("character.giveJobItems", this, spawnPoint, isPvPMode); } public void GiveIdCardTags(WayPoint spawnPoint, bool createNetworkEvent = false) diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/Health/Afflictions/Affliction.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/Health/Afflictions/Affliction.cs index 2dbe048f5..1202d80f4 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/Health/Afflictions/Affliction.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/Health/Afflictions/Affliction.cs @@ -482,7 +482,6 @@ namespace Barotrauma { GrainEffectStrength -= amount; } - GameMain.LuaCs.Hook.Call("afflictionUpdate", new object[] { this, characterHealth, targetLimb, deltaTime }); } public void ApplyStatusEffects(ActionType type, float deltaTime, CharacterHealth characterHealth, Limb targetLimb) diff --git a/Barotrauma/BarotraumaShared/SharedSource/ContentManagement/ContentPackageManager.cs b/Barotrauma/BarotraumaShared/SharedSource/ContentManagement/ContentPackageManager.cs index 3a1f8d0f0..dba9f064b 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/ContentManagement/ContentPackageManager.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/ContentManagement/ContentPackageManager.cs @@ -53,8 +53,6 @@ namespace Barotrauma public static void SetCore(CorePackage newCore) { SetCoreEnumerable(newCore).Consume(); - GameMain.LuaCs.EventService.PublishEvent( - sub => sub.OnEnabledPackageListChanged(Core, Regular)); } public static IEnumerable SetCoreEnumerable(CorePackage newCore) @@ -94,8 +92,6 @@ namespace Barotrauma public static void SetRegular(IReadOnlyList newRegular) { SetRegularEnumerable(newRegular).Consume(); - GameMain.LuaCs.EventService.PublishEvent( - sub => sub.OnEnabledPackageListChanged(Core, Regular)); } public static IEnumerable SetRegularEnumerable(IReadOnlyList inNewRegular) @@ -338,9 +334,6 @@ namespace Barotrauma Debug.WriteLine($"Loaded \"{newPackage.Name}\""); } - - GameMain.LuaCs.EventService.PublishEvent(sub => - sub.OnAllPackageListChanged(ContentPackageManager.CorePackages, ContentPackageManager.RegularPackages)); } private readonly string directory; @@ -580,12 +573,6 @@ namespace Barotrauma yield return p.Transform(loadingRange); } - GameMain.LuaCs.EventService.PublishEvent( - sub => sub.OnAllPackageListChanged(CorePackages, RegularPackages)); - - GameMain.LuaCs.EventService.PublishEvent( - sub => sub.OnEnabledPackageListChanged(EnabledPackages.Core, EnabledPackages.Regular)); - yield return LoadProgress.Progress(1.0f); } diff --git a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/IEvents.cs b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/IEvents.cs index 8c311239a..673ac328f 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/IEvents.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/IEvents.cs @@ -1,4 +1,5 @@ -using System; +using System.Runtime.CompilerServices; +using System; using System.Collections.Generic; using System.Reflection; using Barotrauma.LuaCs.Data; @@ -69,6 +70,69 @@ internal interface IEventSettingInstanceLifetime : IEvent +{ + void OnAfflictionUpdate(Affliction affliction, CharacterHealth characterHealth, Limb targetLimb, float deltaTime); + static IEventAfflictionUpdate IEvent.GetLuaRunner(IDictionary luaFunc) => new + { + IsLuaRunner = Return.Arguments(() => true), + OnKeyUpdate = ReturnVoid.Arguments((Affliction affliction, CharacterHealth characterHealth, Limb targetLimb, float deltaTime) => luaFunc[nameof(OnAfflictionUpdate)](affliction, characterHealth, targetLimb, deltaTime)) + }.ActLike(); +} + +internal interface IEventGiveCharacterJobItems : IEvent +{ + void OnGiveCharacterJobItems(Character character, WayPoint spawnPoint, bool isPvPMode); + static IEventGiveCharacterJobItems IEvent.GetLuaRunner(IDictionary luaFunc) => new + { + IsLuaRunner = Return.Arguments(() => true), + OnKeyUpdate = ReturnVoid.Arguments((Character character, WayPoint spawnPoint, bool isPvPMode) => luaFunc[nameof(OnGiveCharacterJobItems)](character, spawnPoint, isPvPMode)) + }.ActLike(); +} + +internal interface IEventCharacterCreated : IEvent +{ + void OnCharacterCreated(Character character); + static IEventCharacterCreated IEvent.GetLuaRunner(IDictionary luaFunc) => new + { + IsLuaRunner = Return.Arguments(() => true), + OnKeyUpdate = ReturnVoid.Arguments((Character character) => luaFunc[nameof(OnCharacterCreated)](character)) + }.ActLike(); +} + +/* +internal interface IEventHumanCPRFailed : IEvent +{ + void OnHumanCPRFailed(Character character); + static IEventHumanCPRFailed IEvent.GetLuaRunner(IDictionary luaFunc) => new + { + IsLuaRunner = Return.Arguments(() => true), + OnKeyUpdate = ReturnVoid.Arguments((Character character) => luaFunc[nameof(OnHumanCPRFailed)](character)) + }.ActLike(); +} + + +internal interface IEventHumanCPRSuccess : IEvent +{ + void OnHumanCPRSuccess(Character character); + static IEventHumanCPRSuccess IEvent.GetLuaRunner(IDictionary luaFunc) => new + { + IsLuaRunner = Return.Arguments(() => true), + OnKeyUpdate = ReturnVoid.Arguments((Character character) => luaFunc[nameof(OnHumanCPRSuccess)](character)) + }.ActLike(); +} +*/ + +public interface IEventKeyUpdate : IEvent +{ + void OnKeyUpdate(double deltaTime); + static IEventKeyUpdate IEvent.GetLuaRunner(IDictionary luaFunc) => new + { + IsLuaRunner = Return.Arguments(() => true), + OnKeyUpdate = ReturnVoid.Arguments((double deltaTime) => luaFunc[nameof(OnKeyUpdate)](deltaTime)) + }.ActLike(); +} + /// /// Called as soon as round begins to load before any loading takes place. /// @@ -121,31 +185,17 @@ public interface IEventDrawUpdate : IEvent }.ActLike(); } -#if CLIENT -public interface IEventServerRawNetMessageReceived : IEvent -{ - void OnReceivedServerNetMessage(IReadMessage netMessage, ServerPacketHeader serverPacketHeader); -} - -public interface IEventConnectedToServer : IEvent -{ - void OnConnectedToServer(); -} - -#elif SERVER -public interface IEventClientRawNetMessageReceived : IEvent -{ - void OnReceivedClientNetMessage(IReadMessage netMessage, ClientPacketHeader serverPacketHeader, NetworkConnection sender); -} -#endif - #endregion #region Networking - #region Networking-Server #if SERVER +public interface IEventClientRawNetMessageReceived : IEvent +{ + void OnReceivedClientNetMessage(IReadMessage netMessage, ClientPacketHeader serverPacketHeader, NetworkConnection sender); +} + /// /// Called when a client connects to the server and has loaded into the lobby. /// @@ -163,10 +213,17 @@ interface IEventClientConnected : IEvent }.ActLike(); } #endif + #endregion #region Networking-Client #if CLIENT + +public interface IEventServerRawNetMessageReceived : IEvent +{ + void OnReceivedServerNetMessage(IReadMessage netMessage, ServerPacketHeader serverPacketHeader); +} + /// /// Called when the client has connected to the server and loaded to the lobby. /// diff --git a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/LuaCsSetup.cs b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/LuaCsSetup.cs index db4fbbfd0..5ffb73d69 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/LuaCsSetup.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/LuaCsSetup.cs @@ -1,25 +1,21 @@ -using System; -using System.Collections.Concurrent; +using Barotrauma.LuaCs; +using Barotrauma.LuaCs.Compatibility; +using Barotrauma.LuaCs.Data; +using Barotrauma.LuaCs.Events; +using Barotrauma.Networking; +using FluentResults; +using ImpromptuInterface; +using LightInject; +using System; using System.Collections.Generic; using System.Collections.Immutable; using System.IO; using System.Linq; -using System.Net.Mime; -using System.Reflection; -using System.Threading; -using System.Threading.Tasks; -using Barotrauma.LuaCs; -using Barotrauma.LuaCs.Data; -using Barotrauma.LuaCs.Events; -using Barotrauma.LuaCs.Compatibility; -using Barotrauma.Networking; -using Barotrauma.Steam; -using FluentResults; -using ImpromptuInterface; -using LightInject; -using Microsoft.Toolkit.Diagnostics; +using System.Runtime.CompilerServices; using AssemblyLoader = Barotrauma.LuaCs.AssemblyLoader; +[assembly: InternalsVisibleTo("ImpromptuInterfaceDynamicAssembly")] +[assembly: InternalsVisibleTo("Dynamitey")] namespace Barotrauma { internal delegate void LuaCsMessageLogger(string message); @@ -34,6 +30,9 @@ namespace Barotrauma // == startup _servicesProvider = SetupServicesProvider(); _runStateMachine = SetupStateMachine(); + + _servicesProvider.GetService(); + SubscribeToLuaCsEvents(); } @@ -186,6 +185,7 @@ namespace Barotrauma servicesProvider.RegisterServiceType(ServiceLifetime.Singleton); servicesProvider.RegisterServiceType(ServiceLifetime.Singleton); servicesProvider.RegisterServiceType(ServiceLifetime.Transient); + servicesProvider.RegisterServiceType(ServiceLifetime.Singleton); // Extension/Sub Services servicesProvider.RegisterServiceType(ServiceLifetime.Transient); @@ -379,7 +379,7 @@ namespace Barotrauma // Technically not very accurate, but we want to call after we run mods anyway if (GameMain.Client != null) { - EventService.PublishEvent(static p => p.OnConnectedToServer()); + EventService.PublishEvent(static p => p.OnServerConnected()); } #endif CurrentRunState = RunState.Running; diff --git a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/_Services/HarmonyEventPatchesService.cs b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/_Services/HarmonyEventPatchesService.cs new file mode 100644 index 000000000..c31ac49db --- /dev/null +++ b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/_Services/HarmonyEventPatchesService.cs @@ -0,0 +1,130 @@ +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(x => x.OnUpdate(Timing.TotalTime)); + _loggerService.ProcessLogs(); + } + + [HarmonyPatch(typeof(Screen), nameof(Screen.Select)), HarmonyPostfix] + public static void Screen_Selected_Post(Screen __instance) + { + _eventService.PublishEvent(x => x.OnScreenSelected(__instance)); + } + + [HarmonyPatch(typeof(ContentPackageManager.PackageSource), nameof(ContentPackageManager.PackageSource.Refresh)), HarmonyPostfix] + public static void PackageSource_Refresh_Post() + { + _eventService.PublishEvent(x => x.OnAllPackageListChanged(ContentPackageManager.CorePackages, ContentPackageManager.RegularPackages)); + } + + [HarmonyPatch(typeof(ContentPackageManager), nameof(ContentPackageManager.Init)), HarmonyPostfix] + public static void ContentPackageManager_Init_Post() + { + _eventService.PublishEvent(x => x.OnAllPackageListChanged(ContentPackageManager.CorePackages, ContentPackageManager.RegularPackages)); + _eventService.PublishEvent(sub => sub.OnEnabledPackageListChanged(EnabledPackages.Core, EnabledPackages.Regular)); + } + + [HarmonyPatch(typeof(ContentPackageManager.EnabledPackages), nameof(ContentPackageManager.EnabledPackages.SetCore)), HarmonyPostfix] + public static void EnabledPackages_SetCore_Post() + { + _eventService.PublishEvent(sub => sub.OnEnabledPackageListChanged(EnabledPackages.Core, EnabledPackages.Regular)); + } + + [HarmonyPatch(typeof(ContentPackageManager.EnabledPackages), nameof(ContentPackageManager.EnabledPackages.SetRegular)), HarmonyPostfix] + public static void EnabledPackages_SetRegular_Post() + { + _eventService.PublishEvent(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.PeekByte(); // Read but don't advance the read pointer + _eventService.PublishEvent(x => x.OnReceivedServerNetMessage(inc, header)); + } + + [HarmonyPatch(typeof(SubEditorScreen), nameof(SubEditorScreen.Select), new Type[] { }), HarmonyPostfix] + public static void SubEditorScreen_Selected_Post(Screen __instance) + { + _eventService.PublishEvent(x => x.OnScreenSelected(__instance)); + } + + [HarmonyPatch(typeof(PlayerInput), nameof(PlayerInput.Update)), HarmonyPrefix] + public static void PlayerInput_Update_Pre(double deltaTime) + { + _eventService.PublishEvent(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.PeekByte(); // Read but don't advance the read pointer + _eventService.PublishEvent(x => x.OnReceivedClientNetMessage(inc, header, sender)); + } +#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(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(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(x => x.OnAfflictionUpdate(__instance, characterHealth, targetLimb, deltaTime)); + } + + public void Dispose() + { + Harmony.UnpatchSelf(); + IsDisposed = true; + } +} diff --git a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/_Services/LuaScriptManagementService.cs b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/_Services/LuaScriptManagementService.cs index ed67f6525..04b21c67a 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/_Services/LuaScriptManagementService.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/_Services/LuaScriptManagementService.cs @@ -172,6 +172,11 @@ class LuaScriptManagementService : ILuaScriptManagementService, ILuaDataService private void RegisterLuaEvents() { _eventService.RegisterLuaEventAlias("think", "OnUpdate"); + _eventService.RegisterLuaEventAlias("keyUpdate", "OnKeyUpdate"); + _eventService.RegisterLuaEventAlias("character.created", "OnCharacterCreated"); + _eventService.RegisterLuaEventAlias("character.giveJobItems", "OnGiveCharacterJobItems"); + _eventService.RegisterLuaEventAlias("afflictionUpdate", "OnAfflictionUpdate"); + } private void SetupEnvironment(bool enableSandbox) diff --git a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/_Services/NetworkingService.cs b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/_Services/NetworkingService.cs index 8c8cac4ef..909e1f2c7 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/_Services/NetworkingService.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/_Services/NetworkingService.cs @@ -147,7 +147,7 @@ internal partial class NetworkingService : INetworkingService private void SubscribeToEvents() { #if CLIENT - _eventService.Subscribe(this); + _eventService.Subscribe(this); _eventService.Subscribe(this); #elif SERVER _eventService.Subscribe(this); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Screens/Screen.cs b/Barotrauma/BarotraumaShared/SharedSource/Screens/Screen.cs index abe2c0f3d..622a47591 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Screens/Screen.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Screens/Screen.cs @@ -43,7 +43,6 @@ GUI.SettingsMenuOpen = false; #endif Selected = this; - GameMain.LuaCs.EventService.PublishEvent(sub => sub.OnScreenSelected(this)); } public virtual Camera Cam => null;