Résolu GUIs non mises à jour côté client
-
Salut !
Je reviens à la charge avec un autre problème : j’ai un inventaire, lorsque je pose un item dedans, il est sensé aller se ranger directement en haut à gauche dès que je le place. Pour cela, j’exécute une fonction qui déplace tous les items de la table ItemStack[] inventory, seulement, ce problème apparaît :
https://www.youtube.com/watch?v=zdXBmxrBxgQ
J’imagine que c’est parce que le serveur n’envoie pas immédiatement l’info au client. Comment puis-je faire cela ?
Voici le contenu de ma TileEntity implements IInventory :
public void onDataPacket(NetworkManager net, S35PacketUpdateTileEntity pkt) { this.readFromNBT(pkt.func_148857_g()); } public Packet getDescriptionPacket() { NBTTagCompound nbttagcompound = new NBTTagCompound(); this.writeToNBT(nbttagcompound); return new S35PacketUpdateTileEntity(this.xCoord, this.yCoord, this.zCoord, 3, nbttagcompound); } @Override public ItemStack decrStackSize(int slotId, int quantity) { if (this.inventory[slotId] != null) { ItemStack itemstack; if (this.inventory[slotId].stackSize <= quantity) { itemstack = this.inventory[slotId]; this.inventory[slotId] = null; if (!worldObj.isRemote) { this.checkSorting(); this.iAmLookingForSomething(); this.checkSorting(); } this.markDirty(); return itemstack; } else { itemstack = this.inventory[slotId].splitStack(quantity); if (this.inventory[slotId].stackSize == 0) { this.inventory[slotId] = null; } if (!worldObj.isRemote) { this.checkSorting(); this.iAmLookingForSomething(); this.checkSorting(); } this.markDirty(); return itemstack; } } else { return null; } } @Override public void setInventorySlotContents(int slotId, ItemStack stack) { this.inventory[slotId] = stack; if (stack != null && stack.stackSize > this.getInventoryStackLimit()) { int redrop = stack.stackSize - this.getInventoryStackLimit(); stack.stackSize = this.getInventoryStackLimit(); } if (!worldObj.isRemote) { this.checkSorting(); this.iAmLookingForSomething(); this.checkSorting(); } this.markDirty(); } public void checkSorting() { // algo temporaire boolean areThereItems; for (int k = 0; 26 > k; k++) { areThereItems = false; for (int i = k; 27 > i; i++){ if (this.inventory* != null){ areThereItems = true; } } if (areThereItems) { while (this.inventory[k] == null){ for (int i = k; 26 > i; i++){ this.inventory* = this.inventory[i+1]; this.inventory[i+1] = null; } } } } }
Merci d’avance !
-
Il faudrait exécuter aussi la fonction en client je pense, donc enlève le if (!worldObj.isRemote) {
Car les donnés sont bien synchro (c’est le but de la fonction this.markDirty()) en revanche c’est le gui qui n’est pas mit à jour. Exécuter la fonction en client pourrait régler le problème, sinon il faudrait refaire un draw du gui. -
Merci, ça fonctionne. Par contre j’aimerai en profiter pour enchaîner sur un sujet tellement similaire que ce n’est pas la peine d’ouvrir un autre topic. iAmLookingForSomething :
public void iAmLookingForSomething() { if (this.hasMaster && (!worldObj.isRemote) && this.inventory[0] != null && this.getPowerState()) { ItemStack backup = this.inventory[0]; this.inventory[0] = ((TileEntityMultiblockControler) this.master).giveStack(this.inventory[0]); if (backup != this.inventory[0]) { if (this.inventory[0] != null) { ((TileEntityMultiblockControler) this.master).consumeEnergy(materializationEnergyCost * (backup.stackSize - this.inventory[0].stackSize)); } else { ((TileEntityMultiblockControler) this.master).consumeEnergy(materializationEnergyCost * backup.stackSize); } } } checkSorting(); this.markDirty(); }
Je pose les objets, qui sont sensé être pompés immédiatement, mais ça ne fait rien. Par contre en faisant une update comme dans la vidéo, le compte s’adapte. Aussi, ça ne le fait qu’avec le premier objet, quand les objets suivants sont pompés, tout se met à jour comme il faut. D’ailleurs, le pompage du deuxième objet agit comme une mise à jour.
Comment régler cela ?
Merci d’avance.
-
Le problème est le même non ? Il faudrait enlever !worldObj.isRemote ou refresh le gui.
-
Le problème c’est que si j’enlève le !worldObj.isRemote, ça fait faire des tonnes de calculs supplémentaires au client, n’est-ce pas ?
-
Les calcules sont pas si énorme que ça, si ? Et puis ta fonction n’est pas lancé à chaque tick, donc c’est loin d’être lourd.
-
iAmLookingForSomething envoie à toutes les chambres de traitement d’objet les objets.
Le truc c’est qu’à termes, des chambres de traitement il pourra y en avoir une centaine par multiblock. Alors le moins de calcul que je peux faire serait le mieux. Mais je pense que provisoirement je peux remettre ça, et au fur et à mesure des release beta privée je soulagerai le code. Je te donne des nouvelles voir si ça débug…EDIT : Exact même problème…
-
Ah oui en effet, ça fait lourd. Il faudrait trouver comment refresh le gui.
-
Dans la classe container il ya des methodes qui mettent à jour le GUI, je peut détailler si besoin (enfin je les connais pas toutes).
-
Ouai je veux bien s’il te plait.
-
Alors je vais essayer de t’expliquer ce que j’ai compris … (je fonctionne avec buildcraft mais normalement tout ce que je vais te montrer ça marche sans ).
Dans la classe Container liée à ton GUI tu peut avoir ces 3 fonctions :
@Override public void addCraftingToCrafters(ICrafting crafting) { super.addCraftingToCrafters(crafting); } public void detectAndSendChanges() { super.detectAndSendChanges(); } @SideOnly(Side.CLIENT) public void updateProgressBar(int id, int value) { }
Normalement elles servent surtout à mettre à jour les barres de progression des four et tout les autres truc dans le genre mais l’important c’est de savoir qu’avec ça tu peut vérifier qu’une variable (en int) est la même sur le client et le serveur et si non tu vas mettre a jour le client. (en fait j’ai eu le même problème que toi pendant 6 mois et je suis tombé la dessus par hasard en fouillant dans mes codes ).
Par exemple : (c’est pour un four à liquide personnalisé )
private int lastCookTime; private int lastBurnTime; private int lastItemBurnTime; private int lastfluidamout; private int lastfluidid;
Donc je déclare mes variable dans le container (temps de cuisson, quantité de liquide et l’id du liquide) j’ai des variable équivalente dans la tile entity de mon block.
@Override public void addCraftingToCrafters(ICrafting crafting) { super.addCraftingToCrafters(crafting); crafting.sendProgressBarUpdate(this, 0, this.tileEntity.furnaceCookTime); crafting.sendProgressBarUpdate(this, 1, this.tileEntity.furnaceBurnTime); crafting.sendProgressBarUpdate(this, 2, this.tileEntity.currentItemBurnTime); crafting.sendProgressBarUpdate(this, 3, this.tileEntity.fluidamount); crafting.sendProgressBarUpdate(this, 4, this.tileEntity.fluidid); }
Ensuite première fonction elle va récupérer les valeurs des variables sur le serveur (bien mettre un chiffre différent à chaque ligne en 2ème argument).
public void detectAndSendChanges() { super.detectAndSendChanges(); for(int i = 0; i < this.crafters.size(); ++i) { ICrafting icrafting = (ICrafting)this.crafters.get(i); if(this.lastCookTime != this.tileEntity.furnaceCookTime) { icrafting.sendProgressBarUpdate(this, 0, this.tileEntity.furnaceCookTime); } if(this.lastBurnTime != this.tileEntity.furnaceBurnTime) { icrafting.sendProgressBarUpdate(this, 1, this.tileEntity.furnaceBurnTime); } if(this.lastItemBurnTime != this.tileEntity.currentItemBurnTime) { icrafting.sendProgressBarUpdate(this, 2, this.tileEntity.currentItemBurnTime); } if(this.lastfluidamout != this.tileEntity.fluidamount){ icrafting.sendProgressBarUpdate(this, 3, this.tileEntity.fluidamount); } if(this.lastfluidid != this.tileEntity.fluidid){ icrafting.sendProgressBarUpdate(this, 4, this.tileEntity.fluidid); } } this.lastCookTime = this.tileEntity.furnaceCookTime; this.lastBurnTime = this.tileEntity.furnaceBurnTime; this.lastItemBurnTime = this.tileEntity.currentItemBurnTime; }
Celle la va juste comparer la valeur actuel à la dernière valeur envoyée au client (qui est enregistrée dans les variables plus haut).
@SideOnly(Side.CLIENT) public void updateProgressBar(int id, int value) { if(id == 0) { this.tileEntity.furnaceCookTime = value; } if(id == 1) { this.tileEntity.furnaceBurnTime = value; } if(id == 2) { this.tileEntity.currentItemBurnTime = value; } if(id == 3) { this.tileEntity.fluidamount = value; } if(id == 4) { this.tileEntity.fluidid = value; } }
Si les valeurs n’étaient pas les même on les update avec celle la (au fait la fonction d’avant apelle une fonction qui envois un packet au client qui appelle cette fonction. #édit : les id sont ceux rentré à la première fonction.
Voila c’est à peut près tout ce que je sais, c’est un peu confu et il ya surement des truc pas très juste ou mal utilisé mais ça ma bien aidé. Si tu veux des détails en plus tu peux demander.
-
D’accord. Je vais tester ça dès que j’ai le temps/courage, et te tiens au courant. Merci.