Fix: Add periodic villager position sync from server
- Server syncs villager positions every ~3 seconds to clients - Only syncs villagers that moved more than 0.5 units (bandwidth optimization) - Maintains position cache to detect movement - Clears cache on lobby leave to prevent stale data 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
86
Main.cs
86
Main.cs
@@ -182,43 +182,75 @@ namespace KCM
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
public static int FixedUpdateInterval = 0;
|
public static int FixedUpdateInterval = 0;
|
||||||
|
private static Dictionary<Guid, Vector3> lastVillagerPositions = new Dictionary<Guid, Vector3>();
|
||||||
|
|
||||||
|
public static void ClearVillagerPositionCache()
|
||||||
|
{
|
||||||
|
lastVillagerPositions.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
private void FixedUpdate()
|
private void FixedUpdate()
|
||||||
{
|
{
|
||||||
// send batched building placement info
|
// Periodic villager position sync from server to clients
|
||||||
/*if (PlaceHook.QueuedBuildings.Count > 0 && (FixedUpdateInterval % 25 == 0))
|
// 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()
|
SyncVillagerPositions();
|
||||||
{
|
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
catch (Exception e)
|
||||||
PlaceHook.QueuedBuildings.Clear();
|
{
|
||||||
}*/
|
helper.Log($"Error in villager sync: {e.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
FixedUpdateInterval++;
|
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"
|
#region "TransitionTo"
|
||||||
public static void TransitionTo(MenuState state)
|
public static void TransitionTo(MenuState state)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -160,6 +160,7 @@ namespace Riptide.Demos.Steam.PlayerHosted
|
|||||||
Main.helper.Log("clear players");
|
Main.helper.Log("clear players");
|
||||||
Main.kCPlayers.Clear();
|
Main.kCPlayers.Clear();
|
||||||
Main.clientSteamIds.Clear(); // Clear client-to-steam ID mapping
|
Main.clientSteamIds.Clear(); // Clear client-to-steam ID mapping
|
||||||
|
Main.ClearVillagerPositionCache(); // Clear villager sync cache
|
||||||
LobbyHandler.ClearPlayerList();
|
LobbyHandler.ClearPlayerList();
|
||||||
LobbyHandler.ClearChatEntries();
|
LobbyHandler.ClearChatEntries();
|
||||||
Main.helper.Log("end clear players");
|
Main.helper.Log("end clear players");
|
||||||
|
|||||||
Reference in New Issue
Block a user