yeah i know this .. maybe i didn't explain it in a good way
i meant the texture itself
because i did make a kunai .. it looks so horrible when you throw it ( in horizontal way )
Oh I see. You'll need to make a custom Render for your item that rotates the texture 90 degrees. Have a look at RenderArrow and you'll see what I mean:
Oh I see. You'll need to make a custom Render for your item that rotates the texture 90 degrees. Have a look at RenderArrow and you'll see what I mean:
Hey, i have tried this tutorial for a second time and i got this crash, please help me!
~snip~ EDIT: I looked through the previous comments, and even though they confuse me, i managed to get it to work! Is there any way i could make this get shot by my wand instead though? I have tried but every time the wand shoots, it shoots nothing...
Glad you got it to work. To make it shoot from your wand, use the same code you did in ItemThrowingRock 'onItemUse' method - just in your ItemWand instead.
// in ItemWand
public ItemStack onItemRightClick(ItemStack itemstack, World world, EntityPlayer player)
{
if (!player.capabilities.isCreativeMode)
{
// instead of decreasing the wand stack size, we need to consume your ammo
// --itemstack.stackSize;
// here we check if an ammo item was consumed and, if not, return without spawning an entity
if (!player.inventory.consumeInventoryItem(YourMod.yourAmmoItem.itemID))
return itemstack;
}
world.playSoundAtEntity(player, "random.bow", 0.5F, 0.4F / (itemRand.nextFloat() * 0.4F + 0.8F));
if (!world.isRemote)
{
world.spawnEntityInWorld(new YourCustomEntity(world, player));
}
return itemstack;
}
Look for the sound you want in minecraft jars/assets/sound folder, then change the sound played. "random.bow" looks in the folder 'sound/random/' for the sound file 'bow'. There is 'random.explode1' 2, 3, or 4, and also fireworks sounds that you could try.
Updated to Forge 871 - just a few tweaks to the RenderThrowingRock class. 'func_110777_b(Entity)' is now 'bindEntityTexture(Entity)', and this method was added, allowing easier manipulation of texture file to return:
I made a mistake in the tutorial that will affect your entity in multiplayer. You need to register the entity on the server side as well, so not in the ClientProxy. I suggest registering your entities in the main mod load method, like so:
@EventHandler
public void load(FMLInitializationEvent event)
{
// If you have a lot of Entities to register, consider creating a class with a static 'initEntity' method
// so your main class stays tidy and readable
EntityRegistry.registerModEntity(EntityThrowingRock.class, "Throwing Rock", ++modEntityID, this, 64, 10, true);
}
Now your entity will work both for single and multi-player, whereas before it would be invisible in multi-player but render correctly in single.
My apologies if you've had any problems due to this oversight. The tutorial has been updated with the correct information.
I'm having trouble getting my throwing item's entity to render. My game doesn't crash or anything, and I get at least the particle effect of it being thrown. I'm also putting the registering mod entity part in my FML Initialization part of my main mod class instead of the ClientProxy class. Can someone take a look at my code and tell me if I'm doing anything wrong?
RockItem.java (Item class)
package spelunkcraft.items;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import spelunkcraft.SpelunkcraftMain;
import spelunkcraft.client.entity.EntityRock;
import spelunkcraft.lib.config.Names;
import net.minecraft.client.renderer.texture.IconRegister;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.projectile.EntitySnowball;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.world.World;
public class RockItem extends Item {
public RockItem(int id)
{
super(id);
this.maxStackSize = 16;
this.setUnlocalizedName(Names.rockItem_unlocalizedName);
this.setCreativeTab(SpelunkcraftMain.spelunkcrafttab);
}
@SideOnly(Side.CLIENT)
public void registerIcons(IconRegister par1IconRegister)
{
this.itemIcon = par1IconRegister.registerIcon(spelunkcraft.lib.ModInfo.MODID + ":" + (this.getUnlocalizedName().substring(5)));
}
/**
* Called whenever this item is equipped and the right mouse button is pressed.
* Args: itemStack, world, entityPlayer
*/
public ItemStack onItemRightClick(ItemStack par1ItemStack, World par2World, EntityPlayer par3EntityPlayer){
if (!par3EntityPlayer.capabilities.isCreativeMode){
--par1ItemStack.stackSize;
}
par2World.playSoundAtEntity(par3EntityPlayer, "random.bow", 0.5F, 0.4F / (itemRand.nextFloat() * 0.4F + 0.8F));
if (par2World.isRemote) {
par2World.spawnEntityInWorld(new EntityRock(par2World, par3EntityPlayer));
}
return par1ItemStack;
}
}
EntityRock.java (Entity class)
package spelunkcraft.client.entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.projectile.EntityThrowable;
import net.minecraft.util.DamageSource;
import net.minecraft.util.MovingObjectPosition;
import net.minecraft.world.World;
public class EntityRock extends EntityThrowable
{
public EntityRock(World par1World)
{
super(par1World);
}
public EntityRock(World par1World, EntityLivingBase par2EntityLivingBase)
{
super(par1World, par2EntityLivingBase);
// TODO Auto-generated constructor stub
}
public EntityRock(World par1World, double par2, double par4, double par6)
{
super(par1World, par2, par4, par6);
// TODO Auto-generated constructor stub
}
/**
* Called when this EntityThrowable hits a block or entity.
*/
@Override
protected void onImpact(MovingObjectPosition movObjPos)
{
if (movObjPos.entityHit != null)
{
// We changed this to type 'float' and set to '2'
float rockDamage = 2;
// now in this line we don't need to cast as 'float', since our variable is already that type
movObjPos.entityHit.attackEntityFrom(DamageSource.causeThrownDamage(this, this.getThrower()), rockDamage);
}
// spawn 4 "crit" particles at the point of impact
for (int l = 0; l < 4; ++l)
{
this.worldObj.spawnParticle("crit", this.posX, this.posY, this.posZ, 0.0D, 0.0D, 0.0D);
}
// be sure to set the entity to 'dead' or it will keep updating forever and you'll end up with lots of
// leftover entities in your world
if (!this.worldObj.isRemote)
{
this.setDead();
}
}
}
RenderRock.java (Rendering class)
package spelunkcraft.client.tileentity;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL12;
import spelunkcraft.client.entity.EntityRock;
import spelunkcraft.lib.ModInfo;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.entity.Render;
import net.minecraft.client.renderer.texture.TextureMap;
import net.minecraft.entity.Entity;
import net.minecraft.entity.projectile.EntityPotion;
import net.minecraft.item.Item;
import net.minecraft.util.Icon;
import net.minecraft.util.ResourceLocation;
import cpw.mods.fml.relauncher.SideOnly;
import cpw.mods.fml.relauncher.Side;
public class RenderRock extends Render
{
private static final ResourceLocation rock = new ResourceLocation("ladestitute_spelunkcraft/textures/items/rockItem.png");
public RenderRock(Item par1Item)
{
}
/**
* Actually renders the given argument. This is a synthetic bridge method, always casting down its argument and then
* handing it off to a worker function which does the actual work. In all probabilty, the class Render is generic
* (Render<T extends Entity) and this method has signature public void doRender(T entity, double d, double d1,
* double d2, float f, float f1). But JAD is pre 1.5, so don't do that.
*/
public void Render(EntityRock rock, double par2, double par4, double par6, float par8, float par9)
{
GL11.glPushMatrix();
GL11.glTranslatef((float)par2, (float)par4, (float)par6);
GL11.glEnable(GL12.GL_RESCALE_NORMAL);
GL11.glScalef(0.5F, 0.5F, 0.5F);
// this.func_110777_b(par1Entity); // worked in Forge 804, but no longer; use this:
this.bindEntityTexture(rock);
Tessellator tessellator = Tessellator.instance;
GL11.glDisable(GL12.GL_RESCALE_NORMAL);
GL11.glPopMatrix();
}
@Override
protected ResourceLocation getEntityTexture(Entity entity)
{
return rock;
}
private void func_77026_a(Tessellator par1Tessellator, Icon par2Icon)
{
float f = par2Icon.getMinU();
float f1 = par2Icon.getMaxU();
float f2 = par2Icon.getMinV();
float f3 = par2Icon.getMaxV();
float f4 = 1.0F;
float f5 = 0.5F;
float f6 = 0.25F;
GL11.glRotatef(180.0F - this.renderManager.playerViewY, 0.0F, 1.0F, 0.0F);
GL11.glRotatef(-this.renderManager.playerViewX, 1.0F, 0.0F, 0.0F);
par1Tessellator.startDrawingQuads();
par1Tessellator.setNormal(0.0F, 1.0F, 0.0F);
par1Tessellator.addVertexWithUV((double)(0.0F - f5), (double)(0.0F - f6), 0.0D, (double)f, (double)f3);
par1Tessellator.addVertexWithUV((double)(f4 - f5), (double)(0.0F - f6), 0.0D, (double)f1, (double)f3);
par1Tessellator.addVertexWithUV((double)(f4 - f5), (double)(f4 - f6), 0.0D, (double)f1, (double)f2);
par1Tessellator.addVertexWithUV((double)(0.0F - f5), (double)(f4 - f6), 0.0D, (double)f, (double)f2);
par1Tessellator.draw();
}
@Override
public void doRender(Entity rock, double d0, double d1, double d2, float f,
float f1) {
Render((EntityRock)rock, d0, d1, d2, f, f1);
}
}
ClientProxy.java (ClientProxy class)
package spelunkcraft.client;
import java.util.Map;
import spelunkcraft.SpelunkcraftMain;
import spelunkcraft.SpelunkcraftSounds;
import spelunkcraft.client.entity.EntityGrappleHook;
import spelunkcraft.client.entity.EntityMidairRope;
import spelunkcraft.client.entity.EntityPowderBoxPrimed;
import spelunkcraft.client.entity.EntityRock;
import spelunkcraft.items.RockItem;
import spelunkcraft.client.tileentity.RenderGrappleHook;
import spelunkcraft.client.tileentity.RenderMidairRope;
import spelunkcraft.client.tileentity.RenderPowderBoxPrimed;
import spelunkcraft.client.tileentity.RenderRock;
import spelunkcraft.client.tileentity.TileEntityBigChest;
import spelunkcraft.client.tileentity.TileEntityBigChestRenderer;
import cpw.mods.fml.client.FMLClientHandler;
import cpw.mods.fml.client.registry.ClientRegistry;
import cpw.mods.fml.client.registry.RenderingRegistry;
import cpw.mods.fml.common.registry.EntityRegistry;
import net.minecraft.client.renderer.ChestItemRenderHelper;
import net.minecraft.world.World;
import net.minecraftforge.client.MinecraftForgeClient;
import net.minecraft.client.renderer.entity.Render;
import net.minecraft.entity.Entity;
import net.minecraftforge.common.Configuration;
import net.minecraftforge.common.MinecraftForge;
import spelunkcraft.client.IProxy;
import cpw.mods.fml.common.registry.TickRegistry;
import cpw.mods.fml.relauncher.Side;
public class ClientProxy extends CommonProxy {
public static int BigChestBlockRendererID;
public static int PowderBoxBlockRendererID;
int modEntityID = 1;
private boolean hasRopeOut;
private int renderIDGrapplingHook;
public ClientProxy()
{
hasRopeOut = false;
}
@Override
public void initRenderers() {
// This is for rendering textures and so forth later on
BigChestBlockRendererID = RenderingRegistry.getNextAvailableRenderId();
PowderBoxBlockRendererID = RenderingRegistry.getNextAvailableRenderId();
super.registerTileEntities();
RenderingRegistry.registerEntityRenderingHandler(EntityPowderBoxPrimed.class, new RenderPowderBoxPrimed());
RenderingRegistry.registerEntityRenderingHandler(EntityGrappleHook.class, new RenderGrappleHook());
RenderingRegistry.registerEntityRenderingHandler(EntityMidairRope.class, new RenderMidairRope());
RenderingRegistry.registerEntityRenderingHandler(EntityRock.class, new RenderRock(spelunkcraft.items.Items.rockItem));
ClientRegistry.bindTileEntitySpecialRenderer(spelunkcraft.client.tileentity.TileEntityBigChest.class, new TileEntityBigChestRenderer());
}
@Override
public void initSounds() {
// This is for rendering sounds and so forth later on
}
@Override
public int getGrapplingHookRenderId()
{
return renderIDGrapplingHook;
}
@Override
public boolean getHasClientRopeOut()
{
return hasRopeOut;
}
@Override
public void setHasClientRopeOut(boolean
{
hasRopeOut = b;
}
@Override
public void loadConfig(Configuration configFile) {
MinecraftForge.EVENT_BUS.register(new SpelunkcraftSounds());
}
@SuppressWarnings("unchecked")
@Override
public void load() {
TickRegistry.registerTickHandler(new SpelunkcraftClient(), Side.CLIENT);
}
}
I think I see the problem. You need to don't call 'this.func_77026_a(tessellator, icon);' in your Render() method! Call it at the end right after you get the tessellator instance.
For this you need an icon, of course, which is why you pass the Item in to the constructor, but you're not storing it in a local variable. Your constructor should look more like this:
At the beginning of the Render method. All of this stuff is straight from the RenderSnowball class, which is what I showed in the tutorial, too. Look closely and you'll see where to place it.
Okay, I'm one step closer, actually. I finally got it to render, but it's just a purple square. It also just goes right through entities, so doesn't hurt things like cows or pigs, for that matter.
Edit: Okay, I got it to render! I had to do a little code workaround to get it to render, as it just crashes the client otherwise. I can explain more, as for why it's crashing.
But weirdly, the game is still ignoring it's collision detection with other blocks/entities.
Ok, that's because in your ItemRock you spawn the entity when the world is remote... that's the opposite of what you want to do.
Your code:
if (par2World.isRemote) {
par2World.spawnEntityInWorld(new EntityRock(par2World, par3EntityPlayer));
}
Proper code:
if (!par2World.isRemote) {
par2World.spawnEntityInWorld(new EntityRock(par2World, par3EntityPlayer));
}
Notice the ' ! ' in front of it. You should only spawn entities on the server side, because on the client side they are just empty place holders for rendering purposes only. Spawning on the server will automatically create the shell entity for rendering client side.
// If you have a lot of Entities to register, consider creating a class with a static 'initEntity' method
// so your main class stays tidy and readable
EntityRegistry.registerModEntity(EntityThrowingRock.class, "Throwing Rock", ++modEntityID, this, 64, 10, true);
I would like to create the initEntity() method like you said, but this does not work with static. What can I replace it with?
// If you have a lot of Entities to register, consider creating a class with a static 'initEntity' method
// so your main class stays tidy and readable
EntityRegistry.registerModEntity(EntityThrowingRock.class, "Throwing Rock", ++modEntityID, this, 64, 10, true);
I would like to create the initEntity() method like you said, but this does not work with static. What can I replace it with?
'this' is the instance of your mod, so you'd use "YourModsName.instance" instead:
Updated to clarify a point that has caused problems for some people:
PROBLEM: Null Pointer Exception at line 42 of your Render class
at Icon icon = this.field_94151_a.getIconFromDamage(this.field_94150_f);
SOLUTION: Be sure to finish initializing all Items before registering the Render class, otherwise the Item's icon will be null when the Render is registered, resulting in an NPE.
Also updated the custom Render class section to point out a much simpler method of doing it; rather than copy / paste, simply extend the RenderSnowball class. Done. This can be done almost any time you want to do something exactly like or similarly to the way it's done in vanilla code, and is much cleaner than creating lots of duplicate code.
@SideOnly(Side.CLIENT)
public class RenderThrowingRock extends RenderSnowball
{
public RenderThrowingRock(Item item) {
this(item, 0);
}
public RenderThrowingRock(Item item, int par2) {
super(item, par2);
}
}
Of course, in this case, you don't even really have to create a custom class, you can simply pass your Item class to the vanilla RenderSnowball renderer.
RenderingRegistry.registerEntityRenderingHandler(EntityThrowingRock.class, new RenderSnowball(TutorialMain.throwingRock));
Hello,
After 2 days of hard works triying to solve my render problem, i found this post, and now it's works, Thank you !
Well, in fact i have another problem now:
My render works well in Creative but in Survival when i shoot i see the arrow(or the bullet for my mod) rotate to 180 degrees and face me but the trajectory still working. Don't really matter but still annoying.
If someone know how to fix it.
Sorry for typing error, English is not my native language.
Thanks for help !
yeah i know this .. maybe i didn't explain it in a good way
i meant the texture itself
because i did make a kunai .. it looks so horrible when you throw it ( in horizontal way )
Oh I see. You'll need to make a custom Render for your item that rotates the texture 90 degrees. Have a look at RenderArrow and you'll see what I mean:
par9 - 90.0F <- that part
Thanks
Glad you got it to work. To make it shoot from your wand, use the same code you did in ItemThrowingRock 'onItemUse' method - just in your ItemWand instead.
Everything else should still work as is.
I made a mistake in the tutorial that will affect your entity in multiplayer. You need to register the entity on the server side as well, so not in the ClientProxy. I suggest registering your entities in the main mod load method, like so:
Now your entity will work both for single and multi-player, whereas before it would be invisible in multi-player but render correctly in single.
My apologies if you've had any problems due to this oversight. The tutorial has been updated with the correct information.
RockItem.java (Item class)
EntityRock.java (Entity class)
RenderRock.java (Rendering class)
ClientProxy.java (ClientProxy class)
The following is true, the former is false.
For this you need an icon, of course, which is why you pass the Item in to the constructor, but you're not storing it in a local variable. Your constructor should look more like this:
Now you can use this.item.getIconFromDamage(0) to get the icon for the method call.
I tried adding some of the stuff you suggested, so I'm curious where the last bit goes and wouldn't want to screw up.
The following is true, the former is false.
Edit: Okay, I got it to render! I had to do a little code workaround to get it to render, as it just crashes the client otherwise. I can explain more, as for why it's crashing.
But weirdly, the game is still ignoring it's collision detection with other blocks/entities.
The following is true, the former is false.
Your code:
Proper code:
Notice the ' ! ' in front of it. You should only spawn entities on the server side, because on the client side they are just empty place holders for rendering purposes only. Spawning on the server will automatically create the shell entity for rendering client side.
The following is true, the former is false.
Great Don't forget to up the green arrow for posts that help you Happy modding!
I would like to create the initEntity() method like you said, but this does not work with static. What can I replace it with?
'this' is the instance of your mod, so you'd use "YourModsName.instance" instead:
PROBLEM: Null Pointer Exception at line 42 of your Render class
at Icon icon = this.field_94151_a.getIconFromDamage(this.field_94150_f);
SOLUTION: Be sure to finish initializing all Items before registering the Render class, otherwise the Item's icon will be null when the Render is registered, resulting in an NPE.
Of course, in this case, you don't even really have to create a custom class, you can simply pass your Item class to the vanilla RenderSnowball renderer.
How's that for simple?
After 2 days of hard works triying to solve my render problem, i found this post, and now it's works, Thank you !
Well, in fact i have another problem now:
My render works well in Creative but in Survival when i shoot i see the arrow(or the bullet for my mod) rotate to 180 degrees and face me but the trajectory still working. Don't really matter but still annoying.
If someone know how to fix it.
Sorry for typing error, English is not my native language.
Thanks for help !