Генерация блоков на поверхности над рудной жилой

Версия Minecraft
1.15.2
75
1
2
Есть генерация руды в виде 1 жила на 20 чанков. Как сделать так, чтоб в чанке, где сгенерировалась руда, на поверхности земли спавнилось несколько блоков этой самой руды?
Java:
private static ConfiguredFeature oreConfiguredFeature(int chance, int nubmer, OreFeatureConfig.FillerBlockType fillertype, BlockState state, int veinsize, int veincount, int veinbottom, int veintop, int veinmax) {
        if (oreConfiguredFeature == null) {
            oreConfiguredFeature = new OreFeature(OreFeatureConfig::deserialize) {
                @Override
                public boolean place(IWorld worldIn, ChunkGenerator generator, Random rand, BlockPos pos, OreFeatureConfig config) {
                    if(rand.nextInt(chance) == nubmer)
                        return super.place(worldIn, generator, rand, pos, config);
                    else
                        return false;
                }
            }.withConfiguration(new OreFeatureConfig(fillertype, state, veinsize))
                    .withPlacement(Placement.COUNT_RANGE.configure(new CountRangeConfig(veincount, veinbottom, veintop, veinmax)));
        }

        return oreConfiguredFeature;
    }
 
Решение
Получить блокстейт World#getBlockState
Получить блок IBlockState#GetBlock
Получить материал Blokc#getMaterial
Сравнить с Material.AIR

В принципе можно сравнивать сам блок, но в модах могут быть какие-то кастомные блоки воздуха, поэтому лучше опираться на материал
7,099
324
1,510
super.place(worldIn, generator, rand, pos, config);
К этому добавь генерацию блока на поверхности.
В объекте мира должен быть метод, называющийся как-то похоже на getTopSolidOrLiquidBlock, этот метод возвращает блокпозу самого высокого блока не воздуха в координатах x,z
 
75
1
2
Нашёл 2 метода
1)Класс Chunk:
Java:
public int getTopBlockY(Heightmap.Type heightmapType, int x, int z) {
      return this.heightMap.get(heightmapType).getHeight(x & 15, z & 15) - 1;
   }
2)Класс WorldEntitySpawner:
Java:
private static BlockPos getTopSolidOrLiquidBlock(IWorldReader worldIn, @Nullable EntityType<?> p_208498_1_, int x, int z) {
      BlockPos blockpos = new BlockPos(x, worldIn.getHeight(EntitySpawnPlacementRegistry.func_209342_b(p_208498_1_), x, z), z);
      BlockPos blockpos1 = blockpos.down();
      return worldIn.getBlockState(blockpos1).allowsMovement(worldIn, blockpos1, PathType.LAND) ? blockpos1 : blockpos;
   }
Если я правильно понял, в первом случае возвращается позиция самого высокого блока в чанке. Второй, кажется, только для entities, а не для блоков.
Ещё вопрос, как нужно будет добавить к коду? Ведь второй return не прокатит. Да и что именно нужно возвращать чтобы фича работала?
И наконец. Я примерно представляю работу примерно так: после выполнения условия if, генерируется от 2 до 7 случайных координат по x и z в пределах данного чанка, для каждой из этих позиций получаем наивысший твёрдый блок и генерируем на нём наш блок. Есть ли методы с которыми можно было бы нормально написать такую реализацию? Или есть что-то уже встроенное и более эффективное?
 
7,099
324
1,510
А это не подойдет?
Метод из чанка похож на то, что нужно.
Ещё вопрос, как нужно будет добавить к коду? Ведь второй return не прокатит. Да и что именно нужно возвращать чтобы фича работала?
Если фича возвращает true - значит, она применилась.
Можно сделать так:
Java:
if(super.place(worldIn, generator, rand, pos, config)) {//если фича применилась
    //дополнительная генерация
    return true;
}else
    return false;
 
75
1
2
Как-то так. В цикле планирую доставать y-координату и вместе с имеющимися x и z сгенерировать на них по одному блоку. Как привязать это к данному чанку и как генерировать координаты только в его пределах? И наконец, каков метод генерации одного блока на заданных координатах?
Java:
private static ConfiguredFeature oreConfiguredFeature(int chance, int nubmer, OreFeatureConfig.FillerBlockType fillertype, BlockState state, int veinsize, int veincount, int veinbottom, int veintop, int veinmax) {
        if (oreConfiguredFeature == null) {
            oreConfiguredFeature = new OreFeature(OreFeatureConfig::deserialize) {
                @Override
                public boolean place(IWorld worldIn, ChunkGenerator generator, Random rand, BlockPos pos, OreFeatureConfig config) {
                    if(rand.nextInt(chance) == nubmer) {
                        if (super.place(worldIn, generator, rand, pos, config))
                        {
                            int samplesCount=rand.nextInt(5)+2;
                            int x;
                            int z;
                            for (int i=0; i<=samplesCount; i++)
                            {

                            }
                        }
                    }
                    else
                        return false;
                }
            }.withConfiguration(new OreFeatureConfig(fillertype, state, veinsize))
                    .withPlacement(Placement.COUNT_RANGE.configure(new CountRangeConfig(veincount, veinbottom, veintop, veinmax)));
        }
        return oreConfiguredFeature;
    }
 
7,099
324
1,510
И наконец, каков метод генерации одного блока на заданных координатах?
world.setBlockState(pos, blockstate)
Как привязать это к данному чанку и как генерировать координаты только в его пределах?
Ты вроде хотел генерировать еще руду ровно над своей рудой. Значит, позиция будет равна pos из аргумента с Y-координатой верхнего блока
int samplesCount=rand.nextInt(5)+2; int x; int z; for (int i=0; i<=samplesCount; i++)
Хочешь сгенерировать не один блок, а жилу? Тогда можно еще раз вызвать super-метод, передав в него уже верхнюю позицию
 
7,099
324
1,510
Думаю ,стоит сделать еще одну фичу с другими параметрами жилы и вызывать ее place с позицией верхнего блока
 
75
1
2
Короче говоря, при помощи палки и бубна, получилось что-то такое:
Java:
private static ConfiguredFeature oreConfiguredFeature;

    private static ConfiguredFeature oreConfiguredFeature(int chance, int nubmer, OreFeatureConfig.FillerBlockType fillertype, BlockState state, int veinsize, int veincount, int veinbottom, int veintop, int veinmax) {
        if (oreConfiguredFeature == null) {
            oreConfiguredFeature = new OreFeature(OreFeatureConfig::deserialize) {
                @Override
                public boolean place(IWorld worldIn, ChunkGenerator generator, Random rand, BlockPos pos, OreFeatureConfig config) {
                    if(rand.nextInt(chance) == nubmer) {
                            int samplesCount=rand.nextInt(5)+2;
                            int x = pos.getX();
                            int z = pos.getZ();
                            for (int i=0; i<=samplesCount; i++)
                            {
                                int step = rand.nextInt(3);
                                x+=step;
                                z+=step;
                                BlockPos position = new BlockPos(x, worldIn.getHeight(), z);
                                worldIn.setBlockState(position, state, 2);
                            }

                            return super.place(worldIn, generator, rand, pos, config);
                    }
                    else
                        return false;
                }
            }.withConfiguration(new OreFeatureConfig(fillertype, state, veinsize))
                    .withPlacement(Placement.COUNT_RANGE.configure(new CountRangeConfig(veincount, veinbottom, veintop, veinmax)));
        }
        return oreConfiguredFeature;
    }

Однако не работает, сама жила генерируется, блоки на поверхности - нет. Как починить?
 
7,099
324
1,510
Подебажь, выясни, почему строчка worldIn.setBlockState(position, state, 2) не выполняется или выполняется, но блок не появляется.
 
7,099
324
1,510
Можно искать верхний блок так: начиная от верха мира идти вниз до тех пор, пока не встретится не воздух
 
7,099
324
1,510
Получить блокстейт World#getBlockState
Получить блок IBlockState#GetBlock
Получить материал Blokc#getMaterial
Сравнить с Material.AIR

В принципе можно сравнивать сам блок, но в модах могут быть какие-то кастомные блоки воздуха, поэтому лучше опираться на материал
 
Сверху