Не восстанавливает инвентарь после смерти.

Версия Minecraft
1.7.10
API
Forge
Сделал я команду, которая восстанавливает вещи после смерти. Выдаёт - проверено, тем, что создана команда сохраняющая в нбт игрока инвентарь.
Сделал эвент, который при смерти игрока записывал бы в нбт его вещи. Вроде работает. Но вещи по команде не выдаются. При восстановлении все значения в нбт тупо null. Заранее спасибо!
И, да, хандлер зареган, всё как надо. Команды учился делать по одному из местных гайдов.

ForgeEventHandler:
    @SubscribeEvent
    public void onDeath(LivingDeathEvent e) {
        if(e.entityLiving instanceof EntityPlayer) {
            EntityPlayer player = (EntityPlayer)e.entityLiving;
            ItemStack[] aslots = player.inventory.armorInventory;
            ItemStack[] islots = player.inventory.mainInventory;

            saveSlots("Armor", aslots, player.getEntityData());
            saveSlots("Inventory", islots, player.getEntityData());
        }
    }
    
    private void saveSlots(String name, ItemStack[] slots, NBTTagCompound nbt) {
        NBTTagList list = new NBTTagList();

        for (int i = 0; i < slots.length; i++) {
            if (slots[i] != null) {
                NBTTagCompound nbt1 = new NBTTagCompound();
                nbt1.setByte("Slot", (byte)i);
                slots[i].writeToNBT(nbt1);
                list.appendTag(nbt1);
            }
        }
        
        nbt.setTag("Inventory", list);
    }
Регистрация хандлера:
        new ForgeEventHandler();
        MinecraftForge.EVENT_BUS.register(new ForgeEventHandler());
Команда восстановления инвентаря:
    private final String
    NAME = "it will restore your inventory after death",
    ALIAS1 = "ir",
    ALIAS2 = "invrest",
    USAGE = "/invrest";
    
    @Override
    public String getCommandName() {
        return NAME;
    }

    @Override
    public String getCommandUsage(ICommandSender sender) {
        return USAGE;
    }

    @Override
    public void processCommand(ICommandSender sender, String[] args) {
        sender.addChatMessage((IChatComponent)new ChatComponentText((Object)EnumChatFormatting.AQUA + "Restoring inventory..."));
        EntityPlayer player = (EntityPlayer)sender;
        if(isInventoryEmpty(player)) {
            ItemStack[] aslots = getSlots("Armor", player.getEntityData());
            ItemStack[] islots = getSlots("Inventory", player.getEntityData());
            
            player.inventory.armorInventory = aslots;
            player.inventory.mainInventory = islots;
            
            clearSlots(player.getEntityData());
            sender.addChatMessage((IChatComponent)new ChatComponentText((Object)EnumChatFormatting.AQUA + "Restoring done."));
        } else
            sender.addChatMessage((IChatComponent)new ChatComponentText((Object)EnumChatFormatting.RED + "Restoring can't complete.Inventory isn't empty."));
            
    }

    private ItemStack[] getSlots(String name, NBTTagCompound nbt) {
        ItemStack[] slots = new ItemStack[(name.equalsIgnoreCase("armor") ? 4 : 36)];
        NBTTagList list = nbt.getTagList(name, 10);
        
        for (int i = 0; i < list.tagCount(); i++) {
            NBTTagCompound nbt1 = (NBTTagCompound)list.getCompoundTagAt(i);
            byte b0 = nbt1.getByte("Slot");

            if (b0 >= 0 && b0 < slots.length) {
                slots[b0] = ItemStack.loadItemStackFromNBT(nbt1);
            }
        }
        return slots;
    }
    
    private void clearSlots(NBTTagCompound nbt) {
        nbt.setTag("Armor", new NBTTagList());
        nbt.setTag("Inventory", new NBTTagList());
    }

    public boolean isInventoryEmpty(EntityPlayer player) {
        ItemStack[] aslots = player.inventory.armorInventory;
        ItemStack[] islots = player.inventory.mainInventory;
        
        for(ItemStack is : aslots)
            if(is != null) return false;
        for(ItemStack is : islots)
            if(is != null) return false;
        
        return true;
    }
    
    @Override
    public boolean canCommandSenderUseCommand(ICommandSender sender) {
        return sender instanceof EntityPlayer ? MinecraftServer.getServer().getConfigurationManager().func_152596_g(((EntityPlayer) sender).getGameProfile()) : false;
    }

    @Override
    public List<String> getCommandAliases() {
        List<String> aliases = new ArrayList<String>();
        aliases.add(ALIAS1);
        aliases.add(ALIAS2);
        return aliases;
    }
Команда сохранения инвентаря:
    private final String
    NAME = "it will save your inventory",
    ALIAS1 = "is",
    ALIAS2 = "invsave",
    USAGE = "/invsave";
    
    @Override
    public String getCommandName() {
        return NAME;
    }

    @Override
    public String getCommandUsage(ICommandSender sender) {
        return USAGE;
    }

    @Override
    public void processCommand(ICommandSender sender, String[] args) {
        sender.addChatMessage((IChatComponent)new ChatComponentText((Object)EnumChatFormatting.AQUA + "Saving inventory..."));
        EntityPlayer player = (EntityPlayer)sender;
        ItemStack[] aslots = player.inventory.armorInventory;
        ItemStack[] islots = player.inventory.mainInventory;

        saveSlots("Armor", aslots, player.getEntityData());
        saveSlots("Inventory", islots, player.getEntityData());
        
        sender.addChatMessage((IChatComponent)new ChatComponentText((Object)EnumChatFormatting.AQUA + "Saving done."));
    }
    
    private void saveSlots(String name, ItemStack[] slots, NBTTagCompound nbt) {
        NBTTagList list = new NBTTagList();

        for (int i = 0; i < slots.length; i++) {
            if (slots[i] != null) {
                NBTTagCompound nbt1 = new NBTTagCompound();
                nbt1.setByte("Slot", (byte)i);
                slots[i].writeToNBT(nbt1);
                list.appendTag(nbt1);
            }
        }
        
        nbt.setTag("Inventory", list);
    }
    
    @Override
    public boolean canCommandSenderUseCommand(ICommandSender sender) {
        return sender instanceof EntityPlayer ? MinecraftServer.getServer().getConfigurationManager().func_152596_g(((EntityPlayer) sender).getGameProfile()) : false;
    }

    @Override
    public List<String> getCommandAliases() {
        List<String> aliases = new ArrayList<String>();
        aliases.add(ALIAS1);
        aliases.add(ALIAS2);
        return aliases;
    }
 
Решение
Данные о сохранённом инвентаре ты сохраняешь на уже мёртвом игроке, который потом в мире пересоздаётся уже с новыми nbt-данными. Чтобы заставить это работать, тебе надо будет сохранять данные инвентаря в WorldSavedData.
1,560
86
204
Данные о сохранённом инвентаре ты сохраняешь на уже мёртвом игроке, который потом в мире пересоздаётся уже с новыми nbt-данными. Чтобы заставить это работать, тебе надо будет сохранять данные инвентаря в WorldSavedData.
 
Оффтоп, но чем тебе не угодил /gamerule keepInventory true? Ещё твоя команда дюпает вещи)
Ну, если злоупотреблять ею - то да, дюпает.А представь если ты умер и могила с твоими вещами или сами вещи забаговались и улетели в пустоту?
который потом в мире пересоздаётся уже с новыми nbt-данными.
Вон оно чё, Михалыч! Спасибо, не знал)
 
Если кому-то пригодится, решил я это так:

ForgeEventHandler:
    @SubscribeEvent
    public void onDeath(LivingDeathEvent e) {
        if(e.entityLiving instanceof EntityPlayer) {
            EntityPlayer player = (EntityPlayer)e.entityLiving;
            WorldSavedData wsd = new SavedInventory("Armor", player.inventory.armorInventory);
            ((SavedInventory)wsd).writeToNBT(SavedInventory.nbttagmod);
            player.worldObj.mapStorage.setData(player.getDisplayName() + "A", wsd);
            wsd = new SavedInventory("Inventory", player.inventory.mainInventory);
            ((SavedInventory)wsd).writeToNBT(SavedInventory.nbttagmod);
            player.worldObj.mapStorage.setData(player.getDisplayName() + "I", wsd);
        }
    }
Команда восстановления инвентаря:
    private final String
    NAME = "it will restore your inventory after death",
    ALIAS1 = "ir",
    ALIAS2 = "invrest",
    USAGE = "/invrest <d/s>";
    
    @Override
    public String getCommandName() {
        return NAME;
    }

    @Override
    public String getCommandUsage(ICommandSender sender) {
        return USAGE;
    }

    @Override
    public void processCommand(ICommandSender sender, String[] args) {
        if(args.length < 1 && args.length > 1) {
            sender.addChatMessage((IChatComponent)new ChatComponentText((Object)EnumChatFormatting.RED + "Missing argument."));
            return;
        } else if(!args[0].equalsIgnoreCase("d") && !args[0].equalsIgnoreCase("s")) {
            sender.addChatMessage((IChatComponent)new ChatComponentText((Object)EnumChatFormatting.RED + "Invalid argument."));
            return;
        }
        sender.addChatMessage((IChatComponent)new ChatComponentText((Object)EnumChatFormatting.AQUA + "Restoring inventory..."));
        EntityPlayer player = (EntityPlayer)sender;
        if(isInventoryEmpty(player)) {
            ItemStack[] aslots = new ItemStack[4];
            ItemStack[] islots = new ItemStack[36];
            if(args[0].equalsIgnoreCase("d")) {
                MapStorage mp = player.worldObj.mapStorage;
                SavedInventory adata = (SavedInventory) mp.loadData(SavedInventory.class, player.getDisplayName() + "A");
                if(adata != null) {
                    adata.readFromNBT(SavedInventory.nbttagmod);
                    aslots = adata.getStacks();
                }
                SavedInventory idata = (SavedInventory) mp.loadData(SavedInventory.class, player.getDisplayName() + "I");
                if(idata != null) {
                    idata.readFromNBT(SavedInventory.nbttagmod);
                    islots = idata.getStacks();
                }
            } else if(args[0].equalsIgnoreCase("s")) {
                aslots = getSlots("Armor", player.getEntityData());
                islots = getSlots("Inventory", player.getEntityData());
            } else {
                sender.addChatMessage((IChatComponent)new ChatComponentText((Object)EnumChatFormatting.RED + "Invalid argument."));
            }
            
            player.inventory.armorInventory = aslots;
            player.inventory.mainInventory = islots;
            
            clearSlots(player.getEntityData());
            sender.addChatMessage((IChatComponent)new ChatComponentText((Object)EnumChatFormatting.AQUA + "Restoring done."));
        } else
            sender.addChatMessage((IChatComponent)new ChatComponentText((Object)EnumChatFormatting.RED + "Restoring can't complete.Inventory isn't empty."));   
    }

    private ItemStack[] getSlots(String name, NBTTagCompound nbt) {
        ItemStack[] slots = new ItemStack[(name.equalsIgnoreCase("armor") ? 4 : 36)];
        NBTTagList list = nbt.getTagList(name, 10);
        
        for (int i = 0; i < list.tagCount(); i++) {
            NBTTagCompound nbt1 = (NBTTagCompound)list.getCompoundTagAt(i);
            byte b0 = nbt1.getByte("Slot");

            if (b0 >= 0 && b0 < slots.length) {
                slots[b0] = ItemStack.loadItemStackFromNBT(nbt1);
            }
        }
        return slots;
    }
    
    private void clearSlots(NBTTagCompound nbt) {
        nbt.setTag("Armor", new NBTTagList());
        nbt.setTag("Inventory", new NBTTagList());
    }

    public boolean isInventoryEmpty(EntityPlayer player) {
        ItemStack[] aslots = player.inventory.armorInventory;
        ItemStack[] islots = player.inventory.mainInventory;
        
        for(ItemStack is : aslots)
            if(is != null) return false;
        for(ItemStack is : islots)
            if(is != null) return false;
        
        return true;
    }
    
    @Override
    public boolean canCommandSenderUseCommand(ICommandSender sender) {
        return sender instanceof EntityPlayer ? MinecraftServer.getServer().getConfigurationManager().func_152596_g(((EntityPlayer) sender).getGameProfile()) : false;
    }

    @Override
    public List<String> getCommandAliases() {
        List<String> aliases = new ArrayList<String>();
        aliases.add(ALIAS1);
        aliases.add(ALIAS2);
        return aliases;
    }
 
167
10
69
На форуме есть слив кода от тимахи, при котором помеченные вещи сами сохраняются после смерти, куда удобнее и без дюпов, чем прописывать команду. Нужно слегка переделать, чтобы фулл сохранять.
 
1,560
86
204
А представь если ты умер и могила с твоими вещами или сами вещи забаговались и улетели в пустоту?
/gamerule keepInventory true просто не даёт выпасть предметам и при смерти сохраняет весь инвентарь в игроке.
 
3,005
192
592
Мне кажется, или сохранять в WSD это костыль? Просто нужно при клоне передать твои nbt новому челику и все?
 
Сверху