|
17 | 17 | import net.minecraft.commands.arguments.GameProfileArgument; |
18 | 18 | import net.minecraft.core.BlockPos; |
19 | 19 | import net.minecraft.core.Direction; |
20 | | -import net.minecraft.core.Holder; |
21 | 20 | import net.minecraft.core.registries.Registries; |
22 | 21 | import net.minecraft.network.chat.Component; |
23 | 22 | import net.minecraft.resources.ResourceLocation; |
24 | 23 | import net.minecraft.server.level.ServerLevel; |
25 | 24 | import net.minecraft.server.level.ServerPlayer; |
| 25 | +import net.minecraft.tags.BiomeTags; |
26 | 26 | import net.minecraft.tags.TagKey; |
27 | 27 | import net.minecraft.util.Mth; |
28 | 28 | import net.minecraft.world.level.Level; |
29 | 29 | import net.minecraft.world.level.biome.Biome; |
30 | 30 | import net.minecraft.world.level.block.Block; |
31 | 31 | import net.minecraft.world.level.block.state.BlockState; |
32 | | -import net.minecraft.world.level.border.WorldBorder; |
33 | 32 | import net.minecraft.world.level.levelgen.Heightmap; |
34 | 33 | import net.minecraft.world.phys.BlockHitResult; |
35 | 34 | import net.minecraft.world.phys.Vec3; |
|
38 | 37 | * @author LatvianModder |
39 | 38 | */ |
40 | 39 | public class TeleportCommands { |
41 | | - public static final TagKey<Block> IGNORE_RTP = TagKey.create(Registries.BLOCK, new ResourceLocation(FTBEssentials.MOD_ID, "ignore_rtp")); |
| 40 | + public static final TagKey<Block> IGNORE_RTP_BLOCKS = TagKey.create(Registries.BLOCK, new ResourceLocation(FTBEssentials.MOD_ID, "ignore_rtp")); |
| 41 | + public static final TagKey<Biome> IGNORE_RTP_BIOMES = TagKey.create(Registries.BIOME, new ResourceLocation(FTBEssentials.MOD_ID, "ignore_rtp")); |
42 | 42 |
|
43 | 43 | public static void register(CommandDispatcher<CommandSourceStack> dispatcher) { |
44 | 44 | if (FTBEConfig.BACK.isEnabled()) { |
@@ -144,63 +144,58 @@ public static int rtp(ServerPlayer player) { |
144 | 144 | } |
145 | 145 | return FTBEPlayerData.getOrCreate(player).map(data -> data.rtpTeleporter.teleport(player, p -> { |
146 | 146 | p.displayClientMessage(Component.literal("Looking for random location..."), false); |
147 | | - return findBlockPos((ServerLevel) player.level(), p, 1); |
| 147 | + return findBlockPos((ServerLevel) player.level(), p); |
148 | 148 | }).runCommand(player)) |
149 | 149 | .orElse(0); |
150 | 150 | } |
151 | 151 |
|
152 | | - private static TeleportPos findBlockPos(ServerLevel world, ServerPlayer player, int attempt) { |
153 | | - if (attempt > FTBEConfig.RTP_MAX_TRIES.get()) { |
154 | | - player.displayClientMessage(Component.literal("Could not find a valid location to teleport to!").withStyle(ChatFormatting.RED), false); |
155 | | - return new TeleportPos(player); |
156 | | - } |
157 | | - |
158 | | - double dist = FTBEConfig.RTP_MIN_DISTANCE.get() + world.random.nextDouble() * (FTBEConfig.RTP_MAX_DISTANCE.get() - FTBEConfig.RTP_MIN_DISTANCE.get()); |
159 | | - double angle = world.random.nextDouble() * Math.PI * 2D; |
160 | | - |
161 | | - int x = Mth.floor(Math.cos(angle) * dist); |
162 | | - int y = 256; |
163 | | - int z = Mth.floor(Math.sin(angle) * dist); |
164 | | - BlockPos currentPos = new BlockPos(x, y, z); |
165 | | - |
166 | | - WorldBorder border = world.getWorldBorder(); |
167 | | - |
168 | | - if (!border.isWithinBounds(currentPos)) { |
169 | | - return findBlockPos(world, player, attempt + 1); |
170 | | - } |
171 | | - |
172 | | - Holder<Biome> biomeKey = world.getBiome(currentPos); |
| 152 | + private static TeleportPos findBlockPos(ServerLevel world, ServerPlayer player) { |
| 153 | + for (int attempt = 0; attempt < FTBEConfig.RTP_MAX_TRIES.get(); attempt++) { |
| 154 | + double dist = FTBEConfig.RTP_MIN_DISTANCE.get() + world.random.nextDouble() * (FTBEConfig.RTP_MAX_DISTANCE.get() - FTBEConfig.RTP_MIN_DISTANCE.get()); |
| 155 | + double angle = world.random.nextDouble() * Math.PI * 2D; |
173 | 156 |
|
174 | | - if (biomeKey.unwrapKey().isPresent() && biomeKey.unwrapKey().get().location().getPath().contains("ocean")) { |
175 | | - return findBlockPos(world, player, attempt + 1); |
176 | | - } |
| 157 | + int x = Mth.floor(Math.cos(angle) * dist); |
| 158 | + int y = 256; |
| 159 | + int z = Mth.floor(Math.sin(angle) * dist); |
| 160 | + BlockPos currentPos = new BlockPos(x, y, z); |
177 | 161 |
|
178 | | - // TODO: FTB Chunks will listen to RTPEvent and cancel it if position is inside a claimed chunk |
179 | | - EventResult res = FTBEssentialsEvents.RTP_EVENT.invoker().teleport(world, player, currentPos, attempt); |
180 | | - if (res.isFalse()) { |
181 | | - return findBlockPos(world, player, attempt + 1); |
182 | | - } |
| 162 | + if (!world.getWorldBorder().isWithinBounds(currentPos)) { |
| 163 | + continue; |
| 164 | + } |
| 165 | + if (world.getBiome(currentPos).is(IGNORE_RTP_BIOMES)) { |
| 166 | + continue; |
| 167 | + } |
| 168 | + // TODO: FTB Chunks will listen to RTPEvent and cancel it if position is inside a claimed chunk |
| 169 | + EventResult res = FTBEssentialsEvents.RTP_EVENT.invoker().teleport(world, player, currentPos, attempt); |
| 170 | + if (res.isFalse()) { |
| 171 | + continue; |
| 172 | + } |
183 | 173 |
|
184 | | - // TODO: is there an equivalent to HEIGHTMAPS on 1.20? |
185 | | - world.getChunk(currentPos.getX() >> 4, currentPos.getZ() >> 4/*, ChunkStatus.HEIGHTMAPS*/); |
186 | | - BlockPos hmPos = world.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, currentPos); |
187 | | - |
188 | | - if (hmPos.getY() > 0) { |
189 | | - if (hmPos.getY() >= world.getLogicalHeight()) { // broken heightmap (nether, other mod dimensions) |
190 | | - for (BlockPos newPos : BlockPos.spiralAround(new BlockPos(hmPos.getX(), world.getSeaLevel(), hmPos.getY()), 16, Direction.EAST, Direction.SOUTH)) { |
191 | | - BlockState bs = world.getBlockState(newPos); |
192 | | - if (bs.blocksMotion() && !bs.is(IGNORE_RTP) && world.isEmptyBlock(newPos.above(1)) && world.isEmptyBlock(newPos.above(2)) && world.isEmptyBlock(newPos.above(3))) { |
193 | | - 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); |
194 | | - return new TeleportPos(world.dimension(), newPos.above()); |
| 174 | + world.getChunkAt(currentPos); |
| 175 | + BlockPos hmPos = world.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, currentPos); |
| 176 | + |
| 177 | + if (hmPos.getY() > 0) { |
| 178 | + BlockPos goodPos = null; |
| 179 | + if (hmPos.getY() < world.getLogicalHeight()) { |
| 180 | + goodPos = hmPos; |
| 181 | + } else { |
| 182 | + // broken heightmap (nether, other mod dimensions) |
| 183 | + for (BlockPos newPos : BlockPos.spiralAround(new BlockPos(hmPos.getX(), world.getSeaLevel(), hmPos.getY()), 16, Direction.EAST, Direction.SOUTH)) { |
| 184 | + BlockState bs = world.getBlockState(newPos); |
| 185 | + if (bs.blocksMotion() && !bs.is(IGNORE_RTP_BLOCKS) && world.isEmptyBlock(newPos.above(1)) |
| 186 | + && world.isEmptyBlock(newPos.above(2)) && world.isEmptyBlock(newPos.above(3))) { |
| 187 | + goodPos = newPos; |
| 188 | + } |
195 | 189 | } |
196 | 190 | } |
197 | | - } else { |
198 | | - 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); |
199 | | - return new TeleportPos(world.dimension(), hmPos.above()); |
| 191 | + if (goodPos != null) { |
| 192 | + 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); |
| 193 | + return new TeleportPos(world.dimension(), goodPos.above()); |
| 194 | + } |
200 | 195 | } |
201 | 196 | } |
202 | | - |
203 | | - return findBlockPos(world, player, attempt + 1); |
| 197 | + player.displayClientMessage(Component.literal("Could not find a valid location to teleport to!").withStyle(ChatFormatting.RED), false); |
| 198 | + return new TeleportPos(player); |
204 | 199 | } |
205 | 200 |
|
206 | 201 | public static int tpLast(ServerPlayer player, GameProfile to) { |
|
0 commit comments