Let Bukkit serialize (some) inventories...

Since ConfigurationSerializable, there's no need to manually serialize
items anymore, and thus we let Bukkit serialize player inventories for
when players join arenas.

However, the "repairables" in the soft-restore mechanism still use the
now obsolete SerializableItem and SerializableInventory classes, and
should perhaps be rewritten.

Note that for 1.0, it may still be necessary to write a custom means
of serializing items, since we don't know if a given implementation
supports native serialization (however it should be possible to rely
on Bukkit's in the Bukkit-specific classes).
This commit is contained in:
Andreas Troelsen
2013-06-10 00:44:56 +02:00
parent c23e01e1dd
commit ffe270511c
3 changed files with 74 additions and 119 deletions
+1 -1
View File
@@ -1,7 +1,7 @@
name: MobArena name: MobArena
author: garbagemule author: garbagemule
main: com.garbagemule.MobArena.MobArena main: com.garbagemule.MobArena.MobArena
version: 0.94.4.98.2 version: 0.94.4.98.3
softdepend: [Spout,Towny,Heroes,MagicSpells,Vault] softdepend: [Spout,Towny,Heroes,MagicSpells,Vault]
commands: commands:
ma: ma:
+12 -2
View File
@@ -792,7 +792,12 @@ public class ArenaImpl implements Arena
mp.update(); mp.update();
// And update the inventory as well. // And update the inventory as well.
inventoryManager.storeInventory(p); try {
inventoryManager.storeInv(p);
} catch (Exception e) {
e.printStackTrace();
Messenger.severe("Failed to store inventory for player " + p.getName() + "!");
}
} }
@Override @Override
@@ -858,7 +863,12 @@ public class ArenaImpl implements Arena
private void restoreInvAndExp(Player p) { private void restoreInvAndExp(Player p) {
inventoryManager.clearInventory(p); inventoryManager.clearInventory(p);
inventoryManager.restoreInventory(p); try {
inventoryManager.restoreInv(p);
} catch (Exception e) {
e.printStackTrace();
Messenger.severe("Failed to restore inventory for player " + p.getName() + "!");
}
rewardManager.grantRewards(p); rewardManager.grantRewards(p);
if (!settings.getBoolean("keep-exp", false)) { if (!settings.getBoolean("keep-exp", false)) {
@@ -2,8 +2,11 @@ package com.garbagemule.MobArena.util.inventory;
import java.io.*; import java.io.*;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory; import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryView; import org.bukkit.inventory.InventoryView;
@@ -15,7 +18,6 @@ import com.garbagemule.MobArena.framework.Arena;
public class InventoryManager public class InventoryManager
{ {
private static String EXT = ".inv";
private File dir; private File dir;
private Map<Player,ItemStack[]> items, armor; private Map<Player,ItemStack[]> items, armor;
@@ -27,54 +29,57 @@ public class InventoryManager
this.armor = new HashMap<Player,ItemStack[]>(); this.armor = new HashMap<Player,ItemStack[]>();
} }
/** public void storeInv(Player p) throws IOException {
* Store a player's inventory in memory and in a file. // Avoid overwrites
* @param p a player if (items.containsKey(p)) return;
* @return true, if the inventory was stored, false if it already existed
*/
public boolean storeInventory(Player p) {
if (items.containsKey(p) && armor.containsKey(p)) {
return false;
}
// Store the inventory in memory // Fetch the player's items and armor
PlayerInventory inv = p.getInventory(); ItemStack[] items = p.getInventory().getContents();
ItemStack[] memItems = inv.getContents(); ItemStack[] armor = p.getInventory().getArmorContents();
ItemStack[] memArmor = inv.getArmorContents();
items.put(p, memItems);
armor.put(p, memArmor);
// And save it to a file // Store them in memory
saveToFile(p); this.items.put(p, items);
this.armor.put(p, armor);
// And on disk
File file = new File(dir, p.getName());
YamlConfiguration config = new YamlConfiguration();
config.set("items", items);
config.set("armor", armor);
config.save(file);
// And clear the inventory
clearInventory(p); clearInventory(p);
return true;
} }
/** public void restoreInv(Player p) throws FileNotFoundException, IOException, InvalidConfigurationException {
* Restore a player's inventory from memory or from a file // Grab the file on disk
* Note that this method is idempotent; calling it multiple times will File file = new File(dir, p.getName());
* not duplicate player items or anything like that.
* @param p a player
* @return true, if the inventory was restored successfully, false otherwise
*/
public boolean restoreInventory(Player p) {
ItemStack[] memItems = items.remove(p);
ItemStack[] memArmor = armor.remove(p);
// Restore from inventory if possible // Try to grab the items from memory first
if (memItems != null && memArmor != null) { ItemStack[] items = this.items.remove(p);
PlayerInventory inv = p.getInventory(); ItemStack[] armor = this.armor.remove(p);
inv.setContents(memItems); // If we can't restore from memory, restore from file
inv.setArmorContents(memArmor); if (items == null || armor == null) {
YamlConfiguration config = new YamlConfiguration();
config.load(file);
new File(dir, p.getName() + EXT).delete(); // Get the items and armor lists
List<?> itemsList = config.getList("items");
List<?> armorList = config.getList("armor");
return true; // Turn the lists into arrays
items = itemsList.toArray(new ItemStack[itemsList.size()]);
armor = armorList.toArray(new ItemStack[armorList.size()]);
} }
// Otherwise, load from file // Set the player inventory contents
return loadFromFile(p); p.getInventory().setContents(items);
p.getInventory().setArmorContents(armor);
// Delete the file
file.delete();
} }
/** /**
@@ -98,59 +103,6 @@ public class InventoryManager
} }
} }
private boolean saveToFile(Player p) {
File file = new File(dir, p.getName() + EXT);
// If the file exists, encourage restoring first.
if (file.exists()) {
return false;
}
try {
SerializableInventory inv = new SerializableInventory(p.getInventory());
FileOutputStream fos = new FileOutputStream(file);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(inv);
oos.close();
return true;
}
catch (Exception e) {
e.printStackTrace();
return false;
}
}
private boolean loadFromFile(Player p) {
File file = new File(dir, p.getName() + EXT);
// If the file doesn't exist, we can't restore from it!
if (!file.exists()) {
return false;
}
try {
FileInputStream fis = new FileInputStream(file);
ObjectInputStream ois = new ObjectInputStream(fis);
Object o = ois.readObject();
ois.close();
SerializableInventory inv = (SerializableInventory) o;
SerializableInventory.loadContents(p, inv);
file.delete();
return true;
}
catch (Exception e) {
e.printStackTrace();
return false;
}
}
public static boolean hasEmptyInventory(Player p) { public static boolean hasEmptyInventory(Player p) {
ItemStack[] inventory = p.getInventory().getContents(); ItemStack[] inventory = p.getInventory().getContents();
ItemStack[] armor = p.getInventory().getArmorContents(); ItemStack[] armor = p.getInventory().getArmorContents();
@@ -170,38 +122,31 @@ public class InventoryManager
return true; return true;
} }
/**
* Restore a player's inventory from file
* @param plugin MobArena instance
* @param p a player
* @return true, if the inventory was restored successfully, false otherwise
*/
public static boolean restoreFromFile(MobArena plugin, Player p) { public static boolean restoreFromFile(MobArena plugin, Player p) {
File dir = new File(plugin.getDataFolder(), "inventories");
File file = new File(dir, p.getName() + EXT);
// If the file doesn't exist, we can't restore from it!
if (!file.exists()) {
return false;
}
try { try {
FileInputStream fis = new FileInputStream(file); // Grab the file and load the config
ObjectInputStream ois = new ObjectInputStream(fis); File dir = new File(plugin.getDataFolder(), "inventories");
File file = new File(dir, p.getName());
YamlConfiguration config = new YamlConfiguration();
config.load(file);
Object o = ois.readObject(); // Get the items and armor lists
ois.close(); List<?> itemsList = config.getList("items");
List<?> armorList = config.getList("armor");
SerializableInventory inv = (SerializableInventory) o; // Turn the lists into arrays
SerializableInventory.loadContents(p, inv); ItemStack[] items = itemsList.toArray(new ItemStack[itemsList.size()]);
ItemStack[] armor = armorList.toArray(new ItemStack[armorList.size()]);
// Set the player inventory contents
p.getInventory().setContents(items);
p.getInventory().setArmorContents(armor);
// Delete files
file.delete(); file.delete();
return true; return true;
} } catch (Exception e) {
catch (Exception e) {
e.printStackTrace();
return false; return false;
} }
} }