Implemented SegmentableBlock as is in 1.21.5, including all needed misc classes etc.
This commit is contained in:
@ -0,0 +1,57 @@
|
|||||||
|
package dev.micle.wildflowers_backport.block;
|
||||||
|
|
||||||
|
import dev.micle.wildflowers_backport.block.state.properties.ModBlockStateProperties;
|
||||||
|
import dev.micle.wildflowers_backport.util.ShapesUtils;
|
||||||
|
import dev.micle.wildflowers_backport.util.VoxelShapeUtils;
|
||||||
|
import net.minecraft.core.Direction;
|
||||||
|
import net.minecraft.world.item.context.BlockPlaceContext;
|
||||||
|
import net.minecraft.world.level.block.Block;
|
||||||
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
import net.minecraft.world.level.block.state.properties.EnumProperty;
|
||||||
|
import net.minecraft.world.level.block.state.properties.IntegerProperty;
|
||||||
|
import net.minecraft.world.phys.shapes.Shapes;
|
||||||
|
import net.minecraft.world.phys.shapes.VoxelShape;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
public interface SegmentableBlock {
|
||||||
|
int MIN_SEGMENT = 1;
|
||||||
|
int MAX_SEGMENT = 4;
|
||||||
|
IntegerProperty AMOUNT = ModBlockStateProperties.SEGMENT_AMOUNT;
|
||||||
|
|
||||||
|
default Function<BlockState, VoxelShape> getShapeCalculator(EnumProperty<Direction> dir, IntegerProperty property) {
|
||||||
|
Map<Direction, VoxelShape> map = ShapesUtils.rotateHorizontal(Block.box(0.0, 0.0, 0.0, 8.0, this.getShapeHeight(), 8.0));
|
||||||
|
return x -> {
|
||||||
|
VoxelShape voxelShape = Shapes.empty();
|
||||||
|
Direction direction = x.getValue(dir);
|
||||||
|
int i = x.getValue(property);
|
||||||
|
|
||||||
|
for (int j = 0; j < i; j++) {
|
||||||
|
voxelShape = Shapes.or(voxelShape, map.get(direction));
|
||||||
|
direction = direction.getCounterClockWise();
|
||||||
|
}
|
||||||
|
|
||||||
|
return VoxelShapeUtils.singleEncompassing(voxelShape);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
default IntegerProperty getSegmentAmountProperty() {
|
||||||
|
return AMOUNT;
|
||||||
|
}
|
||||||
|
|
||||||
|
default double getShapeHeight() {
|
||||||
|
return 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
default boolean canBeReplaced(BlockState blockState, BlockPlaceContext blockPlaceContext, IntegerProperty property) {
|
||||||
|
return !blockPlaceContext.isSecondaryUseActive() && blockPlaceContext.getItemInHand().is(blockState.getBlock().asItem()) && blockState.getValue(property) < 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
default BlockState getStateForPlacement(BlockPlaceContext blockPlaceContext, Block block, IntegerProperty property, EnumProperty<Direction> dir) {
|
||||||
|
BlockState blockState = blockPlaceContext.getLevel().getBlockState(blockPlaceContext.getClickedPos());
|
||||||
|
return blockState.is(block)
|
||||||
|
? blockState.setValue(property, Math.min(4, blockState.getValue(property) + 1))
|
||||||
|
: block.defaultBlockState().setValue(dir, blockPlaceContext.getHorizontalDirection().getOpposite());
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
package dev.micle.wildflowers_backport.block.state.properties;
|
||||||
|
|
||||||
|
import net.minecraft.world.level.block.state.properties.IntegerProperty;
|
||||||
|
|
||||||
|
public class ModBlockStateProperties {
|
||||||
|
public static final IntegerProperty SEGMENT_AMOUNT = IntegerProperty.create("segment_amount", 1, 4);
|
||||||
|
}
|
||||||
@ -0,0 +1,34 @@
|
|||||||
|
package dev.micle.wildflowers_backport.math;
|
||||||
|
|
||||||
|
import com.mojang.serialization.Codec;
|
||||||
|
import com.mojang.serialization.DataResult;
|
||||||
|
import net.minecraft.util.Mth;
|
||||||
|
|
||||||
|
public enum Quadrant {
|
||||||
|
R0(0),
|
||||||
|
R90(1),
|
||||||
|
R180(2),
|
||||||
|
R270(3);
|
||||||
|
|
||||||
|
public static final Codec<Quadrant> CODEC = Codec.INT.comapFlatMap(x -> {
|
||||||
|
return switch (Mth.positiveModulo(x, 360)) {
|
||||||
|
case 0 -> DataResult.success(R0);
|
||||||
|
case 90 -> DataResult.success(R90);
|
||||||
|
case 180 -> DataResult.success(R180);
|
||||||
|
case 270 -> DataResult.success(R270);
|
||||||
|
default -> DataResult.error(() -> "Invalid rotation " + x + " found, only 0/90/180/270 allowed");
|
||||||
|
};
|
||||||
|
}, y -> {
|
||||||
|
return switch (y) {
|
||||||
|
case R0 -> 0;
|
||||||
|
case R90 -> 90;
|
||||||
|
case R180 -> 180;
|
||||||
|
case R270 -> 270;
|
||||||
|
};
|
||||||
|
});
|
||||||
|
public final int shift;
|
||||||
|
|
||||||
|
Quadrant(final int shift) {
|
||||||
|
this.shift = shift;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,15 @@
|
|||||||
|
package dev.micle.wildflowers_backport.mixin;
|
||||||
|
|
||||||
|
import it.unimi.dsi.fastutil.doubles.DoubleList;
|
||||||
|
import net.minecraft.world.phys.shapes.ArrayVoxelShape;
|
||||||
|
import net.minecraft.world.phys.shapes.DiscreteVoxelShape;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.gen.Invoker;
|
||||||
|
|
||||||
|
@Mixin(ArrayVoxelShape.class)
|
||||||
|
public interface ArrayVoxelShapeAccessor {
|
||||||
|
@Invoker("<init>")
|
||||||
|
static ArrayVoxelShape newArrayVoxelShape(DiscreteVoxelShape pShape, DoubleList pXs, DoubleList pYs, DoubleList pZs) {
|
||||||
|
throw new AssertionError();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
package dev.micle.wildflowers_backport.mixin;
|
||||||
|
|
||||||
|
import net.minecraft.world.phys.shapes.CubeVoxelShape;
|
||||||
|
import net.minecraft.world.phys.shapes.DiscreteVoxelShape;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.gen.Invoker;
|
||||||
|
|
||||||
|
@Mixin(CubeVoxelShape.class)
|
||||||
|
public interface CubeVoxelShapeAccessor {
|
||||||
|
@Invoker("<init>")
|
||||||
|
static CubeVoxelShape newCubeVoxelShape(DiscreteVoxelShape pShape) {
|
||||||
|
throw new AssertionError();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
package dev.micle.wildflowers_backport.mixin;
|
||||||
|
|
||||||
|
import com.mojang.math.OctahedralGroup;
|
||||||
|
import com.mojang.math.SymmetricGroup3;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||||
|
|
||||||
|
@Mixin(OctahedralGroup.class)
|
||||||
|
public interface OctahedralGroupAccessor {
|
||||||
|
@Accessor("permutation")
|
||||||
|
SymmetricGroup3 wildflowers_backport$getPermutation();
|
||||||
|
}
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
package dev.micle.wildflowers_backport.mixin;
|
||||||
|
|
||||||
|
import it.unimi.dsi.fastutil.doubles.DoubleList;
|
||||||
|
import net.minecraft.core.Direction;
|
||||||
|
import net.minecraft.world.phys.shapes.DiscreteVoxelShape;
|
||||||
|
import net.minecraft.world.phys.shapes.VoxelShape;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||||
|
import org.spongepowered.asm.mixin.gen.Invoker;
|
||||||
|
|
||||||
|
@Mixin(VoxelShape.class)
|
||||||
|
public interface VoxelShapeAccessor {
|
||||||
|
@Accessor("shape")
|
||||||
|
DiscreteVoxelShape wildflowers_backport$getShape();
|
||||||
|
|
||||||
|
@Invoker("getCoords")
|
||||||
|
DoubleList wildflowers_backport$getCoords(Direction.Axis pAxis);
|
||||||
|
}
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
package dev.micle.wildflowers_backport.util;
|
||||||
|
|
||||||
|
import net.minecraft.core.Direction;
|
||||||
|
|
||||||
|
public class DirectionAxisUtils {
|
||||||
|
public static boolean choose(Direction.Axis axis, boolean x, boolean y, boolean z) {
|
||||||
|
return switch (axis) {
|
||||||
|
case X -> x;
|
||||||
|
case Y -> y;
|
||||||
|
case Z -> z;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,37 @@
|
|||||||
|
package dev.micle.wildflowers_backport.util;
|
||||||
|
|
||||||
|
import com.mojang.math.OctahedralGroup;
|
||||||
|
import dev.micle.wildflowers_backport.math.Quadrant;
|
||||||
|
import dev.micle.wildflowers_backport.mixin.OctahedralGroupAccessor;
|
||||||
|
import net.minecraft.Util;
|
||||||
|
import net.minecraft.core.Direction;
|
||||||
|
|
||||||
|
public class OctahedralGroupUtils {
|
||||||
|
private static final Direction.Axis[] AXES = Direction.Axis.values();
|
||||||
|
private static final OctahedralGroup[][] XY_TABLE = Util.make(new OctahedralGroup[Quadrant.values().length][Quadrant.values().length], x -> {
|
||||||
|
for (Quadrant quadrant : Quadrant.values()) {
|
||||||
|
for (Quadrant quadrant1 : Quadrant.values()) {
|
||||||
|
OctahedralGroup octahedralGroup = OctahedralGroup.IDENTITY;
|
||||||
|
|
||||||
|
for (int i = 0; i < quadrant1.shift; i++) {
|
||||||
|
octahedralGroup = octahedralGroup.compose(OctahedralGroup.ROT_90_Y_NEG);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int j = 0; j < quadrant.shift; j++) {
|
||||||
|
octahedralGroup = octahedralGroup.compose(OctahedralGroup.ROT_90_X_NEG);
|
||||||
|
}
|
||||||
|
|
||||||
|
x[quadrant.ordinal()][quadrant1.ordinal()] = octahedralGroup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
public static Direction.Axis permute(OctahedralGroup octahedralGroup, Direction.Axis axis) {
|
||||||
|
return AXES[((OctahedralGroupAccessor) (Object) octahedralGroup).wildflowers_backport$getPermutation().permutation(axis.ordinal())];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static OctahedralGroup fromXYAngles(Quadrant quadrant, Quadrant quadrant1) {
|
||||||
|
return XY_TABLE[quadrant.ordinal()][quadrant1.ordinal()];
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,93 @@
|
|||||||
|
package dev.micle.wildflowers_backport.util;
|
||||||
|
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
import com.mojang.math.OctahedralGroup;
|
||||||
|
import dev.micle.wildflowers_backport.math.Quadrant;
|
||||||
|
import dev.micle.wildflowers_backport.mixin.ArrayVoxelShapeAccessor;
|
||||||
|
import dev.micle.wildflowers_backport.mixin.CubeVoxelShapeAccessor;
|
||||||
|
import dev.micle.wildflowers_backport.mixin.VoxelShapeAccessor;
|
||||||
|
import it.unimi.dsi.fastutil.doubles.DoubleArrayList;
|
||||||
|
import it.unimi.dsi.fastutil.doubles.DoubleList;
|
||||||
|
import net.minecraft.core.Direction;
|
||||||
|
import net.minecraft.world.phys.Vec3;
|
||||||
|
import net.minecraft.world.phys.shapes.CubeVoxelShape;
|
||||||
|
import net.minecraft.world.phys.shapes.DiscreteVoxelShape;
|
||||||
|
import net.minecraft.world.phys.shapes.VoxelShape;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class ShapesUtils {
|
||||||
|
private static final Vec3 BLOCK_CENTER = new Vec3(0.5, 0.5, 0.5);
|
||||||
|
|
||||||
|
public static VoxelShape rotate(VoxelShape voxelShape, OctahedralGroup octahedralGroup) {
|
||||||
|
return rotate(voxelShape, octahedralGroup, BLOCK_CENTER);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static VoxelShape rotate(VoxelShape voxelShape, OctahedralGroup octahedralGroup, Vec3 vec3) {
|
||||||
|
if (octahedralGroup == OctahedralGroup.IDENTITY) {
|
||||||
|
return voxelShape;
|
||||||
|
} else {
|
||||||
|
DiscreteVoxelShape discreteVoxelShape = ((VoxelShapeAccessor) voxelShape).wildflowers_backport$getShape();
|
||||||
|
if (voxelShape instanceof CubeVoxelShape && BLOCK_CENTER.equals(vec3)) {
|
||||||
|
return CubeVoxelShapeAccessor.newCubeVoxelShape(discreteVoxelShape);
|
||||||
|
} else {
|
||||||
|
Direction.Axis direction$axis = OctahedralGroupUtils.permute(octahedralGroup, Direction.Axis.X);
|
||||||
|
Direction.Axis direction$axis1 = OctahedralGroupUtils.permute(octahedralGroup, Direction.Axis.Y);
|
||||||
|
Direction.Axis direction$axis2 = OctahedralGroupUtils.permute(octahedralGroup, Direction.Axis.Z);
|
||||||
|
|
||||||
|
DoubleList doubleList = ((VoxelShapeAccessor) voxelShape).wildflowers_backport$getCoords(direction$axis);
|
||||||
|
DoubleList doubleList1 = ((VoxelShapeAccessor) voxelShape).wildflowers_backport$getCoords(direction$axis1);
|
||||||
|
DoubleList doubleList2 = ((VoxelShapeAccessor) voxelShape).wildflowers_backport$getCoords(direction$axis2);
|
||||||
|
|
||||||
|
boolean flag = octahedralGroup.inverts(direction$axis);
|
||||||
|
boolean flag1 = octahedralGroup.inverts(direction$axis1);
|
||||||
|
boolean flag2 = octahedralGroup.inverts(direction$axis2);
|
||||||
|
boolean flag3 = DirectionAxisUtils.choose(direction$axis, flag, flag1, flag2);
|
||||||
|
boolean flag4 = DirectionAxisUtils.choose(direction$axis1, flag, flag1, flag2);
|
||||||
|
boolean flag5 = DirectionAxisUtils.choose(direction$axis2, flag, flag1, flag2);
|
||||||
|
|
||||||
|
return ArrayVoxelShapeAccessor.newArrayVoxelShape(
|
||||||
|
discreteVoxelShape,
|
||||||
|
makeAxis(doubleList, flag3, vec3.get(direction$axis), vec3.x),
|
||||||
|
makeAxis(doubleList1, flag4, vec3.get(direction$axis1), vec3.y),
|
||||||
|
makeAxis(doubleList2, flag5, vec3.get(direction$axis2), vec3.z)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Map<Direction, VoxelShape> rotateHorizontal(VoxelShape voxelShape) {
|
||||||
|
return rotateHorizontal(voxelShape, BLOCK_CENTER);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Map<Direction, VoxelShape> rotateHorizontal(VoxelShape voxelShape, Vec3 vec3) {
|
||||||
|
return Maps.newEnumMap(
|
||||||
|
Map.of(
|
||||||
|
Direction.NORTH,
|
||||||
|
voxelShape,
|
||||||
|
Direction.EAST,
|
||||||
|
rotate(voxelShape, OctahedralGroupUtils.fromXYAngles(Quadrant.R0, Quadrant.R90), vec3),
|
||||||
|
Direction.SOUTH,
|
||||||
|
rotate(voxelShape, OctahedralGroupUtils.fromXYAngles(Quadrant.R0, Quadrant.R180), vec3),
|
||||||
|
Direction.WEST,
|
||||||
|
rotate(voxelShape, OctahedralGroupUtils.fromXYAngles(Quadrant.R0, Quadrant.R270), vec3)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DoubleList makeAxis(DoubleList doubleList, boolean flag, double d1, double d2) {
|
||||||
|
if (!flag && d1 == d2) {
|
||||||
|
return doubleList;
|
||||||
|
} else {
|
||||||
|
int i = doubleList.size();
|
||||||
|
DoubleList doubleList1 = new DoubleArrayList(i);
|
||||||
|
int j = flag ? -1 : 1;
|
||||||
|
|
||||||
|
for (int k = flag ? i - 1 : 0; k >= 0 && k < i; k += j) {
|
||||||
|
doubleList1.add(d2 + j * (doubleList.getDouble(k) - d1));
|
||||||
|
}
|
||||||
|
|
||||||
|
return doubleList1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,20 @@
|
|||||||
|
package dev.micle.wildflowers_backport.util;
|
||||||
|
|
||||||
|
import net.minecraft.core.Direction;
|
||||||
|
import net.minecraft.world.phys.shapes.Shapes;
|
||||||
|
import net.minecraft.world.phys.shapes.VoxelShape;
|
||||||
|
|
||||||
|
public class VoxelShapeUtils {
|
||||||
|
public static VoxelShape singleEncompassing(VoxelShape voxelShape) {
|
||||||
|
return voxelShape.isEmpty()
|
||||||
|
? Shapes.empty()
|
||||||
|
: Shapes.box(
|
||||||
|
voxelShape.min(Direction.Axis.X),
|
||||||
|
voxelShape.min(Direction.Axis.Y),
|
||||||
|
voxelShape.min(Direction.Axis.Z),
|
||||||
|
voxelShape.min(Direction.Axis.X),
|
||||||
|
voxelShape.min(Direction.Axis.Y),
|
||||||
|
voxelShape.min(Direction.Axis.Z)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -5,6 +5,10 @@
|
|||||||
"compatibilityLevel": "JAVA_8",
|
"compatibilityLevel": "JAVA_8",
|
||||||
"refmap": "firefly_bush_backport.refmap.json",
|
"refmap": "firefly_bush_backport.refmap.json",
|
||||||
"mixins": [
|
"mixins": [
|
||||||
|
"OctahedralGroupAccessor",
|
||||||
|
"VoxelShapeAccessor",
|
||||||
|
"ArrayVoxelShapeAccessor",
|
||||||
|
"CubeVoxelShapeAccessor"
|
||||||
],
|
],
|
||||||
"client": [
|
"client": [
|
||||||
],
|
],
|
||||||
|
|||||||
Reference in New Issue
Block a user