Résolu Player Capability et Gui Rendering problem
-
j’ai créé une capablility a mon joueur qui est basiquement un système de soif Enum Provider tout ce qui va avec le système fonctionne bien comme je le souhaite mais je cherche a écrire les valeurs de ce système de soif a l’écran comme le système utilise un event onPlayerTick pour dépenser l’eau du joueur j’aimerai éviter de passer par des paquet pour récupérer la valeur de l’eau sur le joueur en multiplayer (serveur dédier) pour l’afficher a l’écran par ce que si il doit demander au serveur les valeur a chaque tick multiplier par tout les joueur pour un simple affichage ca me semble un peu exagérer et minecraft.getMinecraft().getCapability() ne pourra pas fonctionner si je ne m’abuse dans ce contexte
Si quelqu’un peut m’éclairer sur la possibilité ou non de ceci et si c’est possible sur la façon dont je pourrait le faire ça m’enlèverai une sale migraine en approche ;^p
ps:ce coup si je fourni pas le code c’est du code fait a 4H du matin c’est pas propre donc pas reutilisable
-
Bonjour,
Il faut forcement un paquet pour synchroniser les valeurs, ce n’est pas possible sans.
Par contre tu n’es pas obligé de synchroniser la valeur à chaque tick. -
oui mais du coup le paquet seras appeler par le gui et le gui il s’update bien a chaque tick? les gui c’est vraiment pas ma tasse de thé je suis plus code technique que interface utilisateur
-
Je Galère avec les packets je comprend pas des masse comment ça marche j’ trois classe pour le système d’eau
public class Water implements IWater{ private float maxWaterLevel = 600F; private float waterLevel = 600.0F; @Override public void consume(float amount) { this.waterLevel -= amount; if (this.waterLevel < 0.0F) this.waterLevel = 0.0F;//make it no go to low } @Override public void fill(float amount) { this.waterLevel += amount; if(this.waterLevel > maxWaterLevel) this.waterLevel = maxWaterLevel;//make it no go too hight } @Override public void set(float amount) { this.waterLevel = amount; } @Override public float getWater() { return this.waterLevel; } @Override public float getMaxWater() { return this.maxWaterLevel; } }
public class WaterProvider implements ICapabilitySerializable<NBTBase>{ @CapabilityInject(IWater.class) public static final Capability<IWater> WATER_CAP = null; private IWater instance = WATER_CAP.getDefaultInstance(); @Override public boolean hasCapability(Capability<?> capability, EnumFacing facing){ return capability == WATER_CAP; } @Override public <T> T getCapability(Capability<T> capability, EnumFacing facing){ return capability == WATER_CAP ? WATER_CAP.<T> cast(this.instance) : null; } @Override public NBTBase serializeNBT(){ return WATER_CAP.getStorage().writeNBT(WATER_CAP, this.instance, null); } @Override public void deserializeNBT(NBTBase nbt){ WATER_CAP.getStorage().readNBT(WATER_CAP, this.instance, null, nbt); } }
public class WaterStorage implements IStorage<IWater>{ @Override public NBTBase writeNBT(Capability<IWater> capability, IWater instance, EnumFacing side) { return new NBTTagFloat(instance.getWater()); } @Override public void readNBT(Capability<IWater> capability, IWater instance, EnumFacing side, NBTBase nbt) { instance.set(((NBTPrimitive) nbt).getFloat()); } }
J’ai une Interface
public interface IWater { public void consume(float points); public void fill(float points); public void set(float points); public float getWater(); public float getMaxWater(); }
et je l’enregistre comme ça dans mon commonProxy
public void load() { MinecraftForge.EVENT_BUS.register(new CapabilityHandler()); CapabilityManager.INSTANCE.register(IWater.class, new WaterStorage(), Water.class); }
Ha et j’ai oublier
public class CapabilityHandler { public static final ResourceLocation WATER_CAP = new ResourceLocation(Reference.MOD_ID, "water"); @SubscribeEvent public void attachCapability(AttachCapabilitiesEvent<Entity> event){ if (!(event.getObject() instanceof EntityPlayer)) return; event.addCapability(WATER_CAP, new WaterProvider()); } }
J’ai essayer de créé un packet :
public class SyncWaterData implements IMessage{ private float water; // We need to initialize our data, so provide a suitable constructor: public SyncWaterData(IWater water) { this.water = water.getWater(); } @Override public void fromBytes(ByteBuf buf) { water = buf.readInt(); } @Override public void toBytes(ByteBuf buf) { buf.writeFloat(water); } public static class Handler implements IMessageHandler<SyncWaterData, IMessage> { @Override public IMessage onMessage(SyncWaterData message, MessageContext ctx) { VirusZMod.proxy.addScheduledTaskClient(() -> handle(message, ctx)); return null; } private void handle(SyncWaterData message, MessageContext ctx) { EntityPlayer player = VirusZMod.proxy.getClientPlayer(); if (player instanceof EntityPlayer) { ((IWater) player.getCapability(WaterProvider.WATER_CAP, null)).getWater(); } } } }
que j’ai enregistrer avec network manager tout ca et j’ai le meme paquet a quelque modif pret qui sert de Requester coter serveur la partie que je trouve pas c’est Comment utiliser ce paquet pour recuperer les donnée dans mon gui
Il y aurait des exemple concret existant parce je suis paumer le la doc a part me donner un migraine ca ma pas vraiment aider j’avoue que les packet et tout ce qui est serveur / HUD / interface graphique c’est pas vraiment mon fort
-
Le plus simple c’est que dans l’handler tu paquets tu assignes la valeur de
message.water
vers la capability.
Comme ça tu aura juste à passer par la capa pour récupérer la valeur depuis le gui. -
Comme ca?
((IWater) player.getCapability(WaterProvider.WATER_CAP, null)).set(message.water);
Le problème c’est que ce paquet comment je l’envoie ou le demande? c’est automatique quand on utilise les capability?
network.registerMessage(SyncWaterData.Handler.class, SyncWaterData.class, 0, Side.CLIENT);
j’ai trouver comme on l’utilisait
new SyncWaterData(player.getCapability(WaterProvider.WATER_CAP, null));
mais je comprend pas ce que tu me dit :c
-
en gros j’ai changer par set au lieu de get mais ça change rien a mon affichage je suis pas sure mais j’ai essayer de print message dans mon handler et ça print jamais ya un truc que je fait mal surement devant mes yeux mais comme les paquets pour moi c’est de la magie noir je suis perdu xD
-
Il faut que tu envoies la valeur depuis le serveur quand elle change.
ClassePrincipale.network.sendTo(ew SyncWaterData(player.getCapability(WaterProvider.WATER_CAP, null)), player);
-
@robin4002 a dit dans Player Capability et Gui Rendering problem :
ClassePrincipale.network.sendTo(ew SyncWaterData(player.getCapability(WaterProvider.WATER_CAP, null)), player);
Merci!!!
pour ceux qui veulent réutiliser le code au dessus vous pouvez mais je préfére prévenir c’est pas très très propre(écrit a 4H du mat corriger a 6H avec 2H sommeil) je vous conseillerait de faire ça par vous même au lieu de copier coller et aussi parce que l’exercice est sur intéressent et que si vous copier coller le code vous apprendrez pas son fonctionnement et le jour ou vous aurez besoin le faire par vous même vous allez galérer et avoir besoin ce jour la de tout réapprendre ;^pPS: ya des erreur dedans je vous laisse les trouver x)