12 way slope blocks (hitboxes broken now)
This commit is contained in:
parent
aea5fa4e5d
commit
d70997faa0
@ -89,7 +89,8 @@ public class TemplatesClient implements ClientModInitializer {
|
|||||||
provider.addTemplateModel(Templates.id("lever_on_special"), new UnbakedJsonRetexturedModel(Templates.id("block/lever_on")));
|
provider.addTemplateModel(Templates.id("lever_on_special"), new UnbakedJsonRetexturedModel(Templates.id("block/lever_on")));
|
||||||
|
|
||||||
//mesh models
|
//mesh models
|
||||||
provider.addTemplateModel(Templates.id("slope_special"), new UnbakedMeshRetexturedModel(Templates.id("block/slope_base"), SlopeBaseMesh::make));
|
provider.addTemplateModel(Templates.id("slope_special"), new UnbakedMeshRetexturedModel(Templates.id("block/slope_base"), SlopeBaseMesh::makeUpright));
|
||||||
|
provider.addTemplateModel(Templates.id("slope_side_special"), new UnbakedMeshRetexturedModel(Templates.id("block/slope_base"), SlopeBaseMesh::makeSide));
|
||||||
|
|
||||||
//item only models
|
//item only models
|
||||||
provider.addTemplateModel(Templates.id("button_inventory_special"), new UnbakedAutoRetexturedModel(new Identifier("block/button_inventory")));
|
provider.addTemplateModel(Templates.id("button_inventory_special"), new UnbakedAutoRetexturedModel(new Identifier("block/button_inventory")));
|
||||||
|
@ -1,19 +1,15 @@
|
|||||||
package io.github.cottonmc.templates.block;
|
package io.github.cottonmc.templates.block;
|
||||||
|
|
||||||
import com.google.common.base.MoreObjects;
|
import com.google.common.base.MoreObjects;
|
||||||
import io.github.cottonmc.templates.Templates;
|
import io.github.cottonmc.templates.util.EdgeDirection;
|
||||||
import io.github.cottonmc.templates.api.TemplateInteractionUtil;
|
|
||||||
import io.github.cottonmc.templates.util.StairShapeMaker;
|
import io.github.cottonmc.templates.util.StairShapeMaker;
|
||||||
import net.minecraft.block.Block;
|
import net.minecraft.block.Block;
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.block.ShapeContext;
|
import net.minecraft.block.ShapeContext;
|
||||||
import net.minecraft.block.entity.BlockEntity;
|
|
||||||
import net.minecraft.block.enums.BlockHalf;
|
import net.minecraft.block.enums.BlockHalf;
|
||||||
import net.minecraft.item.ItemPlacementContext;
|
import net.minecraft.item.ItemPlacementContext;
|
||||||
import net.minecraft.state.StateManager;
|
import net.minecraft.state.StateManager;
|
||||||
import net.minecraft.state.property.DirectionProperty;
|
|
||||||
import net.minecraft.state.property.EnumProperty;
|
import net.minecraft.state.property.EnumProperty;
|
||||||
import net.minecraft.state.property.Properties;
|
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.util.math.Direction;
|
import net.minecraft.util.math.Direction;
|
||||||
import net.minecraft.util.shape.VoxelShape;
|
import net.minecraft.util.shape.VoxelShape;
|
||||||
@ -22,14 +18,14 @@ import net.minecraft.world.BlockView;
|
|||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
public class TemplateSlopeBlock extends WaterloggableTemplateBlock {
|
public class TemplateSlopeBlock extends WaterloggableTemplateBlock {
|
||||||
public static final DirectionProperty FACING = Properties.HORIZONTAL_FACING;
|
public static final EnumProperty<EdgeDirection> FACING = EnumProperty.of("facing", EdgeDirection.class);
|
||||||
public static final EnumProperty<BlockHalf> HALF = Properties.BLOCK_HALF;
|
|
||||||
|
|
||||||
private static final VoxelShape[] shapes = new VoxelShape[8];
|
private static final VoxelShape[] shapes = new VoxelShape[8];
|
||||||
private static int shapeIndex(Direction dir, BlockHalf half) {
|
private static int shapeIndex(Direction dir, BlockHalf half) {
|
||||||
return dir.getHorizontal() + (half == BlockHalf.TOP ? 4 : 0);
|
return dir.getHorizontal() + (half == BlockHalf.TOP ? 4 : 0);
|
||||||
}
|
}
|
||||||
static {
|
static {
|
||||||
|
//TODO
|
||||||
for(BlockHalf half : BlockHalf.values()) {
|
for(BlockHalf half : BlockHalf.values()) {
|
||||||
for(Direction d : Direction.values()) {
|
for(Direction d : Direction.values()) {
|
||||||
if(d.getHorizontal() == -1) continue;
|
if(d.getHorizontal() == -1) continue;
|
||||||
@ -40,36 +36,37 @@ public class TemplateSlopeBlock extends WaterloggableTemplateBlock {
|
|||||||
|
|
||||||
public TemplateSlopeBlock(Settings settings) {
|
public TemplateSlopeBlock(Settings settings) {
|
||||||
super(settings);
|
super(settings);
|
||||||
setDefaultState(getDefaultState().with(FACING, Direction.NORTH).with(HALF, BlockHalf.BOTTOM));
|
setDefaultState(getDefaultState().with(FACING, EdgeDirection.DOWN_NORTH));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
|
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
|
||||||
super.appendProperties(builder.add(FACING, HALF));
|
super.appendProperties(builder.add(FACING));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public BlockState getPlacementState(ItemPlacementContext ctx) {
|
public BlockState getPlacementState(ItemPlacementContext ctx) {
|
||||||
|
EdgeDirection.guessFromHitResult(ctx.getHitPos(), ctx.getBlockPos());
|
||||||
|
|
||||||
BlockState sup = super.getPlacementState(ctx);
|
BlockState sup = super.getPlacementState(ctx);
|
||||||
if(sup != null) sup = sup
|
if(sup != null) sup = sup.with(FACING, EdgeDirection.guessFromHitResult(ctx.getHitPos(), ctx.getBlockPos()));
|
||||||
.with(FACING, ctx.getHorizontalPlayerFacing())
|
|
||||||
.with(HALF, switch(ctx.getSide()) {
|
|
||||||
case UP -> BlockHalf.BOTTOM;
|
|
||||||
case DOWN -> BlockHalf.TOP;
|
|
||||||
default -> (ctx.getHitPos().getY() - (double) ctx.getBlockPos().getY() < 0.5) ? BlockHalf.BOTTOM : BlockHalf.TOP;
|
|
||||||
});
|
|
||||||
|
|
||||||
return sup;
|
return sup;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public VoxelShape getCollisionShape(BlockState state, BlockView view, BlockPos pos, ShapeContext ctx) {
|
public VoxelShape getCollisionShape(BlockState state, BlockView view, BlockPos pos, ShapeContext ctx) {
|
||||||
return MoreObjects.firstNonNull(super.getCollisionShape(state, view, pos, ctx), shapes[shapeIndex(state.get(FACING), state.get(HALF))]);
|
return MoreObjects.firstNonNull(
|
||||||
|
super.getCollisionShape(state, view, pos, ctx),
|
||||||
|
//shapes[shapeIndex(state.get(FACING_OLD), state.get(HALF_OLD))]
|
||||||
|
shapes[0] //TODO
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public VoxelShape getOutlineShape(BlockState state, BlockView view, BlockPos pos, ShapeContext ctx) {
|
public VoxelShape getOutlineShape(BlockState state, BlockView view, BlockPos pos, ShapeContext ctx) {
|
||||||
return shapes[shapeIndex(state.get(FACING), state.get(HALF))];
|
//return shapes[shapeIndex(state.get(FACING_OLD), state.get(HALF_OLD))];
|
||||||
|
return shapes[0]; //TODO
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -75,8 +75,14 @@ public class MeshTransformUtil {
|
|||||||
quad.pos(i, pos4.x + 0.5f, pos4.y + 0.5f, pos4.z + 0.5f);
|
quad.pos(i, pos4.x + 0.5f, pos4.y + 0.5f, pos4.z + 0.5f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//permute tags
|
||||||
|
int tag = quad.tag();
|
||||||
|
if(tag != 0) quad.tag(facePermutation.get(RetexturingBakedModel.DIRECTIONS[tag - 1]).ordinal() + 1);
|
||||||
|
|
||||||
|
//permute lighting face (?)
|
||||||
quad.nominalFace(facePermutation.get(quad.lightFace()));
|
quad.nominalFace(facePermutation.get(quad.lightFace()));
|
||||||
|
|
||||||
|
//permute cullface
|
||||||
Direction cull = quad.cullFace();
|
Direction cull = quad.cullFace();
|
||||||
if(cull != null) quad.cullFace(facePermutation.get(cull));
|
if(cull != null) quad.cullFace(facePermutation.get(cull));
|
||||||
|
|
||||||
|
@ -5,11 +5,9 @@ import net.fabricmc.fabric.api.renderer.v1.Renderer;
|
|||||||
import net.fabricmc.fabric.api.renderer.v1.mesh.Mesh;
|
import net.fabricmc.fabric.api.renderer.v1.mesh.Mesh;
|
||||||
import net.fabricmc.fabric.api.renderer.v1.mesh.MeshBuilder;
|
import net.fabricmc.fabric.api.renderer.v1.mesh.MeshBuilder;
|
||||||
import net.fabricmc.fabric.api.renderer.v1.mesh.QuadEmitter;
|
import net.fabricmc.fabric.api.renderer.v1.mesh.QuadEmitter;
|
||||||
import net.minecraft.client.texture.Sprite;
|
|
||||||
import net.minecraft.client.util.SpriteIdentifier;
|
|
||||||
import net.minecraft.util.math.Direction;
|
import net.minecraft.util.math.Direction;
|
||||||
|
import net.minecraft.util.math.RotationAxis;
|
||||||
import java.util.function.Function;
|
import org.joml.Matrix4f;
|
||||||
|
|
||||||
public class SlopeBaseMesh {
|
public class SlopeBaseMesh {
|
||||||
/**
|
/**
|
||||||
@ -21,7 +19,7 @@ public class SlopeBaseMesh {
|
|||||||
public static final int TAG_BACK = Direction.SOUTH.ordinal() + 1;
|
public static final int TAG_BACK = Direction.SOUTH.ordinal() + 1;
|
||||||
public static final int TAG_BOTTOM = Direction.DOWN.ordinal() + 1;
|
public static final int TAG_BOTTOM = Direction.DOWN.ordinal() + 1;
|
||||||
|
|
||||||
public static Mesh make() {
|
public static Mesh makeUpright() {
|
||||||
Renderer renderer = TemplatesClient.getFabricRenderer();
|
Renderer renderer = TemplatesClient.getFabricRenderer();
|
||||||
|
|
||||||
MeshBuilder builder = renderer.meshBuilder();
|
MeshBuilder builder = renderer.meshBuilder();
|
||||||
@ -56,4 +54,11 @@ public class SlopeBaseMesh {
|
|||||||
.emit();
|
.emit();
|
||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Mesh makeSide() {
|
||||||
|
Matrix4f mat = new Matrix4f();
|
||||||
|
RotationAxis.POSITIVE_Z.rotationDegrees(90).get(mat);
|
||||||
|
|
||||||
|
return MeshTransformUtil.pretransformMesh(makeUpright(), MeshTransformUtil.applyMatrix(mat));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,94 @@
|
|||||||
|
package io.github.cottonmc.templates.util;
|
||||||
|
|
||||||
|
import it.unimi.dsi.fastutil.bytes.Byte2ObjectMap;
|
||||||
|
import it.unimi.dsi.fastutil.bytes.Byte2ObjectOpenHashMap;
|
||||||
|
import net.minecraft.util.StringIdentifiable;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
public enum EdgeDirection implements StringIdentifiable {
|
||||||
|
DOWN_NORTH(AxisRelation.PARALLEL, AxisRelation.LOW_SIDE, AxisRelation.LOW_SIDE),
|
||||||
|
DOWN_SOUTH(AxisRelation.PARALLEL, AxisRelation.LOW_SIDE, AxisRelation.HIGH_SIDE),
|
||||||
|
UP_SOUTH(AxisRelation.PARALLEL, AxisRelation.HIGH_SIDE, AxisRelation.HIGH_SIDE),
|
||||||
|
UP_NORTH(AxisRelation.PARALLEL, AxisRelation.HIGH_SIDE, AxisRelation.LOW_SIDE),
|
||||||
|
NORTH_WEST(AxisRelation.LOW_SIDE, AxisRelation.PARALLEL, AxisRelation.LOW_SIDE),
|
||||||
|
SOUTH_WEST(AxisRelation.LOW_SIDE, AxisRelation.PARALLEL, AxisRelation.HIGH_SIDE),
|
||||||
|
SOUTH_EAST(AxisRelation.HIGH_SIDE, AxisRelation.PARALLEL, AxisRelation.HIGH_SIDE),
|
||||||
|
NORTH_EAST(AxisRelation.HIGH_SIDE, AxisRelation.PARALLEL, AxisRelation.LOW_SIDE),
|
||||||
|
DOWN_WEST(AxisRelation.LOW_SIDE, AxisRelation.LOW_SIDE, AxisRelation.PARALLEL),
|
||||||
|
UP_WEST(AxisRelation.LOW_SIDE, AxisRelation.HIGH_SIDE, AxisRelation.PARALLEL),
|
||||||
|
UP_EAST(AxisRelation.HIGH_SIDE, AxisRelation.HIGH_SIDE, AxisRelation.PARALLEL),
|
||||||
|
DOWN_EAST(AxisRelation.HIGH_SIDE, AxisRelation.LOW_SIDE, AxisRelation.PARALLEL),
|
||||||
|
;
|
||||||
|
|
||||||
|
EdgeDirection(AxisRelation x, AxisRelation y, AxisRelation z) {
|
||||||
|
this.key = key(x, y, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final byte key;
|
||||||
|
|
||||||
|
private static final Byte2ObjectMap<EdgeDirection> LOOKUP = new Byte2ObjectOpenHashMap<>();
|
||||||
|
static { for(EdgeDirection e : values()) LOOKUP.put(e.key, e); }
|
||||||
|
|
||||||
|
private static byte key(AxisRelation x, AxisRelation y, AxisRelation z) {
|
||||||
|
return (byte) (x.ordinal() + 1 << 4 | y.ordinal() + 1 << 2 | z.ordinal() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static EdgeDirection guessFromHitResult(Vec3d precise, BlockPos coarse) {
|
||||||
|
double dx = precise.x - coarse.getX();
|
||||||
|
double dy = precise.y - coarse.getY();
|
||||||
|
double dz = precise.z - coarse.getZ();
|
||||||
|
|
||||||
|
//distances your click was from the 6 faces of the block (each 0..1)
|
||||||
|
float distToLowX = (float) (dx);
|
||||||
|
float distToHighX = (float) (1 - dx);
|
||||||
|
float distToLowY = (float) (dy);
|
||||||
|
float distToHighY = (float) (1 - dy);
|
||||||
|
float distToLowZ = (float) (dz);
|
||||||
|
float distToHighZ = (float) (1 - dz);
|
||||||
|
|
||||||
|
//distances your click was from either pair of edges (each 0..0.5)
|
||||||
|
float distToAnyX = Math.min(distToLowX, distToHighX);
|
||||||
|
float distToAnyY = Math.min(distToLowY, distToHighY);
|
||||||
|
float distToAnyZ = Math.min(distToLowZ, distToHighZ);
|
||||||
|
|
||||||
|
//figure out which two differences are the smallest
|
||||||
|
AxisRelation clickX, clickY, clickZ;
|
||||||
|
if((distToAnyX < distToAnyZ) && (distToAnyY < distToAnyZ)) {
|
||||||
|
clickX = lowOrHigh(distToLowX);
|
||||||
|
clickY = lowOrHigh(distToLowY);
|
||||||
|
clickZ = AxisRelation.PARALLEL;
|
||||||
|
} else if((distToAnyX < distToAnyY) && (distToAnyZ < distToAnyY)) {
|
||||||
|
clickX = lowOrHigh(distToLowX);
|
||||||
|
clickY = AxisRelation.PARALLEL;
|
||||||
|
clickZ = lowOrHigh(distToLowZ);
|
||||||
|
} else {
|
||||||
|
clickX = AxisRelation.PARALLEL;
|
||||||
|
clickY = lowOrHigh(distToLowY);
|
||||||
|
clickZ = lowOrHigh(distToLowZ);
|
||||||
|
}
|
||||||
|
|
||||||
|
return LOOKUP.getOrDefault(key(clickX, clickY, clickZ), DOWN_SOUTH);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String asString() {
|
||||||
|
return name().toLowerCase(Locale.ROOT);
|
||||||
|
}
|
||||||
|
|
||||||
|
//if you imagine moving along this edge, your coordinates:
|
||||||
|
public enum AxisRelation {
|
||||||
|
//change along this axis
|
||||||
|
PARALLEL,
|
||||||
|
//stay fixed along this axis, with the coordinate being the more negative possibility
|
||||||
|
LOW_SIDE,
|
||||||
|
//stay fixed along this axis, with the coordinate being the more positive possibility
|
||||||
|
HIGH_SIDE
|
||||||
|
}
|
||||||
|
|
||||||
|
private static AxisRelation lowOrHigh(float distToLow) {
|
||||||
|
return (distToLow < 0.5f) ? AxisRelation.LOW_SIDE : AxisRelation.HIGH_SIDE;
|
||||||
|
}
|
||||||
|
}
|
@ -1,45 +1,64 @@
|
|||||||
{
|
{
|
||||||
"variants": {
|
"variants": {
|
||||||
"facing=east,half=bottom": {
|
"facing=down_east": {
|
||||||
"model": "templates:slope_special",
|
"model": "templates:slope_special",
|
||||||
"uvlock": true,
|
"uvlock": true,
|
||||||
"y": 270
|
"y": 270
|
||||||
},
|
},
|
||||||
"facing=north,half=bottom": {
|
"facing=down_north": {
|
||||||
"model": "templates:slope_special",
|
"model": "templates:slope_special",
|
||||||
"uvlock": true,
|
"uvlock": true,
|
||||||
"y": 180
|
"y": 180
|
||||||
},
|
},
|
||||||
"facing=south,half=bottom": {
|
"facing=down_south": {
|
||||||
"model": "templates:slope_special"
|
"model": "templates:slope_special"
|
||||||
},
|
},
|
||||||
"facing=west,half=bottom": {
|
"facing=down_west": {
|
||||||
"model": "templates:slope_special",
|
"model": "templates:slope_special",
|
||||||
"uvlock": true,
|
"uvlock": true,
|
||||||
"y": 90
|
"y": 90
|
||||||
},
|
},
|
||||||
"facing=east,half=top": {
|
"facing=up_east": {
|
||||||
"model": "templates:slope_special",
|
"model": "templates:slope_special",
|
||||||
"uvlock": true,
|
"uvlock": true,
|
||||||
"x": 180,
|
"x": 180,
|
||||||
"y": 90
|
"y": 90
|
||||||
},
|
},
|
||||||
"facing=north,half=top": {
|
"facing=up_north": {
|
||||||
"model": "templates:slope_special",
|
"model": "templates:slope_special",
|
||||||
"uvlock": true,
|
"uvlock": true,
|
||||||
"x": 180
|
"x": 180
|
||||||
},
|
},
|
||||||
"facing=south,half=top": {
|
"facing=up_south": {
|
||||||
"model": "templates:slope_special",
|
"model": "templates:slope_special",
|
||||||
"uvlock": true,
|
"uvlock": true,
|
||||||
"x": 180,
|
"x": 180,
|
||||||
"y": 180
|
"y": 180
|
||||||
},
|
},
|
||||||
"facing=west,half=top": {
|
"facing=up_west": {
|
||||||
"model": "templates:slope_special",
|
"model": "templates:slope_special",
|
||||||
"uvlock": true,
|
"uvlock": true,
|
||||||
"x": 180,
|
"x": 180,
|
||||||
"y": 270
|
"y": 270
|
||||||
|
},
|
||||||
|
"facing=north_east": {
|
||||||
|
"model": "templates:slope_side_special",
|
||||||
|
"uvlock": true,
|
||||||
|
"y": 270
|
||||||
|
},
|
||||||
|
"facing=north_west": {
|
||||||
|
"model": "templates:slope_side_special",
|
||||||
|
"uvlock": true,
|
||||||
|
"y": 180
|
||||||
|
},
|
||||||
|
"facing=south_east": {
|
||||||
|
"model": "templates:slope_side_special",
|
||||||
|
"uvlock": true
|
||||||
|
},
|
||||||
|
"facing=south_west": {
|
||||||
|
"model": "templates:slope_side_special",
|
||||||
|
"uvlock": true,
|
||||||
|
"y": 90
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user