timeout for bordermessage

cancel teleport events if destination is outside border
This commit is contained in:
Paul Schulze 2012-09-29 22:53:44 +02:00
parent a469f5a427
commit 19b8e12ff4
10 changed files with 231 additions and 68 deletions

Binary file not shown.

View File

@ -4,7 +4,7 @@
<groupId>CraftincBorderProtection</groupId>
<artifactId>CraftincBorderProtection</artifactId>
<packaging>jar</packaging>
<version>0.9.5</version>
<version>0.9.9</version>
<name>CraftincGates</name>
<url>http://maven.apache.org</url>
<properties>

View File

@ -2,10 +2,12 @@ package de.craftinc.borderprotection;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.entity.Player;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.HashMap;
public class BorderManager
@ -25,15 +27,21 @@ public class BorderManager
private HashMap<String, ArrayList<Location>> borders = null;
/**
* the buffer in blocks which applies when a player is teleported inside the border. 0 means the player
* For every player save the time when he got the last borderMessage
*/
public HashMap<String, Long> lastBorderMessage = new HashMap<String, Long>();
/**
* The buffer in blocks which applies when a player is teleported inside the border. 0 means the player
* will be teleported directly to the border.
*/
private double buffer = 0.5;
public Serializer getSerializer()
{
return serializer;
}
/**
* A timeout for the border message. When a player tries to cross the border and sees the border message,
* the earliest possible time the message will show up again is after <code>timeout</code> milliseconds.
*/
private Long timeout = 10000L;
/**
* Serializer, which is used for loading and saving data to harddisk
@ -59,11 +67,21 @@ public class BorderManager
* **********************************************************
*/
public Serializer getSerializer()
{
return serializer;
}
public double getBuffer()
{
return buffer;
}
public Long getTimeout()
{
return timeout;
}
public HashMap<String, ArrayList<Location>> getBorders()
{
return borders;
@ -103,4 +121,89 @@ public class BorderManager
borders.put(worldName, locations);
}
/**
* Checks if the given location is inside the border rectangle. Returns null if yes, otherwise new coordinates.
*
* @param location location to check
* @param borderPoints points which define the border rectangle
* @param buffer if the player will be teleported back, then he will be <code>buffer</code> far away
* from the border he tried to cross
* @return null if the player is inside, otherwise a new player location
*/
public Double[] checkBorder( Location location, ArrayList<Location> borderPoints, double buffer )
{
// New x and z: null by default
Double[] newXZ = { null, null };
// check if player is withing the X borders
newXZ[0] = _checkBorder(location.getX(), borderPoints.get(0).getX(), borderPoints.get(1).getX(), buffer);
// check if player is withing the Z borders
newXZ[1] = _checkBorder(location.getZ(), borderPoints.get(0).getZ(), borderPoints.get(1).getZ(), buffer);
// Do nothing, if no new coordinates have been calculated.
if ( newXZ[0] == null && newXZ[1] == null )
{
return null;
}
return newXZ;
}
/**
* Checks if the given location is between one specific border pair.
*
* @param location part of the location coordinates
* @param border1 one side of the rectangle
* @param border2 opposite side of the rectangle
* @return null if the location is inside, otherwise a new location
*/
public Double _checkBorder( double location, double border1, double border2, double buffer )
{
double bigBorder = Math.max(border1, border2);
double smallBorder = Math.min(border1, border2);
// if location is between borders do nothing
if ( location >= smallBorder && location <= bigBorder )
{
return null;
}
else
{
if ( location > bigBorder )
{
// if location is outside of the bigBorder, teleport to the bigBorder
return bigBorder - buffer;
}
else
{
// if location is outside of the smallBorder, teleport to the smallBorder
return smallBorder + buffer;
}
}
}
/**
* Show the border message to a player and respect the timeout.
*
* @param player Player who will see the border message.
*/
public void showMessageWithTimeout( Player player, String message )
{
// get the current time
Long now = Calendar.getInstance().getTimeInMillis();
if ( ( lastBorderMessage.get(player.getName()) != null &&
now - getTimeout() > lastBorderMessage.get(player.getName()) ) ||
lastBorderMessage.get(player.getName()) == null )
{
// show message
player.sendMessage(message);
// set last sent message for this player to now
lastBorderMessage.put(player.getName(), now);
}
}
}

View File

@ -37,15 +37,22 @@ public class Messages
return sb.toString();
}
private static String borderExplanation =
"One day the holy mods and administrators will expand the border. It is then your mission to explore " +
"strange new worlds, to seek out new life and new civilizations, to boldly go where no one has gone before.";
public static String borderMessage =
"Sorry Dude! This is the border... the final frontier! One day the holy mods " +
"and administrators will expand the border. It is then your mission to explore " +
"strange new worlds, to seek out new life and new civilizations, to boldly go " +
"where no one has gone before.";
"Sorry Dude! This is the border... the final frontier! " + borderExplanation + NEWLINE +
makeCmd("/cibp get", "shows the borders of the current world");
public static String borderTeleportMessage =
"Sorry Dude! You cannot teleport outside the border. " + borderExplanation + NEWLINE +
makeCmd("/cibp get", "shows the borders of the current world");
public static String helpGeneral =
ChatColor.GREEN + "CraftInc BorderProtection - Usage:" + NEWLINE +
makeCmd("help", "shows this help") +
makeCmd("get | info", "shows the borders of the current world") +
makeCmd("set", "Border rectangle edges will be this far away from point of origin.", "<integer>") +
makeCmd("set", "Border rectangle is defined by the two points. A point is specified as: x,z",
"<point1>", "<point2>");
@ -56,7 +63,7 @@ public class Messages
public static String borderInfo( String worldName, String borderDef )
{
return ChatColor.WHITE + "Border definition of world " +
return ChatColor.WHITE + "Borders of world " +
ChatColor.YELLOW + worldName +
ChatColor.WHITE + ": " +
ChatColor.YELLOW + borderDef;

View File

@ -21,39 +21,6 @@ public class PlayerMoveListener implements Listener
this.borderManager = borderManager;
}
/**
* Checks if the player is outside of one specific border.
*
* @param player part of the player coordinates
* @param border1 one side of the rectangle
* @param border2 opposite side of the rectangle
* @return null if the player is inside, otherwise a new player location
*/
private Double checkBorder( double player, double border1, double border2 )
{
double bigBorder = Math.max(border1, border2);
double smallBorder = Math.min(border1, border2);
// if player is between borders do nothing
if ( player >= smallBorder && player <= bigBorder )
{
return null;
}
else
{
if ( player > bigBorder )
{
// if player is outside of the bigBorder, teleport him to the bigBorder
return bigBorder - borderManager.getBuffer();
}
else
{
// if player is outside of the smallBorder, teleport him to the smallBorder
return smallBorder + borderManager.getBuffer();
}
}
}
private Double goUpUntilFreeSpot( Player player )
{
// go up in height until the player can stand in AIR
@ -82,14 +49,19 @@ public class PlayerMoveListener implements Listener
return;
}
// do nothing if there is no border defined
// do nothing if there are no border definitions at all
if ( borderManager.getBorders() == null )
{
return;
}
Location pl = e.getPlayer().getLocation();
// player location
Location playerLocation = e.getPlayer().getLocation();
// world where the player is in
String worldName = e.getPlayer().getWorld().getName();
// borders of this world
ArrayList<Location> borderPoints = borderManager.getBorders().get(worldName);
// do nothing if there are no borders for this specific world
@ -97,29 +69,30 @@ public class PlayerMoveListener implements Listener
return;
// change x or z. default: do not change
Double newX, newY, newZ;
Double[] newXZ;
newX = checkBorder(pl.getX(), borderPoints.get(0).getX(), borderPoints.get(1).getX());
newZ = checkBorder(pl.getZ(), borderPoints.get(0).getZ(), borderPoints.get(1).getZ());
// check if player is inside the borders. null if yes, otherwise a tuple which defines the new player position
newXZ = borderManager.checkBorder(playerLocation, borderPoints, borderManager.getBuffer());
// Do nothing, if no new coordinates have been calculated.
if ( newX == null && newZ == null )
if ( newXZ == null )
{
return;
}
// if one of the coordinates is null, set it to the player's value
newX = newX == null ? pl.getX() : newX;
newZ = newZ == null ? pl.getZ() : newZ;
newXZ[0] = newXZ[0] == null ? playerLocation.getX() : newXZ[0];
newXZ[1] = newXZ[1] == null ? playerLocation.getZ() : newXZ[1];
// change Y if necessary (when there is no free spot)
newY = goUpUntilFreeSpot(e.getPlayer());
Double newY = goUpUntilFreeSpot(e.getPlayer());
// teleport the player to the new X and Z coordinates
e.getPlayer().teleport(
new Location(e.getPlayer().getWorld(), newX, newY, newZ, pl.getYaw(), pl.getPitch()));
new Location(e.getPlayer().getWorld(), newXZ[0], newY, newXZ[1], playerLocation.getYaw(),
playerLocation.getPitch()));
// send a message to the player
e.getPlayer().sendMessage(Messages.borderMessage);
borderManager.showMessageWithTimeout(e.getPlayer(), Messages.borderMessage);
}
}

View File

@ -0,0 +1,64 @@
package de.craftinc.borderprotection;
import org.bukkit.Location;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerTeleportEvent;
import java.util.ArrayList;
public class PlayerTeleportListener implements Listener
{
private BorderManager borderManager;
public PlayerTeleportListener( BorderManager borderManager )
{
this.borderManager = borderManager;
}
@EventHandler(priority = EventPriority.LOWEST)
public void onPlayerMove( PlayerTeleportEvent e )
{
// do nothing if player has the ignoreborders permission
if ( e.getPlayer().hasPermission("craftinc.borderprotection.ignoreborders") )
{
return;
}
// do nothing if there are no border definitions at all
if ( borderManager.getBorders() == null )
{
return;
}
// target location
Location targetLocation = e.getTo();
// world where the player is in
String worldName = targetLocation.getWorld().getName();
// borders of this world
ArrayList<Location> borderPoints = borderManager.getBorders().get(worldName);
// do nothing if there are no borders for this specific world
if ( borderPoints == null )
{
return;
}
// change x or z. default: do not change
Double[] newXZ;
// check if target is inside the borders. null if yes, otherwise a tuple which defines the new position
newXZ = borderManager.checkBorder(targetLocation, borderPoints, borderManager.getBuffer());
// Cancel event, if new coordinates have been calculated.
if ( newXZ != null )
{
e.setCancelled(true);
borderManager.showMessageWithTimeout(e.getPlayer(), Messages.borderTeleportMessage);
}
}
}

View File

@ -23,11 +23,16 @@ public class Plugin extends JavaPlugin
Plugin.cibpPlugin = this;
BorderManager borderManager = new BorderManager();
PlayerMoveListener eventListener = new PlayerMoveListener(borderManager);
Commands commandExecutor = new Commands(borderManager);
PlayerMoveListener playerMoveListener = new PlayerMoveListener(borderManager);
PlayerTeleportListener playerTeleportListener = new PlayerTeleportListener(borderManager);
PluginManager pm = this.getServer().getPluginManager();
// commands
Commands commandExecutor = new Commands(borderManager);
getCommand("cibp").setExecutor(commandExecutor);
pm.registerEvents(eventListener, this);
// listeners
PluginManager pm = this.getServer().getPluginManager();
pm.registerEvents(playerMoveListener, this);
pm.registerEvents(playerTeleportListener, this);
}
}

View File

@ -17,6 +17,11 @@ public class Util
for ( Object jsonEntry : json.toArray() )
{
JSONObject j = (JSONObject) jsonEntry;
// // check if border for this world is enabled. continue if not
// String enabled = (String) j.get("enabled");
// if (enabled != "1") {
// continue;
// }
String worldname = (String) j.get("worldname");
ArrayList<Location> locations = new ArrayList<Location>();
JSONArray borderPoints = (JSONArray) j.get("borderPoints");
@ -32,18 +37,20 @@ public class Util
data.put(worldname, locations);
}
if (data.size() > 0) {
if ( data.size() > 0 )
{
return data;
}
return null;
}
public static JSONArray encodeJSON( HashMap<String,ArrayList<Location>> data )
public static JSONArray encodeJSON( HashMap<String, ArrayList<Location>> data )
{
JSONArray json = new JSONArray();
int i = 0;
for (ArrayList<Location> border: data.values()) {
for ( ArrayList<Location> border : data.values() )
{
// add point 1 as json array
JSONArray point1 = new JSONArray();
@ -62,15 +69,19 @@ public class Util
// Add points and worldname to world json object
JSONObject borderOfAWorld = new JSONObject();
try {
try
{
borderOfAWorld.put("worldname", border.get(0).getWorld().getName());
borderOfAWorld.put("borderPoints", points);
json.add(i, borderOfAWorld);
i++;
}
catch (NullPointerException e) {
if (border.get(0).getWorld() == null) {
Plugin.getPlugin().getLogger().warning("A world is null. Ignoring this border (not saving this border).");
catch ( NullPointerException e )
{
if ( border.get(0).getWorld() == null )
{
Plugin.getPlugin().getLogger()
.warning("A world is null. Ignoring this border (not saving this border).");
}
}
}

View File

@ -1,6 +1,6 @@
name: CraftincBorderProtection
main: de.craftinc.borderprotection.Plugin
version: 0.9.5
version: 0.9.9
author: ddidderr
website: http://www.craftinc.de/plugins/borderprotection