protected virtual void TrySetBlock(ChunkColumnStorage chunk, ChunkWorldPos chunkWorldPos, BlockWorldPos pos, BlockState state) { if (pos.ToChunkWorldPos() == chunkWorldPos) { BlockChunkPos blockChunkPos = pos.ToBlockChunkPos(); chunk[blockChunkPos.X, blockChunkPos.Y, blockChunkPos.Z] = state; } }
protected virtual Task <BlockState> GetBlock(IWorld world, ChunkWorldPos chunkWorldPos, BlockWorldPos pos) { var chunkColumnKey = world.MakeAddressByPartitionKey(pos.ToChunkWorldPos()); var chunkGrain = GrainFactory.GetGrain <IChunkColumn>(chunkColumnKey); BlockChunkPos blockChunkPos = pos.ToBlockChunkPos(); return(chunkGrain.GetBlockStateUnsafe(blockChunkPos.X, blockChunkPos.Y, blockChunkPos.Z)); }
public Task <BiomeId> GetBlockBiome(BlockWorldPos pos) { BlockChunkPos blockChunkPos = pos.ToBlockChunkPos(); ChunkWorldPos chunkWorldPos = pos.ToChunkWorldPos(); IWorld world = AttachedObject.GetWorld(); var chunkColumnKey = world.MakeAddressByPartitionKey(new ChunkWorldPos(chunkWorldPos.X, chunkWorldPos.Z)); return(GrainFactory.GetGrain <IChunkColumn>(chunkColumnKey).GetBlockBiome( blockChunkPos.X, blockChunkPos.Z)); }
public bool CanFlowerGrow(PlantsType type, ChunkColumnStorage chunk, BlockChunkPos pos) { if (chunk[pos.X, pos.Y - 1, pos.Z] == BlockStates.GrassBlock() || chunk[pos.X, pos.Y - 1, pos.Z] == BlockStates.Dirt()) { return(true); } else { return(false); } }
public override void Generate(IWorld world, IGrainFactory grainFactory, ChunkColumnCompactStorage chunk, Biome biome, Random random, BlockWorldPos pos) { BlockChunkPos chunkPos = pos.ToBlockChunkPos(); int x = chunkPos.X; int y = chunkPos.Y; int z = chunkPos.Z; // TODO use block accessor if (chunk[x, y, z].IsAir() && chunk[x, y - 1, z] == BlockStates.GrassBlock()) { chunk[x, y, z] = BlockStates.Grass(GrassType.TallGrass); } }
public bool CanMobStand(IWorld world, IGrainFactory grainFactory, IChunkColumnStorage chunk, Random random, BlockChunkPos pos) { // TODO 以后结合boundbox判断 BlockChunkPos downPos = new BlockChunkPos(pos.X, pos.Y - 1, pos.Z); if (chunk[pos.X, pos.Y - 1, pos.Z].IsLightOpacity() == 0) { if (chunk[pos.X, pos.Y, pos.Z] == BlockStates.Air() && chunk[pos.X, pos.Y + 1, pos.Z] == BlockStates.Air()) { return(true); } } return(false); }
public bool CanTreeGrow(IWorld world, IGrainFactory grainFactory, ChunkColumnCompactStorage chunk, Biome biome, Random random, BlockWorldPos pos, int height) { bool result = true; // 检查所有方块可替换 for (int y = pos.Y; y <= pos.Y + 1 + height; ++y) { int xzSize = 1; // 底端 if (y == pos.Y) { xzSize = 0; } // 顶端 if (y >= pos.Y + height - 1) { xzSize = 2; } // 检查这个平面所有方块可替换 for (int x = pos.X - xzSize; x <= pos.X + xzSize && result; ++x) { for (int z = pos.Z - xzSize; z <= pos.Z + xzSize && result; ++z) { if (y >= 0 && y < 256) { BlockChunkPos chunkPos = pos.ToBlockChunkPos(); BlockState state = chunk[chunkPos.X, chunkPos.Y, chunkPos.Z]; if (!state.IsAir() && state.IsSameId(BlockStates.Leaves()) && state.IsSameId(BlockStates.Leaves2())) { result = false; } } else { result = false; } } } } return(result); }
public override void Generate(IWorld world, IGrainFactory grainFactory, ChunkColumnStorage chunk, Biome biome, Random random, BlockWorldPos pos) { int num = random.Next(_flowersMaxNum); for (int i = 0; i < num; ++i) { BlockWorldPos blockpos = BlockWorldPos.Add(pos, random.Next(8), random.Next(4), random.Next(8)); BlockChunkPos chunkpos = blockpos.ToBlockChunkPos(); if (chunk[chunkpos.X, chunkpos.Y, chunkpos.Z].IsAir() && blockpos.Y < 254 && CanFlowerGrow(_flowerType, chunk, chunkpos)) { chunk[chunkpos.X, chunkpos.Y, chunkpos.Z] = BlockStates.LargeFlowers(LargeFlowerType.Sunflower); chunk[chunkpos.X, chunkpos.Y + 1, chunkpos.Z] = BlockStates.LargeFlowers(LargeFlowerType.TopHalfFlag); } } }
public override void Generate(IWorld world, IGrainFactory grainFactory, ChunkColumnCompactStorage chunk, Biome biome, Random random, BlockWorldPos pos) { int num = random.Next(_grassMaxNum); for (int i = 0; i < num; ++i) { BlockWorldPos blockpos = BlockWorldPos.Add(pos, random.Next(8), random.Next(4), random.Next(8)); BlockChunkPos chunkpos = blockpos.ToBlockChunkPos(); if (chunk[chunkpos.X, chunkpos.Y, chunkpos.Z].IsAir() && blockpos.Y < 254 && CanGrassGrow(_grassType, chunk, chunkpos)) { chunk[chunkpos.X, chunkpos.Y, chunkpos.Z] = BlockStates.TallGrass(TallGrassHalfType.Lower); chunk[chunkpos.X, chunkpos.Y + 1, chunkpos.Z] = BlockStates.TallGrass(TallGrassHalfType.Upper); } } }
public override void Generate(IWorld world, IGrainFactory grainFactory, ChunkColumnStorage chunk, Biome biome, Random random, BlockWorldPos pos) { int height = random.Next(3) + _minCactiHeight; BlockChunkPos chunkPos = pos.ToBlockChunkPos(); // 不超出世界边界 if (pos.Y >= 1 && pos.Y + height + 1 <= 256) { if (CanCactiGrow(world, grainFactory, chunk, biome, random, pos, height)) { BlockState state = chunk[chunkPos.X, chunkPos.Y - 1, chunkPos.Z]; if (CanSustainCacti(state)) { for (int y = 0; y < height; ++y) { chunk[chunkPos.X, chunkPos.Y + y, chunkPos.Z] = BlockStates.Cactus(CactusType.Interval15); } } } } }
public override void Generate(IWorld world, IGrainFactory grainFactory, ChunkColumnCompactStorage chunk, Biome biome, Random random, BlockWorldPos pos) { BlockChunkPos chunkPos = pos.ToBlockChunkPos(); int x = chunkPos.X; int y = chunkPos.Y; int z = chunkPos.Z; // TODO use block accessor if (chunk[x, y, z].IsAir() && chunk[x, y - 1, z] == BlockStates.GrassBlock()) { var flowerType = biome.GetRandomFlower(random); switch (flowerType) { case PlantsType.Poppy: chunk[x, y, z] = BlockStates.Poppy(); break; case PlantsType.Dandelion: chunk[x, y, z] = BlockStates.Dandelion(); break; } } }
public override void Generate(IWorld world, IGrainFactory grainFactory, ChunkColumnCompactStorage chunk, Biome biome, Random random, BlockWorldPos pos) { int height = random.Next(3) + _minTreeHeight; // 不超出世界边界 if (pos.Y >= 1 && pos.Y + height + 1 <= 256) { bool canTreeGrow = CanTreeGrow(world, grainFactory, chunk, biome, random, pos, height); if (canTreeGrow) { BlockWorldPos downPos = new BlockWorldPos(pos.X, pos.Y - 1, pos.Z); BlockChunkPos chunkDownPos = downPos.ToBlockChunkPos(); BlockState downBlock = chunk[chunkDownPos.X, chunkDownPos.Y, chunkDownPos.Z]; // 是可生成树的土壤 bool isSoil = CanSustainTree(_treeType, downBlock); if (isSoil && pos.Y < 256 - height - 1) { // 生成叶子 for (int y = pos.Y + height - 3; y <= pos.Y + height; ++y) { int restHeight = y - (pos.Y + height); int xzSize = 1 - restHeight / 2; for (int x = pos.X - xzSize; x <= pos.X + xzSize; ++x) { int xOffset = x - pos.X; for (int z = pos.Z - xzSize; z <= pos.Z + xzSize; ++z) { int zOffset = z - pos.Z; if (Math.Abs(xOffset) != xzSize || Math.Abs(zOffset) != xzSize || // 不在边缘4个点 (random.Next(2) != 0 && restHeight != 0)) { BlockWorldPos blockpos = new BlockWorldPos(x, y, z); BlockChunkPos chunkBlockPos = blockpos.ToBlockChunkPos(); BlockState block = chunk[chunkBlockPos.X, chunkBlockPos.Y, chunkBlockPos.Z]; if (block.IsAir() || block.IsSameId(BlockStates.Leaves()) || block.IsSameId(BlockStates.Vines())) { chunk[chunkBlockPos.X, chunkBlockPos.Y, chunkBlockPos.Z] = _leaves; } } } } } // 生成木头 BlockWorldPos upPos = pos; for (int y = 0; y < height; ++y) { BlockChunkPos chunkUpPos = upPos.ToBlockChunkPos(); BlockState upBlock = chunk[chunkUpPos.X, chunkUpPos.Y, chunkUpPos.Z]; if (upBlock.IsAir() || upBlock.IsSameId(BlockStates.Leaves()) || upBlock.IsSameId(BlockStates.Vines())) { chunk[chunkUpPos.X, chunkUpPos.Y, chunkUpPos.Z] = _wood; } // 生成藤蔓 if (_vines && y > 0) { if (random.Next(3) > 0 && chunk[chunkUpPos.X - 1, chunkUpPos.Y, chunkUpPos.Z].IsAir()) { chunk[chunkUpPos.X - 1, chunkUpPos.Y, chunkUpPos.Z] = BlockStates.Vines(VineType.East); } if (random.Next(3) > 0 && chunk[chunkUpPos.X + 1, chunkUpPos.Y, chunkUpPos.Z].IsAir()) { chunk[chunkUpPos.X + 1, chunkUpPos.Y, chunkUpPos.Z] = BlockStates.Vines(VineType.West); } if (random.Next(3) > 0 && chunk[chunkUpPos.X, chunkUpPos.Y, chunkUpPos.Z - 1].IsAir()) { chunk[chunkUpPos.X, chunkUpPos.Y, chunkUpPos.Z - 1] = BlockStates.Vines(VineType.South); } if (random.Next(3) > 0 && chunk[chunkUpPos.X, chunkUpPos.Y, chunkUpPos.Z + 1].IsAir()) { chunk[chunkUpPos.X, chunkUpPos.Y, chunkUpPos.Z + 1] = BlockStates.Vines(VineType.North); } } ++upPos.Y; } // 生成藤蔓 BlockChunkPos chunkPos = pos.ToBlockChunkPos(); if (_vines) { for (int y = chunkPos.Y + height - 3; y <= chunkPos.Y + height; ++y) { int restHeight = y - (chunkPos.Y + height); int xzSize = 2 - restHeight / 2; for (int x = chunkPos.X - xzSize; x <= chunkPos.X + xzSize; ++x) { for (int z = chunkPos.Z - xzSize; z <= chunkPos.Z + xzSize; ++z) { if (chunk[x, y, z].IsLeaves()) { if (random.Next(4) == 0 && chunk[x - 1, y, z].IsAir()) { chunk[x - 1, y, z] = BlockStates.Vines(VineType.East); } if (random.Next(4) == 0 && chunk[x + 1, y, z].IsAir()) { chunk[x + 1, y, z] = BlockStates.Vines(VineType.West); } if (random.Next(4) == 0 && chunk[x, y, z - 1].IsAir()) { chunk[x, y, z - 1] = BlockStates.Vines(VineType.South); } if (random.Next(4) == 0 && chunk[x, y, z + 1].IsAir()) { chunk[x, y, z + 1] = BlockStates.Vines(VineType.North); } } } } } } } } } }
public void Generate(IWorld world, IGrainFactory grainFactory, ChunkColumnCompactStorage chunk, Random rand, BlockWorldPos position) { // 在xz平面上的方向 float angle = (float)rand.NextDouble() * (float)Math.PI; // 起始点和结束点 double startX = (double)((float)(position.X + 8) + Math.Sin(angle) * (float)NumberOfBlocks / 8.0F); double endX = (double)((float)(position.X + 8) - Math.Sin(angle) * (float)NumberOfBlocks / 8.0F); double startZ = (double)((float)(position.Z + 8) + Math.Cos(angle) * (float)NumberOfBlocks / 8.0F); double endZ = (double)((float)(position.Z + 8) - Math.Cos(angle) * (float)NumberOfBlocks / 8.0F); double startY = (double)(position.Y + rand.Next(3) - 2); double endY = (double)(position.Y + rand.Next(3) - 2); for (int i = 0; i < NumberOfBlocks; ++i) { // 插值参数 float t = (float)i / (float)NumberOfBlocks; // 椭球中心 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)NumberOfBlocks / 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); BlockChunkPos posInChunk = blockpos.ToBlockChunkPos(); if (posInChunk.Y >= 0 && posInChunk.Y < 255 && chunk[posInChunk.X, posInChunk.Y, posInChunk.Z] == BlockStates.Stone()) { // 替换为矿石 chunk[posInChunk.X, posInChunk.Y, posInChunk.Z] = OreBlock; } } } } } } } } }