소스 검색

add OreGeneratorGrain

jstzwj 6 년 전
부모
커밋
3d541b334f

+ 1 - 1
README-zh.md

@@ -23,7 +23,7 @@ MineCase
 ## 安装
 
 ## 从源码编译安装
-* 1 . 下载并安装 [.NET Core sdk 2.0](https://www.microsoft.com/net/download)。
+* 1 . 下载并安装 [.NET Core sdk](https://www.microsoft.com/net/download)。
 * 2 . 下载并安装 [MongoDB](https://www.mongodb.com/download-center?jmp=nav#community)。
 * 3 . 从 [github page](https://github.com/dotnetGame/MineCase/archive/master.zip) 下载`MineCase`(或者使用 **clone:** 指令)。
 	```bash

+ 3 - 1
README.md

@@ -11,6 +11,8 @@ The project is designed to create a high-performance, distributed system by usin
 Different chunks are managed by different servers so that all players can play in a world. This makes minecraft servers more scalable.
 It written in `C#` with `.NET Core 2.0` env and based on `orleans` framework to work with released [1.12 protocol](https://minecraft.net/en-us/article/minecraft-112-pre-release-6).
 
+**MineCase is not stable and lack of many features now. Please don't use MineCase in production unless you know what you're doing.**
+
 ![Screenshots](screenshots/1.jpg)
 
 ## Run Requirements
@@ -18,7 +20,7 @@ It written in `C#` with `.NET Core 2.0` env and based on `orleans` framework to
 * [MongoDB](https://www.mongodb.com/download-center/community)
 
 ## Install (Build From Source)
-* 1 . Download and install a `.NET Core sdk 2.0` from this [page](https://www.microsoft.com/net/download).
+* 1 . Download and install a `.NET Core sdk` from this [page](https://www.microsoft.com/net/download).
 * 2 . Download and install a `MongoDB` from this [page](https://www.mongodb.com/download-center?jmp=nav#community).
 * 3 . Download a `MineCase` archive from the [github page](https://github.com/dotnetGame/MineCase/archive/master.zip)  (or **clone:**)
 	```bash

+ 13 - 0
doc/readme-zh.md

@@ -0,0 +1,13 @@
+# Minecase文档
+
+## 概要
+
+本文件夹包含着MineCase项目的文档。文档分为两部分,一部分是用户指南,一部分是开发者手册。
+
+## 用户指南
+
+这部分文档提供给MineCase的用户,文档描述了MineCase的一些主要概念,安装方法,配置方法以及常见问题。
+
+## 开发者指南
+
+这部分文档提供给想要开发MineCase的开发者,文档描述了MineCase如何从源码编译,源码中主要的文件夹的功能以及项目的功能,以及如何参与到MineCase开发中来。

+ 8 - 2
doc/user/readme-zh.md

@@ -5,7 +5,7 @@ MineCase的部署方式和普通服务器一样方便。MineCase的程序主要
 
 ## 安装
 
-### 从源码安装
+#### 从源码安装
 * 1 . 下载并安装 [.NET Core sdk 2.0](https://www.microsoft.com/net/download)。
 * 2 . 下载并安装 [MongoDB](https://www.mongodb.com/download-center?jmp=nav#community)。
 * 3 . 从 [github page](https://github.com/dotnetGame/MineCase/archive/master.zip) 下载`MineCase`(或者使用 **clone:** 指令)。
@@ -19,9 +19,15 @@ MineCase的部署方式和普通服务器一样方便。MineCase的程序主要
     * **Linux** : 运行 `build_and_run.sh`.
     * **Win** : 双击 `build_and_run.bat`.
 
-### 使用二进制安装
+#### 使用二进制安装
 * 1 . 暂不提供
 
+
+
+## 升级
+
+* 目前暂不提供升级方案
+
 ## 使用方法
 
 

+ 1 - 0
src/MineCase.Core/Block/Block.cs

@@ -36,6 +36,7 @@ namespace MineCase.Block
 
         /** true if the Block contains a Tile Entity */
         protected bool IsBlockContainer { get; set; }
+
         /** Sound of stepping on the block */
         protected SoundType BlockSoundType { get; set; }
 

+ 24 - 3
src/MineCase.Server.Grains/World/Decoration/Biomes/BiomeDecoratorGrain.cs

@@ -5,9 +5,11 @@ using System.Threading.Tasks;
 using MineCase.Algorithm.Noise;
 using MineCase.Block;
 using MineCase.Server.Game.Entities;
+using MineCase.Server.World.Decoration.Mine;
 using MineCase.Server.World.Decoration.Plants;
 using MineCase.World;
 using MineCase.World.Biomes;
+using MineCase.World.Generation;
 using MineCase.World.Plants;
 using Orleans;
 
@@ -15,6 +17,8 @@ namespace MineCase.Server.World.Decoration.Biomes
 {
     public abstract class BiomeDecoratorGrain : Grain, IBiomeDecorator
     {
+        public GeneratorSettings GenSettings { get; set; } = new GeneratorSettings();
+
         public BiomeProperties BiomeProperties { get; set; } = new BiomeProperties();
 
         /** The block expected to be on the top of this biome */
@@ -38,17 +42,34 @@ namespace MineCase.Server.World.Decoration.Biomes
 
         public List<MobType> MonsterList { get; set; } = new List<MobType>();
 
-        public virtual Task Decorate(IWorld world, ChunkWorldPos chunkWorldPos)
+        protected async Task GenerateOre(IWorld world, ChunkWorldPos chunkWorldPos, GeneratorSettings settings)
+        {
+            var oreGenerator = GrainFactory.GetGrain<IMinableGenerator>(0);
+            await oreGenerator.Generate(world, chunkWorldPos, BlockStates.Dirt(), settings.DirtCount, settings.DirtSize, settings.DirtMinHeight, settings.DirtMaxHeight);
+            await oreGenerator.Generate(world, chunkWorldPos, BlockStates.Gravel(), settings.GravelCount, settings.GravelSize, settings.GravelMinHeight, settings.GravelMaxHeight);
+            await oreGenerator.Generate(world, chunkWorldPos, BlockStates.Stone(StoneType.Granite), settings.GraniteCount, settings.GraniteSize, settings.GraniteMinHeight, settings.GraniteMaxHeight);
+            await oreGenerator.Generate(world, chunkWorldPos, BlockStates.Stone(StoneType.Diorite), settings.DioriteCount, settings.DioriteSize, settings.DioriteMinHeight, settings.DioriteMaxHeight);
+            await oreGenerator.Generate(world, chunkWorldPos, BlockStates.Stone(StoneType.Andesite), settings.AndesiteCount, settings.AndesiteSize, settings.AndesiteMinHeight, settings.AndesiteMaxHeight);
+
+            await oreGenerator.Generate(world, chunkWorldPos, BlockStates.CoalOre(), settings.CoalCount, settings.CoalSize, settings.CoalMinHeight, settings.CoalMaxHeight);
+            await oreGenerator.Generate(world, chunkWorldPos, BlockStates.IronOre(), settings.IronCount, settings.IronSize, settings.IronMinHeight, settings.IronMaxHeight);
+            await oreGenerator.Generate(world, chunkWorldPos, BlockStates.GoldOre(), settings.GoldCount, settings.GoldSize, settings.GoldMinHeight, settings.GoldMaxHeight);
+            await oreGenerator.Generate(world, chunkWorldPos, BlockStates.DiamondOre(), settings.DiamondCount, settings.DiamondSize, settings.DiamondMinHeight, settings.DiamondMaxHeight);
+            await oreGenerator.Generate(world, chunkWorldPos, BlockStates.RedstoneOre(), settings.RedstoneCount, settings.RedstoneSize, settings.RedstoneMinHeight, settings.RedstoneMaxHeight);
+            await oreGenerator.Generate(world, chunkWorldPos, BlockStates.LapisLazuliOre(), settings.LapisCount, settings.LapisSize, settings.LapisCenterHeight - settings.LapisSpread, settings.LapisCenterHeight + settings.LapisSpread);
+        }
+
+        public virtual Task Decorate(IWorld world, ChunkWorldPos chunkWorldPos, GeneratorSettings settings)
         {
             throw new NotImplementedException();
         }
 
-        public virtual Task SpawnMob(IWorld world, ChunkWorldPos chunkWorldPos)
+        public virtual Task SpawnMob(IWorld world, ChunkWorldPos chunkWorldPos, GeneratorSettings settings)
         {
             throw new NotImplementedException();
         }
 
-        public virtual Task SpawnMonster(IWorld world, ChunkWorldPos chunkWorldPos)
+        public virtual Task SpawnMonster(IWorld world, ChunkWorldPos chunkWorldPos, GeneratorSettings settings)
         {
             throw new NotImplementedException();
         }

+ 6 - 3
src/MineCase.Server.Grains/World/Decoration/Biomes/BiomeForestDecoratorGrain.cs

@@ -7,6 +7,7 @@ using MineCase.Server.Game.Entities;
 using MineCase.Server.World.Decoration.Plants;
 using MineCase.World;
 using MineCase.World.Biomes;
+using MineCase.World.Generation;
 using MineCase.World.Plants;
 using Newtonsoft.Json;
 using Orleans;
@@ -50,8 +51,10 @@ namespace MineCase.Server.World.Decoration.Biomes
             return Task.CompletedTask;
         }
 
-        public async override Task Decorate(IWorld world, ChunkWorldPos chunkWorldPos)
+        public async override Task Decorate(IWorld world, ChunkWorldPos chunkWorldPos, GeneratorSettings settings)
         {
+            await GenerateOre(world, chunkWorldPos, settings);
+
             var grassGenerator = GrainFactory.GetGrain<IGrassGenerator>(JsonConvert.SerializeObject(new PlantsInfo { }));
             await grassGenerator.Generate(world, chunkWorldPos, 10);
 
@@ -84,12 +87,12 @@ namespace MineCase.Server.World.Decoration.Biomes
             await dandelionGenerator.Generate(world, chunkWorldPos, 3);
         }
 
-        public override Task SpawnMob(IWorld world, ChunkWorldPos chunkWorldPos)
+        public override Task SpawnMob(IWorld world, ChunkWorldPos chunkWorldPos, GeneratorSettings settings)
         {
             throw new NotImplementedException();
         }
 
-        public override Task SpawnMonster(IWorld world, ChunkWorldPos chunkWorldPos)
+        public override Task SpawnMonster(IWorld world, ChunkWorldPos chunkWorldPos, GeneratorSettings settings)
         {
             throw new NotImplementedException();
         }

+ 6 - 3
src/MineCase.Server.Grains/World/Decoration/Biomes/BiomeHillDecoratorGrain.cs

@@ -7,6 +7,7 @@ using MineCase.Server.Game.Entities;
 using MineCase.Server.World.Decoration.Plants;
 using MineCase.World;
 using MineCase.World.Biomes;
+using MineCase.World.Generation;
 using MineCase.World.Plants;
 using Newtonsoft.Json;
 using Orleans;
@@ -64,8 +65,10 @@ namespace MineCase.Server.World.Decoration.Biomes
             return Task.CompletedTask;
         }
 
-        public async override Task Decorate(IWorld world, ChunkWorldPos chunkWorldPos)
+        public async override Task Decorate(IWorld world, ChunkWorldPos chunkWorldPos, GeneratorSettings settings)
         {
+            await GenerateOre(world, chunkWorldPos, settings);
+
             var grassGenerator = GrainFactory.GetGrain<IGrassGenerator>(JsonConvert.SerializeObject(new PlantsInfo { }));
             await grassGenerator.Generate(world, chunkWorldPos, 10);
 
@@ -91,12 +94,12 @@ namespace MineCase.Server.World.Decoration.Biomes
             await oaktreeGenerator.Generate(world, chunkWorldPos, 1);
         }
 
-        public override Task SpawnMob(IWorld world, ChunkWorldPos chunkWorldPos)
+        public override Task SpawnMob(IWorld world, ChunkWorldPos chunkWorldPos, GeneratorSettings settings)
         {
             throw new NotImplementedException();
         }
 
-        public override Task SpawnMonster(IWorld world, ChunkWorldPos chunkWorldPos)
+        public override Task SpawnMonster(IWorld world, ChunkWorldPos chunkWorldPos, GeneratorSettings settings)
         {
             throw new NotImplementedException();
         }

+ 5 - 4
src/MineCase.Server.Grains/World/Decoration/Biomes/BiomeOceanDecoratorGrain.cs

@@ -7,6 +7,7 @@ using MineCase.Server.Game.Entities;
 using MineCase.Server.World.Decoration.Plants;
 using MineCase.World;
 using MineCase.World.Biomes;
+using MineCase.World.Generation;
 using MineCase.World.Plants;
 using Orleans;
 using Orleans.Concurrency;
@@ -54,17 +55,17 @@ namespace MineCase.Server.World.Decoration.Biomes
             return Task.CompletedTask;
         }
 
-        public override Task Decorate(IWorld world, ChunkWorldPos chunkWorldPos)
+        public async override Task Decorate(IWorld world, ChunkWorldPos chunkWorldPos, GeneratorSettings settings)
         {
-            return Task.CompletedTask;
+            await GenerateOre(world, chunkWorldPos, settings);
         }
 
-        public override Task SpawnMob(IWorld world, ChunkWorldPos chunkWorldPos)
+        public override Task SpawnMob(IWorld world, ChunkWorldPos chunkWorldPos, GeneratorSettings settings)
         {
             throw new NotImplementedException();
         }
 
-        public override Task SpawnMonster(IWorld world, ChunkWorldPos chunkWorldPos)
+        public override Task SpawnMonster(IWorld world, ChunkWorldPos chunkWorldPos, GeneratorSettings settings)
         {
             throw new NotImplementedException();
         }

+ 7 - 3
src/MineCase.Server.Grains/World/Decoration/Biomes/BiomePlainsDecoratorGrain.cs

@@ -4,9 +4,11 @@ using System.Text;
 using System.Threading.Tasks;
 using MineCase.Block;
 using MineCase.Server.Game.Entities;
+using MineCase.Server.World.Decoration.Mine;
 using MineCase.Server.World.Decoration.Plants;
 using MineCase.World;
 using MineCase.World.Biomes;
+using MineCase.World.Generation;
 using MineCase.World.Plants;
 using Newtonsoft.Json;
 using Orleans;
@@ -66,8 +68,10 @@ namespace MineCase.Server.World.Decoration.Biomes
             return Task.CompletedTask;
         }
 
-        public async override Task Decorate(IWorld world, ChunkWorldPos chunkWorldPos)
+        public async override Task Decorate(IWorld world, ChunkWorldPos chunkWorldPos, GeneratorSettings settings)
         {
+            await GenerateOre(world, chunkWorldPos, settings);
+
             var grassGenerator = GrainFactory.GetGrain<IGrassGenerator>(JsonConvert.SerializeObject(new PlantsInfo { }));
             await grassGenerator.Generate(world, chunkWorldPos, 10);
 
@@ -93,12 +97,12 @@ namespace MineCase.Server.World.Decoration.Biomes
             await oaktreeGenerator.Generate(world, chunkWorldPos, 1);
         }
 
-        public override Task SpawnMob(IWorld world, ChunkWorldPos chunkWorldPos)
+        public override Task SpawnMob(IWorld world, ChunkWorldPos chunkWorldPos, GeneratorSettings settings)
         {
             throw new NotImplementedException();
         }
 
-        public override Task SpawnMonster(IWorld world, ChunkWorldPos chunkWorldPos)
+        public override Task SpawnMonster(IWorld world, ChunkWorldPos chunkWorldPos, GeneratorSettings settings)
         {
             throw new NotImplementedException();
         }

+ 4 - 3
src/MineCase.Server.Grains/World/Decoration/Biomes/BiomeSavannaDecoratorGrain.cs

@@ -3,22 +3,23 @@ using System.Collections.Generic;
 using System.Text;
 using System.Threading.Tasks;
 using MineCase.World;
+using MineCase.World.Generation;
 
 namespace MineCase.Server.World.Decoration.Biomes
 {
     public class BiomeSavannaDecoratorGrain : BiomeDecoratorGrain, IBiomeSavannaDecorator
     {
-        public override Task Decorate(IWorld world, ChunkWorldPos chunkWorldPos)
+        public override Task Decorate(IWorld world, ChunkWorldPos chunkWorldPos, GeneratorSettings settings)
         {
             throw new NotImplementedException();
         }
 
-        public override Task SpawnMob(IWorld world, ChunkWorldPos chunkWorldPos)
+        public override Task SpawnMob(IWorld world, ChunkWorldPos chunkWorldPos, GeneratorSettings settings)
         {
             throw new NotImplementedException();
         }
 
-        public override Task SpawnMonster(IWorld world, ChunkWorldPos chunkWorldPos)
+        public override Task SpawnMonster(IWorld world, ChunkWorldPos chunkWorldPos, GeneratorSettings settings)
         {
             throw new NotImplementedException();
         }

+ 6 - 3
src/MineCase.Server.Grains/World/Decoration/Biomes/BiomeTaigaDecoratorGrain.cs

@@ -7,6 +7,7 @@ using MineCase.Server.Game.Entities;
 using MineCase.Server.World.Decoration.Plants;
 using MineCase.World;
 using MineCase.World.Biomes;
+using MineCase.World.Generation;
 using MineCase.World.Plants;
 using Newtonsoft.Json;
 using Orleans;
@@ -56,8 +57,10 @@ namespace MineCase.Server.World.Decoration.Biomes
             return Task.CompletedTask;
         }
 
-        public async override Task Decorate(IWorld world, ChunkWorldPos chunkWorldPos)
+        public async override Task Decorate(IWorld world, ChunkWorldPos chunkWorldPos, GeneratorSettings settings)
         {
+            await GenerateOre(world, chunkWorldPos, settings);
+
             var grassGenerator = GrainFactory.GetGrain<IGrassGenerator>(JsonConvert.SerializeObject(new PlantsInfo { }));
             await grassGenerator.Generate(world, chunkWorldPos, 4);
 
@@ -90,12 +93,12 @@ namespace MineCase.Server.World.Decoration.Biomes
             await dandelionGenerator.Generate(world, chunkWorldPos, 1);
         }
 
-        public override Task SpawnMob(IWorld world, ChunkWorldPos chunkWorldPos)
+        public override Task SpawnMob(IWorld world, ChunkWorldPos chunkWorldPos, GeneratorSettings settings)
         {
             throw new NotImplementedException();
         }
 
-        public override Task SpawnMonster(IWorld world, ChunkWorldPos chunkWorldPos)
+        public override Task SpawnMonster(IWorld world, ChunkWorldPos chunkWorldPos, GeneratorSettings settings)
         {
             throw new NotImplementedException();
         }

+ 134 - 0
src/MineCase.Server.Grains/World/Decoration/Mine/MinableGeneratorGrain.cs

@@ -0,0 +1,134 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading.Tasks;
+using MineCase.Block;
+using MineCase.World;
+using Orleans;
+using Orleans.Concurrency;
+
+namespace MineCase.Server.World.Decoration.Mine
+{
+    [StatelessWorker]
+    public class MinableGeneratorGrain : Grain, IMinableGenerator
+    {
+        public async Task Generate(IWorld world, ChunkWorldPos chunkWorldPos, BlockState blockState, int count, int size, int minHeight, int maxHeight)
+        {
+            int seed = await world.GetSeed();
+
+            BlockWorldPos curChunkCorner = chunkWorldPos.ToBlockWorldPos();
+
+            int chunkSeed = chunkWorldPos.X ^ chunkWorldPos.Z ^ seed ^ blockState.GetHashCode();
+            Random random = new Random(chunkSeed);
+
+            if (minHeight > maxHeight)
+            {
+                int tmp = minHeight;
+                minHeight = maxHeight;
+                maxHeight = tmp;
+            }
+            else if (maxHeight == minHeight)
+            {
+                if (minHeight < 255)
+                    ++maxHeight;
+                else
+                    --minHeight;
+            }
+
+            for (int j = 0; j < count; ++j)
+            {
+                BlockWorldPos blockpos = BlockWorldPos.Add(
+                    curChunkCorner,
+                    random.Next(16),
+                    random.Next(maxHeight - minHeight) + minHeight,
+                    random.Next(16));
+                await GenerateSingle(world, chunkWorldPos, blockpos, blockState, size);
+            }
+        }
+
+        public async Task GenerateSingle(IWorld world, ChunkWorldPos chunkWorldPos, BlockWorldPos pos, BlockState state, int size)
+        {
+            int seed = await world.GetSeed();
+
+            int oreSeed = pos.X ^ pos.Z ^ seed ^ state.GetHashCode();
+            Random random = new Random(oreSeed);
+
+            await GenerateImpl(world, chunkWorldPos, pos, state, size, random);
+        }
+
+        private async Task GenerateImpl(IWorld world, ChunkWorldPos chunkWorldPos, BlockWorldPos pos, BlockState state, int size, Random rand)
+        {
+            // 在xz平面上的方向
+            float angle = (float)rand.NextDouble() * (float)Math.PI;
+
+            // 起始点和结束点
+            double startX = (double)((float)(pos.X + 8) + Math.Sin(angle) * (float)size / 8.0F);
+            double endX = (double)((float)(pos.X + 8) - Math.Sin(angle) * (float)size / 8.0F);
+            double startZ = (double)((float)(pos.Z + 8) + Math.Cos(angle) * (float)size / 8.0F);
+            double endZ = (double)((float)(pos.Z + 8) - Math.Cos(angle) * (float)size / 8.0F);
+            double startY = (double)(pos.Y + rand.Next(3) - 2);
+            double endY = (double)(pos.Y + rand.Next(3) - 2);
+
+            for (int i = 0; i < size; ++i)
+            {
+                // 插值参数
+                float t = (float)i / (float)size;
+
+                // 椭球中心
+                double centerX = startX + (endX - startX) * (double)t;
+                double centerY = startY + (endY - startY) * (double)t;
+                double centerZ = startZ + (endZ - startZ) * (double)t;
+
+                // 椭球尺寸(可以看出XZ和Y尺寸一样,应该是球)
+                double scale = rand.NextDouble() * (double)size / 16.0D;
+                double diameterXZ = (double)(Math.Sin((float)Math.PI * t) + 1.0F) * scale + 1.0D;
+                double diameterY = (double)(Math.Sin((float)Math.PI * t) + 1.0F) * scale + 1.0D;
+
+                // 椭球包围盒
+                int minX = (int)Math.Floor(centerX - diameterXZ / 2.0D);
+                int minY = (int)Math.Floor(centerY - diameterY / 2.0D);
+                int minZ = (int)Math.Floor(centerZ - diameterXZ / 2.0D);
+                int maxX = (int)Math.Floor(centerX + diameterXZ / 2.0D);
+                int maxY = (int)Math.Floor(centerY + diameterY / 2.0D);
+                int maxZ = (int)Math.Floor(centerZ + diameterXZ / 2.0D);
+
+                // 把这个椭球里的方块替换为矿石
+                for (int x = minX; x <= maxX; ++x)
+                {
+                    double xDist = ((double)x + 0.5D - centerX) / (diameterXZ / 2.0D);
+
+                    // 参考椭球方程
+                    if (xDist * xDist < 1.0D)
+                    {
+                        for (int y = minY; y <= maxY; ++y)
+                        {
+                            double yDist = ((double)y + 0.5D - centerY) / (diameterY / 2.0D);
+
+                            // 参考椭球方程
+                            if (xDist * xDist + yDist * yDist < 1.0D)
+                            {
+                                for (int z = minZ; z <= maxZ; ++z)
+                                {
+                                    double zDist = ((double)z + 0.5D - centerZ) / (diameterXZ / 2.0D);
+
+                                    // 参考椭球方程
+                                    if (xDist * xDist + yDist * yDist + zDist * zDist < 1.0D)
+                                    {
+                                        BlockWorldPos blockpos = new BlockWorldPos(x, y, z);
+                                        if (blockpos.Y >= 0 &&
+                                            blockpos.Y < 255 &&
+                                            (await world.GetBlockState(this.GrainFactory, blockpos)) == BlockStates.Stone())
+                                        {
+                                            // 替换为矿石
+                                            await world.SetBlockState(this.GrainFactory, blockpos, state);
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+}

+ 3 - 3
src/MineCase.Server.Grains/World/Generation/ChunkGeneratorOverworldGrain.cs

@@ -107,19 +107,19 @@ namespace MineCase.Server.World.Generation
             if (chunkBiome.GetBiomeId() == BiomeId.Plains)
             {
                 var decorator = GrainFactory.GetGrain<IBiomePlainsDecorator>((long)BiomeId.Plains);
-                await decorator.Decorate(world, new ChunkWorldPos(x, z));
+                await decorator.Decorate(world, new ChunkWorldPos(x, z), settings);
 
                 // decorator.SpawnMob(world, chunk, new ChunkWorldPos(x, z), new BlockWorldPos { X = blockX, Z = blockZ });
             }
             else if (chunkBiome.GetBiomeId() == BiomeId.Forest)
             {
                 var decorator = GrainFactory.GetGrain<IBiomeForestDecorator>((long)BiomeId.Forest);
-                await decorator.Decorate(world, new ChunkWorldPos(x, z));
+                await decorator.Decorate(world, new ChunkWorldPos(x, z), settings);
             }
             else if (chunkBiome.GetBiomeId() == BiomeId.Taiga)
             {
                 var decorator = GrainFactory.GetGrain<IBiomeTaigaDecorator>((long)BiomeId.Taiga);
-                await decorator.Decorate(world, new ChunkWorldPos(x, z));
+                await decorator.Decorate(world, new ChunkWorldPos(x, z), settings);
             }
         }
 

+ 4 - 3
src/MineCase.Server.Interfaces/World/Decoration/Biomes/IBiomeDecorator.cs

@@ -3,16 +3,17 @@ using System.Collections.Generic;
 using System.Text;
 using System.Threading.Tasks;
 using MineCase.World;
+using MineCase.World.Generation;
 using Orleans;
 
 namespace MineCase.Server.World.Decoration.Biomes
 {
     public interface IBiomeDecorator : IGrainWithIntegerKey
     {
-        Task Decorate(IWorld world, ChunkWorldPos chunkWorldPos);
+        Task Decorate(IWorld world, ChunkWorldPos chunkWorldPos, GeneratorSettings settings);
 
-        Task SpawnMob(IWorld world, ChunkWorldPos chunkWorldPos);
+        Task SpawnMob(IWorld world, ChunkWorldPos chunkWorldPos, GeneratorSettings settings);
 
-        Task SpawnMonster(IWorld world, ChunkWorldPos chunkWorldPos);
+        Task SpawnMonster(IWorld world, ChunkWorldPos chunkWorldPos, GeneratorSettings settings);
     }
 }

+ 15 - 0
src/MineCase.Server.Interfaces/World/Decoration/Mine/IMinableGenerator.cs

@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading.Tasks;
+using MineCase.Block;
+using MineCase.World;
+using Orleans;
+
+namespace MineCase.Server.World.Decoration.Mine
+{
+    public interface IMinableGenerator : IGrainWithIntegerKey
+    {
+        Task Generate(IWorld world, ChunkWorldPos chunkWorldPos, BlockState blockState, int count, int size, int minHeight, int maxHeight);
+    }
+}

+ 15 - 13
src/MineCase.Server.Interfaces/World/WorldExtensions.cs

@@ -58,17 +58,19 @@ namespace MineCase.Server.World
         /// </summary>
         /// <param name="world">The world Grain.</param>
         /// <param name="grainFactory">The grain factory.</param>
-        /// <param name="pos">The position.</param>
+        /// <param name="x">The x.</param>
+        /// <param name="y">The y.</param>
+        /// <param name="z">The z.</param>
         /// <returns>方块类型.</returns>
         public static Task<BlockState> GetBlockState(this IWorld world, IGrainFactory grainFactory, BlockWorldPos pos)
         {
-            var xOffset = MakeRelativeBlockOffset(pos.X);
-            var zOffset = MakeRelativeBlockOffset(pos.Z);
-            var chunkColumnKey = world.MakeAddressByPartitionKey(new ChunkWorldPos(xOffset.chunk, zOffset.chunk));
+            var chunkPos = pos.ToChunkWorldPos();
+            var blockChunkPos = pos.ToBlockChunkPos();
+            var chunkColumnKey = world.MakeAddressByPartitionKey(chunkPos);
             return grainFactory.GetGrain<IChunkColumn>(chunkColumnKey).GetBlockState(
-                xOffset.block,
-                pos.Y,
-                zOffset.block);
+                blockChunkPos.X,
+                blockChunkPos.Y,
+                blockChunkPos.Z);
         }
 
         /// <summary>
@@ -101,13 +103,13 @@ namespace MineCase.Server.World
         /// <param name="state">The state.</param>
         public static Task SetBlockState(this IWorld world, IGrainFactory grainFactory, BlockWorldPos pos, BlockState state)
         {
-            var xOffset = MakeRelativeBlockOffset(pos.X);
-            var zOffset = MakeRelativeBlockOffset(pos.Z);
-            var chunkColumnKey = world.MakeAddressByPartitionKey(new ChunkWorldPos(xOffset.chunk, zOffset.chunk));
+            var chunkPos = pos.ToChunkWorldPos();
+            var blockChunkPos = pos.ToBlockChunkPos();
+            var chunkColumnKey = world.MakeAddressByPartitionKey(chunkPos);
             return grainFactory.GetGrain<IChunkColumn>(chunkColumnKey).SetBlockState(
-                xOffset.block,
-                pos.Y,
-                zOffset.block,
+                blockChunkPos.X,
+                blockChunkPos.Y,
+                blockChunkPos.Z,
                 state);
         }