diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 8ea7123..f2af885 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -7,7 +7,9 @@ "Bash(git add:*)", "Bash(git commit:*)", "Bash(tail:*)", - "Bash(connection\", or \"server disconnected\" messages, and couldn''t reconnect \nwithout restarting the game. Game state wasn''t properly cleaned up \nafter disconnect.\n\nRoot causes:\n1. Static client/server objects never reinitialized after disconnect\n2. Event handlers lost when new client/server instances created\n3. Incomplete state cleanup after disconnect\n4. Short timeout values (5s) causing frequent disconnections\n\nSolutions:\n\nKCClient.cs:\n- Add InitializeClient() method that:\n * Cleans up old client instance\n * Disconnects existing connections\n * Unsubscribes from old event handlers\n * Creates fresh Client instance\n * Sets higher timeout (15s -> reduces timeouts by ~70%)\n * Re-subscribes to all event handlers\n- Connect() now reinitializes client before each connection attempt\n- Increased max connection attempts (5 -> 10)\n- Improved Client_Disconnected handler:\n * Clears clientSteamIds state\n * Distinguishes voluntary vs unexpected disconnects\n * Only shows error modal for unexpected disconnects\n\nKCServer.cs:\n- Add InitializeServer() method with same cleanup pattern\n- Extract event handlers to static methods (OnClientConnected, \n OnClientDisconnected) so they persist across server instances\n- StartServer() now reinitializes server for clean state\n- Add try-catch in OnClientDisconnected to prevent crashes\n- Set higher timeout (15s) to reduce disconnections\n\nLobbyManager.cs:\n- Complete rewrite of LeaveLobby() with:\n * Detailed logging for debugging\n * Null-safe checks for all operations\n * Try-catch wrapper for safe cleanup\n * Clears both kCPlayers and clientSteamIds\n * Resets all flags (loadingSave, registerServer)\n * Guarantees return to ServerBrowser even on errors\n\nResults:\n✅ Players can now reconnect without restarting game\n✅ ~70% reduction in timeout/poor connection messages\n✅ Clean state after every disconnect\n✅ Event handlers remain stable across reinitializations\n✅ Better error handling and logging for diagnostics\n\nAdded comprehensive README.md documenting:\n- All fixes with code examples\n- Previous fixes (map sync, StartGame NullRef)\n- Installation and usage instructions\n- Known issues section (currently none)\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)\n\nCo-Authored-By: Claude Sonnet 4.5 \nEOF\n)\")" + "Bash(connection\", or \"server disconnected\" messages, and couldn''t reconnect \nwithout restarting the game. Game state wasn''t properly cleaned up \nafter disconnect.\n\nRoot causes:\n1. Static client/server objects never reinitialized after disconnect\n2. Event handlers lost when new client/server instances created\n3. Incomplete state cleanup after disconnect\n4. Short timeout values (5s) causing frequent disconnections\n\nSolutions:\n\nKCClient.cs:\n- Add InitializeClient() method that:\n * Cleans up old client instance\n * Disconnects existing connections\n * Unsubscribes from old event handlers\n * Creates fresh Client instance\n * Sets higher timeout (15s -> reduces timeouts by ~70%)\n * Re-subscribes to all event handlers\n- Connect() now reinitializes client before each connection attempt\n- Increased max connection attempts (5 -> 10)\n- Improved Client_Disconnected handler:\n * Clears clientSteamIds state\n * Distinguishes voluntary vs unexpected disconnects\n * Only shows error modal for unexpected disconnects\n\nKCServer.cs:\n- Add InitializeServer() method with same cleanup pattern\n- Extract event handlers to static methods (OnClientConnected, \n OnClientDisconnected) so they persist across server instances\n- StartServer() now reinitializes server for clean state\n- Add try-catch in OnClientDisconnected to prevent crashes\n- Set higher timeout (15s) to reduce disconnections\n\nLobbyManager.cs:\n- Complete rewrite of LeaveLobby() with:\n * Detailed logging for debugging\n * Null-safe checks for all operations\n * Try-catch wrapper for safe cleanup\n * Clears both kCPlayers and clientSteamIds\n * Resets all flags (loadingSave, registerServer)\n * Guarantees return to ServerBrowser even on errors\n\nResults:\n✅ Players can now reconnect without restarting game\n✅ ~70% reduction in timeout/poor connection messages\n✅ Clean state after every disconnect\n✅ Event handlers remain stable across reinitializations\n✅ Better error handling and logging for diagnostics\n\nAdded comprehensive README.md documenting:\n- All fixes with code examples\n- Previous fixes (map sync, StartGame NullRef)\n- Installation and usage instructions\n- Known issues section (currently none)\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)\n\nCo-Authored-By: Claude Sonnet 4.5 \nEOF\n)\")", + "Bash(dir \"C:\\Program Files (x86)\\Steam\\steamapps\\workshop\\content\\569480\\3105755541\")", + "Bash(findstr:*)" ] } } diff --git a/Main.cs b/Main.cs index 261fb71..729b202 100644 --- a/Main.cs +++ b/Main.cs @@ -126,11 +126,6 @@ namespace KCM var lobbyManager = new GameObject("LobbyManager").AddComponent(); DontDestroyOnLoad(lobbyManager); - //SteamFriends.InviteUserToGame(new CSteamID(76561198036307537), "test"); - //SteamMatchmaking.lobby - - //Main.helper.Log($"Timer duration for hazardpay {Player.inst.hazardPayWarmup.Duration}"); - try { @@ -147,10 +142,7 @@ namespace KCM FirstSibling = true, OnClick = () => { - //Constants.MainMenuUI_T.Find("TopLevelUICanvas/TopLevel").gameObject.SetActive(false); SfxSystem.PlayUiSelect(); - - //ServerBrowser.serverBrowserRef.SetActive(true); TransitionTo(MenuState.ServerBrowser); } }; @@ -185,37 +177,6 @@ namespace KCM private void FixedUpdate() { - // send batched building placement info - /*if (PlaceHook.QueuedBuildings.Count > 0 && (FixedUpdateInterval % 25 == 0)) - { - foreach (Building building in PlaceHook.QueuedBuildings) - { - new WorldPlace() - { - uniqueName = building.UniqueName, - customName = building.customName, - guid = building.guid, - rotation = building.transform.GetChild(0).rotation, - globalPosition = building.transform.position, - localPosition = building.transform.GetChild(0).localPosition, - built = building.IsBuilt(), - placed = building.IsPlaced(), - open = building.Open, - doBuildAnimation = building.doBuildAnimation, - constructionPaused = building.constructionPaused, - constructionProgress = building.constructionProgress, - life = building.Life, - ModifiedMaxLife = building.ModifiedMaxLife, - //CollectForBuild = CollectForBuild, - yearBuilt = building.YearBuilt, - decayProtection = building.decayProtection, - seenByPlayer = building.seenByPlayer - }.Send(); - } - - PlaceHook.QueuedBuildings.Clear(); - }*/ - FixedUpdateInterval++; } @@ -224,11 +185,24 @@ namespace KCM { try { - ServerBrowser.serverBrowserRef.SetActive(state == MenuState.ServerBrowser); - ServerBrowser.serverLobbyRef.SetActive(state == MenuState.ServerLobby); + // Only interact with multiplayer UI if it was successfully created + if (ServerBrowser.serverBrowserRef != null && ServerBrowser.serverLobbyRef != null && ServerBrowser.KCMUICanvas != null) + { + ServerBrowser.serverBrowserRef.SetActive(state == MenuState.ServerBrowser); + ServerBrowser.serverLobbyRef.SetActive(state == MenuState.ServerLobby); - ServerBrowser.KCMUICanvas.gameObject.SetActive((int)state > 21); - helper.Log(((int)state > 21).ToString()); + ServerBrowser.KCMUICanvas.gameObject.SetActive((int)state > 21); + helper.Log(((int)state > 21).ToString()); + } + else if ((int)state > 21) + { + // User tried to access multiplayer menu but UI is not loaded + helper.Log("WARNING: Cannot transition to multiplayer menu - UI not loaded (asset bundle missing)"); + ModalManager.ShowModal("Multiplayer Not Available", + "The multiplayer UI could not be loaded. The asset bundle file is missing.\n\nPlease reinstall the mod or contact the developer.", + "OK"); + return; + } GameState.inst.mainMenuMode.TransitionTo((MainMenuMode.State)state); } @@ -258,9 +232,6 @@ namespace KCM helper.Log("Preload start in main"); try { - - - //MainMenuPatches.Patch(); Main.helper = helper; helper.Log(helper.modPath); diff --git a/PrefabManager.cs b/PrefabManager.cs index 083a765..ad5e1c1 100644 --- a/PrefabManager.cs +++ b/PrefabManager.cs @@ -28,12 +28,19 @@ namespace KCM assetBundle = KCModHelper.LoadAssetBundle(_helper.modPath, "serverbrowserpkg"); - Main.helper.Log(String.Join(", ", assetBundle.GetAllAssetNames())); + 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; + } + + Main.helper.Log("Asset bundle loaded successfully"); + Main.helper.Log("Assets in bundle: " + String.Join(", ", assetBundle.GetAllAssetNames())); serverBrowserPrefab = assetBundle.LoadAsset("assets/workspace/serverbrowser.prefab") as GameObject; serverEntryItemPrefab = assetBundle.LoadAsset("assets/workspace/serverentryitem.prefab") as GameObject; - serverLobbyPrefab = assetBundle.LoadAsset("assets/workspace/serverlobby.prefab") as GameObject; serverLobbyPlayerEntryPrefab = assetBundle.LoadAsset("assets/workspace/serverlobbyplayerentry.prefab") as GameObject; serverChatEntryPrefab = assetBundle.LoadAsset("assets/workspace/serverchatentry.prefab") as GameObject; @@ -41,10 +48,11 @@ namespace KCM modalUIPrefab = assetBundle.LoadAsset("assets/workspace/modalui.prefab") as GameObject; - Main.helper.Log("Loaded assets"); + Main.helper.Log("Loaded all UI prefabs successfully"); } catch (Exception ex) { + Main.helper.Log("ERROR loading asset bundle:"); Main.helper.Log(ex.ToString()); Main.helper.Log(ex.Message); Main.helper.Log(ex.StackTrace); diff --git a/README.md b/README.md index 7a0fa09..618f6b5 100644 --- a/README.md +++ b/README.md @@ -219,9 +219,80 @@ Ezekkel a változtatásokkal a következő problémák lettek megoldva: 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", "..."); +} +``` + +**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 + +**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 -Jelenleg nincsenek ismert kritikus problémák. Ha hibát találsz, kérlek jelentsd a fejlesztőknek. +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 diff --git a/ServerBrowser/ServerBrowser.cs b/ServerBrowser/ServerBrowser.cs index f37ebd8..d948961 100644 --- a/ServerBrowser/ServerBrowser.cs +++ b/ServerBrowser/ServerBrowser.cs @@ -299,6 +299,15 @@ namespace KCM try { + // Check if prefabs are loaded + if (PrefabManager.serverBrowserPrefab == null || PrefabManager.serverLobbyPrefab == null) + { + Main.helper.Log("ERROR: UI prefabs not loaded. Asset bundle is missing."); + Main.helper.Log("Multiplayer UI features will not be available."); + Main.helper.Log("Please ensure 'serverbrowserpkg' asset bundle is in the mod directory."); + return; + } + GameObject kcmUICanvas = Instantiate(Constants.MainMenuUI_T.Find("TopLevelUICanvas").gameObject); for (int i = 0; i < kcmUICanvas.transform.childCount; i++)