Jump to content

How to Avoid Using Int Enchant IDs in JSON Recipes


codahq

Recommended Posts

I'm trying to update my mod to 1.12.2.  Some of my recipes return books with stored enchants.  I can't figure out how to do this without using NBT and the int IDs of the enchants.  

 

 

According to @diesieben07 they should never be used.  How do I avoid using them in this scenario?  For example, I am using this as a recipe.  

 

{
    "type": "minecraft:crafting_shaped",
    "pattern":
    [
        "pbp",
        " p "
    ],
    "key":
    {
        "p":
        {
            "item": "minecraft:ender_pearl"
        },
        "b":
        {
            "item": "minecraft:book"
        }
    },
    "result":
    {
        "item": "minecraft:enchanted_book",
        "nbt": 
        {
            "StoredEnchantments": 
            [
                {
                    "id": 32,
                    "lvl": 1
                }
            ]
        }
    }
}

 

How can this be done without the int ID.  This is especially important since I also have custom enchants.

Edited by codahq
Additional Information:
Link to comment
Share on other sites

It took me a little while to figure this out because there aren't really that many examples out there but thanks for getting me on correct path.  Here is what I ended up doing.

 

JSON recipe:

{
    "type": "pearlmod:shaped_enchanting_book_recipe",
    "pattern": 
    [
        "fbf",
        " p "
    ],

    "key": 
    {
        "p": 
        {
            "item": "minecraft:ender_pearl"
        },

        "b": 
        {
            "item": "minecraft:book"
        },

        "f": 
        {
            "item": "minecraft:feather"
        }
    },

    "result": 
    {
        "item": "minecraft:enchanted_book",
        "enchantments": 
        [
            {
                "enchant": "minecraft:infinity",
                "lvl": 1
            }
        ]
    }
}

 

Parse method on recipe factory:

@Override
	public IRecipe parse(JsonContext context, JsonObject json)
	{
		ShapedOreRecipe recipe = ShapedOreRecipe.factory(context, json);
		ItemStack output = recipe.getRecipeOutput();

		final JsonObject result = JsonUtils.getJsonObject(json, "result");
		final String item = JsonUtils.getString(result, "item");
		assert item == "minecraft:enchanted_book";
		final JsonArray enchantments = JsonUtils.getJsonArray(result, "enchantments");
		for (JsonElement e : enchantments)
		{
			final String enchant = JsonUtils.getString(e.getAsJsonObject(), "enchant");
			final int lvl = JsonUtils.getInt(e.getAsJsonObject(), "lvl");
			EnchantmentData storedEnchant = new EnchantmentData(Enchantment.getEnchantmentByLocation(enchant), lvl);
			ItemEnchantedBook.addEnchantment(output, storedEnchant);
		}

		ShapedPrimer primer = new ShapedPrimer();
		primer.width = recipe.getRecipeWidth();
		primer.height = recipe.getRecipeHeight();
		primer.mirrored = JsonUtils.getBoolean(json, "mirrored", true);
		primer.input = recipe.func_192400_c();

		return new ShapedEnchantingBookRecipe(new ResourceLocation(Constants.modid, "shaped_enchanting_book_recipe"), output, primer);
	}

 

I'm not sure if there was a more effective way of parsing the JSON or not.  I'm not familiar with teh goog's JSON library and I didn't find any quick examples so I just fudged this together quickly.

 

At any rate, this works.  If anybody has a suggestion to make it better please contribute to the example.

Link to comment
Share on other sites

So, embarrassingly enough this doesn't work but I didn't notice because I didn't test it very well. 

 

At any rate, it works with the OOB enchants but it doesn't work with the custom enchants.  In parse it stores an int for the custom enchant's without using resource location for compatibility so it's just an int ID in NBT.  But by the time you are in-game and the recipe class's getCraftingResult method is called those enchant IDs have been changed.  Since I can't control when EITHER of the registry events happen (recipe factory or enchant registering), what am I supposed to do now?'

 

I guess I could store NBT data in the stack so I can find it later and just build the output stack when getCraftingResult is called but won't that break NEI, JEI, etc?

Link to comment
Share on other sites

5 hours ago, codahq said:

what am I supposed to do now?

Write your own IRecipe implementation. Potentially just override getResult() from one of the ShapedRecipes. (I think that is the methods name). And have it return a new ItemStack with the EnchantmentData that is stored in your IRecipe implementation.

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Link to comment
Share on other sites

Here's an example:

https://github.com/Draco18s/ReasonableRealism/blob/1.14.4/src/main/java/com/draco18s/hardlib/api/recipe/RecipeTagOutput.java

My recipe returns an output based on tags (as all things tagged as iron (copper, steel, tin...) ingots (dust, nuggets...) are all functionally iron ingots, and all I want is to have an iron ingot output, find all items tagged as iron ingot and get the first one), but the general process would be the same for grabbing enchantments by registry name.

Edited by Draco18s

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.

Link to comment
Share on other sites

Yes, thank you to both of you.  I understand that I need to implement logic on the result.  I'm not able to just implement logic in parse as I was doing previously.  The dilemma now is that the result itemstack that I give during parse (and pre-init) is different than the result itemstack that I would give during recipe use and when getCraftingResult is called in-game.

 

For example...  the id in the NBT for stored enchant in pre-init is assigned to, let's say 85, and written to the item stack.  But if I call Enchantment.getEnchantmentbyId(85) in-game that enchant ID has been moved since pre-init and it fails to find an enchant with 85.  If I get the id again with the resource location it returns 95 let's say.

 

So, if I use the old result with the old ID it has bad enchantment data in it.  I can recreate the output (which I'm doing in the current implementation in getCraftingResult) by getting the new id from the resource location but that breaks mods like JEI, NEI which must be caching or grabbing data created during pre-init.  

 

Doesn't that bother anybody?  That I have to return two different stacks?  Or is that the way it should be?  Shouldn't those stacks be the same?  Wouldn't you think the factory event should fire AFTER the enchant IDs are moved so that the result that is saved during the factory's parse stores a recipe result with the current enchant IDs?

Link to comment
Share on other sites

34 minutes ago, codahq said:

For example...  the id in the NBT for stored enchant in pre-init is assigned to, let's say 85, and written to the item stack.  But if I call Enchantment.getEnchantmentbyId(85) in-game that enchant ID has been moved since pre-init and it fails to find an enchant with 85.  If I get the id again with the resource location it returns 95 let's say.

And this is why you don't used numerical IDs anywhere ever.

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.

Link to comment
Share on other sites

3 hours ago, Draco18s said:

And this is why you don't used numerical IDs anywhere ever.

I'm not.  You're not getting it yet.  I'm using the resource location as is best practice.  Minecraft/forge is assigning the int ID.  Then it runs the recipe factories and builds the result with the first IDs.  Then at some point it changes the IDs.  Eventually in game when I use the same resource location I get a different ID back.  The recipe output built during pre-init has the wrong IDs.  Do you understand?

Edited by codahq
*spelling
Link to comment
Share on other sites

Let me tee it up for you.  See the attached code examples:

 

The output:

[22:24:34] [main/INFO] [STDOUT]: [me.bendy.pearlmod.recipe.ShapedEnchantingBookRecipeFactory:parse:48]: pre-init :: location: pearlmod:ender_stability id: 11 lvl: 1

 

And when I use the recipe in a table in-game later on:

[22:25:31] [Server thread/INFO] [STDOUT]: [me.bendy.pearlmod.recipe.ShapedEnchantingBookRecipeFactory$ShapedEnchantingBookRecipe:getCraftingResult:91]: in-game :: location: pearlmod:ender_stability id: 90 lvl: 1

 

PearlmodEnchants.java ShapedEnchantingBookRecipeFactory.java _factories.json book_ender_stability.json

Link to comment
Share on other sites

11 hours ago, codahq said:

Doesn't that bother anybody?  That I have to return two different stacks?

Why would you have to return two different stacks?

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Link to comment
Share on other sites

5 hours ago, Animefan8888 said:

Why would you have to return two different stacks?

Because forge has changed the int IDs of the enchants since the factories were called.  If I don't return a different stack, when the recipe is used the first stack is returned with IDs that no longer match any enchants.  Since the IDs are not the same anymore it the ItemStack shows as an enchanted book with stored enchants but the stored enchants are missing.

Link to comment
Share on other sites

2 minutes ago, codahq said:

Because forge has changed the int IDs of the enchants since the factories were called.  If I don't return a different stack, when the recipe is used the first stack is returned with IDs that no longer match any enchants.  Since the IDs are not the same anymore it the ItemStack shows as an enchanted book with stored enchants but the stored enchants are missing.

Why not just return one stack...Pass in the raw enchantment data. IE the registry names and levels. Then compute the enchantments after the registry has been loaded. In both the output methods in your IRecipe implementation because it appears you are only doing it in one.

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Link to comment
Share on other sites

That exactly what I did in my workaround.  I decided to put the resource location and level in the factory ItemStack so it would be there for easy access in getCraftingResult.  This is still a problem though because apparently mods like NEI/JEI look and cache recipes during pre-init or shortly afterwards.  If I don't put the wrong, soon-to-be-replaced enchants on the books during factory pre-init they won't show up in those mods.  

 

I don't need a workaround.  I don't need a solution.  I have that already.  I'm continuing to post now because I want somebody to realize and validate what I'm saying about the order of these events.  Why are the IDs changed AFTER recipe registration instead of before?  Or why aren't they adjusted?  I have to return ItemStacks with two different IDs for the same enchant for this to work.  The order should be changed so that I don't have to do that OR when the IDs are changed by forge forge SHOULD go to all of the places they are used and update them.

Link to comment
Share on other sites

6 hours ago, codahq said:

I'm continuing to post now because I want somebody to realize and validate what I'm saying about the order of these events.

It didn't replicate the issue when I downloaded your file you sent.
 

Quote

[04:02:58] [main/INFO] [STDOUT]: [me.bendy.pearlmod.recipe.ShapedEnchantingBookRecipeFactory:parse:47]: pre-init :: location: blah:stability id: 11 lvl: 1
...
[04:03:46] [Server thread/INFO] [STDOUT]: [me.bendy.pearlmod.recipe.ShapedEnchantingBookRecipeFactory$ShapedEnchantingBookRecipe:getCraftingResult:90]: in-game :: location: blah:stability id: 11 lvl: 1

Try creating a new world.

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Link to comment
Share on other sites

9 hours ago, codahq said:

This is still a problem though because apparently mods like NEI/JEI look and cache recipes during pre-init or shortly afterwards. 

That's their problem and they should fix it.

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.

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.

Announcements



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • LOGIN DAN DAFTAR DISINI CEPAT!! AYUTOGEL adalah situs judi online yang memudahkan para pemainnya, dengan menggunakan deposit pulsa terbilang cukup memudahkan para pemainnya dikarenakan setiap orang pasti bisa mengisi pulsa di mana pun dengan agen agen pulsa, dengan mudah di dapat kan dimana mana jika para pemain tidak memiliki e-money atau m-banking anda tidak perlu khawatir lagi di karenakan AYUTOGEL adalah situs slot deposit pulsa. Slot Deposit pulsa adalah sebuah situs judi slot online yang melayani deposit menggunakan transfer pulsa atau menggunakan pulsa ponsel yang tersedia.
    • DAFTAR DAN LOGIN DISINI   Hantogel atau handogel adalah bentuk pengumpulan duka uang yang populer di dunia judi online, khususnya dalam permainan slot gacor. Banyak situs judi online yang menawarkan handogel slot gacor, dan sebagai pemain, penting untuk mengetahui cara memilih dan mengakses situs tersebut dengan aman dan amanah. Dalam artikel ini, kami akan membahas cara memilih situs slot gacor online yang berkualitas dan tahu cara mengakses handogelnya.
    • DAFTAR & LOGIN SIRITOGEL Siritogel adalah kumpulan kata yang mungkin baru saja dikenal oleh masyarakat, namun dengan perkembangan teknologi dan banyaknya informasi yang tersedia di internet, kalau kita siritogel (mencari informasi dengan cara yang cermat dan rinci) tentang situs slot gacor online, maka kita akan menemukan banyak hal yang menarik dan membahayakan sama sekali. Dalam artikel ini, kita akan mencoba menjelaskan apa itu situs slot gacor online dan bagaimana cara mengatasi dampaknya yang negatif.
    • This honestly might just work for you @SubscribeEvent public static void onScreenRender(ScreenEvent.Render.Post event) { final var player = Minecraft.getInstance().player; final var options = Minecraft.getInstance().options; if(!hasMyEffect(player)) return; // TODO: You provide hasMyEffect float f = Mth.lerp(event.getPartialTick(), player.oSpinningEffectIntensity, player.spinningEffectIntensity); float f1 = ((Double)options.screenEffectScale().get()).floatValue(); if(f <= 0F || f1 >= 1F) return; float p_282656_ = f * (1.0F - f1); final var p_282460_ = event.getGuiGraphics(); int i = p_282460_.guiWidth(); int j = p_282460_.guiHeight(); p_282460_.pose().pushPose(); float f5 = Mth.lerp(p_282656_, 2.0F, 1.0F); p_282460_.pose().translate((float)i / 2.0F, (float)j / 2.0F, 0.0F); p_282460_.pose().scale(f5, f5, f5); p_282460_.pose().translate((float)(-i) / 2.0F, (float)(-j) / 2.0F, 0.0F); float f4 = 0.2F * p_282656_; float f2 = 0.4F * p_282656_; float f3 = 0.2F * p_282656_; RenderSystem.disableDepthTest(); RenderSystem.depthMask(false); RenderSystem.enableBlend(); RenderSystem.blendFuncSeparate(GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ONE, GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ONE); p_282460_.setColor(f4, f2, f3, 1.0F); p_282460_.blit(new ResourceLocation("textures/misc/nausea.png"), 0, 0, -90, 0.0F, 0.0F, i, j, i, j); p_282460_.setColor(1.0F, 1.0F, 1.0F, 1.0F); RenderSystem.defaultBlendFunc(); RenderSystem.disableBlend(); RenderSystem.depthMask(true); RenderSystem.enableDepthTest(); p_282460_.pose().popPose(); }   Note: Most of this is directly copied from GameRenderer as you pointed out you found. The only thing you'll have to likely do is update the `oSpinningEffectIntensity` + `spinningEffectIntensity` variables on the player when your effect is applied. Which values should be there? Not 100% sure, might be a game of guess and check, but `handleNetherPortalClient` in LocalPlayer has some hard coded you might be able to start with.
    • Dalam dunia perjudian online yang berkembang pesat, mencari platform yang dapat memberikan kemenangan maksimal dan hasil terbaik adalah impian setiap penjudi. OLXTOTO, dengan bangga, mempersembahkan dirinya sebagai jawaban atas pencarian itu. Sebagai platform terbesar untuk kemenangan maksimal dan hasil optimal, OLXTOTO telah menciptakan gelombang besar di komunitas perjudian online. Satu dari banyak keunggulan yang dimiliki OLXTOTO adalah koleksi permainan yang luas dan beragam. Dari togel hingga slot online, dari live casino hingga permainan kartu klasik, OLXTOTO memiliki sesuatu untuk setiap pemain. Dibangun dengan teknologi terkini dan dikembangkan oleh para ahli industri, setiap permainan di platform ini dirancang untuk memberikan pengalaman yang tak tertandingi bagi para penjudi. Namun, keunggulan OLXTOTO tidak hanya terletak pada variasi permainan yang mereka tawarkan. Mereka juga menonjol karena komitmen mereka terhadap keamanan dan keadilan. Dengan sistem keamanan tingkat tinggi dan proses audit yang ketat, OLXTOTO memastikan bahwa setiap putaran permainan berjalan dengan adil dan transparan. Para pemain dapat merasa aman dan yakin bahwa pengalaman berjudi mereka di OLXTOTO tidak akan terganggu oleh masalah keamanan atau keadilan. Tak hanya itu, OLXTOTO juga terkenal karena layanan pelanggan yang luar biasa. Tim dukungan mereka selalu siap sedia untuk membantu para pemain dengan segala pertanyaan atau masalah yang mereka hadapi. Dengan respon cepat dan solusi yang efisien, OLXTOTO memastikan bahwa pengalaman berjudi para pemain tetap mulus dan menyenangkan. Dengan semua fitur dan keunggulan yang ditawarkannya, tidak mengherankan bahwa OLXTOTO telah menjadi pilihan utama bagi jutaan penjudi online di seluruh dunia. Jika Anda mencari platform yang dapat memberikan kemenangan maksimal dan hasil optimal, tidak perlu mencari lebih jauh dari OLXTOTO. Bergabunglah dengan OLXTOTO hari ini dan mulailah petualangan Anda menuju kemenangan besar dan hasil terbaik!
  • Topics

×
×
  • Create New...

Important Information

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