Skip to content

Commit

Permalink
Use VoxelShape arrays instead of Byte2ObjectMaps for block shape caches
Browse files Browse the repository at this point in the history
  • Loading branch information
Juuxel committed Aug 19, 2024
1 parent 302413f commit ec919fa
Show file tree
Hide file tree
Showing 5 changed files with 30 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -78,11 +78,11 @@ public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos po
);
}

protected static byte getShapeKey(boolean north, boolean east, boolean south, boolean west, boolean hasCarpet) {
return (byte) ((north ? 1 : 0) << 4 | (east ? 1 : 0) << 3 | (south ? 1 : 0) << 2 | (west ? 1 : 0) << 1 | (hasCarpet ? 1 : 0));
protected static int getShapeKey(boolean north, boolean east, boolean south, boolean west, boolean hasCarpet) {
return (north ? 1 : 0) << 4 | (east ? 1 : 0) << 3 | (south ? 1 : 0) << 2 | (west ? 1 : 0) << 1 | (hasCarpet ? 1 : 0);
}

protected abstract VoxelShape getShapeForKey(byte key);
protected abstract VoxelShape getShapeForKey(int key);

@Override
public boolean canPathfindThrough(BlockState state, NavigationType type) {
Expand Down
14 changes: 6 additions & 8 deletions common/src/main/java/juuxel/adorn/block/BenchBlock.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package juuxel.adorn.block;

import it.unimi.dsi.fastutil.bytes.Byte2ObjectArrayMap;
import it.unimi.dsi.fastutil.bytes.Byte2ObjectMap;
import juuxel.adorn.block.variant.BlockVariant;
import juuxel.adorn.lib.AdornStats;
import juuxel.adorn.util.AdornUtil;
Expand Down Expand Up @@ -38,7 +36,7 @@ public final class BenchBlock extends SeatBlock implements Waterloggable, BlockW
private static final String DESCRIPTION_KEY = "block.adorn.bench.description";
private static final VoxelShape X_TOP_SHAPE = createCuboidShape(0.0, 8.0, 1.0, 16.0, 10.0, 15.0);
private static final VoxelShape Z_TOP_SHAPE = createCuboidShape(1.0, 8.0, 0.0, 15.0, 10.0, 16.0);
private static final Byte2ObjectMap<VoxelShape> SHAPES = new Byte2ObjectArrayMap<>();
private static final VoxelShape[] SHAPES = new VoxelShape[8];

static {
var legShapes = Shapes.buildShapeRotationsFromNorth(2, 0, 2, 14, 8, 4);
Expand All @@ -61,8 +59,8 @@ public final class BenchBlock extends SeatBlock implements Waterloggable, BlockW
parts.add(positiveLeg);
}

var key = getShapeKey(axis, connectedN, connectedP);
SHAPES.put(key, VoxelShapes.union(topShape, parts.toArray(VoxelShape[]::new)));
int key = getShapeKey(axis, connectedN, connectedP);
SHAPES[key] = VoxelShapes.union(topShape, parts.toArray(VoxelShape[]::new));
}
}
}
Expand Down Expand Up @@ -106,11 +104,11 @@ private BlockState updateConnections(BlockView world, BlockPos pos, BlockState s

@Override
public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
return SHAPES.get(getShapeKey(state.get(AXIS), state.get(CONNECTED_N), state.get(CONNECTED_P)));
return SHAPES[getShapeKey(state.get(AXIS), state.get(CONNECTED_N), state.get(CONNECTED_P))];
}

private static byte getShapeKey(Direction.Axis axis, boolean connectedN, boolean connectedP) {
return (byte) ((axis == Direction.Axis.X ? 1 : 0) << 2 | (connectedN ? 1 : 0) << 1 | (connectedP ? 1 : 0));
private static int getShapeKey(Direction.Axis axis, boolean connectedN, boolean connectedP) {
return (axis == Direction.Axis.X ? 1 : 0) << 2 | (connectedN ? 1 : 0) << 1 | (connectedP ? 1 : 0);
}

@Override
Expand Down
12 changes: 5 additions & 7 deletions common/src/main/java/juuxel/adorn/block/CopperPipeBlock.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package juuxel.adorn.block;

import it.unimi.dsi.fastutil.bytes.Byte2ObjectMap;
import it.unimi.dsi.fastutil.bytes.Byte2ObjectOpenHashMap;
import juuxel.adorn.lib.AdornTags;
import juuxel.adorn.util.Shapes;
import net.minecraft.block.Block;
Expand Down Expand Up @@ -35,7 +33,7 @@ public class CopperPipeBlock extends Block implements Waterloggable, BlockWithDe
public static final BooleanProperty WATERLOGGED = Properties.WATERLOGGED;

private static final String DESCRIPTION_KEY = "block.adorn.copper_pipe.description";
private static final Byte2ObjectMap<VoxelShape> SHAPES = new Byte2ObjectOpenHashMap<>();
private static final VoxelShape[] SHAPES = new VoxelShape[64];

static {
var center = createCuboidShape(6.0, 6.0, 6.0, 10.0, 10.0, 10.0);
Expand Down Expand Up @@ -92,7 +90,7 @@ public class CopperPipeBlock extends Block implements Waterloggable, BlockWithDe
if (up) shape = VoxelShapes.union(shape, pipes.get(Direction.UP));
if (down) shape = VoxelShapes.union(shape, pipes.get(Direction.DOWN));

SHAPES.put(getShapeKey(north, east, south, west, up, down), shape);
SHAPES[getShapeKey(north, east, south, west, up, down)] = shape;
}
}
}
Expand All @@ -112,18 +110,18 @@ public String getDescriptionKey() {

@Override
public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
return SHAPES.get(getShapeKey(state.get(NORTH), state.get(EAST), state.get(SOUTH), state.get(WEST), state.get(UP), state.get(DOWN)));
return SHAPES[getShapeKey(state.get(NORTH), state.get(EAST), state.get(SOUTH), state.get(WEST), state.get(UP), state.get(DOWN))];
}

private static byte getShapeKey(boolean north, boolean east, boolean south, boolean west, boolean up, boolean down) {
private static int getShapeKey(boolean north, boolean east, boolean south, boolean west, boolean up, boolean down) {
int northB = north ? 1 : 0;
int eastB = east ? 1 : 0;
int southB = south ? 1 : 0;
int westB = west ? 1 : 0;
int upB = up ? 1 : 0;
int downB = down ? 1 : 0;

return (byte) (northB << 5 | eastB << 4 | southB << 3 | westB << 2 | upB << 1 | downB);
return northB << 5 | eastB << 4 | southB << 3 | westB << 2 | upB << 1 | downB;
}

@Override
Expand Down
26 changes: 12 additions & 14 deletions common/src/main/java/juuxel/adorn/block/SofaBlock.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package juuxel.adorn.block;

import it.unimi.dsi.fastutil.bytes.Byte2ObjectMap;
import it.unimi.dsi.fastutil.bytes.Byte2ObjectOpenHashMap;
import juuxel.adorn.block.property.FrontConnection;
import juuxel.adorn.block.variant.BlockVariant;
import juuxel.adorn.lib.AdornStats;
Expand Down Expand Up @@ -52,8 +50,8 @@ public class SofaBlock extends SeatBlock implements Waterloggable, SneakClickHan
public static final EnumProperty<FrontConnection> FRONT_CONNECTION = EnumProperty.of("front", FrontConnection.class);
public static final BooleanProperty WATERLOGGED = Properties.WATERLOGGED;

private static final Byte2ObjectMap<VoxelShape> OUTLINE_SHAPE_MAP = buildShapeMap(false);
private static final Byte2ObjectMap<VoxelShape> COLLISION_SHAPE_MAP = buildShapeMap(true);
private static final VoxelShape[] OUTLINE_SHAPES = buildShapes(false);
private static final VoxelShape[] COLLISION_SHAPES = buildShapes(true);
private static final String DESCRIPTION_KEY = "block.adorn.sofa.description";

public SofaBlock(BlockVariant variant) {
Expand Down Expand Up @@ -168,26 +166,26 @@ private BlockState updateConnections(BlockState state, WorldAccess world, BlockP

@Override
public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
return OUTLINE_SHAPE_MAP.get(
return OUTLINE_SHAPES[
getShapeKey(
state.get(FACING),
state.get(CONNECTED_LEFT),
state.get(CONNECTED_RIGHT),
state.get(FRONT_CONNECTION)
)
);
];
}

@Override
public VoxelShape getCollisionShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
return COLLISION_SHAPE_MAP.get(
return COLLISION_SHAPES[
getShapeKey(
state.get(FACING),
state.get(CONNECTED_LEFT),
state.get(CONNECTED_RIGHT),
state.get(FRONT_CONNECTION)
)
);
];
}

@Override
Expand All @@ -210,7 +208,7 @@ public double getSittingOffset(World world, BlockState state, BlockPos pos) {
return 0.4375; // 7/16
}

private static Byte2ObjectMap<VoxelShape> buildShapeMap(boolean thin) {
private static VoxelShape[] buildShapes(boolean thin) {
var bottom = createCuboidShape(0.0, 2.0, 0.0, 16.0, 7.0, 16.0);
var leftArms = Shapes.buildShapeRotations(5, 7, 13, 16, 13, 16);
var rightArms = Shapes.buildShapeRotations(5, 7, 0, 16, 13, 3);
Expand All @@ -220,7 +218,7 @@ private static Byte2ObjectMap<VoxelShape> buildShapeMap(boolean thin) {
var leftCorners = Shapes.buildShapeRotations(5, 7, 11, 16, 16, 16);
var rightCorners = Shapes.buildShapeRotations(5, 7, 0, 16, 16, 5);
var booleans = new boolean[] { true, false };
Byte2ObjectMap<VoxelShape> result = new Byte2ObjectOpenHashMap<>();
var result = new VoxelShape[48];
for (var facing : FACING.getValues()) {
for (var left : booleans) {
for (var right : booleans) {
Expand All @@ -240,18 +238,18 @@ private static Byte2ObjectMap<VoxelShape> buildShapeMap(boolean thin) {
case RIGHT -> parts.add(rightCorners.get(facing));
}

var key = getShapeKey(facing, left, right, front);
int key = getShapeKey(facing, left, right, front);
var shape = VoxelShapes.union(bottom, parts.toArray(VoxelShape[]::new));
result.put(key, shape);
result[key] = shape;
}
}
}
}
return result;
}

private static byte getShapeKey(Direction facing, boolean left, boolean right, FrontConnection front) {
return (byte) (facing.getHorizontal() << 5 | (left ? 1 : 0) << 3 | (right ? 1 : 0) << 2 | front.ordinal());
private static int getShapeKey(Direction facing, boolean left, boolean right, FrontConnection front) {
return front.ordinal() << 4 | (left ? 1 : 0) << 3 | (right ? 1 : 0) << 2 | facing.getHorizontal();
}

public static @Nullable Direction getSleepingDirection(BlockView world, BlockPos pos) {
Expand Down
10 changes: 4 additions & 6 deletions common/src/main/java/juuxel/adorn/block/TableBlock.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package juuxel.adorn.block;

import it.unimi.dsi.fastutil.bytes.Byte2ObjectMap;
import it.unimi.dsi.fastutil.bytes.Byte2ObjectOpenHashMap;
import juuxel.adorn.block.variant.BlockVariant;
import net.minecraft.block.BlockState;
import net.minecraft.util.Identifier;
Expand All @@ -15,7 +13,7 @@

public final class TableBlock extends AbstractTableBlock implements BlockWithDescription {
private static final String DESCRIPTION_KEY = "block.adorn.table.description";
private static final Byte2ObjectMap<VoxelShape> SHAPES = new Byte2ObjectOpenHashMap<>();
private static final VoxelShape[] SHAPES = new VoxelShape[32];

static {
var topShape = createCuboidShape(0.0, 14.0, 0.0, 16.0, 16.0, 16.0);
Expand All @@ -32,7 +30,7 @@ public final class TableBlock extends AbstractTableBlock implements BlockWithDes
for (var hasCarpet : booleans) {
var key = getShapeKey(north, east, south, west, hasCarpet);
var shape = makeShape(north, east, south, west, hasCarpet, topShape, legX0Z0, legX1Z0, legX0Z1, legX1Z1);
SHAPES.put(key, shape);
SHAPES[key] = shape;
}
}
}
Expand Down Expand Up @@ -69,8 +67,8 @@ protected boolean canConnectTo(BlockState state, Direction sideOfSelf) {
}

@Override
protected VoxelShape getShapeForKey(byte key) {
return SHAPES.get(key);
protected VoxelShape getShapeForKey(int key) {
return SHAPES[key];
}

private static VoxelShape makeShape(
Expand Down

0 comments on commit ec919fa

Please sign in to comment.