void UpdatePlayerVisibleChunks(PlayerChunkLoadState state) { if (state.Entity == null) { return; } state.ChunksToUnload.Clear(); _tempVisList.Clear(); var centerPos = ChunkHelper.GetChunkIdFromCoords(state.Entity.Position); var dim = (WorldOptions.MaxLoadRadius - 1) * 2; ChunkHelper.Spiral(dim, dim, (x, y) => { _tempVisList.Add(centerPos.Add(x, 0, y)); }); foreach (var c in _tempVisList) { if (state.SentChunks.Contains(c) || state.SendQueue.Contains(c) || state.LoadGenQueue.Contains(c)) { continue; } state.LoadGenQueue.Enqueue(c); } var maxLoadDistance = WorldOptions.ChunkUnloadDistance * WorldOptions.ChunkUnloadDistance; foreach (var c in state.SentChunks) { var dist = Int3.SquareDistanceFlat(centerPos, c); if (dist > maxLoadDistance) { state.ChunksToUnload.Add(c); } } }
void UnloadChunkOnClient(PlayerChunkLoadState state, Int3 index) { state.SentChunks.Remove(index); ServerController.Instance.SendNetMessage(state.Client, ServerPacketID.ChunkUnload, new S_UnloadChunkMessage() { X = index.X, Y = index.Y, Z = index.Z }); }
void UpdateClientQueues(PlayerChunkLoadState state) { while (state.LoadGenQueue.Count > 0) { var c = state.LoadGenQueue.Dequeue(); state.SendQueue.Enqueue(c); var chunk = GetChunk(c); if (!_usedChunks.ContainsKey(c)) { _usedChunks.Add(c, 1); } else { _usedChunks[c] += 1; } if (chunk == null) { GenOrLoad(c.X, c.Z, true); break; } } if (state.SendQueue.Count > 0) { var c = state.SendQueue.Dequeue(); var chunk = GetChunk(c); if (chunk != null) { SendChunkToClient(state, chunk.GetData(), c); } else { state.SendQueue.Enqueue(c); } } if (state.ChunksToUnload.Count > 0) { foreach (var item in state.ChunksToUnload) { UnloadChunkOnClient(state, item); _usedChunks[item] -= 1; if (_usedChunks[item] <= 0) { _usedChunks.Remove(item); } } state.ChunksToUnload.Clear(); } if (state.SendQueue.Count == 0 && !state.PlayerInited) { state.PlayerInited = true; FinalizeClientWorldInitialization(state.Client); } }
void CreateInitialSendQueue(PlayerChunkLoadState state) { Vector3 spawnPoint = ServerPlayerEntityManager.Instance.GetLastSavedPosition(state.Client); var centerChunk = ChunkHelper.GetChunkIdFromCoords(spawnPoint); var queue = state.LoadGenQueue; var dim = (WorldOptions.ChunkLoadRadius - 1) * 2; ChunkHelper.Spiral(dim, dim, (x, z) => { queue.Enqueue(centerChunk.Add(x, 0, z)); }); }
void SendChunkToClient(PlayerChunkLoadState state, ChunkData data, Int3 index) { state.SentChunks.Add(index); var blockCount = (data.Height + 1) * 16 * 16; using (var str = new MemoryStream(_chunkSendBuffer)) { using (var writer = new BinaryWriter(str)) { var count = ChunkSerializer.Serialize(data, writer, true); var dst = new byte[count]; System.Array.Copy(_chunkSendBuffer, dst, count); ServerController.Instance.SendRawNetMessage(state.Client, ServerPacketID.ChunkInit, dst, false); } } }
void OnPlayerJoin(OnClientConnected e) { DebugOutput.LogFormat("Player {0} joined. Starting to send world info.", e.State.UserName); var state = new PlayerChunkLoadState() { Client = e.State, PlayerInited = false }; _playerStates.Add(e.State, state); CreateInitialSendQueue(state); var wsc = ServerWorldStateController.Instance; //TODO: Move to world state controller wsc.SendToClient(e.State); }