diff --git a/src/main/java/net/knarcraft/minigames/arena/parkour/ParkourArena.java b/src/main/java/net/knarcraft/minigames/arena/parkour/ParkourArena.java index 97cf974..3b4bbaa 100644 --- a/src/main/java/net/knarcraft/minigames/arena/parkour/ParkourArena.java +++ b/src/main/java/net/knarcraft/minigames/arena/parkour/ParkourArena.java @@ -12,6 +12,7 @@ import net.knarcraft.minigames.util.StringSanitizer; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -326,9 +327,16 @@ public class ParkourArena implements Arena { } @Override - public boolean willCauseWin(Block block) { - return (this.winLocation != null && this.winLocation.getBlock().equals(block)) || - (this.winLocation == null && this.winBlockType == block.getType()); + public boolean willCauseWin(@NotNull Block block) { + if (this.winLocation != null) { + return this.winLocation.getBlock().equals(block); + } else { + if (this.winBlockType.isSolid()) { + return this.winBlockType == block.getRelative(BlockFace.DOWN).getType(); + } else { + return this.winBlockType == block.getType(); + } + } } @Override diff --git a/src/main/java/net/knarcraft/minigames/listener/MoveListener.java b/src/main/java/net/knarcraft/minigames/listener/MoveListener.java index cc35fc4..418a9ac 100644 --- a/src/main/java/net/knarcraft/minigames/listener/MoveListener.java +++ b/src/main/java/net/knarcraft/minigames/listener/MoveListener.java @@ -29,6 +29,7 @@ import java.util.Calendar; import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.logging.Level; /** * A listener for players moving inside a dropper arena @@ -101,7 +102,8 @@ public class MoveListener implements Listener { * @param targetBlock

The block the player is moving to

* @param player

The player moving

*/ - private void updateCheckpoint(ParkourArenaSession arenaSession, Block targetBlock, Player player) { + private void updateCheckpoint(@NotNull ParkourArenaSession arenaSession, @NotNull Block targetBlock, + @NotNull Player player) { ParkourArena arena = arenaSession.getArena(); List checkpoints = arena.getCheckpoints(); for (Location checkpoint : checkpoints) { @@ -202,8 +204,49 @@ public class MoveListener implements Listener { double liquidDepth = sharedConfiguration.getLiquidHitBoxDepth(); Arena arena = arenaSession.getArena(); - // For water, only trigger when the player enters the water, but trigger earlier for everything else + + if (arena instanceof DropperArena) { + return checkDropperWin(arenaSession, toLocation, solidDepth, liquidDepth) || + checkDropperDeathBlocks((DropperArenaSession) arenaSession, toLocation, solidDepth, liquidDepth); + } else if (arena instanceof ParkourArena) { + return checkParkourWin(arenaSession, toLocation.getBlock()) || + checkParkourDeathBlock((ParkourArenaSession) arenaSession, toLocation); + } else { + MiniGames.log(Level.SEVERE, "Unknown arena type encountered!"); + } + + return false; + } + + /** + * Checks if the player has triggered a parkour win block + * + * @param arenaSession

The player's current arena session

+ * @param targetBlock

The block the player moved to

+ * @return

True if the player triggered a parkour win block

+ */ + private boolean checkParkourWin(@NotNull ArenaSession arenaSession, @NotNull Block targetBlock) { + boolean winBlock = arenaSession.getArena().willCauseWin(targetBlock); + if (winBlock) { + arenaSession.triggerWin(); + } + return winBlock; + } + + /** + * Checks if the player has triggered a dropper win block + * + * @param arenaSession

The player's arena session

+ * @param toLocation

The location the player moved to

+ * @param solidDepth

The distance away from solid blocks that will trigger a hit

+ * @param liquidDepth

The depth players need to be inside a liquid to trigger a hit

+ * @return

True if the player triggered a dropper win block

+ */ + private boolean checkDropperWin(@NotNull ArenaSession arenaSession, @NotNull Location toLocation, double solidDepth, + double liquidDepth) { + Arena arena = arenaSession.getArena(); Set potentialWinTriggerBlocks; + // For water, only trigger when the player enters the water, but trigger earlier for everything else if (arena.winLocationIsSolid()) { potentialWinTriggerBlocks = getBlocksBeneathLocation(toLocation, solidDepth); } else { @@ -215,25 +258,36 @@ public class MoveListener implements Listener { return true; } } + return false; + } - if (arena instanceof DropperArena) { - // Check if the player is about to hit a non-air and non-liquid block - for (Block block : getBlocksBeneathLocation(toLocation, solidDepth)) { - if (!block.getType().isAir() && !block.isLiquid() && arena.willCauseLoss(block)) { - arenaSession.triggerLoss(); - return true; - } - } + /** + * Checks if a player is moving onto a block part of the dropper arena death plane + * + * @param arenaSession

The player's arena session

+ * @param toLocation

The location the player is moving to

+ * @param solidDepth

The distance away from solid blocks that will trigger a hit

+ * @param liquidDepth

The depth players need to be inside a liquid to trigger a hit

+ * @return

True if the player triggered a dropper death block

+ */ + private boolean checkDropperDeathBlocks(@NotNull DropperArenaSession arenaSession, + @NotNull Location toLocation, double solidDepth, double liquidDepth) { + Arena arena = arenaSession.getArena(); - // Check if the player has entered a liquid that causes a loss - for (Block block : getBlocksBeneathLocation(toLocation, liquidDepth)) { - if (block.isLiquid() && arena.willCauseLoss(block)) { - arenaSession.triggerLoss(); - return true; - } + // Check if the player is about to hit a non-air and non-liquid block + for (Block block : getBlocksBeneathLocation(toLocation, solidDepth)) { + if (!block.getType().isAir() && !block.isLiquid() && arena.willCauseLoss(block)) { + arenaSession.triggerLoss(); + return true; + } + } + + // Check if the player has entered a liquid that causes a loss + for (Block block : getBlocksBeneathLocation(toLocation, liquidDepth)) { + if (block.isLiquid() && arena.willCauseLoss(block)) { + arenaSession.triggerLoss(); + return true; } - } else if (arena instanceof ParkourArena) { - return checkParkourDeathBlock((ParkourArenaSession) arenaSession, toLocation); } return false;