1.12.2 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.


  • Moddeurs confirmés Rédacteurs Administrateurs

    Dans ton writeNBT et dans ton readNBT remplace capability.getDefaultInstance() par instance


  • Moddeurs confirmés Rédacteurs Administrateurs

    Dans ton writeNBT et dans ton readNBT remplace capability.getDefaultInstance() par instance



  • Ah ! Très bien, au moins c'était rapide 😁. Merci beaucoup, cela fonctionne aussi bien sur le client que sur le serveur !


Log in to reply