Implement rest of block safety methods

This commit is contained in:
Ben Woo 2025-01-15 14:11:01 +08:00
parent 3b9a91c010
commit 2df1f39ef9

View File

@ -5,10 +5,17 @@ import jakarta.inject.Inject;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.block.Block; 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.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jvnet.hk2.annotations.Service; import org.jvnet.hk2.annotations.Service;
import org.mvplugins.multiverse.core.api.LocationManipulation;
/**
*
*/
@Service @Service
public class AdvancedBlockSafety { public class AdvancedBlockSafety {
@ -16,8 +23,11 @@ public class AdvancedBlockSafety {
public static final int DEFAULT_HORIZONTAL_RANGE = 3; public static final int DEFAULT_HORIZONTAL_RANGE = 3;
public static final int DEFAULT_VERTICAL_RANGE = 2; public static final int DEFAULT_VERTICAL_RANGE = 2;
private final LocationManipulation locationManipulation;
@Inject @Inject
private AdvancedBlockSafety() { AdvancedBlockSafety(@NotNull LocationManipulation locationManipulation) {
this.locationManipulation = locationManipulation;
} }
public boolean playerCanSpawnSafelyAt(@NotNull Location location) { public boolean playerCanSpawnSafelyAt(@NotNull Location location) {
@ -25,6 +35,7 @@ public class AdvancedBlockSafety {
} }
public boolean playerCanSpawnSafelyAt(@NotNull Block block) { 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)) { if (isUnsafeSpawnBody(block)) {
// Player body will be stuck in solid // Player body will be stuck in solid
Logging.finest("Unsafe location for player's body."); Logging.finest("Unsafe location for player's body.");
@ -42,6 +53,7 @@ public class AdvancedBlockSafety {
Logging.finest("Unsafe location due to invalid platform."); Logging.finest("Unsafe location due to invalid platform.");
return false; return false;
} }
Logging.finest("Location is safe.");
return true; return true;
} }
@ -79,47 +91,88 @@ public class AdvancedBlockSafety {
return block.getRelative(0, -1, 0).getType() == Material.WATER; return block.getRelative(0, -1, 0).getType() == Material.WATER;
} }
/**
*
*
* @param location
* @return The safe location, or null
*/
@Nullable @Nullable
public Location adjustSafeSpawnLocation(@NotNull Location location) { public Location adjustSafeSpawnLocation(@NotNull Location location) {
return adjustSafeSpawnLocation(location, DEFAULT_HORIZONTAL_RANGE, DEFAULT_VERTICAL_RANGE); return adjustSafeSpawnLocation(location, DEFAULT_HORIZONTAL_RANGE, DEFAULT_VERTICAL_RANGE);
} }
/**
*
* @param location
* @param horizontalRange
* @param verticalRange
* @return The safe location, or null
*/
@Nullable @Nullable
public Location adjustSafeSpawnLocation(@NotNull Location location, int horizontalRange, int verticalRange) { public Location adjustSafeSpawnLocation(@NotNull Location location, int horizontalRange, int verticalRange) {
Block safeBlock = adjustSafeSpawnBlock(location.getBlock(), horizontalRange, verticalRange); Block safeBlock = adjustSafeSpawnBlock(location.getBlock(), horizontalRange, verticalRange);
if (safeBlock == null) { if (safeBlock == null) {
return null; return null;
} }
Location safeLocation = safeBlock.getLocation(); return new Location(
// Adjust to center of block location.getWorld(),
safeLocation.add(0.5, 0, 0.5); safeBlock.getX() + 0.5,
return safeLocation; safeBlock.getY(),
safeBlock.getZ() + 0.5,
location.getYaw(),
location.getPitch());
} }
/**
*
* @param block
* @return The safe block, or null
*/
@Nullable @Nullable
public Block adjustSafeSpawnBlock(@NotNull Block block) { public Block adjustSafeSpawnBlock(@NotNull Block block) {
return adjustSafeSpawnBlock(block, DEFAULT_HORIZONTAL_RANGE, DEFAULT_VERTICAL_RANGE); return adjustSafeSpawnBlock(block, DEFAULT_HORIZONTAL_RANGE, DEFAULT_VERTICAL_RANGE);
} }
/**
*
* @param block
* @param horizontalRange
* @param verticalRange
* @return The safe block, or null
*/
@Nullable @Nullable
public Block adjustSafeSpawnBlock(@NotNull Block block, int horizontalRange, int verticalRange) { public Block adjustSafeSpawnBlock(@NotNull Block block, int horizontalRange, int verticalRange) {
Block searchResult = searchAroundXZ(block, horizontalRange); Block searchResult = searchAroundXZ(block, horizontalRange);
if (searchResult != null) { if (searchResult != null) {
return searchResult; return searchResult;
} }
int maxHeight = block.getWorld().getMaxHeight();
int minHeight = block.getWorld().getMinHeight();
for (int i = 1; i <= verticalRange; i++) { for (int i = 1; i <= verticalRange; i++) {
searchResult = searchAroundXZ(block.getRelative(0, i, 0), horizontalRange); if (block.getY() + i < maxHeight) {
if (searchResult != null) { searchResult = searchAroundXZ(block.getRelative(0, i, 0), horizontalRange);
return searchResult; if (searchResult != null) {
return searchResult;
}
} }
searchResult = searchAroundXZ(block.getRelative(0, -i, 0), horizontalRange); if (block.getY() - i >= minHeight) {
if (searchResult != null) { searchResult = searchAroundXZ(block.getRelative(0, -i, 0), horizontalRange);
return searchResult; if (searchResult != null) {
return searchResult;
}
} }
} }
return null; 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 @Nullable
private Block searchAroundXZ(Block block, int radius) { private Block searchAroundXZ(Block block, int radius) {
if (playerCanSpawnSafelyAt(block)) { if (playerCanSpawnSafelyAt(block)) {
@ -147,28 +200,72 @@ public class AdvancedBlockSafety {
return null; 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 @Nullable
private Block searchPlusMinusPermutation(Block block, int x, int z) { private Block searchPlusMinusPermutation(Block block, int x, int z) {
Block relative = block.getRelative(-x, 0, 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);
if (playerCanSpawnSafelyAt(relative)) { if (playerCanSpawnSafelyAt(relative)) {
return relative; return relative;
} }
if (z != 0) { if (z != 0) {
relative = block.getRelative(x, 0, -z); relative = block.getRelative(-x, 0, z);
if (playerCanSpawnSafelyAt(relative)) { if (playerCanSpawnSafelyAt(relative)) {
return 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; 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());
}
} }