Jump to content

[1.8.9] Different item model for inventory/held in hand


Roboguy99

Recommended Posts

I want to make it so my items are rendered using a 2D texture in the inventory screen (as in, in a container slot), but I'd like them to have a completely different 3D model when the player actually holds them and its rendered in their hand. Is this at all possible, and if so how would I go about doing such a thing?

I have no idea what I'm doing.

Link to comment
Share on other sites

This is super useful, thanks. Two (hopefully) small things though -1)  I've got over a hundred items I need to do this to. Can I use the same

IFlexibleBakedModel, IPerspectiveAwareModel

class for all of them and pass the item through the constructor? 2) Does

ModelBakery.registerItemVariants(<item>, <modelA>, <modelB>) 

replace registering each one with the item model mesher?

I have no idea what I'm doing.

Link to comment
Share on other sites

Ok so as far as I can work out, I've done everything you said, but nothing has a texture in game. The console doesn't appear to be throwing out any errors when loading models either.

 

I've updated my repo with the code, if you wouldn't mind having a look and spotting my inevitably obvious and stupid mistake:

https://github.com/JakeStanger/Chemistry/tree/master/src/main/java/roboguy99/chemistry/item/element/render

 

EDIT: I just realised that

element 

isn't actually set anywhere by me, and I assume that Forge isn't a supercomputer capable of guessing my mind. Where would I pass it? Also, I haven't ever created an instance of the model loader class. (Where) would I do that?

I have no idea what I'm doing.

Link to comment
Share on other sites

You need to encode which model you want in the ResourceLocation and then check it in the loader. That's what it's for, it's identifying which model you want. Then the loader can select the correct Element and pass it to the IModel.

 

How would I go about doing this? I'm unsure as to what you mean.

If it means anything, I tried hard-coding

element

as a single element and passing that to the

IModel

, but I still had 0 textures in-game.

I have no idea what I'm doing.

Link to comment
Share on other sites

E.g. if you have elements "foo", "bar", and "baz" use ResourceLocations "myMod:item_foo", "myMod:item_bar", etc.

 

Sorry, I'm still not quite getting it...

 

Where do these ResourceLocations go? I see

loadModel

takes a ResourceLocation, so I presume it has something to do with this?

I have no idea what I'm doing.

Link to comment
Share on other sites

ModelLoader.setCustomModelResourceLocation says which resourcelocation to use for which Item. This RL is then passed to your custom model loader (if it accepts it) to produce that model.

 

I'm sorta getting it, but I'm afraid I'm still not there. I know I'm being really dumb...

 

I'm not sure where to actually put the

ModelLoader.setCustomModelResourceLocation

. I tried putting it in the preInit, but doing this obviously resulted in this being the only texture that item has.

Also, I think my

accepts

method is broken, ignoring the fact that it creates a new

ModelResourceLocation

for every single model in the game and it's still hard-coded to Hydrogen because I haven't figured out what I should be doing there.

 

I've pushed the changes to the repo, so if you wouldn't mind taking a look and basically pointing out where I've gone wrong and what it should be, that would be absolutely fantastic.

 

https://github.com/JakeStanger/Chemistry/tree/master/src/main/java/roboguy99/chemistry/item/element/render

https://github.com/JakeStanger/Chemistry/blob/master/src/main/java/roboguy99/chemistry/Chemistry.java

I have no idea what I'm doing.

Link to comment
Share on other sites

Your ModelLoader should not have an Element field.

You need to analyze the MRL you get. E.g. check if the resurce domain is your ModID and if the path starts with "myItem". If so, get the part after the myItem and interpret it as an Element name.

 

I'm still unsure as to where I should be analysing it, and what to do with the interpreted element name. I've updated the

accepts

method with the interpretation code, which is where I assumed it went.

 

Again, sorry if I'm being really dumb...

I have no idea what I'm doing.

Link to comment
Share on other sites

Assume your RL is like this: "myMod:myItem_foo".

 

Then do this:

boolean accepted = rl.getResourceDomain().equals("myMod") && rl.getResourcePath().startsWith("models/item/myItem_");
String elementName = rl.getResourcePath().substring("models/item/myItem_".length());

 

elementName would then be "foo". Then you just need to find the Element named "foo" and give it to the IModel.

 

Ok, I've changed it to what you put, but I'm still not getting any textures in-game.

Presumably, this is because I haven't actually implemented

ModelLoader.setCustomModelResourceLocation

anywhere. Where does this go? Do I need one for both models?

I have no idea what I'm doing.

Link to comment
Share on other sites

You need it for every item. setCustomModelResourceLocation means "use this model for this item". So you need to give it the MRL you expect in your loader.

 

So I put it in my preInit, in the same place as the item variants are registered. When the game goes to render the item the game is throwing a NullPointerException. The crash log gives no indication of anything wrong in my code (see below).

 

 

java.lang.NullPointerException: Rendering item
at net.minecraft.client.renderer.entity.RenderItem.renderQuads(RenderItem.java:213)
at net.minecraft.client.renderer.entity.RenderItem.renderModel(RenderItem.java:128)
at net.minecraft.client.renderer.entity.RenderItem.renderModel(RenderItem.java:112)
at net.minecraft.client.renderer.entity.RenderItem.renderItem(RenderItem.java:153)
at net.minecraft.client.renderer.entity.RenderItem.renderItemIntoGUI(RenderItem.java:357)
at net.minecraft.client.renderer.entity.RenderItem.renderItemAndEffectIntoGUI(RenderItem.java:396)
at net.minecraft.client.gui.inventory.GuiContainerCreative.func_147051_a(GuiContainerCreative.java:907)
at net.minecraft.client.gui.inventory.GuiContainerCreative.drawGuiContainerBackgroundLayer(GuiContainerCreative.java:739)
at net.minecraft.client.gui.inventory.GuiContainer.drawScreen(GuiContainer.java:93)
at net.minecraft.client.renderer.InventoryEffectRenderer.drawScreen(InventoryEffectRenderer.java:57)
at net.minecraft.client.gui.inventory.GuiContainerCreative.drawScreen(GuiContainerCreative.java:626)
at net.minecraftforge.client.ForgeHooksClient.drawScreen(ForgeHooksClient.java:310)
at net.minecraft.client.renderer.EntityRenderer.updateCameraAndRender(EntityRenderer.java:1156)
at net.minecraft.client.Minecraft.runGameLoop(Minecraft.java:1107)
at net.minecraft.client.Minecraft.run(Minecraft.java:380)
at net.minecraft.client.main.Main.main(Main.java:116)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at net.minecraft.launchwrapper.Launch.launch(Launch.java:135)
at net.minecraft.launchwrapper.Launch.main(Launch.java:28)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at net.minecraftforge.gradle.GradleStartCommon.launch(GradleStartCommon.java:97)
at GradleStart.main(GradleStart.java:26)

 

 

I've got a feeling this is something to do with the method in the baked model class that you said I should leave blank. Is this the case, or is it something else and I'm being really dumb again?

 

Again, changes pushed to repo.

 

EDIT: I'm almost certain this is related to

getGeneralQuads

in the baked model class

I have no idea what I'm doing.

Link to comment
Share on other sites

That is really strange. No idea why that is.

 

Yeah, I stuck some code in both of the quad methods and sure enough it was run. I even tried exactly what you said and threw an exception, which was thrown. Perhaps this was a change in one of the minor updates?

 

I found some code somebody else had for a block where they were calling it on another model, so it doesn't quite work, but might be a step in the right direction. Any ideas?

I've modified it a bit, so now it calls itself indefinitely, which didn't really help...

 

@Override
public List<BakedQuad> getFaceQuads(EnumFacing face)
{
	List<BakedQuad> quads = new ArrayList<BakedQuad>();
	List<BakedQuad> faceQuads = this.getFaceQuads(face);
	for (BakedQuad q : faceQuads) {
	quads.add(new BakedQuad((q.getVertexData()), 0, face));
	}
	return quads;
}

@Override
public List<BakedQuad> getGeneralQuads()
{
	List<BakedQuad> quads = new ArrayList<BakedQuad>();
	List<BakedQuad> generalQuads = this.getGeneralQuads();
	for (BakedQuad q : generalQuads) {
	quads.add( new BakedQuad(q.getVertexData(), 0, q.getFace()));
	}
	return quads;
}

 

(Source: http://www.minecraftforge.net/forum/index.php?topic=30271.5;wap2)

I have no idea what I'm doing.

Link to comment
Share on other sites

Your IPerspectiveAwareModel must return a "real" model. It returns the reference to itself. You must have two JSON models, one for in GUI one for outside. Only those two can be returned from the IPAM.

 

Ok, so I have the separate JSON models. Do you mean I should be returning something other than an

IBakedModel

? If so, what and how? If not, then what?

I have no idea what I'm doing.

Link to comment
Share on other sites

No, I mean you must return the result of getting the Model for a ResourceLocatino that is NOT your IPAM.

 

Ah, right. I see what you're saying.

So the problem is, currently I'm setting the model to itself, which you obviously can't do.

 

How do I actually get the model then?

 

Bare in mind that this is the first time, other than learning how to give an item a texture yesterday, that I've used any of the 'new' 1.8 rendering system. I am pretty confused right now :|

I have no idea what I'm doing.

Link to comment
Share on other sites

How do I actually get the model then?

You do it just 2 lines above...

 

Maybe I'm brain-dead, but I'm still not getting you.

 

When you say return, are you referring to setting

model

on the else line or the actual method return? What's the significant difference between those two lines? If I simply return the model from the first of the 2 lines, I get the same crash. Why? What were Mojang thinking when they switched to blockstates from the perfectly adequate previous system?

 

Apologies for the high-levels of brain-deaded-ness and inevitable face-palms

I have no idea what I'm doing.

Link to comment
Share on other sites

I'd like to say this is over and I get it, but I still don't. I slept on it, came back to it and I still can't make proper sense of what you're saying. I feel like this thread has reached a point where we're getting nowhere. As much as I hate to say this, I think it might just benefit the both of us if you just outright tell me what should be where.

 

Basically I don't understand what the significant difference between those two lines is - surely they both point to a JSON model? Also, if I hard-code the return of the first one, the game still crashes with the same error. Maybe I'm still not getting it at all.

 

Sorry...

I have no idea what I'm doing.

Link to comment
Share on other sites

That image helped a lot, and cleared quite a bit up, but I still don't understand *how* I should be "choosing the proper JSON model" for each element. After quite a lot of thinking (maybe over-thinking) and researching, I've possibly understood what you mean.

But probably not.

 

Here goes:

 

Do I need to have 2 JSON models - one which points straight to the texture for when the item is held, and one which points to all of the element JSON files (like how fire works, I think...)?

 

Or:

 

Do I just need to change the syntax of that second line? If so, could you please tell me EXACTLY what it should be. My understanding of the JSON model system is (evidently) very lacking, so although I'm understanding what you're saying, I don't know what I actually should be doing to fix it.

 

Or:

 

Something else? If so, how am I doing such a bad job of understanding what on earth is going on?

 

I feel at this point, before I'm banned from the modding community forever for sheer stupidity and you quit the forums due to frustration (there must be people worse than me sometimes, no?), we need to get this over and done with. Again, I'm sorry for the pain you undergo.

I have no idea what I'm doing.

Link to comment
Share on other sites

Ok, so.

There are 3 models here. One for when the item is held (might be different for each type of item, but I will ignore that for now). One for when the item is rendered everywhere else. These two are not bound to any item at all.

 

Then there is your IPAM Model, which you bind to your Item. This model then selects (based on held or not) one of the other two models.

 

Ok, I think (at long last!) I've gotcha and it's *almost* working. The biggest indication of this is that a) the game no longer crashes and b) items are rendered differently in the inventory than anywhere else (they're flat). I've hardcoded the inventory JSON file for now so there's only one.

 

Two problems exist now: 1) Nothing is textured (and in the case of held items they're rendered in the same way anything without a JSON file are) and 2) Any elements on the floor crash the game with a NullPointerException in RenderEntityItem

 

If you wouldn't mind helping me with that I'd be very grateful.

I have no idea what I'm doing.

Link to comment
Share on other sites

I've appropriately re-named everything so that I'm not registering every item in my mod, and the held textures are now showing up in-game. The models are being rendered separately. I think I did everything you said.

 

But:

 

Things in the GUI are still not being textured, and throwing things on the floor still crash the game.

 

Did I miss something or is it something else?

 

EDIT: I tried using

elementModel

and

testModel

to pass to

ModelLoader.setCustomModelResourceLocation

, both of which had the exact same result.

I have no idea what I'm doing.

Link to comment
Share on other sites

- You register these models multiple times (in the for loop below). Only register every model once.

 

- This model does not exist and you do not (try to) register it either.

 

Well I've just completely removed the loop for now and corrected the incorrect model path, and now I'm back to the same crash as before...

 

Did I actually break something in the process or is there something else wrong?

I have no idea what I'm doing.

Link to comment
Share on other sites

I really don't know at this point. All I can see is: this model still doesn't exist. Use a debugger to find out what's happening.

 

It seems that you're right, but I have no idea why...

 

The JSON file for it is in the same place as all the others. The contents of the JSON file is literally a copied+pasted version of one of the elements in which I have changed nothing at all.

I tried fully disabling all of the model code and just sticking to a static model like I was using before this whole thread, and putting in the ModelResourceLocation of the model and it just completely ignored it. I then tried using on of the standard element models, and it worked fine.

 

Sticking a breakpoint on getting the ModelResourceLocation showed a message variable saying that the path was null. Which I presume it shouldn't...

 

When you say "use a debugger" is there some tool other than outputting variables + breakpoints I should know about?

 

EDIT: The elementHeld model, which *was* working absolutely fine now isn't working. I changed nothing. I am beyond confused.

I have no idea what I'm doing.

Link to comment
Share on other sites

Sorry to bring this thread up again. I've got everything working (helps if you don't name every model with the prefix used to in the loader :/) except I still can't throw anything on the floor - as soon as they're turned to

EntityItems

the game crashes rendering them.

 

As can be seen in the crash report.

 

The only occurrence I've found of this happening before after a Google (with 4 results) was here, but this seems unlikely for something as simple as what I've done.

 

Do I need to follow what you said to do in that guide or have I just done something really stupid again?

 

If yes to following that post, could you explain the steps in a little more detail. I've sorta realised I was obviously doing something wrong, but wasn't sure where to go and what to fix and got stumped (see here).

I have no idea what I'm doing.

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.