diff --git a/build.gradle.kts b/build.gradle.kts index 72d68696e..926abc85d 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -59,6 +59,7 @@ tasks { dependsOn("shadowJar") from("build/libs") { include("SkBee-*.jar") + exclude("*-sources.jar") destinationDir = file("/Users/ShaneBee/Desktop/Server/${serverLocation}/plugins/") } } @@ -82,7 +83,7 @@ tasks { relocate("fr.mrmicky.fastboard", "com.shanebeestudios.skbee.api.fastboard.base") relocate("com.shanebeestudios.vf", "com.shanebeestudios.skbee.api.virtualfurnace") relocate("org.bstats", "com.shanebeestudios.skbee.metrics") - exclude("META-INF/**", "LICENSE") + exclude("META-INF/**", "LICENSE", "plugin.yml") } jar { enabled = false diff --git a/src/main/java/com/shanebeestudios/skbee/AddonLoader.java b/src/main/java/com/shanebeestudios/skbee/AddonLoader.java index 5cf221a38..0d71ae29e 100644 --- a/src/main/java/com/shanebeestudios/skbee/AddonLoader.java +++ b/src/main/java/com/shanebeestudios/skbee/AddonLoader.java @@ -51,7 +51,6 @@ import org.bukkit.plugin.Plugin; import org.bukkit.plugin.PluginManager; import org.bukkit.scoreboard.Objective; -import org.skriptlang.skript.addon.SkriptAddon; /** * @hidden @@ -63,28 +62,26 @@ public class AddonLoader { private final Registration registration; private final Config config; private final Plugin skriptPlugin; - private final SkriptAddon addon; public AddonLoader(SkBee plugin) { this.plugin = plugin; - this.registration = plugin.getRegistration(); + this.registration = new Registration("SkBee", true); this.pluginManager = plugin.getServer().getPluginManager(); this.config = plugin.getPluginConfig(); MinecraftVersion.replaceLogger(LoggerBee.getLogger()); this.skriptPlugin = pluginManager.getPlugin("Skript"); - this.addon = this.registration.getAddon(); } - public SkriptAddon getAddon() { - return this.addon; + public Registration getRegistration() { + return this.registration; } boolean canLoadPlugin() { - if (skriptPlugin == null) { + if (this.skriptPlugin == null) { Util.logLoading("&cDependency Skript was not found, Skript elements cannot load."); return false; } - if (!skriptPlugin.isEnabled()) { + if (!this.skriptPlugin.isEnabled()) { Util.logLoading("&cDependency Skript is not enabled, Skript elements cannot load."); Util.logLoading("&cThis could mean SkBee is being forced to load before Skript."); return false; @@ -146,8 +143,7 @@ private void loadSkriptElements() { loadTestingElements(); // Load elements into Skript - SkBeeAddonModule module = new SkBeeAddonModule(this.registration); - addon.loadModules(module); + this.registration.finalizeRegistration(); // ELEMENT COUNT int typeCount = this.registration.getTypes().size(); @@ -556,8 +552,10 @@ private void loadWorldCreatorElements() { @SuppressWarnings("ThrowableNotThrown") private void logFailure(String element, Exception ex) { + Throwable cause = ex.getCause(); + String message = cause != null ? cause.getMessage() : ex.getMessage(); Skript.exception(ex); - Util.logLoading("&e%s Elements &7failed to load due to &r'&c%s&r'", element, ex.getCause().getMessage()); + Util.logLoading("&e%s Elements &7failed to load due to &r'&c%s&r'", element, message); } private boolean isPlugmanReloaded() { diff --git a/src/main/java/com/shanebeestudios/skbee/SkBee.java b/src/main/java/com/shanebeestudios/skbee/SkBee.java index 40cd4f9b3..78c37a4c4 100644 --- a/src/main/java/com/shanebeestudios/skbee/SkBee.java +++ b/src/main/java/com/shanebeestudios/skbee/SkBee.java @@ -9,7 +9,6 @@ import com.shanebeestudios.skbee.api.bound.BoundConfig; import com.shanebeestudios.skbee.api.command.SkBeeInfo; import com.shanebeestudios.skbee.api.region.TaskUtils; -import com.shanebeestudios.skbee.api.registration.Registration; import com.shanebeestudios.skbee.api.structure.StructureManager; import com.shanebeestudios.skbee.api.util.Util; import com.shanebeestudios.skbee.api.util.update.UpdateChecker; @@ -43,7 +42,6 @@ public class SkBee extends JavaPlugin { VirtualFurnaceAPI virtualFurnaceAPI; BeeWorldConfig beeWorldConfig; StructureManager structureManager = null; - private Registration registration; private AddonLoader addonLoader = null; /** @@ -65,10 +63,9 @@ public void onEnable() { TaskUtils.initialize(this, Util.IS_RUNNING_FOLIA || this.config.settings_use_paper_schedulers); - this.registration = new Registration(); this.addonLoader = new AddonLoader(this); // Check if SkriptAddon can actually load - this.properlyEnabled = addonLoader.canLoadPlugin(); + this.properlyEnabled = this.addonLoader.canLoadPlugin(); loadCommands(); loadMetrics(); @@ -107,7 +104,7 @@ private void loadMetrics() { //6719 Version version = new Version(this.getPluginMeta().getVersion()); Table table = HashBasedTable.create(1, 1); table.put( - version.getMajor() + "." + version.getMinor(), // upper label + version.getMajor() + "." + version.getMinor() + ".x", // upper label version.toString(), // lower label 1 // weight ); @@ -117,7 +114,7 @@ private void loadMetrics() { //6719 Version version = Skript.getVersion(); Table table = HashBasedTable.create(1, 1); table.put( - version.getMajor() + "." + version.getMinor(), // upper label + version.getMajor() + "." + version.getMinor() + ".x", // upper label version.toString(), // lower label 1 // weight ); @@ -130,14 +127,14 @@ private void loadMetrics() { //6719 if (version.getMajor() == 1) { // Minecraft 1.x.x versioning table.put( - version.getMajor() + "." + version.getMinor(), // upper label + version.getMajor() + "." + version.getMinor() + ".x", // upper label version.toString(), // lower label 1 // weight ); } else { // Minecraft (year).x.x versioning table.put( - "" + version.getMajor(), // upper label + version.getMajor() + ".x", // upper label version.toString(), // lower label 1 // weight ); @@ -245,10 +242,6 @@ public StructureManager getStructureManager() { return structureManager; } - public Registration getRegistration() { - return this.registration; - } - /** * @hidden */ diff --git a/src/main/java/com/shanebeestudios/skbee/SkBeeAddonModule.java b/src/main/java/com/shanebeestudios/skbee/SkBeeAddonModule.java deleted file mode 100644 index 1f8444f89..000000000 --- a/src/main/java/com/shanebeestudios/skbee/SkBeeAddonModule.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.shanebeestudios.skbee; - -import com.shanebeestudios.skbee.api.registration.Registration; -import org.skriptlang.skript.addon.AddonModule; -import org.skriptlang.skript.addon.SkriptAddon; - -public class SkBeeAddonModule implements AddonModule { - - private final Registration registration; - - public SkBeeAddonModule(Registration registration) { - this.registration = registration; - } - - @Override - public void init(SkriptAddon addon) { - this.registration.registerInit(); - } - - @Override - public void load(SkriptAddon addon) { - this.registration.registerLoad(); - } - - @Override - public String name() { - return "SkBee"; - } - -} diff --git a/src/main/java/com/shanebeestudios/skbee/api/command/SkBeeInfo.java b/src/main/java/com/shanebeestudios/skbee/api/command/SkBeeInfo.java index fd1485946..1ab88c633 100644 --- a/src/main/java/com/shanebeestudios/skbee/api/command/SkBeeInfo.java +++ b/src/main/java/com/shanebeestudios/skbee/api/command/SkBeeInfo.java @@ -113,7 +113,7 @@ else if (args[0].equalsIgnoreCase("properties")) { // JSON DOCS else if (args[0].equalsIgnoreCase("docs")) { - JsonDocGenerator docs = new JsonDocGenerator(this.plugin, this.plugin.getRegistration()); + JsonDocGenerator docs = new JsonDocGenerator(this.plugin, this.plugin.getAddonLoader().getRegistration()); docs.generateDocs(); } } diff --git a/src/main/java/com/shanebeestudios/skbee/api/wrapper/EnumWrapper.java b/src/main/java/com/shanebeestudios/skbee/api/registration/EnumWrapper.java similarity index 99% rename from src/main/java/com/shanebeestudios/skbee/api/wrapper/EnumWrapper.java rename to src/main/java/com/shanebeestudios/skbee/api/registration/EnumWrapper.java index 41039764a..cafb98df3 100644 --- a/src/main/java/com/shanebeestudios/skbee/api/wrapper/EnumWrapper.java +++ b/src/main/java/com/shanebeestudios/skbee/api/registration/EnumWrapper.java @@ -1,4 +1,4 @@ -package com.shanebeestudios.skbee.api.wrapper; +package com.shanebeestudios.skbee.api.registration; import ch.njol.skript.classes.ClassInfo; import ch.njol.skript.classes.Parser; diff --git a/src/main/java/com/shanebeestudios/skbee/api/registration/JsonDocGenerator.java b/src/main/java/com/shanebeestudios/skbee/api/registration/JsonDocGenerator.java index 22aba3222..952405da9 100644 --- a/src/main/java/com/shanebeestudios/skbee/api/registration/JsonDocGenerator.java +++ b/src/main/java/com/shanebeestudios/skbee/api/registration/JsonDocGenerator.java @@ -18,6 +18,7 @@ import com.shanebeestudios.skbee.api.registration.Registration.StructureRegistrar; import com.shanebeestudios.skbee.api.registration.Registration.TypeRegistrar; import com.shanebeestudios.skbee.api.util.Util; +import org.bukkit.event.Cancellable; import org.bukkit.event.Event; import org.bukkit.plugin.Plugin; import org.jetbrains.annotations.Nullable; @@ -42,6 +43,7 @@ public class JsonDocGenerator { private final Registration registration; private final Gson gson = new GsonBuilder().setPrettyPrinting().create(); private int total = 0; + private final List IDS = new ArrayList<>(); public JsonDocGenerator(Plugin plugin, Registration registration) { this.plugin = plugin; @@ -168,6 +170,16 @@ private void generateEvents(JsonObject mainDoc) { } gemerateGeneric("type", documentation, syntaxObject, patterns.toArray(new String[0])); + // Cancelable + boolean cancellable = false; + for (Class eventClass : event.eventClasses) { + if (Cancellable.class.isAssignableFrom(eventClass)) { + cancellable = true; + break; + } + } + syntaxObject.addProperty("cancellable", cancellable); + // EventValues List eventValueList = new ArrayList<>(); for (Class eventClass : event.eventClasses) { @@ -444,7 +456,12 @@ private void gemerateGeneric(String type, Documentation documentation, JsonObjec private String generateId(String type, String name) { type = type.toLowerCase(Locale.ROOT).replace(" ", "_"); name = name.toLowerCase(Locale.ROOT).replace(" ", "_"); - return String.format("%s:%s:%s", this.addonName, type, name); + String id = String.format("%s:%s:%s", this.addonName, type, name); + if (this.IDS.contains(id)) { + Util.log("&cID '%s' already exists", id); + } + this.IDS.add(id); + return id; } @SuppressWarnings("UnstableApiUsage") diff --git a/src/main/java/com/shanebeestudios/skbee/api/registration/Registration.java b/src/main/java/com/shanebeestudios/skbee/api/registration/Registration.java index 87776524c..0c36b7c23 100644 --- a/src/main/java/com/shanebeestudios/skbee/api/registration/Registration.java +++ b/src/main/java/com/shanebeestudios/skbee/api/registration/Registration.java @@ -18,15 +18,13 @@ import ch.njol.skript.lang.SkriptEvent; import ch.njol.skript.lang.function.Functions; import ch.njol.skript.registrations.Classes; -import com.shanebeestudios.skbee.SkBeeAddonModule; import com.shanebeestudios.skbee.api.util.Util; -import com.shanebeestudios.skbee.api.wrapper.EnumWrapper; -import com.shanebeestudios.skbee.api.wrapper.RegistryClassInfo; import org.bukkit.Keyed; import org.bukkit.Registry; import org.bukkit.event.Event; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.skriptlang.skript.addon.AddonModule; import org.skriptlang.skript.addon.SkriptAddon; import org.skriptlang.skript.bukkit.registration.BukkitSyntaxInfos; import org.skriptlang.skript.common.function.DefaultFunction; @@ -47,6 +45,8 @@ public class Registration { private final SkriptAddon addon; + private final RegistrationAddonModule module; + private final List> preRegistrations = new ArrayList<>(); private final List> types = new ArrayList<>(); private final List effects = new ArrayList<>(); private final List conditions = new ArrayList<>(); @@ -56,9 +56,12 @@ public class Registration { private final List> structures = new ArrayList<>(); private final List functions = new ArrayList<>(); - public Registration() { - this.addon = Skript.instance().registerAddon(SkBeeAddonModule.class, "SkBee"); - this.addon.localizer().setSourceDirectories("lang", null); + public Registration(String name, boolean includeLang) { + this.addon = Skript.instance().registerAddon(RegistrationAddonModule.class, name); + if (includeLang) { + this.addon.localizer().setSourceDirectories("lang", null); + } + this.module = new RegistrationAddonModule(name, this); } public SkriptAddon getAddon() { @@ -98,10 +101,14 @@ public List getFunctions() { } @SuppressWarnings("unchecked") - public static class Registrar> { + public class Registrar> { private final Documentation documentation = new Documentation(); private boolean registered; + public Registrar() { + Registration.this.preRegistrations.add(this); + } + public T noDoc() { this.documentation.setNoDoc(true); return (T) this; @@ -142,7 +149,7 @@ public boolean isRegistered() { public void register() { if (this.registered) { - Util.skriptError("Syntax '%s' is already registered!", this.documentation.getName()); + skriptError("Syntax '%s' is already registered!", this.documentation.getName()); return; } this.registered = true; @@ -496,13 +503,27 @@ public FunctionRegistrar newFunction(DefaultFunction function) { return new FunctionRegistrar(function); } + public void finalizeRegistration() { + this.addon.loadModules(this.module); + } + public void registerInit() { + // CHECK REGISTRATION + this.preRegistrations.forEach(registrar -> { + if (!registrar.isRegistered()) { + String name = registrar.documentation.getName(); + if (name == null) { + name = registrar.getClass().getSimpleName(); + skriptError("Unnamed registrar in '%s' not registered!", name); + } else { + skriptError("Registrar for '%s' not registered!", name); + } + } + }); + this.preRegistrations.clear(); + // TYPES for (TypeRegistrar type : getTypes()) { - if (!type.isRegistered()) { - Util.skriptError("Type '" + type.codename + "' is not registered!"); - continue; - } ClassInfo classInfo; if (type instanceof EnumTypeRegistrar enumTypeRegistrar) { classInfo = enumTypeRegistrar.classInfo; @@ -551,10 +572,6 @@ public void registerLoad() { // STRUCTURES for (Registration.StructureRegistrar structure : getStructures()) { - if (!structure.isRegistered()) { - Util.skriptError("Structure '%s' is not registered!", structure.structureClass.getSimpleName()); - continue; - } DefaultSyntaxInfos.Structure build = DefaultSyntaxInfos.Structure.builder( (Class) structure.structureClass) @@ -566,10 +583,6 @@ public void registerLoad() { } // EVENTS for (Registration.EventRegistrar event : getEvents()) { - if (!event.isRegistered()) { - Util.skriptError("Event '" + event.getDocumentation().getName() + "' is not registered!"); - continue; - } BukkitSyntaxInfos.Event.Builder, SkriptEvent> builder = BukkitSyntaxInfos.Event.builder( (Class) event.skriptEventClass, event.getDocumentation().getName()); @@ -583,10 +596,6 @@ public void registerLoad() { // SECTIONS for (Registration.SectionRegistrar section : getSections()) { - if (!section.isRegistered()) { - Util.skriptError("Section '" + section.section.getSimpleName() + "' is not registered!"); - continue; - } Supplier
supplier = () -> { try { @@ -605,10 +614,6 @@ public void registerLoad() { // EFFECTS for (EffectRegistrar effect : getEffects()) { - if (!effect.isRegistered()) { - Util.skriptError("Effect '" + effect.effect.getSimpleName() + "' is not registered!"); - continue; - } Supplier supplier = () -> { try { return effect.effect.getConstructor().newInstance(); @@ -627,10 +632,6 @@ public void registerLoad() { // EXPRESSIONS for (Registration.ExpressionRegistrar expression : getExpressions()) { - if (!expression.isRegistered()) { - Util.skriptError("Expression '%s' is not registered!", expression.expressionClass.getSimpleName()); - continue; - } Supplier supplier = () -> { try { return expression.expressionClass.getConstructor().newInstance(); @@ -649,19 +650,12 @@ public void registerLoad() { // FUNCTIONS for (FunctionRegistrar function : getFunctions()) { - if (!function.isRegistered()) { - Util.skriptError("Function '%s' is not register", function.function.name()); - } Functions.register(function.function); } // CONDITIONS for (ConditionRegistrar condition : getConditions()) { - if (!condition.isRegistered()) { - Util.skriptError("Condition '" + condition.condition.getSimpleName() + "' is not registered!"); - continue; - } Supplier supplier = () -> { try { return condition.condition.getConstructor().newInstance(); @@ -679,4 +673,35 @@ public void registerLoad() { } } + private static void skriptError(String format, Object... args) { + Util.skriptError(format, args); + } + + public static class RegistrationAddonModule implements AddonModule { + + private final String name; + private final Registration registration; + + public RegistrationAddonModule(String name, Registration registration) { + this.name = name; + this.registration = registration; + } + + @Override + public void init(SkriptAddon addon) { + this.registration.registerInit(); + } + + @Override + public void load(SkriptAddon addon) { + this.registration.registerLoad(); + } + + @Override + public String name() { + return this.name; + } + + } + } diff --git a/src/main/java/com/shanebeestudios/skbee/api/wrapper/RegistryClassInfo.java b/src/main/java/com/shanebeestudios/skbee/api/registration/RegistryClassInfo.java similarity index 99% rename from src/main/java/com/shanebeestudios/skbee/api/wrapper/RegistryClassInfo.java rename to src/main/java/com/shanebeestudios/skbee/api/registration/RegistryClassInfo.java index a9141ac3f..5e8473cad 100644 --- a/src/main/java/com/shanebeestudios/skbee/api/wrapper/RegistryClassInfo.java +++ b/src/main/java/com/shanebeestudios/skbee/api/registration/RegistryClassInfo.java @@ -1,4 +1,4 @@ -package com.shanebeestudios.skbee.api.wrapper; +package com.shanebeestudios.skbee.api.registration; import ch.njol.skript.classes.ClassInfo; import ch.njol.skript.classes.Parser; diff --git a/src/main/java/com/shanebeestudios/skbee/api/util/Util.java b/src/main/java/com/shanebeestudios/skbee/api/util/Util.java index b22e2fae6..91427caa6 100644 --- a/src/main/java/com/shanebeestudios/skbee/api/util/Util.java +++ b/src/main/java/com/shanebeestudios/skbee/api/util/Util.java @@ -123,9 +123,9 @@ public static void clearDebugs() { public static NamespacedKey getNamespacedKey(@Nullable String key, boolean error) { if (key == null) return null; if (!key.contains(":")) key = "minecraft:" + key; - if (key.length() > 255) { + if (key.length() > Short.MAX_VALUE) { if (error) - skriptError("An invalid key was provided, key must be less than 256 characters: %s", key); + skriptError("An invalid key was provided, key must be less than 32767 characters: %s", key); return null; } key = key.toLowerCase(); diff --git a/src/main/java/com/shanebeestudios/skbee/api/wrapper/ComponentWrapper.java b/src/main/java/com/shanebeestudios/skbee/api/wrapper/ComponentWrapper.java index f24cb8123..a1ce32777 100644 --- a/src/main/java/com/shanebeestudios/skbee/api/wrapper/ComponentWrapper.java +++ b/src/main/java/com/shanebeestudios/skbee/api/wrapper/ComponentWrapper.java @@ -33,6 +33,7 @@ import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.block.Block; +import org.bukkit.block.BlockType; import org.bukkit.block.Sign; import org.bukkit.block.data.BlockData; import org.bukkit.block.sign.Side; @@ -659,18 +660,22 @@ public static void sendSignChange(Player player, Location location, ComponentWra } } BlockData blockData = location.getBlock().getBlockData(); - if (blockData.createBlockState() instanceof Sign sign) { - SignSide signSide = sign.getSide(side); - for (int i = 0; i < components.size(); i++) { - signSide.line(i, components.get(i)); - signSide.setGlowingText(isGlowing); - } + Sign sign; + if (blockData.createBlockState() instanceof Sign sign1) { + sign = sign1; + } else { + sign = (Sign) BlockType.OAK_SIGN.createBlockData().createBlockState(); + } + SignSide signSide = sign.getSide(side); + for (int i = 0; i < components.size(); i++) { + signSide.line(i, components.get(i)); + signSide.setGlowingText(isGlowing); + } - if (color == null) { - signSide.setColor(color); - } - player.sendBlockUpdate(location, sign); + if (color != null) { + signSide.setColor(color); } + player.sendBlockUpdate(location, sign); } diff --git a/src/main/java/com/shanebeestudios/skbee/api/wrapper/LazyLocation.java b/src/main/java/com/shanebeestudios/skbee/api/wrapper/LazyLocation.java index 161b16f8b..d72fade73 100644 --- a/src/main/java/com/shanebeestudios/skbee/api/wrapper/LazyLocation.java +++ b/src/main/java/com/shanebeestudios/skbee/api/wrapper/LazyLocation.java @@ -3,6 +3,7 @@ import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.World; +import org.bukkit.configuration.serialization.SerializableAs; import org.bukkit.util.NumberConversions; import org.jetbrains.annotations.NotNull; @@ -13,6 +14,7 @@ *
These are used in {@link com.shanebeestudios.skbee.api.bound.Bound Bounds} * when a world might not have been loaded yet */ +@SerializableAs("LazyLocation") public class LazyLocation extends Location { private String worldName; diff --git a/src/main/java/com/shanebeestudios/skbee/elements/bossbar/types/Types.java b/src/main/java/com/shanebeestudios/skbee/elements/bossbar/types/Types.java index 1bfe7f0a4..bd3a74981 100644 --- a/src/main/java/com/shanebeestudios/skbee/elements/bossbar/types/Types.java +++ b/src/main/java/com/shanebeestudios/skbee/elements/bossbar/types/Types.java @@ -9,7 +9,7 @@ import ch.njol.yggdrasil.Fields; import com.shanebeestudios.skbee.api.registration.Registration; import com.shanebeestudios.skbee.api.util.Util; -import com.shanebeestudios.skbee.api.wrapper.EnumWrapper; +import com.shanebeestudios.skbee.api.registration.EnumWrapper; import org.bukkit.Bukkit; import org.bukkit.NamespacedKey; import org.bukkit.boss.BarFlag; diff --git a/src/main/java/com/shanebeestudios/skbee/elements/dialog/sections/dialogs/SecConfirmationDialogRegister.java b/src/main/java/com/shanebeestudios/skbee/elements/dialog/sections/dialogs/SecConfirmationDialogRegister.java index 3aa566e8c..8774e954f 100644 --- a/src/main/java/com/shanebeestudios/skbee/elements/dialog/sections/dialogs/SecConfirmationDialogRegister.java +++ b/src/main/java/com/shanebeestudios/skbee/elements/dialog/sections/dialogs/SecConfirmationDialogRegister.java @@ -177,7 +177,7 @@ public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelaye }); dialogBaseBuilder.body(dialogEvent.getBodies()); dialogBaseBuilder.inputs(dialogEvent.getInputs()); - + dialogBaseBuilder.pause(false); DialogAfterAction afterAction = this.afterAction == null ? DialogAfterAction.CLOSE : switch (Objects.requireNonNull(this.afterAction.getSingle(event))) { case "none" -> DialogAfterAction.NONE; diff --git a/src/main/java/com/shanebeestudios/skbee/elements/dialog/sections/dialogs/SecDialogListDialogRegister.java b/src/main/java/com/shanebeestudios/skbee/elements/dialog/sections/dialogs/SecDialogListDialogRegister.java index 2c4f4c2f7..56bb95664 100644 --- a/src/main/java/com/shanebeestudios/skbee/elements/dialog/sections/dialogs/SecDialogListDialogRegister.java +++ b/src/main/java/com/shanebeestudios/skbee/elements/dialog/sections/dialogs/SecDialogListDialogRegister.java @@ -199,7 +199,7 @@ public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelaye }); dialogBaseBuilder.body(dialogEvent.getBodies()); dialogBaseBuilder.inputs(dialogEvent.getInputs()); - + dialogBaseBuilder.pause(false); DialogBase.DialogAfterAction afterAction = this.afterAction == null ? DialogBase.DialogAfterAction.CLOSE : switch (Objects.requireNonNull(this.afterAction.getSingle(event))) { case "none" -> DialogBase.DialogAfterAction.NONE; diff --git a/src/main/java/com/shanebeestudios/skbee/elements/dialog/sections/dialogs/SecMultiDialogRegister.java b/src/main/java/com/shanebeestudios/skbee/elements/dialog/sections/dialogs/SecMultiDialogRegister.java index 5d9a2c1a0..50b7f589c 100644 --- a/src/main/java/com/shanebeestudios/skbee/elements/dialog/sections/dialogs/SecMultiDialogRegister.java +++ b/src/main/java/com/shanebeestudios/skbee/elements/dialog/sections/dialogs/SecMultiDialogRegister.java @@ -202,6 +202,7 @@ public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelaye default -> DialogBase.DialogAfterAction.CLOSE; }; dialogBaseBuilder.afterAction(afterAction); + dialogBaseBuilder.pause(false); List actions = dialogEvent.getActions(); if (actions.isEmpty()) { diff --git a/src/main/java/com/shanebeestudios/skbee/elements/dialog/sections/dialogs/SecNoticeDialogRegister.java b/src/main/java/com/shanebeestudios/skbee/elements/dialog/sections/dialogs/SecNoticeDialogRegister.java index 04ac7c2a2..c7600fc1c 100644 --- a/src/main/java/com/shanebeestudios/skbee/elements/dialog/sections/dialogs/SecNoticeDialogRegister.java +++ b/src/main/java/com/shanebeestudios/skbee/elements/dialog/sections/dialogs/SecNoticeDialogRegister.java @@ -174,6 +174,7 @@ public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelaye }); dialogBaseBuilder.body(dialogEvent.getBodies()); dialogBaseBuilder.inputs(dialogEvent.getInputs()); + dialogBaseBuilder.pause(false); DialogBase.DialogAfterAction afterAction = this.afterAction == null ? DialogBase.DialogAfterAction.CLOSE : switch (Objects.requireNonNull(this.afterAction.getSingle(event))) { case "none" -> DialogBase.DialogAfterAction.NONE; diff --git a/src/main/java/com/shanebeestudios/skbee/elements/itemcomponent/ItemComponentElementRegistration.java b/src/main/java/com/shanebeestudios/skbee/elements/itemcomponent/ItemComponentElementRegistration.java index 433183e2e..1e6d75c7f 100644 --- a/src/main/java/com/shanebeestudios/skbee/elements/itemcomponent/ItemComponentElementRegistration.java +++ b/src/main/java/com/shanebeestudios/skbee/elements/itemcomponent/ItemComponentElementRegistration.java @@ -6,6 +6,7 @@ import com.shanebeestudios.skbee.elements.itemcomponent.effects.EffClearComponent; import com.shanebeestudios.skbee.elements.itemcomponent.expressions.ExprBundleContents; import com.shanebeestudios.skbee.elements.itemcomponent.expressions.ExprChargedProjectilesComponent; +import com.shanebeestudios.skbee.elements.itemcomponent.expressions.ExprDamageResistantComponent; import com.shanebeestudios.skbee.elements.itemcomponent.expressions.ExprDamageTypeComponent; import com.shanebeestudios.skbee.elements.itemcomponent.expressions.ExprDyedColorComponent; import com.shanebeestudios.skbee.elements.itemcomponent.expressions.ExprEnchantableComponent; @@ -33,6 +34,7 @@ import com.shanebeestudios.skbee.elements.itemcomponent.sections.SecJukeboxPlayableComponent; import com.shanebeestudios.skbee.elements.itemcomponent.sections.SecPiercingWeapon; import com.shanebeestudios.skbee.elements.itemcomponent.sections.SecPotionContentsComponent; +import com.shanebeestudios.skbee.elements.itemcomponent.sections.SecProfileComponent; import com.shanebeestudios.skbee.elements.itemcomponent.sections.SecSwingAnimationComponent; import com.shanebeestudios.skbee.elements.itemcomponent.sections.SecToolComponent; import com.shanebeestudios.skbee.elements.itemcomponent.sections.SecToolRule; @@ -54,6 +56,7 @@ public static void register(Registration reg) { // EXPRESSIONS ExprBundleContents.register(reg); ExprChargedProjectilesComponent.register(reg); + ExprDamageResistantComponent.register(reg); ExprDamageTypeComponent.register(reg); ExprDyedColorComponent.register(reg); ExprEnchantableComponent.register(reg); @@ -83,6 +86,7 @@ public static void register(Registration reg) { SecJukeboxPlayableComponent.register(reg); SecPiercingWeapon.register(reg); SecPotionContentsComponent.register(reg); + SecProfileComponent.register(reg); SecSwingAnimationComponent.register(reg); SecToolComponent.register(reg); SecToolRule.register(reg); diff --git a/src/main/java/com/shanebeestudios/skbee/elements/itemcomponent/expressions/ExprDamageResistantComponent.java b/src/main/java/com/shanebeestudios/skbee/elements/itemcomponent/expressions/ExprDamageResistantComponent.java new file mode 100644 index 000000000..d055f1a2d --- /dev/null +++ b/src/main/java/com/shanebeestudios/skbee/elements/itemcomponent/expressions/ExprDamageResistantComponent.java @@ -0,0 +1,81 @@ +package com.shanebeestudios.skbee.elements.itemcomponent.expressions; + +import ch.njol.skript.classes.Changer.ChangeMode; +import ch.njol.util.coll.CollectionUtils; +import com.shanebeestudios.skbee.api.registration.Registration; +import com.shanebeestudios.skbee.api.skript.base.SimplePropertyExpression; +import com.shanebeestudios.skbee.api.util.ItemComponentUtils; +import com.shanebeestudios.skbee.api.util.ItemUtils; +import io.papermc.paper.datacomponent.DataComponentTypes; +import io.papermc.paper.datacomponent.item.DamageResistant; +import io.papermc.paper.registry.RegistryKey; +import io.papermc.paper.registry.tag.TagKey; +import org.bukkit.event.Event; +import org.bukkit.inventory.ItemStack; +import org.jspecify.annotations.Nullable; + +@SuppressWarnings({"rawtypes", "UnstableApiUsage"}) +public class ExprDamageResistantComponent extends SimplePropertyExpression { + + public static void register(Registration reg) { + reg.newPropertyExpression(ExprDamageResistantComponent.class, TagKey.class, + "damage resistant [component]", "itemstacks/itemtypes/slots") + .name("ItemComponent - Damage Resistant") + .description("Represents the damage resistant component of an item.", + "If specified, this item is invulnerable to the specified damage types when in entity form or equipped.", + "See [**Damage Resistant**](https://minecraft.wiki/w/Data_component_format#damage_resistant) on McWiki for more details.", + "", + "**Changers**:", + "`set` = Will set the damage resistant component of the item (Accepts a DamageType TagKey).", + "`delete` = Will delete the damage resistant component of this item.", + "`reset` = Will reset the damage resistant component back to the original value.") + .examples("set {_key} to damage resistent component of player's tool", + "set damage resistent component of player's tool to tag key \"minecraft:is_fire\" from damage_type registry", + "reset damage resistent component of player's tool", + "delete damage resistent component of player's tool") + .since("INSERT VERSION") + .register(); + } + + @Override + public @Nullable TagKey convert(Object from) { + ItemStack itemStack = ItemUtils.getItemStackFromObjects(from); + if (itemStack != null && itemStack.hasData(DataComponentTypes.DAMAGE_RESISTANT)) { + DamageResistant data = itemStack.getData(DataComponentTypes.DAMAGE_RESISTANT); + if (data != null) { + return data.types(); + } + } + return null; + } + + @Override + public Class @Nullable [] acceptChange(ChangeMode mode) { + if (mode == ChangeMode.SET) return CollectionUtils.array(TagKey.class); + else if (mode == ChangeMode.DELETE || mode == ChangeMode.RESET) return CollectionUtils.array(); + return null; + } + + @SuppressWarnings("unchecked") + @Override + public void change(Event event, Object @Nullable [] delta, ChangeMode mode) { + DamageResistant damageResistant = null; + if (delta != null && delta[0] instanceof TagKey tagKey && tagKey.registryKey() == RegistryKey.DAMAGE_TYPE) { + damageResistant = DamageResistant.damageResistant(tagKey); + } + + ItemComponentUtils.modifyComponent(getExpr().getArray(event), mode, + DataComponentTypes.DAMAGE_RESISTANT, damageResistant); + } + + @Override + protected String getPropertyName() { + return "damage resistant component"; + } + + @Override + public Class getReturnType() { + return TagKey.class; + } + +} diff --git a/src/main/java/com/shanebeestudios/skbee/elements/itemcomponent/sections/SecProfileComponent.java b/src/main/java/com/shanebeestudios/skbee/elements/itemcomponent/sections/SecProfileComponent.java new file mode 100644 index 000000000..ed0beaf06 --- /dev/null +++ b/src/main/java/com/shanebeestudios/skbee/elements/itemcomponent/sections/SecProfileComponent.java @@ -0,0 +1,214 @@ +package com.shanebeestudios.skbee.elements.itemcomponent.sections; + +import ch.njol.skript.classes.Changer.ChangeMode; +import ch.njol.skript.config.SectionNode; +import ch.njol.skript.lang.Expression; +import ch.njol.skript.lang.SkriptParser.ParseResult; +import ch.njol.skript.lang.TriggerItem; +import ch.njol.util.Kleenean; +import com.destroystokyo.paper.profile.ProfileProperty; +import com.shanebeestudios.skbee.api.registration.Registration; +import com.shanebeestudios.skbee.api.skript.base.Section; +import com.shanebeestudios.skbee.api.util.ItemComponentUtils; +import com.shanebeestudios.skbee.api.util.SimpleEntryValidator; +import com.shanebeestudios.skbee.api.util.Util; +import io.papermc.paper.datacomponent.DataComponentTypes; +import io.papermc.paper.datacomponent.item.ResolvableProfile; +import io.papermc.paper.datacomponent.item.ResolvableProfile.SkinPatchBuilder; +import org.bukkit.NamespacedKey; +import org.bukkit.block.Block; +import org.bukkit.block.BlockState; +import org.bukkit.block.Skull; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Mannequin; +import org.bukkit.event.Event; +import org.bukkit.profile.PlayerTextures.SkinModel; +import org.jetbrains.annotations.Nullable; +import org.skriptlang.skript.lang.entry.EntryContainer; +import org.skriptlang.skript.lang.entry.EntryValidator; + +import java.util.List; +import java.util.UUID; + +@SuppressWarnings("UnstableApiUsage") +public class SecProfileComponent extends Section { + + private static EntryValidator VALIDATOR; + + public static void register(Registration reg) { + VALIDATOR = SimpleEntryValidator.builder() + .addOptionalEntry("name", String.class) + .addOptionalEntry("id", UUID.class) + .addOptionalEntry("texture-value", String.class) + .addOptionalEntry("texture-signature", String.class) + .addOptionalEntry("texture", String.class) + .addOptionalEntry("cape", String.class) + .addOptionalEntry("elytra", String.class) + .addOptionalEntry("model", String.class) + .build(); + + reg.newSection(SecProfileComponent.class, VALIDATOR, "apply profile [component] to %itemstacks/itemtypes/slots/blocks/entities%") + .name("ItemComponent - Profile Component Apply") + .description("Apply a profile component to an item/entity/block.", + "This is generally used for player heads and mannequins.", + "See [**Profile Component**](https://minecraft.wiki/w/Data_component_format#profile) on McWiki for more details.", + "", + "**Entries**:", + " - `name` = A username with a maximum length of 16, and only consisting of username-allowed characters [optional].", + " - `id` = A UUID. If no other profile fields are specified, this is used to dynamically request the profile of a player " + + "with that UUID from Mojang's servers. Once received, that profile's properties (such as its skin, cape, and elytra textures) " + + "can be used for rendering. If the profile does not exist, a random default skin is provided [optional].", + " - `texture-value` = A base64 encoded string representing the texture data for the profile. [optional].", + " - `texture-signature` = A base64 encoded string representing the signature of the texture data. [optional].", + " - `model` = The model of the skin, either `classic` or `slim`. Defaults to `classic` if not specified. [optional].", + " - `texture` = Namespaced path to a player skin texture, relative to the `textures` folder in a resource pack [optional].", + " - `cape` = Namespaced path to a cape texture, relative to the `textures` folder in a resource pack. [optional].", + " - `elytra` = Namespaced path to an elytra texture, relative to the `textures` folder in a resource pack. [optional].") + .examples("# Hamburger Head", + "set {_i} to 1 of player head", + "apply profile to {_i}:", + "\ttexture-value: \"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYmJlNjAyN2NhM2MwZTE3MDJlOGU0ODE4ZjlkYjk0NDc1NTU4MDVjZDE1NjFlYTUyZWNhODRjOTkyNDk1NTRlMyJ9fX0=\"", + "give {_i} to player", + "", + "# Yours Truly's Head", + "set {_i} to 1 of player head", + "apply profile to {_i}:", + "\tname: \"ShaneBee\"", + "give {_i} to player", + "", + "# Batman", + "spawn a mannequin above target block of player:", + "\tapply profile to entity:", + "\t\tname: \"Batman\"") + .since("INSERT VERSION") + .register(); + } + + private Expression items; + private Expression name; + private Expression id; + private Expression textureValue; + private Expression textureSignature; + private Expression texture; + private Expression cape; + private Expression elytra; + private Expression model; + + @SuppressWarnings("unchecked") + @Override + public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, + ParseResult parseResult, SectionNode sectionNode, List triggerItems) { + EntryContainer container = VALIDATOR.validate(sectionNode); + if (container == null) return false; + + this.items = (Expression) exprs[0]; + this.name = (Expression) container.getOptional("name", false); + this.id = (Expression) container.getOptional("id", false); + this.textureValue = (Expression) container.getOptional("texture-value", false); + this.textureSignature = (Expression) container.getOptional("texture-signature", false); + this.texture = (Expression) container.getOptional("texture", false); + this.cape = (Expression) container.getOptional("cape", false); + this.elytra = (Expression) container.getOptional("elytra", false); + this.model = (Expression) container.getOptional("model", false); + return true; + } + + @SuppressWarnings("PatternValidation") + @Override + protected @Nullable TriggerItem walk(Event event) { + ResolvableProfile.Builder builder = ResolvableProfile.resolvableProfile(); + + if (this.name != null) { + String name = this.name.getSingle(event); + if (name != null) builder.name(name); + } + + if (this.id != null) { + UUID id = this.id.getSingle(event); + if (id != null) builder.uuid(id); + } + + if (this.textureValue != null) { + String value = this.textureValue.getSingle(event); + String signature = null; + if (this.textureSignature != null) { + signature = this.textureSignature.getSingle(event); + } + if (value != null) { + ProfileProperty textures = new ProfileProperty("textures", value, signature); + builder.addProperty(textures); + } + } + + builder.skinPatch(skin(event).build()); + ResolvableProfile profile = builder.build(); + + for (Object object : this.items.getArray(event)) { + if (object instanceof Entity entity) { + if (entity instanceof Mannequin mannequin) { + mannequin.setProfile(profile); + } + } else if (object instanceof Block block) { + BlockState state = block.getState(); + if (state instanceof Skull skull) { + skull.setProfile(profile); + skull.update(); + } + } else { + ItemComponentUtils.modifyComponent(new Object[]{object}, ChangeMode.SET, + DataComponentTypes.PROFILE, profile); + } + } + + return super.walk(event, false); + } + + private SkinPatchBuilder skin(Event event) { + SkinPatchBuilder builder = ResolvableProfile.SkinPatch.skinPatch(); + if (this.texture != null) { + String single = this.texture.getSingle(event); + if (single != null) { + NamespacedKey namespacedKey = Util.getNamespacedKey(single, false); + if (namespacedKey != null) { + builder.body(namespacedKey.key()); + } + } + } + + if (this.cape != null) { + String single = this.cape.getSingle(event); + if (single != null) { + NamespacedKey namespacedKey = Util.getNamespacedKey(single, false); + if (namespacedKey != null) { + builder.cape(namespacedKey.key()); + } + } + } + + if (this.elytra != null) { + String single = this.elytra.getSingle(event); + if (single != null) { + NamespacedKey namespacedKey = Util.getNamespacedKey(single, false); + if (namespacedKey != null) { + builder.elytra(namespacedKey.key()); + } + } + } + + if (this.model != null) { + String single = this.model.getSingle(event); + if (single != null) { + SkinModel m = single.equalsIgnoreCase("slim") ? SkinModel.SLIM : SkinModel.CLASSIC; + builder.model(m); + } + } + + return builder; + } + + @Override + public String toString(@Nullable Event event, boolean debug) { + return "apply profile component to " + this.items.toString(event, debug); + } + +} diff --git a/src/main/java/com/shanebeestudios/skbee/elements/other/OtherElementRegistration.java b/src/main/java/com/shanebeestudios/skbee/elements/other/OtherElementRegistration.java index 3b3f79bfe..75485d6a9 100644 --- a/src/main/java/com/shanebeestudios/skbee/elements/other/OtherElementRegistration.java +++ b/src/main/java/com/shanebeestudios/skbee/elements/other/OtherElementRegistration.java @@ -95,6 +95,8 @@ import com.shanebeestudios.skbee.elements.other.expressions.ExprEntityOrigin; import com.shanebeestudios.skbee.elements.other.expressions.ExprEntityPose; import com.shanebeestudios.skbee.elements.other.expressions.ExprEntityVisibility; +import com.shanebeestudios.skbee.elements.other.expressions.ExprEntityWaypointColor; +import com.shanebeestudios.skbee.elements.other.expressions.ExprEntityWaypointStyle; import com.shanebeestudios.skbee.elements.other.expressions.ExprExactBlockLocation; import com.shanebeestudios.skbee.elements.other.expressions.ExprGameTick; import com.shanebeestudios.skbee.elements.other.expressions.ExprGiveOrReturn; @@ -254,6 +256,8 @@ public static void register(Registration registration) { ExprEntityOrigin.register(registration); ExprEntityPose.register(registration); ExprEntityVisibility.register(registration); + ExprEntityWaypointColor.register(registration); + ExprEntityWaypointStyle.register(registration); ExprExactBlockLocation.register(registration); ExprGameTick.register(registration); ExprGiveOrReturn.register(registration); diff --git a/src/main/java/com/shanebeestudios/skbee/elements/other/events/EvtPreSpawn.java b/src/main/java/com/shanebeestudios/skbee/elements/other/events/EvtPreSpawn.java index 890581127..584f3b55f 100644 --- a/src/main/java/com/shanebeestudios/skbee/elements/other/events/EvtPreSpawn.java +++ b/src/main/java/com/shanebeestudios/skbee/elements/other/events/EvtPreSpawn.java @@ -68,7 +68,7 @@ public static void register(Registration reg) { .since("2.16.0") .register(); - EventValues.registerEventValue(PhantomPreSpawnEvent.class, Entity.class, event -> event.getSpawningEntity(), EventValues.TIME_NOW); + EventValues.registerEventValue(PhantomPreSpawnEvent.class, Entity.class, PhantomPreSpawnEvent::getSpawningEntity, EventValues.TIME_NOW); } @@ -77,7 +77,9 @@ public static void register(Registration reg) { @SuppressWarnings({"unchecked"}) @Override public boolean init(Literal[] literals, int matchedPattern, ParseResult parseResult) { - this.spawnedEntities = (Literal>) literals[0]; + if (literals.length > 0) { + this.spawnedEntities = (Literal>) literals[0]; + } return true; } diff --git a/src/main/java/com/shanebeestudios/skbee/elements/other/events/EvtSpawnerSpawn.java b/src/main/java/com/shanebeestudios/skbee/elements/other/events/EvtSpawnerSpawn.java index 5cbf02ff6..05ebc5c68 100644 --- a/src/main/java/com/shanebeestudios/skbee/elements/other/events/EvtSpawnerSpawn.java +++ b/src/main/java/com/shanebeestudios/skbee/elements/other/events/EvtSpawnerSpawn.java @@ -23,7 +23,8 @@ public static void register(Registration reg) { .description("Called whenever an entity is spawned via a spawner.") .examples("on spawner spawn of zombie:", "\treset spawner timer of event-block") - .since("2.16.0"); + .since("2.16.0") + .register(); EventValues.registerEventValue(SpawnerSpawnEvent.class, Block.class, event -> { CreatureSpawner spawner = event.getSpawner(); diff --git a/src/main/java/com/shanebeestudios/skbee/elements/other/events/OtherEvents.java b/src/main/java/com/shanebeestudios/skbee/elements/other/events/OtherEvents.java index f75b535d8..fe53ef49f 100644 --- a/src/main/java/com/shanebeestudios/skbee/elements/other/events/OtherEvents.java +++ b/src/main/java/com/shanebeestudios/skbee/elements/other/events/OtherEvents.java @@ -80,7 +80,8 @@ public static void register(Registration reg) { "\t\t\t\tenchant {_i} with sharpness 6", "\t\t\t\tset event-slot to {_i}", "\t\t\t\tset repair cost of event-inventory to 30") - .since("1.11.0"); + .since("1.11.0") + .register(); EventValues.registerEventValue(PrepareAnvilEvent.class, Slot.class, event -> new Slot() { final ItemStack result = event.getResult(); diff --git a/src/main/java/com/shanebeestudios/skbee/elements/other/events/TabEvent.java b/src/main/java/com/shanebeestudios/skbee/elements/other/events/TabEvent.java index f1570d014..47fd70316 100644 --- a/src/main/java/com/shanebeestudios/skbee/elements/other/events/TabEvent.java +++ b/src/main/java/com/shanebeestudios/skbee/elements/other/events/TabEvent.java @@ -33,6 +33,7 @@ public static void register(Registration reg) { "\t\tclear tab completions") .since("1.7.0") .register(); + EventValues.registerEventValue(TabCompleteEvent.class, Player.class, event -> { CommandSender sender = event.getSender(); if (sender instanceof Player) { diff --git a/src/main/java/com/shanebeestudios/skbee/elements/other/expressions/ExprEntityWaypointColor.java b/src/main/java/com/shanebeestudios/skbee/elements/other/expressions/ExprEntityWaypointColor.java new file mode 100644 index 000000000..6ed59eb46 --- /dev/null +++ b/src/main/java/com/shanebeestudios/skbee/elements/other/expressions/ExprEntityWaypointColor.java @@ -0,0 +1,66 @@ +package com.shanebeestudios.skbee.elements.other.expressions; + +import ch.njol.skript.classes.Changer.ChangeMode; +import ch.njol.skript.util.Color; +import ch.njol.skript.util.ColorRGB; +import ch.njol.skript.util.SkriptColor; +import ch.njol.util.coll.CollectionUtils; +import com.shanebeestudios.skbee.api.registration.Registration; +import com.shanebeestudios.skbee.api.skript.base.SimplePropertyExpression; +import org.bukkit.entity.LivingEntity; +import org.bukkit.event.Event; +import org.jetbrains.annotations.Nullable; + +public class ExprEntityWaypointColor extends SimplePropertyExpression { + + public static void register(Registration reg) { + reg.newPropertyExpression(ExprEntityWaypointColor.class, Color.class, + "waypoint color", "livingentities") + .name("Entity Waypoint Color") + .description("Get/set/delete the waypoint color of an entity.") + .examples("set {_color} to waypoint color of player", + "set waypoint color of all players to red", + "set waypoint color of player to rgb(10, 200, 150)", + "reset waypoint color of target entity") + .since("INSERT VERSION") + .register(); + } + + @Override + public @Nullable Color convert(LivingEntity from) { + SkriptColor skriptColor = SkriptColor.fromBukkitColor(from.getWaypointColor()); + if (skriptColor != null) return skriptColor; + return ColorRGB.fromBukkitColor(from.getWaypointColor()); + } + + @Override + public Class @Nullable [] acceptChange(ChangeMode mode) { + if (mode == ChangeMode.SET || mode == ChangeMode.DELETE || mode == ChangeMode.RESET) { + return CollectionUtils.array(Color.class); + } + return null; + } + + @Override + public void change(Event event, Object @Nullable [] delta, ChangeMode mode) { + org.bukkit.Color color = null; + if (delta != null && delta.length > 0 && delta[0] instanceof Color skriptcolor) { + color = skriptcolor.asBukkitColor(); + } + + for (LivingEntity entity : getExpr().getArray(event)) { + entity.setWaypointColor(color); + } + } + + @Override + protected String getPropertyName() { + return "waypoint color"; + } + + @Override + public Class getReturnType() { + return Color.class; + } + +} diff --git a/src/main/java/com/shanebeestudios/skbee/elements/other/expressions/ExprEntityWaypointStyle.java b/src/main/java/com/shanebeestudios/skbee/elements/other/expressions/ExprEntityWaypointStyle.java new file mode 100644 index 000000000..dd9032e23 --- /dev/null +++ b/src/main/java/com/shanebeestudios/skbee/elements/other/expressions/ExprEntityWaypointStyle.java @@ -0,0 +1,68 @@ +package com.shanebeestudios.skbee.elements.other.expressions; + +import ch.njol.skript.classes.Changer.ChangeMode; +import ch.njol.util.coll.CollectionUtils; +import com.shanebeestudios.skbee.api.registration.Registration; +import com.shanebeestudios.skbee.api.skript.base.SimplePropertyExpression; +import com.shanebeestudios.skbee.api.util.Util; +import org.bukkit.NamespacedKey; +import org.bukkit.entity.LivingEntity; +import org.bukkit.event.Event; +import org.jetbrains.annotations.Nullable; + +public class ExprEntityWaypointStyle extends SimplePropertyExpression { + + public static void register(Registration reg) { + reg.newPropertyExpression(ExprEntityWaypointStyle.class, NamespacedKey.class, + "waypoint style", "livingentities") + .name("Entity Waypoint Style") + .description("Get/set/delete the waypoint style of an entity.", + "Can be set to a NamespacedKey or a string.", + "See [**Waypoint Style**](https://minecraft.wiki/w/Waypoint_style) on McWiki for more info.") + .examples("set {_key} to waypoint style of player", + "set waypoint style of target entity to \"minecraft:bowtie\"", + "reset waypoint style of all players") + .since("INSERT VERSION") + .register(); + } + + @Override + public @Nullable NamespacedKey convert(LivingEntity from) { + return NamespacedKey.fromString(from.getWaypointStyle().asString()); + } + + @Override + public Class @Nullable [] acceptChange(ChangeMode mode) { + if (mode == ChangeMode.SET || mode == ChangeMode.DELETE || mode == ChangeMode.RESET) { + return CollectionUtils.array(NamespacedKey.class, String.class); + } + return null; + } + + @Override + public void change(Event event, Object @Nullable [] delta, ChangeMode mode) { + NamespacedKey key = null; + if (delta != null && delta.length > 0) { + if (delta[0] instanceof NamespacedKey nsk) { + key = nsk; + } else if (delta[0] instanceof String str) { + key = Util.getNamespacedKey(str, false); + } + } + + for (LivingEntity entity : getExpr().getArray(event)) { + entity.setWaypointStyle(key); + } + } + + @Override + protected String getPropertyName() { + return "waypoint style"; + } + + @Override + public Class getReturnType() { + return NamespacedKey.class; + } + +} diff --git a/src/main/java/com/shanebeestudios/skbee/elements/other/sections/SecAttributeModifier.java b/src/main/java/com/shanebeestudios/skbee/elements/other/sections/SecAttributeModifier.java index 67213a4e4..97c4e1ced 100644 --- a/src/main/java/com/shanebeestudios/skbee/elements/other/sections/SecAttributeModifier.java +++ b/src/main/java/com/shanebeestudios/skbee/elements/other/sections/SecAttributeModifier.java @@ -138,7 +138,7 @@ public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelaye return this.attribute != null && this.amount != null; } - @SuppressWarnings("removal") + @SuppressWarnings({"removal", "DataFlowIssue"}) @Override protected @Nullable TriggerItem walk(Event event) { Attribute attribute = this.attribute.getSingle(event); @@ -200,20 +200,29 @@ public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelaye if (object instanceof ItemType itemType) { ItemMeta itemMeta = itemType.getItemMeta(); - if (!ItemUtils.hasAttributeModifier(itemMeta, attribute, attributeModifier)) { - itemMeta.addAttributeModifier(attribute, attributeModifier); + if (ItemUtils.hasAttributeModifier(itemMeta, attribute, attributeModifier)) { + // Remove the old modifier so we can override + for (AttributeModifier modifier : itemMeta.getAttributeModifiers(attribute)) { + if (modifier.getKey().equals(attributeModifier.getKey())) { + itemMeta.removeAttributeModifier(attribute, modifier); + } + } } + itemMeta.addAttributeModifier(attribute, attributeModifier); itemType.setItemMeta(itemMeta); } else if (object instanceof LivingEntity entity) { AttributeInstance attributeInstance = entity.getAttribute(attribute); if (attributeInstance == null) continue; - if (!EntityUtils.hasAttributeModifier(entity, attribute, attributeModifier)) { - if (this.trans) { - attributeInstance.addTransientModifier(attributeModifier); - } else { - attributeInstance.addModifier(attributeModifier); - } + + if (EntityUtils.hasAttributeModifier(entity, attribute, attributeModifier)) { + attributeInstance.removeModifier(attributeModifier.key()); + } + + if (this.trans) { + attributeInstance.addTransientModifier(attributeModifier); + } else { + attributeInstance.addModifier(attributeModifier); } } } diff --git a/src/main/java/com/shanebeestudios/skbee/elements/other/type/Types.java b/src/main/java/com/shanebeestudios/skbee/elements/other/type/Types.java index aebdd3ec4..cf60ce4d1 100644 --- a/src/main/java/com/shanebeestudios/skbee/elements/other/type/Types.java +++ b/src/main/java/com/shanebeestudios/skbee/elements/other/type/Types.java @@ -16,7 +16,7 @@ import com.shanebeestudios.skbee.api.util.MathUtil; import com.shanebeestudios.skbee.api.util.SkriptUtils; import com.shanebeestudios.skbee.api.util.Util; -import com.shanebeestudios.skbee.api.wrapper.RegistryClassInfo; +import com.shanebeestudios.skbee.api.registration.RegistryClassInfo; import io.papermc.paper.connection.PlayerConnection; import io.papermc.paper.event.entity.EntityKnockbackEvent; import io.papermc.paper.event.player.PlayerFailMoveEvent;