public Task AsyncLoadTask(ChunkPos chunkPos)
        {
            if (_unloadTask == null || _unloadTask.IsCompleted)
            {
                _unloadTask = AsyncUnloadTask();
            }

            var oldChunkPos = ChunkPos;

            ChunkPos = chunkPos;

            if (_loadTask != null && !_loadTask.IsCompleted)
            {
                _cts.Cancel();
            }

            _cts = new CancellationTokenSource();

            var loadTask = new Task(() =>
            {
                _unloadTask.Wait();
                GameManager.WorldManager.worldLoader.LoadEntity(chunkPos, ref _entityDataList);
                _isDirty = true;
            }, _cts.Token);

            loadTask.Start();
            _loadTask = loadTask;
            return(loadTask);
        }
Exemple #2
0
        public void Load(BinaryReader reader)
        {
            var version = reader.ReadInt32();

            if (version != WorldVersion)
            {
                Debug.LogError("Unsupport to update");
                // UpdateWorld(version, WorldGenerator.GeneratorVersion);
            }

            worldName          = reader.ReadString();
            worldGeneratorType = reader.ReadString();

            var worldSizeX = reader.ReadInt32();
            var worldSizeZ = reader.ReadInt32();

            var blockSizeX = reader.ReadSingle();
            var blockSizeY = reader.ReadSingle();
            var blockSizeZ = reader.ReadSingle();

            var chunkSizeX = reader.ReadInt32();
            var chunkSizeY = reader.ReadInt32();
            var chunkSizeZ = reader.ReadInt32();

            blockSize = new Vector3(blockSizeX, blockSizeY, blockSizeZ);
            chunkSize = new Vector3Int(chunkSizeX, chunkSizeY, chunkSizeZ);
            worldSize = new ChunkPos(worldSizeX, worldSizeZ);
        }
        public void Generate(string worldName, ChunkPos worldSize, Vector3 blockSize, Vector3Int chunkSize)
        {
            worldInfo = new GameObject().AddComponent <WorldInfo>();

            worldInfo.worldName          = worldName;
            worldInfo.worldGeneratorType = GetType().FullName;
            worldInfo.chunkSize          = chunkSize;
            worldInfo.worldSize          = worldSize;
            worldInfo.blockSize          = blockSize;

            // 获取目录位置
            outDir = Application.persistentDataPath + "/world/" + worldName;

            while (Directory.Exists(outDir))
            {
                outDir += "-";
            }
            outDir += "/";

            Directory.CreateDirectory(outDir);

            worldInfo.worldPath = outDir;

            // 创建世界基本信息
            GenerateWorldInfo();
        }
Exemple #4
0
        public override void GenChunk(ChunkPos chunkPos, ref Block[,,] blocks)
        {
            // 生成地形
            for (var x = 0; x < worldInfo.chunkSize.x; ++x)
            {
                for (var z = 0; z < worldInfo.chunkSize.z; ++z)
                {
                    var height = GetHeight(
                        x + chunkPos.x * worldInfo.chunkSize.x,
                        z + chunkPos.z * worldInfo.chunkSize.z,
                        worldInfo.chunkSize.y / 3 * 2);

                    for (var y = 0; y < worldInfo.chunkSize.y; ++y)
                    {
                        if (y > height)
                        {
                            blocks[x, y, z].blockProxy = air;
                        }
                        else if (y == height)
                        {
                            blocks[x, y, z].blockProxy = grass;
                        }
                        else
                        {
                            blocks[x, y, z].blockProxy = dirt;
                        }
                    }
                }
            }
        }
Exemple #5
0
        public Task AsyncLoadTask(ChunkPos chunkPos)
        {
            ChunkPos = chunkPos;

            var loadBlockTask  = _blockContainer.AsyncLoadTask(ChunkPos);
            var loadEntityTask = _entityContainer.AsyncLoadTask(ChunkPos);

            var loadTask = new Task(() =>
            {
                loadBlockTask.Wait();
                loadEntityTask.Wait();
            });

            loadTask.Start();

#if UNITY_EDITOR
            name = "Chunk: " + ChunkPos.x + ", " + ChunkPos.z;
#endif
            transform.position = new Vector3(
                ChunkPos.x * _blockContainer.ContainerSize.x * _blockContainer.BlockSize.x,
                0,
                ChunkPos.z * _blockContainer.ContainerSize.z * _blockContainer.BlockSize.z);

            return(loadTask);
        }
        /// <summary>
        /// 加载实体
        /// </summary>
        /// <param name="entitys"></param>
        public void LoadEntity(ChunkPos chunkPos, ref List <DataTag> entityDataList)
        {
            var entityDataName = chunkPos.IsGlobal() ? "global" : chunkPos.x + "." + chunkPos.z;

            var loadPath = _dir + "e." + entityDataName + ".dat";

            if (!chunkPos.IsAvailable())
            {
                return;
            }

            // 如果未创建实体信息则生成
            if (!File.Exists(loadPath))
            {
                var worldSize = GameManager.WorldManager.worldInfo.worldSize;
                if (!chunkPos.IsGlobal())
                {
                    if (
                        !(chunkPos.x < 0 || chunkPos.x > worldSize.x ||
                          chunkPos.z < 0 || chunkPos.z > worldSize.z))
                    {
                        GameManager.WorldManager.worldGenerator.GenChunkEntity(chunkPos, ref entityDataList);
                    }
                }
                else
                {
                    GameManager.WorldManager.worldGenerator.GenGlobalEntity(ref entityDataList);
                }
                return;
            }

            var entityStream         = File.OpenRead(loadPath);
            var decompressFileStream = new GZipStream(entityStream, CompressionMode.Decompress);
            var reader = new BinaryReader(decompressFileStream);

            // 加载实体
            var entityCount = reader.ReadInt32();

            for (var i = 0; i < entityCount; ++i)
            {
                var entityData = DataTag.Empty();
                entityData.Load(reader);

                entityDataList.Add(entityData);
            }

            reader.Close();
            decompressFileStream.Close();
            entityStream.Close();
        }
        /// <summary>
        /// 保存实体
        /// </summary>
        /// <param name="entitys"></param>
        public void SaveEntity(ChunkPos chunkPos, List <DataTag> entityDataList)
        {
            if (!chunkPos.IsAvailable())
            {
                return;
            }

            if (!chunkPos.IsGlobal())
            {
                SaveEntity(chunkPos.x + "." + chunkPos.z, entityDataList);
            }
            else
            {
                SaveEntity("global", entityDataList);
            }
        }
Exemple #8
0
        public Task AsyncUnloadTask()
        {
            // 卸载网格
            if (ChunkPos.IsAvailable())
            {
                _chunkMeshGenerator?.Unload();
            }

            if (_unloadTask != null && !_unloadTask.IsCompleted)
            {
                return(_unloadTask);
            }

            var needSave    = IsLoaded;
            var oldChunkPos = ChunkPos;

            IsLoaded = false;
            _isDirty = false;

            // 卸载Chunk
            _unloadTask = new Task(() =>
            {
                if (!oldChunkPos.IsAvailable())
                {
                    return;
                }

                if (needSave)
                {
                    GameManager.WorldManager.worldLoader.SaveBlock(oldChunkPos, _blocks);
                }

                for (var x = 0; x < ContainerSize.x; ++x)
                {
                    for (var y = 0; y < ContainerSize.y; ++y)
                    {
                        for (var z = 0; z < ContainerSize.z; ++z)
                        {
                            _blocks[x, y, z].blockProxy = null;
                        }
                    }
                }
            });
            _unloadTask.Start();

            return(_unloadTask);
        }
Exemple #9
0
        public Task AsyncLoadTask(ChunkPos chunkPos)
        {
            // 加载前结束之前此Chunk所有加载任务
            if (_genChunkTask != null && !_genChunkTask.IsCompleted)
            {
                _cts.Cancel();
            }

            // 卸载已经加载的区块
            if (_unloadTask == null || _unloadTask.IsCompleted)
            {
                _unloadTask = AsyncUnloadTask();
            }

            var oldChunkPos = ChunkPos;

            ChunkPos = chunkPos;

            _genChunkTask = new Task(() =>
            {
                // 等待卸载任务完成
                _unloadTask.Wait();

                _cts = new CancellationTokenSource();

                // 加载Chunk
                _genChunkTask = new Task(() =>
                {
                    GameManager.WorldManager.worldLoader.LoadBlock(chunkPos, ref _blocks);
                    IsLoaded = true;
                }, _cts.Token);

                // 等待区块加载完成
                _genChunkTask.Start();
                _genChunkTask.Wait();

                _isDirty = true;
            });

            _genChunkTask.Start();

            return(_genChunkTask);
        }
Exemple #10
0
 public static float Distance(ChunkPos chunkPos1, ChunkPos chunkPos2)
 {
     return(Mathf.Sqrt(Mathf.Pow(chunkPos1.x - chunkPos2.x, 2) + Mathf.Pow(chunkPos1.z - chunkPos2.z, 2)));
 }
 public abstract void GenChunkEntity(ChunkPos chunkPos, ref List <DataTag> entityData);
 public abstract void GenChunk(ChunkPos chunkPos, ref Block[,,] blocks);
Exemple #13
0
        public override void GenChunkEntity(ChunkPos chunkPos, ref List <DataTag> entityData)
        {
            var count = _random.Next() % 50 + 1;

            for (var i = 0; i < count; ++i)
            {
                var x = _random.Next() % 16;
                var z = _random.Next() % 16;

                var height = GetHeight(
                    chunkPos.x * worldInfo.chunkSize.x + x,
                    chunkPos.z * worldInfo.chunkSize.z + z,
                    worldInfo.chunkSize.y / 3 * 2);

                var pos = new Vector3(
                    chunkPos.x * worldInfo.chunkSize.x + (x + 0.5f) * worldInfo.blockSize.x,
                    height * worldInfo.blockSize.y,
                    chunkPos.z * worldInfo.chunkSize.z + (z + 0.5f) * worldInfo.blockSize.z);

                var type = _random.Next(0, 3);

                if (type == 0)
                {
                    var envElement = new DataTag(
                        new Dictionary <string, object>
                    {
                        {
                            "name", "EnvElement"
                        },
                        {
                            "type", "island.entity:env_element"
                        },
                        {
                            "position", pos
                        },
                        {
                            "envElement", "island.env_element:withered_grass"
                        }
                    }
                        );
                    entityData.Add(envElement);
                }
                else if (type == 1)
                {
                    var envElement = new DataTag(
                        new Dictionary <string, object>
                    {
                        {
                            "name", "EnvElement"
                        },
                        {
                            "type", "island.entity:env_element"
                        },
                        {
                            "position", pos
                        },
                        {
                            "envElement", "island.env_element:grass"
                        }
                    }
                        );
                    entityData.Add(envElement);
                }
                else if (type == 2)
                {
                    var dropStone = new DataTag(
                        new Dictionary <string, object>
                    {
                        {
                            "name", "DropStone"
                        },
                        {
                            "type", "island.entity:drop_item"
                        },
                        {
                            "position", pos + Vector3.up * 0.5f
                        },
                        {
                            "item", "island.item:stone"
                        },
                        {
                            "itemCount", 1
                        }
                    }
                        );
                    entityData.Add(dropStone);
                }
            }

            if (chunkPos.x == 1 && chunkPos.z == 1)
            {
                var height2 = GetHeight(
                    chunkPos.x * worldInfo.chunkSize.x,
                    chunkPos.z * worldInfo.chunkSize.z,
                    worldInfo.chunkSize.y / 3 * 2);

                var pos2 = new Vector3(
                    chunkPos.x * worldInfo.chunkSize.x + 0.5f * worldInfo.blockSize.x,
                    height2 * worldInfo.blockSize.y,
                    chunkPos.z * worldInfo.chunkSize.z + 0.5f * worldInfo.blockSize.z);

                var chest = new DataTag(
                    new Dictionary <string, object>
                {
                    {
                        "name", "Chest"
                    },
                    {
                        "type", "island.entity:chest"
                    },
                    {
                        "position", pos2 - Vector3.left
                    }
                }
                    );

                entityData.Add(chest);

                var craftTable = new DataTag(
                    new Dictionary <string, object>
                {
                    {
                        "name", "CraftTable"
                    },
                    {
                        "position", pos2 + Vector3.left
                    },
                    {
                        "type", "island.entity:craft_table"
                    }
                }
                    );
                entityData.Add(craftTable);
            }
        }
        public void LoadBlock(ChunkPos chunkPos, ref Block[,,] blocks)
        {
            if (_dir == "")
            {
                Debug.LogError("Not load world");
                return;
            }

            if (!chunkPos.IsAvailable())
            {
                return;
            }

            var chunkFilePath    = _dir + "c." + chunkPos.x + "." + chunkPos.z + ".dat";
            var chunkTmpFilePath = chunkFilePath + ".tmp";

            while (File.Exists(chunkTmpFilePath))
            {
                Thread.Yield();
            }

            var chunkSize = GameManager.WorldManager.ChunkSize;

            // Chunk不存在
            var isChunkExists = File.Exists(chunkFilePath);

            if (!isChunkExists)
            {
                var worldSize = GameManager.WorldManager.worldInfo.worldSize;
                if (chunkPos.x < 0 || chunkPos.x > worldSize.x ||
                    chunkPos.z < 0 || chunkPos.z > worldSize.z)
                {
                    for (var x = 0; x < chunkSize.x; ++x)
                    {
                        for (var y = 0; y < chunkSize.y; ++y)
                        {
                            for (var z = 0; z < chunkSize.z; ++z)
                            {
                                blocks[x, y, z].ReadFrom(null, null);
                            }
                        }
                    }
                }
                else
                {
                    GameManager.WorldManager.worldGenerator.GenChunk(chunkPos, ref blocks);
                }

                return;
            }

            var chunkStream          = File.OpenRead(chunkFilePath);
            var decompressFileStream = new GZipStream(chunkStream, CompressionMode.Decompress);
            var reader = new BinaryReader(decompressFileStream);

            // 读取索引表
            var indexSize  = reader.ReadInt32();
            var blockIndex = new List <IBlock>(indexSize);

            for (var i = 0; i < indexSize; ++i)
            {
                var blockName = reader.ReadString();
                blockIndex.Add(GameManager.ProxyManager.Get <IBlock>(blockName));
            }

            for (var x = 0; x < chunkSize.x; ++x)
            {
                for (var y = 0; y < chunkSize.y; ++y)
                {
                    for (var z = 0; z < chunkSize.z; ++z)
                    {
                        blocks[x, y, z].ReadFrom(reader, blockIndex);
                    }
                }
            }

            reader.Close();
            decompressFileStream.Close();
            chunkStream.Close();
        }
        public void SaveBlock(ChunkPos chunkPos, Block[,,] blocks)
        {
            if (_dir == "")
            {
                Debug.LogError("Not load world");
                return;
            }

            if (!chunkPos.IsAvailable())
            {
                return;
            }

            var chunkSize = GameManager.WorldManager.ChunkSize;

            var savePath           = _dir + "c." + chunkPos.x + "." + chunkPos.z + ".dat";
            var saveTmpPath        = savePath + ".tmp";
            var chunkStream        = File.Create(saveTmpPath);
            var compressFileStream = new GZipStream(chunkStream, CompressionMode.Compress);
            var writer             = new BinaryWriter(compressFileStream);

            // 创建索引表
            List <string> blockIndex = new List <string>();

            for (var x = 0; x < chunkSize.x; ++x)
            {
                for (var y = 0; y < chunkSize.y; ++y)
                {
                    for (var z = 0; z < chunkSize.z; ++z)
                    {
                        var blockData = blocks[x, y, z].blockProxy;
                        var blockName = blockData == null ? "island.block:air" : blockData.Name;
                        if (!blockIndex.Contains(blockName))
                        {
                            blockIndex.Add(blockName);
                        }
                    }
                }
            }

            // 写入索引表
            writer.Write(blockIndex.Count);

            foreach (var str in blockIndex)
            {
                writer.Write(str);
            }

            // 写入Block信息
            for (var x = 0; x < chunkSize.x; ++x)
            {
                for (var y = 0; y < chunkSize.y; ++y)
                {
                    for (var z = 0; z < chunkSize.z; ++z)
                    {
                        blocks[x, y, z].WriteTo(writer, blockIndex);
                    }
                }
            }

            writer.Close();
            compressFileStream.Close();
            chunkStream.Close();

            // 复制文件
            File.Copy(saveTmpPath, savePath, true);

            // 删除临时文件
            File.Delete(saveTmpPath);
        }