-
-
Notifications
You must be signed in to change notification settings - Fork 42
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Rework EffectLib Integration #384
Merged
mcmonkey4eva
merged 1 commit into
DenizenScript:master
from
tal5:EffectLib_Command_Update
Aug 27, 2022
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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()); | ||
} | ||
} | ||
} |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Feels weird for this to be a deprecation - should probably be the other way around if anything - aim to support case-insensitivity better rather than plan its removal.