• Register
    • Login
    • Search
    • Recent
    • Tags
    • Popular
    • Users
    • Groups

    Extended Entity Properties

    Les entités
    1.7.2
    21
    127
    28499
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • Gugu
      Gugu last edited by robin4002

      Sommaire

      • Introduction
      • Pré-requis
      • Code
        • Classe ExtendedEntityProperties
        • Classe Event Handler
        • Classe du Packet
        • Common Proxy
      • Bonus
      • Résultat
      • Crédits

      Introduction

      Les Extended Entity Properties (que nous appellerons Propriétés d’entité) permettent d’ajouter de manière modulable des informations à une entité.
      Leurs utilisations sont nombreuses.
      Par exemple, le mod StarMiner (mod Japonais) qui en utilise pour stocker l’état de gravité du joueur, ou même mon propre mod, Ratchet & Clank mod, qui en utilise pour stocker une monnaie.

      Dans ce tutoriel, nous verrons principalement un système de monnaie, mais les modifications pour en faire un système de mana sont très simples.

      #Pré-requis(Pré-requis)

      Pour ce tutoriel, vous devez savoir manipuler les packets, et avoir une classe d’events.
      Je conseille aussi d’avoir un item pour tester votre propriété (Un item click droit qui vous dis votre argent, étant donné que ce tutoriel ne parleras pas de comment faire un GUI).

      Code

      Classe ExtendedProperties :

      La classe ExtendedProperties va gérer tout ce qui touche à votre propriété. Si c’est de l’argent, on peut faire des méthodes pour en retirer, en ajouter, ou payer ( Return d’un boolean disant si le joueur possède l’argent, tout en consommant celui-ci ).

      Pour commencer, nous allons simplement faire une classe :

      public class ExtendedEntityPropTuto implements IExtendedEntityProperties {
          @Override
          public void saveNBTData(NBTTagCompound compound) {
              // TODO Auto-generated method stub
          }
      
          @Override
          public void loadNBTData(NBTTagCompound compound) {
              // TODO Auto-generated method stub
          }
      
          @Override
          public void init(Entity entity, World world) {
              // TODO Auto-generated method stub
          }
      
      }
      

      Les méthodes seront générées automatiquement quand vous implémenterez la classe IExtendedEntityProperties.

      Maintenant, nous allons ajouter un identifiant à la propriété, ainsi que les variables qu’elle utilisera. Dans notre cas, le joueur cible, de l’argent, et une limite d’argent.

          public final static String EXT_PROP_NAME = "ExtPropTuto";
      
          private final EntityPlayer player;
      
          public long money;
          public long maxMoney;
      

      L’utilisation d’un long permet un stockage de grande taille pour votre argent. Si vous ne comptez pas atteindre plus de 2.147.483.647 d’argent, utilisez un int.

      On ajoute ensuite le constructeur. Il prend en paramètre le player auquel nous allons toucher.

      public ExtendedEntityPropTuto(EntityPlayer player) {
              this.player = player;
              this.money = 0;
              this.maxMoney = {Votre limite};
          }
      

      Maintenant, nous allons faire deux méthodes. Celles-ci vont ajouter les propriétés au joueur, et les obtenir, pour avoir son état actuel.

              public static final void register(EntityPlayer player) {
              player.registerExtendedProperties(ExtendedEntityPropTuto.EXT_PROP_NAME,
                      new ExtendedEntityPropTuto(player));
          }
      
          public static final ExtendedEntityPropTuto get(EntityPlayer player) {
              return (ExtendedEntityPropTuto) player.getExtendedProperties(EXT_PROP_NAME);
          }
      

      Simple n’est-ce pas ? La méthode get sera utilisée très souvent, dès que vous touchez à un player.

      Nous allons maintenant remplir les deux méthodes concernant la sauvegarde et l’obtention de ces données :

          @Override
          public void saveNBTData(NBTTagCompound compound) {
      
              NBTTagCompound properties = new NBTTagCompound();
      
              properties.setLong("Money", this.money);
              properties.setLong("MaxMoney", this.maxMoney);
      
              compound.setTag(EXT_PROP_NAME, properties);
          }
      
          @Override
          public void loadNBTData(NBTTagCompound compound) {
              NBTTagCompound properties = (NBTTagCompound) compound
                      .getTag(EXT_PROP_NAME);
              this.money = properties.getLong("Money");
              this.maxMoney = properties.getLong("MaxMoney");
          }
      

      La base est déjà là. On peut stocker des données dans notre joueur !

      Maintenant, nous arrivons à une partie assez lourde : La synchronisation client / serveur.
      Pour cela, il faudra que vous créez un packet qui enverra les informations.
      J’utilise FFMT API pour mes packets, et je vous le conseille.
      Je ne peux que donner ma méthode, et vous verrez ma classe packet un peu plus loin dans le tutoriel.

      public final void sync() {
              PacketMoney packetMoney = new PacketMoney(this.maxMoney, this.money);
                  //La ligne suivante dépend de votre manière d'envoyer les packets. Celle-ci vient de mon mod, je ne la changerais pas car je ne peux l'appliquer à votre mod, mais elle reste bonne pour un exemple.
              RcMod.rcModPacketHandler.sendToServer(packetMoney);
      
              if (!player.worldObj.isRemote) {
                  EntityPlayerMP player1 = (EntityPlayerMP) player;
                              //Ici, même chose que précédemment, sauf que le packet est envoyé au player.
                  RcMod.rcModPacketHandler.sendTo(packetMoney, player1);
              }
          }
      

      Cette fonction reste assez simple. On crée un packet avec les informations et on l’envoie.

      Encore une méthode de sauvegarde :

      private static String getSaveKey(EntityPlayer player) {
              return player.getDisplayName() + ":" + EXT_PROP_NAME;
          }
      

      Des méthodes utilitaires, qui seront utilisées dans l’event handler :

          public static void saveProxyData(EntityPlayer player) {
              ExtendedEntityPropTuto playerData = ExtendedEntityPropTuto.get(player);
              NBTTagCompound savedData = new NBTTagCompound();
      
              playerData.saveNBTData(savedData);
              CommonProxy.storeEntityData(getSaveKey(player), savedData);
          }
      
          public static void loadProxyData(EntityPlayer player) {
              ExtendedEntityPropTuto playerData = ExtendedEntityPropTuto.get(player);
              NBTTagCompound savedData = CommonProxy
                      .getEntityData(getSaveKey(player));
      
              if (savedData != null) {
                  playerData.loadNBTData(savedData);
              }
              playerData.sync();
          }
      

      Celles-ci servent, une fois de plus, à la sauvegarde et à la lecture des données.

      Voilà ! Les méthodes génériques sont terminées, et on peut maintenant passer à ce qui nous intéresse : Les méthodes spécifiques. Dans notre cas, nous voulons plusieurs méthodes :
      Une pour ajouter de l’argent, une pour en retirer, une deuxième méthode pour en retirer, qui aura un fonctionnement particulier : Elle vérifiera que le player possède assez d’argent lors du retrait, et retournera true si le retrait a bien été effectué. C’est le principe du paiement : Si vous avez assez d’argent, l’action que vous comptez faire est valide, et on prend l’argent.
      Une autre méthode peut-être utile, pour avoir une commande qui met votre argent à une certaine valeur. Par exemple, pour vos tests, vous pouvez faire /argent 1000 pour avoir 1000 d’argent etc…

      Je les donnes à la suite, car elle sont relativement simples :

      public boolean pay(long amount) {
              boolean sufficient = amount <= this.money;
      
              if (sufficient) {
                  this.money -= amount;
                  this.sync();
              } else {
                  return false;
              }
      
              return sufficient;
          }
      
          public void addMoney(long amount) {
              this.money += amount;
              this.sync();
          }
      
          public long getMoney() {
              return this.money;
          }
      
          public void setMoney(long newMoney) {
              this.money = newMoney;
              this.sync();
          }
      

      Comme vous le remarquez, après chaque changement, on synchronise.

      C’est tout pour la classe des propriétés. On peut y ajouter bien d’autres fonctions, le système d’argent est juste simple à comprendre.

      EventHandler :

      Dans votre event handler, vous allez avoir besoin de pas mal d’events.
      Nous devons obtenir la propriété très souvent : quand l’entité quitte le monde, rejoint le monde, meurt etc…
      Je donne les méthodes directement, car il n’y a pas de réel intérêt à les expliquer :

          @SubscribeEvent
          public void onEntityConstructing(EntityConstructing event) {
      
              if (event.entity instanceof EntityPlayer
                      && ExtendedEntityPropTuto.get((EntityPlayer) event.entity) == null)
      
                  ExtendedEntityPropTuto.register((EntityPlayer) event.entity);
          }
      
      @SubscribeEvent
          public void onLivingDeathEvent(LivingDeathEvent event) {
              if (!event.entity.worldObj.isRemote
                      && event.entity instanceof EntityPlayer) {
                  NBTTagCompound playerData = new NBTTagCompound();
                  ((ExtendedEntityPropTuto) (event.entity
                          .getExtendedProperties(ExtendedEntityPropTuto.EXT_PROP_NAME)))
                          .saveNBTData(playerData);
                  proxy.storeEntityData(
                          ((EntityPlayer) event.entity).getDisplayName(), playerData);
                  ExtendedEntityPropTuto.saveProxyData((EntityPlayer) event.entity);
              } else {
      
              }
          }
      

      Cette méthode permet de conserver les données après la mort. Dans le cas du mana, elle n’est pas nécessaire si vous souhaitez que le joueur reparte avec 0 de mana. Si votre maximum de mana peut varier, conservez la.

      @SubscribeEvent
          public void onEntityJoinWorld(EntityJoinWorldEvent event) {
              if (!event.entity.worldObj.isRemote && event.entity instanceof EntityPlayer) {
                  NBTTagCompound playerData = proxy
                          .getEntityData(((EntityPlayer) event.entity)
                                  .getDisplayName());
                  if (playerData != null) {
                      ((ExtendedEntityPropTuto) (event.entity
                              .getExtendedProperties(ExtendedEntityPropTuto.EXT_PROP_NAME)))
                              .loadNBTData(playerData);
                  }
      
                  ((ExtendedEntityPropTuto) (event.entity
                          .getExtendedProperties(ExtendedEntityPropTuto.EXT_PROP_NAME)))
                          .sync();
              }
          }
      

      Quand l’entité change de monde / se connecte.

      C’est tout pour l’event handler !

      Classe du packet :

      Le packet est ce qui va permettre au client et au serveur de se transmettre les données. Cette classe est propre à ma manière d’utiliser les packets. Il est possible que vous n’ayez pas à faire la même chose. Dans ce cas, inspirez-vous de ce que je fais.

      Note : Si vous souhaitez faire comme moi, vous devez avoir FFMT-Lib

      
      public class PacketMoney extends AbstractPacket{
      
          private long maxMoney, Money;
      
          public PacketMoney(){
      
          }
      
          public PacketMoney(long maxMoney, long money){
              this.maxMoney = maxMoney;
              this.money = money;
          }
      
          @Override
          public void encodeInto(ChannelHandlerContext ctx, ByteBuf buffer) {
              buffer.writeLong(maxMoney);
              buffer.writeLong(money);
      
          }
      
          @Override
          public void decodeInto(ChannelHandlerContext ctx, ByteBuf buffer) {
              this.maxMoney = buffer.readLong();
              this.money = buffer.readLong();
          }
      
          @Override
          public void handleClientSide(EntityPlayer player) {
              ExtendedEntityPropTuto props = ExtendedEntityPropTuto
                      .get(player);	
              props.maxMoney = this.maxMoney;
              props.money = this.money;
          }
      
          @Override
          public void handleServerSide(EntityPlayer player) {
              ExtendedEntityPropTuto props = ExtendedEntityPropTuto
                      .get(player);
              props.maxMoney = this.maxMoney;
              props.money = this.money;
          }
      }
      

      CommonProxy :

      Dans votre CommonProxy, vous devez ajouter ces deux méthodes :

      public static void storeEntityData(String name, NBTTagCompound compound) {
              extendedEntityData.put(name, compound);
          }
      
          public static NBTTagCompound getEntityData(String name) {
              return extendedEntityData.remove(name);
          }
      

      Vous allez avoir une erreur, c’est normal, le proxy n’as pas la variable extendedEntityData

      La voici :

      private static final Map <String, NBTTagCompound> extendedEntityData = new HashMap<String, NBTTagCompound>();
      

      Pensez bien a mettre tout ça dans le COMMON proxy ! C’est assez rare d’y mettre autre chose que des méthodes vides, mais mettez y bien dedans !

      Bonus

      Classe d’un Item :

          @Override
          public ItemStack onItemRightClick(ItemStack itemstack, World world,
                  EntityPlayer player) {
              if (!world.isRemote) {
      
                  ExtendedEntityPropTuto props = ExtendedEntityPropTuto.get(player);
      
                  if (props.pay(15)) {
                      System.out
                              .println("Squalala, nous sommes partis!");
                  } else {
                      System.out
                              .println("Pas d'argent ! Je suis triste !");
                  }
              }
              return itemstack;
          }
      

      Un exemple d’utilisation :

      Résultat

      Le résultat n’est pas immédiatement visible. Vous aurez besoin de vous en servir dans un autre système !

      Crédits

      Rédaction :

      • Gugu42

      Correction :

      • jglrxavpok
      • FireDreft
      • gagoi

      Creative Commons
      Ce tutoriel de Minecraft Forge France est mis à disposition selon les termes de la licence Creative Commons Attribution - Pas d’Utilisation Commerciale - Partage dans les Mêmes Conditions 4.0 International

      retourRetour vers le sommaire des tutoriels

      "If you have a comprehensive explanation for everything then it decreases uncertainty and anxiety and reduces your cognitive load. And if you can use that simplifying algorithm to put yourself on the side of moral virtue then you’re constantly a good person with a minimum of effort."
      ― Jordan B. Peterson

      1 Reply Last reply Reply Quote 0
      • Gugu
        Gugu last edited by

        Tutoriel sorti ! 🙂

        "If you have a comprehensive explanation for everything then it decreases uncertainty and anxiety and reduces your cognitive load. And if you can use that simplifying algorithm to put yourself on the side of moral virtue then you’re constantly a good person with a minimum of effort."
        ― Jordan B. Peterson

        1 Reply Last reply Reply Quote 0
        • bbcmh3
          bbcmh3 last edited by

          Super Tuto !!! Je ne penses pas m’en servir pour le moment mais peut-être que par la suite…. 🙂

          1 Reply Last reply Reply Quote 0
          • isador
            isador Moddeurs confirmés Modérateurs last edited by

            Génial gugu j’en aurai besoin pour la refonte de minecraft que j’effectue

            1 Reply Last reply Reply Quote 0
            • Gugu
              Gugu last edited by

              Si vous avez besoin d’aide pour par exemple modifier le système, je suis disponible 😉

              "If you have a comprehensive explanation for everything then it decreases uncertainty and anxiety and reduces your cognitive load. And if you can use that simplifying algorithm to put yourself on the side of moral virtue then you’re constantly a good person with a minimum of effort."
              ― Jordan B. Peterson

              1 Reply Last reply Reply Quote 0
              • arthur111213
                arthur111213 last edited by

                Merci beaucoup. Je vais pouvoir continuer mon mod plus rapidement que prévu finalement :)Merci de la vitesse à laquelle tu as fait ce tuto 🙂

                1 Reply Last reply Reply Quote 0
                • isador
                  isador Moddeurs confirmés Modérateurs last edited by

                  J’ai une question: comment l’adapter pour que ça marche en 1.6.x??

                  1 Reply Last reply Reply Quote 0
                  • DarkSilver974
                    DarkSilver974 last edited by

                    Merci beaucoup gugu42! Sans toi je n’aurais jamais trouvé, avant qu’on ne me parle de ton tuto j’ai deja cherché une journée en vain xD

                    1 Reply Last reply Reply Quote 0
                    • Gugu
                      Gugu last edited by

                      @‘isador34’:

                      J’ai une question: comment l’adapter pour que ça marche en 1.6.x??

                      Hm, essaie de faire la même chose qu’en 1.7 et envoie moi les erreurs. C’est la solution la plus simple.

                      "If you have a comprehensive explanation for everything then it decreases uncertainty and anxiety and reduces your cognitive load. And if you can use that simplifying algorithm to put yourself on the side of moral virtue then you’re constantly a good person with a minimum of effort."
                      ― Jordan B. Peterson

                      1 Reply Last reply Reply Quote 0
                      • DarkSilver974
                        DarkSilver974 last edited by

                        => le lien de FFMT API est mort, je fait une erreur 404

                        1 Reply Last reply Reply Quote 0
                        • robin4002
                          robin4002 Moddeurs confirmés Rédacteurs Administrateurs last edited by

                          http://mods.mcnanotech.fr/index.php/Accueil
                          La doc n’est pas encore complète, mais si tu veux tu peux regarder sur nanotech mod : https://github.com/FFMT/nanotech_mod

                          1 Reply Last reply Reply Quote 0
                          • RedRelay
                            RedRelay Moddeurs confirmés last edited by

                            Super j’en avais besoin pour mon mod 😄 Merci 🙂

                            –------------------------------------------------------------------------------------
                            Si tu trouves mon intervention pertinente, n'hésite pas a m…

                            1 Reply Last reply Reply Quote 0
                            • isador
                              isador Moddeurs confirmés Modérateurs last edited by

                              bha gugu le problème c’est que tu utiliser des fonction de FFMT dans ton code hors, c’est fonction n’existait pas en 1.6.x……
                              ainsi que le AbstractPacket

                              1 Reply Last reply Reply Quote 0
                              • Gugu
                                Gugu last edited by

                                Bah, tu a juste a envoyer un Packet qui contient les informations ^^

                                https://github.com/Gugu42/RatchetAndClankMod/commit/16c2a6711e91a672bda4892db67f6cbdf6987ab2

                                Ce commit contient la manière dont j’ai fait mes packets en 1.6.x

                                "If you have a comprehensive explanation for everything then it decreases uncertainty and anxiety and reduces your cognitive load. And if you can use that simplifying algorithm to put yourself on the side of moral virtue then you’re constantly a good person with a minimum of effort."
                                ― Jordan B. Peterson

                                1 Reply Last reply Reply Quote 0
                                • isador
                                  isador Moddeurs confirmés Modérateurs last edited by

                                  Merci 🙂

                                  1 Reply Last reply Reply Quote 0
                                  • BlackDrag00n
                                    BlackDrag00n last edited by

                                    Il y a une petite erreur a ce niveau là (par rapport au fait de pouvoir tapez des commandes)

                                    public int getMoney() {
                                    return this.money;
                                    }
                                    

                                    Ici ce n’est pas un “public int getMoney()” mais plutôt un “public long getMoney()” étant donnée que juste au dessus on a déclarer la Money comme étant un “long”

                                    public final static String EXT_PROP_NAME = "ExtPropTuto";
                                    
                                    private final EntityPlayer player;
                                    
                                    public long money;
                                    public long maxMoney;
                                    

                                    C’est possible d’avoir un GitHub avec le codage au complet car j’ai du mal a situé ou doivent être tous les éléments indiquer dans le tuto ?

                                    merci d’avance 🙂

                                    1 Reply Last reply Reply Quote 0
                                    • Gugu
                                      Gugu last edited by

                                      Heu pour le github, je n’en ai pas fait un, je me base sur celui de mon mod Ratchet & Clank ( http://github.com/Gugu42/ratchetandclankmod/ )

                                      "If you have a comprehensive explanation for everything then it decreases uncertainty and anxiety and reduces your cognitive load. And if you can use that simplifying algorithm to put yourself on the side of moral virtue then you’re constantly a good person with a minimum of effort."
                                      ― Jordan B. Peterson

                                      1 Reply Last reply Reply Quote 0
                                      • BlackDrag00n
                                        BlackDrag00n last edited by

                                        Le problème est que visiblement dans ce GitHub une ancienne version de “FFMT” car on utilise plus ceci :

                                        public class PacketRefill extends FFMTPacket {
                                        
                                        public void encodeInto(ChannelHandlerContext ctx, ByteBuf buffer) {
                                        
                                        public void decodeInto(ChannelHandlerContext ctx, ByteBuf buffer) {
                                        

                                        On utilise quelques choses de similaire a ça :

                                        public class PacketRefill extends AbstractPacket {
                                        
                                        public void writeData(ByteBuf buffer) throws IOException {
                                        
                                        public void readData(ByteBuf buffer) {
                                        

                                        Donc je peux pas vraiment m’en servir 😕 je regarde un peu plus car moi ce qui m’interesse dans le GitHub c’etait ou été placer les EVENT HANDLER.


                                        Je vois que sur le GitHub tu utilise une classe “RcEventHandler.java”

                                        Et que tu l’initialise ici :

                                        @EventHandler
                                        public void PostInit(FMLPostInitializationEvent event) {
                                        NetworkRegistry.INSTANCE.registerGuiHandler(this, new GuiHandler());
                                        MinecraftForge.EVENT_BUS.register(new RcEventHandler());
                                        

                                        C’est bien ça ?

                                        1 Reply Last reply Reply Quote 0
                                        • Gugu
                                          Gugu last edited by

                                          Mais … c’est exactement la même chose, les méthodes sont juste renommées ._.

                                          "If you have a comprehensive explanation for everything then it decreases uncertainty and anxiety and reduces your cognitive load. And if you can use that simplifying algorithm to put yourself on the side of moral virtue then you’re constantly a good person with a minimum of effort."
                                          ― Jordan B. Peterson

                                          1 Reply Last reply Reply Quote 0
                                          • BlackDrag00n
                                            BlackDrag00n last edited by

                                            Oui oui ça moi je l’est compris mais début j’avais du mal … car j’étais débutant 😛 tu vois ce que je veux dire … c’est en discutant avec vous et en posant des question qu’on comprend tous ça… ce qui est malheureux pour un tuto ou on devrait pas vous déranger … surtout pour des choses si futile 😉

                                            1 Reply Last reply Reply Quote 0
                                            • 1
                                            • 2
                                            • 3
                                            • 4
                                            • 5
                                            • 6
                                            • 7
                                            • 1 / 7
                                            • First post
                                              Last post
                                            Design by Woryk
                                            Contact / Mentions Légales

                                            MINECRAFT FORGE FRANCE © 2018

                                            Powered by NodeBB