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); }
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(); }
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; } } } } }
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); } }
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); }
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); }
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);
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); }