diff --git a/api/src/main/java/net/thenextlvl/portals/action/ActionTypeRegistry.java b/api/src/main/java/net/thenextlvl/portals/action/ActionTypeRegistry.java index 9b8ea6d..0699fba 100644 --- a/api/src/main/java/net/thenextlvl/portals/action/ActionTypeRegistry.java +++ b/api/src/main/java/net/thenextlvl/portals/action/ActionTypeRegistry.java @@ -1,5 +1,7 @@ package net.thenextlvl.portals.action; +import net.thenextlvl.binder.StaticBinder; +import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.Unmodifiable; @@ -11,7 +13,8 @@ * * @since 0.1.0 */ -public sealed interface ActionTypeRegistry permits SimpleActionTypeRegistry { +@ApiStatus.NonExtendable +public interface ActionTypeRegistry { /** * Gets the action type registry. * @@ -20,7 +23,7 @@ public sealed interface ActionTypeRegistry permits SimpleActionTypeRegistry { */ @Contract(pure = true) static ActionTypeRegistry registry() { - return SimpleActionTypeRegistry.INSTANCE; + return StaticBinder.getInstance(ActionTypeRegistry.class.getClassLoader()).find(ActionTypeRegistry.class); } /** diff --git a/api/src/main/java/net/thenextlvl/portals/action/ActionTypes.java b/api/src/main/java/net/thenextlvl/portals/action/ActionTypes.java index ed06533..08af2b6 100644 --- a/api/src/main/java/net/thenextlvl/portals/action/ActionTypes.java +++ b/api/src/main/java/net/thenextlvl/portals/action/ActionTypes.java @@ -1,8 +1,10 @@ package net.thenextlvl.portals.action; +import net.thenextlvl.binder.StaticBinder; import net.thenextlvl.portals.PortalLike; import net.thenextlvl.portals.model.Bounds; import org.bukkit.Location; +import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Contract; import java.net.InetSocketAddress; @@ -12,7 +14,8 @@ * * @since 0.1.0 */ -public sealed interface ActionTypes permits SimpleActionTypes { +@ApiStatus.NonExtendable +public interface ActionTypes { /** * Gets the action type registry. * @@ -21,7 +24,7 @@ public sealed interface ActionTypes permits SimpleActionTypes { */ @Contract(pure = true) static ActionTypes types() { - return SimpleActionTypes.INSTANCE; + return StaticBinder.getInstance(ActionTypes.class.getClassLoader()).find(ActionTypes.class); } /** diff --git a/src/main/java/net/thenextlvl/portals/PortalsPlugin.java b/src/main/java/net/thenextlvl/portals/PortalsPlugin.java index da43a01..b6ddf46 100644 --- a/src/main/java/net/thenextlvl/portals/PortalsPlugin.java +++ b/src/main/java/net/thenextlvl/portals/PortalsPlugin.java @@ -6,7 +6,11 @@ import net.kyori.adventure.key.Key; import net.thenextlvl.binder.StaticBinder; import net.thenextlvl.nbt.serialization.NBT; +import net.thenextlvl.portals.action.ActionTypeRegistry; +import net.thenextlvl.portals.action.ActionTypes; import net.thenextlvl.portals.action.EntryAction; +import net.thenextlvl.portals.action.SimpleActionTypeRegistry; +import net.thenextlvl.portals.action.SimpleActionTypes; import net.thenextlvl.portals.adapter.BoundingBoxAdapter; import net.thenextlvl.portals.adapter.EntryActionAdapter; import net.thenextlvl.portals.adapter.KeyAdapter; @@ -53,6 +57,8 @@ public final class PortalsPlugin extends JavaPlugin { .build(); public PortalsPlugin() { + StaticBinder.getInstance(ActionTypes.class.getClassLoader()).bind(ActionTypes.class, SimpleActionTypes.INSTANCE); + StaticBinder.getInstance(ActionTypeRegistry.class.getClassLoader()).bind(ActionTypeRegistry.class, SimpleActionTypeRegistry.INSTANCE); StaticBinder.getInstance(PortalConfig.class.getClassLoader()).bind(PortalConfig.class, portalConfig); StaticBinder.getInstance(PortalProvider.class.getClassLoader()).bind(PortalProvider.class, portalProvider); diff --git a/api/src/main/java/net/thenextlvl/portals/action/SimpleActionTypeRegistry.java b/src/main/java/net/thenextlvl/portals/action/SimpleActionTypeRegistry.java similarity index 87% rename from api/src/main/java/net/thenextlvl/portals/action/SimpleActionTypeRegistry.java rename to src/main/java/net/thenextlvl/portals/action/SimpleActionTypeRegistry.java index 62ca0e6..ebe41c3 100644 --- a/api/src/main/java/net/thenextlvl/portals/action/SimpleActionTypeRegistry.java +++ b/src/main/java/net/thenextlvl/portals/action/SimpleActionTypeRegistry.java @@ -1,13 +1,15 @@ package net.thenextlvl.portals.action; import org.jetbrains.annotations.Unmodifiable; +import org.jspecify.annotations.NullMarked; import java.util.HashSet; import java.util.Optional; import java.util.Set; -final class SimpleActionTypeRegistry implements ActionTypeRegistry { - public static final ActionTypeRegistry INSTANCE = new SimpleActionTypeRegistry(); +@NullMarked +public final class SimpleActionTypeRegistry implements ActionTypeRegistry { + public static final SimpleActionTypeRegistry INSTANCE = new SimpleActionTypeRegistry(); private final Set> actionTypes = new HashSet<>(Set.of( ActionTypes.types().connect(), diff --git a/api/src/main/java/net/thenextlvl/portals/action/SimpleActionTypes.java b/src/main/java/net/thenextlvl/portals/action/SimpleActionTypes.java similarity index 94% rename from api/src/main/java/net/thenextlvl/portals/action/SimpleActionTypes.java rename to src/main/java/net/thenextlvl/portals/action/SimpleActionTypes.java index af57dde..d2a3835 100644 --- a/api/src/main/java/net/thenextlvl/portals/action/SimpleActionTypes.java +++ b/src/main/java/net/thenextlvl/portals/action/SimpleActionTypes.java @@ -3,16 +3,19 @@ import core.paper.messenger.PluginMessenger; import io.papermc.paper.entity.TeleportFlag; import net.thenextlvl.portals.PortalLike; +import net.thenextlvl.portals.listener.PortalListener; import net.thenextlvl.portals.model.Bounds; import org.bukkit.Location; import org.bukkit.entity.Player; import org.bukkit.event.player.PlayerTeleportEvent; import org.bukkit.plugin.java.JavaPlugin; +import org.jspecify.annotations.NullMarked; import java.net.InetSocketAddress; import java.util.concurrent.ThreadLocalRandom; -final class SimpleActionTypes implements ActionTypes { +@NullMarked +public final class SimpleActionTypes implements ActionTypes { public static final SimpleActionTypes INSTANCE = new SimpleActionTypes(); private final PluginMessenger messenger = new PluginMessenger(JavaPlugin.getProvidingPlugin(SimpleActionTypes.class)); @@ -103,7 +106,9 @@ final class SimpleActionTypes implements ActionTypes { dest[tW] = tMin[tW] + fw * tSize[tW]; var destination = new Location(targetPortal.getWorld(), dest[0], dest[1], dest[2]).setRotation(from.getRotation()); - entity.teleportAsync(destination, PlayerTeleportEvent.TeleportCause.PLUGIN, TeleportFlag.Relative.values()); + entity.teleportAsync(destination, PlayerTeleportEvent.TeleportCause.PLUGIN, TeleportFlag.Relative.values()).thenAccept(success -> { + if (success) PortalListener.setLastPortal(entity, targetPortal); + }); return true; }).orElse(false); diff --git a/src/main/java/net/thenextlvl/portals/listener/PortalListener.java b/src/main/java/net/thenextlvl/portals/listener/PortalListener.java index 9cce6a7..f76def7 100644 --- a/src/main/java/net/thenextlvl/portals/listener/PortalListener.java +++ b/src/main/java/net/thenextlvl/portals/listener/PortalListener.java @@ -12,9 +12,7 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; -import org.bukkit.event.entity.EntityTeleportEvent; import org.bukkit.event.player.PlayerMoveEvent; -import org.bukkit.event.player.PlayerTeleportEvent; import org.bukkit.event.player.PlayerToggleSneakEvent; import org.jspecify.annotations.NullMarked; @@ -25,26 +23,15 @@ @NullMarked public final class PortalListener implements Listener { + private static final Map> lastEntry = new HashMap<>(); + private static final Map lastPortal = new HashMap<>(); + private final PortalsPlugin plugin; - private final Map> lastEntry = new HashMap<>(); - private final Map lastPortal = new HashMap<>(); public PortalListener(PortalsPlugin plugin) { this.plugin = plugin; } - private boolean hasCooldown(Portal portal, Entity entity) { - var entries = this.lastEntry.get(portal); - if (entries == null) return false; - var lastEntry = entries.get(entity.getUniqueId()); - return lastEntry != null && Instant.now().isBefore(lastEntry.plus(portal.getCooldown())); - } - - private void setLastEntry(Portal portal, Entity entity) { - lastEntry.computeIfAbsent(portal, ignored -> new HashMap<>()) - .put(entity.getUniqueId(), Instant.now()); - } - @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) public void onEntityMove(EntityMoveEvent event) { if (!event.hasChangedPosition()) return; @@ -62,24 +49,6 @@ public void onPlayerMove(PlayerMoveEvent event) { event.setCancelled(true); } - @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) - public void onPlayerTeleport(PlayerTeleportEvent event) { - processTeleport(event.getPlayer(), event.getTo()); - } - - @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) - public void onEntityTeleport(EntityTeleportEvent event) { - var to = event.getTo() != null ? event.getTo() : event.getEntity().getLocation(); - processTeleport(event.getEntity(), to); - } - - private void processTeleport(Entity entity, Location to) { - var boundingBox = translate(entity.getBoundingBox(), to); - plugin.portalProvider().getPortals(to.getWorld()) - .filter(portal -> portal.getBoundingBox().overlaps(boundingBox)) - .findAny().ifPresent(portal -> lastPortal.put(entity.getUniqueId(), portal)); - } - @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) public void onPlayerToggleSneak(PlayerToggleSneakEvent event) { if (event.isSneaking()) return; @@ -110,7 +79,7 @@ private boolean processMovement(Entity entity, Location to) { if (!new EntityPortalEnterEvent(portal, entity).callEvent()) return false; if (portal.getCooldown().isPositive()) setLastEntry(portal, entity); - lastPortal.put(entity.getUniqueId(), portal); + setLastPortal(entity, portal); return portal.getEntryAction().map(action -> action.onEntry(entity, portal)).orElse(true); }).orElseGet(() -> { @@ -120,16 +89,6 @@ private boolean processMovement(Entity entity, Location to) { }); } - private org.bukkit.util.BoundingBox translate(org.bukkit.util.BoundingBox boundingBox, Location location) { - var widthX = boundingBox.getWidthX() / 2; - var widthZ = boundingBox.getWidthZ() / 2; - - return new org.bukkit.util.BoundingBox( - location.getX() - widthX, location.getY(), location.getZ() - widthZ, - location.getX() + widthX, location.getY() + boundingBox.getHeight(), location.getZ() + widthZ - ); - } - private void pushAway(Entity entity, Location to) { if (!plugin.config().pushBackOnEntryDenied()) return; entity.getScheduler().run(plugin, task -> { @@ -143,4 +102,30 @@ private boolean withdrawEntryCost(Portal portal, Entity entity) { if (!(entity instanceof Player player)) return true; return plugin.economyProvider().withdraw(player, portal.getEntryCost()); } + + public static void setLastPortal(Entity entity, Portal portal) { + lastPortal.put(entity.getUniqueId(), portal); + } + + private static org.bukkit.util.BoundingBox translate(org.bukkit.util.BoundingBox boundingBox, Location location) { + var widthX = boundingBox.getWidthX() / 2; + var widthZ = boundingBox.getWidthZ() / 2; + + return new org.bukkit.util.BoundingBox( + location.getX() - widthX, location.getY(), location.getZ() - widthZ, + location.getX() + widthX, location.getY() + boundingBox.getHeight(), location.getZ() + widthZ + ); + } + + private static boolean hasCooldown(Portal portal, Entity entity) { + var entries = lastEntry.get(portal); + if (entries == null) return false; + var lastEntry = entries.get(entity.getUniqueId()); + return lastEntry != null && Instant.now().isBefore(lastEntry.plus(portal.getCooldown())); + } + + private static void setLastEntry(Portal portal, Entity entity) { + lastEntry.computeIfAbsent(portal, ignored -> new HashMap<>()) + .put(entity.getUniqueId(), Instant.now()); + } }