diff --git a/src/main/java/ch/njol/skript/classes/data/BukkitClasses.java b/src/main/java/ch/njol/skript/classes/data/BukkitClasses.java index 0e7cb76279a..988d179a882 100644 --- a/src/main/java/ch/njol/skript/classes/data/BukkitClasses.java +++ b/src/main/java/ch/njol/skript/classes/data/BukkitClasses.java @@ -24,8 +24,6 @@ import org.bukkit.block.banner.PatternType; import org.bukkit.block.data.BlockData; import org.bukkit.command.CommandSender; -import org.bukkit.enchantments.Enchantment; -import org.bukkit.enchantments.EnchantmentOffer; import org.bukkit.entity.*; import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; import org.bukkit.event.entity.EntityDamageEvent.DamageCause; @@ -424,17 +422,6 @@ public boolean mustSyncDeserialization() { } })); - Classes.registerClass(new RegistryClassInfo<>(Enchantment.class, Registry.ENCHANTMENT, "enchantment", "enchantments") - .user("enchantments?") - .name("Enchantment") - .description("An enchantment, e.g. 'sharpness' or 'fortune'. Unlike enchantment type " + - "this type has no level, but you usually don't need to use this type anyway.", - "NOTE: Minecraft namespaces are supported, ex: 'minecraft:basalt_deltas'.", - "As of Minecraft 1.21 this will also support custom enchantments using namespaces, ex: 'myenchants:explosive'.") - .examples("") - .since("1.4.6") - .before("enchantmenttype")); - Material[] allMaterials = Material.values(); Classes.registerClass(new ClassInfo<>(Material.class, "material") .name(ClassInfo.NO_DOC) @@ -615,31 +602,6 @@ public String[] getPatterns() { ExpressionPropertyHandler.of(GameRule::getName, String.class) )); - Classes.registerClass(new ClassInfo<>(EnchantmentOffer.class, "enchantmentoffer") - .user("enchant[ment][ ]offers?") - .name("Enchantment Offer") - .description("The enchantmentoffer in an enchant prepare event.") - .examples("on enchant prepare:", - "\tset enchant offer 1 to sharpness 1", - "\tset the cost of enchant offer 1 to 10 levels") - .since("2.5") - .parser(new Parser<>() { - @Override - public boolean canParse(ParseContext context) { - return false; - } - - @Override - public String toString(EnchantmentOffer eo, int flags) { - return Classes.toString(eo.getEnchantment()) + " " + eo.getEnchantmentLevel(); - } - - @Override - public String toVariableNameString(EnchantmentOffer eo) { - return "offer:" + Classes.toString(eo.getEnchantment()) + "=" + eo.getEnchantmentLevel(); - } - })); - Classes.registerClass(new RegistryClassInfo<>(Attribute.class, Registry.ATTRIBUTE, "attributetype", "attribute types") .user("attribute ?types?") .name("Attribute Type") 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 1fa65336b20..9dee9a86b63 100644 --- a/src/main/java/ch/njol/skript/classes/data/DefaultComparators.java +++ b/src/main/java/ch/njol/skript/classes/data/DefaultComparators.java @@ -545,35 +545,6 @@ public boolean supportsOrdering() { } }); - // EnchantmentOffer Comparators - // EnchantmentOffer - EnchantmentType - Comparators.registerComparator(EnchantmentOffer.class, EnchantmentType.class, new Comparator() { - @Override - public Relation compare(EnchantmentOffer eo, EnchantmentType et) { - return Relation.get(eo.getEnchantment() == et.getType() && eo.getEnchantmentLevel() == et.getLevel()); - } - - @Override - public boolean supportsOrdering() { - return false; - } - }); - // EnchantmentOffer - Experience - Comparators.registerComparator(EnchantmentOffer.class, Experience.class, new Comparator() { - @Override - public Relation compare(EnchantmentOffer eo, Experience exp) { - return Relation.get(eo.getCost() == exp.getXP()); - } - - @Override public boolean supportsOrdering() { - return false; - } - }); - - //EnchantmentType - Enchantment - Comparators.registerComparator(EnchantmentType.class, Enchantment.class, ((enchantmentType, enchantment) -> - Relation.get(enchantmentType.getType().equals(enchantment)))); - Comparators.registerComparator(Inventory.class, InventoryType.class, new Comparator() { @Override public Relation compare(Inventory inventory, InventoryType inventoryType) { diff --git a/src/main/java/ch/njol/skript/classes/data/DefaultConverters.java b/src/main/java/ch/njol/skript/classes/data/DefaultConverters.java index d27fbf7fd6e..577ab1b52b9 100644 --- a/src/main/java/ch/njol/skript/classes/data/DefaultConverters.java +++ b/src/main/java/ch/njol/skript/classes/data/DefaultConverters.java @@ -21,8 +21,6 @@ import org.bukkit.block.DoubleChest; import org.bukkit.command.BlockCommandSender; import org.bukkit.command.CommandSender; -import org.bukkit.enchantments.Enchantment; -import org.bukkit.enchantments.EnchantmentOffer; import org.bukkit.entity.Entity; import org.bukkit.entity.EntitySnapshot; import org.bukkit.entity.LivingEntity; @@ -304,15 +302,9 @@ public void setAmount(Number amount) { return null; }); - // Enchantment - EnchantmentType - Converters.registerConverter(Enchantment.class, EnchantmentType.class, e -> new EnchantmentType(e, -1)); - // Vector - Direction Converters.registerConverter(Vector.class, Direction.class, Direction::new); - // EnchantmentOffer - EnchantmentType - Converters.registerConverter(EnchantmentOffer.class, EnchantmentType.class, eo -> new EnchantmentType(eo.getEnchantment(), eo.getEnchantmentLevel())); - Converters.registerConverter(String.class, World.class, Bukkit::getWorld); if (Skript.classExists("org.bukkit.entity.EntitySnapshot")) diff --git a/src/main/java/ch/njol/skript/classes/data/SkriptClasses.java b/src/main/java/ch/njol/skript/classes/data/SkriptClasses.java index 4fd2d2de791..a5e5f69c269 100644 --- a/src/main/java/ch/njol/skript/classes/data/SkriptClasses.java +++ b/src/main/java/ch/njol/skript/classes/data/SkriptClasses.java @@ -382,33 +382,6 @@ public String toVariableNameString(Color color) { "grow a huge red mushroom above the block") .since("1.0")); - Classes.registerClass(new ClassInfo<>(EnchantmentType.class, "enchantmenttype") - .user("enchant(ing|ment) types?") - .name("Enchantment Type") - .description("An enchantment with an optional level, e.g. 'sharpness 2' or 'fortune'.") - .usage(" []") - .examples("enchant the player's tool with sharpness 5", - "helmet is enchanted with waterbreathing") - .since("1.4.6") - .parser(new Parser() { - @Override - @Nullable - public EnchantmentType parse(final String s, final ParseContext context) { - return EnchantmentType.parse(s); - } - - @Override - public String toString(final EnchantmentType t, final int flags) { - return t.toString(); - } - - @Override - public String toVariableNameString(final EnchantmentType o) { - return o.toString(); - } - }) - .serializer(new YggdrasilSerializer<>())); - Classes.registerClass(new ClassInfo<>(Experience.class, "experience") .user("experience ?(points?)?") .name("Experience") diff --git a/src/main/java/ch/njol/skript/expressions/ExprEnchantItem.java b/src/main/java/ch/njol/skript/expressions/ExprEnchantItem.java deleted file mode 100644 index b76aeccad44..00000000000 --- a/src/main/java/ch/njol/skript/expressions/ExprEnchantItem.java +++ /dev/null @@ -1,116 +0,0 @@ -package ch.njol.skript.expressions; - -import ch.njol.skript.lang.EventRestrictedSyntax; -import org.bukkit.event.Event; -import org.bukkit.event.enchantment.EnchantItemEvent; -import org.bukkit.event.enchantment.PrepareItemEnchantEvent; -import org.jetbrains.annotations.Nullable; - -import ch.njol.skript.Skript; -import ch.njol.skript.aliases.ItemType; -import ch.njol.skript.classes.Changer.ChangeMode; -import ch.njol.skript.doc.Description; -import ch.njol.skript.doc.Events; -import ch.njol.skript.doc.Example; -import ch.njol.skript.doc.Name; -import ch.njol.skript.doc.Since; -import ch.njol.skript.lang.Expression; -import ch.njol.skript.lang.ExpressionType; -import ch.njol.skript.lang.SkriptParser.ParseResult; -import ch.njol.skript.lang.util.SimpleExpression; -import ch.njol.skript.log.ErrorQuality; -import ch.njol.util.Kleenean; -import ch.njol.util.coll.CollectionUtils; - -@Name("Enchant Item") -@Description({"The enchant item in an enchant prepare event or enchant event.", - "It can be modified, but enchantments will still be applied in the enchant event."}) -@Example(""" - on enchant: - set the enchanted item to a diamond chestplate - """) -@Example(""" - on enchant prepare: - set the enchant item to a wooden sword - """) -@Events({"enchant prepare", "enchant"}) -@Since("2.5") -public class ExprEnchantItem extends SimpleExpression implements EventRestrictedSyntax { - - static { - Skript.registerExpression(ExprEnchantItem.class, ItemType.class, ExpressionType.SIMPLE, "[the] enchant[ed] item"); - } - - @Override - public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { - return true; - } - - @Override - public Class[] supportedEvents() { - return CollectionUtils.array(EnchantItemEvent.class, PrepareItemEnchantEvent.class); - } - - @Override - @Nullable - protected ItemType[] get(Event e) { - if (e instanceof PrepareItemEnchantEvent) - return new ItemType[]{new ItemType(((PrepareItemEnchantEvent) e).getItem())}; - else if (e instanceof EnchantItemEvent) - return new ItemType[]{new ItemType(((EnchantItemEvent) e).getItem())}; - else - return null; - } - - @Override - @Nullable - public Class[] acceptChange(ChangeMode mode) { - if (mode == ChangeMode.SET) - return CollectionUtils.array(ItemType.class); - return null; - } - - @Override - public void change(Event event, @Nullable Object[] delta, ChangeMode mode) { - if (delta == null) - return; - ItemType item = ((ItemType) delta[0]); - switch (mode) { - case SET: - if (event instanceof PrepareItemEnchantEvent) { - PrepareItemEnchantEvent e = (PrepareItemEnchantEvent) event; - e.getItem().setType(item.getMaterial()); - e.getItem().setItemMeta(item.getItemMeta()); - e.getItem().setAmount(item.getAmount()); - } else if (event instanceof EnchantItemEvent) { - EnchantItemEvent e = (EnchantItemEvent) event; - e.getItem().setType(item.getMaterial()); - e.getItem().setItemMeta(item.getItemMeta()); - e.getItem().setAmount(item.getAmount()); - } - break; - case ADD: - case REMOVE: - case RESET: - case DELETE: - case REMOVE_ALL: - assert false; - } - } - - @Override - public boolean isSingle() { - return true; - } - - @Override - public Class getReturnType() { - return ItemType.class; - } - - @Override - public String toString(@Nullable Event e, boolean debug) { - return "enchanted item"; - } - -} diff --git a/src/main/java/ch/njol/skript/expressions/ExprEnchantingExpCost.java b/src/main/java/ch/njol/skript/expressions/ExprEnchantingExpCost.java deleted file mode 100644 index 97d0d4f2f0e..00000000000 --- a/src/main/java/ch/njol/skript/expressions/ExprEnchantingExpCost.java +++ /dev/null @@ -1,105 +0,0 @@ -package ch.njol.skript.expressions; - -import ch.njol.skript.lang.EventRestrictedSyntax; -import org.bukkit.event.Event; -import org.bukkit.event.enchantment.EnchantItemEvent; -import org.jetbrains.annotations.Nullable; - -import ch.njol.skript.Skript; -import ch.njol.skript.classes.Changer.ChangeMode; -import ch.njol.skript.doc.Description; -import ch.njol.skript.doc.Events; -import ch.njol.skript.doc.Example; -import ch.njol.skript.doc.Name; -import ch.njol.skript.doc.Since; -import ch.njol.skript.lang.Expression; -import ch.njol.skript.lang.ExpressionType; -import ch.njol.skript.lang.SkriptParser.ParseResult; -import ch.njol.skript.lang.util.SimpleExpression; -import ch.njol.skript.log.ErrorQuality; -import ch.njol.skript.util.Experience; -import ch.njol.util.Kleenean; -import ch.njol.util.coll.CollectionUtils; - -@Name("Enchanting Experience Cost") -@Description({"The cost of enchanting in an enchant event.", - "This is number that was displayed in the enchantment table, not the actual number of levels removed."}) -@Example(""" - on enchant: - send "Cost: %the displayed enchanting cost%" to player - """) -@Events("enchant") -@Since("2.5") -public class ExprEnchantingExpCost extends SimpleExpression implements EventRestrictedSyntax { - - static { - Skript.registerExpression(ExprEnchantingExpCost.class, Long.class, ExpressionType.SIMPLE, - "[the] [displayed] ([e]xp[erience]|enchanting) cost"); - } - - @Override - public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { - return true; - } - - @Override - public Class[] supportedEvents() { - return CollectionUtils.array(EnchantItemEvent.class); - } - - @Override - @Nullable - protected Long[] get(Event e) { - return new Long[]{(long) ((EnchantItemEvent) e).getExpLevelCost()}; - } - - @Override - @Nullable - public Class[] acceptChange(ChangeMode mode) { - if (mode == ChangeMode.RESET || mode == ChangeMode.DELETE || mode == ChangeMode.REMOVE_ALL) - return null; - return CollectionUtils.array(Number.class, Experience.class); - } - - @Override - public void change(Event event, @Nullable Object[] delta, ChangeMode mode) { - if (delta == null) - return; - Object c = delta[0]; - int cost = c instanceof Number ? ((Number) c).intValue() : ((Experience) c).getXP(); - EnchantItemEvent e = (EnchantItemEvent) event; - switch (mode) { - case SET: - e.setExpLevelCost(cost); - break; - case ADD: - int add = e.getExpLevelCost() + cost; - e.setExpLevelCost(add); - break; - case REMOVE: - int subtract = e.getExpLevelCost() - cost; - e.setExpLevelCost(subtract); - break; - case RESET: - case DELETE: - case REMOVE_ALL: - assert false; - } - } - - @Override - public boolean isSingle() { - return true; - } - - @Override - public Class getReturnType() { - return Long.class; - } - - @Override - public String toString(@Nullable Event e, boolean debug) { - return "the displayed cost of enchanting"; - } - -} diff --git a/src/main/java/org/skriptlang/skript/bukkit/BukkitModule.java b/src/main/java/org/skriptlang/skript/bukkit/BukkitModule.java index b1e42eadc10..470df36b3bc 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/BukkitModule.java +++ b/src/main/java/org/skriptlang/skript/bukkit/BukkitModule.java @@ -9,6 +9,7 @@ import org.skriptlang.skript.bukkit.breeding.BreedingModule; import org.skriptlang.skript.bukkit.brewing.BrewingModule; import org.skriptlang.skript.bukkit.damagesource.DamageSourceModule; +import org.skriptlang.skript.bukkit.enchantments.EnchantmentModule; import org.skriptlang.skript.bukkit.entity.EntityModule; import org.skriptlang.skript.bukkit.fishing.FishingModule; import org.skriptlang.skript.bukkit.input.InputModule; @@ -50,7 +51,8 @@ public Iterable children() { new PDCModule(this), new PotionModule(this), new TagModule(this), - new TextModule(this) + new TextModule(this), + new EnchantmentModule(this) ); } diff --git a/src/main/java/org/skriptlang/skript/bukkit/enchantments/EnchantmentModule.java b/src/main/java/org/skriptlang/skript/bukkit/enchantments/EnchantmentModule.java new file mode 100644 index 00000000000..86a3abe6b81 --- /dev/null +++ b/src/main/java/org/skriptlang/skript/bukkit/enchantments/EnchantmentModule.java @@ -0,0 +1,150 @@ +package org.skriptlang.skript.bukkit.enchantments; + +import ch.njol.skript.classes.ClassInfo; +import ch.njol.skript.classes.Parser; +import ch.njol.skript.classes.YggdrasilSerializer; +import ch.njol.skript.classes.registry.RegistryClassInfo; +import ch.njol.skript.lang.ParseContext; +import ch.njol.skript.registrations.Classes; +import ch.njol.skript.util.EnchantmentType; +import ch.njol.skript.util.Experience; +import io.papermc.paper.registry.RegistryAccess; +import io.papermc.paper.registry.RegistryKey; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.enchantments.EnchantmentOffer; +import org.jetbrains.annotations.Nullable; +import org.skriptlang.skript.addon.AddonModule; +import org.skriptlang.skript.addon.HierarchicalAddonModule; +import org.skriptlang.skript.addon.SkriptAddon; +import org.skriptlang.skript.bukkit.enchantments.elements.conditions.CondIsEnchanted; +import org.skriptlang.skript.bukkit.enchantments.elements.conditions.CondItemEnchantmentGlint; +import org.skriptlang.skript.bukkit.enchantments.elements.effects.EffEnchant; +import org.skriptlang.skript.bukkit.enchantments.elements.effects.EffForceEnchantmentGlint; +import org.skriptlang.skript.bukkit.enchantments.elements.expressions.*; +import org.skriptlang.skript.lang.comparator.Comparators; +import org.skriptlang.skript.lang.comparator.Relation; +import org.skriptlang.skript.lang.converter.Converters; + +public class EnchantmentModule extends HierarchicalAddonModule { + + public EnchantmentModule(AddonModule parentModule) { + super(parentModule); + } + + @Override + protected void initSelf(SkriptAddon addon) { + initClasses(); + initComparators(); + initConverters(); + } + + private void initClasses() { + Classes.registerClass(new RegistryClassInfo<>( + Enchantment.class, RegistryAccess.registryAccess().getRegistry(RegistryKey.ENCHANTMENT), + "enchantment", "enchantments") + .user("enchantments?") + .name("Enchantment") + .description("An enchantment, e.g. 'sharpness' or 'fortune'. Unlike enchantment type " + + "this type has no level, but you usually don't need to use this type anyway.", + "NOTE: Minecraft namespaces are supported, ex: 'minecraft:basalt_deltas'.", + "This also supports custom enchantments using namespaces, ex: 'myenchants:explosive'.") + .examples("") + .since("1.4.6") + .before("enchantmenttype")); + + Classes.registerClass(new ClassInfo<>(EnchantmentType.class, "enchantmenttype") + .user("enchant(ing|ment) ?types?") + .name("Enchantment Type") + .description("An enchantment with an optional level, e.g. 'sharpness 2' or 'fortune'.") + .usage(" []") + .examples("enchant the player's tool with sharpness 5", + "helmet is enchanted with waterbreathing") + .since("1.4.6") + .parser(new Parser<>() { + @Override + public @Nullable EnchantmentType parse(String string, ParseContext context) { + return EnchantmentType.parse(string); + } + + @Override + public String toString(EnchantmentType type, int flags) { + return type.toString(); + } + + @Override + public String toVariableNameString(EnchantmentType type) { + return type.toString(); + } + }) + .serializer(new YggdrasilSerializer<>())); + + Classes.registerClass(new ClassInfo<>(EnchantmentOffer.class, "enchantmentoffer") + .user("enchant[ment][ ]offers?") + .name("Enchantment Offer") + .description("The enchantmentoffer in an enchant prepare event.") + .examples(""" + on enchant prepare: + set enchant offer 1 to sharpness 1 + set the cost of enchant offer 1 to 10 levels + """) + .since("2.5") + .parser(new Parser<>() { + @Override + public boolean canParse(ParseContext context) { + return false; + } + + @Override + public String toString(EnchantmentOffer eo, int flags) { + return Classes.toString(eo.getEnchantment()) + " " + eo.getEnchantmentLevel(); + } + + @Override + public String toVariableNameString(EnchantmentOffer eo) { + return "offer:" + Classes.toString(eo.getEnchantment()) + "=" + eo.getEnchantmentLevel(); + } + })); + } + + private void initComparators() { + Comparators.registerComparator(EnchantmentOffer.class, EnchantmentType.class, (offer, enchantmentType) -> + Relation.get(offer.getEnchantment() == enchantmentType.getType() && offer.getEnchantmentLevel() == enchantmentType.getLevel())); + Comparators.registerComparator(EnchantmentOffer.class, Experience.class, (offer, experience) -> + Relation.get(offer.getCost() == experience.getXP())); + Comparators.registerComparator(EnchantmentType.class, Enchantment.class, ((enchantmentType, enchantment) -> + Relation.get(enchantmentType.getType().equals(enchantment)))); + } + + private void initConverters() { + Converters.registerConverter(Enchantment.class, EnchantmentType.class, e -> new EnchantmentType(e, -1)); + Converters.registerConverter(EnchantmentOffer.class, EnchantmentType.class, eo -> new EnchantmentType(eo.getEnchantment(), eo.getEnchantmentLevel())); + } + + @Override + protected void loadSelf(SkriptAddon addon) { + register(addon, + CondIsEnchanted::register, + CondItemEnchantmentGlint::register, + EffEnchant::register, + EffForceEnchantmentGlint::register, + ExprAppliedEnchantments::register, + ExprEnchantmentLevel::register, + ExprEnchantmentOffer::register, + ExprEnchantmentBonus::register, + ExprEnchantmentOfferCost::register, + ExprEnchantments::register, + ExprEnchantingExpCost::register, + ExprEnchantItem::register, + ExprItemWithEnchantmentGlint::register, + ExprMaximumEnchantmentLevel::register, + ExprMinimumEnchantmentLevel::register, + ExprStoredEnchantments::register + ); + } + + @Override + public String name() { + return "enchantment"; + } + +} diff --git a/src/main/java/ch/njol/skript/conditions/CondIsEnchanted.java b/src/main/java/org/skriptlang/skript/bukkit/enchantments/elements/conditions/CondIsEnchanted.java similarity index 85% rename from src/main/java/ch/njol/skript/conditions/CondIsEnchanted.java rename to src/main/java/org/skriptlang/skript/bukkit/enchantments/elements/conditions/CondIsEnchanted.java index bc3fad378c1..8ccd96e4abd 100644 --- a/src/main/java/ch/njol/skript/conditions/CondIsEnchanted.java +++ b/src/main/java/org/skriptlang/skript/bukkit/enchantments/elements/conditions/CondIsEnchanted.java @@ -1,4 +1,4 @@ -package ch.njol.skript.conditions; +package org.skriptlang.skript.bukkit.enchantments.elements.conditions; import ch.njol.skript.aliases.ItemType; import ch.njol.skript.conditions.base.PropertyCondition; @@ -14,6 +14,7 @@ import ch.njol.util.Kleenean; import org.bukkit.event.Event; import org.jetbrains.annotations.Nullable; +import org.skriptlang.skript.registration.SyntaxRegistry; @Name("Is Enchanted") @Description("Checks whether an item is enchanted. Enchants must match the exact level by default, unless 'or better' or 'or worse' are used.") @@ -39,8 +40,10 @@ public String toSkriptString() { } } - static { - PropertyCondition.register(CondIsEnchanted.class, "enchanted [with %-enchantmenttypes% [or (1:(better|greater|higher|above)|2:(worse|lesser|lower|below))]]", "itemtypes"); + public static void register(SyntaxRegistry registry) { + registry.register(SyntaxRegistry.CONDITION, PropertyCondition.infoBuilder(CondIsEnchanted.class, PropertyType.BE, + "enchanted [with %-enchantmenttypes% [or (1:(better|greater|higher|above)" + + "|2:(worse|lesser|lower|below))]]", "itemtypes").build()); } private Expression items; diff --git a/src/main/java/ch/njol/skript/conditions/CondItemEnchantmentGlint.java b/src/main/java/org/skriptlang/skript/bukkit/enchantments/elements/conditions/CondItemEnchantmentGlint.java similarity index 55% rename from src/main/java/ch/njol/skript/conditions/CondItemEnchantmentGlint.java rename to src/main/java/org/skriptlang/skript/bukkit/enchantments/elements/conditions/CondItemEnchantmentGlint.java index aa93247cf8c..41cff18e34b 100644 --- a/src/main/java/ch/njol/skript/conditions/CondItemEnchantmentGlint.java +++ b/src/main/java/org/skriptlang/skript/bukkit/enchantments/elements/conditions/CondItemEnchantmentGlint.java @@ -1,14 +1,14 @@ -package ch.njol.skript.conditions; +package org.skriptlang.skript.bukkit.enchantments.elements.conditions; import org.bukkit.inventory.meta.ItemMeta; -import ch.njol.skript.Skript; import ch.njol.skript.aliases.ItemType; import ch.njol.skript.conditions.base.PropertyCondition; import ch.njol.skript.doc.*; import ch.njol.skript.lang.Expression; import ch.njol.skript.lang.SkriptParser.ParseResult; import ch.njol.util.Kleenean; +import org.skriptlang.skript.registration.SyntaxRegistry; @Name("Item Has Enchantment Glint Override") @Description("Checks whether an item has the enchantment glint overridden, or is forced to glint or not.") @@ -24,44 +24,48 @@ else: send "This item does not have any glint override." to player """) -@RequiredPlugins("Spigot 1.20.5+") @Since("2.10") public class CondItemEnchantmentGlint extends PropertyCondition { - static { - if (Skript.methodExists(ItemMeta.class, "getEnchantmentGlintOverride")) { - register(CondItemEnchantmentGlint.class, PropertyType.HAVE, "enchantment glint overrid(den|e)", "itemtypes"); - register(CondItemEnchantmentGlint.class, PropertyType.BE, "forced to [:not] glint", "itemtypes"); - } + public static void register(SyntaxRegistry registry) { + registry.register(SyntaxRegistry.CONDITION, PropertyCondition + .infoBuilder(CondItemEnchantmentGlint.class, PropertyType.HAVE, "enchantment glint (override:overrid(den|e))", "itemtypes") + .addPatterns(getPatterns(PropertyType.BE, "forced to [:not] glint", "itemtypes")) + .supplier(CondItemEnchantmentGlint::new).build()); } - private int matchedPattern; - private boolean glint; + private boolean expectedGlintOverride; + private boolean override; @Override public boolean init(Expression[] expressions, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { - this.matchedPattern = matchedPattern; - glint = !parseResult.hasTag("not"); - return super.init(expressions, matchedPattern, isDelayed, parseResult); + if (!super.init(expressions, matchedPattern, isDelayed, parseResult)) return false; + override = parseResult.hasTag("override"); + expectedGlintOverride = !parseResult.hasTag("not"); + + // We override setNegated to correctly handle multiple patterns. Note that the [:not] parse tag is not negating. + setNegated(matchedPattern % 2 != 0); + return true; } @Override public boolean check(ItemType itemType) { ItemMeta meta = itemType.getItemMeta(); - // enchantment glint override - if (matchedPattern == 0) + + if (override) return meta.hasEnchantmentGlintOverride(); - // forced to glint + if (!meta.hasEnchantmentGlintOverride()) return false; - return meta.getEnchantmentGlintOverride(); + + return meta.getEnchantmentGlintOverride() == expectedGlintOverride; } @Override protected String getPropertyName() { - if (matchedPattern == 0) + if (override) return "enchantment glint overridden"; - return "forced to " + (glint ? "" : "not ") + "glint"; + return "forced to " + (expectedGlintOverride ? "" : "not ") + "glint"; } } diff --git a/src/main/java/ch/njol/skript/effects/EffEnchant.java b/src/main/java/org/skriptlang/skript/bukkit/enchantments/elements/effects/EffEnchant.java similarity index 82% rename from src/main/java/ch/njol/skript/effects/EffEnchant.java rename to src/main/java/org/skriptlang/skript/bukkit/enchantments/elements/effects/EffEnchant.java index f9021d64605..164744fa6d2 100644 --- a/src/main/java/ch/njol/skript/effects/EffEnchant.java +++ b/src/main/java/org/skriptlang/skript/bukkit/enchantments/elements/effects/EffEnchant.java @@ -1,4 +1,4 @@ -package ch.njol.skript.effects; +package org.skriptlang.skript.bukkit.enchantments.elements.effects; import ch.njol.skript.Skript; import ch.njol.skript.aliases.ItemType; @@ -16,6 +16,8 @@ import org.bukkit.inventory.ItemFactory; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.Nullable; +import org.skriptlang.skript.registration.SyntaxInfo; +import org.skriptlang.skript.registration.SyntaxRegistry; import java.util.concurrent.ThreadLocalRandom; import java.util.function.Function; @@ -37,16 +39,17 @@ private enum Operation { DISENCHANT } - private static final Patterns patterns; + private static final Patterns PATTERNS = new Patterns<>(new Object[][]{ + {"enchant %~itemtypes% with %enchantmenttypes%", Operation.ENCHANT}, + {"[naturally|randomly] enchant %~itemtypes% at level %number%[treasure:[,] allowing treasure enchant[ment]s]", + Operation.ENCHANT_AT_LEVEL}, + {"disenchant %~itemtypes%", Operation.DISENCHANT} + }); - static { - patterns = new Patterns<>(new Object[][]{ - {"enchant %~itemtypes% with %enchantmenttypes%", Operation.ENCHANT}, - {"[naturally|randomly] enchant %~itemtypes% at level %number%[treasure:[,] allowing treasure enchant[ment]s]", - Operation.ENCHANT_AT_LEVEL}, - {"disenchant %~itemtypes%", Operation.DISENCHANT} - }); - Skript.registerEffect(EffEnchant.class, patterns.getPatterns()); + public static void register(SyntaxRegistry registry) { + registry.register(SyntaxRegistry.EFFECT, SyntaxInfo.builder(EffEnchant.class) + .addPatterns(PATTERNS.getPatterns()) + .supplier(EffEnchant::new).build()); } private Expression items; @@ -69,7 +72,7 @@ public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelaye level = (Expression) exprs[1]; treasure = parseResult.hasTag("treasure"); } - operation = patterns.getInfo(matchedPattern); + operation = PATTERNS.getInfo(matchedPattern); return true; } diff --git a/src/main/java/ch/njol/skript/effects/EffForceEnchantmentGlint.java b/src/main/java/org/skriptlang/skript/bukkit/enchantments/elements/effects/EffForceEnchantmentGlint.java similarity index 64% rename from src/main/java/ch/njol/skript/effects/EffForceEnchantmentGlint.java rename to src/main/java/org/skriptlang/skript/bukkit/enchantments/elements/effects/EffForceEnchantmentGlint.java index 956e4302344..e626b378086 100644 --- a/src/main/java/ch/njol/skript/effects/EffForceEnchantmentGlint.java +++ b/src/main/java/org/skriptlang/skript/bukkit/enchantments/elements/effects/EffForceEnchantmentGlint.java @@ -1,32 +1,33 @@ -package ch.njol.skript.effects; +package org.skriptlang.skript.bukkit.enchantments.elements.effects; import org.bukkit.event.Event; import org.bukkit.inventory.meta.ItemMeta; import org.jetbrains.annotations.Nullable; -import ch.njol.skript.Skript; import ch.njol.skript.aliases.ItemType; import ch.njol.skript.doc.*; import ch.njol.skript.lang.Effect; import ch.njol.skript.lang.Expression; import ch.njol.skript.lang.SkriptParser.ParseResult; import ch.njol.util.Kleenean; +import org.skriptlang.skript.registration.SyntaxInfo; +import org.skriptlang.skript.registration.SyntaxRegistry; @Name("Force Enchantment Glint") @Description("Forces the items to glint or not, or removes its existing enchantment glint enforcement.") @Example("force {_items::*} to glint") @Example("force the player's tool to stop glinting") -@RequiredPlugins("Spigot 1.20.5+") @Since("2.10") public class EffForceEnchantmentGlint extends Effect { - static { - if (Skript.methodExists(ItemMeta.class, "setEnchantmentGlintOverride", Boolean.class)) - Skript.registerEffect(EffForceEnchantmentGlint.class, - "(force|make) %itemtypes% [to] [start] glint[ing]", - "(force|make) %itemtypes% [to] (not|stop) glint[ing]", - "(clear|delete|reset) [the] enchantment glint override of %itemtypes%", - "(clear|delete|reset) %itemtypes%'s enchantment glint override"); + public static void register(SyntaxRegistry registry) { + registry.register(SyntaxRegistry.EFFECT, SyntaxInfo.builder(EffForceEnchantmentGlint.class) + .addPatterns( + "(force|make) %itemtypes% [to] [start] glint[ing]", + "(force|make) %itemtypes% [to] (not|stop) glint[ing]", + "(clear|delete|reset) [the] enchantment glint override of %itemtypes%", + "(clear|delete|reset) %itemtypes%'s enchantment glint override" + ).supplier(EffForceEnchantmentGlint::new).build()); } private Expression itemTypes; @@ -44,17 +45,11 @@ public boolean init(Expression[] expressions, int matchedPattern, Kleenean is protected void execute(Event event) { for (ItemType itemType : itemTypes.getArray(event)) { ItemMeta meta = itemType.getItemMeta(); - Boolean glint; - if (pattern == 0) { - // Pattern: forced to glint - glint = true; - } else if (pattern == 1) { - // Pattern: forced to not glint - glint = false; - } else { - // Pattern: Clear glint override - glint = null; - } + Boolean glint = switch (pattern) { + case 0 -> true; // Pattern: forced to glint + case 1 -> false; // Pattern: forced to not glint + default -> null; // Pattern: Clear glint override + }; meta.setEnchantmentGlintOverride(glint); itemType.setItemMeta(meta); } diff --git a/src/main/java/ch/njol/skript/expressions/ExprAppliedEnchantments.java b/src/main/java/org/skriptlang/skript/bukkit/enchantments/elements/expressions/ExprAppliedEnchantments.java similarity index 53% rename from src/main/java/ch/njol/skript/expressions/ExprAppliedEnchantments.java rename to src/main/java/org/skriptlang/skript/bukkit/enchantments/elements/expressions/ExprAppliedEnchantments.java index 85885ddcc9f..cf59cda5445 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprAppliedEnchantments.java +++ b/src/main/java/org/skriptlang/skript/bukkit/enchantments/elements/expressions/ExprAppliedEnchantments.java @@ -1,12 +1,10 @@ -package ch.njol.skript.expressions; +package org.skriptlang.skript.bukkit.enchantments.elements.expressions; import ch.njol.skript.lang.EventRestrictedSyntax; -import org.bukkit.enchantments.Enchantment; import org.bukkit.event.Event; import org.bukkit.event.enchantment.EnchantItemEvent; import org.jetbrains.annotations.Nullable; -import ch.njol.skript.Skript; import ch.njol.skript.classes.Changer.ChangeMode; import ch.njol.skript.doc.Description; import ch.njol.skript.doc.Events; @@ -14,17 +12,20 @@ import ch.njol.skript.doc.Name; import ch.njol.skript.doc.Since; import ch.njol.skript.lang.Expression; -import ch.njol.skript.lang.ExpressionType; import ch.njol.skript.lang.SkriptParser.ParseResult; import ch.njol.skript.lang.util.SimpleExpression; -import ch.njol.skript.log.ErrorQuality; import ch.njol.skript.util.EnchantmentType; import ch.njol.util.Kleenean; import ch.njol.util.coll.CollectionUtils; +import org.skriptlang.skript.registration.SyntaxRegistry; + +import static org.skriptlang.skript.registration.DefaultSyntaxInfos.Expression.builder; @Name("Applied Enchantments") -@Description({"The applied enchantments in an enchant event.", - " Deleting or removing the applied enchantments will prevent the item's enchantment."}) +@Description(""" + The applied enchantments in an enchant event. + Deleting or removing the applied enchantments will prevent the item's enchantment. + """) @Example(""" on enchant: set the applied enchantments to sharpness 10 and fire aspect 5 @@ -33,8 +34,11 @@ @Since("2.5") public class ExprAppliedEnchantments extends SimpleExpression implements EventRestrictedSyntax { - static { - Skript.registerExpression(ExprAppliedEnchantments.class, EnchantmentType.class, ExpressionType.SIMPLE, "[the] applied enchant[ment]s"); + public static void register(SyntaxRegistry registry) { + registry.register(SyntaxRegistry.EXPRESSION, + builder(ExprAppliedEnchantments.class, EnchantmentType.class) + .addPattern("[the] applied enchant[ment]s") + .supplier(ExprAppliedEnchantments::new).build()); } @Override @@ -47,58 +51,54 @@ public Class[] supportedEvents() { return CollectionUtils.array(EnchantItemEvent.class); } - @SuppressWarnings("null") @Override - @Nullable - protected EnchantmentType[] get(Event e) { - if (!(e instanceof EnchantItemEvent)) + @SuppressWarnings("null") + protected EnchantmentType @Nullable [] get(Event event) { + if (!(event instanceof EnchantItemEvent)) return null; - return ((EnchantItemEvent) e).getEnchantsToAdd().entrySet().stream() - .map(entry -> new EnchantmentType(entry.getKey(), entry.getValue())) - .toArray(EnchantmentType[]::new); + return ((EnchantItemEvent) event).getEnchantsToAdd().entrySet().stream() + .map(entry -> new EnchantmentType(entry.getKey(), entry.getValue())) + .toArray(EnchantmentType[]::new); } @Override - @Nullable - public Class[] acceptChange(ChangeMode mode) { - if (mode == ChangeMode.REMOVE_ALL || mode == ChangeMode.RESET) - return null; - return CollectionUtils.array(Enchantment[].class, EnchantmentType[].class); + public Class @Nullable [] acceptChange(ChangeMode mode) { + return switch (mode) { + case ADD, SET, DELETE, REMOVE -> CollectionUtils.array(EnchantmentType[].class); + default -> null; + }; } @SuppressWarnings("null") @Override - public void change(Event event, @Nullable Object[] delta, ChangeMode mode) { - if (!(event instanceof EnchantItemEvent)) + public void change(Event event, Object @Nullable [] delta, ChangeMode mode) { + if (!(event instanceof EnchantItemEvent enchantEvent)) return; EnchantmentType[] enchants = new EnchantmentType[delta != null ? delta.length : 0]; if (delta != null && delta.length != 0) { for (int i = 0; i < delta.length; i++) { - if (delta[i] instanceof EnchantmentType) - enchants[i] = (EnchantmentType) delta[i]; - else - enchants[i] = new EnchantmentType((Enchantment) delta[i]); + enchants[i] = (EnchantmentType) delta[i]; } } - EnchantItemEvent e = (EnchantItemEvent) event; + + if (mode == ChangeMode.SET || mode == ChangeMode.DELETE) + enchantEvent.getEnchantsToAdd().clear(); + switch (mode) { - case SET: - e.getEnchantsToAdd().clear(); - case ADD: + case DELETE -> {} + case SET, ADD -> { for (EnchantmentType enchant : enchants) - e.getEnchantsToAdd().put(enchant.getType(), enchant.getLevel()); - break; - case REMOVE: + enchantEvent.getEnchantsToAdd().put(enchant.getType(), enchant.getLevel()); + } + case REMOVE -> { for (EnchantmentType enchant : enchants) - e.getEnchantsToAdd().remove(enchant.getType(), enchant.getLevel()); - break; - case DELETE: - e.getEnchantsToAdd().clear(); - case REMOVE_ALL: - case RESET: + enchantEvent.getEnchantsToAdd().remove(enchant.getType(), enchant.getLevel()); + } + default -> { assert false; + } } } @@ -113,7 +113,7 @@ public Class getReturnType() { } @Override - public String toString(@Nullable Event e, boolean debug) { + public String toString(@Nullable Event event, boolean debug) { return "applied enchantments"; } diff --git a/src/main/java/org/skriptlang/skript/bukkit/enchantments/elements/expressions/ExprEnchantItem.java b/src/main/java/org/skriptlang/skript/bukkit/enchantments/elements/expressions/ExprEnchantItem.java new file mode 100644 index 00000000000..690324d1eb0 --- /dev/null +++ b/src/main/java/org/skriptlang/skript/bukkit/enchantments/elements/expressions/ExprEnchantItem.java @@ -0,0 +1,116 @@ +package org.skriptlang.skript.bukkit.enchantments.elements.expressions; + +import ch.njol.skript.aliases.ItemType; +import ch.njol.skript.lang.EventRestrictedSyntax; +import org.bukkit.event.Event; +import org.bukkit.event.enchantment.EnchantItemEvent; +import org.bukkit.event.enchantment.PrepareItemEnchantEvent; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.Nullable; + +import ch.njol.skript.classes.Changer.ChangeMode; +import ch.njol.skript.doc.Description; +import ch.njol.skript.doc.Events; +import ch.njol.skript.doc.Example; +import ch.njol.skript.doc.Name; +import ch.njol.skript.doc.Since; +import ch.njol.skript.lang.Expression; +import ch.njol.skript.lang.SkriptParser.ParseResult; +import ch.njol.skript.lang.util.SimpleExpression; +import ch.njol.util.Kleenean; +import ch.njol.util.coll.CollectionUtils; +import org.skriptlang.skript.lang.script.ScriptWarning; +import org.skriptlang.skript.registration.SyntaxRegistry; + +import static org.skriptlang.skript.registration.DefaultSyntaxInfos.Expression.builder; + +@Name("Enchant Item") +@Description(""" + The enchant item in an enchant prepare event or enchant event. + It can be modified, but enchantments will still be applied in the enchant event. + """) +@Example(""" + on enchant: + set the enchanted item to a diamond chestplate + """) +@Example(""" + on enchant prepare: + set the enchant item to a wooden sword + """) +@Events({"enchant prepare", "enchant"}) +@Since("2.5") +public class ExprEnchantItem extends SimpleExpression implements EventRestrictedSyntax { + + public static void register(SyntaxRegistry registry) { + registry.register(SyntaxRegistry.EXPRESSION, builder(ExprEnchantItem.class, ItemType.class) + .addPatterns("[the] enchant[:ed] item") + .supplier(ExprEnchantItem::new).build()); + } + + @Override + public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { + if (!parseResult.hasTag("ed")) + ScriptWarning.printDeprecationWarning("The 'enchant item' form of the enchanted item expression is deprecated, please use 'enchanted 'item'!"); + return true; + } + + @Override + public Class[] supportedEvents() { + return CollectionUtils.array(EnchantItemEvent.class, PrepareItemEnchantEvent.class); + } + + @Override + protected ItemType[] get(Event event) { + return new ItemType[]{new ItemType(switch (event) { + case PrepareItemEnchantEvent prepare -> prepare.getItem(); + case EnchantItemEvent enchant -> enchant.getItem(); + case null, default -> throw new IllegalStateException("Unsupported event " + event); + })}; + } + + @Override + public Class @Nullable [] acceptChange(ChangeMode mode) { + if (mode == ChangeMode.SET) + return CollectionUtils.array(ItemType.class); + return null; + } + + @Override + public void change(Event event, Object @Nullable [] delta, ChangeMode mode) { + if (delta == null) + return; + ItemType item = ((ItemType) delta[0]); + switch (mode) { + case SET -> { + ItemStack existing = switch (event) { + case PrepareItemEnchantEvent prepare -> prepare.getItem(); + case EnchantItemEvent enchant -> enchant.getItem(); + default -> throw new AssertionError("unreachable"); + }; + //noinspection deprecation back-compat; danger danger !! + existing.setType(item.getMaterial()); + existing.setItemMeta(item.getItemMeta()); + existing.setAmount(item.getAmount()); + } + case null, default -> { + assert false; + } + } + } + + @Override + public boolean isSingle() { + return true; + } + + @Override + public Class getReturnType() { + return ItemType.class; + } + + @Override + public String toString(@Nullable Event event, boolean debug) { + return "enchanted item"; + } + +} diff --git a/src/main/java/org/skriptlang/skript/bukkit/enchantments/elements/expressions/ExprEnchantingExpCost.java b/src/main/java/org/skriptlang/skript/bukkit/enchantments/elements/expressions/ExprEnchantingExpCost.java new file mode 100644 index 00000000000..714c1051995 --- /dev/null +++ b/src/main/java/org/skriptlang/skript/bukkit/enchantments/elements/expressions/ExprEnchantingExpCost.java @@ -0,0 +1,104 @@ +package org.skriptlang.skript.bukkit.enchantments.elements.expressions; + +import ch.njol.skript.lang.EventRestrictedSyntax; +import org.bukkit.event.Event; +import org.bukkit.event.enchantment.EnchantItemEvent; +import org.jetbrains.annotations.Nullable; + +import ch.njol.skript.classes.Changer.ChangeMode; +import ch.njol.skript.doc.Description; +import ch.njol.skript.doc.Events; +import ch.njol.skript.doc.Example; +import ch.njol.skript.doc.Name; +import ch.njol.skript.doc.Since; +import ch.njol.skript.lang.Expression; +import ch.njol.skript.lang.SkriptParser.ParseResult; +import ch.njol.skript.lang.util.SimpleExpression; +import ch.njol.util.Kleenean; +import ch.njol.util.coll.CollectionUtils; +import org.skriptlang.skript.registration.SyntaxRegistry; + +import static org.skriptlang.skript.registration.DefaultSyntaxInfos.Expression.builder; + +@Name("Enchanting Experience Cost") +@Description(""" + The cost of enchanting in an enchant event. + This is number that was displayed in the enchantment table, not the actual number of levels removed. + """) +@Example(""" + on enchant: + send "Cost: %the displayed enchanting cost%" to player + """) +@Events("enchant") +@Since("2.5") +public class ExprEnchantingExpCost extends SimpleExpression implements EventRestrictedSyntax { + + public static void register(SyntaxRegistry registry) { + registry.register(SyntaxRegistry.EXPRESSION, builder(ExprEnchantingExpCost.class, Integer.class) + .addPattern("[the] [displayed] ([e]xp[erience]|enchanting) cost") + .supplier(ExprEnchantingExpCost::new).build()); + } + + @Override + public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { + return true; + } + + @Override + public Class[] supportedEvents() { + return CollectionUtils.array(EnchantItemEvent.class); + } + + @Override + protected Integer @Nullable [] get(Event event) { + if (!(event instanceof EnchantItemEvent enchantEvent)) + return null; + + return new Integer[]{enchantEvent.getExpLevelCost()}; + } + + @Override + public Class @Nullable [] acceptChange(ChangeMode mode) { + return switch (mode) { + case SET, ADD, REMOVE -> CollectionUtils.array(Number.class); + default -> null; + }; + } + + @Override + public void change(Event event, Object @Nullable [] delta, ChangeMode mode) { + if (delta == null || delta.length == 0 || !(event instanceof EnchantItemEvent enchantEvent)) + return; + int cost = ((Number) delta[0]).intValue(); + switch (mode) { + case SET -> enchantEvent.setExpLevelCost(cost); + case ADD -> { + int add = enchantEvent.getExpLevelCost() + cost; + enchantEvent.setExpLevelCost(add); + } + case REMOVE -> { + int subtract = enchantEvent.getExpLevelCost() - cost; + enchantEvent.setExpLevelCost(subtract); + } + case RESET, DELETE, REMOVE_ALL -> { + assert false; + } + } + } + + @Override + public boolean isSingle() { + return true; + } + + @Override + public Class getReturnType() { + return Integer.class; + } + + @Override + public String toString(@Nullable Event event, boolean debug) { + return "the displayed cost of enchanting"; + } + +} diff --git a/src/main/java/ch/njol/skript/expressions/ExprEnchantmentBonus.java b/src/main/java/org/skriptlang/skript/bukkit/enchantments/elements/expressions/ExprEnchantmentBonus.java similarity index 50% rename from src/main/java/ch/njol/skript/expressions/ExprEnchantmentBonus.java rename to src/main/java/org/skriptlang/skript/bukkit/enchantments/elements/expressions/ExprEnchantmentBonus.java index 42b53e16623..abf3c5e5286 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprEnchantmentBonus.java +++ b/src/main/java/org/skriptlang/skript/bukkit/enchantments/elements/expressions/ExprEnchantmentBonus.java @@ -1,23 +1,21 @@ -package ch.njol.skript.expressions; +package org.skriptlang.skript.bukkit.enchantments.elements.expressions; -import ch.njol.skript.lang.EventRestrictedSyntax; -import ch.njol.util.coll.CollectionUtils; -import org.bukkit.event.Event; -import org.bukkit.event.enchantment.PrepareItemEnchantEvent; -import org.jetbrains.annotations.Nullable; - -import ch.njol.skript.Skript; import ch.njol.skript.doc.Description; import ch.njol.skript.doc.Events; import ch.njol.skript.doc.Example; import ch.njol.skript.doc.Name; import ch.njol.skript.doc.Since; +import ch.njol.skript.lang.EventRestrictedSyntax; import ch.njol.skript.lang.Expression; -import ch.njol.skript.lang.ExpressionType; import ch.njol.skript.lang.SkriptParser.ParseResult; import ch.njol.skript.lang.util.SimpleExpression; -import ch.njol.skript.log.ErrorQuality; import ch.njol.util.Kleenean; +import org.bukkit.event.Event; +import org.bukkit.event.enchantment.PrepareItemEnchantEvent; +import org.jetbrains.annotations.Nullable; +import org.skriptlang.skript.registration.SyntaxRegistry; + +import static org.skriptlang.skript.registration.DefaultSyntaxInfos.Expression.builder; @Name("Enchantment Bonus") @Description("The enchantment bonus in an enchant prepare event. This represents the number of bookshelves affecting/surrounding the enchantment table.") @@ -27,26 +25,31 @@ """) @Events("enchant prepare") @Since("2.5") -public class ExprEnchantmentBonus extends SimpleExpression implements EventRestrictedSyntax { - - static { - Skript.registerExpression(ExprEnchantmentBonus.class, Long.class, ExpressionType.SIMPLE, "[the] enchantment bonus"); +public class ExprEnchantmentBonus extends SimpleExpression implements EventRestrictedSyntax { + + public static void register(SyntaxRegistry registry) { + registry.register(SyntaxRegistry.EXPRESSION, builder(ExprEnchantmentBonus.class, Integer.class) + .addPattern("[the] enchant[ment] bonus") + .supplier(ExprEnchantmentBonus::new).build()); } @Override - public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { + public boolean init(Expression[] expressions, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { return true; } @Override + @SuppressWarnings("unchecked") /* hard-coded event type */ public Class[] supportedEvents() { - return CollectionUtils.array(PrepareItemEnchantEvent.class); + return new Class[]{PrepareItemEnchantEvent.class}; } @Override - @Nullable - protected Long[] get(Event e) { - return new Long[]{(long) ((PrepareItemEnchantEvent) e).getEnchantmentBonus()}; + protected Integer @Nullable [] get(Event event) { + if (!(event instanceof PrepareItemEnchantEvent prepare)) + return null; + + return new Integer[]{prepare.getEnchantmentBonus()}; } @Override @@ -54,14 +57,13 @@ public boolean isSingle() { return true; } - @Override - public Class getReturnType() { - return Long.class; + public Class getReturnType() { + return Integer.class; } @Override - public String toString(@Nullable Event e, boolean debug) { + public String toString(@Nullable Event event, boolean debug) { return "enchantment bonus"; } diff --git a/src/main/java/ch/njol/skript/expressions/ExprEnchantmentLevel.java b/src/main/java/org/skriptlang/skript/bukkit/enchantments/elements/expressions/ExprEnchantmentLevel.java similarity index 58% rename from src/main/java/ch/njol/skript/expressions/ExprEnchantmentLevel.java rename to src/main/java/org/skriptlang/skript/bukkit/enchantments/elements/expressions/ExprEnchantmentLevel.java index 9fa8ffd771f..33d69e93f06 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprEnchantmentLevel.java +++ b/src/main/java/org/skriptlang/skript/bukkit/enchantments/elements/expressions/ExprEnchantmentLevel.java @@ -1,14 +1,13 @@ -package ch.njol.skript.expressions; +package org.skriptlang.skript.bukkit.enchantments.elements.expressions; -import ch.njol.skript.Skript; import ch.njol.skript.aliases.ItemType; import ch.njol.skript.classes.Changer.ChangeMode; import ch.njol.skript.doc.Description; import ch.njol.skript.doc.Example; import ch.njol.skript.doc.Name; import ch.njol.skript.doc.Since; +import ch.njol.skript.expressions.base.PropertyExpression; import ch.njol.skript.lang.Expression; -import ch.njol.skript.lang.ExpressionType; import ch.njol.skript.lang.SkriptParser.ParseResult; import ch.njol.skript.lang.util.SimpleExpression; import ch.njol.skript.util.EnchantmentType; @@ -17,9 +16,12 @@ import org.bukkit.enchantments.Enchantment; import org.bukkit.event.Event; import org.jetbrains.annotations.Nullable; +import org.skriptlang.skript.registration.SyntaxRegistry; import java.util.stream.Stream; +import static org.skriptlang.skript.registration.DefaultSyntaxInfos.Expression.builder; + @Name("Enchantment Level") @Description("The level of a particular enchantment on an item.") @Example(""" @@ -29,18 +31,19 @@ @Since("2.0") public class ExprEnchantmentLevel extends SimpleExpression { - static { - Skript.registerExpression(ExprEnchantmentLevel.class, Long.class, ExpressionType.PROPERTY, - "[the] [enchant[ment]] level[s] of %enchantments% (on|of) %itemtypes%", - "[the] %enchantments% [enchant[ment]] level[s] (on|of) %itemtypes%", - "%itemtypes%'[s] %enchantments% [enchant[ment]] level[s]", - "%itemtypes%'[s] [enchant[ment]] level[s] of %enchantments%"); + public static void register(SyntaxRegistry registry) { + registry.register(SyntaxRegistry.EXPRESSION, builder(ExprEnchantmentLevel.class, Long.class) + .addPatterns( + "[the] [enchant[ment]] level[s] of %enchantments% (on|of) %itemtypes%", + "[the] %enchantments% [enchant[ment]] level[s] (on|of) %itemtypes%", + "%itemtypes%'[s] %enchantments% [enchant[ment]] level[s]", + "%itemtypes%'[s] [enchant[ment]] level[s] of %enchantments%") + .supplier(ExprEnchantmentLevel::new) + .priority(PropertyExpression.DEFAULT_PRIORITY).build()); } - @SuppressWarnings("NotNullFieldNotInitialized") private Expression items; - @SuppressWarnings("NotNullFieldNotInitialized") private Expression enchants; @Override @@ -53,9 +56,9 @@ public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelaye } @Override - protected Long[] get(Event e) { - Enchantment[] enchantments = enchants.getArray(e); - return Stream.of(items.getArray(e)) + protected Long[] get(Event event) { + Enchantment[] enchantments = enchants.getArray(event); + return Stream.of(items.getArray(event)) .map(ItemType::getEnchantmentTypes) .flatMap(Stream::of) .filter(enchantment -> CollectionUtils.contains(enchantments, enchantment.getType())) @@ -65,22 +68,19 @@ protected Long[] get(Event e) { } @Override - @Nullable - public Class[] acceptChange(ChangeMode mode) { - switch (mode) { - case SET: - case REMOVE: - case ADD: - return CollectionUtils.array(Number.class); - default: - return null; - } + public Class @Nullable [] acceptChange(ChangeMode mode) { + return switch (mode) { + case SET, REMOVE, ADD -> CollectionUtils.array(Number.class); + default -> null; + }; } @Override - public void change(Event e, @Nullable Object[] delta, ChangeMode mode) { - ItemType[] itemTypes = items.getArray(e); - Enchantment[] enchantments = enchants.getArray(e); + public void change(Event event, Object @Nullable [] delta, ChangeMode mode) { + ItemType[] itemTypes = items.getArray(event); + Enchantment[] enchantments = enchants.getArray(event); + if (delta == null || delta.length == 0) + return; int changeValue = ((Number) delta[0]).intValue(); for (ItemType itemType : itemTypes) { @@ -90,18 +90,13 @@ public void change(Event e, @Nullable Object[] delta, ChangeMode mode) { int newItemLevel; switch (mode) { - case ADD: - newItemLevel = oldLevel + changeValue; - break; - case REMOVE: - newItemLevel = oldLevel - changeValue; - break; - case SET: - newItemLevel = changeValue; - break; - default: + case ADD -> newItemLevel = oldLevel + changeValue; + case REMOVE -> newItemLevel = oldLevel - changeValue; + case SET -> newItemLevel = changeValue; + default -> { assert false; return; + } } if (newItemLevel <= 0) { @@ -124,8 +119,8 @@ public Class getReturnType() { } @Override - public String toString(@Nullable Event e, boolean debug) { - return "the level of " + enchants.toString(e, debug) + " of " + items.toString(e, debug); + public String toString(@Nullable Event event, boolean debug) { + return "the level of " + enchants.toString(event, debug) + " of " + items.toString(event, debug); } } diff --git a/src/main/java/ch/njol/skript/expressions/ExprEnchantmentOffer.java b/src/main/java/org/skriptlang/skript/bukkit/enchantments/elements/expressions/ExprEnchantmentOffer.java similarity index 53% rename from src/main/java/ch/njol/skript/expressions/ExprEnchantmentOffer.java rename to src/main/java/org/skriptlang/skript/bukkit/enchantments/elements/expressions/ExprEnchantmentOffer.java index d574d0c8e31..f529c4dcfd4 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprEnchantmentOffer.java +++ b/src/main/java/org/skriptlang/skript/bukkit/enchantments/elements/expressions/ExprEnchantmentOffer.java @@ -1,4 +1,4 @@ -package ch.njol.skript.expressions; +package org.skriptlang.skript.bukkit.enchantments.elements.expressions; import java.util.ArrayList; import java.util.Arrays; @@ -11,22 +11,22 @@ import org.bukkit.event.enchantment.PrepareItemEnchantEvent; import org.jetbrains.annotations.Nullable; -import ch.njol.skript.Skript; import ch.njol.skript.classes.Changer.ChangeMode; import ch.njol.skript.doc.Description; import ch.njol.skript.doc.Events; import ch.njol.skript.doc.Example; import ch.njol.skript.doc.Name; -import ch.njol.skript.doc.RequiredPlugins; import ch.njol.skript.doc.Since; import ch.njol.skript.lang.Expression; -import ch.njol.skript.lang.ExpressionType; import ch.njol.skript.lang.SkriptParser.ParseResult; import ch.njol.skript.lang.util.SimpleExpression; -import ch.njol.skript.log.ErrorQuality; import ch.njol.skript.util.EnchantmentType; import ch.njol.util.Kleenean; import ch.njol.util.coll.CollectionUtils; +import org.skriptlang.skript.registration.SyntaxInfo; +import org.skriptlang.skript.registration.SyntaxRegistry; + +import static org.skriptlang.skript.registration.DefaultSyntaxInfos.Expression.builder; @Name("Enchantment Offer") @Description("The enchantment offer in enchant prepare events.") @@ -36,16 +36,20 @@ """) @Since("2.5") @Events("enchant prepare") -@RequiredPlugins("1.11 or newer") public class ExprEnchantmentOffer extends SimpleExpression implements EventRestrictedSyntax { - static { - if (Skript.classExists("org.bukkit.enchantments.EnchantmentOffer")) { - Skript.registerExpression(ExprEnchantmentOffer.class, EnchantmentOffer.class, ExpressionType.SIMPLE, - "[all [of]] [the] enchant[ment] offers", - "enchant[ment] offer[s] %numbers%", - "[the] %number%(st|nd|rd|th) enchant[ment] offer"); - } + /* + * This should probably be an event value, but ExprElement doesn't support the %number%(st|nd|rd|th) %classinfo% syntax, + * and we have to keep it for backward compatibility, so for now it's best to just keep it as an expression + * */ + public static void register(SyntaxRegistry registry) { + registry.register(SyntaxRegistry.EXPRESSION, builder(ExprEnchantmentOffer.class, EnchantmentOffer.class) + .addPatterns( + "[all [of]] [the] enchant[ment] offers", + "enchant[ment] offer[s] %numbers%", + "[the] %number%(st|nd|rd|th) enchant[ment] offer") + .supplier(ExprEnchantmentOffer::new) + .priority(SyntaxInfo.SIMPLE).build()); } @SuppressWarnings("null") @@ -56,8 +60,8 @@ public class ExprEnchantmentOffer extends SimpleExpression imp // Used for getCost() private final Random rand = new Random(); - @SuppressWarnings({"null", "unchecked"}) @Override + @SuppressWarnings({"null", "unchecked"}) public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { if (matchedPattern == 0) { all = true; @@ -75,83 +79,70 @@ public Class[] supportedEvents() { @SuppressWarnings({"null", "unused"}) @Override - @Nullable - protected EnchantmentOffer[] get(Event e) { - if (!(e instanceof PrepareItemEnchantEvent)) + protected EnchantmentOffer @Nullable [] get(Event event) { + if (!(event instanceof PrepareItemEnchantEvent)) return null; if (all) - return ((PrepareItemEnchantEvent) e).getOffers(); + return ((PrepareItemEnchantEvent) event).getOffers(); if (exprOfferNumber == null) return new EnchantmentOffer[0]; if (exprOfferNumber.isSingle()) { - Number offerNumber = exprOfferNumber.getSingle(e); + Number offerNumber = exprOfferNumber.getSingle(event); if (offerNumber == null) return new EnchantmentOffer[0]; int offer = offerNumber.intValue(); - if (offer < 1 || offer > ((PrepareItemEnchantEvent) e).getOffers().length) + if (offer < 1 || offer > ((PrepareItemEnchantEvent) event).getOffers().length) return new EnchantmentOffer[0]; - return new EnchantmentOffer[]{((PrepareItemEnchantEvent) e).getOffers()[offer - 1]}; + return new EnchantmentOffer[]{((PrepareItemEnchantEvent) event).getOffers()[offer - 1]}; } List offers = new ArrayList<>(); - int i; - for (Number n : exprOfferNumber.getArray(e)) { - i = n.intValue(); - if (i >= 1 || i <= ((PrepareItemEnchantEvent) e).getOffers().length) - offers.add(((PrepareItemEnchantEvent) e).getOffers()[i - 1]); + int intIndex; + for (Number index : exprOfferNumber.getArray(event)) { + intIndex = index.intValue(); + if (intIndex >= 1 && intIndex <= ((PrepareItemEnchantEvent) event).getOffers().length) + offers.add(((PrepareItemEnchantEvent) event).getOffers()[intIndex - 1]); } return offers.toArray(new EnchantmentOffer[0]); } @Override - @Nullable - public Class[] acceptChange(ChangeMode mode) { + public Class @Nullable [] acceptChange(ChangeMode mode) { if (mode == ChangeMode.SET || mode == ChangeMode.DELETE) return CollectionUtils.array(EnchantmentType.class); return null; } - @SuppressWarnings("null") @Override - public void change(Event event, @Nullable Object[] delta, ChangeMode mode) { + @SuppressWarnings("null") + public void change(Event event, Object @Nullable [] delta, ChangeMode mode) { if (delta == null && mode != ChangeMode.DELETE) return; - EnchantmentType et = mode != ChangeMode.DELETE ? (EnchantmentType) delta[0] : null; - if (event instanceof PrepareItemEnchantEvent) { - PrepareItemEnchantEvent e = (PrepareItemEnchantEvent) event; + EnchantmentType type = mode != ChangeMode.DELETE ? (EnchantmentType) delta[0] : null; + if (event instanceof PrepareItemEnchantEvent prepareEvent) { switch (mode) { case SET: - if (all) { - for (int i = 0; i <= 2; i++) { - EnchantmentOffer eo = e.getOffers()[i]; - if (eo == null) { - eo = new EnchantmentOffer(et.getType(), et.getLevel(), getCost(i + 1, e.getEnchantmentBonus())); - e.getOffers()[i] = eo; - } else { - eo.setEnchantment(et.getType()); - eo.setEnchantmentLevel(et.getLevel()); - } - } - } else { - for (Number n : exprOfferNumber.getArray(e)) { - int slot = n.intValue() - 1; - EnchantmentOffer eo = e.getOffers()[slot]; - if (eo == null) { - eo = new EnchantmentOffer(et.getType(), et.getLevel(), getCost(slot + 1, e.getEnchantmentBonus())); - e.getOffers()[slot] = eo; - } else { - eo.setEnchantment(et.getType()); - eo.setEnchantmentLevel(et.getLevel()); - } + assert type != null; + Number[] indices = all ? new Number[]{1, 2, 3} : exprOfferNumber.getArray(prepareEvent); + for (Number index : indices) { + int slot = index.intValue() - 1; + EnchantmentOffer offer = prepareEvent.getOffers()[slot]; + if (offer == null) { + offer = new EnchantmentOffer(type.getType(), type.getLevel(), + getCost(slot + 1, prepareEvent.getEnchantmentBonus())); + prepareEvent.getOffers()[slot] = offer; + } else { + offer.setEnchantment(type.getType()); + offer.setEnchantmentLevel(type.getLevel()); } } break; case DELETE: if (all) { - Arrays.fill(e.getOffers(), null); + Arrays.fill(prepareEvent.getOffers(), null); } else { - for (Number n : exprOfferNumber.getArray(e)) - e.getOffers()[n.intValue() - 1] = null; + for (Number index : exprOfferNumber.getArray(prepareEvent)) + prepareEvent.getOffers()[index.intValue() - 1] = null; } break; case ADD: @@ -174,8 +165,8 @@ public Class getReturnType() { } @Override - public String toString(@Nullable Event e, boolean debug) { - return all ? "the enchantment offers" : "enchantment offer(s) " + exprOfferNumber.toString(e, debug); + public String toString(@Nullable Event event, boolean debug) { + return all ? "the enchantment offers" : "enchantment offer(s) " + exprOfferNumber.toString(event, debug); } /** @@ -186,13 +177,13 @@ public String toString(@Nullable Event e, boolean debug) { */ public int getCost(int slot, int bookshelves) { // (from 1 to 8) + floor(bookshelves / 2) + (from 0 to bookshelves) - int base = (int) ((rand.nextInt(7) + 1) + Math.floor(bookshelves / 2) + (rand.nextInt(bookshelves + 1))); - switch (slot) { - case 1: return Math.max(base / 3, 1); - case 2: return (base * 2) / 3 + 1; - case 3: return Math.max(base, bookshelves * 2); - default: return 1; - } + int base = (rand.nextInt(7) + 1) + (bookshelves / 2) + (rand.nextInt(bookshelves + 1)); + return switch (slot) { + case 1 -> Math.max(base / 3, 1); + case 2 -> (base * 2) / 3 + 1; + case 3 -> Math.max(base, bookshelves * 2); + default -> 1; + }; } } diff --git a/src/main/java/ch/njol/skript/expressions/ExprEnchantmentOfferCost.java b/src/main/java/org/skriptlang/skript/bukkit/enchantments/elements/expressions/ExprEnchantmentOfferCost.java similarity index 62% rename from src/main/java/ch/njol/skript/expressions/ExprEnchantmentOfferCost.java rename to src/main/java/org/skriptlang/skript/bukkit/enchantments/elements/expressions/ExprEnchantmentOfferCost.java index 1aa1844b024..1730b763c01 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprEnchantmentOfferCost.java +++ b/src/main/java/org/skriptlang/skript/bukkit/enchantments/elements/expressions/ExprEnchantmentOfferCost.java @@ -1,19 +1,17 @@ -package ch.njol.skript.expressions; +package org.skriptlang.skript.bukkit.enchantments.elements.expressions; import org.bukkit.enchantments.EnchantmentOffer; import org.bukkit.event.Event; import org.jetbrains.annotations.Nullable; -import ch.njol.skript.Skript; import ch.njol.skript.classes.Changer.ChangeMode; import ch.njol.skript.doc.Description; import ch.njol.skript.doc.Example; import ch.njol.skript.doc.Name; -import ch.njol.skript.doc.RequiredPlugins; import ch.njol.skript.doc.Since; import ch.njol.skript.expressions.base.SimplePropertyExpression; -import ch.njol.skript.util.Experience; import ch.njol.util.coll.CollectionUtils; +import org.skriptlang.skript.registration.SyntaxRegistry; @Name("Enchantment Offer Cost") @Description({ @@ -24,12 +22,12 @@ }) @Example("set cost of enchantment offer 1 to 50") @Since("2.5") -@RequiredPlugins("1.11 or newer") public class ExprEnchantmentOfferCost extends SimplePropertyExpression { - static { - if (Skript.classExists("org.bukkit.enchantments.EnchantmentOffer")) - register(ExprEnchantmentOfferCost.class, Long.class, "[enchant[ment]] cost", "enchantmentoffers"); + public static void register(SyntaxRegistry registry) { + registry.register(SyntaxRegistry.EXPRESSION, infoBuilder( + ExprEnchantmentOfferCost.class, Long.class, "[enchant[ment]] cost", "enchantmentoffers", false) + .supplier(ExprEnchantmentOfferCost::new).build()); } @Override @@ -38,48 +36,42 @@ public Long convert(final EnchantmentOffer offer) { } @Override - @Nullable - public Class[] acceptChange(ChangeMode mode) { + public Class @Nullable [] acceptChange(ChangeMode mode) { if (mode == ChangeMode.REMOVE || mode == ChangeMode.REMOVE_ALL || mode == ChangeMode.RESET) return null; - return CollectionUtils.array(Number.class, Experience.class); + return CollectionUtils.array(Number.class); } @Override - public void change(Event event, @Nullable Object[] delta, ChangeMode mode) { + public void change(Event event, Object @Nullable [] delta, ChangeMode mode) { EnchantmentOffer[] offers = getExpr().getArray(event); if (offers.length == 0 || delta == null) return; - Object c = delta[0]; - int cost = c instanceof Number ? ((Number) c).intValue() : ((Experience) c).getXP(); + if (delta[0] == null) + return; + int cost = ((Number) delta[0]).intValue(); if (cost < 1) return; int change; - switch (mode) { - case SET: - for (EnchantmentOffer offer : offers) - offer.setCost(cost); - break; - case ADD: - for (EnchantmentOffer offer : offers) { + for (EnchantmentOffer offer : offers) { + switch (mode) { + case SET -> offer.setCost(cost); + case ADD -> { change = offer.getCost() + cost; - if (change < 1) + if (change < 1) return; offer.setCost(change); } - break; - case REMOVE: - for (EnchantmentOffer offer : offers) { + case REMOVE -> { change = offer.getCost() - cost; - if (change < 1) + if (change < 1) return; offer.setCost(change); } - break; - case RESET: - case DELETE: - case REMOVE_ALL: - assert false; + case RESET, DELETE, REMOVE_ALL -> { + assert false; + } + } } } diff --git a/src/main/java/ch/njol/skript/expressions/ExprEnchantments.java b/src/main/java/org/skriptlang/skript/bukkit/enchantments/elements/expressions/ExprEnchantments.java similarity index 64% rename from src/main/java/ch/njol/skript/expressions/ExprEnchantments.java rename to src/main/java/org/skriptlang/skript/bukkit/enchantments/elements/expressions/ExprEnchantments.java index 2df74875524..ed6e030113a 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprEnchantments.java +++ b/src/main/java/org/skriptlang/skript/bukkit/enchantments/elements/expressions/ExprEnchantments.java @@ -1,4 +1,4 @@ -package ch.njol.skript.expressions; +package org.skriptlang.skript.bukkit.enchantments.elements.expressions; import java.util.ArrayList; import java.util.Collections; @@ -18,28 +18,27 @@ import ch.njol.skript.expressions.base.PropertyExpression; import ch.njol.skript.lang.Expression; import ch.njol.skript.lang.SkriptParser.ParseResult; -import ch.njol.skript.lang.util.SimpleExpression; import ch.njol.skript.util.EnchantmentType; import ch.njol.util.Kleenean; import ch.njol.util.coll.CollectionUtils; +import org.skriptlang.skript.registration.SyntaxRegistry; @Name("Item Enchantments") @Description("All the enchantments an item type has.") @Example("clear enchantments of event-item") @Since("2.2-dev36") -public class ExprEnchantments extends SimpleExpression { +public class ExprEnchantments extends PropertyExpression { - static { - PropertyExpression.register(ExprEnchantments.class, EnchantmentType.class, "enchantments", "itemtypes"); + public static void register(SyntaxRegistry registry) { + registry.register(SyntaxRegistry.EXPRESSION, + infoBuilder(ExprEnchantments.class, EnchantmentType.class, "enchantments", "itemtypes", false) + .supplier(ExprEnchantments::new).build()); } - @SuppressWarnings("null") - private Expression items; - - @SuppressWarnings({"null","unchecked"}) @Override + @SuppressWarnings({"null","unchecked"}) public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { - items = (Expression) exprs[0]; + setExpr((Expression) exprs[0]); return true; } @@ -49,11 +48,9 @@ public boolean isSingle() { } @Override - @Nullable - protected EnchantmentType[] get(Event e) { + protected EnchantmentType[] get(Event event, ItemType[] source) { List enchantments = new ArrayList<>(); - - for (ItemType item : items.getArray(e)) { + for (ItemType item : source) { EnchantmentType[] enchants = item.getEnchantmentTypes(); if (enchants == null) @@ -65,27 +62,23 @@ protected EnchantmentType[] get(Event e) { } @Override - @Nullable - public Class[] acceptChange(ChangeMode mode) { - // Enchantment doesn't get automatically converted to EnchantmentType if you give it more than a one. - // Meaning you can transform an Enchantment array to an EnchantmentType array automatically, - // So, we gotta do it manually. - return CollectionUtils.array(Enchantment[].class, EnchantmentType[].class); + public Class @Nullable [] acceptChange(ChangeMode mode) { + return switch (mode) { + case ADD, SET, REMOVE, REMOVE_ALL, DELETE, RESET -> CollectionUtils.array(EnchantmentType[].class); + default -> null; + }; } @Override - public void change(Event e, @Nullable Object[] delta, ChangeMode mode) { - ItemType[] source = items.getArray(e); - + public void change(Event event, Object @Nullable [] delta, ChangeMode mode) { + ItemType[] source = getExpr().getArray(event); + EnchantmentType[] enchants = new EnchantmentType[delta != null ? delta.length : 0]; - - if (delta != null && delta.length != 0) { - for (int i = 0; i getReturnType() { } @Override - public String toString(@Nullable Event e, boolean debug) { - return "the enchantments of " + items.toString(e, debug); + public String toString(@Nullable Event event, boolean debug) { + return "the enchantments of " + getExpr().toString(event, debug); } } diff --git a/src/main/java/ch/njol/skript/expressions/ExprItemWithEnchantmentGlint.java b/src/main/java/org/skriptlang/skript/bukkit/enchantments/elements/expressions/ExprItemWithEnchantmentGlint.java similarity index 74% rename from src/main/java/ch/njol/skript/expressions/ExprItemWithEnchantmentGlint.java rename to src/main/java/org/skriptlang/skript/bukkit/enchantments/elements/expressions/ExprItemWithEnchantmentGlint.java index e763798f487..1f2c73f42a5 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprItemWithEnchantmentGlint.java +++ b/src/main/java/org/skriptlang/skript/bukkit/enchantments/elements/expressions/ExprItemWithEnchantmentGlint.java @@ -1,29 +1,31 @@ -package ch.njol.skript.expressions; +package org.skriptlang.skript.bukkit.enchantments.elements.expressions; import org.bukkit.event.Event; import org.bukkit.inventory.meta.ItemMeta; import org.jetbrains.annotations.Nullable; -import ch.njol.skript.Skript; import ch.njol.skript.aliases.ItemType; import ch.njol.skript.doc.*; import ch.njol.skript.expressions.base.PropertyExpression; import ch.njol.skript.lang.Expression; -import ch.njol.skript.lang.ExpressionType; import ch.njol.skript.lang.SkriptParser.ParseResult; import ch.njol.util.Kleenean; +import org.skriptlang.skript.registration.SyntaxRegistry; + +import static org.skriptlang.skript.registration.DefaultSyntaxInfos.Expression.builder; @Name("Item with Enchantment Glint") @Description("Get an item with or without enchantment glint.") @Example("set {_item with glint} to diamond with enchantment glint") @Example("set {_item without glint} to diamond without enchantment glint") -@RequiredPlugins("Spigot 1.20.5+") @Since("2.10") public class ExprItemWithEnchantmentGlint extends PropertyExpression { - static { - if (Skript.methodExists(ItemMeta.class, "getEnchantmentGlintOverride")) - Skript.registerExpression(ExprItemWithEnchantmentGlint.class, ItemType.class, ExpressionType.PROPERTY, "%itemtypes% with[:out] [enchant[ment]] glint"); + public static void register(SyntaxRegistry registry) { + registry.register(SyntaxRegistry.EXPRESSION, builder(ExprItemWithEnchantmentGlint.class, ItemType.class) + .addPattern("%itemtypes% with[:out] [enchant[ment]] glint") + .supplier(ExprItemWithEnchantmentGlint::new) + .priority(PropertyExpression.DEFAULT_PRIORITY).build()); } private boolean glint; diff --git a/src/main/java/org/skriptlang/skript/bukkit/enchantments/elements/expressions/ExprMaximumEnchantmentLevel.java b/src/main/java/org/skriptlang/skript/bukkit/enchantments/elements/expressions/ExprMaximumEnchantmentLevel.java new file mode 100644 index 00000000000..eee48b96504 --- /dev/null +++ b/src/main/java/org/skriptlang/skript/bukkit/enchantments/elements/expressions/ExprMaximumEnchantmentLevel.java @@ -0,0 +1,45 @@ +package org.skriptlang.skript.bukkit.enchantments.elements.expressions; + +import ch.njol.skript.doc.Description; +import ch.njol.skript.doc.Example; +import ch.njol.skript.doc.Name; +import ch.njol.skript.doc.Since; +import ch.njol.skript.expressions.base.SimplePropertyExpression; +import org.bukkit.enchantments.Enchantment; +import org.jetbrains.annotations.Nullable; +import org.skriptlang.skript.registration.SyntaxRegistry; + +@Name("Maximum Enchantment Level") +@Description("The maximum allowed level in Minecraft of a particular enchantment") +@Example(""" + set {_maximum} to the maximum enchantment level of sharpness + if the level of sharpness of the player's tool is greater than {_maximum}: + send "Your tool's sharpness level was capped out at the maximum allowed level." + set the level of sharpness of the player's tool to {_maximum} + """) +@Since("INSERT VERSION") +public class ExprMaximumEnchantmentLevel extends SimplePropertyExpression { + + public static void register(SyntaxRegistry registry) { + registry.register(SyntaxRegistry.EXPRESSION, infoBuilder( + ExprMaximumEnchantmentLevel.class, Integer.class, + "max[imum] enchant[ment] level", "enchantments", true) + .supplier(ExprMaximumEnchantmentLevel::new).build()); + } + + @Override + public @Nullable Integer convert(Enchantment from) { + return from.getMaxLevel(); + } + + @Override + public Class getReturnType() { + return Integer.class; + } + + @Override + protected String getPropertyName() { + return "maximum enchantment level"; + } + +} diff --git a/src/main/java/org/skriptlang/skript/bukkit/enchantments/elements/expressions/ExprMinimumEnchantmentLevel.java b/src/main/java/org/skriptlang/skript/bukkit/enchantments/elements/expressions/ExprMinimumEnchantmentLevel.java new file mode 100644 index 00000000000..b2fb9859926 --- /dev/null +++ b/src/main/java/org/skriptlang/skript/bukkit/enchantments/elements/expressions/ExprMinimumEnchantmentLevel.java @@ -0,0 +1,48 @@ +package org.skriptlang.skript.bukkit.enchantments.elements.expressions; + +import ch.njol.skript.doc.Description; +import ch.njol.skript.doc.Example; +import ch.njol.skript.doc.Name; +import ch.njol.skript.doc.Since; +import ch.njol.skript.expressions.base.SimplePropertyExpression; +import org.bukkit.enchantments.Enchantment; +import org.jetbrains.annotations.Nullable; +import org.skriptlang.skript.registration.SyntaxRegistry; + +@Name("Minimum Enchantment Level") +@Description(""" + The minimum starting level in Minecraft of a particular enchantment. + This is 1 for all existing enchantments as of 26.1.2. + """) +@Example(""" + set {_min} to the minimum enchantment level of sharpness + set {_max} to the maximum enchantment level of sharpness + loop integers between {_min} and {_max}: + set slot loop-counter of {_gui} to enchanted book named "Sharpness %loop-value%" with lore "Click to enchant!" + """) +@Since("INSERT VERSION") +public class ExprMinimumEnchantmentLevel extends SimplePropertyExpression { + + public static void register(SyntaxRegistry registry) { + registry.register(SyntaxRegistry.EXPRESSION, infoBuilder( + ExprMinimumEnchantmentLevel.class, Integer.class, + "(min[imum]|start[ing]) enchant[ment] level", "enchantments", true) + .supplier(ExprMinimumEnchantmentLevel::new).build()); + } + + @Override + public @Nullable Integer convert(Enchantment from) { + return from.getStartLevel(); + } + + @Override + public Class getReturnType() { + return Integer.class; + } + + @Override + protected String getPropertyName() { + return "minimum enchantment level"; + } + +} diff --git a/src/main/java/org/skriptlang/skript/bukkit/enchantments/elements/expressions/ExprStoredEnchantments.java b/src/main/java/org/skriptlang/skript/bukkit/enchantments/elements/expressions/ExprStoredEnchantments.java new file mode 100644 index 00000000000..66f9eae5eb6 --- /dev/null +++ b/src/main/java/org/skriptlang/skript/bukkit/enchantments/elements/expressions/ExprStoredEnchantments.java @@ -0,0 +1,145 @@ +package org.skriptlang.skript.bukkit.enchantments.elements.expressions; + +import ch.njol.skript.aliases.ItemType; +import ch.njol.skript.classes.Changer.ChangeMode; +import ch.njol.skript.doc.Description; +import ch.njol.skript.doc.Example; +import ch.njol.skript.doc.Name; +import ch.njol.skript.doc.Since; +import ch.njol.skript.expressions.base.PropertyExpression; +import ch.njol.skript.lang.Expression; +import ch.njol.skript.lang.SkriptParser.ParseResult; +import ch.njol.skript.util.EnchantmentType; +import ch.njol.util.Kleenean; +import ch.njol.util.coll.CollectionUtils; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.event.Event; +import org.bukkit.inventory.meta.EnchantmentStorageMeta; +import org.bukkit.inventory.meta.ItemMeta; +import org.jetbrains.annotations.Nullable; +import org.skriptlang.skript.registration.SyntaxRegistry; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Name("Stored Enchantments") +@Description(""" + The enchantments stored inside an enchanted book. This is different from enchanting the book, as for example a book + of sharpness does not deal more damage when used as a weapon. Corresponds to the minecraft:stored_enchantments data component. + Note that for example resetting the stored enchantments of an enchanted book of Sharpness III removes the sharpness enchantment, since + it is impossible to know what the original enchantments of the item were. Note also that only one entry can exist per enchantment type; + adding Sharpness III to a book with Sharpness V will convert it to a book of Sharpness III. + """) +@Example(""" + command /godbook: + trigger: + set {_item} to minecraft:enchanted_book + add mending to stored enchants of {_item} # adds mending 1 + add knockback 12 to stored enchants of {_item} + add fire aspect 3 to stored enchants of {_item} + give {_item} to player + """) +@Since("INSERT VERSION") +public class ExprStoredEnchantments extends PropertyExpression { + + public static void register(SyntaxRegistry registry) { + registry.register(SyntaxRegistry.EXPRESSION, infoBuilder( + ExprStoredEnchantments.class, EnchantmentType.class, "stored enchant[ment]s", "itemtypes", false) + .supplier(ExprStoredEnchantments::new).build()); + } + + @Override + @SuppressWarnings("unchecked") + public boolean init(Expression[] expressions, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { + setExpr((Expression) expressions[0]); + return true; + } + + @Override + protected EnchantmentType[] get(Event event, ItemType[] source) { + List types = new ArrayList<>(); + for (ItemType type : source) { + ItemMeta meta = type.getItemMeta(); + if (!(meta instanceof EnchantmentStorageMeta storageMeta)) + continue; + + for (Map.Entry entry : storageMeta.getStoredEnchants().entrySet()) { + types.add(new EnchantmentType(entry.getKey(), entry.getValue())); + } + } + + return types.toArray(EnchantmentType[]::new); + } + + @Override + public Class @Nullable [] acceptChange(ChangeMode mode) { + return switch (mode) { + case ADD, SET, DELETE, REMOVE, REMOVE_ALL -> CollectionUtils.array(EnchantmentType[].class); + default -> null; + }; + } + + @Override + public void change(Event event, Object @Nullable [] delta, ChangeMode mode) { + ItemType[] targets = getExpr().getArray(event); + for (ItemType target : targets) { + ItemMeta rawMeta = target.getItemMeta(); + if (!(rawMeta instanceof EnchantmentStorageMeta meta)) + continue; + Map adjusted = new HashMap<>(meta.getStoredEnchants()); + if (mode == ChangeMode.SET || mode == ChangeMode.DELETE) + adjusted.clear(); + + switch (mode) { + case DELETE -> {} + case ADD, SET -> { + assert delta != null; + for (Object change : delta) { + if (!(change instanceof EnchantmentType type)) + continue; + adjusted.put(type.getType(), type.getLevel()); + } + } + case REMOVE, REMOVE_ALL -> { + assert delta != null; + for (Object change : delta) { + if (!(change instanceof EnchantmentType type)) + continue; + if (type.getInternalLevel() == -1) { + adjusted.remove(type.getType()); + } else { + adjusted.remove(type.getType(), type.getLevel()); + } + } + } + default -> throw new IllegalArgumentException("Invalid change mode " + mode); + } + + for (Enchantment existing : meta.getStoredEnchants().keySet()) + meta.removeStoredEnchant(existing); + + for (Map.Entry adjustedEntry : adjusted.entrySet()) + meta.addStoredEnchant(adjustedEntry.getKey(), adjustedEntry.getValue(), true); + + target.setItemMeta(meta); + } + } + + @Override + public boolean isSingle() { + return false; + } + + @Override + public Class getReturnType() { + return EnchantmentType.class; + } + + @Override + public String toString(@Nullable Event event, boolean debug) { + return "stored enchantments of " + getExpr().toString(event, debug); + } + +} diff --git a/src/test/skript/tests/syntaxes/expressions/ExprStoredEnchantments.sk b/src/test/skript/tests/syntaxes/expressions/ExprStoredEnchantments.sk new file mode 100644 index 00000000000..4fda929099f --- /dev/null +++ b/src/test/skript/tests/syntaxes/expressions/ExprStoredEnchantments.sk @@ -0,0 +1,19 @@ +test "stored enchantments": + set {_item} to 3 of minecraft:enchanted_book + + add efficiency 7 to stored enchantments of {_item} + add fire aspect 0 to stored enchantments of {_item} + assert size of stored enchantments of {_item} is 2 with "did not add 2 stored enchantments" + assert stored enchantments of {_item} contain fire aspect 0 with "fire aspect 0 couldn't be added" + + add sharpness to stored enchantments of {_item} + assert stored enchantments of {_item} contain sharpness 1 with "sharpness was not added" + + remove fire aspect 2 and efficiency from stored enchants of {_item} + assert stored enchantments of {_item} contain fire aspect 0 and sharpness 1 with "did not remove properly" + + clear stored enchantments of {_item} + assert stored enchantments of {_item} is not set with "did not clear enchantments properly" + + add sharpness and efficiency to stored enchantments of {_item} + assert stored enchantments of {_item} contain sharpness 1 and efficiency 1 with "did not convert properly"