/// <summary> /// Reconstructs Chunk from a NetworkChunk object, this constructor is used for /// initialising Chunks that have been sent across the Network. /// </summary> /// <param name="networkChunk">The network chunk.</param> public Chunk(NetworkChunk networkChunk) : this(new Vector2Int(networkChunk.X, networkChunk.Y)) { for (int x = 0; x < SIZE; x++) { for (int y = 0; y < SIZE; y++) { Tiles[x, y] = new Tile(networkChunk.NetworkTiles[x * SIZE + y], new Vector2Int(x, y)); } } }
public static NetworkChunk[] ChunkListToNetworkChunkArray(List <Chunk> chunks) { NetworkChunk[] networkChunks = new NetworkChunk[chunks.Count]; for (int i = 0; i < chunks.Count; i++) { networkChunks[i] = new NetworkChunk(chunks[i]); } return(networkChunks); }
/// <summary> /// Called on the server when the chunk that a player is located in changes. (I.E. when a player moves from one chunk to another). /// </summary> /// <param name="playerController"></param> /// <param name="position"></param> public void OnServerPlayerChunkUpdate(PlayerController playerController, Vector2 position) { var playerId = playerController.Id; Vector2Int playerPositionInt = new Vector2Int((int)position.x, (int)position.y); // Find the chunks needed for the player based on their new position var chunksNeededForPlayer = Chunk.ListOfSurroundingChunksOfWorldPosition(playerPositionInt); // Find all of the chunks loaded for the player, // E.G. // Previous -> 5, 6, 7, 8, 9 // Needed -> 7, 8, 9, 10, 11 // // Previous should become -> 5, 6 var chunksLoadedForPlayer = World.GetPlayerLoadedChunkPositions(playerId); var chunksToUnloadForPlayer = chunksLoadedForPlayer.Except(chunksNeededForPlayer).ToList(); var newChunksNeededForPlayer = chunksNeededForPlayer.Except(chunksLoadedForPlayer).ToList(); var chunksToRemove = World.RemoveChunks(playerId, chunksToUnloadForPlayer); GameFile.Instance.Save(chunksToRemove); chunksToUnloadForPlayer.Clear(); foreach (var chunk in chunksToRemove) { chunk.Unload(); chunksToUnloadForPlayer.Add(chunk.Position); } // Tell the world about the chunks that the player now depends upon World.UpdatePlayerChunks(playerId, newChunksNeededForPlayer); // If the chunks are already loaded then we can forget about them World.FilterLoadedChunks(newChunksNeededForPlayer); // Load chunks from file var chunksToLoad = World.FilterKnownChunks(newChunksNeededForPlayer); Debug.Log("[WorldController] - OnServerPlayerChunkUpdate(PlayerController, Vector2)\n" + $"ChunksToLoad Count: {chunksToLoad.Count}"); // If there are more players than just the server client, do this call.. var chunks = GameFile.Instance.LoadChunks(chunksToLoad); World.AddChunks(chunks); // Generate the new chunks var generatedChunks = _worldGeneration.GenerateChunks(newChunksNeededForPlayer); World.AddChunks(generatedChunks); foreach (var chunk in generatedChunks) { chunk.Initialise(); } if (GameManager.NetworkManager.NumberOfClientControllers > 1) { var chunksToLoadBytes = Vector2IntsToBytes(chunksToLoad); var chunksToUnloadBytes = Vector2IntsToBytes(chunksToUnloadForPlayer); NetworkChunk[] generatedNetworkChunks = (generatedChunks.Count > 0) ? NetworkChunk.ChunkListToNetworkChunkArray(generatedChunks) : null; List <NetworkConnection> sendEntitiesTo = new List <NetworkConnection>(); foreach (var clientController in GameManager.NetworkManager.ClientControllers) { if (clientController.IsActive && clientController.WorldController != this) { TargetUpdateChunks(clientController.Connection, chunksToLoadBytes, chunksToUnloadBytes); if (generatedNetworkChunks != null) { sendEntitiesTo.Add(clientController.Connection); TargetReceiveChunks(clientController.Connection, generatedNetworkChunks); } if (clientController.PlayerController.Id == playerId) { TargetUpdateChunkControllers(clientController.Connection); } } } if (sendEntitiesTo.Count > 0) { StartCoroutine(SendEntities(sendEntitiesTo, generatedChunks)); } } if (playerId == GameManager.PlayerController.Id) { StartCoroutine(UpdateChunkControllers(World.GetPlayerLoadedChunks(playerId))); } }