private WrappedStack(Object object, int stackSize) {
    if (object instanceof Item) {
      object = new ItemStack((Item) object);
    } else if (object instanceof Block) {
      object = new ItemStack((Block) object);
    } else if (object instanceof Fluid) {
      object = new FluidStack((Fluid) object, 1000);
    }

    if (object instanceof ItemStack) {
      ItemStack itemStack = ((ItemStack) object).copy();
      objectType = "itemstack";
      this.stackSize = stackSize;
      itemStack.stackSize = 1;
      wrappedStack = itemStack;
    } else if (object instanceof OreStack) {
      OreStack oreStack = (OreStack) object;
      objectType = "orestack";
      this.stackSize = stackSize;
      oreStack.stackSize = 1;
      wrappedStack = oreStack;
    } else if (object instanceof ArrayList) {
      ArrayList<?> objectList = (ArrayList<?>) object;

      OreStack possibleOreStack = OreStack.getOreStackFromList(objectList);

      if (possibleOreStack != null) {
        objectType = "orestack";
        this.stackSize = stackSize;
        possibleOreStack.stackSize = 1;
        wrappedStack = possibleOreStack;
      } else {
        objectType = null;
        this.stackSize = -1;
        wrappedStack = null;
      }
    } else if (object instanceof FluidStack) {
      FluidStack fluidStack = (FluidStack) object;
      objectType = "fluidstack";
      this.stackSize = stackSize;
      fluidStack.amount = 1;
      wrappedStack = fluidStack;
    } else if (object instanceof WrappedStack) {
      WrappedStack wrappedStackObject = (WrappedStack) object;

      if (wrappedStackObject.getWrappedObject() != null) {
        this.objectType = wrappedStackObject.objectType;
        this.stackSize = stackSize;
        this.wrappedStack = wrappedStackObject.wrappedStack;
      } else {
        objectType = null;
        this.stackSize = -1;
        wrappedStack = null;
      }
    } else {
      objectType = null;
      this.stackSize = -1;
      wrappedStack = null;
    }
  }
        @Override
        public int compare(WrappedStack wrappedStack1, WrappedStack wrappedStack2) {

          if (wrappedStack1.wrappedStack instanceof ItemStack) {
            if (wrappedStack2.wrappedStack instanceof ItemStack) {
              return ItemHelper.compare(
                  (ItemStack) wrappedStack1.wrappedStack, (ItemStack) wrappedStack2.wrappedStack);
            } else {
              return Compare.GREATER_THAN;
            }
          } else if (wrappedStack1.wrappedStack instanceof OreStack) {
            if (wrappedStack2.wrappedStack instanceof ItemStack) {
              return Compare.LESSER_THAN;
            } else if (wrappedStack2.wrappedStack instanceof OreStack) {
              return OreStack.compare(
                  (OreStack) wrappedStack1.wrappedStack, (OreStack) wrappedStack2.wrappedStack);
            } else {
              return Compare.GREATER_THAN;
            }
          } else if (wrappedStack1.wrappedStack instanceof EnergyStack) {
            if (wrappedStack2.wrappedStack instanceof ItemStack
                || wrappedStack2.wrappedStack instanceof OreStack) {
              return Compare.LESSER_THAN;
            } else if (wrappedStack2.wrappedStack instanceof EnergyStack) {
              return EnergyStack.compare(
                  (EnergyStack) wrappedStack1.wrappedStack,
                  (EnergyStack) wrappedStack2.wrappedStack);
            } else {
              return Compare.GREATER_THAN;
            }
          } else if (wrappedStack1.wrappedStack instanceof FluidStack) {
            if (wrappedStack2.wrappedStack instanceof ItemStack
                || wrappedStack2.wrappedStack instanceof OreStack
                || wrappedStack2.wrappedStack instanceof EnergyStack) {
              return Compare.LESSER_THAN;
            } else if (wrappedStack2.wrappedStack instanceof FluidStack) {
              return FluidHelper.compare(
                  (FluidStack) wrappedStack1.wrappedStack, (FluidStack) wrappedStack2.wrappedStack);
            } else {
              return Compare.GREATER_THAN;
            }
          } else if (wrappedStack1.wrappedStack == null) {
            if (wrappedStack2.wrappedStack != null) {
              return Compare.LESSER_THAN;
            } else {
              return Compare.EQUALS;
            }
          }

          return Compare.EQUALS;
        }
  public static boolean canBeWrapped(Object object) {
    if (object instanceof WrappedStack) {
      return true;
    } else if (object instanceof Item || object instanceof Block || object instanceof ItemStack) {
      return true;
    } else if (object instanceof OreStack) {
      return true;
    } else if (object instanceof List) {
      if (OreStack.getOreStackFromList((List<?>) object) != null) {
        return true;
      }
    } else if (object instanceof EnergyStack) {
      return true;
    } else if (object instanceof Fluid || object instanceof FluidStack) {
      return true;
    }

    return false;
  }
        @Override
        public int compare(WrappedStack wrappedStack1, WrappedStack wrappedStack2) {
          if (wrappedStack1.wrappedStack instanceof ItemStack) {
            if (wrappedStack2.wrappedStack instanceof ItemStack) {
              return ItemHelper.compare(
                  (ItemStack) wrappedStack1.wrappedStack, (ItemStack) wrappedStack2.wrappedStack);
            } else {
              return 1;
            }
          } else if (wrappedStack1.wrappedStack instanceof OreStack) {
            if (wrappedStack2.wrappedStack instanceof ItemStack) {
              return -1;
            } else if (wrappedStack2.wrappedStack instanceof OreStack) {
              return OreStack.compare(
                  (OreStack) wrappedStack1.wrappedStack, (OreStack) wrappedStack2.wrappedStack);
            } else {
              return 1;
            }
          } else if (wrappedStack1.wrappedStack instanceof FluidStack) {
            if (wrappedStack2.wrappedStack instanceof ItemStack
                || wrappedStack2.wrappedStack instanceof OreStack) {
              return -1;
            } else if (wrappedStack2.wrappedStack instanceof FluidStack) {
              return FluidHelper.compare(
                  (FluidStack) wrappedStack1.wrappedStack, (FluidStack) wrappedStack2.wrappedStack);
            } else {
              return 1;
            }
          } else if (wrappedStack1.wrappedStack == null) {
            if (wrappedStack2.wrappedStack != null) {
              return -1;
            } else {
              return 0;
            }
          }

          return 0;
        }
  public WrappedStack(Object object) {
    if (object instanceof Item) {
      object = new ItemStack((Item) object);
    } else if (object instanceof Block) {
      object = new ItemStack((Block) object);
    } else if (object instanceof Fluid) {
      object = new FluidStack((Fluid) object, 1000);
    }

    if (object instanceof ItemStack) {
      ItemStack itemStack = ((ItemStack) object).copy();

      className = ItemStack.class.getSimpleName();
      stackSize = itemStack.stackSize;
      itemStack.stackSize = 1;
      wrappedStack = itemStack;
    } else if (object instanceof OreStack) {
      OreStack oreStack = (OreStack) object;

      className = OreStack.class.getSimpleName();
      stackSize = oreStack.stackSize;
      oreStack.stackSize = 1;
      wrappedStack = oreStack;
    } else if (object instanceof ArrayList) {
      ArrayList<?> objectList = (ArrayList<?>) object;

      OreStack possibleOreStack = OreStack.getOreStackFromList(objectList);

      if (possibleOreStack != null) {
        className = OreStack.class.getSimpleName();
        stackSize = possibleOreStack.stackSize;
        possibleOreStack.stackSize = 1;
        wrappedStack = possibleOreStack;
      } else {
        stackSize = -1;
        className = null;
        wrappedStack = null;
      }
    } else if (object instanceof EnergyStack) {
      EnergyStack energyStack = (EnergyStack) object;

      className = EnergyStack.class.getSimpleName();
      stackSize = energyStack.stackSize;
      energyStack.stackSize = 1;
      wrappedStack = energyStack;
    } else if (object instanceof FluidStack) {
      FluidStack fluidStack = ((FluidStack) object).copy();

      className = FluidStack.class.getSimpleName();
      stackSize = fluidStack.amount;
      fluidStack.amount = 1;
      wrappedStack = fluidStack;
    } else if (object instanceof WrappedStack) {
      WrappedStack wrappedStackObject = (WrappedStack) object;

      if (wrappedStackObject.getWrappedStack() != null) {
        className = wrappedStackObject.wrappedStack.getClass().getSimpleName();
        this.stackSize = wrappedStackObject.stackSize;
        this.wrappedStack = wrappedStackObject.wrappedStack;
      } else {
        className = null;
        stackSize = -1;
        wrappedStack = null;
      }
    } else if (object instanceof String) {
      WrappedStack wrappedStack = createFromJson((String) object);

      if (wrappedStack != null && wrappedStack.getWrappedStack() != null) {
        className = wrappedStack.getWrappedStack().getClass().getSimpleName();
        stackSize = wrappedStack.stackSize;
        this.wrappedStack = wrappedStack.wrappedStack;
      } else {
        className = null;
        stackSize = -1;
        this.wrappedStack = null;
      }
    } else {
      className = null;
      stackSize = -1;
      wrappedStack = null;
    }
  }
  @Override
  public WrappedStack deserialize(
      JsonElement jsonElement, Type type, JsonDeserializationContext context)
      throws JsonParseException {
    if (!jsonElement.isJsonPrimitive()) {
      JsonObject jsonWrappedStack = (JsonObject) jsonElement;

      int stackSize = -1;
      String className = null;
      Object stackObject = null;

      if (jsonWrappedStack.get("className") != null) {
        className = jsonWrappedStack.get("className").getAsString();
      }

      if (jsonWrappedStack.get("stackSize") != null) {
        stackSize = jsonWrappedStack.get("stackSize").getAsInt();
      }

      if (jsonWrappedStack.get("wrappedStack") != null
          && !jsonWrappedStack.get("wrappedStack").isJsonPrimitive()) {
        if (className != null) {
          if (className.equalsIgnoreCase(ItemStack.class.getSimpleName())) {
            JsonItemStack jsonItemStack =
                gsonSerializer.fromJson(jsonWrappedStack.get("wrappedStack"), JsonItemStack.class);
            ItemStack itemStack = null;
            if (stackSize > 0) {
              itemStack = new ItemStack(jsonItemStack.itemID, stackSize, jsonItemStack.itemDamage);
              if (jsonItemStack.compressedStackTagCompound != null) {
                try {
                  itemStack.stackTagCompound =
                      CompressedStreamTools.decompress(jsonItemStack.compressedStackTagCompound);
                } catch (IOException e) {
                  e.printStackTrace();
                }
              }
            }
            stackObject = itemStack;
          } else if (className.equalsIgnoreCase(OreStack.class.getSimpleName())) {
            OreStack oreStack =
                gsonSerializer.fromJson(jsonWrappedStack.get("wrappedStack"), OreStack.class);

            if (stackSize > 0) {
              oreStack.stackSize = stackSize;
            }
            stackObject = oreStack;
          } else if (className.equalsIgnoreCase(EnergyStack.class.getSimpleName())) {
            EnergyStack energyStack =
                gsonSerializer.fromJson(jsonWrappedStack.get("wrappedStack"), EnergyStack.class);

            if (stackSize > 0) {
              energyStack.stackSize = stackSize;
            }
            stackObject = energyStack;
          } else if (className.equalsIgnoreCase(FluidStack.class.getSimpleName())) {
            FluidStack fluidStack =
                gsonSerializer.fromJson(jsonWrappedStack.get("wrappedStack"), FluidStack.class);

            if (stackSize > 0) {
              fluidStack.amount = stackSize;
            }
            stackObject = fluidStack;
          }
        }
      }

      if (stackObject != null) {
        return new WrappedStack(stackObject);
      } else {
        throw new JsonParseException(
            String.format(
                "Unable to parse a wrappable stack object from the provided json: %s",
                jsonElement.toString()));
      }
    } else {
      throw new JsonParseException(
          String.format(
              "Unable to parse a wrappable stack object from the provided json: %s",
              jsonElement.toString()));
    }
  }
  /**
   * Gson invokes this call-back method during deserialization when it encounters a field of the
   * specified type.
   *
   * <p>In the implementation of this call-back method, you should consider invoking {@link
   * com.google.gson.JsonDeserializationContext#deserialize(com.google.gson.JsonElement,
   * java.lang.reflect.Type)} method to create objects for any non-trivial field of the returned
   * object. However, you should never invoke it on the the same type passing {@code jsonElement}
   * since that will cause an infinite loop (Gson will call your call-back method again).
   *
   * @param jsonElement The Json data being deserialized
   * @param typeOfT The type of the Object to deserialize to
   * @param context
   * @return a deserialized object of the specified type typeOfT which is a subclass of {@code T}
   * @throws com.google.gson.JsonParseException if jsonElement is not in the expected format of
   *     {@code typeofT}
   */
  @Override
  public WrappedStack deserialize(
      JsonElement jsonElement, Type typeOfT, JsonDeserializationContext context)
      throws JsonParseException {
    if (!jsonElement.isJsonPrimitive()) {
      JsonObject jsonWrappedStack = (JsonObject) jsonElement;

      int stackSize = 1;
      String objectType = null;
      Object stackObject = null;

      if (jsonWrappedStack.get("type") != null) {
        objectType = jsonWrappedStack.get("type").getAsString();
      }

      if (jsonWrappedStack.get("stackSize") != null) {
        stackSize = jsonWrappedStack.get("stackSize").getAsInt();
      }

      if (jsonWrappedStack.get("objectData") != null
          && !jsonWrappedStack.get("objectData").isJsonPrimitive()) {
        if (objectType != null) {
          if (objectType.equalsIgnoreCase("ItemStack")) {
            JsonItemStack jsonItemStack =
                JsonItemStack.jsonSerializer.fromJson(
                    jsonWrappedStack.get("objectData"), JsonItemStack.class);
            ItemStack itemStack = null;
            Item item = (Item) Item.itemRegistry.getObject(jsonItemStack.itemName);
            if (stackSize > 0 && item != null) {
              itemStack = new ItemStack(item, stackSize, jsonItemStack.itemDamage);
              if (jsonItemStack.itemNBTTagCompound != null) {
                itemStack.stackTagCompound = jsonItemStack.itemNBTTagCompound;
              }
            }
            stackObject = itemStack;
          } else if (objectType.equalsIgnoreCase("OreStack")) {
            OreStack oreStack =
                jsonSerializer.fromJson(jsonWrappedStack.get("objectData"), OreStack.class);

            if (stackSize > 0) {
              oreStack.stackSize = stackSize;
            }
            stackObject = oreStack;
          } else if (objectType.equalsIgnoreCase("FluidStack")) {
            JsonFluidStack jsonFluidStack =
                JsonFluidStack.jsonSerializer.fromJson(
                    jsonWrappedStack.get("objectData"), JsonFluidStack.class);
            FluidStack fluidStack =
                new FluidStack(jsonFluidStack.fluid, jsonFluidStack.amount, jsonFluidStack.tag);

            if (stackSize > 0) {
              fluidStack.amount = stackSize;
            }
            stackObject = fluidStack;
          }
        }
      }

      if (stackObject != null) {
        return new WrappedStack(stackObject);
      } else {
        throw new JsonParseException(
            String.format(
                "Unable to parse a wrappable stack object from the provided json: %s",
                jsonElement.toString()));
      }
    } else {
      throw new JsonParseException(
          String.format(
              "Unable to parse a wrappable stack object from the provided json: %s",
              jsonElement.toString()));
    }
  }