diff --git a/Essentials/src/main/java/com/earth2me/essentials/Essentials.java b/Essentials/src/main/java/com/earth2me/essentials/Essentials.java index b1e6d0241..c85a58fb5 100644 --- a/Essentials/src/main/java/com/earth2me/essentials/Essentials.java +++ b/Essentials/src/main/java/com/earth2me/essentials/Essentials.java @@ -47,6 +47,7 @@ import net.ess3.api.IEssentials; import net.ess3.api.IItemDb; import net.ess3.api.IJails; 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.ReflKnownCommandsProvider; 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.ModernItemUnbreakableProvider; 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.PaperKnownCommandsProvider; 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)) { - worldInfoProvider = new ModernWorldInfoProvider(); + worldInfoProvider = new ModernDataWorldInfoProvider(); + } else if (VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_16_5_R01)) { + worldInfoProvider = new ReflDataWorldInfoProvider(); } else { worldInfoProvider = new FixedHeightWorldInfoProvider(); } diff --git a/Essentials/src/main/java/com/earth2me/essentials/RandomTeleport.java b/Essentials/src/main/java/com/earth2me/essentials/RandomTeleport.java index 3dfbfd1e0..b1c1cb417 100644 --- a/Essentials/src/main/java/com/earth2me/essentials/RandomTeleport.java +++ b/Essentials/src/main/java/com/earth2me/essentials/RandomTeleport.java @@ -177,7 +177,7 @@ public class RandomTeleport implements IConf { final Location location = new Location( center.getWorld(), center.getX() + offsetX, - ess.getWorldInfoProvider().getMaxSafeHeight(center.getWorld()), + ess.getWorldInfoProvider().getMaxHeight(center.getWorld()), center.getZ() + offsetZ, 360 * RANDOM.nextFloat() - 180, 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 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())) { return y; } @@ -204,6 +204,6 @@ public class RandomTeleport implements IConf { } 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()); } } diff --git a/Essentials/src/main/java/com/earth2me/essentials/commands/Commandtop.java b/Essentials/src/main/java/com/earth2me/essentials/commands/Commandtop.java index 60b7f53d9..f39b12789 100644 --- a/Essentials/src/main/java/com/earth2me/essentials/commands/Commandtop.java +++ b/Essentials/src/main/java/com/earth2me/essentials/commands/Commandtop.java @@ -22,7 +22,7 @@ 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 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 CompletableFuture future = new CompletableFuture<>(); future.thenAccept(success -> { diff --git a/Essentials/src/main/java/com/earth2me/essentials/utils/LocationUtil.java b/Essentials/src/main/java/com/earth2me/essentials/utils/LocationUtil.java index e9ea72440..1a9b5c5f7 100644 --- a/Essentials/src/main/java/com/earth2me/essentials/utils/LocationUtil.java +++ b/Essentials/src/main/java/com/earth2me/essentials/utils/LocationUtil.java @@ -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) { - 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) { @@ -203,8 +203,9 @@ public final class LocationUtil { throw new Exception(tl("destinationNotSet")); } final World world = loc.getWorld(); - final int worldMinY = ess.getWorldInfoProvider().getMinSafeHeight(world); - final int worldMaxY = ess.getWorldInfoProvider().getMaxSafeHeight(world); + final int worldMinY = ess.getWorldInfoProvider().getMinHeight(world); + final int worldLogicalY = ess.getWorldInfoProvider().getLogicalHeight(world); + final int worldMaxY = loc.getBlockY() < worldLogicalY ? worldLogicalY : ess.getWorldInfoProvider().getMaxHeight(world); int x = loc.getBlockX(); int y = (int) Math.round(loc.getY()); int z = loc.getBlockZ(); diff --git a/providers/BaseProviders/src/main/java/net/ess3/provider/WorldInfoProvider.java b/providers/BaseProviders/src/main/java/net/ess3/provider/WorldInfoProvider.java index b1f4034d4..39b2b1bf1 100644 --- a/providers/BaseProviders/src/main/java/net/ess3/provider/WorldInfoProvider.java +++ b/providers/BaseProviders/src/main/java/net/ess3/provider/WorldInfoProvider.java @@ -4,18 +4,27 @@ import org.bukkit.World; 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. - * @return The maximum safe height for teleportation + * @param world The world of which to check the maximum height. + * @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 */ - int getMinSafeHeight(World world); + int getMinHeight(World world); } diff --git a/providers/BaseProviders/src/main/java/net/ess3/provider/providers/FixedHeightWorldInfoProvider.java b/providers/BaseProviders/src/main/java/net/ess3/provider/providers/FixedHeightWorldInfoProvider.java index 80a34f85b..b4d4ffda6 100644 --- a/providers/BaseProviders/src/main/java/net/ess3/provider/providers/FixedHeightWorldInfoProvider.java +++ b/providers/BaseProviders/src/main/java/net/ess3/provider/providers/FixedHeightWorldInfoProvider.java @@ -6,16 +6,24 @@ import org.bukkit.World; public class FixedHeightWorldInfoProvider implements WorldInfoProvider { @Override public String getDescription() { - return "World info provider for fixed world heights"; + return "Fixed world info provider for pre-1.16"; } @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; } @Override - public int getMinSafeHeight(World world) { + public int getMinHeight(World world) { + // Worlds could not go below 0 until Minecraft 1.16 return 0; } } diff --git a/providers/BaseProviders/src/main/java/net/ess3/provider/providers/ModernDataWorldInfoProvider.java b/providers/BaseProviders/src/main/java/net/ess3/provider/providers/ModernDataWorldInfoProvider.java new file mode 100644 index 000000000..55e10f253 --- /dev/null +++ b/providers/BaseProviders/src/main/java/net/ess3/provider/providers/ModernDataWorldInfoProvider.java @@ -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(); + } +} diff --git a/providers/BaseProviders/src/main/java/net/ess3/provider/providers/ModernWorldInfoProvider.java b/providers/BaseProviders/src/main/java/net/ess3/provider/providers/ModernWorldInfoProvider.java deleted file mode 100644 index 634eb8345..000000000 --- a/providers/BaseProviders/src/main/java/net/ess3/provider/providers/ModernWorldInfoProvider.java +++ /dev/null @@ -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(); - } -} diff --git a/providers/NMSReflectionProvider/src/main/java/net/ess3/nms/refl/providers/ReflDataWorldInfoProvider.java b/providers/NMSReflectionProvider/src/main/java/net/ess3/nms/refl/providers/ReflDataWorldInfoProvider.java new file mode 100644 index 000000000..f9ac85c8c --- /dev/null +++ b/providers/NMSReflectionProvider/src/main/java/net/ess3/nms/refl/providers/ReflDataWorldInfoProvider.java @@ -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; + } +}