Jump to content

[1.7.10] Getting Entity Data based off of look vector doesnt work


Recommended Posts

Posted

I have an item that is a 3D custom rendered item. I want to give it the ability to check a mobs stats that have been saved to NBT on Right click based on the players look vector. For some reason I always get a 0 for all the stats I try to check and im not sure why. I think I am successfully getting the entity my consol prints "This mobs maxHP is 0" and it doesnt matter which stat I try to implement they are all 0. Anyone know why

 

My on Item Right Click Method

 

 

 

@Override
public ItemStack onItemRightClick(ItemStack itemStack, World world, EntityPlayer player) {

	if (world.isRemote){

		int maxCheckRange = 15;
		   Vec3 vec3 = player.getLookVec().normalize();
		   for(int initialCheckRange = 1;initialCheckRange<maxCheckRange;initialCheckRange++){

		    AxisAlignedBB aabb = AxisAlignedBB.getBoundingBox(player.posX + vec3.xCoord * initialCheckRange, player.posY + vec3.yCoord * initialCheckRange, player.posZ + vec3.zCoord * initialCheckRange, player.posX + vec3.xCoord * initialCheckRange, player.posY + vec3.yCoord * initialCheckRange, player.posZ + vec3.zCoord * initialCheckRange);
		    List list = world.getEntitiesWithinAABB(EntityMyMob.class, aabb);
		    if(list.iterator().hasNext()){
		    EntityMyMob ent = (EntityMyMob)list.get(0);
		   int maxHP = ent.getEntityData().getInteger("MaxHP");
	        System.out.println("This mobs maxHP is " + maxHP);
		    
		    }}

		System.out.println("Right-Clicked");
	}
	return itemStack;	
				}


}

 

 

In My custom mobs class I am saving the stats in the following manner

My Entity Class

 

 

public class EntityMyMob extends EntityAnimal {

//IDs for DataWatcher
private static final int ownerDataID = 25;
private static final int hpDataID = 26;
private static final int levelDataID = 27;


public int registryID;

//initialize stats variable so that we can create a unique instance of the MyMobStats class for each MyMob object
public MyMobStats stats = new MyMobStats();
//private boolean baseStatsSaved = false;

public EntityMyMob(World world) {
	/**
	 * gets the texture, sets hitbox size, movement speed, and gets the AI's, get stats for each mob here
	 */
	super(world);
	this.setSize(0.9F, 0.9F); // hitbox size?
	setupAI();
	if(!world.isRemote){
		this.addBaseStatsInformation(this.getEntityData());
	}
}

public int getRegistryID(){
	return MyMobRegistry.getRegistryID(this.getClass());
}

protected void entityInit() {
	super.entityInit();
	this.dataWatcher.addObject(ownerDataID, "");
	this.dataWatcher.addObject(hpDataID, 100);
	this.dataWatcher.addObject(levelDataID, 20);
}

// set up AI tasks
protected void setupAI()
{	
	this.getNavigator().setAvoidsWater(true);
	clearAITasks(); // clear any tasks assigned in super classes
	double speed = 0.5F;
	//this.tasks.addTask(0, new EntityAISwimming(this));
	this.tasks.addTask(1, new EntityAIMyMobWander(this, speed));
	this.tasks.addTask(2, new EntityAIWatchClosest(this, EntityPlayer.class, 12.0F));
	this.tasks.addTask(3, new EntityAIPanic(this, speed)); // speed is the second parameter
	this.tasks.addTask(4, new EntityAILookIdle(this));
	this.tasks.addTask(5, new EntityAIWatchClosest(this, EntityMyMob.class, 6.0F));
}
// clears AI Task list in super class
protected void clearAITasks()
{
	tasks.taskEntries.clear();
	targetTasks.taskEntries.clear();
}

// Returns true if the newer Entity AI code should be run
@Override
public boolean isAIEnabled() {
	return true;
}

protected void updateAITasks() {
	super.updateAITasks();
}


@Override
public String getCustomNameTag(){
	if(this.getOwnerName().length() > 0){
		return this.getOwnerName() + "'s " + this.getName();
	}
	return "";
}

//Add a textbox on top of mob if it has a ownerr
public boolean hasCustomNameTag(){
	return this.getOwnerName().length() > 0;
	//return true;
}

@Override
public boolean getAlwaysRenderNameTag(){
	return this.dataWatcher.getWatchableObjectByte(11) == 1;
}

public void setNameTagVisible(boolean visible){
	this.dataWatcher.updateObject(11, (byte)(visible ? 1 : 0));
}

public String getName(){
	return this.getEntityString();
}

public String getOwnerName(){
	return this.dataWatcher.getWatchableObjectString(this.ownerDataID);
}

public EntityLivingBase getOwner(){
	return this.worldObj.getPlayerEntityByName(this.getOwnerName());
}

public void setOwner(String ownerName){
	this.dataWatcher.updateObject(this.ownerDataID,ownerName);
}

public int getHP(){
	return stats.hp;
	//return this.dataWatcher.getWatchableObjectInt(this.hpDataID);
}

public void setHP(int hp){
	stats.hp = hp;
	//this.dataWatcher.updateObject(this.hpDataID, hp);
}


public int getLevel(){
	return this.dataWatcher.getWatchableObjectInt(this.levelDataID);
}

public void setLevel(int level){
	this.dataWatcher.updateObject(this.levelDataID, level);
}

@Override
public void readEntityFromNBT(NBTTagCompound nbtCompound)
{   
	super.readEntityFromNBT(nbtCompound);
	nbtCompound.getString("MobName");
	stats.hp = nbtCompound.getInteger("BaseHP");
	stats.att = nbtCompound.getInteger("BaseAtt");
	stats.def = nbtCompound.getInteger("BaseDef");
	stats.spAtt = nbtCompound.getInteger("BaseSpAtt");
	stats.spDef = nbtCompound.getInteger("BaseSpDef");
	stats.spd = nbtCompound.getInteger("BaseSpd");
}

@Override
public void writeEntityToNBT(NBTTagCompound nbtCompound)
{ 
	super.writeEntityToNBT(nbtCompound);
	//nbtCompound.setBoolean("baseStatsSaved",baseStatsSaved);
	nbtCompound.setString("MobName", EntityList.getEntityString(this));
	nbtCompound.setInteger("BaseHP",stats.hp);
	nbtCompound.setInteger("BaseAtt",stats.att);
	nbtCompound.setInteger("BaseDef",stats.def);
	nbtCompound.setInteger("BaseSpAtt",stats.spAtt);
	nbtCompound.setInteger("BaseSpDef",stats.spDef);
	nbtCompound.setInteger("BaseSpd",stats.spd);
}

public void addBaseStatsInformation(NBTTagCompound nbtCompound){

	String MobName = getName();
	CalcMyMobStats statCalculator = CalcMyMobStats.getInstance();
	statCalculator.generateRandomGenes(stats);
	stats.hp = statCalculator.getBaseHP(MobName) + stats.Genes_HP;
	stats.att = statCalculator.getBaseAttack(MobName) + stats.Genes_Att;
	stats.def = statCalculator.getBaseDefense(MobName) + stats.Genes_Def;
	stats.spAtt = statCalculator.getBaseSpecialAttack(MobName) + stats.Genes_SpAtt;
	stats.spDef = statCalculator.getBaseSpecialDefense(MobName) + stats.Genes_SpDef;
	stats.spd = statCalculator.getBaseSpeed(MobName) +  + stats.Genes_Spd;
}


@Override
public EntityMyMob createChild(EntityAgeable entityageable) {
	return new EntityMyMob(this.worldObj);
}

@Override
/**
 * handles entity death timer, experience orb and particle creation and I think it also despawns the entity after its death animation is played
 */
protected void onDeathUpdate()
{
	++this.deathTime;	//important. Do not remove. Used elsewhere in death animations
	//this.setDead(); //<- commenting this line out results in any mob that dies to fall on its side to the ground and not despawn
}

@Override
public void onDeath(DamageSource p_70645_1_){ 
	//This is called when an entities hp reaches 0, we need to add stuff here to control what happens when a mob's hp reaches 0
}

}

 

 

 

My Stats Container class

 

 

//container that holds stats of a mob
public class MyMobStats {
//TODO: need a way to serialize this structure into a string
//and restore it!
public int registryID;

//current stats
public int level;

public int hp, currentHp;
public int att, currentAtt;
public int def, currentDef;
public int spAtt, currentSpAtt;
public int spDef, currentSpDef;
public int spd, currentSpd;

//random number to be added to base stats to induce mob genetics where some mobs will be stronger than others. These should be initialized when the mob is created, and should
//never change.
public int Genes_HP;
public int Genes_Att;
public int Genes_Def;
public int Genes_SpAtt;
public int Genes_SpDef;
public int Genes_Spd;

//total experience gained from fighting
public int exp;
	}

 

 

Posted

I know that the stats are being saved correctly and calculated correctly Since I have a method to check this where the item that I use to catch my mobs stores their stats and displays them and so I know the stats work correctly. I just cant seem to be able to access these stats using this new item based on a look vector and I dunno y

Posted

world.isRemote - client

!world.isRemote - server

 

You did world.isRemote.

 

As a follow-up - you know that client's values will be 0 (not like server ones), you will need to use packets/dataWatchers.

 

Also - consider making all your stats = 0 (they are not initialized when constructed). Might save you NPE in some critical case (idk your whole coding style, might not).

1.7.10 is no longer supported by forge, you are on your own.

Posted

So I should use !world.isRemote to get the entity server side then send a packet to the client to update the values? If I do !world.isRemote for some reason nothing is displayed to the consol on right click except "Right-Clicked". Shouldnt I be able to see the value of the entities stat that exists on the server if i use !world.isRemote?

Posted

I don't quite get what you mean.

 

Getting entity from vector should be made on server (!world.isRemote) then you will apply changes to server-side values and send packet to clients that will update client-side values, you shouldnt ever use client to compute stuff, unless you have predictable results (operation mirroring). What is the problem?

 

And btw:

if(list.iterator().hasNext()){
		    EntityMyMob ent = (EntityMyMob)list.get(0);

This piece of code breaks eveary law of iteration. xD

1.7.10 is no longer supported by forge, you are on your own.

Posted

I guess what Im trying to say is It seems my code doesnt get the entity from the look vector then I dont think, since It doesnt display anything to the consol when I try to outprint the server values for my stats

Posted

I have no idea why but for some reason I cant seem to get the EntityData server side. Does anyone know why? If I change the

 

if (world.isRemote){} to

 

if (!world.isRemote){} then for some reason none of the code inside this if statement gets executed.

Posted

@Override
public ItemStack onItemRightClick(ItemStack itemStack, World world, EntityPlayer player)
{
if (!world.isRemote)
{
	System.out.println("WORKS");
}
}

 

Are you telling me this is not printing ANYTHING?

 

Cleanup your code and repost it.

1.7.10 is no longer supported by forge, you are on your own.

Posted

I hope this clarifies it,

 

The System.out.print at line 6 in the code below outprints just fine meaning the method is called on the server just fine

The System.out.print at line 20 inside the for loop does not outprint when I am on the server - when I am on the client however this line DOES work. <- Really weird

[Line 1] @Override
[Line 2]	public ItemStack onItemRightClick(ItemStack itemStack, World world, EntityPlayer player) {
[Line 3]    if (!world.isRemote) {
[Line 4]			int maxCheckRange = 15;
[Line 5]			Vec3 vec3 = player.getLookVec().normalize();
[Line 6]			System.out.println("On Server"); // This outprints just fine meaning this method gets called on the server successfully
[Line 7]			for (int initialCheckRange = 1; initialCheckRange < maxCheckRange; initialCheckRange++) {
[Line 8]
[Line 9]				AxisAlignedBB aabb = AxisAlignedBB.getBoundingBox(
[Line 10]						player.posX + vec3.xCoord * initialCheckRange,
[Line 11]						player.posY	+ vec3.yCoord * initialCheckRange,
[Line 12]						player.posZ	+ vec3.zCoord * initialCheckRange,
[Line 13]						player.posX	+ vec3.xCoord * initialCheckRange,
[Line 14]						player.posY + vec3.yCoord * initialCheckRange,
[Line 15]						player.posZ	+ vec3.zCoord * initialCheckRange);
[Line 16]				List list = world.getEntitiesWithinAABB(EntityMyMob.class,aabb);
[Line 17]				if (list.iterator().hasNext()) {
[Line 18]					EntityMyMob ent = (EntityMyMob) list.get(0);
[Line 19]					int maxHP = ent.getEntityData().getInteger("MaxHP");
[Line 20]					System.out.println("This mobs maxHP is " + maxHP); // This does not out print when I am on the server But does outprint when I am on the client
[Line 21]
[Line 22]				}
[Line 23]			}
[Line 24]
[Line 25]		}
[Line 26]                    return itemStack;
[Line 27] }

 

I have now moved on from trying the method above and have written the following one and it works correctly displaying the hp stats of each entity but I need this method to have a much greater range. Any ideas?

@Override
public ItemStack onItemRightClick(ItemStack itemStack, World world, EntityPlayer player) {

		   if (!world.isRemote){
			    Minecraft mc = Minecraft.getMinecraft();
			    MovingObjectPosition objectMouseOver = mc.objectMouseOver;
			    if(mc.objectMouseOver != null && mc.objectMouseOver.entityHit != null) {
			        Entity Target = objectMouseOver.entityHit;
			        if(Target instanceof EntityMyMob){
			        	System.out.println("getting entity ");
			        	int maxHP = ((EntityMyMob) Target).stats.hp;
			        	System.out.println("This mobs maxHP is " + maxHP);
			}
		}
	}
	return itemStack;

}

int maxHP = ent.getEntityData().getInteger("MaxHP"); wouldnt work at all and would return 0 no matter what. My stats are being saved to NBT but apparently I cannot get them back from NBT in this way for each instance of MyMob entity in game. Dont know why

I have no idea why

Posted

<facepalm>

 

Minecraft.getMinecraft(), along with objectMouseOver, are both CLIENT side ONLY. Your code will not only not work, but it will also crash if you try it on a server.

 

If you just want to get the entity that the player is looking at, since you are in an Item class, you can use Item#getMovingObjectPositionFromPlayer - this gives you a MovingObjectPosition which you can then check hitType and entityHit.

 

Or you can do the vector calculations yourself.

Posted

I tried the following didnt work :/ turns out raytraces are hard. Im not sure what else to try at this point I cant seem to be able to get the entity

 

@Override
public ItemStack onItemRightClick(ItemStack itemStack, World world, EntityPlayer player) {

	Entity Target = this.getEntityFromLookVector(world, player);
	System.out.println(Target);
	if (!world.isRemote & Target != null) {
		if (Target instanceof EntityMyMob) {
			System.out.println("getting entity ");
			int maxHP = ((EntityMyMob) Target).stats.hp;
			System.out.println("This mobs maxHP is " + maxHP);
		}
	}
	return itemStack;
}

@SideOnly(Side.CLIENT)
public Entity getEntityFromLookVector (World world, EntityPlayer player){

	MovingObjectPosition mop = player.rayTrace(15, 1.0f);
	if (mop != null)
	{
		System.out.println("mop isnt null" + mop);
	    if (mop.typeOfHit == MovingObjectPosition.MovingObjectType.ENTITY)
	    {
	    	System.out.println("hit ent");
	        return mop.entityHit;
	    }
}
	return null;
}
}

 

this code never returned an entity as being hit. Even if I stood right next to my mob or even a cow/sheep it would either return one of the following

 

mop isnt nullHitResult{type=BLOCK, x=206, y=3, z=888, f=1, pos=(206.5229233287801, 4.0, 888.9466416142508), entity=null}

mop isnt nullHitResult{type=MISS, x=219, y=12, z=892, f=4, pos=(219.0, 12.750675644892668, 892.5001750429458), entity=null}

Posted

... ... ... Seriously? Again? Look at the method:

[b]@SideOnly(Side.CLIENT)[/b]
public Entity getEntityFromLookVector (World world, EntityPlayer player){

Let's hope the bold works on CLIENT SIDE ONLY!!! Yet you expect results on the server.

 

Did you not read my previous previous comment? I told you exactly which method you can use that already exists - you don't need to write anything but one line to get the raytrace (i.e. MovingObjectPosition). Please read it again.

 

Also, you should know that your naming conventions are incorrect: "Target" would be a class name, not the name of a variable - that would be 'target'.

Posted

@Override
public ItemStack onItemRightClick(ItemStack itemStack, World world, EntityPlayer player) {

	if (!world.isRemote){
		MovingObjectPosition mop = this.getMovingObjectPositionFromPlayer(world, player, true);	
		System.out.println(mop);
	}
	return itemStack;
	}	
				}

 

this outprints either null or type hit = block and never outprints type hit to be of type Entity

Posted

Ya Ive been looking, If anyone has a solution to getting entity data based on a look vector/raytrace please let me know ill keep looking and post a solution if i come across one.

Posted

I have some code which isn't exactly what you need, but you could use it until you figure out a better solution (which you could find by researching / duplicating the code Minecraft uses on the client to determine the objectMouseOver).

 

Anyway, it's a method that searches for the nearest entity to the player within a certain distance and with a maximum deviation from line-of-sight; if you set the deviation to be small, it will effectively get the objectMouseOver.

 

Still, I would look into EntityRenderer#getMouseOver, or you could even just send the current objectMouseOver's entityId (or null) in a packet from the client, then handle your effect on the server when you receive that packet. That would save you from duplicating a bunch of code at the cost of delaying your action by the amount of time it takes to send a packet (which is usually negligible).

Posted

Thanks coolAlias for the code snippet but I went my own route. I solved my problem by updating the entity by sending a packet from server to client and then getting the entity data client side only. It seems to work ok for what I needed. Although getting it server side would be ideal. For now Im just keeping it client side since Im using my item to test the stats generation that I have implemented.

 

This is my solution (Its pretty ugly but seems to do the job) I open a gui to display the stats that my mob has by using the entityID of the custom mob that was clicked on where its ID is passed through the x coordinate. Don't really know how else to do it and any suggestions would be appreciated.

 

public ItemStack onItemRightClick(ItemStack itemStack, World world, EntityPlayer player) {
	if (world.isRemote){
		int maxCheckRange = 15;
		Vec3 vec3 = player.getLookVec().normalize();
		for(int initialCheckRange = 1;initialCheckRange<maxCheckRange;initialCheckRange++){

			AxisAlignedBB aabb = AxisAlignedBB.getBoundingBox(player.posX + vec3.xCoord * initialCheckRange, player.posY + vec3.yCoord * initialCheckRange, player.posZ + vec3.zCoord * initialCheckRange, player.posX + vec3.xCoord * initialCheckRange, player.posY + vec3.yCoord * initialCheckRange, player.posZ + vec3.zCoord * initialCheckRange);
			List list = world.getEntitiesWithinAABB(EntityMyMob.class, aabb);
			if(list.iterator().hasNext()){
				EntityMyMob ent = (EntityMyMob)list.get(0);

				//Open a GuiStatsDisplay which displays info about the custom mob the player clicked on.
				//(kind of a hack) - the entityID of the custom mob clicked on is passed through the x coordinate.
				//Don't really know how else to do it.
				player.openGui(CustomMod.instance, PWGuiHandler.STATS_GUI_ID, world, (int)ent.getEntityId(), 0, 0);
			}
		}
	}
	return itemStack;	
}

Posted

How about you have a static variable somewhere that stores the ID of the last mob right clicked, it is set before the GUI is open and then in the getClientGuiElement or wherever you need it just access that variable.

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.