Skip to content

Commit

Permalink
Guard against teleporting back to the arena on death.
Browse files Browse the repository at this point in the history
The /back command in Essentials - and similar commands from other plugins that allow you to warp back to your location of death - makes it possible to re-enter the arena after dying.

This commit builds upon the "leaving players" of commit 02f75d0 and introduces a more general notion of players being "moved". The arena is "moving" a player if the player is being teleported somewhere by MobArena (to any arena warp), and in this case, all teleports of a player are permitted. This takes care of the cases where MobArena "might be doing it". The rest of the cases are due to commands, plugins, ender pearls, etc., and they are a little easier to deal with separately. The new logic is more straightforward and should prevent most exploits and permit most legit warp cases.

This (hopefully) fixes #313.
  • Loading branch information
garbagemule committed Apr 24, 2018
1 parent 37de1e6 commit 31aa4c1
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 30 deletions.
21 changes: 21 additions & 0 deletions src/main/java/com/garbagemule/MobArena/ArenaImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ public class ArenaImpl implements Arena
private Map<Player,PlayerData> playerData = new HashMap<>();

private Set<Player> arenaPlayers, lobbyPlayers, readyPlayers, specPlayers, deadPlayers;
private Set<Player> movingPlayers;
private Set<Player> leavingPlayers;
private Set<Player> randoms;

Expand Down Expand Up @@ -165,6 +166,7 @@ public ArenaImpl(MobArena plugin, ConfigurationSection section, String name, Wor
this.specPlayers = new HashSet<>();
this.deadPlayers = new HashSet<>();
this.randoms = new HashSet<>();
this.movingPlayers = new HashSet<>();
this.leavingPlayers = new HashSet<>();

// Classes, items and permissions
Expand Down Expand Up @@ -518,7 +520,9 @@ public boolean startArena() {
System.out.println("[MobArena] Invincibility glitch attempt stopped!");
}

movingPlayers.add(p);
p.teleport(region.getArenaWarp());
movingPlayers.remove(p);
p.setAllowFlight(false);
p.setFlying(false);
//movePlayerToLocation(p, region.getArenaWarp());
Expand Down Expand Up @@ -663,6 +667,11 @@ public boolean playerJoin(Player p, Location loc)
return false;
}

if (movingPlayers.contains(p)) {
return false;
}
movingPlayers.add(p);

// Announce globally (must happen before moving player)
if (settings.getBoolean("global-join-announce", false)) {
if (lobbyPlayers.isEmpty()) {
Expand Down Expand Up @@ -710,6 +719,7 @@ public boolean playerJoin(Player p, Location loc)
}
}

movingPlayers.remove(p);
return true;
}

Expand Down Expand Up @@ -785,6 +795,11 @@ public boolean playerLeave(Player p)
return true;
}

@Override
public boolean isMoving(Player p) {
return movingPlayers.contains(p) || leavingPlayers.contains(p);
}

@Override
public boolean isLeaving(Player p) {
return leavingPlayers.contains(p);
Expand Down Expand Up @@ -878,11 +893,17 @@ public Location getRespawnLocation(Player p) {

@Override
public void playerSpec(Player p, Location loc) {
if (movingPlayers.contains(p)) {
return;
}
movingPlayers.add(p);

storePlayerData(p, loc);
MAUtils.sitPets(p);
movePlayerToSpec(p);

messenger.tell(p, Msg.SPEC_PLAYER_SPECTATE);
movingPlayers.remove(p);
}

private void spawnPets() {
Expand Down
70 changes: 40 additions & 30 deletions src/main/java/com/garbagemule/MobArena/ArenaListener.java
Original file line number Diff line number Diff line change
Expand Up @@ -1173,44 +1173,54 @@ public TeleportResponse onPlayerTeleport(PlayerTeleportEvent event) {
return TeleportResponse.IDGAF;
}

Location to = event.getTo();
Location from = event.getFrom();
Player p = event.getPlayer();

if (region.contains(from)) {
// Players with proper admin permission can warp out
if (p.hasPermission("mobarena.admin.teleport")) {
return TeleportResponse.ALLOW;
}

// Players not in the arena are free to warp out.
if (!arena.inArena(p) && !arena.inLobby(p) && !arena.inSpec(p)) {
return TeleportResponse.ALLOW;
}
/*
* Players that are being moved around by the arena are always allowed
* to teleport. They stay in this "moving" state only during the actual
* transition and are removed from that state as soon as the transition
* is complete.
*/
if (arena.isMoving(p) || p.hasPermission("mobarena.admin.teleport")) {
return TeleportResponse.ALLOW;
}

// Covers the case in which both locations are in the arena.
if (region.contains(to) || region.isWarp(to) || to.equals(arena.getPlayerEntry(p))) {
return TeleportResponse.ALLOW;
}
Location to = event.getTo();
Location from = event.getFrom();

arena.getMessenger().tell(p, Msg.WARP_FROM_ARENA);
return TeleportResponse.REJECT;
}
else if (region.contains(to)) {
// Players with proper admin permission can warp in
if (p.hasPermission("mobarena.admin.teleport")) {
/*
* At this point we're looking at warping of players that are either in
* the arena - but not in the "moving" state - or not in the arena. The
* tricky bit here is to figure out the edge cases. This is essentially
* a matter of players "teleporting on their own" (or with assistance
* from other plugins).
*/
if (region.contains(from)) {
if (region.contains(to)) {
// Inside -> inside
if (!arena.inArena(p)) {
arena.getMessenger().tell(p, Msg.WARP_TO_ARENA);
return TeleportResponse.REJECT;
}
return TeleportResponse.ALLOW;
} else {
// Inside -> outside
if (arena.getAllPlayers().contains(p)) {
arena.getMessenger().tell(p, Msg.WARP_FROM_ARENA);
return TeleportResponse.REJECT;
}
return TeleportResponse.IDGAF;
}

if (region.isWarp(from) || region.isWarp(to) || to.equals(arena.getPlayerEntry(p))) {
return TeleportResponse.ALLOW;
} else {
if (region.contains(to)) {
// Outside -> inside
arena.getMessenger().tell(p, Msg.WARP_TO_ARENA);
return TeleportResponse.REJECT;
} else {
// Outside -> outside
return TeleportResponse.IDGAF;
}

arena.getMessenger().tell(p, Msg.WARP_TO_ARENA);
return TeleportResponse.REJECT;
}

return TeleportResponse.IDGAF;
}

public void onPlayerCommandPreprocess(PlayerCommandPreprocessEvent event) {
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/com/garbagemule/MobArena/framework/Arena.java
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,8 @@ public interface Arena

boolean playerLeave(Player p);

boolean isMoving(Player p);

boolean isLeaving(Player p);

void playerDeath(Player p);
Expand Down

0 comments on commit 31aa4c1

Please sign in to comment.