diff --git a/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/world/PlayEffectCommand.java b/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/world/PlayEffectCommand.java index 2da37c6516..5c0a842e80 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/world/PlayEffectCommand.java +++ b/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/world/PlayEffectCommand.java @@ -10,17 +10,12 @@ import com.denizenscript.denizencore.exceptions.InvalidArgumentsException; import com.denizenscript.denizencore.objects.Argument; import com.denizenscript.denizencore.objects.ObjectTag; -import com.denizenscript.denizencore.objects.core.ColorTag; -import com.denizenscript.denizencore.objects.core.DurationTag; -import com.denizenscript.denizencore.objects.core.ElementTag; -import com.denizenscript.denizencore.objects.core.ListTag; +import com.denizenscript.denizencore.objects.core.*; import com.denizenscript.denizencore.scripts.ScriptEntry; import com.denizenscript.denizencore.scripts.commands.AbstractCommand; import com.denizenscript.denizencore.utilities.CoreUtilities; import com.denizenscript.denizencore.utilities.debugging.Debug; -import org.bukkit.Effect; -import org.bukkit.Particle; -import org.bukkit.Vibration; +import org.bukkit.*; import org.bukkit.block.data.BlockData; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; @@ -40,7 +35,7 @@ public class PlayEffectCommand extends AbstractCommand { public PlayEffectCommand() { setName("playeffect"); - setSyntax("playeffect [effect:] [at:|...] (data:<#.#>) (special_data:) (visibility:<#.#>) (quantity:<#>) (offset:<#.#>,<#.#>,<#.#>) (targets:|...) (velocity:)"); + setSyntax("playeffect [effect:] [at:|...] (data:<#.#>) (special_data:) (visibility:<#.#>) (quantity:<#>) (offset:<#.#>,<#.#>,<#.#>) (targets:|...) (velocity:)"); setRequiredArguments(2, 8); isProcedural = false; } @@ -59,7 +54,7 @@ public PlayEffectCommand() { // <--[command] // @Name PlayEffect - // @Syntax playeffect [effect:] [at:|...] (data:<#.#>) (special_data:) (visibility:<#.#>) (quantity:<#>) (offset:<#.#>,<#.#>,<#.#>) (targets:|...) (velocity:) + // @Syntax playeffect [effect:] [at:|...] (data:<#.#>) (special_data:) (visibility:<#.#>) (quantity:<#>) (offset:<#.#>,<#.#>,<#.#>) (targets:|...) (velocity:) // @Required 2 // @Maximum 8 // @Short Plays a visible or audible effect at the location. @@ -80,12 +75,16 @@ public PlayEffectCommand() { // The distinction is in whether you include the (now expected to use) "at:" prefix on your location argument. // If you do not have this prefix, the system will assume your command is older, and will apply the 1-block height offset. // - // Some particles will require input to the "special_data" argument. The data input is unique per particle. - // - For REDSTONE particles, the input is of format: |, for example: "1.2|red". Color input is any valid ColorTag object. - // - For DUST_COLOR_TRANSITION particles, the input is of format ||, for example "1.2|red|blue". Color input is any valid ColorTag object. - // - For BLOCK_MARKER, FALLING_DUST, BLOCK_CRACK, or BLOCK_DUST particles, the input is any valid MaterialTag, eg "stone". - // - For VIBRATION, the input is || where origin is a LocationTag and destination is either LocationTag or EntityTag, for example "5s||" - // - For ITEM_CRACK particles, the input is any valid ItemTag, eg "stick". + // Some particles will require input to the "special_data" argument. The data input is a MapTag with different keys per particle. + // - For DUST particles, the input is of format [size=;color=], e.g. "[size=1.2;color=red]". + // - For DUST_COLOR_TRANSITION particles, the input is of format [size=;from=;to=], e.g "[size=1.2;from=red;to=blue]". + // - For BLOCK, BLOCK_CRUMBLE, BLOCK_MARKER, DUST_PILLAR, or FALLING_DUST particles, the input is of format [material=], e.g. [material=stone] + // - For VIBRATION particles, the input is of format [origin=;destination=;duration=], for example: [origin=;destination=;duration=5s] + // - For ITEM particles, the input is of format [item=], e.g. "[item=stick]". + // - For TRAIL particles, the input is of format [color=;target=;duration=], e.g. "[color=red;target=;duration=20s]". + // - For ENTITY_EFFECT particles, the input is of format [color=], e.g. "[color=green]". + // - For SHRIEK particles, the input is of format [duration=], e.g. "[duration=1m]". + // - For SCULK_CHARGE particles, the input is of format [radians=], e.g. "[radians=]". // // Optionally specify a velocity vector for standard particles to move. Note that this ignores the 'data' input if used. // @@ -104,6 +103,26 @@ public PlayEffectCommand() { // @Usage // Use to play some effects at spawn. // - playeffect effect:FIREWORKS_SPARK at: visibility:100 quantity:375 data:0 offset:50.0 + // + // @Usage + // Use to spawn a cloud of rainbow-colored ENTITY_EFFECT particles around yourself. + // - foreach as:color: + // - playeffect effect:ENTITY_EFFECT at: quantity:25 special_data:[color=<[color]>] + // + // @Usage + // Use to shoot particles in to the direction you're looking at. + // - repeat 10: + // - playeffect effect:TRAIL at: quantity:1 offset:0 special_data:[color=red;target=;duration=5s] + // - wait 1t + // + // @Usage + // Use to spawn a SCULK_CHARGE effect upside down. + // - playeffect effect:SCULK_CHARGE at: quantity:1 offset:0 special_data:[radians=] + // + // @Usage + // Use to play a SHRIEK effect with a 5-second delay. + // - playeffect effect:SHRIEK at: quantity:1 special_data:[duration=5s] + // // --> @Override @@ -292,62 +311,178 @@ else if (particleEffect != null) { Debug.echoError("Missing required special data for particle: " + particleEffect.name()); return; } - else if (clazz == Particle.DustOptions.class) { + MapTag dataMap = MapTag.valueOf(special_data.asString(), scriptEntry.getContext()); + if (dataMap == null) { ListTag dataList = ListTag.valueOf(special_data.asString(), scriptEntry.getContext()); - if (dataList.size() != 2) { - Debug.echoError("DustOptions special_data must have 2 list entries for particle: " + particleEffect.name()); - return; - } - else { + BukkitImplDeprecations.playEffectSpecialDataListInput.warn(scriptEntry.getContext()); + if (clazz == Particle.DustOptions.class) { + if (dataList.size() != 2) { + Debug.echoError("DustOptions special_data must have 2 list entries for particle: " + particleEffect.name()); + return; + } float size = Float.parseFloat(dataList.get(0)); ColorTag color = ColorTag.valueOf(dataList.get(1), scriptEntry.context); dataObject = new Particle.DustOptions(BukkitColorExtensions.getColor(color), size); } - } - else if (clazz == BlockData.class) { - MaterialTag blockMaterial = MaterialTag.valueOf(special_data.asString(), scriptEntry.getContext()); - dataObject = blockMaterial.getModernData(); - } - else if (clazz == ItemStack.class) { - ItemTag itemType = ItemTag.valueOf(special_data.asString(), scriptEntry.getContext()); - dataObject = itemType.getItemStack(); - } - else if (clazz == Particle.DustTransition.class) { - ListTag dataList = ListTag.valueOf(special_data.asString(), scriptEntry.getContext()); - if (dataList.size() != 3) { - Debug.echoError("DustTransition special_data must have 3 list entries for particle: " + particleEffect.name()); - return; + else if (clazz == BlockData.class) { + MaterialTag blockMaterial = MaterialTag.valueOf(special_data.asString(), scriptEntry.getContext()); + dataObject = blockMaterial.getModernData(); + } + else if (clazz == ItemStack.class) { + ItemTag itemType = ItemTag.valueOf(special_data.asString(), scriptEntry.getContext()); + dataObject = itemType.getItemStack(); + } + else if (clazz == Particle.DustTransition.class) { + if (dataList.size() != 3) { + Debug.echoError("DustTransition special_data must have 3 list entries for particle: " + particleEffect.name()); + return; + } + else { + float size = Float.parseFloat(dataList.get(0)); + ColorTag fromColor = ColorTag.valueOf(dataList.get(1), scriptEntry.context); + ColorTag toColor = ColorTag.valueOf(dataList.get(2), scriptEntry.context); + dataObject = new Particle.DustTransition(BukkitColorExtensions.getColor(fromColor), BukkitColorExtensions.getColor(toColor), size); + } + } + else if (clazz == Vibration.class) { + if (dataList.size() != 3) { + Debug.echoError("Vibration special_data must have 3 list entries for particle: " + particleEffect.name()); + return; + } + else { + DurationTag duration = dataList.getObject(0).asType(DurationTag.class, scriptEntry.context); + LocationTag origin = dataList.getObject(1).asType(LocationTag.class, scriptEntry.context); + ObjectTag destination = dataList.getObject(2); + Vibration.Destination destObj; + if (destination.shouldBeType(EntityTag.class)) { + destObj = new Vibration.Destination.EntityDestination(destination.asType(EntityTag.class, scriptEntry.context).getBukkitEntity()); + } + else { + destObj = new Vibration.Destination.BlockDestination(destination.asType(LocationTag.class, scriptEntry.context)); + } + dataObject = new Vibration(origin, destObj, duration.getTicksAsInt()); + } } else { - float size = Float.parseFloat(dataList.get(0)); - ColorTag fromColor = ColorTag.valueOf(dataList.get(1), scriptEntry.context); - ColorTag toColor = ColorTag.valueOf(dataList.get(2), scriptEntry.context); - dataObject = new Particle.DustTransition(BukkitColorExtensions.getColor(fromColor), BukkitColorExtensions.getColor(toColor), size); + Debug.echoError("Unknown particle data type: " + clazz.getCanonicalName() + " for particle: " + particleEffect.name() + ". Are you sure it exists and are not using a legacy format?"); + return; } } - else if (clazz == Vibration.class) { - ListTag dataList = ListTag.valueOf(special_data.asString(), scriptEntry.getContext()); - if (dataList.size() != 3) { - Debug.echoError("Vibration special_data must have 3 list entries for particle: " + particleEffect.name()); - return; + else { + if (clazz == Particle.DustOptions.class) { + ElementTag size = dataMap.getObjectAs("size", ElementTag.class, scriptEntry.context); + if (size == null || !size.isFloat()) { + Debug.echoError("special_data input must have a 'size' key with a valid number, for particle " + particleEffect.name()); + return; + } + ColorTag color = dataMap.getObjectAs("color", ColorTag.class, scriptEntry.context); + if (color == null) { + Debug.echoError("special_data input must have a 'color' key with a valid ColorTag, for particle: " + particleEffect.name()); + return; + } + dataObject = new Particle.DustOptions(BukkitColorExtensions.getColor(color), size.asFloat()); } - else { - DurationTag duration = dataList.getObject(0).asType(DurationTag.class, scriptEntry.context); - LocationTag origin = dataList.getObject(1).asType(LocationTag.class, scriptEntry.context); - ObjectTag destination = dataList.getObject(2); + else if (clazz == BlockData.class) { + MaterialTag blockMaterial = dataMap.getObjectAs("material", MaterialTag.class, scriptEntry.context); + if (blockMaterial == null) { + Debug.echoError("special_data input must have a 'material' key with a valid MaterialTag, for particle: " + particleEffect.name()); + return; + } + dataObject = blockMaterial.getModernData(); + } + else if (clazz == ItemStack.class) { + ItemTag itemType = dataMap.getObjectAs("item", ItemTag.class, scriptEntry.context); + if (itemType == null) { + Debug.echoError("special_data input must have a 'item' key with a valid ItemTag, for particle: " + particleEffect.name()); + return; + } + dataObject = itemType.getItemStack(); + } + else if (clazz == Particle.DustTransition.class) { + ElementTag size = dataMap.getObjectAs("size", ElementTag.class, scriptEntry.context); + if (size == null || !size.isFloat()) { + Debug.echoError("special_data input must have a 'size' key with a valid number, for particle: " + particleEffect.name()); + return; + } + ColorTag fromColor = dataMap.getObjectAs("from", ColorTag.class, scriptEntry.context); + ColorTag toColor = dataMap.getObjectAs("to", ColorTag.class, scriptEntry.context); + if (fromColor == null || toColor == null) { + Debug.echoError("special_data input must have a 'to' and 'size' key with a valid ColorTag, for particle: " + particleEffect.name()); + return; + } + dataObject = new Particle.DustTransition(BukkitColorExtensions.getColor(fromColor), BukkitColorExtensions.getColor(toColor), size.asFloat()); + } + else if (clazz == Vibration.class) { + DurationTag duration = dataMap.getObjectAs("duration", DurationTag.class, scriptEntry.context); + if (duration == null) { + Debug.echoError("special_data input must have a 'duration' key with a valid LocationTag, for particle: " + particleEffect.name()); + return; + } + LocationTag origin = dataMap.getObjectAs("origin", LocationTag.class, scriptEntry.context); + if (origin == null) { + Debug.echoError("special_data input must have a 'origin' key with a valid LocationTag, for particle: " + particleEffect.name()); + return; + } + ObjectTag destination = dataMap.getObjectAs("destination", ObjectTag.class, scriptEntry.context); Vibration.Destination destObj; if (destination.shouldBeType(EntityTag.class)) { destObj = new Vibration.Destination.EntityDestination(destination.asType(EntityTag.class, scriptEntry.context).getBukkitEntity()); } - else { + else if (destination.shouldBeType(LocationTag.class)){ destObj = new Vibration.Destination.BlockDestination(destination.asType(LocationTag.class, scriptEntry.context)); } + else { + Debug.echoError("special_data input must have a 'destination' key with a valid LocationTag or EntityTag, for particle: " + particleEffect.name()); + return; + } dataObject = new Vibration(origin, destObj, duration.getTicksAsInt()); } - } - else { - Debug.echoError("Unknown particle data type: " + clazz.getCanonicalName() + " for particle: " + particleEffect.name()); - return; + else if (clazz == Particle.Trail.class) { + ColorTag color = dataMap.getObjectAs("color", ColorTag.class, scriptEntry.context); + if (color == null) { + Debug.echoError("special_data input must have a 'color' key with a valid ColorTag, for particle: " + particleEffect.name()); + return; + } + LocationTag target = dataMap.getObjectAs("target", LocationTag.class, scriptEntry.context); + if (target == null) { + Debug.echoError("special_data input must have a 'target' key with a valid LocationTag, for particle: " + particleEffect.name()); + return; + } + DurationTag duration = dataMap.getObjectAs("duration", DurationTag.class, scriptEntry.context); + if (duration == null) { + Debug.echoError("special_data input must have a 'duration' key with a valid DurationTag, for particle: " + particleEffect.name()); + return; + } + dataObject = new Particle.Trail(target, BukkitColorExtensions.getColor(color), duration.getTicksAsInt()); + } + else if (clazz == Color.class) { + ColorTag color = dataMap.getObjectAs("color", ColorTag.class, scriptEntry.context); + if (!dataMap.getObject("color").canBeType(ColorTag.class)) { + Debug.echoError("special_data input must have a 'color' key with a valid ColorTag, for particle: " + particleEffect.name()); + return; + } + dataObject = BukkitColorExtensions.getColor(color); + } + else if (clazz == Integer.class) { + DurationTag duration = dataMap.getObjectAs("duration", DurationTag.class, scriptEntry.context); + if (duration == null) { + Debug.echoError("special_data input must have a 'duration' key with a valid DurationTag, for particle: " + particleEffect.name()); + return; + } + dataObject = duration.getTicksAsInt(); + } + else if (clazz == Float.class) { + ElementTag radians = dataMap.getObjectAs("radians", ElementTag.class, scriptEntry.context); + if (radians == null || !radians.isFloat()) { + Debug.echoError("special_data input must have a 'radians' key with a valid number, for particle: " + particleEffect.name()); + return; + } + dataObject = radians.asFloat(); + } + else { + Debug.echoError("Unknown particle data type: " + clazz.getCanonicalName() + " for particle: " + particleEffect.name()); + return; + } } } else if (special_data != null) { diff --git a/plugin/src/main/java/com/denizenscript/denizen/utilities/BukkitImplDeprecations.java b/plugin/src/main/java/com/denizenscript/denizen/utilities/BukkitImplDeprecations.java index 235cc0d677..d7e3d01336 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/utilities/BukkitImplDeprecations.java +++ b/plugin/src/main/java/com/denizenscript/denizen/utilities/BukkitImplDeprecations.java @@ -446,6 +446,9 @@ public class BukkitImplDeprecations { // Added 2025/01/12 public static Warning arrowBasePotionType = new FutureWarning("arrowBasePotionType", "Using 'EntityTag.potion' to get an arrow's base potion type is deprecated in favor of 'EntityTag.potion_type'."); + // Added 2025/01/04 + public static Warning playEffectSpecialDataListInput = new FutureWarning("playEffectSpecialDataListInput", "List input for the special_data argument in playeffect command is now deprecated. Please use a MapTag instead."); + // ==================== PAST deprecations of things that are already gone but still have a warning left behind ==================== // Removed upstream 2023/10/29 without warning.