Saving player inventory

HcgRandon picture HcgRandon · Mar 21, 2012 · Viewed 8.4k times · Source

Working on a command allowing to transfer worlds, I'm trying to save the player inventory.

public void savePlayerInv(Player p, World w){
    File playerInvConfigFile = new File(plugin.getDataFolder() + File.separator + "players" + File.separator + p.getName(), "inventory.yml");
    FileConfiguration pInv = YamlConfiguration.loadConfiguration(playerInvConfigFile);
    PlayerInventory inv = p.getInventory();
    int i = 0;

    for (ItemStack stack : inv.getContents()) {
        //increment integer
        i++;
        String startInventory = w.getName() + ".inv." + Integer.toString(i);

        //save inv
        pInv.set(startInventory + ".amount", stack.getAmount());
        pInv.set(startInventory + ".durability", Short.toString(stack.getDurability()));
        pInv.set(startInventory + ".type", stack.getTypeId());
        //pInv.set(startInventory + ".enchantment", stack.getEnchantments());
        //TODO add enchant saveing
    }

    i = 0;
    for (ItemStack armor : inv.getArmorContents()){
            i++;
            String startArmor = w.getName() + ".armor." + Integer.toString(i);

            //save armor
            pInv.set(startArmor + ".amount", armor.getAmount());
            pInv.set(startArmor + ".durability", armor.getDurability());
            pInv.set(startArmor + ".type", armor.getTypeId());
            //pInv.set(startArmor + ".enchantment", armor.getEnchantments());
    }

    //save exp
    if (p.getExp() != 0) {
            pInv.set(w.getName() + ".exp", p.getExp());
    }
}

The problem is on line 130:

pInv.set(startInventory + ".amount", stack.getAmount());

I get this stacktrace:

2012-03-21 13:23:25 [SEVERE] null
org.bukkit.command.CommandException: Unhandled exception executing command 'wtp' in plugin Needs v1.0
at org.bukkit.command.PluginCommand.execute(PluginCommand.java:42)
at org.bukkit.command.SimpleCommandMap.dispatch(SimpleCommandMap.java:166)
at org.bukkit.craftbukkit.CraftServer.dispatchCommand(CraftServer.java:461)
at net.minecraft.server.NetServerHandler.handleCommand(NetServerHandler.java:818)
at net.minecraft.server.NetServerHandler.chat(NetServerHandler.java:778)
at net.minecraft.server.NetServerHandler.a(NetServerHandler.java:761)
at net.minecraft.server.Packet3Chat.handle(Packet3Chat.java:33)
at net.minecraft.server.NetworkManager.b(NetworkManager.java:229)
at net.minecraft.server.NetServerHandler.a(NetServerHandler.java:112)
at net.minecraft.server.NetworkListenThread.a(NetworkListenThread.java:78)
at net.minecraft.server.MinecraftServer.w(MinecraftServer.java:554)
at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:452)
at net.minecraft.server.ThreadServerApplication.run(SourceFile:490)
    Caused by: java.lang.NullPointerException
at com.devoverflow.improved.needs.commands.CommandWorldtp.savePlayerInv(CommandWorldtp.java:130)
at com.devoverflow.improved.needs.commands.CommandWorldtp.onCommand(CommandWorldtp.java:60)
at org.bukkit.command.PluginCommand.execute(PluginCommand.java:40)
... 12 more

Answer

Perdog picture Perdog · Mar 21, 2012

When you do inv.getContents(), you retrieve every slot in the player inventory, including the empty slots. These empty slots return null because there is nothing in them.

To fix, add an if statement right after you start the for loop:

for (ItemStack stack : inv.getContents()) {
    if (stack == null) continue;
    // And keep everything else the same
}

The problem you might encounter later would be replacing everything in the exact same slot it came from. I suggest using a HashMap or something to keep track of which slot the item came from.