diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/event/actions/player/ActionPlayerLaunchPads.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/event/actions/player/ActionPlayerLaunchPads.java index 449a084a6..b5c254d62 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/event/actions/player/ActionPlayerLaunchPads.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/event/actions/player/ActionPlayerLaunchPads.java @@ -1,37 +1,29 @@ package net.swofty.type.skyblockgeneric.event.actions.player; import net.kyori.adventure.key.Key; +import net.swofty.commons.StringUtility; import org.tinylog.Logger; import net.kyori.adventure.sound.Sound; -import org.tinylog.Logger; import net.minestom.server.coordinate.Pos; -import org.tinylog.Logger; import net.minestom.server.coordinate.Vec; -import org.tinylog.Logger; import net.minestom.server.entity.EntityType; -import org.tinylog.Logger; import net.minestom.server.entity.LivingEntity; -import org.tinylog.Logger; import net.minestom.server.event.player.PlayerMoveEvent; -import org.tinylog.Logger; import net.minestom.server.network.packet.server.play.ParticlePacket; -import org.tinylog.Logger; import net.minestom.server.particle.Particle; -import org.tinylog.Logger; +import net.swofty.commons.ServerType; +import net.swofty.proxyapi.ProxyInformation; import net.swofty.type.generic.event.EventNodes; -import org.tinylog.Logger; import net.swofty.type.generic.event.HypixelEvent; -import org.tinylog.Logger; import net.swofty.type.generic.event.HypixelEventClass; -import org.tinylog.Logger; import net.swofty.type.generic.utility.MathUtility; -import org.tinylog.Logger; import net.swofty.type.skyblockgeneric.user.SkyBlockPlayer; -import org.tinylog.Logger; import net.swofty.type.skyblockgeneric.utility.LaunchPads; -import org.tinylog.Logger; import java.util.List; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; @@ -41,6 +33,7 @@ public class ActionPlayerLaunchPads implements HypixelEventClass { private static final int SEGMENTS = 30; private static final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); + private static final Set notifiedPlayers = ConcurrentHashMap.newKeySet(); @HypixelEvent(node = EventNodes.PLAYER, requireDataLoaded = true, isAsync = true) @@ -53,7 +46,12 @@ public void run(PlayerMoveEvent event) { } catch (ExceptionInInitializerError err) { return; } - if (pad == null) return; + + if (pad == null) { + notifiedPlayers.remove(player.getUuid()); + return; + } + if (player.isInLaunchpad()) return; player.setInLaunchpad(true); @@ -84,37 +82,78 @@ public void run(PlayerMoveEvent event) { player.setInLaunchpad(false); return; } - player.playSound(Sound.sound(Key.key("entity.firework_rocket.launch"), Sound.Source.PLAYER, 1, 1)); - - LivingEntity armorStand = new LivingEntity(EntityType.ARMOR_STAND); - armorStand.getEntityMeta().setInvisible(true); - armorStand.getEntityMeta().setHasNoGravity(true); - armorStand.setInstance(player.getInstance(), player.getPosition()); - armorStand.addPassenger(player); - - List curve = MathUtility.bezierCurve(player.getPosition(), pad.getDestination(), SEGMENTS); - long timeToSleep = 3000 / SEGMENTS; - - // Use ScheduledExecutorService to run the launch trajectory with delays - AtomicInteger index = new AtomicInteger(0); - ScheduledFuture[] taskHolder = new ScheduledFuture[1]; - taskHolder[0] = scheduler.scheduleAtFixedRate(() -> { - int currentIndex = index.getAndIncrement(); - if (currentIndex >= curve.size()) { - // Cancel the task - if (taskHolder[0] != null) { - taskHolder[0].cancel(false); + + // Check server availability before starting animation + ServerType targetServerType = pad.getTargetServerType(); + ProxyInformation proxyInfo = new ProxyInformation(); + proxyInfo.getServerInformation(targetServerType).thenAccept(servers -> { + if (servers == null || servers.isEmpty()) { + player.setInLaunchpad(false); + if (!notifiedPlayers.contains(player.getUuid())) { + notifiedPlayers.add(player.getUuid()); + player.sendMessage("§cThere are no " + StringUtility.toNormalCase(targetServerType.name()) + " servers available at the moment. Please try again later."); } - // Execute the after finished callback - player.sendMessage("Done"); - pad.getAfterFinished().accept(player); return; } - Pos pos = curve.get(currentIndex); - Vec toGoTo = pos.asVec(); - Vec direction = toGoTo.sub(player.getPosition().asVec()).normalize(); - armorStand.setVelocity(direction.mul(50, 5, 50)); - }, 0, timeToSleep, TimeUnit.MILLISECONDS); + notifiedPlayers.remove(player.getUuid()); + + Pos originalPosition = player.getPosition(); + player.playSound(Sound.sound(Key.key("entity.firework_rocket.launch"), Sound.Source.PLAYER, 1, 1)); + + LivingEntity armorStand = new LivingEntity(EntityType.ARMOR_STAND); + armorStand.getEntityMeta().setInvisible(true); + armorStand.getEntityMeta().setHasNoGravity(true); + armorStand.setInstance(player.getInstance(), player.getPosition()); + armorStand.addPassenger(player); + + List curve = MathUtility.bezierCurve(player.getPosition(), pad.getDestination(), SEGMENTS); + long timeToSleep = 3000 / SEGMENTS; + + // Use ScheduledExecutorService to run the launch trajectory with delays + AtomicInteger index = new AtomicInteger(0); + ScheduledFuture[] taskHolder = new ScheduledFuture[1]; + taskHolder[0] = scheduler.scheduleAtFixedRate(() -> { + int currentIndex = index.getAndIncrement(); + if (currentIndex >= curve.size()) { + // Cancel the task + if (taskHolder[0] != null) { + taskHolder[0].cancel(false); + } + + player.setInLaunchpad(false); + notifiedPlayers.remove(player.getUuid()); + + // Execute the after finished callback + player.sendMessage("Done"); + pad.getAfterFinished().accept(player); + + // Check after a delay if player is still on this server (transfer failed) + scheduler.schedule(() -> { + // If player is still on the same server and instance, teleport them back + if (player.getInstance() != null && player.getInstance().equals(armorStand.getInstance())) { + player.teleport(originalPosition); + player.sendMessage("§cFailed to connect to the server. You have been teleported back."); + } + try { + armorStand.remove(); + } catch (Exception e) { + } + }, 2, TimeUnit.SECONDS); + + return; + } + + Pos pos = curve.get(currentIndex); + Vec toGoTo = pos.asVec(); + Vec direction = toGoTo.sub(player.getPosition().asVec()).normalize(); + armorStand.setVelocity(direction.mul(50, 5, 50)); + }, 0, timeToSleep, TimeUnit.MILLISECONDS); + }).exceptionally(ex -> { + Logger.error(ex, "Error checking server availability for launch pad"); + player.setInLaunchpad(false); + player.sendMessage("§cAn error occurred while checking server availability. Please try again later."); + return null; + }); } } diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/utility/LaunchPads.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/utility/LaunchPads.java index 1daee7e34..3b2f27a98 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/utility/LaunchPads.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/utility/LaunchPads.java @@ -25,7 +25,7 @@ @Getter public enum LaunchPads { VILLAGE_TO_FARMING(getSlimeBlocksNear(new Pos(79, 71, -185)), ServerType.SKYBLOCK_HUB, - new Pos(116.5, 74, -210.5), (player) -> { + ServerType.SKYBLOCK_THE_FARMING_ISLANDS, new Pos(116.5, 74, -210.5), (player) -> { player.sendTo(ServerType.SKYBLOCK_THE_FARMING_ISLANDS); }, (player) -> player.getSkills().getCurrentLevel(SkillCategories.FARMING) >= 5, "§cYou must be at least Farming Level V to join this island!", @@ -46,7 +46,7 @@ public enum LaunchPads { } }), FARMING_TO_VILLAGE(getSlimeBlocksNear(new Pos(111, 71, -202)), ServerType.SKYBLOCK_THE_FARMING_ISLANDS, - new Pos(74, 72, -180), (player) -> { + ServerType.SKYBLOCK_HUB, new Pos(74, 72, -180), (player) -> { player.sendTo(ServerType.SKYBLOCK_HUB); }, (player) -> true, "", @@ -63,17 +63,19 @@ public enum LaunchPads { private final List slimeBlocks; private final ServerType serverType; + private final ServerType targetServerType; private final Pos destination; private final Consumer afterFinished; private final Function shouldAllow; private final String rejectionMessage; private final Function hologramDisplay; - LaunchPads(List slimeBlocks, ServerType serverType, Pos destination, + LaunchPads(List slimeBlocks, ServerType serverType, ServerType targetServerType, Pos destination, Consumer<@NonNull SkyBlockPlayer> afterFinished, Function shouldAllow, String rejectionMessage, Function<@NonNull SkyBlockPlayer, PlayerHolograms.ExternalPlayerHologram> hologramDisplay) { this.slimeBlocks = slimeBlocks; this.serverType = serverType; + this.targetServerType = targetServerType; this.destination = destination; this.afterFinished = afterFinished; this.shouldAllow = shouldAllow;