Merge bc36bcbee3
into f9d89034b4
This commit is contained in:
commit
2e7cffd637
20
pom.xml
20
pom.xml
|
@ -3,7 +3,7 @@
|
|||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.wimbli.WorldBorder</groupId>
|
||||
<artifactId>WorldBorder</artifactId>
|
||||
<version>1.8.5</version>
|
||||
<version>1.8.8</version>
|
||||
<name>WorldBorder</name>
|
||||
<url>https://github.com/Brettflan/WorldBorder</url>
|
||||
<issueManagement>
|
||||
|
@ -31,13 +31,13 @@
|
|||
<dependency>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot-api</artifactId>
|
||||
<version>1.8.7-R0.1-SNAPSHOT</version>
|
||||
<version>1.9-R0.1-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<!--Bukkit API-->
|
||||
<dependency>
|
||||
<groupId>org.bukkit</groupId>
|
||||
<artifactId>bukkit</artifactId>
|
||||
<version>1.8.7-R0.1-SNAPSHOT</version>
|
||||
<version>1.9-R0.1-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<!--Dynmap API-->
|
||||
<dependency>
|
||||
|
@ -49,15 +49,21 @@
|
|||
|
||||
<build>
|
||||
<defaultGoal>clean install</defaultGoal>
|
||||
<finalName>${project.artifactId}</finalName>
|
||||
<finalName>${project.artifactId}-${project.version}</finalName>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<filtering>true</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>2.0.2</version>
|
||||
<version>3.5.1</version>
|
||||
<configuration>
|
||||
<source>1.6</source>
|
||||
<target>1.6</target>
|
||||
<source>1.7</source>
|
||||
<target>1.7</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
|
|
|
@ -2,8 +2,9 @@ package com.wimbli.WorldBorder;
|
|||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
|
@ -17,7 +18,7 @@ import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
|
|||
import org.bukkit.Location;
|
||||
import org.bukkit.util.Vector;
|
||||
import org.bukkit.World;
|
||||
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
public class BorderCheckTask implements Runnable
|
||||
{
|
||||
|
@ -36,8 +37,97 @@ public class BorderCheckTask implements Runnable
|
|||
}
|
||||
}
|
||||
|
||||
// track players who are being handled (moved back inside the border) already; needed since Bukkit is sometimes sending teleport events with the old (now incorrect) location still indicated, which can lead to a loop when we then teleport them thinking they're outside the border, triggering event again, etc.
|
||||
private static Set<String> handlingPlayers = Collections.synchronizedSet(new LinkedHashSet<String>());
|
||||
/** track players who are being handled (moved back inside the border) already; needed
|
||||
* since Bukkit is sometimes sending teleport events with the old (now incorrect) location
|
||||
* still indicated, which can lead to a loop when we then teleport them thinking they're
|
||||
* outside the border, triggering event again, etc.
|
||||
*/
|
||||
private static Map<String, BukkitRunnable> handlingPlayers = Collections.synchronizedMap(new LinkedHashMap<String, BukkitRunnable>());
|
||||
|
||||
/**
|
||||
* In 1.9, there is a significant delay between teleportation event and when the player's location is actually updated.
|
||||
* However, the player world is updated immediately. This disconnection causes the regular checkPlayer to
|
||||
* incorrectly test the player's prior-world location against the new-world location during that amorphous
|
||||
* in-between period. Basically, this checks for the location to actually update, e.g. to be different from the
|
||||
* "from" location of the portal event.
|
||||
*
|
||||
* This function allows a configurable recheck to let Minecraft "catch up" the player's <i>real</i> location.
|
||||
*
|
||||
* In the meantime, the player is exempted from border crossing checks (and from spurious additional teleport event
|
||||
* checks).
|
||||
*
|
||||
* Note that additional portal teleports (e.g. if the player immediately portals back) will reset
|
||||
* this check gracefully.
|
||||
*
|
||||
* @param player The player who is being exempted.
|
||||
* @param prior the location the player has come from
|
||||
* @param maxDelay The <i>maximum</i> ticks to spend exempting this player
|
||||
* @param recheckDelay The ticks to wait inbetween rechecks.
|
||||
*/
|
||||
public static void timedPlayerExemption(final Player player, final Location prior, final long maxDelay, final long recheckDelay) {
|
||||
|
||||
// Check for existing watch; cancel if one exists.
|
||||
BukkitRunnable alreadyWatching = handlingPlayers.get(player.getName().toLowerCase());
|
||||
if (alreadyWatching != null) {
|
||||
try {
|
||||
alreadyWatching.cancel();
|
||||
} catch (IllegalStateException e){}
|
||||
}
|
||||
|
||||
alreadyWatching = new BukkitRunnable() {
|
||||
private final String playerName = player.getName().toLowerCase();
|
||||
private final UUID playerUUID = player.getUniqueId();
|
||||
private long currentDelay = recheckDelay;
|
||||
@Override
|
||||
public void run() {
|
||||
// Are we done checking?
|
||||
if (currentDelay > maxDelay) {
|
||||
this.cancel();
|
||||
handlingPlayers.remove(playerName);
|
||||
if (Config.Debug())
|
||||
Config.log("Done watching " + playerName + ". They are in the hands of fate, now.");
|
||||
return;
|
||||
}
|
||||
currentDelay += recheckDelay;
|
||||
|
||||
// Is this player still online?
|
||||
Player player = Bukkit.getPlayer(playerUUID);
|
||||
if (player == null) { // assume offline
|
||||
this.cancel();
|
||||
handlingPlayers.remove(playerName);
|
||||
if (Config.Debug())
|
||||
Config.log("Looks like " + playerName + " logged off. Suspending watch.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Are we still stuck between worlds?
|
||||
Location current = player.getLocation();
|
||||
if (current.getBlockX() != prior.getBlockX() && current.getBlockY() != prior.getBlockY() &&
|
||||
current.getBlockZ() != prior.getBlockZ()) {
|
||||
// No, we made it!
|
||||
this.cancel();
|
||||
handlingPlayers.remove(playerName);
|
||||
if (Config.Debug())
|
||||
Config.log("Minecraft caught up with " + playerName + ". Ending watch.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (Config.Debug()) {
|
||||
Config.log("Based on teleport " + playerName +
|
||||
" has moved, but Minecraft still has them at old location " +
|
||||
prior.toString() + ". Checking again in " + recheckDelay);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Store the exemption and start the recheck.
|
||||
handlingPlayers.put(player.getName().toLowerCase(), alreadyWatching);
|
||||
alreadyWatching.runTaskTimer(WorldBorder.plugin, recheckDelay, recheckDelay);
|
||||
|
||||
if (Config.Debug())
|
||||
Config.log("Rechecking " + player.getName() + "'s world every " +
|
||||
recheckDelay + " ticks for " + maxDelay + " ticks.");
|
||||
}
|
||||
|
||||
// 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, boolean notify)
|
||||
|
@ -56,11 +146,11 @@ public class BorderCheckTask implements Runnable
|
|||
return null;
|
||||
|
||||
// if player is in bypass list (from bypass command), allow them beyond border; also ignore players currently being handled already
|
||||
if (Config.isPlayerBypassing(player.getUniqueId()) || handlingPlayers.contains(player.getName().toLowerCase()))
|
||||
if (Config.isPlayerBypassing(player.getUniqueId()) || handlingPlayers.containsKey(player.getName().toLowerCase()))
|
||||
return null;
|
||||
|
||||
// tag this player as being handled so we can't get stuck in a loop due to Bukkit currently sometimes repeatedly providing incorrect location through teleport event
|
||||
handlingPlayers.add(player.getName().toLowerCase());
|
||||
handlingPlayers.put(player.getName().toLowerCase(), null);
|
||||
|
||||
Location newLoc = newLocation(player, loc, border, notify);
|
||||
boolean handlingVehicle = false;
|
||||
|
|
|
@ -56,6 +56,8 @@ public class Config
|
|||
private static int fillMemoryTolerance = 500;
|
||||
private static boolean preventBlockPlace = false;
|
||||
private static boolean preventMobSpawn = false;
|
||||
private static long maxExemptionTicks = 21l;
|
||||
private static long portalRecheckTicks = 4l; // These together give 5 recheck chances over the course of a second.
|
||||
|
||||
// for monitoring plugin efficiency
|
||||
// public static long timeUsed = 0;
|
||||
|
@ -544,6 +546,21 @@ public class Config
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public static long getMaxExemptionTicks() {
|
||||
return maxExemptionTicks;
|
||||
}
|
||||
public static void setMaxExemptionTicks(long maxExemptionTicks) {
|
||||
Config.maxExemptionTicks = maxExemptionTicks;
|
||||
}
|
||||
|
||||
public static long getPortalRecheckTicks() {
|
||||
return portalRecheckTicks;
|
||||
}
|
||||
public static void setPortalRecheckTicks(long portalRecheckTicks) {
|
||||
Config.portalRecheckTicks = portalRecheckTicks;
|
||||
}
|
||||
|
||||
|
||||
public static String replaceAmpColors (String message)
|
||||
|
@ -605,6 +622,8 @@ public class Config
|
|||
fillMemoryTolerance = cfg.getInt("fill-memory-tolerance", 500);
|
||||
preventBlockPlace = cfg.getBoolean("prevent-block-place");
|
||||
preventMobSpawn = cfg.getBoolean("prevent-mob-spawn");
|
||||
maxExemptionTicks = cfg.getLong("max-exemption-ticks", 21l);
|
||||
portalRecheckTicks = cfg.getLong("portal-recheck-ticks", 4l);
|
||||
|
||||
StartBorderTimer();
|
||||
|
||||
|
@ -713,6 +732,8 @@ public class Config
|
|||
cfg.set("fill-memory-tolerance", fillMemoryTolerance);
|
||||
cfg.set("prevent-block-place", preventBlockPlace);
|
||||
cfg.set("prevent-mob-spawn", preventMobSpawn);
|
||||
cfg.set("max-exemption-ticks", maxExemptionTicks);
|
||||
cfg.set("portal-recheck-ticks", portalRecheckTicks);
|
||||
|
||||
cfg.set("worlds", null);
|
||||
for(Entry<String, BorderData> stringBorderDataEntry : borders.entrySet())
|
||||
|
@ -751,4 +772,5 @@ public class Config
|
|||
if (logIt)
|
||||
logConfig("Configuration saved.");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -9,7 +9,6 @@ import org.bukkit.event.player.PlayerPortalEvent;
|
|||
import org.bukkit.event.world.ChunkLoadEvent;
|
||||
import org.bukkit.Location;
|
||||
|
||||
|
||||
public class WBListener implements Listener
|
||||
{
|
||||
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
|
||||
|
@ -19,8 +18,11 @@ public class WBListener implements Listener
|
|||
if (Config.KnockBack() == 0.0)
|
||||
return;
|
||||
|
||||
if (Config.Debug())
|
||||
Config.log("Teleport cause: " + event.getCause().toString());
|
||||
if (event instanceof PlayerPortalEvent) { // Avoid overlapping management.
|
||||
if (Config.Debug())
|
||||
Config.log("Skipping teleport management event - covered by onPlayerPortal");
|
||||
return;
|
||||
}
|
||||
|
||||
Location newLoc = BorderCheckTask.checkPlayer(event.getPlayer(), event.getTo(), true, true);
|
||||
if (newLoc != null)
|
||||
|
@ -38,13 +40,20 @@ public class WBListener implements Listener
|
|||
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
|
||||
public void onPlayerPortal(PlayerPortalEvent event)
|
||||
{
|
||||
if (Config.Debug())
|
||||
Config.log("Player Portal Teleport cause: " + event.getCause().toString());
|
||||
|
||||
// if knockback is set to 0, or portal redirection is disabled, simply return
|
||||
if (Config.KnockBack() == 0.0 || !Config.portalRedirection())
|
||||
return;
|
||||
|
||||
Location newLoc = BorderCheckTask.checkPlayer(event.getPlayer(), event.getTo(), true, false);
|
||||
if (newLoc != null)
|
||||
if (newLoc != null) {
|
||||
event.setTo(newLoc);
|
||||
}
|
||||
|
||||
BorderCheckTask.timedPlayerExemption(event.getPlayer(), event.getFrom().clone(),
|
||||
Config.getMaxExemptionTicks(), Config.getPortalRecheckTicks());
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
name: WorldBorder
|
||||
name: ${project.name}
|
||||
author: Brettflan
|
||||
description: Efficient, feature-rich plugin for limiting the size of your worlds.
|
||||
version: 1.8.5
|
||||
version: ${project.version}
|
||||
main: com.wimbli.WorldBorder.WorldBorder
|
||||
softdepend:
|
||||
- dynmap
|
||||
|
|
Loading…
Reference in New Issue