private void SendChunkUpdates(SimulationEntity playerEntity)
        {
            ChunkUpdatesMessage updates = new ChunkUpdatesMessage();

            //Loop through visible chunks and grab entities that should be displayed
            foreach (string visibleChunkKey in playerEntity.VisibleChunks)
            {
                //If the versions are the same we do not need to send the chunk
                if (playerEntity.ChunkVersions[visibleChunkKey] == World.ChunkIndex[visibleChunkKey].ChunkVersion)
                {
                    continue;
                }

                if (World.ChunkIndex[visibleChunkKey].NeedChunkUpdate(playerEntity.ChunkVersions[visibleChunkKey]))//Gets an entire chunk for updating
                {
                    updates.ChunkUpdates.Add(World.ChunkIndex[visibleChunkKey].GetChunkUpdate());
                }
                else
                {
                    updates.ChunkTileUpdates.Add(World.ChunkIndex[visibleChunkKey].GetChunkTileUpdates(playerEntity.ChunkVersions[visibleChunkKey]));//Gets individual tile updates in a chunk
                }
                playerEntity.ChunkVersions[visibleChunkKey] = World.ChunkIndex[visibleChunkKey].ChunkVersion;
            }

            if (updates.ChunkUpdates.Any() || updates.ChunkTileUpdates.Any())
            {
                OnChunkUpdates?.Invoke(playerEntity.EntityId, updates);
            }
        }
        public void ApplyChunkUpdateMessage(ChunkUpdatesMessage updates)
        {
            if (ChunkMap == null)
            {
                return;
            }

            //Process full chunk updates
            foreach (ChunkUpdate chunkUpdate in updates.ChunkUpdates)
            {
                if (!ChunkExist(chunkUpdate.ChunkX, chunkUpdate.ChunkY))
                {
                    continue;
                }

                ChunkMap[chunkUpdate.ChunkX, chunkUpdate.ChunkY].ChunkKey = chunkUpdate.ChunkKey;
                ChunkMap[chunkUpdate.ChunkX, chunkUpdate.ChunkY].Block    = chunkUpdate.Block;
                ChunkMap[chunkUpdate.ChunkX, chunkUpdate.ChunkY].Wall     = chunkUpdate.Wall;
            }

            //process tile map updates
            foreach (ChunkTileUpdates chunkTileUpdates in updates.ChunkTileUpdates)
            {
                if (!ChunkExist(chunkTileUpdates.ChunkX, chunkTileUpdates.ChunkY))
                {
                    continue;
                }

                Chunk chunk = ChunkMap[chunkTileUpdates.ChunkX, chunkTileUpdates.ChunkY];

                foreach (TileUpdate chunkTileUpdate in chunkTileUpdates.TileChanges)
                {
                    chunk.ApplyBlockUpdate(chunkTileUpdate, true);
                }
            }
        }