package cc.nsg.bukkit.syncnbt;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import me.dpohvar.powernbt.nbt.NBTBase;
import me.dpohvar.powernbt.nbt.NBTContainerItem;
import me.dpohvar.powernbt.nbt.NBTTagByte;
import me.dpohvar.powernbt.nbt.NBTTagByteArray;
import me.dpohvar.powernbt.nbt.NBTTagCompound;
import me.dpohvar.powernbt.nbt.NBTTagDouble;
import me.dpohvar.powernbt.nbt.NBTTagFloat;
import me.dpohvar.powernbt.nbt.NBTTagInt;
import me.dpohvar.powernbt.nbt.NBTTagIntArray;
import me.dpohvar.powernbt.nbt.NBTTagList;
import me.dpohvar.powernbt.nbt.NBTTagLong;
import me.dpohvar.powernbt.nbt.NBTTagShort;
import me.dpohvar.powernbt.nbt.NBTTagString;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.PlayerInventory;
import org.bukkit.material.MaterialData;
/**
* This is a helper class to save/restore NBT data with PowerNBT.
* @author Stefan Berggren
*
*/
public class NBTData {
Connection connection = null;
Database db = null;
public NBTData(Database db) {
this.connection = db.getConnection();
this.db = db;
}
/**
* Saves the content (and all sub tags) of the given NBTTagCompound to the database
* @param compound
* @param item_pos
* @param parent_id
* @param player
* @throws SQLException
*/
public void saveExtraNBTData(NBTTagCompound compound, int item_pos, int parent_id, Player player) throws SQLException {
db.openConnection();
for (NBTBase nbtBase : compound) {
String sql = "INSERT INTO syncnbt_nbtdata (inventory_pos, parent_id, name, type, data, player_name) VALUES(?,?,?,?,?,?)";
PreparedStatement statement = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
statement.setInt(1, item_pos);
statement.setInt(2, parent_id);
statement.setString(3, nbtBase.getName());
statement.setString(4, nbtBase.getType().name());
statement.setString(6, player.getName());
switch (nbtBase.getType().name()) {
case "COMPOUND":
statement.setByte(5, (byte) 0);
break;
case "LIST":
statement.setBytes(5, ((NBTTagList)nbtBase).toBytes());
break;
case "BYTE":
statement.setInt(5, new Integer(nbtBase.toString()).intValue());
break;
case "INT":
statement.setInt(5, new Integer(nbtBase.toString()).intValue());
break;
case "SHORT":
statement.setShort(5, new Integer(nbtBase.toString()).shortValue());
break;
case "DOUBLE":
statement.setDouble(5, new Double(nbtBase.toString()).doubleValue());
break;
case "LONG":
statement.setLong(5, new Long(nbtBase.toString()));
break;
case "FLOAT":
statement.setFloat(5, new Float(nbtBase.toString()));
break;
case "STRING":
statement.setString(5, new String(nbtBase.toString()));
break;
case "BYTEARRAY":
statement.setBytes(5, ((NBTTagByteArray)nbtBase).toBytes());
break;
case "INTARRAY":
statement.setString(5, ((NBTTagIntArray)nbtBase).toString());
System.out.println("INTARRAY: " + ((NBTTagIntArray)nbtBase).toString() + " saved as a string!");
break;
default:
statement.setString(5, "");
System.out.println("Error: " + nbtBase.getType().name() + " not defined!");
break;
}
statement.executeUpdate();
if (nbtBase.getType().name().equals("COMPOUND")) {
int id = -2;
ResultSet rs = statement.getGeneratedKeys();
if (rs.next()) {
id = rs.getInt(1);
}
saveExtraNBTData((NBTTagCompound) nbtBase, item_pos, id, player);
}
}
}
/**
* Restores the NBT data from the database and overwrites the players local inventory
* @param item_pos
* @param parent_id
* @return
* @throws SQLException
*/
public NBTTagCompound restoreExtraNBTTags(int item_pos, int parent_id, Player player) throws SQLException {
db.openConnection();
NBTTagCompound compound = new NBTTagCompound();
String sql_nbt = "SELECT * FROM syncnbt_nbtdata WHERE inventory_pos = ? AND parent_id = ? AND player_name = ?";
PreparedStatement statement = connection.prepareStatement(sql_nbt, Statement.RETURN_GENERATED_KEYS);
statement.setInt(1, item_pos);
statement.setInt(2, parent_id);
statement.setString(3, player.getName());
ResultSet res = statement.executeQuery();
while (res.next()) {
int id = res.getInt("id");
String name = res.getString("name");
String type = res.getString("type");
switch (type) {
case "COMPOUND": // java7
NBTTagCompound rc = restoreExtraNBTTags(item_pos, id, player);
compound.set(name, rc);
break;
case "LIST":
byte[] data_list = res.getBytes("data");
NBTTagList list = new NBTTagList();
list.fromBytes(data_list);
compound.set(name, list);
break;
case "BYTE":
byte data_byte = res.getByte("data");
NBTTagByte b = new NBTTagByte();
b.set(data_byte);
compound.set(name, b);
break;
case "INT":
int data_int = res.getInt("data");
NBTTagInt i = new NBTTagInt();
i.set(data_int);
compound.set(name, i);
break;
case "SHORT":
short data_short = res.getShort("data");
NBTTagShort sh = new NBTTagShort();
sh.set(data_short);
compound.set(name, sh);
break;
case "DOUBLE":
int data_double = res.getInt("data");
NBTTagDouble d = new NBTTagDouble();
d.set(data_double);
compound.set(name, d);
break;
case "LONG":
long data_long = res.getLong("data");
NBTTagLong l = new NBTTagLong();
l.set(data_long);
compound.set(name, l);
break;
case "FLOAT":
float data_float = res.getFloat("data");
NBTTagFloat f = new NBTTagFloat();
f.set(data_float);
compound.set(name, f);
break;
case "STRING":
String data_str = res.getString("data");
NBTTagString s = new NBTTagString();
s.set(data_str);
compound.set(name, s);
break;
/* case "INTARRAY":
int[] data_inta = res.getBytes("data");
NBTTagIntArray ia = new NBTTagIntArray();
s.set(data_str);
compound.set(name, s);
break;*/
case "BYTEARRAY":
byte[] data_bytea = res.getBytes("data");
NBTTagByteArray ba = new NBTTagByteArray();
ba.set(data_bytea);
compound.set(name, ba);
break;
default:
System.out.println("Error: " + type + " not defined!");
break;
}
}
return compound;
}
@SuppressWarnings("deprecation")
public void walkInventory(PlayerInventory inventory, Player player, ItemStack is, int slot) {
db.openConnection();
int amount = is.getAmount();
short durability = is.getDurability();
int type = is.getTypeId();
byte data = is.getData().getData();
db.saveItem(slot, player.getName(), amount, durability, type, data);
NBTContainerItem con = null;
switch (slot) {
case -100:
con = new NBTContainerItem(inventory.getHelmet());
break;
case -101:
con = new NBTContainerItem(inventory.getChestplate());
break;
case -102:
con = new NBTContainerItem(inventory.getLeggings());
break;
case -103:
con = new NBTContainerItem(inventory.getBoots());
break;
default:
con = new NBTContainerItem(inventory.getItem(slot));
break;
}
NBTTagCompound compound = con.getTag();
if (compound == null) return;
try {
saveExtraNBTData(compound, slot, -1, player);
} catch (SQLException e) {
e.printStackTrace();
}
}
@SuppressWarnings("deprecation")
public void restoreInventory(Player player) {
db.openConnection();
PlayerInventory inventory = player.getInventory();
Connection connection = db.getConnection();
try {
String sql = "SELECT * FROM syncnbt_items WHERE player_name = ?";
PreparedStatement statement = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
statement.setString(1, player.getName());
ResultSet res = statement.executeQuery();
while (res.next()) {
int amount = res.getInt("amount");
short durability = res.getShort("durability");
int type = res.getInt("type");
byte data = res.getByte("data");
int slot = res.getInt("slot");
ItemStack item = new ItemStack(type, amount, durability);
item.setData(new MaterialData(data));
NBTContainerItem con = null;
switch (slot) {
case -100:
inventory.setHelmet(item);
con = new NBTContainerItem(player.getInventory().getHelmet());
break;
case -101:
inventory.setChestplate(item);
con = new NBTContainerItem(player.getInventory().getChestplate());
break;
case -102:
inventory.setLeggings(item);
con = new NBTContainerItem(player.getInventory().getLeggings());
break;
case -103:
inventory.setBoots(item);
con = new NBTContainerItem(player.getInventory().getBoots());
break;
default:
inventory.setItem(slot, item);
con = new NBTContainerItem(player.getInventory().getItem(slot));
break;
}
NBTTagCompound rc = restoreExtraNBTTags(slot, -1, player);
if (rc.size() > 0) {
con.setTag(rc);
}
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
String sql = "DELETE FROM syncnbt_items WHERE player_name = ?";
PreparedStatement statement = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
statement.setString(1, player.getName());
statement.execute();
} catch (SQLException e1) {
e1.printStackTrace();
}
try {
String sql = "DELETE FROM syncnbt_nbtdata WHERE player_name = ?";
PreparedStatement statement = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
statement.setString(1, player.getName());
statement.execute();
} catch (SQLException e1) {
e1.printStackTrace();
}
}
public void saveInventory(Player player) {
// Player inventory (not armor)
PlayerInventory inventory = player.getInventory();
for (int slot = 0; slot < inventory.getSize(); slot++) {
ItemStack is = inventory.getItem(slot);
if (is == null) continue;
walkInventory(inventory, player, is, slot);
}
// Player armor
ItemStack is = player.getInventory().getHelmet();
if (is != null) {;
walkInventory(inventory, player, is, -100);
is.setType(Material.AIR); // clear helmet
}
is = player.getInventory().getChestplate();
if (is != null) {;
walkInventory(inventory, player, is, -101);
is.setType(Material.AIR); // clear chest
}
is = player.getInventory().getLeggings();
if (is != null) {;
walkInventory(inventory, player, is, -102);
is.setType(Material.AIR); // clear legs
}
is = player.getInventory().getBoots();
if (is != null) {;
walkInventory(inventory, player, is, -103);
is.setType(Material.AIR); // clear boots
}
inventory.clear();
}
}