L'event drop


  • Administrateurs

    Vous savez que le but de forge est d'assurer une compatibilité maximum, et donc en conséquence, il ne faut pas modifier les classes de minecraft. Peut-être que vous avez déjà voulu changé le drop d'un mob vanille ou même d'effectuer des actions lors du drop d'un mob ? Dans ce tutoriel, nous allons voir comment interagir avec les drop de n'importe quel mob sans modifier sa classe.

    Dans la classe principale

    Dans la méthode Init, ajoutez le code pour enregistrer un event bus :

    MinecraftForge.EVENT_BUS.register(new LivingEvent());
    

    Je vais mettre dans la classe LivingEvent tout les events qui sont liés aux entités vivante, vous pouvez aussi créer une classe par event, à chaqu'un sa façon de s'organiser 🙂

    La classe de l'event

    package tutoriel.common;
    
    import net.minecraftforge.event.ForgeSubscribe;
    import net.minecraftforge.event.entity.living.LivingDropsEvent;
    
    public class LivingEvent
    {
       @ForgeSubscribe
       public void onLivingDrops(LivingDropsEvent event)
       {
    
       }
    }
    

    Comme d'habitude, une méthode avec l'annotation @ForgeSubscriber. D'ailleurs, sachez que cette annotation supporte les priorités :

       @ForgeSubscribe(priority = EventPriority.NORMAL)
    

    dans l'ordre du premier au dernier éxecuté : HIGHEST, HIGH, NORMAL, LOW et pour finir LOWEST, par défaut NORMAL est utilisé.

    Un petit tour des variables qui se trouve dans LivingDropsEvent que nous pouvons utiliser :

    • event.source : le type de dégât qui à causé la mort de l'entité.
    • event.drops : une ArrayList du type EntityItem de tout les drops.
    • event.lootingLevel : Le niveau de l'enchantement looting si l'entité à été tué par un joueur qui avait une épée looting
    • event.recentlyHit : si le mob a été attaqué récemment ou pas

    Avec ces 5 paramètres on peut faire pas mal de chose, à vous de voir ce que vous souhaitez faire.

    Quelques exemples

    Rassurez-vous, je vais pas vous laisser avec juste ça, voici quelque exemple avec les explications :
    Supprimer des drop d'un mob :

           if(event.entity instanceof EntitySkeleton)
           {
               EntitySkeleton skeleton = (EntitySkeleton)event.entity;
               if(skeleton.getSkeletonType() == 0)
               {
                    for(int i = 0; i < event.drops.size(); i ++)
                    {
                           if(event.drops.get(i).getEntityItem().itemID != Item.bone.itemID || event.drops.get(i).getEntityItem().itemID != Item.arrow.itemID)
                           {
                                  event.drops.remove(i);
                           }
                    }
               }
           }
    

    Je commence par vérifier si l'entité est un squelette. Ensuite, j'instancie l'EntitySkeleton et je vérifie que c'est un squelette normal, (les "wither skeleton" sont du type 1).
    Et pour finir, je vérifie si l'id de l'item que contient l'itemStack contenue par l'entityItem et une flèche ou un os, et si c'est ni un os ni une flèche, je supprime le drop. La boucle for sert à vérifier sur toute la taille de l'ArrayList.
    Donc avec ce code je supprime tout les drop rare (armure, arc, etc …)

           if(event.entity instanceof EntityPig)
           {
                  for(int i = 0; i < event.drops.size(); i ++)
                  {
                         if(event.drops.get(i).getEntityItem().itemID == Item.porkCooked.itemID && event.source.getDamageType().equals("anvil"))
                         {
                                event.entity.worldObj.newExplosion(event.entity, event.entity.posX, event.entity.posY, event.entity.posZ, 5, true, true);
                         }
                  }
           }
    

    Si le cochon drop des côtelettes cuite (ce qui est le cas lorsqu'il est en feu) et que la cause de la mort est une enclume qui lui est tombé sur la tête (probabilité vraiment très faible sauf si c'est voulu), il va y avoir une explosion.

    Un dernier exemple :

           if(event.entity instanceof EntitySkeleton)
           {
                  EntitySkeleton skeleton = (EntitySkeleton)event.entity;
                  if(skeleton.getSkeletonType() == 1)
                  {
                         for(int i = 0; i < event.drops.size(); i ++)
                         {
                                if(event.drops.get(i).getEntityItem().itemID == Item.skull.itemID && event.lootingLevel == 2)
                                {
                                    event.entity.worldObj.newExplosion(event.entity, event.entity.posX, event.entity.posY, event.entity.posZ, 15, true, true);
                               }
                        }
                 }
           }
    

    robin4002 was blown up by Skeleton
    mince, j'ai encore utilisé mon épée 2 pour farmer des wither skeleton

    Pour ajouter un nouveau drop :

    EntityItem newdrop = new EntityItem(event.entity.worldObj, event.entity.posX, event.entity.posY, event.entity.posZ,
    new ItemStack(item ou bloc, quantité, metadata));
    event.drops.add(newdrop)
    

    Si certains codes doivent être détaillés, n'hésitez pas à demander des explications supplémentaire.

    Rendu final sur github



  • Salut,

    Est-ce qu'il est possible que le drop soit un nombre aléatoire entre 0 et 3 par exemple?

    J'ai vu cette méthode dans le cochon :

    protected void dropFewItems(boolean par1, int par2)
    {
    int j = this.rand.nextInt(3) + 1 + this.rand.nextInt(1 + par2);
    
    for (int k = 0; k < j; ++k)
    {
    if (this.isBurning())
    {
    this.dropItem(Item.porkCooked.itemID, 1);
    }
    else
    {
    this.dropItem(Item.porkRaw.itemID, 1);
    }
    }
    
    if (this.getSaddled())
    {
    this.dropItem(Item.saddle.itemID, 1);
    }
    }
    

    Mais je ne sais pas comment l'utiliser avec forge :s

    Merci d'avance 🙂


  • Administrateurs

    C'est possible, tout simplement, les lignes où il y a "dropItem", au bout tu as le chiffre 1, tu le remplace par : rand.nextInt(3) et puis voilà (bien sur, faut virer la boucle for 😉 )



  • J'ai essayé mais ça me dit que " void is an invalid type for the variable dropFewItems " et rand me dit comme erreur " rand cannot be resolved or is not a field ".

    Voici ma classe sans le drop aléatoire :

    package nyvelia.common;
    
    import net.minecraft.entity.item.EntityItem;
    import net.minecraft.entity.passive.EntityWolf;
    import net.minecraft.item.Item;
    import net.minecraft.item.ItemStack;
    import net.minecraftforge.event.ForgeSubscribe;
    import net.minecraftforge.event.entity.living.LivingDropsEvent;
    
    public class LivingEvent
    {
    @ForgeSubscribe
    public void onLivingDrops(LivingDropsEvent event)
    {
    if(event.entity instanceof EntityWolf)
    {
    EntityItem newdrop = new EntityItem(event.entity.worldObj, event.entity.posX, event.entity.posY, event.entity.posZ,
    new ItemStack(Nyvelia.Tissu, 1));
    event.drops.add(newdrop);
    }
    }
    }
    

    Je sais pas trop où l'ajouter en faite :s


  • Administrateurs

    "new ItemStack(Nyvelia.Tissu, 1));" remplace le 1 par rand.nextInt(3) alors 🙂



  • " rand cannot be resolved " T_T


  • Administrateurs

    Mh… envoie ta class !



  • Je l'ai envoyé juste au-dessus ^^ j'ai juste changé " new ItemStack(Nyvelia.Tissu, 1)); " en " new ItemStack(Nyvelia.Tissu, rand.nextInt(3))); ".


  • Administrateurs

    
    package nyvelia.common;
    
    import net.minecraft.entity.item.EntityItem;
    import net.minecraft.entity.passive.EntityWolf;
    import net.minecraft.item.Item;
    import net.minecraft.item.ItemStack;
    import net.minecraftforge.event.ForgeSubscribe;
    import net.minecraftforge.event.entity.living.LivingDropsEvent;
    
    public class LivingEvent
    {
    public final Random rand = new Random();
    @ForgeSubscribe
    public void onLivingDrops(LivingDropsEvent event)
    {
    if(event.entity instanceof EntityWolf)
    {
    EntityItem newdrop = new EntityItem(event.entity.worldObj, event.entity.posX, event.entity.posY, event.entity.posZ,
    new ItemStack(Nyvelia.Tissu, rand.nextInt(3)));
    event.drops.add(newdrop);
    }
    }
    }
    
    

    Voili voilou 🙂



  • Merci ça marche impec 🙂



  • Salut petit probleme mon eclipse me propose de créer l'anotation forgesubscribe je doit le faire?

    merci de votre réponse



  • Remplace par @SubscribeEvent



  • @'Portuar':

    Remplace par @SubscribeEvent

    merci bien cela marche mais pourquoi je doit utiliser SubscribeEvent?


  • Administrateurs

    Car ForgeSubscribe a été remplacé par SubscribeEvent en 1.7