From 3dc5faef10ecd6712a06175d0cf660f05901c30c Mon Sep 17 00:00:00 2001 From: starfish <50672801+starfi5h@users.noreply.github.com> Date: Wed, 10 Apr 2024 02:00:35 +0800 Subject: [PATCH] Fix sync soil sand count incorrect in client --- .../Players/PlayerSandCountProcessor.cs | 12 ++- NebulaPatcher/Patches/Dynamic/Player_Patch.cs | 75 +++++++++++++++---- 2 files changed, 66 insertions(+), 21 deletions(-) diff --git a/NebulaNetwork/PacketProcessors/Players/PlayerSandCountProcessor.cs b/NebulaNetwork/PacketProcessors/Players/PlayerSandCountProcessor.cs index 95c4b59b4..1daad0f39 100644 --- a/NebulaNetwork/PacketProcessors/Players/PlayerSandCountProcessor.cs +++ b/NebulaNetwork/PacketProcessors/Players/PlayerSandCountProcessor.cs @@ -14,19 +14,17 @@ public class PlayerSandCountProcessor : PacketProcessor { protected override void ProcessPacket(PlayerSandCount packet, NebulaConnection conn) { + var player = GameMain.mainPlayer; + var originalSandCount = player.sandCount; + if (IsHost) { - if (!packet.IsDelta) - { - // when receive update request, host UpdateSyncedSandCount and send to other players - GameMain.mainPlayer.SetSandCount(packet.SandCount); - } + // when receive update request, host UpdateSyncedSandCount and send to other players + player.SetSandCount(packet.IsDelta ? originalSandCount + packet.SandCount : packet.SandCount); return; } // taken from Player.SetSandCount() - var player = GameMain.mainPlayer; - var originalSandCount = player.sandCount; if (packet.IsDelta) { player.sandCount += packet.SandCount; diff --git a/NebulaPatcher/Patches/Dynamic/Player_Patch.cs b/NebulaPatcher/Patches/Dynamic/Player_Patch.cs index 3758c3ab3..668f8581e 100644 --- a/NebulaPatcher/Patches/Dynamic/Player_Patch.cs +++ b/NebulaPatcher/Patches/Dynamic/Player_Patch.cs @@ -14,36 +14,83 @@ namespace NebulaPatcher.Patches.Dynamic; [HarmonyPatch(typeof(Player))] internal class Player_Patch { + [HarmonyPrefix] + [HarmonyPatch(nameof(Player.ExchangeSand))] + public static bool ExchangeSand_Prefix(Player __instance) + { + if (!Multiplayer.IsActive) + { + return true; + } + + var gainedSand = 0; + for (var i = 0; i < __instance.package.size; i++) + { + if (__instance.package.grids[i].itemId == 1099) // 1099: enemy drop sand item + { + gainedSand += __instance.package.grids[i].count; + __instance.package.grids[i].itemId = 0; + __instance.package.grids[i].filter = 0; + __instance.package.grids[i].count = 0; + __instance.package.grids[i].inc = 0; + __instance.package.grids[i].stackSize = 0; + } + } + + // Only call SetSandCount when there is sand change in client + if (gainedSand > 0) + { + if (Config.Options.SyncSoil && Multiplayer.Session.IsClient) + { + // Report to server to add sand in shared pool + Multiplayer.Session.Client.SendPacket(new PlayerSandCount(gainedSand, true)); + } + else + { + __instance.SetSandCount(__instance.sandCount + gainedSand); + } + } + return false; + } + + [HarmonyPrefix] [HarmonyPatch(nameof(Player.SetSandCount))] public static bool SetSandCount_Prefix(long newSandCount) { + if (!Multiplayer.IsActive) + { + return true; + } + if (!Config.Options.SyncSoil) { - return !Multiplayer.IsActive || Multiplayer.Session.Factories.PacketAuthor == Multiplayer.Session.LocalPlayer.Id || + return Multiplayer.Session.Factories.PacketAuthor == Multiplayer.Session.LocalPlayer.Id || Multiplayer.Session.LocalPlayer.IsHost && Multiplayer.Session.Factories.PacketAuthor == NebulaModAPI.AUTHOR_NONE || !Multiplayer.Session.Factories.IsIncomingRequest.Value; } - switch (Multiplayer.IsActive) + if (Multiplayer.Session.LocalPlayer.IsHost) { //Soil should be given in singleplayer or to the host who then syncs it back to all players. - case true when Multiplayer.Session.LocalPlayer.IsHost: - var deltaSandCount = (int)(newSandCount - GameMain.mainPlayer.sandCount); - if (deltaSandCount != 0) - { - UpdateSyncedSandCount(deltaSandCount); - Multiplayer.Session.Server.SendPacket(new PlayerSandCount(newSandCount)); - } - break; + var deltaSandCount = (int)(newSandCount - GameMain.mainPlayer.sandCount); + if (deltaSandCount != 0) + { + UpdateSyncedSandCount(deltaSandCount); + Multiplayer.Session.Server.SendPacket(new PlayerSandCount(newSandCount)); + } + } + else + { //Or client that use reform tool - case true when GameMain.mainPlayer.controller.actionBuild.reformTool.drawing: - Multiplayer.Session.Network.SendPacket(new PlayerSandCount(newSandCount)); - break; + if (GameMain.mainPlayer.controller.actionBuild.reformTool.drawing) + { + Multiplayer.Session.Client.SendPacket(new PlayerSandCount(newSandCount)); + } } - return !Multiplayer.IsActive || Multiplayer.Session.LocalPlayer.IsHost; + return Multiplayer.Session.LocalPlayer.IsHost; //Soil should be given in singleplayer or to the player who is author of the "Build" request, or to the host if there is no author. }