mirror of
https://github.com/PaperMC/Paper.git
synced 2025-01-01 05:47:45 +01:00
Add ItemMeta factory and interfaces. This adds BUKKIT-15
Included with ItemMeta is a new serializable class Color. PotionEffects are now serializable. By: Wesley Wolfe <weswolf@aol.com>
This commit is contained in:
parent
2bf21e7e18
commit
ac66053f35
@ -138,7 +138,7 @@
|
||||
<dependency>
|
||||
<groupId>org.hamcrest</groupId>
|
||||
<artifactId>hamcrest-library</artifactId>
|
||||
<version>1.2.1</version>
|
||||
<version>1.3</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
@ -26,6 +26,7 @@ import org.bukkit.plugin.messaging.Messenger;
|
||||
import org.bukkit.scheduler.BukkitScheduler;
|
||||
|
||||
import com.avaje.ebean.config.ServerConfig;
|
||||
import org.bukkit.inventory.ItemFactory;
|
||||
|
||||
/**
|
||||
* Represents the Bukkit core, for version and Server singleton handling
|
||||
@ -390,4 +391,8 @@ public final class Bukkit {
|
||||
public static WarningState getWarningState() {
|
||||
return server.getWarningState();
|
||||
}
|
||||
|
||||
public static ItemFactory getItemFactory() {
|
||||
return server.getItemFactory();
|
||||
}
|
||||
}
|
||||
|
339
paper-api/src/main/java/org/bukkit/Color.java
Normal file
339
paper-api/src/main/java/org/bukkit/Color.java
Normal file
@ -0,0 +1,339 @@
|
||||
package org.bukkit;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.configuration.serialization.ConfigurationSerializable;
|
||||
import org.bukkit.configuration.serialization.SerializableAs;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
/**
|
||||
* A container for a color palette. This class is immutable; the set methods return a new color.
|
||||
* The color names listed as fields are HTML4 standards, but subject to change.
|
||||
*/
|
||||
@SerializableAs("Color")
|
||||
public final class Color implements ConfigurationSerializable {
|
||||
private static final int BIT_MASK = 0xff;
|
||||
|
||||
/**
|
||||
* White, or (0xFF,0xFF,0xFF) in (R,G,B)
|
||||
*/
|
||||
public static final Color WHITE = fromRGB(0xFFFFFF);
|
||||
|
||||
/**
|
||||
* Silver, or (0xC0,0xC0,0xC0) in (R,G,B)
|
||||
*/
|
||||
public static final Color SILVER = fromRGB(0xC0C0C0);
|
||||
|
||||
/**
|
||||
* Gray, or (0x80,0x80,0x80) in (R,G,B)
|
||||
*/
|
||||
public static final Color GRAY = fromRGB(0x808080);
|
||||
|
||||
/**
|
||||
* Black, or (0x00,0x00,0x00) in (R,G,B)
|
||||
*/
|
||||
public static final Color BLACK = fromRGB(0x000000);
|
||||
|
||||
/**
|
||||
* Red, or (0xFF,0x00,0x00) in (R,G,B)
|
||||
*/
|
||||
public static final Color RED = fromRGB(0xFF0000);
|
||||
|
||||
/**
|
||||
* Maroon, or (0x80,0x00,0x00) in (R,G,B)
|
||||
*/
|
||||
public static final Color MAROON = fromRGB(0x800000);
|
||||
|
||||
/**
|
||||
* Yellow, or (0xFF,0xFF,0x00) in (R,G,B)
|
||||
*/
|
||||
public static final Color YELLOW = fromRGB(0xFFFF00);
|
||||
|
||||
/**
|
||||
* Olive, or (0x80,0x80,0x00) in (R,G,B)
|
||||
*/
|
||||
public static final Color OLIVE = fromRGB(0x808000);
|
||||
|
||||
/**
|
||||
* Lime, or (0x00,0xFF,0x00) in (R,G,B)
|
||||
*/
|
||||
public static final Color LIME = fromRGB(0x00FF00);
|
||||
|
||||
/**
|
||||
* Green, or (0x00,0x80,0x00) in (R,G,B)
|
||||
*/
|
||||
public static final Color GREEN = fromRGB(0x008000);
|
||||
|
||||
/**
|
||||
* Aqua, or (0x00,0xFF,0xFF) in (R,G,B)
|
||||
*/
|
||||
public static final Color AQUA = fromRGB(0x00FFFF);
|
||||
|
||||
/**
|
||||
* Teal, or (0x00,0x80,0x80) in (R,G,B)
|
||||
*/
|
||||
public static final Color TEAL = fromRGB(0x008080);
|
||||
|
||||
/**
|
||||
* Blue, or (0x00,0x00,0xFF) in (R,G,B)
|
||||
*/
|
||||
public static final Color BLUE = fromRGB(0x0000FF);
|
||||
|
||||
/**
|
||||
* Navy, or (0x00,0x00,0x80) in (R,G,B)
|
||||
*/
|
||||
public static final Color NAVY = fromRGB(0x000080);
|
||||
|
||||
/**
|
||||
* Fuchsia, or (0xFF,0x00,0xFF) in (R,G,B)
|
||||
*/
|
||||
public static final Color FUCHSIA = fromRGB(0xFF00FF);
|
||||
|
||||
/**
|
||||
* Purple, or (0x80,0x00,0x80) in (R,G,B)
|
||||
*/
|
||||
public static final Color PURPLE = fromRGB(0x800080);
|
||||
|
||||
/**
|
||||
* Orange, or (0xFF,0xA5,0x00) in (R,G,B)
|
||||
*/
|
||||
public static final Color ORANGE = fromRGB(0xFFA500);
|
||||
|
||||
private final byte red;
|
||||
private final byte green;
|
||||
private final byte blue;
|
||||
|
||||
/**
|
||||
* Creates a new Color object from a red, green, and blue
|
||||
*
|
||||
* @param red integer from 0-255
|
||||
* @param green integer from 0-255
|
||||
* @param blue integer from 0-255
|
||||
* @return a new Color object for the red, green, blue
|
||||
* @throws IllegalArgumentException if any value is strictly >255 or <0
|
||||
*/
|
||||
public static Color fromRGB(int red, int green, int blue) throws IllegalArgumentException {
|
||||
return new Color(red, green, blue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Color object from a blue, green, and red
|
||||
*
|
||||
* @param blue integer from 0-255
|
||||
* @param green integer from 0-255
|
||||
* @param red integer from 0-255
|
||||
* @return a new Color object for the red, green, blue
|
||||
* @throws IllegalArgumentException if any value is strictly >255 or <0
|
||||
*/
|
||||
public static Color fromBGR(int blue, int green, int red) throws IllegalArgumentException {
|
||||
return new Color(red, green, blue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new color object from an integer that contains the red, green, and blue bytes in the lowest order 24 bits.
|
||||
*
|
||||
* @param rgb the integer storing the red, green, and blue values
|
||||
* @return a new color object for specified values
|
||||
* @throws IllegalArgumentException if any data is in the highest order 8 bits
|
||||
*/
|
||||
public static Color fromRGB(int rgb) throws IllegalArgumentException {
|
||||
Validate.isTrue((rgb >> 24) == 0, "Extrenuous data in: ", rgb);
|
||||
return fromRGB(rgb >> 16 & BIT_MASK, rgb >> 8 & BIT_MASK, rgb >> 0 & BIT_MASK);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new color object from an integer that contains the blue, green, and red bytes in the lowest order 24 bits.
|
||||
*
|
||||
* @param bgr the integer storing the blue, green, and red values
|
||||
* @return a new color object for specified values
|
||||
* @throws IllegalArgumentException if any data is in the highest order 8 bits
|
||||
*/
|
||||
public static Color fromBGR(int bgr) throws IllegalArgumentException {
|
||||
Validate.isTrue((bgr >> 24) == 0, "Extrenuous data in: ", bgr);
|
||||
return fromBGR(bgr >> 16 & BIT_MASK, bgr >> 8 & BIT_MASK, bgr >> 0 & BIT_MASK);
|
||||
}
|
||||
|
||||
private Color(int red, int green, int blue) {
|
||||
Validate.isTrue(red >= 0 && red <= BIT_MASK, "Red is not between 0-255: ", red);
|
||||
Validate.isTrue(green >= 0 && green <= BIT_MASK, "Red is not between 0-255: ", green);
|
||||
Validate.isTrue(blue >= 0 && blue <= BIT_MASK, "Red is not between 0-255: ", blue);
|
||||
|
||||
this.red = (byte) red;
|
||||
this.green = (byte) green;
|
||||
this.blue = (byte) blue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the red component
|
||||
*
|
||||
* @return red component, from 0 to 255
|
||||
*/
|
||||
public int getRed() {
|
||||
return BIT_MASK & red;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Color object with specified component
|
||||
*
|
||||
* @param red the red component, from 0 to 255
|
||||
* @return a new color object with the red component
|
||||
*/
|
||||
public Color setRed(int red) {
|
||||
return fromRGB(red, getGreen(), getBlue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the green component
|
||||
*
|
||||
* @return green component, from 0 to 255
|
||||
*/
|
||||
public int getGreen() {
|
||||
return BIT_MASK & green;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Color object with specified component
|
||||
*
|
||||
* @param green the red component, from 0 to 255
|
||||
* @return a new color object with the red component
|
||||
*/
|
||||
public Color setGreen(int green) {
|
||||
return fromRGB(getRed(), green, getBlue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the blue component
|
||||
*
|
||||
* @return blue component, from 0 to 255
|
||||
*/
|
||||
public int getBlue() {
|
||||
return BIT_MASK & blue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Color object with specified component
|
||||
*
|
||||
* @param blue the red component, from 0 to 255
|
||||
* @return a new color object with the red component
|
||||
*/
|
||||
public Color setBlue(int blue) {
|
||||
return fromRGB(getRed(), getGreen(), blue);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return An integer representation of this color, as 0xRRGGBB
|
||||
*/
|
||||
public int asRGB() {
|
||||
return getRed() << 16 | getGreen() << 8 | getBlue() << 0;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return An integer representation of this color, as 0xBBGGRR
|
||||
*/
|
||||
public int asBGR() {
|
||||
return getBlue() << 16 | getGreen() << 8 | getRed() << 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new color with its RGB components changed as if it was dyed with the colors passed in, replicating
|
||||
* vanilla workbench dyeing
|
||||
*
|
||||
* @param colors The DyeColors to dye with
|
||||
* @return A new color with the changed rgb components
|
||||
*/
|
||||
// TODO: Javadoc what this method does, not what it mimics. API != Implementation
|
||||
public Color mixDyes(DyeColor... colors) {
|
||||
Validate.noNullElements(colors, "Colors cannot be null");
|
||||
|
||||
Color[] toPass = new Color[colors.length];
|
||||
for (int i = 0; i < colors.length; i++) {
|
||||
toPass[i] = colors[i].getColor();
|
||||
}
|
||||
|
||||
return mixColors(toPass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new color with its RGB components changed as if it was dyed with the colors passed in, replicating
|
||||
* vanilla workbench dyeing
|
||||
*
|
||||
* @param colors The colors to dye with
|
||||
* @return A new color with the changed rgb components
|
||||
*/
|
||||
// TODO: Javadoc what this method does, not what it mimics. API != Implementation
|
||||
public Color mixColors(Color... colors) {
|
||||
Validate.noNullElements(colors, "Colors cannot be null");
|
||||
|
||||
int totalRed = this.getRed();
|
||||
int totalGreen = this.getGreen();
|
||||
int totalBlue = this.getBlue();
|
||||
int totalMax = Math.max(Math.max(totalRed, totalGreen), totalBlue);
|
||||
for (Color color : colors) {
|
||||
totalRed += color.getRed();
|
||||
totalGreen += color.getGreen();
|
||||
totalBlue += color.getBlue();
|
||||
totalMax += Math.max(Math.max(color.getRed(), color.getGreen()), color.getBlue());
|
||||
}
|
||||
|
||||
float averageRed = totalRed / (colors.length + 1);
|
||||
float averageGreen = totalGreen / (colors.length + 1);
|
||||
float averageBlue = totalBlue / (colors.length + 1);
|
||||
float averageMax = totalMax / (colors.length + 1);
|
||||
|
||||
float maximumOfAverages = Math.max(Math.max(averageRed, averageGreen), averageBlue);
|
||||
float gainFactor = averageMax / maximumOfAverages;
|
||||
|
||||
return Color.fromRGB((int) (averageRed * gainFactor), (int) (averageGreen * gainFactor), (int) (averageBlue * gainFactor));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (!(o instanceof Color)) {
|
||||
return false;
|
||||
}
|
||||
final Color that = (Color) o;
|
||||
return this.blue == that.blue && this.green == that.green && this.red == that.red;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return asRGB() ^ Color.class.hashCode();
|
||||
}
|
||||
|
||||
public Map<String, Object> serialize() {
|
||||
return ImmutableMap.<String, Object>of(
|
||||
"RED", getRed(),
|
||||
"BLUE", getBlue(),
|
||||
"GREEN", getGreen()
|
||||
);
|
||||
}
|
||||
|
||||
@SuppressWarnings("javadoc")
|
||||
public static Color deserialize(Map<String, Object> map) {
|
||||
return fromRGB(
|
||||
asInt("RED", map),
|
||||
asInt("GREEN", map),
|
||||
asInt("BLUE", map)
|
||||
);
|
||||
}
|
||||
|
||||
private static int asInt(String string, Map<String, Object> map) {
|
||||
Object value = map.get(string);
|
||||
if (value == null) {
|
||||
throw new IllegalArgumentException(string + " not in map " + map);
|
||||
}
|
||||
if (!(value instanceof Number)) {
|
||||
throw new IllegalArgumentException(string + '(' + value + ") is not a number");
|
||||
}
|
||||
return ((Number) value).intValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Color:[rgb0x" + Integer.toHexString(getRed()).toUpperCase() + Integer.toHexString(getGreen()).toUpperCase() + Integer.toHexString(getBlue()).toUpperCase() + "]";
|
||||
}
|
||||
}
|
@ -12,73 +12,76 @@ public enum DyeColor {
|
||||
/**
|
||||
* Represents white dye
|
||||
*/
|
||||
WHITE(0x0),
|
||||
WHITE(0x0, Color.WHITE),
|
||||
/**
|
||||
* Represents orange dye
|
||||
*/
|
||||
ORANGE(0x1),
|
||||
ORANGE(0x1, Color.fromRGB(0xD87f33)),
|
||||
/**
|
||||
* Represents magenta dye
|
||||
*/
|
||||
MAGENTA(0x2),
|
||||
MAGENTA(0x2, Color.fromRGB(0xB24CD8)),
|
||||
/**
|
||||
* Represents light blue dye
|
||||
*/
|
||||
LIGHT_BLUE(0x3),
|
||||
LIGHT_BLUE(0x3, Color.fromRGB(0x6699D8)),
|
||||
/**
|
||||
* Represents yellow dye
|
||||
*/
|
||||
YELLOW(0x4),
|
||||
YELLOW(0x4, Color.fromRGB(0xE5E533)),
|
||||
/**
|
||||
* Represents lime dye
|
||||
*/
|
||||
LIME(0x5),
|
||||
LIME(0x5, Color.fromRGB(0x7FCC19)),
|
||||
/**
|
||||
* Represents pink dye
|
||||
*/
|
||||
PINK(0x6),
|
||||
PINK(0x6, Color.fromRGB(0xF27FA5)),
|
||||
/**
|
||||
* Represents gray dye
|
||||
*/
|
||||
GRAY(0x7),
|
||||
GRAY(0x7, Color.fromRGB(0x4C4C4C)),
|
||||
/**
|
||||
* Represents silver dye
|
||||
*/
|
||||
SILVER(0x8),
|
||||
SILVER(0x8, Color.fromRGB(0x999999)),
|
||||
/**
|
||||
* Represents cyan dye
|
||||
*/
|
||||
CYAN(0x9),
|
||||
CYAN(0x9, Color.fromRGB(0x4C7F99)),
|
||||
/**
|
||||
* Represents purple dye
|
||||
*/
|
||||
PURPLE(0xA),
|
||||
PURPLE(0xA, Color.fromRGB(0x7F3FB2)),
|
||||
/**
|
||||
* Represents blue dye
|
||||
*/
|
||||
BLUE(0xB),
|
||||
BLUE(0xB, Color.fromRGB(0x334CB2)),
|
||||
/**
|
||||
* Represents brown dye
|
||||
*/
|
||||
BROWN(0xC),
|
||||
BROWN(0xC, Color.fromRGB(0x664C33)),
|
||||
/**
|
||||
* Represents green dye
|
||||
*/
|
||||
GREEN(0xD),
|
||||
GREEN(0xD, Color.fromRGB(0x667F33)),
|
||||
/**
|
||||
* Represents red dye
|
||||
*/
|
||||
RED(0xE),
|
||||
RED(0xE, Color.fromRGB(0x993333)),
|
||||
/**
|
||||
* Represents black dye
|
||||
*/
|
||||
BLACK(0xF);
|
||||
BLACK(0xF, Color.fromRGB(0x191919));
|
||||
|
||||
private final byte data;
|
||||
private final Color color;
|
||||
private final static Map<Byte, DyeColor> BY_DATA = Maps.newHashMap();
|
||||
private final static Map<Color, DyeColor> BY_COLOR = Maps.newHashMap();
|
||||
|
||||
private DyeColor(final int data) {
|
||||
private DyeColor(final int data, Color color) {
|
||||
this.data = (byte) data;
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -90,6 +93,15 @@ public enum DyeColor {
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the color that this dye represents
|
||||
*
|
||||
* @return The {@link Color} that this dye represents
|
||||
*/
|
||||
public Color getColor() {
|
||||
return color;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the DyeColor with the given data value
|
||||
*
|
||||
@ -100,9 +112,20 @@ public enum DyeColor {
|
||||
return BY_DATA.get(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the DyeColor with the given color value
|
||||
*
|
||||
* @param color Color value to get the dye by
|
||||
* @return The {@link DyeColor} representing the given value, or null if it doesn't exist
|
||||
*/
|
||||
public static DyeColor getByColor(final Color color) {
|
||||
return BY_COLOR.get(color);
|
||||
}
|
||||
|
||||
static {
|
||||
for (DyeColor color : values()) {
|
||||
BY_DATA.put(color.getData(), color);
|
||||
BY_COLOR.put(color.getColor(), color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ import com.google.common.collect.Maps;
|
||||
* An enum of all material ids accepted by the official server + client
|
||||
*/
|
||||
public enum Material {
|
||||
AIR(0),
|
||||
AIR(0, 0),
|
||||
STONE(1),
|
||||
GRASS(2),
|
||||
DIRT(3),
|
||||
|
@ -28,6 +28,8 @@ import org.bukkit.plugin.messaging.PluginMessageRecipient;
|
||||
import org.bukkit.scheduler.BukkitScheduler;
|
||||
|
||||
import com.avaje.ebean.config.ServerConfig;
|
||||
import org.bukkit.inventory.ItemFactory;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
|
||||
/**
|
||||
* Represents a server implementation
|
||||
@ -679,4 +681,12 @@ public interface Server extends PluginMessageRecipient {
|
||||
* @return The configured WarningState
|
||||
*/
|
||||
public WarningState getWarningState();
|
||||
|
||||
/**
|
||||
* Gets the instance of the item factory (for {@link ItemMeta}).
|
||||
*
|
||||
* @return the item factory
|
||||
* @see ItemFactory
|
||||
*/
|
||||
ItemFactory getItemFactory();
|
||||
}
|
||||
|
15
paper-api/src/main/java/org/bukkit/Utility.java
Normal file
15
paper-api/src/main/java/org/bukkit/Utility.java
Normal file
@ -0,0 +1,15 @@
|
||||
package org.bukkit;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* This annotation indicates a method (and sometimes constructor) will chain its internal operations.
|
||||
* This is solely meant for identifying methods that don't need to be overridden / handled manually.
|
||||
*/
|
||||
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface Utility {
|
||||
}
|
@ -3,6 +3,8 @@ package org.bukkit.configuration;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.Color;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.util.Vector;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
@ -664,6 +666,43 @@ public interface ConfigurationSection {
|
||||
*/
|
||||
public boolean isItemStack(String path);
|
||||
|
||||
/**
|
||||
* Gets the requested Color by path.
|
||||
* <p />
|
||||
* If the Color does not exist but a default value has been specified, this
|
||||
* will return the default value. If the Color does not exist and no default
|
||||
* value was specified, this will return null.
|
||||
*
|
||||
* @param path Path of the Color to get.
|
||||
* @return Requested Color.
|
||||
*/
|
||||
public Color getColor(String path);
|
||||
|
||||
/**
|
||||
* Gets the requested {@link Color} by path, returning a default value if not found.
|
||||
* <p />
|
||||
* If the Color does not exist then the specified default value will returned
|
||||
* regardless of if a default has been identified in the root {@link Configuration}.
|
||||
*
|
||||
* @param path Path of the Color to get.
|
||||
* @param def The default value to return if the path is not found or is not an Color.
|
||||
* @return Requested Color.
|
||||
*/
|
||||
public Color getColor(String path, Color def);
|
||||
|
||||
/**
|
||||
* Checks if the specified path is a Color.
|
||||
* <p />
|
||||
* If the path exists but is not a Color, this will return false. If the path does not
|
||||
* exist, this will return false. If the path does not exist but a default value
|
||||
* has been specified, this will check if that default value is a Color and return
|
||||
* appropriately.
|
||||
*
|
||||
* @param path Path of the Color to check.
|
||||
* @return Whether or not the specified path is an Color.
|
||||
*/
|
||||
public boolean isColor(String path);
|
||||
|
||||
/**
|
||||
* Gets the requested ConfigurationSection by path.
|
||||
* <p />
|
||||
|
@ -1,16 +1,19 @@
|
||||
package org.bukkit.configuration;
|
||||
|
||||
import static org.bukkit.util.NumberConversions.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.Color;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.util.Vector;
|
||||
import static org.bukkit.util.NumberConversions.*;
|
||||
|
||||
/**
|
||||
* A type of {@link ConfigurationSection} that is stored in memory.
|
||||
@ -653,6 +656,21 @@ public class MemorySection implements ConfigurationSection {
|
||||
return val instanceof ItemStack;
|
||||
}
|
||||
|
||||
public Color getColor(String path) {
|
||||
Object def = getDefault(path);
|
||||
return getColor(path, (def instanceof Color) ? (Color) def : null);
|
||||
}
|
||||
|
||||
public Color getColor(String path, Color def) {
|
||||
Object val = get(path, def);
|
||||
return (val instanceof Color) ? (Color) val : def;
|
||||
}
|
||||
|
||||
public boolean isColor(String path) {
|
||||
Object val = get(path);
|
||||
return val instanceof Color;
|
||||
}
|
||||
|
||||
public ConfigurationSection getConfigurationSection(String path) {
|
||||
Object val = get(path, null);
|
||||
if (val != null) {
|
||||
|
@ -10,8 +10,10 @@ import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.Color;
|
||||
import org.bukkit.configuration.Configuration;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
import org.bukkit.util.BlockVector;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
@ -27,6 +29,8 @@ public class ConfigurationSerialization {
|
||||
registerClass(Vector.class);
|
||||
registerClass(BlockVector.class);
|
||||
registerClass(ItemStack.class);
|
||||
registerClass(Color.class);
|
||||
registerClass(PotionEffect.class);
|
||||
}
|
||||
|
||||
protected ConfigurationSerialization(Class<? extends ConfigurationSerializable> clazz) {
|
||||
|
@ -0,0 +1,82 @@
|
||||
package org.bukkit.inventory;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.inventory.meta.BookMeta;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.bukkit.inventory.meta.SkullMeta;
|
||||
|
||||
/**
|
||||
* An instance of the ItemFactory can be obtained with {@link Server#getItemFactory()}.
|
||||
* The ItemFactory is solely responsible for creating item meta containers to apply on item stacks.
|
||||
*/
|
||||
public interface ItemFactory {
|
||||
|
||||
/**
|
||||
* This creates a new item meta for the material.
|
||||
* @param material The material to consider as base for the meta
|
||||
* @return a new ItemMeta that could be applied to an item stack of the specified material
|
||||
*/
|
||||
ItemMeta getItemMeta(final Material material);
|
||||
|
||||
/**
|
||||
* This method checks the item meta to confirm that it is applicable (no data lost if applied) to the specified ItemStack.
|
||||
* A {@link SkullMeta} would not be valid for a sword, but a normal {@link ItemMeta} from an enchanted dirt block would.
|
||||
* @param meta Meta to check
|
||||
* @param stack Item that meta will be applied to
|
||||
* @return true if the meta can be applied without losing data, false otherwise
|
||||
* @throws IllegalArgumentException if the meta was not created by this factory
|
||||
*/
|
||||
boolean isApplicable(final ItemMeta meta, final ItemStack stack) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* This method checks the item meta to confirm that it is applicable (no data lost if applied) to the specified Material.
|
||||
* A {@link SkullMeta} would not be valid for a sword, but a normal {@link ItemMeta} from an enchanted dirt block would.
|
||||
* @param meta Meta to check
|
||||
* @param material Material that meta will be applied to
|
||||
* @return true if the meta can be applied without losing data, false otherwise
|
||||
* @throws IllegalArgumentException if the meta was not created by this factory
|
||||
*/
|
||||
boolean isApplicable(final ItemMeta meta, final Material material) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* This method is used to compare two item meta data objects.
|
||||
* @param meta1 First meta to compare, and may be null to indicate no data
|
||||
* @param meta2 Second meta to compare, and may be null to indicate no data
|
||||
* @return false if one of the meta has data the other does not, otherwise true
|
||||
* @throws IllegalArgumentException if either meta was not created by this factory
|
||||
*/
|
||||
boolean equals(final ItemMeta meta1, final ItemMeta meta2) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Returns an appropriate item meta for the specified stack.
|
||||
* The item meta returned will always be a valid meta for a given item stack of the specified material.
|
||||
* It may be a more or less specific meta, and could also be the same meta or meta type as the parameter.
|
||||
* The item meta returned will also always be the most appropriate meta. <br>
|
||||
* <br>
|
||||
* Example, if a {@link SkullMeta} is being applied to a book, this method would return a {@link BookMeta} containing all
|
||||
* information in the specified meta that is applicable to an {@link ItemMeta}, the highest common interface.
|
||||
*
|
||||
* @param meta the meta to convert
|
||||
* @param stack the stack to convert the meta for
|
||||
* @return An appropriate item meta for the specified item stack. No guarantees are made as to if a copy is returned. This will be null for a stack of air.
|
||||
* @throws IllegalArgumentException if the specified meta was not created by this factory
|
||||
*/
|
||||
ItemMeta asMetaFor(final ItemMeta meta, final ItemStack stack) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Returns an appropriate item meta for the specified material.
|
||||
* The item meta returned will always be a valid meta for a given item stack of the specified material.
|
||||
* It may be a more or less specific meta, and could also be the same meta or meta type as the parameter.
|
||||
* The item meta returned will also always be the most appropriate meta. <br>
|
||||
* <br>
|
||||
* Example, if a {@link SkullMeta} is being applied to a book, this method would return a {@link BookMeta} containing all
|
||||
* information in the specified meta that is applicable to an {@link ItemMeta}, the highest common interface.
|
||||
*
|
||||
* @param meta the meta to convert
|
||||
* @param material the material to convert the meta for
|
||||
* @return An appropriate item meta for the specified item material. No guarantees are made as to if a copy is returned. This will be null for air.
|
||||
* @throws IllegalArgumentException if the specified meta was not created by this factory
|
||||
*/
|
||||
ItemMeta asMetaFor(final ItemMeta meta, final Material material) throws IllegalArgumentException;
|
||||
}
|
@ -1,48 +1,97 @@
|
||||
package org.bukkit.inventory;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Utility;
|
||||
import org.bukkit.configuration.serialization.ConfigurationSerializable;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.bukkit.material.MaterialData;
|
||||
|
||||
/**
|
||||
* Represents a stack of items
|
||||
*/
|
||||
public class ItemStack implements Cloneable, ConfigurationSerializable {
|
||||
private int type;
|
||||
private int type = 0;
|
||||
private int amount = 0;
|
||||
private MaterialData data = null;
|
||||
private short durability = 0;
|
||||
private Map<Enchantment, Integer> enchantments = new HashMap<Enchantment, Integer>();
|
||||
private ItemMeta meta;
|
||||
|
||||
@Utility
|
||||
protected ItemStack() {}
|
||||
|
||||
/**
|
||||
* Defaults stack size to 1, with no extra data
|
||||
*
|
||||
* @param type item material id
|
||||
*/
|
||||
public ItemStack(final int type) {
|
||||
this(type, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Defaults stack size to 1, with no extra data
|
||||
*
|
||||
* @param type item material
|
||||
*/
|
||||
public ItemStack(final Material type) {
|
||||
this(type, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* An item stack with no extra data
|
||||
*
|
||||
* @param type item material id
|
||||
* @param amount stack size
|
||||
*/
|
||||
public ItemStack(final int type, final int amount) {
|
||||
this(type, amount, (short) 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* An item stack with no extra data
|
||||
*
|
||||
* @param type item material
|
||||
* @param amount stack size
|
||||
*/
|
||||
public ItemStack(final Material type, final int amount) {
|
||||
this(type.getId(), amount);
|
||||
}
|
||||
|
||||
/**
|
||||
* An item stack with the specified damage / durability
|
||||
*
|
||||
* @param type item material id
|
||||
* @param amount stack size
|
||||
* @param damage durability / damage
|
||||
*/
|
||||
public ItemStack(final int type, final int amount, final short damage) {
|
||||
this(type, amount, damage, null);
|
||||
this.type = type;
|
||||
this.amount = amount;
|
||||
this.durability = damage;
|
||||
}
|
||||
|
||||
/**
|
||||
* An item stack with the specified damage / durabiltiy
|
||||
*
|
||||
* @param type item material
|
||||
* @param amount stack size
|
||||
* @param damage durability / damage
|
||||
*/
|
||||
public ItemStack(final Material type, final int amount, final short damage) {
|
||||
this(type.getId(), amount, damage);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated this method uses an ambiguous data byte object
|
||||
*/
|
||||
@Deprecated
|
||||
public ItemStack(final int type, final int amount, final short damage, final Byte data) {
|
||||
this.type = type;
|
||||
this.amount = amount;
|
||||
@ -53,18 +102,29 @@ public class ItemStack implements Cloneable, ConfigurationSerializable {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated this method uses an ambiguous data byte object
|
||||
*/
|
||||
@Deprecated
|
||||
public ItemStack(final Material type, final int amount, final short damage, final Byte data) {
|
||||
this(type.getId(), amount, damage, data);
|
||||
}
|
||||
|
||||
public ItemStack(final ItemStack stack) {
|
||||
this.type = stack.type;
|
||||
this.amount = stack.amount;
|
||||
this.durability = stack.durability;
|
||||
if (stack.data != null) {
|
||||
this.data = stack.data.clone();
|
||||
/**
|
||||
* Creates a new item stack derived from the specified stack
|
||||
*
|
||||
* @param stack the stack to copy
|
||||
* @throws IllegalArgumentException if the specified stack is null or returns an item meta not created by the item factory
|
||||
*/
|
||||
public ItemStack(final ItemStack stack) throws IllegalArgumentException {
|
||||
Validate.notNull(stack, "Cannot copy null stack");
|
||||
this.type = stack.getTypeId();
|
||||
this.amount = stack.getAmount();
|
||||
this.durability = stack.getDurability();
|
||||
this.data = stack.getData();
|
||||
if (stack.hasItemMeta()) {
|
||||
setItemMeta0(stack.getItemMeta(), getType0());
|
||||
}
|
||||
this.addUnsafeEnchantments(stack.getEnchantments());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -72,8 +132,18 @@ public class ItemStack implements Cloneable, ConfigurationSerializable {
|
||||
*
|
||||
* @return Type of the items in this stack
|
||||
*/
|
||||
@Utility
|
||||
public Material getType() {
|
||||
return Material.getMaterial(type);
|
||||
return getType0(getTypeId());
|
||||
}
|
||||
|
||||
private Material getType0() {
|
||||
return getType0(this.type);
|
||||
}
|
||||
|
||||
private static Material getType0(int id) {
|
||||
Material material = Material.getMaterial(id);
|
||||
return material == null ? Material.AIR : material;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -83,7 +153,9 @@ public class ItemStack implements Cloneable, ConfigurationSerializable {
|
||||
*
|
||||
* @param type New type to set the items in this stack to
|
||||
*/
|
||||
@Utility
|
||||
public void setType(Material type) {
|
||||
Validate.notNull(type, "Material cannot be null");
|
||||
setTypeId(type.getId());
|
||||
}
|
||||
|
||||
@ -105,6 +177,9 @@ public class ItemStack implements Cloneable, ConfigurationSerializable {
|
||||
*/
|
||||
public void setTypeId(int type) {
|
||||
this.type = type;
|
||||
if (this.meta != null) {
|
||||
this.meta = Bukkit.getItemFactory().asMetaFor(meta, getType0());
|
||||
}
|
||||
createData((byte) 0);
|
||||
}
|
||||
|
||||
@ -132,9 +207,9 @@ public class ItemStack implements Cloneable, ConfigurationSerializable {
|
||||
* @return MaterialData for this item
|
||||
*/
|
||||
public MaterialData getData() {
|
||||
Material mat = Material.getMaterial(getTypeId());
|
||||
if (mat != null && mat.getData() != null) {
|
||||
data = mat.getNewData((byte) this.durability);
|
||||
Material mat = getType();
|
||||
if (data == null && mat != null && mat.getData() != null) {
|
||||
data = mat.getNewData((byte) this.getDurability());
|
||||
}
|
||||
|
||||
return data;
|
||||
@ -148,7 +223,7 @@ public class ItemStack implements Cloneable, ConfigurationSerializable {
|
||||
public void setData(MaterialData data) {
|
||||
Material mat = getType();
|
||||
|
||||
if ((mat == null) || (mat.getData() == null)) {
|
||||
if (data == null || mat == null || mat.getData() == null) {
|
||||
this.data = data;
|
||||
} else {
|
||||
if ((data.getClass() == mat.getData()) || (data.getClass() == MaterialData.class)) {
|
||||
@ -183,12 +258,12 @@ public class ItemStack implements Cloneable, ConfigurationSerializable {
|
||||
*
|
||||
* @return The maximum you can stack this material to.
|
||||
*/
|
||||
@Utility
|
||||
public int getMaxStackSize() {
|
||||
Material material = getType();
|
||||
if (material != null) {
|
||||
return material.getMaxStackSize();
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -203,19 +278,44 @@ public class ItemStack implements Cloneable, ConfigurationSerializable {
|
||||
}
|
||||
|
||||
@Override
|
||||
@Utility
|
||||
public String toString() {
|
||||
return "ItemStack{" + getType().name() + " x " + getAmount() + "}";
|
||||
StringBuilder toString = new StringBuilder("ItemStack{").append(getType().name()).append(" x ").append(getAmount());
|
||||
if (hasItemMeta()) {
|
||||
toString.append(", ").append(getItemMeta());
|
||||
}
|
||||
return toString.append('}').toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Utility
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (!(obj instanceof ItemStack)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ItemStack item = (ItemStack) obj;
|
||||
ItemStack stack = (ItemStack) obj;
|
||||
return getAmount() == stack.getAmount() && isSimilar(stack);
|
||||
}
|
||||
|
||||
return item.getAmount() == getAmount() && item.getTypeId() == getTypeId() && getDurability() == item.getDurability() && getEnchantments().equals(item.getEnchantments());
|
||||
/**
|
||||
* This method is the same as equals, but does not consider stack size (amount).
|
||||
*
|
||||
* @param stack the item stack to compare to
|
||||
* @return true if the two stacks are equal, ignoring the amount
|
||||
*/
|
||||
@Utility
|
||||
public boolean isSimilar(ItemStack stack) {
|
||||
if (stack == null) {
|
||||
return false;
|
||||
}
|
||||
if (stack == this) {
|
||||
return true;
|
||||
}
|
||||
return getTypeId() == stack.getTypeId() && getDurability() == stack.getDurability() && hasItemMeta() == stack.hasItemMeta() && (hasItemMeta() ? Bukkit.getItemFactory().equals(getItemMeta(), stack.getItemMeta()) : true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -223,7 +323,10 @@ public class ItemStack implements Cloneable, ConfigurationSerializable {
|
||||
try {
|
||||
ItemStack itemStack = (ItemStack) super.clone();
|
||||
|
||||
itemStack.enchantments = new HashMap<Enchantment, Integer>(this.enchantments);
|
||||
if (this.meta != null) {
|
||||
itemStack.meta = this.meta.clone();
|
||||
}
|
||||
|
||||
if (this.data != null) {
|
||||
itemStack.data = this.data.clone();
|
||||
}
|
||||
@ -235,11 +338,15 @@ public class ItemStack implements Cloneable, ConfigurationSerializable {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 11;
|
||||
@Utility
|
||||
public final int hashCode() {
|
||||
int hash = 1;
|
||||
|
||||
hash = hash * 31 + getTypeId();
|
||||
hash = hash * 31 + getAmount();
|
||||
hash = hash * 31 + (getDurability() & 0xffff);
|
||||
hash = hash * 31 + (hasItemMeta() ? (meta == null ? getItemMeta().hashCode() : meta.hashCode()) : 0);
|
||||
|
||||
hash = hash * 19 + 7 * getTypeId(); // Overriding hashCode since equals is overridden, it's just
|
||||
hash = hash * 7 + 23 * getAmount(); // too bad these are mutable values... Q_Q
|
||||
return hash;
|
||||
}
|
||||
|
||||
@ -250,7 +357,7 @@ public class ItemStack implements Cloneable, ConfigurationSerializable {
|
||||
* @return True if this has the given enchantment
|
||||
*/
|
||||
public boolean containsEnchantment(Enchantment ench) {
|
||||
return enchantments.containsKey(ench);
|
||||
return meta == null ? false : meta.hasEnchant(ench);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -260,7 +367,7 @@ public class ItemStack implements Cloneable, ConfigurationSerializable {
|
||||
* @return Level of the enchantment, or 0
|
||||
*/
|
||||
public int getEnchantmentLevel(Enchantment ench) {
|
||||
return enchantments.get(ench);
|
||||
return meta == null ? 0 : meta.getEnchantLevel(ench);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -269,7 +376,7 @@ public class ItemStack implements Cloneable, ConfigurationSerializable {
|
||||
* @return Map of enchantments.
|
||||
*/
|
||||
public Map<Enchantment, Integer> getEnchantments() {
|
||||
return ImmutableMap.copyOf(enchantments);
|
||||
return meta == null ? ImmutableMap.<Enchantment, Integer>of() : meta.getEnchants();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -279,8 +386,13 @@ public class ItemStack implements Cloneable, ConfigurationSerializable {
|
||||
* for each element of the map.
|
||||
*
|
||||
* @param enchantments Enchantments to add
|
||||
* @throws IllegalArgumentException if the specified enchantments is null
|
||||
* @throws IllegalArgumentException if any specific enchantment or level is null.
|
||||
* <b>Warning</b>: Some enchantments may be added before this exception is thrown.
|
||||
*/
|
||||
@Utility
|
||||
public void addEnchantments(Map<Enchantment, Integer> enchantments) {
|
||||
Validate.notNull(enchantments, "Enchantments cannot be null");
|
||||
for (Map.Entry<Enchantment, Integer> entry : enchantments.entrySet()) {
|
||||
addEnchantment(entry.getKey(), entry.getValue());
|
||||
}
|
||||
@ -293,8 +405,11 @@ public class ItemStack implements Cloneable, ConfigurationSerializable {
|
||||
*
|
||||
* @param ench Enchantment to add
|
||||
* @param level Level of the enchantment
|
||||
* @throws IllegalArgumentException if enchantment null, or enchantment is not applicable
|
||||
*/
|
||||
@Utility
|
||||
public void addEnchantment(Enchantment ench, int level) {
|
||||
Validate.notNull(ench, "Enchantment cannot be null");
|
||||
if ((level < ench.getStartLevel()) || (level > ench.getMaxLevel())) {
|
||||
throw new IllegalArgumentException("Enchantment level is either too low or too high (given " + level + ", bounds are " + ench.getStartLevel() + " to " + ench.getMaxLevel());
|
||||
} else if (!ench.canEnchantItem(this)) {
|
||||
@ -312,6 +427,7 @@ public class ItemStack implements Cloneable, ConfigurationSerializable {
|
||||
*
|
||||
* @param enchantments Enchantments to add
|
||||
*/
|
||||
@Utility
|
||||
public void addUnsafeEnchantments(Map<Enchantment, Integer> enchantments) {
|
||||
for (Map.Entry<Enchantment, Integer> entry : enchantments.entrySet()) {
|
||||
addUnsafeEnchantment(entry.getKey(), entry.getValue());
|
||||
@ -330,7 +446,7 @@ public class ItemStack implements Cloneable, ConfigurationSerializable {
|
||||
* @param level Level of the enchantment
|
||||
*/
|
||||
public void addUnsafeEnchantment(Enchantment ench, int level) {
|
||||
enchantments.put(ench, level);
|
||||
(meta == null ? meta = Bukkit.getItemFactory().getItemMeta(getType0()) : meta).addEnchant(ench, level, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -340,38 +456,43 @@ public class ItemStack implements Cloneable, ConfigurationSerializable {
|
||||
* @return Previous level, or 0
|
||||
*/
|
||||
public int removeEnchantment(Enchantment ench) {
|
||||
Integer previous = enchantments.remove(ench);
|
||||
return (previous == null) ? 0 : previous;
|
||||
int level = getEnchantmentLevel(ench);
|
||||
if (level == 0 || meta == null) {
|
||||
return level;
|
||||
}
|
||||
meta.removeEnchant(ench);
|
||||
return level;
|
||||
}
|
||||
|
||||
@Utility
|
||||
public Map<String, Object> serialize() {
|
||||
Map<String, Object> result = new LinkedHashMap<String, Object>();
|
||||
|
||||
result.put("type", getType().name());
|
||||
|
||||
if (durability != 0) {
|
||||
result.put("damage", durability);
|
||||
if (getDurability() != 0) {
|
||||
result.put("damage", getDurability());
|
||||
}
|
||||
|
||||
if (amount != 1) {
|
||||
result.put("amount", amount);
|
||||
if (getAmount() != 1) {
|
||||
result.put("amount", getAmount());
|
||||
}
|
||||
|
||||
Map<Enchantment, Integer> enchants = getEnchantments();
|
||||
|
||||
if (enchants.size() > 0) {
|
||||
Map<String, Integer> safeEnchants = new HashMap<String, Integer>();
|
||||
|
||||
for (Map.Entry<Enchantment, Integer> entry : enchants.entrySet()) {
|
||||
safeEnchants.put(entry.getKey().getName(), entry.getValue());
|
||||
}
|
||||
|
||||
result.put("enchantments", safeEnchants);
|
||||
ItemMeta meta = getItemMeta();
|
||||
if (!Bukkit.getItemFactory().equals(meta, null)) {
|
||||
result.put("meta", meta);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Required method for configuration serialization
|
||||
*
|
||||
* @param args map to deserialize
|
||||
* @return deserialized item stack
|
||||
* @see ConfigurationSerializable
|
||||
*/
|
||||
public static ItemStack deserialize(Map<String, Object> args) {
|
||||
Material type = Material.getMaterial((String) args.get("type"));
|
||||
short damage = 0;
|
||||
@ -387,7 +508,7 @@ public class ItemStack implements Cloneable, ConfigurationSerializable {
|
||||
|
||||
ItemStack result = new ItemStack(type, amount, damage);
|
||||
|
||||
if (args.containsKey("enchantments")) {
|
||||
if (args.containsKey("enchantments")) { // Backward compatiblity, @deprecated
|
||||
Object raw = args.get("enchantments");
|
||||
|
||||
if (raw instanceof Map) {
|
||||
@ -401,8 +522,61 @@ public class ItemStack implements Cloneable, ConfigurationSerializable {
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (args.containsKey("meta")) { // We cannot and will not have meta when enchantments (pre-ItemMeta) exist
|
||||
Object raw = args.get("meta");
|
||||
if (raw instanceof ItemMeta) {
|
||||
result.setItemMeta((ItemMeta) raw);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a copy of this ItemStack's {@link ItemMeta}.
|
||||
*
|
||||
* @return a copy of the current ItemStack's ItemData
|
||||
*/
|
||||
public ItemMeta getItemMeta() {
|
||||
return this.meta == null ? Bukkit.getItemFactory().getItemMeta(getType0()) : this.meta.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if any meta data has been defined.
|
||||
*
|
||||
* @return Returns true if some meta data has been set for this item
|
||||
*/
|
||||
public boolean hasItemMeta() {
|
||||
return !Bukkit.getItemFactory().equals(meta, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the ItemMeta of this ItemStack.
|
||||
*
|
||||
* @param itemMeta new ItemMeta, or null to indicate meta data be cleared.
|
||||
* @return True if successfully applied ItemMeta, see {@link ItemFactory#isApplicable(ItemMeta, ItemStack)}
|
||||
* @throws IllegalArgumentException if the item meta was not created by the {@link ItemFactory}
|
||||
*/
|
||||
public boolean setItemMeta(ItemMeta itemMeta) {
|
||||
return setItemMeta0(itemMeta, getType0());
|
||||
}
|
||||
|
||||
/*
|
||||
* Cannot be overridden, so it's safe for constructor call
|
||||
*/
|
||||
private boolean setItemMeta0(ItemMeta itemMeta, Material material) {
|
||||
if (itemMeta == null) {
|
||||
this.meta = null;
|
||||
return true;
|
||||
}
|
||||
if (!Bukkit.getItemFactory().isApplicable(itemMeta, material)) {
|
||||
return false;
|
||||
}
|
||||
this.meta = Bukkit.getItemFactory().asMetaFor(itemMeta, material);
|
||||
if (this.meta == itemMeta) {
|
||||
this.meta = itemMeta.clone();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
114
paper-api/src/main/java/org/bukkit/inventory/meta/BookMeta.java
Normal file
114
paper-api/src/main/java/org/bukkit/inventory/meta/BookMeta.java
Normal file
@ -0,0 +1,114 @@
|
||||
package org.bukkit.inventory.meta;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.Material;
|
||||
|
||||
/**
|
||||
* Represents a book ({@link Material#BOOK_AND_QUILL} or {@link Material#WRITTEN_BOOK}) that can have a title, an author, and pages.
|
||||
*/
|
||||
public interface BookMeta extends ItemMeta {
|
||||
|
||||
/**
|
||||
* Checks for the existence of a title in the book.
|
||||
*
|
||||
* @return true if the book has a title
|
||||
*/
|
||||
boolean hasTitle();
|
||||
|
||||
/**
|
||||
* Gets the title of the book.
|
||||
*
|
||||
* @return the title of the book
|
||||
*/
|
||||
String getTitle();
|
||||
|
||||
/**
|
||||
* Sets the title of the book. Limited to 16 characters.
|
||||
*
|
||||
* @param title the title to set
|
||||
* @return true if the title was successfully set
|
||||
*/
|
||||
boolean setTitle(String title);
|
||||
|
||||
/**
|
||||
* Checks for the existence of an author in the book.
|
||||
*
|
||||
* @return the author of the book
|
||||
*/
|
||||
boolean hasAuthor();
|
||||
|
||||
/**
|
||||
* Gets the author of the book.
|
||||
*
|
||||
* @return the author of the book
|
||||
*/
|
||||
String getAuthor();
|
||||
|
||||
/**
|
||||
* Sets the author of the book.
|
||||
*
|
||||
* @param author the author of the book
|
||||
*/
|
||||
void setAuthor(String author);
|
||||
|
||||
/**
|
||||
* Checks for the existence of pages in the book.
|
||||
*
|
||||
* @return true if the book has pages
|
||||
*/
|
||||
boolean hasPages();
|
||||
|
||||
/**
|
||||
* Gets the specified page in the book.
|
||||
*
|
||||
* @param page the page number to get
|
||||
* @return the page from the book
|
||||
*/
|
||||
String getPage(int page);
|
||||
|
||||
/**
|
||||
* Sets the specified page in the book.
|
||||
*
|
||||
* @param page the page number to set
|
||||
* @param data the data to set for that page
|
||||
*/
|
||||
void setPage(int page, String data);
|
||||
|
||||
/**
|
||||
* Gets all the pages in the book.
|
||||
*
|
||||
* @return list of all the pages in the book
|
||||
*/
|
||||
List<String> getPages();
|
||||
|
||||
/**
|
||||
* Clears the existing book pages, and sets the book to use the provided pages. Maximum 50 pages with 256 characters per page.
|
||||
*
|
||||
* @param pages A list of pages to set the book to use
|
||||
*/
|
||||
void setPages(List<String> pages);
|
||||
|
||||
/**
|
||||
* Clears the existing book pages, and sets the book to use the provided pages. Maximum 50 pages with 256 characters per page.
|
||||
*
|
||||
* @param pages A list of strings, each being a page
|
||||
*/
|
||||
void setPages(String... pages);
|
||||
|
||||
/**
|
||||
* Adds new pages to the end of the book.
|
||||
*
|
||||
* @param pages A list of strings, each being a page
|
||||
*/
|
||||
void addPage(String... pages);
|
||||
|
||||
/**
|
||||
* Gets the number of pages in the book.
|
||||
*
|
||||
* @return the number of pages in the book
|
||||
*/
|
||||
int getPageCount();
|
||||
|
||||
BookMeta clone();
|
||||
}
|
108
paper-api/src/main/java/org/bukkit/inventory/meta/ItemMeta.java
Normal file
108
paper-api/src/main/java/org/bukkit/inventory/meta/ItemMeta.java
Normal file
@ -0,0 +1,108 @@
|
||||
package org.bukkit.inventory.meta;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.bukkit.configuration.serialization.ConfigurationSerializable;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
|
||||
/**
|
||||
* This type represents the storage mechanism for auxiliary item data.
|
||||
* An implementation will handle the creation and application for ItemMeta.
|
||||
* This class should not be implemented by a plugin in a live environment.
|
||||
*/
|
||||
public interface ItemMeta extends Cloneable, ConfigurationSerializable {
|
||||
|
||||
/**
|
||||
* Checks for existence of a display name
|
||||
*
|
||||
* @return true if this has a display name
|
||||
*/
|
||||
boolean hasDisplayName();
|
||||
|
||||
/**
|
||||
* Gets the display name that is set
|
||||
*
|
||||
* @return the display name that is set
|
||||
*/
|
||||
String getDisplayName();
|
||||
|
||||
/**
|
||||
* Sets the display name
|
||||
*
|
||||
* @param name the name to set
|
||||
*/
|
||||
void setDisplayName(String name);
|
||||
|
||||
/**
|
||||
* Checks for existence of lore
|
||||
*
|
||||
* @return true if this has lore
|
||||
*/
|
||||
boolean hasLore();
|
||||
|
||||
/**
|
||||
* Gets the lore that is set
|
||||
*
|
||||
* @return a list of lore that is set
|
||||
*/
|
||||
List<String> getLore();
|
||||
|
||||
/**
|
||||
* Sets the lore for this item
|
||||
*
|
||||
* @param lore the lore that will be set
|
||||
*/
|
||||
void setLore(List<String> lore);
|
||||
|
||||
/**
|
||||
* Checks for the existence of any enchantments
|
||||
*
|
||||
* @return true if an enchantment exists on this meta
|
||||
*/
|
||||
boolean hasEnchants();
|
||||
|
||||
/**
|
||||
* Checks for existence of the specified enchantment
|
||||
*
|
||||
* @param ench enchantment to check
|
||||
* @return true if this enchantment exists for this meta
|
||||
*/
|
||||
boolean hasEnchant(Enchantment ench);
|
||||
|
||||
/**
|
||||
* Checks for the level of the specified enchantment
|
||||
*
|
||||
* @param ench enchantment to check
|
||||
* @return The level that the specified enchantment has, or 0 if none
|
||||
*/
|
||||
int getEnchantLevel(Enchantment ench);
|
||||
|
||||
/**
|
||||
* This method gets a copy the enchantments in this ItemMeta
|
||||
*
|
||||
* @return An immutable copy of the enchantments
|
||||
*/
|
||||
Map<Enchantment, Integer> getEnchants();
|
||||
|
||||
/**
|
||||
* This method adds the specified enchantment to this item meta
|
||||
*
|
||||
* @param ench Enchantment to add
|
||||
* @param level Level for the enchantment
|
||||
* @param ignoreLevelRestriction this indicates the enchantment should be applied, ignoring the level limit
|
||||
* @return true if the item meta changed as a result of this call, false otherwise
|
||||
*/
|
||||
boolean addEnchant(Enchantment ench, int level, boolean ignoreLevelRestriction);
|
||||
|
||||
/**
|
||||
* This method removes the specified enchantment from this item meta
|
||||
*
|
||||
* @param ench Enchantment to remove
|
||||
* @return true if the item meta changed as a result of this call, false otherwise
|
||||
*/
|
||||
boolean removeEnchant(Enchantment ench);
|
||||
|
||||
@SuppressWarnings("javadoc")
|
||||
ItemMeta clone();
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package org.bukkit.inventory.meta;
|
||||
|
||||
import org.bukkit.Color;
|
||||
import org.bukkit.Material;
|
||||
|
||||
/**
|
||||
* Represents leather armor ({@link Material#LEATHER_BOOTS}, {@link Material#LEATHER_CHESTPLATE}, {@link Material#LEATHER_HELMET}, or {@link Material#LEATHER_LEGGINGS}) that can be colored.
|
||||
*/
|
||||
public interface LeatherArmorMeta extends ItemMeta {
|
||||
|
||||
/**
|
||||
* Gets the color of the armor
|
||||
*
|
||||
* @return the color of the armor, never null
|
||||
*/
|
||||
Color getColor();
|
||||
|
||||
/**
|
||||
* Sets the color of the armor
|
||||
*
|
||||
* @param color the color to set, null makes it the default leather color
|
||||
*/
|
||||
void setColor(Color color);
|
||||
|
||||
LeatherArmorMeta clone();
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
package org.bukkit.inventory.meta;
|
||||
|
||||
/**
|
||||
* Represents a map that can be scalable.
|
||||
*/
|
||||
public interface MapMeta extends ItemMeta {
|
||||
|
||||
/**
|
||||
* Checks to see if this map is scaling
|
||||
*
|
||||
* @return true if this map is scaling
|
||||
*/
|
||||
boolean isScaling();
|
||||
|
||||
/**
|
||||
* Sets if this map is scaling or not
|
||||
*
|
||||
* @param value true to scale
|
||||
*/
|
||||
void setScaling(boolean value);
|
||||
|
||||
MapMeta clone();
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
package org.bukkit.inventory.meta;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Represents a potion ({@link Material#POTION}) that can have custom effects.
|
||||
*/
|
||||
public interface PotionMeta extends ItemMeta {
|
||||
|
||||
/**
|
||||
* Checks for the presence of custom potion effects
|
||||
*
|
||||
* @return true if custom potion effects are applied
|
||||
*/
|
||||
boolean hasCustomEffects();
|
||||
|
||||
/**
|
||||
* Gets an immutable list containing all custom potion effects applied to this potion
|
||||
*
|
||||
* @return the immutable list of custom potion effects
|
||||
*/
|
||||
List<PotionEffect> getCustomEffects();
|
||||
|
||||
/**
|
||||
* Adds a custom potion effect to this potion
|
||||
*
|
||||
* @param effect the potion effect to add
|
||||
* @param overwrite true if any existing effect of the same type should be overwritten
|
||||
* @return true if the potion meta changed as a result of this call
|
||||
*/
|
||||
boolean addCustomEffect(PotionEffect effect, boolean overwrite);
|
||||
|
||||
/**
|
||||
* Removes a custom potion effect from this potion
|
||||
*
|
||||
* @param type the potion effect type to remove
|
||||
* @return true if the potion meta changed as a result of this call
|
||||
*/
|
||||
boolean removeCustomEffect(PotionEffectType type);
|
||||
|
||||
/**
|
||||
* Checks for a specific custom potion effect type on this potion
|
||||
* @param type the potion effect type to check for
|
||||
* @return true if the potion has this effect
|
||||
*/
|
||||
boolean hasCustomEffect(PotionEffectType type);
|
||||
|
||||
/**
|
||||
* Moves a potion effect to the top of the potion effect list.
|
||||
* This causes the client to display the potion effect in the potion's name.
|
||||
*
|
||||
* @param type the potion effect type to move
|
||||
* @return true if the potion meta changed as a result of this call
|
||||
*/
|
||||
boolean setMainEffect(PotionEffectType type);
|
||||
|
||||
/**
|
||||
* Removes all custom potion effects from this potion
|
||||
*
|
||||
* @return true if the potion meta changed as a result of this call
|
||||
*/
|
||||
boolean clearCustomEffects();
|
||||
|
||||
PotionMeta clone();
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
package org.bukkit.inventory.meta;
|
||||
|
||||
/**
|
||||
* Represents an item that can be repaired at an anvil.
|
||||
*/
|
||||
public interface Repairable {
|
||||
|
||||
/**
|
||||
* Checks to see if this has a repair penalty
|
||||
*
|
||||
* @return true if this has a repair penalty
|
||||
*/
|
||||
boolean hasRepairCost();
|
||||
|
||||
/**
|
||||
* Gets the repair penalty
|
||||
*
|
||||
* @return the repair penalty
|
||||
*/
|
||||
int getRepairCost();
|
||||
|
||||
/**
|
||||
* Sets the repair penalty
|
||||
*
|
||||
* @param cost repair penalty
|
||||
*/
|
||||
void setRepairCost(int cost);
|
||||
|
||||
@SuppressWarnings("javadoc")
|
||||
Repairable clone();
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
package org.bukkit.inventory.meta;
|
||||
|
||||
import org.bukkit.Material;
|
||||
|
||||
/**
|
||||
* Represents a skull ({@link Material#SKULL_ITEM}) that can have an owner.
|
||||
*/
|
||||
public interface SkullMeta extends ItemMeta {
|
||||
|
||||
/**
|
||||
* Gets the owner of the skull
|
||||
*
|
||||
* @return the owner if the skull
|
||||
*/
|
||||
String getOwner();
|
||||
|
||||
/**
|
||||
* Checks to see if the skull has an owner
|
||||
*
|
||||
* @return true if the skull has an owner
|
||||
*/
|
||||
boolean hasOwner();
|
||||
|
||||
/**
|
||||
* Sets the owner of the skull
|
||||
*
|
||||
* @param owner the new owner of the skull
|
||||
* @return true if the owner was successfully set
|
||||
*/
|
||||
boolean setOwner(String owner);
|
||||
|
||||
SkullMeta clone();
|
||||
}
|
@ -1,24 +1,101 @@
|
||||
package org.bukkit.potion;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.configuration.serialization.ConfigurationSerializable;
|
||||
import org.bukkit.configuration.serialization.SerializableAs;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
/**
|
||||
* Represents a potion effect, that can be added to a {@link LivingEntity}. A
|
||||
* potion effect has a duration that it will last for, an amplifier that will
|
||||
* enhance its effects, and a {@link PotionEffectType}, that represents its
|
||||
* effect on an entity.
|
||||
*/
|
||||
public class PotionEffect {
|
||||
@SerializableAs("PotionEffect")
|
||||
public class PotionEffect implements ConfigurationSerializable {
|
||||
private static final String AMPLIFIER = "amplifier";
|
||||
private static final String DURATION = "duration";
|
||||
private static final String TYPE = "effect";
|
||||
private static final String AMBIENT = "ambient";
|
||||
private final int amplifier;
|
||||
private final int duration;
|
||||
private final PotionEffectType type;
|
||||
private final boolean ambient;
|
||||
|
||||
public PotionEffect(PotionEffectType type, int duration, int amplifier) {
|
||||
/**
|
||||
* Creates a potion effect.
|
||||
*
|
||||
* @param type effect type
|
||||
* @param duration measured in ticks, see {@link PotionEffect#getDuration()}
|
||||
* @param amplifier the amplifier, see {@link PotionEffect#getAmplifier()}
|
||||
* @param ambient the ambient status, see {@link PotionEffect#isAmbient()}
|
||||
*/
|
||||
public PotionEffect(PotionEffectType type, int duration, int amplifier, boolean ambient) {
|
||||
Validate.notNull(type, "effect type cannot be null");
|
||||
this.type = type;
|
||||
this.duration = duration;
|
||||
this.amplifier = amplifier;
|
||||
this.ambient = ambient;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a potion affect. Assumes ambient is true.
|
||||
*
|
||||
* @param type Effect type
|
||||
* @param duration measured in ticks
|
||||
* @param amplifier the amplifier for the affect
|
||||
* @see PotionEffect#PotionEffect(PotionEffectType, int, int, boolean)
|
||||
*/
|
||||
public PotionEffect(PotionEffectType type, int duration, int amplifier) {
|
||||
this(type, duration, amplifier, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for deserialization.
|
||||
*
|
||||
* @param map the map to deserialize from
|
||||
*/
|
||||
public PotionEffect(Map<String, Object> map) {
|
||||
this(getEffectType(map), getInt(map, DURATION), getInt(map, AMPLIFIER), getBool(map, AMBIENT));
|
||||
}
|
||||
|
||||
private static PotionEffectType getEffectType(Map<?,?> map) {
|
||||
int type = getInt(map, TYPE);
|
||||
PotionEffectType effect = PotionEffectType.getById(type);
|
||||
if (effect != null) {
|
||||
return effect;
|
||||
}
|
||||
throw new NoSuchElementException(map + " does not contain " + TYPE);
|
||||
}
|
||||
|
||||
private static int getInt(Map<?,?> map, Object key) {
|
||||
Object num = map.get(key);
|
||||
if (num instanceof Integer) {
|
||||
return (Integer) num;
|
||||
}
|
||||
throw new NoSuchElementException(map + " does not contain " + key);
|
||||
}
|
||||
|
||||
private static boolean getBool(Map<?,?> map, Object key) {
|
||||
Object bool = map.get(key);
|
||||
if (bool instanceof Boolean) {
|
||||
return (Boolean) bool;
|
||||
}
|
||||
throw new NoSuchElementException(map + " does not contain " + key);
|
||||
}
|
||||
|
||||
public Map<String, Object> serialize() {
|
||||
return ImmutableMap.<String, Object>of(
|
||||
TYPE, type.getId(),
|
||||
DURATION, duration,
|
||||
AMPLIFIER, amplifier,
|
||||
AMBIENT, ambient
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -38,18 +115,11 @@ public class PotionEffect {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null || getClass() != obj.getClass()) {
|
||||
if (!(obj instanceof PotionEffect)) {
|
||||
return false;
|
||||
}
|
||||
PotionEffect other = (PotionEffect) obj;
|
||||
if (type == null) {
|
||||
if (other.type != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!type.equals(other.type)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
PotionEffect that = (PotionEffect) obj;
|
||||
return this.type.equals(that.type) && this.ambient == that.ambient && this.amplifier == that.amplifier && this.duration == that.duration;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -80,8 +150,27 @@ public class PotionEffect {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes potion effect produce more, translucent, particles.
|
||||
*
|
||||
* @return if this effect is ambient
|
||||
*/
|
||||
public boolean isAmbient() {
|
||||
return ambient;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return 31 + ((type == null) ? 0 : type.hashCode());
|
||||
};
|
||||
int hash = 1;
|
||||
hash = hash * 31 + type.hashCode();
|
||||
hash = hash * 31 + amplifier;
|
||||
hash = hash * 31 + duration;
|
||||
hash ^= 0x22222222 >> (ambient ? 1 : -1);
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return type.getName() + (ambient ? ":(" : ":") + duration + "t-x" + amplifier + (ambient ? ")" : "");
|
||||
}
|
||||
}
|
||||
|
@ -115,6 +115,14 @@ public abstract class PotionEffectType {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a PotionEffect from this PotionEffectType, applying duration modifiers and checks.
|
||||
*
|
||||
* @see PotionBrewer#createEffect(PotionEffectType, int, int)
|
||||
* @param duration time in ticks
|
||||
* @param amplifier the effect's amplifier
|
||||
* @return a resulting potion effect
|
||||
*/
|
||||
public PotionEffect createEffect(int duration, int amplifier) {
|
||||
return Potion.getBrewer().createEffect(this, duration, amplifier);
|
||||
}
|
||||
|
365
paper-api/src/test/java/org/bukkit/ColorTest.java
Normal file
365
paper-api/src/test/java/org/bukkit/ColorTest.java
Normal file
@ -0,0 +1,365 @@
|
||||
package org.bukkit;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.junit.Test;
|
||||
|
||||
@SuppressWarnings("javadoc")
|
||||
public class ColorTest {
|
||||
static class TestColor {
|
||||
static int id = 0;
|
||||
final String name;
|
||||
final int rgb;
|
||||
final int bgr;
|
||||
final int r;
|
||||
final int g;
|
||||
final int b;
|
||||
|
||||
TestColor(int rgb, int bgr, int r, int g, int b) {
|
||||
this.rgb = rgb;
|
||||
this.bgr = bgr;
|
||||
this.r = r;
|
||||
this.g = g;
|
||||
this.b = b;
|
||||
this.name = id + ":" + Integer.toHexString(rgb).toUpperCase() + "_" + Integer.toHexString(bgr).toUpperCase() + "-r" + Integer.toHexString(r).toUpperCase() + "-g" + Integer.toHexString(g).toUpperCase() + "-b" + Integer.toHexString(b).toUpperCase();
|
||||
}
|
||||
}
|
||||
|
||||
static TestColor[] examples = new TestColor[] {
|
||||
/* 0xRRGGBB, 0xBBGGRR, 0xRR, 0xGG, 0xBB */
|
||||
new TestColor(0xFFFFFF, 0xFFFFFF, 0xFF, 0xFF, 0xFF),
|
||||
new TestColor(0xFFFFAA, 0xAAFFFF, 0xFF, 0xFF, 0xAA),
|
||||
new TestColor(0xFF00FF, 0xFF00FF, 0xFF, 0x00, 0xFF),
|
||||
new TestColor(0x67FF22, 0x22FF67, 0x67, 0xFF, 0x22),
|
||||
new TestColor(0x000000, 0x000000, 0x00, 0x00, 0x00)
|
||||
};
|
||||
|
||||
@Test
|
||||
public void testSerialization() throws Throwable {
|
||||
for (TestColor testColor : examples) {
|
||||
Color base = Color.fromRGB(testColor.rgb);
|
||||
|
||||
YamlConfiguration toSerialize = new YamlConfiguration();
|
||||
toSerialize.set("color", base);
|
||||
String serialized = toSerialize.saveToString();
|
||||
|
||||
YamlConfiguration deserialized = new YamlConfiguration();
|
||||
deserialized.loadFromString(serialized);
|
||||
|
||||
assertThat(testColor.name + " on " + serialized, base, is(deserialized.getColor("color")));
|
||||
}
|
||||
}
|
||||
|
||||
// Equality tests
|
||||
@Test
|
||||
public void testEqualities() {
|
||||
for (TestColor testColor : examples) {
|
||||
Color fromRGB = Color.fromRGB(testColor.rgb);
|
||||
Color fromBGR = Color.fromBGR(testColor.bgr);
|
||||
Color fromRGBs = Color.fromRGB(testColor.r, testColor.g, testColor.b);
|
||||
Color fromBGRs = Color.fromBGR(testColor.b, testColor.g, testColor.r);
|
||||
|
||||
assertThat(testColor.name, fromRGB, is(fromRGBs));
|
||||
assertThat(testColor.name, fromRGB, is(fromBGR));
|
||||
assertThat(testColor.name, fromRGB, is(fromBGRs));
|
||||
assertThat(testColor.name, fromRGBs, is(fromBGR));
|
||||
assertThat(testColor.name, fromRGBs, is(fromBGRs));
|
||||
assertThat(testColor.name, fromBGR, is(fromBGRs));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInequalities() {
|
||||
for (int i = 1; i < examples.length; i++) {
|
||||
TestColor testFrom = examples[i];
|
||||
Color from = Color.fromRGB(testFrom.rgb);
|
||||
for (int j = i - 1; j >= 0; j--) {
|
||||
TestColor testTo = examples[j];
|
||||
Color to = Color.fromRGB(testTo.rgb);
|
||||
String name = testFrom.name + " to " + testTo.name;
|
||||
assertThat(name, from, is(not(to)));
|
||||
|
||||
Color transform = from.setRed(testTo.r).setBlue(testTo.b).setGreen(testTo.g);
|
||||
assertThat(name, transform, is(not(sameInstance(from))));
|
||||
assertThat(name, transform, is(to));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// RGB tests
|
||||
@Test
|
||||
public void testRGB() {
|
||||
for (TestColor testColor : examples) {
|
||||
assertThat(testColor.name, Color.fromRGB(testColor.rgb).asRGB(), is(testColor.rgb));
|
||||
assertThat(testColor.name, Color.fromBGR(testColor.bgr).asRGB(), is(testColor.rgb));
|
||||
assertThat(testColor.name, Color.fromRGB(testColor.r, testColor.g, testColor.b).asRGB(), is(testColor.rgb));
|
||||
assertThat(testColor.name, Color.fromBGR(testColor.b, testColor.g, testColor.r).asRGB(), is(testColor.rgb));
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testInvalidRGB1() {
|
||||
Color.fromRGB(0x01000000);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testInvalidRGB2() {
|
||||
Color.fromRGB(Integer.MIN_VALUE);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testInvalidRGB3() {
|
||||
Color.fromRGB(Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testInvalidRGB4() {
|
||||
Color.fromRGB(-1);
|
||||
}
|
||||
|
||||
// BGR tests
|
||||
@Test
|
||||
public void testBGR() {
|
||||
for (TestColor testColor : examples) {
|
||||
assertThat(testColor.name, Color.fromRGB(testColor.rgb).asBGR(), is(testColor.bgr));
|
||||
assertThat(testColor.name, Color.fromBGR(testColor.bgr).asBGR(), is(testColor.bgr));
|
||||
assertThat(testColor.name, Color.fromRGB(testColor.r, testColor.g, testColor.b).asBGR(), is(testColor.bgr));
|
||||
assertThat(testColor.name, Color.fromBGR(testColor.b, testColor.g, testColor.r).asBGR(), is(testColor.bgr));
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testInvalidBGR1() {
|
||||
Color.fromBGR(0x01000000);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testInvalidBGR2() {
|
||||
Color.fromBGR(Integer.MIN_VALUE);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testInvalidBGR3() {
|
||||
Color.fromBGR(Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testInvalidBGR4() {
|
||||
Color.fromBGR(-1);
|
||||
}
|
||||
|
||||
// Red tests
|
||||
@Test
|
||||
public void testRed() {
|
||||
for (TestColor testColor : examples) {
|
||||
assertThat(testColor.name, Color.fromRGB(testColor.rgb).getRed(), is(testColor.r));
|
||||
assertThat(testColor.name, Color.fromBGR(testColor.bgr).getRed(), is(testColor.r));
|
||||
assertThat(testColor.name, Color.fromRGB(testColor.r, testColor.g, testColor.b).getRed(), is(testColor.r));
|
||||
assertThat(testColor.name, Color.fromBGR(testColor.b, testColor.g, testColor.r).getRed(), is(testColor.r));
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testInvalidR01() {
|
||||
Color.fromRGB(-1, 0x00, 0x00);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testInvalidR02() {
|
||||
Color.fromRGB(Integer.MAX_VALUE, 0x00, 0x00);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testInvalidR03() {
|
||||
Color.fromRGB(Integer.MIN_VALUE, 0x00, 0x00);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testInvalidR04() {
|
||||
Color.fromRGB(0x100, 0x00, 0x00);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testInvalidR05() {
|
||||
Color.fromBGR(0x00, 0x00, -1);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testInvalidR06() {
|
||||
Color.fromBGR(0x00, 0x00, Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testInvalidR07() {
|
||||
Color.fromBGR(0x00, 0x00, Integer.MIN_VALUE);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testInvalidR08() {
|
||||
Color.fromBGR(0x00, 0x00, 0x100);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testInvalidR09() {
|
||||
Color.WHITE.setRed(-1);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testInvalidR10() {
|
||||
Color.WHITE.setRed(Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testInvalidR11() {
|
||||
Color.WHITE.setRed(Integer.MIN_VALUE);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testInvalidR12() {
|
||||
Color.WHITE.setRed(0x100);
|
||||
}
|
||||
|
||||
// Blue tests
|
||||
@Test
|
||||
public void testBlue() {
|
||||
for (TestColor testColor : examples) {
|
||||
assertThat(testColor.name, Color.fromRGB(testColor.rgb).getBlue(), is(testColor.b));
|
||||
assertThat(testColor.name, Color.fromBGR(testColor.bgr).getBlue(), is(testColor.b));
|
||||
assertThat(testColor.name, Color.fromRGB(testColor.r, testColor.g, testColor.b).getBlue(), is(testColor.b));
|
||||
assertThat(testColor.name, Color.fromBGR(testColor.b, testColor.g, testColor.r).getBlue(), is(testColor.b));
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testInvalidB01() {
|
||||
Color.fromRGB(0x00, 0x00, -1);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testInvalidB02() {
|
||||
Color.fromRGB(0x00, 0x00, Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testInvalidB03() {
|
||||
Color.fromRGB(0x00, 0x00, Integer.MIN_VALUE);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testInvalidB04() {
|
||||
Color.fromRGB(0x00, 0x00, 0x100);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testInvalidB05() {
|
||||
Color.fromBGR(-1, 0x00, 0x00);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testInvalidB06() {
|
||||
Color.fromBGR(Integer.MAX_VALUE, 0x00, 0x00);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testInvalidB07() {
|
||||
Color.fromBGR(Integer.MIN_VALUE, 0x00, 0x00);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testInvalidB08() {
|
||||
Color.fromBGR(0x100, 0x00, 0x00);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testInvalidB09() {
|
||||
Color.WHITE.setBlue(-1);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testInvalidB10() {
|
||||
Color.WHITE.setBlue(Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testInvalidB11() {
|
||||
Color.WHITE.setBlue(Integer.MIN_VALUE);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testInvalidB12() {
|
||||
Color.WHITE.setBlue(0x100);
|
||||
}
|
||||
|
||||
// Green tests
|
||||
@Test
|
||||
public void testGreen() {
|
||||
for (TestColor testColor : examples) {
|
||||
assertThat(testColor.name, Color.fromRGB(testColor.rgb).getGreen(), is(testColor.g));
|
||||
assertThat(testColor.name, Color.fromBGR(testColor.bgr).getGreen(), is(testColor.g));
|
||||
assertThat(testColor.name, Color.fromRGB(testColor.r, testColor.g, testColor.b).getGreen(), is(testColor.g));
|
||||
assertThat(testColor.name, Color.fromBGR(testColor.b, testColor.g, testColor.r).getGreen(), is(testColor.g));
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testInvalidG01() {
|
||||
Color.fromRGB(0x00, -1, 0x00);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testInvalidG02() {
|
||||
Color.fromRGB(0x00, Integer.MAX_VALUE, 0x00);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testInvalidG03() {
|
||||
Color.fromRGB(0x00, Integer.MIN_VALUE, 0x00);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testInvalidG04() {
|
||||
Color.fromRGB(0x00, 0x100, 0x00);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testInvalidG05() {
|
||||
Color.fromBGR(0x00, -1, 0x00);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testInvalidG06() {
|
||||
Color.fromBGR(0x00, Integer.MAX_VALUE, 0x00);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testInvalidG07() {
|
||||
Color.fromBGR(0x00, Integer.MIN_VALUE, 0x00);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testInvalidG08() {
|
||||
Color.fromBGR(0x00, 0x100, 0x00);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testInvalidG09() {
|
||||
Color.WHITE.setGreen(-1);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testInvalidG10() {
|
||||
Color.WHITE.setGreen(Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testInvalidG11() {
|
||||
Color.WHITE.setGreen(Integer.MIN_VALUE);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testInvalidG12() {
|
||||
Color.WHITE.setGreen(0x100);
|
||||
}
|
||||
}
|
@ -403,7 +403,7 @@ public abstract class ConfigurationSectionTest {
|
||||
map.put("two", "two");
|
||||
map.put("three", 3.14);
|
||||
|
||||
List<Object> value = Arrays.asList((Object) "One", "Two", "Three", 4, "5", 6.0, true, "false", map);
|
||||
List<Object> value = Arrays.asList("One", "Two", "Three", 4, "5", 6.0, true, "false", map);
|
||||
|
||||
section.set(key, value);
|
||||
|
||||
|
@ -1,55 +0,0 @@
|
||||
package org.bukkit.configuration.file;
|
||||
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.enchantments.EnchantmentTarget;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
public class TestEnchantment extends Enchantment {
|
||||
|
||||
public static void registerEnchantments() {
|
||||
Enchantment.registerEnchantment(new TestEnchantment(0, "DUMMY_0"));
|
||||
Enchantment.registerEnchantment(new TestEnchantment(1, "DUMMY_1"));
|
||||
Enchantment.registerEnchantment(new TestEnchantment(2, "DUMMY_2"));
|
||||
Enchantment.registerEnchantment(new TestEnchantment(3, "DUMMY_3"));
|
||||
Enchantment.registerEnchantment(new TestEnchantment(4, "DUMMY_4"));
|
||||
Enchantment.registerEnchantment(new TestEnchantment(5, "DUMMY_5"));
|
||||
}
|
||||
|
||||
private final String name;
|
||||
|
||||
private TestEnchantment(final int id, final String name) {
|
||||
super(id);
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxLevel() {
|
||||
return 5;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getStartLevel() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EnchantmentTarget getItemTarget() {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canEnchantItem(ItemStack item) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean conflictsWith(Enchantment other) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
@ -1,19 +1,9 @@
|
||||
package org.bukkit.configuration.file;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.configuration.InvalidConfigurationException;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class YamlConfigurationTest extends FileConfigurationTest {
|
||||
static {
|
||||
TestEnchantment.registerEnchantments();
|
||||
}
|
||||
|
||||
@Override
|
||||
public YamlConfiguration getConfig() {
|
||||
@ -63,47 +53,4 @@ public class YamlConfigurationTest extends FileConfigurationTest {
|
||||
|
||||
assertEquals(expected, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSaveRestoreCompositeList() throws InvalidConfigurationException {
|
||||
YamlConfiguration out = getConfig();
|
||||
|
||||
List<ItemStack> stacks = new ArrayList<ItemStack>();
|
||||
stacks.add(new ItemStack(1));
|
||||
stacks.add(new ItemStack(2));
|
||||
stacks.add(new ItemStack(3));
|
||||
stacks.add(new ItemStack(4, 17));
|
||||
stacks.add(new ItemStack(5, 63));
|
||||
stacks.add(new ItemStack(6, 1, (short) 1));
|
||||
stacks.add(new ItemStack(18, 32, (short) 2));
|
||||
|
||||
ItemStack item7 = new ItemStack(256);
|
||||
item7.addEnchantment(Enchantment.getById(1), 1);
|
||||
stacks.add(item7);
|
||||
|
||||
ItemStack item8 = new ItemStack(257);
|
||||
item8.addEnchantment(Enchantment.getById(2), 2);
|
||||
item8.addEnchantment(Enchantment.getById(3), 1);
|
||||
item8.addEnchantment(Enchantment.getById(4), 5);
|
||||
item8.addEnchantment(Enchantment.getById(5), 4);
|
||||
stacks.add(item8);
|
||||
|
||||
out.set("composite-list.abc.def", stacks);
|
||||
String yaml = out.saveToString();
|
||||
|
||||
YamlConfiguration in = new YamlConfiguration();
|
||||
in.loadFromString(yaml);
|
||||
List<?> raw = in.getList("composite-list.abc.def");
|
||||
|
||||
assertEquals(stacks.size(), raw.size());
|
||||
assertEquals(stacks.get(0), raw.get(0));
|
||||
assertEquals(stacks.get(1), raw.get(1));
|
||||
assertEquals(stacks.get(2), raw.get(2));
|
||||
assertEquals(stacks.get(3), raw.get(3));
|
||||
assertEquals(stacks.get(4), raw.get(4));
|
||||
assertEquals(stacks.get(5), raw.get(5));
|
||||
assertEquals(stacks.get(6), raw.get(6));
|
||||
assertEquals(stacks.get(7), raw.get(7));
|
||||
assertEquals(stacks.get(8), raw.get(8));
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user