Posted March 11, 201510 yr 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; }
March 11, 201510 yr Author 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
March 11, 201510 yr 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.
March 11, 201510 yr 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). Not necessary - primitive types can not be null and they all default to the equivalent of zero. http://i.imgur.com/NdrFdld.png[/img]
March 11, 201510 yr Author 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?
March 11, 201510 yr 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. 1.7.10 is no longer supported by forge, you are on your own.
March 11, 201510 yr Author 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
March 11, 201510 yr Author 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.
March 11, 201510 yr @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.
March 13, 201510 yr Author 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
March 13, 201510 yr <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. http://i.imgur.com/NdrFdld.png[/img]
March 13, 201510 yr Author 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}
March 13, 201510 yr ... ... ... 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'. http://i.imgur.com/NdrFdld.png[/img]
March 13, 201510 yr Author @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
March 13, 201510 yr Yeah, shit, I forgot it just ray traces blocks. Well, you're going to either have to do some fancy Vec3 mathematics (I'm sure there's an example somewhere in vanilla) or manually iterate over the player's look vector until you hit something. http://i.imgur.com/NdrFdld.png[/img]
March 13, 201510 yr Author 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.
March 13, 201510 yr 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). http://i.imgur.com/NdrFdld.png[/img]
March 18, 201510 yr Author 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; }
March 18, 201510 yr 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.