Last active
September 29, 2019 01:49
-
-
Save NanoAi/3190108c948e09f7c4b0188904f1b555 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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