mirror of
https://github.com/EssentialsX/Essentials.git
synced 2025-02-25 16:51:54 +01:00
Support 0>y>256 for safe/random teleports (#4641)
Co-authored-by: pop4959 <pop4959@gmail.com> Co-authored-by: Josh Roy <10731363+JRoy@users.noreply.github.com>
This commit is contained in:
parent
c0082ee734
commit
1509cf8978
Essentials/src/main/java/com/earth2me/essentials
AsyncTeleport.javaEssentials.javaEssentialsPlayerListener.javaIEssentials.javaRandomTeleport.javaSpawnMob.javaTeleport.java
commands
utils
providers/BaseProviders/src/main/java/net/ess3/provider
@ -189,7 +189,7 @@ public class AsyncTeleport implements IAsyncTeleport {
|
||||
}
|
||||
PaperLib.getChunkAtAsync(targetLoc.getWorld(), targetLoc.getBlockX() >> 4, targetLoc.getBlockZ() >> 4, true, true).thenAccept(chunk -> {
|
||||
Location loc = targetLoc;
|
||||
if (LocationUtil.isBlockUnsafeForUser(teleportee, chunk.getWorld(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ())) {
|
||||
if (LocationUtil.isBlockUnsafeForUser(ess, teleportee, chunk.getWorld(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ())) {
|
||||
if (ess.getSettings().isTeleportSafetyEnabled()) {
|
||||
if (ess.getSettings().isForceDisableTeleportSafety()) {
|
||||
//The chunk we're teleporting to is 100% going to be loaded here, no need to teleport async.
|
||||
|
@ -69,16 +69,19 @@ import net.ess3.provider.SpawnEggProvider;
|
||||
import net.ess3.provider.SpawnerBlockProvider;
|
||||
import net.ess3.provider.SpawnerItemProvider;
|
||||
import net.ess3.provider.SyncCommandsProvider;
|
||||
import net.ess3.provider.WorldInfoProvider;
|
||||
import net.ess3.provider.providers.BasePotionDataProvider;
|
||||
import net.ess3.provider.providers.BlockMetaSpawnerItemProvider;
|
||||
import net.ess3.provider.providers.BukkitMaterialTagProvider;
|
||||
import net.ess3.provider.providers.BukkitSpawnerBlockProvider;
|
||||
import net.ess3.provider.providers.FixedHeightWorldInfoProvider;
|
||||
import net.ess3.provider.providers.FlatSpawnEggProvider;
|
||||
import net.ess3.provider.providers.LegacyItemUnbreakableProvider;
|
||||
import net.ess3.provider.providers.LegacyPotionMetaProvider;
|
||||
import net.ess3.provider.providers.LegacySpawnEggProvider;
|
||||
import net.ess3.provider.providers.ModernItemUnbreakableProvider;
|
||||
import net.ess3.provider.providers.ModernPersistentDataProvider;
|
||||
import net.ess3.provider.providers.ModernWorldInfoProvider;
|
||||
import net.ess3.provider.providers.PaperContainerProvider;
|
||||
import net.ess3.provider.providers.PaperKnownCommandsProvider;
|
||||
import net.ess3.provider.providers.PaperMaterialTagProvider;
|
||||
@ -170,6 +173,7 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
|
||||
private transient PersistentDataProvider persistentDataProvider;
|
||||
private transient ReflOnlineModeProvider onlineModeProvider;
|
||||
private transient ItemUnbreakableProvider unbreakableProvider;
|
||||
private transient WorldInfoProvider worldInfoProvider;
|
||||
private transient Kits kits;
|
||||
private transient RandomTeleport randomTeleport;
|
||||
private transient UpdateChecker updateChecker;
|
||||
@ -419,6 +423,12 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
|
||||
unbreakableProvider = new LegacyItemUnbreakableProvider();
|
||||
}
|
||||
|
||||
if (VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_17_1_R01)) {
|
||||
worldInfoProvider = new ModernWorldInfoProvider();
|
||||
} else {
|
||||
worldInfoProvider = new FixedHeightWorldInfoProvider();
|
||||
}
|
||||
|
||||
execTimer.mark("Init(Providers)");
|
||||
reload();
|
||||
|
||||
@ -1284,6 +1294,11 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
|
||||
return unbreakableProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorldInfoProvider getWorldInfoProvider() {
|
||||
return worldInfoProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PluginCommand getPluginCommand(final String cmd) {
|
||||
return this.getCommand(cmd);
|
||||
|
@ -217,7 +217,7 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
|
||||
to.setY(from.getY());
|
||||
to.setZ(from.getZ());
|
||||
try {
|
||||
event.setTo(LocationUtil.getSafeDestination(to));
|
||||
event.setTo(LocationUtil.getSafeDestination(ess, to));
|
||||
} catch (final Exception ex) {
|
||||
event.setTo(to);
|
||||
}
|
||||
@ -412,7 +412,7 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
|
||||
|
||||
if (user.isAuthorized("essentials.fly.safelogin")) {
|
||||
user.getBase().setFallDistance(0);
|
||||
if (LocationUtil.shouldFly(user.getLocation())) {
|
||||
if (LocationUtil.shouldFly(ess, user.getLocation())) {
|
||||
user.getBase().setAllowFlight(true);
|
||||
user.getBase().setFlying(true);
|
||||
if (ess.getSettings().isSendFlyEnableOnJoin()) {
|
||||
|
@ -19,6 +19,7 @@ import net.ess3.provider.SerializationProvider;
|
||||
import net.ess3.provider.SpawnerBlockProvider;
|
||||
import net.ess3.provider.SpawnerItemProvider;
|
||||
import net.ess3.provider.SyncCommandsProvider;
|
||||
import net.ess3.provider.WorldInfoProvider;
|
||||
import net.essentialsx.api.v2.services.BalanceTop;
|
||||
import net.essentialsx.api.v2.services.mail.MailService;
|
||||
import org.bukkit.Server;
|
||||
@ -162,5 +163,7 @@ public interface IEssentials extends Plugin {
|
||||
|
||||
ItemUnbreakableProvider getItemUnbreakableProvider();
|
||||
|
||||
WorldInfoProvider getWorldInfoProvider();
|
||||
|
||||
PluginCommand getPluginCommand(String cmd);
|
||||
}
|
||||
|
@ -22,12 +22,12 @@ import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
public class RandomTeleport implements IConf {
|
||||
private static final Random RANDOM = new Random();
|
||||
private static final int HIGHEST_BLOCK_Y_OFFSET = VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_15_R01) ? 1 : 0;
|
||||
private final IEssentials essentials;
|
||||
private final IEssentials ess;
|
||||
private final EssentialsConfiguration config;
|
||||
private final ConcurrentLinkedQueue<Location> cachedLocations = new ConcurrentLinkedQueue<>();
|
||||
|
||||
public RandomTeleport(final IEssentials essentials) {
|
||||
this.essentials = essentials;
|
||||
this.ess = essentials;
|
||||
config = new EssentialsConfiguration(new File(essentials.getDataFolder(), "tpr.yml"), "/tpr.yml",
|
||||
"Configuration for the random teleport command.\nSome settings may be defaulted, and can be changed via the /settpr command in-game.");
|
||||
reloadConfig();
|
||||
@ -47,8 +47,8 @@ public class RandomTeleport implements IConf {
|
||||
}
|
||||
} catch (final InvalidWorldException ignored) {
|
||||
}
|
||||
final Location center = essentials.getServer().getWorlds().get(0).getWorldBorder().getCenter();
|
||||
center.setY(center.getWorld().getHighestBlockYAt(center) + 1);
|
||||
final Location center = ess.getServer().getWorlds().get(0).getWorldBorder().getCenter();
|
||||
center.setY(center.getWorld().getHighestBlockYAt(center) + HIGHEST_BLOCK_Y_OFFSET);
|
||||
setCenter(center);
|
||||
return center;
|
||||
}
|
||||
@ -124,7 +124,7 @@ public class RandomTeleport implements IConf {
|
||||
|
||||
// Prompts caching random valid locations, up to a maximum number of attempts
|
||||
public void cacheRandomLocations(final Location center, final double minRange, final double maxRange) {
|
||||
essentials.getServer().getScheduler().scheduleSyncDelayedTask(essentials, () -> {
|
||||
ess.getServer().getScheduler().scheduleSyncDelayedTask(ess, () -> {
|
||||
for (int i = 0; i < this.getFindAttempts(); ++i) {
|
||||
calculateRandomLocation(center, minRange, maxRange).thenAccept(location -> {
|
||||
if (isValidRandomLocation(location)) {
|
||||
@ -177,7 +177,7 @@ public class RandomTeleport implements IConf {
|
||||
final Location location = new Location(
|
||||
center.getWorld(),
|
||||
center.getX() + offsetX,
|
||||
center.getWorld().getMaxHeight(),
|
||||
ess.getWorldInfoProvider().getMaxSafeHeight(center.getWorld()),
|
||||
center.getZ() + offsetZ,
|
||||
360 * RANDOM.nextFloat() - 180,
|
||||
0
|
||||
@ -195,8 +195,8 @@ public class RandomTeleport implements IConf {
|
||||
|
||||
// Returns an appropriate elevation for a given location in the nether, or -1 if none is found
|
||||
private double getNetherYAt(final Location location) {
|
||||
for (int y = 32; y < location.getWorld().getMaxHeight() / 2; ++y) {
|
||||
if (!LocationUtil.isBlockUnsafe(location.getWorld(), location.getBlockX(), y, location.getBlockZ())) {
|
||||
for (int y = 32; y < ess.getWorldInfoProvider().getMaxSafeHeight(location.getWorld()); ++y) {
|
||||
if (!LocationUtil.isBlockUnsafe(ess, location.getWorld(), location.getBlockX(), y, location.getBlockZ())) {
|
||||
return y;
|
||||
}
|
||||
}
|
||||
@ -204,6 +204,6 @@ public class RandomTeleport implements IConf {
|
||||
}
|
||||
|
||||
private boolean isValidRandomLocation(final Location location) {
|
||||
return location.getBlockY() > 0 && !this.getExcludedBiomes().contains(location.getBlock().getBiome());
|
||||
return location.getBlockY() > ess.getWorldInfoProvider().getMinSafeHeight(location.getWorld()) && !this.getExcludedBiomes().contains(location.getBlock().getBiome());
|
||||
}
|
||||
}
|
||||
|
@ -103,7 +103,7 @@ public final class SpawnMob {
|
||||
|
||||
// This method spawns a mob at loc, owned by target
|
||||
public static void spawnmob(final IEssentials ess, final Server server, final CommandSource sender, final User target, final Location loc, final List<String> parts, final List<String> data, int mobCount) throws Exception {
|
||||
final Location sloc = LocationUtil.getSafeDestination(loc);
|
||||
final Location sloc = LocationUtil.getSafeDestination(ess, loc);
|
||||
|
||||
for (final String part : parts) {
|
||||
final Mob mob = Mob.fromName(part);
|
||||
|
@ -145,7 +145,7 @@ public class Teleport implements ITeleport {
|
||||
teleportee.getBase().eject();
|
||||
}
|
||||
|
||||
if (LocationUtil.isBlockUnsafeForUser(teleportee, loc.getWorld(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ())) {
|
||||
if (LocationUtil.isBlockUnsafeForUser(ess, teleportee, loc.getWorld(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ())) {
|
||||
if (ess.getSettings().isTeleportSafetyEnabled()) {
|
||||
if (ess.getSettings().isForceDisableTeleportSafety()) {
|
||||
PaperLib.teleportAsync(teleportee.getBase(), loc, cause);
|
||||
|
@ -51,7 +51,7 @@ public class Commandsethome extends EssentialsCommand {
|
||||
}
|
||||
|
||||
final Location location = user.getLocation();
|
||||
if ((!ess.getSettings().isTeleportSafetyEnabled() || !ess.getSettings().isForceDisableTeleportSafety()) && LocationUtil.isBlockUnsafeForUser(usersHome, location.getWorld(), location.getBlockX(), location.getBlockY(), location.getBlockZ())) {
|
||||
if ((!ess.getSettings().isTeleportSafetyEnabled() || !ess.getSettings().isForceDisableTeleportSafety()) && LocationUtil.isBlockUnsafeForUser(ess, usersHome, location.getWorld(), location.getBlockX(), location.getBlockY(), location.getBlockZ())) {
|
||||
throw new Exception(tl("unsafeTeleportDestination", location.getWorld().getName(), location.getBlockX(), location.getBlockY(), location.getBlockZ()));
|
||||
}
|
||||
|
||||
|
@ -22,13 +22,14 @@ public class Commandtop extends EssentialsCommand {
|
||||
final int topZ = user.getLocation().getBlockZ();
|
||||
final float pitch = user.getLocation().getPitch();
|
||||
final float yaw = user.getLocation().getYaw();
|
||||
final Location loc = LocationUtil.getSafeDestination(new Location(user.getWorld(), topX, user.getWorld().getMaxHeight(), topZ, yaw, pitch));
|
||||
final Location unsafe = new Location(user.getWorld(), topX, ess.getWorldInfoProvider().getMaxSafeHeight(user.getWorld()), topZ, yaw, pitch);
|
||||
final Location safe = LocationUtil.getSafeDestination(ess, unsafe);
|
||||
final CompletableFuture<Boolean> future = new CompletableFuture<>();
|
||||
future.thenAccept(success -> {
|
||||
if (success) {
|
||||
user.sendMessage(tl("teleportTop", loc.getWorld().getName(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()));
|
||||
user.sendMessage(tl("teleportTop", safe.getWorld().getName(), safe.getBlockX(), safe.getBlockY(), safe.getBlockZ()));
|
||||
}
|
||||
});
|
||||
user.getAsyncTeleport().teleport(loc, new Trade(this.getName(), ess), TeleportCause.COMMAND, getNewExceptionFuture(user.getSource(), commandLabel));
|
||||
user.getAsyncTeleport().teleport(safe, new Trade(this.getName(), ess), TeleportCause.COMMAND, getNewExceptionFuture(user.getSource(), commandLabel));
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.earth2me.essentials.utils;
|
||||
|
||||
import com.earth2me.essentials.IEssentials;
|
||||
import com.google.common.primitives.Ints;
|
||||
import net.ess3.api.IUser;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.Location;
|
||||
@ -95,8 +96,8 @@ public final class LocationUtil {
|
||||
return block.getLocation();
|
||||
}
|
||||
|
||||
public static boolean isBlockAboveAir(final World world, final int x, final int y, final int z) {
|
||||
return y > world.getMaxHeight() || HOLLOW_MATERIALS.contains(world.getBlockAt(x, y - 1, z).getType());
|
||||
public static boolean isBlockAboveAir(IEssentials ess, final World world, final int x, final int y, final int z) {
|
||||
return y > ess.getWorldInfoProvider().getMaxSafeHeight(world) || HOLLOW_MATERIALS.contains(world.getBlockAt(x, y - 1, z).getType());
|
||||
}
|
||||
|
||||
public static boolean isBlockOutsideWorldBorder(final World world, final int x, final int z) {
|
||||
@ -131,7 +132,7 @@ public final class LocationUtil {
|
||||
return z;
|
||||
}
|
||||
|
||||
public static boolean isBlockUnsafeForUser(final IUser user, final World world, final int x, final int y, final int z) {
|
||||
public static boolean isBlockUnsafeForUser(IEssentials ess, final IUser user, final World world, final int x, final int y, final int z) {
|
||||
if (user.getBase().isOnline() && world.equals(user.getBase().getWorld()) && (user.getBase().getGameMode() == GameMode.CREATIVE || user.getBase().getGameMode() == GameMode.SPECTATOR || user.isGodModeEnabled()) && user.getBase().getAllowFlight()) {
|
||||
return false;
|
||||
}
|
||||
@ -139,14 +140,14 @@ public final class LocationUtil {
|
||||
if (isBlockDamaging(world, x, y, z)) {
|
||||
return true;
|
||||
}
|
||||
if (isBlockAboveAir(world, x, y, z)) {
|
||||
if (isBlockAboveAir(ess, world, x, y, z)) {
|
||||
return true;
|
||||
}
|
||||
return isBlockOutsideWorldBorder(world, x, z);
|
||||
}
|
||||
|
||||
public static boolean isBlockUnsafe(final World world, final int x, final int y, final int z) {
|
||||
return isBlockDamaging(world, x, y, z) || isBlockAboveAir(world, x, y, z);
|
||||
public static boolean isBlockUnsafe(IEssentials ess, final World world, final int x, final int y, final int z) {
|
||||
return isBlockDamaging(world, x, y, z) || isBlockAboveAir(ess, world, x, y, z);
|
||||
}
|
||||
|
||||
public static boolean isBlockDamaging(final World world, final int x, final int y, final int z) {
|
||||
@ -184,7 +185,7 @@ public final class LocationUtil {
|
||||
|
||||
public static Location getSafeDestination(final IEssentials ess, final IUser user, final Location loc) throws Exception {
|
||||
if (user.getBase().isOnline() && (ess == null || !ess.getSettings().isAlwaysTeleportSafety()) && (user.getBase().getGameMode() == GameMode.CREATIVE || user.getBase().getGameMode() == GameMode.SPECTATOR || user.isGodModeEnabled())) {
|
||||
if (shouldFly(loc) && user.getBase().getAllowFlight()) {
|
||||
if (shouldFly(ess, loc) && user.getBase().getAllowFlight()) {
|
||||
user.getBase().setFlying(true);
|
||||
}
|
||||
// ess can be null if old deprecated method is calling it.
|
||||
@ -194,14 +195,16 @@ public final class LocationUtil {
|
||||
return loc;
|
||||
}
|
||||
}
|
||||
return getSafeDestination(loc);
|
||||
return getSafeDestination(ess, loc);
|
||||
}
|
||||
|
||||
public static Location getSafeDestination(final Location loc) throws Exception {
|
||||
public static Location getSafeDestination(IEssentials ess, final Location loc) throws Exception {
|
||||
if (loc == null || loc.getWorld() == null) {
|
||||
throw new Exception(tl("destinationNotSet"));
|
||||
}
|
||||
final World world = loc.getWorld();
|
||||
final int worldMinY = ess.getWorldInfoProvider().getMinSafeHeight(world);
|
||||
final int worldMaxY = ess.getWorldInfoProvider().getMaxSafeHeight(world);
|
||||
int x = loc.getBlockX();
|
||||
int y = (int) Math.round(loc.getY());
|
||||
int z = loc.getBlockZ();
|
||||
@ -212,42 +215,43 @@ public final class LocationUtil {
|
||||
final int origX = x;
|
||||
final int origY = y;
|
||||
final int origZ = z;
|
||||
while (isBlockAboveAir(world, x, y, z)) {
|
||||
while (isBlockAboveAir(ess, world, x, y, z)) {
|
||||
y -= 1;
|
||||
if (y < 0) {
|
||||
y = origY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (isBlockUnsafe(world, x, y, z)) {
|
||||
if (isBlockUnsafe(ess, world, x, y, z)) {
|
||||
x = Math.round(loc.getX()) == origX ? x - 1 : x + 1;
|
||||
z = Math.round(loc.getZ()) == origZ ? z - 1 : z + 1;
|
||||
}
|
||||
int i = 0;
|
||||
while (isBlockUnsafe(world, x, y, z)) {
|
||||
while (isBlockUnsafe(ess, world, x, y, z)) {
|
||||
i++;
|
||||
if (i >= VOLUME.length) {
|
||||
x = origX;
|
||||
y = origY + RADIUS;
|
||||
y = Ints.constrainToRange(origY + RADIUS, worldMinY, worldMaxY);
|
||||
z = origZ;
|
||||
break;
|
||||
}
|
||||
x = origX + VOLUME[i].x;
|
||||
y = origY + VOLUME[i].y;
|
||||
y = Ints.constrainToRange(origY + VOLUME[i].y, worldMinY, worldMaxY);
|
||||
z = origZ + VOLUME[i].z;
|
||||
}
|
||||
while (isBlockUnsafe(world, x, y, z)) {
|
||||
while (isBlockUnsafe(ess, world, x, y, z)) {
|
||||
y += 1;
|
||||
if (y >= world.getMaxHeight()) {
|
||||
if (y >= worldMaxY) {
|
||||
x += 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (isBlockUnsafe(world, x, y, z)) {
|
||||
while (isBlockUnsafe(ess, world, x, y, z)) {
|
||||
y -= 1;
|
||||
if (y <= 1) {
|
||||
if (y <= worldMinY + 1) {
|
||||
x += 1;
|
||||
y = world.getHighestBlockYAt(x, z);
|
||||
// Allow spawning at the top of the world, but not above the nether roof
|
||||
y = Math.min(world.getHighestBlockYAt(x, z) + 1, worldMaxY);
|
||||
if (x - 48 > loc.getBlockX()) {
|
||||
throw new Exception(tl("holeInFloor"));
|
||||
}
|
||||
@ -256,13 +260,13 @@ public final class LocationUtil {
|
||||
return new Location(world, x + 0.5, y, z + 0.5, loc.getYaw(), loc.getPitch());
|
||||
}
|
||||
|
||||
public static boolean shouldFly(final Location loc) {
|
||||
public static boolean shouldFly(IEssentials ess, final Location loc) {
|
||||
final World world = loc.getWorld();
|
||||
final int x = loc.getBlockX();
|
||||
int y = (int) Math.round(loc.getY());
|
||||
final int z = loc.getBlockZ();
|
||||
int count = 0;
|
||||
while (LocationUtil.isBlockUnsafe(world, x, y, z) && y > -1) {
|
||||
while (LocationUtil.isBlockUnsafe(ess, world, x, y, z) && y > -1) {
|
||||
y--;
|
||||
count++;
|
||||
if (count > 2) {
|
||||
|
@ -0,0 +1,21 @@
|
||||
package net.ess3.provider;
|
||||
|
||||
import org.bukkit.World;
|
||||
|
||||
public interface WorldInfoProvider extends Provider {
|
||||
/**
|
||||
* Gets the maximum safe height for teleportation.
|
||||
*
|
||||
* @param world The world of which to check the maximum safe height.
|
||||
* @return The maximum safe height for teleportation
|
||||
*/
|
||||
int getMaxSafeHeight(World world);
|
||||
|
||||
/**
|
||||
* Gets the minimum safe height for teleportation.
|
||||
*
|
||||
* @param world The world of which to check the base height.
|
||||
* @return The minimum safe height for teleportation
|
||||
*/
|
||||
int getMinSafeHeight(World world);
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
package net.ess3.provider.providers;
|
||||
|
||||
import net.ess3.provider.WorldInfoProvider;
|
||||
import org.bukkit.World;
|
||||
|
||||
public class FixedHeightWorldInfoProvider implements WorldInfoProvider {
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "World info provider for fixed world heights";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxSafeHeight(World world) {
|
||||
return world.getEnvironment() == World.Environment.NETHER ? 128 : 256;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinSafeHeight(World world) {
|
||||
return 0;
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
package net.ess3.provider.providers;
|
||||
|
||||
import net.ess3.provider.WorldInfoProvider;
|
||||
import org.bukkit.World;
|
||||
|
||||
public class ModernWorldInfoProvider implements WorldInfoProvider {
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "World info provider for data-driven world generation";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxSafeHeight(World world) {
|
||||
return world.getLogicalHeight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinSafeHeight(World world) {
|
||||
return world.getMinHeight();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user