Jump to content

Item with Multiple Models managed via NBT and ModelLoader


kitsushadow

Recommended Posts

I have an item which needs to change its model based on NBT.

 

How do I go about utilizing and implementing an item with NBT that can take advantage of the ModelLoader.setCustomMeshDefinition()

 

I was reading this article https://gist.github.com/williewillus/57d7093efa80163e96e0

It was suggested that, "You can do things like return different models depending on NBT" when using ModelLoader.setCustomMeshDefinition()
Now I've read a lot of articles from Choonster and other informed members of the community. I have yet to succeed with anything I have tried due to the lack of concrete complete implementations.

I am already aware of how to write NBT data to an item.

Anyones help with this will be greatly appreciated but if you do intend to leave an answer please be patient and leave a well informed detailed response or please link a source code example as reference.
Thanks!

Link to comment
Share on other sites

Create a new instance of ItemMeshDefinition, and in the one method return the proper ModelResourceLocation for that variant. You have a ItemStack parameter to use to get the NBT from.

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

You first need to register each possible model location using ModelBakery.registerItemVariants. This tells Minecraft to load the models.

 

Your implementation of ItemMeshDefinition#getModelLocation receives the ItemStack being rendered and needs to return a ModelResourceLocation pointing to the desired model. You can use any aspect of the ItemStack (or none) to determine the model location, including NBT.

 

I have an explanation of how ModelResourceLocations are mapped to model files here.

Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.

Link to comment
Share on other sites

3 minutes ago, Animefan8888 said:

Create a new instance of ItemMeshDefinition, and in the one method return the proper ModelResourceLocation for that variant. You have a ItemStack parameter to use to get the NBT from.

 

1 minute ago, Choonster said:

You first need to register each possible model location using ModelBakery.registerItemVariants. This tells Minecraft to load the models.

 

Your implementation of ItemMeshDefinition#getModelLocation receives the ItemStack being rendered and needs to return a ModelResourceLocation pointing to the desired model. You can use any aspect of the ItemStack (or none) to determine the model location, including NBT.

 

I have an explanation of how ModelResourceLocations are mapped to model files here.


Thank you both for the response, can I get a more concrete example. Like a source code example to use as reference?

Link to comment
Share on other sites

Hopefully I understand it correctly for you (never used it).

ModelBakery.registerItemVariants(Items.APPLE, Items.APPLE.getRegistryName(), new ResourceLocation("modid", "fileName"));
		ModelLoader.setCustomMeshDefinition(Items.APPLE, new ItemMeshDefinition() {
			
			@Override
			public ModelResourceLocation getModelLocation(ItemStack stack) {
				if (stack.hasTagCompound()) {
					if (stack.getTagCompound().getBoolean("charged")) {
						// return new ModelResourceLocation to charged sub type
					} else {
						// return new ModelResourceLocation to not charged sub type
					}
				}
				return new ModelResourceLocation(stack.getItem().getRegistryName(), "inventory");
			}
		});

 

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

14 minutes ago, Animefan8888 said:

Hopefully I understand it correctly for you (never used it).


ModelBakery.registerItemVariants(Items.APPLE, Items.APPLE.getRegistryName(), new ResourceLocation("modid", "fileName"));
		ModelLoader.setCustomMeshDefinition(Items.APPLE, new ItemMeshDefinition() {
			
			@Override
			public ModelResourceLocation getModelLocation(ItemStack stack) {
				if (stack.hasTagCompound()) {
					if (stack.getTagCompound().getBoolean("charged")) {
						// return new ModelResourceLocation to charged sub type
					} else {
						// return new ModelResourceLocation to not charged sub type
					}
				}
				return new ModelResourceLocation(stack.getItem().getRegistryName(), "inventory");
			}
		});

 

Thanks, will give it a shot!

Link to comment
Share on other sites

1 minute ago, kitsushadow said:

@Animefan8888 this goes in my RegistryRender which gets initialized in the main class yes?

I would say so, that is where it would make the most sense to me, make sure it is after ItemRegistry and during preInit, or in the ModelRegistryEvent.

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

@Animefan8888  so I gave that a try and I'm pretty close. I think the next step is the json trickery to make it work.
 

The model with no NBT loads as seen in the creative mode inventory. The model WITH NBT fails to load.

I have a stonetongs.json and a stonetongs_defualt.json in the models/item directory

If you'd like to view the source code you can find it here. https://github.com/kitsushadow/forgecraft/tree/master/1.11/src/main

 


RenderRegistry

    public static void registerCustomRenders(){
        ModelBakery.registerItemVariants(ModItems.stonetongs, ModItems.stonetongs.getRegistryName(), new ResourceLocation(ModInfo.MOD_ID, "stonetongs"));
        ModelLoader.setCustomMeshDefinition(ModItems.stonetongs, new ItemMeshDefinition() {

            @Override
            public ModelResourceLocation getModelLocation(ItemStack stack) {
                if (stack.hasTagCompound()) {
                    //if (stack.getTagCompound().getInteger("type")) {
                      if (stack.getTagCompound().getInteger("type") == 0 ){
                        return new ModelResourceLocation(stack.getItem().getRegistryName() + "_default");
                    } else {
                          return new ModelResourceLocation(stack.getItem().getRegistryName(), "inventory");
                    }
                }
                return new ModelResourceLocation(stack.getItem().getRegistryName(), "inventory");
            }
        });
    }

 

ItemClass

public class ItemStoneTongs extends Item {

    public ItemStoneTongs(String unlocalizedName) {
        setUnlocalizedName(unlocalizedName);
        this.setRegistryName(unlocalizedName);
        //this.setMaxDamage(0);
        //this.setHasSubtypes(true);  //This just says the item has metadata
        this.setMaxStackSize(1);
        this.setCreativeTab(ModInfo.TAB_FORGECRAFT);
    }


    public void onUpdate(ItemStack item, World world, Entity player, int itemSlot, boolean isSelected) {
        if (!item.hasTagCompound()) {
            item.setTagCompound(new NBTTagCompound());
            item.getTagCompound().setInteger("type", 0);
        }
    }

    public EnumActionResult onItemUse(EntityPlayer player, World world, BlockPos pos, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ)
    {
        //pos = pos.offset(facing);
        ItemStack itemstack = player.getHeldItem(hand);

        if (world.getBlockState(pos).getBlock() == ModBlocks.bloomery) {
            TileBloomery tile = (TileBloomery) world.getTileEntity(pos);
            System.out.println(tile.getSlotStack(1));
            //itemstack.damageItem(1, player);
            return EnumActionResult.SUCCESS;
        } else return EnumActionResult.FAIL;
    }

}

 

Edited by kitsushadow
Link to comment
Share on other sites

You call ModelBakery.registerItemVariants with the registry name of ModItems.stonetongs (which is presumably <modid>:stonetongs) and <modid>:stonetongs, but your ItemMeshDefinition returns the registry name with the _default suffix (<modid>:stonetongs_default which you haven't registered).

Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.

Link to comment
Share on other sites

@Animefan8888 @Choonster

You all are lifesavers! It's working now! 

Thanks again for your help. For those looking for the final solution I have linked my source code here

https://github.com/kitsushadow/forgecraft/tree/master/1.11/src/main

 

The files that you would need to look at are:
init/ModItems.java

items/ItemStoneTongs.java

proxy/ClientProxy.java

ForgeCraft.java

resources/models/item/

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



×
×
  • Create New...

Important Information

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