From 31b1c11fb4e1d7985259042add5f44ccc2a41386 Mon Sep 17 00:00:00 2001 From: Des Herriott Date: Sat, 30 Sep 2023 08:51:43 +0100 Subject: [PATCH 1/4] fix: use a proper tag check to check for oceans for /rtp Better than looking for "ocean" in the biome name... --- .../dev/ftb/mods/ftbessentials/command/TeleportCommands.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/src/main/java/dev/ftb/mods/ftbessentials/command/TeleportCommands.java b/common/src/main/java/dev/ftb/mods/ftbessentials/command/TeleportCommands.java index 95046e4..bb6a3d4 100644 --- a/common/src/main/java/dev/ftb/mods/ftbessentials/command/TeleportCommands.java +++ b/common/src/main/java/dev/ftb/mods/ftbessentials/command/TeleportCommands.java @@ -23,6 +23,7 @@ import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; +import net.minecraft.tags.BiomeTags; import net.minecraft.tags.TagKey; import net.minecraft.util.Mth; import net.minecraft.world.level.Level; @@ -170,8 +171,7 @@ private static TeleportPos findBlockPos(ServerLevel world, ServerPlayer player, } Holder biomeKey = world.getBiome(currentPos); - - if (biomeKey.unwrapKey().isPresent() && biomeKey.unwrapKey().get().location().getPath().contains("ocean")) { + if (biomeKey.is(BiomeTags.IS_OCEAN)) { return findBlockPos(world, player, attempt + 1); } From 4fec417333ec7c7bba82c8772cf159b099e7fa78 Mon Sep 17 00:00:00 2001 From: Des Herriott Date: Mon, 9 Oct 2023 17:10:54 +0100 Subject: [PATCH 2/4] feat: make RTP ignore blocks and biomes more explicit as tags Also make TeleportCommands#findBlockPos use an iterative algorithm instead of a recursive one --- .../command/TeleportCommands.java | 91 +++++++++---------- .../{ => tags/blocks}/ignore_rtp.json | 0 .../tags/worldgen/biome/ignore_rtp.json | 6 ++ 3 files changed, 49 insertions(+), 48 deletions(-) rename common/src/main/resources/data/ftbessentials/{ => tags/blocks}/ignore_rtp.json (100%) create mode 100644 common/src/main/resources/data/ftbessentials/tags/worldgen/biome/ignore_rtp.json diff --git a/common/src/main/java/dev/ftb/mods/ftbessentials/command/TeleportCommands.java b/common/src/main/java/dev/ftb/mods/ftbessentials/command/TeleportCommands.java index bb6a3d4..694dda3 100644 --- a/common/src/main/java/dev/ftb/mods/ftbessentials/command/TeleportCommands.java +++ b/common/src/main/java/dev/ftb/mods/ftbessentials/command/TeleportCommands.java @@ -17,7 +17,6 @@ import net.minecraft.commands.arguments.GameProfileArgument; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; -import net.minecraft.core.Holder; import net.minecraft.core.registries.Registries; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; @@ -30,7 +29,6 @@ import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.border.WorldBorder; import net.minecraft.world.level.levelgen.Heightmap; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.Vec3; @@ -39,7 +37,8 @@ * @author LatvianModder */ public class TeleportCommands { - public static final TagKey IGNORE_RTP = TagKey.create(Registries.BLOCK, new ResourceLocation(FTBEssentials.MOD_ID, "ignore_rtp")); + public static final TagKey IGNORE_RTP_BLOCKS = TagKey.create(Registries.BLOCK, new ResourceLocation(FTBEssentials.MOD_ID, "ignore_rtp")); + public static final TagKey IGNORE_RTP_BIOMES = TagKey.create(Registries.BIOME, new ResourceLocation(FTBEssentials.MOD_ID, "ignore_rtp")); public static void register(CommandDispatcher dispatcher) { if (FTBEConfig.BACK.isEnabled()) { @@ -145,62 +144,58 @@ public static int rtp(ServerPlayer player) { } return FTBEPlayerData.getOrCreate(player).map(data -> data.rtpTeleporter.teleport(player, p -> { p.displayClientMessage(Component.literal("Looking for random location..."), false); - return findBlockPos((ServerLevel) player.level(), p, 1); + return findBlockPos((ServerLevel) player.level(), p); }).runCommand(player)) .orElse(0); } - private static TeleportPos findBlockPos(ServerLevel world, ServerPlayer player, int attempt) { - if (attempt > FTBEConfig.RTP_MAX_TRIES.get()) { - player.displayClientMessage(Component.literal("Could not find a valid location to teleport to!").withStyle(ChatFormatting.RED), false); - return new TeleportPos(player); - } - - double dist = FTBEConfig.RTP_MIN_DISTANCE.get() + world.random.nextDouble() * (FTBEConfig.RTP_MAX_DISTANCE.get() - FTBEConfig.RTP_MIN_DISTANCE.get()); - double angle = world.random.nextDouble() * Math.PI * 2D; - - int x = Mth.floor(Math.cos(angle) * dist); - int y = 256; - int z = Mth.floor(Math.sin(angle) * dist); - BlockPos currentPos = new BlockPos(x, y, z); - - WorldBorder border = world.getWorldBorder(); + private static TeleportPos findBlockPos(ServerLevel world, ServerPlayer player) { + for (int attempt = 0; attempt < FTBEConfig.RTP_MAX_TRIES.get(); attempt++) { + double dist = FTBEConfig.RTP_MIN_DISTANCE.get() + world.random.nextDouble() * (FTBEConfig.RTP_MAX_DISTANCE.get() - FTBEConfig.RTP_MIN_DISTANCE.get()); + double angle = world.random.nextDouble() * Math.PI * 2D; - if (!border.isWithinBounds(currentPos)) { - return findBlockPos(world, player, attempt + 1); - } - - Holder biomeKey = world.getBiome(currentPos); - if (biomeKey.is(BiomeTags.IS_OCEAN)) { - return findBlockPos(world, player, attempt + 1); - } + int x = Mth.floor(Math.cos(angle) * dist); + int y = 256; + int z = Mth.floor(Math.sin(angle) * dist); + BlockPos currentPos = new BlockPos(x, y, z); - // TODO: FTB Chunks will listen to RTPEvent and cancel it if position is inside a claimed chunk - EventResult res = FTBEssentialsEvents.RTP_EVENT.invoker().teleport(world, player, currentPos, attempt); - if (res.isFalse()) { - return findBlockPos(world, player, attempt + 1); - } + if (!world.getWorldBorder().isWithinBounds(currentPos)) { + continue; + } + if (world.getBiome(currentPos).is(IGNORE_RTP_BIOMES)) { + continue; + } + // TODO: FTB Chunks will listen to RTPEvent and cancel it if position is inside a claimed chunk + EventResult res = FTBEssentialsEvents.RTP_EVENT.invoker().teleport(world, player, currentPos, attempt); + if (res.isFalse()) { + continue; + } - // TODO: is there an equivalent to HEIGHTMAPS on 1.20? - world.getChunk(currentPos.getX() >> 4, currentPos.getZ() >> 4/*, ChunkStatus.HEIGHTMAPS*/); - BlockPos hmPos = world.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, currentPos); - - if (hmPos.getY() > 0) { - if (hmPos.getY() >= world.getLogicalHeight()) { // broken heightmap (nether, other mod dimensions) - for (BlockPos newPos : BlockPos.spiralAround(new BlockPos(hmPos.getX(), world.getSeaLevel(), hmPos.getY()), 16, Direction.EAST, Direction.SOUTH)) { - BlockState bs = world.getBlockState(newPos); - if (bs.blocksMotion() && !bs.is(IGNORE_RTP) && world.isEmptyBlock(newPos.above(1)) && world.isEmptyBlock(newPos.above(2)) && world.isEmptyBlock(newPos.above(3))) { - player.displayClientMessage(Component.literal(String.format("Found good location after %d " + (attempt == 1 ? "attempt" : "attempts") + " @ [x %d, z %d]", attempt, newPos.getX(), newPos.getZ())), false); - return new TeleportPos(world.dimension(), newPos.above()); + world.getChunkAt(currentPos); + BlockPos hmPos = world.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, currentPos); + + if (hmPos.getY() > 0) { + BlockPos goodPos = null; + if (hmPos.getY() < world.getLogicalHeight()) { + goodPos = hmPos; + } else { + // broken heightmap (nether, other mod dimensions) + for (BlockPos newPos : BlockPos.spiralAround(new BlockPos(hmPos.getX(), world.getSeaLevel(), hmPos.getY()), 16, Direction.EAST, Direction.SOUTH)) { + BlockState bs = world.getBlockState(newPos); + if (bs.blocksMotion() && !bs.is(IGNORE_RTP_BLOCKS) && world.isEmptyBlock(newPos.above(1)) + && world.isEmptyBlock(newPos.above(2)) && world.isEmptyBlock(newPos.above(3))) { + goodPos = newPos; + } } } - } else { - player.displayClientMessage(Component.literal(String.format("Found good location after %d " + (attempt == 1 ? "attempt" : "attempts") + " @ [x %d, z %d]", attempt, hmPos.getX(), hmPos.getZ())), false); - return new TeleportPos(world.dimension(), hmPos.above()); + if (goodPos != null) { + player.displayClientMessage(Component.literal(String.format("Found good location after %d " + (attempt == 1 ? "attempt" : "attempts") + " @ [x %d, z %d]", attempt, goodPos.getX(), goodPos.getZ())), false); + return new TeleportPos(world.dimension(), goodPos.above()); + } } } - - return findBlockPos(world, player, attempt + 1); + player.displayClientMessage(Component.literal("Could not find a valid location to teleport to!").withStyle(ChatFormatting.RED), false); + return new TeleportPos(player); } public static int tpLast(ServerPlayer player, GameProfile to) { diff --git a/common/src/main/resources/data/ftbessentials/ignore_rtp.json b/common/src/main/resources/data/ftbessentials/tags/blocks/ignore_rtp.json similarity index 100% rename from common/src/main/resources/data/ftbessentials/ignore_rtp.json rename to common/src/main/resources/data/ftbessentials/tags/blocks/ignore_rtp.json diff --git a/common/src/main/resources/data/ftbessentials/tags/worldgen/biome/ignore_rtp.json b/common/src/main/resources/data/ftbessentials/tags/worldgen/biome/ignore_rtp.json new file mode 100644 index 0000000..3e4e90e --- /dev/null +++ b/common/src/main/resources/data/ftbessentials/tags/worldgen/biome/ignore_rtp.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "#minecraft:is_ocean" + ] +} \ No newline at end of file From 4299feb58b72d2b64bbf63eb4594ce2e16fe6ba9 Mon Sep 17 00:00:00 2001 From: Des Herriott Date: Tue, 10 Oct 2023 08:27:44 +0100 Subject: [PATCH 3/4] fix: player tick event should only run on the server side! Running on client side can lead to unwanted effects, like the player being able to cheat-fly on servers... https://github.com/FTBTeam/FTB-Mods-Issues/issues/972 --- .../mods/ftbessentials/FTBEEventHandler.java | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/common/src/main/java/dev/ftb/mods/ftbessentials/FTBEEventHandler.java b/common/src/main/java/dev/ftb/mods/ftbessentials/FTBEEventHandler.java index 5b963ee..5aa39da 100644 --- a/common/src/main/java/dev/ftb/mods/ftbessentials/FTBEEventHandler.java +++ b/common/src/main/java/dev/ftb/mods/ftbessentials/FTBEEventHandler.java @@ -122,19 +122,21 @@ private static void playerLoggedOut(ServerPlayer serverPlayer) { } private static void playerTickPost(Player player) { - FTBEPlayerData.getOrCreate(player).ifPresent(data -> { - var abilities = player.getAbilities(); + if (!player.level().isClientSide) { + FTBEPlayerData.getOrCreate(player).ifPresent(data -> { + var abilities = player.getAbilities(); - if (data.isGod() && !abilities.invulnerable) { - abilities.invulnerable = true; - player.onUpdateAbilities(); - } + if (data.isGod() && !abilities.invulnerable) { + abilities.invulnerable = true; + player.onUpdateAbilities(); + } - if (data.canFly() && !abilities.mayfly) { - abilities.mayfly = true; - player.onUpdateAbilities(); - } - }); + if (data.canFly() && !abilities.mayfly) { + abilities.mayfly = true; + player.onUpdateAbilities(); + } + }); + } } private static void serverTickPost(MinecraftServer server) { From 831eb09c9d45f6d5814c8dfc757164832dd8b805 Mon Sep 17 00:00:00 2001 From: Des Herriott Date: Tue, 10 Oct 2023 08:30:45 +0100 Subject: [PATCH 4/4] build: version -> 2001.2.1, changelog updated --- CHANGELOG.md | 11 +++++++++++ gradle.properties | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ed5c0c6..6b4e7ee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,17 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [2001.2.1] + +### Added +* The `/rtp` command now makes better use of block and biome tags to control valid RTP destinations + * `ftbessentials:ignore_rtp` block tag lists blocks which are not valid for the player to land on (leaves and Bedrock by default) + * `ftbessentials:ignore_rtp` biome tag lists biomes which are not valid for the player to land in (`#minecraft:is_ocean` by default) + +### Fixed +* Fixed an event handler running on the client side which shouldn't have been + * Led to undesirable effects like players flying when they shouldn't + ## [2001.2.0] ### Added diff --git a/gradle.properties b/gradle.properties index 96b3da3..05575ab 100644 --- a/gradle.properties +++ b/gradle.properties @@ -5,7 +5,7 @@ mod_id=ftbessentials archives_base_name=ftb-essentials maven_group=dev.ftb.mods minecraft_version=1.20.1 -mod_version=2001.2.0 +mod_version=2001.2.1 mod_author=FTB Team architectury_version=9.0.8