112 lines
3.4 KiB
Java
112 lines
3.4 KiB
Java
package com.wimbli.WorldBorder;
|
|
|
|
import org.bukkit.ChatColor;
|
|
import org.bukkit.Effect;
|
|
import org.bukkit.entity.Player;
|
|
import org.bukkit.entity.Vehicle;
|
|
import org.bukkit.Location;
|
|
import org.bukkit.Server;
|
|
import org.bukkit.util.Vector;
|
|
import org.bukkit.World;
|
|
|
|
public class BorderCheckTask implements Runnable
|
|
{
|
|
private transient Server server = null;
|
|
|
|
public BorderCheckTask(Server theServer)
|
|
{
|
|
this.server = theServer;
|
|
}
|
|
|
|
public void run()
|
|
{
|
|
if (server == null)
|
|
return;
|
|
|
|
Player[] players = server.getOnlinePlayers();
|
|
|
|
for (int i = 0; i < players.length; i++){
|
|
checkPlayer(players[i], null, false);
|
|
}
|
|
}
|
|
|
|
// set targetLoc only if not current player location; set returnLocationOnly to true to have new Location returned if they need to be moved to one, instead of directly handling it
|
|
public static Location checkPlayer(Player player, Location targetLoc, boolean returnLocationOnly)
|
|
{
|
|
if (player == null || !player.isOnline()) return null;
|
|
|
|
Location loc = (targetLoc == null) ? player.getLocation() : targetLoc;
|
|
if (loc == null) return null;
|
|
|
|
World world = loc.getWorld();
|
|
if (world == null) return null;
|
|
BorderData border = Config.Border(world.getName());
|
|
if (border == null) return null;
|
|
|
|
if (border.insideBorder(loc.getX(), loc.getZ(), Config.ShapeRound()))
|
|
return null;
|
|
|
|
Location newLoc = newLocation(player, loc, border);
|
|
|
|
if (Config.whooshEffect())
|
|
{ // give some particle and sound effects where the player was beyond the border
|
|
world.playEffect(loc, Effect.ENDER_SIGNAL, 0);
|
|
world.playEffect(loc, Effect.ENDER_SIGNAL, 0);
|
|
world.playEffect(loc, Effect.SMOKE, 4);
|
|
world.playEffect(loc, Effect.SMOKE, 4);
|
|
world.playEffect(loc, Effect.SMOKE, 4);
|
|
world.playEffect(loc, Effect.GHAST_SHOOT, 0);
|
|
}
|
|
|
|
if (returnLocationOnly)
|
|
return newLoc;
|
|
|
|
if (!player.isInsideVehicle())
|
|
player.teleport(newLoc);
|
|
else
|
|
{
|
|
Vehicle ride = player.getVehicle();
|
|
if (ride != null)
|
|
{ // vehicles need to be offset vertically and have velocity stopped
|
|
double vertOffset = ride.getLocation().getY() - loc.getY();
|
|
newLoc.setY(newLoc.getY() + vertOffset);
|
|
ride.setVelocity(new Vector(0, 0, 0));
|
|
ride.teleport(newLoc);
|
|
}
|
|
else
|
|
{ // if player.getVehicle() returns null (when riding a pig on older Bukkit releases, for instance), player has to be ejected
|
|
player.leaveVehicle();
|
|
player.teleport(newLoc);
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private static Location newLocation(Player player, Location loc, BorderData border)
|
|
{
|
|
if (Config.Debug())
|
|
{
|
|
Config.LogWarn("Border crossing in \"" + loc.getWorld().getName() + "\". Border " + border.toString());
|
|
Config.LogWarn("Player position X: " + Config.coord.format(loc.getX()) + " Y: " + Config.coord.format(loc.getY()) + " Z: " + Config.coord.format(loc.getZ()));
|
|
}
|
|
|
|
Location newLoc = border.correctedPosition(loc, Config.ShapeRound());
|
|
|
|
// it's remotely possible (such as in the Nether) a suitable location isn't available, in which case...
|
|
if (newLoc == null)
|
|
{
|
|
if (Config.Debug())
|
|
Config.LogWarn("Target new location unviable, using spawn.");
|
|
newLoc = player.getWorld().getSpawnLocation();
|
|
}
|
|
|
|
if (Config.Debug())
|
|
Config.LogWarn("New position in world \"" + newLoc.getWorld().getName() + "\" at X: " + Config.coord.format(newLoc.getX()) + " Y: " + Config.coord.format(newLoc.getY()) + " Z: " + Config.coord.format(newLoc.getZ()));
|
|
|
|
player.sendMessage(ChatColor.RED + Config.Message());
|
|
|
|
return newLoc;
|
|
}
|
|
}
|