Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
123 additions
and
122 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
4 changes: 4 additions & 0 deletions
4
src/main/java/com/denizenscript/depenizen/bukkit/bridges/EffectLibBridge.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,16 +1,20 @@ | ||
package com.denizenscript.depenizen.bukkit.bridges; | ||
|
||
import com.denizenscript.denizencore.DenizenCore; | ||
import com.denizenscript.depenizen.bukkit.Depenizen; | ||
import com.denizenscript.depenizen.bukkit.commands.effectlib.EffectLibCommand; | ||
import com.denizenscript.depenizen.bukkit.Bridge; | ||
import de.slikey.effectlib.EffectManager; | ||
|
||
public class EffectLibBridge extends Bridge { | ||
|
||
public static EffectLibBridge instance; | ||
public EffectManager effectManager; | ||
|
||
@Override | ||
public void init() { | ||
instance = this; | ||
effectManager = new EffectManager(Depenizen.instance); | ||
DenizenCore.commandRegistry.registerCommand(EffectLibCommand.class); | ||
} | ||
} |
237 changes: 117 additions & 120 deletions
237
src/main/java/com/denizenscript/depenizen/bukkit/commands/effectlib/EffectLibCommand.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,170 +1,167 @@ | ||
package com.denizenscript.depenizen.bukkit.commands.effectlib; | ||
|
||
import com.denizenscript.denizencore.objects.Argument; | ||
import com.denizenscript.depenizen.bukkit.bridges.EffectLibBridge; | ||
import de.slikey.effectlib.EffectManager; | ||
import de.slikey.effectlib.effect.ArcEffect; | ||
import de.slikey.effectlib.effect.AtomEffect; | ||
import de.slikey.effectlib.effect.BleedEffect; | ||
import com.denizenscript.denizen.objects.EntityTag; | ||
import com.denizenscript.denizen.objects.LocationTag; | ||
import com.denizenscript.denizen.objects.PlayerTag; | ||
import com.denizenscript.denizen.utilities.Utilities; | ||
import com.denizenscript.denizencore.exceptions.InvalidArgumentsException; | ||
import com.denizenscript.denizencore.objects.ObjectTag; | ||
import com.denizenscript.denizencore.objects.core.DurationTag; | ||
import com.denizenscript.denizencore.objects.core.MapTag; | ||
import com.denizenscript.denizencore.scripts.ScriptEntry; | ||
import com.denizenscript.denizencore.scripts.commands.AbstractCommand; | ||
import com.denizenscript.denizencore.scripts.commands.Holdable; | ||
import com.denizenscript.denizencore.scripts.commands.generator.ArgDefaultNull; | ||
import com.denizenscript.denizencore.scripts.commands.generator.ArgName; | ||
import com.denizenscript.denizencore.scripts.commands.generator.ArgPrefixed; | ||
import com.denizenscript.denizencore.tags.TagContext; | ||
import com.denizenscript.denizencore.utilities.CoreUtilities; | ||
import com.denizenscript.denizencore.utilities.debugging.Debug; | ||
import org.bukkit.Location; | ||
import com.denizenscript.denizencore.utilities.debugging.SlowWarning; | ||
import com.denizenscript.denizencore.utilities.debugging.Warning; | ||
import com.denizenscript.denizencore.utilities.text.StringHolder; | ||
import com.denizenscript.depenizen.bukkit.bridges.EffectLibBridge; | ||
import de.slikey.effectlib.Effect; | ||
import de.slikey.effectlib.util.DynamicLocation; | ||
import org.bukkit.configuration.ConfigurationSection; | ||
import org.bukkit.configuration.MemoryConfiguration; | ||
|
||
public class EffectLibCommand extends AbstractCommand { | ||
import java.util.Map; | ||
|
||
public class EffectLibCommand extends AbstractCommand implements Holdable { | ||
|
||
public EffectLibCommand() { | ||
setName("effectlib"); | ||
setSyntax("effectlib (type:<effect name>) (duration:<duration>) (target:<entity>/location:<location>)"); | ||
setRequiredArguments(1, 3); | ||
setSyntax("effectlib [type:<effect>] (origin:<entity>/<location>) (target:<entity>/<location>) (for:<player>) (effect_data:<map>)"); | ||
setRequiredArguments(1, 5); | ||
autoCompile(); | ||
} | ||
|
||
// <--[command] | ||
// @Name effectlib | ||
// @Syntax effectlib (type:<effect name>) (duration:<duration>) (target:<entity>/location:<location>) | ||
// @Syntax effectlib [type:<effect>] (origin:<entity>/<location>) (target:<entity>/<location>) (for:<player>) (effect_data:<map>) | ||
// @Group Depenizen | ||
// @Plugin Depenizen, EffectLib | ||
// @Required 1 | ||
// @Maximum 3 | ||
// @Maximum 5 | ||
// @Short Show custom effects using EffectLib | ||
// | ||
// @Description | ||
// Use to show custom effects in a easier way using the config file in EffectLib. | ||
// The effect names comes from the config file. | ||
// Specify a location instead of a target to show the effect at a location instead. | ||
// Displays EffectLib effects. | ||
// Specify which effect to display using the 'type:' argument, note that effect names are CASE-SENSITIVE. | ||
// The origin is the entity/location to play the effect at. If an entity is specified, the effect will follow it. | ||
// Defaults to the linked player if unspecified. | ||
// Some effects (such as the 'Line' effect) require an origin and a target, an effect's target can be a location or an entity. | ||
// If an entity is specified, the effect will follow it. | ||
// | ||
// You can optionally use the 'for:' argument to show the effect to one player only. | ||
// | ||
// EffectLib effects can take additional data to change how the effect looks/works, you can specify that data in the form of a MapTag using the 'effect_data:' argument. | ||
// See EffectLib's docs for further information on the available options for each effect: <@link url https://reference.elmakers.com/#effectlib> | ||
// | ||
// Note that this should only be used for displaying effects. for showing single particles, etc. use <@link command playeffect>. | ||
// | ||
// Note that most users should instead use <@link command playeffect>. | ||
// The effectlib command is ~waitable. Refer to <@link language ~waitable>. | ||
// When ~waited for, the command will wait until the effect is done playing. | ||
// | ||
// @Tags | ||
// None | ||
// | ||
// @Usage | ||
// Use to show a effect on the attached player in queue. | ||
// - effectlib bleed duration:10s | ||
// Use to show a helix of end rod sparks below the linked player for 5 seconds. | ||
// - effectlib type:Helix effect_data:[duration=<duration[5s].in_milliseconds>;particle=end_rod;offset=0,-1.5,0] | ||
// | ||
// @Usage | ||
// Use to show a effect on a target entity. | ||
// - effectlib atom target:<player.target> duration:10s | ||
// Use to show a line of electric sparks between 2 entities for 1 minute. | ||
// - effectlib type:Line origin:<[originEntity]> target:<[targetEntity]> effect_data:[duration=<duration[1m].in_milliseconds>;particle=electric_spark] | ||
// | ||
// @Usage | ||
// Use to show effect at a position of the player. | ||
// - effectlib type:atom duration:10s location:<player.location> | ||
// Use to show an atom effect at a location, and narrate a message after it's done playing. | ||
// - ~effectlib type:Atom origin:<[location]> | ||
// - narrate "It's done!" | ||
// | ||
// --> | ||
|
||
private enum Action { | ||
BLEED, ARC, ATOM | ||
} | ||
public static Warning durationArgument = new SlowWarning("effectlibCommandDuration", "The 'duration:<duration>' argument for the 'effectlib' command is deprecated in favour of the 'duration' key in the 'effect_data' map, refer to the meta docs for more information."); | ||
public static Warning oldTargetArguments = new SlowWarning("effectlibCommandOldTarget", "The 'target:<entity>'/'location:<location>' arguments for the 'effectlib' command are deprecated in favour of the 'origin:<entity>/<location>' argument."); | ||
public static Warning caseInsensitiveEffectName = new SlowWarning("effectlibCommandCaseInsensitiveType", "Case-Insensitive effect types in the 'effectlib' commands are deprecated. make sure you're using correct casing."); | ||
|
||
@Override | ||
public void parseArgs(ScriptEntry scriptEntry) throws InvalidArgumentsException { | ||
for (Argument arg : scriptEntry) { | ||
if (!scriptEntry.hasObject("target") | ||
&& arg.matchesPrefix("target")) { | ||
scriptEntry.addObject("target", arg.asType(EntityTag.class)); | ||
} | ||
else if (!scriptEntry.hasObject("duration") | ||
&& arg.matchesPrefix("duration")) { | ||
scriptEntry.addObject("duration", arg.asType(DurationTag.class)); | ||
} | ||
else if (!scriptEntry.hasObject("location") | ||
&& arg.matchesPrefix("location")) { | ||
scriptEntry.addObject("location", arg.asType(LocationTag.class)); | ||
} | ||
else if (!scriptEntry.hasObject("action") | ||
&& arg.matchesEnum(Action.class)) { | ||
scriptEntry.addObject("action", Action.valueOf(arg.getValue().toUpperCase())); | ||
} | ||
else { | ||
arg.reportUnhandled(); | ||
} | ||
public static void autoExecute(ScriptEntry scriptEntry, | ||
@ArgPrefixed @ArgName("type") String effectInput, | ||
@ArgDefaultNull @ArgPrefixed @ArgName("origin") ObjectTag originInput, | ||
@ArgDefaultNull @ArgPrefixed @ArgName("target") ObjectTag targetInput, | ||
@ArgDefaultNull @ArgPrefixed @ArgName("for") PlayerTag forPlayer, | ||
@ArgDefaultNull @ArgPrefixed @ArgName("effect_data") MapTag effectData, | ||
@ArgDefaultNull @ArgPrefixed @ArgName("duration") DurationTag duration, | ||
@ArgDefaultNull @ArgPrefixed @ArgName("location") LocationTag oldLocation) { | ||
if (originInput == null && oldLocation != null) { | ||
oldTargetArguments.warn(scriptEntry); | ||
originInput = oldLocation; | ||
targetInput = null; | ||
} | ||
if (originInput == null && targetInput != null && targetInput.shouldBeType(EntityTag.class)) { | ||
oldTargetArguments.warn(scriptEntry); | ||
originInput = targetInput; | ||
targetInput = null; | ||
} | ||
if (!scriptEntry.hasObject("action")) { | ||
throw new InvalidArgumentsException("Effect not specified!"); | ||
if (originInput == null && Utilities.entryHasPlayer(scriptEntry)) { | ||
originInput = Utilities.getEntryPlayer(scriptEntry); | ||
} | ||
if (!scriptEntry.hasObject("duration")) { | ||
throw new InvalidArgumentsException("Duration not specified!"); | ||
if (originInput == null) { | ||
Debug.echoError(scriptEntry, "Must specify an origin location or entity!"); | ||
return; | ||
} | ||
// EffectLib is case-sensitive, and the way the command used to handle effect names let you input 'atom', where now 'Atom' is required | ||
if (Character.isLowerCase(effectInput.charAt(0))) { | ||
caseInsensitiveEffectName.warn(scriptEntry); | ||
effectInput = Character.toUpperCase(effectInput.charAt(0)) + effectInput.substring(1); | ||
} | ||
if (!scriptEntry.hasObject("target")) { | ||
if (Utilities.entryHasPlayer(scriptEntry)) { | ||
scriptEntry.addObject("target", Utilities.getEntryPlayer(scriptEntry).getDenizenEntity()); | ||
Effect effect; | ||
if (effectData == null) { | ||
effect = EffectLibBridge.instance.effectManager.getEffectByClassName(effectInput); | ||
if (effect != null) { | ||
effect.setDynamicOrigin(getEffectLibLocationFrom(originInput, scriptEntry.context)); | ||
effect.setDynamicTarget(getEffectLibLocationFrom(targetInput, scriptEntry.context)); | ||
effect.setTargetPlayer(forPlayer != null ? forPlayer.getPlayerEntity() : null); | ||
} | ||
} | ||
|
||
} | ||
|
||
@Override | ||
public void execute(final ScriptEntry scriptEntry) { | ||
EntityTag target = scriptEntry.getObjectTag("target"); | ||
Action action = (Action) scriptEntry.getObject("action"); | ||
DurationTag duration = scriptEntry.getObjectTag("duration"); | ||
LocationTag location = scriptEntry.getObjectTag("location"); | ||
if (scriptEntry.dbCallShouldDebug()) { | ||
Debug.report(scriptEntry, getName(), target, action, duration, location); | ||
else { | ||
ConfigurationSection effectLibData = new MemoryConfiguration(); | ||
for (Map.Entry<StringHolder, ObjectTag> entry : effectData.map.entrySet()) { | ||
effectLibData.set(entry.getKey().str, CoreUtilities.objectTagToJavaForm(entry.getValue(), false, true)); | ||
} | ||
effect = EffectLibBridge.instance.effectManager.getEffect( | ||
effectInput, | ||
effectLibData, | ||
getEffectLibLocationFrom(originInput, scriptEntry.context), | ||
getEffectLibLocationFrom(targetInput, scriptEntry.context), | ||
null, | ||
forPlayer != null ? forPlayer.getPlayerEntity() : null); | ||
} | ||
if (target == null && location == null) { | ||
Debug.echoError(scriptEntry, "Target not found!"); | ||
if (effect == null) { | ||
Debug.echoError(scriptEntry, "Invalid effect specified: " + effectInput); | ||
return; | ||
} | ||
if (action == null) { | ||
Debug.echoError(scriptEntry, "Effect type not specified!"); | ||
return; | ||
effect.callback = () -> scriptEntry.setFinished(true); | ||
if (duration != null) { | ||
durationArgument.warn(scriptEntry); | ||
effect.iterations = duration.getTicksAsInt(); | ||
} | ||
if (duration == null) { | ||
Debug.echoError(scriptEntry, "Duration not specified!"); | ||
return; | ||
effect.start(); | ||
} | ||
|
||
public static DynamicLocation getEffectLibLocationFrom(ObjectTag object, TagContext context) { | ||
if (object == null) { | ||
return null; | ||
} | ||
int ticks = duration.getTicksAsInt(); | ||
EffectManager effectManager = new EffectManager(EffectLibBridge.instance.plugin); | ||
// TODO: Find a better way to handle all effects and add custom ones as well | ||
switch (action) { | ||
case BLEED: { | ||
BleedEffect effect = new BleedEffect(effectManager); | ||
if (location == null) { | ||
effect.setEntity(target.getBukkitEntity()); | ||
} | ||
else { | ||
effect.setLocation(new Location(location.getWorld(), location.getX(), location.getY(), location.getZ())); | ||
} | ||
effect.callback = () -> scriptEntry.setFinished(true); | ||
effect.iterations = ticks; | ||
effect.start(); | ||
return; | ||
} | ||
case ARC: { | ||
ArcEffect effect = new ArcEffect(effectManager); | ||
if (location == null) { | ||
effect.setEntity(target.getBukkitEntity()); | ||
} | ||
else { | ||
effect.setLocation(new Location(location.getWorld(), location.getX(), location.getY(), location.getZ())); | ||
} | ||
effect.callback = () -> scriptEntry.setFinished(true); | ||
effect.iterations = ticks; | ||
effect.start(); | ||
return; | ||
} | ||
case ATOM: { | ||
AtomEffect effect = new AtomEffect(effectManager); | ||
if (location == null) { | ||
effect.setEntity(target.getBukkitEntity()); | ||
} | ||
else { | ||
effect.setLocation(new Location(location.getWorld(), location.getX(), location.getY(), location.getZ())); | ||
} | ||
effect.callback = () -> scriptEntry.setFinished(true); | ||
effect.iterations = ticks; | ||
effect.start(); | ||
return; | ||
} | ||
default: { | ||
Debug.echoError(scriptEntry, "Effect type not found!"); | ||
if (object.shouldBeType(LocationTag.class)) { | ||
return new DynamicLocation(object.asType(LocationTag.class, context)); | ||
} | ||
else { | ||
EntityTag entity = object.asType(EntityTag.class, context); | ||
if (entity == null) { | ||
Debug.echoError(context, "Invalid input specified '" + object + "': must be a valid location or entity."); | ||
return null; | ||
} | ||
return new DynamicLocation(entity.getBukkitEntity()); | ||
} | ||
} | ||
} |