From 47bd4651241eb4da47d01f07abb1127e873be1c9 Mon Sep 17 00:00:00 2001 From: starfish <50672801+starfi5h@users.noreply.github.com> Date: Fri, 8 Mar 2024 14:17:20 +0800 Subject: [PATCH 01/12] Recycle all fleets of client when joining --- .../Dynamic/CombatModuleComponent_Patch.cs | 31 +++++++++++++++++++ NebulaWorld/SimulatedWorld.cs | 16 ++++++++++ 2 files changed, 47 insertions(+) create mode 100644 NebulaPatcher/Patches/Dynamic/CombatModuleComponent_Patch.cs diff --git a/NebulaPatcher/Patches/Dynamic/CombatModuleComponent_Patch.cs b/NebulaPatcher/Patches/Dynamic/CombatModuleComponent_Patch.cs new file mode 100644 index 000000000..89dbdc3f3 --- /dev/null +++ b/NebulaPatcher/Patches/Dynamic/CombatModuleComponent_Patch.cs @@ -0,0 +1,31 @@ +#region + +using System; +using HarmonyLib; +using NebulaModel.Logger; + +#endregion + +namespace NebulaPatcher.Patches.Dynamic; + +[HarmonyPatch(typeof(CombatModuleComponent))] +internal class CombatModuleComponent_Patch +{ + static int s_errorCount = 0; + + [HarmonyFinalizer] + [HarmonyPatch(typeof(CombatModuleComponent), nameof(CombatModuleComponent.GameTick))] + public static Exception GameTick_Finalizer(Exception __exception) + { + if (__exception != null) + { + // After 10 exception triggered, suppress the following messages + if (s_errorCount++ < 10) + { + var msg = "GameTick_Finalizer suppressed exception: \n" + __exception.ToString(); + Log.Error(msg); + } + } + return null; + } +} diff --git a/NebulaWorld/SimulatedWorld.cs b/NebulaWorld/SimulatedWorld.cs index 7b5f89443..94da7062b 100644 --- a/NebulaWorld/SimulatedWorld.cs +++ b/NebulaWorld/SimulatedWorld.cs @@ -109,6 +109,22 @@ public void SetupInitialPlayerState() GameMain.mainPlayer.mecha.forge.gameHistory = GameMain.data.history; GameMain.mainPlayer.mecha.groundCombatModule.AfterImport(GameMain.data); // do we need to do something about the spaceSector? GameMain.mainPlayer.mecha.spaceCombatModule.AfterImport(GameMain.data); // do we need to do something about the spaceSector? + + // Recycle all fleets + var module = GameMain.mainPlayer.mecha.groundCombatModule; + for (var fleetIndex = 0; fleetIndex < module.fleetCount; fleetIndex++) + { + ref var ptr = ref module.moduleFleets[fleetIndex]; + if (ptr.fleetId == 0) continue; + ptr.OnFleetComponentRemoved(); + } + module = GameMain.mainPlayer.mecha.spaceCombatModule; + for (var fleetIndex = 0; fleetIndex < module.fleetCount; fleetIndex++) + { + ref var ptr = ref module.moduleFleets[fleetIndex]; + if (ptr.fleetId == 0) continue; + ptr.OnFleetComponentRemoved(); + } } // Initialization on the host side after game is loaded From df81f047b6a7a70f00434fd2158afb7835590e0a Mon Sep 17 00:00:00 2001 From: starfish <50672801+starfi5h@users.noreply.github.com> Date: Sun, 10 Mar 2024 23:29:28 +0800 Subject: [PATCH 02/12] Warn when attempting to send unregistered packet type --- .../Serialization/LiteNetLib/NetPacketProcessor.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/NebulaModel/Networking/Serialization/LiteNetLib/NetPacketProcessor.cs b/NebulaModel/Networking/Serialization/LiteNetLib/NetPacketProcessor.cs index b1875cd0a..b4e08da5e 100644 --- a/NebulaModel/Networking/Serialization/LiteNetLib/NetPacketProcessor.cs +++ b/NebulaModel/Networking/Serialization/LiteNetLib/NetPacketProcessor.cs @@ -73,7 +73,12 @@ protected virtual SubscribeDelegate GetCallbackFromData(NetDataReader reader) protected virtual void WriteHash(NetDataWriter writer) { - writer.Put(GetHash()); + var hash = GetHash(); + writer.Put(hash); + if (!_callbacks.ContainsKey(hash)) + { + Log.WarnInform($"WriteHash for unregistered type: " + typeof(T).ToString()); + } } /// From b23c7f4f62f3a004c1bbf0f83c3dc13037068e4b Mon Sep 17 00:00:00 2001 From: starfish <50672801+starfi5h@users.noreply.github.com> Date: Mon, 11 Mar 2024 01:24:02 +0800 Subject: [PATCH 03/12] Fix NRE of PropertyLogic.UpdateProduction in client --- .../Patches/Dynamic/PropertyLogic_Patch.cs | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 NebulaPatcher/Patches/Dynamic/PropertyLogic_Patch.cs diff --git a/NebulaPatcher/Patches/Dynamic/PropertyLogic_Patch.cs b/NebulaPatcher/Patches/Dynamic/PropertyLogic_Patch.cs new file mode 100644 index 000000000..d09d019a7 --- /dev/null +++ b/NebulaPatcher/Patches/Dynamic/PropertyLogic_Patch.cs @@ -0,0 +1,22 @@ +#region + +using HarmonyLib; +using NebulaWorld; + +#endregion + +namespace NebulaPatcher.Patches.Dynamic; + +[HarmonyPatch(typeof(PropertyLogic))] +internal class PropertyLogic_Patch +{ + [HarmonyPrefix] + [HarmonyPatch(nameof(PropertyLogic.GameTick))] + public static bool PrepareTick_Prefix() + { + if (!Multiplayer.IsActive) return true; + + // Disable UpdateProduction in client to prevent errror + return Multiplayer.Session.IsServer; + } +} From 2627f60fa8a260ac697c91829d72e2ad70739aaa Mon Sep 17 00:00:00 2001 From: starfish <50672801+starfi5h@users.noreply.github.com> Date: Sun, 10 Mar 2024 02:45:38 +0800 Subject: [PATCH 04/12] Add base null guard in DFGUpdateBaseStatusPacket --- .../Combat/GroundEnemy/DFGUpdateBaseStatusProcessor.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/NebulaNetwork/PacketProcessors/Combat/GroundEnemy/DFGUpdateBaseStatusProcessor.cs b/NebulaNetwork/PacketProcessors/Combat/GroundEnemy/DFGUpdateBaseStatusProcessor.cs index 32aa22824..2f67d01f0 100644 --- a/NebulaNetwork/PacketProcessors/Combat/GroundEnemy/DFGUpdateBaseStatusProcessor.cs +++ b/NebulaNetwork/PacketProcessors/Combat/GroundEnemy/DFGUpdateBaseStatusProcessor.cs @@ -18,6 +18,7 @@ protected override void ProcessPacket(DFGUpdateBaseStatusPacket packet, NebulaCo if (factory == null) return; var dFBase = factory.enemySystem.bases.buffer[packet.BaseId]; + if (dFBase == null) return; ref var evolveData = ref dFBase.evolve; evolveData.threat = packet.Threat; if (evolveData.level != packet.Level) From d96254072e5e36ba718c317136e2fa759bf79f66 Mon Sep 17 00:00:00 2001 From: starfish <50672801+starfi5h@users.noreply.github.com> Date: Mon, 11 Mar 2024 02:33:00 +0800 Subject: [PATCH 05/12] Fix preset enemyId --- .../GroundEnemy/DFGLaunchAssaultProcessor.cs | 14 +--- NebulaWorld/Combat/EnemyManager.cs | 66 +++++++++++++++++++ 2 files changed, 68 insertions(+), 12 deletions(-) diff --git a/NebulaNetwork/PacketProcessors/Combat/GroundEnemy/DFGLaunchAssaultProcessor.cs b/NebulaNetwork/PacketProcessors/Combat/GroundEnemy/DFGLaunchAssaultProcessor.cs index 5b65f7241..f40a5062a 100644 --- a/NebulaNetwork/PacketProcessors/Combat/GroundEnemy/DFGLaunchAssaultProcessor.cs +++ b/NebulaNetwork/PacketProcessors/Combat/GroundEnemy/DFGLaunchAssaultProcessor.cs @@ -7,6 +7,7 @@ using NebulaModel.Packets; using NebulaModel.Packets.Combat.GroundEnemy; using NebulaWorld; +using NebulaWorld.Combat; #endregion @@ -28,18 +29,7 @@ protected override void ProcessPacket(DFGLaunchAssaultPacket packet, NebulaConne using (Multiplayer.Session.Combat.IsIncomingRequest.On()) { // Set enemyRecycle pool to make enemyId stay in sync - factory.enemyCursor = packet.EnemyCursor; - var capacity = factory.enemyCapacity; - while (capacity <= factory.enemyCursor) - { - capacity *= 2; - } - if (capacity > factory.enemyCapacity) - { - factory.SetEnemyCapacity(capacity); - } - factory.enemyRecycleCursor = packet.EnemyRecyle.Length; - Array.Copy(packet.EnemyRecyle, factory.enemyRecycle, packet.EnemyRecyle.Length); + EnemyManager.SetPlanetFactoryRecycle(factory, packet.EnemyCursor, packet.EnemyRecyle); var dFBase = factory.enemySystem.bases.buffer[packet.BaseId]; dFBase.turboTicks = 60; diff --git a/NebulaWorld/Combat/EnemyManager.cs b/NebulaWorld/Combat/EnemyManager.cs index 918b49d4d..34cd17118 100644 --- a/NebulaWorld/Combat/EnemyManager.cs +++ b/NebulaWorld/Combat/EnemyManager.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using NebulaModel.DataStructures; using NebulaModel.DataStructures.Chat; +using NebulaModel.Logger; using NebulaModel.Packets.Combat.DFHive; using NebulaModel.Packets.Combat.GroundEnemy; using NebulaWorld.Chat.ChatLinks; @@ -163,11 +164,52 @@ public static void SetPlanetFactoryNextEnemyId(PlanetFactory factory, int enemyI } else { + ref var ptr = ref factory.enemyPool[enemyId]; + if (ptr.id == enemyId) + { + // This is inside Combat.IsIncomingRequest, so it is approved and won't broadcast back to server + Log.Warn("SetPlanetFactoryNextEnemyId: Kill ground enemy " + enemyId); + ptr.isInvincible = false; + factory.KillEnemyFinally(GameMain.mainPlayer, enemyId, ref CombatStat.empty); + } + factory.enemyRecycle[0] = enemyId; factory.enemyRecycleCursor = 1; } } + public static void SetPlanetFactoryRecycle(PlanetFactory factory, int enemyCusor, int[] enemyRecycle) + { + // Make sure the enemyId about to use are empty + for (var i = 0; i < enemyRecycle.Length; i++) + { + var enemyId = enemyRecycle[i]; + if (enemyId >= factory.enemyCursor) continue; + + ref var ptr = ref factory.enemyPool[enemyId]; + if (ptr.id == enemyId) + { + // This is inside Combat.IsIncomingRequest, so it is approved and won't broadcast back to server + Log.Warn("SetPlanetFactoryRecycle: Kill ground enemy " + enemyId); + ptr.isInvincible = false; + factory.KillEnemyFinally(GameMain.mainPlayer, enemyId, ref CombatStat.empty); + } + } + + factory.enemyCursor = enemyCusor; + var capacity = factory.enemyCapacity; + while (capacity <= factory.enemyCursor) + { + capacity *= 2; + } + if (capacity > factory.enemyCapacity) + { + factory.SetEnemyCapacity(capacity); + } + factory.enemyRecycleCursor = enemyRecycle.Length; + Array.Copy(enemyRecycle, factory.enemyRecycle, enemyRecycle.Length); + } + public static void SetSpaceSectorNextEnemyId(int enemyId) { var spaceSector = GameMain.spaceSector; @@ -182,6 +224,14 @@ public static void SetSpaceSectorNextEnemyId(int enemyId) } else { + ref var ptr = ref spaceSector.enemyPool[enemyId]; + if (ptr.id == enemyId) + { + // This is inside Enemies.IsIncomingRequest, so it is approved and won't broadcast back to server + Log.Warn("SetSpaceSectorNextEnemyId: Kill space enemy " + enemyId); + ptr.isInvincible = false; + spaceSector.KillEnemyFinal(enemyId, ref CombatStat.empty); + } spaceSector.enemyRecycle[0] = enemyId; spaceSector.enemyRecycleCursor = 1; } @@ -191,6 +241,22 @@ public static void SetSpaceSectorRecycle(int enemyCusor, int[] enemyRecycle) { var spaceSector = GameMain.spaceSector; + // Make sure the enemyId about to use are empty + for (var i = 0; i < enemyRecycle.Length; i++) + { + var enemyId = enemyRecycle[i]; + if (enemyId >= spaceSector.enemyCursor) continue; + + ref var ptr = ref spaceSector.enemyPool[enemyId]; + if (ptr.id == enemyId) + { + // This is inside Enemies.IsIncomingRequest, so it is approved and won't broadcast back to server + Log.Warn("SetSpaceSectorRecycle: Kill space enemy " + enemyId); + ptr.isInvincible = false; + spaceSector.KillEnemyFinal(enemyId, ref CombatStat.empty); + } + } + spaceSector.enemyCursor = enemyCusor; var capacity = spaceSector.enemyCapacity; while (capacity <= spaceSector.enemyCursor) From a992570ae7b04c4a016d7089e0959b2df5ffc6f6 Mon Sep 17 00:00:00 2001 From: starfish <50672801+starfi5h@users.noreply.github.com> Date: Mon, 11 Mar 2024 11:05:34 +0800 Subject: [PATCH 06/12] Set dedicated server player alive status to false --- NebulaPatcher/Patches/Dynamic/Dedicated_Server_Patch.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/NebulaPatcher/Patches/Dynamic/Dedicated_Server_Patch.cs b/NebulaPatcher/Patches/Dynamic/Dedicated_Server_Patch.cs index f8ef6e095..df33b3868 100644 --- a/NebulaPatcher/Patches/Dynamic/Dedicated_Server_Patch.cs +++ b/NebulaPatcher/Patches/Dynamic/Dedicated_Server_Patch.cs @@ -36,6 +36,12 @@ public static void GameMainBegin_Postfix() { GameMain.Pause(); } + + if (GameMain.mainPlayer != null) + { + // Don't let the player of dedicated server to interact with enemies + GameMain.mainPlayer.isAlive = false; + } } // Stop game rendering From d42e3778a14dbeac35f4c73ec286d87ff1e56bc0 Mon Sep 17 00:00:00 2001 From: starfish <50672801+starfi5h@users.noreply.github.com> Date: Mon, 11 Mar 2024 13:02:00 +0800 Subject: [PATCH 07/12] Fix NRE when reversing belts with item on them --- .../Packets/Factory/Belt/BeltReversePacket.cs | 15 ------- .../Factory/Belt/BeltReverseRequest.cs | 17 +++++++ .../Factory/Belt/BeltReverseProcessor.cs | 45 ++++++++++++------- .../Patches/Dynamic/UIBeltWindow_Patch.cs | 21 ++++++--- 4 files changed, 63 insertions(+), 35 deletions(-) delete mode 100644 NebulaModel/Packets/Factory/Belt/BeltReversePacket.cs create mode 100644 NebulaModel/Packets/Factory/Belt/BeltReverseRequest.cs diff --git a/NebulaModel/Packets/Factory/Belt/BeltReversePacket.cs b/NebulaModel/Packets/Factory/Belt/BeltReversePacket.cs deleted file mode 100644 index 65b03329c..000000000 --- a/NebulaModel/Packets/Factory/Belt/BeltReversePacket.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace NebulaModel.Packets.Factory.Belt; - -public class BeltReversePacket -{ - public BeltReversePacket() { } - - public BeltReversePacket(int beltId, int planetId) - { - BeltId = beltId; - PlanetId = planetId; - } - - public int BeltId { get; set; } - public int PlanetId { get; set; } -} diff --git a/NebulaModel/Packets/Factory/Belt/BeltReverseRequest.cs b/NebulaModel/Packets/Factory/Belt/BeltReverseRequest.cs new file mode 100644 index 000000000..bad5247c6 --- /dev/null +++ b/NebulaModel/Packets/Factory/Belt/BeltReverseRequest.cs @@ -0,0 +1,17 @@ +namespace NebulaModel.Packets.Factory.Belt; + +public class BeltReverseRequest +{ + public BeltReverseRequest() { } + + public BeltReverseRequest(int beltId, int planetId, int authorId) + { + BeltId = beltId; + PlanetId = planetId; + AuthorId = authorId; + } + + public int BeltId { get; set; } + public int PlanetId { get; set; } + public int AuthorId { get; set; } +} diff --git a/NebulaNetwork/PacketProcessors/Factory/Belt/BeltReverseProcessor.cs b/NebulaNetwork/PacketProcessors/Factory/Belt/BeltReverseProcessor.cs index 86925c004..493f8237e 100644 --- a/NebulaNetwork/PacketProcessors/Factory/Belt/BeltReverseProcessor.cs +++ b/NebulaNetwork/PacketProcessors/Factory/Belt/BeltReverseProcessor.cs @@ -1,18 +1,21 @@ #region +using System; using NebulaAPI; using NebulaAPI.Networking; using NebulaAPI.Packets; +using NebulaModel.Logger; using NebulaModel.Packets.Factory.Belt; +using NebulaWorld; #endregion namespace NebulaNetwork.PacketProcessors.Factory.Belt; [RegisterPacketProcessor] -internal class BeltReverseProcessor : BasePacketProcessor +internal class BeltReverseProcessor : BasePacketProcessor { - public override void ProcessPacket(BeltReversePacket packet, INebulaConnection conn) + public override void ProcessPacket(BeltReverseRequest packet, INebulaConnection conn) { var factory = GameMain.galaxy.PlanetById(packet.PlanetId).factory; if (factory == null) @@ -20,28 +23,40 @@ public override void ProcessPacket(BeltReversePacket packet, INebulaConnection c return; } + if (IsHost) + { + var starId = packet.PlanetId / 100; + Multiplayer.Session.Server.SendPacketToStar(packet, starId); + } + using (NebulaModAPI.MultiplayerSession.Factories.IsIncomingRequest.On()) { NebulaModAPI.MultiplayerSession.Factories.EventFactory = factory; NebulaModAPI.MultiplayerSession.Factories.TargetPlanet = packet.PlanetId; - if (NebulaModAPI.MultiplayerSession.LocalPlayer.IsHost) - { - // Load planet model - NebulaModAPI.MultiplayerSession.Factories.AddPlanetTimer(packet.PlanetId); - } + NebulaModAPI.MultiplayerSession.Factories.PacketAuthor = packet.AuthorId; var beltWindow = UIRoot.instance.uiGame.beltWindow; - beltWindow._Close(); // close the window first to avoid changing unwant variable when setting beltId - var tmpFactory = beltWindow.factory; - var tmpBeltId = beltWindow.beltId; - beltWindow.factory = factory; - beltWindow.beltId = packet.BeltId; - beltWindow.OnReverseButtonClick(0); - beltWindow.factory = tmpFactory; - beltWindow.beltId = tmpBeltId; + try + { + beltWindow._Close(); // close the window first to avoid changing unwant variable when setting beltId + beltWindow.factory = factory; + beltWindow.traffic = factory.cargoTraffic; + beltWindow.player = GameMain.mainPlayer; + beltWindow.beltId = packet.BeltId; + beltWindow.OnReverseButtonClick(0); + beltWindow._Close(); + } + catch (Exception e) + { + Log.Warn(e); + beltWindow._tmp_ids.Clear(); + beltWindow._tmp_cargos.Clear(); + beltWindow._Close(); + } NebulaModAPI.MultiplayerSession.Factories.EventFactory = null; NebulaModAPI.MultiplayerSession.Factories.TargetPlanet = NebulaModAPI.PLANET_NONE; + NebulaModAPI.MultiplayerSession.Factories.PacketAuthor = NebulaModAPI.AUTHOR_NONE; } } } diff --git a/NebulaPatcher/Patches/Dynamic/UIBeltWindow_Patch.cs b/NebulaPatcher/Patches/Dynamic/UIBeltWindow_Patch.cs index 51878cbd8..4980bf942 100644 --- a/NebulaPatcher/Patches/Dynamic/UIBeltWindow_Patch.cs +++ b/NebulaPatcher/Patches/Dynamic/UIBeltWindow_Patch.cs @@ -11,15 +11,26 @@ namespace NebulaPatcher.Patches.Dynamic; [HarmonyPatch(typeof(UIBeltWindow))] internal class UIBeltWindow_Patch { - [HarmonyPostfix] + [HarmonyPrefix] [HarmonyPatch(typeof(UIBeltWindow), nameof(UIBeltWindow.OnReverseButtonClick))] - public static void OnReverseButtonClick_Postfix(UIBeltWindow __instance) + public static bool OnReverseButtonClick_Prefix(UIBeltWindow __instance) { + if (!Multiplayer.IsActive) return true; + if (Multiplayer.Session.Factories.IsIncomingRequest.Value) return true; + // Notify others about belt direction reverse - if (Multiplayer.IsActive && !Multiplayer.Session.Factories.IsIncomingRequest.Value) + var packet = new BeltReverseRequest(__instance.beltId, __instance.factory.planetId, Multiplayer.Session.LocalPlayer.Id); + if (Multiplayer.Session.IsServer) + { + var starId = __instance.factory.planetId / 100; + Multiplayer.Session.Server.SendPacketToStar(packet, starId); + return true; + } + else { - Multiplayer.Session.Network.SendPacketToLocalStar(new BeltReversePacket(__instance.beltId, - __instance.factory.planetId)); + // Request reverse change and wait for server to approve + Multiplayer.Session.Client.SendPacket(packet); + return false; } } } From b2ba48d7e9453710ba1112f5722b0de232a8356e Mon Sep 17 00:00:00 2001 From: starfish <50672801+starfi5h@users.noreply.github.com> Date: Mon, 11 Mar 2024 20:13:07 +0800 Subject: [PATCH 08/12] Fix error when removing base pit on foundation --- .../Packets/Factory/Foundation/FoundationBuildUpdatePacket.cs | 3 +++ .../Factory/Foundation/FoundationBuildUpdateProcessor.cs | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/NebulaModel/Packets/Factory/Foundation/FoundationBuildUpdatePacket.cs b/NebulaModel/Packets/Factory/Foundation/FoundationBuildUpdatePacket.cs index 49002a82c..efdfdcdcd 100644 --- a/NebulaModel/Packets/Factory/Foundation/FoundationBuildUpdatePacket.cs +++ b/NebulaModel/Packets/Factory/Foundation/FoundationBuildUpdatePacket.cs @@ -28,12 +28,14 @@ public FoundationBuildUpdatePacket(Vector3 center, float radius, int reformSize, ReformIndices = btr?.extraCircleIndices; ExtraCenter = center.ToFloat3(); CirclePointCount = btr.circlePointCount; + IsCircle = true; } else //Normal reform { ReformIndices = btr?.cursorIndices; ExtraCenter = new Float3(Vector3.zero); CirclePointCount = 0; + IsCircle = false; } } @@ -48,4 +50,5 @@ public FoundationBuildUpdatePacket(Vector3 center, float radius, int reformSize, public Float3 GroundTestPos { get; set; } public Float3 ExtraCenter { get; set; } public int CirclePointCount { get; set; } + public bool IsCircle { get; set; } } diff --git a/NebulaNetwork/PacketProcessors/Factory/Foundation/FoundationBuildUpdateProcessor.cs b/NebulaNetwork/PacketProcessors/Factory/Foundation/FoundationBuildUpdateProcessor.cs index 5df7fe5ed..ccc247d94 100644 --- a/NebulaNetwork/PacketProcessors/Factory/Foundation/FoundationBuildUpdateProcessor.cs +++ b/NebulaNetwork/PacketProcessors/Factory/Foundation/FoundationBuildUpdateProcessor.cs @@ -45,7 +45,7 @@ protected override void ProcessPacket(FoundationBuildUpdatePacket packet, Nebula //Perform terrain operation var center = packet.ExtraCenter.ToVector3(); var area = packet.CirclePointCount; - if (packet.CirclePointCount == 0) //Normal reform + if (!packet.IsCircle) //Normal reform { var reformPointsCount = factory.planet.aux.ReformSnap(packet.GroundTestPos.ToVector3(), packet.ReformSize, packet.ReformType, packet.ReformColor, reformPoints, packet.ReformIndices, factory.platformSystem, From 27b0007f4fee788c4afe92d51453500b2bd288b8 Mon Sep 17 00:00:00 2001 From: starfish <50672801+starfi5h@users.noreply.github.com> Date: Mon, 11 Mar 2024 20:37:15 +0800 Subject: [PATCH 09/12] Fix UIPlanetDetail error when client join from lobby --- NebulaPatcher/Patches/Dynamic/UIGalaxySelect_Patch.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/NebulaPatcher/Patches/Dynamic/UIGalaxySelect_Patch.cs b/NebulaPatcher/Patches/Dynamic/UIGalaxySelect_Patch.cs index 09ad32d6a..b790d362a 100644 --- a/NebulaPatcher/Patches/Dynamic/UIGalaxySelect_Patch.cs +++ b/NebulaPatcher/Patches/Dynamic/UIGalaxySelect_Patch.cs @@ -178,7 +178,7 @@ public static void SetStarmapGalaxy_Prefix() [HarmonyPatch(nameof(UIGalaxySelect.UpdateParametersUIDisplay))] public static void UpdateParametersUIDisplay_Postfix(UIGalaxySelect __instance) { - if (!Multiplayer.IsInMultiplayerMenu || !Multiplayer.Session.LocalPlayer.IsHost) + if (!Multiplayer.IsInMultiplayerMenu || !Multiplayer.IsActive || !Multiplayer.Session.LocalPlayer.IsHost) { return; } @@ -201,7 +201,7 @@ public static void UpdateParametersUIDisplay_Postfix(UIGalaxySelect __instance) [SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "Original Function Name")] public static void _OnUpdate_Postfix(UIGalaxySelect __instance) { - if (!Multiplayer.IsInMultiplayerMenu) + if (!Multiplayer.IsInMultiplayerMenu || !Multiplayer.IsActive || !Multiplayer.Session.IsInLobby) { return; } From ee16f8978cb17d4a907e925cef022f4f53c7bd81 Mon Sep 17 00:00:00 2001 From: starfish <50672801+starfi5h@users.noreply.github.com> Date: Wed, 13 Mar 2024 17:05:49 +0800 Subject: [PATCH 10/12] Temporary fix NRE of factoryStatPool in PowerSystem.GameTick --- .../Patches/Dynamic/PowerSystem_Patch.cs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/NebulaPatcher/Patches/Dynamic/PowerSystem_Patch.cs b/NebulaPatcher/Patches/Dynamic/PowerSystem_Patch.cs index c6eb31792..37e9612d1 100644 --- a/NebulaPatcher/Patches/Dynamic/PowerSystem_Patch.cs +++ b/NebulaPatcher/Patches/Dynamic/PowerSystem_Patch.cs @@ -12,13 +12,23 @@ internal class PowerSystem_Patch { [HarmonyPrefix] [HarmonyPatch(nameof(PowerSystem.GameTick))] - public static void PowerSystem_GameTick_Prefix(long time, ref bool isActive) + public static void PowerSystem_GameTick_Prefix(PowerSystem __instance, long time, ref bool isActive) { - //Enable signType update on remote planet every 64 tick - if ((time & 63) == 0 && Multiplayer.IsActive && Multiplayer.Session.LocalPlayer.IsHost) + if (!Multiplayer.IsActive) return; + + // Enable signType update on remote planet every 64 tick + if ((time & 63) == 0 && Multiplayer.Session.IsServer) { isActive = true; } + + // Temporary fix NRE of factoryStatPool in client (note: try to find the root cause in the future) + var factoryIndex = __instance.factory.index; + if (GameMain.statistics.production.factoryStatPool[factoryIndex] == null) + { + GameMain.statistics.production.factoryStatPool[factoryIndex] = new FactoryProductionStat(); + GameMain.statistics.production.factoryStatPool[factoryIndex].Init(); + } } [HarmonyPrefix] From 8203ccb7ce1192b16e9421ef2e3dfb84afa612b7 Mon Sep 17 00:00:00 2001 From: starfish <50672801+starfi5h@users.noreply.github.com> Date: Thu, 14 Mar 2024 22:35:09 +0800 Subject: [PATCH 11/12] Fix EnemyFormation.AddUnit() --- .../Transpilers/DFGReplicatorComponent_Transpiler.cs | 8 ++++++-- .../Transpilers/DFSReplicatorComponent_Transpiler.cs | 8 ++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/NebulaPatcher/Patches/Transpilers/DFGReplicatorComponent_Transpiler.cs b/NebulaPatcher/Patches/Transpilers/DFGReplicatorComponent_Transpiler.cs index 563e857e6..6c107e942 100644 --- a/NebulaPatcher/Patches/Transpilers/DFGReplicatorComponent_Transpiler.cs +++ b/NebulaPatcher/Patches/Transpilers/DFGReplicatorComponent_Transpiler.cs @@ -63,8 +63,12 @@ static int AddUnit(EnemyFormation enemyFormation, DFGBaseComponent gbase, int fo } var portId = enemyFormation.AddUnit(); - var packet = new DFGFormationAddUnitPacket(gbase.groundSystem.planet.id, gbase.id, formId, portId); - Multiplayer.Session.Network.SendPacketToStar(packet, gbase.groundSystem.planet.star.id); + if (portId > 0) + { + // Only broadcast if add unit success (vacancyCursor > 0) + var packet = new DFGFormationAddUnitPacket(gbase.groundSystem.planet.id, gbase.id, formId, portId); + Multiplayer.Session.Server.SendPacketToStar(packet, gbase.groundSystem.planet.star.id); + } return 0; // Skip the following call to InitiateUnitDeferred } } diff --git a/NebulaPatcher/Patches/Transpilers/DFSReplicatorComponent_Transpiler.cs b/NebulaPatcher/Patches/Transpilers/DFSReplicatorComponent_Transpiler.cs index 9aa2aa1ee..6e4e06727 100644 --- a/NebulaPatcher/Patches/Transpilers/DFSReplicatorComponent_Transpiler.cs +++ b/NebulaPatcher/Patches/Transpilers/DFSReplicatorComponent_Transpiler.cs @@ -63,8 +63,12 @@ static int AddUnit(EnemyFormation enemyFormation, EnemyDFHiveSystem hive, int fo } var portId = enemyFormation.AddUnit(); - var packet = new DFSFormationAddUnitPacket(hive.hiveAstroId, formId, portId); - Multiplayer.Session.Network.SendPacket(packet); + if (portId > 0) + { + // Only broadcast if add unit success (vacancyCursor > 0) + var packet = new DFSFormationAddUnitPacket(hive.hiveAstroId, formId, portId); + Multiplayer.Session.Server.SendPacket(packet); + } return 0; // Skip the following call to InitiateUnitDeferred } } From 7962507d51a39beea5047fef6d05437fa2b0d6ff Mon Sep 17 00:00:00 2001 From: starfish <50672801+starfi5h@users.noreply.github.com> Date: Fri, 15 Mar 2024 02:24:08 +0800 Subject: [PATCH 12/12] Address comments --- ...BeltReverseRequest.cs => BeltReverseRequestPacket.cs} | 6 +++--- .../Factory/Belt/BeltReverseProcessor.cs | 9 +++++++-- NebulaPatcher/Patches/Dynamic/UIBeltWindow_Patch.cs | 2 +- 3 files changed, 11 insertions(+), 6 deletions(-) rename NebulaModel/Packets/Factory/Belt/{BeltReverseRequest.cs => BeltReverseRequestPacket.cs} (62%) diff --git a/NebulaModel/Packets/Factory/Belt/BeltReverseRequest.cs b/NebulaModel/Packets/Factory/Belt/BeltReverseRequestPacket.cs similarity index 62% rename from NebulaModel/Packets/Factory/Belt/BeltReverseRequest.cs rename to NebulaModel/Packets/Factory/Belt/BeltReverseRequestPacket.cs index bad5247c6..d77f157d4 100644 --- a/NebulaModel/Packets/Factory/Belt/BeltReverseRequest.cs +++ b/NebulaModel/Packets/Factory/Belt/BeltReverseRequestPacket.cs @@ -1,10 +1,10 @@ namespace NebulaModel.Packets.Factory.Belt; -public class BeltReverseRequest +public class BeltReverseRequestPacket { - public BeltReverseRequest() { } + public BeltReverseRequestPacket() { } - public BeltReverseRequest(int beltId, int planetId, int authorId) + public BeltReverseRequestPacket(int beltId, int planetId, int authorId) { BeltId = beltId; PlanetId = planetId; diff --git a/NebulaNetwork/PacketProcessors/Factory/Belt/BeltReverseProcessor.cs b/NebulaNetwork/PacketProcessors/Factory/Belt/BeltReverseProcessor.cs index 493f8237e..29f2f77b4 100644 --- a/NebulaNetwork/PacketProcessors/Factory/Belt/BeltReverseProcessor.cs +++ b/NebulaNetwork/PacketProcessors/Factory/Belt/BeltReverseProcessor.cs @@ -13,9 +13,9 @@ namespace NebulaNetwork.PacketProcessors.Factory.Belt; [RegisterPacketProcessor] -internal class BeltReverseProcessor : BasePacketProcessor +internal class BeltReverseProcessor : BasePacketProcessor { - public override void ProcessPacket(BeltReverseRequest packet, INebulaConnection conn) + public override void ProcessPacket(BeltReverseRequestPacket packet, INebulaConnection conn) { var factory = GameMain.galaxy.PlanetById(packet.PlanetId).factory; if (factory == null) @@ -34,6 +34,11 @@ public override void ProcessPacket(BeltReverseRequest packet, INebulaConnection NebulaModAPI.MultiplayerSession.Factories.EventFactory = factory; NebulaModAPI.MultiplayerSession.Factories.TargetPlanet = packet.PlanetId; NebulaModAPI.MultiplayerSession.Factories.PacketAuthor = packet.AuthorId; + if (IsHost) + { + // Load planet model + NebulaModAPI.MultiplayerSession.Factories.AddPlanetTimer(packet.PlanetId); + } var beltWindow = UIRoot.instance.uiGame.beltWindow; try diff --git a/NebulaPatcher/Patches/Dynamic/UIBeltWindow_Patch.cs b/NebulaPatcher/Patches/Dynamic/UIBeltWindow_Patch.cs index 4980bf942..87b4a9a74 100644 --- a/NebulaPatcher/Patches/Dynamic/UIBeltWindow_Patch.cs +++ b/NebulaPatcher/Patches/Dynamic/UIBeltWindow_Patch.cs @@ -19,7 +19,7 @@ public static bool OnReverseButtonClick_Prefix(UIBeltWindow __instance) if (Multiplayer.Session.Factories.IsIncomingRequest.Value) return true; // Notify others about belt direction reverse - var packet = new BeltReverseRequest(__instance.beltId, __instance.factory.planetId, Multiplayer.Session.LocalPlayer.Id); + var packet = new BeltReverseRequestPacket(__instance.beltId, __instance.factory.planetId, Multiplayer.Session.LocalPlayer.Id); if (Multiplayer.Session.IsServer) { var starId = __instance.factory.planetId / 100;