diff --git a/Main.cs b/Main.cs index 4125245..1c28bb0 100644 --- a/Main.cs +++ b/Main.cs @@ -182,43 +182,75 @@ namespace KCM #endregion public static int FixedUpdateInterval = 0; + private static Dictionary lastVillagerPositions = new Dictionary(); + + public static void ClearVillagerPositionCache() + { + lastVillagerPositions.Clear(); + } private void FixedUpdate() { - // send batched building placement info - /*if (PlaceHook.QueuedBuildings.Count > 0 && (FixedUpdateInterval % 25 == 0)) + // Periodic villager position sync from server to clients + // Sync every 150 frames (~3 seconds at 50 FPS) to reduce bandwidth + if (KCServer.IsRunning && KCClient.client.IsConnected && FixedUpdateInterval % 150 == 0) { - foreach (Building building in PlaceHook.QueuedBuildings) + try { - 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(); + SyncVillagerPositions(); } - - PlaceHook.QueuedBuildings.Clear(); - }*/ + catch (Exception e) + { + helper.Log($"Error in villager sync: {e.Message}"); + } + } FixedUpdateInterval++; } + private void SyncVillagerPositions() + { + // Only sync villagers that have moved significantly + const float movementThreshold = 0.5f; + + foreach (var kcPlayer in kCPlayers.Values) + { + if (kcPlayer.inst == null) continue; + + for (int i = 0; i < kcPlayer.inst.Workers.Count; i++) + { + var villager = kcPlayer.inst.Workers.data[i]; + if (villager == null) continue; + + Vector3 currentPos = villager.Pos; + Vector3 lastPos; + + bool shouldSync = false; + if (!lastVillagerPositions.TryGetValue(villager.guid, out lastPos)) + { + // First time seeing this villager + lastVillagerPositions[villager.guid] = currentPos; + shouldSync = true; + } + else if (Vector3.Distance(currentPos, lastPos) > movementThreshold) + { + // Villager has moved significantly + lastVillagerPositions[villager.guid] = currentPos; + shouldSync = true; + } + + if (shouldSync) + { + new Packets.Game.GameVillager.VillagerTeleportTo() + { + guid = villager.guid, + pos = currentPos + }.SendToAll(KCClient.client.Id); + } + } + } + } + #region "TransitionTo" public static void TransitionTo(MenuState state) { diff --git a/RiptideSteamTransport/LobbyManager.cs b/RiptideSteamTransport/LobbyManager.cs index 9fa21dd..53a1812 100644 --- a/RiptideSteamTransport/LobbyManager.cs +++ b/RiptideSteamTransport/LobbyManager.cs @@ -160,6 +160,7 @@ namespace Riptide.Demos.Steam.PlayerHosted Main.helper.Log("clear players"); Main.kCPlayers.Clear(); Main.clientSteamIds.Clear(); // Clear client-to-steam ID mapping + Main.ClearVillagerPositionCache(); // Clear villager sync cache LobbyHandler.ClearPlayerList(); LobbyHandler.ClearChatEntries(); Main.helper.Log("end clear players");