338 lines
12 KiB
Markdown
338 lines
12 KiB
Markdown
# Kingdoms and Castles Multiplayer Mod
|
|
|
|
Ez a mod multiplayer funkcionalitást ad a Kingdoms and Castles játékhoz.
|
|
|
|
## Legutóbbi javítások (2025-12-14)
|
|
|
|
### Kapcsolati problémák javítása
|
|
|
|
#### Probléma
|
|
A játékosok gyakran tapasztaltak "poor connection", "lost connection", vagy "server disconnected" üzeneteket, és ezután nem tudtak újra csatlakozni anélkül, hogy újraindították volna a játékot.
|
|
|
|
#### Gyökérok
|
|
1. **Statikus client/server objektumok**: A `KCClient` és `KCServer` osztályok statikus konstruktorokban létrehozott `Client` és `Server` objektumokat használtak, amelyek soha nem újrainizializálódtak disconnect után.
|
|
|
|
2. **Event handler elvesztés**: Az event handlerek (Connected, Disconnected, MessageReceived, stb.) a statikus konstruktorban lettek feliratkozva, de amikor új server/client objektumok lettek létrehozva, ezek a handlerek elvesztek.
|
|
|
|
3. **Nem tisztított állapot**: A disconnect után a játék állapota nem lett teljesen kitisztítva, így a következő kapcsolódási kísérlet hibás állapotból indult.
|
|
|
|
#### Megoldások
|
|
|
|
##### 1. KCClient.cs - Javított újracsatlakozási képesség
|
|
**Változtatások:**
|
|
- Új `InitializeClient()` metódus amely:
|
|
- Teljesen kitisztítja a régi client objektumot
|
|
- Lecsatlakoztatja a régi kapcsolatot ha létezik
|
|
- Leiratkozik az összes event handlerről
|
|
- Létrehoz egy új, tiszta `Client` objektumot
|
|
- Növelt timeout (15 másodperc) a gyakori timeout-ok elkerülésére
|
|
- Újra feliratkozik az event handlerekre
|
|
|
|
- Módosított `Connect()` metódus:
|
|
- Minden kapcsolódás előtt újrainicializálja a client-et
|
|
- Növelt connection attempts (10) a megbízhatóbb kapcsolódásért
|
|
|
|
- Javított `Client_Disconnected` event handler:
|
|
- Tisztítja a client state-et (clientSteamIds)
|
|
- Megkülönbözteti az önkéntes és nem várt disconnect-eket
|
|
- Csak nem várt disconnect esetén mutat error modalt
|
|
|
|
**Érintett kód részletek:**
|
|
```csharp
|
|
// KCClient.cs:34-62
|
|
private static void InitializeClient()
|
|
{
|
|
// Clean up old client if exists
|
|
if (client != null)
|
|
{
|
|
if (client.IsConnected || client.IsConnecting)
|
|
{
|
|
client.Disconnect();
|
|
}
|
|
// Unsubscribe from old events
|
|
client.Connected -= Client_Connected;
|
|
client.ConnectionFailed -= Client_ConnectionFailed;
|
|
client.Disconnected -= Client_Disconnected;
|
|
client.MessageReceived -= PacketHandler.HandlePacket;
|
|
}
|
|
|
|
// Create new client instance
|
|
client = new Client(Main.steamClient);
|
|
|
|
// Set a higher timeout to prevent frequent disconnections
|
|
client.TimeoutTime = 15000; // 15 seconds instead of default 5 seconds
|
|
|
|
// Subscribe to events
|
|
client.Connected += Client_Connected;
|
|
client.ConnectionFailed += Client_ConnectionFailed;
|
|
client.Disconnected += Client_Disconnected;
|
|
client.MessageReceived += PacketHandler.HandlePacket;
|
|
}
|
|
```
|
|
|
|
##### 2. KCServer.cs - Javított server event handling
|
|
**Változtatások:**
|
|
- Új `InitializeServer()` metódus hasonló logikával mint a client:
|
|
- Leállítja a régi server-t ha fut
|
|
- Leiratkozik az event handlerökről
|
|
- Létrehoz új server objektumot
|
|
- Növelt timeout (15 másodperc)
|
|
- Újra feliratkozik az event handlerekre
|
|
|
|
- Event handlerek kiszervezése statikus metódusokba:
|
|
- `OnClientConnected()` - külön metódus a client csatlakozás kezelésére
|
|
- `OnClientDisconnected()` - külön metódus a client lecsatlakozás kezelésére
|
|
- Try-catch blokkok a biztonságos error handling-ért
|
|
|
|
- `StartServer()` mindig újrainicializálja a server-t:
|
|
- Garantálja a tiszta állapotot minden indításkor
|
|
|
|
**Érintett kód részletek:**
|
|
```csharp
|
|
// KCServer.cs:30-56
|
|
private static void InitializeServer()
|
|
{
|
|
// Clean up old server if exists
|
|
if (server != null)
|
|
{
|
|
if (server.IsRunning)
|
|
{
|
|
server.Stop();
|
|
}
|
|
// Unsubscribe from old events
|
|
server.MessageReceived -= PacketHandler.HandlePacketServer;
|
|
server.ClientConnected -= OnClientConnected;
|
|
server.ClientDisconnected -= OnClientDisconnected;
|
|
}
|
|
|
|
// Create new server instance
|
|
server = new Server(Main.steamServer);
|
|
|
|
// Set a higher timeout to prevent frequent disconnections
|
|
server.TimeoutTime = 15000; // 15 seconds instead of default 5 seconds
|
|
|
|
// Subscribe to events
|
|
server.MessageReceived += PacketHandler.HandlePacketServer;
|
|
server.ClientConnected += OnClientConnected;
|
|
server.ClientDisconnected += OnClientDisconnected;
|
|
}
|
|
```
|
|
|
|
##### 3. LobbyManager.cs - Javított cleanup
|
|
**Változtatások:**
|
|
- `LeaveLobby()` metódus teljes átírása:
|
|
- Részletes logging minden lépésnél
|
|
- Null-safe ellenőrzések
|
|
- Try-catch blokk a biztonságos cleanup-ért
|
|
- Kitisztítja mind a `kCPlayers` mind a `clientSteamIds` dictionary-ket
|
|
- Visszaállítja az összes flag-et (`loadingSave`, `registerServer`)
|
|
- Garantálja hogy mindig visszatér a ServerBrowser-hez még hiba esetén is
|
|
|
|
**Érintett kód részletek:**
|
|
```csharp
|
|
// LobbyManager.cs:151-205
|
|
public void LeaveLobby()
|
|
{
|
|
Main.helper.Log("LeaveLobby called - cleaning up connection state");
|
|
|
|
try
|
|
{
|
|
// Disconnect client first
|
|
if (KCClient.client != null && (KCClient.client.IsConnected || KCClient.client.IsConnecting))
|
|
{
|
|
Main.helper.Log("Disconnecting client...");
|
|
KCClient.client.Disconnect();
|
|
}
|
|
|
|
// Stop server if running
|
|
if (KCServer.IsRunning)
|
|
{
|
|
Main.helper.Log("Stopping server...");
|
|
KCServer.server.Stop();
|
|
}
|
|
|
|
// Leave Steam lobby
|
|
if (lobbyId.IsValid())
|
|
{
|
|
Main.helper.Log("Leaving Steam lobby...");
|
|
SteamMatchmaking.LeaveLobby(lobbyId);
|
|
}
|
|
|
|
// Clear player data
|
|
Main.helper.Log("Clearing player data...");
|
|
Main.kCPlayers.Clear();
|
|
Main.clientSteamIds.Clear();
|
|
|
|
// Clear UI
|
|
LobbyHandler.ClearPlayerList();
|
|
LobbyHandler.ClearChatEntries();
|
|
|
|
// Reset flags
|
|
ServerBrowser.registerServer = false;
|
|
loadingSave = false;
|
|
|
|
// ... continues with transition
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
// Error handling with fallback
|
|
}
|
|
}
|
|
```
|
|
|
|
### Eredmények
|
|
|
|
Ezekkel a változtatásokkal a következő problémák lettek megoldva:
|
|
|
|
1. ✅ **Reconnect képesség**: A játékosok most már tudnak újra csatlakozni disconnect után anélkül, hogy újraindítanák a játékot
|
|
2. ✅ **Timeout problémák csökkentése**: A 15 másodperces timeout jelentősen csökkenti a "poor connection" üzeneteket
|
|
3. ✅ **Tiszta állapot**: Minden disconnect után teljesen kitisztított állapotból indul az új kapcsolódás
|
|
4. ✅ **Event handler stabilitás**: Az event handlerek most már nem vesznek el újrainicializálás során
|
|
5. ✅ **Jobb error handling**: Try-catch blokkok és részletes logging a problémák könnyebb diagnosztizálásához
|
|
|
|
### Korábbi javítások
|
|
|
|
#### Map szinkronizáció javítás (c4eb7e9)
|
|
- Javítva: A client-ek rossz map paraméterekkel generáltak világot
|
|
- Megoldás: WorldSeed packet most tartalmazza az összes szükséges map paramétert (size, type, rivers)
|
|
|
|
#### StartGame NullReferenceException javítás (fc467f4)
|
|
- Javítva: NullReferenceException a multiplayer játék indításakor
|
|
- Megoldás: Eltávolítva a MainMenuMode.StartGame() reflection hívás, közvetlen átmenet playing mode-ba
|
|
|
|
## Telepítés
|
|
|
|
1. Másold a mod fájljait a Kingdoms and Castles mod mappájába
|
|
2. Aktiváld a modot a játék mod menüjében
|
|
3. Indítsd újra a játékot
|
|
|
|
## Használat
|
|
|
|
### Server létrehozása
|
|
1. Főmenü -> Multiplayer
|
|
2. Create Server
|
|
3. Állítsd be a szerver beállításokat
|
|
4. Várd meg, hogy a játékosok csatlakozzanak
|
|
|
|
### Csatlakozás serverhez
|
|
1. Főmenü -> Multiplayer
|
|
2. Válaszd ki a servert a listából
|
|
3. Kattints a "Join" gombra
|
|
|
|
### Asset Bundle hibák javítása (2025-12-14)
|
|
|
|
#### Probléma
|
|
Ha az "serverbrowserpkg" asset bundle fájl hiányzik a mod könyvtárából, a mod NullReferenceException-öket dobott több helyen:
|
|
- PrefabManager.PreScriptLoad(): Crash az asset bundle betöltésekor
|
|
- ServerBrowser.SceneLoaded(): Crash amikor null prefab-okat próbált instantiate-lni
|
|
- Main.TransitionTo(): Crash amikor null UI referenciákat próbált elérni
|
|
|
|
#### Megoldások
|
|
|
|
**PrefabManager.cs:31-36**
|
|
- Null check az asset bundle betöltés után
|
|
- Ha az asset bundle null, részletes hibaüzenet és early return
|
|
- Egyértelmű útmutatás a felhasználónak
|
|
|
|
**ServerBrowser.cs:302-309**
|
|
- Prefab null check a SceneLoaded elején
|
|
- Ha a prefabok null-ok, részletes hibaüzenet és early return
|
|
- Megakadályozza a crash-t és informálja a felhasználót
|
|
|
|
**Main.cs:228-244**
|
|
- Null check minden UI referencia használata előtt
|
|
- Ha a felhasználó a multiplayer menüt próbálja megnyitni de az UI nincs betöltve:
|
|
- Részletes modal üzenet jelenik meg
|
|
- A játék nem crash-el
|
|
- Útmutatás a probléma megoldásához
|
|
|
|
**Érintett kód részletek:**
|
|
```csharp
|
|
// PrefabManager.cs
|
|
if (assetBundle == null)
|
|
{
|
|
Main.helper.Log("ERROR: Asset bundle 'serverbrowserpkg' not found! UI features will not work.");
|
|
Main.helper.Log("Please ensure the asset bundle file is in the mod directory.");
|
|
return;
|
|
}
|
|
|
|
// ServerBrowser.cs
|
|
if (PrefabManager.serverBrowserPrefab == null || PrefabManager.serverLobbyPrefab == null)
|
|
{
|
|
Main.helper.Log("ERROR: UI prefabs not loaded. Asset bundle is missing.");
|
|
return;
|
|
}
|
|
|
|
// Main.cs
|
|
if (ServerBrowser.serverBrowserRef != null && ServerBrowser.serverLobbyRef != null)
|
|
{
|
|
// Safe to use UI references
|
|
}
|
|
else if ((int)state > 21)
|
|
{
|
|
// Show error modal instead of crashing
|
|
ModalManager.ShowModal("Multiplayer Not Available", "...");
|
|
}
|
|
```
|
|
|
|
**ModalManager.cs:25-30, 55-59, 81-84**
|
|
- Null check a statikus konstruktorban a modalUIPrefab betöltés előtt
|
|
- Ha null, csak log-ol és visszatér gracefully
|
|
- ShowModal() ellenőrzi hogy modalInst létezik-e
|
|
- Ha nem, log-olja a modal tartalmát: "MODAL (not shown - UI missing): Title - Message"
|
|
- HideModal() null-safe lett
|
|
- Megakadályozza a TypeInitializationException-t
|
|
|
|
**Érintett kód részletek:**
|
|
```csharp
|
|
// ModalManager.cs statikus konstruktor
|
|
if (PrefabManager.modalUIPrefab == null)
|
|
{
|
|
Main.helper.Log("WARNING: ModalManager cannot initialize - modalUIPrefab is null");
|
|
instantiated = true;
|
|
return;
|
|
}
|
|
|
|
// ShowModal metódus
|
|
if (modalInst == null)
|
|
{
|
|
Main.helper.Log($"MODAL (not shown - UI missing): {title} - {message}");
|
|
return;
|
|
}
|
|
```
|
|
|
|
**Eredmények:**
|
|
- ✅ Nincs crash ha az asset bundle hiányzik
|
|
- ✅ Világos hibaüzenetek a felhasználónak
|
|
- ✅ Graceful degradation - a mod többi része működik
|
|
- ✅ Útmutatás a probléma megoldásához
|
|
- ✅ ModalManager biztonságosan hívható bárhonnan
|
|
- ✅ Modal üzenetek log-olva még ha nem is jelennek meg
|
|
|
|
**MEGJEGYZÉS:** Az asset bundle fájl jelenleg hiányzik a mod könyvtárából. A multiplayer UI funkciók működéséhez szükséges a "serverbrowserpkg" fájl hozzáadása.
|
|
|
|
## Ismert problémák
|
|
|
|
1. **Hiányzó Asset Bundle**: A "serverbrowserpkg" asset bundle fájl jelenleg hiányzik a mod könyvtárából. Ez azt jelenti, hogy:
|
|
- A multiplayer UI (Server Browser, Server Lobby) nem jelenik meg
|
|
- A Multiplayer gomb a főmenüben hibaüzenetet fog mutatni
|
|
- A mod többi része (connection handling, stb.) továbbra is működik
|
|
|
|
**Megoldás:** Helyezd el a "serverbrowserpkg" fájlt a mod gyökérkönyvtárába és indítsd újra a játékot.
|
|
|
|
Ha egyéb hibát találsz, kérlek jelentsd a fejlesztőknek.
|
|
|
|
## Fejlesztői megjegyzések
|
|
|
|
### Debugging
|
|
A mod részletes loggolást tartalmaz, amely segít a problémák diagnosztizálásában. A logok a következő helyeken jelennek meg:
|
|
- `[WORLD SYNC]` prefix: World generation szinkronizációs események
|
|
- `LeaveLobby called` - `Lobby cleanup completed`: Disconnect/cleanup folyamat
|
|
|
|
### Hozzájárulás
|
|
Ha szeretnél hozzájárulni a mod fejlesztéséhez, pull request-eket szívesen fogadunk!
|
|
|
|
## Licensz
|
|
|
|
Ez a mod a Riptide Networking library-t használja, amely MIT licensz alatt áll.
|