Created
July 8, 2014 17:07
-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} | |
}; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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