MFF

    Minecraft Forge France
    • Récent
    • Mots-clés
    • Populaire
    • Utilisateurs
    • Groupes
    • Forge Events
      • Automatique
      • Foncé
      • Clair
    • S'inscrire
    • Se connecter

    Équiper une Entité custom (armure + objets dans les mains) aux travers d'une GUI

    Planifier Épinglé Verrouillé Déplacé Résolu 1.9.x et 1.10.x
    1.10.x
    4 Messages 2 Publieurs 1.2k Vues 1 Watching
    Charger plus de messages
    • Du plus ancien au plus récent
    • Du plus récent au plus ancien
    • Les plus votés
    Répondre
    • Répondre à l'aide d'un nouveau sujet
    Se connecter pour répondre
    Ce sujet a été supprimé. Seuls les utilisateurs avec les droits d'administration peuvent le voir.
    • MajorSquirrelM Hors-ligne
      MajorSquirrel
      dernière édition par

      Hello !

      Je fais suivre mon topic sur le forum anglophone, celui-ci semble ne pas soulever d’idées pour le moment. 😄

      J’ai créé une GUI qui me permet de changer l’équipement de mon entité custom (un NPC), mais visiblement ça ne fonctionne pas très bien (du tout).

      ContainerNPCInventory:

      
      public class                ContainerNPCInventory extends Container {
      
         private static final EntityEquipmentSlot[]  VALID_EQUIPMENT_SLOTS = new EntityEquipmentSlot[] {
                 EntityEquipmentSlot.HEAD,
                 EntityEquipmentSlot.CHEST,
                 EntityEquipmentSlot.LEGS,
                 EntityEquipmentSlot.FEET
         };
      
         private final EntityNPCDialog   entityNPC;
         private Iterable <itemstack>inventoryArmor;
         private Iterable <itemstack>heldEquipment;
      
         private final InventoryPlayer   playerInventory;
         private InventoryBasic          entityInventory;
      
         public                  ContainerNPCInventory(EntityPlayer playerIn, EntityNPCDialog entityNPC) {
             this.entityNPC = entityNPC;
             this.inventoryArmor = entityNPC.getArmorInventoryList();
             this.heldEquipment = entityNPC.getHeldEquipment();
      
             this.playerInventory = playerIn.inventory;
             this.entityInventory = new InventoryBasic("NPC Inventory", true,
                     Iterables.size(this.inventoryArmor) + Iterables.size(this.heldEquipment));
             this.entityInventory.addInventoryChangeListener(entityNPC);
      
             for (int index = 0; index < 4; ++index) {
                 final EntityEquipmentSlot   equipmentSlot = ContainerNPCInventory.VALID_EQUIPMENT_SLOTS[index];
      
                 this.addSlotToContainer(new Slot(this.entityInventory, index, 8, 8 + index * 18) {
      
                     @Override
                     public boolean  isItemValid(@Nullable ItemStack stack) {
                         return (stack != null && stack.getItem().isValidArmor(stack, equipmentSlot, entityNPC));
                     }
      
                     @Override
                     public int      getSlotStackLimit() {
                         return (1);
                     }
      
                     @Nullable
                     @Override
                     public String   getSlotTexture() {
                         return (ItemArmor.EMPTY_SLOT_NAMES[equipmentSlot.getIndex()]);
                     }
                 });
             }
      
             this.addSlotToContainer(new Slot(this.entityInventory, 4, 77, 8));
      
             this.addSlotToContainer(new Slot(this.entityInventory, 5, 95, 8) {
      
                 @Nullable
                 @Override
                 public String   getSlotTexture() {
                     return ("minecraft:items/empty_armor_slot_shield");
                 }
             });
      
             for (int index = 0; index < 9; ++index) {
                 this.addSlotToContainer(new Slot(this.playerInventory, index, 9 + index * 18, 112));
             }
         }
      
         @Override
         public boolean          canInteractWith(EntityPlayer playerIn) {
             return (true);
         }
      }
      
      

      EntityNPCDialog:

      
      public class                EntityNPCDialog extends EntityLiving implements IInventoryChangedListener {
      
      //    private static final DataParameter <integer>TEXTURE_INDEX = EntityDataManager.<integer>createKey(EntityNPCDialog.class, DataSerializers.VARINT);
      
         public                  EntityNPCDialog(World worldIn) {
             super(worldIn);
         }
      
         @Override
         protected void          initEntityAI() {
             super.initEntityAI();
      
             this.tasks.addTask(0, new EntityAISwimming(this));
             this.tasks.addTask(1, new EntityAIWatchClosest(this, EntityPlayer.class, 16.0F, 42.0F));
             this.tasks.addTask(2, new EntityAILookIdle(this));
         }
      
         @Override
         public boolean          canBePushed() {
             return (false);
         }
      
         @Override
         public boolean          isPushedByWater() {
             return (false);
         }
      
         @Override
         protected boolean       canDespawn() {
             return(false);
         }
      
         @Override
         public void             addVelocity(double x, double y, double z) {}
      
         @Override
         public boolean          canRiderInteract() {
             return (false);
         }
      
         @Override
         public boolean          isEntityInvulnerable(DamageSource source) {
             return (false);
         }
      
         @Override
         public boolean          isPotionApplicable(PotionEffect potioneffectIn) {
             return (false);
         }
      
         @Override
         public boolean          isImmuneToExplosions() {
             return (false);
         }
      
         @Nullable
         @Override
         protected SoundEvent    getAmbientSound() {
             return (CraftAndConquerSounds.NPCDialogSoundEvent);
         }
      
         @Nullable
         @Override
         protected SoundEvent    getHurtSound() {
             return (CraftAndConquerSounds.NPCDialogSoundEvent);
         }
      
         @Nullable
         @Override
         protected SoundEvent    getDeathSound() {
             return (CraftAndConquerSounds.NPCDialogSoundEvent);
         }
      
         @Override
         protected SoundEvent    getFallSound(int heightIn) {
             return (CraftAndConquerSounds.NPCDialogSoundEvent);
         }
      
         @Override
         protected SoundEvent    getSwimSound() {
             return (CraftAndConquerSounds.NPCDialogSoundEvent);
         }
      
         @Override
         protected SoundEvent    getSplashSound() {
             return (CraftAndConquerSounds.NPCDialogSoundEvent);
         }
      
         public static ThreadDownloadImageData   getDownloadImageSkin(ResourceLocation resourceLocationIn) {
             TextureManager          textureManager = Minecraft.getMinecraft().getTextureManager();
             ThreadDownloadImageData threadDownloadImageData;
      
             threadDownloadImageData = new ThreadDownloadImageData(null, "http://imgur.com/Z0pbA3P.png", DefaultNPCSkin.getDefaultSkin(), new ImageBufferDownload() {
      
                 @Override
                 public BufferedImage    parseUserSkin(BufferedImage image) {
                     return (image);
                 }
      
             });
      
             textureManager.loadTexture(resourceLocationIn, threadDownloadImageData);
      
             return (threadDownloadImageData);
         }
      
         private void            updateNPCSlots(InventoryBasic inventoryBasic) {
             if (!this.worldObj.isRemote) {
                 this.setItemStackToSlot(EntityEquipmentSlot.HEAD, inventoryBasic.getStackInSlot(0));
                 this.setItemStackToSlot(EntityEquipmentSlot.CHEST, inventoryBasic.getStackInSlot(1));
                 this.setItemStackToSlot(EntityEquipmentSlot.LEGS, inventoryBasic.getStackInSlot(2));
                 this.setItemStackToSlot(EntityEquipmentSlot.FEET, inventoryBasic.getStackInSlot(3));
                 this.setItemStackToSlot(EntityEquipmentSlot.MAINHAND, inventoryBasic.getStackInSlot(4));
                 this.setItemStackToSlot(EntityEquipmentSlot.OFFHAND, inventoryBasic.getStackInSlot(5));
             }
         }
      
         @Override
         public void             onInventoryChanged(InventoryBasic inventoryBasic) {
             this.updateNPCSlots(inventoryBasic);
         }
      }
      
      

      Pour faire tout cela, je me suis inspiré de GuiContainerCreative qui est la GUI du joueur quand il est en creative mode, de ContainerHorseInventory qui est le container pour les chevaux et d’EntityZombie. Ce que je souhaite faire aux travers de mon code, c’est dès que je place un équipement dans le slot associé de la GUI, ça équipe mon NPC de cet équipement en question. Et évidemment, dès que je le retire, ça enlève l’équipement en question.

      Les ItemStack[] des équipements sont inventoryHands et inventoryArmor dans EntityLiving. Évidemment, on ne peut pas y accéder directement puisque ces variables sont private. Pour cela, il y a la méthode EntityLiving#setItemStackToSlot(EntityEquipmentSlot slotIn, @Nullable ItemStack stack) qui met l’item au bon endroit (soit dans les mains, soit dans l’armure). Mais même en appelant cette méthode dans mon code ça ne fonctionne pas.

      Je ne sais pas trop quoi faire, j’ai essayé bien des choses comme override la méthode Slot#onSlotChanged(), faire que mon Entity implémente IInventoryChangedListener, mais je n’ai toujours pas le résultat attendu. Les items rentrent bien dans les slots, certes, mais dès que je quitte la GUI et que je reviens dessus, les items disparaissent (je n’ai pas besoin de write ou read les NBTTags, EntityLiving le fait déjà à ma place). Quand je place l’item dans le slot, il ne se passe rien, l’entité n’équipe même pas l’équipement en question (test visible puisque si je mets un casque sur l’entité, on le voit sur sa tête, hors là ça ne marche pas). J’ai essayé une approche beaucoup plus simpliste qui est que, quand je clique droit sur mon entité avec un objet, il l’équipe. Et devinez quoi, ça marche.

      NPCInteractEvent:

      
         @SubscribeEvent
         public void     onEntityNPCInteract(PlayerInteractEvent.EntityInteract event) {
             ItemStack   heldItem = event.getEntityPlayer().getHeldItem(EnumHand.MAIN_HAND);
             ItemBase    npcManager = CraftAndConquerItems.npcManager;
      
             if (event.getTarget() instanceof EntityNPCDialog && event.getHand().equals(EnumHand.MAIN_HAND) && heldItem != null) {
                 if (!event.getWorld().isRemote) {
                     if (heldItem.getItem().equals(npcManager))
                         event.getEntityPlayer().openGui(CraftAndConquer.instance, GuiHandler.CAC_NPC_GUI, event.getWorld(), event.getTarget().getEntityId(), 0, 0);
                     else if (heldItem.getItem().equals(Items.DIAMOND_HELMET))
                         event.getTarget().setItemStackToSlot(EntityEquipmentSlot.HEAD, heldItem);
                     else if (heldItem.getItem().equals(Items.DIAMOND_CHESTPLATE))
                         event.getTarget().setItemStackToSlot(EntityEquipmentSlot.CHEST, heldItem);
                     else if (heldItem.getItem().equals(Items.DIAMOND_LEGGINGS))
                         event.getTarget().setItemStackToSlot(EntityEquipmentSlot.LEGS, heldItem);
                     else if (heldItem.getItem().equals(Items.DIAMOND_BOOTS))
                         event.getTarget().setItemStackToSlot(EntityEquipmentSlot.FEET, heldItem);
                     else if (heldItem.getItem().equals(Items.DIAMOND_SWORD))
                         event.getTarget().setItemStackToSlot(EntityEquipmentSlot.MAINHAND, heldItem);
                     else if (heldItem.getItem().equals(Items.SHIELD))
                         event.getTarget().setItemStackToSlot(EntityEquipmentSlot.OFFHAND, heldItem);
                 }
             }
         }
      
      

      Le code ci-dessus fonctionne. Les items sont bien sauvegardés dans l’entité, et quand je déco-reco ils restent bien là, mais impossible de faire ça en passant par une GUI.

      Avez-vous une petite idée ?  :'(</integer></integer></itemstack></itemstack>

      1 réponse Dernière réponse Répondre Citer 0
      • AymericRedA Hors-ligne
        AymericRed
        dernière édition par

        Bizarre…mets deux prints dans la fonction updateNPCSlots, un avant et un après le if(), et regarde si ça serait pas la fonction qui est appelé que côté client, si oui, montres comment tu ouvres ton gui.

        Si je vous ai aidé, n'oubliez pas d’être heureux, j'aiderai encore +

        AymericRed, moddeur expérimenté qui aide sur ce forum et qui peut accepter de faire un mod Forge rémunéré de temps en temps.

        Mes tutos : Table de craft, plugin NEI, plugin JEI, modifier l'overlay
        Je suis un membre apprécié et joueur, j'ai déjà obtenu 6 points de réputation.

        1 réponse Dernière réponse Répondre Citer 0
        • MajorSquirrelM Hors-ligne
          MajorSquirrel
          dernière édition par

          @‘AymericRed’:

          Bizarre…mets deux prints dans la fonction updateNPCSlots, un avant et un après le if(), et regarde si ça serait pas la fonction qui est appelé que côté client, si oui, montres comment tu ouvres ton gui.

          Alors, j’ai mis un message log avant, pendant, et après. Voici les logs au moment où la GUI s’ouvre :

          
          [17:55:14] [Client thread/INFO] [craftandconquer]: [BEFORE] This message is called BEFORE the if condition !
          [17:55:14] [Client thread/INFO] [craftandconquer]: [AFTER] This message is called AFTER the if condition !
          [17:55:14] [Client thread/INFO] [craftandconquer]: [BEFORE] This message is called BEFORE the if condition !
          [17:55:14] [Client thread/INFO] [craftandconquer]: [AFTER] This message is called AFTER the if condition !
          [17:55:14] [Client thread/INFO] [craftandconquer]: [BEFORE] This message is called BEFORE the if condition !
          [17:55:14] [Client thread/INFO] [craftandconquer]: [AFTER] This message is called AFTER the if condition !
          [17:55:14] [Client thread/INFO] [craftandconquer]: [BEFORE] This message is called BEFORE the if condition !
          [17:55:14] [Client thread/INFO] [craftandconquer]: [AFTER] This message is called AFTER the if condition !
          [17:55:14] [Client thread/INFO] [craftandconquer]: [BEFORE] This message is called BEFORE the if condition !
          [17:55:14] [Client thread/INFO] [craftandconquer]: [AFTER] This message is called AFTER the if condition !
          [17:55:14] [Client thread/INFO] [craftandconquer]: [BEFORE] This message is called BEFORE the if condition !
          [17:55:14] [Client thread/INFO] [craftandconquer]: [AFTER] This message is called AFTER the if condition !
          [17:55:14] [Client thread/INFO] [craftandconquer]: [BEFORE] This message is called BEFORE the if condition !
          [17:55:14] [Client thread/INFO] [craftandconquer]: [AFTER] This message is called AFTER the if condition !
          [17:55:14] [Client thread/INFO] [craftandconquer]: [BEFORE] This message is called BEFORE the if condition !
          [17:55:14] [Client thread/INFO] [craftandconquer]: [AFTER] This message is called AFTER the if condition !
          [17:55:14] [Client thread/INFO] [craftandconquer]: [BEFORE] This message is called BEFORE the if condition !
          [17:55:14] [Client thread/INFO] [craftandconquer]: [AFTER] This message is called AFTER the if condition !
          [17:55:14] [Client thread/INFO] [craftandconquer]: [BEFORE] This message is called BEFORE the if condition !
          [17:55:14] [Client thread/INFO] [craftandconquer]: [AFTER] This message is called AFTER the if condition !
          [17:55:14] [Client thread/INFO] [craftandconquer]: [BEFORE] This message is called BEFORE the if condition !
          [17:55:14] [Client thread/INFO] [craftandconquer]: [AFTER] This message is called AFTER the if condition !
          [17:55:14] [Client thread/INFO] [craftandconquer]: [BEFORE] This message is called BEFORE the if condition !
          [17:55:14] [Client thread/INFO] [craftandconquer]: [AFTER] This message is called AFTER the if condition !
          
          

          Et voici les logs au moment où je mets l’item dans un slot:

          
          [17:53:40] [Client thread/INFO] [craftandconquer]: [BEFORE] This message is called BEFORE the if condition !
          [17:53:40] [Client thread/INFO] [craftandconquer]: [AFTER] This message is called AFTER the if condition !
          [17:53:40] [Client thread/INFO] [craftandconquer]: [BEFORE] This message is called BEFORE the if condition !
          [17:53:40] [Client thread/INFO] [craftandconquer]: [AFTER] This message is called AFTER the if condition !
          [17:53:40] [Client thread/INFO] [craftandconquer]: [BEFORE] This message is called BEFORE the if condition !
          [17:53:40] [Client thread/INFO] [craftandconquer]: [AFTER] This message is called AFTER the if condition !
          [17:53:40] [Server thread/INFO] [craftandconquer]: [BEFORE] This message is called BEFORE the if condition !
          [17:53:40] [Server thread/INFO] [craftandconquer]: [DURING] This message is called DURING the if condition !
          [17:53:40] [Server thread/INFO] [craftandconquer]: [AFTER] This message is called AFTER the if condition !
          [17:53:40] [Server thread/INFO] [craftandconquer]: [BEFORE] This message is called BEFORE the if condition !
          [17:53:40] [Server thread/INFO] [craftandconquer]: [DURING] This message is called DURING the if condition !
          [17:53:40] [Server thread/INFO] [craftandconquer]: [AFTER] This message is called AFTER the if condition !
          [17:53:40] [Server thread/INFO] [craftandconquer]: [BEFORE] This message is called BEFORE the if condition !
          [17:53:40] [Server thread/INFO] [craftandconquer]: [DURING] This message is called DURING the if condition !
          [17:53:40] [Server thread/INFO] [craftandconquer]: [AFTER] This message is called AFTER the if condition !
          
          

          Je ne sais pas trop comment interpréter le résultat.

          1 réponse Dernière réponse Répondre Citer 0
          • MajorSquirrelM Hors-ligne
            MajorSquirrel
            dernière édition par

            Bonsoir !

            J’ai résolu mon problème. 🙂 Et je ne sais pas trop comment …

            Après avoir fait plusieurs tests, il s’avère que je n’utilise plus d’Iterable<itemstack> mais j’appelle directement les méthodes EntityLiving#getItemStackFromSlot et EntityLiving#setItemStackFromSlot pour mettre à jour correctement l’InventoryBasic et mon Entity (pour faire la passerelle correctement entre les deux quoi).

            Voici le code qui fonctionne, si jamais quelqu’un passe après moi.

            EntityNPCDialog:

            
            public class                EntityNPCDialog extends EntityLiving {
            
            //    private static final DataParameter <integer>TEXTURE_INDEX = EntityDataManager.<integer>createKey(EntityNPCDialog.class, DataSerializers.VARINT);
            
               public                  EntityNPCDialog(World worldIn) {
                   super(worldIn);
               }
            
               @Override
               protected void          initEntityAI() {
                   super.initEntityAI();
            
                   this.tasks.addTask(0, new EntityAISwimming(this));
                   this.tasks.addTask(1, new EntityAIWatchClosest(this, EntityPlayer.class, 16.0F, 42.0F));
                   this.tasks.addTask(2, new EntityAILookIdle(this));
               }
            
               @Override
               public boolean          canBePushed() {
                   return (false);
               }
            
               @Override
               public boolean          isPushedByWater() {
                   return (false);
               }
            
               @Override
               protected boolean       canDespawn() {
                   return(false);
               }
            
               @Override
               public void             addVelocity(double x, double y, double z) {}
            
               @Override
               public boolean          canRiderInteract() {
                   return (false);
               }
            
               @Override
               public boolean          isEntityInvulnerable(DamageSource source) {
                   return (false);
               }
            
               @Override
               public boolean          isPotionApplicable(PotionEffect potioneffectIn) {
                   return (false);
               }
            
               @Override
               public boolean          isImmuneToExplosions() {
                   return (false);
               }
            
               @Nullable
               @Override
               protected SoundEvent    getAmbientSound() {
                   return (CraftAndConquerSounds.NPCDialogSoundEvent);
               }
            
               @Nullable
               @Override
               protected SoundEvent    getHurtSound() {
                   return (CraftAndConquerSounds.NPCDialogSoundEvent);
               }
            
               @Nullable
               @Override
               protected SoundEvent    getDeathSound() {
                   return (CraftAndConquerSounds.NPCDialogSoundEvent);
               }
            
               @Override
               protected SoundEvent    getFallSound(int heightIn) {
                   return (CraftAndConquerSounds.NPCDialogSoundEvent);
               }
            
               @Override
               protected SoundEvent    getSwimSound() {
                   return (CraftAndConquerSounds.NPCDialogSoundEvent);
               }
            
               @Override
               protected SoundEvent    getSplashSound() {
                   return (CraftAndConquerSounds.NPCDialogSoundEvent);
               }
            
            //    public static ThreadDownloadImageData   getDownloadImageSkin(ResourceLocation resourceLocationIn) {
            //        TextureManager          textureManager = Minecraft.getMinecraft().getTextureManager();
            //        ThreadDownloadImageData threadDownloadImageData;
            //
            //        threadDownloadImageData = new ThreadDownloadImageData(null, "http://imgur.com/Z0pbA3P.png", DefaultNPCSkin.getDefaultSkin(), new ImageBufferDownload() {
            //
            //            @Override
            //            public BufferedImage    parseUserSkin(BufferedImage image) {
            //                return (image);
            //            }
            //
            //        });
            //
            //        textureManager.loadTexture(resourceLocationIn, threadDownloadImageData);
            //
            //        return (threadDownloadImageData);
            //    }
            }
            
            

            ContainerNPCInventory:

            
            public class                ContainerNPCInventory extends Container {
            
               public static final EntityEquipmentSlot[]   VALID_EQUIPMENT_SLOTS = new EntityEquipmentSlot[] {
                       EntityEquipmentSlot.HEAD,
                       EntityEquipmentSlot.CHEST,
                       EntityEquipmentSlot.LEGS,
                       EntityEquipmentSlot.FEET,
                       EntityEquipmentSlot.MAINHAND,
                       EntityEquipmentSlot.OFFHAND
               };
            
               private EntityNPCDialog         entityNPC;
            
               private final InventoryPlayer   playerInventory;
               private InventoryBasic          entityInventory;
            
               public                  ContainerNPCInventory(EntityPlayer playerIn, EntityNPCDialog entityNPC) {
                   this.entityNPC = entityNPC;
            
                   this.playerInventory = playerIn.inventory;
                   this.entityInventory = new InventoryBasic("NPC Inventory", true, ContainerNPCInventory.VALID_EQUIPMENT_SLOTS.length);
                   for (int index = 0; index < ContainerNPCInventory.VALID_EQUIPMENT_SLOTS.length; ++index) {
                       this.entityInventory.setInventorySlotContents(index, entityNPC.getItemStackFromSlot(ContainerNPCInventory.VALID_EQUIPMENT_SLOTS[index]));
                   }
            
                   for (int index = 0; index < 4; ++index) {
                       final EntityEquipmentSlot   equipmentSlot = ContainerNPCInventory.VALID_EQUIPMENT_SLOTS[index];
            
                       this.addSlotToContainer(new Slot(this.entityInventory, index, 8, 8 + index * 18) {
            
                           @Override
                           public void onSlotChanged() {
                               entityNPC.setItemStackToSlot(equipmentSlot, this.getStack());
                               super.onSlotChanged();
                           }
            
                           @Override
                           public boolean  isItemValid(@Nullable ItemStack stack) {
                               return (stack != null && stack.getItem().isValidArmor(stack, equipmentSlot, entityNPC));
                           }
            
                           @Override
                           public int      getSlotStackLimit() {
                               return (1);
                           }
            
                           @Nullable
                           @Override
                           public String   getSlotTexture() {
                               return (ItemArmor.EMPTY_SLOT_NAMES[equipmentSlot.getIndex()]);
                           }
                       });
                   }
            
                   this.addSlotToContainer(new Slot(this.entityInventory, 4, 77, 8) {
            
                       @Override
                       public void onSlotChanged() {
                           entityNPC.setItemStackToSlot(ContainerNPCInventory.VALID_EQUIPMENT_SLOTS[4], this.getStack());
                           super.onSlotChanged();
                       }
                   });
            
                   this.addSlotToContainer(new Slot(this.entityInventory, 5, 95, 8) {
            
                       @Override
                       public void onSlotChanged() {
                           entityNPC.setItemStackToSlot(ContainerNPCInventory.VALID_EQUIPMENT_SLOTS[5], this.getStack());
                           super.onSlotChanged();
                       }
            
                       @SideOnly(Side.CLIENT)
                       @Nullable
                       @Override
                       public String   getSlotTexture() {
                           return ("minecraft:items/empty_armor_slot_shield");
                       }
                   });
            
                   for (int index = 0; index < 9; ++index) {
                       this.addSlotToContainer(new Slot(this.playerInventory, index, 9 + index * 18, 112));
                   }
               }
            
               @Override
               public boolean          canInteractWith(EntityPlayer playerIn) {
                   return (true);
               }
            }
            
            

            Cela fonctionne également en multiplayer. :D</integer></integer></itemstack>

            1 réponse Dernière réponse Répondre Citer 0
            • 1 / 1
            • Premier message
              Dernier message
            Design by Woryk
            ContactMentions Légales

            MINECRAFT FORGE FRANCE © 2024

            Powered by NodeBB