From 162c1c323fec03f72e4a81aa11ffb5b5a053f0ef Mon Sep 17 00:00:00 2001 From: ZephireNZ Date: Sun, 21 Sep 2014 16:55:58 +1200 Subject: [PATCH] Added API for manipulating banners and banner patterns. Banner blocks have facing, base color, and pattern. Banner patterns are a list of layers, which have a shape and color. --- src/main/java/org/bukkit/BannerPattern.java | 170 +++++++++++++ src/main/java/org/bukkit/Material.java | 4 +- src/main/java/org/bukkit/block/Banner.java | 38 +++ .../org/bukkit/inventory/meta/BannerMeta.java | 24 ++ src/main/java/org/bukkit/material/Banner.java | 240 ++++++++++++++++++ 5 files changed, 474 insertions(+), 2 deletions(-) create mode 100644 src/main/java/org/bukkit/BannerPattern.java create mode 100644 src/main/java/org/bukkit/block/Banner.java create mode 100644 src/main/java/org/bukkit/inventory/meta/BannerMeta.java create mode 100644 src/main/java/org/bukkit/material/Banner.java diff --git a/src/main/java/org/bukkit/BannerPattern.java b/src/main/java/org/bukkit/BannerPattern.java new file mode 100644 index 0000000000..c041eed139 --- /dev/null +++ b/src/main/java/org/bukkit/BannerPattern.java @@ -0,0 +1,170 @@ +package org.bukkit; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Maps; +import org.apache.commons.lang.Validate; + +import java.util.List; +import java.util.Map; + +/** + * Represents a complete pattern for a banner. + */ +public class BannerPattern { + + /** + * Represents an individual pattern texture on a banner.

+ */ + public static enum LayerTexture { + BORDER("bo"), + BOTTOM_HALF("hhb"), + BRICK("bri"), + CIRCLE("mc"), + CREEPER("cre"), + CURLY_BORDER("cbo"), + DIAGONAL_CROSS("cr"), + FLOWER("flo"), + GRADIENT("gra"), + GRADIENT_UP("gru"), + LEFT_HALF("vh"), + MOJANG("moj"), + RIGHT_HALF("vhr"), + RHOMBUS("mr"), + SAW_BOTTOM("bts"), + SAW_TOP("tts"), + SKULL("sku"), + STRIPES("ss"), + SQUARE_BOTTOM_LEFT("bl"), + SQUARE_BOTTOM_RIGHT("br"), + SQUARE_TOP_LEFT("tl"), + SQUARE_TOP_RIGHT("tr"), + STRIPE_BOTTOM("bs"), + STRAIGHT_CROSS("sc"), + STRIPE_DOWN_LEFT("dls"), + STRIPE_DOWN_RIGHT("drs"), + STRIPE_LEFT("ls"), + STRIPE_HORIZONTAL("ms"), + STRIPE_RIGHT("rs"), + STRIPE_TOP("ts"), + STRIPE_VERTICAL("cs"), + TOP_HALF("hh"), + TRIANGLE_BOTTOM("bt"), + TRIANGLE_BOTTOM_LEFT("lud"), + TRIANGLE_BOTTOM_RIGHT("rd"), + TRIANGLE_TOP("tt"), + TRIANGLE_TOP_LEFT("ld"), + TRIANGLE_TOP_RIGHT("rud"); + + private final String code; + private final static Map BY_CODE = Maps.newHashMap(); + + private LayerTexture(String code) { + this.code = code; + } + + /** + * Gets the internal code of this banner texture + * + * @return The 2 or 3 character pattern code + * @deprecated Magic value + */ + @Deprecated + public String getCode() { + return code; + } + + /** + * Gets a texture by the code + * + * @param code 2 or 3 character pattern code + * @return Banner pattern + * @deprecated Magic value + */ + @Deprecated + public static LayerTexture getByCode(String code) { + return BY_CODE.get(code); + } + + static { + for (LayerTexture type : LayerTexture.values()) { + BY_CODE.put(type.code, type); + } + } + } + + /** + * Representation of a single colored layer on a banner. + */ + public static class BannerLayer { + + private LayerTexture texture; + private DyeColor color; + + private BannerLayer(LayerTexture texture, DyeColor color) { + this.texture = texture; + this.color = color; + } + + public LayerTexture getTexture() { + return texture; + } + + public DyeColor getColor() { + return color; + } + } + + /** + * Construct a builder for a BannerPattern. + * + * @return BannerPattern Builder + */ + public static Builder builder() { + return new Builder(); + } + + public static final class Builder { + ImmutableList.Builder layers = ImmutableList.builder(); + + /** + * Adds a colored layer to the banner. + * + * @param texture Pattern for this layer + * @param color Color of the layer + * @return This object, for chaining + * @throws IllegalArgumentException If texture or color is null + */ + public Builder layer(LayerTexture texture, DyeColor color) { + Validate.notNull(texture, "Cannot have null texture"); + Validate.notNull(color, "Cannot have null color"); + layers.add(new BannerLayer(texture, color)); + + return this; + } + + /** + * Creates a {@link BannerPattern} from the contents of this builder. + * + * @return The built BannerPattern + */ + public BannerPattern build() { + return new BannerPattern(layers.build()); + } + } + + private final ImmutableList layers; + + private BannerPattern(ImmutableList layers) { + this.layers = layers; + } + + /** + * Get the layers of this pattern. + * + * @return The layers of this pattern + */ + public List getLayers() { + return layers; + } + +} \ No newline at end of file diff --git a/src/main/java/org/bukkit/Material.java b/src/main/java/org/bukkit/Material.java index f6c67968ec..f38ef73649 100644 --- a/src/main/java/org/bukkit/Material.java +++ b/src/main/java/org/bukkit/Material.java @@ -193,8 +193,8 @@ public enum Material { COAL_BLOCK(173), PACKED_ICE(174), DOUBLE_PLANT(175), - STANDING_BANNER(176), - WALL_BANNER(177), + STANDING_BANNER(176, Banner.class), + WALL_BANNER(177, Banner.class), DAYLIGHT_DETECTOR_INVERTED(178), RED_SANDSTONE(179, Sandstone.class), RED_SANDSTONE_STAIRS(180, Stairs.class), diff --git a/src/main/java/org/bukkit/block/Banner.java b/src/main/java/org/bukkit/block/Banner.java new file mode 100644 index 0000000000..8c16e69667 --- /dev/null +++ b/src/main/java/org/bukkit/block/Banner.java @@ -0,0 +1,38 @@ +package org.bukkit.block; + +import org.bukkit.BannerPattern; +import org.bukkit.DyeColor; + +/** + * Represents either a standing or hanging banner. + */ +public interface Banner extends BlockState { + + /** + * Sets the base color of the banner. + * + * @param color Base color, must not be null. + */ + public void setBase(DyeColor color); + + /** + * Get the base color of the banner. + * + * @return Base color + */ + public DyeColor getBase(); + + /** + * Sets the pattern of the banner. The old pattern is removed completely. + * + * @param pattern Pattern to change to, must not be null. + */ + public void setPattern(BannerPattern pattern); + + /** + * Gets the banner's pattern. + * + * @return Pattern currently on this banner + */ + public BannerPattern getPattern(); +} diff --git a/src/main/java/org/bukkit/inventory/meta/BannerMeta.java b/src/main/java/org/bukkit/inventory/meta/BannerMeta.java new file mode 100644 index 0000000000..eadef92fca --- /dev/null +++ b/src/main/java/org/bukkit/inventory/meta/BannerMeta.java @@ -0,0 +1,24 @@ +package org.bukkit.inventory.meta; + +import org.bukkit.BannerPattern; + +/** + * Represents a banner item. + */ +public interface BannerMeta extends ItemMeta { + + /** + * Sets the pattern of the banner. The old pattern is removed completely. + * + * @param pattern Pattern to change to, must not be null + */ + public void setPattern(BannerPattern pattern); + + /** + * Gets the banner's pattern. + * + * @return Pattern currently on this banner + */ + public BannerPattern getPattern(); + +} diff --git a/src/main/java/org/bukkit/material/Banner.java b/src/main/java/org/bukkit/material/Banner.java new file mode 100644 index 0000000000..3692c8516b --- /dev/null +++ b/src/main/java/org/bukkit/material/Banner.java @@ -0,0 +1,240 @@ +package org.bukkit.material; + +import org.bukkit.Material; +import org.bukkit.block.BlockFace; + +/** + * MaterialData for placed Banners + */ +public class Banner extends MaterialData implements Attachable { + + public Banner() { + super(Material.STANDING_BANNER); + } + + /** + * @deprecated Magic value + */ + @Deprecated + public Banner(final int type) { + super(type); + } + + public Banner(final Material type) { + super(type); + } + + /** + * @deprecated Magic value + */ + @Deprecated + public Banner(final int type, final byte data) { + super(type, data); + } + + /** + * @deprecated Magic value + */ + @Deprecated + public Banner(final Material type, final byte data) { + super(type, data); + } + + /** + * Check whether this Banner is attached to a wall. + * + * @return true if Banner is attached to a wall, false if on top of a block + */ + public boolean isWallBanner() { + return getItemType() == Material.WALL_BANNER; + } + + @Override + public BlockFace getAttachedFace() { + if (!isWallBanner()) { + return BlockFace.DOWN; + } + + byte data = getData(); + switch (data) { + case 0x2: + return BlockFace.SOUTH; + + case 0x3: + return BlockFace.NORTH; + + case 0x4: + return BlockFace.EAST; + + case 0x5: + return BlockFace.WEST; + + } + + return null; + } + + @Override + public void setFacingDirection(BlockFace face) { + byte data; + + if (isWallBanner()) { + switch (face) { + case NORTH: + data = 0x2; + break; + + case SOUTH: + data = 0x3; + break; + + case WEST: + data = 0x4; + break; + + case EAST: + default: + data = 0x5; + } + } else { + switch (face) { + case SOUTH: + data = 0x0; + break; + + case SOUTH_SOUTH_WEST: + data = 0x1; + break; + + case SOUTH_WEST: + data = 0x2; + break; + + case WEST_SOUTH_WEST: + data = 0x3; + break; + + case WEST: + data = 0x4; + break; + + case WEST_NORTH_WEST: + data = 0x5; + break; + + case NORTH_WEST: + data = 0x6; + break; + + case NORTH_NORTH_WEST: + data = 0x7; + break; + + case NORTH: + data = 0x8; + break; + + case NORTH_NORTH_EAST: + data = 0x9; + break; + + case NORTH_EAST: + data = 0xA; + break; + + case EAST_NORTH_EAST: + data = 0xB; + break; + + case EAST: + data = 0xC; + break; + + case EAST_SOUTH_EAST: + data = 0xD; + break; + + case SOUTH_SOUTH_EAST: + data = 0xF; + break; + + case SOUTH_EAST: + default: + data = 0xE; + } + } + + setData(data); + } + + @Override + public BlockFace getFacing() { + byte data = getData(); + + if (isWallBanner()) { + return getAttachedFace().getOppositeFace(); + } + + switch (data) { + case 0x0: + return BlockFace.SOUTH; + + case 0x1: + return BlockFace.SOUTH_SOUTH_WEST; + + case 0x2: + return BlockFace.SOUTH_WEST; + + case 0x3: + return BlockFace.WEST_SOUTH_WEST; + + case 0x4: + return BlockFace.WEST; + + case 0x5: + return BlockFace.WEST_NORTH_WEST; + + case 0x6: + return BlockFace.NORTH_WEST; + + case 0x7: + return BlockFace.NORTH_NORTH_WEST; + + case 0x8: + return BlockFace.NORTH; + + case 0x9: + return BlockFace.NORTH_NORTH_EAST; + + case 0xA: + return BlockFace.NORTH_EAST; + + case 0xB: + return BlockFace.EAST_NORTH_EAST; + + case 0xC: + return BlockFace.EAST; + + case 0xD: + return BlockFace.EAST_SOUTH_EAST; + + case 0xE: + return BlockFace.SOUTH_EAST; + + case 0xF: + return BlockFace.SOUTH_SOUTH_EAST; + } + + return null; + } + + @Override + public String toString() { + return super.toString() + " facing " + getFacing(); + } + + @Override + public Banner clone() { + return (Banner) super.clone(); + } +}