Jump to content

[SOLVED] (1.19) Configuring Per-Biome Spawn Weight for Entities using TOML Configs


Recommended Posts

Posted (edited)

I'm currently updating my mod from 1.18, which previously allowed players to define the spawn weight of my custom entity for any biome via .TOML config files. This was done by subscribing to BiomeLoadingEvent and adding to the spawn list. That event has now been removed in favor of the new data-driven system, which I am still trying to fully grasp.

My current idea is to hook into GatherDataEvent and iterate through the list of user-defined biomes from the config, but the issue is that the configs aren't loaded at this stage, and runData crashes because the ForgeConfigSpec isn't initialized yet.

Here's what I currently have:

@SubscribeEvent
    public static void gatherData(GatherDataEvent event)
    {
        DataGenerator generator = event.getGenerator();
        ExistingFileHelper helper = event.getExistingFileHelper();
        RegistryOps<JsonElement> registryOps = RegistryOps.create(JsonOps.INSTANCE, RegistryAccess.builtinCopy());

		<...>          
          
        EntityType<ChameleonEntity> chameleon = EntityInit.CHAMELEON.get();
        ConfigSettings.CHAMELEON_BIOMES.get().forEach((biomeID, weight) ->
        {
            ForgeRegistries.BIOMES.getHolder(biomeID).ifPresent(biomeHolder ->
            {
                modifiers.put(new ResourceLocation(ColdSweat.MOD_ID, "chameleon_spawns_" + biomeID.getNamespace() + "_" + biomeID.getPath()),
                              ForgeBiomeModifiers.AddSpawnsBiomeModifier.singleSpawn(HolderSet.direct(biomeHolder), new MobSpawnSettings.SpawnerData(chameleon, weight, 1, 1)));
            });
        });

        JsonCodecProvider<BiomeModifier> jsonCodecProvider = JsonCodecProvider.forDatapackRegistry(generator, helper, ColdSweat.MOD_ID, registryOps, ForgeRegistries.Keys.BIOME_MODIFIERS, modifiers);
        generator.addProvider(event.includeServer(), jsonCodecProvider);
    }

And here's the code on GitHub: https://github.com/Momo-Studios/Cold-Sweat/blob/1.19.x-FG/src/main/java/dev/momostudios/coldsweat/data/ColdSweatData.java

Is there a way to access the configs at this stage, or should I be using another way? I'd highly prefer using the configs since they're simpler to edit for users.

Edited by Mikul
Solved
Posted
13 hours ago, Mikul said:

I'm currently updating my mod from 1.18, which previously allowed players to define the spawn weight of my custom entity for any biome via .TOML config files.

You should just let people change this via a datapack. That's literally the point since they can replace the values themselves.

Posted
1 hour ago, ChampionAsh5357 said:

You should just let people change this via a datapack. That's literally the point since they can replace the values themselves.

I understand that it's their intended purpose, and they're definitely much more versatile, but I find them more cumbersome to use than the configs I had set up before, and I think most of my user base would agree.

Plus, what I'm attempting to do wouldn't prevent anyone from using a data pack if they want, to my knowledge.

  • Mikul changed the title to (1.19) Configuring Per-Biome Spawn Weight for Entities using Configs
Posted (edited)

I think I've misunderstood how data generation works. I thought GatherDataEvent was called at runtime, but I've found that it's only used for generating static JSON files when runData is executed, which are shipped with the mod. It seems to me that it's now impossible to do this in the way that I originally had.

And I now have another concern about these data-driven biome modifiers. How is inter-mod compatibility implemented? Say I wanted my entity to spawn in rainforests from Biomes O' Plenty (optional dependency). If I make a file adding the mob to "biomesoplenty:rainforest", datapack loading now fails unless the "biomesoplenty" is loaded. I cannot find any way to make this an "optional" biome modifier, similar to how tags can be optional. Am I missing something?

Edited by Mikul
  • Mikul changed the title to (1.19) Configuring Per-Biome Spawn Weight for Entities using TOML Configs
Posted
13 hours ago, Mikul said:

It seems to me that it's now impossible to do this in the way that I originally had.

You can technically screw with it using a biome modifier to force the config check yourself; however, I still recommend against it.

13 hours ago, Mikul said:

I cannot find any way to make this an "optional" biome modifier, similar to how tags can be optional. Am I missing something?

You can make an optional biome modifier. Create your own that checks if the mod is loaded first, and don't do anything if it isn't.

Posted
35 minutes ago, ChampionAsh5357 said:

You can technically screw with it using a biome modifier to force the config check yourself; however, I still recommend against it.

You can make an optional biome modifier. Create your own that checks if the mod is loaded first, and don't do anything if it isn't.

Alright, then I'll look into making my own. Thank you for the suggestion. If biome modifiers are a Forge construct then I might suggest that optionality be added To the built-in ones.

Posted
3 minutes ago, Mikul said:

If biome modifiers are a Forge construct then I might suggest that optionality be added To the built-in ones.

They are, but there is a PR in the works to add conditional loading to all JSON files, so that's likely the implementation it's going for.

Posted (edited)

Making a custom biome modifier worked. I just need a dummy JSON file for the modifier to be loaded, then it injects the spawns according to the config settings. I also added an option to disable this, if the user wanted to define the spawns the normal way. It looks something like this:

// This is a generic version of my implementation, without all the stuff specific to my mod
@Override
public void modify(Holder<Biome> biome, Phase phase, ModifiableBiomeInfo.BiomeInfo.Builder builder)
{
    // Ensure proper phase and user is using configs
    if (phase == Phase.ADD && useConfigs)
    {   // Null check for optional ResourceKey
        biome.unwrapKey().ifPresent(biomeKey ->
        {   
            ResourceLocation biomeID = biomeKey.location();
            // I have a static map of the user's configured spawn weights parsed from the config
            Integer weight = MAP_OF_ENTITY_WEIGHTS.get(biomeID);
            // Weight is null if undefined
            if (weight != null)
            {   builder.getMobSpawnSettings().addSpawn(MobCategory.CREATURE, new MobSpawnSettings.SpawnerData(MyEntity, weight, 1, 1));
            }
        });
    }
}

This also has no problems with other mods' biomes being present or not, since it's only called for existing biomes in the registry.

Thanks for pointing me in the right direction. I needed to take a second look at custom biome modifiers to see how to do this.

Edited by Mikul
  • Mikul changed the title to [SOLVED] (1.19) Configuring Per-Biome Spawn Weight for Entities using TOML Configs

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

    • Im trying to build my mod using shade since i use the luaj library however i keep getting this error Reason: Task ':reobfJar' uses this output of task ':shadowJar' without declaring an explicit or implicit dependency. This can lead to incorrect results being produced, depending on what order the tasks are executed. So i try adding reobfJar.dependsOn shadowJar  Could not get unknown property 'reobfJar' for object of type org.gradle.api.internal.artifacts.dsl.dependencies.DefaultDependencyHandler. my gradle file plugins { id 'eclipse' id 'idea' id 'maven-publish' id 'net.minecraftforge.gradle' version '[6.0,6.2)' id 'com.github.johnrengelman.shadow' version '7.1.2' id 'org.spongepowered.mixin' version '0.7.+' } apply plugin: 'net.minecraftforge.gradle' apply plugin: 'org.spongepowered.mixin' apply plugin: 'com.github.johnrengelman.shadow' version = mod_version group = mod_group_id base { archivesName = mod_id } // Mojang ships Java 17 to end users in 1.18+, so your mod should target Java 17. java.toolchain.languageVersion = JavaLanguageVersion.of(17) //jarJar.enable() println "Java: ${System.getProperty 'java.version'}, JVM: ${System.getProperty 'java.vm.version'} (${System.getProperty 'java.vendor'}), Arch: ${System.getProperty 'os.arch'}" minecraft { mappings channel: mapping_channel, version: mapping_version copyIdeResources = true runs { configureEach { workingDirectory project.file('run') property 'forge.logging.markers', 'REGISTRIES' property 'forge.logging.console.level', 'debug' arg "-mixin.config=derp.mixin.json" mods { "${mod_id}" { source sourceSets.main } } } client { // Comma-separated list of namespaces to load gametests from. Empty = all namespaces. property 'forge.enabledGameTestNamespaces', mod_id } server { property 'forge.enabledGameTestNamespaces', mod_id args '--nogui' } gameTestServer { property 'forge.enabledGameTestNamespaces', mod_id } data { workingDirectory project.file('run-data') args '--mod', mod_id, '--all', '--output', file('src/generated/resources/'), '--existing', file('src/main/resources/') } } } sourceSets.main.resources { srcDir 'src/generated/resources' } repositories { flatDir { dirs './libs' } maven { url = "https://jitpack.io" } } configurations { shade implementation.extendsFrom shade } dependencies { minecraft "net.minecraftforge:forge:${minecraft_version}-${forge_version}" implementation 'org.luaj:luaj-jse-3.0.2' implementation fg.deobf("com.github.Virtuoel:Pehkui:${pehkui_version}") annotationProcessor 'org.spongepowered:mixin:0.8.5:processor' minecraftLibrary 'luaj:luaj-jse:3.0.2' shade 'luaj:luaj-jse:3.0.2' } // Example for how to get properties into the manifest for reading at runtime. tasks.named('jar', Jar).configure { manifest { attributes([ 'Specification-Title' : mod_id, 'Specification-Vendor' : mod_authors, 'Specification-Version' : '1', // We are version 1 of ourselves 'Implementation-Title' : project.name, 'Implementation-Version' : project.jar.archiveVersion, 'Implementation-Vendor' : mod_authors, 'Implementation-Timestamp': new Date().format("yyyy-MM-dd'T'HH:mm:ssZ"), "TweakClass" : "org.spongepowered.asm.launch.MixinTweaker", "TweakOrder" : 0, "MixinConfigs" : "derp.mixin.json" ]) } rename 'mixin.refmap.json', 'derp.mixin-refmap.json' } shadowJar { archiveClassifier = '' configurations = [project.configurations.shade] finalizedBy 'reobfShadowJar' } assemble.dependsOn shadowJar reobf { re shadowJar {} } publishing { publications { mavenJava(MavenPublication) { artifact jar } } repositories { maven { url "file://${project.projectDir}/mcmodsrepo" } } }  
    • All versions of Minecraft Forge suddenly black screen even without mods (tried reinstalling original Minecraft, Java, updating drivers doesn't work)
    • When i join minecraft all ok, when i join world all working fine, but when i open indentity menu, i get this The game crashed whilst unexpected error Error: java.lang.NullPointerException: Cannot invoke "top.ribs.scguns.common.Gun$Projectile.getDamage()" because "this.projectile" is null crash report here https://paste.ee/p/0vKaf
  • Topics

×
×
  • Create New...

Important Information

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