package de.linus122.playerworlds; import java.io.File; import java.io.IOException; import java.util.function.Consumer; import net.minecraft.core.Position; import org.apache.commons.io.FileUtils; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.World; import org.bukkit.WorldCreator; import org.bukkit.World.Environment; import org.bukkit.craftbukkit.v1_19_R1.CraftWorld; import org.bukkit.craftbukkit.v1_19_R1.entity.CraftEntity; import org.bukkit.craftbukkit.v1_19_R1.entity.CraftPlayer; import org.bukkit.event.Cancellable; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.entity.EntityPortalEvent; import org.bukkit.event.player.PlayerRespawnEvent; import org.bukkit.event.player.PlayerTeleportEvent; import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; public class Listeners implements Listener { private final Main main; private final String SUFFIX_NETHER = "_nether"; private final String SUFFIX_END = "_the_end"; public Listeners(Main main) { this.main = main; } @EventHandler public void onEntityTeleport(EntityPortalEvent event) { this.main.debug("EntityPortalEvent %s %s -> %s".formatted(event.getEntityType(), event.getFrom().getWorld().getName(), event.getTo().getWorld().getName())); if (!event.getFrom().getWorld().equals(event.getTo().getWorld())) { if (event.getFrom().getWorld().getEnvironment().equals(Environment.NETHER) ^ event.getTo().getWorld().getEnvironment().equals(Environment.NETHER)) { this.onTeleport(event.getFrom(), event.getTo(), TeleportCause.NETHER_PORTAL, world -> { CraftEntity craftEntity = (CraftEntity)event.getEntity(); craftEntity.getHandle().teleportTo(((CraftWorld) world).getHandle(), (Position) null); this.main.debug("Entity teleported %s %s -> %s".formatted(event.getEntityType(), event.getFrom().getWorld().getName(), world.getName())); }, event); } if (event.getFrom().getWorld().getEnvironment().equals(Environment.THE_END) ^ event.getTo().getWorld().getEnvironment().equals(Environment.THE_END)) { this.onTeleport(event.getFrom(), event.getTo(), TeleportCause.END_PORTAL, world -> { CraftEntity craftEntity = (CraftEntity)event.getEntity(); craftEntity.getHandle().teleportTo(((CraftWorld) world).getHandle(), (Position) null); this.main.debug("Entity teleported %s %s -> %s".formatted(event.getEntityType(), event.getFrom().getWorld().getName(), world.getName())); }, event); } } } @EventHandler public void onRespawn(PlayerRespawnEvent event) { if (event.getPlayer().getLocation().getBlock().getType().equals(Material.END_PORTAL) && event.getPlayer().getLocation().getWorld().getEnvironment() == Environment.THE_END) { String newName = event.getPlayer().getWorld().getName().replaceFirst("_the_end", ""); World world = Bukkit.getWorld(newName); Location respawnLocation = world.getSpawnLocation(); if (event.getPlayer().getBedSpawnLocation() != null) { respawnLocation = event.getPlayer().getBedSpawnLocation(); } event.setRespawnLocation(respawnLocation); this.main.debug("Respawn from end %s %s -> %s".formatted(event.getPlayer().getName(), event.getPlayer().getLocation().getWorld().getName(), respawnLocation)); } } @EventHandler public void onTeleport(PlayerTeleportEvent event) { this.main.debug("PlayerTeleportEvent %s %s -> %s".formatted(event.getPlayer().getName(), event.getFrom().getWorld().getName(), event.getTo().getWorld().getName())); this.onTeleport(event.getFrom(), event.getTo(), event.getCause(), world -> { CraftPlayer craftPlayer = (CraftPlayer) event.getPlayer(); craftPlayer.getHandle().changeDimension(((CraftWorld)world).getHandle(), event.getCause()); this.main.debug("Player teleported %s -> %s".formatted(event.getFrom().getWorld().getName(), world.getName())); }, event); } private void onTeleport(Location from, Location to, TeleportCause cause, Consumer action, Cancellable event) { Environment fromEnv = from.getWorld().getEnvironment(); Environment toEnv = to.getWorld().getEnvironment(); if (to.getWorld().getName().startsWith("world")) { if (cause.equals(TeleportCause.NETHER_PORTAL) || cause.equals(TeleportCause.END_PORTAL) || cause.equals(TeleportCause.END_GATEWAY)) { String newWorldname = null; if (fromEnv.equals(Environment.NORMAL) && toEnv.equals(Environment.NETHER)) { newWorldname = from.getWorld().getName() + SUFFIX_NETHER; } else if (fromEnv.equals(Environment.NETHER) && toEnv.equals(Environment.NORMAL)) { newWorldname = from.getWorld().getName().replaceFirst(SUFFIX_NETHER, ""); } else if (fromEnv.equals(Environment.NORMAL) && toEnv.equals(Environment.THE_END)) { newWorldname = from.getWorld().getName() + SUFFIX_END; } else if (fromEnv.equals(Environment.THE_END) && toEnv.equals(Environment.NORMAL)) { newWorldname = from.getWorld().getName().replaceFirst(SUFFIX_END, ""); } World toNew = Bukkit.getWorld(newWorldname); if (toNew == null && !toEnv.equals(Environment.NORMAL)) { try { this.copyNewWorld(newWorldname, toEnv); } catch (IOException exception) { exception.printStackTrace(); } WorldCreator wc = new WorldCreator(newWorldname); wc.environment(toEnv); wc.createWorld(); toNew = Bukkit.getWorld(newWorldname); } event.setCancelled(true); action.accept(toNew); } } } private void copyNewWorld(String worldName, Environment env) throws IOException { File newWorldFolder = new File(worldName); if (!newWorldFolder.exists()) { String originalWorldFolderName = this.main.getConfig().getString(env.toString().toLowerCase()); this.main.getLogger().info(originalWorldFolderName); File sourceWorldFolder = new File(this.main.getDataFolder(), originalWorldFolderName); FileUtils.copyDirectory(sourceWorldFolder, newWorldFolder); } } }