Compare commits
2 Commits
62db70c1c4
...
1cc3042781
| Author | SHA1 | Date | |
|---|---|---|---|
| 1cc3042781 | |||
| 181936e3d4 |
1
Main.cs
1
Main.cs
@@ -435,7 +435,6 @@ namespace KCM
|
|||||||
// Your code here
|
// Your code here
|
||||||
|
|
||||||
// Get the name of the last method that called OnPlayerPlacement
|
// Get the name of the last method that called OnPlayerPlacement
|
||||||
string callTree = "";
|
|
||||||
List<string> strings = new List<string>();
|
List<string> strings = new List<string>();
|
||||||
|
|
||||||
for (int i = 1; i < 10; i++)
|
for (int i = 1; i < 10; i++)
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ namespace KCM.Packets
|
|||||||
{
|
{
|
||||||
if (KCServer.IsRunning && toClient != 0)
|
if (KCServer.IsRunning && toClient != 0)
|
||||||
{
|
{
|
||||||
KCServer.server.Send(PacketHandler.SerialisePacket(this), toClient, Riptide.MessageSendMode.Reliable);
|
KCServer.server.Send(PacketHandler.SerialisePacket(this), toClient, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|||||||
38
README.md
Normal file
38
README.md
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
# Kingdoms and Castles Multiplayer Mod Fixes
|
||||||
|
|
||||||
|
This document summarizes the fixes and improvements implemented to enhance the stability and functionality of the multiplayer mod for Kingdoms and Castles.
|
||||||
|
|
||||||
|
## Implemented Fixes:
|
||||||
|
|
||||||
|
### 1. Improved Lobby Stability
|
||||||
|
- **Issue:** Previously, joining a multiplayer lobby could lead to an immediate crash (NullReferenceException in `PlayerEntryScript.cs`).
|
||||||
|
- **Fix:** Corrected the initialization order of UI components in `PlayerEntryScript.cs` to prevent NullReferenceExceptions, ensuring stable lobby entry.
|
||||||
|
|
||||||
|
### 2. Enhanced Session Cleanup
|
||||||
|
- **Issue:** Users previously had to restart the entire game after leaving a multiplayer session to join or host a new one. This was due to residual game state and an aggressive cleanup that inadvertently shut down Steamworks.
|
||||||
|
- **Fix:** Implemented a comprehensive `CleanupMultiplayerSession()` routine in `Main.cs`. This routine now properly resets static mod data (player lists, client/server states), and, crucially, no longer destroys the core `KCMSteamManager` (Steamworks API manager). This allows for seamless transitions between multiplayer sessions without game restarts.
|
||||||
|
|
||||||
|
### 3. Optimized Building Synchronization Performance
|
||||||
|
- **Issue:** Rapid changes in building state (e.g., during construction) could generate excessive network traffic, potentially contributing to "poor connection" issues.
|
||||||
|
- **Fix:** Implemented a throttling mechanism in `BuildingStateManager.cs`. Building state updates are now limited to 10 times per second per building, significantly reducing network spam while maintaining visual fluidity.
|
||||||
|
|
||||||
|
### 4. Resolved Villager Freezing
|
||||||
|
- **Issue:** Villagers would sometimes freeze during gameplay, despite other game elements functioning correctly. This was caused by the game attempting to synchronize the state of already destroyed building components, leading to a cascade of errors.
|
||||||
|
- **Fix:** Added a robust null check in `BuildingStateManager.cs`. If an observed building has been destroyed, its associated observer is now properly de-registered (by destroying its GameObject), preventing further errors and ensuring continuous game logic for villagers and other entities. This also handles cases where buildings are replaced (e.g., construction completed).
|
||||||
|
|
||||||
|
### 5. Fixed Map Desynchronization
|
||||||
|
- **Issue:** When starting a new multiplayer game, clients often generated a different map than the host, even if the seed was specified. This was due to the host not sending the definitive world seed at the critical moment.
|
||||||
|
- **Fix:** Modified `ServerLobbyScript.cs` to ensure that when the host clicks "Start Game", the current world seed (either from UI input or newly generated) is explicitly sent to all clients via a `WorldSeed` packet *before* the game starts. This guarantees all players generate the exact same map.
|
||||||
|
|
||||||
|
### 6. Reliable Save Game Transfer
|
||||||
|
- **Issue:** Loading a saved multiplayer game would often fail for clients, resulting in an incomplete save file and desynchronized gameplay. This occurred because save file chunks were sent unreliably over the network.
|
||||||
|
- **Fix:** Changed the save game chunk transfer in `ClientConnected.cs` to use Riptide's `Reliable` message send mode. This ensures that all parts of the save file are guaranteed to arrive at the client, allowing for complete and successful save game loading.
|
||||||
|
|
||||||
|
### 7. Compilation Errors & Warnings Addressed
|
||||||
|
- All reported compilation errors and warnings (including issues with `Packet.Send` overloads and `World.SeedFromText`) have been investigated and resolved, ensuring the mod compiles cleanly.
|
||||||
|
|
||||||
|
## Pending Task:
|
||||||
|
|
||||||
|
### Resource Synchronization
|
||||||
|
- **Goal:** Implement synchronization for player resources (Gold, Wood, Stone, Food) to ensure all players see consistent resource counts.
|
||||||
|
- **Status:** Awaiting confirmation from the user regarding the exact `FreeResourceType` enum names (`Wood`, `Stone`, `Food`) to proceed with implementation.
|
||||||
@@ -60,8 +60,6 @@ namespace KCM
|
|||||||
Falle
|
Falle
|
||||||
}
|
}
|
||||||
|
|
||||||
bool awake = false;
|
|
||||||
|
|
||||||
public void Start()
|
public void Start()
|
||||||
{
|
{
|
||||||
Main.helper.Log("ServerLobby start called");
|
Main.helper.Log("ServerLobby start called");
|
||||||
@@ -188,14 +186,30 @@ namespace KCM
|
|||||||
StartGameButton.GetComponentInChildren<TextMeshProUGUI>().text = "Start";
|
StartGameButton.GetComponentInChildren<TextMeshProUGUI>().text = "Start";
|
||||||
StartGameButton.onClick.AddListener(() =>
|
StartGameButton.onClick.AddListener(() =>
|
||||||
{
|
{
|
||||||
if (World.inst.GetTextSeed() != WorldSeed.text)
|
int definitiveSeed;
|
||||||
|
if (string.IsNullOrWhiteSpace(WorldSeed.text))
|
||||||
{
|
{
|
||||||
World.inst.seed = World.inst.SeedFromText(WorldSeed.text);
|
World.inst.Generate();
|
||||||
|
definitiveSeed = World.inst.seed;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (int.TryParse(WorldSeed.text, out int parsedSeed))
|
||||||
|
{
|
||||||
|
definitiveSeed = parsedSeed;
|
||||||
|
World.inst.Generate(definitiveSeed);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Main.helper.LogWarning($"Invalid seed '{WorldSeed.text}' entered. Generating a random seed.");
|
||||||
|
World.inst.Generate();
|
||||||
|
definitiveSeed = World.inst.seed;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
new WorldSeed()
|
new WorldSeed()
|
||||||
{
|
{
|
||||||
Seed = World.inst.seed
|
Seed = definitiveSeed
|
||||||
}.SendToAll(KCClient.client.Id);
|
}.SendToAll(KCClient.client.Id);
|
||||||
|
|
||||||
new StartGame().SendToAll();
|
new StartGame().SendToAll();
|
||||||
|
|||||||
Reference in New Issue
Block a user