Skip to content

Commit

Permalink
Add the ability to store an NBT compound in a given ItemStack.
Browse files Browse the repository at this point in the history
  • Loading branch information
aadnk committed Jul 17, 2013
1 parent aa9d84c commit 9448e06
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,22 @@ public static <T> NbtWrapper<T> fromBase(NbtBase<T> base) {
}
}

/**
* Set the NBT compound tag of a given item stack.
* <p>
* The item stack must be a wrapper for a CraftItemStack. Use
* {@link MinecraftReflection#getBukkitItemStack(ItemStack)} if not.
* @param stack - the item stack.
* @param compound - the new NBT compound.
*/
public static void setItemTag(ItemStack stack, NbtCompound compound) {
if (!MinecraftReflection.isCraftItemStack(stack))
throw new IllegalArgumentException("Stack must be a CraftItemStack.");

StructureModifier<NbtBase<?>> modifier = getStackModifier(stack);
modifier.write(0, compound);
}

/**
* Construct a wrapper for an NBT tag stored (in memory) in an item stack. This is where
* auxillary data such as enchanting, name and lore is stored. It doesn't include the items
Expand All @@ -127,16 +143,7 @@ public static NbtWrapper<?> fromItemTag(ItemStack stack) {
if (!MinecraftReflection.isCraftItemStack(stack))
throw new IllegalArgumentException("Stack must be a CraftItemStack.");

Object nmsStack = MinecraftReflection.getMinecraftItemStack(stack);

if (itemStackModifier == null) {
itemStackModifier = new StructureModifier<Object>(nmsStack.getClass(), Object.class, false);
}

// Use the first and best NBT tag
StructureModifier<NbtBase<?>> modifier = itemStackModifier.
withTarget(nmsStack).
withType(MinecraftReflection.getNBTBaseClass(), BukkitConverters.getNbtConverter());
StructureModifier<NbtBase<?>> modifier = getStackModifier(stack);
NbtBase<?> result = modifier.read(0);

// Create the tag if it doesn't exist
Expand All @@ -147,6 +154,25 @@ public static NbtWrapper<?> fromItemTag(ItemStack stack) {
return fromBase(result);
}

/**
* Retrieve a structure modifier that automatically marshalls between NBT wrappers and their NMS counterpart.
* @param stack - the stack that will store the NBT compound.
* @return The structure modifier.
*/
private static StructureModifier<NbtBase<?>> getStackModifier(ItemStack stack) {
Object nmsStack = MinecraftReflection.getMinecraftItemStack(stack);

if (itemStackModifier == null) {
itemStackModifier = new StructureModifier<Object>(nmsStack.getClass(), Object.class, false);
}

// Use the first and best NBT tag
return itemStackModifier.
withTarget(nmsStack).
withType(MinecraftReflection.getNBTBaseClass(),
BukkitConverters.getNbtConverter());
}

/**
* Initialize a NBT wrapper.
* @param handle - the underlying net.minecraft.server object to wrap.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,21 +26,29 @@
import java.io.DataOutput;
import java.io.DataOutputStream;

import org.bukkit.Material;
import org.bukkit.craftbukkit.v1_6_R2.inventory.CraftItemFactory;
import org.bukkit.inventory.ItemStack;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;

import com.comphenix.protocol.BukkitInitialization;
import com.comphenix.protocol.utility.MinecraftReflection;
import com.comphenix.protocol.wrappers.nbt.io.NbtBinarySerializer;

@RunWith(org.powermock.modules.junit4.PowerMockRunner.class)
@PrepareForTest(CraftItemFactory.class)
public class NbtFactoryTest {
@BeforeClass
public static void initializeBukkit() throws IllegalAccessException {
BukkitInitialization.initializePackage();
BukkitInitialization.initializeItemMeta();
}

@Test
public void testFromStream() {
WrappedCompound compound = WrappedCompound.fromName("tag");

compound.put("name", "Test Testerson");
compound.put("age", 42);

Expand All @@ -59,4 +67,18 @@ public void testFromStream() {
assertEquals(compound.getInteger("age"), cloned.getInteger("age"));
assertEquals(compound.getList("nicknames"), cloned.getList("nicknames"));
}

@Test
public void testItemTag() {
ItemStack test = new ItemStack(Material.GOLD_AXE);
ItemStack craftTest = MinecraftReflection.getBukkitItemStack(test);

NbtCompound compound = NbtFactory.ofCompound("tag");
compound.put("name", "Test Testerson");
compound.put("age", 42);

NbtFactory.setItemTag(craftTest, compound);

assertEquals(compound, NbtFactory.fromItemTag(craftTest));
}
}

0 comments on commit 9448e06

Please sign in to comment.