Refactor world info provider; only clamp to logical height when already below

Fixes #4657.
This commit is contained in:
MD 2021-11-30 16:02:49 +00:00
parent 0983167740
commit e35c65b976
9 changed files with 97 additions and 40 deletions

View file

@ -47,6 +47,7 @@ import net.ess3.api.IEssentials;
import net.ess3.api.IItemDb; import net.ess3.api.IItemDb;
import net.ess3.api.IJails; import net.ess3.api.IJails;
import net.ess3.api.ISettings; import net.ess3.api.ISettings;
import net.ess3.nms.refl.providers.ReflDataWorldInfoProvider;
import net.ess3.nms.refl.providers.ReflFormattedCommandAliasProvider; import net.ess3.nms.refl.providers.ReflFormattedCommandAliasProvider;
import net.ess3.nms.refl.providers.ReflKnownCommandsProvider; import net.ess3.nms.refl.providers.ReflKnownCommandsProvider;
import net.ess3.nms.refl.providers.ReflOnlineModeProvider; import net.ess3.nms.refl.providers.ReflOnlineModeProvider;
@ -81,7 +82,7 @@ import net.ess3.provider.providers.LegacyPotionMetaProvider;
import net.ess3.provider.providers.LegacySpawnEggProvider; import net.ess3.provider.providers.LegacySpawnEggProvider;
import net.ess3.provider.providers.ModernItemUnbreakableProvider; import net.ess3.provider.providers.ModernItemUnbreakableProvider;
import net.ess3.provider.providers.ModernPersistentDataProvider; import net.ess3.provider.providers.ModernPersistentDataProvider;
import net.ess3.provider.providers.ModernWorldInfoProvider; import net.ess3.provider.providers.ModernDataWorldInfoProvider;
import net.ess3.provider.providers.PaperContainerProvider; import net.ess3.provider.providers.PaperContainerProvider;
import net.ess3.provider.providers.PaperKnownCommandsProvider; import net.ess3.provider.providers.PaperKnownCommandsProvider;
import net.ess3.provider.providers.PaperMaterialTagProvider; import net.ess3.provider.providers.PaperMaterialTagProvider;
@ -424,7 +425,9 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
} }
if (VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_17_1_R01)) { if (VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_17_1_R01)) {
worldInfoProvider = new ModernWorldInfoProvider(); worldInfoProvider = new ModernDataWorldInfoProvider();
} else if (VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_16_5_R01)) {
worldInfoProvider = new ReflDataWorldInfoProvider();
} else { } else {
worldInfoProvider = new FixedHeightWorldInfoProvider(); worldInfoProvider = new FixedHeightWorldInfoProvider();
} }

View file

@ -177,7 +177,7 @@ public class RandomTeleport implements IConf {
final Location location = new Location( final Location location = new Location(
center.getWorld(), center.getWorld(),
center.getX() + offsetX, center.getX() + offsetX,
ess.getWorldInfoProvider().getMaxSafeHeight(center.getWorld()), ess.getWorldInfoProvider().getMaxHeight(center.getWorld()),
center.getZ() + offsetZ, center.getZ() + offsetZ,
360 * RANDOM.nextFloat() - 180, 360 * RANDOM.nextFloat() - 180,
0 0
@ -195,7 +195,7 @@ public class RandomTeleport implements IConf {
// Returns an appropriate elevation for a given location in the nether, or -1 if none is found // Returns an appropriate elevation for a given location in the nether, or -1 if none is found
private double getNetherYAt(final Location location) { private double getNetherYAt(final Location location) {
for (int y = 32; y < ess.getWorldInfoProvider().getMaxSafeHeight(location.getWorld()); ++y) { for (int y = 32; y < ess.getWorldInfoProvider().getMaxHeight(location.getWorld()); ++y) {
if (!LocationUtil.isBlockUnsafe(ess, location.getWorld(), location.getBlockX(), y, location.getBlockZ())) { if (!LocationUtil.isBlockUnsafe(ess, location.getWorld(), location.getBlockX(), y, location.getBlockZ())) {
return y; return y;
} }
@ -204,6 +204,6 @@ public class RandomTeleport implements IConf {
} }
private boolean isValidRandomLocation(final Location location) { private boolean isValidRandomLocation(final Location location) {
return location.getBlockY() > ess.getWorldInfoProvider().getMinSafeHeight(location.getWorld()) && !this.getExcludedBiomes().contains(location.getBlock().getBiome()); return location.getBlockY() > ess.getWorldInfoProvider().getMinHeight(location.getWorld()) && !this.getExcludedBiomes().contains(location.getBlock().getBiome());
} }
} }

View file

@ -22,7 +22,7 @@ public class Commandtop extends EssentialsCommand {
final int topZ = user.getLocation().getBlockZ(); final int topZ = user.getLocation().getBlockZ();
final float pitch = user.getLocation().getPitch(); final float pitch = user.getLocation().getPitch();
final float yaw = user.getLocation().getYaw(); final float yaw = user.getLocation().getYaw();
final Location unsafe = new Location(user.getWorld(), topX, ess.getWorldInfoProvider().getMaxSafeHeight(user.getWorld()), topZ, yaw, pitch); final Location unsafe = new Location(user.getWorld(), topX, ess.getWorldInfoProvider().getMaxHeight(user.getWorld()), topZ, yaw, pitch);
final Location safe = LocationUtil.getSafeDestination(ess, unsafe); final Location safe = LocationUtil.getSafeDestination(ess, unsafe);
final CompletableFuture<Boolean> future = new CompletableFuture<>(); final CompletableFuture<Boolean> future = new CompletableFuture<>();
future.thenAccept(success -> { future.thenAccept(success -> {

View file

@ -97,7 +97,7 @@ public final class LocationUtil {
} }
public static boolean isBlockAboveAir(IEssentials ess, final World world, final int x, final int y, final int z) { 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()); return y > ess.getWorldInfoProvider().getMaxHeight(world) || HOLLOW_MATERIALS.contains(world.getBlockAt(x, y - 1, z).getType());
} }
public static boolean isBlockOutsideWorldBorder(final World world, final int x, final int z) { public static boolean isBlockOutsideWorldBorder(final World world, final int x, final int z) {
@ -203,8 +203,9 @@ public final class LocationUtil {
throw new Exception(tl("destinationNotSet")); throw new Exception(tl("destinationNotSet"));
} }
final World world = loc.getWorld(); final World world = loc.getWorld();
final int worldMinY = ess.getWorldInfoProvider().getMinSafeHeight(world); final int worldMinY = ess.getWorldInfoProvider().getMinHeight(world);
final int worldMaxY = ess.getWorldInfoProvider().getMaxSafeHeight(world); final int worldLogicalY = ess.getWorldInfoProvider().getLogicalHeight(world);
final int worldMaxY = loc.getBlockY() < worldLogicalY ? worldLogicalY : ess.getWorldInfoProvider().getMaxHeight(world);
int x = loc.getBlockX(); int x = loc.getBlockX();
int y = (int) Math.round(loc.getY()); int y = (int) Math.round(loc.getY());
int z = loc.getBlockZ(); int z = loc.getBlockZ();

View file

@ -4,18 +4,27 @@ import org.bukkit.World;
public interface WorldInfoProvider extends Provider { public interface WorldInfoProvider extends Provider {
/** /**
* Gets the maximum safe height for teleportation. * Gets the maximum height of the world.
* *
* @param world The world of which to check the maximum safe height. * @param world The world of which to check the maximum height.
* @return The maximum safe height for teleportation * @return The maximum height of the world.
*/ */
int getMaxSafeHeight(World world); int getMaxHeight(World world);
/** /**
* Gets the minimum safe height for teleportation. * Gets the "logical" height of the world, which is the highest Y level at which vanilla spawns Nether portals and
* performs chorus fruit teleports.
* *
* @param world The world of which to check the base height. * @param world The world of which to check the logical height.
* @return The logical height of the world.
*/
int getLogicalHeight(World world);
/**
* Gets the minimum height of the world.
*
* @param world The world of which to check the minimum height.
* @return The minimum safe height for teleportation * @return The minimum safe height for teleportation
*/ */
int getMinSafeHeight(World world); int getMinHeight(World world);
} }

View file

@ -6,16 +6,24 @@ import org.bukkit.World;
public class FixedHeightWorldInfoProvider implements WorldInfoProvider { public class FixedHeightWorldInfoProvider implements WorldInfoProvider {
@Override @Override
public String getDescription() { public String getDescription() {
return "World info provider for fixed world heights"; return "Fixed world info provider for pre-1.16";
} }
@Override @Override
public int getMaxSafeHeight(World world) { public int getMaxHeight(World world) {
// Method has existed since Beta 1.7 (yes, *beta*)
return world.getMaxHeight();
}
@Override
public int getLogicalHeight(World world) {
// This mirrors the vanilla behaviour up until Minecraft 1.16
return world.getEnvironment() == World.Environment.NETHER ? 128 : 256; return world.getEnvironment() == World.Environment.NETHER ? 128 : 256;
} }
@Override @Override
public int getMinSafeHeight(World world) { public int getMinHeight(World world) {
// Worlds could not go below 0 until Minecraft 1.16
return 0; return 0;
} }
} }

View file

@ -0,0 +1,26 @@
package net.ess3.provider.providers;
import net.ess3.provider.WorldInfoProvider;
import org.bukkit.World;
public class ModernDataWorldInfoProvider implements WorldInfoProvider {
@Override
public String getDescription() {
return "API world info provider for data-driven worldgen for 1.17.1+";
}
@Override
public int getMaxHeight(World world) {
return world.getMaxHeight();
}
@Override
public int getLogicalHeight(World world) {
return world.getLogicalHeight();
}
@Override
public int getMinHeight(World world) {
return world.getMinHeight();
}
}

View file

@ -1,21 +0,0 @@
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();
}
}

View file

@ -0,0 +1,31 @@
package net.ess3.nms.refl.providers;
import net.ess3.provider.WorldInfoProvider;
import org.bukkit.World;
public class ReflDataWorldInfoProvider implements WorldInfoProvider {
@Override
public String getDescription() {
return "NMS world info provider for data-driven worldgen for 1.16.x";
}
@Override
public int getMaxHeight(World world) {
// Method has existed since Beta 1.7 (yes, *beta*)
return world.getMaxHeight();
}
@Override
public int getLogicalHeight(World world) {
// TODO: THIS IS INCORRECT
// This mirrors the vanilla behaviour up until Minecraft 1.16
return world.getEnvironment() == World.Environment.NETHER ? 128 : 256;
}
@Override
public int getMinHeight(World world) {
// TODO: THIS IS INCORRECT
// Worlds could not go below 0 until Minecraft 1.16
return 0;
}
}