feat: Implement BuildingRemoveHook to manage building removal and prevent infinite loops
fix: Enhance SaveTransferPacket handling for out-of-order delivery and reset transfer state
This commit is contained in:
33
Main.cs
33
Main.cs
@@ -1015,6 +1015,39 @@ namespace KCM
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HarmonyPatch(typeof(Building), "Remove")]
|
||||||
|
public class BuildingRemoveHook
|
||||||
|
{
|
||||||
|
public static void Prefix(Building __instance)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Skip if we're processing a remove packet (prevents infinite loop)
|
||||||
|
if (Packets.Game.GameBuilding.BuildingRemovePacket.isProcessingPacket)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (KCClient.client.IsConnected)
|
||||||
|
{
|
||||||
|
// Only send packet if this building belongs to a player
|
||||||
|
if (__instance.TeamID() >= 0)
|
||||||
|
{
|
||||||
|
Main.helper.Log($"Building {__instance.UniqueName} (guid: {__instance.guid}) being removed, sending packet");
|
||||||
|
|
||||||
|
new Packets.Game.GameBuilding.BuildingRemovePacket()
|
||||||
|
{
|
||||||
|
guid = __instance.guid
|
||||||
|
}.Send();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
helper.Log($"Error in BuildingRemoveHook: {e.Message}");
|
||||||
|
helper.Log(e.StackTrace);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region "Time Hooks"
|
#region "Time Hooks"
|
||||||
|
|||||||
@@ -30,9 +30,11 @@ namespace KCM.Packets.Lobby
|
|||||||
|
|
||||||
public override void HandlePacketClient()
|
public override void HandlePacketClient()
|
||||||
{
|
{
|
||||||
if (chunkId == 0)
|
// Initialize on first chunk OR if arrays aren't properly sized yet
|
||||||
|
// This handles out-of-order packet delivery
|
||||||
|
if (!loadingSave || saveData.Length != saveSize || chunksReceived.Length != totalChunks)
|
||||||
{
|
{
|
||||||
Main.helper.Log("Save Transfer started! Resetting static transfer state.");
|
Main.helper.Log($"Save Transfer initializing. saveSize={saveSize}, totalChunks={totalChunks}");
|
||||||
loadingSave = true;
|
loadingSave = true;
|
||||||
|
|
||||||
saveData = new byte[saveSize];
|
saveData = new byte[saveSize];
|
||||||
@@ -42,6 +44,12 @@ namespace KCM.Packets.Lobby
|
|||||||
ServerLobbyScript.LoadingSave.SetActive(true);
|
ServerLobbyScript.LoadingSave.SetActive(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Skip if we already received this chunk (duplicate packet)
|
||||||
|
if (chunksReceived[chunkId])
|
||||||
|
{
|
||||||
|
Main.helper.Log($"[SaveTransfer] Duplicate chunk {chunkId} received, skipping.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Array.Copy(saveDataChunk, 0, saveData, saveDataIndex, saveDataChunk.Length);
|
Array.Copy(saveDataChunk, 0, saveData, saveDataIndex, saveDataChunk.Length);
|
||||||
|
|
||||||
@@ -51,6 +59,7 @@ namespace KCM.Packets.Lobby
|
|||||||
|
|
||||||
Main.helper.Log($"[SaveTransfer] Processed chunk {chunkId}/{totalChunks}. Received: {received} bytes of {saveSize}.");
|
Main.helper.Log($"[SaveTransfer] Processed chunk {chunkId}/{totalChunks}. Received: {received} bytes of {saveSize}.");
|
||||||
|
|
||||||
|
// Update progress bar
|
||||||
if (saveSize > 0)
|
if (saveSize > 0)
|
||||||
{
|
{
|
||||||
float savePercent = (float)received / (float)saveSize;
|
float savePercent = (float)received / (float)saveSize;
|
||||||
@@ -68,26 +77,13 @@ namespace KCM.Packets.Lobby
|
|||||||
ServerLobbyScript.ProgressText.text = "0.00 KB / 0.00 KB";
|
ServerLobbyScript.ProgressText.text = "0.00 KB / 0.00 KB";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IsTransferComplete())
|
|
||||||
{
|
|
||||||
Main.helper.Log($"[SaveTransfer] Transfer not yet complete after chunk {chunkId}. Missing: {WhichIsNotComplete()}");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (chunkId + 1 == totalChunks)
|
|
||||||
{
|
|
||||||
Main.helper.Log($"Received last save transfer packet. Final check: IsComplete={IsTransferComplete()}");
|
|
||||||
|
|
||||||
if (!IsTransferComplete())
|
|
||||||
{
|
|
||||||
Main.helper.Log($"[SaveTransfer] WARNING: Transfer is NOT complete even after last chunk. Missing: {WhichIsNotComplete()}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (IsTransferComplete())
|
if (IsTransferComplete())
|
||||||
{
|
{
|
||||||
Main.helper.Log("Save Transfer complete!");
|
Main.helper.Log("Save Transfer complete!");
|
||||||
|
|
||||||
|
// Reset the loading state before processing
|
||||||
|
loadingSave = false;
|
||||||
|
|
||||||
LoadSaveLoadHook.saveBytes = saveData;
|
LoadSaveLoadHook.saveBytes = saveData;
|
||||||
LoadSaveLoadHook.memoryStreamHook = true;
|
LoadSaveLoadHook.memoryStreamHook = true;
|
||||||
|
|
||||||
@@ -99,27 +95,25 @@ namespace KCM.Packets.Lobby
|
|||||||
Broadcast.OnLoadedEvent.Broadcast(new OnLoadedEvent());
|
Broadcast.OnLoadedEvent.Broadcast(new OnLoadedEvent());
|
||||||
|
|
||||||
ServerLobbyScript.LoadingSave.SetActive(false);
|
ServerLobbyScript.LoadingSave.SetActive(false);
|
||||||
|
|
||||||
|
// Reset static state for next transfer
|
||||||
|
ResetTransferState();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void ResetTransferState()
|
||||||
|
{
|
||||||
|
saveData = new byte[1];
|
||||||
|
chunksReceived = new bool[1];
|
||||||
|
loadingSave = false;
|
||||||
|
received = 0;
|
||||||
|
}
|
||||||
|
|
||||||
public static bool IsTransferComplete()
|
public static bool IsTransferComplete()
|
||||||
{
|
{
|
||||||
return chunksReceived.All(x => x == true);
|
return chunksReceived.All(x => x == true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string WhichIsNotComplete()
|
|
||||||
{
|
|
||||||
string notComplete = "";
|
|
||||||
for (int i = 0; i < chunksReceived.Length; i++)
|
|
||||||
{
|
|
||||||
if (!chunksReceived[i])
|
|
||||||
{
|
|
||||||
notComplete += i + ", ";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return notComplete;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void HandlePacketServer()
|
public override void HandlePacketServer()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user