Teleport 'warmup' time - delay before teleport

Closes #507.

War now includes a configuration option "TPWARMUP" to add delays
before teleporting players to a war. This can be used on full-world
PvP servers to prevent players from running away from a fight.

The configuration option is specified in ticks - 20/sec.

The delay is activated for /zone and /warhub.

@taoneill @cmastudios documentate for 1.9 release.
This commit is contained in:
cmastudios 2014-02-22 19:46:53 -06:00
parent 72a2f08d70
commit 64ae4c617f
7 changed files with 148 additions and 2 deletions

View File

@ -183,6 +183,7 @@ public class War extends JavaPlugin {
warConfig.put(WarConfig.MAXSIZE, 750);
warConfig.put(WarConfig.LANGUAGE, Locale.getDefault().toString());
warConfig.put(WarConfig.AUTOJOIN, "");
warConfig.put(WarConfig.TPWARMUP, 0);
warzoneDefaultConfig.put(WarzoneConfig.AUTOASSIGN, false);
warzoneDefaultConfig.put(WarzoneConfig.BLOCKHEADS, true);

View File

@ -1,5 +1,7 @@
package com.tommytony.war.command;
import com.tommytony.war.config.WarConfig;
import com.tommytony.war.job.TeleportPlayerJob;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
@ -36,7 +38,15 @@ public class WarhubCommand extends AbstractWarCommand {
if (playerWarzone != null) { // was in zone
playerWarzone.handlePlayerLeave(player, War.war.getWarHub().getLocation(), true);
}
player.teleport(War.war.getWarHub().getLocation());
int warmup = War.war.getWarConfig().getInt(WarConfig.TPWARMUP);
if (warmup > 0) {
final int TICKS_PER_SECOND = 20;
TeleportPlayerJob job = new TeleportPlayerJob(player, War.war.getWarHub().getLocation());
job.runTaskLater(War.war, warmup);
this.msg("command.tp.init", warmup / TICKS_PER_SECOND);
} else {
player.teleport(War.war.getWarHub().getLocation());
}
}
return true;
}

View File

@ -1,5 +1,7 @@
package com.tommytony.war.command;
import com.tommytony.war.config.WarConfig;
import com.tommytony.war.job.TeleportPlayerJob;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
@ -30,8 +32,14 @@ public class WarzoneCommand extends AbstractWarCommand {
Warzone warzone = Warzone.getZoneByName(args[0]);
if (warzone != null && warzone.getTeleport() != null) {
Warzone playerWarzone = Warzone.getZoneByPlayerName(player.getName());
int warmup = War.war.getWarConfig().getInt(WarConfig.TPWARMUP);
if (playerWarzone != null) {
playerWarzone.handlePlayerLeave(player, warzone.getTeleport(), true);
} else if (warmup > 0) {
final int TICKS_PER_SECOND = 20;
TeleportPlayerJob job = new TeleportPlayerJob(player, warzone.getTeleport());
job.runTaskLater(War.war, warmup);
this.msg("command.tp.init", warmup / TICKS_PER_SECOND);
} else {
player.teleport(warzone.getTeleport());
}

View File

@ -12,7 +12,8 @@ public enum WarConfig {
RESETSPEED (Integer.class),
MAXSIZE (Integer.class),
LANGUAGE (String.class),
AUTOJOIN (String.class);
AUTOJOIN (String.class),
TPWARMUP(Integer.class);
private final Class<?> configType;

View File

@ -0,0 +1,51 @@
package com.tommytony.war.job;
import com.tommytony.war.War;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerTeleportEvent;
import org.bukkit.scheduler.BukkitRunnable;
public class TeleportPlayerJob extends BukkitRunnable {
private final Player player;
private final Location location;
private final Location originalLocation;
private final double originalHealth;
public TeleportPlayerJob(Player player, Location location) {
this.player = player;
this.location = location;
this.originalLocation = player.getLocation().clone();
this.originalHealth = player.getHealth();
}
@Override
public void run() {
if (!player.isOnline()) {
} else if (hasPlayerMoved()) {
War.war.badMsg(player, "command.tp.moved");
} else if (hasPlayerTakenDamage()) {
War.war.badMsg(player, "command.tp.damaged");
} else {
player.teleport(location, PlayerTeleportEvent.TeleportCause.COMMAND);
War.war.msg(player, "command.tp.success");
}
}
boolean hasPlayerMoved() {
final double MAX_MOVE_TOLERANCE = 1.5;
return distance3D(player.getLocation(), originalLocation) > MAX_MOVE_TOLERANCE;
}
boolean hasPlayerTakenDamage() {
final double MAX_DAMAGE_TOLERANCE = 2;
return Math.abs(originalHealth - player.getHealth()) > MAX_DAMAGE_TOLERANCE;
}
double distance3D(Location pos1, Location pos2) {
double distX = pos2.getX() - pos1.getX();
double distY = pos2.getY() - pos1.getY();
double distZ = pos2.getZ() - pos1.getZ();
return Math.sqrt(Math.pow(distX, 2) + Math.pow(distY, 2) + Math.pow(distZ, 2));
}
}

View File

@ -9,6 +9,10 @@ build.denied.zone.place = You cannot place blocks in this warzone.
build.denied.zone.type = You cannot modify this type of block.
command.console = You can't do this if you are not in game.
command.disabled = You can only use War commands (e.g. /leave) while playing.
command.tp.init = Please wait for {0} seconds before teleportation. Movement or damage will cancel the timer.
command.tp.moved = Teleportation cancelled due to movement.
command.tp.damaged = Teleportation cancelled due to damage.
command.tp.success = You have been teleported. Thanks for your patience.
drop.bomb.broadcast = {0} dropped the {1} bomb!
drop.bomb.disabled = You can't drop items while stealing bomb. What are you doing?! Run for your enemy's spawn!
drop.cake.broadcast = {0} dropped the {1} cake!

View File

@ -0,0 +1,71 @@
package com.tommytony.war.job;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.entity.Player;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class TeleportPlayerJobTest {
World world;
Player player;
TeleportPlayerJob job;
@Before
public void setUp() throws Exception {
player = mock(Player.class);
world = mock(World.class);
when(world.getName()).thenReturn("world");
when(player.getHealth()).thenReturn(20.0);
when(player.getLocation()).thenReturn(new Location(world, 0, 0, 0));
job = new TeleportPlayerJob(player, new Location(world, 0, 0, 0));
}
@Test
public void testPlayerMove_noMovement_false() {
when(player.getLocation()).thenReturn(new Location(world, 0, 0, 0));
assertFalse(job.hasPlayerMoved());
}
@Test
public void testPlayerMove_smallMovement_false() {
when(player.getLocation()).thenReturn(new Location(world, 0.5, 0.5, 0.5));
assertFalse(job.hasPlayerMoved());
}
@Test
public void testPlayerMove_largeMovement_true() {
when(player.getLocation()).thenReturn(new Location(world, 5, 1, 3));
assertTrue(job.hasPlayerMoved());
}
@Test
public void testPlayerDamage_noDamage_false() {
when(player.getHealth()).thenReturn(20.0);
assertFalse(job.hasPlayerTakenDamage());
}
@Test
public void testPlayerDamage_slightDamage_false() {
when(player.getHealth()).thenReturn(19.5);
assertFalse(job.hasPlayerTakenDamage());
}
@Test
public void testPlayerDamage_largeDamage_true() {
when(player.getHealth()).thenReturn(14.0);
assertTrue(job.hasPlayerTakenDamage());
}
}