diff --git a/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityTeleportScriptEvent.java b/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityTeleportScriptEvent.java index 4d227f0d81..6a411893d3 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityTeleportScriptEvent.java +++ b/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityTeleportScriptEvent.java @@ -17,6 +17,18 @@ public class EntityTeleportScriptEvent extends BukkitScriptEvent implements Listener { + // <--[language] + // @name Teleport Cause + // @group Useful Lists + // @description + // Possible player teleport causes: <@link url https://hub.spigotmc.org/javadocs/spigot/org/bukkit/event/player/PlayerTeleportEvent.TeleportCause.html> + // These are used in <@link event entity teleports>, <@link tag server.teleport_causes>, <@link command teleport>, ... + // Note that these causes will only work for player entities. + // + // Additionally, Denizen provides two basic teleport causes for non-player entity teleport events: ENTITY_PORTAL and ENTITY_TELEPORT. + // These additional causes are not usable in <@link command teleport>, and will not show in <@link tag server.teleport_causes>. + // --> + // <--[event] // @Events // entity teleports @@ -37,8 +49,7 @@ public class EntityTeleportScriptEvent extends BukkitScriptEvent implements List // returns the EntityTag. // returns the LocationTag the entity teleported from. // returns the LocationTag the entity teleported to. - // returns an ElementTag of the teleport cause. Can be: - // COMMAND, END_PORTAL, ENDER_PEARL, NETHER_PORTAL, PLUGIN, END_GATEWAY, CHORUS_FRUIT, SPECTATE, UNKNOWN, ENTITY_TELEPORT, or ENTITY_PORTAL + // returns an ElementTag of the teleport cause - see <@link language teleport cause> for causes. // // @Determine // "ORIGIN:" + LocationTag to change the location the entity teleported from. diff --git a/plugin/src/main/java/com/denizenscript/denizen/objects/EntityTag.java b/plugin/src/main/java/com/denizenscript/denizen/objects/EntityTag.java index f238d40463..9402c101d2 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/objects/EntityTag.java +++ b/plugin/src/main/java/com/denizenscript/denizen/objects/EntityTag.java @@ -736,6 +736,10 @@ public World getWorld() { } public void spawnAt(Location location) { + spawnAt(location, TeleportCause.PLUGIN); + } + + public void spawnAt(Location location, TeleportCause cause) { if (location.getWorld() == null) { Debug.echoError("Cannot teleport or spawn entity at location '" + new LocationTag(location) + "' because it is missing a world."); return; @@ -743,7 +747,7 @@ public void spawnAt(Location location) { // If the entity is already spawned, teleport it. if (isCitizensNPC()) { if (getDenizenNPC().getCitizen().isSpawned()) { - getDenizenNPC().getCitizen().teleport(location, TeleportCause.PLUGIN); + getDenizenNPC().getCitizen().teleport(location, cause); } else { if (getDenizenNPC().getCitizen().spawn(location)) { @@ -761,7 +765,7 @@ public void spawnAt(Location location) { } } else if (isUnique() && entity != null) { - teleport(location); + teleport(location, cause); } else { if (entity_type != null) { @@ -942,15 +946,19 @@ public void remove() { } public void teleport(Location location) { + teleport(location, TeleportCause.PLUGIN); + } + + public void teleport(Location location, TeleportCause cause) { if (isCitizensNPC()) { - getDenizenNPC().getCitizen().teleport(location, TeleportCause.PLUGIN); + getDenizenNPC().getCitizen().teleport(location, cause); } else if (isFake) { NMSHandler.getEntityHelper().snapPositionTo(entity, location.toVector()); NMSHandler.getEntityHelper().look(entity, location.getYaw(), location.getPitch()); } else { - getBukkitEntity().teleport(location); + getBukkitEntity().teleport(location, cause); if (entity.getWorld().equals(location.getWorld())) { // Force the teleport through (for things like mounts) NMSHandler.getEntityHelper().teleport(entity, location); } diff --git a/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/entity/TeleportCommand.java b/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/entity/TeleportCommand.java index 110997f149..f6ed61ef2c 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/entity/TeleportCommand.java +++ b/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/entity/TeleportCommand.java @@ -7,11 +7,13 @@ import com.denizenscript.denizen.objects.LocationTag; import com.denizenscript.denizencore.exceptions.InvalidArgumentsException; import com.denizenscript.denizencore.objects.Argument; +import com.denizenscript.denizencore.objects.core.ElementTag; import com.denizenscript.denizencore.objects.core.ListTag; import com.denizenscript.denizencore.objects.notable.Notable; import com.denizenscript.denizencore.objects.notable.NoteManager; import com.denizenscript.denizencore.scripts.ScriptEntry; import com.denizenscript.denizencore.scripts.commands.AbstractCommand; +import org.bukkit.event.player.PlayerTeleportEvent; import java.util.Collections; import java.util.List; @@ -21,16 +23,16 @@ public class TeleportCommand extends AbstractCommand { public TeleportCommand() { setName("teleport"); - setSyntax("teleport (|...) []"); - setRequiredArguments(1, 2); + setSyntax("teleport (|...) [] (cause:)"); + setRequiredArguments(1, 3); isProcedural = false; } // <--[command] // @Name Teleport - // @Syntax teleport (|...) [] + // @Syntax teleport (|...) [] (cause:) // @Required 1 - // @Maximum 2 + // @Maximum 3 // @Short Teleports the entity(s) to a new location. // @Synonyms tp // @Group entity @@ -38,6 +40,7 @@ public TeleportCommand() { // @Description // Teleports the entity or entities to the new location. // Entities can be teleported between worlds using this command. + // You may optionally specify a teleport cause for player entities, allowing proper teleport event handling. When not specified, this is "PLUGIN". See <@link language teleport cause> for causes. // // @Tags // @@ -61,6 +64,10 @@ public TeleportCommand() { // @Usage // Use to teleport the NPC to a location that was noted wih the <@link command note> command. // - teleport my_prenoted_location + // + // @Usage + // Use to teleport a player to some location, and inform events that it was caused by a nether portal. + // - teleport cause:nether_portal // --> @Override @@ -85,6 +92,10 @@ else if (!scriptEntry.hasObject("entities") else if (arg.matches("npc") && Utilities.entryHasNPC(scriptEntry)) { scriptEntry.addObject("entities", Collections.singletonList(Utilities.getEntryNPC(scriptEntry).getDenizenEntity())); } + else if (!scriptEntry.hasObject("cause") + && arg.matchesEnum(PlayerTeleportEvent.TeleportCause.values())) { + scriptEntry.addObject("cause", arg.asElement()); + } else { arg.reportUnhandled(); } @@ -101,16 +112,18 @@ else if (arg.matches("npc") && Utilities.entryHasNPC(scriptEntry)) { public void execute(final ScriptEntry scriptEntry) { LocationTag location = scriptEntry.getObjectTag("location"); List entities = (List) scriptEntry.getObject("entities"); + ElementTag cause = scriptEntry.getElement("cause"); if (scriptEntry.dbCallShouldDebug()) { - Debug.report(scriptEntry, getName(), location, db("entities", entities)); + Debug.report(scriptEntry, getName(), location, db("entities", entities), cause); } + PlayerTeleportEvent.TeleportCause causeEnum = cause == null ? PlayerTeleportEvent.TeleportCause.PLUGIN : PlayerTeleportEvent.TeleportCause.valueOf(cause.asString().toUpperCase()); for (EntityTag entity : entities) { if (entity.isFake && entity.getWorld().equals(location.getWorld())) { NMSHandler.getEntityHelper().snapPositionTo(entity.getBukkitEntity(), location.toVector()); NMSHandler.getEntityHelper().look(entity.getBukkitEntity(), location.getYaw(), location.getPitch()); return; } - entity.spawnAt(location); + entity.spawnAt(location, causeEnum); } } } diff --git a/plugin/src/main/java/com/denizenscript/denizen/tags/core/ServerTagBase.java b/plugin/src/main/java/com/denizenscript/denizen/tags/core/ServerTagBase.java index 74a3f6bffb..9cde51213d 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/tags/core/ServerTagBase.java +++ b/plugin/src/main/java/com/denizenscript/denizen/tags/core/ServerTagBase.java @@ -52,6 +52,7 @@ import org.bukkit.event.HandlerList; import org.bukkit.event.Listener; import org.bukkit.event.entity.EntityDamageEvent; +import org.bukkit.event.player.PlayerTeleportEvent; import org.bukkit.inventory.*; import org.bukkit.loot.LootContext; import org.bukkit.loot.LootTable; @@ -675,6 +676,23 @@ else if (recipe instanceof CookingRecipe) { return; } + // <--[tag] + // @attribute + // @returns ListTag + // @description + // Returns a list of all registered player teleport causes. + // Generally used with <@link event entity teleports>. + // See <@link language teleport cause> for the current list of causes. + // --> + if (attribute.startsWith("teleport_causes")) { + ListTag list = new ListTag(); + for (PlayerTeleportEvent.TeleportCause teleportCause : PlayerTeleportEvent.TeleportCause.values()) { + list.add(teleportCause.name()); + } + event.setReplacedObject(list.getObjectAttribute(attribute.fulfill(1))); + return; + } + // <--[tag] // @attribute // @returns ListTag(BiomeTag)