diff --git a/src/main/java/io/ib67/sfcraft/module/command/BackModule.java b/src/main/java/io/ib67/sfcraft/module/command/BackModule.java index 541211f..5d29ee3 100644 --- a/src/main/java/io/ib67/sfcraft/module/command/BackModule.java +++ b/src/main/java/io/ib67/sfcraft/module/command/BackModule.java @@ -42,10 +42,10 @@ public class BackModule extends ServerModule { var nearby = wld.getClosestPlayer(_pos.getX(), _pos.getY(), _pos.getZ(), 20, true); if (nearby != null) { _pos = nearby.getBlockPos(); - player.teleport(wld, _pos.getX(), _pos.getY(), _pos.getZ(), 0, 0); + Helper.teleportSafely(player, wld, _pos.getX(), _pos.getY(), _pos.getZ()); } else { if (SFConsts.UNLIMITED_COMMAND_BACK.hasPermission(player)) { - player.teleport(wld, _pos.getX(), _pos.getY(), _pos.getZ(), 0, 0); + Helper.teleportSafely(player, wld, _pos.getX(), _pos.getY(), _pos.getZ()); return 0; } player.sendMessage(Text.of("周围没有玩家。").copy().withColor(Colors.RED)); diff --git a/src/main/java/io/ib67/sfcraft/util/Helper.java b/src/main/java/io/ib67/sfcraft/util/Helper.java index 5520e68..d13dec9 100644 --- a/src/main/java/io/ib67/sfcraft/util/Helper.java +++ b/src/main/java/io/ib67/sfcraft/util/Helper.java @@ -5,7 +5,16 @@ import io.ib67.sfcraft.SFCraft; import io.ib67.sfcraft.config.SFConfig; import io.ib67.sfcraft.geoip.GeoIPService; import lombok.SneakyThrows; +import net.minecraft.fluid.EmptyFluid; +import net.minecraft.fluid.LavaFluid; +import net.minecraft.fluid.WaterFluid; import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.text.Text; +import net.minecraft.util.Colors; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; +import net.minecraft.world.World; import java.net.InetSocketAddress; import java.nio.file.Files; @@ -13,6 +22,8 @@ import java.nio.file.Path; import java.util.Optional; public class Helper { + public static final char COLOR = '§'; + public static boolean canBack(ServerPlayerEntity player) { if (!SFConsts.COMMAND_BACK.hasPermission(player)) return false; var pos = player.getLastDeathPos().get(); @@ -23,6 +34,41 @@ public class Helper { return nearby != null; } + public static boolean teleportSafely(ServerPlayerEntity player, ServerWorld world, int x, int y, int z) { + var pos = new BlockPos(x, y, z); + var stand = world.getBlockState(pos); + if (!stand.isAir() && !stand.isSolidBlock(world, pos)) { + // check block type + var fluid = stand.getFluidState().getFluid(); + if (!(fluid instanceof EmptyFluid) && !(fluid instanceof WaterFluid)) { + player.sendMessage(Text.literal("§c传送目的地具有非水流体, 因此拒绝传送。")); + return false; + } + } + var groundPos = new BlockPos(x, y - 1, z); + var ground = world.getBlockState(groundPos); + if (!ground.hasSolidTopSurface(world, groundPos, player) + && !stand.isSolidSurface(world, pos, player, Direction.DOWN)) { + player.sendMessage(Text.literal("§c传送目的地没有可靠落地点,且为非空气方块, 因此拒绝传送。")); + return false; + } else { + var deltaY = 0.0; + var deltaX = 0.5; + var deltaZ = 0.5; + var fluid = stand.getFluidState().getFluid(); + if (!stand.isAir()) { + deltaY = stand.getCollisionShape(world, pos).getMax(Direction.Axis.Y); + deltaY = Double.isFinite(deltaY) ? deltaY + 0.1 : 0; + deltaX = stand.getCollisionShape(world, pos).getMax(Direction.Axis.X); + deltaX = Double.isFinite(deltaX) ? deltaX / 2 : 0.5; + deltaZ = stand.getCollisionShape(world, pos).getMax(Direction.Axis.X); + deltaZ = Double.isFinite(deltaZ) ? deltaZ / 2 : 0.5; + } + player.teleport(world, x + deltaX, y + deltaY, z + deltaZ, 0, 0); + } + return true; + } + public static String getVersionString(InetSocketAddress address) { var geoIp = SFCraft.getInjector().getInstance(GeoIPService.class); var config = SFCraft.getInjector().getInstance(SFConfig.class); @@ -36,6 +82,7 @@ public class Helper { } return null; } + @SneakyThrows public static Optional getConfigResource(Path root, String resource) { if (Files.exists(root)) {