Jump to content

[1.18.2] Getting ore rarities


MistaOmega

Recommended Posts

Hi all o/

I'm working on a miner that generates ores from the void, much like the Void Miners from ETech.
ETech is closed source, so I haven't been able to see how that developer handled ore generation in a way that kept to the rarities of certain ores, or if it even did it at all.

So far I have used Tags.Blocks.ORES on all the registered blocks in ForgeRegisteries to get a complete list of forge ores, from here I am unsure how to get there rarities, this being, how commonly they spawn underground

I plan to use this value as a modifier during random selection, much like a loot table with each ore having a percentage chance of being selected.

Most of this is determined during world generation, but I am unsure if there's a way to work backwards, or if these ores may contain properties that determine spawn rarity, nothing in the OreBlock class gave this away.

If this is possible, or if anyone has any good information regarding this, please let me know, thank you.

Edited by MistaOmega
Link to comment
Share on other sites

  • MistaOmega changed the title to [1.18.2] Getting ore rarities

In general it is not possible.

If you want to try, e.g. if you just want ores that are placed using the vanilla ore feature you can get the placed features from the server registry

@Mod.EventBusSubscriber(modid = MODID)
public class OreTest {

    @SubscribeEvent
    public static void serverStarting(ServerStartingEvent event) {

        var placedFeatures = event.getServer().registryAccess().registryOrThrow(Registry.PLACED_FEATURE_REGISTRY);

        placedFeatures.forEach(placed -> {
            if (placed.feature().value().config() instanceof OreConfiguration)
                LOGGER.info(placed.toString());
            
        });
    }
}

That misses if/how many biomes use that feature. You would need to check each Biome's BiomeGenerationSettings to find that out.

Then of course you have the issue of whether the biome is used. 🙂 

 

But that's not the hard part. You have to parse the PlacementModifiers. Which are opaque. You can try to parse the known vanilla ones.

 

So, you can work out how to do the above if it is for vanilla (and maybe even known modded ones) but you can't for all mods.

Which is why it isn't really possible.

 

I have heard of people in the past doing some kind of monte carlo simulation where you generate chunks in a dummy world in the background to see how many of each ore was placed.

I can't remember which mod that was?

 

Edited by warjort
  • Like 1

Boilerplate:

If you don't post your logs/debug.log we can't help you. For curseforge you need to enable the forge debug.log in its minecraft settings. You should also post your crash report if you have one.

If there is no error in the log file and you don't have a crash report then post the launcher_log.txt from the minecraft folder. Again for curseforge this will be in your curseforge/minecraft/Install

Large files should be posted to a file sharing site like https://gist.github.com  You should also read the support forum sticky post.

Link to comment
Share on other sites

3 hours ago, warjort said:

In general it is not possible.

If you want to try, e.g. if you just want ores that are placed using the vanilla ore feature you can get the placed features from the server registry

@Mod.EventBusSubscriber(modid = MODID)
public class OreTest {

    @SubscribeEvent
    public static void serverStarting(ServerStartingEvent event) {

        var placedFeatures = event.getServer().registryAccess().registryOrThrow(Registry.PLACED_FEATURE_REGISTRY);

        placedFeatures.forEach(placed -> {
            if (placed.feature().value().config() instanceof OreConfiguration)
                LOGGER.info(placed.toString());
            
        });
    }
}

That misses if/how many biomes use that feature. You would need to check each Biome's BiomeGenerationSettings to find that out.

Then of course you have the issue of whether the biome is used. 🙂 

 

But that's not the hard part. You have to parse the PlacementModifiers. Which are opaque. You can try to parse the known vanilla ones.

 

So, you can work out how to do the above if it is for vanilla (and maybe even known modded ones) but you can't for all mods.

Which is why it isn't really possible.

 

I have heard of people in the past doing some kind of monte carlo simulation where you generate chunks in a dummy world in the background to see how many of each ore was placed.

I can't remember which mod that was?

 

Thank you for that remarkably thorough and detailed answer. Gotta tell me how you got so good lmao

I'll attempt that kind of work around and have a deep dive into it to see if I can pull anything off. Thank you again!

Link to comment
Share on other sites

@warjortAgain your advice was invaluable, thank you, it was a good idea to think of a new method

Here's how I've done it:

A generic ore rarities class will allow the addition of any resource location, you can assign a 0-1 rarity value

A random number gen will give me a random number of up to 6 decimal points of precision, this means the lowest value is 0.000001
Rarity is handled by having these categories of ores, entered into a selection pool based on the value, say the number is 0.1, anything with a value greater than 0.1 is entered into the pool, and an item selected at random. This allows for a good rarity distribution and I've left a copy of my "RarityItem" class here for your viewing displeasure. This class aims to have json support for adding different mods to the system later without having to define them in-code. This class also has versatility in using forge ore prefixes, or exact resource locations
 

package mistaomega.belladonna.lib.helpers;

import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.material.MaterialColor;

import java.math.BigDecimal;

/**
 * Helper class to handle rarity for random resource generation
 * You must have an impl class that defines rarities for each item.
 * TODO This class supports JSON based imports which can be used to define custom ores that aren't by default included
 * This uses BigDecimal, When using the values use the {@link BigDecimal#doubleValue()} method to get the double back
 * This can also use material colors to add the ability to add a color-based rarity modifier if required
 */
public class RarityItem {

    public final ResourceLocation resourceLocation;
    public final BigDecimal weighting;
    public final MaterialColor MaterialColor;

    public RarityItem(String resourceEnd, BigDecimal weighting, MaterialColor MaterialColor){
        this(new ResourceLocation("forge", resourceEnd), weighting, MaterialColor);
    }

    public RarityItem(String resourceEnd, double weighting, MaterialColor MaterialColor){
        this(new ResourceLocation("forge", resourceEnd), BigDecimal.valueOf(weighting), MaterialColor);
    }

    public RarityItem(ResourceLocation resourceLocation, RarityType weighting, MaterialColor MaterialColor){
        this(resourceLocation, BigDecimal.valueOf(weighting.getValue()), MaterialColor);
    }

    public RarityItem(String resourceEnd, RarityType weighting, MaterialColor MaterialColor){
        this(new ResourceLocation("forge", resourceEnd), BigDecimal.valueOf(weighting.getValue()), MaterialColor);
    }

    public RarityItem(ResourceLocation resourceLocation, BigDecimal weighting, MaterialColor MaterialColor){
        if(weighting.doubleValue() > 1d || weighting.doubleValue() < 0d || weighting.scale() > 6){
            throw new IllegalArgumentException("Weighting not in correct ranges: 0 - 1");
        }
        this.resourceLocation = resourceLocation;
        this.weighting = weighting;
        this.MaterialColor = MaterialColor;
    }

    /**
     * Rarity type works on a floating point selection between 0 and 1
     * The category is selected based on the value being less than or equal to the weighting,
     * E.G 0.652, selects up to a common item, 0.011 selects up to an ultra rare item.
     * Note that the logic behind this simply adds the item to the loot table per operation, if the value is 0.000001, all ores can be selected
     * But there is no guarantee it will be an "Impossibly rare" item
     */
    public enum RarityType{
        BASIC(1),
        COMMON(0.8),
        RARE(0.5),
        VERY_RARE(0.2),
        ULTRA_RARE(0.1),
        STUPID_RARE(0.01),
        IMPOSSIBLY_RARE(0.000005);

        private final double value;
        RarityType(double value) {
            this.value = value;
        }

        public double getValue() {
            return value;
        }
    }
}

And here is the current staus of my impl class:

package mistaomega.belladonna.recipe;

import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.material.MaterialColor;

import java.util.ArrayList;
import java.util.List;

import mistaomega.belladonna.lib.helpers.RarityItem;

public class OreRarityImpl {

    public static List<RarityItem> OreRarities = new ArrayList<>();


    public static void init(boolean extras){
        //region vanilla ores
        OreRarities.add(new RarityItem("ores/coal", RarityItem.RarityType.BASIC, MaterialColor.COLOR_LIGHT_GRAY));
        OreRarities.add(new RarityItem("ores/copper", RarityItem.RarityType.BASIC, MaterialColor.COLOR_ORANGE));
        OreRarities.add(new RarityItem("ores/iron", RarityItem.RarityType.COMMON, MaterialColor.COLOR_LIGHT_GRAY));
        OreRarities.add(new RarityItem("ores/gold", RarityItem.RarityType.RARE, MaterialColor.GOLD));
        OreRarities.add(new RarityItem("ores/lapis", RarityItem.RarityType.RARE, MaterialColor.COLOR_BLUE));
        OreRarities.add(new RarityItem("ores/diamond", RarityItem.RarityType.VERY_RARE, MaterialColor.COLOR_LIGHT_BLUE));
        OreRarities.add(new RarityItem("ores/emerald", RarityItem.RarityType.VERY_RARE, MaterialColor.COLOR_GREEN));
        OreRarities.add(new RarityItem("ores/netherite_scrap", RarityItem.RarityType.ULTRA_RARE, MaterialColor.COLOR_BLACK));
        //endregion

        //region mekanism
        OreRarities.add(new RarityItem("ores/osmium", RarityItem.RarityType.COMMON, MaterialColor.COLOR_LIGHT_GRAY));
        OreRarities.add(new RarityItem("ores/tin", RarityItem.RarityType.COMMON, MaterialColor.COLOR_LIGHT_GRAY));
        OreRarities.add(new RarityItem("ores/uranium", RarityItem.RarityType.VERY_RARE, MaterialColor.COLOR_LIGHT_GREEN));
        OreRarities.add(new RarityItem("ores/fluorite", RarityItem.RarityType.RARE, MaterialColor.SNOW));
        OreRarities.add(new RarityItem("ores/lead", RarityItem.RarityType.COMMON, MaterialColor.COLOR_BLUE));
        //endregion

        //region MythicBotany
        OreRarities.add(new RarityItem(new ResourceLocation("mythicbotany:elementium_ore"), RarityItem.RarityType.VERY_RARE, MaterialColor.COLOR_PINK));
        OreRarities.add(new RarityItem(new ResourceLocation("mythicbotany:dragonstone_ore"), RarityItem.RarityType.ULTRA_RARE, MaterialColor.COLOR_PINK));
        //endregion

        //region Thermal
        OreRarities.add(new RarityItem("ores/cinnabar", RarityItem.RarityType.RARE, MaterialColor.COLOR_RED));
        OreRarities.add(new RarityItem("ores/niter", RarityItem.RarityType.RARE, MaterialColor.SNOW));
        OreRarities.add(new RarityItem("ores/silver", RarityItem.RarityType.RARE, MaterialColor.COLOR_LIGHT_GRAY));
        OreRarities.add(new RarityItem("ores/nickel", RarityItem.RarityType.COMMON, MaterialColor.COLOR_YELLOW));
        OreRarities.add(new RarityItem("ores/sulfur", RarityItem.RarityType.COMMON, MaterialColor.COLOR_YELLOW));
        //endregion
    }

    private void initExtrasFromFile(){

    }
}

 

Link to comment
Share on other sites

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.



×
×
  • Create New...

Important Information

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