Jump to content

Render Item as custom Tile Entity in 1.8


Bedrock_Miner

Recommended Posts

Heyho Guys!

 

I want to know whether it's possible to render an Item as it's corresponding TileEntity using the builtin/entity tag in the item's model file. Can I do this? And if so: how?

Also, I'm wondering whether it's possible to register different Item models depending on the rendering type (So, one model for the Item in 3rd Person, one for 1st Person, one for Inventory etc.).

 

If any of those is not possible, do you think I should request this as a new Forge feature? Or should I just say nothing and use the (deprecated  >:( ) IItemRenderer Interface?

 

Any Ideas are very much appreciated!

 

-BM

Link to comment
Share on other sites

Hi

 

1st question: yep

http://www.minecraftforge.net/forum/index.php/topic,28873.msg148526.html#msg148526

 

2nd question:

Yes (I think) but I'll need to test something in code first... if nobody else replies first, I'll hopefully have something that works later today. 

If you want to try it in the meantime, Item.getModel will be useful for changing the model in first and third person.

 

IItemRenderer is dead, I don't even think it works in 1.8 at all.

 

-TGG

Link to comment
Share on other sites

Ok, so the technique for the TileEntity Rendering looks pretty awesome, although I'm going to change it a bit so that I have a "registry" where I can add the renderers with the associated Item or Block (or with a Predicate<ItemStack>). I'm still thinking if there's any way of eliminating the changes made by some modders who don't chain the classes like you did in your post.

 

I'll take a look at the getModel method and try to find out something useful.

 

Is there any chance that the IItemRenderer gets revived? Because for some Items which show a complicated model it isn't even possible to use the Minecraft model files. However, the only workaround I can imagine so far is to use the hijacked TileEntity renderer here again. I need to work a bit with this method, then I can see whether I still need the IItemRenderer.

 

-BM

 

EDIT:

OK, My Registry thingy is working just perfect! It even works for Items, you just need to skip the registration in the builtin-block list.

The best thing is that I don't even need to apply any transformations in the Item render file, without them it's perfect anyway.

 

The Item.getModel() method looks quite nice as well (NOW I finally know how to make custom bows with changing texture!), but I don't know how to get the render type of the Item from inside this method. Any Ideas here?

 

-BM

Link to comment
Share on other sites

No, I did not change the texture with NBT (although that would be possible with getModel()), but I was able to register a rendering handler for items using the method tgg mentioned.

 

I'm still trying to figure out how to get the current rendering mode from the getModel() method, but I discovered already that this method is only called when the Item is rendered in 1st or 3rd person, not in Item state or in the Inventory and also not when a Mob carries the Item. Thus, a method to get the current rendering state would be very useful, especially when using custom

ItemMeshDefinition

s or

ISmartItemModel

s. Probably the getModel method isn't that useful at all, because it's only called in very special circumstances. It's better to work with ISmartItemModels here (although this is quite complicated), because this is called everytime. But also here I need this method so much!

Link to comment
Share on other sites

I worked a bit on the problem with the rendering state and I found a solution:

I created a class which analyzes the current StackTrace and returns the render type based on this information. It basically works quite well, so I thought I'll share it with you:

 

 

package minersbasic.api.client;

import net.minecraft.client.gui.GuiScreen;
import minersbasic.api.reflec.ModReflectionHelper;

/**
* The Class ItemRenderPhaseChecker. This class allows users to get the current
* phase (or type) of item rendering. This can be used to return custom models
* based on the phase.
*
* @author _Bedrock_Miner_ ([email protected])
*/
public final class ItemRenderPhaseChecker {

/**
 * Gets the current render phase by analyzing the current Thread's Stack
 * Trace.
 *
 * @return the current render phase
 */
public static RenderPhase getCurrentRenderPhase() {
	for (StackTraceElement e : Thread.currentThread().getStackTrace()) {
		if (e.getMethodName().equals("renderItemAndEffectIntoGUI") && e.getClassName().equals("net.minecraft.client.renderer.entity.RenderItem") || e.getMethodName().equals("drawScreen") && isSubclass(ModReflectionHelper.findClass(e.getClassName()), GuiScreen.class)) {
			return RenderPhase.GUI;
		}
		if (e.getMethodName().equals("renderItemInFirstPerson") && e.getClassName().equals("net.minecraft.client.renderer.ItemRenderer")) {
			return RenderPhase.FIRST_PERSON;
		}
		if (e.getMethodName().equals("doRender") && e.getClassName().equals("net.minecraft.client.renderer.entity.RenderPlayer")) {
			return RenderPhase.THIRD_PERSON_PLAYER;
		}
		if (e.getMethodName().equals("doRenderLayer") && e.getClassName().equals("net.minecraft.client.renderer.entity.layers.LayerHeldItem")) {
			return RenderPhase.THIRD_PERSON;
		}
		if (e.getMethodName().equals("doRender") && e.getClassName().equals("net.minecraft.client.renderer.entity.RenderEntityItem")) {
			return RenderPhase.ITEM;
		}
		if (e.getMethodName().equals("renderItem") && e.getClassName().equals("net.minecraft.client.renderer.tileentity.RenderItemFrame")) {
			return RenderPhase.ITEM_FRAME;
		}
		if (e.getMethodName().equals("renderItemModel") && e.getClassName().equals("net.minecraft.client.renderer.entity.RenderItem")) {
			return RenderPhase.RAW;
		}
	}
	return RenderPhase.UNKNOWN;
}

/**
 * Checks if a class is a subclass of another one.
 *
 * @param subclass
 * the class to check
 * @param superclass
 * the superclass to match
 * @return <code>true</code>, if it is a subclass of the superclass
 */
private static boolean isSubclass(Class<?> subclass, Class<?> superclass) {
	if (subclass.getSuperclass() == Object.class && superclass != Object.class)
		return false;
	if (subclass == superclass)
		return true;
	if (subclass.getSuperclass() == superclass)
		return true;
	return isSubclass(subclass.getSuperclass(), superclass);
}

/**
 * The Enum RenderPhase.
 *
 * @author _Bedrock_Miner_ ([email protected])
 */
public enum RenderPhase {

	/** Rendering inside a GUI */
	GUI,

	/** Rendering as an equipped item in first person */
	FIRST_PERSON,

	/** Rendering as an equipped item in third person on a player */
	THIRD_PERSON_PLAYER,

	/** Rendering as an equipped item in third person on another entity */
	THIRD_PERSON,

	/** Rendering an item on the ground */
	ITEM,

	/** Rendering an item in an item frame */
	ITEM_FRAME,

	/**
	 * Raw call of the renderItemModel method. This can happen in custom
	 * renderers. Should execute the same rendering as ITEM_FRAME
	 */
	RAW,

	/** Unknown rendering call. */
	UNKNOWN;
}
}

 

 

The only disadvantage is that I cannot find out which Entity is currently rendered, so I cannot differentiate between rendering for a Skeleton and rendering for a Zombie. It would be possible however if anyone knows a method how to get the values of local variables in the execution stack at runtime, because the Entity is passed as an argument to the caller methods that I check for. But as far as I know, it's not possible to get local variables, so I think I can forget this idea (unless I make a coremod and play with ASM).

Link to comment
Share on other sites

Heyho, it's me again!

 

I have a new small problem:

I tried to make my Item-TileEntity renderer accept the texture given in the model file. The file should look like this:

{
    "parent":"builtin/entity",
    "textures": {
        "layer0":"modid:anytexture"  //Or any other texture name (for instance "all")
    }
}

The next thing I want is retrieving the texture in my rendering code.

I can get the model using

IBakedModel model = Minecraft.getMinecraft().getRenderItem().getItemModelMesher().getItemModel(stack);

But I don't know how to get the textures by name. The normal method getTexture() (which returns only one texture for some reason) doesn't work anyway, because the model is an instance of BuiltInModel, which overrides most of the methods to return null.

 

Does anyone have any idea how I can use the textures I defined in the file in my rendering code?

...I just need to get the resource location of the images by their names

Link to comment
Share on other sites

Well, with this method I can get the image's position on the icon map, but I wanted to get the image's position based on the model file. Or, an even better method would be a method to just render the model with texture and everything...

 

I discovered, that there is the interface ICustomModelLoader which could be a good thing, because it obviously can replace the default model object with a custom one, but I cannot get it to work... Does anyone here know how I can bring this to work?

 

Maybe I should tell you what I actually want to do:

I want to create a custom bow (already done).

This bow should be pulled in 0.5 seconds instead of 1 (done as well).

The problem: The vanilla bow behaviour is copied for my bow: If the bow is fully drawn, it still moves back until a vanilla bow would be drawn as well... I had this problem back in 1.7.10 already, but there I was able to use the IItemRenderer to apply some reverse transformations. This lead to a giant amount of cryptical code (see below  :P ) but it worked...

 

@Override
public void renderItem(ItemRenderType type, ItemStack item, Object... data) {
	if (item != null && item.getItem() != null && item.getItem() instanceof ItemMagicBow) {
//			GL11.glTranslated(2.0, 2.0, 0.0);
//			GL11.glRotated(90, 0, 1, 0);
		if (type == ItemRenderType.EQUIPPED_FIRST_PERSON) {
			if (Minecraft.getMinecraft().thePlayer.getItemInUseCount() > 0) {
				this.adjustVanillaMovement(item);
                }
		}

		if (type == ItemRenderType.EQUIPPED) {
			o.scale(1.5, 1.5, 1.5);
			o.rotate(-80, 0, 1, 0);
			o.translate(0, 0, -0.4);
			o.rotate(-45, 0, 0, 1);
			o.translate(-0.6, -0.6, 0);
		}

		MagicBowMaterial material = ((ItemMagicBow)item.getItem()).getBowMaterial();
		int use = Minecraft.getMinecraft().thePlayer.getItemInUseDuration();
		IIcon icon = ((ItemMagicBow)item.getItem()).getItemIconForUseDuration(use);
		o.renderSolidifiedFaceWithGlint(icon, 1.0f/16.0f, item.hasEffect(0));
	}
}

private void adjustVanillaMovement(ItemStack item) {
    	o.rotate(-45, 0, 0, 1);
    	//Reset Vanilla stuff
    	float time = item.getMaxItemUseDuration() - (Minecraft.getMinecraft().thePlayer.getItemInUseCount() + 1.0f - worldTimer.renderPartialTicks);
    	float vf = time / 20.0F;
    	vf = (vf * vf + vf * 2.0F) / 3.0F;
    	if (vf > 1.0f) vf = 1.0f;
    	o.scale(1.0, 1.0 / (1.0 + vf * 0.2), 1.0);
    	o.translate(0, vf * 0.2, 0);
    	if (vf > 0.1F)
            o.translate(MathHelper.sin((time - 0.1F) * 1.3F) * 0.006F * (vf - 0.1F), -MathHelper.sin((time - 0.1F) * 1.3F) * 0.003F * (vf - 0.1F), 0.0);
    	//Own Calculations
    	vf = time / ((ItemMagicBow)item.getItem()).getBowMaterial().getDrawDuration();
    	vf = (vf * vf + vf * 2.0F) / 3.0F;
    	if (vf > 1.0f) vf = 1.0f;

    	if (vf > 0.1F)
            o.translate(MathHelper.sin((time - 0.1F) * 1.3F) * 0.003F * (vf - 0.1F), 0.0, 0.0);
    	o.translate(0, -vf * 0.2, 0);
    	o.scale(1.0, 1.0 + vf * 0.2, 1.0);
    	o.rotate(45, 0, 0, 1);
}

 

Now, I don't have the IItemRenderer anymore, so I need to find another way of doing this. I was pretty glad when I found the method with the builtin/entity renderer for Items and I think that's the only way to add actually real code into the rendering procedure.

What I want to do now is to use the Item model to render the bow item with the transformation needed, but therefore I need to get the texture (or a method to directly render the model).

 

It was much easier with the IItemRenderer.... Especially because IItemRenderer already had the correct transformations for an item, not for a block. Maybe, however, Forge could add some events to intercept the rendering execution at some point.

 

It would be so great if you could simply start rendering without caring for any transformations first, like for the TileEntities in Item state.

 

EDIT: And even more problems: I just discovered that the block rendered with my TileEntity thingy does not have the correct destruction particles. Instead the missingtexture particles are used.. I have NO idea how to fix this, as I have no model file for the block.. (special renderer, you remember  ;) )

Link to comment
Share on other sites

I discovered, that there is the interface ICustomModelLoader which could be a good thing, because it obviously can replace the default model object with a custom one, but I cannot get it to work... Does anyone here know how I can bring this to work?

example MBE05 in this project has an example of that

https://github.com/TheGreyGhost/MinecraftByExample

 

I want to create a custom bow (already done).

This bow should be pulled in 0.5 seconds instead of 1 (done as well).

The problem: The vanilla bow behaviour is copied for my bow: If the bow is fully drawn, it still moves back until a vanilla bow would be drawn as well...

Not sure I understood exactly what you want to do, but MBE12 does something very similar using Item.getModel()

 

-TGG

 

 

 

Link to comment
Share on other sites

Ok, so the ICustomModelLoader looks pretty nice. I see what I can do with it.

 

My problem is not the changing texture, I have done this already. My problem is that the normal bow rendering behaviour includes a movement backwards and a scaling effect. But these are optimated for a draw duration of 20 ticks. However, my bow should have 10 ticks, so I need to change the behaviour somehow.

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.