/**
   * Determine if this workaround is required.
   *
   * @return TRUE if we must use this workaround, FALSE otherwise.
   */
  public static boolean isRequired() {
    Boolean result = IS_REQUIRED;

    if (result != null) {
      return result;
    }

    try {
      // Used to check if custom NBT data survives the round trip
      NbtCompound proof =
          NbtFactory.ofCompound("", Collections.singletonList(NbtFactory.of("value", "TEST")));

      ItemStack source = new ItemStack(Material.IRON_AXE);
      ItemStack stored =
          CompoundStore.getNativeStore(source, "com.comphenix.test").saveCompound(proof);

      StreamSerializer rawSerializer = new StreamSerializer();
      SpigotSafeSerializer safeSerializer = new SpigotSafeSerializer();

      // We are testing the raw serializer here
      ItemStack roundTrip =
          safeSerializer.deserializeItemStack(rawSerializer.serializeItemStack(stored));
      NbtCompound extracted =
          CompoundStore.getNativeStore(roundTrip, "com.comphenix.test").loadCompound();

      // Did it survive unscathed?
      result = !Objects.equal(proof, extracted);
      IS_REQUIRED = result;
      return result;

    } catch (IOException e) {
      throw new RuntimeException("Unexpected error during round trip test.", e);
    }
  }
  @Override
  public void serializeItemStack(DataOutputStream output, ItemStack stack) throws IOException {
    // Speed things up if the workaround is not required
    if (!isRequired()) {
      super.serializeItemStack(output, stack);
      return;
    }
    NbtCompound tag =
        stack != null && stack.getType() != Material.AIR
            ? NbtFactory.asCompound(NbtFactory.fromItemTag(stack))
            : null;

    // Note that we can't write the stack data directly, as 1.8 switched to sending a
    // item name instead of an item ID.
    if (tag != null) {
      ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
      DataOutputStream dataStream = new DataOutputStream(byteStream);
      ItemStack withoutTag =
          new ItemStack(stack.getType(), stack.getAmount(), stack.getDurability());

      // This will write the stack as normal, without its tag compound and the tag field length
      super.serializeItemStack(dataStream, withoutTag);
      output.write(byteStream.toByteArray(), 0, byteStream.size() - 2);
      serializeCompound(output, tag);

    } else {
      // Write the stack as normal
      super.serializeItemStack(output, stack);
    }
  }
Пример #3
0
  /**
   * 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 material, damage
   * value or count.
   *
   * <p>The item stack must be a wrapper for a CraftItemStack. Use {@link
   * MinecraftReflection#getCraftItemStack(ItemStack)} if not.
   *
   * @param stack - the item stack.
   * @return A wrapper for its NBT tag.
   */
  public static NbtWrapper<?> fromItemTag(ItemStack stack) {
    checkItemStack(stack);

    StructureModifier<NbtBase<?>> modifier = getStackModifier(stack);
    NbtBase<?> result = modifier.read(0);

    // Create the tag if it doesn't exist
    if (result == null) {
      result = NbtFactory.ofCompound("tag");
      modifier.write(0, result);
    }
    return fromBase(result);
  }
  /**
   * Read an ItemStack from a input stream without "scrubbing" the NBT content.
   *
   * @param input - the input stream.
   * @return The deserialized item stack.
   * @throws IOException If anything went wrong.
   */
  @Override
  public ItemStack deserializeItemStack(DataInputStream input) throws IOException {
    ItemStack result = null;
    short type = input.readShort();

    if (type >= 0) {
      byte amount = input.readByte();
      short damage = input.readShort();

      result = new ItemStack(type, amount, damage);
      NbtCompound tag = super.deserializeCompound(input);

      if (tag != null) {
        result = MinecraftReflection.getBukkitItemStack(result);
        NbtFactory.setItemTag(result, tag);
      }
    }
    return result;
  }
Пример #5
0
 /**
  * Retrieve the NBT compound from a given NMS handle.
  *
  * @param handle - the underlying net.minecraft.server object to wrap.
  * @return A NBT compound wrapper
  */
 public static NbtCompound fromNMSCompound(@Nonnull Object handle) {
   if (handle == null) throw new IllegalArgumentException("handle cannot be NULL.");
   return (NbtCompound) NbtFactory.<Map<String, NbtBase<?>>>fromNMS(handle);
 }