"Accroché" une entité à une autre entité
-
Salut
J’ai fait des recherches mais je ne comprend pas à quoi servent les Integer. C’est grâce à ça qu’on pourra détecter l’ID du renne accroché ? Et pour ta seconde question, on pourra accroché plusieurs rennes à la fois (un maximum de 6) -
Les integers stockeraient alors les id’s des rennes concernés. Et au moment de les relier au traîneau, on ferait alors un getEntityID (me souviens plus de la clase exacte), et on irait get dans les NBT de la rope actuellement tenu par le joueurs, tous les rennes précédemment attachés. Et ainsi avec toutes les instances d’EntityRenne qu’on aurait eu, t’aurais pu appeler ta méthode spécialement codée pour les accrocher au bon endroit, avec la bonne rotation, etc…Tu vois ou t’as d’autres questions ?
Moi après c’est ce que j’aurais fait, peut-être que d’autres personnes auraient vu + simple… -
Ok merci. Je vais essayer et je reviens quand j’aurais des problèmes (car malheureusement j’en aurai)
EDIT : J’ai fait une trouvaille sans doute interressante. Je cherchait l’entité de la corde (celle qui se créer quand le renne est accroché au joueur(car je ne pense pas qu’on puisse mettre un integer à un item, en tout cas j’ai rien trouvé)) et là j’ai trouvé un packet ayant pour paramètre l’entité acccroché etr un boolean Je suis allé dedans et j’ai vu ```java
public SPacketEntityAttach(Entity entityIn, @Nullable Entity vehicleIn)
{
this.entityId = entityIn.getEntityId();
this.vehicleEntityId = vehicleIn != null ? vehicleIn.getEntityId() : -1;
}::: Voilà la classe du packet en entier : ```java package net.minecraft.network.play.server; import java.io.IOException; import javax.annotation.Nullable; import net.minecraft.entity.Entity; import net.minecraft.network.Packet; import net.minecraft.network.PacketBuffer; import net.minecraft.network.play.INetHandlerPlayClient; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; public class SPacketEntityAttach implements Packet <inethandlerplayclient>{ private int entityId; private int vehicleEntityId; public SPacketEntityAttach() { } public SPacketEntityAttach(Entity entityIn, @Nullable Entity vehicleIn) { this.entityId = entityIn.getEntityId(); this.vehicleEntityId = vehicleIn != null ? vehicleIn.getEntityId() : -1; } /** * Reads the raw packet data from the data stream. */ public void readPacketData(PacketBuffer buf) throws IOException { this.entityId = buf.readInt(); this.vehicleEntityId = buf.readInt(); } /** * Writes the raw packet data to the data stream. */ public void writePacketData(PacketBuffer buf) throws IOException { buf.writeInt(this.entityId); buf.writeInt(this.vehicleEntityId); } /** * Passes this Packet on to the NetHandler for processing. */ public void processPacket(INetHandlerPlayClient handler) { handler.handleEntityAttach(this); } @SideOnly(Side.CLIENT) public int getEntityId() { return this.entityId; } @SideOnly(Side.CLIENT) public int getVehicleEntityId() { return this.vehicleEntityId; } }
:::</inethandlerplayclient>
-
Je vais faire des recherches sur l’utilisation de ce packet.
Mais crois moi que dans ton cas ça serait plus facile des NBT, puisque là on est both sides, donc le packet, bof bof l’utlité -
Du coup, je fait l’autre méthode. J’ai compris pour les integer, mais c’est dans l’entité de la corde qu’il faut enregistré les Nbt. Mais je ne la trouve pas. Et dans l’item, rien ne fait référence à l’entité accroché.
-
J’ai compris comment il faut faire mais je vois pas comment commencer. Déjà, je sais qu’il faut faire ça dans la classe de la corde et qu’il faut get les ID des rennes pour les stocker, mais je ne sais pas comment faire pour récupérer leurs instances (parce qu’il faut récupérer l’instance du renne pour ensuite récupérer l’ID). J’ai quand même commencer : ```java
package This_is_Christmas.Entity;import javax.annotation.Nullable;
import This_is_Christmas.CreateItems;
import net.minecraft.crash.CrashReport;
import net.minecraft.crash.CrashReportCategory;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityHanging;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.SoundEvents;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.nbt.NBTTagString;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.ReportedException;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.World;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;public class EntityRopeKnot extends EntityHanging
{
protected Entity entityPosition;public EntityRopeKnot(World worldIn)
{
super(worldIn);
}public EntityRopeKnot(World worldIn, Entity entityPositionIn)
{
this(worldIn);
this.entityPosition = entityPositionIn;
this.setPosition((double)entityPositionIn.posX + 0.5D, (double)entityPositionIn.posY + 0.5D, (double)entityPositionIn.posZ + 0.5D);
float f = 0.125F;
float f1 = 0.1875F;
float f2 = 0.25F;
this.setEntityBoundingBox(new AxisAlignedBB(this.posX - 0.1875D, this.posY - 0.25D + 0.125D, this.posZ - 0.1875D, this.posX + 0.1875D, this.posY + 0.25D + 0.125D, this.posZ + 0.1875D));
}/**
- Sets the x,y,z of the entity from the given parameters. Also seems to set up a bounding box.
*/
public void setPosition(double x, double y, double z)
{
super.setPosition((double)MathHelper.floor_double(x) + 0.5D, (double)MathHelper.floor_double(y) + 0.5D, (double)MathHelper.floor_double(z) + 0.5D);
}
/**
- Updates the entity bounding box based on current facing
/
//TODO
/ protected void updateBoundingBox()
{
this.posX = (double)this.entityPosition.posX + 0.5D;
this.posY = (double)this.entityPosition.posY + 0.5D;
this.posZ = (double)this.entityPosition.posZ + 0.5D;
}
/**
- Updates facing and bounding box based on it
*/
public void updateFacingWithBoundingBox(EnumFacing facingDirectionIn)
{
}
public int getWidthPixels()
{
return 9;
}public int getHeightPixels()
{
return 9;
}public float getEyeHeight()
{
return -0.0625F;
}/**
- Checks if the entity is in range to render.
*/
@SideOnly(Side.CLIENT)
public boolean isInRangeToRenderDist(double distance)
{
return distance < 1024.0D;
}
/**
- Called when this entity is broken. Entity parameter may be null.
*/
public void onBroken(@Nullable Entity brokenEntity)
{
this.playSound(SoundEvents.ENTITY_LEASHKNOT_BREAK, 1.0F, 1.0F);
}
/**
- Either write this entity to the NBT tag given and return true, or return false without doing anything. If this
- returns false the entity is not saved on disk. Ridden entities return false here as they are saved with their
- rider.
*/
public boolean writeToNBTOptional(NBTTagCompound compound)
{
return false;
}
/**
- (abstract) Protected helper method to write subclass entity data to NBT.
*/
public void writeEntityToNBT(NBTTagCompound compound)
{
}
/**
- (abstract) Protected helper method to read subclass entity data from NBT.
*/
public void readEntityFromNBT(NBTTagCompound compound)
{
}
public boolean processInitialInteract(EntityPlayer player, @Nullable ItemStack stack, EnumHand hand)
{
if (this.worldObj.isRemote)
{
return true;
}
else
{
boolean flag = false;if (stack != null && stack.getItem() == CreateItems.Rope)
{
double d0 = 7.0D;for (EntityLiving entityliving : this.worldObj.getEntitiesWithinAABB(EntityLiving.class, new AxisAlignedBB(this.posX - d0, this.posY - d0, this.posZ - d0, this.posX + d0, this.posY + d0, this.posZ + d0)))
{
if (entityliving.getLeashed() && entityliving.getLeashedToEntity() == player)
{
entityliving.setLeashedToEntity(this, true);
flag = true;
}
}
}if (!flag)
{
this.setDead();if (player.capabilities.isCreativeMode)
{
double d1 = 7.0D;for (EntityLiving entityliving1 : this.worldObj.getEntitiesWithinAABB(EntityLiving.class, new AxisAlignedBB(this.posX - d1, this.posY - d1, this.posZ - d1, this.posX + d1, this.posY + d1, this.posZ + d1)))
{
if (entityliving1.getLeashed() && entityliving1.getLeashedToEntity() == this)
{
entityliving1.clearLeashed(true, false);
}
}
}
}return true;
}
}/**
- checks to make sure painting can be placed there
*/
public boolean onValidSurface()
{
return this.worldObj.getEntityByID(504) instanceof EntitySleigh;
}
public static EntityRopeKnot createKnot(World worldIn, Entity entity)
{
EntityRopeKnot entityleashknot = new EntityRopeKnot(worldIn, entity);
entityleashknot.forceSpawn = true;
worldIn.spawnEntityInWorld(entityleashknot);
entityleashknot.playPlaceSound();
return entityleashknot;
}public static EntityRopeKnot getKnotForPosition(World worldIn, Entity entity)
{
int i = (int)entity.posX;
int j = (int)entity.posY;
int k = (int)entity.posZ;for (EntityRopeKnot entityleashknot : worldIn.getEntitiesWithinAABB(EntityRopeKnot.class, new AxisAlignedBB((double)i - 1.0D, (double)j - 1.0D, (double)k - 1.0D, (double)i + 1.0D, (double)j + 1.0D, (double)k + 1.0D)))
{
if (entityleashknot.getEntityPosition().equals(entity))
{
return entityleashknot;
}
}return null;
}public void playPlaceSound()
{
this.playSound(SoundEvents.ENTITY_LEASHKNOT_PLACE, 1.0F, 1.0F);
}public Entity getEntityPosition()
{
return this.entityPosition;
}@Override
public NBTTagCompound writeToNBT(NBTTagCompound compound)
{
super.writeToNBT(compound);
NBTTagList nbttaglist = new NBTTagList();if(/Id du renne/ != null)
{
NBTTagCompound compound1 = new NBTTagCompound();
compound1.setInteger(“reindeerId”, /Id du renne/);
nbttaglist.appendTag(compound1);
}compound.setTag(“reindeersIds”, nbttaglist);
}
@Override
public void readFromNBT(NBTTagCompound compound)
{
super.readFromNBT(compound);
NBTTagList nbttaglist = compound.getTagList(“reindeersIds”, /que mettre ?/);/Id du renne/ = nbttaglist.getDoubleAt(/que mettre ?/);
}
}Mais j'en suis pas sûr que ça marchera
- Sets the x,y,z of the entity from the given parameters. Also seems to set up a bounding box.
-
Non, tu dois te servir de la méthode itemInteractionForEntity, de ta classe ItemRope. Non de ta classe EntityRope.
-
C’est déjà plus simple. Mais j’ai un problème (sans doute simple) : j’ai fait ça
@Override public boolean itemInteractionForEntity(ItemStack stack, EntityPlayer playerIn, EntityLivingBase target, EnumHand hand) { super.itemInteractionForEntity(stack, playerIn, target, hand); if(target instanceof EntityReindeer) { System.out.println("est une instance de reindeer"); //EntityReindeer reindeer = (EntityReindeer)target; return true; } else { System.out.println("n'est pas une instance de reindeer"); return true; } } ```Quand je click droit sur un mob autre qu'un renne, ça m'affiche le 2ème message (comme quoi c'est pas un renne) (normal). Mais quand je click droit sur un renne, rien du tout. C'est censé m'affiché le 1er message mais rien du tout.
-
Print target pour voir ce que te dis la console.
-
Quand je faisais clic droit sur un autre mob, ça me mettait toutes ses infos (nom de la classe, client ou server et sa position. Quand je faisait click droit sur le renne, toujours rien jusqu’à que je décide de mettre en commentaire la fonction processInteract de EntityReindeer. Maintenant, ça affiche bien mais pourquoi la fonction processInteract est en conflit avec ? Et pis faut pas que je l’enlève, j’en ai besoin
EDIT : j’ai trouvé. Ce n’est pas vraiement la fonction qui est en conflit, c’est quand je disais que quand je click droit avec la rope, ça l’accrochait. J’ai enlevé ça et ça marche bien. Du coup, autant mettre ça dans l’ItemRope
EDIT n°2 : Désolé mais j’ai encore des problèmes : j’ai fait ```java
@Override
public boolean itemInteractionForEntity(ItemStack stack, EntityPlayer playerIn, EntityLivingBase target, EnumHand hand)
{
super.itemInteractionForEntity(stack, playerIn, target, hand);
System.out.println(target);
if(target instanceof EntityReindeer)
{
System.out.println(“est une instance de reindeer”);
EntityReindeer reindeer = (EntityReindeer)target;
if (reindeer.canBeLeashedTo(playerIn))
{
reindeer.setLeashedToEntity(playerIn, true);
–stack.stackSize;
}int ReindeerId = reindeer.getEntityId();
System.out.println(ReindeerId);
return true;
}
else
{
System.out.println(“n’est pas une instance de reindeer”);
return true;
}
} -
Sinon oublie les id’s, tu n’enregistre qu’une seule valeur dans les NBT, le nombre de rennes attachés. Et lors de la liaison avec le traîneau, tu fais une boucle for, qui spawnera de nouveaux rennes et tueras ceux attachés à la corde. Les id’s ne sont peut-être pas indispensables.
Essaie avec l’event EntityInteractEvent, voir si ton traîneau est détecté. Sinon tu seras forcé de l’extends EntityLivingBase, et de nous montrer de + près la stacktrace. -
Salut
Désolé du temps de la réponse.
Je pense avoir trouvé une alternative aux id : les uuids. Ils restent tout le temps les mêmes.Dans mon ItemRope, j’ai fait : ```java
public void reindeerToNBT(ItemStack stack, EntityLivingBase target)
{
NBTTagList nbttaglist = this.getReindeer(stack);
boolean flag = true;for (int i = 0; i < nbttaglist.tagCount(); i++)
{
NBTTagCompound nbttagcompound = nbttaglist.getCompoundTagAt(i);if (nbttagcompound.getUniqueId(“uuid”) != target.getUniqueID())
{
nbttagcompound.setUniqueId(“uuid”, target.getUniqueID());
}flag = false;
break;
}if (flag)
{
NBTTagCompound nbttagcompound1 = new NBTTagCompound();
nbttagcompound1.setUniqueId(“uuid”, target.getUniqueID());
nbttaglist.appendTag(nbttagcompound1);
}if (!stack.hasTagCompound())
{
stack.setTagCompound(new NBTTagCompound());
}stack.getTagCompound().setTag(“Reindeers”, nbttaglist);
}public NBTTagList getReindeer(ItemStack stack)
{
NBTTagCompound nbttagcompound = stack.getTagCompound();
return nbttagcompound != null && nbttagcompound.hasKey(“Reindeers”, 9) ? (NBTTagList)nbttagcompound.getTag(“Reindeers”) : new NBTTagList();
}
et j'appelle la première fonction grâce à
java
@Override
public boolean itemInteractionForEntity(ItemStack stack, EntityPlayer playerIn, EntityLivingBase target, EnumHand hand)
{
super.itemInteractionForEntity(stack, playerIn, target, hand);
System.out.println(target);
if(target instanceof EntityReindeer)
{
System.out.println(“est une instance de reindeer”);
EntityReindeer reindeer = (EntityReindeer)target;
if (reindeer.canBeLeashedTo(playerIn))
{
reindeer.setLeashedToEntity(playerIn, true);
–stack.stackSize;
this.reindeerToNBT(stack, target);
}UUID ReindeerId = reindeer.getUniqueID();
System.out.println(ReindeerId);
return true;
}
else
{
System.out.println(“n’est pas une instance de reindeer”);
return true;
}
}Dans mon CommonEventHandler, j'ai fait :```java @SubscribeEvent public void test(EntityInteract event) { Entity target = event.getTarget(); EntityPlayer player = event.getEntityPlayer(); if(player instanceof EntityPlayer) { if(target instanceof EntitySleigh) { EntitySleigh sleigh = (EntitySleigh)event.getTarget(); Item item = event.getItemStack().getItem(); if(item instanceof ItemRope) { ItemRope rope = (ItemRope)event.getItemStack().getItem(); /*appelle d'une fonction qui return des reindeers (ou leurs UUIDs)*/ for(int i=/*nombre de reindeer dans le nbt de l'itemrope*/; /*je sais pas quoi mettre*/; i--) { /*reindeer récupéré*/.setDead; EntityReindeer reindeer = new EntityReindeer(event.getWorld()); event.getWorld().spawnEntityInWorld(reindeer); reindeer.setLeashedToEntity(sleigh, true); } } } } } ``` J'ai préparé la fonction, mais il manque certaines choses. Par contre, j'ai un problème et un petit warning dans le code : le problème c'est que quand j'attache des rennes à ma corde, ça accroche bien mais ne me suivent plus, ils ne bougent pas (j'ai testé avant de modifié le code). Le warning c'est dans le for de la fonction reindeerToNbt, à l'incrémentation de i. Ca me dit que c'est un code mort (dead code). Qu'est ce que ça veut dire ? Merci d'avance
-
Normalement du code mort c’est qu’il ne pourra jamais être atteint, de quelque façon qu’il soit
-
Ici, le problème, c’est que ta boucle est exécutée qu’une seul fois à cause du “break”. Je pence que le break et le “flag = false” devraient aller dans la condition, après “nbttagcompound.setUniqueId(…)”
-
Merci, ça marche mieux (enfin …, ce que je veux dire par là, c’est que y’a plus le warning). Mais je sais toujours pas comment appelé ces fonctions et surtout si c’est juste.
Merci d’avance
EDIT : Je pense avoir trouvé. J’ai modifié l’ItemRope pour ajouté une liste de type UUID qui s’enregistre dans le nbt. Du coup, dans le nbt, j’aurais 2 tags : un de type UUID et un de type int (qui récupère la taille de la liste UUID). J’ai également fait deux nouvelles fonctions qui return l’uuid et le nombre de renne (la taille de la liste) (tout les deux regardant dans les nbt). Et dans l’event EntityInteract, j’ai aussi un peu modifié : j’ai ajouté un petit while qui tant que le nombre de renne n’est pas à 0 récupère l’uuid, tue le renne et en fait spawn un autre qui est directement attaché au traîneau. Mais il me manque un bout de code.
Voilà ce que j’ai fait (comme je l’ai dit je n’explique pas très bien, aussi vous comprendrez mieux) :
dans l’itemRopeArrayList <uuid>nmbReindeer = new ArrayList<uuid>(); @Override public boolean itemInteractionForEntity(ItemStack stack, EntityPlayer playerIn, EntityLivingBase target, EnumHand hand) { super.itemInteractionForEntity(stack, playerIn, target, hand); System.out.println(target); if(target instanceof EntityReindeer) { System.out.println("est une instance de reindeer"); EntityReindeer reindeer = (EntityReindeer)target; if (reindeer.canBeLeashedTo(playerIn)) { reindeer.setLeashedToEntity(playerIn, true); --stack.stackSize; this.reindeerToNBT(stack, target); nmbReindeer.add(reindeer.getUniqueID()); } return true; } else { System.out.println("n'est pas une instance de reindeer"); return true; } } public void reindeerToNBT(ItemStack stack, EntityLivingBase target) { NBTTagList nbttaglist = this.getReindeer(stack); boolean flag = true; for (int i = 0; i < nbttaglist.tagCount(); i++) { NBTTagCompound nbttagcompound = nbttaglist.getCompoundTagAt(i); if (nbttagcompound.getUniqueId("uuidReindeer") != target.getUniqueID()) { nbttagcompound.setUniqueId("uuidReindeer", target.getUniqueID()); flag = false; break; } if(nbttagcompound.getInteger("nmbReindeer") != nmbReindeer.size()) { nbttagcompound.setInteger("nmbReindeer", nmbReindeer.size()); } } if (flag) { NBTTagCompound nbttagcompound1 = new NBTTagCompound(); nbttagcompound1.setUniqueId("uuidReindeer", target.getUniqueID()); nbttaglist.appendTag(nbttagcompound1); NBTTagCompound nbttagcompound2 = new NBTTagCompound(); nbttagcompound1.setInteger("nmbReindeer", nmbReindeer.size()); nbttaglist.appendTag(nbttagcompound2); } if (!stack.hasTagCompound()) { stack.setTagCompound(new NBTTagCompound()); } stack.getTagCompound().setTag("Reindeers", nbttaglist); } public NBTTagList getReindeer(ItemStack stack) { NBTTagCompound nbttagcompound = stack.getTagCompound(); return nbttagcompound != null && nbttagcompound.hasKey("Reindeers", 9) ? (NBTTagList)nbttagcompound.getTag("Reindeers") : new NBTTagList(); } public int getNmbReindeer(ItemStack stack) { NBTTagCompound nbttagcompound = stack.getTagCompound(); if(nbttagcompound != null && nbttagcompound.hasKey("nmbReindeer")) { int nmbReindeer = nbttagcompound.getInteger("nmbReindeer"); return nmbReindeer; } else { return 0; } } public UUID getUUIDReindeer(ItemStack stack) { NBTTagCompound nbttagcompound = stack.getTagCompound(); if(nbttagcompound != null && nbttagcompound.hasKey("uuidReindeer")) { UUID uuidReindeer = nbttagcompound.getUniqueId("uuidReindeer"); return uuidReindeer; } else { return (UUID)null; } }
Et dans l’event EntityInteract
@SubscribeEvent public void test(EntityInteract event) { Entity target = event.getTarget(); EntityPlayer player = event.getEntityPlayer(); if(player instanceof EntityPlayer) { if(target instanceof EntitySleigh) { EntitySleigh sleigh = (EntitySleigh)event.getTarget(); Item item = event.getItemStack().getItem(); if(item instanceof ItemRope) { ItemRope rope = (ItemRope)event.getItemStack().getItem(); int nmbReindeer = rope.getNmbReindeer(event.getItemStack()); while (nmbReindeer > 0) { UUID uuid = rope.getUUIDReindeer(event.getItemStack()); /*reindeer récupéré*/.setDead; EntityReindeer reindeer = new EntityReindeer(event.getWorld()); event.getWorld().spawnEntityInWorld(reindeer); reindeer.setLeashedToEntity(sleigh, true); nmbReindeer--; } } } } }
Voilà, je sais pas du tout si ça va marcher (en tout cas je pense que ça marchera déjà mieux que ce que j’avais proposé avant), et même si ça marche je sais pas du tout ce que ça va donner.
Si vous pouvez (encore) m’aidez, merci d’avance
Merci d’avance</uuid></uuid>
-
Je pence que tu pourrais faire comme quand on attache un mob à une barrière :
double d0 = 7.0D; for (EntityReindeer entityliving : worldIn.getEntitiesWithinAABB(EntityReindeer.class, new AxisAlignedBB((double)player.posX - d0, (double)player.posY - d0, (double)player.posZ - d0, (double)player.posX + d0, (double)player.posY + d0, (double)player.posZ + d0))) { if (entityliving.getLeashed() && entityliving.getLeashedToEntity() == player) { entityliving.setLeashedToEntity(sleigh, true); } }
-
Justement. Je voulais faire ça mais il fallait détecté le click droit du joueur, si il clickait droit sur le traîneau. Et à partir de ça, on est arrivé à l’event EntityInteract
EDIT : Salut. Au pire, si nous n’avons pas de solution, je peux faire un autre truc qui sera surement plus simple : je créer un item qui, quand on click droit avec sur un renne, ça le supprime du monde et j’obtient un nouveau item. Et quand je fais click droit sur le traîneau avec cet item, ça fait spawn un nouveau renne (si possible avec les mêmes tags que l’autre) directement accroché au traîneau. C’est surement plus simple. Après, bien sûr je continuerai quand même de chercher comment faire, mais c’est une alternative.