From 2df1f39ef96a35e1805315673cc8ffa62ff71ece Mon Sep 17 00:00:00 2001 From: Ben Woo <30431861+benwoo1110@users.noreply.github.com> Date: Wed, 15 Jan 2025 14:11:01 +0800 Subject: [PATCH] Implement rest of block safety methods --- .../teleportation/AdvancedBlockSafety.java | 143 +++++++++++++++--- 1 file changed, 120 insertions(+), 23 deletions(-) diff --git a/src/main/java/org/mvplugins/multiverse/core/teleportation/AdvancedBlockSafety.java b/src/main/java/org/mvplugins/multiverse/core/teleportation/AdvancedBlockSafety.java index bd328837..43cf6cc1 100644 --- a/src/main/java/org/mvplugins/multiverse/core/teleportation/AdvancedBlockSafety.java +++ b/src/main/java/org/mvplugins/multiverse/core/teleportation/AdvancedBlockSafety.java @@ -5,10 +5,17 @@ import jakarta.inject.Inject; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.block.Block; +import org.bukkit.block.data.Rail; +import org.bukkit.entity.Minecart; +import org.bukkit.entity.Vehicle; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jvnet.hk2.annotations.Service; +import org.mvplugins.multiverse.core.api.LocationManipulation; +/** + * + */ @Service public class AdvancedBlockSafety { @@ -16,8 +23,11 @@ public class AdvancedBlockSafety { public static final int DEFAULT_HORIZONTAL_RANGE = 3; public static final int DEFAULT_VERTICAL_RANGE = 2; + private final LocationManipulation locationManipulation; + @Inject - private AdvancedBlockSafety() { + AdvancedBlockSafety(@NotNull LocationManipulation locationManipulation) { + this.locationManipulation = locationManipulation; } public boolean playerCanSpawnSafelyAt(@NotNull Location location) { @@ -25,6 +35,7 @@ public class AdvancedBlockSafety { } public boolean playerCanSpawnSafelyAt(@NotNull Block block) { + Logging.finest("Checking spawn safety for location: %s, %s, %s", block.getX(), block.getY(), block.getZ()); if (isUnsafeSpawnBody(block)) { // Player body will be stuck in solid Logging.finest("Unsafe location for player's body."); @@ -42,6 +53,7 @@ public class AdvancedBlockSafety { Logging.finest("Unsafe location due to invalid platform."); return false; } + Logging.finest("Location is safe."); return true; } @@ -79,47 +91,88 @@ public class AdvancedBlockSafety { return block.getRelative(0, -1, 0).getType() == Material.WATER; } + /** + * + * + * @param location + * @return The safe location, or null + */ @Nullable public Location adjustSafeSpawnLocation(@NotNull Location location) { return adjustSafeSpawnLocation(location, DEFAULT_HORIZONTAL_RANGE, DEFAULT_VERTICAL_RANGE); } + /** + * + * @param location + * @param horizontalRange + * @param verticalRange + * @return The safe location, or null + */ @Nullable public Location adjustSafeSpawnLocation(@NotNull Location location, int horizontalRange, int verticalRange) { Block safeBlock = adjustSafeSpawnBlock(location.getBlock(), horizontalRange, verticalRange); if (safeBlock == null) { return null; } - Location safeLocation = safeBlock.getLocation(); - // Adjust to center of block - safeLocation.add(0.5, 0, 0.5); - return safeLocation; + return new Location( + location.getWorld(), + safeBlock.getX() + 0.5, + safeBlock.getY(), + safeBlock.getZ() + 0.5, + location.getYaw(), + location.getPitch()); } + /** + * + * @param block + * @return The safe block, or null + */ @Nullable public Block adjustSafeSpawnBlock(@NotNull Block block) { return adjustSafeSpawnBlock(block, DEFAULT_HORIZONTAL_RANGE, DEFAULT_VERTICAL_RANGE); } + /** + * + * @param block + * @param horizontalRange + * @param verticalRange + * @return The safe block, or null + */ @Nullable public Block adjustSafeSpawnBlock(@NotNull Block block, int horizontalRange, int verticalRange) { Block searchResult = searchAroundXZ(block, horizontalRange); if (searchResult != null) { return searchResult; } + int maxHeight = block.getWorld().getMaxHeight(); + int minHeight = block.getWorld().getMinHeight(); for (int i = 1; i <= verticalRange; i++) { - searchResult = searchAroundXZ(block.getRelative(0, i, 0), horizontalRange); - if (searchResult != null) { - return searchResult; + if (block.getY() + i < maxHeight) { + searchResult = searchAroundXZ(block.getRelative(0, i, 0), horizontalRange); + if (searchResult != null) { + return searchResult; + } } - searchResult = searchAroundXZ(block.getRelative(0, -i, 0), horizontalRange); - if (searchResult != null) { - return searchResult; + if (block.getY() - i >= minHeight) { + searchResult = searchAroundXZ(block.getRelative(0, -i, 0), horizontalRange); + if (searchResult != null) { + return searchResult; + } } } return null; } + /** + * Search a square from n - radius to n + radius for both x and z + * + * @param block + * @param radius + * @return The safe block, or null + */ @Nullable private Block searchAroundXZ(Block block, int radius) { if (playerCanSpawnSafelyAt(block)) { @@ -147,28 +200,72 @@ public class AdvancedBlockSafety { return null; } + /** + * Search 4 relative blocks with the following offsets: (-x, -z) (-x, z) (x, -z) (x, z) + * + * @param block The block to be relative to + * @param x Amount to offset for the x axis + * @param z Amount to offset for the z axis + * @return The safe block, or null + */ @Nullable private Block searchPlusMinusPermutation(Block block, int x, int z) { - Block relative = block.getRelative(-x, 0, z); - if (playerCanSpawnSafelyAt(relative)) { - return relative; - } - if (x != 0) { - relative = block.getRelative(-x, 0, -z); - if (playerCanSpawnSafelyAt(relative)) { - return relative; - } - } - relative = block.getRelative(x, 0, z); + Block relative = block.getRelative(-x, 0, -z); if (playerCanSpawnSafelyAt(relative)) { return relative; } if (z != 0) { - relative = block.getRelative(x, 0, -z); + relative = block.getRelative(-x, 0, z); if (playerCanSpawnSafelyAt(relative)) { return relative; } } + if (x != 0) { + relative = block.getRelative(x, 0, -z); + if (playerCanSpawnSafelyAt(relative)) { + return relative; + } + if (z != 0) { + relative = block.getRelative(x, 0, z); + if (playerCanSpawnSafelyAt(relative)) { + return relative; + } + } + } return null; } + + public boolean isBlockAboveAir(Location location) { + return location.getBlock().getRelative(0, -1, 0).getType().isAir(); + } + + /** + * + * @param location + * @return + */ + public boolean isEntityOnTrack(Location location) { + return location.getBlock().getBlockData() instanceof Rail; + } + + /** + * + * @param cart + * @return + */ + public boolean canSpawnCartSafely(Minecart cart) { + if (isBlockAboveAir(cart.getLocation())) { + return true; + } + return isEntityOnTrack(locationManipulation.getNextBlock(cart)); + } + + /** + * + * @param vehicle + * @return + */ + public boolean canSpawnVehicleSafely(Vehicle vehicle) { + return isBlockAboveAir(vehicle.getLocation()); + } }