Compare commits

..

No commits in common. "d5369823d9630f22f75c58902f8c101fa0e82404" and "fa44408836cd2cb3ff8b02dce3497a41aae9b12b" have entirely different histories.

47 changed files with 335 additions and 521 deletions

View File

@ -4,7 +4,7 @@ import fr.altarik.CreateTag
plugins { plugins {
id "com.modrinth.minotaur" version "2.+" id "com.modrinth.minotaur" version "2.+"
id 'fabric-loom' version '1.6-SNAPSHOT' id 'fabric-loom' version '1.5-SNAPSHOT'
id 'maven-publish' id 'maven-publish'
} }

View File

@ -5,7 +5,7 @@ org.gradle.jvmargs=-Xmx1G
# check these on https://modmuss50.me/fabric.html # check these on https://modmuss50.me/fabric.html
minecraft_version=1.20.4 minecraft_version=1.20.4
yarn_mappings=1.20.4+build.3 yarn_mappings=1.20.4+build.3
loader_version=0.15.10 loader_version=0.15.6
# Mod Properties # Mod Properties
modrinth_id = jCpoCBpn modrinth_id = jCpoCBpn
@ -16,7 +16,7 @@ mod_id = reframed
# Dependencies # Dependencies
# check this on https://modmuss50.me/fabric.html # check this on https://modmuss50.me/fabric.html
fabric_version=0.97.0+1.20.4 fabric_version=0.95.4+1.20.4
git_owner=Altarik git_owner=Altarik
git_repo=ReFramed git_repo=ReFramed

View File

@ -37,7 +37,7 @@ public class ReFramed implements ModInitializer {
public static final String MODID = "reframed"; public static final String MODID = "reframed";
public static final ArrayList<Block> BLOCKS = new ArrayList<>(); public static final ArrayList<Block> BLOCKS = new ArrayList<>();
public static Block CUBE, SMALL_CUBE, SMALL_CUBES_STEP, STAIR, HALF_STAIR, STAIRS_CUBE, HALF_STAIRS_SLAB, HALF_STAIRS_STAIR, SLAB, SLABS_CUBE, STEP, STEPS_SLAB, LAYER, PILLAR, PILLARS_WALL, WALL; public static Block CUBE, SMALL_CUBE, SMALL_CUBES_STEP, STAIR, HALF_STAIR, STAIRS_CUBE, HALF_STAIRS_SLAB, HALF_STAIRS_STAIR, SLAB, SLABS_CUBE, STEP, STEPS_SLAB, LAYER, PILLAR, WALL;
public static final ArrayList<Item> ITEMS = new ArrayList<>(); public static final ArrayList<Item> ITEMS = new ArrayList<>();
public static Item HAMMER, SCREWDRIVER, BLUEPRINT, BLUEPRINT_WRITTEN; public static Item HAMMER, SCREWDRIVER, BLUEPRINT, BLUEPRINT_WRITTEN;
@ -65,8 +65,7 @@ public class ReFramed implements ModInitializer {
STEP = registerBlock("step" , new ReFramedStepBlock(cp(Blocks.OAK_SLAB))); STEP = registerBlock("step" , new ReFramedStepBlock(cp(Blocks.OAK_SLAB)));
STEPS_SLAB = registerBlock("steps_slab" , new ReFramedStepsSlabBlock(cp(Blocks.OAK_SLAB))); STEPS_SLAB = registerBlock("steps_slab" , new ReFramedStepsSlabBlock(cp(Blocks.OAK_SLAB)));
PILLAR = registerBlock("pillar" , new ReFramedPillarBlock(cp(Blocks.OAK_FENCE))); PILLAR = registerBlock("pillar" , new ReFramedPillarBlock(cp(Blocks.OAK_FENCE)));
PILLARS_WALL = registerBlock("pillars_wall" , new ReFramedPillarsWallBlock(cp(Blocks.OAK_FENCE))); WALL = registerBlock("wall" , new ReframedWallBlock(cp(Blocks.OAK_FENCE)));
WALL = registerBlock("wall" , new ReFramedWallBlock(cp(Blocks.OAK_FENCE)));
HAMMER = registerItem("hammer" , new ReFramedHammerItem(new Item.Settings().maxCount(1))); HAMMER = registerItem("hammer" , new ReFramedHammerItem(new Item.Settings().maxCount(1)));
SCREWDRIVER = registerItem("screwdriver" , new ReFramedScrewdriverItem(new Item.Settings().maxCount(1))); SCREWDRIVER = registerItem("screwdriver" , new ReFramedScrewdriverItem(new Item.Settings().maxCount(1)));

View File

@ -43,6 +43,16 @@ public class ReFramedBlock extends Block implements BlockEntityProvider {
setDefaultState(getDefaultState().with(LIGHT, false)); setDefaultState(getDefaultState().with(LIGHT, false));
} }
/**
* Generates a record for the key so that it replaces the blockstate
* which may have states that returns same models
* @param state - the state_key to generate the key from
* @return a cache key with only relevant properties
*/
public Object getModelCacheKey(BlockState state) {
return "";
}
//For addon devs: override this so your blocks don't end up trying to place my block entity, my BlockEntityType only handles blocks internal to the mod //For addon devs: override this so your blocks don't end up trying to place my block entity, my BlockEntityType only handles blocks internal to the mod
//Just make your own BlockEntityType, it's fine, you can even use the same ReFramedEntity class //Just make your own BlockEntityType, it's fine, you can even use the same ReFramedEntity class
@Override @Override

View File

@ -69,12 +69,12 @@ public abstract class ReFramedDoubleBlock extends ReFramedBlock {
@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 isGhost(view, pos) ? empty() : fullCube(); return getCullingShape(state, view, pos);
} }
@Override @Override
public VoxelShape getCullingShape(BlockState state, BlockView view, BlockPos pos) { public VoxelShape getCullingShape(BlockState state, BlockView view, BlockPos pos) {
return getCollisionShape(state, view, pos, ShapeContext.absent()); return isGhost(view, pos) ? empty() : fullCube();
} }
@Override @Override

View File

@ -29,11 +29,18 @@ public class ReFramedHalfStairBlock extends WaterloggableReFramedBlock {
public static final VoxelShape[] HALF_STAIR_VOXELS; public static final VoxelShape[] HALF_STAIR_VOXELS;
private record ModelCacheKey(Corner corner, int face) {}
public ReFramedHalfStairBlock(Settings settings) { public ReFramedHalfStairBlock(Settings settings) {
super(settings); super(settings);
setDefaultState(getDefaultState().with(CORNER, NORTH_EAST_DOWN).with(CORNER_FACE, 0)); setDefaultState(getDefaultState().with(CORNER, NORTH_EAST_DOWN).with(CORNER_FACE, 0));
} }
@Override
public Object getModelCacheKey(BlockState state) {
return new ModelCacheKey(state.get(CORNER), state.get(CORNER_FACE));
}
@Override @Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) { protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(builder.add(CORNER,CORNER_FACE)); super.appendProperties(builder.add(CORNER,CORNER_FACE));

View File

@ -22,11 +22,18 @@ import static net.minecraft.util.shape.VoxelShapes.empty;
public class ReFramedHalfStairsSlabBlock extends WaterloggableReFramedDoubleBlock { public class ReFramedHalfStairsSlabBlock extends WaterloggableReFramedDoubleBlock {
private record ModelCacheKey(Corner corner, int face) {}
public ReFramedHalfStairsSlabBlock(Settings settings) { public ReFramedHalfStairsSlabBlock(Settings settings) {
super(settings); super(settings);
setDefaultState(getDefaultState().with(CORNER, NORTH_EAST_DOWN).with(CORNER_FACE, 0)); setDefaultState(getDefaultState().with(CORNER, NORTH_EAST_DOWN).with(CORNER_FACE, 0));
} }
@Override
public Object getModelCacheKey(BlockState state) {
return new ModelCacheKey(state.get(CORNER), state.get(CORNER_FACE));
}
@Override @Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) { protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(builder.add(CORNER,CORNER_FACE)); super.appendProperties(builder.add(CORNER,CORNER_FACE));
@ -41,7 +48,7 @@ public class ReFramedHalfStairsSlabBlock extends WaterloggableReFramedDoubleBloc
} }
@Override @Override
public VoxelShape getCollisionShape(BlockState state, BlockView view, BlockPos pos, ShapeContext ctx) { public VoxelShape getCullingShape(BlockState state, BlockView view, BlockPos pos) {
return isGhost(view, pos) ? empty(): getSlabShape(state.get(CORNER).getDirection(state.get(CORNER_FACE))); return isGhost(view, pos) ? empty(): getSlabShape(state.get(CORNER).getDirection(state.get(CORNER_FACE)));
} }

View File

@ -27,6 +27,11 @@ public class ReFramedHalfStairsStairBlock extends WaterloggableReFramedDoubleBlo
setDefaultState(getDefaultState().with(EDGE, NORTH_DOWN)); setDefaultState(getDefaultState().with(EDGE, NORTH_DOWN));
} }
@Override
public Object getModelCacheKey(BlockState state) {
return state.get(EDGE);
}
@Override @Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) { protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(builder.add(EDGE)); super.appendProperties(builder.add(EDGE));
@ -39,7 +44,7 @@ public class ReFramedHalfStairsStairBlock extends WaterloggableReFramedDoubleBlo
} }
@Override @Override
public VoxelShape getCollisionShape(BlockState state, BlockView view, BlockPos pos, ShapeContext ctx) { public VoxelShape getCullingShape(BlockState state, BlockView view, BlockPos pos) {
return isGhost(view, pos) ? empty(): getStairShape(state.get(EDGE), StairShape.STRAIGHT); return isGhost(view, pos) ? empty(): getStairShape(state.get(EDGE), StairShape.STRAIGHT);
} }

View File

@ -8,6 +8,7 @@ import net.minecraft.item.BlockItem;
import net.minecraft.item.ItemPlacementContext; import net.minecraft.item.ItemPlacementContext;
import net.minecraft.state.StateManager; import net.minecraft.state.StateManager;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.shape.VoxelShape; import net.minecraft.util.shape.VoxelShape;
import net.minecraft.world.BlockView; import net.minecraft.world.BlockView;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@ -19,12 +20,18 @@ import static net.minecraft.state.property.Properties.LAYERS;
public class ReFramedLayerBlock extends ReFramedSlabBlock { public class ReFramedLayerBlock extends ReFramedSlabBlock {
public static final VoxelShape[] LAYER_VOXELS; public static final VoxelShape[] LAYER_VOXELS;
private record ModelCacheKey(Direction face, int layer) {}
public ReFramedLayerBlock(Settings settings) { public ReFramedLayerBlock(Settings settings) {
super(settings); super(settings);
setDefaultState(getDefaultState().with(LAYERS, 1)); setDefaultState(getDefaultState().with(LAYERS, 1));
} }
@Override
public Object getModelCacheKey(BlockState state) {
return new ModelCacheKey(state.get(FACING), state.get(LAYERS));
}
@Override @Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) { protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(builder.add(LAYERS)); super.appendProperties(builder.add(LAYERS));

View File

@ -26,6 +26,11 @@ public class ReFramedPillarBlock extends WaterloggableReFramedBlock {
setDefaultState(getDefaultState().with(AXIS, Direction.Axis.Y)); setDefaultState(getDefaultState().with(AXIS, Direction.Axis.Y));
} }
@Override
public Object getModelCacheKey(BlockState state) {
return state.get(AXIS);
}
@Override @Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) { protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(builder.add(AXIS)); super.appendProperties(builder.add(AXIS));

View File

@ -1,117 +0,0 @@
package fr.adrien1106.reframed.block;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.ShapeContext;
import net.minecraft.block.enums.WallShape;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.state.StateManager;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.util.shape.VoxelShapes;
import net.minecraft.world.BlockView;
import net.minecraft.world.World;
import net.minecraft.world.WorldAccess;
import org.jetbrains.annotations.Nullable;
import java.util.Map;
import java.util.stream.Collectors;
import static fr.adrien1106.reframed.block.ReFramedWallBlock.*;
import static net.minecraft.state.property.Properties.*;
import static net.minecraft.util.shape.VoxelShapes.empty;
public class ReFramedPillarsWallBlock extends WaterloggableReFramedDoubleBlock {
public ReFramedPillarsWallBlock(Settings settings) {
super(settings);
setDefaultState(getDefaultState()
.with(EAST_WALL_SHAPE, WallShape.NONE)
.with(NORTH_WALL_SHAPE, WallShape.NONE)
.with(WEST_WALL_SHAPE, WallShape.NONE)
.with(SOUTH_WALL_SHAPE, WallShape.NONE)
);
}
@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(builder.add(EAST_WALL_SHAPE, NORTH_WALL_SHAPE, SOUTH_WALL_SHAPE, WEST_WALL_SHAPE));
}
@Override
public BlockState getStateForNeighborUpdate(BlockState state, Direction dir, BlockState other_state, WorldAccess world, BlockPos pos, BlockPos moved) {
BlockState new_state = super.getStateForNeighborUpdate(state, dir, other_state, world, pos, moved);
if (dir == Direction.DOWN) return new_state;
BlockState top_state = dir == Direction.UP? other_state: world.getBlockState(pos.up());
boolean fs = top_state.isSideSolidFullSquare(world, pos.up(), Direction.DOWN);
VoxelShape top_shape = fs ? null : top_state.getCollisionShape(world, pos.up()).getFace(Direction.DOWN);
Map<Direction, BlockState> neighbors = Direction.Type.HORIZONTAL.stream()
.collect(Collectors.toMap(d -> d, d -> {
if (d == dir) return other_state;
return world.getBlockState(pos.offset(d));
}));
return getWallState(new_state, top_state, neighbors, top_shape, fs, world, pos);
}
@Override
public @Nullable BlockState getPlacementState(ItemPlacementContext ctx) {
BlockState state = super.getPlacementState(ctx);
World world = ctx.getWorld();
BlockPos pos = ctx.getBlockPos();
BlockState top_state = world.getBlockState(pos.up());
boolean fs = top_state.isSideSolidFullSquare(world, pos.up(), Direction.DOWN);
VoxelShape top_shape = fs ? null : top_state.getCollisionShape(world, pos.up()).getFace(Direction.DOWN);
Map<Direction, BlockState> neighbors = Direction.Type.HORIZONTAL.stream()
.collect(Collectors.toMap(d -> d, d -> world.getBlockState(pos.offset(d))));
return getWallState(state, top_state, neighbors, top_shape, fs, world, pos);
}
@Override
public void onStateReplaced(BlockState state, World world, BlockPos pos, BlockState newState, boolean moved) {
super.onStateReplaced(state, world, pos, newState, moved);
if(!state.isOf(newState.getBlock())) world.removeBlockEntity(pos);
}
@Override
public VoxelShape getCollisionShape(BlockState state, BlockView view, BlockPos pos, ShapeContext ctx) {
if (isGhost(view, pos)) return empty();
VoxelShape shape = WALL_VOXELS[9];
for (Direction dir : Direction.Type.HORIZONTAL) {
if (state.get(getWallShape(dir)) != WallShape.NONE)
shape = VoxelShapes.union(shape, WALL_VOXELS[8 + dir.ordinal()]);
}
return shape;
}
@Override
public VoxelShape getCullingShape(BlockState state, BlockView view, BlockPos pos) {
return isGhost(view, pos) ? empty(): getOutlineShape(state, view, pos, ShapeContext.absent());
}
@Override
public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
VoxelShape shape = WALL_VOXELS[0];
for (Direction dir: Direction.Type.HORIZONTAL) {
WallShape wall_shape = state.get(getWallShape(dir));
if (wall_shape != WallShape.NONE)
shape = VoxelShapes.union(shape, WALL_VOXELS[1 + (wall_shape.ordinal()-1) * 4 + (dir.ordinal() - 2)]);
}
return shape;
}
@Override
public VoxelShape getShape(BlockState state, int i) {
if (i == 1) return WALL_VOXELS[0];
VoxelShape shape = VoxelShapes.empty();
for (Direction dir: Direction.Type.HORIZONTAL) {
WallShape wall_shape = state.get(getWallShape(dir));
if (wall_shape != WallShape.NONE)
shape = VoxelShapes.union(shape, WALL_VOXELS[1 + (wall_shape.ordinal()-1) * 4 + (dir.ordinal() - 2)]);
}
return shape;
}
}

View File

@ -33,6 +33,11 @@ public class ReFramedSlabBlock extends WaterloggableReFramedBlock {
setDefaultState(getDefaultState().with(FACING, Direction.DOWN)); setDefaultState(getDefaultState().with(FACING, Direction.DOWN));
} }
@Override
public Object getModelCacheKey(BlockState state) {
return state.get(FACING);
}
@Override @Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) { protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(builder.add(FACING)); super.appendProperties(builder.add(FACING));

View File

@ -18,6 +18,11 @@ public class ReFramedSlabsCubeBlock extends ReFramedDoubleBlock {
setDefaultState(getDefaultState().with(AXIS, Direction.Axis.Y)); setDefaultState(getDefaultState().with(AXIS, Direction.Axis.Y));
} }
@Override
public Object getModelCacheKey(BlockState state) {
return state.get(AXIS);
}
@Override @Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) { protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(builder.add(AXIS)); super.appendProperties(builder.add(AXIS));

View File

@ -34,6 +34,11 @@ public class ReFramedSmallCubeBlock extends WaterloggableReFramedBlock {
setDefaultState(getDefaultState().with(CORNER, NORTH_EAST_DOWN)); setDefaultState(getDefaultState().with(CORNER, NORTH_EAST_DOWN));
} }
@Override
public Object getModelCacheKey(BlockState state) {
return state.get(CORNER);
}
@Override @Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) { protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(builder.add(CORNER)); super.appendProperties(builder.add(CORNER));

View File

@ -25,6 +25,11 @@ public class ReFramedSmallCubesStepBlock extends WaterloggableReFramedDoubleBloc
setDefaultState(getDefaultState().with(EDGE, Edge.NORTH_DOWN)); setDefaultState(getDefaultState().with(EDGE, Edge.NORTH_DOWN));
} }
@Override
public Object getModelCacheKey(BlockState state) {
return state.get(EDGE);
}
@Override @Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) { protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(builder.add(EDGE)); super.appendProperties(builder.add(EDGE));
@ -37,7 +42,7 @@ public class ReFramedSmallCubesStepBlock extends WaterloggableReFramedDoubleBloc
} }
@Override @Override
public VoxelShape getCollisionShape(BlockState state, BlockView view, BlockPos pos, ShapeContext ctx) { public VoxelShape getCullingShape(BlockState state, BlockView view, BlockPos pos) {
return isGhost(view, pos) ? empty(): getStepShape(state.get(EDGE)); return isGhost(view, pos) ? empty(): getStepShape(state.get(EDGE));
} }

View File

@ -31,12 +31,18 @@ import static fr.adrien1106.reframed.util.blocks.StairShape.*;
public class ReFramedStairBlock extends WaterloggableReFramedBlock { public class ReFramedStairBlock extends WaterloggableReFramedBlock {
public static final VoxelShape[] STAIR_VOXELS; public static final VoxelShape[] STAIR_VOXELS;
private record ModelCacheKey(Edge edge, StairShape shape) {}
public ReFramedStairBlock(Settings settings) { public ReFramedStairBlock(Settings settings) {
super(settings); super(settings);
setDefaultState(getDefaultState().with(EDGE, Edge.NORTH_DOWN).with(STAIR_SHAPE, STRAIGHT)); setDefaultState(getDefaultState().with(EDGE, Edge.NORTH_DOWN).with(STAIR_SHAPE, STRAIGHT));
} }
@Override
public Object getModelCacheKey(BlockState state) {
return new ModelCacheKey(state.get(EDGE), state.get(STAIR_SHAPE));
}
@Override @Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) { protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(builder.add(EDGE, STAIR_SHAPE)); super.appendProperties(builder.add(EDGE, STAIR_SHAPE));

View File

@ -22,12 +22,18 @@ import static fr.adrien1106.reframed.util.blocks.BlockProperties.STAIR_SHAPE;
public class ReFramedStairsCubeBlock extends ReFramedDoubleBlock { public class ReFramedStairsCubeBlock extends ReFramedDoubleBlock {
private static final VoxelShape[] STAIRS_CUBE_VOXELS = VoxelListBuilder.buildFrom(STAIR_VOXELS); private static final VoxelShape[] STAIRS_CUBE_VOXELS = VoxelListBuilder.buildFrom(STAIR_VOXELS);
private record ModelCacheKey(Edge edge, StairShape shape) {}
public ReFramedStairsCubeBlock(Settings settings) { public ReFramedStairsCubeBlock(Settings settings) {
super(settings); super(settings);
setDefaultState(getDefaultState().with(EDGE, Edge.NORTH_DOWN).with(STAIR_SHAPE, StairShape.STRAIGHT)); setDefaultState(getDefaultState().with(EDGE, Edge.NORTH_DOWN).with(STAIR_SHAPE, StairShape.STRAIGHT));
} }
@Override
public Object getModelCacheKey(BlockState state) {
return new ModelCacheKey(state.get(EDGE), state.get(STAIR_SHAPE));
}
@Override @Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) { protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(builder.add(EDGE, STAIR_SHAPE)); super.appendProperties(builder.add(EDGE, STAIR_SHAPE));

View File

@ -34,6 +34,11 @@ public class ReFramedStepBlock extends WaterloggableReFramedBlock {
setDefaultState(getDefaultState().with(EDGE, Edge.NORTH_DOWN)); setDefaultState(getDefaultState().with(EDGE, Edge.NORTH_DOWN));
} }
@Override
public Object getModelCacheKey(BlockState state) {
return state.get(EDGE);
}
@Override @Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) { protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(builder.add(EDGE)); super.appendProperties(builder.add(EDGE));

View File

@ -22,12 +22,18 @@ import static net.minecraft.state.property.Properties.FACING;
import static net.minecraft.util.shape.VoxelShapes.empty; import static net.minecraft.util.shape.VoxelShapes.empty;
public class ReFramedStepsSlabBlock extends WaterloggableReFramedDoubleBlock { public class ReFramedStepsSlabBlock extends WaterloggableReFramedDoubleBlock {
private record ModelCacheKey(Direction facing, Axis axis) {}
public ReFramedStepsSlabBlock(Settings settings) { public ReFramedStepsSlabBlock(Settings settings) {
super(settings); super(settings);
setDefaultState(getDefaultState().with(FACING, Direction.DOWN).with(AXIS, Axis.X)); setDefaultState(getDefaultState().with(FACING, Direction.DOWN).with(AXIS, Axis.X));
} }
@Override
public Object getModelCacheKey(BlockState state) {
return new ModelCacheKey(state.get(FACING), state.get(AXIS));
}
@Override @Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) { protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(builder.add(FACING, AXIS)); super.appendProperties(builder.add(FACING, AXIS));
@ -42,7 +48,7 @@ public class ReFramedStepsSlabBlock extends WaterloggableReFramedDoubleBlock {
} }
@Override @Override
public VoxelShape getCollisionShape(BlockState state, BlockView view, BlockPos pos, ShapeContext ctx) { public VoxelShape getCullingShape(BlockState state, BlockView view, BlockPos pos) {
return isGhost(view, pos) ? empty() : getSlabShape(state.get(FACING)); return isGhost(view, pos) ? empty() : getSlabShape(state.get(FACING));
} }

View File

@ -15,20 +15,19 @@ import net.minecraft.util.shape.VoxelShapes;
import net.minecraft.world.BlockView; import net.minecraft.world.BlockView;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraft.world.WorldAccess; import net.minecraft.world.WorldAccess;
import net.minecraft.world.WorldView;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
import static net.minecraft.state.property.Properties.*; import static net.minecraft.state.property.Properties.*;
public class ReFramedWallBlock extends WaterloggableReFramedBlock { public class ReframedWallBlock extends WaterloggableReFramedBlock {
public static final VoxelShape[] WALL_VOXELS; public static final VoxelShape[] WALL_VOXELS;
public ReFramedWallBlock(Settings settings) { private record ModelCacheKey(boolean up, WallShape east, WallShape north, WallShape west, WallShape south) {}
public ReframedWallBlock(Settings settings) {
super(settings); super(settings);
setDefaultState(getDefaultState() setDefaultState(getDefaultState()
.with(UP, true) .with(UP, true)
@ -39,6 +38,17 @@ public class ReFramedWallBlock extends WaterloggableReFramedBlock {
); );
} }
@Override
public Object getModelCacheKey(BlockState state) {
return new ModelCacheKey(
state.get(UP),
state.get(EAST_WALL_SHAPE),
state.get(NORTH_WALL_SHAPE),
state.get(WEST_WALL_SHAPE),
state.get(SOUTH_WALL_SHAPE)
);
}
@Override @Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) { protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(builder.add(UP, EAST_WALL_SHAPE, NORTH_WALL_SHAPE, SOUTH_WALL_SHAPE, WEST_WALL_SHAPE)); super.appendProperties(builder.add(UP, EAST_WALL_SHAPE, NORTH_WALL_SHAPE, SOUTH_WALL_SHAPE, WEST_WALL_SHAPE));
@ -51,13 +61,34 @@ public class ReFramedWallBlock extends WaterloggableReFramedBlock {
BlockState top_state = dir == Direction.UP? other_state: world.getBlockState(pos.up()); BlockState top_state = dir == Direction.UP? other_state: world.getBlockState(pos.up());
boolean fs = top_state.isSideSolidFullSquare(world, pos.up(), Direction.DOWN); boolean fs = top_state.isSideSolidFullSquare(world, pos.up(), Direction.DOWN);
VoxelShape top_shape = fs ? null : top_state.getCollisionShape(world, pos.up()).getFace(Direction.DOWN); VoxelShape top_shape = fs ? null : top_state.getCollisionShape(world, pos.up()).getFace(Direction.DOWN);
if (dir == Direction.UP) {
for (Direction d : Direction.Type.HORIZONTAL) {
Property<WallShape> wall_shape = getWallShape(d);
if (state.get(wall_shape) == WallShape.NONE) continue;
new_state = new_state.with(
wall_shape,
fs
|| (top_state.contains(wall_shape) && top_state.get(wall_shape) != WallShape.NONE)
|| shouldUseTall(WALL_VOXELS[dir.ordinal() + 3], top_shape)
? WallShape.TALL
: WallShape.LOW
);
}
return new_state.with(UP, shouldHavePost(new_state, top_state, top_shape));
}
Map<Direction, BlockState> neighbors = Direction.Type.HORIZONTAL.stream() boolean side_full = other_state.isSideSolidFullSquare(world, moved, dir.getOpposite());
.collect(Collectors.toMap(d -> d, d -> { if (shouldConnectTo(other_state, side_full, dir.getOpposite())) {
if (d == dir) return other_state; Property<WallShape> wall_shape = getWallShape(dir);
return world.getBlockState(pos.offset(d)); new_state = new_state.with(
})); wall_shape,
new_state = getWallState(new_state, top_state, neighbors, top_shape, fs, world, pos); fs
|| (top_state.contains(wall_shape) && top_state.get(wall_shape) != WallShape.NONE)
|| shouldUseTall(WALL_VOXELS[dir.ordinal() + 3], top_shape)
? WallShape.TALL
: WallShape.LOW
);
} else new_state = new_state.with(getWallShape(dir), WallShape.NONE);
return new_state.with(UP, shouldHavePost(new_state, top_state, top_shape)); return new_state.with(UP, shouldHavePost(new_state, top_state, top_shape));
} }
@ -66,14 +97,25 @@ public class ReFramedWallBlock extends WaterloggableReFramedBlock {
BlockState state = super.getPlacementState(ctx); BlockState state = super.getPlacementState(ctx);
World world = ctx.getWorld(); World world = ctx.getWorld();
BlockPos pos = ctx.getBlockPos(); BlockPos pos = ctx.getBlockPos();
BlockState top_state = world.getBlockState(pos.up()); BlockState top_state = world.getBlockState(pos.up());
boolean fs = top_state.isSideSolidFullSquare(world, pos.up(), Direction.DOWN); boolean fs = top_state.isSideSolidFullSquare(world, pos.up(), Direction.DOWN);
VoxelShape top_shape = fs ? null : top_state.getCollisionShape(world, pos.up()).getFace(Direction.DOWN); VoxelShape top_shape = fs ? null : top_state.getCollisionShape(world, pos.up()).getFace(Direction.DOWN);
for (Direction dir : Direction.Type.HORIZONTAL) {
Map<Direction, BlockState> neighbors = Direction.Type.HORIZONTAL.stream() BlockPos offset = pos.offset(dir);
.collect(Collectors.toMap(d -> d, d -> world.getBlockState(pos.offset(d)))); BlockState neighbor = world.getBlockState(offset);
state = getWallState(state, top_state, neighbors, top_shape, fs, world, pos); boolean side_full = neighbor.isSideSolidFullSquare(world, offset, dir.getOpposite());
if (shouldConnectTo(neighbor, side_full, dir.getOpposite())) {
Property<WallShape> wall_shape = getWallShape(dir);
state = state.with(
wall_shape,
fs
|| (top_state.contains(wall_shape) && top_state.get(wall_shape) != WallShape.NONE)
|| shouldUseTall(WALL_VOXELS[dir.ordinal() + 3], top_shape)
? WallShape.TALL
: WallShape.LOW
);
}
}
return state.with(UP, shouldHavePost(state, top_state, top_shape)); return state.with(UP, shouldHavePost(state, top_state, top_shape));
} }
@ -106,29 +148,9 @@ public class ReFramedWallBlock extends WaterloggableReFramedBlock {
return shape; return shape;
} }
public static BlockState getWallState(BlockState state, BlockState top_state, Map<Direction, BlockState> neighbors, VoxelShape top_shape, boolean fs, WorldView world, BlockPos pos) { private static boolean shouldHavePost(BlockState state, BlockState top_state, VoxelShape top_shape) {
for (Direction dir : Direction.Type.HORIZONTAL) {
BlockPos offset = pos.offset(dir);
BlockState neighbor = neighbors.get(dir);
boolean side_full = neighbor.isSideSolidFullSquare(world, offset, dir.getOpposite());
Property<WallShape> wall_shape = getWallShape(dir);
if (shouldConnectTo(neighbor, side_full, dir.getOpposite())) {
state = state.with(
wall_shape,
fs
|| (top_state.contains(wall_shape) && top_state.get(wall_shape) != WallShape.NONE)
|| shouldUseTall(WALL_VOXELS[dir.ordinal() + 3], top_shape)
? WallShape.TALL
: WallShape.LOW
);
} else state = state.with(wall_shape, WallShape.NONE);
}
return state;
}
public static boolean shouldHavePost(BlockState state, BlockState top_state, VoxelShape top_shape) {
// above has post // above has post
if ((top_state.contains(UP) && top_state.get(UP)) || (!top_state.contains(UP) && top_state.contains(NORTH_WALL_SHAPE))) return true; if (top_state.contains(NORTH_WALL_SHAPE) && top_state.get(UP)) return true;
if (Stream.of(Direction.SOUTH, Direction.EAST) // Opposites are different if (Stream.of(Direction.SOUTH, Direction.EAST) // Opposites are different
.anyMatch(dir -> state.get(getWallShape(dir)) != state.get(getWallShape(dir.getOpposite()))) .anyMatch(dir -> state.get(getWallShape(dir)) != state.get(getWallShape(dir.getOpposite())))
@ -138,22 +160,23 @@ public class ReFramedWallBlock extends WaterloggableReFramedBlock {
if (Direction.Type.HORIZONTAL.stream().allMatch(dir -> state.get(getWallShape(dir)) == WallShape.NONE)) if (Direction.Type.HORIZONTAL.stream().allMatch(dir -> state.get(getWallShape(dir)) == WallShape.NONE))
return true; return true;
// Matching sides // tall Matching sides
if (Stream.of(Direction.SOUTH, Direction.EAST) if (Stream.of(Direction.SOUTH, Direction.EAST)
.anyMatch(dir -> .anyMatch(dir ->
state.get(getWallShape(dir)) == state.get(getWallShape(dir.getOpposite())) state.get(getWallShape(dir)) == WallShape.TALL
&& state.get(getWallShape(dir.getOpposite())) == WallShape.TALL
)) return false; )) return false;
return top_state.isIn(BlockTags.WALL_POST_OVERRIDE) || top_shape == null || shouldUseTall(WALL_VOXELS[0], top_shape); return top_state.isIn(BlockTags.WALL_POST_OVERRIDE) || top_shape == null || shouldUseTall(WALL_VOXELS[0], top_shape);
} }
public static boolean shouldConnectTo(BlockState state, boolean side_full, Direction side) { private static boolean shouldConnectTo(BlockState state, boolean side_full, Direction side) {
Block block = state.getBlock(); Block block = state.getBlock();
boolean bl = block instanceof FenceGateBlock && FenceGateBlock.canWallConnect(state, side); boolean bl = block instanceof FenceGateBlock && FenceGateBlock.canWallConnect(state, side);
return state.isIn(BlockTags.WALLS) || !WallBlock.cannotConnect(state) && side_full || block instanceof PaneBlock || bl; return state.isIn(BlockTags.WALLS) || !WallBlock.cannotConnect(state) && side_full || block instanceof PaneBlock || bl;
} }
public static boolean shouldUseTall(VoxelShape self_shape, VoxelShape other_shape) { private static boolean shouldUseTall(VoxelShape self_shape, VoxelShape other_shape) {
return !VoxelShapes.matchesAnywhere( return !VoxelShapes.matchesAnywhere(
self_shape, self_shape,
other_shape, other_shape,
@ -161,7 +184,7 @@ public class ReFramedWallBlock extends WaterloggableReFramedBlock {
); );
} }
public static Property<WallShape> getWallShape(Direction dir) { private static Property<WallShape> getWallShape(Direction dir) {
return switch (dir) { return switch (dir) {
case EAST -> EAST_WALL_SHAPE; case EAST -> EAST_WALL_SHAPE;
case NORTH -> NORTH_WALL_SHAPE; case NORTH -> NORTH_WALL_SHAPE;

View File

@ -14,6 +14,10 @@ import net.minecraft.resource.ResourceType;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import net.minecraft.util.math.ChunkSectionPos; import net.minecraft.util.math.ChunkSectionPos;
import static fr.adrien1106.reframed.util.blocks.BlockProperties.*;
import static fr.adrien1106.reframed.util.blocks.BlockProperties.STAIR_SHAPE;
import static net.minecraft.state.property.Properties.*;
public class ReFramedClient implements ClientModInitializer { public class ReFramedClient implements ClientModInitializer {
public static final ReFramedModelProvider PROVIDER = new ReFramedModelProvider(); public static final ReFramedModelProvider PROVIDER = new ReFramedModelProvider();
@ -27,96 +31,92 @@ public class ReFramedClient implements ClientModInitializer {
BlockRenderLayerMap.INSTANCE.putBlocks(RenderLayer.getCutout(), ReFramed.BLOCKS.toArray(new Block[0])); BlockRenderLayerMap.INSTANCE.putBlocks(RenderLayer.getCutout(), ReFramed.BLOCKS.toArray(new Block[0]));
// CUBE // CUBE
HELPER.addReFramedModel("cube" , HELPER.auto(new Identifier("block/cube"))); HELPER.addReFramedModel("cube" , HELPER.auto(new Identifier("block/cube"), 2));
// SMALL_CUBE // SMALL_CUBE
HELPER.addReFramedModel("small_cube" , HELPER.auto(ReFramed.id("block/small_cube/base"))); HELPER.addReFramedModel("small_cube" , HELPER.auto(ReFramed.id("block/small_cube/base"), 9, CORNER));
// SMALL_CUBES_STEP // SMALL_CUBES_STEP
HELPER.addReFramedModel("small_cubes_step" , HELPER.autoDouble(ReFramed.id("block/small_cube/base"), ReFramed.id("block/small_cube/step/base"))); HELPER.addReFramedModel("small_cubes_step" , HELPER.autoDouble(ReFramed.id("block/small_cube/base"), ReFramed.id("block/small_cube/step/base"), 9, EDGE));
HELPER.addReFramedModel("small_cubes_step_reverse" , HELPER.autoDouble(ReFramed.id("block/small_cube/step/base"), ReFramed.id("block/small_cube/base"))); HELPER.addReFramedModel("small_cubes_step_reverse" , HELPER.autoDouble(ReFramed.id("block/small_cube/step/base"), ReFramed.id("block/small_cube/base"), 4, EDGE));
// SLAB // SLAB
HELPER.addReFramedModel("slab" , HELPER.auto(new Identifier("block/slab"))); HELPER.addReFramedModel("slab" , HELPER.auto(new Identifier("block/slab"), 7, FACING));
// SLAB_CUBE // SLAB_CUBE
HELPER.addReFramedModel("double_slab" , HELPER.autoDouble(new Identifier("block/slab"), new Identifier("block/slab_top"))); HELPER.addReFramedModel("double_slab" , HELPER.autoDouble(new Identifier("block/slab"), new Identifier("block/slab_top"), 4, AXIS));
// STAIR // STAIR
HELPER.addReFramedModel("stair" , HELPER.auto(ReFramed.id("block/stair/straight"))); HELPER.addReFramedModel("stair" , HELPER.auto(ReFramed.id("block/stair/straight"), 13, EDGE));
HELPER.addReFramedModel("outers_stair" , HELPER.auto(ReFramed.id("block/stair/double_outer"))); HELPER.addReFramedModel("outers_stair" , HELPER.auto(ReFramed.id("block/stair/double_outer"), 24, EDGE, STAIR_SHAPE));
HELPER.addReFramedModel("inner_stair" , HELPER.auto(ReFramed.id("block/stair/inner"))); HELPER.addReFramedModel("inner_stair" , HELPER.auto(ReFramed.id("block/stair/inner"), 24, EDGE, STAIR_SHAPE));
HELPER.addReFramedModel("outer_stair" , HELPER.auto(ReFramed.id("block/stair/outer"))); HELPER.addReFramedModel("outer_stair" , HELPER.auto(ReFramed.id("block/stair/outer"), 16, EDGE, STAIR_SHAPE));
HELPER.addReFramedModel("outer_side_stair" , HELPER.auto(ReFramed.id("block/stair/outer_side"))); HELPER.addReFramedModel("outer_side_stair" , HELPER.auto(ReFramed.id("block/stair/outer_side"), 32, EDGE, STAIR_SHAPE));
// STAIRS_CUBE // STAIRS_CUBE
HELPER.addReFramedModel("stairs_cube" , HELPER.autoDouble(ReFramed.id("block/stair/straight"), ReFramed.id("block/stair/cube/straight"))); HELPER.addReFramedModel("stairs_cube" , HELPER.autoDouble(ReFramed.id("block/stair/straight"), ReFramed.id("block/stair/cube/straight"), 13, EDGE));
HELPER.addReFramedModel("outers_stairs_cube" , HELPER.autoDouble(ReFramed.id("block/stair/double_outer"), ReFramed.id("block/stair/cube/double_outer"))); HELPER.addReFramedModel("outers_stairs_cube" , HELPER.autoDouble(ReFramed.id("block/stair/double_outer"), ReFramed.id("block/stair/cube/double_outer"), 24, EDGE, STAIR_SHAPE));
HELPER.addReFramedModel("inner_stairs_cube" , HELPER.autoDouble(ReFramed.id("block/stair/inner"), ReFramed.id("block/stair/cube/inner"))); HELPER.addReFramedModel("inner_stairs_cube" , HELPER.autoDouble(ReFramed.id("block/stair/inner"), ReFramed.id("block/stair/cube/inner"), 24, EDGE, STAIR_SHAPE));
HELPER.addReFramedModel("outer_stairs_cube" , HELPER.autoDouble(ReFramed.id("block/stair/outer"), ReFramed.id("block/stair/cube/outer"))); HELPER.addReFramedModel("outer_stairs_cube" , HELPER.autoDouble(ReFramed.id("block/stair/outer"), ReFramed.id("block/stair/cube/outer"), 16, EDGE, STAIR_SHAPE));
HELPER.addReFramedModel("outer_side_stairs_cube" , HELPER.autoDouble(ReFramed.id("block/stair/outer_side"), ReFramed.id("block/stair/cube/outer_side"))); HELPER.addReFramedModel("outer_side_stairs_cube" , HELPER.autoDouble(ReFramed.id("block/stair/outer_side"), ReFramed.id("block/stair/cube/outer_side"), 32, EDGE, STAIR_SHAPE));
// HALF_STAIR // HALF_STAIR
HELPER.addReFramedModel("half_stair_down" , HELPER.auto(ReFramed.id("block/half_stair/down"))); HELPER.addReFramedModel("half_stair_down" , HELPER.auto(ReFramed.id("block/half_stair/down"), 9, CORNER, CORNER_FACE));
HELPER.addReFramedModel("half_stair_side" , HELPER.auto(ReFramed.id("block/half_stair/side"))); HELPER.addReFramedModel("half_stair_side" , HELPER.auto(ReFramed.id("block/half_stair/side"), 16, CORNER, CORNER_FACE));
// HALF_STAIRS_SLAB // HALF_STAIRS_SLAB
HELPER.addReFramedModel("half_stairs_slab_down" , HELPER.autoDouble(ReFramed.id("block/half_stair/down"), ReFramed.id("block/half_stair/slab/down"))); HELPER.addReFramedModel("half_stairs_slab_down" , HELPER.autoDouble(ReFramed.id("block/half_stair/down"), ReFramed.id("block/half_stair/slab/down"), 9, CORNER, CORNER_FACE));
HELPER.addReFramedModel("half_stairs_slab_side" , HELPER.autoDouble(ReFramed.id("block/half_stair/side"), ReFramed.id("block/half_stair/slab/side"))); HELPER.addReFramedModel("half_stairs_slab_side" , HELPER.autoDouble(ReFramed.id("block/half_stair/side"), ReFramed.id("block/half_stair/slab/side"), 16, CORNER, CORNER_FACE));
// HALF_STAIRS_STAIR // HALF_STAIRS_STAIR
HELPER.addReFramedModel("half_stairs_stair_down" , HELPER.autoDouble(ReFramed.id("block/half_stair/down"), ReFramed.id("block/half_stair/stair/down"))); HELPER.addReFramedModel("half_stairs_stair_down" , HELPER.autoDouble(ReFramed.id("block/half_stair/down"), ReFramed.id("block/half_stair/stair/down"), 5, EDGE));
HELPER.addReFramedModel("half_stairs_stair_side" , HELPER.autoDouble(ReFramed.id("block/half_stair/side"), ReFramed.id("block/half_stair/stair/side"))); HELPER.addReFramedModel("half_stairs_stair_side" , HELPER.autoDouble(ReFramed.id("block/half_stair/side"), ReFramed.id("block/half_stair/stair/side"), 6, EDGE));
HELPER.addReFramedModel("half_stairs_stair_reverse" , HELPER.autoDouble(ReFramed.id("block/half_stair/stair/side"), ReFramed.id("block/half_stair/side"))); HELPER.addReFramedModel("half_stairs_stair_reverse" , HELPER.autoDouble(ReFramed.id("block/half_stair/stair/side"), ReFramed.id("block/half_stair/side"), 2, EDGE));
// STEP // STEP
HELPER.addReFramedModel("step" , HELPER.auto(ReFramed.id("block/step/down"))); HELPER.addReFramedModel("step" , HELPER.auto(ReFramed.id("block/step/down"), 13, EDGE));
// STEPS_SLAB // STEPS_SLAB
HELPER.addReFramedModel("steps_slab" , HELPER.autoDouble(ReFramed.id("block/step/down"), ReFramed.id("block/step/slab/down"))); HELPER.addReFramedModel("steps_slab" , HELPER.autoDouble(ReFramed.id("block/step/down"), ReFramed.id("block/step/slab/down"), 5, FACING, AXIS));
HELPER.addReFramedModel("steps_slab_side" , HELPER.autoDouble(ReFramed.id("block/step/side"), ReFramed.id("block/step/slab/side"))); HELPER.addReFramedModel("steps_slab_side" , HELPER.autoDouble(ReFramed.id("block/step/side"), ReFramed.id("block/step/slab/side"), 8, FACING, AXIS));
// LAYER // LAYER
HELPER.addReFramedModel("layer_1" , HELPER.auto(new Identifier("block/snow_height2"))); HELPER.addReFramedModel("layer_1" , HELPER.auto(new Identifier("block/snow_height2"), 7, FACING));
HELPER.addReFramedModel("layer_2" , HELPER.auto(new Identifier("block/snow_height4"))); HELPER.addReFramedModel("layer_2" , HELPER.auto(new Identifier("block/snow_height4"), 6, FACING));
HELPER.addReFramedModel("layer_3" , HELPER.auto(new Identifier("block/snow_height6"))); HELPER.addReFramedModel("layer_3" , HELPER.auto(new Identifier("block/snow_height6"), 6, FACING));
HELPER.addReFramedModel("layer_4" , HELPER.auto(new Identifier("block/snow_height8"))); HELPER.addReFramedModel("layer_4" , HELPER.auto(new Identifier("block/snow_height8"), 6, FACING));
HELPER.addReFramedModel("layer_5" , HELPER.auto(new Identifier("block/snow_height10"))); HELPER.addReFramedModel("layer_5" , HELPER.auto(new Identifier("block/snow_height10"), 6, FACING));
HELPER.addReFramedModel("layer_6" , HELPER.auto(new Identifier("block/snow_height12"))); HELPER.addReFramedModel("layer_6" , HELPER.auto(new Identifier("block/snow_height12"), 6, FACING));
HELPER.addReFramedModel("layer_7" , HELPER.auto(new Identifier("block/snow_height14"))); HELPER.addReFramedModel("layer_7" , HELPER.auto(new Identifier("block/snow_height14"), 6, FACING));
HELPER.addReFramedModel("layer_8" , HELPER.auto(new Identifier("block/cube"))); HELPER.addReFramedModel("layer_8" , HELPER.auto(new Identifier("block/cube"), 1));
// PILLAR // PILLAR
HELPER.addReFramedModel("pillar" , HELPER.auto(ReFramed.id("block/pillar"))); HELPER.addReFramedModel("pillar" , HELPER.auto(ReFramed.id("block/pillar"), 4, AXIS));
// WALL // WALL
HELPER.addReFramedModel("wall_inventory" , HELPER.auto(ReFramed.id("block/wall/inventory/default"))); HELPER.addReFramedModel("wall_inventory" , HELPER.auto(ReFramed.id("block/wall/inventory/default"), 1));
// --------------------- pillar // --------------------- pillar
HELPER.addReFramedModel("wall_core" , HELPER.auto(ReFramed.id("block/wall/pillar/core"))); HELPER.addReFramedModel("wall_core" , HELPER.auto(ReFramed.id("block/wall/pillar/core"), 1, UP));
HELPER.addReFramedModel("wall_pillar_low" , HELPER.auto(ReFramed.id("block/wall/pillar/low"))); HELPER.addReFramedModel("wall_pillar_low" , HELPER.auto(ReFramed.id("block/wall/pillar/low"), 4, NORTH_WALL_SHAPE, EAST_WALL_SHAPE, SOUTH_WALL_SHAPE, WEST_WALL_SHAPE));
HELPER.addReFramedModel("wall_pillar_tall" , HELPER.auto(ReFramed.id("block/wall/pillar/tall"))); HELPER.addReFramedModel("wall_pillar_tall" , HELPER.auto(ReFramed.id("block/wall/pillar/tall"), 4, NORTH_WALL_SHAPE, EAST_WALL_SHAPE, SOUTH_WALL_SHAPE, WEST_WALL_SHAPE));
HELPER.addReFramedModel("wall_pillar_none" , HELPER.auto(ReFramed.id("block/wall/pillar/none"))); HELPER.addReFramedModel("wall_pillar_none" , HELPER.auto(ReFramed.id("block/wall/pillar/none"), 4, NORTH_WALL_SHAPE, EAST_WALL_SHAPE, SOUTH_WALL_SHAPE, WEST_WALL_SHAPE));
// --------------------- side // --------------------- side
HELPER.addReFramedModel("wall_side_low" , HELPER.auto(ReFramed.id("block/wall/side/low"))); HELPER.addReFramedModel("wall_side_low" , HELPER.auto(ReFramed.id("block/wall/side/low"), 92, NORTH_WALL_SHAPE, EAST_WALL_SHAPE, SOUTH_WALL_SHAPE, WEST_WALL_SHAPE));
HELPER.addReFramedModel("wall_side_tall" , HELPER.auto(ReFramed.id("block/wall/side/tall"))); HELPER.addReFramedModel("wall_side_tall" , HELPER.auto(ReFramed.id("block/wall/side/tall"), 92, NORTH_WALL_SHAPE, EAST_WALL_SHAPE, SOUTH_WALL_SHAPE, WEST_WALL_SHAPE));
// --------------------- junction // --------------------- junction
HELPER.addReFramedModel("wall_low_e" , HELPER.auto(ReFramed.id("block/wall/junction/low"))); HELPER.addReFramedModel("wall_low_e" , HELPER.auto(ReFramed.id("block/wall/junction/low"), 4, NORTH_WALL_SHAPE, EAST_WALL_SHAPE, SOUTH_WALL_SHAPE, WEST_WALL_SHAPE));
HELPER.addReFramedModel("wall_tall_e" , HELPER.auto(ReFramed.id("block/wall/junction/tall"))); HELPER.addReFramedModel("wall_tall_e" , HELPER.auto(ReFramed.id("block/wall/junction/tall"), 4, NORTH_WALL_SHAPE, EAST_WALL_SHAPE, SOUTH_WALL_SHAPE, WEST_WALL_SHAPE));
// --------------------- junction_i // --------------------- junction_i
HELPER.addReFramedModel("wall_low_i" , HELPER.auto(ReFramed.id("block/wall/junction/low_i"))); HELPER.addReFramedModel("wall_low_i" , HELPER.auto(ReFramed.id("block/wall/junction/low_i"), 4, NORTH_WALL_SHAPE, EAST_WALL_SHAPE, SOUTH_WALL_SHAPE, WEST_WALL_SHAPE));
HELPER.addReFramedModel("wall_tall_i" , HELPER.auto(ReFramed.id("block/wall/junction/tall_i"))); HELPER.addReFramedModel("wall_tall_i" , HELPER.auto(ReFramed.id("block/wall/junction/tall_i"), 4, NORTH_WALL_SHAPE, EAST_WALL_SHAPE, SOUTH_WALL_SHAPE, WEST_WALL_SHAPE));
HELPER.addReFramedModel("wall_low_tall_i" , HELPER.auto(ReFramed.id("block/wall/junction/low_tall_i"))); HELPER.addReFramedModel("wall_low_tall_i" , HELPER.auto(ReFramed.id("block/wall/junction/low_tall_i"), 4, NORTH_WALL_SHAPE, EAST_WALL_SHAPE, SOUTH_WALL_SHAPE, WEST_WALL_SHAPE));
// --------------------- junction_c // --------------------- junction_c
HELPER.addReFramedModel("wall_low_c" , HELPER.auto(ReFramed.id("block/wall/junction/low_c"))); HELPER.addReFramedModel("wall_low_c" , HELPER.auto(ReFramed.id("block/wall/junction/low_c"), 4, NORTH_WALL_SHAPE, EAST_WALL_SHAPE, SOUTH_WALL_SHAPE, WEST_WALL_SHAPE));
HELPER.addReFramedModel("wall_tall_c" , HELPER.auto(ReFramed.id("block/wall/junction/tall_c"))); HELPER.addReFramedModel("wall_tall_c" , HELPER.auto(ReFramed.id("block/wall/junction/tall_c"), 4, NORTH_WALL_SHAPE, EAST_WALL_SHAPE, SOUTH_WALL_SHAPE, WEST_WALL_SHAPE));
HELPER.addReFramedModel("wall_low_tall_c" , HELPER.auto(ReFramed.id("block/wall/junction/low_tall_c"))); HELPER.addReFramedModel("wall_low_tall_c" , HELPER.auto(ReFramed.id("block/wall/junction/low_tall_c"), 4, NORTH_WALL_SHAPE, EAST_WALL_SHAPE, SOUTH_WALL_SHAPE, WEST_WALL_SHAPE));
HELPER.addReFramedModel("wall_tall_low_c" , HELPER.auto(ReFramed.id("block/wall/junction/tall_low_c"))); HELPER.addReFramedModel("wall_tall_low_c" , HELPER.auto(ReFramed.id("block/wall/junction/tall_low_c"), 4, NORTH_WALL_SHAPE, EAST_WALL_SHAPE, SOUTH_WALL_SHAPE, WEST_WALL_SHAPE));
// --------------------- junction_t // --------------------- junction_t
HELPER.addReFramedModel("wall_low_t" , HELPER.auto(ReFramed.id("block/wall/junction/low_t"))); HELPER.addReFramedModel("wall_low_t" , HELPER.auto(ReFramed.id("block/wall/junction/low_t"), 4, NORTH_WALL_SHAPE, EAST_WALL_SHAPE, SOUTH_WALL_SHAPE, WEST_WALL_SHAPE));
HELPER.addReFramedModel("wall_tall_t" , HELPER.auto(ReFramed.id("block/wall/junction/tall_t"))); HELPER.addReFramedModel("wall_tall_t" , HELPER.auto(ReFramed.id("block/wall/junction/tall_t"), 4, NORTH_WALL_SHAPE, EAST_WALL_SHAPE, SOUTH_WALL_SHAPE, WEST_WALL_SHAPE));
HELPER.addReFramedModel("wall_tall_low_c_t" , HELPER.auto(ReFramed.id("block/wall/junction/tall_low_c_t"))); HELPER.addReFramedModel("wall_tall_low_c_t" , HELPER.auto(ReFramed.id("block/wall/junction/tall_low_c_t"), 4, NORTH_WALL_SHAPE, EAST_WALL_SHAPE, SOUTH_WALL_SHAPE, WEST_WALL_SHAPE));
HELPER.addReFramedModel("wall_tall_i_low_t" , HELPER.auto(ReFramed.id("block/wall/junction/tall_i_low_t"))); HELPER.addReFramedModel("wall_tall_i_low_t" , HELPER.auto(ReFramed.id("block/wall/junction/tall_i_low_t"), 4, NORTH_WALL_SHAPE, EAST_WALL_SHAPE, SOUTH_WALL_SHAPE, WEST_WALL_SHAPE));
HELPER.addReFramedModel("wall_low_i_tall_t" , HELPER.auto(ReFramed.id("block/wall/junction/low_i_tall_t"))); HELPER.addReFramedModel("wall_low_i_tall_t" , HELPER.auto(ReFramed.id("block/wall/junction/low_i_tall_t"), 4, NORTH_WALL_SHAPE, EAST_WALL_SHAPE, SOUTH_WALL_SHAPE, WEST_WALL_SHAPE));
HELPER.addReFramedModel("wall_low_tall_c_t" , HELPER.auto(ReFramed.id("block/wall/junction/low_tall_c_t"))); HELPER.addReFramedModel("wall_low_tall_c_t" , HELPER.auto(ReFramed.id("block/wall/junction/low_tall_c_t"), 4, NORTH_WALL_SHAPE, EAST_WALL_SHAPE, SOUTH_WALL_SHAPE, WEST_WALL_SHAPE));
HELPER.addReFramedModel("wall_low_c_tall_t" , HELPER.auto(ReFramed.id("block/wall/junction/low_c_tall_t"))); HELPER.addReFramedModel("wall_low_c_tall_t" , HELPER.auto(ReFramed.id("block/wall/junction/low_c_tall_t"), 4, NORTH_WALL_SHAPE, EAST_WALL_SHAPE, SOUTH_WALL_SHAPE, WEST_WALL_SHAPE));
HELPER.addReFramedModel("wall_tall_c_low_t" , HELPER.auto(ReFramed.id("block/wall/junction/tall_c_low_t"))); HELPER.addReFramedModel("wall_tall_c_low_t" , HELPER.auto(ReFramed.id("block/wall/junction/tall_c_low_t"), 4, NORTH_WALL_SHAPE, EAST_WALL_SHAPE, SOUTH_WALL_SHAPE, WEST_WALL_SHAPE));
// --------------------- junction_x // --------------------- junction_x
HELPER.addReFramedModel("wall_low_x" , HELPER.auto(ReFramed.id("block/wall/junction/low_x"))); HELPER.addReFramedModel("wall_low_x" , HELPER.auto(ReFramed.id("block/wall/junction/low_x"), 4, NORTH_WALL_SHAPE, EAST_WALL_SHAPE, SOUTH_WALL_SHAPE, WEST_WALL_SHAPE));
HELPER.addReFramedModel("wall_tall_x" , HELPER.auto(ReFramed.id("block/wall/junction/tall_x"))); HELPER.addReFramedModel("wall_tall_x" , HELPER.auto(ReFramed.id("block/wall/junction/tall_x"), 4, NORTH_WALL_SHAPE, EAST_WALL_SHAPE, SOUTH_WALL_SHAPE, WEST_WALL_SHAPE));
HELPER.addReFramedModel("wall_tall_i_low_i_x" , HELPER.auto(ReFramed.id("block/wall/junction/tall_i_low_i_x"))); HELPER.addReFramedModel("wall_tall_i_low_i_x" , HELPER.auto(ReFramed.id("block/wall/junction/tall_i_low_i_x"), 4, NORTH_WALL_SHAPE, EAST_WALL_SHAPE, SOUTH_WALL_SHAPE, WEST_WALL_SHAPE));
HELPER.addReFramedModel("wall_tall_low_t_x" , HELPER.auto(ReFramed.id("block/wall/junction/tall_low_t_x"))); HELPER.addReFramedModel("wall_tall_low_t_x" , HELPER.auto(ReFramed.id("block/wall/junction/tall_low_t_x"), 4, NORTH_WALL_SHAPE, EAST_WALL_SHAPE, SOUTH_WALL_SHAPE, WEST_WALL_SHAPE));
HELPER.addReFramedModel("wall_tall_c_low_c_x" , HELPER.auto(ReFramed.id("block/wall/junction/tall_c_low_c_x"))); HELPER.addReFramedModel("wall_tall_c_low_c_x" , HELPER.auto(ReFramed.id("block/wall/junction/tall_c_low_c_x"), 4, NORTH_WALL_SHAPE, EAST_WALL_SHAPE, SOUTH_WALL_SHAPE, WEST_WALL_SHAPE));
HELPER.addReFramedModel("wall_tall_t_low_x" , HELPER.auto(ReFramed.id("block/wall/junction/tall_t_low_x"))); HELPER.addReFramedModel("wall_tall_t_low_x" , HELPER.auto(ReFramed.id("block/wall/junction/tall_t_low_x"), 4, NORTH_WALL_SHAPE, EAST_WALL_SHAPE, SOUTH_WALL_SHAPE, WEST_WALL_SHAPE));
// PILLAR WALL
HELPER.addReFramedModel("pillars_wall_inventory" , HELPER.autoDouble(ReFramed.id("block/pillar"), ReFramed.id("block/wall/full/inventory/sides")));
HELPER.addReFramedModel("pillars_wall_low" , HELPER.autoDouble(ReFramed.id("block/wall/full/pillar/low"), ReFramed.id("block/wall/full/side/low")));
HELPER.addReFramedModel("pillars_wall_tall" , HELPER.autoDouble(ReFramed.id("block/wall/full/pillar/tall"), ReFramed.id("block/wall/full/side/tall")));
//item model assignments (in lieu of models/item/___.json) //item model assignments (in lieu of models/item/___.json)
@ -134,7 +134,6 @@ public class ReFramedClient implements ClientModInitializer {
HELPER.assignItemModel("steps_slab" , ReFramed.STEPS_SLAB); HELPER.assignItemModel("steps_slab" , ReFramed.STEPS_SLAB);
HELPER.assignItemModel("layer_1" , ReFramed.LAYER); HELPER.assignItemModel("layer_1" , ReFramed.LAYER);
HELPER.assignItemModel("pillar" , ReFramed.PILLAR); HELPER.assignItemModel("pillar" , ReFramed.PILLAR);
HELPER.assignItemModel("pillars_wall_inventory", ReFramed.PILLARS_WALL);
HELPER.assignItemModel("wall_inventory" , ReFramed.WALL); HELPER.assignItemModel("wall_inventory" , ReFramed.WALL);
} }

View File

@ -13,6 +13,7 @@ import net.minecraft.client.render.model.UnbakedModel;
import net.minecraft.client.texture.Sprite; import net.minecraft.client.texture.Sprite;
import net.minecraft.client.util.SpriteIdentifier; import net.minecraft.client.util.SpriteIdentifier;
import net.minecraft.item.ItemConvertible; import net.minecraft.item.ItemConvertible;
import net.minecraft.state.property.Property;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -27,18 +28,18 @@ public class ReFramedClientHelper {
private final ReFramedModelProvider prov; private final ReFramedModelProvider prov;
public UnbakedRetexturedModel auto(Identifier parent) { public UnbakedRetexturedModel auto(Identifier parent, int model_count, Property<?>... properties) {
return new UnbakedAutoRetexturedModel(parent); return new UnbakedAutoRetexturedModel(parent, model_count, properties);
} }
public UnbakedRetexturedModel json(Identifier parent) { public UnbakedRetexturedModel json(Identifier parent, int model_count, Property<?>... properties) {
return new UnbakedJsonRetexturedModel(parent); return new UnbakedJsonRetexturedModel(parent, model_count, properties);
} }
public UnbakedModel autoDouble(Identifier first, Identifier second) { public UnbakedModel autoDouble(Identifier first, Identifier second, int model_count, Property<?>... properties) {
return new UnbakedDoubleRetexturedModel( return new UnbakedDoubleRetexturedModel(
auto(first), auto(first, model_count, properties),
auto(second) auto(second, model_count, properties)
); );
} }

View File

@ -17,8 +17,8 @@ import java.util.function.Supplier;
@Environment(EnvType.CLIENT) @Environment(EnvType.CLIENT)
public class DoubleRetexturingBakedModel extends ForwardingBakedModel implements MultiRetexturableModel { public class DoubleRetexturingBakedModel extends ForwardingBakedModel implements MultiRetexturableModel {
private final RetexturingBakedModel model_1, model_2; private final ForwardingBakedModel model_1, model_2;
public DoubleRetexturingBakedModel(RetexturingBakedModel model_1, RetexturingBakedModel model_2) { public DoubleRetexturingBakedModel(ForwardingBakedModel model_1, ForwardingBakedModel model_2) {
this.wrapped = model_1.getWrappedModel(); this.wrapped = model_1.getWrappedModel();
this.model_1 = model_1; this.model_1 = model_1;
this.model_2 = model_2; this.model_2 = model_2;
@ -44,7 +44,7 @@ public class DoubleRetexturingBakedModel extends ForwardingBakedModel implements
} }
@Override @Override
public List<RetexturingBakedModel> models() { public List<ForwardingBakedModel> models() {
return List.of(model_1, model_2); return List.of(model_1, model_2);
} }
} }

View File

@ -1,8 +1,10 @@
package fr.adrien1106.reframed.client.model; package fr.adrien1106.reframed.client.model;
import net.fabricmc.fabric.api.renderer.v1.model.ForwardingBakedModel;
import java.util.List; import java.util.List;
public interface MultiRetexturableModel { public interface MultiRetexturableModel {
List<RetexturingBakedModel> models(); List<ForwardingBakedModel> models();
} }

View File

@ -20,28 +20,38 @@ import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.ModelBakeSettings; import net.minecraft.client.render.model.ModelBakeSettings;
import net.minecraft.client.texture.Sprite; import net.minecraft.client.texture.Sprite;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.state.property.Property;
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.math.random.Random; import net.minecraft.util.math.random.Random;
import net.minecraft.world.BlockRenderView; import net.minecraft.world.BlockRenderView;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Supplier; import java.util.function.Supplier;
import java.util.stream.Stream;
public abstract class RetexturingBakedModel extends ForwardingBakedModel { public abstract class RetexturingBakedModel extends ForwardingBakedModel {
public RetexturingBakedModel(BakedModel base_model, CamoAppearanceManager tam, int theme_index, ModelBakeSettings settings, BlockState item_state) { public RetexturingBakedModel(BakedModel base_model, CamoAppearanceManager tam, int theme_index, ModelBakeSettings settings, BlockState item_state, int model_count, Property<?>... properties) {
this.wrapped = base_model; //field from the superclass; vanilla getQuads etc. will delegate through to this this.wrapped = base_model; //field from the superclass; vanilla getQuads etc. will delegate through to this
this.appearance_manager = tam; this.appearance_manager = tam;
this.theme_index = theme_index; this.theme_index = theme_index;
this.uv_lock = settings.isUvLocked(); this.uv_lock = settings.isUvLocked();
this.item_state = item_state; this.item_state = item_state;
this.properties = properties;
BASE_MESH_CACHE = new Object2ObjectLinkedOpenHashMap<>(model_count, 0.25f) {
@Override
protected void rehash(int v) {}
};
} }
protected final CamoAppearanceManager appearance_manager; protected final CamoAppearanceManager appearance_manager;
protected final int theme_index; protected final int theme_index;
protected final boolean uv_lock; protected final boolean uv_lock;
protected final BlockState item_state; protected final BlockState item_state;
protected final Property<?>[] properties;
protected record MeshCacheKey(Object state_key, CamoAppearance appearance, int model_id) {} protected record MeshCacheKey(Object state_key, CamoAppearance appearance, int model_id) {}
/** cache that store retextured models */ /** cache that store retextured models */
@ -49,11 +59,7 @@ public abstract class RetexturingBakedModel extends ForwardingBakedModel {
protected final Cache<MeshCacheKey, Mesh> RETEXTURED_MESH_CACHE = CacheBuilder.newBuilder().maximumSize(256).build(); protected final Cache<MeshCacheKey, Mesh> RETEXTURED_MESH_CACHE = CacheBuilder.newBuilder().maximumSize(256).build();
/** cache that stores the base meshes which has the size of the amount of models */ /** cache that stores the base meshes which has the size of the amount of models */
protected final Object2ObjectLinkedOpenHashMap<Object, Mesh> BASE_MESH_CACHE = protected final Object2ObjectLinkedOpenHashMap<Object, Mesh> BASE_MESH_CACHE;
new Object2ObjectLinkedOpenHashMap<>(2, 0.25f) {
@Override
protected void rehash(int v) {}
};
protected static final Direction[] DIRECTIONS_AND_NULL; protected static final Direction[] DIRECTIONS_AND_NULL;
static { static {
@ -82,18 +88,15 @@ public abstract class RetexturingBakedModel extends ForwardingBakedModel {
return appearance_manager.getDefaultAppearance(theme_index).getSprites(Direction.UP, 0).get(0).sprite(); return appearance_manager.getDefaultAppearance(theme_index).getSprites(Direction.UP, 0).get(0).sprite();
} }
public int getThemeIndex() {
return theme_index;
}
@Override @Override
public void emitBlockQuads(BlockRenderView world, BlockState state, BlockPos pos, Supplier<Random> randomSupplier, RenderContext context) { public void emitBlockQuads(BlockRenderView world, BlockState state, BlockPos pos, Supplier<Random> randomSupplier, RenderContext context) {
BlockState theme = (world.getBlockEntity(pos) instanceof ThemeableBlockEntity s) ? s.getTheme(theme_index) : null; BlockState theme = (world.getBlockEntity(pos) instanceof ThemeableBlockEntity s) ? s.getTheme(theme_index) : null;
QuadEmitter quad_emitter = context.getEmitter(); QuadEmitter quad_emitter = context.getEmitter();
List<?> model_key = Stream.of(properties).map(state::get).toList();
if(theme == null || theme.isAir()) { if(theme == null || theme.isAir()) {
getRetexturedMesh( getRetexturedMesh(
new MeshCacheKey( new MeshCacheKey(
hashCode(), model_key,
appearance_manager.getDefaultAppearance(theme_index), appearance_manager.getDefaultAppearance(theme_index),
0 0
), ),
@ -109,7 +112,7 @@ public abstract class RetexturingBakedModel extends ForwardingBakedModel {
if (camo instanceof WeightedComputedAppearance wca) model_id = wca.getAppearanceIndex(seed); if (camo instanceof WeightedComputedAppearance wca) model_id = wca.getAppearanceIndex(seed);
int tint = 0xFF000000 | MinecraftClient.getInstance().getBlockColors().getColor(theme, world, pos, 0); int tint = 0xFF000000 | MinecraftClient.getInstance().getBlockColors().getColor(theme, world, pos, 0);
MeshCacheKey key = new MeshCacheKey(hashCode(), camo, model_id); MeshCacheKey key = new MeshCacheKey(model_key, camo, model_id);
// do not clutter the cache with single-use meshes // do not clutter the cache with single-use meshes
Mesh untintedMesh = camo.hashCode() == -1 ? transformMesh(key, state) : getRetexturedMesh(key, state); Mesh untintedMesh = camo.hashCode() == -1 ? transformMesh(key, state) : getRetexturedMesh(key, state);
@ -151,13 +154,6 @@ public abstract class RetexturingBakedModel extends ForwardingBakedModel {
} }
} }
public boolean useAmbientOcclusion(BlockRenderView view, BlockPos pos) {
if (!(view.getBlockEntity(pos) instanceof ThemeableBlockEntity frame_entity)) return false;
CamoAppearance appearance = appearance_manager
.getCamoAppearance(view, frame_entity.getTheme(theme_index), pos, theme_index, false);
return appearance.getAO(theme_index);
}
protected Mesh getRetexturedMesh(MeshCacheKey key, BlockState state) { protected Mesh getRetexturedMesh(MeshCacheKey key, BlockState state) {
if (RETEXTURED_MESH_CACHE.asMap().containsKey(key)) return RETEXTURED_MESH_CACHE.getIfPresent(key); if (RETEXTURED_MESH_CACHE.asMap().containsKey(key)) return RETEXTURED_MESH_CACHE.getIfPresent(key);
Mesh mesh = transformMesh(key, state); Mesh mesh = transformMesh(key, state);

View File

@ -14,6 +14,7 @@ import net.minecraft.client.render.model.Baker;
import net.minecraft.client.render.model.ModelBakeSettings; import net.minecraft.client.render.model.ModelBakeSettings;
import net.minecraft.client.texture.Sprite; import net.minecraft.client.texture.Sprite;
import net.minecraft.client.util.SpriteIdentifier; import net.minecraft.client.util.SpriteIdentifier;
import net.minecraft.state.property.Property;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import net.minecraft.util.math.Direction; import net.minecraft.util.math.Direction;
import net.minecraft.util.math.random.Random; import net.minecraft.util.math.random.Random;
@ -23,8 +24,8 @@ import java.util.function.Function;
public class UnbakedAutoRetexturedModel extends UnbakedRetexturedModel { public class UnbakedAutoRetexturedModel extends UnbakedRetexturedModel {
public UnbakedAutoRetexturedModel(Identifier parent) { public UnbakedAutoRetexturedModel(Identifier parent, int state_count, Property<?>... properties) {
super(parent); super(parent, state_count, properties);
item_state = Blocks.AIR.getDefaultState(); item_state = Blocks.AIR.getDefaultState();
} }
@ -36,7 +37,9 @@ public class UnbakedAutoRetexturedModel extends UnbakedRetexturedModel {
ReFramedClient.HELPER.getCamoAppearanceManager(texture_getter), ReFramedClient.HELPER.getCamoAppearanceManager(texture_getter),
theme_index, theme_index,
bake_settings, bake_settings,
item_state item_state,
state_count,
properties
) { ) {
protected Mesh convertModel(BlockState state) { protected Mesh convertModel(BlockState state) {
Renderer r = ReFramedClient.HELPER.getFabricRenderer(); Renderer r = ReFramedClient.HELPER.getFabricRenderer();

View File

@ -1,5 +1,6 @@
package fr.adrien1106.reframed.client.model; package fr.adrien1106.reframed.client.model;
import net.fabricmc.fabric.api.renderer.v1.model.ForwardingBakedModel;
import net.minecraft.client.render.model.BakedModel; import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.Baker; import net.minecraft.client.render.model.Baker;
import net.minecraft.client.render.model.ModelBakeSettings; import net.minecraft.client.render.model.ModelBakeSettings;
@ -40,8 +41,8 @@ public class UnbakedDoubleRetexturedModel implements UnbakedModel {
@Override @Override
public BakedModel bake(Baker baker, Function<SpriteIdentifier, Sprite> texture_getter, ModelBakeSettings model_bake_settings, Identifier identifier) { public BakedModel bake(Baker baker, Function<SpriteIdentifier, Sprite> texture_getter, ModelBakeSettings model_bake_settings, Identifier identifier) {
return new DoubleRetexturingBakedModel( return new DoubleRetexturingBakedModel(
(RetexturingBakedModel) model_1.bake(baker, texture_getter, model_bake_settings, identifier), (ForwardingBakedModel) model_1.bake(baker, texture_getter, model_bake_settings, identifier),
(RetexturingBakedModel) model_2.bake(baker, texture_getter, model_bake_settings, identifier) (ForwardingBakedModel) model_2.bake(baker, texture_getter, model_bake_settings, identifier)
); );
} }
} }

View File

@ -15,6 +15,7 @@ import net.minecraft.client.render.model.ModelBakeSettings;
import net.minecraft.client.texture.Sprite; import net.minecraft.client.texture.Sprite;
import net.minecraft.client.util.SpriteIdentifier; import net.minecraft.client.util.SpriteIdentifier;
import net.minecraft.screen.PlayerScreenHandler; import net.minecraft.screen.PlayerScreenHandler;
import net.minecraft.state.property.Property;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import net.minecraft.util.math.Direction; import net.minecraft.util.math.Direction;
import net.minecraft.util.math.random.Random; import net.minecraft.util.math.random.Random;
@ -24,8 +25,8 @@ import java.util.Objects;
import java.util.function.Function; import java.util.function.Function;
public class UnbakedJsonRetexturedModel extends UnbakedRetexturedModel { public class UnbakedJsonRetexturedModel extends UnbakedRetexturedModel {
public UnbakedJsonRetexturedModel(Identifier parent) { public UnbakedJsonRetexturedModel(Identifier parent, int state_count, Property<?>... properties) {
super(parent); super(parent, state_count, properties);
} }
@Nullable @Nullable
@ -44,7 +45,9 @@ public class UnbakedJsonRetexturedModel extends UnbakedRetexturedModel {
ReFramedClient.HELPER.getCamoAppearanceManager(spriteLookup), ReFramedClient.HELPER.getCamoAppearanceManager(spriteLookup),
theme_index, theme_index,
bake_settings, bake_settings,
item_state item_state,
state_count,
properties
) { ) {
protected Mesh convertModel(BlockState state) { protected Mesh convertModel(BlockState state) {
Renderer r = ReFramedClient.HELPER.getFabricRenderer(); Renderer r = ReFramedClient.HELPER.getFabricRenderer();

View File

@ -2,6 +2,7 @@ package fr.adrien1106.reframed.client.model;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.client.render.model.UnbakedModel; import net.minecraft.client.render.model.UnbakedModel;
import net.minecraft.state.property.Property;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import java.util.Collection; import java.util.Collection;
@ -14,9 +15,13 @@ public abstract class UnbakedRetexturedModel implements UnbakedModel {
protected int theme_index = 1; protected int theme_index = 1;
protected BlockState item_state; protected BlockState item_state;
protected final int state_count;
protected final Property<?>[] properties;
public UnbakedRetexturedModel(Identifier parent) { public UnbakedRetexturedModel(Identifier parent, int state_count, Property<?>... properties) {
this.parent = parent; this.parent = parent;
this.state_count = state_count;
this.properties = properties;
} }
public UnbakedRetexturedModel setThemeIndex(int theme_index) { public UnbakedRetexturedModel setThemeIndex(int theme_index) {

View File

@ -5,7 +5,6 @@ import com.google.common.cache.CacheBuilder;
import fr.adrien1106.reframed.block.ReFramedBlock; import fr.adrien1106.reframed.block.ReFramedBlock;
import fr.adrien1106.reframed.client.ReFramedClient; import fr.adrien1106.reframed.client.ReFramedClient;
import fr.adrien1106.reframed.client.model.QuadPosBounds; import fr.adrien1106.reframed.client.model.QuadPosBounds;
import fr.adrien1106.reframed.client.model.RetexturingBakedModel;
import fr.adrien1106.reframed.util.blocks.ThemeableBlockEntity; import fr.adrien1106.reframed.util.blocks.ThemeableBlockEntity;
import net.fabricmc.api.EnvType; import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment; import net.fabricmc.api.Environment;
@ -33,18 +32,18 @@ import static net.minecraft.util.shape.VoxelShapes.combine;
public class RenderHelper { public class RenderHelper {
// self culling cache of the models not made thread local so that it is only computed once // self culling cache of the models not made thread local so that it is only computed once
private static final Cache<CullElement, Integer[]> INNER_CULL_MAP = CacheBuilder.newBuilder().build(); private static final Cache<CullElement, Integer[]> INNER_CULL_MAP = CacheBuilder.newBuilder().maximumSize(1024).build();
private record CullElement(Block block, Object state_key, int model) {} private record CullElement(Block block, Object state_key, int model) {}
/** /**
* compute which quad might cull with another model quad * compute which quad might cull with another model quad
* @param state - the state of the model * @param state - the state of the model
* @param models - list of models on the same block * @param models - list of models on the same block
* @param hash - the hash of main model
*/ */
public static void computeInnerCull(BlockState state, List<RetexturingBakedModel> models, int hash) { public static void computeInnerCull(BlockState state, List<ForwardingBakedModel> models) {
if (!(state.getBlock() instanceof ReFramedBlock frame_block)) return; if (!(state.getBlock() instanceof ReFramedBlock frame_block)) return;
if (INNER_CULL_MAP.asMap().containsKey(new CullElement(frame_block, hash, 1))) return; Object key = frame_block.getModelCacheKey(state);
if (INNER_CULL_MAP.asMap().containsKey(new CullElement(frame_block, key, 1))) return;
Renderer r = ReFramedClient.HELPER.getFabricRenderer(); Renderer r = ReFramedClient.HELPER.getFabricRenderer();
QuadEmitter quad_emitter = r.meshBuilder().getEmitter(); QuadEmitter quad_emitter = r.meshBuilder().getEmitter();
@ -74,15 +73,15 @@ public class RenderHelper {
} }
} }
} }
INNER_CULL_MAP.put(new CullElement(frame_block, hash, self_id), cull_array); INNER_CULL_MAP.put(new CullElement(frame_block, key, self_id), cull_array);
} }
} }
public static boolean shouldDrawInnerFace(BlockState state, BlockRenderView view, BlockPos pos, int quad_index, int theme_index, int hash) { public static boolean shouldDrawInnerFace(BlockState state, BlockRenderView view, BlockPos pos, int quad_index, int theme_index) {
if ( !(state.getBlock() instanceof ReFramedBlock frame_block) if ( !(state.getBlock() instanceof ReFramedBlock frame_block)
|| !(view.getBlockEntity(pos) instanceof ThemeableBlockEntity frame_entity) || !(view.getBlockEntity(pos) instanceof ThemeableBlockEntity frame_entity)
) return true; ) return true;
CullElement key = new CullElement(frame_block, hash, theme_index); CullElement key = new CullElement(frame_block, frame_block.getModelCacheKey(state), theme_index);
if (!INNER_CULL_MAP.asMap().containsKey(key)) return true; if (!INNER_CULL_MAP.asMap().containsKey(key)) return true;
// needs to be Integer object because array is initialized with null not 0 // needs to be Integer object because array is initialized with null not 0

View File

@ -14,11 +14,9 @@ import java.util.Map;
public class RebakedModel implements BakedModel { public class RebakedModel implements BakedModel {
protected final Map<Direction, List<BakedQuad>> face_quads; protected final Map<Direction, List<BakedQuad>> face_quads;
protected boolean ambient_occlusion;
public RebakedModel(Map<Direction, List<BakedQuad>> face_quads, boolean ambient_occlusion) { public RebakedModel(Map<Direction, List<BakedQuad>> face_quads) {
this.face_quads = face_quads; this.face_quads = face_quads;
this.ambient_occlusion = ambient_occlusion;
} }
@Override @Override
@ -28,7 +26,7 @@ public class RebakedModel implements BakedModel {
@Override @Override
public boolean useAmbientOcclusion() { public boolean useAmbientOcclusion() {
return ambient_occlusion; return true;
} }
@Override @Override

View File

@ -16,8 +16,7 @@ import java.util.concurrent.CompletableFuture;
public class GBlockTag extends BlockTagProvider { public class GBlockTag extends BlockTagProvider {
private static final Map<Class<? extends Block>, TagGetter> providers = new HashMap<>(); private static final Map<Class<? extends Block>, TagGetter> providers = new HashMap<>();
static { static {
providers.put(ReFramedPillarsWallBlock.class, new PillarsWall()); providers.put(ReframedWallBlock.class, new Wall());
providers.put(ReFramedWallBlock.class, new Wall());
} }
public GBlockTag(FabricDataOutput output, CompletableFuture<WrapperLookup> registries) { public GBlockTag(FabricDataOutput output, CompletableFuture<WrapperLookup> registries) {

View File

@ -32,8 +32,7 @@ public class GBlockstate extends FabricModelProvider {
providers.put(ReFramedStairsCubeBlock.class, new StairsCube()); providers.put(ReFramedStairsCubeBlock.class, new StairsCube());
providers.put(ReFramedStepBlock.class, new Step()); providers.put(ReFramedStepBlock.class, new Step());
providers.put(ReFramedStepsSlabBlock.class, new StepsSlab()); providers.put(ReFramedStepsSlabBlock.class, new StepsSlab());
providers.put(ReFramedPillarsWallBlock.class, new PillarsWall()); providers.put(ReframedWallBlock.class, new Wall());
providers.put(ReFramedWallBlock.class, new Wall());
} }
public GBlockstate(FabricDataOutput output) { public GBlockstate(FabricDataOutput output) {

View File

@ -34,8 +34,7 @@ public class GRecipe extends FabricRecipeProvider {
providers.put(ReFramedStairsCubeBlock.class, new StairsCube()); providers.put(ReFramedStairsCubeBlock.class, new StairsCube());
providers.put(ReFramedStepBlock.class, new Step()); providers.put(ReFramedStepBlock.class, new Step());
providers.put(ReFramedStepsSlabBlock.class, new StepsSlab()); providers.put(ReFramedStepsSlabBlock.class, new StepsSlab());
providers.put(ReFramedPillarsWallBlock.class, new PillarsWall()); providers.put(ReframedWallBlock.class, new Wall());
providers.put(ReFramedWallBlock.class, new Wall());
providers.put(ReFramedBlueprintItem.class, new Blueprint()); providers.put(ReFramedBlueprintItem.class, new Blueprint());
providers.put(ReFramedHammerItem.class, new Hammer()); providers.put(ReFramedHammerItem.class, new Hammer());
providers.put(ReFramedScrewdriverItem.class, new Screwdriver()); providers.put(ReFramedScrewdriverItem.class, new Screwdriver());

View File

@ -1,82 +0,0 @@
package fr.adrien1106.reframed.generator.block;
import fr.adrien1106.reframed.ReFramed;
import fr.adrien1106.reframed.generator.BlockStateProvider;
import fr.adrien1106.reframed.generator.GBlockstate;
import fr.adrien1106.reframed.generator.RecipeSetter;
import fr.adrien1106.reframed.generator.TagGetter;
import net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider;
import net.minecraft.block.Block;
import net.minecraft.data.client.BlockStateSupplier;
import net.minecraft.data.client.MultipartBlockStateSupplier;
import net.minecraft.data.server.recipe.RecipeExporter;
import net.minecraft.data.server.recipe.RecipeProvider;
import net.minecraft.data.server.recipe.ShapelessRecipeJsonBuilder;
import net.minecraft.item.ItemConvertible;
import net.minecraft.recipe.book.RecipeCategory;
import net.minecraft.registry.tag.BlockTags;
import net.minecraft.registry.tag.TagKey;
import net.minecraft.util.Identifier;
import java.util.List;
import static net.minecraft.block.enums.WallShape.*;
import static net.minecraft.data.client.VariantSettings.Rotation.*;
import static net.minecraft.state.property.Properties.*;
public class PillarsWall implements RecipeSetter, TagGetter, BlockStateProvider {
@Override
public void setRecipe(RecipeExporter exporter, ItemConvertible convertible) {
RecipeProvider.offerStonecuttingRecipe(exporter, RecipeCategory.BUILDING_BLOCKS, convertible, ReFramed.CUBE, 1);
ShapelessRecipeJsonBuilder
.create(RecipeCategory.BUILDING_BLOCKS, convertible, 2)
.input(ReFramed.WALL, 2)
.criterion(FabricRecipeProvider.hasItem(ReFramed.CUBE), FabricRecipeProvider.conditionsFromItem(ReFramed.CUBE))
.criterion(FabricRecipeProvider.hasItem(convertible), FabricRecipeProvider.conditionsFromItem(convertible))
.offerTo(exporter);
}
@Override
public List<TagKey<Block>> getTags() {
return List.of(BlockTags.WALLS);
}
@Override
public BlockStateSupplier getMultipart(Block block) {
Identifier
low = ReFramed.id("pillars_wall_low_special"),
tall = ReFramed.id("pillars_wall_tall_special"),
none = ReFramed.id("wall_pillar_none_special");
return MultipartBlockStateSupplier.create(block)
// PILLAR CORE
.with(GBlockstate.variant(ReFramed.id("wall_core_special"), true, R0, R0))
// LOW
.with(GBlockstate.when(NORTH_WALL_SHAPE, LOW),
GBlockstate.variant(low, true, R0, R0))
.with(GBlockstate.when(EAST_WALL_SHAPE, LOW),
GBlockstate.variant(low, true, R0, R90))
.with(GBlockstate.when(SOUTH_WALL_SHAPE, LOW),
GBlockstate.variant(low, true, R0, R180))
.with(GBlockstate.when(WEST_WALL_SHAPE, LOW),
GBlockstate.variant(low, true, R0, R270))
// TALL
.with(GBlockstate.when(NORTH_WALL_SHAPE, TALL),
GBlockstate.variant(tall, true, R0, R0))
.with(GBlockstate.when(EAST_WALL_SHAPE, TALL),
GBlockstate.variant(tall, true, R0, R90))
.with(GBlockstate.when(SOUTH_WALL_SHAPE, TALL),
GBlockstate.variant(tall, true, R0, R180))
.with(GBlockstate.when(WEST_WALL_SHAPE, TALL),
GBlockstate.variant(tall, true, R0, R270))
// PILLAR NONE
.with(GBlockstate.when(NORTH_WALL_SHAPE, NONE),
GBlockstate.variant(none, true, R0, R0))
.with(GBlockstate.when(EAST_WALL_SHAPE, NONE),
GBlockstate.variant(none, true, R0, R90))
.with(GBlockstate.when(SOUTH_WALL_SHAPE, NONE),
GBlockstate.variant(none, true, R0, R180))
.with(GBlockstate.when(WEST_WALL_SHAPE, NONE),
GBlockstate.variant(none, true, R0, R270));
}
}

View File

@ -32,8 +32,6 @@ public abstract class AthenaBakedModelMixin implements DynamicBakedModel, BakedM
@Shadow(remap = false) @Final private Int2ObjectMap<Sprite> textures; @Shadow(remap = false) @Final private Int2ObjectMap<Sprite> textures;
@Shadow public abstract boolean useAmbientOcclusion();
/** /**
* Reuses the emitQuad method to compute the quads to be used by the frame * Reuses the emitQuad method to compute the quads to be used by the frame
* *
@ -79,6 +77,6 @@ public abstract class AthenaBakedModelMixin implements DynamicBakedModel, BakedM
})); }));
}); });
return new RebakedModel(face_quads, useAmbientOcclusion()); return new RebakedModel(face_quads);
} }
} }

View File

@ -89,6 +89,6 @@ public abstract class ContinuityCTMBakedModelMixin extends ForwardingBakedModel
transform.getProcessingContext().reset(); // reset instead of outputting to emitter transform.getProcessingContext().reset(); // reset instead of outputting to emitter
transform.invokeReset(); transform.invokeReset();
return new RebakedModel(face_quads, useAmbientOcclusion()); return new RebakedModel(face_quads);
} }
} }

View File

@ -24,6 +24,6 @@ public abstract class IndiumAbstractBlockRenderContextMixin {
private boolean shouldDrawInnerQuad(AbstractBlockRenderContext instance, Direction face, @Local(argsOnly = true) MutableQuadViewImpl quad) { private boolean shouldDrawInnerQuad(AbstractBlockRenderContext instance, Direction face, @Local(argsOnly = true) MutableQuadViewImpl quad) {
if (face != null || quad.tag() == 0 || !(blockInfo instanceof IBlockRenderInfoMixin info) || info.getThemeIndex() == 0) return isFaceCulled(face); if (face != null || quad.tag() == 0 || !(blockInfo instanceof IBlockRenderInfoMixin info) || info.getThemeIndex() == 0) return isFaceCulled(face);
return !RenderHelper.shouldDrawInnerFace(blockInfo.blockState, blockInfo.blockView, blockInfo.blockPos, quad.tag() >>> 8, info.getThemeIndex(), info.getModelHash()); return !RenderHelper.shouldDrawInnerFace(blockInfo.blockState, blockInfo.blockView, blockInfo.blockPos, quad.tag() >>> 8, info.getThemeIndex());
} }
} }

View File

@ -19,7 +19,6 @@ import org.spongepowered.asm.mixin.injection.Redirect;
public abstract class IndiumTerrainBlockRenderInfoMixin extends BlockRenderInfo implements IBlockRenderInfoMixin { public abstract class IndiumTerrainBlockRenderInfoMixin extends BlockRenderInfo implements IBlockRenderInfoMixin {
@Unique private int theme_index = 0; @Unique private int theme_index = 0;
@Unique private int model_hash = 0;
@Redirect( @Redirect(
method = "shouldDrawFaceInner", method = "shouldDrawFaceInner",
@ -37,9 +36,8 @@ public abstract class IndiumTerrainBlockRenderInfoMixin extends BlockRenderInfo
} }
@Override @Override
public void prepareForBlock(BlockState blockState, BlockPos blockPos, long seed, boolean modelAo, int theme_index, int model_hash) { public void prepareForBlock(BlockState blockState, BlockPos blockPos, long seed, boolean modelAo, int theme_index) {
this.theme_index = theme_index; this.theme_index = theme_index;
this.model_hash = model_hash;
prepareForBlock(blockState, blockPos, seed, modelAo); prepareForBlock(blockState, blockPos, seed, modelAo);
} }
@ -47,9 +45,4 @@ public abstract class IndiumTerrainBlockRenderInfoMixin extends BlockRenderInfo
public int getThemeIndex() { public int getThemeIndex() {
return theme_index; return theme_index;
} }
@Override
public int getModelHash() {
return model_hash;
}
} }

View File

@ -1,19 +1,15 @@
package fr.adrien1106.reframed.mixin.compat; package fr.adrien1106.reframed.mixin.compat;
import fr.adrien1106.reframed.client.model.MultiRetexturableModel; import fr.adrien1106.reframed.client.model.MultiRetexturableModel;
import fr.adrien1106.reframed.client.model.RetexturingBakedModel;
import fr.adrien1106.reframed.client.util.RenderHelper; import fr.adrien1106.reframed.client.util.RenderHelper;
import fr.adrien1106.reframed.util.mixin.IBlockRenderInfoMixin; import fr.adrien1106.reframed.util.mixin.IBlockRenderInfoMixin;
import fr.adrien1106.reframed.util.mixin.IMultipartBakedModelMixin; import fr.adrien1106.reframed.util.mixin.IMultipartBakedModelMixin;
import link.infra.indium.renderer.aocalc.AoCalculator;
import link.infra.indium.renderer.render.AbstractBlockRenderContext; import link.infra.indium.renderer.render.AbstractBlockRenderContext;
import link.infra.indium.renderer.render.BlockRenderInfo;
import link.infra.indium.renderer.render.TerrainRenderContext; import link.infra.indium.renderer.render.TerrainRenderContext;
import me.jellysquid.mods.sodium.client.render.chunk.compile.pipeline.BlockRenderContext; import me.jellysquid.mods.sodium.client.render.chunk.compile.pipeline.BlockRenderContext;
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext; import net.fabricmc.fabric.api.renderer.v1.model.ForwardingBakedModel;
import net.minecraft.client.render.model.BakedModel; import net.minecraft.client.render.model.BakedModel;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@ -32,34 +28,18 @@ public abstract class IndiumTerrainRenderContextMixin extends AbstractBlockRende
), remap = false, ), remap = false,
cancellable = true) cancellable = true)
private void renderMultipleModels(BlockRenderContext ctx, CallbackInfo ci) { private void renderMultipleModels(BlockRenderContext ctx, CallbackInfo ci) {
if (!(ctx.model() instanceof IMultipartBakedModelMixin wrapped)) return; if (!(ctx.model() instanceof IMultipartBakedModelMixin wrapped)
List<BakedModel> models = wrapped.getModels(ctx.state()); || !(wrapped.getModel(ctx.state()) instanceof MultiRetexturableModel retexturing_model)) return;
if (models.stream().noneMatch(bakedModel ->
bakedModel instanceof MultiRetexturableModel
|| bakedModel instanceof RetexturingBakedModel
)) return;
models.forEach(model -> { List<ForwardingBakedModel> models = retexturing_model.models();
if (model instanceof MultiRetexturableModel multi_model) { RenderHelper.computeInnerCull(ctx.state(), models);
RenderHelper.computeInnerCull(ctx.state(), multi_model.models(), model.hashCode()); int i = 0;
multi_model.models().forEach(rexteruable_model -> for (BakedModel model : models) {
renderModel(ctx, rexteruable_model, aoCalc, blockInfo, this, model.hashCode()) i++;
); aoCalc.clear();
} else if (model instanceof RetexturingBakedModel rexteruable_model) ((IBlockRenderInfoMixin) blockInfo).prepareForBlock(ctx.state(), ctx.pos(), ctx.seed(), model.useAmbientOcclusion(), i);
renderModel(ctx, rexteruable_model, aoCalc, blockInfo, this, model.hashCode()); model.emitBlockQuads(blockInfo.blockView, blockInfo.blockState, blockInfo.blockPos, blockInfo.randomSupplier, this);
else model.emitBlockQuads(blockInfo.blockView, blockInfo.blockState, blockInfo.blockPos, blockInfo.randomSupplier, this); }
});
ci.cancel(); ci.cancel();
} }
@Unique
private static void renderModel(BlockRenderContext ctx, RetexturingBakedModel model, AoCalculator aoCalc, BlockRenderInfo block_info, RenderContext context, int model_hash) {
aoCalc.clear();
((IBlockRenderInfoMixin) block_info).prepareForBlock(
ctx.state(), ctx.pos(), ctx.seed(),
model.useAmbientOcclusion(block_info.blockView, ctx.pos()),
model.getThemeIndex(), model_hash
);
model.emitBlockQuads(block_info.blockView, block_info.blockState, block_info.blockPos, block_info.randomSupplier, context);
}
} }

View File

@ -29,12 +29,8 @@ public abstract class AbstractBlockRenderContextMixin {
) )
) )
private boolean shouldDrawInnerQuad(AbstractBlockRenderContext instance, Direction face, @Local(argsOnly = true) MutableQuadViewImpl quad) { private boolean shouldDrawInnerQuad(AbstractBlockRenderContext instance, Direction face, @Local(argsOnly = true) MutableQuadViewImpl quad) {
if (face != null if (face != null || quad.tag() == 0 || !(blockInfo instanceof IBlockRenderInfoMixin info) || info.getThemeIndex() == 0) return isFaceCulled(face);
|| quad.tag() == 0
|| !(blockInfo instanceof IBlockRenderInfoMixin info)
|| info.getThemeIndex() == 0
) return isFaceCulled(face);
return !RenderHelper.shouldDrawInnerFace(blockInfo.blockState, blockInfo.blockView, blockInfo.blockPos, quad.tag() >>> 8, info.getThemeIndex(), info.getModelHash()); return !RenderHelper.shouldDrawInnerFace(blockInfo.blockState, blockInfo.blockView, blockInfo.blockPos, quad.tag() >>> 8, info.getThemeIndex());
} }
} }

View File

@ -25,7 +25,6 @@ public abstract class BlockRenderInfoMixin implements IBlockRenderInfoMixin {
@Shadow public BlockRenderView blockView; @Shadow public BlockRenderView blockView;
@Unique private int theme_index = 0; @Unique private int theme_index = 0;
@Unique private int model_hash = 0;
@ModifyArg(method = "prepareForBlock", @ModifyArg(method = "prepareForBlock",
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/RenderLayers;" + at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/RenderLayers;" +
@ -43,9 +42,8 @@ public abstract class BlockRenderInfoMixin implements IBlockRenderInfoMixin {
@Override @Override
@Unique @Unique
public void prepareForBlock(BlockState state, BlockPos pos, boolean ao, int theme_index, int model_hash) { public void prepareForBlock(BlockState state, BlockPos pos, boolean ao, int theme_index) {
this.theme_index = theme_index; this.theme_index = theme_index;
this.model_hash = model_hash;
prepareForBlock(state, pos, ao); prepareForBlock(state, pos, ao);
} }
@ -53,9 +51,4 @@ public abstract class BlockRenderInfoMixin implements IBlockRenderInfoMixin {
public int getThemeIndex() { public int getThemeIndex() {
return theme_index; return theme_index;
} }
@Override
public int getModelHash() {
return model_hash;
}
} }

View File

@ -19,7 +19,7 @@ public class MultipartBakedModelMixin implements IMultipartBakedModelMixin {
@Shadow @Final private List<Pair<Predicate<BlockState>, BakedModel>> components; @Shadow @Final private List<Pair<Predicate<BlockState>, BakedModel>> components;
@Override @Override
public List<BakedModel> getModels(BlockState state) { public BakedModel getModel(BlockState state) {
return components.stream().map(pair -> pair.getLeft().test(state) ? pair.getRight(): null).filter(Objects::nonNull).toList(); return components.stream().map(pair -> pair.getLeft().test(state) ? pair.getRight(): null).filter(Objects::nonNull).findAny().orElse(null);
} }
} }

View File

@ -1,21 +1,17 @@
package fr.adrien1106.reframed.mixin.render; package fr.adrien1106.reframed.mixin.render;
import fr.adrien1106.reframed.client.model.MultiRetexturableModel; import fr.adrien1106.reframed.client.model.MultiRetexturableModel;
import fr.adrien1106.reframed.client.model.RetexturingBakedModel;
import fr.adrien1106.reframed.client.util.RenderHelper; import fr.adrien1106.reframed.client.util.RenderHelper;
import fr.adrien1106.reframed.util.mixin.IBlockRenderInfoMixin; import fr.adrien1106.reframed.util.mixin.IBlockRenderInfoMixin;
import fr.adrien1106.reframed.util.mixin.IMultipartBakedModelMixin; import fr.adrien1106.reframed.util.mixin.IMultipartBakedModelMixin;
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext; import net.fabricmc.fabric.api.renderer.v1.model.ForwardingBakedModel;
import net.fabricmc.fabric.impl.client.indigo.renderer.aocalc.AoCalculator;
import net.fabricmc.fabric.impl.client.indigo.renderer.render.AbstractBlockRenderContext; import net.fabricmc.fabric.impl.client.indigo.renderer.render.AbstractBlockRenderContext;
import net.fabricmc.fabric.impl.client.indigo.renderer.render.BlockRenderInfo;
import net.fabricmc.fabric.impl.client.indigo.renderer.render.TerrainRenderContext; import net.fabricmc.fabric.impl.client.indigo.renderer.render.TerrainRenderContext;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.client.render.model.BakedModel; import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.util.math.MatrixStack; import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@ -31,34 +27,18 @@ public abstract class TerrainRenderContextMixin extends AbstractBlockRenderConte
), remap = false, ), remap = false,
cancellable = true) cancellable = true)
private void renderMultipleModels(BlockState state, BlockPos pos, BakedModel wrapper, MatrixStack matrixStack, CallbackInfo ci) { private void renderMultipleModels(BlockState state, BlockPos pos, BakedModel wrapper, MatrixStack matrixStack, CallbackInfo ci) {
if (!(wrapper instanceof IMultipartBakedModelMixin wrapped)) return; if (!(wrapper instanceof IMultipartBakedModelMixin wrapped)
List<BakedModel> models = wrapped.getModels(state); || !(wrapped.getModel(state) instanceof MultiRetexturableModel retexturing_model)) return;
if (models.stream().noneMatch(bakedModel ->
bakedModel instanceof MultiRetexturableModel
|| bakedModel instanceof RetexturingBakedModel
)) return;
models.forEach(model -> { List<ForwardingBakedModel> models = retexturing_model.models();
if (model instanceof MultiRetexturableModel multi_model) { RenderHelper.computeInnerCull(state, models);
RenderHelper.computeInnerCull(state, multi_model.models(), model.hashCode()); int i = 0;
multi_model.models().forEach(retexturable_model -> for (BakedModel model : models) {
renderModel(state, retexturable_model, pos, aoCalc, blockInfo, this, model.hashCode()) i++;
); aoCalc.clear();
} else if (model instanceof RetexturingBakedModel retexturable_model) ((IBlockRenderInfoMixin) blockInfo).prepareForBlock(state, pos, model.useAmbientOcclusion(), i);
renderModel(state, retexturable_model, pos, aoCalc, blockInfo, this, model.hashCode()); model.emitBlockQuads(blockInfo.blockView, blockInfo.blockState, blockInfo.blockPos, blockInfo.randomSupplier, this);
else model.emitBlockQuads(blockInfo.blockView, blockInfo.blockState, blockInfo.blockPos, blockInfo.randomSupplier, this); }
});
ci.cancel(); ci.cancel();
} }
@Unique
private static void renderModel(BlockState state, RetexturingBakedModel model, BlockPos pos, AoCalculator aoCalc, BlockRenderInfo block_info, RenderContext context, int model_hash) {
aoCalc.clear();
((IBlockRenderInfoMixin) block_info).prepareForBlock(
state, pos,
model.useAmbientOcclusion(block_info.blockView, pos),
model.getThemeIndex(), model_hash
);
model.emitBlockQuads(block_info.blockView, block_info.blockState, block_info.blockPos, block_info.randomSupplier, context);
}
} }

View File

@ -5,11 +5,9 @@ import net.minecraft.util.math.BlockPos;
public interface IBlockRenderInfoMixin { public interface IBlockRenderInfoMixin {
void prepareForBlock(BlockState state, BlockPos pos, boolean ao, int theme_index, int model_hash); void prepareForBlock(BlockState state, BlockPos pos, boolean ao, int theme_index);
void prepareForBlock(BlockState state, BlockPos pos, long seed, boolean ao, int theme_index, int model_hash); void prepareForBlock(BlockState state, BlockPos pos, long seed, boolean ao, int theme_index);
int getThemeIndex(); int getThemeIndex();
int getModelHash();
} }

View File

@ -3,9 +3,7 @@ package fr.adrien1106.reframed.util.mixin;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.client.render.model.BakedModel; import net.minecraft.client.render.model.BakedModel;
import java.util.List;
public interface IMultipartBakedModelMixin { public interface IMultipartBakedModelMixin {
List<BakedModel> getModels(BlockState state); BakedModel getModel(BlockState state);
} }

View File

@ -1,33 +0,0 @@
{
"credit": "Made with Blockbench",
"parent": "block/block",
"textures": {
"particle": "#side"
},
"elements": [
{
"from": [5, 0, 0],
"to": [11, 14, 4],
"faces": {
"north": {"uv": [5, 2, 11, 16], "texture": "#side", "cullface": "north"},
"east": {"uv": [12, 2, 16, 16], "texture": "#side"},
"south": {"uv": [5, 2, 11, 16], "texture": "#side"},
"west": {"uv": [0, 2, 4, 16], "texture": "#side"},
"up": {"uv": [5, 0, 11, 4], "texture": "#top"},
"down": {"uv": [5, 12, 11, 16], "texture": "#bottom"}
}
},
{
"from": [5, 0, 12],
"to": [11, 14, 16],
"faces": {
"north": {"uv": [5, 2, 11, 16], "texture": "#side"},
"east": {"uv": [0, 2, 4, 16], "texture": "#side"},
"south": {"uv": [5, 2, 11, 16], "texture": "#side", "cullface": "south"},
"west": {"uv": [12, 2, 16, 16], "texture": "#side"},
"up": {"uv": [5, 12, 11, 16], "texture": "#top"},
"down": {"uv": [5, 0, 11, 4], "texture": "#bottom"}
}
}
]
}