Résolu Changer l'Item d'un joueur avec le PlayerInteractEvent (synchronisation)
-
Bonjour, je reviens avec encore un nouveau problème de synchronisation client / serveur : utiliser l’event PlayerInteractEvent pour changer une fiole d’eau.
Ce qu’il se passe :
je fais clique droit dans de l’eau, les bouteilles en main se consument et çà m’ajoute 1 bouteille fantômes dans l’inventaire mais lorsque je déco-reco, les bouteilles ont disparus et les anciennes sont ré-apparus. (J’arrive à les récupérer en les bougeant dans mon inventaire avant de me déconnecter)Le code :
@SubscribeEvent public void onItemRightClick(PlayerInteractEvent event) { ItemStack stack = event.entityPlayer.getCurrentEquippedItem(); if (event.action == PlayerInteractEvent.Action.RIGHT_CLICK_AIR && stack != null && stack.getItem() == Items.glass_bottle) { MovingObjectPosition mop = getMovingObjectPositionFromPlayer(event.world, event.entityPlayer, true); if (mop != null) { int i = mop.blockX; int j = mop.blockY; int k = mop.blockZ; Hilium.LOGGER.info(event.x + "," + event.y + "," + event.z + " | " + i + "," + j + "," + k); if (!event.world.canMineBlock(event.entityPlayer, i, j, k) || !event.entityPlayer.canPlayerEdit(i, j, k, mop.sideHit, stack)) return; if (event.world.getBlock(i, j, k).getMaterial() == Material.water) { event.entityPlayer.inventory.decrStackSize(event.entityPlayer.inventory.currentItem, 1); if (!event.entityPlayer.inventory.addItemStackToInventory(new ItemStack(Items.apple))) event.entityPlayer.dropPlayerItemWithRandomChoice(new ItemStack(Items.apple), false); event.setCanceled(true); } } } }
J’ai rajouté un logger et il s’avère que l’événement n’est appelé que côté client (or dans un de mes mods fonctionnant seulement côté serveur en 1.8, j’utilise cet event qui est appelé de la même manière qu’en 1.7 et le code s’exécute correctement). Je n’ai pas trouvé de fonction ni de paquet pour mettre à jour l’inventaire du joueur.
-
Que côté client ?! Au contraire normalement cette event se trouve que côté serveur. Et pour synchro, c’est player.inventory.makeDirty() il me semble
-
Le logger indique client thread, c’est pour çà que c’est bizarre. J’ai déjà utiliser cette méthode mais elle ne changeais rien
-
Envoie un packet a la place de faire les actions sur l’inventaire, et toutes les actions que tu veux faire tu les mets dans le packet
-
Ta classe ne serait pas enregistré que côté client ?
-
Non car dans cette classe j’utilise aussi un tickevent côté serveur
-
J’ai trouvé d’où vient le problème : en fait l’event PlayerInteractEvent est appelé côté client à chaque fois mais il est appelé côté serveur seulement lorsque l’on clique sur un block. Donc je pense que le seul moyen d’y arriver est un paquet. Et pour le markDirty : la méthode change un booléen mais celui-ci n’est jamais appelé.
Finalement j’ai décidé d’utiliser la méthode GameRegistry.addSubstitutionAlias, pour ceux qui veulent le code :
private void register() { try { GameRegistry.addSubstitutionAlias("minecraft:glass_bottle", GameRegistry.Type.ITEM, this); } catch (ExistingSubstitutionException e) {} }