YoungErtu Posted February 3, 2016 Share Posted February 3, 2016 Help, I created an Entity which summonable by right-clicking an item but when i spawn it, it dies instantly and i dont know why, this just happened after i added something and changed a part of the code, before it worked fine and the entity didn't died. here the summon code in the item class: /** * Called whenever this item is equipped and the right mouse button is pressed. Args: itemStack, world, entityPlayer */ public ItemStack onItemRightClick(ItemStack itemStackIn, World world, EntityPlayer player) { NBTTagCompound nbtTagCompound = itemStackIn.getTagCompound(); if (!world.isRemote) { /*if (nbtTagCompound != null && nbtTagCompound.hasKey("IS_SUMMONED") && nbtTagCompound.getBoolean("IS_SUMMONED") == true ) { EntityNikora entitynikora = new EntityNikora(world, player); player.addChatComponentMessage(new ChatComponentText(EnumChatFormatting.RED +"You de-summoned Nikora.")); entitynikora.spawnExplosionParticle(); entitynikora.setDead(); setIsSummoned(itemStackIn, false); }*/ if (nbtTagCompound != null && nbtTagCompound.hasKey("IS_SUMMONED") && nbtTagCompound.getBoolean("IS_SUMMONED") == false ) { //PacketDispatcher.sendToServer(new SpellToServer(10, 10)); EntityNikora entitynikora = new EntityNikora(world, player); entitynikora.setPosition(player.posX, player.posY+1,player.posZ-2); world.spawnEntityInWorld(entitynikora); player.addChatComponentMessage(new ChatComponentText(EnumChatFormatting.GREEN + "You summoned Nikora!")); } } return itemStackIn; } the entity: public class EntityNikora extends EntityTameable implements IEntityOwnable { private int tick; private int manacost = 5; private double spirit_damage = 2.0D; private double spirit_health = 20.0D; public EntityNikora(World w) { this(w, null); } public EntityNikora(World world, Entity caster) { super(world); this.setSize(1, 1); ((PathNavigateGround)this.getNavigator()).func_179690_a(true); this.tasks.addTask(1, new EntityAISwimming(this)); this.tasks.addTask(3, new EntityAILeapAtTarget(this, 0.4F)); this.tasks.addTask(4, new EntityAIAttackOnCollide(this, 1.0D, true)); this.tasks.addTask(5, new EntityAIFollowOwner(this, 1.0D, 2F, 5F)); this.tasks.addTask(6, new EntityAIMate(this, 1.0D)); this.tasks.addTask(7, new EntityAIWander(this, 1.0D)); this.tasks.addTask(9, new EntityAIWatchClosest(this, EntityPlayer.class, 8.0F)); this.tasks.addTask(9, new EntityAILookIdle(this)); this.targetTasks.addTask(1, new EntityAIOwnerHurtByTarget(this)); this.targetTasks.addTask(2, new EntityAIOwnerHurtTarget(this)); this.targetTasks.addTask(3, new EntityAINearestAttackableTarget(this, EntityMob.class, true)); this.targetTasks.addTask(3, new EntityAIHurtByTarget(this, true, new Class[0])); if (caster != null) { this.setTamed(true); this.setAttackTarget((EntityLivingBase)null); this.setOwnerId(caster.getUniqueID().toString()); this.worldObj.setEntityState(this, (byte)7); } } /** * Returns true if the newer Entity AI code should be run */ public boolean isAIEnabled() { return true; } protected void applyEntityAttributes() { super.applyEntityAttributes(); this.getEntityAttribute(SharedMonsterAttributes.maxHealth).setBaseValue(this.spirit_health); this.getEntityAttribute(SharedMonsterAttributes.movementSpeed).setBaseValue(this.spirit_damage); } @Override public void onLivingUpdate() { if(getOwner() != null){ EntityPlayer player = (EntityPlayer)getOwner(); ExtendedPlayer props = ExtendedPlayer.get(player); tick++; if(!worldObj.isRemote){ if(tick > 300){ if(props.getCurrentMana() >= manacost){ props.consumeMana(manacost); tick = 0; } if(props.getCurrentMana() < manacost){ player.addChatComponentMessage(new ChatComponentText(EnumChatFormatting.RED + "You have not enough Mana, your Celestial Spirit was desummoned.")); this.worldObj.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, this.posX, this.posY, this.posZ, 0, 0, 0, 0); this.setDead(); } } } super.onLivingUpdate(); } } /** * Called frequently so the entity can update its state every tick as required. For example, zombies and skeletons * use this to react to sunlight and start to burn. * @param entity */ public void onLivingUpdate(EntityPlayer entity) { super.onLivingUpdate(); if(!(entity instanceof EntityPlayer)) { this.setAttackTarget(entity); } } protected Item getDropItem() { return (null); } @Override public EntityAgeable createChild(EntityAgeable ageable) { return (null); } } note no error, but it dies by his self. thanks for any help! "My Crew is World Wide." 「ヤング • エルトウ」 Link to comment Share on other sites More sharing options...
Failender Posted February 3, 2016 Share Posted February 3, 2016 EntityNikora entitynikora = new EntityNikora(world, player); player.addChatComponentMessage(new ChatComponentText(EnumChatFormatting.RED +"You de-summoned Nikora.")); entitynikora.spawnExplosionParticle(); entitynikora.setDead(); what exactly are you triing to do there Link to comment Share on other sites More sharing options...
DasKaktus Posted February 3, 2016 Share Posted February 3, 2016 EntityNikora entitynikora = new EntityNikora(world, player); player.addChatComponentMessage(new ChatComponentText(EnumChatFormatting.RED +"You de-summoned Nikora.")); entitynikora.spawnExplosionParticle(); entitynikora.setDead(); what exactly are you triing to do there That part is commented out. But back to topic. Sure about getCurrentMana() is over manacost? Not all things in the world are red, there are round objects too! Link to comment Share on other sites More sharing options...
YoungErtu Posted February 3, 2016 Author Share Posted February 3, 2016 EntityNikora entitynikora = new EntityNikora(world, player); player.addChatComponentMessage(new ChatComponentText(EnumChatFormatting.RED +"You de-summoned Nikora.")); entitynikora.spawnExplosionParticle(); entitynikora.setDead(); what exactly are you triing to do there That part is commented out. But back to topic. Sure about getCurrentMana() is over manacost? Yes im sure, when the current mana is lower than the manacost it will send a Chat Message and a System out print but it doesnt do. "My Crew is World Wide." 「ヤング • エルトウ」 Link to comment Share on other sites More sharing options...
DasKaktus Posted February 3, 2016 Share Posted February 3, 2016 Tried to debug and breakpoint to trace where the entity dies? By the way which difficulty level are you running the game in? Not all things in the world are red, there are round objects too! Link to comment Share on other sites More sharing options...
larsgerrits Posted February 3, 2016 Share Posted February 3, 2016 First, make sure you are not in peaceful mode. Second: if(props.getCurrentMana() >= manacost){ props.consumeMana(manacost); tick = 0; } if(props.getCurrentMana() < manacost){ player.addChatComponentMessage(new ChatComponentText(EnumChatFormatting.RED + "You have not enough Mana, your Celestial Spirit was desummoned.")); this.worldObj.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, this.posX, this.posY, this.posZ, 0, 0, 0, 0); this.setDead(); } Let's follow that logic. I don't know your current mana at that point, but let's say you have 6 mana. You have manacost = 5. - if(props.getCurrentMana() >= manacost) Your current mana is 6, and manacost is 5, so that condition is true. --- props.consumeMana(manacost) I suspect consumeMana is reducing your current mana with the manacost, leaving you with only 1 mana left. - if(props.getCurrentMana() < manacost) Your current mana is 1 at this point, and manacost is 5, so that is indeed less and that condition is true. --- Kill the entity Have you figured it out yet? If you don't have atleast 2*manacost when you start, the entity instantly dies because the second if-statement is true because you already removed the mana from the player. You have to add else to the second if-statement. Don't PM me with questions. They will be ignored! Make a thread on the appropriate board for support. 1.12 -> 1.13 primer by williewillus. 1.7.10 and older versions of Minecraft are no longer supported due to it's age! Update to the latest version for support. http://www.howoldisminecraft1710.today/ Link to comment Share on other sites More sharing options...
YoungErtu Posted February 3, 2016 Author Share Posted February 3, 2016 First, make sure you are not in peaceful mode. Second: if(props.getCurrentMana() >= manacost){ props.consumeMana(manacost); tick = 0; } if(props.getCurrentMana() < manacost){ player.addChatComponentMessage(new ChatComponentText(EnumChatFormatting.RED + "You have not enough Mana, your Celestial Spirit was desummoned.")); this.worldObj.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, this.posX, this.posY, this.posZ, 0, 0, 0, 0); this.setDead(); } Let's follow that logic. I don't know your current mana at that point, but let's say you have 6 mana. You have manacost = 5. - if(props.getCurrentMana() >= manacost) Your current mana is 6, and manacost is 5, so that condition is true. --- props.consumeMana(manacost) I suspect consumeMana is reducing your current mana with the manacost, leaving you with only 1 mana left. - if(props.getCurrentMana() < manacost) Your current mana is 1 at this point, and manacost is 5, so that is indeed less and that condition is true. --- Kill the entity Have you figured it out yet? If you don't have atleast 2*manacost when you start, the entity instantly dies because the second if-statement is true because you already removed the mana from the player. You have to add else to the second if-statement. It seems logical what you mean but i found out that this two variables are the problem, i can fix that with replacing them at applyEntityAttributes with there value, but why i can't use them as variables? private double spirit_damage = 2.0D; private double spirit_health = 20D; protected void applyEntityAttributes() { super.applyEntityAttributes(); this.getEntityAttribute(SharedMonsterAttributes.maxHealth).setBaseValue(spirit_health);} The Entity is dying because the health is 0 seems logical, but i would like to know why i can't use this 2 variables that i created. thanks for any help! "My Crew is World Wide." 「ヤング • エルトウ」 Link to comment Share on other sites More sharing options...
DasKaktus Posted February 3, 2016 Share Posted February 3, 2016 NVM Not all things in the world are red, there are round objects too! Link to comment Share on other sites More sharing options...
Ernio Posted February 3, 2016 Share Posted February 3, 2016 1. Read about how Java creates instances. 2. Notice that applyEntityAttributes() is called from super-constructor of your entity. 3. Think about what is happening and say: "Oh, shit, those 2 globals "spirit_damage" and "spirit_health" are not yet initialized! Therefore, generic data in java is set to default 0.0 for doubles! 4. Ahh... so that's why my entity dies! EDIT What you need: Use "static" keyword to make it shared between all entities. If you need different entities have different health you CANNOT use "SharedMonsterAttributes" - notice word "Shared". To achieve different values (and make them sync automatically) for different you need to apply AttributeModifier to entity after it's been spawned. 1.7.10 is no longer supported by forge, you are on your own. Link to comment Share on other sites More sharing options...
YoungErtu Posted February 3, 2016 Author Share Posted February 3, 2016 1. Read about how Java creates instances. 2. Notice that applyEntityAttributes() is called from super-constructor of your entity. 3. Think about what is happening and say: "Oh, shit, those 2 globals "spirit_damage" and "spirit_health" are not yet initialized! Therefore, generic data in java is set to default 0.0 for doubles! 4. Ahh... so that's why my entity dies! thanks! "My Crew is World Wide." 「ヤング • エルトウ」 Link to comment Share on other sites More sharing options...
YoungErtu Posted February 3, 2016 Author Share Posted February 3, 2016 1. Read about how Java creates instances. 2. Notice that applyEntityAttributes() is called from super-constructor of your entity. 3. Think about what is happening and say: "Oh, shit, those 2 globals "spirit_damage" and "spirit_health" are not yet initialized! Therefore, generic data in java is set to default 0.0 for doubles! 4. Ahh... so that's why my entity dies! EDIT What you need: Use "static" keyword to make it shared between all entities. If you need different entities have different health you CANNOT use "SharedMonsterAttributes" - notice word "Shared". To achieve different values (and make them sync automatically) for different you need to apply AttributeModifier to entity after it's been spawned. Thanks Ernio you're the best, it works, thanks for your help! And thanks to you guys for helping me too. "My Crew is World Wide." 「ヤング • エルトウ」 Link to comment Share on other sites More sharing options...
YoungErtu Posted February 3, 2016 Author Share Posted February 3, 2016 I have one last question, how can i get the summoned Entity that if i right-click again the item, the summoned Entity will disappear? "My Crew is World Wide." 「ヤング • エルトウ」 Link to comment Share on other sites More sharing options...
DasKaktus Posted February 3, 2016 Share Posted February 3, 2016 Save a reference to the entity in the item when summoned? Not all things in the world are red, there are round objects too! Link to comment Share on other sites More sharing options...
YoungErtu Posted February 3, 2016 Author Share Posted February 3, 2016 Save a reference to the entity in the item when summoned? i'll try. "My Crew is World Wide." 「ヤング • エルトウ」 Link to comment Share on other sites More sharing options...
Ernio Posted February 3, 2016 Share Posted February 3, 2016 Should be noted: If you don't know yet - Item is singleton, logically speaking "a description of what you are holding". The thing you are actually holding is ItemStack and only ItemStack can hold per-stack data. To save reference to entity in ItemStack you need to use entity.getUniqueId() which can then be saved in ItemStack's NBT as 2 longs (UUID#getMost/LeastSignificantBits()). Then you can re-reference entity by getting it from saved UUID - World#getEntityById (or similar method, i don't remember). Do note that entity might not be found (unloaded), might only be found on server (client is too far to see entity) or other expected or not behaviours - that all needs to be handled properly. 1.7.10 is no longer supported by forge, you are on your own. Link to comment Share on other sites More sharing options...
DasKaktus Posted February 3, 2016 Share Posted February 3, 2016 Or.. If im reading you right there could only be one summoned entity, then tell all entities that have the player as caster to disappear? Not all things in the world are red, there are round objects too! Link to comment Share on other sites More sharing options...
YoungErtu Posted February 4, 2016 Author Share Posted February 4, 2016 Should be noted: If you don't know yet - Item is singleton, logically speaking "a description of what you are holding". The thing you are actually holding is ItemStack and only ItemStack can hold per-stack data. To save reference to entity in ItemStack you need to use entity.getUniqueId() which can then be saved in ItemStack's NBT as 2 longs (UUID#getMost/LeastSignificantBits()). Then you can re-reference entity by getting it from saved UUID - World#getEntityById (or similar method, i don't remember). Do note that entity might not be found (unloaded), might only be found on server (client is too far to see entity) or other expected or not behaviours - that all needs to be handled properly. getEntityByID needs a Int but UUID is a String, so i can't use it. is there any method to get a Entity by his UUID? because there is just a method for player UUID, i changed the item class now its saving the UUID of the Entity but i can't do anything with the UUID, when there is no Method for it. "My Crew is World Wide." 「ヤング • エルトウ」 Link to comment Share on other sites More sharing options...
Ernio Posted February 4, 2016 Share Posted February 4, 2016 Ah, I used bad naming, getEntityByID uses "network" IDs used to sync server and client entity data. It's just that I have my own utilitiy method that does it for UUID (thus, my confusion). Anyway: World isntance has "loadedEntityList". You need to make utility method that will take UUID and return Entity. Then in that method you will iterate through all entities ("loadedEntityList") and check if entity.getUniqueId().equals(paramUUID), if so - return entity. As one could expect - retrieving UUID from ItemStack's NBT, converting it from 2 longs to "new UUID(least, most)" and then comparing it to list of ALL entities (until found) MIGHT be a little overhead if not used with care - so if you'd ever use it in future to manage per-tick actions - try caching refernce at all cost (not quite possible with ItemStacks). 1.7.10 is no longer supported by forge, you are on your own. Link to comment Share on other sites More sharing options...
YoungErtu Posted February 4, 2016 Author Share Posted February 4, 2016 WorldServer has a method getEntityFromUuid. yes, but the problem is, that the UUID that i save into the Item NBT-Tag, is a String, and getEntityFromUuid needs a UUID, so how can i check that? "My Crew is World Wide." 「ヤング • エルトウ」 Link to comment Share on other sites More sharing options...
YoungErtu Posted February 4, 2016 Author Share Posted February 4, 2016 Ah, I used bad naming, getEntityByID uses "network" IDs used to sync server and client entity data. It's just that I have my own utilitiy method that does it for UUID (thus, my confusion). Anyway: World isntance has "loadedEntityList". You need to make utility method that will take UUID and return Entity. Then in that method you will iterate through all entities ("loadedEntityList") and check if entity.getUniqueId().equals(paramUUID), if so - return entity. As one could expect - retrieving UUID from ItemStack's NBT, converting it from 2 longs to "new UUID(least, most)" and then comparing it to list of ALL entities (until found) MIGHT be a little overhead if not used with care - so if you'd ever use it in future to manage per-tick actions - try caching refernce at all cost (not quite possible with ItemStacks). i tried to make a method how you said but im getting errors could you give me an example how you did that? "My Crew is World Wide." 「ヤング • エルトウ」 Link to comment Share on other sites More sharing options...
coolAlias Posted February 4, 2016 Share Posted February 4, 2016 UUID#fromString and UUID#toString? Or, using long values instead: // Writing to NBT: compound.setLong("YourUUIDMost", uuid.getMostSignificantBits()); compound.setLong("YourUUIDLeast", uuid.getLeastSignificantBits()); // Recreating from NBT: UUID uuid = new UUID(compound.getLong("YourUUIDMost"), compound.getLong("YourUUIDLeast")); http://i.imgur.com/NdrFdld.png[/img] Link to comment Share on other sites More sharing options...
YoungErtu Posted February 4, 2016 Author Share Posted February 4, 2016 UUID#fromString and UUID#toString? Or, using long values instead: // Writing to NBT: compound.setLong("YourUUIDMost", uuid.getMostSignificantBits()); compound.setLong("YourUUIDLeast", uuid.getLeastSignificantBits()); // Recreating from NBT: UUID uuid = new UUID(compound.getLong("YourUUIDMost"), compound.getLong("YourUUIDLeast")); i made an method to return the entity when the UUID is the same with the one that is saved to the NBT, but it seems that its not working it seems that the UUID is not the same with the saved UUID. public static Entity getSummonedEntity(){ World world = Minecraft.getMinecraft().theWorld; int i = 0; ItemStack stack = Minecraft.getMinecraft().thePlayer.getCurrentEquippedItem(); //Entity entity2 = (Entity)world.loadedEntityList.get(); if(world.loadedEntityList != null){ for (i = 0; i < world.loadedEntityList.size(); i++) { if (((Entity)world.loadedEntityList.get(i)) instanceof EntityNikora) { System.out.println("NIKORA FOUND"); if (((Entity)world.loadedEntityList.get(i)).getUniqueID().toString().equals(getUUID(stack))) { System.out.println("NIKORA UUID CHECKED"); Entity entity = (Entity)world.loadedEntityList.get(i); return entity; } } } } return (Entity)world.loadedEntityList.get(i); } This line isn't called, so it seems that the EntityUUID is not the same, could somebody tell me why? System.out.println("NIKORA UUID CHECKED"); and here the getUUID method: public static String getUUID(ItemStack stack){ NBTTagCompound nbtTagCompound = stack.getTagCompound(); if (nbtTagCompound != null){ return nbtTagCompound.getString("UUID"); } else return ""; } "My Crew is World Wide." 「ヤング • エルトウ」 Link to comment Share on other sites More sharing options...
Ernio Posted February 4, 2016 Share Posted February 4, 2016 No, No, No, No... Minecraft is client-only class. Everything there is a display stuff - You cannot edit it, it won't do shit to actual data on server. public static UUID getUUID(ItemStack stack) { NBTTagCompound nbt = stack.getTagCompound(); if (nbtTagCompound != null) { return new UUID(nbt.getLong("MSB"), nbt.getLong("LSB")); // most and least significant bits } return null; } In your Item class you need to write data to NBT on usage: UUID uuid = entity.getUniqueId(); // entity is some entity you want to save ref to. nbt.setLong("MSB", uuid.getMostSignificantBits()); // nbt of itemstack. nbt.setLong("LSB", uuid.getLeastSignificantBits()); Getting actual ref: @Override public ItemStack onItemRightClick(ItemStack itemStack, World world, EntityPlayer player) { if (!world.isRemote) // UUIDs ONLY exist on server (not counting players) { UUID uuid = getUUID(itemStack); // 1st method in post Entity entity = ((WorldServer) world).getEntityFromUuid(uuid); Do note that srcs above are unsafe and need null handling for NBT/entity/uuid. 1.7.10 is no longer supported by forge, you are on your own. Link to comment Share on other sites More sharing options...
YoungErtu Posted February 4, 2016 Author Share Posted February 4, 2016 No, No, No, No... Minecraft is client-only class. Everything there is a display stuff - You cannot edit it, it won't do shit to actual data on server. public static UUID getUUID(ItemStack stack) { NBTTagCompound nbt = stack.getTagCompound(); if (nbtTagCompound != null) { return new UUID(nbt.getLong("MSB"), nbt.getLong("LSB")); // most and least significant bits } return null; } In your Item class you need to write data to NBT on usage: UUID uuid = entity.getUniqueId(); // entity is some entity you want to save ref to. nbt.setLong("MSB", uuid.getMostSignificantBits()); // nbt of itemstack. nbt.setLong("LSB", uuid.getLeastSignificantBits()); Getting actual ref: @Override public ItemStack onItemRightClick(ItemStack itemStack, World world, EntityPlayer player) { if (!world.isRemote) // UUIDs ONLY exist on server (not counting players) { UUID uuid = getUUID(itemStack); // 1st method in post Entity entity = ((WorldServer) world).getEntityFromUuid(uuid); Do note that srcs above are unsafe and need null handling for NBT/entity/uuid. Thanks, i understand what you mean, i'll try that. "My Crew is World Wide." 「ヤング • エルトウ」 Link to comment Share on other sites More sharing options...
YoungErtu Posted February 6, 2016 Author Share Posted February 6, 2016 No, No, No, No... Minecraft is client-only class. Everything there is a display stuff - You cannot edit it, it won't do shit to actual data on server. public static UUID getUUID(ItemStack stack) { NBTTagCompound nbt = stack.getTagCompound(); if (nbtTagCompound != null) { return new UUID(nbt.getLong("MSB"), nbt.getLong("LSB")); // most and least significant bits } return null; } In your Item class you need to write data to NBT on usage: UUID uuid = entity.getUniqueId(); // entity is some entity you want to save ref to. nbt.setLong("MSB", uuid.getMostSignificantBits()); // nbt of itemstack. nbt.setLong("LSB", uuid.getLeastSignificantBits()); Getting actual ref: @Override public ItemStack onItemRightClick(ItemStack itemStack, World world, EntityPlayer player) { if (!world.isRemote) // UUIDs ONLY exist on server (not counting players) { UUID uuid = getUUID(itemStack); // 1st method in post Entity entity = ((WorldServer) world).getEntityFromUuid(uuid); Do note that srcs above are unsafe and need null handling for NBT/entity/uuid. THANKS ERNIO, it works perfectly! It wasn't that hard to understand, but im wondering what uuid.getMostSignificantBits() & uuid.getLeastSignificantBits() means, does a UUID have this 2 long variables? Can anyone explain me that? "My Crew is World Wide." 「ヤング • エルトウ」 Link to comment Share on other sites More sharing options...
Recommended Posts