diff --git a/Spigot-API-Patches/0158-Add-Material-Tags.patch b/Spigot-API-Patches/0158-Add-Material-Tags.patch new file mode 100644 index 000000000..678d4d959 --- /dev/null +++ b/Spigot-API-Patches/0158-Add-Material-Tags.patch @@ -0,0 +1,589 @@ +From 9451a08ced2d13e369f3c2f4c3aea4b7615dd26b Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 17 Jul 2018 01:27:15 -0400 +Subject: [PATCH] Add Material Tags + +This adds a bunch of useful and missing Tags to be able to identify items that +are related to each other by a trait. + +diff --git a/src/main/java/com/destroystokyo/paper/MaterialSetTag.java b/src/main/java/com/destroystokyo/paper/MaterialSetTag.java +new file mode 100644 +index 000000000..b4f78e075 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/MaterialSetTag.java +@@ -0,0 +1,139 @@ ++/* ++ * Copyright (c) 2018 Daniel Ennis (Aikar) MIT License ++ */ ++ ++package com.destroystokyo.paper; ++ ++import com.google.common.collect.Lists; ++import com.google.common.collect.Sets; ++import org.bukkit.Material; ++import org.bukkit.Tag; ++import org.bukkit.block.Block; ++import org.bukkit.block.BlockState; ++import org.bukkit.block.data.BlockData; ++import org.bukkit.inventory.ItemStack; ++ ++import java.util.Collection; ++import java.util.Set; ++import java.util.function.Predicate; ++import java.util.stream.Collectors; ++import java.util.stream.Stream; ++ ++public class MaterialSetTag implements Tag { ++ ++ private final Set materials; ++ ++ public MaterialSetTag(Predicate filter) { ++ this(Stream.of(Material.values()).filter(filter).collect(Collectors.toList())); ++ } ++ ++ public MaterialSetTag(Collection materials) { ++ this.materials = Sets.newEnumSet(materials, Material.class); ++ } ++ ++ public MaterialSetTag(Material... materials) { ++ this.materials = Sets.newEnumSet(Lists.newArrayList(materials), Material.class); ++ } ++ ++ public MaterialSetTag add(Tag... tags) { ++ for (Tag tag : tags) { ++ add(tag.getValues()); ++ } ++ return this; ++ } ++ ++ public MaterialSetTag add(MaterialSetTag... tags) { ++ for (Tag tag : tags) { ++ add(tag.getValues()); ++ } ++ return this; ++ } ++ ++ public MaterialSetTag add(Material... material) { ++ this.materials.addAll(Lists.newArrayList(material)); ++ return this; ++ } ++ ++ public MaterialSetTag add(Collection materials) { ++ this.materials.addAll(materials); ++ return this; ++ } ++ ++ public MaterialSetTag contains(String with) { ++ return add(mat -> mat.name().contains(with)); } ++ ++ public MaterialSetTag endsWith(String with) { ++ return add(mat -> mat.name().endsWith(with)); ++ } ++ ++ ++ public MaterialSetTag startsWith(String with) { ++ return add(mat -> mat.name().startsWith(with)); ++ } ++ ++ public MaterialSetTag add(Predicate filter) { ++ add(Stream.of(Material.values()).filter(((Predicate) Material::isLegacy).negate()).filter(filter).collect(Collectors.toList())); ++ return this; ++ } ++ ++ public MaterialSetTag not(MaterialSetTag tags) { ++ not(tags.getValues()); ++ return this; ++ } ++ ++ public MaterialSetTag not(Material... material) { ++ this.materials.removeAll(Lists.newArrayList(material)); ++ return this; ++ } ++ ++ public MaterialSetTag not(Collection materials) { ++ this.materials.removeAll(materials); ++ return this; ++ } ++ ++ public MaterialSetTag not(Predicate filter) { ++ not(Stream.of(Material.values()).filter(((Predicate) Material::isLegacy).negate()).filter(filter).collect(Collectors.toList())); ++ return this; ++ } ++ ++ public MaterialSetTag notEndsWith(String with) { ++ return not(mat -> mat.name().endsWith(with)); ++ } ++ ++ ++ public MaterialSetTag notStartsWith(String with) { ++ return not(mat -> mat.name().startsWith(with)); ++ } ++ ++ public Set getValues() { ++ return this.materials; ++ } ++ ++ public boolean isTagged(BlockData block) { ++ return isTagged(block.getMaterial()); ++ } ++ ++ public boolean isTagged(BlockState block) { ++ return isTagged(block.getType()); ++ } ++ ++ public boolean isTagged(Block block) { ++ return isTagged(block.getType()); ++ } ++ ++ public boolean isTagged(ItemStack item) { ++ return isTagged(item.getType()); ++ } ++ ++ public boolean isTagged(Material material) { ++ return this.materials.contains(material); ++ } ++ ++ public MaterialSetTag ensureSize(String label, int size) { ++ long actual = this.materials.stream().filter(((Predicate) Material::isLegacy).negate()).count(); ++ if (size != actual) { ++ throw new IllegalStateException(label + " - Expected " + size + " materials, got " + actual); ++ } ++ return this; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/MaterialTags.java b/src/main/java/com/destroystokyo/paper/MaterialTags.java +new file mode 100644 +index 000000000..92bb0aef5 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/MaterialTags.java +@@ -0,0 +1,377 @@ ++/* ++ * Copyright (c) 2018 Daniel Ennis (Aikar) MIT License ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining ++ * a copy of this software and associated documentation files (the ++ * "Software"), to deal in the Software without restriction, including ++ * without limitation the rights to use, copy, modify, merge, publish, ++ * distribute, sublicense, and/or sell copies of the Software, and to ++ * permit persons to whom the Software is furnished to do so, subject to ++ * the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be ++ * included in all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND ++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE ++ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION ++ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION ++ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ++ */ ++ ++package com.destroystokyo.paper; ++ ++import org.bukkit.Material; ++import org.bukkit.Tag; ++ ++/** ++ * Represents a collection tags to identify materials that share common properties. ++ * Will map to minecraft for missing tags, as well as custom ones that may be useful. ++ */ ++@SuppressWarnings("NonFinalUtilityClass") ++public class MaterialTags { ++ ++ public static final MaterialSetTag ARROWS = new MaterialSetTag() ++ .endsWith("ARROW") ++ .ensureSize("ARROWS", 3); ++ ++ /** ++ * Cover all 16 colors of beds. ++ */ ++ public static final MaterialSetTag BEDS = new MaterialSetTag() ++ .endsWith("_BED") ++ .ensureSize("BEDS", 16); ++ ++ /** ++ * Covers all bucket items. ++ */ ++ public static final MaterialSetTag BUCKETS = new MaterialSetTag() ++ .endsWith("BUCKET") ++ .ensureSize("BUCKETS", 8); ++ ++ /** ++ * Covers coal and charcoal. ++ */ ++ public static final MaterialSetTag COALS = new MaterialSetTag() ++ .add(Material.COAL, Material.CHARCOAL); ++ ++ /** ++ * Covers both cobblestone wall variants. ++ */ ++ public static final MaterialSetTag COBBLESTONE_WALLS = new MaterialSetTag() ++ .endsWith("COBBLESTONE_WALL") ++ .ensureSize("COBBLESTONE_WALLS", 2); ++ ++ /** ++ * Covers both cobblestone and mossy Cobblestone. ++ */ ++ public static final MaterialSetTag COBBLESTONES = new MaterialSetTag() ++ .add(Material.COBBLESTONE, Material.MOSSY_COBBLESTONE); ++ ++ /** ++ * Covers all 16 colors of concrete. ++ */ ++ public static final MaterialSetTag CONCRETES = new MaterialSetTag() ++ .endsWith("_CONCRETE") ++ .ensureSize("CONCRETES", 16); ++ ++ /** ++ * Covers all 16 colors of concrete powder. ++ */ ++ public static final MaterialSetTag CONCRETE_POWDER = new MaterialSetTag() ++ .endsWith("_CONCRETE_POWDER") ++ .ensureSize("CONCRETE_POWDER", 16); ++ ++ /** ++ * Covers the two types of cooked fish. ++ */ ++ public static final MaterialSetTag COOKED_FISH = new MaterialSetTag() ++ .add(Material.COOKED_COD, Material.COOKED_SALMON); ++ ++ /** ++ * Covers all 16 dyes. ++ */ ++ public static final MaterialSetTag DYES = new MaterialSetTag() ++ .endsWith("_DYE") ++ .add(Material.BONE_MEAL, ++ Material.CACTUS_GREEN, ++ Material.COCOA_BEANS, ++ Material.DANDELION_YELLOW, ++ Material.INK_SAC, ++ Material.LAPIS_LAZULI, ++ Material.ROSE_RED ++ ) ++ .ensureSize("DYES", 16); ++ ++ /** ++ * Covers all 6 wood variants of gates. ++ */ ++ public static final MaterialSetTag FENCE_GATES = new MaterialSetTag() ++ .endsWith("_GATE") ++ .ensureSize("FENCE_GATES", 6); ++ ++ /** ++ * Covers all 6 wood variants and nether brick fence. ++ */ ++ public static final MaterialSetTag FENCES = new MaterialSetTag() ++ .endsWith("_FENCE") ++ .ensureSize("FENCES", 7); ++ ++ /** ++ * Covers all 4 variants of fish buckets. ++ */ ++ public static final MaterialSetTag FISH_BUCKETS = new MaterialSetTag() ++ .add(Material.COD_BUCKET, Material.PUFFERFISH_BUCKET, Material.SALMON_BUCKET, Material.TROPICAL_FISH_BUCKET); ++ ++ /** ++ * Covers the non-colored glass and 16 stained glass (not panes). ++ */ ++ public static final MaterialSetTag GLASS = new MaterialSetTag() ++ .endsWith("_GLASS") ++ .add(Material.GLASS) ++ .ensureSize("GLASS", 17); ++ ++ /** ++ * Covers the non-colored glass panes and 16 stained glass panes (panes only). ++ */ ++ public static final MaterialSetTag GLASS_PANES = new MaterialSetTag() ++ .endsWith("GLASS_PANE") ++ .ensureSize("GLASS_PANES", 17); ++ ++ /** ++ * Covers all 16 glazed terracotta blocks. ++ */ ++ public static final MaterialSetTag GLAZED_TERRACOTTA = new MaterialSetTag() ++ .endsWith("GLAZED_TERRACOTTA") ++ .ensureSize("GLAZED_TERRACOTTA", 16); ++ ++ /** ++ * Covers the 16 colors of stained terracotta. ++ */ ++ public static final MaterialSetTag STAINED_TERRACOTTA = new MaterialSetTag() ++ .endsWith("TERRACOTTA") ++ .not(Material.TERRACOTTA) ++ .notEndsWith("GLAZED_TERRACOTTA") ++ .ensureSize("STAINED_TERRACOTTA", 16); ++ ++ /** ++ * Covers terracotta along with the 16 stained variants. ++ */ ++ public static final MaterialSetTag TERRACOTTA = new MaterialSetTag() ++ .endsWith("TERRACOTTA") ++ .ensureSize("TERRACOTTA", 33); ++ ++ ++ /** ++ * Covers both golden apples. ++ */ ++ public static final MaterialSetTag GOLDEN_APPLES = new MaterialSetTag() ++ .endsWith("GOLDEN_APPLE") ++ .ensureSize("GOLDEN_APPLES", 2); ++ ++ /** ++ * Covers the 3 variants of horse armor. ++ */ ++ public static final MaterialSetTag HORSE_ARMORS = new MaterialSetTag() ++ .endsWith("_HORSE_ARMOR") ++ .ensureSize("HORSE_ARMORS", 3); ++ ++ /** ++ * Covers the 6 variants of infested blocks. ++ */ ++ public static final MaterialSetTag INFESTED_BLOCKS = new MaterialSetTag() ++ .startsWith("INFESTED_") ++ .ensureSize("INFESTED_BLOCKS", 6); ++ ++ /** ++ * Covers the 3 variants of mushroom blocks. ++ */ ++ public static final MaterialSetTag MUSHROOM_BLOCKS = new MaterialSetTag() ++ .endsWith("MUSHROOM_BLOCK") ++ .add(Material.MUSHROOM_STEM) ++ .ensureSize("MUSHROOM_BLOCKS", 3); ++ ++ /** ++ * Covers both mushrooms. ++ */ ++ public static final MaterialSetTag MUSHROOMS = new MaterialSetTag() ++ .add(Material.BROWN_MUSHROOM, Material.RED_MUSHROOM); ++ ++ /** ++ * Covers all 12 music disc items. ++ */ ++ public static final MaterialSetTag MUSIC_DISCS = new MaterialSetTag() ++ .startsWith("MUSIC_DISC_") ++ .ensureSize("MUSIC_DISCS", 12); ++ ++ /** ++ * Covers all 8 ores. ++ */ ++ public static final MaterialSetTag ORES = new MaterialSetTag() ++ .endsWith("_ORE") ++ .ensureSize("ORES", 8); ++ ++ /** ++ * Covers all piston typed items and blocks including the piston head and moving piston. ++ */ ++ public static final MaterialSetTag PISTONS = new MaterialSetTag() ++ .contains("PISTON") ++ .ensureSize("PISTONS", 4); ++ ++ /** ++ * Covers all potato items. ++ */ ++ public static final MaterialSetTag POTATOES = new MaterialSetTag() ++ .endsWith("POTATO") ++ .ensureSize("POTATOES", 3); ++ ++ /** ++ * Covers all 6 wooden pressure plates and the 2 weighted pressure plates and 1 stone pressure plate. ++ */ ++ public static final MaterialSetTag PRESSURE_PLATES = new MaterialSetTag() ++ .endsWith("_PRESSURE_PLATE") ++ .ensureSize("PRESSURE_PLATES", 9); ++ ++ /** ++ * Covers the 3 variants of prismarine blocks. ++ */ ++ public static final MaterialSetTag PRISMARINE = new MaterialSetTag() ++ .add(Material.PRISMARINE, Material.PRISMARINE_BRICKS, Material.DARK_PRISMARINE); ++ ++ /** ++ * Covers the 3 variants of prismarine slabs. ++ */ ++ public static final MaterialSetTag PRISMARINE_SLABS = new MaterialSetTag() ++ .add(Material.PRISMARINE_SLAB, Material.PRISMARINE_BRICK_SLAB, Material.DARK_PRISMARINE_SLAB); ++ ++ /** ++ * Covers the 3 variants of prismarine stairs. ++ */ ++ public static final MaterialSetTag PRISMARINE_STAIRS = new MaterialSetTag() ++ .add(Material.PRISMARINE_STAIRS, Material.PRISMARINE_BRICK_STAIRS, Material.DARK_PRISMARINE_STAIRS); ++ ++ /** ++ * Covers the 3 variants of pumpkins. ++ */ ++ public static final MaterialSetTag PUMPKINS = new MaterialSetTag() ++ .add(Material.CARVED_PUMPKIN, Material.JACK_O_LANTERN, Material.PUMPKIN); ++ ++ /** ++ * Covers the 4 variants of quartz blocks. ++ */ ++ public static final MaterialSetTag QUARTZ_BLOCKS = new MaterialSetTag() ++ .add(Material.QUARTZ_BLOCK, Material.QUARTZ_PILLAR, Material.CHISELED_QUARTZ_BLOCK, Material.SMOOTH_QUARTZ); ++ ++ /** ++ * Covers all uncooked fish items. ++ */ ++ public static final MaterialSetTag RAW_FISH = new MaterialSetTag() ++ .add(Material.COD, Material.PUFFERFISH, Material.SALMON, Material.TROPICAL_FISH); ++ ++ /** ++ * Covers the 4 variants of red sandstone blocks. ++ */ ++ public static final MaterialSetTag RED_SANDSTONES = new MaterialSetTag() ++ .endsWith("RED_SANDSTONE") ++ .ensureSize("RED_SANDSTONES", 4); ++ ++ /** ++ * Covers the 4 variants of sandstone blocks. ++ */ ++ public static final MaterialSetTag SANDSTONES = new MaterialSetTag() ++ .add(Material.SANDSTONE, Material.CHISELED_SANDSTONE, Material.CUT_SANDSTONE, Material.SMOOTH_SANDSTONE); ++ ++ /** ++ * Covers sponge and wet sponge. ++ */ ++ public static final MaterialSetTag SPONGES = new MaterialSetTag() ++ .endsWith("SPONGE") ++ .ensureSize("SPONGES", 2); ++ ++ /** ++ * Covers the non-colored and 16 colored shulker boxes. ++ */ ++ public static final MaterialSetTag SHULKER_BOXES = new MaterialSetTag() ++ .endsWith("SHULKER_BOX") ++ .ensureSize("SHULKER_BOXES", 17); ++ ++ /** ++ * Covers zombie, creeper, skeleton, dragon, and player heads. ++ */ ++ public static final MaterialSetTag SKULLS = new MaterialSetTag() ++ .endsWith("_HEAD") ++ .endsWith("_SKULL") ++ .not(Material.PISTON_HEAD) ++ .ensureSize("SKULLS", 12); ++ ++ /** ++ * Covers all spawn egg items. ++ */ ++ public static final MaterialSetTag SPAWN_EGGS = new MaterialSetTag() ++ .endsWith("_SPAWN_EGG") ++ .ensureSize("SPAWN_EGGS", 51); ++ ++ /** ++ * Covers all 16 colors of stained glass. ++ */ ++ public static final MaterialSetTag STAINED_GLASS = new MaterialSetTag() ++ .endsWith("_STAINED_GLASS") ++ .ensureSize("STAINED_GLASS", 16); ++ ++ /** ++ * Covers all 16 colors of stained glass panes. ++ */ ++ public static final MaterialSetTag STAINED_GLASS_PANES = new MaterialSetTag() ++ .endsWith("STAINED_GLASS_PANE") ++ .ensureSize("STAINED_GLASS_PANES", 16); ++ ++ /** ++ * Covers all 7 variants of trapdoors. ++ */ ++ public static final MaterialSetTag TRAPDOORS = new MaterialSetTag() ++ .endsWith("_TRAPDOOR") ++ .ensureSize("TRAPDOORS", 7); ++ ++ /** ++ * Covers all 6 wood variants of fences. ++ */ ++ public static final MaterialSetTag WOODEN_FENCES = new MaterialSetTag() ++ .endsWith("_FENCE") ++ .not(Material.NETHER_BRICK_FENCE) ++ .ensureSize("WOODEN_FENCES", 6); ++ ++ /** ++ * Covers all 6 wood variants of trapdoors. ++ */ ++ public static final MaterialSetTag WOODEN_TRAPDOORS = new MaterialSetTag() ++ .endsWith("_TRAPDOOR") ++ .not(Material.IRON_TRAPDOOR) ++ .ensureSize("WOODEN_TRAPDOORS", 6); ++ ++ public static final MaterialSetTag WOODEN_GATES = new MaterialSetTag() ++ .endsWith("_GATE") ++ .ensureSize("WOODEN_GATES", 6); ++ ++ public static final MaterialSetTag PURPUR = new MaterialSetTag() ++ .startsWith("PURPUR_") ++ .ensureSize("PURPUR", 4); ++ ++ public static final MaterialSetTag SIGNS = new MaterialSetTag() ++ .add(Material.SIGN, Material.WALL_SIGN) ++ .ensureSize("SIGNS", 2); ++ ++ public static final MaterialSetTag TORCH = new MaterialSetTag() ++ .add(Material.TORCH, Material.WALL_TORCH) ++ .ensureSize("TORCH", 2); ++ ++ public static final MaterialSetTag REDSTONE_TORCH = new MaterialSetTag() ++ .add(Material.REDSTONE_TORCH, Material.REDSTONE_WALL_TORCH) ++ .ensureSize("REDSTONE_TORCH", 2); ++ ++ @SuppressWarnings("unchecked") ++ public static final MaterialSetTag COLORABLE = new MaterialSetTag() ++ .add(Tag.WOOL, Tag.CARPETS).add(SHULKER_BOXES, STAINED_GLASS, STAINED_GLASS_PANES, CONCRETES, BEDS) ++ .ensureSize("COLORABLE", 81); ++} +diff --git a/src/test/java/com/destroystokyo/paper/MaterialTagsTest.java b/src/test/java/com/destroystokyo/paper/MaterialTagsTest.java +new file mode 100644 +index 000000000..01cf1041e +--- /dev/null ++++ b/src/test/java/com/destroystokyo/paper/MaterialTagsTest.java +@@ -0,0 +1,23 @@ ++/* ++ * Copyright (c) 2018 Daniel Ennis (Aikar) MIT License ++ */ ++ ++package com.destroystokyo.paper; ++ ++import org.bukkit.Bukkit; ++import org.junit.Test; ++ ++import java.util.logging.Level; ++ ++public class MaterialTagsTest { ++ @Test ++ public void testInitialize() { ++ try { ++ MaterialTags.SHULKER_BOXES.getValues(); ++ assert true; ++ } catch (Throwable e) { ++ Bukkit.getLogger().log(Level.SEVERE, e.getMessage(), e); ++ assert false; ++ } ++ } ++} +diff --git a/src/test/java/org/bukkit/TestServer.java b/src/test/java/org/bukkit/TestServer.java +index 2d8403206..613675c3b 100644 +--- a/src/test/java/org/bukkit/TestServer.java ++++ b/src/test/java/org/bukkit/TestServer.java +@@ -30,6 +30,16 @@ public class TestServer implements InvocationHandler { + } + } + ); ++ // Paper start ++ methodMap.put( ++ Server.class.getMethod("getTag", String.class, NamespacedKey.class, Class.class), ++ new MethodHandler() { ++ public Object handle(TestServer server, Object[] args) { ++ return new com.destroystokyo.paper.MaterialSetTag(); ++ } ++ } ++ ); ++ // Paper end + methodMap.put( + Server.class.getMethod("getPluginManager"), + new MethodHandler() { +-- +2.19.0 +