package wtf.beatrice.limbomanager.listeners; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat; import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats; import com.sk89q.worldedit.extent.clipboard.io.ClipboardReader; import com.sk89q.worldedit.function.operation.Operation; import com.sk89q.worldedit.function.operation.Operations; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.session.ClipboardHolder; import com.sk89q.worldedit.world.World; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerQuitEvent; import wtf.beatrice.limbomanager.Cache; import wtf.beatrice.limbomanager.LimboManager; import wtf.beatrice.limbomanager.objects.AreaCleanerRunnable; import wtf.beatrice.limbomanager.objects.Coordinates; import wtf.beatrice.limbomanager.utils.LocationUtils; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.util.UUID; public class PlayerTeleporter implements Listener { @EventHandler public void onPlayerJoin(PlayerJoinEvent event) { Player player = event.getPlayer(); String playerName = player.getName(); Coordinates islandCoords = calcNewCoordinates(); Cache.playerIslands.put(playerName, islandCoords); Location islandLocation = new Location(player.getWorld(), islandCoords.getX(), 64, islandCoords.getZ()); // load chunk otherwise it will be buggy (no schem load, no tp) islandLocation.getWorld().loadChunk(islandLocation.getChunk().getX(), islandLocation.getChunk().getZ(), true); String testSchematicPath = LimboManager.getSchematicsFolder().getAbsolutePath() + File.separator + "default.schem"; File schematicFile = new File(testSchematicPath); if(!schematicFile.exists()) { LimboManager.getInstance().getLogger().severe("Missing schematic file. This will cause issues!"); return; } // todo: improve and make as async as possible World islandWEWorld = BukkitAdapter.adapt(islandLocation.getWorld()); Clipboard shematicClipboard; ClipboardFormat clipboardFormat = ClipboardFormats.findByFile(schematicFile); try (ClipboardReader reader = clipboardFormat.getReader(new FileInputStream(schematicFile))) { shematicClipboard = reader.read(); try (EditSession editSession = WorldEdit.getInstance().newEditSession(islandWEWorld)) { Operation operation = new ClipboardHolder(shematicClipboard) .createPaste(editSession) .to(BlockVector3.at(islandLocation.getX(), 64, islandLocation.getZ())) // configure here .build(); Operations.complete(operation); editSession.flushSession(); } catch (WorldEditException e) { throw new RuntimeException(e); } } catch (IOException e) { throw new RuntimeException(e); } LocationUtils.teleportToOwnIsland(player); } @EventHandler public void onPlayerQuit(PlayerQuitEvent event) { Player player = event.getPlayer(); String playerName = player.getName(); // clean the whole island space after the player left. // we will go 20 blocks over the limit in case the location checker timer was extremely slow // and let the player go that far out of them. // // this should never happen. int maxRange = Cache.islandWalkingRange + 20; Location islandSpawnLocation = LocationUtils.getPlayerSpawnLocation(player); Location startFrom = new Location(islandSpawnLocation.getWorld(), islandSpawnLocation.getX() - maxRange, islandSpawnLocation.getWorld().getMinHeight(), islandSpawnLocation.getZ() - maxRange); Location endAt = new Location(islandSpawnLocation.getWorld(), islandSpawnLocation.getX() + maxRange, islandSpawnLocation.getWorld().getMaxHeight(), islandSpawnLocation.getZ() + maxRange); // set the area as being "cleaned up". UUID randomUUID = UUID.randomUUID(); String cleanUpID = "cleanup-" + randomUUID.toString(); Cache.playerIslands.put(cleanUpID, Cache.playerIslands.get(playerName)); Cache.playerIslands.remove(playerName); AreaCleanerRunnable cleanerRunnable = new AreaCleanerRunnable(startFrom, endAt, playerName, cleanUpID); cleanerRunnable.task = Bukkit.getScheduler().runTaskTimerAsynchronously(LimboManager.getInstance(), cleanerRunnable, 20L,1L); } private Coordinates calcNewCoordinates() { /* how are islands laid out? we start from (1000, 1000) and we put islands at blocks distance up to 10000. then we move to a new row. */ Coordinates islandCoords = new Coordinates(Cache.baseCoords); for(Coordinates currentCoords : Cache.playerIslands.values()) { // if the two are not the same, it means we found a free spot. // we can thus quit the loop and keep the current coords as valid. if(!islandCoords.equals(currentCoords)) break; // else, if they are the same, // we have to either increase X or move to a new row and reset X, in case it's over 10000. if(islandCoords.getX() >= 10000) // if we need to create a new row { islandCoords.setX(1000); islandCoords.setZ(islandCoords.getZ() + Cache.islandsDistance); } else { // if we just need to increase the column islandCoords.setX(islandCoords.getX() + Cache.islandsDistance); } } return islandCoords; } } /* player joins -> we look for the first free space -> we add it to the list and generate the island */