Compare commits
140 Commits
679c3c9a52
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 8b9c19186b | |||
| 99398b5479 | |||
| 270a92c617 | |||
| 4d8279719c | |||
| 3d5a53f0e2 | |||
| 25f5af0b4d | |||
| 2ad605138e | |||
| ca517be369 | |||
| df1def69e4 | |||
| db850885f6 | |||
| 71e1e09c75 | |||
| 46ebeb1f80 | |||
| 7d06145a34 | |||
| fcf1ffac76 | |||
| 40369ffe4b | |||
| fc089afcc0 | |||
| cb82d3706f | |||
| 12a207989e | |||
| 4afcaccf75 | |||
| 8f13282e04 | |||
| 0d7d989f76 | |||
| 1cc3042781 | |||
| 181936e3d4 | |||
| 62db70c1c4 | |||
| 36acbb57c5 | |||
| 76f1033bd2 | |||
| 26b5f1201e | |||
| 9ee675ac19 | |||
| 3124f82a2f | |||
| 3a7b81bfd7 | |||
| c4eb7e944d | |||
| 4057cf37c5 | |||
| fc467f4af8 | |||
| dbc0328c6f | |||
| 5f67f488f6 | |||
| b0f790cb6e | |||
| deb0c0ad92 | |||
| 10d20e29ad | |||
| a3409a2d5c | |||
| 5b0f957295 | |||
| faaedcc0fd | |||
| d87c12384e | |||
| 560a985323 | |||
| 490e0d74e6 | |||
| c4e25f6c12 | |||
| 6b014c72db | |||
| c6ca1abc54 | |||
| c3e79c9adf | |||
| dca0140aab | |||
| 55e3cd57e7 | |||
| 4685bc61c2 | |||
| 7a14303353 | |||
| a918262d99 | |||
| 87f65320c0 | |||
| 97bbf059a9 | |||
| aa6fb797c2 | |||
| 739eba8289 | |||
| 1e6f09df18 | |||
| 15cad47b52 | |||
| c074a86423 | |||
| 1035f06884 | |||
| b05c3415f2 | |||
| b02af4d0c7 | |||
| 5dba8137c3 | |||
| b3d7108574 | |||
| ce1c067fca | |||
| 5d086776cf | |||
| 89586ad8df | |||
| 8f3d83e807 | |||
| dd17030e56 | |||
| 8d599e13ad | |||
| eab7931f52 | |||
| 7d6c915b49 | |||
| f7fc5a3969 | |||
| 2f42cf9366 | |||
| 888c807b96 | |||
| bd12485112 | |||
| f03e13236f | |||
| 60d509344c | |||
| 121df60b57 | |||
| 3fbaac2346 | |||
| 0e87108b56 | |||
| 224ba3f912 | |||
| 5ebd94c03a | |||
| 914650c211 | |||
| 93c55dd482 | |||
| 414ab90afc | |||
| 42a86419ca | |||
| 2140fc3868 | |||
| 4a2c73badb | |||
| d6c0ec2a33 | |||
| 634a5f7983 | |||
| 77f4d4fed0 | |||
| 3ee6fc4dc6 | |||
| e0b1b736c3 | |||
| 28e342b1e3 | |||
| 4871f7c150 | |||
| 3dcb9a85b5 | |||
| e91ae0fc99 | |||
| 8edea198cd | |||
| f82ae76a3e | |||
| dc50bf2892 | |||
| e636ad6e19 | |||
| fbb947a23b | |||
| a2d87106ba | |||
| 0f8f3ce818 | |||
| 07c7e14cde | |||
| 0549ab0e19 | |||
| f45402af9a | |||
| 6bf74dda43 | |||
| 8ac2f2df1c | |||
| b351e0c707 | |||
| 0776da883f | |||
| cb6fd3a727 | |||
| 6a128a836d | |||
| 5fa2cc1c92 | |||
| a9c14c3adf | |||
| 7fc86a804a | |||
| 02af5c8c68 | |||
| c6c60a7e07 | |||
| 6e16be8646 | |||
| cb59d5a918 | |||
| efa6016fe5 | |||
| 0b16efc4be | |||
| e523122561 | |||
| 91a1ab4261 | |||
| fd0ebe9014 | |||
| 6117ac93f7 | |||
| 3d5ef1686a | |||
| e6208996f7 | |||
| 4ad7265875 | |||
| a88b3f155e | |||
| 1e49828385 | |||
| 7dd6fab39e | |||
| 6ce0df40ca | |||
| df3e319b62 | |||
| b934751afd | |||
| 13c6527215 | |||
| f199bbde65 | |||
| f3be3584db |
12
.claude/settings.local.json
Normal file
12
.claude/settings.local.json
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"permissions": {
|
||||||
|
"allow": [
|
||||||
|
"Bash(wc:*)",
|
||||||
|
"Bash(find:*)",
|
||||||
|
"Bash(ls:*)",
|
||||||
|
"Bash(git add:*)",
|
||||||
|
"Bash(git commit:*)",
|
||||||
|
"Bash(tail:*)"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
27
.gitignore
vendored
Normal file
27
.gitignore
vendored
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
# Logs / local debug output
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# OS junk
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
Desktop.ini
|
||||||
|
|
||||||
|
# Editor / IDE
|
||||||
|
.vs/
|
||||||
|
*.suo
|
||||||
|
*.user
|
||||||
|
*.userosscache
|
||||||
|
*.sln.docstates
|
||||||
|
*.VC.db
|
||||||
|
*.VC.VC.opendb
|
||||||
|
|
||||||
|
# Build artifacts (C#/Unity tooling)
|
||||||
|
**/bin/
|
||||||
|
**/obj/
|
||||||
|
**/*.mdb
|
||||||
|
**/*.pdb
|
||||||
|
|
||||||
|
/.claude
|
||||||
|
/*.png
|
||||||
|
/*.txt
|
||||||
|
/*.jpg
|
||||||
15
Constants.cs
15
Constants.cs
@@ -15,19 +15,20 @@ namespace KCM
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static class Constants
|
public static class Constants
|
||||||
{
|
{
|
||||||
public static readonly MainMenuMode MainMenuMode = GameState.inst.mainMenuMode;
|
// Use lazy initialization to avoid null reference when GameState isn't ready yet
|
||||||
public static readonly PlayingMode PlayingMode = GameState.inst.playingMode;
|
public static MainMenuMode MainMenuMode => GameState.inst?.mainMenuMode;
|
||||||
public static readonly World World = GameState.inst.world;
|
public static PlayingMode PlayingMode => GameState.inst?.playingMode;
|
||||||
|
public static World World => GameState.inst?.world;
|
||||||
|
|
||||||
#region "UI"
|
#region "UI"
|
||||||
public static readonly Transform MainMenuUI_T = MainMenuMode.mainMenuUI.transform;
|
public static Transform MainMenuUI_T => MainMenuMode?.mainMenuUI?.transform;
|
||||||
public static readonly GameObject MainMenuUI_O = MainMenuMode.mainMenuUI;
|
public static GameObject MainMenuUI_O => MainMenuMode?.mainMenuUI;
|
||||||
|
|
||||||
/* public static readonly Transform TopLevelUI_T = MainMenuUI_T.parent;
|
/* public static readonly Transform TopLevelUI_T = MainMenuUI_T.parent;
|
||||||
public static readonly GameObject TopLevelUI_O = MainMenuUI_T.parent.gameObject;*/
|
public static readonly GameObject TopLevelUI_O = MainMenuUI_T.parent.gameObject;*/
|
||||||
|
|
||||||
public static readonly Transform ChooseModeUI_T = MainMenuMode.chooseModeUI.transform;
|
public static Transform ChooseModeUI_T => MainMenuMode?.chooseModeUI?.transform;
|
||||||
public static readonly GameObject ChooseModeUI_O = MainMenuMode.chooseModeUI;
|
public static GameObject ChooseModeUI_O => MainMenuMode?.chooseModeUI;
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,
|
||||||
@@ -44,6 +41,7 @@ namespace KCM.Enums
|
|||||||
AddVillager = 88,
|
AddVillager = 88,
|
||||||
SetupInitialWorkers = 89,
|
SetupInitialWorkers = 89,
|
||||||
VillagerTeleportTo = 90,
|
VillagerTeleportTo = 90,
|
||||||
PlaceKeepRandomly = 91
|
PlaceKeepRandomly = 91,
|
||||||
|
BuildingRemove = 92
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ namespace KCM
|
|||||||
|
|
||||||
private static void Client_Disconnected(object sender, DisconnectedEventArgs e)
|
private static void Client_Disconnected(object sender, DisconnectedEventArgs e)
|
||||||
{
|
{
|
||||||
|
Main.CleanupMultiplayerSession();
|
||||||
Main.helper.Log("Client disconnected event start");
|
Main.helper.Log("Client disconnected event start");
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|||||||
174
Main.cs
174
Main.cs
@@ -57,7 +57,21 @@ namespace KCM
|
|||||||
|
|
||||||
public static KCPlayer GetPlayerByClientID(ushort clientId)
|
public static KCPlayer GetPlayerByClientID(ushort clientId)
|
||||||
{
|
{
|
||||||
return kCPlayers[clientSteamIds[clientId]];
|
if (TryGetPlayerByClientID(clientId, out KCPlayer player))
|
||||||
|
{
|
||||||
|
return player;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool TryGetPlayerByClientID(ushort clientId, out KCPlayer player)
|
||||||
|
{
|
||||||
|
player = null;
|
||||||
|
if (clientSteamIds.TryGetValue(clientId, out string steamId))
|
||||||
|
{
|
||||||
|
return kCPlayers.TryGetValue(steamId, out player);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Player GetPlayerByTeamID(int teamId) // Need to replace building / production types so that the correct player is used. IResourceStorage and IResourceProvider, and jobs
|
public static Player GetPlayerByTeamID(int teamId) // Need to replace building / production types so that the correct player is used. IResourceStorage and IResourceProvider, and jobs
|
||||||
@@ -106,11 +120,51 @@ namespace KCM
|
|||||||
public static string PlayerSteamID = SteamUser.GetSteamID().ToString();
|
public static string PlayerSteamID = SteamUser.GetSteamID().ToString();
|
||||||
|
|
||||||
public static KCMSteamManager KCMSteamManager = null;
|
public static KCMSteamManager KCMSteamManager = null;
|
||||||
|
public static LobbyManager lobbyManager = null;
|
||||||
public static SteamServer steamServer = new SteamServer();
|
public static SteamServer steamServer = new SteamServer();
|
||||||
public static Riptide.Transports.Steam.SteamClient steamClient = new Riptide.Transports.Steam.SteamClient(steamServer);
|
public static Riptide.Transports.Steam.SteamClient steamClient = new Riptide.Transports.Steam.SteamClient(steamServer);
|
||||||
|
|
||||||
public static ushort currentClient = 0;
|
public static ushort currentClient = 0;
|
||||||
|
|
||||||
|
public static void CleanupMultiplayerSession()
|
||||||
|
{
|
||||||
|
if (helper == null) return; // Avoid running if mod is not fully initialized
|
||||||
|
|
||||||
|
helper.Log("--- Starting Multiplayer Session Cleanup ---");
|
||||||
|
|
||||||
|
// Disconnect client
|
||||||
|
if (KCClient.client != null && KCClient.client.IsConnected)
|
||||||
|
{
|
||||||
|
helper.Log("Disconnecting client...");
|
||||||
|
KCClient.client.Disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop server
|
||||||
|
if (KCServer.server != null && KCServer.IsRunning)
|
||||||
|
{
|
||||||
|
helper.Log("Stopping server...");
|
||||||
|
KCServer.server.Stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear player lists
|
||||||
|
if (kCPlayers.Count > 0 || clientSteamIds.Count > 0)
|
||||||
|
{
|
||||||
|
helper.Log($"Clearing {kCPlayers.Count} KCPlayer entries and {clientSteamIds.Count} client steam IDs.");
|
||||||
|
kCPlayers.Clear();
|
||||||
|
clientSteamIds.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destroy persistent managers
|
||||||
|
if (lobbyManager != null)
|
||||||
|
{
|
||||||
|
helper.Log("Destroying LobbyManager.");
|
||||||
|
Destroy(lobbyManager.gameObject);
|
||||||
|
lobbyManager = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
helper.Log("--- Multiplayer Session Cleanup Finished ---");
|
||||||
|
}
|
||||||
|
|
||||||
#region "SceneLoaded"
|
#region "SceneLoaded"
|
||||||
private void SceneLoaded(KCModHelper helper)
|
private void SceneLoaded(KCModHelper helper)
|
||||||
{
|
{
|
||||||
@@ -123,14 +177,9 @@ namespace KCM
|
|||||||
KCMSteamManager = new GameObject("KCMSteamManager").AddComponent<KCMSteamManager>();
|
KCMSteamManager = new GameObject("KCMSteamManager").AddComponent<KCMSteamManager>();
|
||||||
DontDestroyOnLoad(KCMSteamManager);
|
DontDestroyOnLoad(KCMSteamManager);
|
||||||
|
|
||||||
var lobbyManager = new GameObject("LobbyManager").AddComponent<LobbyManager>();
|
lobbyManager = new GameObject("LobbyManager").AddComponent<LobbyManager>();
|
||||||
DontDestroyOnLoad(lobbyManager);
|
DontDestroyOnLoad(lobbyManager);
|
||||||
|
|
||||||
//SteamFriends.InviteUserToGame(new CSteamID(76561198036307537), "test");
|
|
||||||
//SteamMatchmaking.lobby
|
|
||||||
|
|
||||||
//Main.helper.Log($"Timer duration for hazardpay {Player.inst.hazardPayWarmup.Duration}");
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -140,24 +189,62 @@ namespace KCM
|
|||||||
|
|
||||||
Main.helper.Log(JsonConvert.SerializeObject(World.inst.mapSizeDefs, Formatting.Indented));
|
Main.helper.Log(JsonConvert.SerializeObject(World.inst.mapSizeDefs, Formatting.Indented));
|
||||||
|
|
||||||
KaC_Button serverBrowser = new KaC_Button(Constants.MainMenuUI_T.Find("TopLevelUICanvas/TopLevel/Body/ButtonContainer/New").parent)
|
// Check if MainMenuUI_T is available
|
||||||
|
if (Constants.MainMenuUI_T == null)
|
||||||
|
{
|
||||||
|
Main.helper.Log("MainMenuUI_T is null, cannot create Multiplayer button");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Debug: Log the UI structure to find the correct path
|
||||||
|
Main.helper.Log($"MainMenuUI_T name: {Constants.MainMenuUI_T.name}");
|
||||||
|
Main.helper.Log($"MainMenuUI_T children count: {Constants.MainMenuUI_T.childCount}");
|
||||||
|
for (int i = 0; i < Constants.MainMenuUI_T.childCount; i++)
|
||||||
|
{
|
||||||
|
var child = Constants.MainMenuUI_T.GetChild(i);
|
||||||
|
Main.helper.Log($" Child {i}: {child.name}");
|
||||||
|
for (int j = 0; j < child.childCount; j++)
|
||||||
|
{
|
||||||
|
Main.helper.Log($" SubChild {j}: {child.GetChild(j).name}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Correct path based on debug output: MainMenuUI -> TopLevelUICanvas -> TopLevel -> Body -> ButtonContainer -> New
|
||||||
|
var buttonContainer = Constants.MainMenuUI_T.Find("TopLevelUICanvas/TopLevel/Body/ButtonContainer/New");
|
||||||
|
if (buttonContainer == null)
|
||||||
|
{
|
||||||
|
Main.helper.Log("Button container not found at TopLevelUICanvas/TopLevel/Body/ButtonContainer/New");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Main.helper.Log($"Found button container at: {buttonContainer.name}");
|
||||||
|
|
||||||
|
var templateButton = buttonContainer.GetComponent<Button>();
|
||||||
|
if (templateButton == null)
|
||||||
|
{
|
||||||
|
Main.helper.Log("Template button on container is missing Button component.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
KaC_Button serverBrowser = new KaC_Button(templateButton, buttonContainer.parent)
|
||||||
{
|
{
|
||||||
Name = "Multiplayer",
|
Name = "Multiplayer",
|
||||||
Text = "Multiplayer",
|
Text = "Multiplayer",
|
||||||
FirstSibling = true,
|
FirstSibling = true,
|
||||||
OnClick = () =>
|
OnClick = () =>
|
||||||
{
|
{
|
||||||
//Constants.MainMenuUI_T.Find("TopLevelUICanvas/TopLevel").gameObject.SetActive(false);
|
Main.helper?.Log("Multiplayer button clicked");
|
||||||
SfxSystem.PlayUiSelect();
|
SfxSystem.PlayUiSelect();
|
||||||
|
|
||||||
//ServerBrowser.serverBrowserRef.SetActive(true);
|
|
||||||
TransitionTo(MenuState.ServerBrowser);
|
TransitionTo(MenuState.ServerBrowser);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
serverBrowser.Transform.SetSiblingIndex(2);
|
serverBrowser.Transform.SetSiblingIndex(2);
|
||||||
|
|
||||||
|
var kingdomShare = Constants.MainMenuUI_T.Find("TopLevelUICanvas/TopLevel/Body/ButtonContainer/Kingdom Share")
|
||||||
Destroy(Constants.MainMenuUI_T.Find("TopLevelUICanvas/TopLevel/Body/ButtonContainer/Kingdom Share").gameObject);
|
?? Constants.MainMenuUI_T.Find("MainMenu/TopLevel/Body/ButtonContainer/Kingdom Share");
|
||||||
|
if (kingdomShare != null)
|
||||||
|
{
|
||||||
|
Destroy(kingdomShare.gameObject);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -224,11 +311,22 @@ namespace KCM
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
ServerBrowser.serverBrowserRef.SetActive(state == MenuState.ServerBrowser);
|
// Null checks for ServerBrowser references
|
||||||
ServerBrowser.serverLobbyRef.SetActive(state == MenuState.ServerLobby);
|
if (ServerBrowser.serverBrowserRef != null)
|
||||||
|
ServerBrowser.serverBrowserRef.SetActive(state == MenuState.ServerBrowser);
|
||||||
|
|
||||||
ServerBrowser.KCMUICanvas.gameObject.SetActive((int)state > 21);
|
if (ServerBrowser.serverLobbyRef != null)
|
||||||
helper.Log(((int)state > 21).ToString());
|
ServerBrowser.serverLobbyRef.SetActive(state == MenuState.ServerLobby);
|
||||||
|
|
||||||
|
if (ServerBrowser.KCMUICanvas != null)
|
||||||
|
{
|
||||||
|
ServerBrowser.KCMUICanvas.gameObject.SetActive((int)state > 21);
|
||||||
|
if (state == MenuState.ServerBrowser)
|
||||||
|
{
|
||||||
|
Main.helper?.Log($"TransitionTo ServerBrowser: browserRef={(ServerBrowser.serverBrowserRef != null ? "ready" : "null")}, canvas={(ServerBrowser.KCMUICanvas != null ? "ready" : "null")}");
|
||||||
|
}
|
||||||
|
helper.Log(((int)state > 21).ToString());
|
||||||
|
}
|
||||||
|
|
||||||
GameState.inst.mainMenuMode.TransitionTo((MainMenuMode.State)state);
|
GameState.inst.mainMenuMode.TransitionTo((MainMenuMode.State)state);
|
||||||
}
|
}
|
||||||
@@ -258,9 +356,6 @@ namespace KCM
|
|||||||
helper.Log("Preload start in main");
|
helper.Log("Preload start in main");
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
//MainMenuPatches.Patch();
|
|
||||||
Main.helper = helper;
|
Main.helper = helper;
|
||||||
helper.Log(helper.modPath);
|
helper.Log(helper.modPath);
|
||||||
|
|
||||||
@@ -395,7 +490,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++)
|
||||||
@@ -1255,14 +1349,35 @@ namespace KCM
|
|||||||
{
|
{
|
||||||
Main.helper.Log("Attempting to load save from server");
|
Main.helper.Log("Attempting to load save from server");
|
||||||
|
|
||||||
using (MemoryStream ms = new MemoryStream(saveBytes))
|
try
|
||||||
{
|
{
|
||||||
BinaryFormatter bf = new BinaryFormatter();
|
using (MemoryStream ms = new MemoryStream(saveBytes))
|
||||||
bf.Binder = new MultiplayerSaveDeserializationBinder();
|
{
|
||||||
saveContainer = (MultiplayerSaveContainer)bf.Deserialize(ms);
|
BinaryFormatter bf = new BinaryFormatter();
|
||||||
|
bf.Binder = new MultiplayerSaveDeserializationBinder();
|
||||||
|
saveContainer = (MultiplayerSaveContainer)bf.Deserialize(ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
Main.helper.Log("Deserialize complete, calling Unpack...");
|
||||||
|
saveContainer.Unpack(null);
|
||||||
|
Main.helper.Log("Unpack complete!");
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Main.helper.Log("Error loading save from server");
|
||||||
|
Main.helper.Log(e.Message);
|
||||||
|
Main.helper.Log(e.StackTrace);
|
||||||
|
if (e.InnerException != null)
|
||||||
|
{
|
||||||
|
Main.helper.Log("Inner exception: " + e.InnerException.Message);
|
||||||
|
Main.helper.Log(e.InnerException.StackTrace);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
memoryStreamHook = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
memoryStreamHook = false;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1621,9 +1736,10 @@ namespace KCM
|
|||||||
__instance.JobCustomMaxEnabledFlag = new bool[World.inst.NumLandMasses][];
|
__instance.JobCustomMaxEnabledFlag = new bool[World.inst.NumLandMasses][];
|
||||||
for (int lm = 0; lm < World.inst.NumLandMasses; lm++)
|
for (int lm = 0; lm < World.inst.NumLandMasses; lm++)
|
||||||
{
|
{
|
||||||
__instance.JobFilledAvailable[lm] = new int[38];
|
int numJobTypes = p.JobFilledAvailable.data[lm].GetLength(0);
|
||||||
__instance.JobCustomMaxEnabledFlag[lm] = new bool[38];
|
__instance.JobFilledAvailable[lm] = new int[numJobTypes];
|
||||||
for (int n = 0; n < 38; n++)
|
__instance.JobCustomMaxEnabledFlag[lm] = new bool[numJobTypes];
|
||||||
|
for (int n = 0; n < numJobTypes; n++)
|
||||||
{
|
{
|
||||||
__instance.JobFilledAvailable[lm][n] = p.JobFilledAvailable.data[lm][n, 1];
|
__instance.JobFilledAvailable[lm][n] = p.JobFilledAvailable.data[lm][n, 1];
|
||||||
}
|
}
|
||||||
|
|||||||
91
Packets/Game/GameBuilding/BuildingRemovePacket.cs
Normal file
91
Packets/Game/GameBuilding/BuildingRemovePacket.cs
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace KCM.Packets.Game.GameBuilding
|
||||||
|
{
|
||||||
|
public class BuildingRemovePacket : Packet
|
||||||
|
{
|
||||||
|
public override ushort packetId => (ushort)KCM.Enums.Packets.BuildingRemove;
|
||||||
|
|
||||||
|
// Flag to prevent infinite loop when removing buildings from packet
|
||||||
|
public static bool isProcessingPacket = false;
|
||||||
|
|
||||||
|
public Guid guid { get; set; }
|
||||||
|
|
||||||
|
public override void HandlePacketClient()
|
||||||
|
{
|
||||||
|
if (clientId == KCClient.client.Id) return;
|
||||||
|
|
||||||
|
Main.helper.Log($"Received building remove packet for guid {guid} from {player.name}");
|
||||||
|
|
||||||
|
// Try to find the building in the player who owns it
|
||||||
|
Building building = player.inst.GetBuilding(guid);
|
||||||
|
|
||||||
|
if (building == null)
|
||||||
|
{
|
||||||
|
// Try to find it in any player's buildings
|
||||||
|
foreach (var kcp in Main.kCPlayers.Values)
|
||||||
|
{
|
||||||
|
building = kcp.inst.GetBuilding(guid);
|
||||||
|
if (building != null) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (building == null)
|
||||||
|
{
|
||||||
|
Main.helper.Log($"Building with guid {guid} not found on client, may already be removed.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Main.helper.Log($"Removing building {building.UniqueName} at {building.transform.position}");
|
||||||
|
|
||||||
|
// Set flag to prevent sending packet back
|
||||||
|
isProcessingPacket = true;
|
||||||
|
|
||||||
|
// Set Player.inst to the correct player for this building
|
||||||
|
// This ensures the removal modifies the correct player's job lists
|
||||||
|
Player originalPlayer = Player.inst;
|
||||||
|
Player correctPlayer = Main.GetPlayerByBuilding(building);
|
||||||
|
if (correctPlayer != null)
|
||||||
|
{
|
||||||
|
Player.inst = correctPlayer;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use reflection to call the Remove method from the game assembly
|
||||||
|
MethodInfo removeMethod = typeof(Building).GetMethod("Remove", BindingFlags.Public | BindingFlags.Instance);
|
||||||
|
if (removeMethod != null)
|
||||||
|
{
|
||||||
|
removeMethod.Invoke(building, null);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Fallback: destroy the building GameObject directly
|
||||||
|
Main.helper.Log("Remove method not found, using Destroy fallback");
|
||||||
|
building.destroyedWhileInPlay = true;
|
||||||
|
UnityEngine.Object.Destroy(building.gameObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Restore original Player.inst
|
||||||
|
Player.inst = originalPlayer;
|
||||||
|
isProcessingPacket = false;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
isProcessingPacket = false;
|
||||||
|
Main.helper.Log($"Error removing building: {e.Message}");
|
||||||
|
Main.helper.Log(e.StackTrace);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void HandlePacketServer()
|
||||||
|
{
|
||||||
|
// Forward the remove packet to all other clients
|
||||||
|
SendToAll(clientId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -4,6 +4,7 @@ using System.IO;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Riptide.Demos.Steam.PlayerHosted;
|
||||||
using static KCM.Main;
|
using static KCM.Main;
|
||||||
|
|
||||||
namespace KCM.Packets.Lobby
|
namespace KCM.Packets.Lobby
|
||||||
@@ -29,84 +30,90 @@ namespace KCM.Packets.Lobby
|
|||||||
|
|
||||||
public override void HandlePacketClient()
|
public override void HandlePacketClient()
|
||||||
{
|
{
|
||||||
float savePercent = (float)received / (float)saveSize;
|
// Initialize on first chunk OR if arrays aren't properly sized yet
|
||||||
|
// This handles out-of-order packet delivery
|
||||||
// Initialize saveData and chunksReceived on the first packet received
|
if (!loadingSave || saveData.Length != saveSize || chunksReceived.Length != totalChunks)
|
||||||
if (saveData.Length == 1)
|
|
||||||
{
|
{
|
||||||
|
Main.helper.Log($"Save Transfer initializing. saveSize={saveSize}, totalChunks={totalChunks}");
|
||||||
Main.helper.Log("Save Transfer started!");
|
|
||||||
loadingSave = true;
|
loadingSave = true;
|
||||||
|
|
||||||
ServerLobbyScript.LoadingSave.SetActive(true);
|
|
||||||
|
|
||||||
// save percentage
|
|
||||||
|
|
||||||
|
|
||||||
saveData = new byte[saveSize];
|
saveData = new byte[saveSize];
|
||||||
chunksReceived = new bool[totalChunks];
|
chunksReceived = new bool[totalChunks];
|
||||||
|
received = 0;
|
||||||
|
|
||||||
|
ServerLobbyScript.LoadingSave.SetActive(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Skip if we already received this chunk (duplicate packet)
|
||||||
|
if (chunksReceived[chunkId])
|
||||||
|
{
|
||||||
|
Main.helper.Log($"[SaveTransfer] Duplicate chunk {chunkId} received, skipping.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Copy the chunk data into the correct position in saveData
|
|
||||||
Array.Copy(saveDataChunk, 0, saveData, saveDataIndex, saveDataChunk.Length);
|
Array.Copy(saveDataChunk, 0, saveData, saveDataIndex, saveDataChunk.Length);
|
||||||
|
|
||||||
// Mark this chunk as received
|
|
||||||
chunksReceived[chunkId] = true;
|
chunksReceived[chunkId] = true;
|
||||||
|
|
||||||
// Seek to the next position to write to
|
|
||||||
received += chunkSize;
|
received += chunkSize;
|
||||||
|
|
||||||
|
Main.helper.Log($"[SaveTransfer] Processed chunk {chunkId}/{totalChunks}. Received: {received} bytes of {saveSize}.");
|
||||||
|
|
||||||
ServerLobbyScript.ProgressBar.fillAmount = savePercent;
|
// Update progress bar
|
||||||
ServerLobbyScript.ProgressBarText.text = (savePercent * 100).ToString("0.00") + "%";
|
if (saveSize > 0)
|
||||||
ServerLobbyScript.ProgressText.text = $"{((float)(received / 1000)).ToString("0.00")} KB / {((float)(saveSize / 1000)).ToString("0.00")} KB";
|
|
||||||
|
|
||||||
|
|
||||||
if (chunkId + 1 == totalChunks)
|
|
||||||
{
|
{
|
||||||
Main.helper.Log($"Received last save transfer packet.");
|
float savePercent = (float)received / (float)saveSize;
|
||||||
|
string receivedKB = ((float)received / 1000f).ToString("0.00");
|
||||||
|
string totalKB = ((float)saveSize / 1000f).ToString("0.00");
|
||||||
|
|
||||||
Main.helper.Log(WhichIsNotComplete());
|
ServerLobbyScript.ProgressBar.fillAmount = savePercent;
|
||||||
|
ServerLobbyScript.ProgressBarText.text = (savePercent * 100).ToString("0.00") + "%";
|
||||||
|
ServerLobbyScript.ProgressText.text = $"{receivedKB} KB / {totalKB} KB";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ServerLobbyScript.ProgressBar.fillAmount = 0f;
|
||||||
|
ServerLobbyScript.ProgressBarText.text = "0.00%";
|
||||||
|
ServerLobbyScript.ProgressText.text = "0.00 KB / 0.00 KB";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if all chunks have been received
|
|
||||||
if (IsTransferComplete())
|
if (IsTransferComplete())
|
||||||
{
|
{
|
||||||
// Handle completed transfer here
|
|
||||||
Main.helper.Log("Save Transfer complete!");
|
Main.helper.Log("Save Transfer complete!");
|
||||||
|
|
||||||
|
// Reset the loading state before processing
|
||||||
|
loadingSave = false;
|
||||||
|
|
||||||
LoadSaveLoadHook.saveBytes = saveData;
|
LoadSaveLoadHook.saveBytes = saveData;
|
||||||
LoadSaveLoadHook.memoryStreamHook = true;
|
LoadSaveLoadHook.memoryStreamHook = true;
|
||||||
|
|
||||||
LoadSave.Load();
|
LoadSave.Load();
|
||||||
|
|
||||||
|
GameState.inst.SetNewMode(GameState.inst.playingMode);
|
||||||
|
LobbyManager.loadingSave = false;
|
||||||
|
|
||||||
LoadSaveLoadHook.saveContainer.Unpack(null);
|
|
||||||
Broadcast.OnLoadedEvent.Broadcast(new OnLoadedEvent());
|
Broadcast.OnLoadedEvent.Broadcast(new OnLoadedEvent());
|
||||||
|
|
||||||
ServerLobbyScript.LoadingSave.SetActive(false);
|
ServerLobbyScript.LoadingSave.SetActive(false);
|
||||||
|
|
||||||
|
// Reset static state for next transfer
|
||||||
|
ResetTransferState();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void ResetTransferState()
|
||||||
|
{
|
||||||
|
saveData = new byte[1];
|
||||||
|
chunksReceived = new bool[1];
|
||||||
|
loadingSave = false;
|
||||||
|
received = 0;
|
||||||
|
}
|
||||||
|
|
||||||
public static bool IsTransferComplete()
|
public static bool IsTransferComplete()
|
||||||
{
|
{
|
||||||
return chunksReceived.All(x => x == true);
|
return chunksReceived.All(x => x == true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string WhichIsNotComplete()
|
|
||||||
{
|
|
||||||
string notComplete = "";
|
|
||||||
for (int i = 0; i < chunksReceived.Length; i++)
|
|
||||||
{
|
|
||||||
if (!chunksReceived[i])
|
|
||||||
{
|
|
||||||
notComplete += i + ", ";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return notComplete;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void HandlePacketServer()
|
public override void HandlePacketServer()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,38 +18,26 @@ namespace KCM.Packets.Lobby
|
|||||||
{
|
{
|
||||||
Main.helper.Log(GameState.inst.mainMenuMode.ToString());
|
Main.helper.Log(GameState.inst.mainMenuMode.ToString());
|
||||||
|
|
||||||
// Hide server lobby
|
|
||||||
Main.TransitionTo((MenuState)200);
|
Main.TransitionTo((MenuState)200);
|
||||||
|
|
||||||
// This is run when user clicks "accept" on choose your map screeen
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (!LobbyManager.loadingSave)
|
SpeedControlUI.inst.SetSpeed(0);
|
||||||
{
|
|
||||||
SpeedControlUI.inst.SetSpeed(0);
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
|
||||||
typeof(MainMenuMode).GetMethod("StartGame", BindingFlags.NonPublic | BindingFlags.Instance).Invoke(GameState.inst.mainMenuMode, null);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Main.helper.Log(ex.Message.ToString());
|
|
||||||
Main.helper.Log(ex.ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
SpeedControlUI.inst.SetSpeed(0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
LobbyManager.loadingSave = false;
|
typeof(MainMenuMode).GetMethod("StartGame", BindingFlags.NonPublic | BindingFlags.Instance).Invoke(GameState.inst.mainMenuMode, null);
|
||||||
GameState.inst.SetNewMode(GameState.inst.playingMode);
|
|
||||||
}
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Main.helper.Log(ex.Message.ToString());
|
||||||
|
Main.helper.Log(ex.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
SpeedControlUI.inst.SetSpeed(0);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
// Handle exception here
|
|
||||||
Main.helper.Log(ex.Message.ToString());
|
Main.helper.Log(ex.Message.ToString());
|
||||||
Main.helper.Log(ex.ToString());
|
Main.helper.Log(ex.ToString());
|
||||||
}
|
}
|
||||||
@@ -57,47 +45,18 @@ namespace KCM.Packets.Lobby
|
|||||||
|
|
||||||
public override void HandlePacketClient()
|
public override void HandlePacketClient()
|
||||||
{
|
{
|
||||||
Start();
|
if (!LobbyManager.loadingSave)
|
||||||
|
{
|
||||||
|
Start();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ServerLobbyScript.LoadingSave.SetActive(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void HandlePacketServer()
|
public override void HandlePacketServer()
|
||||||
{
|
{
|
||||||
//Start();
|
|
||||||
|
|
||||||
|
|
||||||
/*AIBrainsContainer.PreStartAIConfig aiConfig = new AIBrainsContainer.PreStartAIConfig();
|
|
||||||
int count = 0;
|
|
||||||
for (int i = 0; i < RivalKingdomSettingsUI.inst.rivalItems.Length; i++)
|
|
||||||
{
|
|
||||||
RivalItemUI r = RivalKingdomSettingsUI.inst.rivalItems[i];
|
|
||||||
bool flag = r.Enabled && !r.Locked;
|
|
||||||
if (flag)
|
|
||||||
{
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
int idx = 0;
|
|
||||||
aiConfig.startData = new AIBrainsContainer.PreStartAIConfig.AIStartData[count];
|
|
||||||
for (int j = 0; j < RivalKingdomSettingsUI.inst.rivalItems.Length; j++)
|
|
||||||
{
|
|
||||||
RivalItemUI item = RivalKingdomSettingsUI.inst.rivalItems[j];
|
|
||||||
bool flag2 = item.Enabled && !item.Locked;
|
|
||||||
if (flag2)
|
|
||||||
{
|
|
||||||
aiConfig.startData[idx] = new AIBrainsContainer.PreStartAIConfig.AIStartData();
|
|
||||||
aiConfig.startData[idx].landmass = item.flag.landmass;
|
|
||||||
aiConfig.startData[idx].bioCode = item.bannerIdx;
|
|
||||||
aiConfig.startData[idx].personalityKey = PersonalityCollection.aiPersonalityKeys[0];
|
|
||||||
aiConfig.startData[idx].skillLevel = item.GetSkillLevel();
|
|
||||||
idx++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
AIBrainsContainer.inst.aiStartInfo = aiConfig;
|
|
||||||
bool isControllerActive = GamepadControl.inst.isControllerActive;
|
|
||||||
if (isControllerActive)
|
|
||||||
{
|
|
||||||
ConsoleCursorMenu.inst.PrepForGamepad();
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -99,10 +99,7 @@ namespace KCM.Packets.Network
|
|||||||
chunkSize = chunk.Length,
|
chunkSize = chunk.Length,
|
||||||
saveDataIndex = sent,
|
saveDataIndex = sent,
|
||||||
totalChunks = chunks.Count
|
totalChunks = chunks.Count
|
||||||
}.Send(clientId);
|
}.SendReliable(clientId);
|
||||||
|
|
||||||
Main.helper.Log(" ");
|
|
||||||
|
|
||||||
packetsSent++;
|
packetsSent++;
|
||||||
sent += chunk.Length;
|
sent += chunk.Length;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,9 +20,6 @@ namespace KCM.Packets
|
|||||||
|
|
||||||
if (!Main.clientSteamIds.ContainsKey(clientId))
|
if (!Main.clientSteamIds.ContainsKey(clientId))
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
//Main.helper.Log($"SteamID: {Main.GetPlayerByClientID(clientId).steamId} for {clientId} ({Main.GetPlayerByClientID(clientId).id})");
|
|
||||||
|
|
||||||
if (Main.kCPlayers.TryGetValue(Main.GetPlayerByClientID(clientId).steamId, out p))
|
if (Main.kCPlayers.TryGetValue(Main.GetPlayerByClientID(clientId).steamId, out p))
|
||||||
return p;
|
return p;
|
||||||
else
|
else
|
||||||
@@ -107,6 +104,37 @@ namespace KCM.Packets
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SendReliable(ushort toClient)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (KCServer.IsRunning && toClient != 0)
|
||||||
|
{
|
||||||
|
KCServer.server.Send(PacketHandler.SerialisePacket(this), toClient, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Main.helper.Log($"Error sending reliable packet {packetId} {this.GetType().Name} from {clientId}");
|
||||||
|
|
||||||
|
Main.helper.Log("----------------------- Main exception -----------------------");
|
||||||
|
Main.helper.Log(ex.ToString());
|
||||||
|
Main.helper.Log("----------------------- Main message -----------------------");
|
||||||
|
Main.helper.Log(ex.Message);
|
||||||
|
Main.helper.Log("----------------------- Main stacktrace -----------------------");
|
||||||
|
Main.helper.Log(ex.StackTrace);
|
||||||
|
if (ex.InnerException != null)
|
||||||
|
{
|
||||||
|
Main.helper.Log("----------------------- Inner exception -----------------------");
|
||||||
|
Main.helper.Log(ex.InnerException.ToString());
|
||||||
|
Main.helper.Log("----------------------- Inner message -----------------------");
|
||||||
|
Main.helper.Log(ex.InnerException.Message);
|
||||||
|
Main.helper.Log("----------------------- Inner stacktrace -----------------------");
|
||||||
|
Main.helper.Log(ex.InnerException.StackTrace);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public abstract void HandlePacketServer();
|
public abstract void HandlePacketServer();
|
||||||
public abstract void HandlePacketClient();
|
public abstract void HandlePacketClient();
|
||||||
}
|
}
|
||||||
|
|||||||
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.
|
||||||
@@ -299,13 +299,35 @@ namespace KCM
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
GameObject kcmUICanvas = Instantiate(Constants.MainMenuUI_T.Find("TopLevelUICanvas").gameObject);
|
if (Constants.MainMenuUI_T == null)
|
||||||
|
{
|
||||||
|
Main.helper.Log("MainMenuUI_T is null in ServerBrowser");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var topLevelCanvas = ResolveMenuCanvas();
|
||||||
|
if (topLevelCanvas == null)
|
||||||
|
{
|
||||||
|
Main.helper.Log("Failed to resolve top-level menu canvas in ServerBrowser");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GameObject kcmUICanvas = Instantiate(topLevelCanvas.gameObject);
|
||||||
|
|
||||||
for (int i = 0; i < kcmUICanvas.transform.childCount; i++)
|
for (int i = 0; i < kcmUICanvas.transform.childCount; i++)
|
||||||
Destroy(kcmUICanvas.transform.GetChild(i).gameObject);
|
Destroy(kcmUICanvas.transform.GetChild(i).gameObject);
|
||||||
|
|
||||||
kcmUICanvas.name = "KCMUICanvas";
|
kcmUICanvas.name = "KCMUICanvas";
|
||||||
kcmUICanvas.transform.SetParent(Constants.MainMenuUI_T);
|
kcmUICanvas.transform.SetParent(Constants.MainMenuUI_T, false);
|
||||||
|
kcmUICanvas.transform.SetAsLastSibling();
|
||||||
|
kcmUICanvas.SetActive(false);
|
||||||
|
|
||||||
|
var canvasComponent = kcmUICanvas.GetComponent<Canvas>();
|
||||||
|
if (canvasComponent != null)
|
||||||
|
{
|
||||||
|
canvasComponent.overrideSorting = true;
|
||||||
|
canvasComponent.sortingOrder = 999;
|
||||||
|
}
|
||||||
|
|
||||||
KCMUICanvas = kcmUICanvas.transform;
|
KCMUICanvas = kcmUICanvas.transform;
|
||||||
|
|
||||||
@@ -322,6 +344,8 @@ namespace KCM
|
|||||||
serverLobbyPlayerRef = serverLobbyRef.transform.Find("Container/PlayerList/Viewport/Content");
|
serverLobbyPlayerRef = serverLobbyRef.transform.Find("Container/PlayerList/Viewport/Content");
|
||||||
serverLobbyChatRef = serverLobbyRef.transform.Find("Container/PlayerChat/Viewport/Content");
|
serverLobbyChatRef = serverLobbyRef.transform.Find("Container/PlayerChat/Viewport/Content");
|
||||||
serverLobbyRef.SetActive(false);
|
serverLobbyRef.SetActive(false);
|
||||||
|
serverBrowserRef.transform.SetAsLastSibling();
|
||||||
|
serverLobbyRef.transform.SetAsLastSibling();
|
||||||
//browser.transform.position = new Vector3(0, 0, 0);
|
//browser.transform.position = new Vector3(0, 0, 0);
|
||||||
|
|
||||||
|
|
||||||
@@ -435,6 +459,29 @@ namespace KCM
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Transform ResolveMenuCanvas()
|
||||||
|
{
|
||||||
|
string[] candidatePaths =
|
||||||
|
{
|
||||||
|
"TopLevelUICanvas",
|
||||||
|
"TopLevel",
|
||||||
|
"MainMenu/TopLevel/TopLevelUICanvas",
|
||||||
|
"MainMenu/TopLevel"
|
||||||
|
};
|
||||||
|
|
||||||
|
foreach (var path in candidatePaths)
|
||||||
|
{
|
||||||
|
var transform = Constants.MainMenuUI_T.Find(path);
|
||||||
|
if (transform != null)
|
||||||
|
{
|
||||||
|
Main.helper.Log($"ServerBrowser: using canvas path '{path}'.");
|
||||||
|
return transform;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
private void Preload(KCModHelper helper)
|
private void Preload(KCModHelper helper)
|
||||||
{
|
{
|
||||||
helper.Log("Hello?");
|
helper.Log("Hello?");
|
||||||
|
|||||||
@@ -21,12 +21,12 @@ namespace KCM.ServerLobby
|
|||||||
|
|
||||||
public void Start()
|
public void Start()
|
||||||
{
|
{
|
||||||
|
banner = transform.Find("PlayerBanner").GetComponent<RawImage>();
|
||||||
|
|
||||||
SetValues();
|
SetValues();
|
||||||
|
|
||||||
InvokeRepeating("SetValues", 0, 0.25f);
|
InvokeRepeating("SetValues", 0, 0.25f);
|
||||||
|
|
||||||
banner = transform.Find("PlayerBanner").GetComponent<RawImage>();
|
|
||||||
|
|
||||||
transform.Find("PlayerBanner").GetComponent<Button>().onClick.AddListener(() =>
|
transform.Find("PlayerBanner").GetComponent<Button>().onClick.AddListener(() =>
|
||||||
{
|
{
|
||||||
Main.TransitionTo(MenuState.NameAndBanner);//ChooseBannerUI Hooks required, as well as townnameui
|
Main.TransitionTo(MenuState.NameAndBanner);//ChooseBannerUI Hooks required, as well as townnameui
|
||||||
@@ -37,13 +37,20 @@ namespace KCM.ServerLobby
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
KCPlayer player;
|
// First check if the client still exists
|
||||||
Main.kCPlayers.TryGetValue(Main.GetPlayerByClientID(Client).steamId, out player);
|
if (!Main.TryGetPlayerByClientID(Client, out KCPlayer player) || player == null)
|
||||||
|
{
|
||||||
|
// Client no longer exists, stop the repeating invoke and destroy this entry
|
||||||
|
CancelInvoke("SetValues");
|
||||||
|
Destroy(gameObject);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
transform.Find("PlayerName").GetComponent<TextMeshProUGUI>().text = player.name;
|
transform.Find("PlayerName").GetComponent<TextMeshProUGUI>().text = player.name;
|
||||||
transform.Find("Ready").gameObject.SetActive(player.ready);
|
transform.Find("Ready").gameObject.SetActive(player.ready);
|
||||||
|
|
||||||
var bannerTexture = World.inst.liverySets[player.banner].banners;
|
var bannerTexture = World.inst.liverySets[player.banner].banners;
|
||||||
|
|
||||||
banner.texture = bannerTexture;
|
banner.texture = bannerTexture;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|||||||
@@ -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");
|
||||||
@@ -144,7 +142,6 @@ namespace KCM
|
|||||||
{
|
{
|
||||||
|
|
||||||
Main.helper.Log("Disable all");
|
Main.helper.Log("Disable all");
|
||||||
//StartGameButton.gameObject.SetActive(false);
|
|
||||||
StartGameButton.onClick.RemoveAllListeners();
|
StartGameButton.onClick.RemoveAllListeners();
|
||||||
StartGameButton.GetComponentInChildren<TextMeshProUGUI>().text = "Ready";
|
StartGameButton.GetComponentInChildren<TextMeshProUGUI>().text = "Ready";
|
||||||
StartGameButton.onClick.AddListener(() =>
|
StartGameButton.onClick.AddListener(() =>
|
||||||
@@ -189,6 +186,32 @@ namespace KCM
|
|||||||
StartGameButton.GetComponentInChildren<TextMeshProUGUI>().text = "Start";
|
StartGameButton.GetComponentInChildren<TextMeshProUGUI>().text = "Start";
|
||||||
StartGameButton.onClick.AddListener(() =>
|
StartGameButton.onClick.AddListener(() =>
|
||||||
{
|
{
|
||||||
|
int definitiveSeed;
|
||||||
|
if (string.IsNullOrWhiteSpace(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.Log($"Invalid seed '{WorldSeed.text}' entered. Generating a random seed.");
|
||||||
|
World.inst.Generate();
|
||||||
|
definitiveSeed = World.inst.seed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
new WorldSeed()
|
||||||
|
{
|
||||||
|
Seed = definitiveSeed
|
||||||
|
}.SendToAll(KCClient.client.Id);
|
||||||
|
|
||||||
new StartGame().SendToAll();
|
new StartGame().SendToAll();
|
||||||
|
|
||||||
if (PlacementType.value == 0 && !LobbyManager.loadingSave)
|
if (PlacementType.value == 0 && !LobbyManager.loadingSave)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using KCM.Packets;
|
using KCM.Packets;
|
||||||
using KCM.Packets.State;
|
using KCM.Packets.State;
|
||||||
using KCM.StateManagement.Observers;
|
using KCM.StateManagement.Observers;
|
||||||
using System;
|
using System;
|
||||||
@@ -6,12 +6,15 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using UnityEngine;
|
||||||
using static KCM.StateManagement.Observers.Observer;
|
using static KCM.StateManagement.Observers.Observer;
|
||||||
|
|
||||||
namespace KCM.StateManagement.BuildingState
|
namespace KCM.StateManagement.BuildingState
|
||||||
{
|
{
|
||||||
public class BuildingStateManager
|
public class BuildingStateManager
|
||||||
{
|
{
|
||||||
|
private static readonly Dictionary<Guid, float> lastUpdateTime = new Dictionary<Guid, float>();
|
||||||
|
private const float UpdateInterval = 0.1f; // 10 times per second
|
||||||
|
|
||||||
public static void BuildingStateChanged(object sender, StateUpdateEventArgs args)
|
public static void BuildingStateChanged(object sender, StateUpdateEventArgs args)
|
||||||
{
|
{
|
||||||
@@ -23,9 +26,29 @@ namespace KCM.StateManagement.BuildingState
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
Observer observer = (Observer)sender;
|
Observer observer = (Observer)sender;
|
||||||
|
|
||||||
Building building = (Building)observer.state;
|
Building building = (Building)observer.state;
|
||||||
|
|
||||||
|
if (building == null)
|
||||||
|
{
|
||||||
|
if(observer != null)
|
||||||
|
{
|
||||||
|
UnityEngine.Object.Destroy(observer.gameObject);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Guid guid = building.guid;
|
||||||
|
|
||||||
|
if (lastUpdateTime.ContainsKey(guid) && Time.time < lastUpdateTime[guid] + UpdateInterval)
|
||||||
|
{
|
||||||
|
return; // Not time to update yet
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!lastUpdateTime.ContainsKey(guid))
|
||||||
|
lastUpdateTime.Add(guid, Time.time);
|
||||||
|
else
|
||||||
|
lastUpdateTime[guid] = Time.time;
|
||||||
|
|
||||||
//Main.helper.Log("Should send building network update for: " + building.UniqueName);
|
//Main.helper.Log("Should send building network update for: " + building.UniqueName);
|
||||||
|
|
||||||
new BuildingStatePacket()
|
new BuildingStatePacket()
|
||||||
@@ -57,4 +80,4 @@ namespace KCM.StateManagement.BuildingState
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -15,6 +15,11 @@ namespace KCM.UI
|
|||||||
class KaC_Button
|
class KaC_Button
|
||||||
{
|
{
|
||||||
public Button Button = null;
|
public Button Button = null;
|
||||||
|
private static readonly string[] ButtonPaths =
|
||||||
|
{
|
||||||
|
"TopLevelUICanvas/TopLevel/Body/ButtonContainer/New",
|
||||||
|
"MainMenu/TopLevel/Body/ButtonContainer/New" // fallback for older versions
|
||||||
|
};
|
||||||
|
|
||||||
public string Name
|
public string Name
|
||||||
{
|
{
|
||||||
@@ -84,14 +89,18 @@ namespace KCM.UI
|
|||||||
set => Transform.SetSiblingIndex(value);
|
set => Transform.SetSiblingIndex(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public KaC_Button(Transform parent = null)
|
public KaC_Button(Transform parent = null) : this(null, parent) { }
|
||||||
{
|
|
||||||
Button b = Constants.MainMenuUI_T.Find("TopLevelUICanvas/TopLevel/Body/ButtonContainer/New").GetComponent<Button>();
|
|
||||||
|
|
||||||
if (parent == null)
|
public KaC_Button(Button b, Transform parent = null)
|
||||||
Button = GameObject.Instantiate(b);
|
{
|
||||||
else
|
var templateButton = ResolveTemplateButton(b);
|
||||||
Button = GameObject.Instantiate(b, parent);
|
|
||||||
|
if (templateButton == null)
|
||||||
|
throw new InvalidOperationException("Template button not found in main menu UI.");
|
||||||
|
|
||||||
|
Button = parent == null
|
||||||
|
? GameObject.Instantiate(templateButton)
|
||||||
|
: GameObject.Instantiate(templateButton, parent);
|
||||||
|
|
||||||
foreach (Localize Localize in Button.GetComponentsInChildren<Localize>())
|
foreach (Localize Localize in Button.GetComponentsInChildren<Localize>())
|
||||||
GameObject.Destroy(Localize);
|
GameObject.Destroy(Localize);
|
||||||
@@ -99,20 +108,27 @@ namespace KCM.UI
|
|||||||
Button.onClick = new Button.ButtonClickedEvent();
|
Button.onClick = new Button.ButtonClickedEvent();
|
||||||
}
|
}
|
||||||
|
|
||||||
public KaC_Button(Button b, Transform parent = null)
|
private static Button ResolveTemplateButton(Button providedButton)
|
||||||
{
|
{
|
||||||
if (b == null)
|
if (providedButton != null)
|
||||||
b = Constants.MainMenuUI_T.Find("TopLevelUICanvas/TopLevel/Body/ButtonContainer/New").GetComponent<Button>();
|
return providedButton;
|
||||||
|
|
||||||
if (parent == null)
|
foreach (var path in ButtonPaths)
|
||||||
Button = GameObject.Instantiate(b);
|
{
|
||||||
else
|
var transform = Constants.MainMenuUI_T?.Find(path);
|
||||||
Button = GameObject.Instantiate(b, parent);
|
if (transform == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
foreach (Localize Localize in Button.GetComponentsInChildren<Localize>())
|
var button = transform.GetComponent<Button>();
|
||||||
GameObject.Destroy(Localize);
|
if (button != null)
|
||||||
|
{
|
||||||
|
Main.helper?.Log($"Using menu button template at '{path}'.");
|
||||||
|
return button;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Button.onClick = new Button.ButtonClickedEvent();
|
Main.helper?.Log("Failed to find menu button template for KaC_Button.");
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
|
|||||||
@@ -1,311 +0,0 @@
|
|||||||
2024-04-17T18:31:45:SENDING PLACE KEEP RANDOMLY FOR Shadowfita ON LANDMASS: 0
|
|
||||||
2024-04-17T18:31:45:SENDING PLACE KEEP RANDOMLY FOR MUFFINMAN ON LANDMASS: 2
|
|
||||||
2024-04-17T18:31:45:GameState (MainMenuMode)
|
|
||||||
2024-04-17T18:31:45:True
|
|
||||||
2024-04-17T18:31:45:Menu set to: 200
|
|
||||||
2024-04-17T18:31:45:Exception has been thrown by the target of an invocation.
|
|
||||||
2024-04-17T18:31:45:System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.NullReferenceException: Object reference not set to an instance of an object
|
|
||||||
at MainMenuMode.StartGame () [0x000ae] in <64d48a4605b74315afc90e0d3d75aed0>:0
|
|
||||||
at (wrapper managed-to-native) System.Reflection.MonoMethod.InternalInvoke(System.Reflection.MonoMethod,object,object[],System.Exception&)
|
|
||||||
at System.Reflection.MonoMethod.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00032] in <eae584ce26bc40229c1b1aa476bfa589>:0
|
|
||||||
--- End of inner exception stack trace ---
|
|
||||||
at System.Reflection.MonoMethod.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00048] in <eae584ce26bc40229c1b1aa476bfa589>:0
|
|
||||||
at System.Reflection.MethodBase.Invoke (System.Object obj, System.Object[] parameters) [0x00000] in <eae584ce26bc40229c1b1aa476bfa589>:0
|
|
||||||
at KCM.Packets.Lobby.StartGame.Start () [0x00058] in <9248c2b646c04c27b08155cb9b937ba4>:0
|
|
||||||
2024-04-17T18:31:45:Last 9 methods in call tree: Update -> HandleMessages -> Handle -> OnMessageReceived -> HandlePacket -> HandlePacketClient -> SendMessage -> SendMessage -> OnPlayerPlacement_Patch1
|
|
||||||
2024-04-17T18:31:45:1
|
|
||||||
2024-04-17T18:31:45:2
|
|
||||||
2024-04-17T18:31:45:3
|
|
||||||
2024-04-17T18:31:45:4
|
|
||||||
2024-04-17T18:31:45:5
|
|
||||||
2024-04-17T18:31:45:6
|
|
||||||
2024-04-17T18:31:45:7
|
|
||||||
2024-04-17T18:31:45:8
|
|
||||||
2024-04-17T18:31:45:9
|
|
||||||
2024-04-17T18:31:45:10
|
|
||||||
2024-04-17T18:31:45:11
|
|
||||||
2024-04-17T18:31:45:12
|
|
||||||
2024-04-17T18:31:45:13
|
|
||||||
2024-04-17T18:31:45:14
|
|
||||||
2024-04-17T18:31:45:Called by: HandlePacketClient
|
|
||||||
2024-04-17T18:31:45:1 Shadowfita - Sending building place packet for keep
|
|
||||||
2024-04-17T18:31:45:Observer created for Building with 15 fields, 0 properties, and 0 non-primitive list variables
|
|
||||||
2024-04-17T18:31:59:Overridden complete build
|
|
||||||
2024-04-17T18:32:17:Received place building packet for keep from MUFFINMAN(2)
|
|
||||||
2024-04-17T18:32:17:Building init
|
|
||||||
2024-04-17T18:32:17:Building unpack
|
|
||||||
2024-04-17T18:32:17:Client Player (2 MUFFINMAN) (Player)
|
|
||||||
2024-04-17T18:32:17:False
|
|
||||||
2024-04-17T18:32:17:2
|
|
||||||
2024-04-17T18:32:17:Player add Building unpacked
|
|
||||||
2024-04-17T18:32:17:1
|
|
||||||
2024-04-17T18:32:17:2
|
|
||||||
2024-04-17T18:32:17:3
|
|
||||||
2024-04-17T18:32:17:4
|
|
||||||
2024-04-17T18:32:17:5
|
|
||||||
2024-04-17T18:32:17:6
|
|
||||||
2024-04-17T18:32:17:7
|
|
||||||
2024-04-17T18:32:17:8
|
|
||||||
2024-04-17T18:32:17:9
|
|
||||||
2024-04-17T18:32:17:10
|
|
||||||
2024-04-17T18:32:17:11
|
|
||||||
2024-04-17T18:32:17:12
|
|
||||||
2024-04-17T18:32:17:13
|
|
||||||
2024-04-17T18:32:17:14
|
|
||||||
2024-04-17T18:32:17:Set keep True
|
|
||||||
2024-04-17T18:32:17:Place from load
|
|
||||||
2024-04-17T18:32:17:unpack stage 2
|
|
||||||
2024-04-17T18:32:17:Landmass owner take ownership
|
|
||||||
2024-04-17T18:32:17:2 (team 22) banner: -1 Placed building Keep(Clone) at (24.0, 0.0, 91.0)
|
|
||||||
2024-04-17T18:32:17:Received add villager packet from MUFFINMAN(2)
|
|
||||||
2024-04-17T18:32:17:Teleporting villager to (26.8, 0.0, 91.2)
|
|
||||||
2024-04-17T18:32:17:Received add villager packet from MUFFINMAN(2)
|
|
||||||
2024-04-17T18:32:17:Teleporting villager to (26.8, 0.0, 91.6)
|
|
||||||
2024-04-17T18:32:17:Received add villager packet from MUFFINMAN(2)
|
|
||||||
2024-04-17T18:32:17:Teleporting villager to (26.4, 0.0, 91.6)
|
|
||||||
2024-04-17T18:32:17:Received add villager packet from MUFFINMAN(2)
|
|
||||||
2024-04-17T18:32:17:Teleporting villager to (26.4, 0.0, 91.2)
|
|
||||||
2024-04-17T18:32:17:Received add villager packet from MUFFINMAN(2)
|
|
||||||
2024-04-17T18:32:17:Teleporting villager to (24.6, 0.0, 92.2)
|
|
||||||
2024-04-17T18:32:28:Received place building packet for road from MUFFINMAN(2)
|
|
||||||
2024-04-17T18:32:28:Building init
|
|
||||||
2024-04-17T18:32:28:Error handling packet 71 WorldPlace from 2
|
|
||||||
2024-04-17T18:32:28:----------------------- Main exception -----------------------
|
|
||||||
2024-04-17T18:32:28:System.ArgumentNullException: Value cannot be null.
|
|
||||||
Parameter name: source
|
|
||||||
at (wrapper managed-to-native) UnityEngine.Material.CreateWithMaterial(UnityEngine.Material,UnityEngine.Material)
|
|
||||||
at UnityEngine.Material..ctor (UnityEngine.Material source) [0x00008] in <85d1d3e7744a4a47b5f51883bf40bba2>:0
|
|
||||||
at (wrapper dynamic-method) Building.Init_Patch0(object)
|
|
||||||
at KCM.Packets.Game.GameWorld.WorldPlace.PlaceBuilding () [0x0018d] in <9248c2b646c04c27b08155cb9b937ba4>:0
|
|
||||||
at KCM.Packets.Game.GameWorld.WorldPlace.HandlePacketClient () [0x00019] in <9248c2b646c04c27b08155cb9b937ba4>:0
|
|
||||||
at KCM.Packets.Handlers.PacketHandler.HandlePacket (System.Object sender, Riptide.MessageReceivedEventArgs messageReceived) [0x00023] in <9248c2b646c04c27b08155cb9b937ba4>:0
|
|
||||||
2024-04-17T18:32:28:----------------------- Main message -----------------------
|
|
||||||
2024-04-17T18:32:28:Value cannot be null.
|
|
||||||
Parameter name: source
|
|
||||||
2024-04-17T18:32:28:----------------------- Main stacktrace -----------------------
|
|
||||||
2024-04-17T18:32:28: at (wrapper managed-to-native) UnityEngine.Material.CreateWithMaterial(UnityEngine.Material,UnityEngine.Material)
|
|
||||||
at UnityEngine.Material..ctor (UnityEngine.Material source) [0x00008] in <85d1d3e7744a4a47b5f51883bf40bba2>:0
|
|
||||||
at (wrapper dynamic-method) Building.Init_Patch0(object)
|
|
||||||
at KCM.Packets.Game.GameWorld.WorldPlace.PlaceBuilding () [0x0018d] in <9248c2b646c04c27b08155cb9b937ba4>:0
|
|
||||||
at KCM.Packets.Game.GameWorld.WorldPlace.HandlePacketClient () [0x00019] in <9248c2b646c04c27b08155cb9b937ba4>:0
|
|
||||||
at KCM.Packets.Handlers.PacketHandler.HandlePacket (System.Object sender, Riptide.MessageReceivedEventArgs messageReceived) [0x00023] in <9248c2b646c04c27b08155cb9b937ba4>:0
|
|
||||||
2024-04-17T18:32:28:Received place building packet for road from MUFFINMAN(2)
|
|
||||||
2024-04-17T18:32:28:Building init
|
|
||||||
2024-04-17T18:32:28:Error handling packet 71 WorldPlace from 2
|
|
||||||
2024-04-17T18:32:28:----------------------- Main exception -----------------------
|
|
||||||
2024-04-17T18:32:28:System.ArgumentNullException: Value cannot be null.
|
|
||||||
Parameter name: source
|
|
||||||
at (wrapper managed-to-native) UnityEngine.Material.CreateWithMaterial(UnityEngine.Material,UnityEngine.Material)
|
|
||||||
at UnityEngine.Material..ctor (UnityEngine.Material source) [0x00008] in <85d1d3e7744a4a47b5f51883bf40bba2>:0
|
|
||||||
at (wrapper dynamic-method) Building.Init_Patch0(object)
|
|
||||||
at KCM.Packets.Game.GameWorld.WorldPlace.PlaceBuilding () [0x0018d] in <9248c2b646c04c27b08155cb9b937ba4>:0
|
|
||||||
at KCM.Packets.Game.GameWorld.WorldPlace.HandlePacketClient () [0x00019] in <9248c2b646c04c27b08155cb9b937ba4>:0
|
|
||||||
at KCM.Packets.Handlers.PacketHandler.HandlePacket (System.Object sender, Riptide.MessageReceivedEventArgs messageReceived) [0x00023] in <9248c2b646c04c27b08155cb9b937ba4>:0
|
|
||||||
2024-04-17T18:32:28:----------------------- Main message -----------------------
|
|
||||||
2024-04-17T18:32:28:Value cannot be null.
|
|
||||||
Parameter name: source
|
|
||||||
2024-04-17T18:32:28:----------------------- Main stacktrace -----------------------
|
|
||||||
2024-04-17T18:32:28: at (wrapper managed-to-native) UnityEngine.Material.CreateWithMaterial(UnityEngine.Material,UnityEngine.Material)
|
|
||||||
at UnityEngine.Material..ctor (UnityEngine.Material source) [0x00008] in <85d1d3e7744a4a47b5f51883bf40bba2>:0
|
|
||||||
at (wrapper dynamic-method) Building.Init_Patch0(object)
|
|
||||||
at KCM.Packets.Game.GameWorld.WorldPlace.PlaceBuilding () [0x0018d] in <9248c2b646c04c27b08155cb9b937ba4>:0
|
|
||||||
at KCM.Packets.Game.GameWorld.WorldPlace.HandlePacketClient () [0x00019] in <9248c2b646c04c27b08155cb9b937ba4>:0
|
|
||||||
at KCM.Packets.Handlers.PacketHandler.HandlePacket (System.Object sender, Riptide.MessageReceivedEventArgs messageReceived) [0x00023] in <9248c2b646c04c27b08155cb9b937ba4>:0
|
|
||||||
2024-04-17T18:32:28:Building not found.
|
|
||||||
2024-04-17T18:32:28:Building not found.
|
|
||||||
2024-04-17T18:32:29:Received place building packet for road from MUFFINMAN(2)
|
|
||||||
2024-04-17T18:32:29:Building init
|
|
||||||
2024-04-17T18:32:29:Error handling packet 71 WorldPlace from 2
|
|
||||||
2024-04-17T18:32:29:----------------------- Main exception -----------------------
|
|
||||||
2024-04-17T18:32:29:System.ArgumentNullException: Value cannot be null.
|
|
||||||
Parameter name: source
|
|
||||||
at (wrapper managed-to-native) UnityEngine.Material.CreateWithMaterial(UnityEngine.Material,UnityEngine.Material)
|
|
||||||
at UnityEngine.Material..ctor (UnityEngine.Material source) [0x00008] in <85d1d3e7744a4a47b5f51883bf40bba2>:0
|
|
||||||
at (wrapper dynamic-method) Building.Init_Patch0(object)
|
|
||||||
at KCM.Packets.Game.GameWorld.WorldPlace.PlaceBuilding () [0x0018d] in <9248c2b646c04c27b08155cb9b937ba4>:0
|
|
||||||
at KCM.Packets.Game.GameWorld.WorldPlace.HandlePacketClient () [0x00019] in <9248c2b646c04c27b08155cb9b937ba4>:0
|
|
||||||
at KCM.Packets.Handlers.PacketHandler.HandlePacket (System.Object sender, Riptide.MessageReceivedEventArgs messageReceived) [0x00023] in <9248c2b646c04c27b08155cb9b937ba4>:0
|
|
||||||
2024-04-17T18:32:29:----------------------- Main message -----------------------
|
|
||||||
2024-04-17T18:32:29:Value cannot be null.
|
|
||||||
Parameter name: source
|
|
||||||
2024-04-17T18:32:29:----------------------- Main stacktrace -----------------------
|
|
||||||
2024-04-17T18:32:29: at (wrapper managed-to-native) UnityEngine.Material.CreateWithMaterial(UnityEngine.Material,UnityEngine.Material)
|
|
||||||
at UnityEngine.Material..ctor (UnityEngine.Material source) [0x00008] in <85d1d3e7744a4a47b5f51883bf40bba2>:0
|
|
||||||
at (wrapper dynamic-method) Building.Init_Patch0(object)
|
|
||||||
at KCM.Packets.Game.GameWorld.WorldPlace.PlaceBuilding () [0x0018d] in <9248c2b646c04c27b08155cb9b937ba4>:0
|
|
||||||
at KCM.Packets.Game.GameWorld.WorldPlace.HandlePacketClient () [0x00019] in <9248c2b646c04c27b08155cb9b937ba4>:0
|
|
||||||
at KCM.Packets.Handlers.PacketHandler.HandlePacket (System.Object sender, Riptide.MessageReceivedEventArgs messageReceived) [0x00023] in <9248c2b646c04c27b08155cb9b937ba4>:0
|
|
||||||
2024-04-17T18:32:29:Building not found.
|
|
||||||
2024-04-17T18:32:29:Received place building packet for road from MUFFINMAN(2)
|
|
||||||
2024-04-17T18:32:29:Building init
|
|
||||||
2024-04-17T18:32:29:Error handling packet 71 WorldPlace from 2
|
|
||||||
2024-04-17T18:32:29:----------------------- Main exception -----------------------
|
|
||||||
2024-04-17T18:32:29:System.ArgumentNullException: Value cannot be null.
|
|
||||||
Parameter name: source
|
|
||||||
at (wrapper managed-to-native) UnityEngine.Material.CreateWithMaterial(UnityEngine.Material,UnityEngine.Material)
|
|
||||||
at UnityEngine.Material..ctor (UnityEngine.Material source) [0x00008] in <85d1d3e7744a4a47b5f51883bf40bba2>:0
|
|
||||||
at (wrapper dynamic-method) Building.Init_Patch0(object)
|
|
||||||
at KCM.Packets.Game.GameWorld.WorldPlace.PlaceBuilding () [0x0018d] in <9248c2b646c04c27b08155cb9b937ba4>:0
|
|
||||||
at KCM.Packets.Game.GameWorld.WorldPlace.HandlePacketClient () [0x00019] in <9248c2b646c04c27b08155cb9b937ba4>:0
|
|
||||||
at KCM.Packets.Handlers.PacketHandler.HandlePacket (System.Object sender, Riptide.MessageReceivedEventArgs messageReceived) [0x00023] in <9248c2b646c04c27b08155cb9b937ba4>:0
|
|
||||||
2024-04-17T18:32:29:----------------------- Main message -----------------------
|
|
||||||
2024-04-17T18:32:29:Value cannot be null.
|
|
||||||
Parameter name: source
|
|
||||||
2024-04-17T18:32:29:----------------------- Main stacktrace -----------------------
|
|
||||||
2024-04-17T18:32:29: at (wrapper managed-to-native) UnityEngine.Material.CreateWithMaterial(UnityEngine.Material,UnityEngine.Material)
|
|
||||||
at UnityEngine.Material..ctor (UnityEngine.Material source) [0x00008] in <85d1d3e7744a4a47b5f51883bf40bba2>:0
|
|
||||||
at (wrapper dynamic-method) Building.Init_Patch0(object)
|
|
||||||
at KCM.Packets.Game.GameWorld.WorldPlace.PlaceBuilding () [0x0018d] in <9248c2b646c04c27b08155cb9b937ba4>:0
|
|
||||||
at KCM.Packets.Game.GameWorld.WorldPlace.HandlePacketClient () [0x00019] in <9248c2b646c04c27b08155cb9b937ba4>:0
|
|
||||||
at KCM.Packets.Handlers.PacketHandler.HandlePacket (System.Object sender, Riptide.MessageReceivedEventArgs messageReceived) [0x00023] in <9248c2b646c04c27b08155cb9b937ba4>:0
|
|
||||||
2024-04-17T18:32:30:Building not found.
|
|
||||||
2024-04-17T18:32:30:Received place building packet for road from MUFFINMAN(2)
|
|
||||||
2024-04-17T18:32:30:Building init
|
|
||||||
2024-04-17T18:32:30:Error handling packet 71 WorldPlace from 2
|
|
||||||
2024-04-17T18:32:30:----------------------- Main exception -----------------------
|
|
||||||
2024-04-17T18:32:30:System.ArgumentNullException: Value cannot be null.
|
|
||||||
Parameter name: source
|
|
||||||
at (wrapper managed-to-native) UnityEngine.Material.CreateWithMaterial(UnityEngine.Material,UnityEngine.Material)
|
|
||||||
at UnityEngine.Material..ctor (UnityEngine.Material source) [0x00008] in <85d1d3e7744a4a47b5f51883bf40bba2>:0
|
|
||||||
at (wrapper dynamic-method) Building.Init_Patch0(object)
|
|
||||||
at KCM.Packets.Game.GameWorld.WorldPlace.PlaceBuilding () [0x0018d] in <9248c2b646c04c27b08155cb9b937ba4>:0
|
|
||||||
at KCM.Packets.Game.GameWorld.WorldPlace.HandlePacketClient () [0x00019] in <9248c2b646c04c27b08155cb9b937ba4>:0
|
|
||||||
at KCM.Packets.Handlers.PacketHandler.HandlePacket (System.Object sender, Riptide.MessageReceivedEventArgs messageReceived) [0x00023] in <9248c2b646c04c27b08155cb9b937ba4>:0
|
|
||||||
2024-04-17T18:32:30:----------------------- Main message -----------------------
|
|
||||||
2024-04-17T18:32:30:Value cannot be null.
|
|
||||||
Parameter name: source
|
|
||||||
2024-04-17T18:32:30:----------------------- Main stacktrace -----------------------
|
|
||||||
2024-04-17T18:32:30: at (wrapper managed-to-native) UnityEngine.Material.CreateWithMaterial(UnityEngine.Material,UnityEngine.Material)
|
|
||||||
at UnityEngine.Material..ctor (UnityEngine.Material source) [0x00008] in <85d1d3e7744a4a47b5f51883bf40bba2>:0
|
|
||||||
at (wrapper dynamic-method) Building.Init_Patch0(object)
|
|
||||||
at KCM.Packets.Game.GameWorld.WorldPlace.PlaceBuilding () [0x0018d] in <9248c2b646c04c27b08155cb9b937ba4>:0
|
|
||||||
at KCM.Packets.Game.GameWorld.WorldPlace.HandlePacketClient () [0x00019] in <9248c2b646c04c27b08155cb9b937ba4>:0
|
|
||||||
at KCM.Packets.Handlers.PacketHandler.HandlePacket (System.Object sender, Riptide.MessageReceivedEventArgs messageReceived) [0x00023] in <9248c2b646c04c27b08155cb9b937ba4>:0
|
|
||||||
2024-04-17T18:32:30:Overridden complete build
|
|
||||||
2024-04-17T18:32:30:Building not found.
|
|
||||||
2024-04-17T18:32:31:Received place building packet for road from MUFFINMAN(2)
|
|
||||||
2024-04-17T18:32:31:Building init
|
|
||||||
2024-04-17T18:32:31:Error handling packet 71 WorldPlace from 2
|
|
||||||
2024-04-17T18:32:31:----------------------- Main exception -----------------------
|
|
||||||
2024-04-17T18:32:31:System.ArgumentNullException: Value cannot be null.
|
|
||||||
Parameter name: source
|
|
||||||
at (wrapper managed-to-native) UnityEngine.Material.CreateWithMaterial(UnityEngine.Material,UnityEngine.Material)
|
|
||||||
at UnityEngine.Material..ctor (UnityEngine.Material source) [0x00008] in <85d1d3e7744a4a47b5f51883bf40bba2>:0
|
|
||||||
at (wrapper dynamic-method) Building.Init_Patch0(object)
|
|
||||||
at KCM.Packets.Game.GameWorld.WorldPlace.PlaceBuilding () [0x0018d] in <9248c2b646c04c27b08155cb9b937ba4>:0
|
|
||||||
at KCM.Packets.Game.GameWorld.WorldPlace.HandlePacketClient () [0x00019] in <9248c2b646c04c27b08155cb9b937ba4>:0
|
|
||||||
at KCM.Packets.Handlers.PacketHandler.HandlePacket (System.Object sender, Riptide.MessageReceivedEventArgs messageReceived) [0x00023] in <9248c2b646c04c27b08155cb9b937ba4>:0
|
|
||||||
2024-04-17T18:32:31:----------------------- Main message -----------------------
|
|
||||||
2024-04-17T18:32:31:Value cannot be null.
|
|
||||||
Parameter name: source
|
|
||||||
2024-04-17T18:32:31:----------------------- Main stacktrace -----------------------
|
|
||||||
2024-04-17T18:32:31: at (wrapper managed-to-native) UnityEngine.Material.CreateWithMaterial(UnityEngine.Material,UnityEngine.Material)
|
|
||||||
at UnityEngine.Material..ctor (UnityEngine.Material source) [0x00008] in <85d1d3e7744a4a47b5f51883bf40bba2>:0
|
|
||||||
at (wrapper dynamic-method) Building.Init_Patch0(object)
|
|
||||||
at KCM.Packets.Game.GameWorld.WorldPlace.PlaceBuilding () [0x0018d] in <9248c2b646c04c27b08155cb9b937ba4>:0
|
|
||||||
at KCM.Packets.Game.GameWorld.WorldPlace.HandlePacketClient () [0x00019] in <9248c2b646c04c27b08155cb9b937ba4>:0
|
|
||||||
at KCM.Packets.Handlers.PacketHandler.HandlePacket (System.Object sender, Riptide.MessageReceivedEventArgs messageReceived) [0x00023] in <9248c2b646c04c27b08155cb9b937ba4>:0
|
|
||||||
2024-04-17T18:32:32:Building not found.
|
|
||||||
2024-04-17T18:32:32:Building not found.
|
|
||||||
2024-04-17T18:32:33:Building not found.
|
|
||||||
2024-04-17T18:32:33:Building not found.
|
|
||||||
2024-04-17T18:32:33:Building not found.
|
|
||||||
2024-04-17T18:32:33:Building not found.
|
|
||||||
2024-04-17T18:32:34:Building not found.
|
|
||||||
2024-04-17T18:32:34:Building not found.
|
|
||||||
2024-04-17T18:32:34:Building not found.
|
|
||||||
2024-04-17T18:32:34:Building not found.
|
|
||||||
2024-04-17T18:32:34:Building not found.
|
|
||||||
2024-04-17T18:32:34:Building not found.
|
|
||||||
2024-04-17T18:32:35:Building not found.
|
|
||||||
2024-04-17T18:32:35:Building not found.
|
|
||||||
2024-04-17T18:32:35:Building not found.
|
|
||||||
2024-04-17T18:32:35:Building not found.
|
|
||||||
2024-04-17T18:32:35:Building not found.
|
|
||||||
2024-04-17T18:32:36:Building not found.
|
|
||||||
2024-04-17T18:32:36:Building not found.
|
|
||||||
2024-04-17T18:32:36:Building not found.
|
|
||||||
2024-04-17T18:32:36:Building not found.
|
|
||||||
2024-04-17T18:32:36:Building not found.
|
|
||||||
2024-04-17T18:32:37:Building not found.
|
|
||||||
2024-04-17T18:32:37:Building not found.
|
|
||||||
2024-04-17T18:32:37:Received place building packet for smallhouse from MUFFINMAN(2)
|
|
||||||
2024-04-17T18:32:37:Building init
|
|
||||||
2024-04-17T18:32:37:Error handling packet 71 WorldPlace from 2
|
|
||||||
2024-04-17T18:32:37:----------------------- Main exception -----------------------
|
|
||||||
2024-04-17T18:32:37:System.ArgumentNullException: Value cannot be null.
|
|
||||||
Parameter name: source
|
|
||||||
at (wrapper managed-to-native) UnityEngine.Material.CreateWithMaterial(UnityEngine.Material,UnityEngine.Material)
|
|
||||||
at UnityEngine.Material..ctor (UnityEngine.Material source) [0x00008] in <85d1d3e7744a4a47b5f51883bf40bba2>:0
|
|
||||||
at (wrapper dynamic-method) Building.Init_Patch0(object)
|
|
||||||
at KCM.Packets.Game.GameWorld.WorldPlace.PlaceBuilding () [0x0018d] in <9248c2b646c04c27b08155cb9b937ba4>:0
|
|
||||||
at KCM.Packets.Game.GameWorld.WorldPlace.HandlePacketClient () [0x00019] in <9248c2b646c04c27b08155cb9b937ba4>:0
|
|
||||||
at KCM.Packets.Handlers.PacketHandler.HandlePacket (System.Object sender, Riptide.MessageReceivedEventArgs messageReceived) [0x00023] in <9248c2b646c04c27b08155cb9b937ba4>:0
|
|
||||||
2024-04-17T18:32:37:----------------------- Main message -----------------------
|
|
||||||
2024-04-17T18:32:37:Value cannot be null.
|
|
||||||
Parameter name: source
|
|
||||||
2024-04-17T18:32:37:----------------------- Main stacktrace -----------------------
|
|
||||||
2024-04-17T18:32:37: at (wrapper managed-to-native) UnityEngine.Material.CreateWithMaterial(UnityEngine.Material,UnityEngine.Material)
|
|
||||||
at UnityEngine.Material..ctor (UnityEngine.Material source) [0x00008] in <85d1d3e7744a4a47b5f51883bf40bba2>:0
|
|
||||||
at (wrapper dynamic-method) Building.Init_Patch0(object)
|
|
||||||
at KCM.Packets.Game.GameWorld.WorldPlace.PlaceBuilding () [0x0018d] in <9248c2b646c04c27b08155cb9b937ba4>:0
|
|
||||||
at KCM.Packets.Game.GameWorld.WorldPlace.HandlePacketClient () [0x00019] in <9248c2b646c04c27b08155cb9b937ba4>:0
|
|
||||||
at KCM.Packets.Handlers.PacketHandler.HandlePacket (System.Object sender, Riptide.MessageReceivedEventArgs messageReceived) [0x00023] in <9248c2b646c04c27b08155cb9b937ba4>:0
|
|
||||||
2024-04-17T18:32:37:Building not found.
|
|
||||||
2024-04-17T18:32:37:Building not found.
|
|
||||||
2024-04-17T18:32:37:Building not found.
|
|
||||||
2024-04-17T18:32:37:Building not found.
|
|
||||||
2024-04-17T18:32:38:Building not found.
|
|
||||||
2024-04-17T18:32:38:Building not found.
|
|
||||||
2024-04-17T18:32:38:Building not found.
|
|
||||||
2024-04-17T18:32:39:Building not found.
|
|
||||||
2024-04-17T18:32:39:Building not found.
|
|
||||||
2024-04-17T18:32:39:Building not found.
|
|
||||||
2024-04-17T18:32:40:Building not found.
|
|
||||||
2024-04-17T18:32:40:Building not found.
|
|
||||||
2024-04-17T18:32:40:Building not found.
|
|
||||||
2024-04-17T18:32:41:Building not found.
|
|
||||||
2024-04-17T18:32:41:Building not found.
|
|
||||||
2024-04-17T18:32:42:Building not found.
|
|
||||||
2024-04-17T18:32:42:Building not found.
|
|
||||||
2024-04-17T18:32:42:Building not found.
|
|
||||||
2024-04-17T18:32:43:Building not found.
|
|
||||||
2024-04-17T18:32:43:Building not found.
|
|
||||||
2024-04-17T18:32:43:Building not found.
|
|
||||||
2024-04-17T18:32:44:Building not found.
|
|
||||||
2024-04-17T18:32:44:Building not found.
|
|
||||||
2024-04-17T18:32:44:Building not found.
|
|
||||||
2024-04-17T18:32:45:Building not found.
|
|
||||||
2024-04-17T18:32:45:Building not found.
|
|
||||||
2024-04-17T18:32:45:Building not found.
|
|
||||||
2024-04-17T18:32:46:Building not found.
|
|
||||||
2024-04-17T18:32:46:Building not found.
|
|
||||||
2024-04-17T18:32:46:Building not found.
|
|
||||||
2024-04-17T18:32:46:Building not found.
|
|
||||||
2024-04-17T18:32:47:Building not found.
|
|
||||||
2024-04-17T18:32:47:Building not found.
|
|
||||||
2024-04-17T18:32:47:Building not found.
|
|
||||||
2024-04-17T18:32:48:Building not found.
|
|
||||||
2024-04-17T18:32:48:Building not found.
|
|
||||||
2024-04-17T18:32:48:Building not found.
|
|
||||||
2024-04-17T18:32:49:Building not found.
|
|
||||||
2024-04-17T18:32:49:Building not found.
|
|
||||||
2024-04-17T18:32:49:Building not found.
|
|
||||||
2024-04-17T18:32:50:Building not found.
|
|
||||||
2024-04-17T18:32:50:Building not found.
|
|
||||||
2024-04-17T18:32:50:Building not found.
|
|
||||||
2024-04-17T18:32:51:Building not found.
|
|
||||||
2024-04-17T18:32:51:Building not found.
|
|
||||||
2024-04-17T18:32:51:Building not found.
|
|
||||||
2024-04-17T18:32:52:Building not found.
|
|
||||||
2024-04-17T18:32:52:Building not found.
|
|
||||||
2024-04-17T18:32:52:Building not found.
|
|
||||||
2024-04-17T18:32:52:Building not found.
|
|
||||||
2024-04-17T18:32:53:Building not found.
|
|
||||||
2024-04-17T18:32:53:Building not found.
|
|
||||||
2024-04-17T18:32:53:Building not found.
|
|
||||||
2024-04-17T18:32:54:Building not found.
|
|
||||||
2024-04-17T18:32:54:Building not found.
|
|
||||||
2024-04-17T18:32:54:Building not found.
|
|
||||||
2024-04-17T18:32:55:Building not found.
|
|
||||||
2024-04-17T18:32:55:Building not found.
|
|
||||||
File diff suppressed because it is too large
Load Diff
11992
output-attempt 3.txt
11992
output-attempt 3.txt
File diff suppressed because it is too large
Load Diff
683835
output.txt
683835
output.txt
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user