Skip to content

Instantly share code, notes, and snippets.

@aadnk
Created July 8, 2014 17:07
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save aadnk/e703968f7961c69be497 to your computer and use it in GitHub Desktop.
Save aadnk/e703968f7961c69be497 to your computer and use it in GitHub Desktop.
AttributeStorage example (required) - store the content of a chest directly in its item stack.
package com.comphenix.example;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import org.bukkit.Material;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.yaml.snakeyaml.external.biz.base64Coder.Base64Coder;
import com.comphenix.example.NbtFactory.NbtCompound;
import com.comphenix.example.NbtFactory.NbtList;
import com.comphenix.example.NbtFactory.StreamOptions;
import com.google.common.io.ByteStreams;
import com.google.common.io.OutputSupplier;
public final class ItemSerialization {
private ItemSerialization() {
// Not constructable
}
@SuppressWarnings("deprecation")
public static String serializeInventory(Inventory source) throws IOException {
NbtCompound container = NbtFactory.createCompound();
NbtList items = NbtFactory.createList();
for (int i = 0; i < source.getSize(); i++) {
ItemStack stack = source.getItem(i);
NbtCompound nbt = NbtFactory.createCompound();
// Manually save the data in an item stack
if (stack != null && stack.getType() != Material.AIR) {
NbtCompound tag = NbtFactory.fromItemTag(stack);
nbt.put("id", (short)stack.getTypeId());
nbt.put("data", (short)stack.getDurability());
nbt.put("count", (byte)stack.getAmount());
if (tag != null) {
nbt.put("tag", tag);
}
} else {
nbt.put("id", (short)0); // AIR
}
items.add(nbt);
}
// Save items
container.put("items", items);
ByteArrayOutputStream output = new ByteArrayOutputStream();
NbtFactory.saveStream(container,
getSupplier(output), StreamOptions.GZIP_COMPRESSION);
return Base64Coder.encodeLines(output.toByteArray());
}
public static void deserializeInventory(String data, Inventory destination) throws IOException {
NbtCompound container = NbtFactory.fromStream(
ByteStreams.newInputStreamSupplier(Base64Coder.decodeLines(data)),
StreamOptions.GZIP_COMPRESSION
);
int index = 0;
// Each entry should be an NbtCompound
for (Object element : container.getList("items", true)) {
NbtCompound nbt = (NbtCompound) element;
System.out.println("Stack tag: " + nbt);
@SuppressWarnings("deprecation")
ItemStack stack = new ItemStack(
nbt.getShort("id", (short)0),
nbt.getByte("count", (byte)0),
nbt.getShort("data", (short)0));
if (nbt.containsKey("tag")) {
// Necessary to be able to manipulate NBT tags
stack = NbtFactory.getCraftItemStack(stack);
NbtFactory.setItemTag(stack, nbt.getMap("tag", false));
}
destination.setItem(index++, stack);
}
}
private static OutputSupplier<OutputStream> getSupplier(final ByteArrayOutputStream output) {
return new OutputSupplier<OutputStream>() {
@Override
public OutputStream getOutput() throws IOException {
return output;
}
};
}
}
package com.comphenix.example;
import java.io.IOException;
import java.util.Map;
import java.util.UUID;
import org.bukkit.Material;
import org.bukkit.entity.HumanEntity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryCloseEvent;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.event.player.PlayerItemHeldEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.PlayerInventory;
import org.bukkit.plugin.java.JavaPlugin;
import com.google.common.collect.Maps;
public class MobileChest extends JavaPlugin implements Listener {
private static final UUID KEY_STORED_INVENTORY = UUID.fromString("373b3cb4-6430-46bf-bac0-28c21bc63ae3");
private Map<String, Integer> viewingHeldInventory = Maps.newHashMap();
@Override
public void onEnable() {
super.onEnable();
getServer().getPluginManager().registerEvents(this, this);
// TODO Handle the case of a user moving a chest into itself
}
@EventHandler
public void onPlayerMarkChest(PlayerItemHeldEvent e) {
Player player = e.getPlayer();
ItemStack held = player.getInventory().getItem(e.getNewSlot());
if (held != null && Material.CHEST.equals(held.getType())) {
String data = AttributeStorage.newTarget(held, KEY_STORED_INVENTORY).getData(null);
Inventory heldInventory = getServer().createInventory(player, InventoryType.CHEST);
try {
// Only if we have data to deserialize
if (data != null) {
ItemSerialization.deserializeInventory(data, heldInventory);
}
player.openInventory(heldInventory);
viewingHeldInventory.put(player.getName(), e.getNewSlot());
} catch (IOException ex) {
throw new RuntimeException(ex);
}
}
}
@EventHandler
public void onInventoryClosed(InventoryCloseEvent e) {
HumanEntity entity = e.getPlayer();
// Only players may use mobile inventories
if (entity instanceof Player && e.getView().getTopInventory() == e.getInventory()) {
closeHeldInventory((Player) entity, e.getInventory());
}
}
@EventHandler
public void onPlayerQuit(PlayerQuitEvent e) {
closeHeldInventory(e.getPlayer(),
e.getPlayer().getOpenInventory().getTopInventory());
}
@Override
public void onDisable() {
// TODO Close all inventories here
super.onDisable();
}
private void closeHeldInventory(Player player, Inventory inventory) {
// Ensure the inventory is of the correct type
if (inventory == null || inventory.getType() != InventoryType.CHEST) {
return;
}
Integer itemSlot = viewingHeldInventory.remove(player.getName());
PlayerInventory playerInventory = player.getInventory();
if (itemSlot != null) {
// Save it
try {
AttributeStorage storage = AttributeStorage.newTarget(playerInventory.getItem(itemSlot), KEY_STORED_INVENTORY);
storage.setData(
ItemSerialization.serializeInventory(inventory)
);
playerInventory.setItem(itemSlot, storage.getTarget());
} catch (IOException ex) {
throw new RuntimeException(ex);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment