Jump to content

[1.17.1] Replacing leaves on trees / Generating world generation data


Recommended Posts

Posted

Hello!

I want to replace the leaves on trees that generate in the world with other blocks. One way I've found to do this is to manually create files in data/minecraft/worldgen/configured_feature that correspond to vanilla's features and replacing the block in "foliage_provider" with the one I want. Doing it manually works well, but it's not convenient to do at a large scale, and obviously has other drawbacks.

I'd ideally use the data generator system, like I do for recipes and loot tables. Unfortunately, there is no built in support for specifically world generation, like there is for recipes and loot tables. I could create the json files if I managed to convert the features to JsonElements, but I don't know how I would do that.

To summarise, I have one objective:

  • Replacing leaves on trees placed in the world by
    • world generation and
    • saplings.

But I would gladly receive help on how to generate json files of ConfiguredFeatures such as Features.OAK.

Thanks in advance!

Posted

you need to create your own FoliagePlacer, then use BiomeLoadingEvent to loop through the Features, check if the Feature is an TreeFeature then replace the original FoliagePlacer with Reflection or use an AT

Posted
19 hours ago, Luis_ST said:

you need to create your own FoliagePlacer, then use BiomeLoadingEvent to loop through the Features, check if the Feature is an TreeFeature then replace the original FoliagePlacer with Reflection or use an AT

Thanks for your reply! I have done it using data generation now. It works well for world generation, and I have realised that I don't care about saplings, so it works well.

For anyone looking to do something similar, I include files to show what I did. They are just a bit hacky and incomplete now, but they can probably easily be generalised.

 

import static net.anju.larus.data.ResourceLocationUtil.prefix;
import static net.anju.larus.data.ResourceLocationUtil.slash;

@MethodsReturnNonnullByDefault
@ParametersAreNonnullByDefault
public abstract class LarusFeatureProvider<T> implements DataProvider {

    private static final Gson GSON = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create();

    protected final Set<FeatureEntry> featureEntries = new HashSet<>();

    private final DataGenerator generator;

    protected LarusFeatureProvider(DataGenerator generator, Registry<T> registry) {
        this.generator = generator;
        for (Map.Entry<ResourceKey<T>, T> entry : registry.entrySet()) {
            ResourceKey<T> key = entry.getKey();
            T feature = entry.getValue();
            JsonElement jsonElement = getJson(feature);
            if (jsonElement != null) {
                FeatureEntry featureEntry = new FeatureEntry(prefix(key.location(), key.getRegistryName()), jsonElement);
                featureEntries.add(featureEntry);
            }
        }
    }

    private void addFeatures() {
        for (FeatureEntry featureEntry : featureEntries) {
            modifyFeatureEntry(featureEntry);
        }
    }

    protected abstract void modifyFeatureEntry(FeatureEntry featureEntry);

    @Override
    public void run(HashCache cache) {
        addFeatures();
        writeFiles(cache, this.generator.getOutputFolder(), featureEntries);
    }

    // Actually write out the tables in the output folder
    private static void writeFiles(HashCache cache, Path outputFolder, Set<FeatureEntry> featureEntries) {
        for (FeatureEntry featureEntry : featureEntries) {
            if (featureEntry.isModified()) {
                ResourceLocation key = featureEntry.resourceLocation;
                JsonElement jsonElement = featureEntry.jsonElement;
                Path path = getPath(outputFolder, key);
                try {
                    DataProvider.save(GSON, cache, jsonElement, path);
                } catch (IOException e) {
                    LarusMod.LOGGER.error("Couldn't write data {}", key, e);
                }
            }
        }
    }

    @Override
    public String getName() {
        return "Larus features";
    }

    @Nullable
    public JsonElement getJson(T feature) {
        if (feature instanceof ConfiguredFeature<?, ?> configuredFeature) {
            Optional<JsonElement> optional = ConfiguredFeature.DIRECT_CODEC.encodeStart(JsonOps.INSTANCE, configuredFeature).result();
            return optional.orElse(null);
        }
        return null;
    }

    public static Path getPath(Path outputFolder, ResourceLocation key) {
        return outputFolder.resolve("data/" + slash(key) + ".json");
    }

    protected static class FeatureEntry {

        boolean modified = false;
        private final ResourceLocation resourceLocation;
        private final JsonElement jsonElement;

        private FeatureEntry(ResourceLocation resourceLocation, JsonElement jsonElement) {
            this.resourceLocation = resourceLocation;
            this.jsonElement = jsonElement;
        }

        public JsonElement getJsonElement() {
            return jsonElement;
        }

        protected void markModified() {
            this.modified = true;
        }

        private boolean isModified() {
            return this.modified;
        }

    }

}
public class LarusLeavesFeatureProvider extends LarusFeatureProvider<ConfiguredFeature<?, ?>> {

    public LarusLeavesFeatureProvider(DataGenerator generator) {
        super(generator, BuiltinRegistries.CONFIGURED_FEATURE);
    }

    @Override
    protected void modifyFeatureEntry(FeatureEntry featureEntry) {
        JsonElement jsonElement = featureEntry.getJsonElement();
        if (jsonElement.isJsonObject()) {
            JsonObject jsonObject = jsonElement.getAsJsonObject();
            if (jsonObject.has("config")) {
                JsonObject config = jsonObject.get("config").getAsJsonObject();
                if (config.has("foliage_provider")) {
                    JsonObject mcFoliage = config.get("foliage_provider").getAsJsonObject();
                    JsonObject larusFoliage = larusFoliage(mcFoliage);
                    if (larusFoliage != null) {
                        config.add("foliage_provider", larusFoliage);
                        featureEntry.markModified();
                    }
                }
            }
        }
    }

    @Nullable
    protected JsonObject larusFoliage(JsonObject mcFoliage) {
        JsonElement type = mcFoliage.get("type");
        if (type.getAsString().equals("minecraft:simple_state_provider")) {
            JsonObject state = mcFoliage.get("state").getAsJsonObject();

            // Change leaves
            String mcLeaves = state.get("Name").getAsString();
            LarusLeavesBlock larusLeavesBlock = larusLeavesBlock(mcLeaves);
            if (larusLeavesBlock == null || larusLeavesBlock.getRegistryName() == null)
                return null;
            String larusLeaves = larusLeavesBlock.getRegistryName().toString();
            state.add("Name", new JsonPrimitive(larusLeaves));

            // Transform properties
            JsonObject mcProperties = state.get("Properties").getAsJsonObject();
            transformProperties(mcProperties, larusLeavesBlock);
        } else {
            LarusMod.LOGGER.warn("Unexpected type for MC foliage " + mcFoliage);
        }
        return mcFoliage;
    }

    protected void transformProperties(JsonObject properties, LarusLeavesBlock larusLeavesBlock) {
        if (larusLeavesBlock instanceof LarusDeciduousLeavesBlock)
            properties.add("leafy", new JsonPrimitive("green"));
    }

    @Nullable
    protected LarusLeavesBlock larusLeavesBlock(String mcLeaves) {
        switch (mcLeaves) {
            case "minecraft:oak_leaves" -> {
                return LarusBlocks.OAK_LEAVES.get();
            }
            case "minecraft:birch_leaves" -> {
                return LarusBlocks.BIRCH_LEAVES.get();
            }
            case "minecraft:acacia_leaves" -> {
                return LarusBlocks.ACACIA_LEAVES.get();
            }
            case "minecraft:jungle_leaves" -> {
                return LarusBlocks.JUNGLE_LEAVES.get();
            }
            case "minecraft:dark_oak_leaves" -> {
                return LarusBlocks.DARK_OAK_LEAVES.get();
            }
            case "minecraft:spruce_leaves" -> {
                return LarusBlocks.SPRUCE_LEAVES.get();
            }
        }
        return null;
    }


}

 

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

    • i have just made a modpack and i accidentally added a few fabric mods and after deleting them i can no longer launch the pack if any one could help these are my latest logs [22:42:24] [main/INFO]:additionalClassesLocator: [optifine., net.optifine.] [22:42:25] [main/INFO]:Compatibility level set to JAVA_17 [22:42:25] [main/ERROR]:Mixin config epicsamurai.mixins.json does not specify "minVersion" property [22:42:25] [main/INFO]:Launching target 'forgeclient' with arguments [--version, forge-43.4.0, --gameDir, C:\Users\Mytht\curseforge\minecraft\Instances\overseer (1), --assetsDir, C:\Users\Mytht\curseforge\minecraft\Install\assets, --uuid, 4c176bf14d4041cba29572aa4333ca1d, --username, mythtitan0, --assetIndex, 1.19, --accessToken, ????????, --clientId, MGJiMTEzNGEtMjc3Mi00ODE0LThlY2QtNzFiODMyODEyYjM4, --xuid, 2535469006485684, --userType, msa, --versionType, release, --width, 854, --height, 480] [22:42:25] [main/WARN]:Reference map 'insanelib.refmap.json' for insanelib.mixins.json could not be read. If this is a development environment you can ignore this message [22:42:25] [main/WARN]:Reference map 'corpsecurioscompat.refmap.json' for gravestonecurioscompat.mixins.json could not be read. If this is a development environment you can ignore this message [22:42:25] [main/WARN]:Reference map 'nitrogen_internals.refmap.json' for nitrogen_internals.mixins.json could not be read. If this is a development environment you can ignore this message [22:42:25] [main/WARN]:Reference map 'arclight.mixins.refmap.json' for epicsamurai.mixins.json could not be read. If this is a development environment you can ignore this message [22:42:25] [main/WARN]:Reference map 'simplyswords-common-refmap.json' for simplyswords-common.mixins.json could not be read. If this is a development environment you can ignore this message [22:42:25] [main/WARN]:Reference map 'simplyswords-forge-refmap.json' for simplyswords.mixins.json could not be read. If this is a development environment you can ignore this message [22:42:25] [main/WARN]:Reference map '${refmap_target}refmap.json' for corgilib.forge.mixins.json could not be read. If this is a development environment you can ignore this message [22:42:25] [main/WARN]:Reference map 'MysticPotions-forge-refmap.json' for mysticpotions.mixins.json could not be read. If this is a development environment you can ignore this message [22:42:26] [main/WARN]:Reference map 'packetfixer-forge-forge-refmap.json' for packetfixer-forge.mixins.json could not be read. If this is a development environment you can ignore this message [22:42:26] [main/WARN]:Error loading class: atomicstryker/multimine/client/MultiMineClient (java.lang.ClassNotFoundException: atomicstryker.multimine.client.MultiMineClient) [22:42:26] [main/WARN]:@Mixin target atomicstryker.multimine.client.MultiMineClient was not found treechop.forge.compat.mixins.json:MultiMineMixin [22:42:26] [main/WARN]:Error loading class: com/simibubi/create/content/contraptions/components/fan/AirCurrent (java.lang.ClassNotFoundException: com.simibubi.create.content.contraptions.components.fan.AirCurrent) [22:42:26] [main/WARN]:Error loading class: shadows/apotheosis/ench/table/ApothEnchantContainer (java.lang.ClassNotFoundException: shadows.apotheosis.ench.table.ApothEnchantContainer) [22:42:26] [main/WARN]:@Mixin target shadows.apotheosis.ench.table.ApothEnchantContainer was not found origins_classes.mixins.json:common.apotheosis.ApotheosisEnchantmentMenuMixin [22:42:26] [main/WARN]:Error loading class: se/mickelus/tetra/blocks/workbench/WorkbenchTile (java.lang.ClassNotFoundException: se.mickelus.tetra.blocks.workbench.WorkbenchTile) [22:42:26] [main/WARN]:@Mixin target se.mickelus.tetra.blocks.workbench.WorkbenchTile was not found origins_classes.mixins.json:common.tetra.WorkbenchTileMixin [22:42:27] [main/WARN]:Error loading class: tfar/davespotioneering/blockentity/AdvancedBrewingStandBlockEntity (java.lang.ClassNotFoundException: tfar.davespotioneering.blockentity.AdvancedBrewingStandBlockEntity) [22:42:27] [main/WARN]:@Mixin target tfar.davespotioneering.blockentity.AdvancedBrewingStandBlockEntity was not found itemproductionlib.mixins.json:davespotioneering/AdvancedBrewingStandBlockEntityMixin [22:42:27] [main/WARN]:Error loading class: fuzs/visualworkbench/world/inventory/ModCraftingMenu (java.lang.ClassNotFoundException: fuzs.visualworkbench.world.inventory.ModCraftingMenu) [22:42:27] [main/WARN]:@Mixin target fuzs.visualworkbench.world.inventory.ModCraftingMenu was not found itemproductionlib.mixins.json:visualworkbench/ModCraftingMenuMixin [22:42:27] [main/WARN]:Error loading class: fuzs/easymagic/world/inventory/ModEnchantmentMenu (java.lang.ClassNotFoundException: fuzs.easymagic.world.inventory.ModEnchantmentMenu) [22:42:27] [main/WARN]:@Mixin target fuzs.easymagic.world.inventory.ModEnchantmentMenu was not found skilltree.mixins.json:easymagic/ModEnchantmentMenuMixin [22:42:27] [main/WARN]:Error loading class: shadows/apotheosis/ench/table/ApothEnchantmentMenu (java.lang.ClassNotFoundException: shadows.apotheosis.ench.table.ApothEnchantmentMenu) [22:42:27] [main/WARN]:@Mixin target shadows.apotheosis.ench.table.ApothEnchantmentMenu was not found skilltree.mixins.json:apotheosis/ApothEnchantContainerMixin [22:42:27] [main/WARN]:Error loading class: shadows/apotheosis/adventure/affix/socket/SocketingRecipe (java.lang.ClassNotFoundException: shadows.apotheosis.adventure.affix.socket.SocketingRecipe) [22:42:27] [main/WARN]:@Mixin target shadows.apotheosis.adventure.affix.socket.SocketingRecipe was not found skilltree.mixins.json:apotheosis/SocketingRecipeMixin [22:42:27] [main/WARN]:Error loading class: shadows/apotheosis/adventure/affix/socket/gem/bonus/AttributeBonus (java.lang.ClassNotFoundException: shadows.apotheosis.adventure.affix.socket.gem.bonus.AttributeBonus) [22:42:27] [main/WARN]:@Mixin target shadows.apotheosis.adventure.affix.socket.gem.bonus.AttributeBonus was not found skilltree.mixins.json:apotheosis/AttributeBonusMixin [22:42:27] [main/WARN]:Error loading class: shadows/apotheosis/adventure/affix/socket/gem/bonus/EnchantmentBonus (java.lang.ClassNotFoundException: shadows.apotheosis.adventure.affix.socket.gem.bonus.EnchantmentBonus) [22:42:27] [main/WARN]:@Mixin target shadows.apotheosis.adventure.affix.socket.gem.bonus.EnchantmentBonus was not found skilltree.mixins.json:apotheosis/EnchantmentBonusMixin [22:42:27] [main/WARN]:Error loading class: shadows/apotheosis/adventure/client/AdventureModuleClient (java.lang.ClassNotFoundException: shadows.apotheosis.adventure.client.AdventureModuleClient) [22:42:27] [main/WARN]:@Mixin target shadows.apotheosis.adventure.client.AdventureModuleClient was not found skilltree.mixins.json:apotheosis/AdventureModuleClientMixin [22:42:27] [main/WARN]:Error loading class: me/shedaniel/rei/RoughlyEnoughItemsCoreClient (java.lang.ClassNotFoundException: me.shedaniel.rei.RoughlyEnoughItemsCoreClient) [22:42:27] [main/WARN]:Error loading class: com/replaymod/replay/ReplayHandler (java.lang.ClassNotFoundException: com.replaymod.replay.ReplayHandler) [22:42:27] [main/WARN]:Error loading class: net/coderbot/iris/pipeline/newshader/ExtendedShader (java.lang.ClassNotFoundException: net.coderbot.iris.pipeline.newshader.ExtendedShader) [22:42:27] [main/WARN]:Error loading class: net/irisshaders/iris/pipeline/programs/ExtendedShader (java.lang.ClassNotFoundException: net.irisshaders.iris.pipeline.programs.ExtendedShader) [22:42:27] [main/INFO]:Initializing MixinExtras via com.llamalad7.mixinextras.service.MixinExtrasServiceImpl(version=0.3.6).
    • My Mohist server crashed as well but all it says in logs is " C:\Minecraft Mohist server>java -Xm6G -jar mohist.jar nogul  Error: Unable to access jarfile mohist.jar   C:\Minecraft Mohist server>PAUSE press any key to continue  .  .  . " Any ideas? i have the server file that its looking for where its looking for it.
    • It is an issue with Pixelmon - maybe report it to the creators
  • Topics

  • Who's Online (See full list)

×
×
  • Create New...

Important Information

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