Résolu Problème de persistance avec une capability
-
Bonjour,
J’ai créé une nouvelle Capability représentant la température. Jusque là pas de problème, elle s’incrémente bien lorsque je casse un block (c’était pour tester). Le problème vient quand je me déconnecte et que je me reconnecte je perds toutes les données, rien n’a été sauvegardé sur le serveur. Voici donc les fichiers concernés :
ITemperature.java
package com.capabilities.modcapabilities.temperature; import net.minecraft.entity.player.EntityPlayer; public interface ITemperature { public void setTemperature(float t); public float getTemperature(); public void addTemperature(float t); public void removeTemperature(float t); public void sync(EntityPlayer player); }
Temperature.java
package com.capabilities.modcapabilities.temperature; import com.capabilities.modcapabilities.ModCapabilities; import com.capabilities.modcapabilities.network.TemperaturePacket; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; public class Temperature implements ITemperature { public float temperature; public static int MIN = 0, MAX=100; public Temperature() { } public Temperature(float t) { temperature = t; } @Override public void setTemperature(float t) { if(t>= MIN && t <= MAX) temperature = t; else if(t> MAX) temperature = (float)MAX; else temperature = (float)MIN; } @Override public float getTemperature() { return temperature; } @Override public void addTemperature(float t) { setTemperature(getTemperature()+t); } @Override public void removeTemperature(float t) { setTemperature(getTemperature()-t); } @Override public void sync(EntityPlayer player) //sync data between player and server { TemperaturePacket packet = new TemperaturePacket(temperature); if(!player.world.isRemote) { System.out.println("sync, isRemote ? : no, send to player"); EntityPlayerMP playerMP = (EntityPlayerMP)player; ModCapabilities.network.sendTo(packet, playerMP); } else { System.out.println("sync, isRemote ? : yes, send to server"); ModCapabilities.network.sendToServer(packet); } } }
TemperatureCapability.java
package com.capabilities.modcapabilities.temperature; import com.capabilities.modcapabilities.ModCapabilities; import com.capabilities.modcapabilities.network.TemperaturePacket; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; 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 TemperatureCapability implements ICapabilityProvider, INBTSerializable<NBTTagCompound> { protected ITemperature temperature; protected EntityPlayer player; @Override public NBTTagCompound serializeNBT() { return (NBTTagCompound) ModCapabilities.TEMPERATURE_CAPABILITY.writeNBT(this.temperature, null); } @Override public void deserializeNBT(NBTTagCompound nbt) { ModCapabilities.TEMPERATURE_CAPABILITY.readNBT(this.temperature, null, nbt); } @Override public boolean hasCapability(Capability<?> capability, EnumFacing facing) { // TODO Auto-generated method stub return ModCapabilities.TEMPERATURE_CAPABILITY != null && capability == ModCapabilities.TEMPERATURE_CAPABILITY; } @Override public <T> T getCapability(Capability<T> capability, EnumFacing facing) { return this.hasCapability(capability, facing) ? ModCapabilities.TEMPERATURE_CAPABILITY.cast(this.temperature) : null; } public static void register() { CapabilityManager.INSTANCE.register(ITemperature.class, new TemperatureStorage(), Temperature::new); } public TemperatureCapability(EntityPlayer player) { this.temperature = new Temperature(0.0F); this.player = player; } public ITemperature getTemperatureObj() { return temperature; } }
TemperatureStorage
package com.capabilities.modcapabilities.temperature; import java.util.concurrent.Callable; import com.capabilities.modcapabilities.ModCapabilities; 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.CapabilityInject; public class TemperatureStorage implements Capability.IStorage<ITemperature> { @Override public NBTBase writeNBT(Capability<ITemperature> capability, ITemperature instance, EnumFacing side) { NBTTagCompound nbt = new NBTTagCompound(); nbt.setFloat("temperature", capability.getDefaultInstance().getTemperature()); return nbt; } @Override public void readNBT(Capability<ITemperature> capability, ITemperature instance, EnumFacing side, NBTBase base) { if(base instanceof NBTTagCompound) { NBTTagCompound nbt = (NBTTagCompound)base; capability.getDefaultInstance().setTemperature(nbt.getFloat("temperature")); } } }
La classe principale
package com.capabilities.modcapabilities; import net.minecraft.init.Blocks; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.CapabilityInject; import net.minecraftforge.common.capabilities.CapabilityManager; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod.EventHandler; import net.minecraftforge.fml.common.event.FMLInitializationEvent; import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; import net.minecraftforge.fml.common.network.NetworkRegistry; import net.minecraftforge.fml.common.network.simpleimpl.SimpleNetworkWrapper; import net.minecraftforge.fml.relauncher.Side; import org.apache.logging.log4j.Logger; import com.capabilities.modcapabilities.network.TemperaturePacket; import com.capabilities.modcapabilities.temperature.ITemperature; import com.capabilities.modcapabilities.temperature.Temperature; import com.capabilities.modcapabilities.temperature.TemperatureCapability; import com.capabilities.modcapabilities.temperature.TemperatureStorage; @Mod(modid = ModCapabilities.MODID, name = ModCapabilities.NAME, version = ModCapabilities.VERSION) public class ModCapabilities { @CapabilityInject(ITemperature.class) public static final Capability <ITemperature> TEMPERATURE_CAPABILITY = null; public static final String MODID = "mocapa"; public static final String NAME = "Mod Capabilities"; public static final String VERSION = "1.0"; public static SimpleNetworkWrapper network; private static Logger logger; @EventHandler public void preInit(FMLPreInitializationEvent event) { logger = event.getModLog(); //Register network max range 255 network = NetworkRegistry.INSTANCE.newSimpleChannel("ModCapabilities"); //Server processing network.registerMessage(TemperaturePacket.ServerHandler.class, TemperaturePacket.class, 1, Side.SERVER); if(event.getSide() != Side.SERVER) { //Client processing network.registerMessage(TemperaturePacket.ClientHandler.class, TemperaturePacket.class, 0, Side.CLIENT); } } public void init(FMLInitializationEvent event) { //Register temperature capability TemperatureCapability.register(); } }
Les events
package com.capabilities.modcapabilities; import com.capabilities.modcapabilities.network.TemperaturePacket; import com.capabilities.modcapabilities.temperature.ITemperature; import com.capabilities.modcapabilities.temperature.TemperatureCapability; import com.capabilities.modcapabilities.temperature.TemperatureStorage; import net.minecraft.entity.Entity; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.util.ResourceLocation; import net.minecraft.util.text.TextComponentString; import net.minecraftforge.event.AttachCapabilitiesEvent; import net.minecraftforge.event.entity.player.PlayerEvent; import net.minecraftforge.event.entity.player.PlayerInteractEvent; import net.minecraftforge.event.world.BlockEvent; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod.EventBusSubscriber; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.gameevent.PlayerEvent.PlayerLoggedInEvent; import net.minecraftforge.fml.common.gameevent.PlayerEvent.PlayerLoggedOutEvent; import net.minecraftforge.fml.common.gameevent.PlayerEvent.PlayerRespawnEvent; import net.minecraftforge.fml.common.gameevent.TickEvent.PlayerTickEvent; import net.minecraftforge.fml.relauncher.Side; @Mod.EventBusSubscriber public class CapabilitiesEvent { @SubscribeEvent public static void onAttachCapability(AttachCapabilitiesEvent<Entity> event) { Entity entity = event.getObject(); if(entity instanceof EntityPlayer) { event.addCapability(new ResourceLocation(ModCapabilities.MODID + ":temperature_capability"), new TemperatureCapability((EntityPlayer) entity)); } } @SubscribeEvent public static void onPlayerCloned(PlayerEvent.Clone event) { if(event.isWasDeath()) { if(event.getOriginal().hasCapability(ModCapabilities.TEMPERATURE_CAPABILITY, null)) { //Cloned player has same temperature than old one event.getEntityPlayer().getCapability(ModCapabilities.TEMPERATURE_CAPABILITY, null).setTemperature( event.getOriginal().getCapability(ModCapabilities.TEMPERATURE_CAPABILITY, null).getTemperature());; } } } @SubscribeEvent public static void onPlayerRespawn(PlayerRespawnEvent event) { if(!event.player.world.isRemote) { event.player.getCapability(ModCapabilities.TEMPERATURE_CAPABILITY, null).sync(event.player); } } @SubscribeEvent public static void onPlayerRightClickBlock(BlockEvent.BreakEvent event) { ITemperature temp = event.getPlayer().getCapability(ModCapabilities.TEMPERATURE_CAPABILITY, null); temp.addTemperature(1.0F); temp.sync(event.getPlayer()); event.getPlayer().sendMessage(new TextComponentString("ta temperature : " + (temp.getTemperature()))); } @SubscribeEvent public static void onPlayerLoggedIn(PlayerLoggedInEvent event) { ITemperature temp = event.player.getCapability(ModCapabilities.TEMPERATURE_CAPABILITY, null); temp.sync(event.player); } @SubscribeEvent public static void onPlayerLoggedOut(PlayerLoggedOutEvent event) { ITemperature temp = event.player.getCapability(ModCapabilities.TEMPERATURE_CAPABILITY, null); //TemperaturePacket packet = new TemperaturePacket(temp.getTemperature()); System.out.println("Avant deconnexion : " + temp.getTemperature()); temp.sync(event.player); } }
ScheduledPacketTask .java
package com.capabilities.modcapabilities.network; import com.capabilities.modcapabilities.ModCapabilities; 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 TemperaturePacket message; public ScheduledPacketTask(EntityPlayer player, TemperaturePacket message) { this.player = player; this.message = message; } @Override public void run() { EntityPlayer player = this.player == null ? getPlayer() : this.player; player.getCapability(ModCapabilities.TEMPERATURE_CAPABILITY, null).setTemperature(message.temperature); } @SideOnly(Side.CLIENT) private EntityPlayer getPlayer() { return Minecraft.getMinecraft().player; } }
le paquet
package com.capabilities.modcapabilities.network; import io.netty.buffer.ByteBuf; import net.minecraft.client.Minecraft; import net.minecraft.server.MinecraftServer; import net.minecraft.world.WorldServer; import net.minecraftforge.fml.common.FMLCommonHandler; 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; import net.minecraftforge.fml.server.FMLServerHandler; public class TemperaturePacket implements IMessage { public float temperature; public TemperaturePacket(float temperature) { this.temperature = temperature; } public TemperaturePacket() { } @Override public void fromBytes(ByteBuf buf) { temperature = buf.readFloat(); } @Override public void toBytes(ByteBuf buf) { buf.writeFloat(temperature); } public static class ServerHandler implements IMessageHandler <TemperaturePacket, IMessage>{ @Override public IMessage onMessage(TemperaturePacket message, MessageContext ctx) { System.out.println("Packet recu serveur, temperature = " + message.temperature); ctx.getServerHandler().player.getServerWorld().addScheduledTask(new ScheduledPacketTask(ctx.getServerHandler().player, message)); return null; } } @SideOnly(Side.CLIENT) public static class ClientHandler implements IMessageHandler <TemperaturePacket, IMessage>{ @Override public IMessage onMessage(TemperaturePacket message, MessageContext ctx) { System.out.println("Packet recu client, temperature = " + message.temperature); Minecraft.getMinecraft().addScheduledTask(new ScheduledPacketTask(null, message)); return null; } } }
J’ai suivi ce tuto où j’ai modifié quelques petites choses… Toutes les synchronisations affichent “Packet recu client, temperature = …” même quand je lance le jeu sur le serveur… Merci de votre aide.
-
Dans ton writeNBT et dans ton readNBT remplace
capability.getDefaultInstance()
parinstance
-
Dans ton writeNBT et dans ton readNBT remplace
capability.getDefaultInstance()
parinstance
-
Ah ! Très bien, au moins c’était rapide :beaming_face_with_smiling_eyes:. Merci beaucoup, cela fonctionne aussi bien sur le client que sur le serveur !