From d4ccff74c90614375b4bc41c032bfa19c6bb2ae5 Mon Sep 17 00:00:00 2001 From: sovdee <10354869+sovdeeth@users.noreply.github.com> Date: Mon, 1 Jul 2024 22:38:24 +0200 Subject: [PATCH] Exposes 'load default aliases' config option and removes hardcoded alias dependencies (#6834) * Removes dependencies on hardcoded aliases (javaItemType) and exposes 'load deafult aliases' config option * Update ItemUtils.java * Apply suggestions from code review Co-authored-by: Patrick Miller * requested changes * requested * Update src/main/java/ch/njol/skript/expressions/ExprSpawnerType.java Co-authored-by: Patrick Miller --------- Co-authored-by: Patrick Miller --- .../java/ch/njol/skript/aliases/Aliases.java | 11 ++- .../java/ch/njol/skript/aliases/ItemType.java | 13 +++ .../ch/njol/skript/bukkitutil/ItemUtils.java | 59 +++++++++++- .../bukkitutil/block/NewBlockCompat.java | 90 ++++++++++--------- .../classes/data/BukkitEventValues.java | 6 +- .../classes/data/DefaultComparators.java | 3 +- .../java/ch/njol/skript/effects/EffEquip.java | 61 +++++++++++-- .../ch/njol/skript/effects/EffOpenBook.java | 5 +- .../ch/njol/skript/entity/BoatChestData.java | 29 ++---- .../java/ch/njol/skript/entity/BoatData.java | 24 ++--- .../njol/skript/entity/ThrownPotionData.java | 19 ++-- .../java/ch/njol/skript/events/EvtMoveOn.java | 14 ++- .../njol/skript/events/EvtPressurePlate.java | 31 +++++-- .../skript/expressions/ExprBurnCookTime.java | 15 ++-- .../ch/njol/skript/expressions/ExprName.java | 4 +- .../njol/skript/expressions/ExprSignText.java | 22 ++--- .../ch/njol/skript/expressions/ExprSkull.java | 5 +- .../skript/expressions/ExprSpawnerType.java | 19 ++-- src/main/resources/config.sk | 10 +++ 19 files changed, 290 insertions(+), 150 deletions(-) diff --git a/src/main/java/ch/njol/skript/aliases/Aliases.java b/src/main/java/ch/njol/skript/aliases/Aliases.java index 56bffc24f9a..fe1a3a624c4 100644 --- a/src/main/java/ch/njol/skript/aliases/Aliases.java +++ b/src/main/java/ch/njol/skript/aliases/Aliases.java @@ -25,6 +25,7 @@ import ch.njol.skript.config.Node; import ch.njol.skript.config.SectionNode; import ch.njol.skript.entity.EntityData; +import org.bukkit.entity.EntityType; import org.skriptlang.skript.lang.script.Script; import ch.njol.skript.lang.parser.ParserInstance; import ch.njol.skript.localization.ArgsMessage; @@ -431,7 +432,6 @@ private static void loadInternal() throws IOException { Path aliasesPath = zipFs.getPath("/", "aliases-english"); assert aliasesPath != null; loadDirectory(aliasesPath); - loadMissingAliases(); } } catch (URISyntaxException e) { assert false; @@ -445,6 +445,9 @@ private static void loadInternal() throws IOException { assert aliasesFolder != null; loadDirectory(aliasesFolder); } + + // generate aliases from item names for any missing items + loadMissingAliases(); // Update tracked item types for (Map.Entry entry : trackedTypes.entrySet()) { @@ -554,10 +557,16 @@ public static EntityData getRelatedEntity(ItemData data) { *

Item types provided by this method are updated when aliases are * reloaded. However, this also means they are tracked by aliases system * and NOT necessarily garbage-collected. + * + *

Relying on this method to create item types is not safe, + * as users can change aliases at any point. ItemTypes should instead be created + * via {@link Material}s, {@link org.bukkit.Tag}s, or any other manual method. + * * @param name Name of item to search from aliases. * @return An item. * @throws IllegalArgumentException When item is not found. */ + @Deprecated(forRemoval = true, since = "2.9.0") public static ItemType javaItemType(String name) { ItemType type = parseItemType(name); if (type == null) { diff --git a/src/main/java/ch/njol/skript/aliases/ItemType.java b/src/main/java/ch/njol/skript/aliases/ItemType.java index 0b47617ef5c..efaa59249f2 100644 --- a/src/main/java/ch/njol/skript/aliases/ItemType.java +++ b/src/main/java/ch/njol/skript/aliases/ItemType.java @@ -40,6 +40,7 @@ import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.OfflinePlayer; +import org.bukkit.Tag; import org.bukkit.block.Block; import org.bukkit.block.BlockState; import org.bukkit.block.Skull; @@ -173,6 +174,18 @@ public ItemType(Material id) { add_(new ItemData(id)); } + public ItemType(Material... ids) { + for (Material id : ids) { + add_(new ItemData(id)); + } + } + + public ItemType(Tag tag) { + for (Material id : tag.getValues()) { + add_(new ItemData(id)); + } + } + public ItemType(Material id, String tags) { add_(new ItemData(id, tags)); } diff --git a/src/main/java/ch/njol/skript/bukkitutil/ItemUtils.java b/src/main/java/ch/njol/skript/bukkitutil/ItemUtils.java index 216be44b918..611aba0d1d7 100644 --- a/src/main/java/ch/njol/skript/bukkitutil/ItemUtils.java +++ b/src/main/java/ch/njol/skript/bukkitutil/ItemUtils.java @@ -21,7 +21,13 @@ import ch.njol.skript.Skript; import ch.njol.skript.aliases.ItemType; import org.bukkit.Material; +import org.bukkit.Tag; import org.bukkit.TreeType; +import org.bukkit.block.Block; +import org.bukkit.block.data.BlockData; +import org.bukkit.block.data.type.Fence; +import org.bukkit.block.data.type.Gate; +import org.bukkit.block.data.type.Wall; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.Damageable; import org.bukkit.inventory.meta.ItemMeta; @@ -234,5 +240,56 @@ public static boolean isAir(Material type) { public static Material getTreeSapling(TreeType treeType) { return TREE_TO_SAPLING_MAP.get(treeType); } - + + + private static final boolean HAS_FENCE_TAGS = !Skript.isRunningMinecraft(1, 14); + + /** + * Whether the block is a fence or a wall. + * @param block the block to check. + * @return whether the block is a fence/wall. + */ + public static boolean isFence(Block block) { + // TODO: 1.13 only, so remove in 2.10 + if (!HAS_FENCE_TAGS) { + BlockData data = block.getBlockData(); + return data instanceof Fence + || data instanceof Wall + || data instanceof Gate; + } + + Material type = block.getType(); + return Tag.FENCES.isTagged(type) + || Tag.FENCE_GATES.isTagged(type) + || Tag.WALLS.isTagged(type); + } + + /** + * @param material The material to check + * @return whether the material is a full glass block + */ + public static boolean isGlass(Material material) { + switch (material) { + case GLASS: + case RED_STAINED_GLASS: + case ORANGE_STAINED_GLASS: + case YELLOW_STAINED_GLASS: + case LIGHT_BLUE_STAINED_GLASS: + case BLUE_STAINED_GLASS: + case CYAN_STAINED_GLASS: + case LIME_STAINED_GLASS: + case GREEN_STAINED_GLASS: + case MAGENTA_STAINED_GLASS: + case PURPLE_STAINED_GLASS: + case PINK_STAINED_GLASS: + case WHITE_STAINED_GLASS: + case LIGHT_GRAY_STAINED_GLASS: + case GRAY_STAINED_GLASS: + case BLACK_STAINED_GLASS: + case BROWN_STAINED_GLASS: + return true; + default: + return false; + } + } } diff --git a/src/main/java/ch/njol/skript/bukkitutil/block/NewBlockCompat.java b/src/main/java/ch/njol/skript/bukkitutil/block/NewBlockCompat.java index e5cf9c0567b..e72a947996f 100644 --- a/src/main/java/ch/njol/skript/bukkitutil/block/NewBlockCompat.java +++ b/src/main/java/ch/njol/skript/bukkitutil/block/NewBlockCompat.java @@ -22,6 +22,7 @@ import ch.njol.skript.aliases.Aliases; import ch.njol.skript.aliases.ItemType; import ch.njol.skript.aliases.MatchQuality; +import ch.njol.skript.bukkitutil.ItemUtils; import ch.njol.skript.variables.Variables; import ch.njol.yggdrasil.Fields; import org.bukkit.Bukkit; @@ -31,10 +32,12 @@ import org.bukkit.block.Block; import org.bukkit.block.BlockFace; import org.bukkit.block.BlockState; +import org.bukkit.block.BlockSupport; import org.bukkit.block.data.Bisected; import org.bukkit.block.data.BlockData; import org.bukkit.block.data.Directional; import org.bukkit.block.data.type.Bed; +import org.bukkit.block.data.type.Snow; import org.bukkit.entity.FallingBlock; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; @@ -141,15 +144,6 @@ public void deserialize(@NonNull Fields fields) throws StreamCorruptedException } private static class NewBlockSetter implements BlockSetter { - - private ItemType floorTorch; - private ItemType wallTorch; - - private ItemType specialTorchSides; - private ItemType specialTorchFloors; - - private boolean typesLoaded = false; - private static final BlockFace[] CARDINAL_FACES = new BlockFace[] {BlockFace.NORTH, BlockFace.EAST, BlockFace.SOUTH, BlockFace.WEST}; @@ -158,14 +152,11 @@ public NewBlockSetter() {} @Override public void setBlock(Block block, Material type, @Nullable BlockValues values, int flags) { - if (!typesLoaded) - loadTypes(); - - boolean rotate = (flags | ROTATE) != 0; - boolean rotateForce = (flags | ROTATE_FORCE) != 0; - boolean rotateFixType = (flags | ROTATE_FIX_TYPE) != 0; - boolean multipart = (flags | MULTIPART) != 0; - boolean applyPhysics = (flags | APPLY_PHYSICS) != 0; + boolean rotate = (flags & ROTATE) != 0; + boolean rotateForce = (flags & ROTATE_FORCE) != 0; + boolean rotateFixType = (flags & ROTATE_FIX_TYPE) != 0; + boolean multipart = (flags & MULTIPART) != 0; + boolean applyPhysics = (flags & APPLY_PHYSICS) != 0; NewBlockValues ourValues = null; if (values != null) ourValues = (NewBlockValues) values; @@ -178,31 +169,23 @@ public void setBlock(Block block, Material type, @Nullable BlockValues values, i */ boolean placed = false; if (rotate) { - if (floorTorch.isOfType(type) || (rotateFixType && wallTorch.isOfType(type))) { + if (type == Material.TORCH || (rotateFixType && type == Material.WALL_TORCH)) { // If floor torch cannot be placed, try a wall torch Block under = block.getRelative(0, -1, 0); - boolean canPlace = true; - if (!under.getType().isOccluding()) { // Usually cannot be placed, but there are exceptions - // TODO check for stairs and slabs, currently complicated since there is no 'any' alias - if (specialTorchFloors.isOfType(under)) { - canPlace = true; - } else { - canPlace = false; - } - } + boolean canPlace = canSupportFloorTorch(under); // Can't really place a floor torch, try wall one instead if (!canPlace) { BlockFace face = findWallTorchSide(block); if (face != null) { // Found better torch spot - block.setType(wallTorch.getMaterial()); + block.setType(Material.WALL_TORCH); Directional data = (Directional) block.getBlockData(); data.setFacing(face); block.setBlockData(data, applyPhysics); placed = true; } } - } else if (wallTorch.isOfType(type)) { + } else if (type == Material.WALL_TORCH) { Directional data; if (ourValues != null) data = (Directional) ourValues.data; @@ -210,7 +193,7 @@ public void setBlock(Block block, Material type, @Nullable BlockValues values, i data = (Directional) Bukkit.createBlockData(type); Block relative = block.getRelative(data.getFacing()); - if ((!relative.getType().isOccluding() && !specialTorchSides.isOfType(relative)) || rotateForce) { + if ((!canSupportWallTorch(relative, data.getFacing().getOppositeFace())) || rotateForce) { // Attempt to figure out a better rotation BlockFace face = findWallTorchSide(block); if (face != null) { // Found better torch spot @@ -294,22 +277,49 @@ public void setBlock(Block block, Material type, @Nullable BlockValues values, i block.setBlockData(ourValues.data, applyPhysics); } } - - private void loadTypes() { - floorTorch = Aliases.javaItemType("floor torch"); - wallTorch = Aliases.javaItemType("wall torch"); - - specialTorchSides = Aliases.javaItemType("special torch sides"); - specialTorchFloors = Aliases.javaItemType("special torch floors"); - - typesLoaded = true; + + // 1.19+ + // TODO: remove in 2.10 + private static final boolean HAS_BLOCK_SUPPORT = Skript.classExists("org.bukkit.block.BlockSupport"); + + /** + * Returns whether this block can support a floor torch. + * @param block The block the torch will be placed on + * @return whether the block can support the torch. + */ + private static boolean canSupportFloorTorch(Block block) { + if (HAS_BLOCK_SUPPORT) + return block.getBlockData().isFaceSturdy(BlockFace.UP, BlockSupport.CENTER); + + Material material = block.getType(); + return (material.isOccluding() + || canSupportWallTorch(block, null) + || ItemUtils.isFence(block) + || ItemUtils.isGlass(material) + || material == Material.HOPPER + || (material == Material.SNOW && (((Snow) block.getBlockData()).getLayers() == 8)) + ); + } + + /** + * Returns whether this block can support a wall torch. In 1.19+, a face can be specified. + * @param block The block the torch will be placed on + * @param face The face the torch will be placed on (only considered in 1.19+) + * @return whether the block face can support the torch. + */ + private static boolean canSupportWallTorch(Block block, @Nullable BlockFace face) { + if (HAS_BLOCK_SUPPORT && face != null) + return block.getBlockData().isFaceSturdy(face, BlockSupport.FULL); + + Material material = block.getType(); + return material.isOccluding() || material == Material.SOUL_SAND || material == Material.SPAWNER; } @Nullable private BlockFace findWallTorchSide(Block block) { for (BlockFace face : CARDINAL_FACES) { Block relative = block.getRelative(face); - if (relative.getType().isOccluding() || specialTorchSides.isOfType(relative)) + if (relative.getType().isOccluding() || canSupportWallTorch(relative, face.getOppositeFace())) return face.getOppositeFace(); // Torch can be rotated towards from this face } diff --git a/src/main/java/ch/njol/skript/classes/data/BukkitEventValues.java b/src/main/java/ch/njol/skript/classes/data/BukkitEventValues.java index 6a49566c827..34792550178 100644 --- a/src/main/java/ch/njol/skript/classes/data/BukkitEventValues.java +++ b/src/main/java/ch/njol/skript/classes/data/BukkitEventValues.java @@ -392,12 +392,11 @@ public Block get(final BlockBreakEvent e) { return new DelayedChangeBlock(e.getBlock()); } }, 0); - ItemType stationaryWater = Aliases.javaItemType("stationary water"); EventValues.registerEventValue(BlockBreakEvent.class, Block.class, new Getter() { @Override public Block get(final BlockBreakEvent e) { final BlockState s = e.getBlock().getState(); - s.setType(s.getType() == Material.ICE ? stationaryWater.getMaterial() : Material.AIR); + s.setType(s.getType() == Material.ICE ? Material.WATER : Material.AIR); s.setRawData((byte) 0); return new BlockStateBlock(s, true); } @@ -760,12 +759,11 @@ public Block get(final PlayerBucketEmptyEvent e) { return e.getBlockClicked().getRelative(e.getBlockFace()); } }, -1); - ItemType stationaryLava = Aliases.javaItemType("stationary lava"); EventValues.registerEventValue(PlayerBucketEmptyEvent.class, Block.class, new Getter() { @Override public Block get(final PlayerBucketEmptyEvent e) { final BlockState s = e.getBlockClicked().getRelative(e.getBlockFace()).getState(); - s.setType(e.getBucket() == Material.WATER_BUCKET ? stationaryWater.getMaterial() : stationaryLava.getMaterial()); + s.setType(e.getBucket() == Material.WATER_BUCKET ? Material.WATER : Material.LAVA); s.setRawData((byte) 0); return new BlockStateBlock(s, true); } diff --git a/src/main/java/ch/njol/skript/classes/data/DefaultComparators.java b/src/main/java/ch/njol/skript/classes/data/DefaultComparators.java index 87fa10b1089..e5e42bf1423 100644 --- a/src/main/java/ch/njol/skript/classes/data/DefaultComparators.java +++ b/src/main/java/ch/njol/skript/classes/data/DefaultComparators.java @@ -496,7 +496,6 @@ public boolean supportsOrdering() { }); // DamageCause - ItemType - ItemType lava = Aliases.javaItemType("lava"); Comparators.registerComparator(DamageCause.class, ItemType.class, new Comparator() { @Override public Relation compare(DamageCause dc, ItemType t) { @@ -504,7 +503,7 @@ public Relation compare(DamageCause dc, ItemType t) { case FIRE: return Relation.get(t.isOfType(Material.FIRE)); case LAVA: - return Relation.get(t.equals(lava)); + return Relation.get(t.getMaterial() == Material.LAVA); case MAGIC: return Relation.get(t.isOfType(Material.POTION)); case HOT_FLOOR: diff --git a/src/main/java/ch/njol/skript/effects/EffEquip.java b/src/main/java/ch/njol/skript/effects/EffEquip.java index c66a5a1d2fd..baa7334b160 100644 --- a/src/main/java/ch/njol/skript/effects/EffEquip.java +++ b/src/main/java/ch/njol/skript/effects/EffEquip.java @@ -18,7 +18,9 @@ */ package ch.njol.skript.effects; +import ch.njol.skript.aliases.ItemData; import org.bukkit.Material; +import org.bukkit.Tag; import org.bukkit.entity.AbstractHorse; import org.bukkit.entity.ChestedHorse; import org.bukkit.entity.LivingEntity; @@ -93,13 +95,58 @@ public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelaye private static final boolean SUPPORTS_STEERABLE = Skript.classExists("org.bukkit.entity.Steerable"); - private static final ItemType CHESTPLATE = Aliases.javaItemType("chestplate"); - private static final ItemType LEGGINGS = Aliases.javaItemType("leggings"); - private static final ItemType BOOTS = Aliases.javaItemType("boots"); - private static final ItemType HORSE_ARMOR = Aliases.javaItemType("horse armor"); - private static final ItemType SADDLE = Aliases.javaItemType("saddle"); - private static final ItemType CHEST = Aliases.javaItemType("chest"); - private static final ItemType CARPET = Aliases.javaItemType("carpet"); + private static ItemType CHESTPLATE; + private static ItemType LEGGINGS; + private static ItemType BOOTS; + private static ItemType CARPET; + private static final ItemType HORSE_ARMOR = new ItemType(Material.IRON_HORSE_ARMOR, Material.GOLDEN_HORSE_ARMOR, Material.DIAMOND_HORSE_ARMOR); + private static final ItemType SADDLE = new ItemType(Material.SADDLE); + private static final ItemType CHEST = new ItemType(Material.CHEST); + + static { + boolean usesWoolCarpetTag = Skript.fieldExists(Tag.class, "WOOL_CARPET"); + CARPET = new ItemType(usesWoolCarpetTag ? Tag.WOOL_CARPETS : Tag.CARPETS); + // added in 1.20.6 + if (Skript.fieldExists(Tag.class, "ITEM_CHEST_ARMOR")) { + CHESTPLATE = new ItemType(Tag.ITEMS_CHEST_ARMOR); + LEGGINGS = new ItemType(Tag.ITEMS_LEG_ARMOR); + BOOTS = new ItemType(Tag.ITEMS_FOOT_ARMOR); + } else { + CHESTPLATE = new ItemType( + Material.LEATHER_CHESTPLATE, + Material.CHAINMAIL_CHESTPLATE, + Material.GOLDEN_CHESTPLATE, + Material.IRON_CHESTPLATE, + Material.DIAMOND_CHESTPLATE, + Material.ELYTRA + ); + + LEGGINGS = new ItemType( + Material.LEATHER_LEGGINGS, + Material.CHAINMAIL_LEGGINGS, + Material.GOLDEN_LEGGINGS, + Material.IRON_LEGGINGS, + Material.DIAMOND_LEGGINGS + ); + + BOOTS = new ItemType( + Material.LEATHER_BOOTS, + Material.CHAINMAIL_BOOTS, + Material.GOLDEN_BOOTS, + Material.IRON_BOOTS, + Material.DIAMOND_BOOTS + ); + + // netherite + if (Skript.isRunningMinecraft(1,16)) { + CHESTPLATE.add(new ItemData(Material.NETHERITE_CHESTPLATE)); + LEGGINGS.add(new ItemData(Material.NETHERITE_LEGGINGS)); + BOOTS.add(new ItemData(Material.NETHERITE_BOOTS)); + } + } + } + + private static final ItemType[] ALL_EQUIPMENT = new ItemType[] {CHESTPLATE, LEGGINGS, BOOTS, HORSE_ARMOR, SADDLE, CHEST, CARPET}; diff --git a/src/main/java/ch/njol/skript/effects/EffOpenBook.java b/src/main/java/ch/njol/skript/effects/EffOpenBook.java index 5b96114818b..f49df089abe 100644 --- a/src/main/java/ch/njol/skript/effects/EffOpenBook.java +++ b/src/main/java/ch/njol/skript/effects/EffOpenBook.java @@ -18,6 +18,7 @@ */ package ch.njol.skript.effects; +import org.bukkit.Material; import org.bukkit.entity.Player; import org.bukkit.event.Event; import org.bukkit.inventory.ItemStack; @@ -49,8 +50,6 @@ public class EffOpenBook extends Effect { } } - private static final ItemType bookItemType = Aliases.javaItemType("written book"); - @SuppressWarnings("null") private Expression book; @SuppressWarnings("null") @@ -69,7 +68,7 @@ protected void execute(final Event e) { ItemType itemType = book.getSingle(e); if (itemType != null) { ItemStack itemStack = itemType.getRandom(); - if (itemStack != null && bookItemType.isOfType(itemStack)) { + if (itemStack.getType() == Material.WRITTEN_BOOK) { for (Player player : players.getArray(e)) { player.openBook(itemStack); } diff --git a/src/main/java/ch/njol/skript/entity/BoatChestData.java b/src/main/java/ch/njol/skript/entity/BoatChestData.java index bb8d8506e23..bb29004028d 100644 --- a/src/main/java/ch/njol/skript/entity/BoatChestData.java +++ b/src/main/java/ch/njol/skript/entity/BoatChestData.java @@ -23,6 +23,7 @@ import ch.njol.skript.aliases.ItemType; import ch.njol.skript.lang.Literal; import ch.njol.skript.lang.SkriptParser; +import org.bukkit.Material; import org.bukkit.TreeSpecies; import org.bukkit.entity.ChestBoat; import org.bukkit.inventory.ItemStack; @@ -32,21 +33,8 @@ public class BoatChestData extends EntityData { - private static ItemType oakBoat = null; - private static ItemType spruceBoat = null; - private static ItemType birchBoat = null; - private static ItemType jungleBoat = null; - private static ItemType acaciaBoat = null; - private static ItemType darkOakBoat = null; - static { if (Skript.classExists("org.bukkit.entity.ChestBoat")) { - oakBoat = Aliases.javaItemType("oak chest boat"); - spruceBoat = Aliases.javaItemType("spruce chest boat"); - birchBoat = Aliases.javaItemType("birch chest boat"); - jungleBoat = Aliases.javaItemType("jungle chest boat"); - acaciaBoat = Aliases.javaItemType("acacia chest boat"); - darkOakBoat = Aliases.javaItemType("dark oak chest boat"); EntityData.register(BoatChestData.class, "chest boat", ChestBoat.class, 0, "chest boat", "any chest boat", "oak chest boat", "spruce chest boat", "birch chest boat", "jungle chest boat", "acacia chest boat", "dark oak chest boat"); @@ -120,22 +108,21 @@ public boolean isSupertypeOf(EntityData e) { } public boolean isOfItemType(ItemType itemType) { - if (itemType.getRandom() == null) - return false; int ordinal = -1; ItemStack stack = itemType.getRandom(); - if (oakBoat.isOfType(stack)) + Material type = stack.getType(); + if (type == Material.OAK_CHEST_BOAT) ordinal = 0; - else if (spruceBoat.isOfType(stack)) + else if (type == Material.SPRUCE_CHEST_BOAT) ordinal = TreeSpecies.REDWOOD.ordinal(); - else if (birchBoat.isOfType(stack)) + else if (type == Material.BIRCH_CHEST_BOAT) ordinal = TreeSpecies.BIRCH.ordinal(); - else if (jungleBoat.isOfType(stack)) + else if (type == Material.JUNGLE_CHEST_BOAT) ordinal = TreeSpecies.JUNGLE.ordinal(); - else if (acaciaBoat.isOfType(stack)) + else if (type == Material.ACACIA_CHEST_BOAT) ordinal = TreeSpecies.ACACIA.ordinal(); - else if (darkOakBoat.isOfType(stack)) + else if (type == Material.DARK_OAK_CHEST_BOAT) ordinal = TreeSpecies.DARK_OAK.ordinal(); return hashCode_i() == ordinal + 2 || (matchedPattern + ordinal == 0) || ordinal == 0; } diff --git a/src/main/java/ch/njol/skript/entity/BoatData.java b/src/main/java/ch/njol/skript/entity/BoatData.java index dfeb1f22890..b273f2ca370 100644 --- a/src/main/java/ch/njol/skript/entity/BoatData.java +++ b/src/main/java/ch/njol/skript/entity/BoatData.java @@ -18,8 +18,10 @@ */ package ch.njol.skript.entity; +import java.lang.reflect.Method; import java.util.Random; +import org.bukkit.Material; import org.bukkit.TreeSpecies; import org.bukkit.entity.Boat; import org.bukkit.inventory.ItemStack; @@ -108,30 +110,22 @@ public boolean isSupertypeOf(EntityData e) { return false; } - private static final ItemType oakBoat = Aliases.javaItemType("oak boat"); - private static final ItemType spruceBoat = Aliases.javaItemType("spruce boat"); - private static final ItemType birchBoat = Aliases.javaItemType("birch boat"); - private static final ItemType jungleBoat = Aliases.javaItemType("jungle boat"); - private static final ItemType acaciaBoat = Aliases.javaItemType("acacia boat"); - private static final ItemType darkOakBoat = Aliases.javaItemType("dark oak boat"); - public boolean isOfItemType(ItemType i){ - if (i.getRandom() == null) - return false; int ordinal = -1; ItemStack stack = i.getRandom(); - if (oakBoat.isOfType(stack)) + Material type = stack.getType(); + if (type == Material.OAK_BOAT) ordinal = 0; - else if (spruceBoat.isOfType(stack)) + else if (type == Material.SPRUCE_BOAT) ordinal = TreeSpecies.REDWOOD.ordinal(); - else if (birchBoat.isOfType(stack)) + else if (type == Material.BIRCH_BOAT) ordinal = TreeSpecies.BIRCH.ordinal(); - else if (jungleBoat.isOfType(stack)) + else if (type == Material.JUNGLE_BOAT) ordinal = TreeSpecies.JUNGLE.ordinal(); - else if (acaciaBoat.isOfType(stack)) + else if (type == Material.ACACIA_BOAT) ordinal = TreeSpecies.ACACIA.ordinal(); - else if (darkOakBoat.isOfType(stack)) + else if (type == Material.DARK_OAK_BOAT) ordinal = TreeSpecies.DARK_OAK.ordinal(); return hashCode_i() == ordinal + 2 || (matchedPattern + ordinal == 0) || ordinal == 0; diff --git a/src/main/java/ch/njol/skript/entity/ThrownPotionData.java b/src/main/java/ch/njol/skript/entity/ThrownPotionData.java index 407460d56c5..12d03199fbe 100644 --- a/src/main/java/ch/njol/skript/entity/ThrownPotionData.java +++ b/src/main/java/ch/njol/skript/entity/ThrownPotionData.java @@ -22,6 +22,7 @@ import java.util.function.Consumer; import org.bukkit.Location; +import org.bukkit.Material; import org.bukkit.entity.LingeringPotion; import org.bukkit.entity.ThrownPotion; import org.bukkit.inventory.ItemStack; @@ -51,9 +52,9 @@ public class ThrownPotionData extends EntityData { @SuppressWarnings("removal") private static final Class LINGERING_POTION_ENTITY_CLASS = LINGERING_POTION_ENTITY_USED ? LingeringPotion.class : ThrownPotion.class; - private static final ItemType POTION = Aliases.javaItemType("potion"); - private static final ItemType SPLASH_POTION = Aliases.javaItemType("splash potion"); - private static final ItemType LINGER_POTION = Aliases.javaItemType("lingering potion"); + private static final Material POTION = Material.POTION; + private static final Material SPLASH_POTION = Material.SPLASH_POTION; + private static final Material LINGER_POTION = Material.LINGERING_POTION; @Nullable private ItemType[] types; @@ -63,18 +64,18 @@ protected boolean init(Literal[] exprs, int matchedPattern, ParseResult parse if (exprs.length > 0 && exprs[0] != null) { return (types = Converters.convert((ItemType[]) exprs[0].getAll(), ItemType.class, t -> { // If the itemtype is a potion, lets make it a splash potion (required by Bukkit) - if (t.isSupertypeOf(POTION)) { + if (t.getMaterial() == POTION) { ItemMeta meta = t.getItemMeta(); - ItemType itemType = SPLASH_POTION.clone(); + ItemType itemType = new ItemType(SPLASH_POTION); itemType.setItemMeta(meta); return itemType; - } else if (!t.isSupertypeOf(SPLASH_POTION ) && !t.isSupertypeOf(LINGER_POTION)) { + } else if (t.getMaterial() != SPLASH_POTION && t.getMaterial() != LINGER_POTION) { return null; } return t; })).length != 0; // no error message - other things can be thrown as well } else { - types = new ItemType[]{SPLASH_POTION.clone()}; + types = new ItemType[]{new ItemType(SPLASH_POTION)}; } return true; } @@ -109,7 +110,7 @@ protected boolean match(ThrownPotion entity) { if (i == null) return null; - Class thrownPotionClass = (Class) (LINGER_POTION.isOfType(i) ? LINGERING_POTION_ENTITY_CLASS : ThrownPotion.class); + Class thrownPotionClass = (Class) (i.getType() == LINGER_POTION ? LINGERING_POTION_ENTITY_CLASS : ThrownPotion.class); ThrownPotion potion; if (consumer != null) { potion = EntityData.spawn(location, thrownPotionClass, consumer); @@ -131,7 +132,7 @@ public void set(ThrownPotion entity) { ItemStack i = t.getRandom(); if (i == null) return; // Missing item, can't make thrown potion of it - if (LINGERING_POTION_ENTITY_USED && (LINGERING_POTION_ENTITY_CLASS.isInstance(entity) != LINGER_POTION.isOfType(i))) + if (LINGERING_POTION_ENTITY_USED && (LINGERING_POTION_ENTITY_CLASS.isInstance(entity) != (LINGER_POTION == i.getType()))) return; entity.setItem(i); } diff --git a/src/main/java/ch/njol/skript/events/EvtMoveOn.java b/src/main/java/ch/njol/skript/events/EvtMoveOn.java index 52b552b0040..c5677e5783c 100644 --- a/src/main/java/ch/njol/skript/events/EvtMoveOn.java +++ b/src/main/java/ch/njol/skript/events/EvtMoveOn.java @@ -33,6 +33,7 @@ import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.Material; +import org.bukkit.Tag; import org.bukkit.block.Block; import org.bukkit.event.Event; import org.bukkit.event.Listener; @@ -66,9 +67,6 @@ public class EvtMoveOn extends SkriptEvent { ).since("2.0"); } - // Fence blocks and fence gates - private static final ItemType FENCE_PART = Aliases.javaItemType("fence part"); - private static final Map> ITEM_TYPE_TRIGGERS = new ConcurrentHashMap<>(); private static final AtomicBoolean REGISTERED_EXECUTOR = new AtomicBoolean(); @@ -87,10 +85,10 @@ public class EvtMoveOn extends SkriptEvent { if (triggers == null) return; - int y = getBlockY(to.getY(), id); + int y = getBlockY(to.getY(), block); if (to.getWorld().equals(from.getWorld()) && to.getBlockX() == from.getBlockX() && to.getBlockZ() == from.getBlockZ()) { Block fromOnBlock = getOnBlock(from); - if (fromOnBlock != null && y == getBlockY(from.getY(), fromOnBlock.getType()) && fromOnBlock.getType() == id) + if (fromOnBlock != null && y == getBlockY(from.getY(), fromOnBlock) && fromOnBlock.getType() == id) return; } @@ -114,14 +112,14 @@ private static Block getOnBlock(Location location) { Block block = location.getWorld().getBlockAt(location.getBlockX(), (int) (Math.ceil(location.getY()) - 1), location.getBlockZ()); if (block.getType() == Material.AIR && Math.abs((location.getY() - location.getBlockY()) - 0.5) < Skript.EPSILON) { // Fences block = location.getWorld().getBlockAt(location.getBlockX(), location.getBlockY() - 1, location.getBlockZ()); - if (!FENCE_PART.isOfType(block)) + if (!ItemUtils.isFence(block)) return null; } return block; } - private static int getBlockY(double y, Material id) { - if (FENCE_PART.isOfType(id) && Math.abs((y - Math.floor(y)) - 0.5) < Skript.EPSILON) + private static int getBlockY(double y, Block block) { + if (ItemUtils.isFence(block) && Math.abs((y - Math.floor(y)) - 0.5) < Skript.EPSILON) return (int) Math.floor(y) - 1; return (int) Math.ceil(y) - 1; } diff --git a/src/main/java/ch/njol/skript/events/EvtPressurePlate.java b/src/main/java/ch/njol/skript/events/EvtPressurePlate.java index de320c57f26..4d3f876a3b5 100644 --- a/src/main/java/ch/njol/skript/events/EvtPressurePlate.java +++ b/src/main/java/ch/njol/skript/events/EvtPressurePlate.java @@ -19,6 +19,7 @@ package ch.njol.skript.events; import org.bukkit.Material; +import org.bukkit.Tag; import org.bukkit.block.Block; import org.bukkit.event.Event; import org.bukkit.event.block.Action; @@ -36,6 +37,9 @@ * @author Peter Güttinger */ public class EvtPressurePlate extends SkriptEvent { + + private static final boolean HAS_PRESSURE_PLATE_TAG = Skript.fieldExists(Tag.class, "PRESSURE_PLATES"); + static { // TODO is EntityInteractEvent similar for entities? Skript.registerEvent("Pressure Plate / Trip", EvtPressurePlate.class, PlayerInteractEvent.class, @@ -46,8 +50,6 @@ public class EvtPressurePlate extends SkriptEvent { .since("1.0 (pressure plate), 1.4.4 (tripwire)"); } - private static final ItemType plate = Aliases.javaItemType("pressure plate"); - private boolean tripwire; @Override @@ -55,14 +57,25 @@ public boolean init(final Literal[] args, final int matchedPattern, final Par tripwire = matchedPattern == 1; return true; } - + @Override - public boolean check(final Event e) { - final Block b = ((PlayerInteractEvent) e).getClickedBlock(); - final Material type = b == null ? null : b.getType(); - return type != null && ((PlayerInteractEvent) e).getAction() == Action.PHYSICAL && - (tripwire ? (type == Material.TRIPWIRE || type == Material.TRIPWIRE_HOOK) - : plate.isOfType(type)); + public boolean check(Event event) { + Block clickedBlock = ((PlayerInteractEvent) event).getClickedBlock(); + Material type = clickedBlock == null ? null : clickedBlock.getType(); + if (type == null || ((PlayerInteractEvent) event).getAction() != Action.PHYSICAL ) + return false; + + if (tripwire) + return(type == Material.TRIPWIRE || type == Material.TRIPWIRE_HOOK); + + // TODO: 1.16+, remove check in 2.10 + if (HAS_PRESSURE_PLATE_TAG) + return Tag.PRESSURE_PLATES.isTagged(type); + + return Tag.WOODEN_PRESSURE_PLATES.isTagged(type) + || type == Material.HEAVY_WEIGHTED_PRESSURE_PLATE + || type == Material.LIGHT_WEIGHTED_PRESSURE_PLATE + || type == Material.STONE_PRESSURE_PLATE; } @Override diff --git a/src/main/java/ch/njol/skript/expressions/ExprBurnCookTime.java b/src/main/java/ch/njol/skript/expressions/ExprBurnCookTime.java index 3763d242dc1..0d98c551925 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprBurnCookTime.java +++ b/src/main/java/ch/njol/skript/expressions/ExprBurnCookTime.java @@ -23,6 +23,7 @@ import ch.njol.skript.classes.Changer.ChangeMode; import org.bukkit.block.Block; +import org.bukkit.block.BlockState; import org.bukkit.block.Furnace; import org.bukkit.event.Event; import org.bukkit.event.inventory.FurnaceBurnEvent; @@ -65,8 +66,6 @@ public class ExprBurnCookTime extends PropertyExpression { "[the] (burn|1:cook)[ing] time of %blocks%", "%blocks%'[s] (burn|1:cook)[ing] time"); } - - static final ItemType anyFurnace = Aliases.javaItemType("any furnace"); private boolean cookTime; private boolean isEvent; @@ -92,10 +91,11 @@ protected Timespan[] get(Event event, Block[] source) { return CollectionUtils.array(Timespan.fromTicks(((FurnaceBurnEvent) event).getBurnTime())); } else { return Arrays.stream(source) - .filter(anyFurnace::isOfType) - .map(furnace -> { - Furnace state = (Furnace) furnace.getState(); - return Timespan.fromTicks(cookTime ? state.getCookTime() : state.getBurnTime()); + .map(Block::getState) + .filter(blockState -> blockState instanceof Furnace) + .map(state -> { + Furnace furnace = (Furnace) state; + return Timespan.fromTicks(cookTime ? furnace.getCookTime() : furnace.getBurnTime()); }) .toArray(Timespan[]::new); } @@ -141,7 +141,8 @@ public void change(Event event, @Nullable Object[] delta, ChangeMode mode) { } for (Block block : getExpr().getArray(event)) { - if (!anyFurnace.isOfType(block)) + BlockState state = block.getState(); + if (!(state instanceof Furnace)) continue; Furnace furnace = (Furnace) block.getState(); long time = value.apply(Timespan.fromTicks(cookTime ? furnace.getCookTime() : furnace.getBurnTime())).getTicks(); diff --git a/src/main/java/ch/njol/skript/expressions/ExprName.java b/src/main/java/ch/njol/skript/expressions/ExprName.java index b6f873e0b89..666a39092a1 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprName.java +++ b/src/main/java/ch/njol/skript/expressions/ExprName.java @@ -24,6 +24,7 @@ import java.util.ArrayList; import java.util.List; +import ch.njol.skript.bukkitutil.ItemUtils; import org.bukkit.Bukkit; import org.bukkit.GameRule; import org.bukkit.Nameable; @@ -139,7 +140,6 @@ public class ExprName extends SimplePropertyExpression { * 3 = "tablist name" */ private int mark; - private static final ItemType AIR = Aliases.javaItemType("air"); @Override public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { @@ -282,7 +282,7 @@ public void change(Event event, @Nullable Object[] delta, ChangeMode mode) { } else if (object instanceof Slot) { Slot s = (Slot) object; ItemStack is = s.getItem(); - if (is != null && !AIR.isOfType(is)) { + if (is != null && !ItemUtils.isAir(is.getType())) { ItemMeta m = is.hasItemMeta() ? is.getItemMeta() : Bukkit.getItemFactory().getItemMeta(is.getType()); m.setDisplayName(name); is.setItemMeta(m); diff --git a/src/main/java/ch/njol/skript/expressions/ExprSignText.java b/src/main/java/ch/njol/skript/expressions/ExprSignText.java index 592420ed647..0b549483b17 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprSignText.java +++ b/src/main/java/ch/njol/skript/expressions/ExprSignText.java @@ -18,7 +18,10 @@ */ package ch.njol.skript.expressions; +import ch.njol.skript.bukkitutil.ItemUtils; +import org.bukkit.Material; import org.bukkit.block.Block; +import org.bukkit.block.BlockState; import org.bukkit.block.Sign; import org.bukkit.event.Event; import org.bukkit.event.block.SignChangeEvent; @@ -56,8 +59,6 @@ public class ExprSignText extends SimpleExpression { "[the] line %number% [of %block%]", "[the] (1¦1st|1¦first|2¦2nd|2¦second|3¦3rd|3¦third|4¦4th|4¦fourth) line [of %block%]"); } - private static final ItemType sign = Aliases.javaItemType("sign"); - @SuppressWarnings("null") private Expression line; @SuppressWarnings("null") @@ -99,7 +100,7 @@ protected String[] get(final Event e) { final Block b = block.getSingle(e); if (b == null) return new String[0]; - if (!sign.isOfType(b)) + if (!(b.getState() instanceof Sign)) return new String[0]; return new String[] {((Sign) b.getState()).getLine(line)}; } @@ -143,27 +144,28 @@ public void change(final Event e, final @Nullable Object[] delta, final ChangeMo break; } } else { - if (!sign.isOfType(b)) + BlockState state = b.getState(); + if (!(state instanceof Sign)) return; - final Sign s = (Sign) b.getState(); + Sign sign = (Sign) b.getState(); switch (mode) { case DELETE: - s.setLine(line, ""); + sign.setLine(line, ""); break; case SET: assert delta != null; - s.setLine(line, (String) delta[0]); + sign.setLine(line, (String) delta[0]); break; } if (hasUpdateBooleanBoolean) { try { - s.update(false, false); + sign.update(false, false); } catch (final NoSuchMethodError err) { hasUpdateBooleanBoolean = false; - s.update(); + sign.update(); } } else { - s.update(); + sign.update(); } } } diff --git a/src/main/java/ch/njol/skript/expressions/ExprSkull.java b/src/main/java/ch/njol/skript/expressions/ExprSkull.java index e3a0fa2767d..4e133a79bfd 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprSkull.java +++ b/src/main/java/ch/njol/skript/expressions/ExprSkull.java @@ -18,6 +18,7 @@ */ package ch.njol.skript.expressions; +import org.bukkit.Material; import org.bukkit.OfflinePlayer; import org.bukkit.inventory.meta.SkullMeta; import org.eclipse.jdt.annotation.Nullable; @@ -48,8 +49,6 @@ public class ExprSkull extends SimplePropertyExpression { register(ExprSkull.class, ItemType.class, "(head|skull)", "offlineplayers"); } - private static final ItemType playerSkull = Aliases.javaItemType("player skull"); - /** * In 2017, SkullMeta finally got a method that takes OfflinePlayer. */ @@ -64,7 +63,7 @@ public boolean init(final Expression[] exprs, final int matchedPattern, final @Override @Nullable public ItemType convert(final Object o) { - ItemType skull = playerSkull.clone(); + ItemType skull = new ItemType(Material.PLAYER_HEAD); SkullMeta meta = (SkullMeta) skull.getItemMeta(); if (newSkullOwner) meta.setOwningPlayer((OfflinePlayer) o); diff --git a/src/main/java/ch/njol/skript/expressions/ExprSpawnerType.java b/src/main/java/ch/njol/skript/expressions/ExprSpawnerType.java index d9d31b824cc..24b59ae9dd3 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprSpawnerType.java +++ b/src/main/java/ch/njol/skript/expressions/ExprSpawnerType.java @@ -22,6 +22,7 @@ import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.block.CreatureSpawner; +import org.bukkit.entity.EntityType; import org.bukkit.event.Event; import org.eclipse.jdt.annotation.Nullable; @@ -44,18 +45,19 @@ @Since("2.4") public class ExprSpawnerType extends SimplePropertyExpression { - private static final Material MATERIAL_SPAWNER = Aliases.javaItemType("spawner").getMaterial(); - static { register(ExprSpawnerType.class, EntityData.class, "(spawner|entity|creature) type[s]", "blocks"); } @Override @Nullable - public EntityData convert(final Block b) { - if (b.getType() != MATERIAL_SPAWNER) + public EntityData convert(Block block) { + if (!(block.getState() instanceof CreatureSpawner)) + return null; + EntityType type = ((CreatureSpawner) block.getState()).getSpawnedType(); + if (type == null) return null; - return EntityUtils.toSkriptEntityData(((CreatureSpawner) b.getState()).getSpawnedType()); + return EntityUtils.toSkriptEntityData(type); } @Nullable @@ -68,13 +70,14 @@ public Class[] acceptChange(Changer.ChangeMode mode) { @SuppressWarnings("null") @Override - public void change(final Event e, final @Nullable Object[] delta, final ChangeMode mode) { - for (Block b : getExpr().getArray(e)) { - if (b.getType() != MATERIAL_SPAWNER) + public void change(Event event, Object @Nullable [] delta, ChangeMode mode) { + for (Block b : getExpr().getArray(event)) { + if (!(b.getState() instanceof CreatureSpawner)) continue; CreatureSpawner s = (CreatureSpawner) b.getState(); switch (mode) { case SET: + assert delta != null; s.setSpawnedType(EntityUtils.toBukkitEntityType((EntityData) delta[0])); break; case RESET: diff --git a/src/main/resources/config.sk b/src/main/resources/config.sk index 4ba081e7c33..ff5e1e9e40a 100644 --- a/src/main/resources/config.sk +++ b/src/main/resources/config.sk @@ -80,6 +80,16 @@ log effect commands: false # Whether Skript should log the usage of effect commands. # They will be logged as [INFORMATION] in this format: ' issued effect command: ' + +load default aliases: true +# Whether Skript should use the default, Skript-provided aliases for items. +# Disabling this will cause all aliases to be automatically generated. Some items, like potions, +# will likely not have aliases in this case. +# +# You can provide your own aliases by making an 'aliases' folder in the Skript directory and putting the alias files there. +# The default aliases folder is available with Skript releases on GitHub. + + player variable fix: true # Whether to enable the player variable fix if a player has rejoined and was reciding inside a variable. # Player objects inside a variable(list or normal) are not updated to the new player object