Синхронизация capability

Статус
В этой теме нельзя размещать новые ответы.
Версия Minecraft
1.12.2
Создал кастомный инвентарь по туториалу от @Eifel. Настроил рендер слоя на игроке если в инвентаре лежит определённый предмет, всё работает. Только при перезаходе слой перестаёт рендериться, пока не откроешь кастомный инвентарь. Как это исправить? Пакеты сдал разными способами, но видимо я слабо понимаю как в пакете передать данные на другую сторону.
 
Решение
Смешал код из baubles и твой, вроде должно работать:
public class SyncMessage implements IMessage {

    public NBTTagCompound nbt;
    public int playerId;

    public SyncMessage() {}

    public SyncMessage(NBTTagCompound compound, int id) {
       nbt = compound;
       playerId = id;
    }

    @Override
    public void toBytes(ByteBuf buffer) {
       ByteBufUtils.writeTag(buffer, nbt);
       buffer.writeInt(playerId);
    }

    @Override
    public void fromBytes(ByteBuf buffer) {
        nbt = ByteBufUtils.readTag(buffer);
        playerId = buffer.readInt();
    }

    public static class Handler implements IMessageHandler<SyncMessage, IMessage>
    {
        @Override
        public IMessage onMessage(SyncMessage message, MessageContext ctx) {...
Не получается
Эвенты:
@SubscribeEvent
    public void onStartTracking(PlayerEvent.StartTracking event) {
        Entity target = event.getTarget();
        if (target instanceof EntityPlayerMP) {
            for(byte i = 0; i <= 10; i++) {
                NetworkHandler.network.sendToAllTracking(new SyncMessage((EntityPlayer) target, i, target.getCapability(CAPProvider.INVENTORY_CAP, null).getStackInSlot(i)), target);
            }
        }
    }

    @SubscribeEvent
    public void playerJoin(EntityJoinWorldEvent event) {
        Entity entity = event.getEntity();
        if (entity instanceof EntityPlayerMP) {
            EntityPlayerMP player = (EntityPlayerMP) entity;
            for(byte i = 0; i <= 10; i++) {
                NetworkHandler.network.sendToAllTracking(new SyncMessage(player, i, player.getCapability(CAPProvider.INVENTORY_CAP, null).getStackInSlot(i)), player);
            }
        }
    }
Пакет:
public class SyncMessage implements IMessage {

    int playerId;
    byte slot=0;
    ItemStack bauble;

    public SyncMessage() {}

    public SyncMessage(EntityPlayer p, int slot, ItemStack bauble) {
        this.slot = (byte) slot;
        this.bauble = bauble;
        this.playerId = p.getEntityId();
    }

    @Override
    public void toBytes(ByteBuf buffer) {
        buffer.writeInt(playerId);
        buffer.writeByte(slot);
        ByteBufUtils.writeItemStack(buffer, bauble);
    }

    @Override
    public void fromBytes(ByteBuf buffer) {
        playerId = buffer.readInt();
        slot = buffer.readByte();
        bauble = ByteBufUtils.readItemStack(buffer);
    }

    public static class Handler implements IMessageHandler<SyncMessage, IMessage>
    {
        @Override
        public IMessage onMessage(SyncMessage message, MessageContext ctx) {
            Minecraft.getMinecraft().addScheduledTask(new Runnable(){ public void run() {
                World world = Minecraft.getMinecraft().world;
                if (world==null) return;
                Entity p = world.getEntityByID(message.playerId);
                if (p !=null && p instanceof EntityPlayer) {
                    ICAPCustomInventory cap = p.getCapability(CAPProvider.INVENTORY_CAP, null);

                        cap.setStackInSlot(message.slot, message.bauble);

                }
            }});
            return null;
        }
    }
}
Регистрация пакета:
public class NetworkHandler {
    
    public static SimpleNetworkWrapper network;

    public static void init() {
        

        network = NetworkRegistry.INSTANCE.newSimpleChannel(MyMod.MOD_ID);
        
        network.registerMessage(SyncMessage.Handler.class, SyncMessage.class, 2, Side.CLIENT);
        network.registerMessage(SyncMessage.Handler.class, SyncMessage.class, 2, Side.SERVER);
    }   
}
 
7,099
324
1,510
Перегони капу в нбт(через Storage), перешли нбт, на клиенте перегони нбт в капу
 
Сделал вот так
Эвенты:
@SubscribeEvent
    public void onStartTracking(PlayerEvent.StartTracking event) {
        Entity target = event.getTarget();
        if (target instanceof EntityPlayerMP) {

            NBTBase nbt = CAPProvider.INVENTORY_CAP.getStorage().writeNBT(CAPProvider.INVENTORY_CAP, target.getCapability(CAPProvider.INVENTORY_CAP, null), null);
            NetworkHandler.network.sendToAll(new SyncMessage((NBTTagCompound) nbt));

        }
    }

    @SubscribeEvent
    public void playerJoin(EntityJoinWorldEvent event) {
        Entity entity = event.getEntity();
        if (entity instanceof EntityPlayerMP) {
            EntityPlayerMP player = (EntityPlayerMP) entity;
            NBTBase nbt = CAPProvider.INVENTORY_CAP.getStorage().writeNBT(CAPProvider.INVENTORY_CAP, player.getCapability(CAPProvider.INVENTORY_CAP, null), null);
            NetworkHandler.network.sendToAll(new SyncMessage((NBTTagCompound) nbt));

        }
    }
Пакет:
public class SyncMessage implements IMessage {

    public NBTTagCompound nbt;

    public SyncMessage() {}

    public SyncMessage(NBTTagCompound compound) {
       nbt = compound;
    }

    @Override
    public void toBytes(ByteBuf buffer) {
       ByteBufUtils.writeTag(buffer, nbt);
    }

    @Override
    public void fromBytes(ByteBuf buffer) {
        nbt = ByteBufUtils.readTag(buffer);
    }

    public static class Handler implements IMessageHandler<SyncMessage, IMessage>
    {
        @Override
        public IMessage onMessage(SyncMessage message, MessageContext ctx) {
            CAPProvider.INVENTORY_CAP.getStorage().readNBT(CAPProvider.INVENTORY_CAP, ctx.getServerHandler().player.getCapability(CAPProvider.INVENTORY_CAP, null), null, message.nbt);
            return null;
        }
    }
}
Регистрация пакета:
network.registerMessage(SyncMessage.Handler.class, SyncMessage.class, 2, Side.CLIENT);
network.registerMessage(SyncMessage.Handler.class, SyncMessage.class, 2, Side.SERVER);
Ругается на строку в пакете, где я синхронизирую капу. Выкидывало сначала NPE, теперь это SimpleChannelHandlerWrapper exception java.lang.ClassCastException: net.minecraft.client.network.NetHandlerPlayClient cannot be cast to net.minecraft.network.NetHandlerPlayServer
 
7,099
324
1,510
Потому что пакет, отправляемый с сервера и принимаемый на клиенте надо регать на клиенте.

А лучше юзать пакеты CCL и не париться, там очень простое апи, пакеты не надо регать и они весьма бесформенные
 
Пакет:
@Override
        public IMessage onMessage(SyncMessage message, MessageContext ctx) {
           
            System.out.println(message.nbt);          

System.out.println(Minecraft.getMinecraft().player);
            if(message.nbt != null && Minecraft.getMinecraft().player != null)
            CAPProvider.INVENTORY_CAP.getStorage().readNBT(CAPProvider.INVENTORY_CAP, Minecraft.getMinecraft().player.getCapability(CAPProvider.INVENTORY_CAP, null), null, message.nbt);
            return null;
        }
Строка выводит null при перезаходах
 
7,099
324
1,510
Возможно, проблема связана с асинхронной природой пакетной системы в новых версиях. Пакет может придти до того, как клиент создаст у себя игрока
 
1,007
36
206
Смешал код из baubles и твой, вроде должно работать:
public class SyncMessage implements IMessage {

    public NBTTagCompound nbt;
    public int playerId;

    public SyncMessage() {}

    public SyncMessage(NBTTagCompound compound, int id) {
       nbt = compound;
       playerId = id;
    }

    @Override
    public void toBytes(ByteBuf buffer) {
       ByteBufUtils.writeTag(buffer, nbt);
       buffer.writeInt(playerId);
    }

    @Override
    public void fromBytes(ByteBuf buffer) {
        nbt = ByteBufUtils.readTag(buffer);
        playerId = buffer.readInt();
    }

    public static class Handler implements IMessageHandler<SyncMessage, IMessage>
    {
        @Override
        public IMessage onMessage(SyncMessage message, MessageContext ctx) {

            Minecraft.getMinecraft().addScheduledTask(new Runnable(){ public void run() {
                World world = FMLClientHandler.instance().getClient().world;
                if (world==null) return;
                Entity p = world.getEntityByID(message.playerId);
                if (p !=null && p instanceof EntityPlayer) {
                    CAPProvider.INVENTORY_CAP.getStorage().readNBT(CAPProvider.INVENTORY_CAP, p.getCapability(CAPProvider.INVENTORY_CAP, null), null, message.nbt);
                }
            }});
            return null;
        }
    }
}
 
Статус
В этой теме нельзя размещать новые ответы.
Сверху