Résolu Item complexe : gui, bouton, packet et model custom
-
Et oui, les joies de la 1.8 …
-
Mojang…
-
Je reviens à la question précédant car j’ai réussi mettre à jour l’inventaire du joueur coté client via un packet réponse mais le problème c’est que ça n’update les NBTTag de l’item qui ouvre le gui que quand on ferme puis rouvre le gui, pourtant, j’ai bien fait les modifications de NBTTag.
-
Comme je vois que personne ne répond, je vais donc faire un petit résumé :
J’ai créé un item, lorsque l’on fait clic droit avec lui dans la main, ça ouvre un gui.
Sur ce gui, il y a plusieurs boutons. Lorsque l’on clique sur un bouton, ça envoie un packet au serveur qui vas (si quelques conditions son respectés) modifier deux item de l’inventaire du joueur : il change les NBTTag de l’item en main (celui avec qui le joueur a ouvert le gui) et modifie le nombre d’item dans un autre itemStack de l’inventaire du joueur.
Ensuite, le serveur envoi un packet réponse au client pour qu’il fasse les mêmes modifications mais le NBTTag de l’item ne ce met à jour que lorsque l’on ferme puis rouvre le gui. (Il y a une modification de l’interface selon le NBTTag de l’item : des bouton qui deviennent visibles. Le NBTTag est vérifié dans le drawGuiContainerBackgroundLayer du gui, je pence pas que ce soit ça le problème)
-
Est-ce que l’item garde les tags après avoir sauvegardé puis relancer la map ?
Montre le code où tu set les tags de l’item. -
@‘AymericRed’:
Est-ce que l’item garde les tags après avoir sauvegardé puis relancer la map ?
Montre le code où tu set les tags de l’item.L’item garde bien les tags quand on relance la map.
Pour le code je met un “//ici” pour les endroits où il y a un changement de NBTTag.
- coté serveur : (dans le classe de RuneStoneMessage qui implémente IMessage )
:::public static class ServerMessageHandler implements IMessageHandler <runestonemessage, runestonemessage="">{ @Override public RuneStoneMessage onMessage(RuneStoneMessage message, MessageContext ctx) { EntityPlayer player = ctx.getServerHandler().playerEntity; if (player == null) { return null; } int slotIndex = message.slotIndex; int[] linkIndex = message.linkIndex; InventoryPlayer playerInv = player.inventory; ItemStack runeStoneStack = playerInv.getStackInSlot(slotIndex); ItemStack applyStack = playerInv.getItemStack(); if (runeStoneStack == null || !(runeStoneStack.getItem() instanceof RuneStoneItem) || applyStack == null) { return null; } if (!runeStoneStack.hasTagCompound()) { runeStoneStack.setTagCompound(new NBTTagCompound()); } NBTTagCompound tag = runeStoneStack.getTagCompound(); int[] links = null; if (!tag.hasKey("Links")) { links = Link.linksInit(); tag.setIntArray("Links", links); // ici (on réinitiallise le NBTTag) } else { links = tag.getIntArray("Links"); if (links == null || links.length != 187) { links = Link.linksInit(); tag.setIntArray("Links", links); // ici (on réinitiallise le NBTTag) } } if (linkIndex != null && linkIndex.length != 0 && applyStack.stackSize >= linkIndex.length) { Item applyItem = applyStack.getItem(); if (applyItem == Items.flint) { for (int i : linkIndex) { if(i < 0 || i > 186 || (links* != 1 && i != 0) ) { return null; } } for (int i : linkIndex) { if (i != 0) { links* = 2; applyStack.stackSize -=1; } } tag.setIntArray("Links", links); //ici //playerInv.markDirty(); return message; } } return null; } }
:::
- coté client (dans la même class, c’est trés proche de ce qu’il y a coté serveur) :
:::
public static class ClientMessageHandler implements IMessageHandler <runestonemessage, imessage="">{ @Override public IMessage onMessage(RuneStoneMessage message, MessageContext ctx) { EntityPlayer player = Minecraft.getMinecraft().thePlayer; int slotIndex = message.slotIndex; int[] linkIndex = message.linkIndex; InventoryPlayer playerInv = player.inventory; ItemStack runeStoneStack = playerInv.getStackInSlot(slotIndex); ItemStack applyStack = playerInv.getItemStack(); if (runeStoneStack == null || !(runeStoneStack.getItem() instanceof RuneStoneItem) || applyStack == null) { return null; } if (!runeStoneStack.hasTagCompound()) { runeStoneStack.setTagCompound(new NBTTagCompound()); } NBTTagCompound tag = runeStoneStack.getTagCompound(); int[] links = null; if (!tag.hasKey("Links")) { links = Link.linksInit(); tag.setIntArray("Links", links); // ici (on initiallise le NBTTag) } else { links = tag.getIntArray("Links"); if (links == null || links.length != 187) { links = Link.linksInit(); tag.setIntArray("Links", links); // ici (on réinitiallise le NBTTag) } } if (linkIndex != null && linkIndex.length != 0 && applyStack.stackSize >= linkIndex.length) { Item applyItem = applyStack.getItem(); if (applyItem == Items.flint) { for (int i : linkIndex) { if(i < 0 || i > 186 || (links* != 1 && i != 0) ) { return null; } } for (int i : linkIndex) { if (i != 0) { links* = 2; applyStack.stackSize -=1; } } tag.setIntArray("Links", links); //ici //playerInv.markDirty(); System.out.println(playerInv.inventoryChanged); } } return null; } }
:::</runestonemessage,></runestonemessage,>
- coté client (dans la même class, c’est trés proche de ce qu’il y a coté serveur) :
-
C’est bizarre, ça devrait bien être changé, mets un System.out.println au début de ta fonction côté client pour voir si le packet est bien renvoyé par le serveur. Si oui, tu peux toujours faire Minecraft.getMinecraft().displayGuiSreen(TonGui); pour réafficher le gui mais bon c’est pas très propre…
-
@‘AymericRed’:
C’est bizarre, ça devrait bien être changé, mets un System.out.println au début de ta fonction côté client pour voir si le packet est bien renvoyé par le serveur. Si oui, tu peux toujours faire Minecraft.getMinecraft().displayGuiSreen(TonGui); pour réafficher le gui mais bon c’est pas très propre…
Le packet est bien renvoyé par le serveur et reçut par le client.
Avec Minecraft.getMinecraft().displayGuiSreen(MonGui); ça fonctionne mais comme le joueur a un itemStack sur le curseur, c’est un peut buggé : l’itemStack disparais et est dropé par le joueur quand il referme le gui.EDIT :
J’ai trouvé une solution : après Minecraft.getMinecraft().displayGuiSreen(MonGui); j’ai mis playerInv.setItemStack(applyStack); (applyStack est définit plus haut par playerInv.getItemStack(); ) -
Alors j’ai toujours un problème : l’itemStack ne disparais plus mais dés que je quitte le gui, il se faite drop alors qu’il est pas sur le curseur, comme si ce que j’ai fait après le Minecraft.getMinecraft().displayGuiSreen(MonGui); n’avais pas été fait (si je bouge une item de mon inventaire avant de le refermé, il reviens à sa position initiale).
La fonction pour rouvrir le gui alors qu’il est déjà ouvert fait forcément dropé l’item sur le curseur ?
J’ai tenté de aire ça mais ça ne fonctionne pas :playerInv.setItemStack(null); Minecraft.getMinecraft().displayGuiScreen(new RuneStoneGui(playerInv, slotIndex)); if (applyStack.stackSize <= 0) { playerInv.setItemStack(null); } else { playerInv.setItemStack(applyStack); }
-
J’ai trouvé une solution : au lieux de rajouter Minecraft.getMinecraft().displayGuiScreen(new RuneStoneGui(playerInv, slotIndex)) et de corrigé les problèmes que ça créé, j’ai modifié mon gui pour qu’au lieu d’enregistrer l’itemstack dans une variable (ce qui fait qu’il n’est update que lorsque l’on ferme puis rouvre l’inventaire), j’enregistre l’index du slot dans lequel il est et je get le contenu du slot (ce qui donne l’itemstack ) pour modifier le rendu du gui.
Maintenant que ce problème est réglé, je m’occupe du rendu de l’item !
Dans le NBTTag de mon item, il y a 28 int. je voudrais que chaque int, s’il est égale à 1 affiche une ligne noir sur l’item. Je suppose que je ne peut pas passer par un rendu classique (un model en .json) car en recherchant dans le rendu des item j’ai trouvé ce qui correspond au model builtin/generated et il y a une liste du layer0 au layer4 donc je ne peut pas en mettre 29. (Ou alors il faudrait que j’arrive à mette les 28 lignes sur un layer)
Donc je voudrais savoir de quel manière je pourrais faire le rendu pour pouvoir mettre ces 28 lignes sans (si possible) avoir à faire un model pour chaque combinaison possible (plus tard, il y aura encore plus de possibilités car je voudrais faire en sorte que selon le int, la ligne soit d’une certaine couleur).
-
Je pense que tu pourrais utiliser un IItemRender (après, jamais utilisé donc je ne sais pas trop ce que ça offre).
-
N’existe plus en 1.8. Donc non.
-
Ah okay autant pour moi (ça a disparu comme le ISBHR (un nom de genre avec ces lettres dans un autre ordre) quoi)
Envoyé de mon RAINBOW LITE 4G en utilisant Tapatalk
-
Dommage… Il n’y a pas une autre solution qui pourrais remplacer IItemRender ?
-
Utiliser les JSONs ou utiliser ce projet https://github.com/Thog/ISBRH
-
@‘AymericRed’:
Ah okay autant pour moi (ça a disparu comme le ISBHR (un nom de genre avec ces lettres dans un autre ordre) quoi)
Envoyé de mon RAINBOW LITE 4G en utilisant Tapatalk
C’est ISBRH. Tu y étais presque (ISpecialBlockRenderingHandler)
-
@‘Superloup10’:
Utiliser les JSONs ou utiliser ce projet https://github.com/Thog/ISBRH
Je testerais avec le projet d’ ISBRH quand j’airais du temps libre (surement le week-end prochain), mais en utilisant les JSONs, je ne vois pas comment je peut faire sans avoir à faire un fichier JSON par possibilité.
-
C’est un peu spécial à gérer les jsons mais déjà, tu peux regarder l’arc pour te faire une idée.
-
J’ai un peut cherché pour l’arc …… j’ai pas vraiment l’impression que c’est un bon exemple à utiliser : dans la class de l’item, il y a une liste de strings correspondants aux icônes possibles pour l’arc mais elle est utilisée nul part. Ensuite, j’ai trouvé un endroit qui à l’aire de décidé du model de l’arc en fonction du joueur mais, c’est dans la class RenderItem …
Je me demandais si c’était possible pour les item de faire un peut comme les blockstates : faire en sorte que dans un seul json, selon la metadata, ça choisit un
modelun texture différente pour le layer supérieur du model. (Peut être en utilisant ModelBakery.addVariantName, ModelLoader.setCustomMeshDefinition ou ModelLoader.setCustomStateMapper)EDIT : J’ai trouvé deux nouveautés de la 1.8, qui pourraient surement être utiles : l’event ModelBakeEvent et l’interface ISmartItemModel. Si quelqu’un sais s’en servir, je voudrais bien qu’il me passe son savoir !
-
Tu peux faire comme les blockstates via une fonction à mettre dans la classe de ton Item : “public ModelResourceLocation getModel(ItemStack stack, EntityPlayer player, int useRemaining) {}” il suffit de return le model en fonction de ce que tu veux.
Envoyé de mon RAINBOW LITE 4G en utilisant Tapatalk