Résolu Synchronisation Capabilities
-
Bonjour,
J’ai crée une capability qui me sert à matérialiser le mana d’un joueur.
J’ai ensuite créer une commande utilisant ce mana. De plus le mana est affiché sur le HUD.
Le problème est que quand j’utilise cette commande, le mana baisse pendant une fraction de seconde avant de reprendre sa valeur initialise (c’est à peine visible.)Code de l’execute de la commande :
@Override public void execute(MinecraftServer server, ICommandSender sender, String[] args) throws CommandException { if(sender instanceof EntityPlayer) { EntityPlayer player = (EntityPlayer)sender; if(player.hasCapability(ProjectMod.MANA_CAP, null)) { ManaCapabilities cap = player.getCapability(ProjectMod.MANA_CAP, null); if(cap.getMana() >= 10) { if(player.getHealth() < player.getMaxHealth()) { cap.setMana(cap.getMana() - 10); player.heal(2); cap.sync(); sender.sendMessage(new TextComponentString(TextFormatting.GREEN+"[PMod] "+I18n.format("projectmod.spells.completed"))); } else { sender.sendMessage(new TextComponentString(TextFormatting.RED+"[PMod] "+I18n.format("projectmod.spells.errors.heal"))); } } else { sender.sendMessage(new TextComponentString(TextFormatting.RED+"[PMod] "+I18n.format("projectmod.spells.errors.mana"))); } } } }
Si vous voulez d’autres codes, je peux vous les fournir.
Merci d’avance
-
Salut,
Je ne vois pas de problème de ce côté.
Si la mana baisse bien, il y a peut-être quelque chose qui la remonte ? -
C’est ce que je me suis dit et la seule chose qui modifie la valeur de ma mana, outre cette commande, c’est ce timer :
@SubscribeEvent public static void onPlayerTick(TickEvent.PlayerTickEvent event) { if(event.phase == TickEvent.Phase.END) { if(event.player.hasCapability(ProjectMod.MANA_CAP, null)) { ManaCapabilities cap = event.player.getCapability(ProjectMod.MANA_CAP, null); cap.setTimer(cap.getTimer() - 1); if(cap.getTimer() < 0) { if(cap.getMana() < 100) { cap.setMana(cap.getMana() + 1); } cap.setTimer(100); } cap.sync(); } } }```
-
Là on est sur une remontée toutes les 5 secondes.
Quand tu réduis la mana, il faudrait remettre à 0 le timer au même moment.
-
J’ai ajouté un
cap.setTimer(100);
au niveau de l’execute de la commande
Mais ça change rien… -
Tu peux envoyer le code de la classe ManaCapabilities ?
-
Salut,
Premièrement je ne suis pas d’accord sur le fait qu’il y ai besoin de remettre le timer de régénération de mana à 0 lors de l’utilisation de la commande. En soit, dans un système sort/mana, le fait d’utiliser un sort doit utiliser de la mana mais pas bloquer la régénération de celle-ci.Ensuite c’est de quel côté que la mana se régénère automatiquement ? Client-side only ou serveur/client ? C’est quelque chose qu’il serait bon de savoir.
Dans tous les cas ça serait effectivement bien d’avoir la classe
ManaCapabilities
, et la classe du paquet te permettant de synchroniser tout ce petit monde. -
Normalement c’est en serveur/client.
ManaCapabilities :
package fr.lavapower.projectmod.capabilities; import java.util.concurrent.Callable; import fr.lavapower.projectmod.ProjectMod; import fr.lavapower.projectmod.packets.PacketCapabilities; import net.minecraft.client.resources.I18n; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.nbt.NBTBase; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.EnumFacing; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.CapabilityManager; import net.minecraftforge.common.capabilities.ICapabilityProvider; import net.minecraftforge.common.util.INBTSerializable; public class ManaCapabilities implements ICapabilityProvider, INBTSerializable<NBTTagCompound> { public int mana; public int timer; private EntityPlayer player; public static void register() { CapabilityManager.INSTANCE.register(ManaCapabilities.class, new ManaCapabilities.Storage(), new ManaCapabilities.Factory()); } public ManaCapabilities(EntityPlayer entityPlayer) { this.mana = 0; this.timer = 100; this.player = entityPlayer; } public void sync() { PacketCapabilities packet = new PacketCapabilities(this.getMana(), 1); PacketCapabilities packet2 = new PacketCapabilities(this.getTimer(), 2); if(!this.player.world.isRemote) { EntityPlayerMP playerMP = (EntityPlayerMP)player; ProjectMod.network.sendTo(packet, playerMP); ProjectMod.network.sendTo(packet2, playerMP); } else { ProjectMod.network.sendToServer(packet); ProjectMod.network.sendToServer(packet2); } } @Override public boolean hasCapability(Capability capability, EnumFacing facing) { return ProjectMod.MANA_CAP != null && capability == ProjectMod.MANA_CAP; } @Override public <T> T getCapability(Capability <T>capability, EnumFacing facing) { return ProjectMod.MANA_CAP != null && capability == ProjectMod.MANA_CAP ? (T)this : null; } @Override public NBTTagCompound serializeNBT() { NBTTagCompound compound = new NBTTagCompound(); compound.setInteger("Mana", this.getMana()); compound.setInteger("Timer", this.getTimer()); return compound; } @Override public void deserializeNBT(NBTTagCompound compound) { this.setMana(compound.getInteger("Mana")); this.setTimer(compound.getInteger("Timer")); } public void setMana(int mana) { this.mana = mana; } public int getMana() { return this.mana; } public void setTimer(int timer) { this.timer = timer; } public int getTimer() { return this.timer; } public static class Storage implements Capability.IStorage<ManaCapabilities> { @Override public NBTBase writeNBT(Capability<ManaCapabilities> capability, ManaCapabilities instance, EnumFacing side) { return null; } @Override public void readNBT(Capability<ManaCapabilities> capability, ManaCapabilities instance, EnumFacing side, NBTBase nbt) { } } public static class Factory implements Callable<ManaCapabilities> { @Override public ManaCapabilities call() throws Exception { return null; } } }
Mon packet :
package fr.lavapower.projectmod.packets; import io.netty.buffer.ByteBuf; import net.minecraft.client.Minecraft; import net.minecraft.server.MinecraftServer; import net.minecraft.util.IThreadListener; import net.minecraftforge.fml.common.network.simpleimpl.IMessage; import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; public class PacketCapabilities implements IMessage { public int cap; public int type; public PacketCapabilities() {} public PacketCapabilities(int cap, int type) { this.cap = cap; this.type = type; } @Override public void fromBytes(ByteBuf buf) { this.cap = buf.readInt(); this.type = buf.readInt(); } @Override public void toBytes(ByteBuf buf) { buf.writeInt(this.cap); buf.writeInt(this.type); } public static class ServerHandler implements IMessageHandler <PacketCapabilities, IMessage>{ @Override public IMessage onMessage(PacketCapabilities message, MessageContext ctx) { ctx.getServerHandler().player.mcServer.addScheduledTask(new ScheduledPacketTask(ctx.getServerHandler().player, message)); return null; } } @SideOnly(Side.CLIENT) public static class ClientHandler implements IMessageHandler <PacketCapabilities, IMessage>{ @Override public IMessage onMessage(PacketCapabilities message, MessageContext ctx) { Minecraft.getMinecraft().addScheduledTask(new ScheduledPacketTask(null, message)); return null; } } }
Il faut savoir que mon packet sert à cette capability mais aussi à une autre :x
Du coup, la variable type du packet permet de savoir qu’es ce qui est synchronisé.
(Bon autant, c’est pas une bonne méthode :x ) -
Personne ? Je peux fournir toutes les sources s’il faut :x (même si y’a pas que ça dedans)
-
Salut,
Première question : pourquoi tes classesManaCapabilities.Storage
etManaCapabilities.Factory
ont encore leur implémentation par défaut ?Seconde questions : pourquoi synchroniser le timer ? Et même si tu as besoin du timer client-side, pourquoi synchroniser la mana et le timer via deux envoie de paquets différents ?
Troisième question : pourquoi dans ta méthode
ManaCapabilities#sync
, tu envoies des paquets au serveur ? C’est un peu bizarre, le client n’a rien à envoyer au serveur à priori, sinon il pourrait modifier son mana et se le mettre au max tout le temps.Quatrième question : Qu’est-ce que la classe
ScheduledPacketTask
? J’aimerai bien voir ce que tu fais dedans -
Question 1 : J’ai suivi le tuto :x
Question 2 : Effectivement, c’est réglé
Question 3 : De même c’est réglé
Question 4 :package fr.lavapower.projectmod.packets; import fr.lavapower.projectmod.ProjectMod; import net.minecraft.client.Minecraft; import net.minecraft.entity.player.EntityPlayer; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; public class ScheduledPacketTask implements Runnable { private EntityPlayer player; private PacketCapabilities message; public ScheduledPacketTask(EntityPlayer player, PacketCapabilities message) { this.player = player; this.message = message; } @Override public void run() { EntityPlayer player = this.player == null ? getPlayer() : this.player; switch(message.type) { case 0: player.getCapability(ProjectMod.SPELL_CAP, null).setSpell(message.cap); break; case 1: player.getCapability(ProjectMod.MANA_CAP, null).setMana(message.cap); break; } } @SideOnly(Side.CLIENT) private EntityPlayer getPlayer() { return Minecraft.getMinecraft().player; } }
En réglant les deux trucs en haut, la synchro quand on utilise le sort est bonne mais faut utiliser quel event pour que quand le joueur se connecte, y’a une synchro ?
(Ca le faisait avant mais c’est plus le cas, du coup quand on utilise le mana, y’a la synchro et le mana passe à 90 alors que pour le client il était à 0)C’est bon j’ai trouvé