From b877e61c684a2fc00e1fa2ecf2cfa67f64eed9bb Mon Sep 17 00:00:00 2001 From: 3944Realms Date: Tue, 14 Oct 2025 19:56:30 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=89=A9=E5=85=85=E4=BA=86?= =?UTF-8?q?=E5=BD=A2=E7=8A=B6=E5=B7=A5=E5=85=B7=E7=B1=BB=E7=9A=84=E6=96=B9?= =?UTF-8?q?=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gradle.properties | 2 +- .../lib39/util/shape/ShapeUtil.java | 230 +++++++++++++++--- 2 files changed, 200 insertions(+), 32 deletions(-) diff --git a/gradle.properties b/gradle.properties index f77ca19..e753691 100644 --- a/gradle.properties +++ b/gradle.properties @@ -33,7 +33,7 @@ mod_name=3944Realms 's Lib Mod # The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default. mod_license=MIT # The mod version. See https://semver.org/ -mod_version=0.0.5 +mod_version=0.0.6 # The group ID for the mod. It is only important when publishing as an artifact to a Maven repository. # This should match the base package used for the mod sources. # See https://maven.apache.org/guides/mini/guide-naming-conventions.html diff --git a/src/main/java/top/r3944realms/lib39/util/shape/ShapeUtil.java b/src/main/java/top/r3944realms/lib39/util/shape/ShapeUtil.java index 9629b85..2033e94 100644 --- a/src/main/java/top/r3944realms/lib39/util/shape/ShapeUtil.java +++ b/src/main/java/top/r3944realms/lib39/util/shape/ShapeUtil.java @@ -1,50 +1,218 @@ package top.r3944realms.lib39.util.shape; +import net.minecraft.core.Direction; +import net.minecraft.world.level.block.state.properties.DoubleBlockHalf; import net.minecraft.world.phys.shapes.Shapes; import net.minecraft.world.phys.shapes.VoxelShape; import org.jetbrains.annotations.NotNull; -import java.util.ArrayList; -import java.util.List; +import java.util.*; public class ShapeUtil { + + // ==================== 基础形状创建 ==================== + /** * 创建基于像素的碰撞箱(将像素坐标转换为方块坐标) */ - public static @NotNull VoxelShape createPixelBasedShape(double minX, double minY, double minZ, double maxX, double maxY, double maxZ) { - return Shapes.box(minX / 16.0d, minY / 16.0d, minZ / 16.0d, maxX / 16.0d, maxY / 16.0d, maxZ / 16.0d); - } - public static @NotNull VoxelShape rotateVoxelShapeClockwise(@NotNull VoxelShape in) { - final List generatedShapes = new ArrayList<>(); - in.forAllBoxes((arg0, arg1, arg2, arg3, arg4, arg5) -> { - VoxelShape shape = Shapes.box(1.0 - arg5, arg1, arg0, 1.0 - arg2, arg4, arg3); - generatedShapes.add(shape); - }); - return getVoxelShape(generatedShapes); - } - public static VoxelShape RotateVoxelShapeXAxis(VoxelShape in) { - final List generatedShapes = new ArrayList<>(); - in.forAllBoxes((arg0, arg1, arg2, arg3, arg4, arg5) -> { - VoxelShape shape = Shapes.box(arg0, 1.0 - arg5, arg1, arg3, 1.0 - arg2, arg4); - generatedShapes.add(shape); - }); - return getVoxelShape(generatedShapes); + public static @NotNull VoxelShape createPixelBasedShape(double minX, double minY, double minZ, + double maxX, double maxY, double maxZ) { + return Shapes.box(minX / 16.0d, minY / 16.0d, minZ / 16.0d, + maxX / 16.0d, maxY / 16.0d, maxZ / 16.0d); } + /** + * 便捷方法:创建方块碰撞箱 + */ + public static @NotNull VoxelShape createBox(double minX, double minY, double minZ, + double maxX, double maxY, double maxZ) { + return Shapes.box(minX, minY, minZ, maxX, maxY, maxZ); + } + + // ==================== 多部分方块形状映射 ==================== + + /** + * 创建单一形状的方向映射 + */ + public static Map createUniformDirectionMap(VoxelShape shape) { + return createRotatedDirectionMap(shape); + } + + /** + * 创建双部分方块的形状映射 + */ + public static Map> createTwoPartShapeMap(VoxelShape headShape, VoxelShape footShape) { + EnumMap> shapeMap = new EnumMap<>(BlockPart.class); + shapeMap.put(BlockPart.HEAD, createRotatedDirectionMap(headShape)); + shapeMap.put(BlockPart.FOOT, createRotatedDirectionMap(footShape)); + return shapeMap; + } + + /** + * 创建原版双方块的形状映射 + */ + public static Map> createDoubleBlockShapeMap(VoxelShape lowerShape, VoxelShape upperShape) { + EnumMap> shapeMap = new EnumMap<>(DoubleBlockHalf.class); + shapeMap.put(DoubleBlockHalf.LOWER, createRotatedDirectionMap(lowerShape)); + shapeMap.put(DoubleBlockHalf.UPPER, createRotatedDirectionMap(upperShape)); + return shapeMap; + } + + /** + * 创建三部分方块的形状映射 + */ + public static Map> createThreePartShapeMap(VoxelShape headShape, VoxelShape centerShape, VoxelShape footShape) { + EnumMap> shapeMap = new EnumMap<>(BlockSection.class); + shapeMap.put(BlockSection.HEAD, createRotatedDirectionMap(headShape)); + shapeMap.put(BlockSection.CENTER, createRotatedDirectionMap(centerShape)); + shapeMap.put(BlockSection.FOOT, createRotatedDirectionMap(footShape)); + return shapeMap; + } + + // ==================== 形状旋转 ==================== + + /** + * 顺时针旋转碰撞箱(Y轴旋转) + */ + public static @NotNull VoxelShape rotateVoxelShapeClockwise(@NotNull VoxelShape shape) { + final List generatedShapes = new ArrayList<>(); + shape.forAllBoxes((minX, minY, minZ, maxX, maxY, maxZ) -> { + VoxelShape rotated = Shapes.box(1.0 - maxZ, minY, minX, 1.0 - minZ, maxY, maxX); + generatedShapes.add(rotated); + }); + return combineShapes(generatedShapes); + } + + /** + * 绕X轴旋转碰撞箱 + */ + public static @NotNull VoxelShape rotateVoxelShapeXAxis(@NotNull VoxelShape shape) { + final List generatedShapes = new ArrayList<>(); + shape.forAllBoxes((minX, minY, minZ, maxX, maxY, maxZ) -> { + VoxelShape rotated = Shapes.box(minX, 1.0 - maxZ, minY, maxX, 1.0 - minZ, maxY); + generatedShapes.add(rotated); + }); + return combineShapes(generatedShapes); + } + + /** + * 绕Z轴旋转碰撞箱 + */ + public static @NotNull VoxelShape rotateVoxelShapeZAxis(@NotNull VoxelShape shape) { + final List generatedShapes = new ArrayList<>(); + shape.forAllBoxes((minX, minY, minZ, maxX, maxY, maxZ) -> { + VoxelShape rotated = Shapes.box(minY, minX, minZ, maxY, maxX, maxZ); + generatedShapes.add(rotated); + }); + return combineShapes(generatedShapes); + } + + /** + * 按指定角度旋转碰撞箱 + */ + public static @NotNull VoxelShape rotateShape(@NotNull VoxelShape shape, int degrees) { + int rotations = (degrees / 90) % 4; + VoxelShape result = shape; + + for (int i = 0; i < rotations; i++) { + result = rotateVoxelShapeClockwise(result); + } + return result; + } + + // ==================== 形状组合与优化 ==================== + + /** + * 组合多个形状列表 + */ @NotNull - private static VoxelShape getVoxelShape(List generatedShapes) { - if (generatedShapes.isEmpty()) { + private static VoxelShape combineShapes(List shapes) { + if (shapes.isEmpty()) { return Shapes.block(); - } else { - VoxelShape out = generatedShapes.get(0); + } - for(int i = 1; i < generatedShapes.size(); ++i) { - VoxelShape shape = generatedShapes.get(i); - out = Shapes.or(out, shape); - } + VoxelShape result = shapes.get(0); + for (int i = 1; i < shapes.size(); i++) { + result = Shapes.or(result, shapes.get(i)); + } - out.optimize(); - return out; + return result.optimize(); + } + + /** + * 组合多个形状 + */ + public static @NotNull VoxelShape combineShapes(VoxelShape... shapes) { + return combineShapes(Arrays.asList(shapes)); + } + + // ==================== 内部工具方法 ==================== + + /** + * 创建旋转方向映射 + */ + private static Map createRotatedDirectionMap(VoxelShape baseShape) { + EnumMap directionMap = new EnumMap<>(Direction.class); + directionMap.put(Direction.NORTH, baseShape); + directionMap.put(Direction.EAST, rotateShape(baseShape, 90)); + directionMap.put(Direction.SOUTH, rotateShape(baseShape, 180)); + directionMap.put(Direction.WEST, rotateShape(baseShape, 270)); + return directionMap; + } + + // ==================== 枚举定义 ==================== + + /** + * 方块部分枚举(双部分方块) + */ + public enum BlockPart { + HEAD, + FOOT + } + + /** + * 方块部分枚举(三部分方块) + */ + public enum BlockSection { + HEAD, + CENTER, + FOOT + } + + // ==================== 便捷构建器 ==================== + + /** + * 形状构建器 - 流畅API + */ + public static class ShapeBuilder { + private final List shapes = new ArrayList<>(); + + public ShapeBuilder addPixelBox(double minX, double minY, double minZ, + double maxX, double maxY, double maxZ) { + shapes.add(createPixelBasedShape(minX, minY, minZ, maxX, maxY, maxZ)); + return this; + } + + public ShapeBuilder addBox(double minX, double minY, double minZ, + double maxX, double maxY, double maxZ) { + shapes.add(createBox(minX, minY, minZ, maxX, maxY, maxZ)); + return this; + } + + public ShapeBuilder addShape(VoxelShape shape) { + shapes.add(shape); + return this; + } + + public VoxelShape build() { + return combineShapes(shapes); } } -} + + /** + * 创建形状构建器 + */ + public static ShapeBuilder builder() { + return new ShapeBuilder(); + } +} \ No newline at end of file