Player teleports are now monitored and (if necessary) redirected inside the border; sadly this doesn't prevent the original target chunk from being loaded/generated (which would be nice if it's outside your border), but at least the player never ends up there now for even a fraction of a second

This commit is contained in:
Brettflan 2011-12-14 07:18:18 -06:00
parent 7eb7404dcd
commit beb224fa1e
3 changed files with 69 additions and 48 deletions

View File

@ -20,58 +20,64 @@ public class BorderCheckTask implements Runnable
public void run()
{
// long startTime = Config.Now(); // for monitoring plugin efficiency
if (server == null)
{
// Config.timeUsed += Config.Now() - startTime; // for monitoring plugin efficiency
return;
}
Player[] players = server.getOnlinePlayers();
for (int i = 0; i < players.length; i++){
if (players[i] == null || !players[i].isOnline()) continue;
checkPlayer(players[i], null, false);
}
}
Location loc = players[i].getLocation();
if (loc == null) continue;
// 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;
World world = loc.getWorld();
if (world == null) continue;
BorderData border = Config.Border(world.getName());
if (border == null) continue;
Location loc = (targetLoc == null) ? player.getLocation() : targetLoc;
if (loc == null) return null;
if (border.insideBorder(loc.getX(), loc.getZ(), Config.ShapeRound()))
continue;
World world = loc.getWorld();
if (world == null) return null;
BorderData border = Config.Border(world.getName());
if (border == null) return null;
Location newLoc = newLocation(players[i], loc, border);
if (border.insideBorder(loc.getX(), loc.getZ(), Config.ShapeRound()))
return null;
if (!players[i].isInsideVehicle())
players[i].teleport(newLoc);
else
{
Vehicle ride = players[i].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
players[i].leaveVehicle();
players[i].teleport(newLoc);
}
Location newLoc = newLocation(player, loc, border);
if (Config.whooshEffect())
{ // show some smoke and play the extinguish sound effect where the player was beyond the border
world.playEffect(loc, Effect.SMOKE, 4);
world.playEffect(loc, Effect.SMOKE, 4);
world.playEffect(loc, Effect.EXTINGUISH, 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);
}
if (Config.whooshEffect())
{ // show some smoke and play the extinguish sound effect where the player was beyond the border
world.playEffect(loc, Effect.SMOKE, 4);
world.playEffect(loc, Effect.SMOKE, 4);
world.playEffect(loc, Effect.EXTINGUISH, 0);
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);
}
}
// Config.timeUsed += Config.Now() - startTime; // for monitoring plugin efficiency
return null;
}
private static Location newLocation(Player player, Location loc, BorderData border)

View File

@ -0,0 +1,19 @@
package com.wimbli.WorldBorder;
import org.bukkit.event.player.PlayerListener;
import org.bukkit.event.player.PlayerTeleportEvent;
import org.bukkit.Location;
public class WBPlayerListener extends PlayerListener
{
@Override
public void onPlayerTeleport(PlayerTeleportEvent event)
{
if (event.isCancelled()) return;
Location newLoc = BorderCheckTask.checkPlayer(event.getPlayer(), event.getTo(), true);
if (newLoc != null)
event.setTo(newLoc);
}
}

View File

@ -1,5 +1,7 @@
package com.wimbli.WorldBorder;
import org.bukkit.event.Event;
import org.bukkit.event.Event.Priority;
import org.bukkit.Location;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.plugin.PluginDescriptionFile;
@ -7,6 +9,8 @@ import org.bukkit.plugin.PluginDescriptionFile;
public class WorldBorder extends JavaPlugin
{
private final WBPlayerListener pl = new WBPlayerListener();
public void onEnable()
{
PluginDescriptionFile desc = this.getDescription();
@ -23,16 +27,8 @@ public class WorldBorder extends JavaPlugin
// our one real command, though it does also have aliases "wb" and "worldborder"
getCommand("wborder").setExecutor(new WBCommand(this));
/* // for monitoring plugin efficiency
getServer().getScheduler().scheduleSyncRepeatingTask(this, new Runnable()
{
public long startTime = Config.Now();
public void run()
{
Config.Log("Running for " + (int)((Config.Now() - startTime) / (60000)) + " minutes, has used total border checking time of " + Config.timeUsed + "ms.");
}
}, 1200, 1200);
*/
// keep an eye on teleports, to redirect them to a spot inside the border if necessary
getServer().getPluginManager().registerEvent(Event.Type.PLAYER_TELEPORT, pl, Priority.Lowest, this);
}
public void onDisable()