"Артефакты" при декорации биома

Версия Minecraft
1.12.2
API
Forge
395
34
90
Дратути

Декорировал я биом, сделал так чтобы все блоки выше 100y были в снегу все работает но почему-то появляются такие "артефакты"
2025-01-12_02.47.15.png
для дебага сделал так чтобы при вызове decorate в начале чанка генерировался бедроковый столб,
в итоге похоже что decorate вообще не вызывается для этих чанков, несмотря на то что в этом чанке в основном мой биом!

decorate:
@Override
public void decorate(World worldIn, Random rand, BlockPos pos) {
    Chunk chunk = worldIn.getChunkFromBlockCoords(pos);
    byte[] biomeArray = chunk.getBiomeArray();
    byte[] taintBiomeArray = new byte[16 * 16];

    for (int i = 0; i != 16; i++) {
        for (int j = 0; j != 16; j++) {
            byte k = biomeArray[i + j * 16];
            Biome biome = Biome.getBiomeForId(k);
            if (biome != null) {
                if (BiomeDictionary.hasType(biome, InitBiome.TAINT_TYPE_L)) {
                    taintBiomeArray[i + j * 16] = 1;
                } else if (BiomeDictionary.hasType(biome, InitBiome.TAINT_TYPE_EDGE)) {
                    taintBiomeArray[i + j * 16] = 2;
                }
            }
        }
    }

    decorateNormal(worldIn, rand, chunk.getPos(), taintBiomeArray);
    decorateEdge(worldIn, rand, chunk.getPos(), taintBiomeArray);
}

public void decorateEdge(World worldIn, Random rand, ChunkPos pos, byte[] biomeArray) {
    UltraMutableBlockPos blockPos = new UltraMutableBlockPos(pos); // моя обертка для BlockPos, в конструкторе (x, z) от ChunkPos умножаются на 16
 
    for (int y = 0; y != worldIn.getHeight() - 56; y++) { // дебаг
        blockPos.setY(y);
        worldIn.setBlockState(blockPos, Blocks.BEDROCK.getDefaultState());
    }
    blockPos.setY(0);


    for (int i = 0; i != 16; i++) {
        for (int j = 0; j != 16; j++) {
            if (biomeArray[i + j * 16] == 2) {
                blockPos.pushPos(); // сохранение текущей позиции на стек, типа OpenGL)
                blockPos.add(i, 0, j)
                blockPos.setY(HandlerR.calculateGenerationHeight(worldIn, blockPos.getX(), blockPos.getZ()));
                if (blockPos.getY() >= 100) {
                    worldIn.setBlockState(blockPos.up(), Blocks.SNOW_LAYER.getDefaultState());
                }
                blockPos.popPos(); // загрузка позиции со стека
            }
        }
    }
}

причем такие "артефакты" не очень частые в основном все работает нормально, но они все же есть(

опять магия какаято...
 
Последнее редактирование:
Решение
А как ты регистрируешь декоратор?
Я ванильные биомы не модифицировал, но предполагаю, что генератор берёт только блок в начале чанка, смотрит, какой там биом и применяет список декораторов. Но там же может и не быть твоего биома. То есть, тебе нужно зарегистрировать декоратор для всех биомов )
Возможно, чушь сморозил, так как с декораторами не работал.
А как ты регистрируешь декоратор?
Я ванильные биомы не модифицировал, но предполагаю, что генератор берёт только блок в начале чанка, смотрит, какой там биом и применяет список декораторов. Но там же может и не быть твоего биома. То есть, тебе нужно зарегистрировать декоратор для всех биомов )
Возможно, чушь сморозил, так как с декораторами не работал.
 
Это может быть из-за того, что в чанке есть ещё один биом?
2025-01-12_13.44.52.png
Ну вот тут микро кусочек моего биома но decorate туда вызвался
А как ты регистрируешь декоратор?
У меня просто @Override метод в классе биома)
предполагаю, что генератор берёт только блок в начале чанка, смотрит, какой там биом и применяет список декораторов
А, да, реально, вот это костыль!)
populate:
    public void populate(int x, int z)
    {
        BlockFalling.fallInstantly = true;
        int i = x * 16;
        int j = z * 16;
        BlockPos blockpos = new BlockPos(i, 0, j);
        Biome biome = this.world.getBiome(blockpos.add(16, 0, 16));

        ...
      
        biome.decorate(this.world, this.rand, new BlockPos(i, 0, j));

        ...
    }
То есть, тебе нужно зарегистрировать декоратор для всех биомов )
Думаю это решение, а на мой биом как лучше проверять перебирая chunk.getBiomeArray(); ?
 
Последнее редактирование:
Хотя, раз уж тебе всё равно снег туда ставить, я бы лучше просто прошёлся по всем блокам, проверил биом и сразу же влепил снег, при необходимости. Чтобы два раза не проходиться, так сказать )
 
нужно зарегистрировать декоратор для всех биомов )
Сначала думал что понял потом понял что не понял, в итоге пока сделал так, работает
TerrainHandler:
@Mod.EventBusSubscriber
public class TerrainHandler {

     ...

    @SubscribeEvent
    public static void decorate(DecorateBiomeEvent.Post e) {
        Chunk chunk = e.getWorld().getChunkFromChunkCoords(e.getChunkPos().x, e.getChunkPos().z);
        byte[] biomeArray = chunk.getBiomeArray();

        int taintEdgeId = Biome.getIdForBiome(InitBiome.TAINT_EDGE);
        int taintId = Biome.getIdForBiome(InitBiome.TAINT);


        if (HandlerR.arrayContainsAny(biomeArray, taintId, taintEdgeId)) {
            BiomeTaint.decorateCustom(e.getWorld(), e.getRand(), e.getChunkPos(), biomeArray);
        }
    }
}
arrayContainsAny:
    public static boolean arrayContainsAny(byte[] array, int... params) {
        for (int i : array) {
            for (int j : params) {
                if (i == j) {
                    return true;
                }
            }
        }
        return false;
    }
BiomeTaint:
public class BiomeTaint extends BiomeBase {

    ...

    public static void decorateCustom(World worldIn, Random random, ChunkPos pos, byte[] biomeArray) {
        UltraMutableBlockPos blockPos = new UltraMutableBlockPos(pos);

        int taintEdgeId = Biome.getIdForBiome(InitBiome.TAINT_EDGE);
        int taintId = Biome.getIdForBiome(InitBiome.TAINT);


        for (int i = 0; i != 16; i++) {
            for (int j = 0; j != 16; j++) {
                byte k = biomeArray[i + j * 16];
                if (k == taintId) {
                    blockPos.pushPos();
                    blockPos.add(i, 0, j);
                    decorateNormal(worldIn, random, blockPos);
                    blockPos.popPos();
                } else if (k == taintEdgeId) {
                    blockPos.pushPos();
                    blockPos.add(i, 0, j);
                    decorateEdge(worldIn, random, blockPos);
                    blockPos.popPos();
                }
            }
        }
    }

    private static void decorateEdge(World worldIn, Random rand, UltraMutableBlockPos blockPos) {
        blockPos.setY(HandlerR.calculateGenerationHeight(worldIn, blockPos.getX(), blockPos.getZ()));
        if (blockPos.getY() >= 100) {
            if (blockPos.getY() > 110) {
                worldIn.setBlockState(blockPos.up(), Blocks.SNOW_LAYER.getDefaultState());
            } else if (rand.nextBoolean()) {
                worldIn.setBlockState(blockPos.up(), Blocks.SNOW_LAYER.getDefaultState());
            }
        }
    }

    private static void decorateNormal(World worldIn, Random rand, UltraMutableBlockPos blockPos) {
        if (rand.nextInt(33) == 0) {
            blockPos.setY(HandlerR.calculateGenerationHeight(worldIn, blockPos.getX(), blockPos.getZ()));
            if (worldIn.getBlockState(blockPos).getBlock() == BlocksTC.taintSoil) {
                IBlockState state = BlocksTC.taintFeature.getBlockState().getBaseState();
                blockPos.up();
                worldIn.setBlockState(blockPos, state.withProperty(BlockDirectional.FACING, EnumFacing.UP), 3);
                worldIn.checkLight(blockPos);
            }
        }
    }

    ...
   
}
 
Последнее редактирование:
Назад
Сверху