From 10dfd45afa2dd468ae7b8d4eeefbe81929308494 Mon Sep 17 00:00:00 2001 From: Luke Date: Fri, 3 Jan 2025 09:23:08 +1000 Subject: [PATCH 01/12] Update to .NET 9 --- .github/workflows/build.yml | 6 +++--- .github/workflows/nuget.yml | 6 +++--- .../TerrariaServerAPI.Tests.csproj | 17 ++++++++++------- TerrariaServerAPI/TerrariaServerAPI.csproj | 8 ++++---- 4 files changed, 20 insertions(+), 17 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3115601c..1549c919 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -18,11 +18,11 @@ jobs: # Steps represent a sequence of tasks that will be executed as part of the job steps: # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - - uses: actions/setup-dotnet@v3 + - uses: actions/setup-dotnet@v4 with: - dotnet-version: '6.0.100' + dotnet-version: 9.0.x - name: MonoMod dev build run: dotnet nuget add source https://pkgs.dev.azure.com/MonoMod/MonoMod/_packaging/DevBuilds%40Local/nuget/v3/index.json -n DevBuilds@Local diff --git a/.github/workflows/nuget.yml b/.github/workflows/nuget.yml index 87cb8505..8e6fc2e6 100644 --- a/.github/workflows/nuget.yml +++ b/.github/workflows/nuget.yml @@ -11,11 +11,11 @@ jobs: environment: release steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Setup .NET - uses: actions/setup-dotnet@v3 + uses: actions/setup-dotnet@v4 with: - dotnet-version: 6.0.400 + dotnet-version: 9.0.x - name: Restore dependencies run: dotnet restore - name: Build diff --git a/TerrariaServerAPI.Tests/TerrariaServerAPI.Tests.csproj b/TerrariaServerAPI.Tests/TerrariaServerAPI.Tests.csproj index e2ebd9a0..4a7def9c 100644 --- a/TerrariaServerAPI.Tests/TerrariaServerAPI.Tests.csproj +++ b/TerrariaServerAPI.Tests/TerrariaServerAPI.Tests.csproj @@ -1,19 +1,22 @@ - net6.0 + net9.0 enable false - - - - - - + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/TerrariaServerAPI/TerrariaServerAPI.csproj b/TerrariaServerAPI/TerrariaServerAPI.csproj index afea6530..2a15e5e2 100644 --- a/TerrariaServerAPI/TerrariaServerAPI.csproj +++ b/TerrariaServerAPI/TerrariaServerAPI.csproj @@ -4,7 +4,7 @@ Library TerrariaServer - net6.0 + net9.0 true True Always @@ -21,8 +21,8 @@ - - - + + + From 2233b93b8ffd02697e459adcbeec776edfc3dd69 Mon Sep 17 00:00:00 2001 From: Luke Date: Fri, 3 Jan 2025 11:04:44 +1000 Subject: [PATCH 02/12] Move to OTAPI static hooks --- TerrariaServerAPI.Tests/BaseTest.cs | 6 +- .../TerrariaApi.Server/Hooking/GameHooks.cs | 116 ++++---- .../TerrariaApi.Server/Hooking/ItemHooks.cs | 66 ++--- .../TerrariaApi.Server/Hooking/NetHooks.cs | 273 +++++++++--------- .../TerrariaApi.Server/Hooking/NpcHooks.cs | 233 ++++++++------- .../Hooking/ProjectileHooks.cs | 55 ++-- .../TerrariaApi.Server/Hooking/ServerHooks.cs | 73 ++--- .../TerrariaApi.Server/Hooking/WiringHooks.cs | 35 ++- .../TerrariaApi.Server/Hooking/WorldHooks.cs | 136 +++++---- TerrariaServerAPI/TerrariaServerAPI.csproj | 2 +- 10 files changed, 488 insertions(+), 507 deletions(-) diff --git a/TerrariaServerAPI.Tests/BaseTest.cs b/TerrariaServerAPI.Tests/BaseTest.cs index 568ce226..19d8e078 100644 --- a/TerrariaServerAPI.Tests/BaseTest.cs +++ b/TerrariaServerAPI.Tests/BaseTest.cs @@ -15,19 +15,19 @@ public void EnsureInitialised() { var are = new AutoResetEvent(false); Exception? error = null; - On.Terraria.Main.hook_DedServ cb = (On.Terraria.Main.orig_DedServ orig, Terraria.Main instance) => + HookEvents.HookDelegate cb = (instance, args) => { instance.Initialize(); are.Set(); _initialized = true; }; - On.Terraria.Main.DedServ += cb; + HookEvents.Terraria.Main.DedServ += cb; global::TerrariaApi.Server.Program.Main(new string[] { }); _initialized = are.WaitOne(TimeSpan.FromSeconds(30)); - On.Terraria.Main.DedServ -= cb; + HookEvents.Terraria.Main.DedServ -= cb; Assert.That(_initialized, Is.True); Assert.That(error, Is.Null); diff --git a/TerrariaServerAPI/TerrariaApi.Server/Hooking/GameHooks.cs b/TerrariaServerAPI/TerrariaApi.Server/Hooking/GameHooks.cs index 9e556b61..66e2624b 100644 --- a/TerrariaServerAPI/TerrariaApi.Server/Hooking/GameHooks.cs +++ b/TerrariaServerAPI/TerrariaApi.Server/Hooking/GameHooks.cs @@ -1,80 +1,80 @@ -using Microsoft.Xna.Framework; -using OTAPI; +using OTAPI; -namespace TerrariaApi.Server.Hooking +namespace TerrariaApi.Server.Hooking; + +internal static class GameHooks { - internal static class GameHooks - { - private static HookManager _hookManager; + private static HookManager _hookManager; - /// - /// Attaches any of the OTAPI Game hooks to the existing implementation - /// - /// HookManager instance which will receive the events - public static void AttachTo(HookManager hookManager) - { - _hookManager = hookManager; + /// + /// Attaches any of the OTAPI Game hooks to the existing implementation + /// + /// HookManager instance which will receive the events + public static void AttachTo(HookManager hookManager) + { + _hookManager = hookManager; - On.Terraria.Main.Update += OnUpdate; - On.Terraria.Main.Initialize += OnInitialize; - On.Terraria.Netplay.StartServer += OnStartServer; + HookEvents.Terraria.Main.Update += OnUpdate; + HookEvents.Terraria.Main.Initialize += OnInitialize; + HookEvents.Terraria.Netplay.StartServer += OnStartServer; - Hooks.WorldGen.HardmodeTilePlace += OnHardmodeTilePlace; - Hooks.WorldGen.HardmodeTileUpdate += OnHardmodeTileUpdate; - Hooks.Item.MechSpawn += OnItemMechSpawn; - Hooks.NPC.MechSpawn += OnNpcMechSpawn; - } + Hooks.WorldGen.HardmodeTilePlace += OnHardmodeTilePlace; + Hooks.WorldGen.HardmodeTileUpdate += OnHardmodeTileUpdate; + Hooks.Item.MechSpawn += OnItemMechSpawn; + Hooks.NPC.MechSpawn += OnNpcMechSpawn; + } - private static void OnUpdate(On.Terraria.Main.orig_Update orig, Terraria.Main instance, GameTime gameTime) - { - _hookManager.InvokeGameUpdate(); - orig(instance, gameTime); - _hookManager.InvokeGamePostUpdate(); - } + private static void OnUpdate(Terraria.Main instance, HookEvents.Terraria.Main.UpdateEventArgs args) + { + if (!args.ContinueExecution) return; + args.ContinueExecution = false; + _hookManager.InvokeGameUpdate(); + args.OriginalMethod(args.gameTime); + _hookManager.InvokeGamePostUpdate(); + } - private static void OnHardmodeTileUpdate(object sender, Hooks.WorldGen.HardmodeTileUpdateEventArgs e) + private static void OnHardmodeTileUpdate(object sender, Hooks.WorldGen.HardmodeTileUpdateEventArgs e) + { + if (_hookManager.InvokeGameHardmodeTileUpdate(e.X, e.Y, e.Type)) { - if (_hookManager.InvokeGameHardmodeTileUpdate(e.X, e.Y, e.Type)) - { - e.Result = HookResult.Cancel; - } + e.Result = HookResult.Cancel; } + } - private static void OnHardmodeTilePlace(object sender, Hooks.WorldGen.HardmodeTilePlaceEventArgs e) + private static void OnHardmodeTilePlace(object sender, Hooks.WorldGen.HardmodeTilePlaceEventArgs e) + { + if (_hookManager.InvokeGameHardmodeTileUpdate(e.X, e.Y, e.Type)) { - if (_hookManager.InvokeGameHardmodeTileUpdate(e.X, e.Y, e.Type)) - { - e.Result = HardmodeTileUpdateResult.Cancel; - } + e.Result = HardmodeTileUpdateResult.Cancel; } + } - private static void OnInitialize(On.Terraria.Main.orig_Initialize orig, Terraria.Main instance) - { - HookManager.InitialiseAPI(); - _hookManager.InvokeGameInitialize(); - orig(instance); - } + private static void OnInitialize(Terraria.Main instance, HookEvents.Terraria.Main.InitializeEventArgs args) + { + if (!args.ContinueExecution) return; + HookManager.InitialiseAPI(); + _hookManager.InvokeGameInitialize(); + } - private static void OnStartServer(On.Terraria.Netplay.orig_StartServer orig) - { - _hookManager.InvokeGamePostInitialize(); - orig(); - } + private static void OnStartServer(object? sender, HookEvents.Terraria.Netplay.StartServerEventArgs args) + { + if (!args.ContinueExecution) return; + _hookManager.InvokeGamePostInitialize(); + } - private static void OnItemMechSpawn(object sender, Hooks.Item.MechSpawnEventArgs e) + private static void OnItemMechSpawn(object sender, Hooks.Item.MechSpawnEventArgs e) + { + if (!_hookManager.InvokeGameStatueSpawn(e.Num2, e.Num3, e.Num, (int)(e.X / 16f), (int)(e.Y / 16f), e.Type, false)) { - if (!_hookManager.InvokeGameStatueSpawn(e.Num2, e.Num3, e.Num, (int)(e.X / 16f), (int)(e.Y / 16f), e.Type, false)) - { - e.Result = HookResult.Cancel; - } + e.Result = HookResult.Cancel; } + } - private static void OnNpcMechSpawn(object sender, Hooks.NPC.MechSpawnEventArgs e) + private static void OnNpcMechSpawn(object sender, Hooks.NPC.MechSpawnEventArgs e) + { + if (!_hookManager.InvokeGameStatueSpawn(e.Num2, e.Num3, e.Num, (int)(e.X / 16f), (int)(e.Y / 16f), e.Type, true)) { - if (!_hookManager.InvokeGameStatueSpawn(e.Num2, e.Num3, e.Num, (int)(e.X / 16f), (int)(e.Y / 16f), e.Type, true)) - { - e.Result = HookResult.Cancel; - } + e.Result = HookResult.Cancel; } } } diff --git a/TerrariaServerAPI/TerrariaApi.Server/Hooking/ItemHooks.cs b/TerrariaServerAPI/TerrariaApi.Server/Hooking/ItemHooks.cs index 5919d323..6f64ac5d 100644 --- a/TerrariaServerAPI/TerrariaApi.Server/Hooking/ItemHooks.cs +++ b/TerrariaServerAPI/TerrariaApi.Server/Hooking/ItemHooks.cs @@ -1,49 +1,45 @@ using OTAPI; using Terraria; -using Terraria.GameContent.Items; -namespace TerrariaApi.Server.Hooking -{ - internal static class ItemHooks - { - private static HookManager _hookManager; +namespace TerrariaApi.Server.Hooking; - /// - /// Attaches any of the OTAPI Item hooks to the existing implementation - /// - /// HookManager instance which will receive the events - public static void AttachTo(HookManager hookManager) - { - _hookManager = hookManager; - - On.Terraria.Item.SetDefaults_int_bool_ItemVariant += OnSetDefaults; - On.Terraria.Item.netDefaults += OnNetDefaults; +internal static class ItemHooks +{ + private static HookManager _hookManager; - Hooks.Chest.QuickStack += OnQuickStack; - } + /// + /// Attaches any of the OTAPI Item hooks to the existing implementation + /// + /// HookManager instance which will receive the events + public static void AttachTo(HookManager hookManager) + { + _hookManager = hookManager; - private static void OnNetDefaults(On.Terraria.Item.orig_netDefaults orig, Item item, int type) - { - if (_hookManager.InvokeItemNetDefaults(ref type, item)) - return; + HookEvents.Terraria.Item.SetDefaults_Int32_Boolean_ItemVariant += OnSetDefaults; + HookEvents.Terraria.Item.netDefaults += OnNetDefaults; - orig(item, type); - } + Hooks.Chest.QuickStack += OnQuickStack; + } - private static void OnSetDefaults(On.Terraria.Item.orig_SetDefaults_int_bool_ItemVariant orig, Item item, int type, bool noMatCheck, ItemVariant? variant = null) - { - if (_hookManager.InvokeItemSetDefaultsInt(ref type, item, variant)) - return; + private static void OnNetDefaults(Item item, HookEvents.Terraria.Item.netDefaultsEventArgs args) + { + if (!args.ContinueExecution) return; + if (_hookManager.InvokeItemNetDefaults(ref args.type, item)) + args.ContinueExecution = false; + } - orig(item, type, noMatCheck, variant); - } + private static void OnSetDefaults(Item item, HookEvents.Terraria.Item.SetDefaults_Int32_Boolean_ItemVariantEventArgs args) + { + if (!args.ContinueExecution) return; + if (_hookManager.InvokeItemSetDefaultsInt(ref args.Type, item, args.variant)) + args.ContinueExecution = false; + } - private static void OnQuickStack(object sender, Hooks.Chest.QuickStackEventArgs e) + private static void OnQuickStack(object sender, Hooks.Chest.QuickStackEventArgs e) + { + if (_hookManager.InvokeItemForceIntoChest(Main.chest[e.ChestIndex], e.Item, Main.player[e.PlayerId])) { - if (_hookManager.InvokeItemForceIntoChest(Main.chest[e.ChestIndex], e.Item, Main.player[e.PlayerId])) - { - e.Result = HookResult.Cancel; - } + e.Result = HookResult.Cancel; } } } diff --git a/TerrariaServerAPI/TerrariaApi.Server/Hooking/NetHooks.cs b/TerrariaServerAPI/TerrariaApi.Server/Hooking/NetHooks.cs index 07915205..7ea8bce1 100644 --- a/TerrariaServerAPI/TerrariaApi.Server/Hooking/NetHooks.cs +++ b/TerrariaServerAPI/TerrariaApi.Server/Hooking/NetHooks.cs @@ -1,187 +1,184 @@ -using Microsoft.Xna.Framework; -using OTAPI; +using OTAPI; using System; using Terraria; -using Terraria.Localization; using Terraria.Net; -namespace TerrariaApi.Server.Hooking +namespace TerrariaApi.Server.Hooking; + +internal class NetHooks { - internal class NetHooks + private static HookManager _hookManager; + + public static readonly object syncRoot = new(); + + /// + /// Attaches any of the OTAPI Net hooks to the existing implementation + /// + /// HookManager instance which will receive the events + public static void AttachTo(HookManager hookManager) { - private static HookManager _hookManager; + _hookManager = hookManager; - public static readonly object syncRoot = new object(); + HookEvents.Terraria.NetMessage.greetPlayer += OnGreetPlayer; + HookEvents.Terraria.Netplay.OnConnectionAccepted += OnConnectionAccepted; + HookEvents.Terraria.Chat.ChatHelper.BroadcastChatMessage += OnBroadcastChatMessage; + HookEvents.Terraria.Net.NetManager.SendData += OnSendNetData; - /// - /// Attaches any of the OTAPI Net hooks to the existing implementation - /// - /// HookManager instance which will receive the events - public static void AttachTo(HookManager hookManager) - { - _hookManager = hookManager; + Hooks.NetMessage.SendData += OnSendData; + Hooks.NetMessage.SendBytes += OnSendBytes; + Hooks.MessageBuffer.GetData += OnReceiveData; + Hooks.MessageBuffer.NameCollision += OnNameCollision; + } - On.Terraria.NetMessage.greetPlayer += OnGreetPlayer; - On.Terraria.Netplay.OnConnectionAccepted += OnConnectionAccepted; - On.Terraria.Chat.ChatHelper.BroadcastChatMessage += OnBroadcastChatMessage; - On.Terraria.Net.NetManager.SendData += OnSendNetData; + static void OnBroadcastChatMessage(object? sender, HookEvents.Terraria.Chat.ChatHelper.BroadcastChatMessageEventArgs args) + { + if (!args.ContinueExecution) return; + float r = args.color.R, g = args.color.G, b = args.color.B; - Hooks.NetMessage.SendData += OnSendData; - Hooks.NetMessage.SendBytes += OnSendBytes; - Hooks.MessageBuffer.GetData += OnReceiveData; - Hooks.MessageBuffer.NameCollision += OnNameCollision; - } + var cancel = _hookManager.InvokeServerBroadcast(ref args.text, ref r, ref g, ref b); - static void OnBroadcastChatMessage(On.Terraria.Chat.ChatHelper.orig_BroadcastChatMessage orig, NetworkText text, Color color, int excludedPlayer) + if (!cancel) { - float r = color.R, g = color.G, b = color.B; + args.color = new Microsoft.Xna.Framework.Color(r, g, b); + } - var cancel = _hookManager.InvokeServerBroadcast(ref text, ref r, ref g, ref b); + args.ContinueExecution = !cancel; + } - if (!cancel) + static void OnSendData(object sender, Hooks.NetMessage.SendDataEventArgs e) + { + if (e.Event == HookEvent.Before) + { + var msgType = e.MsgType; + var remoteClient = e.RemoteClient; + var ignoreClient = e.IgnoreClient; + var text = e.Text; + var number = e.Number; + var number2 = e.Number2; + var number3 = e.Number3; + var number4 = e.Number4; + var number5 = e.Number5; + var number6 = e.Number6; + var number7 = e.Number7; + if (_hookManager.InvokeNetSendData + ( + ref msgType, + ref remoteClient, + ref ignoreClient, + ref text, + ref number, + ref number2, + ref number3, + ref number4, + ref number5, + ref number6, + ref number7 + )) { - color.R = (byte)r; - color.G = (byte)g; - color.B = (byte)b; - - orig(text, color, excludedPlayer); + e.Result = HookResult.Cancel; } + + e.MsgType = msgType; + e.RemoteClient = remoteClient; + e.IgnoreClient = ignoreClient; + e.Text = text; + e.Number = number; + e.Number2 = number2; + e.Number3 = number3; + e.Number4 = number4; + e.Number5 = number5; + e.Number6 = number6; + e.Number7 = number7; } + } - static void OnSendData(object sender, Hooks.NetMessage.SendDataEventArgs e) + static void OnSendNetData(NetManager netmanager, HookEvents.Terraria.Net.NetManager.SendDataEventArgs args) + { + if (!args.ContinueExecution) return; + if (_hookManager.InvokeNetSendNetData + ( + ref netmanager, + ref args.socket, + ref args.packet + )) { - if (e.Event == HookEvent.Before) - { - var msgType = e.MsgType; - var remoteClient = e.RemoteClient; - var ignoreClient = e.IgnoreClient; - var text = e.Text; - var number = e.Number; - var number2 = e.Number2; - var number3 = e.Number3; - var number4 = e.Number4; - var number5 = e.Number5; - var number6 = e.Number6; - var number7 = e.Number7; - if (_hookManager.InvokeNetSendData - ( - ref msgType, - ref remoteClient, - ref ignoreClient, - ref text, - ref number, - ref number2, - ref number3, - ref number4, - ref number5, - ref number6, - ref number7 - )) - { - e.Result = HookResult.Cancel; - } - - e.MsgType = msgType; - e.RemoteClient = remoteClient; - e.IgnoreClient = ignoreClient; - e.Text = text; - e.Number = number; - e.Number2 = number2; - e.Number3 = number3; - e.Number4 = number4; - e.Number5 = number5; - e.Number6 = number6; - e.Number7 = number7; - } + args.ContinueExecution = false; } + } - static void OnSendNetData(On.Terraria.Net.NetManager.orig_SendData orig, NetManager netmanager, Terraria.Net.Sockets.ISocket socket, NetPacket packet) + static void OnReceiveData(object sender, Hooks.MessageBuffer.GetDataEventArgs e) + { + if (!Enum.IsDefined(typeof(PacketTypes), (int)e.PacketId)) { - if (!_hookManager.InvokeNetSendNetData - ( - ref netmanager, - ref socket, - ref packet - )) - { - orig(netmanager, socket, packet); - } + e.Result = HookResult.Cancel; } - - static void OnReceiveData(object sender, Hooks.MessageBuffer.GetDataEventArgs e) + else { - if (!Enum.IsDefined(typeof(PacketTypes), (int)e.PacketId)) + var msgId = e.PacketId; + var readOffset = e.ReadOffset; + var length = e.Length; + + if (_hookManager.InvokeNetGetData(ref msgId, e.Instance, ref readOffset, ref length)) { e.Result = HookResult.Cancel; } - else - { - var msgId = e.PacketId; - var readOffset = e.ReadOffset; - var length = e.Length; - - if (_hookManager.InvokeNetGetData(ref msgId, e.Instance, ref readOffset, ref length)) - { - e.Result = HookResult.Cancel; - } - e.PacketId = msgId; - e.ReadOffset = readOffset; - e.Length = length; - } + e.PacketId = msgId; + e.ReadOffset = readOffset; + e.Length = length; } + } - static void OnGreetPlayer(On.Terraria.NetMessage.orig_greetPlayer orig, int plr) - { - if (_hookManager.InvokeNetGreetPlayer(plr)) - return; + static void OnGreetPlayer(object? sender, HookEvents.Terraria.NetMessage.greetPlayerEventArgs args) + { + if (!args.ContinueExecution) return; + if (_hookManager.InvokeNetGreetPlayer(args.plr)) + args.ContinueExecution = false; + } - orig(plr); + static void OnSendBytes(object sender, Hooks.NetMessage.SendBytesEventArgs e) + { + if (_hookManager.InvokeNetSendBytes(Netplay.Clients[e.RemoteClient], e.Data, e.Offset, e.Size)) + { + e.Result = HookResult.Cancel; } + } - static void OnSendBytes(object sender, Hooks.NetMessage.SendBytesEventArgs e) + static void OnNameCollision(object sender, Hooks.MessageBuffer.NameCollisionEventArgs e) + { + if (_hookManager.InvokeNetNameCollision(e.Player.whoAmI, e.Player.name)) { - if (_hookManager.InvokeNetSendBytes(Netplay.Clients[e.RemoteClient], e.Data, e.Offset, e.Size)) - { - e.Result = HookResult.Cancel; - } + e.Result = HookResult.Cancel; } + } - static void OnNameCollision(object sender, Hooks.MessageBuffer.NameCollisionEventArgs e) + static void OnConnectionAccepted(object? sender, HookEvents.Terraria.Netplay.OnConnectionAcceptedEventArgs args) + { + if (!args.ContinueExecution) return; + int slot = FindNextOpenClientSlot(); + if (slot != -1) { - if (_hookManager.InvokeNetNameCollision(e.Player.whoAmI, e.Player.name)) - { - e.Result = HookResult.Cancel; - } + Netplay.Clients[slot].Reset(); + Netplay.Clients[slot].Socket = args.client; } - - static void OnConnectionAccepted(On.Terraria.Netplay.orig_OnConnectionAccepted orig, Terraria.Net.Sockets.ISocket client) + if (FindNextOpenClientSlot() == -1) { - int slot = FindNextOpenClientSlot(); - if (slot != -1) - { - Netplay.Clients[slot].Reset(); - Netplay.Clients[slot].Socket = client; - } - if (FindNextOpenClientSlot() == -1) - { - Netplay.StopListening(); - } + Netplay.StopListening(); } + } - static int FindNextOpenClientSlot() + static int FindNextOpenClientSlot() + { + lock (syncRoot) { - lock (syncRoot) + for (int i = 0; i < Main.maxNetPlayers; i++) { - for (int i = 0; i < Main.maxNetPlayers; i++) + if (!Netplay.Clients[i].IsConnected()) { - if (!Netplay.Clients[i].IsConnected()) - { - return i; - } + return i; } } - return -1; } + return -1; } } diff --git a/TerrariaServerAPI/TerrariaApi.Server/Hooking/NpcHooks.cs b/TerrariaServerAPI/TerrariaApi.Server/Hooking/NpcHooks.cs index a6b501fe..3c91961b 100644 --- a/TerrariaServerAPI/TerrariaApi.Server/Hooking/NpcHooks.cs +++ b/TerrariaServerAPI/TerrariaApi.Server/Hooking/NpcHooks.cs @@ -2,132 +2,84 @@ using OTAPI; using Terraria; -namespace TerrariaApi.Server.Hooking -{ - internal static class NpcHooks - { - private static HookManager _hookManager; +namespace TerrariaApi.Server.Hooking; - /// - /// Attaches any of the OTAPI Npc hooks to the existing implementation - /// - /// HookManager instance which will receive the events - public static void AttachTo(HookManager hookManager) - { - _hookManager = hookManager; - - On.Terraria.NPC.SetDefaults += OnSetDefaultsById; - On.Terraria.NPC.SetDefaultsFromNetId += OnSetDefaultsFromNetId; - On.Terraria.NPC.StrikeNPC += OnStrike; - On.Terraria.NPC.Transform += OnTransform; - On.Terraria.NPC.AI += OnAI; - - Hooks.NPC.Spawn += OnSpawn; - Hooks.NPC.DropLoot += OnDropLoot; - Hooks.NPC.BossBag += OnBossBagItem; - Hooks.NPC.Killed += OnKilled; - } - - static void OnKilled(object sender, Hooks.NPC.KilledEventArgs e) - { - _hookManager.InvokeNpcKilled(e.Npc); - } +internal static class NpcHooks +{ + private static HookManager _hookManager; - static void OnSetDefaultsById(On.Terraria.NPC.orig_SetDefaults orig, NPC npc, int type, NPCSpawnParams spawnparams) - { - if (_hookManager.InvokeNpcSetDefaultsInt(ref type, npc)) - return; + /// + /// Attaches any of the OTAPI Npc hooks to the existing implementation + /// + /// HookManager instance which will receive the events + public static void AttachTo(HookManager hookManager) + { + _hookManager = hookManager; + + HookEvents.Terraria.NPC.SetDefaults += OnSetDefaultsById; + HookEvents.Terraria.NPC.SetDefaultsFromNetId += OnSetDefaultsFromNetId; + HookEvents.Terraria.NPC.StrikeNPC += OnStrike; + HookEvents.Terraria.NPC.Transform += OnTransform; + HookEvents.Terraria.NPC.AI += OnAI; + + Hooks.NPC.Spawn += OnSpawn; + Hooks.NPC.DropLoot += OnDropLoot; + Hooks.NPC.BossBag += OnBossBagItem; + Hooks.NPC.Killed += OnKilled; + } - orig(npc, type, spawnparams); - } + static void OnKilled(object sender, Hooks.NPC.KilledEventArgs e) + { + _hookManager.InvokeNpcKilled(e.Npc); + } - static void OnSetDefaultsFromNetId(On.Terraria.NPC.orig_SetDefaultsFromNetId orig, NPC npc, int id, NPCSpawnParams spawnparams) - { - if (_hookManager.InvokeNpcNetDefaults(ref id, npc)) - return; + static void OnSetDefaultsById(NPC npc, HookEvents.Terraria.NPC.SetDefaultsEventArgs args) + { + if (!args.ContinueExecution) return; + if (_hookManager.InvokeNpcSetDefaultsInt(ref args.Type, npc)) + args.ContinueExecution = false; + } - orig(npc, id, spawnparams); - } + static void OnSetDefaultsFromNetId(NPC npc, HookEvents.Terraria.NPC.SetDefaultsFromNetIdEventArgs args) + { + if (!args.ContinueExecution) return; + if (_hookManager.InvokeNpcNetDefaults(ref args.id, npc)) + args.ContinueExecution = false; + } - static double OnStrike(On.Terraria.NPC.orig_StrikeNPC orig, NPC npc, int Damage, float knockBack, int hitDirection, bool crit, bool noEffect, bool fromNet, Entity entity) + static void OnStrike(NPC npc, HookEvents.Terraria.NPC.StrikeNPCEventArgs args) + { + if (!args.ContinueExecution) return; + if (args.entity is Player player) { - if (entity is Player player) + if (_hookManager.InvokeNpcStrike(npc, ref args.Damage, ref args.knockBack, ref args.hitDirection, ref args.crit, ref args.noEffect, ref args.fromNet, player)) { - if (_hookManager.InvokeNpcStrike(npc, ref Damage, ref knockBack, ref hitDirection, ref crit, ref noEffect, ref fromNet, player)) - { - return 0; - } + args.ContinueExecution = false; + args.HookReturnValue = 0; } - - return orig(npc, Damage, knockBack, hitDirection, crit, noEffect, fromNet, entity); - } - - static void OnTransform(On.Terraria.NPC.orig_Transform orig, NPC npc, int newType) - { - if (_hookManager.InvokeNpcTransformation(npc.whoAmI)) - return; - - orig(npc, newType); } + } - static void OnSpawn(object sender, Hooks.NPC.SpawnEventArgs e) - { - var index = e.Index; - if (_hookManager.InvokeNpcSpawn(ref index)) - { - e.Result = HookResult.Cancel; - e.Index = index; - } - } + static void OnTransform(NPC npc, HookEvents.Terraria.NPC.TransformEventArgs args) + { + if (!args.ContinueExecution) return; + if (_hookManager.InvokeNpcTransformation(npc.whoAmI)) + args.ContinueExecution = false; + } - static void OnDropLoot(object sender, Hooks.NPC.DropLootEventArgs e) + static void OnSpawn(object sender, Hooks.NPC.SpawnEventArgs e) + { + var index = e.Index; + if (_hookManager.InvokeNpcSpawn(ref index)) { - if (e.Event == HookEvent.Before) - { - var Width = e.Width; - var Height = e.Height; - var Type = e.Type; - var Stack = e.Stack; - var noBroadcast = e.NoBroadcast; - var pfix = e.Pfix; - var noGrabDelay = e.NoGrabDelay; - var reverseLookup = e.ReverseLookup; - - var position = new Vector2(e.X, e.Y); - if (_hookManager.InvokeNpcLootDrop - ( - ref position, - ref Width, - ref Height, - ref Type, - ref Stack, - ref noBroadcast, - ref pfix, - e.Npc.type, - e.Npc.whoAmI, - ref noGrabDelay, - ref reverseLookup - )) - { - e.X = (int)position.X; - e.Y = (int)position.Y; - e.Result = HookResult.Cancel; - } - e.X = (int)position.X; - e.Y = (int)position.Y; - - e.Width = Width; - e.Height = Height; - e.Type = Type; - e.Stack = Stack; - e.NoBroadcast = noBroadcast; - e.Pfix = pfix; - e.NoGrabDelay = noGrabDelay; - e.ReverseLookup = reverseLookup; - } + e.Result = HookResult.Cancel; + e.Index = index; } + } - static void OnBossBagItem(object sender, Hooks.NPC.BossBagEventArgs e) + static void OnDropLoot(object sender, Hooks.NPC.DropLootEventArgs e) + { + if (e.Event == HookEvent.Before) { var Width = e.Width; var Height = e.Height; @@ -138,10 +90,10 @@ static void OnBossBagItem(object sender, Hooks.NPC.BossBagEventArgs e) var noGrabDelay = e.NoGrabDelay; var reverseLookup = e.ReverseLookup; - var positon = new Vector2(e.X, e.Y); - if (_hookManager.InvokeDropBossBag + var position = new Vector2(e.X, e.Y); + if (_hookManager.InvokeNpcLootDrop ( - ref positon, + ref position, ref Width, ref Height, ref Type, @@ -154,8 +106,12 @@ static void OnBossBagItem(object sender, Hooks.NPC.BossBagEventArgs e) ref reverseLookup )) { + e.X = (int)position.X; + e.Y = (int)position.Y; e.Result = HookResult.Cancel; } + e.X = (int)position.X; + e.Y = (int)position.Y; e.Width = Width; e.Height = Height; @@ -166,13 +122,52 @@ ref reverseLookup e.NoGrabDelay = noGrabDelay; e.ReverseLookup = reverseLookup; } + } - static void OnAI(On.Terraria.NPC.orig_AI orig, NPC npc) + static void OnBossBagItem(object sender, Hooks.NPC.BossBagEventArgs e) + { + var Width = e.Width; + var Height = e.Height; + var Type = e.Type; + var Stack = e.Stack; + var noBroadcast = e.NoBroadcast; + var pfix = e.Pfix; + var noGrabDelay = e.NoGrabDelay; + var reverseLookup = e.ReverseLookup; + + var positon = new Vector2(e.X, e.Y); + if (_hookManager.InvokeDropBossBag + ( + ref positon, + ref Width, + ref Height, + ref Type, + ref Stack, + ref noBroadcast, + ref pfix, + e.Npc.type, + e.Npc.whoAmI, + ref noGrabDelay, + ref reverseLookup + )) { - if (_hookManager.InvokeNpcAIUpdate(npc)) - return; - - orig(npc); + e.Result = HookResult.Cancel; } + + e.Width = Width; + e.Height = Height; + e.Type = Type; + e.Stack = Stack; + e.NoBroadcast = noBroadcast; + e.Pfix = pfix; + e.NoGrabDelay = noGrabDelay; + e.ReverseLookup = reverseLookup; + } + + static void OnAI(NPC npc, HookEvents.Terraria.NPC.AIEventArgs args) + { + if (!args.ContinueExecution) return; + if (_hookManager.InvokeNpcAIUpdate(npc)) + args.ContinueExecution = false; } } diff --git a/TerrariaServerAPI/TerrariaApi.Server/Hooking/ProjectileHooks.cs b/TerrariaServerAPI/TerrariaApi.Server/Hooking/ProjectileHooks.cs index 31d95635..b958d09f 100644 --- a/TerrariaServerAPI/TerrariaApi.Server/Hooking/ProjectileHooks.cs +++ b/TerrariaServerAPI/TerrariaApi.Server/Hooking/ProjectileHooks.cs @@ -1,36 +1,35 @@ -using OTAPI; -using Terraria; +using Terraria; -namespace TerrariaApi.Server.Hooking -{ - internal static class ProjectileHooks - { - private static HookManager _hookManager; +namespace TerrariaApi.Server.Hooking; - /// - /// Attaches any of the OTAPI Projectile hooks to the existing implementation - /// - /// HookManager instance which will receive the events - public static void AttachTo(HookManager hookManager) - { - _hookManager = hookManager; +internal static class ProjectileHooks +{ + private static HookManager _hookManager; - On.Terraria.Projectile.SetDefaults += OnSetDefaults; - On.Terraria.Projectile.AI += OnAI; - } + /// + /// Attaches any of the OTAPI Projectile hooks to the existing implementation + /// + /// HookManager instance which will receive the events + public static void AttachTo(HookManager hookManager) + { + _hookManager = hookManager; - private static void OnSetDefaults(On.Terraria.Projectile.orig_SetDefaults orig, Projectile projectile, int type) - { - orig(projectile, type); - _hookManager.InvokeProjectileSetDefaults(ref type, projectile); - } + HookEvents.Terraria.Projectile.SetDefaults += OnSetDefaults; + HookEvents.Terraria.Projectile.AI += OnAI; + } - private static void OnAI(On.Terraria.Projectile.orig_AI orig, Projectile projectile) - { - if (_hookManager.InvokeProjectileAIUpdate(projectile)) - return; + private static void OnSetDefaults(Projectile projectile, HookEvents.Terraria.Projectile.SetDefaultsEventArgs args) + { + if (!args.ContinueExecution) return; + args.ContinueExecution = false; + args.OriginalMethod(args.Type); + _hookManager.InvokeProjectileSetDefaults(ref args.Type, projectile); + } - orig(projectile); - } + private static void OnAI(Projectile projectile, HookEvents.Terraria.Projectile.AIEventArgs args) + { + if (!args.ContinueExecution) return; + if (_hookManager.InvokeProjectileAIUpdate(projectile)) + args.ContinueExecution = false; } } diff --git a/TerrariaServerAPI/TerrariaApi.Server/Hooking/ServerHooks.cs b/TerrariaServerAPI/TerrariaApi.Server/Hooking/ServerHooks.cs index f4c0cd2d..bba22df6 100644 --- a/TerrariaServerAPI/TerrariaApi.Server/Hooking/ServerHooks.cs +++ b/TerrariaServerAPI/TerrariaApi.Server/Hooking/ServerHooks.cs @@ -3,56 +3,57 @@ using System.Linq; using Terraria; -namespace TerrariaApi.Server.Hooking +namespace TerrariaApi.Server.Hooking; + +internal static class ServerHooks { - internal static class ServerHooks + private static HookManager _hookManager; + + /// + /// Attaches any of the OTAPI Server hooks to the existing implementation + /// + /// HookManager instance which will receive the events + public static void AttachTo(HookManager hookManager) { - private static HookManager _hookManager; + _hookManager = hookManager; - /// - /// Attaches any of the OTAPI Server hooks to the existing implementation - /// - /// HookManager instance which will receive the events - public static void AttachTo(HookManager hookManager) - { - _hookManager = hookManager; + HookEvents.Terraria.Main.startDedInput += Main_startDedInput; + HookEvents.Terraria.RemoteClient.Reset += RemoteClient_Reset; + Hooks.Main.CommandProcess += OnProcess; + } - On.Terraria.Main.startDedInput += Main_startDedInput; - On.Terraria.RemoteClient.Reset += RemoteClient_Reset; - Hooks.Main.CommandProcess += OnProcess; - } + static void Main_startDedInput(object? sender, HookEvents.Terraria.Main.startDedInputEventArgs args) + { + if (!args.ContinueExecution) return; + args.ContinueExecution = false; - static void Main_startDedInput(On.Terraria.Main.orig_startDedInput orig) + if (Environment.GetCommandLineArgs().Any(x => x.Equals("-disable-commands"))) { - if (Environment.GetCommandLineArgs().Any(x => x.Equals("-disable-commands"))) - { - Console.WriteLine("Command thread has been disabled."); - return; - } - - orig(); + Console.WriteLine("Command thread has been disabled."); + return; } - static void OnProcess(object sender, Hooks.Main.CommandProcessEventArgs e) + args.OriginalMethod(); + } + + static void OnProcess(object sender, Hooks.Main.CommandProcessEventArgs e) + { + if (_hookManager.InvokeServerCommand(e.Command)) { - if (_hookManager.InvokeServerCommand(e.Command)) - { - e.Result = HookResult.Cancel; - } + e.Result = HookResult.Cancel; } + } - static void RemoteClient_Reset(On.Terraria.RemoteClient.orig_Reset orig, RemoteClient client) + static void RemoteClient_Reset(RemoteClient client, HookEvents.Terraria.RemoteClient.ResetEventArgs args) + { + if (!args.ContinueExecution) return; + if (!Netplay.Disconnect) { - if (!Netplay.Disconnect) + if (client.IsActive) { - if (client.IsActive) - { - _hookManager.InvokeServerLeave(client.Id); - } - _hookManager.InvokeServerSocketReset(client); + _hookManager.InvokeServerLeave(client.Id); } - - orig(client); + _hookManager.InvokeServerSocketReset(client); } } } diff --git a/TerrariaServerAPI/TerrariaApi.Server/Hooking/WiringHooks.cs b/TerrariaServerAPI/TerrariaApi.Server/Hooking/WiringHooks.cs index a5ef0ae2..433161d4 100644 --- a/TerrariaServerAPI/TerrariaApi.Server/Hooking/WiringHooks.cs +++ b/TerrariaServerAPI/TerrariaApi.Server/Hooking/WiringHooks.cs @@ -1,29 +1,28 @@ using OTAPI; using Terraria; -namespace TerrariaApi.Server.Hooking +namespace TerrariaApi.Server.Hooking; + +internal static class WiringHooks { - internal static class WiringHooks - { - private static HookManager _hookManager; + private static HookManager _hookManager; - /// - /// Attaches any of the OTAPI Wiring hooks to the existing implementation - /// - /// HookManager instance which will receive the events - public static void AttachTo(HookManager hookManager) - { - _hookManager = hookManager; + /// + /// Attaches any of the OTAPI Wiring hooks to the existing implementation + /// + /// HookManager instance which will receive the events + public static void AttachTo(HookManager hookManager) + { + _hookManager = hookManager; - Hooks.Wiring.AnnouncementBox += OnAnnouncementBox; - } + Hooks.Wiring.AnnouncementBox += OnAnnouncementBox; + } - static void OnAnnouncementBox(object sender, Hooks.Wiring.AnnouncementBoxEventArgs e) + static void OnAnnouncementBox(object sender, Hooks.Wiring.AnnouncementBoxEventArgs e) + { + if (_hookManager.InvokeWireTriggerAnnouncementBox(Wiring.CurrentUser, e.X, e.Y, e.SignId, Main.sign[e.SignId].text)) { - if (_hookManager.InvokeWireTriggerAnnouncementBox(Wiring.CurrentUser, e.X, e.Y, e.SignId, Main.sign[e.SignId].text)) - { - e.Result = HookResult.Cancel; - } + e.Result = HookResult.Cancel; } } } diff --git a/TerrariaServerAPI/TerrariaApi.Server/Hooking/WorldHooks.cs b/TerrariaServerAPI/TerrariaApi.Server/Hooking/WorldHooks.cs index 7095fce4..7de686a5 100644 --- a/TerrariaServerAPI/TerrariaApi.Server/Hooking/WorldHooks.cs +++ b/TerrariaServerAPI/TerrariaApi.Server/Hooking/WorldHooks.cs @@ -1,95 +1,89 @@ using OTAPI; using Terraria; -namespace TerrariaApi.Server.Hooking +namespace TerrariaApi.Server.Hooking; + +internal static class WorldHooks { - internal static class WorldHooks - { - private static HookManager _hookManager; + private static HookManager _hookManager; - /// - /// Attaches any of the OTAPI World hooks to the existing implementation - /// - /// HookManager instance which will receive the events - public static void AttachTo(HookManager hookManager) - { - _hookManager = hookManager; + /// + /// Attaches any of the OTAPI World hooks to the existing implementation + /// + /// HookManager instance which will receive the events + public static void AttachTo(HookManager hookManager) + { + _hookManager = hookManager; - On.Terraria.IO.WorldFile.SaveWorld_bool_bool += WorldFile_SaveWorld; - On.Terraria.WorldGen.StartHardmode += WorldGen_StartHardmode; - On.Terraria.WorldGen.SpreadGrass += WorldGen_SpreadGrass; - On.Terraria.Main.checkXMas += Main_checkXMas; - On.Terraria.Main.checkHalloween += Main_checkHalloween; + HookEvents.Terraria.IO.WorldFile.SaveWorld_Boolean_Boolean += WorldFile_SaveWorld; + HookEvents.Terraria.WorldGen.StartHardmode += WorldGen_StartHardmode; + HookEvents.Terraria.WorldGen.SpreadGrass += WorldGen_SpreadGrass; + HookEvents.Terraria.Main.checkXMas += Main_checkXMas; + HookEvents.Terraria.Main.checkHalloween += Main_checkHalloween; - Hooks.Collision.PressurePlate += OnPressurePlate; - Hooks.WorldGen.Meteor += OnDropMeteor; - } - - static void OnPressurePlate(object sender, Hooks.Collision.PressurePlateEventArgs e) - { - if (e.Entity is NPC npc) - { - if (_hookManager.InvokeNpcTriggerPressurePlate(npc, e.X, e.Y)) - e.Result = HookResult.Cancel; - } - else if (e.Entity is Player player) - { - if (_hookManager.InvokePlayerTriggerPressurePlate(player, e.X, e.Y)) - e.Result = HookResult.Cancel; - } - else if (e.Entity is Projectile projectile) - { - if (_hookManager.InvokeProjectileTriggerPressurePlate(projectile, e.X, e.Y)) - e.Result = HookResult.Cancel; - } - } + Hooks.Collision.PressurePlate += OnPressurePlate; + Hooks.WorldGen.Meteor += OnDropMeteor; + } - static void WorldFile_SaveWorld(On.Terraria.IO.WorldFile.orig_SaveWorld_bool_bool orig, bool useCloudSaving, bool resetTime) + static void OnPressurePlate(object sender, Hooks.Collision.PressurePlateEventArgs e) + { + if (e.Entity is NPC npc) { - if (_hookManager.InvokeWorldSave(resetTime)) - return; - - orig(useCloudSaving, resetTime); + if (_hookManager.InvokeNpcTriggerPressurePlate(npc, e.X, e.Y)) + e.Result = HookResult.Cancel; } - - private static void WorldGen_StartHardmode(On.Terraria.WorldGen.orig_StartHardmode orig) + else if (e.Entity is Player player) { - if (_hookManager.InvokeWorldStartHardMode()) - return; - - orig(); + if (_hookManager.InvokePlayerTriggerPressurePlate(player, e.X, e.Y)) + e.Result = HookResult.Cancel; } - - static void OnDropMeteor(object sender, Hooks.WorldGen.MeteorEventArgs e) + else if (e.Entity is Projectile projectile) { - if (_hookManager.InvokeWorldMeteorDrop(e.X, e.Y)) - { + if (_hookManager.InvokeProjectileTriggerPressurePlate(projectile, e.X, e.Y)) e.Result = HookResult.Cancel; - } } + } - private static void Main_checkXMas(On.Terraria.Main.orig_checkXMas orig) - { - if (_hookManager.InvokeWorldChristmasCheck(ref Terraria.Main.xMas)) - return; + static void WorldFile_SaveWorld(object? sender, HookEvents.Terraria.IO.WorldFile.SaveWorld_Boolean_BooleanEventArgs args) + { + if (!args.ContinueExecution) return; + if (_hookManager.InvokeWorldSave(args.resetTime)) + args.ContinueExecution = false; + } - orig(); - } + private static void WorldGen_StartHardmode(object? sender, HookEvents.Terraria.WorldGen.StartHardmodeEventArgs args) + { + if (!args.ContinueExecution) return; + if (_hookManager.InvokeWorldStartHardMode()) + args.ContinueExecution = false; + } - private static void Main_checkHalloween(On.Terraria.Main.orig_checkHalloween orig) + static void OnDropMeteor(object sender, Hooks.WorldGen.MeteorEventArgs e) + { + if (_hookManager.InvokeWorldMeteorDrop(e.X, e.Y)) { - if (_hookManager.InvokeWorldHalloweenCheck(ref Main.halloween)) - return; - - orig(); + e.Result = HookResult.Cancel; } + } - private static void WorldGen_SpreadGrass(On.Terraria.WorldGen.orig_SpreadGrass orig, int i, int j, int dirt, int grass, bool repeat, TileColorCache color) - { - if (_hookManager.InvokeWorldGrassSpread(i, j, dirt, grass, repeat, color)) - return; + private static void Main_checkXMas(object? sender, HookEvents.Terraria.Main.checkXMasEventArgs args) + { + if (!args.ContinueExecution) return; + if (_hookManager.InvokeWorldChristmasCheck(ref Terraria.Main.xMas)) + args.ContinueExecution = false; + } - orig(i, j, dirt, grass, repeat, color); - } + private static void Main_checkHalloween(object? sender, HookEvents.Terraria.Main.checkHalloweenEventArgs args) + { + if (!args.ContinueExecution) return; + if (_hookManager.InvokeWorldHalloweenCheck(ref Main.halloween)) + args.ContinueExecution = false; + } + + private static void WorldGen_SpreadGrass(object? sender, HookEvents.Terraria.WorldGen.SpreadGrassEventArgs args) + { + if (!args.ContinueExecution) return; + if (_hookManager.InvokeWorldGrassSpread(args.i, args.j, args.dirt, args.grass, args.repeat, args.color)) + args.ContinueExecution = false; } } diff --git a/TerrariaServerAPI/TerrariaServerAPI.csproj b/TerrariaServerAPI/TerrariaServerAPI.csproj index 2a15e5e2..42de3807 100644 --- a/TerrariaServerAPI/TerrariaServerAPI.csproj +++ b/TerrariaServerAPI/TerrariaServerAPI.csproj @@ -23,6 +23,6 @@ - + From e6c5ceb1512abc0959b01fb786643140256f4384 Mon Sep 17 00:00:00 2001 From: Luke Date: Fri, 3 Jan 2025 12:36:31 +1000 Subject: [PATCH 03/12] Expand tests to multiple platforms --- .github/workflows/build.yml | 28 +++++++++++++++++++++------- TerrariaServerAPI.Tests/BaseTest.cs | 2 ++ 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1549c919..946a059c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -12,8 +12,28 @@ on: jobs: # This workflow contains a single job called "build" build: + strategy: + fail-fast: false + matrix: + os: [ + { + name: Windows, + runs-on: windows-latest, + }, + { + name: Ubuntu, + runs-on: ubuntu-latest, + }, + { + name: MacOS, + runs-on: macos-latest, + } + ] + # The type of runner that the job will run on - runs-on: windows-latest + runs-on: ${{ matrix.os.runs-on }} + + name: ${{ matrix.os.name }} # Steps represent a sequence of tasks that will be executed as part of the job steps: @@ -32,9 +52,3 @@ jobs: - name: Run tests run: dotnet test --filter "FullyQualifiedName!~TerrariaServerAPI.Tests.Benchmarks" - - # example task for the release CI - # - name: "Releasing to NuGet: TSAPI" - # env: - # NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }} - # run: dotnet nuget push ./TerrariaServerAPI/bin/Release/TerrariaServer.*.nupkg --source https://api.nuget.org/v3/index.json --api-key "$env:NUGET_API_KEY" diff --git a/TerrariaServerAPI.Tests/BaseTest.cs b/TerrariaServerAPI.Tests/BaseTest.cs index 19d8e078..31b4912b 100644 --- a/TerrariaServerAPI.Tests/BaseTest.cs +++ b/TerrariaServerAPI.Tests/BaseTest.cs @@ -1,5 +1,6 @@ using NUnit.Framework; using System; +using System.Runtime.InteropServices; using System.Threading; namespace TerrariaServerAPI.Tests; @@ -20,6 +21,7 @@ public void EnsureInitialised() instance.Initialize(); are.Set(); _initialized = true; + Console.WriteLine($"Server init process successful for architecture {RuntimeInformation.ProcessArchitecture}"); }; HookEvents.Terraria.Main.DedServ += cb; From 38d42768677591675508d2c4c0fb5ae01b65cb72 Mon Sep 17 00:00:00 2001 From: Luke Date: Fri, 3 Jan 2025 22:03:56 +1000 Subject: [PATCH 04/12] Utilize nunit TestContext instead of console --- TerrariaServerAPI.Tests/BaseTest.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/TerrariaServerAPI.Tests/BaseTest.cs b/TerrariaServerAPI.Tests/BaseTest.cs index 31b4912b..1f740732 100644 --- a/TerrariaServerAPI.Tests/BaseTest.cs +++ b/TerrariaServerAPI.Tests/BaseTest.cs @@ -12,20 +12,21 @@ public class BaseTest [OneTimeSetUp] public void EnsureInitialised() { + TestContext.Out.WriteLine($"Test architecture {RuntimeInformation.ProcessArchitecture}"); + if (!_initialized) { - var are = new AutoResetEvent(false); + AutoResetEvent are = new(false); Exception? error = null; - HookEvents.HookDelegate cb = (instance, args) => + HookEvents.HookDelegate cb = (instance, args) => { instance.Initialize(); are.Set(); _initialized = true; - Console.WriteLine($"Server init process successful for architecture {RuntimeInformation.ProcessArchitecture}"); }; HookEvents.Terraria.Main.DedServ += cb; - global::TerrariaApi.Server.Program.Main(new string[] { }); + global::TerrariaApi.Server.Program.Main([]); _initialized = are.WaitOne(TimeSpan.FromSeconds(30)); From a360e1277210d70e4b66bf7e2694ceac24173376 Mon Sep 17 00:00:00 2001 From: Luke Date: Sat, 4 Jan 2025 15:53:09 +1000 Subject: [PATCH 05/12] OTAPI update for MMRD 25.x + test to confirm Excluding ARM64 as expected to currently fail / not supported --- TerrariaServerAPI.Tests/BaseTest.cs | 16 +++++-------- TerrariaServerAPI.Tests/ServerInitTests.cs | 26 ++++++++++++++++++++++ TerrariaServerAPI/TerrariaServerAPI.csproj | 2 +- 3 files changed, 32 insertions(+), 12 deletions(-) diff --git a/TerrariaServerAPI.Tests/BaseTest.cs b/TerrariaServerAPI.Tests/BaseTest.cs index 1f740732..06c4092d 100644 --- a/TerrariaServerAPI.Tests/BaseTest.cs +++ b/TerrariaServerAPI.Tests/BaseTest.cs @@ -1,7 +1,5 @@ using NUnit.Framework; -using System; using System.Runtime.InteropServices; -using System.Threading; namespace TerrariaServerAPI.Tests; @@ -16,24 +14,20 @@ public void EnsureInitialised() if (!_initialized) { - AutoResetEvent are = new(false); - Exception? error = null; + bool invoked = false; HookEvents.HookDelegate cb = (instance, args) => { - instance.Initialize(); - are.Set(); - _initialized = true; + invoked = true; + // DedServ typically requires input, so no need to continue execution + args.ContinueExecution = false; }; HookEvents.Terraria.Main.DedServ += cb; global::TerrariaApi.Server.Program.Main([]); - _initialized = are.WaitOne(TimeSpan.FromSeconds(30)); - HookEvents.Terraria.Main.DedServ -= cb; - Assert.That(_initialized, Is.True); - Assert.That(error, Is.Null); + Assert.That(invoked, Is.True); } } } diff --git a/TerrariaServerAPI.Tests/ServerInitTests.cs b/TerrariaServerAPI.Tests/ServerInitTests.cs index 49c20d31..70345047 100644 --- a/TerrariaServerAPI.Tests/ServerInitTests.cs +++ b/TerrariaServerAPI.Tests/ServerInitTests.cs @@ -1,4 +1,5 @@ using NUnit.Framework; +using System.Runtime.InteropServices; namespace TerrariaServerAPI.Tests; @@ -9,4 +10,29 @@ public void EnsureBoots() { EnsureInitialised(); } + + [Test] + public void EnsureRuntimeDetours() + { + // Platform exclude doesnt support arm64, so manual check it is... + if (RuntimeInformation.ProcessArchitecture == Architecture.Arm64) + Assert.Ignore("Test is not supported on ARM64 architecture."); + + TestContext.Out.WriteLine($"Test architecture {RuntimeInformation.ProcessArchitecture}"); + + bool invoked = false; + + On.Terraria.Main.hook_DedServ callback = (orig, self) => + { + invoked = true; + // DedServ typically requires input, so no need to continue execution + }; + On.Terraria.Main.DedServ += callback; + + global::TerrariaApi.Server.Program.Main([]); + + On.Terraria.Main.DedServ -= callback; + + Assert.That(invoked, Is.True); + } } diff --git a/TerrariaServerAPI/TerrariaServerAPI.csproj b/TerrariaServerAPI/TerrariaServerAPI.csproj index 42de3807..da76bb8a 100644 --- a/TerrariaServerAPI/TerrariaServerAPI.csproj +++ b/TerrariaServerAPI/TerrariaServerAPI.csproj @@ -23,6 +23,6 @@ - + From 0c9f2f769129a6ce1594485f3f3cbef350addc3e Mon Sep 17 00:00:00 2001 From: Luke Date: Sat, 4 Jan 2025 16:01:23 +1000 Subject: [PATCH 06/12] Correct test variable initialisation --- TerrariaServerAPI.Tests/BaseTest.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/TerrariaServerAPI.Tests/BaseTest.cs b/TerrariaServerAPI.Tests/BaseTest.cs index 06c4092d..172d0157 100644 --- a/TerrariaServerAPI.Tests/BaseTest.cs +++ b/TerrariaServerAPI.Tests/BaseTest.cs @@ -20,6 +20,8 @@ public void EnsureInitialised() invoked = true; // DedServ typically requires input, so no need to continue execution args.ContinueExecution = false; + // DedServ calls the following method, which is needed for subsequent tests + instance.Initialize(); }; HookEvents.Terraria.Main.DedServ += cb; From c6a85aa27ab84e17b4722da8796335ac2bd02429 Mon Sep 17 00:00:00 2001 From: Luke Date: Sat, 4 Jan 2025 16:06:50 +1000 Subject: [PATCH 07/12] Set Main.rand within server init test Avoiding the use of DedServ. --- TerrariaServerAPI.Tests/BaseTest.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/TerrariaServerAPI.Tests/BaseTest.cs b/TerrariaServerAPI.Tests/BaseTest.cs index 172d0157..0880cdb2 100644 --- a/TerrariaServerAPI.Tests/BaseTest.cs +++ b/TerrariaServerAPI.Tests/BaseTest.cs @@ -1,5 +1,6 @@ using NUnit.Framework; using System.Runtime.InteropServices; +using Terraria.Utilities; namespace TerrariaServerAPI.Tests; @@ -20,7 +21,8 @@ public void EnsureInitialised() invoked = true; // DedServ typically requires input, so no need to continue execution args.ContinueExecution = false; - // DedServ calls the following method, which is needed for subsequent tests + // DedServ calls the following, which is needed for subsequent tests + global::Terraria.Main.rand = new UnifiedRandom(); instance.Initialize(); }; HookEvents.Terraria.Main.DedServ += cb; From 123f37c5af00d0103d364a9b1b110c19c7e0b562 Mon Sep 17 00:00:00 2001 From: Luke Date: Sat, 4 Jan 2025 16:27:02 +1000 Subject: [PATCH 08/12] Amend EnsureInitialised init variable --- TerrariaServerAPI.Tests/BaseTest.cs | 12 ++++++------ TerrariaServerAPI.Tests/ServerInitTests.cs | 12 ++++-------- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/TerrariaServerAPI.Tests/BaseTest.cs b/TerrariaServerAPI.Tests/BaseTest.cs index 0880cdb2..4563aa9f 100644 --- a/TerrariaServerAPI.Tests/BaseTest.cs +++ b/TerrariaServerAPI.Tests/BaseTest.cs @@ -1,6 +1,5 @@ using NUnit.Framework; using System.Runtime.InteropServices; -using Terraria.Utilities; namespace TerrariaServerAPI.Tests; @@ -11,27 +10,28 @@ public class BaseTest [OneTimeSetUp] public void EnsureInitialised() { - TestContext.Out.WriteLine($"Test architecture {RuntimeInformation.ProcessArchitecture}"); - if (!_initialized) { + TestContext.Out.WriteLine($"Test architecture {RuntimeInformation.ProcessArchitecture}"); + bool invoked = false; - HookEvents.HookDelegate cb = (instance, args) => + HookEvents.HookDelegate cb = (instance, args) => { invoked = true; // DedServ typically requires input, so no need to continue execution args.ContinueExecution = false; // DedServ calls the following, which is needed for subsequent tests - global::Terraria.Main.rand = new UnifiedRandom(); instance.Initialize(); }; HookEvents.Terraria.Main.DedServ += cb; - global::TerrariaApi.Server.Program.Main([]); + TerrariaApi.Server.Program.Main([]); HookEvents.Terraria.Main.DedServ -= cb; Assert.That(invoked, Is.True); + + _initialized = true; } } } diff --git a/TerrariaServerAPI.Tests/ServerInitTests.cs b/TerrariaServerAPI.Tests/ServerInitTests.cs index 70345047..536739ff 100644 --- a/TerrariaServerAPI.Tests/ServerInitTests.cs +++ b/TerrariaServerAPI.Tests/ServerInitTests.cs @@ -22,16 +22,12 @@ public void EnsureRuntimeDetours() bool invoked = false; - On.Terraria.Main.hook_DedServ callback = (orig, self) => - { - invoked = true; - // DedServ typically requires input, so no need to continue execution - }; - On.Terraria.Main.DedServ += callback; + On.Terraria.Program.hook_RunGame callback = (orig) => invoked = true; + On.Terraria.Program.RunGame += callback; - global::TerrariaApi.Server.Program.Main([]); + Terraria.Program.RunGame(); - On.Terraria.Main.DedServ -= callback; + On.Terraria.Program.RunGame -= callback; Assert.That(invoked, Is.True); } From 622bb9391fd3d51baac86632a48a90d24451e8a0 Mon Sep 17 00:00:00 2001 From: Luke Date: Sun, 5 Jan 2025 13:56:44 +1000 Subject: [PATCH 09/12] Fix OnConnectionAccepted incorrectly allowing continuation --- TerrariaServerAPI/TerrariaApi.Server/Hooking/NetHooks.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/TerrariaServerAPI/TerrariaApi.Server/Hooking/NetHooks.cs b/TerrariaServerAPI/TerrariaApi.Server/Hooking/NetHooks.cs index 57d8123d..0fce42f9 100644 --- a/TerrariaServerAPI/TerrariaApi.Server/Hooking/NetHooks.cs +++ b/TerrariaServerAPI/TerrariaApi.Server/Hooking/NetHooks.cs @@ -171,6 +171,7 @@ static void OnNameCollision(object sender, Hooks.MessageBuffer.NameCollisionEven static void OnConnectionAccepted(object? sender, HookEvents.Terraria.Netplay.OnConnectionAcceptedEventArgs args) { if (!args.ContinueExecution) return; + args.ContinueExecution = false; int slot = FindNextOpenClientSlot(); if (slot != -1) { From 68140fecb0461b5f9bff2e9f6f92ad751ee981e6 Mon Sep 17 00:00:00 2001 From: Luke Date: Sun, 5 Jan 2025 14:03:12 +1000 Subject: [PATCH 10/12] Use OTAPI.Common.VersionShort for version printing --- TerrariaServerAPI/TerrariaApi.Server/HookManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TerrariaServerAPI/TerrariaApi.Server/HookManager.cs b/TerrariaServerAPI/TerrariaApi.Server/HookManager.cs index 2083149a..ba14ebae 100644 --- a/TerrariaServerAPI/TerrariaApi.Server/HookManager.cs +++ b/TerrariaServerAPI/TerrariaApi.Server/HookManager.cs @@ -24,7 +24,7 @@ public static void InitialiseAPI() ServerApi.ApiVersion, Main.versionNumber2, Main.curRelease, - typeof(OTAPI.Hooks).Assembly.GetName().Version + OTAPI.Common.VersionShort ); ServerApi.Initialize(Environment.GetCommandLineArgs(), Main.instance); } From ac7df3196b9ddc3609fb0f390110b6757aaa1da5 Mon Sep 17 00:00:00 2001 From: Luke Date: Sun, 5 Jan 2025 22:55:01 +1000 Subject: [PATCH 11/12] OTAPI 3.2.4 - improve boss bag hook CC: https://github.com/SignatureBeef/Open-Terraria-API/pull/131 https://github.com/Pryaxis/TSAPI/issues/252 https://github.com/Pryaxis/TShock/issues/2998 --- TerrariaServerAPI/TerrariaServerAPI.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TerrariaServerAPI/TerrariaServerAPI.csproj b/TerrariaServerAPI/TerrariaServerAPI.csproj index da76bb8a..38e6621d 100644 --- a/TerrariaServerAPI/TerrariaServerAPI.csproj +++ b/TerrariaServerAPI/TerrariaServerAPI.csproj @@ -23,6 +23,6 @@ - + From d7120220f999d23df71a3f0d500dc4adf985fa95 Mon Sep 17 00:00:00 2001 From: Luke Date: Sun, 26 Jan 2025 11:07:22 +1000 Subject: [PATCH 12/12] Migrate UpdateConnectedClients to static hook --- .../TerrariaApi.Server/Hooking/NetHooks.cs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/TerrariaServerAPI/TerrariaApi.Server/Hooking/NetHooks.cs b/TerrariaServerAPI/TerrariaApi.Server/Hooking/NetHooks.cs index 97626a37..ff122a91 100644 --- a/TerrariaServerAPI/TerrariaApi.Server/Hooking/NetHooks.cs +++ b/TerrariaServerAPI/TerrariaApi.Server/Hooking/NetHooks.cs @@ -23,7 +23,7 @@ public static void AttachTo(HookManager hookManager) HookEvents.Terraria.Netplay.OnConnectionAccepted += OnConnectionAccepted; HookEvents.Terraria.Chat.ChatHelper.BroadcastChatMessage += OnBroadcastChatMessage; HookEvents.Terraria.Net.NetManager.SendData += OnSendNetData; - On.Terraria.Netplay.UpdateConnectedClients += OnUpdateConnectedClients; + HookEvents.Terraria.Netplay.UpdateConnectedClients += OnUpdateConnectedClients; Hooks.NetMessage.SendData += OnSendData; Hooks.NetMessage.SendBytes += OnSendBytes; @@ -31,14 +31,16 @@ public static void AttachTo(HookManager hookManager) Hooks.MessageBuffer.NameCollision += OnNameCollision; } - static void OnUpdateConnectedClients(On.Terraria.Netplay.orig_UpdateConnectedClients orig) + static void OnUpdateConnectedClients(object? sender, HookEvents.Terraria.Netplay.UpdateConnectedClientsEventArgs args) + { + if (!args.ContinueExecution) return; + args.ContinueExecution = false; + args.OriginalMethod(); + if (ServerApi.ForceUpdate) { - orig(); - if (ServerApi.ForceUpdate) - { - Terraria.Netplay.HasClients = true; - } + Terraria.Netplay.HasClients = true; } + } static void OnBroadcastChatMessage(object? sender, HookEvents.Terraria.Chat.ChatHelper.BroadcastChatMessageEventArgs args) {