Fix map synchronization between host and clients

Problem: Clients received WorldSeed packet before ServerSettings,
causing world generation with wrong mapSize/mapBias/mapRivers
parameters. Same seed but different parameters = different maps.

Solution: Include all map parameters directly in WorldSeed packet:
- WorldSize (map size)
- WorldType (map bias - continents/islands/etc)
- WorldRivers (river/lake density)

Now packet order doesn't matter - WorldSeed has everything needed
for identical world generation across all clients.

Changes:
- WorldSeed.cs: Add map parameters, set before Generate()
- ClientConnected.cs: Send full world params to joining clients
- ServerLobbyScript.cs: Send full params on new world generation
- Added [WORLD SYNC] debug logging

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
2025-12-14 21:00:15 +01:00
parent 4057cf37c5
commit c4eb7e944d
4 changed files with 28 additions and 6 deletions

View File

@@ -18,11 +18,8 @@ namespace KCM.Enums
KingdomName = 32, KingdomName = 32,
StartGame = 33, StartGame = 33,
WorldSeed = 34, WorldSeed = 34,
Building = 50, Building = 50,
BuildingOnPlacement = 51, BuildingOnPlacement = 51,
World = 70, World = 70,
WorldPlace = 71, WorldPlace = 71,
FellTree = 72, FellTree = 72,

View File

@@ -13,6 +13,11 @@ namespace KCM.Packets.Lobby
public override ushort packetId => (int)Enums.Packets.WorldSeed; public override ushort packetId => (int)Enums.Packets.WorldSeed;
public int Seed { get; set; } public int Seed { get; set; }
// Map parameters to ensure correct generation
public World.MapSize WorldSize { get; set; }
public World.MapBias WorldType { get; set; }
public World.MapRiverLakes WorldRivers { get; set; }
public override void HandlePacketServer() public override void HandlePacketServer()
{ {
//SetWorldSeed(); //SetWorldSeed();
@@ -27,12 +32,21 @@ namespace KCM.Packets.Lobby
{ {
try try
{ {
// Set map parameters BEFORE generating to ensure correct world
World.inst.mapSize = WorldSize;
World.inst.mapBias = WorldType;
World.inst.mapRiverLakes = WorldRivers;
Main.helper.Log($"[WORLD SYNC] Generating world - Seed: {Seed}, Size: {WorldSize}, Type: {WorldType}, Rivers: {WorldRivers}");
foreach (var player in Main.kCPlayers.Values) foreach (var player in Main.kCPlayers.Values)
player.inst.Reset(); player.inst.Reset();
World.inst.Generate(Seed); World.inst.Generate(Seed);
Vector3 center = World.inst.GetCellData(World.inst.GridWidth / 2, World.inst.GridHeight / 2).Center; Vector3 center = World.inst.GetCellData(World.inst.GridWidth / 2, World.inst.GridHeight / 2).Center;
Cam.inst.SetTrackingPos(center); Cam.inst.SetTrackingPos(center);
Main.helper.Log("[WORLD SYNC] World generation complete");
} }
catch (Exception e) catch (Exception e)
{ {

View File

@@ -111,11 +111,16 @@ namespace KCM.Packets.Network
} }
else else
{ {
// Send world seed with all map parameters to ensure correct generation
new WorldSeed() new WorldSeed()
{ {
Seed = World.inst.seed Seed = World.inst.seed,
WorldSize = World.inst.mapSize,
WorldType = World.inst.mapBias,
WorldRivers = World.inst.mapRiverLakes
}.SendToAll(KCClient.client.Id); }.SendToAll(KCClient.client.Id);
Main.helper.Log($"[WORLD SYNC] Sent world to new client - Seed: {World.inst.seed}, Size: {World.inst.mapSize}, Type: {World.inst.mapBias}, Rivers: {World.inst.mapRiverLakes}");
} }
} }

View File

@@ -247,10 +247,16 @@ namespace KCM
foreach (var player in Main.kCPlayers.Values) foreach (var player in Main.kCPlayers.Values)
player.inst.SetupJobPriorities(); player.inst.SetupJobPriorities();
// Send world seed with all map parameters to ensure clients generate identical world
new WorldSeed() new WorldSeed()
{ {
Seed = World.inst.seed Seed = World.inst.seed,
WorldSize = World.inst.mapSize,
WorldType = World.inst.mapBias,
WorldRivers = World.inst.mapRiverLakes
}.SendToAll(KCClient.client.Id); }.SendToAll(KCClient.client.Id);
Main.helper.Log($"[WORLD SYNC] Generated new world - Seed: {World.inst.seed}, Size: {World.inst.mapSize}, Type: {World.inst.mapBias}, Rivers: {World.inst.mapRiverLakes}");
} }
catch (Exception ex) catch (Exception ex)
{ {