Elliot King
Elliot King

Reputation: 92

How to Make Minecraft Player's looking position be recorded in java

I know this title is confusing. I am making a minecraft mod in java. I made an Item that explodes and spawns lightning when you right click. Currently, it explodes and makes lightning at the position of the player. How would I make it explode at the position the player looks? My item class currently looks like this:

package com.mod.elliotmod;

import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.entity.effect.EntityLightningBolt;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.world.World;
import net.minecraftforge.fml.common.registry.GameRegistry;

public class ItemMyTNT extends Item {

    public ItemMyTNT(String name, int stackSize) {
        GameRegistry.registerItem(this, name);
        setUnlocalizedName(ElliotMod.MODID + "_" + name);
        setCreativeTab(CreativeTabs.tabMisc);
        setMaxStackSize(stackSize);
    }

    public ItemStack onItemRightClick(ItemStack item, World world, EntityPlayer player) {

        world.spawnEntityInWorld(new EntityLightningBolt(world, player.posX, player.posY, player.posZ));
        world.createExplosion(player, player.posX, player.posY, player.posZ, 5.0F, true);

        return item;
    }
}

EDIT: Here is what I now have:

package com.mod.elliotmod;

import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.entity.effect.EntityLightningBolt;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.world.World;
import net.minecraftforge.fml.common.registry.GameRegistry;

public class ItemMyTNT extends Item {

    public ItemMyTNT(String name, int stackSize) {
        GameRegistry.registerItem(this, name);
        setUnlocalizedName(ElliotMod.MODID + "_" + name);
        setCreativeTab(CreativeTabs.tabMisc);
        setMaxStackSize(stackSize);
    }

    public ItemStack onItemRightClick(ItemStack item, World world, EntityPlayer player) {

        double x = player.getLookVec().xCoord;
        double y = player.getLookVec().yCoord;
        double z = player.getLookVec().zCoord; 

        world.spawnEntityInWorld(new EntityLightningBolt(world, x, y, z));
        world.createExplosion(player, x, y, z, 5.0F, true);

        return item;
    }
}

I found this in the Entity Player class. It may help

        Vec3 vec3 = new Vec3(((double)this.rand.nextFloat() - 0.5D) * 0.1D, Math.random() * 0.1D + 0.1D, 0.0D);
        vec3 = vec3.rotatePitch(-this.rotationPitch * (float)Math.PI / 180.0F);
        vec3 = vec3.rotateYaw(-this.rotationYaw * (float)Math.PI / 180.0F);
        double d0 = (double)(-this.rand.nextFloat()) * 0.6D - 0.3D;
        Vec3 vec31 = new Vec3(((double)this.rand.nextFloat() - 0.5D) * 0.3D, d0, 0.6D);
        vec31 = vec31.rotatePitch(-this.rotationPitch * (float)Math.PI / 180.0F);
        vec31 = vec31.rotateYaw(-this.rotationYaw * (float)Math.PI / 180.0F);
        vec31 = vec31.addVector(this.posX, this.posY + (double)this.getEyeHeight(), this.posZ);

I used this class and my code looks like this, but doesn't work:

public ItemStack onItemRightClick(ItemStack item, World world, EntityPlayer player) {
         Random rand = new Random();
         Vec3 vec3 = new Vec3(((double)rand.nextFloat() - 0.5D) * 0.1D, Math.random() * 0.1D + 0.1D, 0.0D);
         vec3 = vec3.rotatePitch(-player.rotationPitch * (float)Math.PI / 180.0F);
         vec3 = vec3.rotateYaw(-player.rotationYaw * (float)Math.PI / 180.0F);
         double d0 = (double)(rand.nextFloat()) * 0.6D - 0.3D;
         Vec3 vec31 = new Vec3(((double)rand.nextFloat() - 0.5D) * 0.3D, d0, 0.6D);
         vec31 = vec31.rotatePitch(-player.rotationPitch * (float)Math.PI / 180.0F);
         vec31 = vec31.rotateYaw(-player.rotationYaw * (float)Math.PI / 180.0F);
         vec31 = vec31.addVector(player.posX, player.posY + (double)player.getEyeHeight(), player.posZ);

        MovingObjectPosition movingobjectposition = world.rayTraceBlocks(vec3, vec31, false, true, false);
        if (movingobjectposition == null) {
            //nothing was under the player's gaze
            return item;
        }
        if (movingobjectposition.typeOfHit == MovingObjectPosition.MovingObjectType.BLOCK) {
            int ix = movingobjectposition.getBlockPos().getX();
            int iy = movingobjectposition.getBlockPos().getY();
            int iz = movingobjectposition.getBlockPos().getZ();
            if (!world.isBlockNormalCube(movingobjectposition.getBlockPos(), true)) {
                --iy;
            }
            world.spawnEntityInWorld(new EntityLightningBolt(world, ix, iy, iz));
        }
        if (movingobjectposition.typeOfHit == MovingObjectPosition.MovingObjectType.ENTITY) {
            double ix = movingobjectposition.hitVec.xCoord;
            double iy = movingobjectposition.hitVec.yCoord;
            double iz = movingobjectposition.hitVec.zCoord;
            world.spawnEntityInWorld(new EntityLightningBolt(world, ix, iy, iz));
        }

        return item;


    }

Upvotes: 0

Views: 1624

Answers (1)

So your first attempt (using the player's position) is half correct but doesn't go where the player is looking.

You correctly identified that you need to use the player's LookVec but you improperly implemented it. An entity's LookVec is a normalized vector it is not a position.

So your second attempt is still only half-correct (and is spawning the lightning within 1 block of (0,0,0).

So to correct your error, you need to add these two values together:

public ItemStack onItemRightClick(ItemStack item, World world, EntityPlayer player) {

    double x = player.posX + player.getLookVec().xCoord;
    double y = player.posY + player.getLookVec().yCoord;
    double z = player.posZ + player.getLookVec().zCoord; 

    world.spawnEntityInWorld(new EntityLightningBolt(world, x, y, z));
    world.createExplosion(player, x, y, z, 5.0F, true);

    return item;
}

Only that's still only partially correct, as it doesn't get the block that the player is looking at: it creates the lightning 1 block in front of the player's face (well, their feet actually, we didn't add in the player's eye height either).

The only way to do that is to do some raytracing.

Notes:

  • the name of world.rayTraceBlocks_do_do may be different depending on your version of Forge. I pulled this code out of an old project and will need some massaging.

  • vec3: the vector that is the player's eye location

  • vec31: the player's gaze direction (per above example)

    MovingObjectPosition movingobjectposition = world.rayTraceBlocks_do_do(vec3, vec31, false, true, false);
    if (movingobjectposition == null) {
        //nothing was under the player's gaze
        return item;
    }
    if (movingobjectposition.typeOfHit == MovingObjectPosition.MovingObjectType.BLOCK) {
        int ix = movingobjectposition.blockX;
        int iy = movingobjectposition.blockY;
        int iz = movingobjectposition.blockZ;
        if (!world.getBlock(ix, iy, iz).isNormalCube()) {
            --iy;
        }
        //spawn lightning (ix, iy, iz)
    }
    if (movingobjectposition.typeOfHit == MovingObjectPosition.MovingObjectType.ENTITY) {
        double ix = movingobjectposition.hitVec.xCoord;
        double iy = movingobjectposition.hitVec.yCoord;
        double iz = movingobjectposition.hitVec.zCoord;
        //spawn lightning (ix, iy, iz)
    }
    

Upvotes: 1

Related Questions