Skip to content

Instantly share code, notes, and snippets.

@NanoAi
Last active September 29, 2019 01:49
Show Gist options
  • Save NanoAi/3190108c948e09f7c4b0188904f1b555 to your computer and use it in GitHub Desktop.
Save NanoAi/3190108c948e09f7c4b0188904f1b555 to your computer and use it in GitHub Desktop.
package red.mirai.spawnsystems;
import org.bukkit.Chunk;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;
import red.mirai.spawnsystems.Events.SpawnProtection;
import java.util.ArrayList;
import java.util.Objects;
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;
import static org.bukkit.Bukkit.getServer;
public class RandomSpawnLocation {
public ArrayList<Player> respawnQueue = new ArrayList<>();
private static int randomInRange(int min, int max) {
if ( min >= max ) {
throw new IllegalArgumentException( "max must be greater than min" );
}
Random r = ThreadLocalRandom.current();
return r.nextInt( ( max - min ) + 1 ) + min;
}
private static Block findSuitableBlock(World world, Block block, Chunk chunk) {
boolean found = false;
boolean checkingArea = false;
boolean exit = false;
int x = chunk.getX();
int z = chunk.getZ();
ArrayList<Block> blocks = new ArrayList<>();
while ( !found && !exit ) {
Material blockMaterial = block.getType();
if ( blockMaterial == Material.AIR ) {
blockMaterial = block.getRelative( BlockFace.DOWN ).getType();
}
switch ( blockMaterial ) {
case LAVA:
case CACTUS:
case MAGMA_BLOCK:
case SWEET_BERRY_BUSH:
case ROSE_BUSH:
case FIRE:
case DEAD_BUSH:
case CAMPFIRE:
if ( !checkingArea ){
checkingArea = true;
for ( int ix = x - 7; ix <= x + 7; ix++ ) {
for ( int iz = z - 7; iz <= z + 7; iz++ ) {
blocks.add( chunk.getWorld().getHighestBlockAt( x, z ) );
}
}
}
int size = blocks.size();
if ( size <= 0 ){
exit = true;
continue;
}
int i = ThreadLocalRandom.current().nextInt( size );
block = blocks.get( i );
blocks.remove( i );
continue;
default:
found = true;
}
}
return found ? block : null;
}
public void send(Player ply) {
respawnQueue.add( ply );
World world = getServer().getWorld( "world" );
Objects.requireNonNull(world);
int worldRadius = (int) world.getWorldBorder().getSize() / 2;
int borderDistance = worldRadius / 1000;
int max = worldRadius - borderDistance;
new BukkitRunnable() {
Location location;
@Override
public void run() {
int x = randomInRange( -max, max );
int z = randomInRange( -max, max );
for ( Player ply : getServer().getOnlinePlayers() ) {
World plyWorld = ply.getWorld();
if ( plyWorld != world ) {
continue;
}
Location plyLocation = ply.getLocation();
int px = plyLocation.getBlockX();
int pz = plyLocation.getBlockZ();
int distance = (int) Math.sqrt( ( pz - z ) * ( pz - z ) + ( px - x ) * ( px - x ) );
if ( distance < 512 ) {
return;
}
}
Chunk chunk = world.getChunkAt( x, z );
SpawnSystems.plugin.getLogger().info( "Loading Chunk @ X: " + x + " Z: " + z );
world.loadChunk( chunk );
Block block = world.getHighestBlockAt( x, z );
switch ( block.getBiome() ) {
case OCEAN:
case COLD_OCEAN:
case WARM_OCEAN:
case FROZEN_OCEAN:
case LUKEWARM_OCEAN:
case DEEP_OCEAN:
case DEEP_COLD_OCEAN:
case DEEP_WARM_OCEAN:
case DEEP_FROZEN_OCEAN:
case DEEP_LUKEWARM_OCEAN:
return;
}
Block safeBlock = findSuitableBlock( world, block, chunk );
if ( safeBlock == null ) {
return;
}
location = safeBlock.getLocation();
world.strikeLightningEffect( location );
if ( !world.isDayTime() ) {
SpawnProtection.apply( ply );
}
ply.teleportAsync( location );
respawnQueue.remove( ply );
cancel();
}
}.runTaskTimer( SpawnSystems.plugin, 0L, 5L );
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment