Jump to content

Recommended Posts

Posted

I'm creating a mod for 1.12, and from what I've seen the JSON recipe system seems to be unable to handle the way my mod is designed.  I recently ran across a thread in this forum that pointed out that the way in which I'm currently registering my recipes in code is completely horrible and should be avoided at all costs.  So, in interest of doing things the right way, I'm hoping someone with a better understanding of the json recipe system could help me out.  My questions are:

 

1. Can the json recipe system handle creating a recipe for items that are not known at compile time?  My mod allows for users to define ores in a .json file, and it will generate ores, ingots, armor, and tools for each ore (based on config).  Registering recipes programmatically makes this trivial, I simple loop through all of my ores and register the recipes for each of them.  In the json system it seems that I would have to know every possible ore that anyone could ever want to create, and have already made a .json for all of them.  

2. Is there a way to take a "template" recipe and at runtime replace a placeholder value with each of my ores in turn? This would solve the issue above.

3. Slightly related, How would a custom IRecipe extending ShapedOreRecipe ignore a portion of an ingredients oredict name.  In my mod, ores can have variants which are registered with name such as oreIronPoor, which would smelt into things like nuggetIron.  I want to have a custom recipe that allows you to craft tools and armor using these lesser versions of ores, and have the end result be pre-damaged.  I don't want to register all of my ores with the oredict name of oreIron, because then even the poor ores could be put through ore-doubling mechanics to completely negate the point of them.

 

I'm hoping someone with a better understanding of this system can at least point me in the right direction.

Posted

1. Yes. At "compile time" there is no compiler relation at all between the JSONs and the item and block classes. The JSON matches based on the string registry names which it doesn't know about until the registration events are run. So recipes are only matched at run time. As long as the items and blocks are registered prior to the recipes I think you're good. For example I've created recipes that change based on configuration settings (requires restart of Minecraft to take effect) because the configuration loads before you register the recipes. You can also create conditions in your recipes and change the conditions in your code to change the behavior of the recipes. I give a few tips on these topics here: http://jabelarminecraft.blogspot.com/p/minecraft-modding-ore-dictionary.html

 

2. You can still implement old-school recipes I think by creating your own IRecipe implementations. They could be a "template" that you construct with different parameters. I haven't tried it but have seen mention of such an approach in other threads.

 

3. If you're extending or implementing the class it is your code, so I think you'd just override the appropriate methods while doing some string processing to take the portion of the name you care about. For example, there is string function for whether a string contains a substring, so if for example the full name contains "OreIron" then you could consider it a match and it should pick up all the variants.

 

All the above is really just about Java. Pretty anything you want to do can be done. You could create your own asset format instead of JSON if you wanted to and use your own Java file handling, you could use reflection and replace major portions of the built-in system, and so forth.

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

Posted
58 minutes ago, jabelar said:

 As long as the items and blocks are registered prior to the recipes I think you're good.

Which if you're using the registry events for your blocks and items, that is guaranteed to run before json recipes are loaded.

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Posted
2 hours ago, jabelar said:

1. Yes. At "compile time" there is no compiler relation at all between the JSONs and the item and block classes. The JSON matches based on the string registry names which it doesn't know about until the registration events are run. So recipes are only matched at run time. As long as the items and blocks are registered prior to the recipes I think you're good. For example I've created recipes that change based on configuration settings (requires restart of Minecraft to take effect) because the configuration loads before you register the recipes. You can also create conditions in your recipes and change the conditions in your code to change the behavior of the recipes. I give a few tips on these topics here: http://jabelarminecraft.blogspot.com/p/minecraft-modding-ore-dictionary.html

By "compile time", I mean when the mod is packaged for release.  In my understanding, the json recipes in the assets folder are placed into the jar at this point.  My issue is that I cannot actually create the recipes ahead of time, because the ores added to my mod are defined by a json file in the configuration directory.  So someone could theoretically use my mod to add an oreUnobtanium.  Aside from some sneaky things like editing the .jar file while it is running, there would be no way to add a "blockUnobtanium.json" (recipe that converts ingots of unobtanium into blocks of unobtanium) into the assets directory of the .jar.  

 

Source code for my mod is here, so it's a little clearer what i'm talking about: Ores 

 

2 hours ago, jabelar said:

 

2. You can still implement old-school recipes I think by creating your own IRecipe implementations. They could be a "template" that you construct with different parameters. I haven't tried it but have seen mention of such an approach in other threads.

I'll look a little deeper into this, I've already implemented a custom IRecipe for some recipes, though I didn't see a way to map a single recipe across an array of possible inputs using the JSON system.

 

Ideally, what i'd like to be able to do is something like this:

{
  "result": {
    "item": "romimocoores:helmet#ORENAME"
  },
  "pattern": [
    "xxx",
    "x x"
  ],
  "type": "forge:wildcard",
  "key": {
    "x": {
      "type": "forge:ore_dict",
      "ore": "ore#ORENAME"
  }
}

Which would then on load be registered for each of the ores in my ModBlocks.ORES hashmap.

 

 

2 hours ago, jabelar said:

3. If you're extending or implementing the class it is your code, so I think you'd just override the appropriate methods while doing some string processing to take the portion of the name you care about. For example, there is string function for whether a string contains a substring, so if for example the full name contains "OreIron" then you could consider it a match and it should pick up all the variants.

Yeah, That was my initial instinct here, though I couldn't wrap my head around how shapedOreRecipe does it's matching of ingredients.  Although after looking, it looks like the answer is in OreIngredient

 

1 hour ago, Draco18s said:

Which if you're using the registry events for your blocks and items, that is guaranteed to run before json recipes are loaded.

Definitely.  Which brings to mind another question.  Is there a RegistryEvent<Recipe>? I originally looked for that so as to do as much as possible in an event driven way, but I didn't see any matching event. 

 

Thanks for the replies.  My Java knowledge is pretty good, and I could hack together something to make this work, however if a way exists to do this using the tools forge provides at the very least it should lead to fewer headaches when 1.13 comes around.

 

 

Posted
28 minutes ago, the_rooster said:

Definitely.  Which brings to mind another question.  Is there a RegistryEvent<Recipe>? I originally looked for that so as to do as much as possible in an event driven way, but I didn't see any matching event.

Yes.

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

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

    • You probably used jd-gui to open it, didn't you? Nothing wrong with that, I also made that mistake, except that Notch was a smart guy and he obfuscated the code. That's why you only see files called "a", "b", "c" and then a file that combines them all. As I said, use RetroMCP to deobfuscate the code so that you will 100% understand it and be able to navigate it.
    • Decompiling minecraft indev, infdev, alpha, beta or whichever legacy version is really easy. I'm not a plug, I just also got interested in modding legacy versions (Infdev to be specific). Use https://github.com/MCPHackers/RetroMCP-Java Once you install their client and the Zulu Architecture that they say they recommend (or use your own Java). I encountered some problems, so I run it with: "java -jar RetroMCP-Java-CLI.jar". You should run it in a seperate folder (not in downloads), otherwise the files and folders will go all over the place. How to use RetroMCP: Type setup (every time you want change version), copy-paste the version number from their list (they support indev), write "decompile" and done! The code will now be deobfuscated and filenames will be normal, instead of "a", "b" and "c"! Hope I helped you, but I don't expect you to reply, as this discussion is 9 years old! What a piece of history!  
    • I know that this may be a basic question, but I am very new to modding. I am trying to have it so that I can create modified Vanilla loot tables that use a custom enchantment as a condition (i.e. enchantment present = item). However, I am having trouble trying to implement this; the LootItemRandomChanceWithEnchantedBonusCondition constructor needs a Holder<Enchantment> and I am unable to use the getOrThrow() method on the custom enchantment declared in my mod's enchantments class. Here is what I have so far in the GLM:   protected void start(HolderLookup.Provider registries) { HolderLookup.RegistryLookup<Enchantment> registrylookup = registries.lookupOrThrow(Registries.ENCHANTMENT); LootItemRandomChanceWithEnchantedBonusCondition lootItemRandomChanceWithEnchantedBonusCondition = new LootItemRandomChanceWithEnchantedBonusCondition(0.0f, LevelBasedValue.perLevel(0.07f), registrylookup.getOrThrow(*enchantment here*)); this.add("nebu_from_deepslate", new AddItemModifier(new LootItemCondition[]{ LootItemBlockStatePropertyCondition.hasBlockStateProperties(Blocks.DEEPSLATE).build(), LootItemRandomChanceCondition.randomChance(0.25f).build(), lootItemRandomChanceWithEnchantedBonusCondition }, OrichalcumItems.NEBU.get())); }   Inserting Enchantments.[vanilla enchantment here] actually works but trying to declare an enchantment from my custom enchantments class as [mod enchantment class].[custom enchantment] does not work even though they are both a ResourceKey and are registered in Registries.ENCHANTMENT. Basically, how would I go about making it so that a custom enchantment declared as a ResourceKey<Enchantment> of value ResourceKey.create(Registries.ENCHANTMENT, ResourceLocation.fromNamespaceAndPath([modid], [name])), declared in a seperate enchantments class, can be used in the LootItemRandomChanceWithEnchantedBonusCondition constructor as a Holder? I can't use getOrThrow() because there is no level or block entity/entity in the start() method and it is running as datagen. It's driving me nuts.
    • Hi here is an update. I was able to fix the code so my mod does not crash Minecraft. Please understand that I am new to modding but I honestly am having a hard time understanding how anyone can get this to work without having extensive programming and debugging experience as well as searching across the Internet, multiple gen AI bots (claude, grok, openai), and examining source code hidden in the gradle directory and in various github repositories. I guess I am wrong because clearly there are thousands of mods so maybe I am just a newbie. Ok, rant over, here is a step by step summary so others can save the 3 days it took me to figure this out.   1. First, I am using forge 54.1.0 and Minecraft 1.21.4 2. I am creating a mod to add a shotgun to Minecraft 3. After creating the mod and compiling it, I installed the .jar file to the proper directory in Minecraft and used 1.21.4-forge-54.1.0 4. The mod immediately crashed with the error: Caused by: java.lang.NullPointerException: Item id not set 5. Using the stack trace, I determined that the Exception was being thrown from the net.minecraft.world.item.Item.Properties class 6. It seems that there are no javadocs for this class, so I used IntelliJ which was able to provide a decompiled version of the class, which I then examined to see the source of the error. Side question: Are there javadocs? 7. This method, specifically, was the culprit: protected String effectiveDescriptionId() {      return this.descriptionId.get(Objects.requireNonNull(this.id, "Item id not set"));  } 8. Now my quest was to determine how to set this.id. Looking at the same source file, I determined there was another method:  public Item.Properties setId(ResourceKey<Item> pId) {             this.id = pId;             return this;   } 9. So now, I need to figure out how to call setId(). This required working backwards a bit. Starting from the constructor, I stubbed out the variable p which is of type Item.Properties public static final RegistryObject<Item> SHOTGUN = ITEMS.register("shotgun", () -> new ShotgunItem(p)); Rather than putting this all on one line, I split it up for readability like this: private static final Item.Properties p = new Item.Properties().useItemDescriptionPrefix().setId(rk); Here is was the missing function, setId(), which takes a type of ResourceKey<Item>. My next problem is that due to the apparent lack of documentation (I tried searching the docs on this site) I could not determine the full import path to ResourceKey. I did some random searching on the Internet and stumbled across a Github repository which gave two clues: import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; Then I created the rk variable like this: private static ResourceKey<Item> rk = ResourceKey.create(Registries.ITEM, ResourceLocation.parse("modid:shotgunmod")); And now putting it all together in order: private static ResourceKey<Item> rk = ResourceKey.create(Registries.ITEM, ResourceLocation.parse("modid:shotgunmod")); private static final Item.Properties p = new Item.Properties().useItemDescriptionPrefix().setId(rk); public static final RegistryObject<Item> SHOTGUN = ITEMS.register("shotgun", () -> new ShotgunItem(p)); This compiled and the mod no longer crashes. I still have more to do on it, but hopefully this will save someone hours. I welcome any feedback and if I missed some obvious modding resource or tutorial that has this information. If not, I might suggest we add it somewhere for people trying to write a mod that doesn't crash. Thank you !!!  
  • Topics

×
×
  • Create New...

Important Information

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