Jump to content

[1.17.1, Solved] Altering or Removing Vanilla Generation Features


fweo

Recommended Posts

What is the preferred method for preventing a particular vanilla ConfiguredFeature from generating (e.g. preventing natural generation of coal ore)? My best guess is that you would do something when you receive a BiomeLoadingEvent, similarly to how you add your own configured features, but I can't think of a good way to do this. I suppose I could loop through the entire list, retrieve the object from each supplier, compare it to the particular vanilla feature, and then remove it if it's the same, but this seems a little clumsy, especially if I want to stop the generation of several features (which I do). If I want to remove the feature from all biomes, is there a way to prevent it from getting added to the list in the first place or replace it with a no-op so it doesn't need to be removed each time a biome loads?

Is this any easier if you only wish to alter an existing feature, e.g. changing an ore vein size or changing what block generates in a vegetation patch?

Edited by fweo
Mark as solved
Link to comment
Share on other sites

Here's my current attempt, which runs with each BiomeLoadingEvent:


        List<Supplier<ConfiguredFeature<?,?>>> orefeatures = event.getGeneration().getFeatures(GenerationStep.Decoration.UNDERGROUND_ORES);
        List<Integer> indicesToRemove = new ArrayList<>();
        for(int i = 0; i < orefeatures.size(); i++) {
            ConfiguredFeature<?,?> feature = orefeatures.get(i).get();
            Main.LOGGER.info(feature.toString());
            if(feature == Features.ORE_COAL || feature == Features.ORE_IRON) {
                indicesToRemove.add(i);
                Main.LOGGER.info("Removing!");
            }
        }
        orefeatures.removeAll(indicesToRemove);

The features all print in the first log, and the two I've picked to remove are included in that list, as expected (they toString into a json format, though, so it's a bit hard to look at). However, it never gets into the body of the if statement, so nothing changes with the generation. Features.ORE_COAL is the exact object put into the list by addDefaultOres in BiomeDefaultFeatures, and that just gets made directly into a Supplier which gets put straight into the list, so those should be the right objects that come out of the Supplier when you call getGeneration.getFeatures(step).get(index).get(). Any ideas about what's wrong? Something up with the ==?

Link to comment
Share on other sites

 

That's helped a bit, but I'm still stuck. If I compare the the configured features in 

Features.ORE_COAL.getFeatures()

to those in

event.getGeneration().getFeatures(GenerationStep.Decoration.UNDERGROUND_ORES).get(i).get().getFeatures();

then for the i that corresponds to coal ore (which won't necessarily always be the same) those two streams both contain four configured features, and the final three of them match in terms of what they toString into, but don't compare as equal with .equals. Am I doing the wrong thing with getFeatures here? Surely there's a proper way to compare them without having to resort to comparing strings or comparing some other complicated properties of them.

That is, if I do something like this then they match in the log but don't get into the if statement:

        List<Supplier<ConfiguredFeature<?,?>>> orefeatures = event.getGeneration().getFeatures(GenerationStep.Decoration.UNDERGROUND_ORES);
        for(int i = 0; i < orefeatures.size(); i++) {
            List<ConfiguredFeature<?, ?>> oneFeature = orefeatures.get(i).get().getFeatures().toList();
            List<ConfiguredFeature<?, ?>> testAgainst = Features.ORE_COAL.getFeatures().toList();
            for(int j = 0; j < oneFeature.size() && j < testAgainst.size(); j++) {
                Main.LOGGER.info(oneFeature.get(j));
                Main.LOGGER.info(testAgainst.get(j));

                if(oneFeature.get(j).equals(testAgainst.get(j))) {
                    Main.LOGGER.info("Matched at " + i);
                    break;
                }
                Main.LOGGER.info("");
            }
        }

Giving the following output:

Spoiler
(... similar output for deepslate ...)
[16:11:44] [Netty Local Client IO #0/INFO]: DataResult[Left[{"config":{"feature":{"config":{"feature":{"config":{"feature":{"config":{"targets":[{"target":{"tag":"minecraft:stone_ore_replaceables","predicate_type":"minecraft:tag_match"},"state":{"Name":"minecraft:coal_ore"}},{"target":{"tag":"minecraft:deepslate_ore_replaceables","predicate_type":"minecraft:tag_match"},"state":{"Name":"minecraft:deepslate_coal_ore"}}],"size":17,"discard_chance_on_air_exposure":0.0},"type":"minecraft:ore"},"decorator":{"config":{"height":{"min_inclusive":{"above_bottom":0},"max_inclusive":{"absolute":127},"type":"minecraft:uniform"}},"type":"minecraft:range"}},"type":"minecraft:decorated"},"decorator":{"config":{},"type":"minecraft:square"}},"type":"minecraft:decorated"},"decorator":{"config":{"count":20},"type":"minecraft:count"}},"type":"minecraft:decorated"}]]
[16:11:44] [Netty Local Client IO #0/INFO]: ResourceKey[minecraft:worldgen/configured_feature / minecraft:ore_coal]
[16:11:44] [Netty Local Client IO #0/INFO]: 
[16:11:44] [Netty Local Client IO #0/INFO]: DataResult[Left[{"config":{"feature":{"config":{"feature":{"config":{"targets":[{"target":{"tag":"minecraft:stone_ore_replaceables","predicate_type":"minecraft:tag_match"},"state":{"Name":"minecraft:coal_ore"}},{"target":{"tag":"minecraft:deepslate_ore_replaceables","predicate_type":"minecraft:tag_match"},"state":{"Name":"minecraft:deepslate_coal_ore"}}],"size":17,"discard_chance_on_air_exposure":0.0},"type":"minecraft:ore"},"decorator":{"config":{"height":{"min_inclusive":{"above_bottom":0},"max_inclusive":{"absolute":127},"type":"minecraft:uniform"}},"type":"minecraft:range"}},"type":"minecraft:decorated"},"decorator":{"config":{},"type":"minecraft:square"}},"type":"minecraft:decorated"}]]
[16:11:44] [Netty Local Client IO #0/INFO]: DataResult[Left[{"config":{"feature":{"config":{"feature":{"config":{"targets":[{"target":{"tag":"minecraft:stone_ore_replaceables","predicate_type":"minecraft:tag_match"},"state":{"Name":"minecraft:coal_ore"}},{"target":{"tag":"minecraft:deepslate_ore_replaceables","predicate_type":"minecraft:tag_match"},"state":{"Name":"minecraft:deepslate_coal_ore"}}],"size":17,"discard_chance_on_air_exposure":0.0},"type":"minecraft:ore"},"decorator":{"config":{"height":{"min_inclusive":{"above_bottom":0},"max_inclusive":{"absolute":127},"type":"minecraft:uniform"}},"type":"minecraft:range"}},"type":"minecraft:decorated"},"decorator":{"config":{},"type":"minecraft:square"}},"type":"minecraft:decorated"}]]
[16:11:44] [Netty Local Client IO #0/INFO]: 
[16:11:44] [Netty Local Client IO #0/INFO]: DataResult[Left[{"config":{"feature":{"config":{"targets":[{"target":{"tag":"minecraft:stone_ore_replaceables","predicate_type":"minecraft:tag_match"},"state":{"Name":"minecraft:coal_ore"}},{"target":{"tag":"minecraft:deepslate_ore_replaceables","predicate_type":"minecraft:tag_match"},"state":{"Name":"minecraft:deepslate_coal_ore"}}],"size":17,"discard_chance_on_air_exposure":0.0},"type":"minecraft:ore"},"decorator":{"config":{"height":{"min_inclusive":{"above_bottom":0},"max_inclusive":{"absolute":127},"type":"minecraft:uniform"}},"type":"minecraft:range"}},"type":"minecraft:decorated"}]]
[16:11:44] [Netty Local Client IO #0/INFO]: DataResult[Left[{"config":{"feature":{"config":{"targets":[{"target":{"tag":"minecraft:stone_ore_replaceables","predicate_type":"minecraft:tag_match"},"state":{"Name":"minecraft:coal_ore"}},{"target":{"tag":"minecraft:deepslate_ore_replaceables","predicate_type":"minecraft:tag_match"},"state":{"Name":"minecraft:deepslate_coal_ore"}}],"size":17,"discard_chance_on_air_exposure":0.0},"type":"minecraft:ore"},"decorator":{"config":{"height":{"min_inclusive":{"above_bottom":0},"max_inclusive":{"absolute":127},"type":"minecraft:uniform"}},"type":"minecraft:range"}},"type":"minecraft:decorated"}]]
[16:11:44] [Netty Local Client IO #0/INFO]: 
[16:11:44] [Netty Local Client IO #0/INFO]: DataResult[Left[{"config":{"targets":[{"target":{"tag":"minecraft:stone_ore_replaceables","predicate_type":"minecraft:tag_match"},"state":{"Name":"minecraft:coal_ore"}},{"target":{"tag":"minecraft:deepslate_ore_replaceables","predicate_type":"minecraft:tag_match"},"state":{"Name":"minecraft:deepslate_coal_ore"}}],"size":17,"discard_chance_on_air_exposure":0.0},"type":"minecraft:ore"}]]
[16:11:44] [Netty Local Client IO #0/INFO]: DataResult[Left[{"config":{"targets":[{"target":{"tag":"minecraft:stone_ore_replaceables","predicate_type":"minecraft:tag_match"},"state":{"Name":"minecraft:coal_ore"}},{"target":{"tag":"minecraft:deepslate_ore_replaceables","predicate_type":"minecraft:tag_match"},"state":{"Name":"minecraft:deepslate_coal_ore"}}],"size":17,"discard_chance_on_air_exposure":0.0},"type":"minecraft:ore"}]]
[16:11:44] [Netty Local Client IO #0/INFO]: 
(... similar output for iron ore ...)

 

 

Link to comment
Share on other sites

i would recommend you to use removeIf, something like this:

event.getGeneration().getFeatures(GenerationStep.Decoration.UNDERGROUND_ORES).removeIf((supplier) -> {

});

then you can loop inside the removeIf through the ConfiguredFeatures, after that check if the ConfiguredFeature.feature is an OreFeature,
then get the OreConfiguration of the feature and from that you can get the targetStates which you can map to a List of Blocks. then return inside the removeIf
if the List contains for example Blocks.COAL_ORE

that was now very theoretical, you can look at this  for a practical example

  • Thanks 1
Link to comment
Share on other sites

  • fweo changed the title to [1.17.1, Solved] Altering or Removing Vanilla Generation Features

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • They were already updated, and just to double check I even did a cleanup and fresh update from that same page. I'm quite sure drivers are not the problem here. 
    • i tried downloading the drivers but it says no AMD graphics hardware has been detected    
    • Update your AMD/ATI drivers - get the drivers from their website - do not update via system  
    • As the title says i keep on crashing on forge 1.20.1 even without any mods downloaded, i have the latest drivers (nvidia) and vanilla minecraft works perfectly fine for me logs: https://pastebin.com/5UR01yG9
    • Hello everyone, I'm making this post to seek help for my modded block, It's a special block called FrozenBlock supposed to take the place of an old block, then after a set amount of ticks, it's supposed to revert its Block State, Entity, data... to the old block like this :  The problem I have is that the system breaks when handling multi blocks (I tried some fix but none of them worked) :  The bug I have identified is that the function "setOldBlockFields" in the item's "setFrozenBlock" function gets called once for the 1st block of multiblock getting frozen (as it should), but gets called a second time BEFORE creating the first FrozenBlock with the data of the 1st block, hence giving the same data to the two FrozenBlock :   Old Block Fields set BlockState : Block{minecraft:black_bed}[facing=east,occupied=false,part=head] BlockEntity : net.minecraft.world.level.block.entity.BedBlockEntity@73681674 BlockEntityData : id:"minecraft:bed",x:3,y:-60,z:-6} Old Block Fields set BlockState : Block{minecraft:black_bed}[facing=east,occupied=false,part=foot] BlockEntity : net.minecraft.world.level.block.entity.BedBlockEntity@6d1aa3da BlockEntityData : {id:"minecraft:bed",x:2,y:-60,z:-6} Frozen Block Entity set BlockState : Block{minecraft:black_bed}[facing=east,occupied=false,part=foot] BlockPos{x=3, y=-60, z=-6} BlockEntity : net.minecraft.world.level.block.entity.BedBlockEntity@6d1aa3da BlockEntityData : {id:"minecraft:bed",x:2,y:-60,z:-6} Frozen Block Entity set BlockState : Block{minecraft:black_bed}[facing=east,occupied=false,part=foot] BlockPos{x=2, y=-60, z=-6} BlockEntity : net.minecraft.world.level.block.entity.BedBlockEntity@6d1aa3da BlockEntityData : {id:"minecraft:bed",x:2,y:-60,z:-6} here is the code inside my custom "freeze" item :    @Override     public @NotNull InteractionResult useOn(@NotNull UseOnContext pContext) {         if (!pContext.getLevel().isClientSide() && pContext.getHand() == InteractionHand.MAIN_HAND) {             BlockPos blockPos = pContext.getClickedPos();             BlockPos secondBlockPos = getMultiblockPos(blockPos, pContext.getLevel().getBlockState(blockPos));             if (secondBlockPos != null) {                 createFrozenBlock(pContext, secondBlockPos);             }             createFrozenBlock(pContext, blockPos);             return InteractionResult.SUCCESS;         }         return super.useOn(pContext);     }     public static void createFrozenBlock(UseOnContext pContext, BlockPos blockPos) {         BlockState oldState = pContext.getLevel().getBlockState(blockPos);         BlockEntity oldBlockEntity = oldState.hasBlockEntity() ? pContext.getLevel().getBlockEntity(blockPos) : null;         CompoundTag oldBlockEntityData = oldState.hasBlockEntity() ? oldBlockEntity.serializeNBT() : null;         if (oldBlockEntity != null) {             pContext.getLevel().removeBlockEntity(blockPos);         }         BlockState FrozenBlock = setFrozenBlock(oldState, oldBlockEntity, oldBlockEntityData);         pContext.getLevel().setBlockAndUpdate(blockPos, FrozenBlock);     }     public static BlockState setFrozenBlock(BlockState blockState, @Nullable BlockEntity blockEntity, @Nullable CompoundTag blockEntityData) {         BlockState FrozenBlock = BlockRegister.FROZEN_BLOCK.get().defaultBlockState();         ((FrozenBlock) FrozenBlock.getBlock()).setOldBlockFields(blockState, blockEntity, blockEntityData);         return FrozenBlock;     }  
  • Topics

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.