/// <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));
         }
     }
 }
Exemple #2
0
        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)));
            }
        }