diff --git a/core/src/main/java/com/sekwah/advancedportals/core/CoreListeners.java b/core/src/main/java/com/sekwah/advancedportals/core/CoreListeners.java index 2ee8913..976b85c 100644 --- a/core/src/main/java/com/sekwah/advancedportals/core/CoreListeners.java +++ b/core/src/main/java/com/sekwah/advancedportals/core/CoreListeners.java @@ -164,13 +164,16 @@ public class CoreListeners { return portalServices.inPortalRegion(entity.getBlockLoc(), 2); } - public boolean portalEvent(PlayerContainer player) { - return !portalServices.inPortalRegion(player.getBlockLoc(), 1) - && (!(player.getHeight() > 1) || !portalServices.inPortalRegion(player.getBlockLoc().addY((int) player.getHeight()), 1)); - } - public boolean entityPortalEvent(EntityContainer entity) { - return !portalServices.inPortalRegion(entity.getBlockLoc(), 1) - && (!(entity.getHeight() > 1) || !portalServices.inPortalRegion(entity.getBlockLoc().addY((int) entity.getHeight()), 1)); + var pos = entity.getBlockLoc(); + if(entity instanceof PlayerContainer player) { + var playerData = playerDataServices.getPlayerData(player); + if(playerData.isPortalCooldown()) { + return false; + } + } + var feetInPortal = portalServices.inPortalRegion(pos, 1); + var headInPortal = portalServices.inPortalRegion(pos.addY((int) entity.getHeight()), 1); + return !(feetInPortal || headInPortal); } } diff --git a/core/src/main/java/com/sekwah/advancedportals/core/commands/subcommands/desti/ShowDestiSubCommand.java b/core/src/main/java/com/sekwah/advancedportals/core/commands/subcommands/desti/ShowDestiSubCommand.java index 96b1858..08c18cd 100644 --- a/core/src/main/java/com/sekwah/advancedportals/core/commands/subcommands/desti/ShowDestiSubCommand.java +++ b/core/src/main/java/com/sekwah/advancedportals/core/commands/subcommands/desti/ShowDestiSubCommand.java @@ -16,6 +16,7 @@ import com.sekwah.advancedportals.core.util.Lang; import java.awt.*; import java.util.List; +import java.util.Objects; /** * This will be different from the old show command and I believe it is 1.16+ till the latest version as of writing this. @@ -47,7 +48,7 @@ public class ShowDestiSubCommand implements SubCommand, SubCommand.SubCommandOnI return; } - var tempData = tempDataServices.getPlayerTempData(sender.getPlayerContainer()); + var tempData = tempDataServices.getPlayerData(sender.getPlayerContainer()); if(tempData.isDestiVisible()) { sender.sendMessage(Lang.translate("messageprefix.negative") + Lang.translate("command.destination.show.disabled")); } else { @@ -80,14 +81,14 @@ public class ShowDestiSubCommand implements SubCommand, SubCommand.SubCommandOnI public void registered() { gameScheduler.intervalTickEvent("show_portal", () -> { for(PlayerContainer player : serverContainer.getPlayers()) { - var tempData = tempDataServices.getPlayerTempData(player); + var tempData = tempDataServices.getPlayerData(player); if(!tempData.isDestiVisible()) { continue; } for (Destination destination : destinationServices.getDestinations()) { var pos = destination.getLoc(); - if(pos.distanceTo(player.getLoc()) < config.getVisibleRange()) { + if(Objects.equals(pos.getWorldName(), player.getWorldName()) && pos.distanceTo(player.getLoc()) < config.getVisibleRange()) { Debug.addMarker(player, pos.toBlockPos(), destination.getArgValues("name")[0], new Color(100, 100, 100, 100), 1300); } } diff --git a/core/src/main/java/com/sekwah/advancedportals/core/commands/subcommands/portal/ShowPortalSubCommand.java b/core/src/main/java/com/sekwah/advancedportals/core/commands/subcommands/portal/ShowPortalSubCommand.java index 02ea046..fc764ae 100644 --- a/core/src/main/java/com/sekwah/advancedportals/core/commands/subcommands/portal/ShowPortalSubCommand.java +++ b/core/src/main/java/com/sekwah/advancedportals/core/commands/subcommands/portal/ShowPortalSubCommand.java @@ -18,6 +18,7 @@ import com.sekwah.advancedportals.core.util.Lang; import java.awt.*; import java.util.List; +import java.util.Objects; /** * This will be different from the old show command and I believe it is 1.16+ till the latest version as of writing this. @@ -29,7 +30,7 @@ public class ShowPortalSubCommand implements SubCommand, SubCommand.SubCommandOn boolean alternate_show_trigger = true; @Inject - PlayerDataServices tempDataServices; + PlayerDataServices playerDataServices; @Inject GameScheduler gameScheduler; @@ -64,7 +65,7 @@ public class ShowPortalSubCommand implements SubCommand, SubCommand.SubCommandOn return; } - var tempData = tempDataServices.getPlayerTempData(sender.getPlayerContainer()); + var tempData = playerDataServices.getPlayerData(sender.getPlayerContainer()); if(tempData.isPortalVisible()) { sender.sendMessage(Lang.translate("messageprefix.negative") + Lang.translate("command.portal.show.disabled")); } else { @@ -98,26 +99,26 @@ public class ShowPortalSubCommand implements SubCommand, SubCommand.SubCommandOn gameScheduler.intervalTickEvent("show_portal", () -> { alternate_show_trigger = !alternate_show_trigger; for(PlayerContainer player : serverContainer.getPlayers()) { - var tempData = tempDataServices.getPlayerTempData(player); + var tempData = playerDataServices.getPlayerData(player); if(!tempData.isPortalVisible()) { continue; } - if (tempData.getPos1() != null && tempData.getPos2() != null) { + if (tempData.getPos1() != null && tempData.getPos2() != null && tempData.getPos1().worldName.equals(player.getWorldName()) && tempData.getPos2().worldName.equals(player.getWorldName())) { debugVisuals(player, tempData.getPos1(), tempData.getPos2(), SELECTION_COLOR, SHOW_TICKS); } - if(tempData.getPos1() != null) { + if(tempData.getPos1() != null && tempData.getPos1().worldName.equals(player.getWorldName())) { Debug.addMarker(player, tempData.getPos1(), "Pos1", POS1_COLOR, SHOW_TICKS); } - if(tempData.getPos2() != null) { + if(tempData.getPos2() != null && tempData.getPos2().worldName.equals(player.getWorldName())) { Debug.addMarker(player, tempData.getPos2(), "Pos2", POS2_COLOR, SHOW_TICKS); } var world = player.getWorld(); for (var portal : portalServices.getPortals()) { - if(portal.isLocationInPortal(player.getLoc(), config.getVisibleRange())) { + if(Objects.equals(portal.getMinLoc().worldName, player.getWorldName()) && portal.isLocationInPortal(player.getLoc(), config.getVisibleRange())) { BlockLocation minLoc = portal.getMinLoc(); BlockLocation maxLoc = portal.getMaxLoc(); int midX = (minLoc.posX + maxLoc.posX) / 2; diff --git a/core/src/main/java/com/sekwah/advancedportals/core/connector/containers/EntityContainer.java b/core/src/main/java/com/sekwah/advancedportals/core/connector/containers/EntityContainer.java index cfb860b..2f938b5 100644 --- a/core/src/main/java/com/sekwah/advancedportals/core/connector/containers/EntityContainer.java +++ b/core/src/main/java/com/sekwah/advancedportals/core/connector/containers/EntityContainer.java @@ -16,4 +16,6 @@ public interface EntityContainer { WorldContainer getWorld(); String getName(); + + String getWorldName(); } diff --git a/core/src/main/java/com/sekwah/advancedportals/core/effect/WarpEffect.java b/core/src/main/java/com/sekwah/advancedportals/core/effect/WarpEffect.java index dc4577d..95befbb 100644 --- a/core/src/main/java/com/sekwah/advancedportals/core/effect/WarpEffect.java +++ b/core/src/main/java/com/sekwah/advancedportals/core/effect/WarpEffect.java @@ -13,13 +13,13 @@ public interface WarpEffect { interface Sound extends WarpEffect { - void onWarpSound(PlayerContainer player, Action action, AdvancedPortal portal); + void onWarpSound(PlayerContainer player, Action action); } interface Visual extends WarpEffect { - void onWarpVisual(PlayerContainer player, Action action, AdvancedPortal portal); + void onWarpVisual(PlayerContainer player, Action action); } } diff --git a/core/src/main/java/com/sekwah/advancedportals/core/portal/AdvancedPortal.java b/core/src/main/java/com/sekwah/advancedportals/core/portal/AdvancedPortal.java index a3f30ca..de3c1f7 100644 --- a/core/src/main/java/com/sekwah/advancedportals/core/portal/AdvancedPortal.java +++ b/core/src/main/java/com/sekwah/advancedportals/core/portal/AdvancedPortal.java @@ -8,6 +8,7 @@ import com.sekwah.advancedportals.core.serializeddata.BlockLocation; import com.sekwah.advancedportals.core.serializeddata.DataTag; import com.sekwah.advancedportals.core.registry.TagRegistry; import com.sekwah.advancedportals.core.serializeddata.PlayerLocation; +import com.sekwah.advancedportals.core.services.PlayerDataServices; import com.sekwah.advancedportals.core.tags.activation.TriggerBlockTag; import com.sekwah.advancedportals.core.warphandler.ActivationData; import com.sekwah.advancedportals.core.warphandler.Tag; @@ -33,6 +34,9 @@ public class AdvancedPortal implements TagTarget { @SerializedName("a") private HashMap args = new HashMap<>(); + @Inject + transient PlayerDataServices playerDataServices; + public AdvancedPortal(BlockLocation minLoc, BlockLocation maxLoc) { this.updateBounds(minLoc, maxLoc); } @@ -123,7 +127,11 @@ public class AdvancedPortal implements TagTarget { activationHandler.postActivated(this, player, data, this.getArgValues(portalTag.NAME)); } } - return true; + if(data.hasActivated()) { + playerDataServices.getPlayerData(player).setNetherPortalCooldown(1000); + return true; + } + return false; } diff --git a/core/src/main/java/com/sekwah/advancedportals/core/serializeddata/PlayerData.java b/core/src/main/java/com/sekwah/advancedportals/core/serializeddata/PlayerData.java index 23d5d35..30dbbd5 100644 --- a/core/src/main/java/com/sekwah/advancedportals/core/serializeddata/PlayerData.java +++ b/core/src/main/java/com/sekwah/advancedportals/core/serializeddata/PlayerData.java @@ -34,12 +34,14 @@ public class PlayerData { /** * If the player is in a portal. Stops re-triggering. */ - private boolean isInPortal = false; + private transient boolean isInPortal = false; /** * The next time System.currentTimeMillis() a player can use a portal. */ - private long globalCooldown; + private transient long globalCooldown; + + private transient long netherPortalCooldown; private HashMap perPortalCooldowns = new HashMap<>(); @@ -66,7 +68,7 @@ public class PlayerData { } public void setGlobalCooldown(long globalCooldown) { - this.globalCooldown = globalCooldown; + this.globalCooldown = System.currentTimeMillis() + globalCooldown; } public String getSelectedPortal() { @@ -100,4 +102,12 @@ public class PlayerData { public void setInPortal(boolean inPortal) { isInPortal = inPortal; } + + public void setNetherPortalCooldown(long netherPortalCooldown) { + this.netherPortalCooldown = System.currentTimeMillis() + netherPortalCooldown; + } + + public boolean isPortalCooldown() { + return System.currentTimeMillis() < netherPortalCooldown; + } } diff --git a/core/src/main/java/com/sekwah/advancedportals/core/services/PlayerDataServices.java b/core/src/main/java/com/sekwah/advancedportals/core/services/PlayerDataServices.java index 8c142c6..ce2939f 100644 --- a/core/src/main/java/com/sekwah/advancedportals/core/services/PlayerDataServices.java +++ b/core/src/main/java/com/sekwah/advancedportals/core/services/PlayerDataServices.java @@ -28,7 +28,7 @@ public final class PlayerDataServices { @Inject private ConfigRepository configRepository; - public PlayerData getPlayerTempData(PlayerContainer player) { + public PlayerData getPlayerData(PlayerContainer player) { return tempDataMap.computeIfAbsent(player.getUUID(), uuid -> { var tempData = tempDataRepository.get(player.getUUID().toString()); @@ -40,17 +40,17 @@ public final class PlayerDataServices { } public void activateCooldown(PlayerContainer player) { - var tempData = getPlayerTempData(player); - tempData.setGlobalCooldown(System.currentTimeMillis() + configRepository.getPortalCooldown()); + var tempData = getPlayerData(player); + tempData.setGlobalCooldown(configRepository.getPortalCooldown() * 1000); } public void playerLeave(PlayerContainer player) { - tempDataRepository.save(player.getUUID().toString(), getPlayerTempData(player)); + tempDataRepository.save(player.getUUID().toString(), getPlayerData(player)); tempDataMap.remove(player.getUUID()); } public void playerSelectorActivate(PlayerContainer player, BlockLocation blockLoc, boolean leftClick) { - var tempData = getPlayerTempData(player); + var tempData = getPlayerData(player); if(leftClick) { tempData.setPos1(blockLoc); } else { diff --git a/core/src/main/java/com/sekwah/advancedportals/core/services/PortalServices.java b/core/src/main/java/com/sekwah/advancedportals/core/services/PortalServices.java index 066b91f..85b2a59 100644 --- a/core/src/main/java/com/sekwah/advancedportals/core/services/PortalServices.java +++ b/core/src/main/java/com/sekwah/advancedportals/core/services/PortalServices.java @@ -73,7 +73,7 @@ public class PortalServices { } public void playerMove(PlayerContainer player, PlayerLocation toLoc) { - PlayerData tempData = playerDataServices.getPlayerTempData(player); + PlayerData tempData = playerDataServices.getPlayerData(player); if(tempData.getGlobalCooldown() > System.currentTimeMillis()) { return; @@ -117,7 +117,7 @@ public class PortalServices { } public AdvancedPortal createPortal(PlayerContainer player, ArrayList tags) { - PlayerData tempData = playerDataServices.getPlayerTempData(player); + PlayerData tempData = playerDataServices.getPlayerData(player); if(tempData.getPos1() == null || tempData.getPos2() == null) { player.sendMessage(Lang.translate("messageprefix.negative") + Lang.translate("portal.error.selection.missing")); diff --git a/core/src/main/java/com/sekwah/advancedportals/core/tags/activation/DestiTag.java b/core/src/main/java/com/sekwah/advancedportals/core/tags/activation/DestiTag.java index 75fd7ee..1aaa1fd 100644 --- a/core/src/main/java/com/sekwah/advancedportals/core/tags/activation/DestiTag.java +++ b/core/src/main/java/com/sekwah/advancedportals/core/tags/activation/DestiTag.java @@ -57,20 +57,30 @@ public class DestiTag implements Tag.Activation, Tag.AutoComplete, Tag.Split { } @Override - public void postActivated(TagTarget target, PlayerContainer player, ActivationData activeData, String[] argData) { + public void postActivated(TagTarget target, PlayerContainer player, ActivationData activationData, String[] argData) { } @Override - public boolean activated(TagTarget target, PlayerContainer player, ActivationData activeData, String[] argData) { - System.out.println("Teleporting to destination"); + public boolean activated(TagTarget target, PlayerContainer player, ActivationData activationData, String[] argData) { Destination destination = destinationServices.getDestination(argData[0]); if (destination != null) { - var warpEffect = warpEffectRegistry.getVisualEffect("ender"); - if (warpEffect != null) { - warpEffect.onWarpVisual(player, ac); + var warpEffectVisual = warpEffectRegistry.getVisualEffect("ender"); + if (warpEffectVisual != null) { + warpEffectVisual.onWarpVisual(player, WarpEffect.Action.ENTER); + } + var warpEffectSound = warpEffectRegistry.getSoundEffect("ender"); + if (warpEffectSound != null) { + warpEffectSound.onWarpSound(player, WarpEffect.Action.ENTER); } player.teleport(destination.getLoc()); + if (warpEffectVisual != null) { + warpEffectVisual.onWarpVisual(player, WarpEffect.Action.EXIT); + } + if (warpEffectSound != null) { + warpEffectSound.onWarpSound(player, WarpEffect.Action.EXIT); + } + activationData.setWarpStatus(ActivationData.WarpedStatus.WARPED); } return true; } diff --git a/core/src/main/java/com/sekwah/advancedportals/core/util/Lang.java b/core/src/main/java/com/sekwah/advancedportals/core/util/Lang.java index e985bc4..a392295 100644 --- a/core/src/main/java/com/sekwah/advancedportals/core/util/Lang.java +++ b/core/src/main/java/com/sekwah/advancedportals/core/util/Lang.java @@ -129,7 +129,6 @@ public class Lang { String line = getNextLine(scanner); HashMap newMap = new HashMap<>(); while (line != null) { - //System.out.println(line); if (!line.startsWith("#") && line.indexOf('=') > -1) { int split = line.indexOf('='); String key = line.substring(0, split); diff --git a/core/src/main/java/com/sekwah/advancedportals/core/warphandler/ActivationData.java b/core/src/main/java/com/sekwah/advancedportals/core/warphandler/ActivationData.java index 1761cf0..f371f2a 100644 --- a/core/src/main/java/com/sekwah/advancedportals/core/warphandler/ActivationData.java +++ b/core/src/main/java/com/sekwah/advancedportals/core/warphandler/ActivationData.java @@ -23,7 +23,7 @@ public class ActivationData { public void setWarpStatus(WarpedStatus warped) { if (this.warpStatus == WarpedStatus.WARPED) { return; - } else if (this.warpStatus == WarpedStatus.NOTACTIVATED) { + } else if (this.warpStatus == WarpedStatus.ACTIVATED && warped != WarpedStatus.WARPED) { return; } this.warpStatus = warped; @@ -46,6 +46,10 @@ public class ActivationData { this.warpAllowed = allowed; } + public boolean hasActivated() { + return this.warpStatus != WarpedStatus.NOTACTIVATED; + } + public enum WarpedStatus { /** * Player has moved or something major has happened. (only one of these should activate) diff --git a/core/src/main/java/com/sekwah/advancedportals/core/warphandler/Tag.java b/core/src/main/java/com/sekwah/advancedportals/core/warphandler/Tag.java index a0003a7..f02cde9 100644 --- a/core/src/main/java/com/sekwah/advancedportals/core/warphandler/Tag.java +++ b/core/src/main/java/com/sekwah/advancedportals/core/warphandler/Tag.java @@ -128,10 +128,10 @@ public interface Tag { * Any actions to do with player location should be done in activate * * @param player - * @param activeData + * @param activationData * @param argData */ - void postActivated(TagTarget target, PlayerContainer player, ActivationData activeData, String[] argData); + void postActivated(TagTarget target, PlayerContainer player, ActivationData activationData, String[] argData); /** * Activates if the portal is allowed from preActivating. Should be used to set the intended warp location @@ -140,12 +140,12 @@ public interface Tag { * triggered here if a desti is listed. * * @param player - * @param activeData + * @param activationData * @param argData * * @return Action performed (only return false if the tag failed to do anything) */ - boolean activated(TagTarget target, PlayerContainer player, ActivationData activeData, String[] argData); + boolean activated(TagTarget target, PlayerContainer player, ActivationData activationData, String[] argData); } diff --git a/spigot/src/main/java/com/sekwah/advancedportals/spigot/Listeners.java b/spigot/src/main/java/com/sekwah/advancedportals/spigot/Listeners.java index b380eeb..2c5c572 100644 --- a/spigot/src/main/java/com/sekwah/advancedportals/spigot/Listeners.java +++ b/spigot/src/main/java/com/sekwah/advancedportals/spigot/Listeners.java @@ -65,7 +65,7 @@ public class Listeners implements Listener { @EventHandler(ignoreCancelled = true) public void onPortalEvent(PlayerPortalEvent event) { - if(!this.coreListeners.portalEvent(new SpigotPlayerContainer(event.getPlayer()))) { + if(!this.coreListeners.entityPortalEvent(new SpigotPlayerContainer(event.getPlayer()))) { event.setCancelled(true); } } diff --git a/spigot/src/main/java/com/sekwah/advancedportals/spigot/commands/subcommands/portal/UpdatePortalSubCommand.java b/spigot/src/main/java/com/sekwah/advancedportals/spigot/commands/subcommands/portal/UpdatePortalSubCommand.java index dd5d56e..37c611c 100644 --- a/spigot/src/main/java/com/sekwah/advancedportals/spigot/commands/subcommands/portal/UpdatePortalSubCommand.java +++ b/spigot/src/main/java/com/sekwah/advancedportals/spigot/commands/subcommands/portal/UpdatePortalSubCommand.java @@ -120,12 +120,13 @@ public class UpdatePortalSubCommand implements SubCommand { int count = 0; for(String destiName : destiSet) { + var destiPos = destiName + ".pos"; var desti = destinationServices.createDesti(new PlayerLocation(config.getString(destiName + ".world"), - config.getDouble(destiName + ".x"), - config.getDouble(destiName + ".y"), - config.getDouble(destiName + ".z"), - (float) config.getDouble(destiName + ".yaw"), - (float) config.getDouble(destiName + ".pitch")), List.of(new DataTag("name", destiName))); + config.getDouble(destiPos + ".X"), + config.getDouble(destiPos + ".Y"), + config.getDouble(destiPos + ".Z"), + (float) config.getDouble(destiPos + ".yaw"), + (float) config.getDouble(destiPos + ".pitch")), List.of(new DataTag("name", destiName))); if(desti != null) count++; } return count; diff --git a/spigot/src/main/java/com/sekwah/advancedportals/spigot/connector/container/SpigotEntityContainer.java b/spigot/src/main/java/com/sekwah/advancedportals/spigot/connector/container/SpigotEntityContainer.java index 529218d..816c0d5 100644 --- a/spigot/src/main/java/com/sekwah/advancedportals/spigot/connector/container/SpigotEntityContainer.java +++ b/spigot/src/main/java/com/sekwah/advancedportals/spigot/connector/container/SpigotEntityContainer.java @@ -53,7 +53,6 @@ public class SpigotEntityContainer implements EntityContainer { return this.entity.teleport(new Location(Bukkit.getWorld(location.getWorldName()), location.getPosX(), location.getPosY(), location.getPosZ())); } - @Override public WorldContainer getWorld() { return new SpigotWorldContainer(this.entity.getWorld()); @@ -63,4 +62,9 @@ public class SpigotEntityContainer implements EntityContainer { public String getName() { return this.entity.getName(); } + + @Override + public String getWorldName() { + return this.entity.getWorld().getName(); + } } diff --git a/spigot/src/main/java/com/sekwah/advancedportals/spigot/warpeffects/EnderWarpEffect.java b/spigot/src/main/java/com/sekwah/advancedportals/spigot/warpeffects/EnderWarpEffect.java index b83be47..00c6b24 100644 --- a/spigot/src/main/java/com/sekwah/advancedportals/spigot/warpeffects/EnderWarpEffect.java +++ b/spigot/src/main/java/com/sekwah/advancedportals/spigot/warpeffects/EnderWarpEffect.java @@ -5,24 +5,32 @@ import com.sekwah.advancedportals.core.effect.WarpEffect; import com.sekwah.advancedportals.core.portal.AdvancedPortal; import com.sekwah.advancedportals.core.serializeddata.WorldLocation; import com.sekwah.advancedportals.spigot.connector.container.SpigotPlayerContainer; +import org.bukkit.Effect; public class EnderWarpEffect implements WarpEffect.Visual, WarpEffect.Sound { @Override - public void onWarpSound(PlayerContainer playerContainer, WarpEffect.Action action, AdvancedPortal portal) { + public void onWarpSound(PlayerContainer playerContainer, WarpEffect.Action action) { if(playerContainer instanceof SpigotPlayerContainer spigotPlayerContainer) { var player = spigotPlayerContainer.getPlayer(); - player.playSound(player.getLocation(), "entity.enderman.teleport", 1, 1); + player.getWorld().playSound(player.getLocation(), "entity.enderman.teleport", 1, 1); } } @Override - public void onWarpVisual(PlayerContainer player, WarpEffect.Action action, AdvancedPortal portal) { - if (action == WarpEffect.Action.ENTER) { - player.spawnParticle(new WorldLocation(portal.getPortalLocation()), "ENDER_SIGNAL", 1, 1, 1, 1, 1); - } else { - player.spawnParticle(new WorldLocation(portal.getPortalLocation()), "ENDER_SIGNAL", 1, 1, 1, 1, 1); + public void onWarpVisual(PlayerContainer playerContainer, WarpEffect.Action action) { + if(playerContainer instanceof SpigotPlayerContainer spigotPlayerContainer) { + var player = spigotPlayerContainer.getPlayer(); + var world = player.getWorld(); + var loc = player.getLocation().clone(); + for(int i = 0; i < 10; i++){ + world.playEffect(loc, Effect.ENDER_SIGNAL, 0); + } + loc.add(0D, 1D, 0D); + for(int i = 0; i < 10; i++){ + world.playEffect(loc, Effect.ENDER_SIGNAL, 0); + } } } }