Beatrice DellacĂ
cadc5854ef
All checks were successful
continuous-integration/drone/push Build is passing
195 lines
7.7 KiB
Java
195 lines
7.7 KiB
Java
package wtf.beatrice.limbomanager.listeners;
|
|
|
|
import com.sk89q.worldedit.EditSession;
|
|
import com.sk89q.worldedit.MaxChangedBlocksException;
|
|
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.regions.CuboidRegion;
|
|
import com.sk89q.worldedit.session.ClipboardHolder;
|
|
import com.sk89q.worldedit.world.World;
|
|
import com.sk89q.worldedit.world.block.BlockState;
|
|
import org.bukkit.Bukkit;
|
|
import org.bukkit.Location;
|
|
import org.bukkit.Material;
|
|
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.Coordinates;
|
|
import wtf.beatrice.limbomanager.utils.LocationUtils;
|
|
|
|
import java.io.File;
|
|
import java.io.FileInputStream;
|
|
import java.io.IOException;
|
|
import java.util.ArrayList;
|
|
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(Cache.limboWorld, 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(Cache.limboWorld);
|
|
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);
|
|
} 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(Cache.limboWorld,
|
|
islandSpawnLocation.getX() - maxRange,
|
|
islandSpawnLocation.getWorld().getMinHeight(),
|
|
islandSpawnLocation.getZ() - maxRange);
|
|
|
|
Location endAt = new Location(islandSpawnLocation.getWorld(),
|
|
islandSpawnLocation.getX() + maxRange,
|
|
islandSpawnLocation.getWorld().getMaxHeight(),
|
|
islandSpawnLocation.getZ() + maxRange);
|
|
|
|
// announce area cleanup
|
|
LimboManager.getInstance().getLogger().info("Player " + playerName + " quit, clearing region...");
|
|
|
|
// WorldEdit API integration for faster area cleanup
|
|
World weWorld = BukkitAdapter.adapt(islandSpawnLocation.getWorld());
|
|
try(EditSession editSession = WorldEdit.getInstance().newEditSession(weWorld))
|
|
{
|
|
// we only need to set everything to air
|
|
BlockState air = BukkitAdapter.adapt(Material.AIR.createBlockData());
|
|
|
|
// convert our area borders to WE blockvectors
|
|
BlockVector3 min = BlockVector3.at(startFrom.getBlockX(), startFrom.getBlockY(), startFrom.getBlockZ());
|
|
BlockVector3 max = BlockVector3.at(endAt.getBlockX(), endAt.getBlockY(), endAt.getBlockZ());
|
|
|
|
// create a cuboid region
|
|
CuboidRegion cuboidRegion = new CuboidRegion(weWorld, min, max);
|
|
|
|
// do the cleaning
|
|
editSession.setBlocks(cuboidRegion, air);
|
|
|
|
// set that island spot to "cool-down mode"
|
|
String randUUID = UUID.randomUUID().toString();
|
|
Coordinates islandCoords = new Coordinates(Cache.playerIslands.get(playerName));
|
|
Cache.playerIslands.put(randUUID, islandCoords);
|
|
Cache.playerIslands.remove(playerName);
|
|
|
|
// start a timer to set the spot to free after X time.
|
|
Bukkit.getScheduler().runTaskLater(LimboManager.getInstance(), () -> {
|
|
|
|
LimboManager.getInstance().getLogger().info("Region [" + randUUID + ", "
|
|
+ islandCoords.getX() + ", "
|
|
+ islandCoords.getZ()
|
|
+ "] of " + playerName + " is now available again.");
|
|
Cache.playerIslands.remove(randUUID);
|
|
|
|
}, 60 * 20L);
|
|
|
|
} catch (MaxChangedBlocksException e) {
|
|
throw new RuntimeException(e);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
private Coordinates calcNewCoordinates() {
|
|
|
|
/*
|
|
how are islands laid out?
|
|
we start from (1000, 1000) and we put islands at <Cache.islandsDistance> blocks distance up to 10000. then we move to a new row.
|
|
*/
|
|
|
|
Coordinates islandCoords = new Coordinates(Cache.baseCoords);
|
|
ArrayList<Coordinates> playerIslands = new ArrayList<>(Cache.playerIslands.values());
|
|
|
|
for(int i = 0; i < playerIslands.size(); i++)
|
|
{
|
|
Coordinates checkCoords = playerIslands.get(i);
|
|
|
|
if(islandCoords.equals(checkCoords))
|
|
{
|
|
// 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);
|
|
}
|
|
i = 0; // restart the loop and check again (ugh)
|
|
}
|
|
} // at the end of the loop, we should have unique coordinates.
|
|
|
|
return islandCoords;
|
|
}
|
|
}
|