Jump to content

[1.12.2] Registering an item with default NBT tag(s)


Nikedemos

Recommended Posts

Hi everyone, I've literally joined just now - mainly to ask a question that has bugging me for a while!

 

I'm quite new to Forge, still learning, but already at a point where I've read / watched all the popular 1.12.2 forge tutorials - and none of them brought me any closer to a solution. I googled and googled, found nothing useful, so here it goes:

 

I know how to get/set NBT tags for itemstacks. I can do it fine in events such as right click/block place / tick update etc - but I have no clue how to make it so a newly registered item

has a default NBT tag BEFORE anything else is done with it. Also, how to make it so items with certain NBT tags are placed in the Creative Inventory?

For instance, I have an item called Watering Can, with water_level (int) tag, going from 0 to 8. I want the two "variants" (not actual variants in the minecraft sense), one with water_level 0,

and one with water_level 8, to be added to my mod's Creative Inventory - but not the ones between 1 and 7, inclusive. And yes, I know how to add "normal" items without tags.

 

This question is related to the mod I'm working on - there's quite an early, but semi-functional version on github. If you think it'd help, let me know, and I'll post the link.

 

I really hope I made the question clear - in any other case, just give me a shout, and I'll re-phrase / elaborate. Thanks!

Link to comment
Share on other sites

6 minutes ago, Nikedemos said:

so a newly registered item

has a default NBT tag BEFORE anything else is done with it

This is impossible. You have to handle the cases where there isn't an NBTTagCompound attached to the item at all. The best way is to stop using NBT alltogether and use capabilities since a capability will always be attached to an ItemStack regardless of how the stack was created.

 

6 minutes ago, Nikedemos said:

how to make it so items with certain NBT tags are placed in the Creative Inventory?

Use Item#getSubItems, create a new ItemStack, assign the NBT needed to it and add it to the list.

 

 

  • Like 1
Link to comment
Share on other sites

Oh wow that was quick! Thanks. I'll definitely look into Capabilities, haven't had the need to use them yet, but it looks like I have no choice now :)

 

when it comes to Item#getSubItems, it looks like it should return a list of subtypes - but I haven't defined any. The "variants" are not actually subtypes, it's just the model is based on the water_level NBT value. Should I define any subtypes in the class code first?

 

EDIT: Oh and also, this is how items are added to the creative tab in my approach. Where does this Item#getSubItems method go, then? In my ModItems class, where I register items?

Edited by Nikedemos
forgot to ask
Link to comment
Share on other sites

7 minutes ago, Nikedemos said:

it looks like it should return a list of subtypes - but I haven't defined any

It's a void method. It doesn't return anything. The list you can add ItemStacks to is passed to you as the second argument, the first one being the creative tab that invoked the method in the first place.

7 minutes ago, Nikedemos said:

The "variants" are not actually subtypes, it's just the model is based on the water_level NBT value. Should I define any subtypes in the class code first?

I think you misunderstand what subtypes are. A subtype for an ItemStack is any itemstack that has the same Item but differs in something else like NBT or metadata(hence the name, it's a sub type of the Item). You do not need to "define them in class code" whatever that even means. Just populate the list passed to you as an argyment with whatever items you want added to the creative tab. For example here is me populating the creative tab with 16 versions of my items, each having a different color stored in it's capability. 

Edited by V0idWa1k3r
Link to comment
Share on other sites

8 minutes ago, V0idWa1k3r said:

It's a void method. It doesn't return anything. The list you can add ItemStacks to is passed to you as the second argument, the first one being the creative tab that invoked the method in the first place.

I think you misunderstand what subtypes are. A subtype for an ItemStack is any itemstack that has the same Item but differs in something else like NBT or metadata(hence the name, it's a sub type of the Item). You do not need to "define them in class code" whatever that even means. Just populate the list passed to you as an argyment with whatever items you want added to the creative tab. For example here is me populating the creative tab with 16 versions of my items, each having a different color stored in it's capability. 

I see! Thanks so much for the provided example... and your patience ;) Basically, by "defining the subtypes in the class code" I meant exactly what you did right there:

        for (EnumDyeColor dyeColor : EnumDyeColor.values())
        {
            ItemStack is = new ItemStack(this, 1, 0);
            IBackpack.of(is).createWrapper().setColor(dyeColor.getColorValue());
            items.add(is);
		}

 

It's a for loop - so it's going to add as many subtypes as there are dyes, correct? Thus, I dunno.... defining them? Defining them by NBT/meta, dye color's value in this case? Maybe that's not the right word... but it definitely adds stuff to the List. I am struggling to understand though - how is that list processed afterwards? Where is the bit that says "yes, add THIS itemstack to the Creative Tab"?

 

Where do I call this getSubTypes method, be it an overriden one, or the one from Item.java? Or does it get called automatically?

Link to comment
Share on other sites

9 minutes ago, Nikedemos said:

I am struggling to understand though - how is that list processed afterwards? Where is the bit that says "yes, add THIS itemstack to the Creative Tab"?

The game simply creates a NonNullList<ItemStack>, then calls this method for each item in the registry with that list as the second parameter and current creative tab as the first. Anything that ended up in the list is displayed in the creative tab. See GuiContainerCreative if you want to study this process in greater detail. This also answers your question of how to use this method. Just override it and you will be good to go.

 

 

Link to comment
Share on other sites

1 minute ago, V0idWa1k3r said:

The game simply creates a NonNullList<ItemStack>, then calls this method for each item in the registry with that list as the second parameter and current creative tab as the first. Anything that ended up in the list is displayed in the creative tab. See GuiContainerCreative if you want to study this process in greater detail. This also answers your question of how to use this method. Just override it and you will be good to go.

 

 

AWESOME. Now it's crystal clear. Consider this <SOLVED>! Thank you so much for all your help!

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

    • Pretty much, although all the recipes im planning to make on it are shapeless. The idea is that the chamber uses energy to "fuse" the items in each of the center slots together, in this case an ingot. The two slots at the sides are fuel. (A special kind of wood in this case). Here is an image of the interface just for reference (The center slot is the output)   As for the code- Can you elaborate a little bit on it? Seeing three different record classes has confused me a lot. (Elaborate as in why make them in three different records. I understand the code itself more or less)
    • Hello im trying to make a mod and the past few days GSON has almost killed me, when i export the mod and then launch it through minecraft launcher i get java.lang.NoSuchMethodError: com.google.gson.JsonParser.parseString(Ljava/lang/String;)Lcom/google/gson/JsonElement; i have literally tried everything here is my build config   dependencies { minecraft("com.mojang:minecraft:1.8.9") mappings("de.oceanlabs.mcp:mcp_stable:22-1.8.9") forge("net.minecraftforge:forge:1.8.9-11.15.1.2318-1.8.9") compileOnly("cc.polyfrost:oneconfig-1.8.9-forge:0.2.2-alpha+") shadowImpl("cc.polyfrost:oneconfig-wrapper-launchwrapper:1.0.0-beta+") { isTransitive = false exclude(module = "gson") } shadowImpl("org.spongepowered:mixin:0.7.11-SNAPSHOT") { isTransitive = false exclude(module = "gson") } annotationProcessor("org.spongepowered:mixin:0.8.5-SNAPSHOT") shadowImpl("org.javassist:javassist:3.15.0-GA") { isTransitive = false exclude(module = "gson") } shadowImpl("com.neovisionaries:nv-i18n:1.28") { isTransitive = false exclude(module = "gson") } shadowImpl("org.apache.commons:commons-lang3:3.4") { isTransitive = false exclude(module = "gson") } shadowImpl("org.apache.httpcomponents:httpcore:4.4.5") { isTransitive = false exclude(module = "gson") } compileOnly("com.google.code.gson:gson:2.8.6") { isTransitive = false } configurations.all { resolutionStrategy { force("com.google.code.gson:gson:2.8.6") } } shadowImpl(fileTree( mapOf( "dir" to "libs", "include" to listOf("*.jar"), "exclude" to listOf( "asm", "asm-commons", "asm-tree", "gson", "unspecified", "nv-i18n" ) ) )) }  
    • @chxr Looks like you're making some sort of a crafting table / furnace hybrid? Are the inputs needing arranging like a shaped recipe, or is it shapeless? I'll assume it's shapeless since that just adds a lot more complexity. In that case I'd probably do something like this { "type": "relativedimensions:particle_rebound", "inputs": [ { "ingredient": { "item": "relativedimensions:aberrant_shard" }, "count": 8 } ], "fuel": { "tag": "relativedimensions:block/aberrant_fuel" }, "output": { "Count": 1, "id": "relativedimensions:aberrant_ingot" } } inputs: A list of ingredients and how many are needed. The count among each input adds up to 8. Since there's only 1 ingredient, the count is set to 8. fuel: Same thing as before but remove the list and just make it an object with a tag. output: Kept the same.   In this case the Codec I would make is public record ParticleReboundIngredient(Ingredient ingredient, int count) { public static final Codec<ParticleReboundIngredient> CODEC = RecordCodecBuilder.create( builder -> builder.group( Ingredient.CODEC.fieldOf("ingredient").forGetter((i) -> i.ingredient), Codec.INT.fieldOf("count").forGetter(i -> i.count) ).apply(builder, ParticleReboundIngredient::new) ); } public record ParticleReboundFuel(String tag) { public static final Codec<ParticleReboundFuel> CODEC = RecordCodecBuilder.create( builder -> builder.group(Codec.STRING.fieldOf("tag").forGetter(f -> f.tag)).apply(builder, ParticleReboundFuel::new) ); public boolean isFuel(ItemStack stack) { // TODO: Check if fuel item matches the tag } } public record ParticleReboundRecipe(List<ParticleReboundIngredient> inputs, ParticleReboundFuel fuel, ItemStack output) { public static final Codec<ParticleReboundRecipe> CODEC = RecordCodecBuilder.create( builder -> builder.group( ParticleReboundIngredient.CODEC.listOf().fieldOf("inputs").forGetter(r -> r.inputs), ParticleReboundFuel.CODEC.fieldOf("fuel").forGetter(r -> r.fuel), ItemStack.CODEC.fieldOf("output").forGetter(r -> r.output) ).apply(builder, ParticleReboundRecipe::new) ); }   There might be a more proper Codec for the fuel and the tag that's built into minecraft / forge, but I didn't look
    • Tested with 5900X, 64GB 3200 MHz, 3070 Ti, driver 551.86 GPU clock range: 200 - 1950 MHz, usually 210 MHz with 10-30% utilisation on desktop idle use Render settings: Vsync ON, Framerate unlimited, Render distance 32, Fullscreen ON (60hz monitor, so 60 fps with vsync) Vanilla minecraft: Main menu: 210mhz idle clock always, ingame clock around 400 - 1000 mhz with ~30% utilisation and after alt+tab stays at same. Modded install with curseforge app, only said forge added: Main menu: 210 mhz idle clock always, ingame clock around 400 - 1000 mhz with ~30% utilisation, but after alt+tab gpu clock shoots up to 1950 mhz and utilisation is at 50-60% After disabling all render and chunk related stuff in config, after alt+tab it goes up to 1500 mhz. So game turns gpu into space heater when its not even seen. GPU usage returns to expected when game comes back on top. If instead of unlimited fps, fps is set to ~60, then during alt+tab gpu stays at same range as vanilla, but minecraft has horrible limit logic and framerate limit causes lot of tearing, so its not an option. So it seems that when alt+tabbing, for some reason logic no longer takes vsync toggle into account. So expected behaviour would be for it to work like vanilla does. keep rendering in same manner, no matter if its seen and use same amount of resources. Essentially noticed this behaviour while playing Supersymmetry and after elimination testing, result was that only Forge was enough to cause it. And also confirmed it by doing fresh pack with only Forge added, so no other mods even in disabled state. Also happened with both singleplayer and remote multiplayer. Other offender was "Universal Tweaks" which introduced same effect to main menu with its # Removes the hardcoded 30 FPS limit in screens like the main menu B:"Uncap FPS"=true setting, meaning when game was on top, it still worked in limits of vsync cap, but after alt+tabbing even in main menu gpu usage shot up to max.
    • Add crash-reports with sites like https://paste.ee/ and paste the link to it here Make a test without the mod auditory
  • Topics

×
×
  • Create New...

Important Information

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