Очистка NBT при смерти

Версия Minecraft
1.7.10
1,417
44
594
Добрый день, в общем, начну с кода:
Java:
public class QuestsProperties implements IExtendedEntityProperties {
    
    private final EntityPlayer player;
    NBTTagCompound QuestsLvls = new NBTTagCompound();
    NBTTagCompound QuestsProces = new NBTTagCompound();
    @Override
    public void init(Entity entity, World world) {   
        System.out.println("Test1");
    }
        public QuestsProperties(EntityPlayer player)
    {   
        System.out.println("Test2");
        this.player = player;
    }
    public static final void register(EntityPlayer player)
    {   
        System.out.println("Test3");
        player.registerExtendedProperties(Constants.QuestsOptions, new QuestsProperties(player));
    }
    public static final QuestsProperties get(EntityPlayer player)
    {   
        System.out.println("Test4");
        return (QuestsProperties) player.getExtendedProperties(Constants.QuestsOptions);
    }
    @Override
    public void saveNBTData(NBTTagCompound compound)
    {   
        NBTTagCompound properties = new NBTTagCompound();
        for(int i = 0; i<ConfigCore.ids; i++) {
            properties.setInteger(QuestReg.getName(i), QuestsLvls.getInteger(QuestReg.getName(i)));
            properties.setInteger(QuestReg.getName(i)+"process", QuestsProces.getInteger(QuestReg.getName(i)+"process"));
        }   
         compound.setTag(Constants.QuestsOptions, properties);
    }
    @Override
    public void loadNBTData(NBTTagCompound compound)
    {
        NBTTagCompound properties = (NBTTagCompound) compound.getTag(Constants.QuestsOptions);
        for(int i = 0; i<ConfigCore.ids; i++) {
            QuestsLvls.setInteger(QuestReg.getName(i), properties.getInteger(QuestReg.getName(i)));   
            QuestsProces.setInteger(QuestReg.getName(i)+"process", properties.getInteger(QuestReg.getName(i)+"process"));
        }
    }
    public void addProcess(int i) {
        String research = QuestReg.getName(i);
        System.out.println(research);
        QuestsProces.setInteger(research, 1);
        ProxyServer.attainmentsnetwork.sendTo(new SetQe(research, 1, 1), (EntityPlayerMP) this.player);
    }
    public void OpenQe(int i)
    {
        String research = QuestReg.getName(i);
        System.out.println(research);
        QuestsLvls.setInteger(research, 1);
        ProxyServer.attainmentsnetwork.sendTo(new SetQe(research, 1, 0), (EntityPlayerMP) this.player);
//        if(server)
//        ProxyServer.attainmentsnetwork.sendTo(new SetAttainments(research, lvl+1), (EntityPlayerMP) this.player);
    }
    public void CloseQe(int i)
    {
        String research = QuestReg.getName(i);
        QuestsLvls.setInteger(research, 0);
        ProxyServer.attainmentsnetwork.sendTo(new SetQe(research, 2, 0), (EntityPlayerMP) this.player);
    }
    public int GiveQe(int i)
    {
        String research = QuestReg.getName(i);
        return QuestsLvls.getInteger(research);
    }
    public int getQel(int lvl) {
        int a=0;
        for(int i = 0; i<ConfigCore.ids; i++) {
            System.out.println(i+" номер "+QuestReg.getName(i)+" с lvl: " + QuestsLvls.getInteger(QuestReg.getName(i)));
            if(QuestsLvls.getInteger(QuestReg.getName(i))==lvl) {
                a++;
            }
        }
        return a;
    }
    public int[] GiveQeAll()
    {
        int[] arr = new int[getQel(1)];
        int a=0;
        for(int i = 0; i<ConfigCore.ids; i++) {
            if(QuestsLvls.getInteger(QuestReg.getName(i))==1) {
                arr[a]=i;
                a++;
            }
        }
        return arr;
    }

    public void copy(QuestsProperties questsProperties) {
        QuestsLvls = questsProperties.QuestsLvls;
        QuestsProces = questsProperties.QuestsProces;
        System.out.println("Send" + QuestsLvls.getInteger(QuestReg.getName(4)));
        ProxyServer.attainmentsnetwork.sendTo(new SetQe(QuestsLvls, 3), (EntityPlayerMP) this.player);
        ProxyServer.attainmentsnetwork.sendTo(new SetQe(QuestsProces, 2), (EntityPlayerMP) this.player);
    }

    public void ClientSet(String key, int value) {
        QuestsLvls.setInteger(key, value);       
    }
    public void ClientNBT(NBTTagCompound nbt, int type) {
        if(type==2) {       
            QuestsProces = nbt;
        }
        if(type==3) {
            System.out.println("Get" + nbt.getInteger(QuestReg.getName(4)));   
            this.QuestsLvls = nbt;
            System.out.println("Get" + QuestsLvls.getInteger(QuestReg.getName(4)));   
        }   
    }
        public void ClientSetProcess(String key, int value) {
        QuestsProces.setInteger(key, value);       
    }
}
Пакет:
Код:
public class SetQe implements IMessage {
    
    String key;
    int value, type;
    NBTTagCompound nbt;
    
    public SetQe() {
    }   
    public SetQe(String key, int value, int type) {
        this.type = type;
        this.key = key;
        this.value = value;
    }
    public SetQe(NBTTagCompound nbt, int type) {
        this.type = type;
        this.nbt = nbt;
    }
    
    @Override
    public void toBytes(ByteBuf buf) {
        buf.writeInt(type);
        if(type>=2) {
            ByteBufUtils.writeTag(buf, nbt);
        } else {
            ByteBufUtils.writeUTF8String(buf, key);
            buf.writeInt(value);           
        }
    }

    @Override
    public void fromBytes(ByteBuf buf) {
        type = buf.readInt();
        if(type>=2) {
            nbt = ByteBufUtils.readTag(buf);
        } else {
        key = ByteBufUtils.readUTF8String(buf);
        value = buf.readInt();
        }
    }
    
    public static class Handler implements IMessageHandler<SetQe, IMessage> {

        @Override
        public IMessage onMessage(SetQe packet, MessageContext message) {
            //NBTTagCompound AttainmentsLvls = packet.AttainmentsLvls;
            int type = packet.type;
            EntityClientPlayerMP player = Minecraft.getMinecraft().thePlayer;
            if(type>=2) {
                NBTTagCompound nbt = packet.nbt;
                if(type==3) {
                    System.out.println("Packet"+nbt.getInteger(QuestReg.getName(4)));
                }
                QuestsProperties.get(player).ClientNBT(nbt, type);       
            } else {
                String key = packet.key;
                int value = packet.value;
                if(type==0) {
                    QuestsProperties.get(player).ClientSet(key, value);               
                } else {
                    QuestsProperties.get(player).ClientSetProcess(key, value);
                }               
            }
            
            return null;
    }
}
}
Ну и эвенты:
Код:
    @SubscribeEvent
    public void onEntityConstructing(EntityConstructing e) {
        if (e.entity instanceof EntityPlayer && e.entity.getExtendedProperties(Constants.QuestsOptions) == null)
            QuestsProperties.register((EntityPlayer) e.entity);
    }
    @SubscribeEvent
    public void onClonePlayer(PlayerEvent.Clone e) {
        QuestsProperties.get(e.entityPlayer).copy(QuestsProperties.get(e.original));
    }
    @SubscribeEvent
    public void onLivingUpdate(LivingUpdateEvent event) {
        if (event.entity instanceof EntityPlayer) {
            EntityPlayer player = (EntityPlayer) event.entity;
            //QuestsProperties.get(player).onUpdate();
        }
    }

Проблема. После смотри данные сохраняются, отправляется пакет на клиент, все хорошо. Но при возражении, после отправки всех пакетов вызывается еще что-то и оно очищает nbt под ноль. Подскажите, пожалуйста, почему не сохраняется?
 
1,159
38
544
Я думаю, дело в том, что при возрождении старая сущность удаляется, а взамен ее создается новая. Естественно с пустым NBT в IEEP. Если я вас верно понял, то вам нужно сохранять NBT старой сущности после смерти до момента возрождения. Если так, то здесь в найдете ответ
 

timaxa007

Модератор
5,831
409
672
@RareScrap У него это есть и именно в этом месте и проблема.
@MagTemTenebrius, я с таким не сталкивался. Но в copy (у меня) я не отправляю пакеты и у меня по другим условиям отправляются подобное. Я лишь могу посоветовать, сделать одну отправку пакета, а не два пакета, т.е. соеденить их.
 
1,417
44
594
Я думаю, дело в том, что при возрождении старая сущность удаляется, а взамен ее создается новая. Естественно с пустым NBT в IEEP. Если я вас верно понял, то вам нужно сохранять NBT старой сущности после смерти до момента возрождения. Если так, то здесь в найдете ответ
Все стоит кб
сделать одну отправку пакета, а не два пакета
Не очень понял. Я отправляю пакеты при изменении с сервера и при респавне, а ты о каких пакетах? (Пакет использую 1, там просто переменная type отвечает за то, что я передаю или это нбт или таг)
 

timaxa007

Модератор
5,831
409
672
ты о каких пакетах?
ProxyServer.attainmentsnetwork.sendTo(new SetQe(QuestsLvls, 3), (EntityPlayerMP) this.player);
ProxyServer.attainmentsnetwork.sendTo(new SetQe(QuestsProces, 2), (EntityPlayerMP) this.player);
Я имел виду превратить эти два пакета в один и отправлять только один с двумя значениями.
А свои типая на следующий тик отправляю.
 

timaxa007

Модератор
5,831
409
672
Знает кто как поправить?
Точно я не знаю, но как я написал ранее:
у меня по другим условиям отправляются
В update тике проверяю текущая переменная не равна предыдущей, то отправлять пакет с этой переменной.
Java:
    @Override
    public void update(EntityLivingBase entity) {
        super.update(entity);

        if (entity instanceof EntityPlayerMP) {
            if (mana_last != mana) SMTMagic.network.sendTo(new MessageMana(mana), (EntityPlayerMP)entity);
            if (mana_max_last != mana_max) SMTMagic.network.sendTo(new MessageManaMax(mana_max), (EntityPlayerMP)entity);
        }

        if (mana_last != mana) mana_last = mana;
        if (mana_max_last != mana_max) mana_max_last = mana_max;
    }
Другого способа как помочь тебе сейчас я не знаю.
 
1,417
44
594
В update тике проверяю текущая переменная не равна предыдущей, то отправлять пакет с этой переменной.
Да, тоже была такая идея, но когда ты задаешь значения?
mana_last и mana_max_last

И да, НБТ отличаются друг от друга, если в них разное значение тага? Или надо получать значение тага?
 

timaxa007

Модератор
5,831
409
672
но когда ты задаешь значения?
mana_last и mana_max_last
Эм... Типа при инициализации класса (вне какого-либо метода) все значения на 0, а изменяются переменные только в методе update, даже в saveNBTData не сохраняю и loadNBTData не загружаю. Даже можно сказать что при первом тике после инициализации отправляются эти два пакета (т.е. есть возможность не использовать EntityJoinWorldEvent, но я как-то забыл даже это проверить без него, как будет время проверю как-нибудь).

можно вообще не слать пакеты при изменении, раз апдат в плеере сам все сделает, верно?
Ну, как-бы мой код, как раз это и делает (только у меня IEEP для Маны разделён на две части: на Common и на Server (в ней просто эти две переменные с отправкой пакета), хотя на самом деле: Client и Common).
 
1,417
44
594
Да, тоже была такая идея, но когда ты задаешь значения?
mana_last и mana_max_last
А, тьфу, не подумал о том куске кода, перепутал чуть, теперь все понял, извиняюсь.

Все же остался вопрос, если я буду сравнивать нбт с собой, то если у 1 будет другое значение тага, он заметит это?
 

timaxa007

Модератор
5,831
409
672
Ну, если всё правильно делать, то он изменяет значение. (set это не append) Но если будет разница в кодировки или типа того, то у тебя будут два тега.
 
2,505
81
397
Вставлю свои 5 копеек насчет всего этого.

Зачем хранить данные в нбт формате? Это очень не оптимально.

Отправлять пакет в клоне не нужно. В этот момент данные копируются с одного объекта игрока в другой на сервере, а на клиенте еще старый объект. Поэтому на клиенте сначала все присваивается старому объекту, а когда-то потом создается новый объект игрока.

Захардкоженый датавотчер (сравнение с prev) выглядит не очень круто. Особенно, если там примитивный обработчик пакета, то лучше сделать нормальный датавотчер, который будет сам отслеживать изменения и отправлять все одним пакетом. Профитно, если таких простых полей (которые синхронятся без особой обработки на клиенте) много.

если я буду сравнивать нбт с собой
То будет плохо. Еще одна причина не использовать нбт для хранения данных.

Тебе нужен EntityJoinWorldEvent. С клиента отправляется запрос - сервер синхронит все, что нужно.
 
1,417
44
594
С НБТ, как по мне, меньше гемора. Причину я понял. спасибо
Отправлять пакет в клоне не нужно. В этот момент данные копируются с одного объекта игрока в другой на сервере, а на клиенте еще старый объект. Поэтому на клиенте сначала все присваивается старому объекту, а когда-то потом создается новый объект игрока.
Датаватчер не выгоден в данной ситуации, если только хукать и расширять его.

Тебе нужен EntityJoinWorldEvent. С клиента отправляется запрос - сервер синхронит все, что нужно.
Хорошо, спасибо, брольшое
 
Сверху