From e30f41071ce9e2e137645b27079e678e2176ca2c Mon Sep 17 00:00:00 2001 From: EpicKnarvik97 Date: Sun, 14 Sep 2025 03:01:03 +0200 Subject: [PATCH] Restructures events, and adds some missing protections --- .../java/net/knarcraft/stargate/Stargate.java | 31 +- .../stargate/command/CommandAbout.java | 2 +- .../stargate/command/CommandConfig.java | 6 +- .../stargate/command/CommandReload.java | 2 +- .../stargate/config/StargateConfig.java | 23 +- .../config/{ => addons}/DynmapManager.java | 2 +- .../config/{ => addons}/EconomyConfig.java | 5 +- .../{ => formatting}/LanguageLoader.java | 2 +- .../config/{ => formatting}/Message.java | 2 +- .../{ => formatting}/SGFormatBuilder.java | 2 +- .../stargate/listener/BungeeCordListener.java | 42 -- .../listener/EntityEventListener.java | 68 --- .../listener/EntitySpawnListener.java | 25 - .../listener/EnvironmentChangeListener.java | 96 ++++ .../listener/PlayerEventListener.java | 214 +------ .../listener/PluginEventListener.java | 60 -- .../listener/PortalEventListener.java | 126 ----- .../listener/StargateBreakListener.java | 267 +++++++++ ...ava => StargateCreateDestroyListener.java} | 128 +---- .../listener/StargateTeleportListener.java | 530 ++++++++++++++++++ .../listener/TeleportEventListener.java | 37 -- .../listener/VehicleEventListener.java | 198 ------- .../stargate/listener/WorldEventListener.java | 51 -- .../net/knarcraft/stargate/portal/Portal.java | 2 +- .../stargate/portal/PortalActivator.java | 4 +- .../stargate/portal/PortalCreator.java | 4 +- .../stargate/portal/PortalHandler.java | 4 +- .../stargate/portal/PortalRegistry.java | 2 +- .../stargate/portal/PortalSignDrawer.java | 4 +- .../stargate/utility/BungeeHelper.java | 4 +- .../stargate/utility/EconomyHelper.java | 6 +- .../stargate/utility/PermissionHelper.java | 4 +- .../stargate/utility/TeleportHelper.java | 4 +- 33 files changed, 962 insertions(+), 995 deletions(-) rename src/main/java/net/knarcraft/stargate/config/{ => addons}/DynmapManager.java (99%) rename src/main/java/net/knarcraft/stargate/config/{ => addons}/EconomyConfig.java (97%) rename src/main/java/net/knarcraft/stargate/config/{ => formatting}/LanguageLoader.java (99%) rename src/main/java/net/knarcraft/stargate/config/{ => formatting}/Message.java (99%) rename src/main/java/net/knarcraft/stargate/config/{ => formatting}/SGFormatBuilder.java (95%) delete mode 100644 src/main/java/net/knarcraft/stargate/listener/BungeeCordListener.java delete mode 100644 src/main/java/net/knarcraft/stargate/listener/EntityEventListener.java delete mode 100644 src/main/java/net/knarcraft/stargate/listener/EntitySpawnListener.java create mode 100644 src/main/java/net/knarcraft/stargate/listener/EnvironmentChangeListener.java delete mode 100644 src/main/java/net/knarcraft/stargate/listener/PluginEventListener.java delete mode 100644 src/main/java/net/knarcraft/stargate/listener/PortalEventListener.java create mode 100644 src/main/java/net/knarcraft/stargate/listener/StargateBreakListener.java rename src/main/java/net/knarcraft/stargate/listener/{BlockEventListener.java => StargateCreateDestroyListener.java} (57%) create mode 100644 src/main/java/net/knarcraft/stargate/listener/StargateTeleportListener.java delete mode 100644 src/main/java/net/knarcraft/stargate/listener/TeleportEventListener.java delete mode 100644 src/main/java/net/knarcraft/stargate/listener/VehicleEventListener.java delete mode 100644 src/main/java/net/knarcraft/stargate/listener/WorldEventListener.java diff --git a/src/main/java/net/knarcraft/stargate/Stargate.java b/src/main/java/net/knarcraft/stargate/Stargate.java index 3a3dec8..3a9f16f 100644 --- a/src/main/java/net/knarcraft/stargate/Stargate.java +++ b/src/main/java/net/knarcraft/stargate/Stargate.java @@ -7,23 +7,19 @@ import net.knarcraft.knarlib.util.ConfigHelper; import net.knarcraft.knarlib.util.UpdateChecker; import net.knarcraft.stargate.command.CommandStarGate; import net.knarcraft.stargate.command.StarGateTabCompleter; -import net.knarcraft.stargate.config.EconomyConfig; -import net.knarcraft.stargate.config.Message; -import net.knarcraft.stargate.config.SGFormatBuilder; import net.knarcraft.stargate.config.StargateConfig; import net.knarcraft.stargate.config.StargateGateConfig; +import net.knarcraft.stargate.config.addons.EconomyConfig; +import net.knarcraft.stargate.config.formatting.Message; +import net.knarcraft.stargate.config.formatting.SGFormatBuilder; import net.knarcraft.stargate.container.BlockChangeRequest; import net.knarcraft.stargate.container.ChunkUnloadRequest; import net.knarcraft.stargate.container.ControlBlockUpdateRequest; -import net.knarcraft.stargate.listener.BlockEventListener; -import net.knarcraft.stargate.listener.EntityEventListener; -import net.knarcraft.stargate.listener.EntitySpawnListener; +import net.knarcraft.stargate.listener.EnvironmentChangeListener; import net.knarcraft.stargate.listener.PlayerEventListener; -import net.knarcraft.stargate.listener.PluginEventListener; -import net.knarcraft.stargate.listener.PortalEventListener; -import net.knarcraft.stargate.listener.TeleportEventListener; -import net.knarcraft.stargate.listener.VehicleEventListener; -import net.knarcraft.stargate.listener.WorldEventListener; +import net.knarcraft.stargate.listener.StargateBreakListener; +import net.knarcraft.stargate.listener.StargateCreateDestroyListener; +import net.knarcraft.stargate.listener.StargateTeleportListener; import net.knarcraft.stargate.portal.PortalHandler; import net.knarcraft.stargate.portal.PortalRegistry; import net.knarcraft.stargate.thread.BlockChangeThread; @@ -407,15 +403,10 @@ public class Stargate extends ConfigCommentPlugin { */ private void registerEventListeners() { pluginManager.registerEvents(new PlayerEventListener(), this); - pluginManager.registerEvents(new BlockEventListener(), this); - - pluginManager.registerEvents(new VehicleEventListener(), this); - pluginManager.registerEvents(new EntityEventListener(), this); - pluginManager.registerEvents(new PortalEventListener(), this); - pluginManager.registerEvents(new WorldEventListener(), this); - pluginManager.registerEvents(new PluginEventListener(this), this); - pluginManager.registerEvents(new TeleportEventListener(), this); - pluginManager.registerEvents(new EntitySpawnListener(), this); + pluginManager.registerEvents(new StargateCreateDestroyListener(), this); + pluginManager.registerEvents(new StargateTeleportListener(), this); + pluginManager.registerEvents(new EnvironmentChangeListener(this), this); + pluginManager.registerEvents(new StargateBreakListener(), this); } /** diff --git a/src/main/java/net/knarcraft/stargate/command/CommandAbout.java b/src/main/java/net/knarcraft/stargate/command/CommandAbout.java index 715e656..caa68d8 100644 --- a/src/main/java/net/knarcraft/stargate/command/CommandAbout.java +++ b/src/main/java/net/knarcraft/stargate/command/CommandAbout.java @@ -3,7 +3,7 @@ package net.knarcraft.stargate.command; import de.themoep.minedown.MineDown; import net.knarcraft.knarlib.util.FileHelper; import net.knarcraft.stargate.Stargate; -import net.knarcraft.stargate.config.Message; +import net.knarcraft.stargate.config.formatting.Message; import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.chat.BaseComponent; import org.bukkit.command.Command; diff --git a/src/main/java/net/knarcraft/stargate/command/CommandConfig.java b/src/main/java/net/knarcraft/stargate/command/CommandConfig.java index dd5d5d2..58f4e63 100644 --- a/src/main/java/net/knarcraft/stargate/command/CommandConfig.java +++ b/src/main/java/net/knarcraft/stargate/command/CommandConfig.java @@ -3,10 +3,10 @@ package net.knarcraft.stargate.command; import net.knarcraft.stargate.Stargate; import net.knarcraft.stargate.config.ConfigOption; import net.knarcraft.stargate.config.ConfigTag; -import net.knarcraft.stargate.config.DynmapManager; -import net.knarcraft.stargate.config.Message; import net.knarcraft.stargate.config.OptionDataType; -import net.knarcraft.stargate.config.SGFormatBuilder; +import net.knarcraft.stargate.config.addons.DynmapManager; +import net.knarcraft.stargate.config.formatting.Message; +import net.knarcraft.stargate.config.formatting.SGFormatBuilder; import net.knarcraft.stargate.portal.Portal; import net.knarcraft.stargate.portal.PortalRegistry; import net.knarcraft.stargate.portal.PortalSignDrawer; diff --git a/src/main/java/net/knarcraft/stargate/command/CommandReload.java b/src/main/java/net/knarcraft/stargate/command/CommandReload.java index 1bf6326..296ed6a 100644 --- a/src/main/java/net/knarcraft/stargate/command/CommandReload.java +++ b/src/main/java/net/knarcraft/stargate/command/CommandReload.java @@ -1,7 +1,7 @@ package net.knarcraft.stargate.command; import net.knarcraft.stargate.Stargate; -import net.knarcraft.stargate.config.SGFormatBuilder; +import net.knarcraft.stargate.config.formatting.SGFormatBuilder; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; diff --git a/src/main/java/net/knarcraft/stargate/config/StargateConfig.java b/src/main/java/net/knarcraft/stargate/config/StargateConfig.java index afb81ff..5a8ad9f 100644 --- a/src/main/java/net/knarcraft/stargate/config/StargateConfig.java +++ b/src/main/java/net/knarcraft/stargate/config/StargateConfig.java @@ -5,13 +5,18 @@ import net.knarcraft.knarlib.formatting.Translator; import net.knarcraft.knarlib.property.ColorConversion; import net.knarcraft.knarlib.util.ConfigHelper; import net.knarcraft.stargate.Stargate; +import net.knarcraft.stargate.config.addons.DynmapManager; +import net.knarcraft.stargate.config.addons.EconomyConfig; +import net.knarcraft.stargate.config.formatting.LanguageLoader; +import net.knarcraft.stargate.config.formatting.Message; +import net.knarcraft.stargate.config.formatting.SGFormatBuilder; import net.knarcraft.stargate.container.BlockChangeRequest; -import net.knarcraft.stargate.listener.BungeeCordListener; import net.knarcraft.stargate.portal.Portal; import net.knarcraft.stargate.portal.PortalHandler; import net.knarcraft.stargate.portal.PortalRegistry; import net.knarcraft.stargate.portal.property.gate.GateHandler; import net.knarcraft.stargate.thread.BlockChangeThread; +import net.knarcraft.stargate.utility.BungeeHelper; import net.knarcraft.stargate.utility.PortalFileHelper; import org.bukkit.Bukkit; import org.bukkit.World; @@ -358,7 +363,21 @@ public final class StargateConfig { if (start) { messenger.registerOutgoingPluginChannel(Stargate.getInstance(), bungeeChannel); - messenger.registerIncomingPluginChannel(Stargate.getInstance(), bungeeChannel, new BungeeCordListener()); + messenger.registerIncomingPluginChannel(Stargate.getInstance(), bungeeChannel, (channel, unused, message) -> { + //Ignore plugin messages if some other plugin message is received + if (!channel.equals(BungeeHelper.getBungeeChannel())) { + return; + } + + //Try to read the plugin message + String receivedMessage = BungeeHelper.readPluginMessage(message); + if (receivedMessage == null) { + return; + } + + //Use the message to initiate teleportation + BungeeHelper.handleTeleportMessage(receivedMessage); + }); } else { messenger.unregisterIncomingPluginChannel(Stargate.getInstance(), bungeeChannel); messenger.unregisterOutgoingPluginChannel(Stargate.getInstance(), bungeeChannel); diff --git a/src/main/java/net/knarcraft/stargate/config/DynmapManager.java b/src/main/java/net/knarcraft/stargate/config/addons/DynmapManager.java similarity index 99% rename from src/main/java/net/knarcraft/stargate/config/DynmapManager.java rename to src/main/java/net/knarcraft/stargate/config/addons/DynmapManager.java index 8283e5a..8a85872 100644 --- a/src/main/java/net/knarcraft/stargate/config/DynmapManager.java +++ b/src/main/java/net/knarcraft/stargate/config/addons/DynmapManager.java @@ -1,4 +1,4 @@ -package net.knarcraft.stargate.config; +package net.knarcraft.stargate.config.addons; import net.knarcraft.stargate.Stargate; import net.knarcraft.stargate.container.RelativeBlockVector; diff --git a/src/main/java/net/knarcraft/stargate/config/EconomyConfig.java b/src/main/java/net/knarcraft/stargate/config/addons/EconomyConfig.java similarity index 97% rename from src/main/java/net/knarcraft/stargate/config/EconomyConfig.java rename to src/main/java/net/knarcraft/stargate/config/addons/EconomyConfig.java index 165cf51..9bbc356 100644 --- a/src/main/java/net/knarcraft/stargate/config/EconomyConfig.java +++ b/src/main/java/net/knarcraft/stargate/config/addons/EconomyConfig.java @@ -1,6 +1,9 @@ -package net.knarcraft.stargate.config; +package net.knarcraft.stargate.config.addons; import net.knarcraft.stargate.Stargate; +import net.knarcraft.stargate.config.ConfigOption; +import net.knarcraft.stargate.config.formatting.Message; +import net.knarcraft.stargate.config.formatting.SGFormatBuilder; import net.knarcraft.stargate.portal.PortalSignDrawer; import net.knarcraft.stargate.portal.property.gate.Gate; import net.knarcraft.stargate.utility.PermissionHelper; diff --git a/src/main/java/net/knarcraft/stargate/config/LanguageLoader.java b/src/main/java/net/knarcraft/stargate/config/formatting/LanguageLoader.java similarity index 99% rename from src/main/java/net/knarcraft/stargate/config/LanguageLoader.java rename to src/main/java/net/knarcraft/stargate/config/formatting/LanguageLoader.java index f36b5c6..83168f6 100644 --- a/src/main/java/net/knarcraft/stargate/config/LanguageLoader.java +++ b/src/main/java/net/knarcraft/stargate/config/formatting/LanguageLoader.java @@ -1,4 +1,4 @@ -package net.knarcraft.stargate.config; +package net.knarcraft.stargate.config.formatting; import net.knarcraft.knarlib.property.ColorConversion; import net.knarcraft.knarlib.util.FileHelper; diff --git a/src/main/java/net/knarcraft/stargate/config/Message.java b/src/main/java/net/knarcraft/stargate/config/formatting/Message.java similarity index 99% rename from src/main/java/net/knarcraft/stargate/config/Message.java rename to src/main/java/net/knarcraft/stargate/config/formatting/Message.java index 312f5ad..aed78c4 100644 --- a/src/main/java/net/knarcraft/stargate/config/Message.java +++ b/src/main/java/net/knarcraft/stargate/config/formatting/Message.java @@ -1,4 +1,4 @@ -package net.knarcraft.stargate.config; +package net.knarcraft.stargate.config.formatting; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/src/main/java/net/knarcraft/stargate/config/SGFormatBuilder.java b/src/main/java/net/knarcraft/stargate/config/formatting/SGFormatBuilder.java similarity index 95% rename from src/main/java/net/knarcraft/stargate/config/SGFormatBuilder.java rename to src/main/java/net/knarcraft/stargate/config/formatting/SGFormatBuilder.java index 23b83fb..feca690 100644 --- a/src/main/java/net/knarcraft/stargate/config/SGFormatBuilder.java +++ b/src/main/java/net/knarcraft/stargate/config/formatting/SGFormatBuilder.java @@ -1,4 +1,4 @@ -package net.knarcraft.stargate.config; +package net.knarcraft.stargate.config.formatting; import net.knarcraft.knarlib.formatting.FormatBuilder; import net.knarcraft.stargate.Stargate; diff --git a/src/main/java/net/knarcraft/stargate/listener/BungeeCordListener.java b/src/main/java/net/knarcraft/stargate/listener/BungeeCordListener.java deleted file mode 100644 index fba579d..0000000 --- a/src/main/java/net/knarcraft/stargate/listener/BungeeCordListener.java +++ /dev/null @@ -1,42 +0,0 @@ -package net.knarcraft.stargate.listener; - -import net.knarcraft.stargate.utility.BungeeHelper; -import org.bukkit.entity.Player; -import org.bukkit.plugin.messaging.PluginMessageListener; -import org.jetbrains.annotations.NotNull; - -/** - * This listener teleports a user if a valid message is received from BungeeCord - * - *

Specifically, if a string starts with SGBungee encoded to be readable by readUTF followed by - * [PlayerUUID]delimiter[DestinationPortal] is received on the BungeeCord channel, this listener will teleport the - * player to the destination portal.

- */ -public class BungeeCordListener implements PluginMessageListener { - - /** - * Receives plugin messages - * - * @param channel

The channel the message was received on

- * @param unused

Unused.

- * @param message

The message received from the plugin

- */ - @Override - public void onPluginMessageReceived(@NotNull String channel, @NotNull Player unused, byte[] message) { - //Ignore plugin messages if some other plugin message is received - if (!channel.equals(BungeeHelper.getBungeeChannel())) { - return; - } - - //Try to read the plugin message - String receivedMessage = BungeeHelper.readPluginMessage(message); - if (receivedMessage == null) { - return; - } - - //Use the message to initiate teleportation - BungeeHelper.handleTeleportMessage(receivedMessage); - } - - -} diff --git a/src/main/java/net/knarcraft/stargate/listener/EntityEventListener.java b/src/main/java/net/knarcraft/stargate/listener/EntityEventListener.java deleted file mode 100644 index adb6d06..0000000 --- a/src/main/java/net/knarcraft/stargate/listener/EntityEventListener.java +++ /dev/null @@ -1,68 +0,0 @@ -package net.knarcraft.stargate.listener; - -import net.knarcraft.stargate.Stargate; -import net.knarcraft.stargate.portal.Portal; -import net.knarcraft.stargate.portal.PortalHandler; -import net.knarcraft.stargate.portal.PortalRegistry; -import net.knarcraft.stargate.utility.EntityHelper; -import org.bukkit.block.Block; -import org.bukkit.entity.Entity; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.Listener; -import org.bukkit.event.entity.EntityExplodeEvent; -import org.bukkit.event.entity.EntityPortalEvent; -import org.jetbrains.annotations.NotNull; - -/** - * This listener listens for any relevant events on portal entities - */ -@SuppressWarnings("unused") -public class EntityEventListener implements Listener { - - /** - * This event handler prevents sending entities to the normal nether instead of the stargate target - * - * @param event

The event to check and possibly cancel

- */ - @EventHandler(priority = EventPriority.LOWEST) - public void onPortalEvent(@NotNull EntityPortalEvent event) { - if (event.isCancelled()) { - return; - } - - Entity entity = event.getEntity(); - //Cancel normal portal event is near a stargate - if (PortalHandler.getByAdjacentEntrance(event.getFrom(), EntityHelper.getEntityMaxSizeInt(entity)) != null) { - event.setCancelled(true); - } - } - - /** - * This method catches any explosion events - * - *

If destroyed by explosions is enabled, any portals destroyed by the explosion will be unregistered. If not, - * the explosion will be cancelled.

- * - * @param event

The triggered explosion event

- */ - @EventHandler - public void onEntityExplode(@NotNull EntityExplodeEvent event) { - if (event.isCancelled()) { - return; - } - for (Block block : event.blockList()) { - Portal portal = PortalHandler.getByBlock(block); - if (portal == null) { - continue; - } - if (Stargate.getGateConfig().destroyedByExplosion()) { - PortalRegistry.unregisterPortal(portal, true); - } else { - event.setCancelled(true); - break; - } - } - } - -} diff --git a/src/main/java/net/knarcraft/stargate/listener/EntitySpawnListener.java b/src/main/java/net/knarcraft/stargate/listener/EntitySpawnListener.java deleted file mode 100644 index f806e6c..0000000 --- a/src/main/java/net/knarcraft/stargate/listener/EntitySpawnListener.java +++ /dev/null @@ -1,25 +0,0 @@ -package net.knarcraft.stargate.listener; - -import net.knarcraft.stargate.Stargate; -import net.knarcraft.stargate.portal.PortalHandler; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.event.entity.CreatureSpawnEvent; -import org.jetbrains.annotations.NotNull; - -/** - * A listener that listens for any relevant events causing entities to spawn - */ -public class EntitySpawnListener implements Listener { - - @EventHandler - public void onCreatureSpawn(@NotNull CreatureSpawnEvent event) { - //Prevent Zombified Piglins and other creatures form spawning at stargates - if (event.getSpawnReason() == CreatureSpawnEvent.SpawnReason.NETHER_PORTAL && - PortalHandler.getByEntrance(event.getLocation()) != null) { - event.setCancelled(true); - Stargate.debug("EntitySpawnListener", "Prevented creature from spawning at Stargate"); - } - } - -} diff --git a/src/main/java/net/knarcraft/stargate/listener/EnvironmentChangeListener.java b/src/main/java/net/knarcraft/stargate/listener/EnvironmentChangeListener.java new file mode 100644 index 0000000..4875d7a --- /dev/null +++ b/src/main/java/net/knarcraft/stargate/listener/EnvironmentChangeListener.java @@ -0,0 +1,96 @@ +package net.knarcraft.stargate.listener; + +import net.knarcraft.stargate.Stargate; +import net.knarcraft.stargate.config.StargateConfig; +import net.knarcraft.stargate.config.formatting.Message; +import net.knarcraft.stargate.config.formatting.SGFormatBuilder; +import net.knarcraft.stargate.portal.PortalRegistry; +import net.knarcraft.stargate.utility.PortalFileHelper; +import org.bukkit.World; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.server.PluginDisableEvent; +import org.bukkit.event.server.PluginEnableEvent; +import org.bukkit.event.world.WorldLoadEvent; +import org.bukkit.event.world.WorldUnloadEvent; +import org.bukkit.plugin.Plugin; +import org.jetbrains.annotations.NotNull; + +/** + * This listener listens for any plugins/worlds being enabled or disabled + */ +public class EnvironmentChangeListener implements Listener { + + private final Stargate stargate; + + /** + * Instantiates a new plugin event listener + * + * @param stargate

A reference to the stargate plugin to

+ */ + public EnvironmentChangeListener(@NotNull Stargate stargate) { + this.stargate = stargate; + } + + /** + * This event listens for and announces that the vault plugin was detected and enabled + * + *

Each time this event is called, the economy handler will try to enable vault

+ * + * @param ignored

The actual event called. This is currently not used

+ */ + @EventHandler + public void onPluginEnable(@NotNull PluginEnableEvent ignored) { + if (Stargate.getEconomyConfig().setupEconomy(stargate.getServer().getPluginManager())) { + Plugin vault = Stargate.getEconomyConfig().getVault(); + if (vault != null) { + String vaultVersion = vault.getDescription().getVersion(); + Stargate.logInfo(new SGFormatBuilder(Message.VAULT_LOADED).replace("%version%", vaultVersion).toString()); + } + } + } + + /** + * This event listens for the vault plugin being disabled and notifies the console + * + * @param event

The event caused by disabling a plugin

+ */ + @EventHandler + public void onPluginDisable(@NotNull PluginDisableEvent event) { + if (event.getPlugin().equals(Stargate.getEconomyConfig().getVault())) { + Stargate.logInfo("Vault plugin lost."); + } + } + + /** + * This listener listens for the loading of a world and loads all gates from the world if not already loaded + * + * @param event

The triggered world load event

+ */ + @EventHandler + public void onWorldLoad(@NotNull WorldLoadEvent event) { + StargateConfig config = Stargate.getStargateConfig(); + if (!config.getManagedWorlds().contains(event.getWorld().getName()) && + PortalFileHelper.loadAllPortals(event.getWorld())) { + config.addManagedWorld(event.getWorld().getName()); + } + } + + /** + * This listener listens for the unloading of a world + * + * @param event

The triggered world unload event

+ */ + @EventHandler + public void onWorldUnload(@NotNull WorldUnloadEvent event) { + Stargate.debug("onWorldUnload", "Reloading all Stargates"); + World world = event.getWorld(); + String worldName = world.getName(); + StargateConfig config = Stargate.getStargateConfig(); + if (config.getManagedWorlds().contains(worldName)) { + config.removeManagedWorld(worldName); + PortalRegistry.clearPortals(world); + } + } + +} diff --git a/src/main/java/net/knarcraft/stargate/listener/PlayerEventListener.java b/src/main/java/net/knarcraft/stargate/listener/PlayerEventListener.java index cac793e..2a1dbb8 100644 --- a/src/main/java/net/knarcraft/stargate/listener/PlayerEventListener.java +++ b/src/main/java/net/knarcraft/stargate/listener/PlayerEventListener.java @@ -3,59 +3,41 @@ package net.knarcraft.stargate.listener; import net.knarcraft.knarlib.formatting.FormatBuilder; import net.knarcraft.knarlib.util.UpdateChecker; import net.knarcraft.stargate.Stargate; -import net.knarcraft.stargate.config.Message; -import net.knarcraft.stargate.config.SGFormatBuilder; -import net.knarcraft.stargate.container.BlockLocation; +import net.knarcraft.stargate.config.formatting.Message; +import net.knarcraft.stargate.config.formatting.SGFormatBuilder; import net.knarcraft.stargate.portal.Portal; import net.knarcraft.stargate.portal.PortalActivator; import net.knarcraft.stargate.portal.PortalHandler; import net.knarcraft.stargate.portal.teleporter.PlayerTeleporter; -import net.knarcraft.stargate.portal.teleporter.VehicleTeleporter; import net.knarcraft.stargate.utility.BungeeHelper; import net.knarcraft.stargate.utility.MaterialHelper; import net.knarcraft.stargate.utility.PermissionHelper; -import net.knarcraft.stargate.utility.TeleportHelper; import net.knarcraft.stargate.utility.UUIDMigrationHelper; import net.md_5.bungee.api.ChatColor; import org.bukkit.Bukkit; import org.bukkit.GameMode; -import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.block.data.type.WallSign; -import org.bukkit.entity.AbstractHorse; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; -import org.bukkit.entity.Vehicle; import org.bukkit.event.Event; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.block.Action; import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.event.player.PlayerJoinEvent; -import org.bukkit.event.player.PlayerMoveEvent; import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.ItemStack; -import org.bukkit.util.Vector; -import org.geysermc.floodgate.api.FloodgateApi; -import org.geysermc.geyser.api.GeyserApi; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import java.util.HashMap; -import java.util.HashSet; import java.util.Map; -import java.util.Set; /** * This listener listens to any player-related events related to stargates */ -@SuppressWarnings("unused") public class PlayerEventListener implements Listener { private static final Map previousEventTimes = new HashMap<>(); - private boolean hasGeyser = true; - private boolean hasFloodgate = true; /** * This event handler handles detection of any player teleporting through a bungee gate @@ -96,198 +78,6 @@ public class PlayerEventListener implements Listener { new PlayerTeleporter(portal, player).teleport(portal, null); } - /** - * This event handler detects if a player moves into a portal - * - * @param event

The player move event which was triggered

- */ - @EventHandler - public void onPlayerMove(@NotNull PlayerMoveEvent event) { - if (event.isCancelled() || event.getTo() == null) { - return; - } - - BlockLocation fromLocation = new BlockLocation(event.getFrom().getBlock()); - BlockLocation toLocation = new BlockLocation(event.getTo().getBlock()); - Player player = event.getPlayer(); - - //Check whether the event needs to be considered - if (!isRelevantMoveEvent(event, player, fromLocation, toLocation)) { - return; - } - Portal entrancePortal = PortalHandler.getByEntrance(toLocation); - //Check an additional block away in case the portal is a bungee portal using END_PORTAL - if (entrancePortal == null) { - entrancePortal = PortalHandler.getByAdjacentEntrance(toLocation); - // This should never realistically be null - if (entrancePortal == null) { - return; - } - } - - Portal destination = entrancePortal.getPortalActivator().getDestination(player); - if (destination == null) { - return; - } - - Entity playerVehicle = player.getVehicle(); - //If the player is in a vehicle, but vehicle handling is disabled, just ignore the player - if (playerVehicle == null || (playerVehicle instanceof LivingEntity && - Stargate.getGateConfig().handleVehicles())) { - teleportPlayer(playerVehicle, player, entrancePortal, destination, event); - } - } - - /** - * Teleports a player, also teleports the player's vehicle if it's a living entity - * - * @param playerVehicle

The vehicle the player is currently sitting in

- * @param player

The player which moved

- * @param entrancePortal

The entrance the player entered

- * @param destination

The destination of the entrance portal

- * @param event

The move event causing the teleportation to trigger

- */ - private void teleportPlayer(@Nullable Entity playerVehicle, @NotNull Player player, @NotNull Portal entrancePortal, - @NotNull Portal destination, @NotNull PlayerMoveEvent event) { - if (playerVehicle instanceof LivingEntity) { - //Make sure any horses are properly tamed - if (playerVehicle instanceof AbstractHorse horse && !horse.isTamed()) { - horse.setTamed(true); - horse.setOwner(player); - } - //Teleport the player's vehicle - player.setVelocity(new Vector()); - new VehicleTeleporter(destination, (Vehicle) playerVehicle).teleportEntity(entrancePortal); - } else { - //Just teleport the player like normal - new PlayerTeleporter(destination, player).teleportPlayer(entrancePortal, event); - } - if (!entrancePortal.getOptions().isQuiet()) { - new SGFormatBuilder(Message.TELEPORTED).success(player); - } - entrancePortal.getPortalOpener().closePortal(false); - } - - /** - * Checks whether a player move event is relevant for this plugin - * - * @param event

The player move event to check

- * @param player

The player which moved

- * @param fromLocation

The location the player is moving from

- * @param toLocation

The location the player is moving to

- * @return

True if the event is relevant

- */ - private boolean isRelevantMoveEvent(@NotNull PlayerMoveEvent event, Player player, - @NotNull BlockLocation fromLocation, @NotNull BlockLocation toLocation) { - //Check to see if the player moved to another block - if (fromLocation.equals(toLocation)) { - return false; - } - - //Get the portal the player entered, if any - Portal entrancePortal = getEnteredPortal(toLocation, player); - if (entrancePortal == null) { - return false; - } - - Portal destination = entrancePortal.getPortalActivator().getDestination(player); - - //Catch always open portals without a valid destination to prevent the user for being teleported and denied - if (!entrancePortal.getOptions().isBungee() && destination == null) { - return false; - } - - //Decide if the anything stops the player from teleport - if (PermissionHelper.playerCannotTeleport(entrancePortal, destination, player, event)) { - return false; - } - - //Decide if the user should be teleported to another bungee server - if (entrancePortal.getOptions().isBungee()) { - if (BungeeHelper.bungeeTeleport(player, entrancePortal, event) && !entrancePortal.getOptions().isQuiet()) { - new SGFormatBuilder(Message.TELEPORTED).success(player); - } - return false; - } - - //Make sure to check if the player has any leashed creatures, even though leashed teleportation is disabled - return TeleportHelper.noLeashedCreaturesPreventTeleportation(player); - } - - /** - * Gets the portal a player entered - * - * @param toLocation

The location the player moved to

- * @param player

The player that moved

- * @return

The portal the player entered, or null if no portal was entered

- */ - private Portal getEnteredPortal(@NotNull BlockLocation toLocation, @NotNull Player player) { - Portal entrancePortal = PortalHandler.getByEntrance(toLocation); - // Return if in an entrance - if (entrancePortal != null) { - return entrancePortal; - } - - //Check an additional block away for special cases like BungeeCord portals using END_PORTAL as its material - entrancePortal = PortalHandler.getByAdjacentEntrance(toLocation); - if (entrancePortal == null) { - return null; - } - - // If END_GATEWAY and END_PORTAL cannot appear, skip further checks - Set entranceMaterials = MaterialHelper.specifiersToMaterials(entrancePortal.getGate().getPortalOpenMaterials()); - if (!entranceMaterials.contains(Material.END_GATEWAY) && !entranceMaterials.contains(Material.END_PORTAL)) { - return null; - } - - // Get the real materials in the entrance, as END_GATEWAY or END_PORTAL may be available, but not chosen - Set materialsInEntrance = new HashSet<>(); - for (BlockLocation location : entrancePortal.getStructure().getEntrances()) { - materialsInEntrance.add(location.getType()); - } - - // Abort if not a special case - if ((!materialsInEntrance.contains(Material.END_GATEWAY) || !isGeyserPlayer(player)) && - (!entrancePortal.getOptions().isBungee() || !materialsInEntrance.contains(Material.END_PORTAL))) { - return null; - } - - return entrancePortal; - } - - /** - * Checks whether the given player is connected through Geyser - * - * @param player

The player to check

- * @return

True if the player is connected through Geyser

- */ - private boolean isGeyserPlayer(@NotNull Player player) { - // Prevent unnecessary checking for non-geyser and floodgate servers - if (!hasGeyser && !hasFloodgate) { - return false; - } - - // Use Geyser API to get connection status - if (hasGeyser) { - try { - return GeyserApi.api().connectionByUuid(player.getUniqueId()) != null; - } catch (NoClassDefFoundError error1) { - hasGeyser = false; - } - } - - // Use Floodgate API to get connection status - if (hasFloodgate) { - try { - return FloodgateApi.getInstance().isFloodgatePlayer(player.getUniqueId()); - } catch (NoClassDefFoundError error2) { - hasFloodgate = false; - } - } - - return false; - } - /** * This event handler detects if a player clicks a button or a sign * diff --git a/src/main/java/net/knarcraft/stargate/listener/PluginEventListener.java b/src/main/java/net/knarcraft/stargate/listener/PluginEventListener.java deleted file mode 100644 index 1981ce5..0000000 --- a/src/main/java/net/knarcraft/stargate/listener/PluginEventListener.java +++ /dev/null @@ -1,60 +0,0 @@ -package net.knarcraft.stargate.listener; - -import net.knarcraft.stargate.Stargate; -import net.knarcraft.stargate.config.Message; -import net.knarcraft.stargate.config.SGFormatBuilder; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.event.server.PluginDisableEvent; -import org.bukkit.event.server.PluginEnableEvent; -import org.bukkit.plugin.Plugin; -import org.jetbrains.annotations.NotNull; - -/** - * This listener listens for any plugins being enabled or disabled to catch the loading of vault - */ -@SuppressWarnings("unused") -public class PluginEventListener implements Listener { - - private final Stargate stargate; - - /** - * Instantiates a new plugin event listener - * - * @param stargate

A reference to the stargate plugin to

- */ - public PluginEventListener(@NotNull Stargate stargate) { - this.stargate = stargate; - } - - /** - * This event listens for and announces that the vault plugin was detected and enabled - * - *

Each time this event is called, the economy handler will try to enable vault

- * - * @param ignored

The actual event called. This is currently not used

- */ - @EventHandler - public void onPluginEnable(@NotNull PluginEnableEvent ignored) { - if (Stargate.getEconomyConfig().setupEconomy(stargate.getServer().getPluginManager())) { - Plugin vault = Stargate.getEconomyConfig().getVault(); - if (vault != null) { - String vaultVersion = vault.getDescription().getVersion(); - Stargate.logInfo(new SGFormatBuilder(Message.VAULT_LOADED).replace("%version%", vaultVersion).toString()); - } - } - } - - /** - * This event listens for the vault plugin being disabled and notifies the console - * - * @param event

The event caused by disabling a plugin

- */ - @EventHandler - public void onPluginDisable(@NotNull PluginDisableEvent event) { - if (event.getPlugin().equals(Stargate.getEconomyConfig().getVault())) { - Stargate.logInfo("Vault plugin lost."); - } - } - -} diff --git a/src/main/java/net/knarcraft/stargate/listener/PortalEventListener.java b/src/main/java/net/knarcraft/stargate/listener/PortalEventListener.java deleted file mode 100644 index 8cf3086..0000000 --- a/src/main/java/net/knarcraft/stargate/listener/PortalEventListener.java +++ /dev/null @@ -1,126 +0,0 @@ -package net.knarcraft.stargate.listener; - -import net.knarcraft.stargate.Stargate; -import net.knarcraft.stargate.container.FromTheEndTeleportation; -import net.knarcraft.stargate.portal.Portal; -import net.knarcraft.stargate.portal.PortalHandler; -import net.knarcraft.stargate.portal.teleporter.PlayerTeleporter; -import net.knarcraft.stargate.utility.PermissionHelper; -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.World; -import org.bukkit.entity.Entity; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.event.entity.EntityPortalEnterEvent; -import org.bukkit.event.player.PlayerRespawnEvent; -import org.bukkit.event.world.PortalCreateEvent; -import org.jetbrains.annotations.NotNull; - -import java.util.HashMap; -import java.util.Map; - -/** - * Listens for and cancels relevant portal events - */ -public class PortalEventListener implements Listener { - - private static final Map playersFromTheEnd = new HashMap<>(); - - /** - * Listens for and aborts vanilla portal creation caused by stargate creation - * - * @param event

The triggered event

- */ - @EventHandler - public void onPortalCreation(@NotNull PortalCreateEvent event) { - if (event.isCancelled()) { - return; - } - //Unnecessary nether portal creation is only triggered by nether pairing - if (event.getReason() == PortalCreateEvent.CreateReason.NETHER_PAIR) { - //If an entity is standing in a Stargate entrance, it can be assumed that the creation is a mistake - Entity entity = event.getEntity(); - if (entity != null && PortalHandler.getByAdjacentEntrance(entity.getLocation()) != null) { - Stargate.debug("PortalEventListener::onPortalCreation", - "Cancelled nether portal create event"); - event.setCancelled(true); - } - } - } - - /** - * Listen for entities entering an artificial end portal - * - * @param event

The triggered event

- */ - @EventHandler - public void onEntityPortalEnter(@NotNull EntityPortalEnterEvent event) { - Location location = event.getLocation(); - World world = location.getWorld(); - Entity entity = event.getEntity(); - - //Hijack normal portal teleportation if teleporting from a stargate, and teleporting from an end portal in the - // end - if (!(entity instanceof Player player) || location.getBlock().getType() != Material.END_PORTAL || - world == null || world.getEnvironment() != World.Environment.THE_END) { - return; - } - - Portal portal = PortalHandler.getByAdjacentEntrance(location); - if (portal == null) { - return; - } - - Stargate.debug("PortalEventListener::onEntityPortalEnter", - "Found player " + player + " entering END_PORTAL " + portal); - - //Decide if the anything stops the player from teleporting - if (PermissionHelper.playerCannotTeleport(portal, portal.getPortalActivator().getDestination(), - player, null) || portal.getOptions().isBungee()) { - //Teleport the player back to the portal they came in, just in case - playersFromTheEnd.put(player, new FromTheEndTeleportation(portal)); - Stargate.debug("PortalEventListener::onEntityPortalEnter", - "Sending player back to the entrance"); - } else { - Portal destination = portal.getPortalActivator().getDestination(); - if (destination != null) { - playersFromTheEnd.put(player, new FromTheEndTeleportation(destination)); - Stargate.debug("PortalEventListener::onEntityPortalEnter", - "Sending player to destination"); - } - } - } - - /** - * Listen for the respawn event to catch players teleporting from the end in an artificial end portal - * - * @param event

The triggered event

- */ - @EventHandler - public void onRespawn(@NotNull PlayerRespawnEvent event) { - Player respawningPlayer = event.getPlayer(); - FromTheEndTeleportation teleportation = playersFromTheEnd.remove(respawningPlayer); - if (teleportation == null) { - return; - } - Portal exitPortal = teleportation.exitPortal(); - - //Overwrite respawn location to respawn in front of the portal - PlayerTeleporter teleporter = new PlayerTeleporter(exitPortal, respawningPlayer); - Location respawnLocation = teleporter.getExit(); - event.setRespawnLocation(respawnLocation); - //Try and force the player if for some reason the changing of respawn location isn't properly handled - Bukkit.getScheduler().scheduleSyncDelayedTask(Stargate.getInstance(), () -> - respawningPlayer.teleport(respawnLocation), 1); - - //Properly close the portal to prevent it from staying in a locked state until it times out - exitPortal.getPortalOpener().closePortal(false); - - Stargate.debug("PortalEventListener::onRespawn", "Overwriting respawn for " + respawningPlayer + - " to " + respawnLocation.getWorld() + ":" + respawnLocation); - } - -} diff --git a/src/main/java/net/knarcraft/stargate/listener/StargateBreakListener.java b/src/main/java/net/knarcraft/stargate/listener/StargateBreakListener.java new file mode 100644 index 0000000..2002474 --- /dev/null +++ b/src/main/java/net/knarcraft/stargate/listener/StargateBreakListener.java @@ -0,0 +1,267 @@ +package net.knarcraft.stargate.listener; + +import net.knarcraft.stargate.Stargate; +import net.knarcraft.stargate.portal.Portal; +import net.knarcraft.stargate.portal.PortalHandler; +import net.knarcraft.stargate.portal.PortalRegistry; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.block.BlockState; +import org.bukkit.block.data.Directional; +import org.bukkit.event.Cancellable; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.block.BlockBurnEvent; +import org.bukkit.event.block.BlockDispenseEvent; +import org.bukkit.event.block.BlockExplodeEvent; +import org.bukkit.event.block.BlockFadeEvent; +import org.bukkit.event.block.BlockFertilizeEvent; +import org.bukkit.event.block.BlockFormEvent; +import org.bukkit.event.block.BlockFromToEvent; +import org.bukkit.event.block.BlockIgniteEvent; +import org.bukkit.event.block.BlockMultiPlaceEvent; +import org.bukkit.event.block.BlockPhysicsEvent; +import org.bukkit.event.block.BlockPistonExtendEvent; +import org.bukkit.event.block.BlockPistonRetractEvent; +import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.block.EntityBlockFormEvent; +import org.bukkit.event.block.LeavesDecayEvent; +import org.bukkit.event.block.SpongeAbsorbEvent; +import org.bukkit.event.block.TNTPrimeEvent; +import org.bukkit.event.entity.CreatureSpawnEvent; +import org.bukkit.event.entity.EntityBreakDoorEvent; +import org.bukkit.event.entity.EntityChangeBlockEvent; +import org.bukkit.event.entity.EntityExplodeEvent; +import org.bukkit.event.entity.EntityPlaceEvent; +import org.bukkit.event.player.PlayerBucketEmptyEvent; +import org.bukkit.event.world.PortalCreateEvent; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +/** + * A listener for any events that might cause a Stargate to be altered or break + */ +public class StargateBreakListener implements Listener { + + /** + * Cancels blocks from being placed in the Stargate's entrance + * + * @param event

The event to check and possibly cancel

+ */ + @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) + public void onBlockPlace(@NotNull BlockPlaceEvent event) { + if (!Stargate.getGateConfig().protectEntrance()) { + return; + } + Block block = event.getBlock(); + Portal portal = PortalHandler.getByEntrance(block); + if (portal != null) { + //Prevent blocks from being placed in the entrance, if protectEntrance is enabled, as breaking the block + // would destroy the portal + event.setCancelled(true); + } + } + + /** + * This method catches any explosion events + * + *

If destroyed by explosions is enabled, any portals destroyed by the explosion will be unregistered. If not, + * the explosion will be cancelled.

+ * + * @param event

The triggered explosion event

+ */ + @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) + public void onEntityExplode(@NotNull EntityExplodeEvent event) { + for (Block block : event.blockList()) { + Portal portal = PortalHandler.getByBlock(block); + if (portal == null) { + continue; + } + if (Stargate.getGateConfig().destroyedByExplosion()) { + PortalRegistry.unregisterPortal(portal, true); + } else { + event.setCancelled(true); + break; + } + } + } + + @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) + public void onCreatureSpawn(@NotNull CreatureSpawnEvent event) { + //Prevent Zombified Piglins and other creatures form spawning at stargates + if (event.getSpawnReason() == CreatureSpawnEvent.SpawnReason.NETHER_PORTAL && + PortalHandler.getByEntrance(event.getLocation()) != null) { + event.setCancelled(true); + Stargate.debug("EntitySpawnListener", "Prevented creature from spawning at Stargate"); + } + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onPistonExtend(BlockPistonExtendEvent event) { + cancelPistonIfNeeded(event.getBlocks(), event.getDirection(), event); + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onPistonRetract(@NotNull BlockPistonRetractEvent event) { + cancelPistonIfNeeded(event.getBlocks(), event.getDirection(), event); + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onBlockExplode(@NotNull BlockExplodeEvent event) { + cancelIfAtEntrance(event, event.blockList()); + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onBlockFromTo(@NotNull BlockFromToEvent event) { + cancelIfAtEntrance(event, event.getToBlock()); + cancelIfAtEntrance(event, event.getBlock()); + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onBlockFormEvent(@NotNull BlockFormEvent event) { + cancelIfAtEntrance(event, event.getBlock()); + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onBlockPhysics(@NotNull BlockPhysicsEvent event) { + cancelIfAtEntrance(event, event.getBlock()); + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onBlockBurn(@NotNull BlockBurnEvent event) { + cancelIfAtEntrance(event, event.getBlock()); + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onBlockIgnite(@NotNull BlockIgniteEvent event) { + cancelIfAtEntrance(event, event.getBlock()); + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onBlockFade(@NotNull BlockFadeEvent event) { + cancelIfAtEntrance(event, event.getBlock()); + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onBlockFertilize(@NotNull BlockFertilizeEvent event) { + cancelIfAtEntrance(event, event.getBlock()); + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onBlockMultiPlace(@NotNull BlockMultiPlaceEvent event) { + cancelIfAtEntrance(event, getBlocksFromBlockStates(event.getReplacedBlockStates())); + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onEntityBlockForm(@NotNull EntityBlockFormEvent event) { + cancelIfAtEntrance(event, event.getBlock()); + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onLeavesDecay(@NotNull LeavesDecayEvent event) { + cancelIfAtEntrance(event, event.getBlock()); + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onSpongeAbsorb(@NotNull SpongeAbsorbEvent event) { + cancelIfAtEntrance(event, getBlocksFromBlockStates(event.getBlocks())); + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onEntityChangeBlock(@NotNull EntityChangeBlockEvent event) { + cancelIfAtEntrance(event, event.getBlock()); + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onEntityBreakDoor(@NotNull EntityBreakDoorEvent event) { + cancelIfAtEntrance(event, event.getBlock()); + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onPortalCreate(@NotNull PortalCreateEvent event) { + cancelIfAtEntrance(event, getBlocksFromBlockStates(event.getBlocks())); + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onEntityPlace(@NotNull EntityPlaceEvent event) { + cancelIfAtEntrance(event, event.getBlock()); + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onPlayerBucketEmpty(@NotNull PlayerBucketEmptyEvent event) { + cancelIfAtEntrance(event, event.getBlock()); + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onBlockDispense(@NotNull BlockDispenseEvent event) { + if (event.getBlock().getBlockData() instanceof Directional dispenser) { + cancelIfAtEntrance(event, event.getBlock().getRelative(dispenser.getFacing())); + } + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onTNTPrime(@NotNull TNTPrimeEvent tntPrimeEvent) { + cancelIfAtEntrance(tntPrimeEvent, tntPrimeEvent.getBlock()); + } + + /** + * Cancels the given event if it involves a Stargate's entrance + * + * @param event

The event to cancel

+ * @param block

The block in question

+ */ + private boolean cancelIfAtEntrance(@NotNull Cancellable event, @NotNull Block block) { + if (PortalHandler.getByEntrance(block) != null || PortalHandler.getByControl(block) != null || + PortalHandler.getByBlock(block) != null) { + event.setCancelled(true); + return true; + } else { + return false; + } + } + + /** + * Cancels the given event if it involves a Stargate's entrance + * + * @param event

The event to cancel

+ * @param blocks

The blocks in question

+ */ + private void cancelIfAtEntrance(@NotNull Cancellable event, @NotNull List blocks) { + for (Block block : blocks) { + if (cancelIfAtEntrance(event, block)) { + return; + } + } + } + + /** + * Gets a list of blocks from a list of block states + * + * @param blockStates

The block states to convert into blocks

+ * @return

The corresponding blocks

+ */ + @NotNull + private List getBlocksFromBlockStates(@NotNull List blockStates) { + return blockStates.stream().map(BlockState::getBlock).toList(); + } + + /** + * Cancels the movement of a piston if it would interfere with a Stargate + * + * @param blocks

The blocks involved in the move

+ * @param blockFace

The block face of the piston

+ * @param event

The event to possibly cancel

+ */ + private void cancelPistonIfNeeded(@NotNull List blocks, @NotNull BlockFace blockFace, + @NotNull Cancellable event) { + cancelIfAtEntrance(event, blocks); + if (event.isCancelled()) { + return; + } + List movedBlocks = blocks.stream().map(block -> block.getRelative(blockFace)).toList(); + cancelIfAtEntrance(event, movedBlocks); + } + +} diff --git a/src/main/java/net/knarcraft/stargate/listener/BlockEventListener.java b/src/main/java/net/knarcraft/stargate/listener/StargateCreateDestroyListener.java similarity index 57% rename from src/main/java/net/knarcraft/stargate/listener/BlockEventListener.java rename to src/main/java/net/knarcraft/stargate/listener/StargateCreateDestroyListener.java index 0200d93..efeaece 100644 --- a/src/main/java/net/knarcraft/stargate/listener/BlockEventListener.java +++ b/src/main/java/net/knarcraft/stargate/listener/StargateCreateDestroyListener.java @@ -1,8 +1,8 @@ package net.knarcraft.stargate.listener; import net.knarcraft.stargate.Stargate; -import net.knarcraft.stargate.config.Message; -import net.knarcraft.stargate.config.SGFormatBuilder; +import net.knarcraft.stargate.config.formatting.Message; +import net.knarcraft.stargate.config.formatting.SGFormatBuilder; import net.knarcraft.stargate.container.BlockChangeRequest; import net.knarcraft.stargate.container.BlockLocation; import net.knarcraft.stargate.event.StargateDestroyEvent; @@ -11,58 +11,23 @@ import net.knarcraft.stargate.portal.PortalCreator; import net.knarcraft.stargate.portal.PortalHandler; import net.knarcraft.stargate.portal.PortalRegistry; import net.knarcraft.stargate.utility.EconomyHelper; -import net.knarcraft.stargate.utility.MaterialHelper; import net.knarcraft.stargate.utility.PermissionHelper; import net.knarcraft.stargate.utility.PortalFileHelper; import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.block.data.type.WallSign; import org.bukkit.entity.Player; -import org.bukkit.entity.Snowman; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.block.BlockBreakEvent; -import org.bukkit.event.block.BlockFromToEvent; -import org.bukkit.event.block.BlockPhysicsEvent; -import org.bukkit.event.block.BlockPistonEvent; -import org.bukkit.event.block.BlockPistonExtendEvent; -import org.bukkit.event.block.BlockPistonRetractEvent; -import org.bukkit.event.block.BlockPlaceEvent; -import org.bukkit.event.block.EntityBlockFormEvent; import org.bukkit.event.block.SignChangeEvent; import org.jetbrains.annotations.NotNull; -import java.util.List; - /** * This class is responsible for listening to relevant block events related to creating and breaking portals */ -public class BlockEventListener implements Listener { - - /** - * Detects snowmen ruining portals - * - *

If entrance protection or portal verification is enabled, the snowman will be prevented from placing snow in - * the portal entrance.

- * - * @param event

The triggered event

- */ - @EventHandler(ignoreCancelled = true) - public void onBlockFormedByEntity(@NotNull EntityBlockFormEvent event) { - if ((!Stargate.getGateConfig().protectEntrance() && - !Stargate.getGateConfig().verifyPortals())) { - return; - } - //We are only interested in snowman events - if (!(event.getEntity() instanceof Snowman)) { - return; - } - //Cancel the event if a snowman is trying to place snow in the portal's entrance - if (PortalHandler.getByEntrance(event.getBlock()) != null) { - event.setCancelled(true); - } - } +public class StargateCreateDestroyListener implements Listener { /** * Detects sign changes to detect if the user is creating a new gate @@ -97,20 +62,6 @@ public class BlockEventListener implements Listener { portal::drawSign, 1); } - @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) - public void onBlockPlace(@NotNull BlockPlaceEvent event) { - if (!Stargate.getGateConfig().protectEntrance()) { - return; - } - Block block = event.getBlock(); - Portal portal = PortalHandler.getByEntrance(block); - if (portal != null) { - //Prevent blocks from being placed in the entrance, if protectEntrance is enabled, as breaking the block - // would destroy the portal - event.setCancelled(true); - } - } - /** * Detects block breaking to detect if the user is destroying a gate * @@ -206,77 +157,4 @@ public class BlockEventListener implements Listener { return true; } - /** - * Prevents any block physics events which may damage parts of the portal - * - * @param event

The event to check and possibly cancel

- */ - @EventHandler(ignoreCancelled = true) - public void onBlockPhysics(@NotNull BlockPhysicsEvent event) { - Block block = event.getBlock(); - Portal portal = null; - - if (block.getType() == Material.NETHER_PORTAL) { - portal = PortalHandler.getByEntrance(block); - } else if (MaterialHelper.isButtonCompatible(block.getType())) { - portal = PortalHandler.getByControl(block); - } - if (portal != null) { - event.setCancelled(true); - } - } - - /** - * Cancels any block move events which may cause a block to enter the opening of a portal - * - * @param event

The event to check and possibly cancel

- */ - @EventHandler(ignoreCancelled = true) - public void onBlockFromTo(@NotNull BlockFromToEvent event) { - Portal portal = PortalHandler.getByEntrance(event.getBlock()); - - if (portal != null && event.getBlock().getY() == event.getToBlock().getY()) { - event.setCancelled(true); - } - } - - /** - * Cancels any piston extend events if the target block is part of a portal - * - * @param event

The event to check and possibly cancel

- */ - @EventHandler(ignoreCancelled = true) - public void onPistonExtend(@NotNull BlockPistonExtendEvent event) { - cancelPistonEvent(event, event.getBlocks()); - } - - /** - * Cancels any piston retract events if the target block is part of a portal - * - * @param event

The event to check and possibly cancel

- */ - @EventHandler(ignoreCancelled = true) - public void onPistonRetract(@NotNull BlockPistonRetractEvent event) { - if (!event.isSticky()) { - return; - } - cancelPistonEvent(event, event.getBlocks()); - } - - /** - * Cancels a piston event if it would destroy a portal - * - * @param event

The event to cancel

- * @param blocks

The blocks included in the event

- */ - private void cancelPistonEvent(@NotNull BlockPistonEvent event, @NotNull List blocks) { - for (Block block : blocks) { - Portal portal = PortalHandler.getByBlock(block); - if (portal != null) { - event.setCancelled(true); - return; - } - } - } - } diff --git a/src/main/java/net/knarcraft/stargate/listener/StargateTeleportListener.java b/src/main/java/net/knarcraft/stargate/listener/StargateTeleportListener.java new file mode 100644 index 0000000..d58a3b8 --- /dev/null +++ b/src/main/java/net/knarcraft/stargate/listener/StargateTeleportListener.java @@ -0,0 +1,530 @@ +package net.knarcraft.stargate.listener; + +import net.knarcraft.stargate.Stargate; +import net.knarcraft.stargate.config.formatting.Message; +import net.knarcraft.stargate.config.formatting.SGFormatBuilder; +import net.knarcraft.stargate.container.BlockLocation; +import net.knarcraft.stargate.container.FromTheEndTeleportation; +import net.knarcraft.stargate.portal.Portal; +import net.knarcraft.stargate.portal.PortalHandler; +import net.knarcraft.stargate.portal.teleporter.PlayerTeleporter; +import net.knarcraft.stargate.portal.teleporter.VehicleTeleporter; +import net.knarcraft.stargate.utility.BungeeHelper; +import net.knarcraft.stargate.utility.EconomyHelper; +import net.knarcraft.stargate.utility.EntityHelper; +import net.knarcraft.stargate.utility.MaterialHelper; +import net.knarcraft.stargate.utility.PermissionHelper; +import net.knarcraft.stargate.utility.TeleportHelper; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.entity.AbstractHorse; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.entity.Vehicle; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityPortalEnterEvent; +import org.bukkit.event.entity.EntityPortalEvent; +import org.bukkit.event.player.PlayerMoveEvent; +import org.bukkit.event.player.PlayerRespawnEvent; +import org.bukkit.event.player.PlayerTeleportEvent; +import org.bukkit.event.vehicle.VehicleMoveEvent; +import org.bukkit.util.Vector; +import org.geysermc.floodgate.api.FloodgateApi; +import org.geysermc.geyser.api.GeyserApi; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * This listener listens for the vehicle move event to teleport vehicles through portals + */ +public class StargateTeleportListener implements Listener { + + private static final Map playersFromTheEnd = new HashMap<>(); + private boolean hasGeyser = true; + private boolean hasFloodgate = true; + + /** + * This event handler handles some special teleportation events + * + *

This event cancels nether portal, end gateway and end portal teleportation if the user teleported from a + * stargate entrance. This prevents the user from just teleporting to the nether or the end with portals using + * the special teleportation blocks.

+ * + * @param event

The event to check and possibly cancel

+ */ + @EventHandler + public void onPlayerTeleport(@NotNull PlayerTeleportEvent event) { + PlayerTeleportEvent.TeleportCause cause = event.getCause(); + + //Block normal portal teleportation if teleporting from a stargate + if (!event.isCancelled() && (cause == PlayerTeleportEvent.TeleportCause.NETHER_PORTAL || + cause == PlayerTeleportEvent.TeleportCause.END_GATEWAY || + cause == PlayerTeleportEvent.TeleportCause.END_PORTAL) + && PortalHandler.getByAdjacentEntrance(event.getFrom()) != null) { + event.setCancelled(true); + } + } + + /** + * This event handler prevents sending entities to the normal nether instead of the stargate target + * + * @param event

The event to check and possibly cancel

+ */ + @EventHandler(priority = EventPriority.LOWEST) + public void onPortalEvent(@NotNull EntityPortalEvent event) { + if (event.isCancelled()) { + return; + } + + Entity entity = event.getEntity(); + //Cancel normal portal event is near a stargate + if (PortalHandler.getByAdjacentEntrance(event.getFrom(), EntityHelper.getEntityMaxSizeInt(entity)) != null) { + event.setCancelled(true); + } + } + + /** + * Check for a vehicle moving through a portal + * + * @param event

The triggered move event

+ */ + @EventHandler + public void onVehicleMove(@NotNull VehicleMoveEvent event) { + if (!Stargate.getGateConfig().handleVehicles()) { + return; + } + List passengers = event.getVehicle().getPassengers(); + Vehicle vehicle = event.getVehicle(); + + Portal entrancePortal; + int entitySize = EntityHelper.getEntityMaxSizeInt(vehicle); + if (EntityHelper.getEntityMaxSize(vehicle) > 1) { + entrancePortal = PortalHandler.getByAdjacentEntrance(event.getTo(), entitySize - 1); + } else { + entrancePortal = PortalHandler.getByEntrance(event.getTo()); + } + + //Return if the portal cannot be teleported through + if (entrancePortal == null || !entrancePortal.isOpen() || entrancePortal.getOptions().isBungee()) { + return; + } + + teleportVehicle(passengers, entrancePortal, vehicle); + } + + /** + * This event handler detects if a player moves into a portal + * + * @param event

The player move event which was triggered

+ */ + @EventHandler + public void onPlayerMove(@NotNull PlayerMoveEvent event) { + if (event.isCancelled() || event.getTo() == null) { + return; + } + + BlockLocation fromLocation = new BlockLocation(event.getFrom().getBlock()); + BlockLocation toLocation = new BlockLocation(event.getTo().getBlock()); + Player player = event.getPlayer(); + + //Check whether the event needs to be considered + if (!isRelevantMoveEvent(event, player, fromLocation, toLocation)) { + return; + } + Portal entrancePortal = PortalHandler.getByEntrance(toLocation); + //Check an additional block away in case the portal is a bungee portal using END_PORTAL + if (entrancePortal == null) { + entrancePortal = PortalHandler.getByAdjacentEntrance(toLocation); + // This should never realistically be null + if (entrancePortal == null) { + return; + } + } + + Portal destination = entrancePortal.getPortalActivator().getDestination(player); + if (destination == null) { + return; + } + + Entity playerVehicle = player.getVehicle(); + //If the player is in a vehicle, but vehicle handling is disabled, just ignore the player + if (playerVehicle == null || (playerVehicle instanceof LivingEntity && + Stargate.getGateConfig().handleVehicles())) { + teleportPlayer(playerVehicle, player, entrancePortal, destination, event); + } + } + + /** + * Listen for entities entering an artificial end portal + * + * @param event

The triggered event

+ */ + @EventHandler + public void onEntityPortalEnter(@NotNull EntityPortalEnterEvent event) { + Location location = event.getLocation(); + World world = location.getWorld(); + Entity entity = event.getEntity(); + + //Hijack normal portal teleportation if teleporting from a stargate, and teleporting from an end portal in the + // end + if (!(entity instanceof Player player) || location.getBlock().getType() != Material.END_PORTAL || + world == null || world.getEnvironment() != World.Environment.THE_END) { + return; + } + + Portal portal = PortalHandler.getByAdjacentEntrance(location); + if (portal == null) { + return; + } + + Stargate.debug("PortalEventListener::onEntityPortalEnter", + "Found player " + player + " entering END_PORTAL " + portal); + + //Decide if the anything stops the player from teleporting + if (PermissionHelper.playerCannotTeleport(portal, portal.getPortalActivator().getDestination(), + player, null) || portal.getOptions().isBungee()) { + //Teleport the player back to the portal they came in, just in case + playersFromTheEnd.put(player, new FromTheEndTeleportation(portal)); + Stargate.debug("PortalEventListener::onEntityPortalEnter", + "Sending player back to the entrance"); + } else { + Portal destination = portal.getPortalActivator().getDestination(); + if (destination != null) { + playersFromTheEnd.put(player, new FromTheEndTeleportation(destination)); + Stargate.debug("PortalEventListener::onEntityPortalEnter", + "Sending player to destination"); + } + } + } + + /** + * Listen for the respawn event to catch players teleporting from the end in an artificial end portal + * + * @param event

The triggered event

+ */ + @EventHandler + public void onRespawn(@NotNull PlayerRespawnEvent event) { + Player respawningPlayer = event.getPlayer(); + FromTheEndTeleportation teleportation = playersFromTheEnd.remove(respawningPlayer); + if (teleportation == null) { + return; + } + Portal exitPortal = teleportation.exitPortal(); + + //Overwrite respawn location to respawn in front of the portal + PlayerTeleporter teleporter = new PlayerTeleporter(exitPortal, respawningPlayer); + Location respawnLocation = teleporter.getExit(); + event.setRespawnLocation(respawnLocation); + //Try and force the player if for some reason the changing of respawn location isn't properly handled + Bukkit.getScheduler().scheduleSyncDelayedTask(Stargate.getInstance(), () -> + respawningPlayer.teleport(respawnLocation), 1); + + //Properly close the portal to prevent it from staying in a locked state until it times out + exitPortal.getPortalOpener().closePortal(false); + + Stargate.debug("PortalEventListener::onRespawn", "Overwriting respawn for " + respawningPlayer + + " to " + respawnLocation.getWorld() + ":" + respawnLocation); + } + + /** + * Teleports a vehicle through a stargate + * + * @param passengers

The passengers inside the vehicle

+ * @param entrancePortal

The portal the vehicle is entering

+ * @param vehicle

The vehicle passing through

+ */ + private static void teleportVehicle(@NotNull List passengers, @NotNull Portal entrancePortal, + @NotNull Vehicle vehicle) { + String route = "VehicleEventListener::teleportVehicle"; + + if (!passengers.isEmpty() && TeleportHelper.containsPlayer(passengers)) { + Stargate.debug(route, "Found passenger vehicle"); + teleportPlayerAndVehicle(entrancePortal, vehicle); + } else { + Stargate.debug(route, "Found vehicle without players"); + Portal destinationPortal = entrancePortal.getPortalActivator().getDestination(); + if (destinationPortal == null) { + Stargate.debug(route, "Unable to find portal destination"); + return; + } + Stargate.debug("vehicleTeleport", destinationPortal.getWorld() + " " + + destinationPortal.getSignLocation()); + new VehicleTeleporter(destinationPortal, vehicle).teleportEntity(entrancePortal); + } + } + + /** + * Teleports a player and the vehicle the player sits in + * + * @param entrancePortal

The portal the minecart entered

+ * @param vehicle

The vehicle to teleport

+ */ + private static void teleportPlayerAndVehicle(@NotNull Portal entrancePortal, @NotNull Vehicle vehicle) { + Entity rootEntity = vehicle; + while (rootEntity.getVehicle() != null) { + rootEntity = rootEntity.getVehicle(); + } + List players = TeleportHelper.getPlayers(rootEntity.getPassengers()); + Portal destinationPortal = getDestinationPortal(players, entrancePortal); + + //Cancel the teleport if no players activated the portal, or if any players are denied access + boolean cancelTeleportation = false; + for (Player player : players) { + if (destinationPortal == null) { + cancelTeleportation = true; + if (!entrancePortal.getOptions().isQuiet()) { + new SGFormatBuilder(Message.INVALID_DESTINATION).error(player); + } + } else if (!TeleportHelper.playerCanTeleport(player, entrancePortal, destinationPortal)) { + cancelTeleportation = true; + } + } + if (cancelTeleportation || destinationPortal == null) { + return; + } + + //Take payment from all players + if (!takePayment(players, entrancePortal, destinationPortal)) { + return; + } + + // Perform the teleportation + teleportPlayerAndVehicle(players, vehicle, entrancePortal, destinationPortal); + } + + /** + * Performs the teleportation of one or more players in a vehicle + * + * @param players

The players to be teleported

+ * @param vehicle

The vehicle that triggered the teleportation

+ * @param entrancePortal

The portal the player(s) and vehicle entered from

+ * @param destinationPortal

The portal the player(s) and vehicle are teleporting to

+ */ + private static void teleportPlayerAndVehicle(@NotNull List players, @NotNull Vehicle vehicle, + @NotNull Portal entrancePortal, @NotNull Portal destinationPortal) { + //Teleport the vehicle and inform the user if the vehicle was teleported + boolean teleported = new VehicleTeleporter(destinationPortal, vehicle).teleportEntity(entrancePortal); + if (!teleported) { + return; + } + + if (!entrancePortal.getOptions().isQuiet()) { + for (Player player : players) { + new SGFormatBuilder(Message.TELEPORTED).success(player); + } + } + entrancePortal.getPortalOpener().closePortal(false); + } + + /** + * Tries to get the destination portal selected by one of the players included in the teleportation + * + * @param players

The players to be teleported

+ * @param entrancePortal

The portal the players are entering

+ * @return

The destination portal, or null if not found

+ */ + @Nullable + private static Portal getDestinationPortal(@NotNull List players, @NotNull Portal entrancePortal) { + for (Player player : players) { + //The entrance portal must be open for one player for the teleportation to happen + if (!entrancePortal.getPortalOpener().isOpenFor(player)) { + continue; + } + + //Check if any of the players has selected the destination + Portal possibleDestinationPortal = entrancePortal.getPortalActivator().getDestination(player); + if (possibleDestinationPortal != null) { + return possibleDestinationPortal; + } + } + + return null; + } + + /** + * Takes payment for the given players + * + * @param players

The players to take payment from

+ * @param entrancePortal

The portal the players are travelling from

+ * @param destinationPortal

The portal the players are travelling to

+ * @return

True if payment was successfully taken, false otherwise

+ */ + private static boolean takePayment(@NotNull List players, @NotNull Portal entrancePortal, + @NotNull Portal destinationPortal) { + for (Player player : players) { + //To prevent the case where the first passenger pays and then the second passenger is denied, this has to be + // run after it has been confirmed that all passengers are able to pay. Also note that some players might + // not have to pay, and thus the cost check has to be in the loop, + int cost = EconomyHelper.getUseCost(player, entrancePortal, destinationPortal); + if (cost > 0) { + if (EconomyHelper.cannotPayTeleportFee(entrancePortal, player, cost)) { + return false; + } + } + } + + return true; + } + + /** + * Teleports a player, also teleports the player's vehicle if it's a living entity + * + * @param playerVehicle

The vehicle the player is currently sitting in

+ * @param player

The player which moved

+ * @param entrancePortal

The entrance the player entered

+ * @param destination

The destination of the entrance portal

+ * @param event

The move event causing the teleportation to trigger

+ */ + private void teleportPlayer(@Nullable Entity playerVehicle, @NotNull Player player, @NotNull Portal entrancePortal, + @NotNull Portal destination, @NotNull PlayerMoveEvent event) { + if (playerVehicle instanceof LivingEntity) { + //Make sure any horses are properly tamed + if (playerVehicle instanceof AbstractHorse horse && !horse.isTamed()) { + horse.setTamed(true); + horse.setOwner(player); + } + //Teleport the player's vehicle + player.setVelocity(new Vector()); + new VehicleTeleporter(destination, (Vehicle) playerVehicle).teleportEntity(entrancePortal); + } else { + //Just teleport the player like normal + new PlayerTeleporter(destination, player).teleportPlayer(entrancePortal, event); + } + if (!entrancePortal.getOptions().isQuiet()) { + new SGFormatBuilder(Message.TELEPORTED).success(player); + } + entrancePortal.getPortalOpener().closePortal(false); + } + + /** + * Checks whether a player move event is relevant for this plugin + * + * @param event

The player move event to check

+ * @param player

The player which moved

+ * @param fromLocation

The location the player is moving from

+ * @param toLocation

The location the player is moving to

+ * @return

True if the event is relevant

+ */ + private boolean isRelevantMoveEvent(@NotNull PlayerMoveEvent event, Player player, + @NotNull BlockLocation fromLocation, @NotNull BlockLocation toLocation) { + //Check to see if the player moved to another block + if (fromLocation.equals(toLocation)) { + return false; + } + + //Get the portal the player entered, if any + Portal entrancePortal = getEnteredPortal(toLocation, player); + if (entrancePortal == null) { + return false; + } + + Portal destination = entrancePortal.getPortalActivator().getDestination(player); + + //Catch always open portals without a valid destination to prevent the user for being teleported and denied + if (!entrancePortal.getOptions().isBungee() && destination == null) { + return false; + } + + //Decide if the anything stops the player from teleport + if (PermissionHelper.playerCannotTeleport(entrancePortal, destination, player, event)) { + return false; + } + + //Decide if the user should be teleported to another bungee server + if (entrancePortal.getOptions().isBungee()) { + if (BungeeHelper.bungeeTeleport(player, entrancePortal, event) && !entrancePortal.getOptions().isQuiet()) { + new SGFormatBuilder(Message.TELEPORTED).success(player); + } + return false; + } + + //Make sure to check if the player has any leashed creatures, even though leashed teleportation is disabled + return TeleportHelper.noLeashedCreaturesPreventTeleportation(player); + } + + /** + * Gets the portal a player entered + * + * @param toLocation

The location the player moved to

+ * @param player

The player that moved

+ * @return

The portal the player entered, or null if no portal was entered

+ */ + private Portal getEnteredPortal(@NotNull BlockLocation toLocation, @NotNull Player player) { + Portal entrancePortal = PortalHandler.getByEntrance(toLocation); + // Return if in an entrance + if (entrancePortal != null) { + return entrancePortal; + } + + //Check an additional block away for special cases like BungeeCord portals using END_PORTAL as its material + entrancePortal = PortalHandler.getByAdjacentEntrance(toLocation); + if (entrancePortal == null) { + return null; + } + + // If END_GATEWAY and END_PORTAL cannot appear, skip further checks + Set entranceMaterials = MaterialHelper.specifiersToMaterials(entrancePortal.getGate().getPortalOpenMaterials()); + if (!entranceMaterials.contains(Material.END_GATEWAY) && !entranceMaterials.contains(Material.END_PORTAL)) { + return null; + } + + // Get the real materials in the entrance, as END_GATEWAY or END_PORTAL may be available, but not chosen + Set materialsInEntrance = new HashSet<>(); + for (BlockLocation location : entrancePortal.getStructure().getEntrances()) { + materialsInEntrance.add(location.getType()); + } + + // Abort if not a special case + if ((!materialsInEntrance.contains(Material.END_GATEWAY) || !isGeyserPlayer(player)) && + (!entrancePortal.getOptions().isBungee() || !materialsInEntrance.contains(Material.END_PORTAL))) { + return null; + } + + return entrancePortal; + } + + /** + * Checks whether the given player is connected through Geyser + * + * @param player

The player to check

+ * @return

True if the player is connected through Geyser

+ */ + private boolean isGeyserPlayer(@NotNull Player player) { + // Prevent unnecessary checking for non-geyser and floodgate servers + if (!hasGeyser && !hasFloodgate) { + return false; + } + + // Use Geyser API to get connection status + if (hasGeyser) { + try { + return GeyserApi.api().connectionByUuid(player.getUniqueId()) != null; + } catch (NoClassDefFoundError error1) { + hasGeyser = false; + } + } + + // Use Floodgate API to get connection status + if (hasFloodgate) { + try { + return FloodgateApi.getInstance().isFloodgatePlayer(player.getUniqueId()); + } catch (NoClassDefFoundError error2) { + hasFloodgate = false; + } + } + + return false; + } + +} diff --git a/src/main/java/net/knarcraft/stargate/listener/TeleportEventListener.java b/src/main/java/net/knarcraft/stargate/listener/TeleportEventListener.java deleted file mode 100644 index 34ab7a6..0000000 --- a/src/main/java/net/knarcraft/stargate/listener/TeleportEventListener.java +++ /dev/null @@ -1,37 +0,0 @@ -package net.knarcraft.stargate.listener; - -import net.knarcraft.stargate.portal.PortalHandler; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.event.player.PlayerTeleportEvent; -import org.jetbrains.annotations.NotNull; - -/** - * This listener listens to teleportation-related events - */ -@SuppressWarnings("unused") -public class TeleportEventListener implements Listener { - - /** - * This event handler handles some special teleportation events - * - *

This event cancels nether portal, end gateway and end portal teleportation if the user teleported from a - * stargate entrance. This prevents the user from just teleporting to the nether or the end with portals using - * the special teleportation blocks.

- * - * @param event

The event to check and possibly cancel

- */ - @EventHandler - public void onPlayerTeleport(@NotNull PlayerTeleportEvent event) { - PlayerTeleportEvent.TeleportCause cause = event.getCause(); - - //Block normal portal teleportation if teleporting from a stargate - if (!event.isCancelled() && (cause == PlayerTeleportEvent.TeleportCause.NETHER_PORTAL || - cause == PlayerTeleportEvent.TeleportCause.END_GATEWAY || - cause == PlayerTeleportEvent.TeleportCause.END_PORTAL) - && PortalHandler.getByAdjacentEntrance(event.getFrom()) != null) { - event.setCancelled(true); - } - } - -} diff --git a/src/main/java/net/knarcraft/stargate/listener/VehicleEventListener.java b/src/main/java/net/knarcraft/stargate/listener/VehicleEventListener.java deleted file mode 100644 index 442e1e2..0000000 --- a/src/main/java/net/knarcraft/stargate/listener/VehicleEventListener.java +++ /dev/null @@ -1,198 +0,0 @@ -package net.knarcraft.stargate.listener; - -import net.knarcraft.stargate.Stargate; -import net.knarcraft.stargate.config.Message; -import net.knarcraft.stargate.config.SGFormatBuilder; -import net.knarcraft.stargate.portal.Portal; -import net.knarcraft.stargate.portal.PortalHandler; -import net.knarcraft.stargate.portal.teleporter.VehicleTeleporter; -import net.knarcraft.stargate.utility.EconomyHelper; -import net.knarcraft.stargate.utility.EntityHelper; -import net.knarcraft.stargate.utility.TeleportHelper; -import org.bukkit.entity.Entity; -import org.bukkit.entity.Player; -import org.bukkit.entity.Vehicle; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.event.vehicle.VehicleMoveEvent; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.List; - -/** - * This listener listens for the vehicle move event to teleport vehicles through portals - */ -@SuppressWarnings("unused") -public class VehicleEventListener implements Listener { - - /** - * Check for a vehicle moving through a portal - * - * @param event

The triggered move event

- */ - @EventHandler - public void onVehicleMove(@NotNull VehicleMoveEvent event) { - if (!Stargate.getGateConfig().handleVehicles()) { - return; - } - List passengers = event.getVehicle().getPassengers(); - Vehicle vehicle = event.getVehicle(); - - Portal entrancePortal; - int entitySize = EntityHelper.getEntityMaxSizeInt(vehicle); - if (EntityHelper.getEntityMaxSize(vehicle) > 1) { - entrancePortal = PortalHandler.getByAdjacentEntrance(event.getTo(), entitySize - 1); - } else { - entrancePortal = PortalHandler.getByEntrance(event.getTo()); - } - - //Return if the portal cannot be teleported through - if (entrancePortal == null || !entrancePortal.isOpen() || entrancePortal.getOptions().isBungee()) { - return; - } - - teleportVehicle(passengers, entrancePortal, vehicle); - } - - /** - * Teleports a vehicle through a stargate - * - * @param passengers

The passengers inside the vehicle

- * @param entrancePortal

The portal the vehicle is entering

- * @param vehicle

The vehicle passing through

- */ - private static void teleportVehicle(@NotNull List passengers, @NotNull Portal entrancePortal, - @NotNull Vehicle vehicle) { - String route = "VehicleEventListener::teleportVehicle"; - - if (!passengers.isEmpty() && TeleportHelper.containsPlayer(passengers)) { - Stargate.debug(route, "Found passenger vehicle"); - teleportPlayerAndVehicle(entrancePortal, vehicle); - } else { - Stargate.debug(route, "Found vehicle without players"); - Portal destinationPortal = entrancePortal.getPortalActivator().getDestination(); - if (destinationPortal == null) { - Stargate.debug(route, "Unable to find portal destination"); - return; - } - Stargate.debug("vehicleTeleport", destinationPortal.getWorld() + " " + - destinationPortal.getSignLocation()); - new VehicleTeleporter(destinationPortal, vehicle).teleportEntity(entrancePortal); - } - } - - /** - * Teleports a player and the vehicle the player sits in - * - * @param entrancePortal

The portal the minecart entered

- * @param vehicle

The vehicle to teleport

- */ - private static void teleportPlayerAndVehicle(@NotNull Portal entrancePortal, @NotNull Vehicle vehicle) { - Entity rootEntity = vehicle; - while (rootEntity.getVehicle() != null) { - rootEntity = rootEntity.getVehicle(); - } - List players = TeleportHelper.getPlayers(rootEntity.getPassengers()); - Portal destinationPortal = getDestinationPortal(players, entrancePortal); - - //Cancel the teleport if no players activated the portal, or if any players are denied access - boolean cancelTeleportation = false; - for (Player player : players) { - if (destinationPortal == null) { - cancelTeleportation = true; - if (!entrancePortal.getOptions().isQuiet()) { - new SGFormatBuilder(Message.INVALID_DESTINATION).error(player); - } - } else if (!TeleportHelper.playerCanTeleport(player, entrancePortal, destinationPortal)) { - cancelTeleportation = true; - } - } - if (cancelTeleportation || destinationPortal == null) { - return; - } - - //Take payment from all players - if (!takePayment(players, entrancePortal, destinationPortal)) { - return; - } - - // Perform the teleportation - teleportPlayerAndVehicle(players, vehicle, entrancePortal, destinationPortal); - } - - /** - * Performs the teleportation of one or more players in a vehicle - * - * @param players

The players to be teleported

- * @param vehicle

The vehicle that triggered the teleportation

- * @param entrancePortal

The portal the player(s) and vehicle entered from

- * @param destinationPortal

The portal the player(s) and vehicle are teleporting to

- */ - private static void teleportPlayerAndVehicle(@NotNull List players, @NotNull Vehicle vehicle, - @NotNull Portal entrancePortal, @NotNull Portal destinationPortal) { - //Teleport the vehicle and inform the user if the vehicle was teleported - boolean teleported = new VehicleTeleporter(destinationPortal, vehicle).teleportEntity(entrancePortal); - if (!teleported) { - return; - } - - if (!entrancePortal.getOptions().isQuiet()) { - for (Player player : players) { - new SGFormatBuilder(Message.TELEPORTED).success(player); - } - } - entrancePortal.getPortalOpener().closePortal(false); - } - - /** - * Tries to get the destination portal selected by one of the players included in the teleportation - * - * @param players

The players to be teleported

- * @param entrancePortal

The portal the players are entering

- * @return

The destination portal, or null if not found

- */ - @Nullable - private static Portal getDestinationPortal(@NotNull List players, @NotNull Portal entrancePortal) { - for (Player player : players) { - //The entrance portal must be open for one player for the teleportation to happen - if (!entrancePortal.getPortalOpener().isOpenFor(player)) { - continue; - } - - //Check if any of the players has selected the destination - Portal possibleDestinationPortal = entrancePortal.getPortalActivator().getDestination(player); - if (possibleDestinationPortal != null) { - return possibleDestinationPortal; - } - } - - return null; - } - - /** - * Takes payment for the given players - * - * @param players

The players to take payment from

- * @param entrancePortal

The portal the players are travelling from

- * @param destinationPortal

The portal the players are travelling to

- * @return

True if payment was successfully taken, false otherwise

- */ - private static boolean takePayment(@NotNull List players, @NotNull Portal entrancePortal, - @NotNull Portal destinationPortal) { - for (Player player : players) { - //To prevent the case where the first passenger pays and then the second passenger is denied, this has to be - // run after it has been confirmed that all passengers are able to pay. Also note that some players might - // not have to pay, and thus the cost check has to be in the loop, - int cost = EconomyHelper.getUseCost(player, entrancePortal, destinationPortal); - if (cost > 0) { - if (EconomyHelper.cannotPayTeleportFee(entrancePortal, player, cost)) { - return false; - } - } - } - - return true; - } - -} diff --git a/src/main/java/net/knarcraft/stargate/listener/WorldEventListener.java b/src/main/java/net/knarcraft/stargate/listener/WorldEventListener.java deleted file mode 100644 index 5606e80..0000000 --- a/src/main/java/net/knarcraft/stargate/listener/WorldEventListener.java +++ /dev/null @@ -1,51 +0,0 @@ -package net.knarcraft.stargate.listener; - -import net.knarcraft.stargate.Stargate; -import net.knarcraft.stargate.config.StargateConfig; -import net.knarcraft.stargate.portal.PortalRegistry; -import net.knarcraft.stargate.utility.PortalFileHelper; -import org.bukkit.World; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.event.world.WorldLoadEvent; -import org.bukkit.event.world.WorldUnloadEvent; -import org.jetbrains.annotations.NotNull; - -/** - * This listener listens for the loading and unloading of worlds to load and unload stargates - */ -@SuppressWarnings("unused") -public class WorldEventListener implements Listener { - - /** - * This listener listens for the loading of a world and loads all gates from the world if not already loaded - * - * @param event

The triggered world load event

- */ - @EventHandler - public void onWorldLoad(@NotNull WorldLoadEvent event) { - StargateConfig config = Stargate.getStargateConfig(); - if (!config.getManagedWorlds().contains(event.getWorld().getName()) && - PortalFileHelper.loadAllPortals(event.getWorld())) { - config.addManagedWorld(event.getWorld().getName()); - } - } - - /** - * This listener listens for the unloading of a world - * - * @param event

The triggered world unload event

- */ - @EventHandler - public void onWorldUnload(@NotNull WorldUnloadEvent event) { - Stargate.debug("onWorldUnload", "Reloading all Stargates"); - World world = event.getWorld(); - String worldName = world.getName(); - StargateConfig config = Stargate.getStargateConfig(); - if (config.getManagedWorlds().contains(worldName)) { - config.removeManagedWorld(worldName); - PortalRegistry.clearPortals(world); - } - } - -} diff --git a/src/main/java/net/knarcraft/stargate/portal/Portal.java b/src/main/java/net/knarcraft/stargate/portal/Portal.java index 28cf3ac..3a8e2ba 100644 --- a/src/main/java/net/knarcraft/stargate/portal/Portal.java +++ b/src/main/java/net/knarcraft/stargate/portal/Portal.java @@ -1,6 +1,5 @@ package net.knarcraft.stargate.portal; -import net.knarcraft.stargate.transformation.SimpleVectorOperation; import net.knarcraft.stargate.container.BlockLocation; import net.knarcraft.stargate.container.RelativeBlockVector; import net.knarcraft.stargate.portal.property.PortalLocation; @@ -10,6 +9,7 @@ import net.knarcraft.stargate.portal.property.PortalOwner; import net.knarcraft.stargate.portal.property.PortalStrings; import net.knarcraft.stargate.portal.property.PortalStructure; import net.knarcraft.stargate.portal.property.gate.Gate; +import net.knarcraft.stargate.transformation.SimpleVectorOperation; import net.knarcraft.stargate.utility.DirectionHelper; import net.md_5.bungee.api.ChatColor; import org.bukkit.World; diff --git a/src/main/java/net/knarcraft/stargate/portal/PortalActivator.java b/src/main/java/net/knarcraft/stargate/portal/PortalActivator.java index ed3fd74..97fcb96 100644 --- a/src/main/java/net/knarcraft/stargate/portal/PortalActivator.java +++ b/src/main/java/net/knarcraft/stargate/portal/PortalActivator.java @@ -1,8 +1,8 @@ package net.knarcraft.stargate.portal; import net.knarcraft.stargate.Stargate; -import net.knarcraft.stargate.config.Message; -import net.knarcraft.stargate.config.SGFormatBuilder; +import net.knarcraft.stargate.config.formatting.Message; +import net.knarcraft.stargate.config.formatting.SGFormatBuilder; import net.knarcraft.stargate.event.StargateActivateEvent; import net.knarcraft.stargate.event.StargateDeactivateEvent; import net.knarcraft.stargate.utility.ListHelper; diff --git a/src/main/java/net/knarcraft/stargate/portal/PortalCreator.java b/src/main/java/net/knarcraft/stargate/portal/PortalCreator.java index e8ab252..15a974c 100644 --- a/src/main/java/net/knarcraft/stargate/portal/PortalCreator.java +++ b/src/main/java/net/knarcraft/stargate/portal/PortalCreator.java @@ -1,8 +1,8 @@ package net.knarcraft.stargate.portal; import net.knarcraft.stargate.Stargate; -import net.knarcraft.stargate.config.Message; -import net.knarcraft.stargate.config.SGFormatBuilder; +import net.knarcraft.stargate.config.formatting.Message; +import net.knarcraft.stargate.config.formatting.SGFormatBuilder; import net.knarcraft.stargate.container.BlockLocation; import net.knarcraft.stargate.container.RelativeBlockVector; import net.knarcraft.stargate.event.StargateCreateEvent; diff --git a/src/main/java/net/knarcraft/stargate/portal/PortalHandler.java b/src/main/java/net/knarcraft/stargate/portal/PortalHandler.java index 836af78..4bd6102 100644 --- a/src/main/java/net/knarcraft/stargate/portal/PortalHandler.java +++ b/src/main/java/net/knarcraft/stargate/portal/PortalHandler.java @@ -1,8 +1,8 @@ package net.knarcraft.stargate.portal; import net.knarcraft.stargate.Stargate; -import net.knarcraft.stargate.config.Message; -import net.knarcraft.stargate.config.SGFormatBuilder; +import net.knarcraft.stargate.config.formatting.Message; +import net.knarcraft.stargate.config.formatting.SGFormatBuilder; import net.knarcraft.stargate.config.material.BukkitTagSpecifier; import net.knarcraft.stargate.container.BlockLocation; import net.knarcraft.stargate.container.RelativeBlockVector; diff --git a/src/main/java/net/knarcraft/stargate/portal/PortalRegistry.java b/src/main/java/net/knarcraft/stargate/portal/PortalRegistry.java index aed92cf..e800829 100644 --- a/src/main/java/net/knarcraft/stargate/portal/PortalRegistry.java +++ b/src/main/java/net/knarcraft/stargate/portal/PortalRegistry.java @@ -1,7 +1,7 @@ package net.knarcraft.stargate.portal; import net.knarcraft.stargate.Stargate; -import net.knarcraft.stargate.config.DynmapManager; +import net.knarcraft.stargate.config.addons.DynmapManager; import net.knarcraft.stargate.config.material.BukkitTagSpecifier; import net.knarcraft.stargate.container.BlockLocation; import net.knarcraft.stargate.utility.PortalFileHelper; diff --git a/src/main/java/net/knarcraft/stargate/portal/PortalSignDrawer.java b/src/main/java/net/knarcraft/stargate/portal/PortalSignDrawer.java index 1df2211..c520a80 100644 --- a/src/main/java/net/knarcraft/stargate/portal/PortalSignDrawer.java +++ b/src/main/java/net/knarcraft/stargate/portal/PortalSignDrawer.java @@ -3,8 +3,8 @@ package net.knarcraft.stargate.portal; import net.knarcraft.knarlib.property.ColorConversion; import net.knarcraft.knarlib.util.ColorHelper; import net.knarcraft.stargate.Stargate; -import net.knarcraft.stargate.config.Message; -import net.knarcraft.stargate.config.SGFormatBuilder; +import net.knarcraft.stargate.config.formatting.Message; +import net.knarcraft.stargate.config.formatting.SGFormatBuilder; import net.knarcraft.stargate.container.SignData; import net.knarcraft.stargate.portal.property.PortalLocation; import net.knarcraft.stargate.utility.PermissionHelper; diff --git a/src/main/java/net/knarcraft/stargate/utility/BungeeHelper.java b/src/main/java/net/knarcraft/stargate/utility/BungeeHelper.java index 8430c95..584729a 100644 --- a/src/main/java/net/knarcraft/stargate/utility/BungeeHelper.java +++ b/src/main/java/net/knarcraft/stargate/utility/BungeeHelper.java @@ -1,8 +1,8 @@ package net.knarcraft.stargate.utility; import net.knarcraft.stargate.Stargate; -import net.knarcraft.stargate.config.Message; -import net.knarcraft.stargate.config.SGFormatBuilder; +import net.knarcraft.stargate.config.formatting.Message; +import net.knarcraft.stargate.config.formatting.SGFormatBuilder; import net.knarcraft.stargate.portal.Portal; import net.knarcraft.stargate.portal.PortalHandler; import net.knarcraft.stargate.portal.teleporter.PlayerTeleporter; diff --git a/src/main/java/net/knarcraft/stargate/utility/EconomyHelper.java b/src/main/java/net/knarcraft/stargate/utility/EconomyHelper.java index db45457..42dfa8a 100644 --- a/src/main/java/net/knarcraft/stargate/utility/EconomyHelper.java +++ b/src/main/java/net/knarcraft/stargate/utility/EconomyHelper.java @@ -2,9 +2,9 @@ package net.knarcraft.stargate.utility; import net.knarcraft.knarlib.formatting.FormatBuilder; import net.knarcraft.stargate.Stargate; -import net.knarcraft.stargate.config.EconomyConfig; -import net.knarcraft.stargate.config.Message; -import net.knarcraft.stargate.config.SGFormatBuilder; +import net.knarcraft.stargate.config.addons.EconomyConfig; +import net.knarcraft.stargate.config.formatting.Message; +import net.knarcraft.stargate.config.formatting.SGFormatBuilder; import net.knarcraft.stargate.portal.Portal; import net.knarcraft.stargate.portal.property.PortalOwner; import net.milkbowl.vault.economy.Economy; diff --git a/src/main/java/net/knarcraft/stargate/utility/PermissionHelper.java b/src/main/java/net/knarcraft/stargate/utility/PermissionHelper.java index 38e7a51..2afac41 100644 --- a/src/main/java/net/knarcraft/stargate/utility/PermissionHelper.java +++ b/src/main/java/net/knarcraft/stargate/utility/PermissionHelper.java @@ -1,8 +1,8 @@ package net.knarcraft.stargate.utility; import net.knarcraft.stargate.Stargate; -import net.knarcraft.stargate.config.Message; -import net.knarcraft.stargate.config.SGFormatBuilder; +import net.knarcraft.stargate.config.formatting.Message; +import net.knarcraft.stargate.config.formatting.SGFormatBuilder; import net.knarcraft.stargate.event.StargateAccessEvent; import net.knarcraft.stargate.portal.Portal; import net.knarcraft.stargate.portal.property.PortalOption; diff --git a/src/main/java/net/knarcraft/stargate/utility/TeleportHelper.java b/src/main/java/net/knarcraft/stargate/utility/TeleportHelper.java index 0ebf770..c245a37 100644 --- a/src/main/java/net/knarcraft/stargate/utility/TeleportHelper.java +++ b/src/main/java/net/knarcraft/stargate/utility/TeleportHelper.java @@ -1,8 +1,8 @@ package net.knarcraft.stargate.utility; import net.knarcraft.stargate.Stargate; -import net.knarcraft.stargate.config.Message; -import net.knarcraft.stargate.config.SGFormatBuilder; +import net.knarcraft.stargate.config.formatting.Message; +import net.knarcraft.stargate.config.formatting.SGFormatBuilder; import net.knarcraft.stargate.portal.Portal; import net.knarcraft.stargate.portal.teleporter.EntityTeleporter; import org.bukkit.Bukkit;