This commit is contained in:
2025-12-14 01:45:02 +01:00
parent 60d509344c
commit f03e13236f
30 changed files with 260 additions and 2480 deletions

View File

@@ -1,56 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace KCM.Packets.Game.GameVillager
{
public class VillagerSnapshotPacket : Packet
{
public override ushort packetId => (ushort)Enums.Packets.VillagerSnapshot;
public List<Guid> guids { get; set; } = new List<Guid>();
public List<Vector3> positions { get; set; } = new List<Vector3>();
public override void HandlePacketClient()
{
if (KCClient.client != null && clientId == KCClient.client.Id)
return;
try
{
int count = Math.Min(guids?.Count ?? 0, positions?.Count ?? 0);
if (count == 0)
return;
for (int i = 0; i < count; i++)
{
Guid guid = guids[i];
Vector3 position = positions[i];
Villager villager = null;
try
{
villager = Villager.villagers?.data.FirstOrDefault(v => v != null && v.guid == guid);
}
catch
{
}
if (villager == null)
continue;
villager.TeleportTo(position);
}
}
catch (Exception e)
{
Main.helper.Log("Error handling villager snapshot packet: " + e.Message);
}
}
public override void HandlePacketServer()
{
}
}
}

View File

@@ -1,9 +1,8 @@
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
namespace KCM.Packets.Game
{
@@ -12,30 +11,18 @@ namespace KCM.Packets.Game
public override ushort packetId => (int)Enums.Packets.SetSpeed;
public int speed { get; set; }
public bool isPaused { get; set; }
public override void HandlePacketClient()
{
if (clientId == KCClient.client.Id) // Prevent speed softlock
return;
try
{
Main.helper.Log($"Received SetSpeed packet: speed={speed}, isPaused={isPaused}");
// Simply apply the speed - SpeedControlUISetSpeedHook will handle this correctly
// since we're coming from a packet (PacketHandler.IsHandlingPacket will be true)
SpeedControlUI.inst.SetSpeed(speed);
}
catch (Exception e)
{
Main.helper.Log("Error handling SetSpeed packet: " + e.Message);
}
SpeedControlUI.inst.SetSpeed(speed);
}
public override void HandlePacketServer()
{
// Server relay is handled automatically by PacketHandler unless [NoServerRelay] is used.
//throw new NotImplementedException();
}
}
}

View File

@@ -35,7 +35,6 @@ namespace KCM.Packets.Handlers
if (!KCServer.IsRunning)
{
Main.kCPlayers.Clear();
Main.clientSteamIds.Clear();
}
}
catch (Exception ex)

View File

@@ -15,14 +15,6 @@ namespace KCM.Packets.Handlers
{
public class PacketHandler
{
[ThreadStatic]
private static bool isHandlingPacket;
public static bool IsHandlingPacket
{
get { return isHandlingPacket; }
}
public static Dictionary<ushort, PacketRef> Packets = new Dictionary<ushort, PacketRef>();
public class PacketRef
{
@@ -92,9 +84,7 @@ namespace KCM.Packets.Handlers
{
IPacket p = (IPacket)Activator.CreateInstance(packet);
var properties = packet.GetProperties(BindingFlags.Instance | BindingFlags.Public)
.Where(prop => prop.Name != "packetId" && prop.Name != "sendMode")
.ToArray();
var properties = packet.GetProperties(BindingFlags.Instance | BindingFlags.Public).Where(prop => prop.Name != "packetId").ToArray();
Array.Sort(properties, (x, y) => String.Compare(x.Name, y.Name));
ushort id = (ushort)p.GetType().GetProperty("packetId").GetValue(p, null);
@@ -147,9 +137,7 @@ namespace KCM.Packets.Handlers
{
packet.HandlePacketServer();
bool shouldRelay = packet.GetType().GetCustomAttributes(typeof(NoServerRelayAttribute), inherit: true).Length == 0;
if (shouldRelay)
((Packet)packet).SendToAll();
((Packet)packet).SendToAll();
}
catch (Exception ex)
{
@@ -191,7 +179,6 @@ namespace KCM.Packets.Handlers
{
try
{
isHandlingPacket = true;
packet.HandlePacketClient();
}
catch (Exception ex)
@@ -214,10 +201,6 @@ namespace KCM.Packets.Handlers
Main.helper.Log(ex.InnerException.StackTrace);
}
}
finally
{
isHandlingPacket = false;
}
}
/* if (PacketHandlers.TryGetValue(id, out PacketHandlerDelegate handler))
@@ -239,20 +222,14 @@ namespace KCM.Packets.Handlers
try
{
var packetRef = Packets[packet.packetId];
MessageSendMode sendMode = MessageSendMode.Reliable;
Packet basePacket = packet as Packet;
if (basePacket != null)
sendMode = basePacket.sendMode;
Message message = Message.Create(sendMode, packet.packetId);
Message message = Message.Create(MessageSendMode.Reliable, packet.packetId);
foreach (var prop in packetRef.properties)
{
if (prop.PropertyType.IsEnum)
{
currentPropName = prop.Name;
message.AddInt(Convert.ToInt32(prop.GetValue(packet, null)));
message.AddInt((int)prop.GetValue(packet, null));
}
else if (prop.PropertyType == typeof(ushort))
{
@@ -323,27 +300,6 @@ namespace KCM.Packets.Handlers
message.AddInt(item);
}
else if (prop.PropertyType == typeof(List<Guid>))
{
currentPropName = prop.Name;
List<Guid> list = (List<Guid>)prop.GetValue(packet, null);
message.AddInt(list.Count);
foreach (var item in list)
message.AddBytes(item.ToByteArray(), true);
}
else if (prop.PropertyType == typeof(List<Vector3>))
{
currentPropName = prop.Name;
List<Vector3> list = (List<Vector3>)prop.GetValue(packet, null);
message.AddInt(list.Count);
foreach (var item in list)
{
message.AddFloat(item.x);
message.AddFloat(item.y);
message.AddFloat(item.z);
}
}
else if (prop.PropertyType.IsGenericType && prop.PropertyType.GetGenericTypeDefinition() == typeof(Dictionary<,>))
{
currentPropName = prop.Name;
@@ -505,7 +461,9 @@ namespace KCM.Packets.Handlers
if (prop.PropertyType.IsEnum)
{
int enumValue = message.GetInt();
prop.SetValue(p, Enum.ToObject(prop.PropertyType, enumValue));
string enumName = Enum.GetName(prop.PropertyType, enumValue);
prop.SetValue(p, Enum.Parse(prop.PropertyType, enumName));
}
else if (prop.PropertyType == typeof(ushort))
{
@@ -577,29 +535,6 @@ namespace KCM.Packets.Handlers
prop.SetValue(p, list);
}
else if (prop.PropertyType == typeof(List<Guid>))
{
int count = message.GetInt();
List<Guid> list = new List<Guid>();
for (int i = 0; i < count; i++)
list.Add(new Guid(message.GetBytes()));
prop.SetValue(p, list);
}
else if (prop.PropertyType == typeof(List<Vector3>))
{
int count = message.GetInt();
List<Vector3> list = new List<Vector3>();
for (int i = 0; i < count; i++)
{
Vector3 vector = new Vector3(message.GetFloat(), message.GetFloat(), message.GetFloat());
list.Add(vector);
}
prop.SetValue(p, list);
}
else if (prop.PropertyType.IsGenericType && prop.PropertyType.GetGenericTypeDefinition() == typeof(Dictionary<,>))
{
IDictionary dictionary = (IDictionary)prop.GetValue(p, null);

View File

@@ -35,17 +35,13 @@ namespace KCM.Packets.Lobby
Main.helper.Log("PlayerList: " + playersName[i] + " " + playersId[i] + " " + steamIds[i]);
KCPlayer player;
if (!Main.kCPlayers.TryGetValue(steamIds[i], out player) || player == null)
Main.kCPlayers.Add(steamIds[i], new KCPlayer(playersName[i], playersId[i], steamIds[i])
{
player = new KCPlayer(playersName[i], playersId[i], steamIds[i]);
Main.kCPlayers[steamIds[i]] = player;
}
player.name = playersName[i];
player.ready = playersReady[i];
player.banner = playersBanner[i];
player.kingdomName = playersKingdomName[i];
name = playersName[i],
ready = playersReady[i],
banner = playersBanner[i],
kingdomName = playersKingdomName[i]
});
if (Main.clientSteamIds.ContainsKey(playersId[i]))
@@ -53,8 +49,7 @@ namespace KCM.Packets.Lobby
else
Main.clientSteamIds.Add(playersId[i], steamIds[i]);
if (player.inst != null && player.inst.PlayerLandmassOwner != null)
player.inst.PlayerLandmassOwner.SetBannerIdx(playersBanner[i]);
Main.kCPlayers[steamIds[i]].inst.PlayerLandmassOwner.SetBannerIdx(playersBanner[i]);
LobbyHandler.AddPlayerEntry(playersId[i]);
}

View File

@@ -14,8 +14,6 @@ namespace KCM.Packets.Lobby
public override void HandlePacketServer()
{
if (player == null)
return;
IsReady = !player.ready;
//SendToAll(KCClient.client.Id);
@@ -24,8 +22,6 @@ namespace KCM.Packets.Lobby
public override void HandlePacketClient()
{
if (player == null)
return;
player.ready = IsReady;
}
}

View File

@@ -4,7 +4,6 @@ using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using KCM.StateManagement.Observers;
using static KCM.Main;
namespace KCM.Packets.Lobby
@@ -18,14 +17,6 @@ namespace KCM.Packets.Lobby
public static bool loadingSave = false;
public static int received = 0;
public static void ResetTransferState()
{
loadingSave = false;
received = 0;
saveData = new byte[1];
chunksReceived = new bool[1];
}
public int chunkId { get; set; }
public int chunkSize { get; set; }
@@ -38,56 +29,38 @@ namespace KCM.Packets.Lobby
public override void HandlePacketClient()
{
bool initialisingTransfer = !loadingSave ||
saveData == null ||
saveData.Length != saveSize ||
chunksReceived == null ||
chunksReceived.Length != totalChunks;
float savePercent = (float)received / (float)saveSize;
if (initialisingTransfer)
// Initialize saveData and chunksReceived on the first packet received
if (saveData.Length == 1)
{
Main.helper.Log("Save Transfer started!");
loadingSave = true;
received = 0;
StateObserver.ClearAll();
ServerLobbyScript.LoadingSave.SetActive(true);
// save percentage
saveData = new byte[saveSize];
chunksReceived = new bool[totalChunks];
if (ServerLobbyScript.LoadingSave != null)
ServerLobbyScript.LoadingSave.SetActive(true);
}
if (chunkId < 0 || chunkId >= totalChunks)
{
Main.helper.Log($"Invalid save chunk id: {chunkId} / {totalChunks}");
return;
}
if (saveDataChunk == null)
{
Main.helper.Log($"Null save chunk data for chunk: {chunkId}");
return;
}
if (saveDataIndex < 0 || saveDataIndex + saveDataChunk.Length > saveData.Length)
{
Main.helper.Log($"Invalid save chunk write range: index={saveDataIndex} len={saveDataChunk.Length} size={saveData.Length}");
return;
}
// Copy the chunk data into the correct position in saveData
Array.Copy(saveDataChunk, 0, saveData, saveDataIndex, saveDataChunk.Length);
// Mark this chunk as received
chunksReceived[chunkId] = true;
// Seek to the next position to write to
received += chunkSize;
float savePercent = saveSize > 0 ? (float)received / (float)saveSize : 0f;
if (ServerLobbyScript.ProgressBar != null)
ServerLobbyScript.ProgressBar.fillAmount = savePercent;
if (ServerLobbyScript.ProgressBarText != null)
ServerLobbyScript.ProgressBarText.text = (savePercent * 100).ToString("0.00") + "%";
if (ServerLobbyScript.ProgressText != null)
ServerLobbyScript.ProgressText.text = $"{((float)(received / 1000)).ToString("0.00")} KB / {((float)(saveSize / 1000)).ToString("0.00")} KB";
ServerLobbyScript.ProgressBar.fillAmount = savePercent;
ServerLobbyScript.ProgressBarText.text = (savePercent * 100).ToString("0.00") + "%";
ServerLobbyScript.ProgressText.text = $"{((float)(received / 1000)).ToString("0.00")} KB / {((float)(saveSize / 1000)).ToString("0.00")} KB";
if (chunkId + 1 == totalChunks)
@@ -108,40 +81,11 @@ namespace KCM.Packets.Lobby
LoadSave.Load();
try
{
Main.SetMultiplayerSaveLoadInProgress(true);
LoadSaveLoadHook.saveContainer.Unpack(null);
}
finally
{
Main.SetMultiplayerSaveLoadInProgress(false);
}
try
{
RunPostLoadRebuild("Save transfer complete");
}
catch
{
}
LoadSaveLoadHook.saveContainer.Unpack(null);
Broadcast.OnLoadedEvent.Broadcast(new OnLoadedEvent());
try
{
new KCM.Packets.Network.ResyncRequestPacket { reason = "post-load" }.Send();
}
catch
{
}
if (ServerLobbyScript.LoadingSave != null)
ServerLobbyScript.LoadingSave.SetActive(false);
loadingSave = false;
received = 0;
saveData = new byte[1];
chunksReceived = new bool[1];
ServerLobbyScript.LoadingSave.SetActive(false);
}
}

View File

@@ -25,7 +25,6 @@ namespace KCM.Packets.Lobby
try
{
int desiredSpeed = 1;
if (!LobbyManager.loadingSave)
{
SpeedControlUI.inst.SetSpeed(0);
@@ -40,13 +39,12 @@ namespace KCM.Packets.Lobby
Main.helper.Log(ex.ToString());
}
SpeedControlUI.inst.SetSpeed(desiredSpeed);
SpeedControlUI.inst.SetSpeed(0);
}
else
{
LobbyManager.loadingSave = false;
GameState.inst.SetNewMode(GameState.inst.playingMode);
SpeedControlUI.inst.SetSpeed(desiredSpeed);
}
}
catch (Exception ex)

View File

@@ -33,14 +33,6 @@ namespace KCM.Packets.Lobby
World.inst.Generate(Seed);
Vector3 center = World.inst.GetCellData(World.inst.GridWidth / 2, World.inst.GridHeight / 2).Center;
Cam.inst.SetTrackingPos(center);
try
{
new KCM.Packets.Network.ResyncRequestPacket { reason = "post-world-seed" }.Send();
}
catch
{
}
}
catch (Exception e)
{

View File

@@ -51,20 +51,6 @@ namespace KCM.Packets.Network
{
Main.helper.Log("Server Player Connected: " + Name + " Id: " + clientId + " SteamID: " + SteamId);
KCPlayer player;
if (Main.kCPlayers.TryGetValue(SteamId, out player))
{
player.id = clientId;
player.name = Name;
player.steamId = SteamId;
}
else
{
Main.kCPlayers[SteamId] = new KCPlayer(Name, clientId, SteamId);
}
Main.clientSteamIds[clientId] = SteamId;
List<KCPlayer> list = Main.kCPlayers.Select(x => x.Value).OrderBy(x => x.id).ToList();
if (list.Count > 0)
@@ -92,7 +78,36 @@ namespace KCM.Packets.Network
return;
byte[] bytes = LoadSaveLoadAtPathHook.saveData;
KCServer.EnqueueSaveTransfer(clientId, bytes);
int chunkSize = 900; // 900 bytes per chunk to fit within packet size limit
List<byte[]> chunks = SplitByteArrayIntoChunks(bytes, chunkSize);
Main.helper.Log("Save Transfer started!");
int sent = 0;
int packetsSent = 0;
for (int i = 0; i < chunks.Count; i++)
{
var chunk = chunks[i];
new SaveTransferPacket()
{
saveSize = bytes.Length,
saveDataChunk = chunk,
chunkId = i,
chunkSize = chunk.Length,
saveDataIndex = sent,
totalChunks = chunks.Count
}.Send(clientId);
Main.helper.Log(" ");
packetsSent++;
sent += chunk.Length;
}
Main.helper.Log($"Sent {packetsSent} save data chunks to client");
}
else
{

View File

@@ -1,35 +0,0 @@
using KCM.Attributes;
using KCM.StateManagement.Sync;
using System;
namespace KCM.Packets.Network
{
[NoServerRelay]
public class ResyncRequestPacket : Packet
{
public override ushort packetId => (ushort)Enums.Packets.ResyncRequest;
public string reason { get; set; }
public override void HandlePacketClient()
{
}
public override void HandlePacketServer()
{
try
{
if (!KCServer.IsRunning)
return;
SyncManager.SendResyncToClient(clientId, reason);
}
catch (Exception ex)
{
Main.helper.Log("Error handling ResyncRequestPacket on server");
Main.helper.Log(ex.ToString());
}
}
}
}

View File

@@ -38,8 +38,7 @@ namespace KCM.Packets.Network
Main.helper.Log("Sending client connected. Client ID is: " + clientId);
Main.kCPlayers[Main.PlayerSteamID] = new KCPlayer(KCClient.inst.Name, clientId, Main.PlayerSteamID);
Main.clientSteamIds[clientId] = Main.PlayerSteamID;
Main.kCPlayers.Add(Main.PlayerSteamID, new KCPlayer(KCClient.inst.Name, clientId, Main.PlayerSteamID));
Player.inst.PlayerLandmassOwner.teamId = clientId * 10 + 2;

View File

@@ -11,21 +11,25 @@ namespace KCM.Packets
{
public abstract ushort packetId { get; }
public ushort clientId { get; set; }
public virtual Riptide.MessageSendMode sendMode => Riptide.MessageSendMode.Reliable;
public KCPlayer player
{
get
{
string steamId;
if (!Main.clientSteamIds.TryGetValue(clientId, out steamId) || string.IsNullOrEmpty(steamId))
KCPlayer p = null;
if (!Main.clientSteamIds.ContainsKey(clientId))
return null;
KCPlayer player;
if (Main.kCPlayers.TryGetValue(steamId, out player))
return player;
//Main.helper.Log($"SteamID: {Main.GetPlayerByClientID(clientId).steamId} for {clientId} ({Main.GetPlayerByClientID(clientId).id})");
if (Main.kCPlayers.TryGetValue(Main.GetPlayerByClientID(clientId).steamId, out p))
return p;
else
{
Main.helper.Log($"Error getting player from packet {packetId} {this.GetType().Name} from {clientId}");
}
Main.helper.Log($"Error getting player from packet {packetId} {GetType().Name} from {clientId}");
return null;
}
}

View File

@@ -1,33 +0,0 @@
using KCM.StateManagement.Sync;
using System;
namespace KCM.Packets.State
{
public class BuildingSnapshotPacket : Packet
{
public override ushort packetId => (ushort)Enums.Packets.BuildingSnapshot;
public byte[] payload { get; set; }
public override void HandlePacketClient()
{
try
{
if (payload == null || payload.Length == 0)
return;
SyncManager.ApplyBuildingSnapshot(payload);
}
catch (Exception ex)
{
Main.helper.Log("Error applying BuildingSnapshotPacket");
Main.helper.Log(ex.ToString());
}
}
public override void HandlePacketServer()
{
}
}
}

View File

@@ -11,7 +11,6 @@ namespace KCM.Packets.State
public class BuildingStatePacket : Packet
{
public override ushort packetId => (ushort)Enums.Packets.BuildingStatePacket;
public override Riptide.MessageSendMode sendMode => Riptide.MessageSendMode.Unreliable;
public string customName { get; set; }
public Guid guid { get; set; }

View File

@@ -1,37 +0,0 @@
using KCM.StateManagement.Sync;
using System;
using System.Collections.Generic;
namespace KCM.Packets.State
{
public class ResourceSnapshotPacket : Packet
{
public override ushort packetId => (ushort)Enums.Packets.ResourceSnapshot;
public override Riptide.MessageSendMode sendMode => Riptide.MessageSendMode.Unreliable;
public List<int> resourceTypes { get; set; }
public List<int> amounts { get; set; }
public override void HandlePacketClient()
{
try
{
if (KCClient.client.IsConnected && KCClient.client.Id == clientId)
return;
SyncManager.ApplyResourceSnapshot(resourceTypes, amounts);
}
catch (Exception ex)
{
Main.helper.Log("Error applying ResourceSnapshotPacket");
Main.helper.Log(ex.ToString());
}
}
public override void HandlePacketServer()
{
}
}
}