11 Commits
dev ... v1.5.7

Author SHA1 Message Date
44f03b2c96 Merge pull request 'New minor version with fix for caching on dynamic models' (#12) from dev into master
All checks were successful
deploy / deploy (push) Successful in 5m25s
Reviewed-on: #12
2024-04-15 20:58:47 +02:00
f1af00738e Merge pull request 'version 1.5.6 fix for server imports + support for continuity and MoreCulling compat' (#11) from dev into master
All checks were successful
deploy / deploy (push) Successful in 5m44s
Reviewed-on: #11
2024-03-25 16:33:09 +01:00
186cca3e27 Merge pull request 'v1.5 new shapes + self culling + caching + coding tools/cleanup' (#10) from dev into master
All checks were successful
deploy / deploy (push) Successful in 5m42s
Reviewed-on: #10
2024-03-14 22:30:29 +01:00
d43d9456ee Merge pull request 'moved and created data generation for all elements other than models + removed block that aren't working' (#9) from dev into master
All checks were successful
deploy / deploy (push) Successful in 5m48s
Reviewed-on: #9
2024-03-05 21:56:03 +01:00
2957a899db Merge pull request 'Sound support + OffHand camo.' (#8) from dev into master
All checks were successful
deploy / deploy (push) Successful in 5m6s
Reviewed-on: #8
2024-03-04 17:04:13 +01:00
f3578a4da5 Merge pull request 'Indium suppor + github runner' (#7) from dev into master
Some checks failed
deploy / deploy (push) Failing after 5m3s
Reviewed-on: #7
2024-03-03 21:34:52 +01:00
28ae110e14 Merge pull request 'Double frames' (#6) from dev into master
All checks were successful
deploy / deploy (push) Successful in 5m14s
Reviewed-on: #6
2024-03-02 02:02:47 +01:00
6dc0cf7fdf Merge pull request 'Athena support + stair improvements + coloration' (#5) from dev into master
All checks were successful
deploy / deploy (push) Successful in 5m13s
Reviewed-on: #5
2024-02-26 17:05:24 +01:00
b30177a5c7 Merge pull request 'Fix mixin trying to inject code in server not available (because the class is client only)' (#3) from dev into master
All checks were successful
deploy / deploy (push) Successful in 4m57s
Reviewed-on: #3
2024-02-17 22:31:39 +01:00
1e132c71ef Merge pull request 'Add data generation before publishing' (#2) from dev into master
All checks were successful
deploy / deploy (push) Successful in 3m56s
Reviewed-on: #2
2024-02-16 22:29:53 +01:00
0233b3fa49 Merge pull request '1.0-SNAPSHOT' (#1) from dev into master
All checks were successful
deploy / deploy (push) Successful in 3m23s
Reviewed-on: #1
2024-02-16 21:50:02 +01:00
215 changed files with 908 additions and 8900 deletions

View File

@@ -21,7 +21,16 @@ or based on preferences add the person(s) to the project
### What Shapes are planed to be added
Currently, the list of shapes to be added is pretty simple as the mod is still under development:
- Wall
- Fence
- Pane
- Button
- Pressure Plate
- Trapdoor
- Door
- Carpet
- Post
- Half Slab (maybe redundant with Layer)
- Slabs Stair (a stair with one end being of a second theme, might be done in multiple blocks)
Any Ideas feel free to make a suggestion [here](https://github.com/DriHut/ReFramed/issues).

View File

@@ -4,7 +4,7 @@ import fr.altarik.CreateTag
plugins {
id "com.modrinth.minotaur" version "2.+"
id 'fabric-loom' version "${loom_version}"
id 'fabric-loom' version '1.5-SNAPSHOT'
id 'maven-publish'
}
@@ -36,9 +36,9 @@ base {
sourceSets {
main {
resources {
srcDirs += [
srcDirs += {
'src/generated'
]
}
}
}
}
@@ -84,9 +84,6 @@ repositories {
includeGroup "maven.modrinth"
}
}
maven {
url = "https://jitpack.io"
}
mavenCentral()
// Add repositories to retrieve artifacts from in here.
@@ -109,11 +106,11 @@ dependencies {
// modRuntimeOnly "maven.modrinth:indium:${project.indium_version}+mc${project.minecraft_version}"
// modRuntimeOnly "maven.modrinth:sodium:mc${project.minecraft_version}-${project.sodium_version}"
// Athena for connected textures
// Athena for connected texture
modCompileOnly "earth.terrarium.athena:athena-fabric-${project.minecraft_version}:${project.athena_version}"
modRuntimeOnly "earth.terrarium.athena:athena-fabric-${project.minecraft_version}:${project.athena_version}"
// Continuity for connected textures
// Continuity for connectedTextures
modCompileOnly "maven.modrinth:continuity:${project.continuity_version}"
modRuntimeOnly "maven.modrinth:continuity:${project.continuity_version}"
@@ -121,10 +118,6 @@ dependencies {
modRuntimeOnly "com.teamresourceful.resourcefullib:resourcefullib-fabric-${project.minecraft_version}:2.4.7"
modRuntimeOnly "earth.terrarium.chipped:Chipped-fabric-${project.minecraft_version}:3.1.2"
// Axiom for blueprint support
modCompileOnly "maven.modrinth:N6n5dqoA:YxeYxQyz"
modCompileOnly "com.github.moulberry:AxiomClientAPI:1.0.5.3"
// Fabric API.
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
}
@@ -207,8 +200,8 @@ publishing {
modrinth {
token = getEnv("MODRINTH_TOKEN", local.getProperty("modrinth_token"))
projectId = project.modrinth_id
versionNumber = "${project.mod_version}-${project.minecraft_version}"
versionName = "${project.archives_base_name} ${project.mod_version}-${project.minecraft_version}"
versionNumber = project.mod_version
versionName = "${project.archives_base_name} ${project.mod_version}"
versionType = project.mod_version.endsWith('SNAPSHOT') ? 'beta' : 'release'
uploadFile = remapJar
gameVersions = [project.minecraft_version]

View File

@@ -5,19 +5,18 @@ org.gradle.jvmargs=-Xmx1G
# check these on https://modmuss50.me/fabric.html
minecraft_version=1.20.4
yarn_mappings=1.20.4+build.3
loader_version=0.17.2
loader_version=0.15.6
# Mod Properties
modrinth_id = jCpoCBpn
mod_version = 1.6.9-SNAPSHOT
mod_version = 1.5.7
maven_group = fr.adrien1106
archives_base_name = ReFramed
mod_id = reframed
# Dependencies
# check this on https://modmuss50.me/fabric.html
fabric_version=0.97.3+1.20.4
loom_version=1.11-SNAPSHOT
fabric_version=0.95.4+1.20.4
git_owner=Altarik
git_repo=ReFramed

View File

@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-9.1.0-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME

View File

@@ -7,6 +7,7 @@ import fr.adrien1106.reframed.item.ReFramedBlueprintWrittenItem;
import fr.adrien1106.reframed.item.ReFramedScrewdriverItem;
import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.itemgroup.v1.FabricItemGroup;
import net.fabricmc.fabric.api.object.builder.v1.block.entity.FabricBlockEntityTypeBuilder;
import net.minecraft.block.AbstractBlock;
import net.minecraft.block.Block;
import net.minecraft.block.Blocks;
@@ -27,28 +28,17 @@ import java.util.stream.Stream;
import static fr.adrien1106.reframed.util.blocks.BlockProperties.LIGHT;
/**
* TODO Dynamic Ambient Occlusion -> not scheduled
* TODO better connected textures -> not scheduled
* TODO Dynamic Ambient Occlusion -> for v1.6
* TODO add minecraft models like wall fence etc -> for v1.6
* TODO better connected textures -> maybe v1.6 ?
* TODO support continuity overlays -> not scheduled
* TODO slopes -> thinking about it
* TODO better state caching per models (e.g. wall only has 3 max per model) -> not scheduled
*/
public class ReFramed implements ModInitializer {
public static final String MODID = "reframed";
public static final ArrayList<Block> BLOCKS = new ArrayList<>();
public static ReFramedBlock
CUBE,
SMALL_CUBE, SMALL_CUBES_STEP,
STAIR, STAIRS_CUBE,
HALF_STAIR, HALF_STAIRS_SLAB, HALF_STAIRS_STAIR, HALF_STAIRS_CUBE_STAIR, HALF_STAIRS_STEP_STAIR,
SLAB, SLABS_CUBE, SLABS_STAIR, SLABS_OUTER_STAIR, SLABS_INNER_STAIR, SLABS_HALF_LAYER, SLABS_LAYER,
HALF_SLAB, HALF_SLABS_SLAB,
STEP, STEPS_SLAB, STEPS_CROSS, STEPS_HALF_LAYER,
LAYER, HALF_LAYER,
PILLAR, PILLARS_WALL, WALL,
PANE, TRAPDOOR, DOOR,
BUTTON,
POST, POST_FENCE, FENCE;
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 Item HAMMER, SCREWDRIVER, BLUEPRINT, BLUEPRINT_WRITTEN;
@@ -62,50 +52,29 @@ public class ReFramed implements ModInitializer {
@Override
public void onInitialize() {
CUBE = registerBlock("cube" , new ReFramedBlock(cp(Blocks.OAK_PLANKS)));
SMALL_CUBE = registerBlock("small_cube" , new ReFramedSmallCubeBlock(cp(Blocks.OAK_PLANKS)));
SMALL_CUBES_STEP = registerBlock("small_cubes_step" , new ReFramedSmallCubesStepBlock(cp(Blocks.OAK_PLANKS)));
STAIR = registerBlock("stair" , new ReFramedStairBlock(cp(Blocks.OAK_STAIRS)));
STAIRS_CUBE = registerBlock("stairs_cube" , new ReFramedStairsCubeBlock(cp(Blocks.OAK_STAIRS)));
HALF_STAIR = registerBlock("half_stair" , new ReFramedHalfStairBlock(cp(Blocks.OAK_STAIRS)));
HALF_STAIRS_SLAB = registerBlock("half_stairs_slab" , new ReFramedHalfStairsSlabBlock(cp(Blocks.OAK_STAIRS)));
HALF_STAIRS_STAIR = registerBlock("half_stairs_stair" , new ReFramedHalfStairsStairBlock(cp(Blocks.OAK_STAIRS)));
HALF_STAIRS_CUBE_STAIR = registerBlock("half_stairs_cube_stair" , new ReFramedHalfStairsCubeStairBlock(cp(Blocks.OAK_STAIRS)));
HALF_STAIRS_STEP_STAIR = registerBlock("half_stairs_step_stair" , new ReFramedHalfStairsStepStairBlock(cp(Blocks.OAK_STAIRS)));
LAYER = registerBlock("layer" , new ReFramedLayerBlock(cp(Blocks.OAK_SLAB)));
HALF_LAYER = registerBlock("half_layer" , new ReFramedHalfLayerBlock(cp(Blocks.OAK_SLAB)));
SLAB = registerBlock("slab" , new ReFramedSlabBlock(cp(Blocks.OAK_SLAB)));
SLABS_CUBE = registerBlock("slabs_cube" , new ReFramedSlabsCubeBlock(cp(Blocks.OAK_SLAB)));
SLABS_STAIR = registerBlock("slabs_stair" , new ReFramedSlabsStairBlock(cp(Blocks.OAK_STAIRS)));
SLABS_OUTER_STAIR = registerBlock("slabs_outer_stair" , new ReFramedSlabsOuterStairBlock(cp(Blocks.OAK_STAIRS)));
SLABS_INNER_STAIR = registerBlock("slabs_inner_stair" , new ReFramedSlabsInnerStairBlock(cp(Blocks.OAK_STAIRS)));
SLABS_HALF_LAYER = registerBlock("slabs_half_layer" , new ReFramedSlabsHalfLayerBlock(cp(Blocks.OAK_SLAB)));
SLABS_LAYER = registerBlock("slabs_layer" , new ReFramedSlabsLayerBlock(cp(Blocks.OAK_SLAB)));
HALF_SLAB = registerBlock("half_slab" , new ReFramedHalfSlabBlock(cp(Blocks.OAK_SLAB)));
HALF_SLABS_SLAB = registerBlock("half_slabs_slab" , new ReFramedHalfSlabsSlabBlock(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_CROSS = registerBlock("steps_cross" , new ReFramedStepsCrossBlock(cp(Blocks.OAK_SLAB)));
STEPS_HALF_LAYER = registerBlock("steps_half_layer" , new ReFramedStepsHalfLayerBlock(cp(Blocks.OAK_SLAB)));
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)));
PANE = registerBlock("pane" , new ReFramedPaneBlock(cp(Blocks.OAK_FENCE)));
TRAPDOOR = registerBlock("trapdoor" , new ReFramedTrapdoorBlock(cp(Blocks.OAK_TRAPDOOR)));
DOOR = registerBlock("door" , new ReFramedDoorBlock(cp(Blocks.OAK_DOOR)));
BUTTON = registerBlock("button" , new ReFramedButtonBlock(cp(Blocks.OAK_BUTTON)));
POST = registerBlock("post" , new ReFramedPostBlock(cp(Blocks.OAK_FENCE)));
FENCE = registerBlock("fence" , new ReFramedFenceBlock(cp(Blocks.OAK_FENCE)));
POST_FENCE = registerBlock("post_fence" , new ReFramedPostFenceBlock(cp(Blocks.OAK_FENCE)));
HAMMER = registerItem("hammer" , new ReFramedHammerItem(new Item.Settings().maxCount(1)));
SCREWDRIVER = registerItem("screwdriver" , new ReFramedScrewdriverItem(new Item.Settings().maxCount(1)));
BLUEPRINT = registerItem("blueprint" , new ReFramedBlueprintItem(new Item.Settings()));
BLUEPRINT_WRITTEN = registerItem("blueprint_written" , new ReFramedBlueprintWrittenItem(new Item.Settings().maxCount(1)));
CUBE = registerBlock("cube" , new ReFramedBlock(cp(Blocks.OAK_PLANKS)));
SMALL_CUBE = registerBlock("small_cube" , new ReFramedSmallCubeBlock(cp(Blocks.OAK_PLANKS)));
SMALL_CUBES_STEP = registerBlock("small_cubes_step" , new ReFramedSmallCubesStepBlock(cp(Blocks.OAK_PLANKS)));
STAIR = registerBlock("stair" , new ReFramedStairBlock(cp(Blocks.OAK_STAIRS)));
STAIRS_CUBE = registerBlock("stairs_cube" , new ReFramedStairsCubeBlock(cp(Blocks.OAK_STAIRS)));
HALF_STAIR = registerBlock("half_stair" , new ReFramedHalfStairBlock(cp(Blocks.OAK_STAIRS)));
HALF_STAIRS_SLAB = registerBlock("half_stairs_slab" , new ReFramedHalfStairsSlabBlock(cp(Blocks.OAK_STAIRS)));
HALF_STAIRS_STAIR = registerBlock("half_stairs_stair" , new ReFramedHalfStairsStairBlock(cp(Blocks.OAK_STAIRS)));
LAYER = registerBlock("layer" , new ReFramedLayerBlock(cp(Blocks.OAK_SLAB)));
SLAB = registerBlock("slab" , new ReFramedSlabBlock(cp(Blocks.OAK_SLAB)));
SLABS_CUBE = registerBlock("slabs_cube" , new ReFramedSlabsCubeBlock(cp(Blocks.OAK_SLAB)));
STEP = registerBlock("step" , new ReFramedStepBlock(cp(Blocks.OAK_SLAB)));
STEPS_SLAB = registerBlock("steps_slab" , new ReFramedStepsSlabBlock(cp(Blocks.OAK_SLAB)));
PILLAR = registerBlock("pillar" , new ReFramedPillarBlock(cp(Blocks.OAK_FENCE)));
WALL = registerBlock("wall" , new ReframedWallBlock(cp(Blocks.OAK_FENCE)));
HAMMER = registerItem("hammer" , new ReFramedHammerItem(new Item.Settings().maxCount(1)));
SCREWDRIVER = registerItem("screwdriver" , new ReFramedScrewdriverItem(new Item.Settings().maxCount(1)));
BLUEPRINT = registerItem("blueprint" , new ReFramedBlueprintItem(new Item.Settings()));
BLUEPRINT_WRITTEN = registerItem("blueprint_written" , new ReFramedBlueprintWrittenItem(new Item.Settings().maxCount(1)));
REFRAMED_BLOCK_ENTITY = Registry.register(Registries.BLOCK_ENTITY_TYPE, id("camo"),
BlockEntityType.Builder.create(
FabricBlockEntityTypeBuilder.create(
(pos, state) -> new ReFramedEntity(REFRAMED_BLOCK_ENTITY, pos, state),
BLOCKS.stream()
.filter(block -> !(block instanceof ReFramedDoubleBlock))
@@ -113,7 +82,7 @@ public class ReFramed implements ModInitializer {
);
REFRAMED_DOUBLE_BLOCK_ENTITY = Registry.register(Registries.BLOCK_ENTITY_TYPE, id("double_camo"),
BlockEntityType.Builder.create(
FabricBlockEntityTypeBuilder.create(
(pos, state) -> new ReFramedDoubleEntity(REFRAMED_DOUBLE_BLOCK_ENTITY, pos, state),
BLOCKS.stream()
.filter(block -> block instanceof ReFramedDoubleBlock)
@@ -135,11 +104,11 @@ public class ReFramed implements ModInitializer {
private static AbstractBlock.Settings cp(Block base) {
return AbstractBlock.Settings.copy(base)
.luminance(state -> state.contains(LIGHT) && state.get(LIGHT) ? 15 : 0)
.nonOpaque()
.sounds(BlockSoundGroup.WOOD)
.hardness(0.2f)
.suffocates(Blocks::never)
.solidBlock(Blocks::always);
// .blockVision(Blocks::always);
.suffocates((a,b,c) -> false)
.blockVision((a,b,c) -> false);
}
private static <I extends Item> I registerItem(String path, I item) {

View File

@@ -1,100 +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.item.ItemPlacementContext;
import net.minecraft.state.StateManager;
import net.minecraft.state.property.BooleanProperty;
import net.minecraft.util.BlockMirror;
import net.minecraft.util.BlockRotation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.world.BlockView;
import net.minecraft.world.World;
import net.minecraft.world.WorldAccess;
import org.apache.commons.lang3.function.TriFunction;
import org.jetbrains.annotations.Nullable;
import static net.minecraft.state.property.Properties.*;
import static net.minecraft.state.property.Properties.SOUTH;
public abstract class ConnectingReFramedBlock extends WaterloggableReFramedBlock {
public ConnectingReFramedBlock(Settings settings) {
super(settings);
setDefaultState(getDefaultState()
.with(EAST, false)
.with(NORTH, false)
.with(WEST, false)
.with(SOUTH, false)
);
}
@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(builder.add(EAST, NORTH, SOUTH, WEST));
}
@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;
return placementState(new_state, world, pos, this::connectsTo);
}
@Override
public @Nullable BlockState getPlacementState(ItemPlacementContext ctx) {
BlockState state = super.getPlacementState(ctx);
World world = ctx.getWorld();
BlockPos pos = ctx.getBlockPos();
return placementState(state, world, pos, this::connectsTo);
}
@Override
@SuppressWarnings("deprecation")
public BlockState rotate(BlockState state, BlockRotation rotation) {
return Direction.Type.HORIZONTAL.stream().reduce(state, (s, dir) ->
s.with(getConnectionProperty(rotation.rotate(dir)), state.get(getConnectionProperty(dir)))
, (prev, next) -> next);
}
@Override
@SuppressWarnings("deprecation")
public BlockState mirror(BlockState state, BlockMirror mirror) {
return Direction.Type.HORIZONTAL.stream().reduce(state, (s, dir) ->
s.with(getConnectionProperty(mirror.apply(dir)), state.get(getConnectionProperty(dir)))
, (prev, next) -> next);
}
protected abstract boolean connectsTo(BlockState state, boolean fs, Direction dir);
@Override
@SuppressWarnings("deprecation")
public abstract VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context);
public static BooleanProperty getConnectionProperty(Direction dir) {
return switch (dir) {
case NORTH -> NORTH;
case EAST -> EAST;
case SOUTH -> SOUTH;
case WEST -> WEST;
default -> null;
};
}
public static BlockState placementState(BlockState state, BlockView world, BlockPos pos, TriFunction<BlockState, Boolean, Direction, Boolean> connectsTo) {
for (Direction dir: Direction.Type.HORIZONTAL) {
BlockState neighbor = world.getBlockState(pos.offset(dir));
state = state.with(getConnectionProperty(dir), connectsTo.apply(
neighbor,
neighbor.isSideSolidFullSquare(world, pos.offset(dir), dir.getOpposite()),
dir
));
}
return state;
}
}

View File

@@ -1,70 +0,0 @@
package fr.adrien1106.reframed.block;
import fr.adrien1106.reframed.util.blocks.BlockHelper;
import fr.adrien1106.reframed.util.blocks.Corner;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.ShapeContext;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.state.StateManager;
import net.minecraft.util.BlockMirror;
import net.minecraft.util.BlockRotation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.world.BlockView;
import org.jetbrains.annotations.Nullable;
import static fr.adrien1106.reframed.util.blocks.BlockProperties.CORNER;
import static fr.adrien1106.reframed.util.blocks.BlockProperties.CORNER_FACE;
public abstract class CornerDoubleReFramedBlock extends WaterloggableReFramedDoubleBlock {
public CornerDoubleReFramedBlock(Settings settings) {
super(settings);
setDefaultState(getDefaultState().with(CORNER, Corner.NORTH_EAST_DOWN).with(CORNER_FACE, 0));
}
@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(builder.add(CORNER,CORNER_FACE));
}
@Override
public @Nullable BlockState getPlacementState(ItemPlacementContext ctx) {
Corner corner = BlockHelper.getPlacementCorner(ctx);
return super.getPlacementState(ctx)
.with(CORNER, corner)
.with(CORNER_FACE, corner.getDirectionIndex(ctx.getSide().getOpposite()));
}
@Override
@SuppressWarnings("deprecation")
public abstract VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context);
@Override
@SuppressWarnings("deprecation")
public BlockState rotate(BlockState state, BlockRotation rotation) {
Corner corner = state.get(CORNER);
Direction face = corner.getDirection(state.get(CORNER_FACE));
corner = corner.rotate(rotation);
return state
.with(CORNER, corner)
.with(CORNER_FACE, corner.getDirectionIndex(rotation.rotate(face)));
}
@Override
@SuppressWarnings("deprecation")
public BlockState mirror(BlockState state, BlockMirror mirror) {
Corner corner = state.get(CORNER);
Direction face = corner.getDirection(state.get(CORNER_FACE));
corner = corner.mirror(mirror);
return state
.with(CORNER, corner)
.with(CORNER_FACE, corner.getDirectionIndex(mirror.apply(face)));
}
@Override
public abstract VoxelShape getShape(BlockState state, int i);
}

View File

@@ -1,64 +0,0 @@
package fr.adrien1106.reframed.block;
import fr.adrien1106.reframed.util.blocks.BlockHelper;
import fr.adrien1106.reframed.util.blocks.Edge;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.ShapeContext;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.state.StateManager;
import net.minecraft.util.BlockMirror;
import net.minecraft.util.BlockRotation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.world.BlockView;
import org.jetbrains.annotations.Nullable;
import static fr.adrien1106.reframed.util.blocks.BlockProperties.EDGE;
import static fr.adrien1106.reframed.util.blocks.BlockProperties.EDGE_FACE;
public abstract class EdgeDoubleReFramedBlock extends WaterloggableReFramedDoubleBlock {
public EdgeDoubleReFramedBlock(Settings settings) {
super(settings);
setDefaultState(getDefaultState().with(EDGE, Edge.NORTH_DOWN).with(EDGE_FACE, 0));
}
@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(builder.add(EDGE, EDGE_FACE));
}
@Override
public @Nullable BlockState getPlacementState(ItemPlacementContext ctx) {
Edge edge = BlockHelper.getPlacementEdge(ctx);
return super.getPlacementState(ctx)
.with(EDGE, edge)
.with(EDGE_FACE, edge.getDirectionIndex(ctx.getSide().getOpposite()));
}
@Override
@SuppressWarnings("deprecation")
public abstract VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context);
@Override
@SuppressWarnings("deprecation")
public BlockState rotate(BlockState state, BlockRotation rotation) {
Edge edge = state.get(EDGE).rotate(rotation);
Direction face = state.get(EDGE).getDirection(state.get(EDGE_FACE));
return state.with(EDGE, edge).with(EDGE_FACE, edge.getDirectionIndex(rotation.rotate(face)));
}
@Override
@SuppressWarnings("deprecation")
public BlockState mirror(BlockState state, BlockMirror mirror) {
Edge edge = state.get(EDGE).mirror(mirror);
Direction face = state.get(EDGE).getDirection(state.get(EDGE_FACE));
return state.with(EDGE, edge).with(EDGE_FACE, edge.getDirectionIndex(mirror.apply(face)));
}
@Override
public abstract VoxelShape getShape(BlockState state, int i);
}

View File

@@ -1,57 +0,0 @@
package fr.adrien1106.reframed.block;
import net.minecraft.block.AbstractBlock;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.ShapeContext;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.state.StateManager;
import net.minecraft.util.BlockMirror;
import net.minecraft.util.BlockRotation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.world.BlockView;
import org.jetbrains.annotations.Nullable;
import static net.minecraft.state.property.Properties.FACING;
public abstract class FacingDoubleReFramedBlock extends WaterloggableReFramedDoubleBlock {
public FacingDoubleReFramedBlock(AbstractBlock.Settings settings) {
super(settings);
setDefaultState(getDefaultState().with(FACING, Direction.DOWN));
}
@Override
protected void appendProperties(StateManager.Builder< Block, BlockState > builder) {
super.appendProperties(builder.add(FACING));
}
@Override
public @Nullable BlockState getPlacementState(ItemPlacementContext ctx) {
return super.getPlacementState(ctx)
.with(FACING, ctx.getSide().getOpposite());
}
@Override
@SuppressWarnings("deprecation")
public abstract VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context);
@Override
@SuppressWarnings("deprecation")
public BlockState rotate(BlockState state, BlockRotation rotation) {
return state
.with(FACING, rotation.rotate(state.get(FACING)));
}
@Override
@SuppressWarnings("deprecation")
public BlockState mirror(BlockState state, BlockMirror mirror) {
return state.with(FACING, mirror.apply(state.get(FACING)));
}
@Override
public abstract VoxelShape getShape(BlockState state, int i);
}

View File

@@ -1,46 +0,0 @@
package fr.adrien1106.reframed.block;
import fr.adrien1106.reframed.ReFramed;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.item.BlockItem;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.item.ItemStack;
import net.minecraft.loot.context.LootContextParameterSet;
import net.minecraft.state.StateManager;
import java.util.List;
import static net.minecraft.state.property.Properties.LAYERS;
public abstract class HalfLayerDoubleReFramedBlock extends EdgeDoubleReFramedBlock {
public HalfLayerDoubleReFramedBlock(Settings settings) {
super(settings);
setDefaultState(getDefaultState().with(LAYERS, 1));
}
@Override
@SuppressWarnings("deprecation")
public List<ItemStack> getDroppedStacks(BlockState state, LootContextParameterSet.Builder builder) {
List<ItemStack> drops = super.getDroppedStacks(state, builder);
if (state.get(LAYERS) > 1)
drops.add(new ItemStack(ReFramed.HALF_LAYER, state.get(LAYERS)-1));
return drops;
}
@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(builder.add(LAYERS));
}
@Override
@SuppressWarnings("deprecation")
public boolean canReplace(BlockState state, ItemPlacementContext context) {
if (context.getPlayer() == null
|| context.getPlayer().isSneaking()
|| !(context.getStack().getItem() instanceof BlockItem block_item)
) return false;
return block_item.getBlock() == ReFramed.HALF_LAYER && state.get(LAYERS) < 8;
}
}

View File

@@ -1,64 +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.item.BlockItem;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.item.ItemStack;
import net.minecraft.loot.context.LootContextParameterSet;
import net.minecraft.state.StateManager;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.world.BlockView;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import static net.minecraft.state.property.Properties.LAYERS;
public abstract class LayeredReFramedBlock extends WaterloggableReFramedBlock {
public LayeredReFramedBlock(Settings settings) {
super(settings);
setDefaultState(getDefaultState().with(LAYERS, 1));
}
@Override
@SuppressWarnings("deprecation")
public List<ItemStack> getDroppedStacks(BlockState state, LootContextParameterSet.Builder builder) {
List<ItemStack> drops = super.getDroppedStacks(state, builder);
drops.forEach((stack) -> {
if (stack.getItem() instanceof BlockItem bi && bi.getBlock() instanceof LayeredReFramedBlock)
stack.setCount(state.get(LAYERS));
});
return drops;
}
@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(builder.add(LAYERS));
}
@Override
@SuppressWarnings("deprecation")
public abstract VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context);
@Override
@SuppressWarnings("deprecation")
public boolean canReplace(BlockState state, ItemPlacementContext context) {
if (context.getPlayer() == null) return false;
return !(
context.getPlayer().isSneaking()
|| !(context.getStack().getItem() instanceof BlockItem block_item)
|| !(block_item.getBlock() == this && state.get(LAYERS) < 8)
);
}
@Override
public @Nullable BlockState getPlacementState(ItemPlacementContext ctx) {
BlockState previous = ctx.getWorld().getBlockState(ctx.getBlockPos());
if (!previous.isOf(this)) return super.getPlacementState(ctx);
return previous.with(LAYERS, previous.get(LAYERS) + 1);
}
}

View File

@@ -1,49 +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.item.ItemPlacementContext;
import net.minecraft.state.StateManager;
import net.minecraft.util.BlockMirror;
import net.minecraft.util.BlockRotation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.world.BlockView;
import org.jetbrains.annotations.Nullable;
import static net.minecraft.state.property.Properties.AXIS;
public abstract class PillarReFramedBlock extends WaterloggableReFramedBlock {
public PillarReFramedBlock(Settings settings) {
super(settings);
setDefaultState(getDefaultState().with(AXIS, Direction.Axis.Y));
}
@Override
protected void appendProperties(StateManager.Builder< Block, BlockState > builder) {
super.appendProperties(builder.add(AXIS));
}
@Override
public @Nullable BlockState getPlacementState(ItemPlacementContext ctx) {
return super.getPlacementState(ctx).with(AXIS, ctx.getSide().getAxis());
}
@Override
@SuppressWarnings("deprecation")
public abstract VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context);
@Override
@SuppressWarnings("deprecation")
public BlockState rotate(BlockState state, BlockRotation rotation) {
return state.with(AXIS, rotation.rotate(Direction.get(Direction.AxisDirection.POSITIVE, state.get(AXIS))).getAxis());
}
@Override
@SuppressWarnings("deprecation")
public BlockState mirror(BlockState state, BlockMirror mirror) {
return state.with(AXIS, mirror.apply(Direction.get(Direction.AxisDirection.POSITIVE, state.get(AXIS))).getAxis());
}
}

View File

@@ -2,15 +2,14 @@ package fr.adrien1106.reframed.block;
import fr.adrien1106.reframed.ReFramed;
import fr.adrien1106.reframed.util.blocks.BlockHelper;
import fr.adrien1106.reframed.util.blocks.ThemeableBlockEntity;
import net.minecraft.block.*;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.ai.pathing.NavigationType;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.BlockItem;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.nbt.NbtHelper;
import net.minecraft.registry.Registries;
@@ -19,11 +18,9 @@ import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.ItemScatterer;
import net.minecraft.util.collection.DefaultedList;
import net.minecraft.util.function.BooleanBiFunction;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.util.shape.VoxelShapes;
import net.minecraft.world.BlockView;
@@ -34,7 +31,6 @@ import org.jetbrains.annotations.Nullable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.IntStream;
import static fr.adrien1106.reframed.block.ReFramedEntity.BLOCKSTATE_KEY;
@@ -43,26 +39,29 @@ import static fr.adrien1106.reframed.util.blocks.BlockProperties.LIGHT;
public class ReFramedBlock extends Block implements BlockEntityProvider {
public ReFramedBlock(Settings settings) {
super(settings.dynamicBounds());
super(settings);
setDefaultState(getDefaultState().with(LIGHT, false));
}
@Override
@SuppressWarnings("deprecation")
public int getOpacity(BlockState state, BlockView world, BlockPos pos) {
if (state.get(LIGHT)) return 0;
if (!(world.getBlockEntity(pos) instanceof ReFramedEntity frame_entity)
|| frame_entity.getTheme(0).isOpaque())
return world.getMaxLightLevel();
return 0;
/**
* 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 "";
}
@Override
@SuppressWarnings("deprecation")
public boolean canPathfindThrough(BlockState state, BlockView world, BlockPos pos, NavigationType type) {
return false;
/**
* @return the amount of models the block can have prevents allocating too much space for a model
*/
public int getModelStateCount() {
return 1;
}
//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
@Override
public @Nullable BlockEntity createBlockEntity(BlockPos pos, BlockState state) {
return ReFramed.REFRAMED_BLOCK_ENTITY.instantiate(pos, state);
@@ -80,25 +79,26 @@ public class ReFramedBlock extends Block implements BlockEntityProvider {
}
@Override
@SuppressWarnings("deprecation")
public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) {
if (!canUse(world, pos, player)) return ActionResult.PASS;
if (!canUse(world, pos, player)) return superUse(state, world, pos, player, hand, hit);
ActionResult result = BlockHelper.useUpgrade(state, world, pos, player, hand);
if (result.isAccepted()) return result;
return BlockHelper.useCamo(state, world, pos, player, hand, hit, 1);
}
// don't like this but might be useful
protected ActionResult superUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) {
return super.onUse(state, world, pos, player, hand, hit);
}
protected boolean canUse(World world, BlockPos pos, PlayerEntity player) {
return player.canModifyBlocks() && world.canPlayerModifyAt(player, pos);
}
@Override
@SuppressWarnings("deprecation")
public void onStateReplaced(BlockState state, World world, BlockPos pos, BlockState new_state, boolean moved) {
if (!new_state.isOf(state.getBlock())) world.removeBlockEntity(pos);
if(!(new_state.getBlock() instanceof ReFramedBlock) &&
public void onStateReplaced(BlockState state, World world, BlockPos pos, BlockState newState, boolean moved) {
if(!(newState.getBlock() instanceof ReFramedBlock) &&
world.getBlockEntity(pos) instanceof ReFramedEntity frame_entity &&
world.getGameRules().getBoolean(GameRules.DO_TILE_DROPS)
) {
@@ -109,9 +109,19 @@ public class ReFramedBlock extends Block implements BlockEntityProvider {
if(theme.getBlock() != Blocks.AIR) drops.add(new ItemStack(theme.getBlock()));
});
if(frame_entity.emitsRedstone()
&& themes.stream().noneMatch(theme -> theme.getWeakRedstonePower(world, pos, Direction.NORTH) != 0))
drops.add(new ItemStack(Items.REDSTONE_TORCH));
if(frame_entity.emitsLight()
&& themes.stream().noneMatch(theme -> theme.getLuminance() != 0))
drops.add(new ItemStack(Items.GLOWSTONE_DUST));
if(!frame_entity.isSolid()
&& themes.stream().anyMatch(AbstractBlockState::isSolid))
drops.add(new ItemStack(Items.POPPED_CHORUS_FRUIT));
ItemScatterer.spawn(world, pos, drops);
}
super.onStateReplaced(state, world, pos, new_state, moved);
super.onStateReplaced(state, world, pos, newState, moved);
}
public void onPlaced(World world, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack stack, BlockState old_state, BlockEntity old_entity) {
@@ -160,22 +170,8 @@ public class ReFramedBlock extends Block implements BlockEntityProvider {
}
onPlaced(world, pos, state, placer, stack);
}
public boolean matchesShape(Vec3d hit, BlockPos pos, BlockState state) {
return matchesShape(hit, pos, state, 0);
}
public boolean matchesShape(Vec3d hit, BlockPos pos, BlockState state, int i) {
Vec3d rel = BlockHelper.getRelativePos(hit, pos);
return matchesShape(rel, getShape(state, i));
}
public boolean matchesShape(Vec3d rel_hit, VoxelShape shape) {
return BlockHelper.cursorMatchesFace(shape, rel_hit);
}
@Override
@SuppressWarnings("deprecation")
public VoxelShape getCollisionShape(BlockState state, BlockView view, BlockPos pos, ShapeContext ctx) {
return isGhost(view, pos)
? VoxelShapes.empty()
@@ -183,14 +179,12 @@ public class ReFramedBlock extends Block implements BlockEntityProvider {
}
@Override
@SuppressWarnings("deprecation")
public VoxelShape getCullingShape(BlockState state, BlockView view, BlockPos pos) {
return isGhost(view, pos)
? VoxelShapes.empty()
: super.getCullingShape(state, view, pos);
}
@SuppressWarnings("deprecation")
public VoxelShape getShape(BlockState state, int i) {
// assuming the shape don't need the world and position
return getOutlineShape(state, null, null, null);
@@ -201,13 +195,11 @@ public class ReFramedBlock extends Block implements BlockEntityProvider {
}
@Override
@SuppressWarnings("deprecation")
public int getWeakRedstonePower(BlockState state, BlockView view, BlockPos pos, Direction dir) {
return view.getBlockEntity(pos) instanceof ReFramedEntity be && be.emitsRedstone() ? 15 : 0;
}
@Override
@SuppressWarnings("deprecation")
public int getStrongRedstonePower(BlockState state, BlockView view, BlockPos pos, Direction dir) {
return getWeakRedstonePower(state, view, pos, dir);
}
@@ -228,17 +220,4 @@ public class ReFramedBlock extends Block implements BlockEntityProvider {
public Map<Integer, Integer> getThemeMap(BlockState state, BlockState new_state) {
return Map.of();
}
public VoxelShape getShadingShape(BlockState state, BlockView world, BlockPos pos) {
if (!(world.getBlockEntity(pos) instanceof ThemeableBlockEntity framed_entity)) return this.getCollisionShape(state, world, pos, ShapeContext.absent());
AtomicInteger i = new AtomicInteger(1);
return framed_entity.getThemes().stream().map((theme) -> {
int index = i.getAndIncrement();
return theme.isTransparent(world, pos) ? VoxelShapes.empty() : this.getShape(state, index);
}).reduce(
VoxelShapes.empty(),
(prev, current) -> VoxelShapes.combine(prev, current, BooleanBiFunction.OR)
);
}
}

View File

@@ -1,245 +0,0 @@
package fr.adrien1106.reframed.block;
import fr.adrien1106.reframed.util.VoxelHelper;
import net.minecraft.block.*;
import net.minecraft.block.enums.BlockFace;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.projectile.PersistentProjectileEntity;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.item.ItemStack;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.sound.SoundCategory;
import net.minecraft.state.StateManager;
import net.minecraft.util.ActionResult;
import net.minecraft.util.BlockMirror;
import net.minecraft.util.BlockRotation;
import net.minecraft.util.Hand;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.random.Random;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.world.BlockView;
import net.minecraft.world.World;
import net.minecraft.world.WorldAccess;
import net.minecraft.world.WorldView;
import net.minecraft.world.event.GameEvent;
import net.minecraft.world.explosion.Explosion;
import org.jetbrains.annotations.Nullable;
import java.util.function.BiConsumer;
import static net.minecraft.state.property.Properties.*;
public class ReFramedButtonBlock extends WaterloggableReFramedBlock {
public static final VoxelShape[] BUTTON_VOXELS;
public ReFramedButtonBlock(Settings settings) {
super(settings);
setDefaultState(getDefaultState()
.with(HORIZONTAL_FACING, Direction.NORTH)
.with(BLOCK_FACE, BlockFace.WALL)
.with(POWERED, false)
);
}
@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(builder.add(HORIZONTAL_FACING, BLOCK_FACE, POWERED));
}
@Override
@SuppressWarnings("deprecation")
public boolean canPlaceAt(BlockState state, WorldView world, BlockPos pos) {
return canPlaceAt(world, pos, getDirection(state).getOpposite());
}
public static boolean canPlaceAt(WorldView world, BlockPos pos, Direction direction) {
BlockPos other_pos = pos.offset(direction);
return world.getBlockState(other_pos).isSideSolidFullSquare(world, other_pos, direction.getOpposite());
}
@Override
public @Nullable BlockState getPlacementState(ItemPlacementContext ctx) {
BlockState state = super.getPlacementState(ctx);
Direction side = ctx.getSide();
return state
.with(HORIZONTAL_FACING, side.getAxis() == Direction.Axis.Y
? ctx.getHorizontalPlayerFacing()
: side
)
.with(BLOCK_FACE, side.getAxis() != Direction.Axis.Y
? BlockFace.WALL
: side == Direction.UP ? BlockFace.FLOOR : BlockFace.CEILING
);
}
@Override
public BlockState getStateForNeighborUpdate(BlockState state, Direction direction, BlockState other_state, WorldAccess world, BlockPos pos, BlockPos other_pos) {
return getDirection(state).getOpposite() == direction && !state.canPlaceAt(world, pos)
? Blocks.AIR.getDefaultState()
: super.getStateForNeighborUpdate(state, direction, other_state, world, pos, other_pos);
}
@Override
public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) {
ActionResult result = super.onUse(state, world, pos, player, hand, hit);
if (result.isAccepted()) return result;
if (state.get(POWERED)) return ActionResult.CONSUME;
powerOn(state, world, pos);
playClickSound(player, world, pos, true);
world.emitGameEvent(player, GameEvent.BLOCK_ACTIVATE, pos);
return ActionResult.success(world.isClient);
}
@Override
@SuppressWarnings("deprecation")
public void onExploded(BlockState state, World world, BlockPos pos, Explosion explosion, BiConsumer<ItemStack, BlockPos> stackMerger) {
if (explosion.getDestructionType() == Explosion.DestructionType.TRIGGER_BLOCK && !world.isClient() && !(Boolean)state.get(POWERED)) {
powerOn(state, world, pos);
}
super.onExploded(state, world, pos, explosion, stackMerger);
}
public void powerOn(BlockState state, World world, BlockPos pos) {
world.setBlockState(pos, state.with(POWERED, true), 3);
updateNeighbors(state, world, pos);
world.scheduleBlockTick(pos, this, 30);
}
protected void playClickSound(@Nullable PlayerEntity player, WorldAccess world, BlockPos pos, boolean powered) {
world.playSound(
powered ? player : null,
pos,
powered ? BlockSetType.OAK.buttonClickOn() : BlockSetType.OAK.buttonClickOff(),
SoundCategory.BLOCKS
);
}
@Override
@SuppressWarnings("deprecation")
public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
return BUTTON_VOXELS[
(state.get(POWERED) ? 12 : 0) +
(4 * state.get(BLOCK_FACE).ordinal()) +
state.get(HORIZONTAL_FACING).ordinal() - 2
];
}
@Override
@SuppressWarnings("deprecation")
public BlockState rotate(BlockState state, BlockRotation rotation) {
return state.with(HORIZONTAL_FACING, rotation.rotate(state.get(HORIZONTAL_FACING)));
}
@Override
@SuppressWarnings("deprecation")
public BlockState mirror(BlockState state, BlockMirror mirror) {
return state.with(HORIZONTAL_FACING, mirror.apply(state.get(HORIZONTAL_FACING)));
}
@Override
public void onStateReplaced(BlockState state, World world, BlockPos pos, BlockState new_state, boolean moved) {
super.onStateReplaced(state, world, pos, new_state, false);
if(!state.isOf(new_state.getBlock())) {
if (!moved && state.get(POWERED)) updateNeighbors(state, world, pos);
}
}
@Override
public int getWeakRedstonePower(BlockState state, BlockView view, BlockPos pos, Direction dir) {
return state.get(POWERED) ? 15 : super.getWeakRedstonePower(state, view, pos, dir);
}
@Override
public int getStrongRedstonePower(BlockState state, BlockView view, BlockPos pos, Direction dir) {
return dir == getDirection(state) ? state.getWeakRedstonePower(view, pos, dir) : 0;
}
@Override
@SuppressWarnings("deprecation")
public boolean emitsRedstonePower(BlockState state) {
return true;
}
@Override
@SuppressWarnings("deprecation")
public void scheduledTick(BlockState state, ServerWorld world, BlockPos pos, Random random) {
if (state.get(POWERED)) tryPowerWithProjectiles(state, world, pos);
}
@Override
@SuppressWarnings("deprecation")
public void onEntityCollision(BlockState state, World world, BlockPos pos, Entity entity) {
if (!world.isClient && !state.get(POWERED)) tryPowerWithProjectiles(state, world, pos);
}
protected void tryPowerWithProjectiles(BlockState state, World world, BlockPos pos) {
PersistentProjectileEntity projectile = world.getNonSpectatingEntities(
PersistentProjectileEntity.class,
state.getOutlineShape(world, pos).getBoundingBox().offset(pos)
).stream().findFirst().orElse(null);
boolean has_projectile = projectile != null;
if (has_projectile != state.get(POWERED)) {
world.setBlockState(pos, state.with(POWERED, has_projectile), 3);
this.updateNeighbors(state, world, pos);
this.playClickSound(null, world, pos, has_projectile);
world.emitGameEvent(projectile, has_projectile ? GameEvent.BLOCK_ACTIVATE : GameEvent.BLOCK_DEACTIVATE, pos);
}
if (has_projectile) {
world.scheduleBlockTick(pos, this, 30);
}
}
private void updateNeighbors(BlockState state, World world, BlockPos pos) {
world.updateNeighborsAlways(pos, this);
world.updateNeighborsAlways(pos.offset(getDirection(state).getOpposite()), this);
}
protected static Direction getDirection(BlockState state) {
return switch (state.get(BLOCK_FACE)) {
case CEILING -> Direction.DOWN;
case FLOOR -> Direction.UP;
default -> state.get(HORIZONTAL_FACING);
};
}
static {
VoxelShape SHAPE = createCuboidShape(5, 0, 6, 11, 2, 10);
VoxelShape POWERED_SHAPE = createCuboidShape(5, 0, 6, 11, 1, 10);
BUTTON_VOXELS = VoxelHelper.VoxelListBuilder.create(SHAPE, 24)
.add()
.add(0, VoxelHelper::rotateY)
.add()
.add(VoxelHelper::rotateZ, VoxelHelper::rotateY)
.add(VoxelHelper::mirrorZ)
.add(VoxelHelper::rotateY)
.add(VoxelHelper::mirrorX)
.add(0, VoxelHelper::mirrorY)
.add()
.add(2, VoxelHelper::mirrorY)
.add()
.add(POWERED_SHAPE)
.add()
.add(12, VoxelHelper::rotateY)
.add()
.add(VoxelHelper::rotateZ, VoxelHelper::rotateY)
.add(VoxelHelper::mirrorZ)
.add(VoxelHelper::rotateY)
.add(VoxelHelper::mirrorX)
.add(12, VoxelHelper::mirrorY)
.add()
.add(13, VoxelHelper::mirrorY)
.add()
.build();
}
}

View File

@@ -1,274 +0,0 @@
package fr.adrien1106.reframed.block;
import fr.adrien1106.reframed.util.VoxelHelper;
import fr.adrien1106.reframed.util.blocks.BlockHelper;
import net.minecraft.block.*;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.block.enums.DoorHinge;
import net.minecraft.block.enums.DoubleBlockHalf;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.ai.pathing.NavigationType;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.fluid.Fluids;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.item.ItemStack;
import net.minecraft.sound.SoundCategory;
import net.minecraft.state.StateManager;
import net.minecraft.util.ActionResult;
import net.minecraft.util.BlockMirror;
import net.minecraft.util.BlockRotation;
import net.minecraft.util.Hand;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.world.BlockView;
import net.minecraft.world.World;
import net.minecraft.world.WorldAccess;
import net.minecraft.world.WorldView;
import net.minecraft.world.event.GameEvent;
import net.minecraft.world.explosion.Explosion;
import org.jetbrains.annotations.Nullable;
import java.util.function.BiConsumer;
import static net.minecraft.state.property.Properties.*;
public class ReFramedDoorBlock extends WaterloggableReFramedBlock {
public static final VoxelShape[] DOOR_VOXELS;
public ReFramedDoorBlock(Settings settings) {
super(settings);
setDefaultState(getDefaultState()
.with(HORIZONTAL_FACING, Direction.NORTH)
.with(DOOR_HINGE, DoorHinge.LEFT)
.with(DOUBLE_BLOCK_HALF, DoubleBlockHalf.LOWER)
.with(OPEN, false)
.with(POWERED, false)
);
}
@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(builder.add(HORIZONTAL_FACING, DOOR_HINGE, DOUBLE_BLOCK_HALF, OPEN, POWERED));
}
@Override
@SuppressWarnings("deprecation")
public boolean canPlaceAt(BlockState state, WorldView world, BlockPos pos) {
BlockPos pos_down = pos.down();
BlockState state_down = world.getBlockState(pos_down);
return state.get(DOUBLE_BLOCK_HALF) == DoubleBlockHalf.LOWER ? !state_down.isAir() : state_down.isOf(this);
}
@Override
@SuppressWarnings("deprecation")
public void neighborUpdate(BlockState state, World world, BlockPos pos, Block source, BlockPos sourcePos, boolean notify) {
if (world.isClient) return;
boolean powered = world.isReceivingRedstonePower(pos)
|| world.isReceivingRedstonePower(
state.get(DOUBLE_BLOCK_HALF) == DoubleBlockHalf.LOWER
? pos.up()
: pos.down()
);
if (!getDefaultState().isOf(source) && powered != state.get(POWERED)) {
if (state.get(OPEN) != powered)
playToggleSound(null, world, pos, powered);
world.setBlockState(pos, state.with(POWERED, powered).with(OPEN, powered), 2);
if (state.get(WATERLOGGED)) {
world.scheduleFluidTick(pos, Fluids.WATER, Fluids.WATER.getTickRate(world));
}
}
}
@Override
public @Nullable BlockState getPlacementState(ItemPlacementContext ctx) {
World world = ctx.getWorld();
BlockPos pos = ctx.getBlockPos();
Direction facing = ctx.getHorizontalPlayerFacing().getOpposite();
if (pos.getY() >= world.getTopY() - 1 || !world.getBlockState(pos.up()).canReplace(ctx)) return null;
BlockState state = super.getPlacementState(ctx)
.with(DOUBLE_BLOCK_HALF, DoubleBlockHalf.LOWER)
.with(HORIZONTAL_FACING, facing);
if (world.isReceivingRedstonePower(pos) || world.isReceivingRedstonePower(pos.up()))
state = state.with(OPEN, true).with(POWERED, true);
return state.with(DOOR_HINGE, getHinge(facing, pos, world, BlockHelper.getRelativePos(ctx.getHitPos(), pos)));
}
@Override
public void onPlaced(World world, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack stack, BlockState old_state, BlockEntity old_entity) {
world.setBlockState(
pos.up(),
state
.with(DOUBLE_BLOCK_HALF, DoubleBlockHalf.UPPER)
.with(WATERLOGGED, world.getFluidState(pos.up()).isOf(Fluids.WATER)),
3
);
}
@Override
public BlockState onBreak(World world, BlockPos pos, BlockState state, PlayerEntity player) {
if (!world.isClient() && (player.isCreative() || player.canHarvest(state))) {
DoubleBlockHalf half = state.get(DOUBLE_BLOCK_HALF);
BlockPos other_pos = half == DoubleBlockHalf.LOWER ? pos.up() : pos.down();
BlockState other_state = world.getBlockState(other_pos);
if (other_state.isOf(this) && other_state.get(DOUBLE_BLOCK_HALF) != half) {
world.setBlockState(other_pos, other_state.get(WATERLOGGED) ? Blocks.WATER.getDefaultState(): Blocks.AIR.getDefaultState(), 35);
world.syncWorldEvent(player, 2001, other_pos, Block.getRawIdFromState(other_state));
}
}
return super.onBreak(world, pos, state, player);
}
@Override
public BlockState getStateForNeighborUpdate(BlockState state, Direction direction, BlockState other, WorldAccess world, BlockPos pos, BlockPos moved) {
if (direction.getAxis() == Direction.Axis.Y
&& other.isOf(this)
&& other.get(DOUBLE_BLOCK_HALF) != state.get(DOUBLE_BLOCK_HALF)
&& other.get(OPEN) != state.get(OPEN)
) return state.cycle(OPEN);
Direction facing = state.get(HORIZONTAL_FACING);
if (direction == (
state.get(DOOR_HINGE) == DoorHinge.RIGHT
? facing.rotateYClockwise()
: facing.rotateYCounterclockwise())
&& other.isOf(this)
&& other.get(DOUBLE_BLOCK_HALF) == state.get(DOUBLE_BLOCK_HALF)
&& other.get(DOOR_HINGE) != state.get(DOOR_HINGE)
&& !state.get(POWERED)
) return state.with(OPEN, other.get(OPEN));
return super.getStateForNeighborUpdate(state, direction, other, world, pos, moved);
}
@Override
public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) {
ActionResult result = super.onUse(state, world, pos, player, hand, hit);
if (result.isAccepted()) return result;
flip(state, world, pos, player);
return ActionResult.success(world.isClient);
}
@Override
@SuppressWarnings("deprecation")
public boolean canPathfindThrough(BlockState state, BlockView world, BlockPos pos, NavigationType type) {
return switch (type) {
case LAND, AIR -> state.get(OPEN);
case WATER -> false;
};
}
@Override
@SuppressWarnings("deprecation")
public void onExploded(BlockState state, World world, BlockPos pos, Explosion explosion, BiConsumer<ItemStack, BlockPos> stack_merger) {
if (explosion.getDestructionType() == Explosion.DestructionType.TRIGGER_BLOCK
&& !world.isClient()
&& !state.get(POWERED)
) flip(state, world, pos, null);
super.onExploded(state, world, pos, explosion, stack_merger);
}
private void flip(BlockState state, World world, BlockPos pos, @Nullable PlayerEntity player) {
state = state.cycle(OPEN);
world.setBlockState(pos, state, 10);
this.playToggleSound(player, world, pos, state.get(OPEN));
}
protected void playToggleSound(@Nullable PlayerEntity player, World world, BlockPos pos, boolean open) {
world.playSound(player, pos, open ? BlockSetType.OAK.doorOpen() : BlockSetType.OAK.doorClose(), SoundCategory.BLOCKS, 1.0F, world.getRandom().nextFloat() * 0.1F + 0.9F);
world.emitGameEvent(player, open ? GameEvent.BLOCK_OPEN : GameEvent.BLOCK_CLOSE, pos);
}
@Override
@SuppressWarnings("deprecation")
public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
Direction direction = state.get(HORIZONTAL_FACING);
if (state.get(OPEN)) direction = switch (state.get(DOOR_HINGE)) {
case RIGHT -> direction.rotateYCounterclockwise();
case LEFT -> direction.rotateYClockwise();
};
return DOOR_VOXELS[direction.ordinal() - 2];
}
@Override
@SuppressWarnings("deprecation")
public BlockState rotate(BlockState state, BlockRotation rotation) {
return state.with(HORIZONTAL_FACING, rotation.rotate(state.get(HORIZONTAL_FACING)));
}
@Override
@SuppressWarnings("deprecation")
public BlockState mirror(BlockState state, BlockMirror mirror) {
return mirror == BlockMirror.NONE ? state : state.with(HORIZONTAL_FACING, mirror.apply(state.get(HORIZONTAL_FACING))).cycle(DOOR_HINGE);
}
@Override
@SuppressWarnings("deprecation")
public long getRenderingSeed(BlockState state, BlockPos pos) {
return MathHelper.hashCode(pos.getX(), pos.down(state.get(DOUBLE_BLOCK_HALF) == DoubleBlockHalf.LOWER ? 0 : 1).getY(), pos.getZ());
}
private DoorHinge getHinge(Direction facing, BlockPos pos, World world, Vec3d hit_pos) {
Direction left = facing.rotateYClockwise();
BlockPos left_pos = pos.offset(left);
BlockState left_state = world.getBlockState(left_pos);
Direction right = facing.rotateYCounterclockwise();
BlockPos right_pos = pos.offset(right);
BlockState right_state = world.getBlockState(right_pos);
DoorHinge hinge = null;
if (left_state.isSideSolidFullSquare(world, left_pos, right))
hinge = DoorHinge.LEFT;
if (right_state.isSideSolidFullSquare(world, right_pos, left))
hinge = hinge == DoorHinge.LEFT ? null : DoorHinge.RIGHT;
if (hinge != null) return hinge;
if (left_state.isOf(this)
&& left_state.get(HORIZONTAL_FACING) == facing
&& left_state.get(DOUBLE_BLOCK_HALF) == DoubleBlockHalf.LOWER
&& left_state.get(DOOR_HINGE) == DoorHinge.LEFT
) hinge = DoorHinge.RIGHT;
if (right_state.isOf(this)
&& right_state.get(HORIZONTAL_FACING) == facing
&& right_state.get(DOUBLE_BLOCK_HALF) == DoubleBlockHalf.LOWER
&& right_state.get(DOOR_HINGE) == DoorHinge.RIGHT
) hinge = hinge == DoorHinge.RIGHT ? null : DoorHinge.LEFT;
if (hinge != null) return hinge;
return switch (facing.getAxis()) {
case Z -> {
if (left.getDirection() == Direction.AxisDirection.POSITIVE)
yield hit_pos.getX() < 0.5 ? DoorHinge.RIGHT : DoorHinge.LEFT;
else // left.getDirection() == Direction.AxisDirection.NEGATIVE
yield hit_pos.getX() < 0.5 ? DoorHinge.LEFT : DoorHinge.RIGHT;
}
case X -> {
if (left.getDirection() == Direction.AxisDirection.POSITIVE)
yield hit_pos.getZ() < 0.5 ? DoorHinge.RIGHT : DoorHinge.LEFT;
else // left.getDirection() == Direction.AxisDirection.NEGATIVE
yield hit_pos.getZ() < 0.5 ? DoorHinge.LEFT : DoorHinge.RIGHT;
}
default -> DoorHinge.LEFT;
};
}
static {
VoxelShape SHAPE = createCuboidShape(0.0, 0.0, 0.0, 16.0, 16.0, 3.0);
DOOR_VOXELS = VoxelHelper.VoxelListBuilder.create(SHAPE, 4)
.add(VoxelHelper::mirrorZ)
.add(VoxelHelper::rotateY)
.add(VoxelHelper::mirrorX)
.build();
}
}

View File

@@ -19,6 +19,7 @@ import net.minecraft.world.World;
import org.jetbrains.annotations.Nullable;
import static net.minecraft.util.shape.VoxelShapes.empty;
import static net.minecraft.util.shape.VoxelShapes.fullCube;
public abstract class ReFramedDoubleBlock extends ReFramedBlock {
public ReFramedDoubleBlock(Settings settings) {
@@ -48,6 +49,14 @@ public abstract class ReFramedDoubleBlock extends ReFramedBlock {
return 0;
}
public boolean matchesShape(Vec3d hit, BlockPos pos, BlockState state, int i) {
Vec3d rel = BlockHelper.getRelativePos(hit, pos);
return BlockHelper.cursorMatchesFace(
getShape(state, i),
rel
);
}
@Override
public boolean isTransparent(BlockState state, BlockView world, BlockPos pos) {
return world.getBlockEntity(pos) instanceof ThemeableBlockEntity framed_entity
@@ -60,17 +69,17 @@ public abstract class ReFramedDoubleBlock extends ReFramedBlock {
@Override
public VoxelShape getCollisionShape(BlockState state, BlockView view, BlockPos pos, ShapeContext ctx) {
return isGhost(view, pos) ? empty() : getOutlineShape(state, view, pos, ctx);
return getCullingShape(state, view, pos);
}
@Override
public VoxelShape getCullingShape(BlockState state, BlockView view, BlockPos pos) {
return getCollisionShape(state, view, pos, ShapeContext.absent());
return isGhost(view, pos) ? empty() : fullCube();
}
@Override
public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) {
if (!canUse(world, pos, player)) return ActionResult.PASS;
if (!canUse(world, pos, player)) return superUse(state, world, pos, player, hand, hit);
ActionResult result = BlockHelper.useUpgrade(state, world, pos, player, hand);
if (result.isAccepted()) return result;
return BlockHelper.useCamo(state, world, pos, player, hand, hit, getHitShape(state, hit));

View File

@@ -57,6 +57,6 @@ public class ReFramedDoubleEntity extends ReFramedEntity {
public void writeNbt(NbtCompound nbt) {
super.writeNbt(nbt);
nbt.put(BLOCKSTATE_KEY + 2, NbtHelper.fromBlockState(second_state));
if(second_state != Blocks.AIR.getDefaultState()) nbt.put(BLOCKSTATE_KEY + 2, NbtHelper.fromBlockState(second_state));
}
}

View File

@@ -32,12 +32,12 @@ public class ReFramedEntity extends BlockEntity implements ThemeableBlockEntity
protected BlockState first_state = Blocks.AIR.getDefaultState();
protected byte bit_field = SOLIDITY_MASK;
public static final byte LIGHT_MASK = 0b001;
public static final byte REDSTONE_MASK = 0b010;
public static final byte SOLIDITY_MASK = 0b100;
protected static final byte LIGHT_MASK = 0b001;
protected static final byte REDSTONE_MASK = 0b010;
protected static final byte SOLIDITY_MASK = 0b100;
public static final String BLOCKSTATE_KEY = "s";
public static final String BITFIELD_KEY = "b";
protected static final String BITFIELD_KEY = "b";
public ReFramedEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
super(type, pos, state);
@@ -52,15 +52,16 @@ public class ReFramedEntity extends BlockEntity implements ThemeableBlockEntity
if (nbt.contains(BITFIELD_KEY)) bit_field = nbt.getByte(BITFIELD_KEY);
// Force a chunk remesh on the client if the displayed blockstate has changed
if(world != null && world.isClient && !Objects.equals(rendered_state, first_state))
if(world != null && world.isClient && !Objects.equals(rendered_state, first_state)) {
ReFramed.chunkRerenderProxy.accept(world, pos);
}
}
@Override
public void writeNbt(NbtCompound nbt) {
super.writeNbt(nbt);
nbt.put(BLOCKSTATE_KEY + 1, NbtHelper.fromBlockState(first_state));
if(first_state != Blocks.AIR.getDefaultState()) nbt.put(BLOCKSTATE_KEY + 1, NbtHelper.fromBlockState(first_state));
if(bit_field != SOLIDITY_MASK) nbt.putByte(BITFIELD_KEY, bit_field);
}
@@ -112,7 +113,7 @@ public class ReFramedEntity extends BlockEntity implements ThemeableBlockEntity
}
public void setTheme(BlockState new_state, int i) {
if(!Objects.equals(first_state, new_state) && i == 1) {
if(!Objects.equals(first_state, new_state)) {
first_state = new_state;
markDirtyAndDispatch();
}
@@ -145,10 +146,7 @@ public class ReFramedEntity extends BlockEntity implements ThemeableBlockEntity
if (isSolid()) bit_field &= ~SOLIDITY_MASK;
else bit_field |= SOLIDITY_MASK;
if(world != null) {
world.setBlockState(pos, getCachedState());
ReFramed.chunkRerenderProxy.accept(world, pos);
}
if(world != null) world.setBlockState(pos, getCachedState());
markDirtyAndDispatch();
}

View File

@@ -1,108 +0,0 @@
package fr.adrien1106.reframed.block;
import fr.adrien1106.reframed.util.VoxelHelper;
import net.minecraft.block.BlockState;
import net.minecraft.block.FenceGateBlock;
import net.minecraft.block.ShapeContext;
import net.minecraft.entity.ai.pathing.NavigationType;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.item.LeadItem;
import net.minecraft.registry.tag.BlockTags;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.function.BooleanBiFunction;
import net.minecraft.util.hit.BlockHitResult;
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;
public class ReFramedFenceBlock extends ConnectingReFramedBlock {
public static final VoxelShape[] FENCE_VOXELS;
public ReFramedFenceBlock(Settings settings) {
super(settings);
}
@Override
protected boolean connectsTo(BlockState state, boolean fs, Direction dir) {
return fs || state.isIn(BlockTags.FENCES)
|| (state.getBlock() instanceof FenceGateBlock && FenceGateBlock.canWallConnect(state, dir));
}
@Override
public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
VoxelShape shape = FENCE_VOXELS[0];
for (Direction dir: Direction.Type.HORIZONTAL) {
if (state.get(getConnectionProperty(dir)))
shape = VoxelShapes.union(shape, FENCE_VOXELS[dir.ordinal() - 1]);
}
return shape;
}
@Override
public VoxelShape getCollisionShape(BlockState state, BlockView view, BlockPos pos, ShapeContext ctx) {
VoxelShape shape = FENCE_VOXELS[5];
for (Direction dir: Direction.Type.HORIZONTAL) {
if (state.get(getConnectionProperty(dir)))
shape = VoxelShapes.union(shape, FENCE_VOXELS[dir.ordinal() + 4]);
}
return shape;
}
@Override
@SuppressWarnings("deprecation")
public VoxelShape getCameraCollisionShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
return getOutlineShape(state, world, pos, context);
}
@Override
public VoxelShape getCullingShape(BlockState state, BlockView view, BlockPos pos) {
return getOutlineShape(state, view, pos, ShapeContext.absent());
}
@Override
@SuppressWarnings("deprecation")
public boolean canPathfindThrough(BlockState state, BlockView world, BlockPos pos, NavigationType type) {
return false;
}
@Override
public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) {
ActionResult result = super.onUse(state, world, pos, player, hand, hit);
if (result.isAccepted()) return result;
if (world.isClient) {
ItemStack itemStack = player.getStackInHand(hand);
return itemStack.isOf(Items.LEAD) ? ActionResult.SUCCESS : ActionResult.PASS;
} else {
return LeadItem.attachHeldMobsToBlock(player, world, pos);
}
}
static {
VoxelShape POST = createCuboidShape(6, 0, 6, 10, 16, 10);
VoxelShape POST_COLLISION = createCuboidShape(6, 0, 6, 10, 24, 10);
VoxelShape SIDE = VoxelShapes.combineAndSimplify(
createCuboidShape(7, 12, 0, 9, 15, 6),
createCuboidShape(7, 6, 0, 9, 9, 6),
BooleanBiFunction.OR
);
VoxelShape SIDE_COLLISION = createCuboidShape(7, 0, 0, 9, 24, 6);
FENCE_VOXELS = VoxelHelper.VoxelListBuilder.create(POST, 5)
.add(SIDE)
.add(VoxelHelper::mirrorZ)
.add(VoxelHelper::rotateY)
.add(VoxelHelper::mirrorX)
.add(POST_COLLISION)
.add(SIDE_COLLISION)
.add(VoxelHelper::mirrorZ)
.add(VoxelHelper::rotateY)
.add(VoxelHelper::mirrorX)
.build();
}
}

View File

@@ -1,188 +0,0 @@
package fr.adrien1106.reframed.block;
import fr.adrien1106.reframed.ReFramed;
import fr.adrien1106.reframed.util.VoxelHelper;
import fr.adrien1106.reframed.util.blocks.BlockHelper;
import fr.adrien1106.reframed.util.blocks.Edge;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.ShapeContext;
import net.minecraft.item.BlockItem;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.state.StateManager;
import net.minecraft.util.BlockMirror;
import net.minecraft.util.BlockRotation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.world.BlockView;
import org.jetbrains.annotations.Nullable;
import java.util.Map;
import static fr.adrien1106.reframed.util.VoxelHelper.VoxelListBuilder;
import static fr.adrien1106.reframed.util.blocks.BlockProperties.EDGE;
import static fr.adrien1106.reframed.util.blocks.BlockProperties.EDGE_FACE;
import static net.minecraft.state.property.Properties.*;
public class ReFramedHalfLayerBlock extends LayeredReFramedBlock {
public static final VoxelShape[] HALF_LAYER_VOXELS;
public ReFramedHalfLayerBlock(Settings settings) {
super(settings);
setDefaultState(getDefaultState().with(EDGE, Edge.NORTH_DOWN).with(EDGE_FACE, 0));
}
@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(builder.add(EDGE, EDGE_FACE));
}
@Override
public boolean canReplace(BlockState state, ItemPlacementContext context) {
if (super.canReplace(state, context)) return true;
if (context.getPlayer() == null
|| context.getPlayer().isSneaking()
|| !(context.getStack().getItem() instanceof BlockItem block_item)
) return false;
Edge edge = state.get(EDGE);
Direction face = edge.getDirection(state.get(EDGE_FACE));
if (block_item.getBlock() == ReFramed.SLAB)
return ReFramed.SLAB
.matchesShape(
context.getHitPos(),
context.getBlockPos(),
ReFramed.SLAB.getDefaultState().with(FACING, edge.getOtherDirection(face).getOpposite())
);
if (block_item.getBlock() == ReFramed.STEP)
return ReFramed.STEP
.matchesShape(
context.getHitPos(),
context.getBlockPos(),
ReFramed.STEP.getDefaultState().with(EDGE, edge.getOpposite(face))
);
return false;
}
@Override
public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
return getHalfLayerShape(
state.get(EDGE),
state.get(EDGE_FACE),
state.get(LAYERS)
);
}
@Override
public @Nullable BlockState getPlacementState(ItemPlacementContext ctx) {
BlockState previous = ctx.getWorld().getBlockState(ctx.getBlockPos());
BlockState state = super.getPlacementState(ctx);
if (previous.isOf(this))
return state;
if (previous.isOf(ReFramed.SLABS_HALF_LAYER) || previous.isOf(ReFramed.STEPS_HALF_LAYER))
return previous.with(LAYERS, Math.min(8, previous.get(LAYERS) + 1));
if (previous.isOf(ReFramed.SLAB)) {
Direction face = previous.get(FACING);
Edge edge;
if (face.getAxis() == ctx.getSide().getAxis()) {
edge = BlockHelper.getPlacementEdge(ctx);
if (face == ctx.getSide()) edge = edge.getOpposite(edge.getOtherDirection(ctx.getSide()));
} else edge = Edge.getByDirections(face, ctx.getSide().getOpposite());
return ReFramed.SLABS_HALF_LAYER.getDefaultState()
.with(EDGE, edge)
.with(EDGE_FACE, edge.getDirectionIndex(face))
.with(WATERLOGGED, previous.get(WATERLOGGED));
}
if (previous.isOf(ReFramed.STEP)) {
int face_index = 0;
Edge edge = previous.get(EDGE);
if (!ReFramed.STEP.matchesShape(
ctx.getHitPos(),
ctx.getBlockPos(),
ReFramed.STEP.getDefaultState().with(EDGE, edge.getOpposite(1))
)) face_index = 1;
return ReFramed.STEPS_HALF_LAYER.getDefaultState()
.with(EDGE, edge)
.with(EDGE_FACE, face_index)
.with(WATERLOGGED, previous.get(WATERLOGGED));
}
Edge edge = BlockHelper.getPlacementEdge(ctx);
return state.with(EDGE, edge).with(EDGE_FACE, edge.getDirectionIndex(ctx.getSide().getOpposite()));
}
@Override
@SuppressWarnings("deprecation")
public BlockState rotate(BlockState state, BlockRotation rotation) {
Edge edge = state.get(EDGE);
Direction face = rotation.rotate(edge.getDirection(state.get(EDGE_FACE)));
edge = edge.rotate(rotation);
return state.with(EDGE, edge).with(EDGE_FACE, edge.getDirectionIndex(face));
}
@Override
@SuppressWarnings("deprecation")
public BlockState mirror(BlockState state, BlockMirror mirror) {
Edge edge = state.get(EDGE);
Direction face = mirror.apply(edge.getDirection(state.get(EDGE_FACE)));
edge = edge.mirror(mirror);
return state.with(EDGE, edge).with(EDGE_FACE, edge.getDirectionIndex(face));
}
@Override
public Map<Integer, Integer> getThemeMap(BlockState state, BlockState new_state) {
if (new_state.isOf(ReFramed.SLABS_HALF_LAYER)
|| new_state.isOf(ReFramed.STEPS_HALF_LAYER)
) return Map.of(1, 2);
return super.getThemeMap(state, new_state);
}
public static VoxelShape getHalfLayerShape(Edge edge, int face, int layer) {
return HALF_LAYER_VOXELS[edge.ordinal() * 16 + face * 8 + layer - 1];
}
static {
VoxelListBuilder builder = VoxelListBuilder.create(createCuboidShape(0, 0, 0, 16, 8, 2), 192)
.add(createCuboidShape(0, 0, 0, 16, 8, 4))
.add(createCuboidShape(0, 0, 0, 16, 8, 6))
.add(createCuboidShape(0, 0, 0, 16, 8, 8))
.add(createCuboidShape(0, 0, 0, 16, 8, 10))
.add(createCuboidShape(0, 0, 0, 16, 8, 12))
.add(createCuboidShape(0, 0, 0, 16, 8, 14))
.add(createCuboidShape(0, 0, 0, 16, 8, 16));
for (int i = 0; i < 8; i++) {
builder.add(i, VoxelHelper::rotateCX, VoxelHelper::mirrorZ);
}
for (int i = 0; i < 48; i++) {
builder.add(i, VoxelHelper::rotateCX);
}
for (int i = 0; i < 64; i++) {
builder.add(i, VoxelHelper::rotateCY);
}
for (int i = 64; i < 80; i++) {
builder.add(i, VoxelHelper::rotateX);
}
for (int i = 80; i < 96; i++) {
builder.add(i, VoxelHelper::rotateX);
}
for (int i = 96; i < 112; i++) {
builder.add(i, VoxelHelper::rotateX);
}
for (int i = 112; i < 128; i++) {
builder.add(i, VoxelHelper::rotateX);
}
HALF_LAYER_VOXELS = builder.build();
}
}

View File

@@ -1,86 +0,0 @@
package fr.adrien1106.reframed.block;
import fr.adrien1106.reframed.ReFramed;
import fr.adrien1106.reframed.util.VoxelHelper;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.ShapeContext;
import net.minecraft.item.BlockItem;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.world.BlockView;
import org.jetbrains.annotations.Nullable;
import java.util.Map;
import static net.minecraft.state.property.Properties.*;
public class ReFramedHalfSlabBlock extends ReFramedSlabBlock {
public static VoxelShape[] HALF_SLAB_SHAPES;
public ReFramedHalfSlabBlock(Settings settings) {
super(settings);
}
@Override
public boolean canReplace(BlockState state, ItemPlacementContext context) {
if (context.getPlayer() == null
|| context.getPlayer().isSneaking()
|| !(context.getStack().getItem() instanceof BlockItem block_item)
) return false;
// allow replacing with slab, step, small cube and half stair
Block block = block_item.getBlock();
if (block != this) return false;
// check if the player is clicking on the inner part of the block
return ReFramed.HALF_SLABS_SLAB
.matchesShape(
context.getHitPos(),
context.getBlockPos(),
ReFramed.HALF_SLABS_SLAB.getDefaultState().with(FACING, state.get(FACING)),
2
);
}
@Nullable
@Override
public BlockState getPlacementState(ItemPlacementContext ctx) {
BlockState current_state = ctx.getWorld().getBlockState(ctx.getBlockPos());
if (current_state.isOf(this))
return ReFramed.HALF_SLABS_SLAB.getDefaultState()
.with(FACING, current_state.get(FACING))
.with(WATERLOGGED, current_state.get(WATERLOGGED));
return super.getPlacementState(ctx).with(FACING, ctx.getSide().getOpposite());
}
@Override
public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
return getHalfSlabShape(state.get(FACING));
}
public static VoxelShape getHalfSlabShape(Direction direction) {
return HALF_SLAB_SHAPES[direction.getId()];
}
@Override
public Map<Integer, Integer> getThemeMap(BlockState state, BlockState new_state) {
if (new_state.isOf(ReFramed.HALF_SLABS_SLAB)) return Map.of(1, 1);
return super.getThemeMap(state, new_state);
}
static {
HALF_SLAB_SHAPES = VoxelHelper.VoxelListBuilder.create(createCuboidShape(0, 0, 0, 16, 4, 16),6)
.add(createCuboidShape(0, 12, 0, 16, 16, 16))
.add(createCuboidShape(0, 0, 0, 16, 16, 4))
.add(createCuboidShape(0, 0, 12, 16, 16, 16))
.add(createCuboidShape(0, 0, 0, 4, 16, 16))
.add(createCuboidShape(12, 0, 0, 16, 16, 16))
.build();
}
}

View File

@@ -1,45 +0,0 @@
package fr.adrien1106.reframed.block;
import fr.adrien1106.reframed.util.VoxelHelper;
import net.minecraft.block.BlockState;
import net.minecraft.block.ShapeContext;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.world.BlockView;
import static fr.adrien1106.reframed.block.ReFramedHalfSlabBlock.getHalfSlabShape;
import static fr.adrien1106.reframed.block.ReFramedSlabBlock.getSlabShape;
import static net.minecraft.state.property.Properties.FACING;
public class ReFramedHalfSlabsSlabBlock extends FacingDoubleReFramedBlock {
public static VoxelShape[] HALF_SLAB_COMP_SHAPES;
public ReFramedHalfSlabsSlabBlock(Settings settings) {
super(settings);
}
@Override
public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
return getSlabShape(state.get(FACING));
}
@Override
public VoxelShape getShape(BlockState state, int i) {
Direction face = state.get(FACING);
return i == 2
? HALF_SLAB_COMP_SHAPES[face.getId()]
: getHalfSlabShape(face);
}
static {
HALF_SLAB_COMP_SHAPES = VoxelHelper.VoxelListBuilder.create(createCuboidShape(0, 4, 0, 16, 8, 16),6)
.add(createCuboidShape(0, 8, 0, 16, 12, 16))
.add(createCuboidShape(0, 0, 4, 16, 16, 8))
.add(createCuboidShape(0, 0, 8, 16, 16, 12))
.add(createCuboidShape(4, 0, 0, 8, 16, 16))
.add(createCuboidShape(8, 0, 0, 12, 16, 16))
.build();
}
}

View File

@@ -10,8 +10,6 @@ import net.minecraft.block.ShapeContext;
import net.minecraft.item.BlockItem;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.state.StateManager;
import net.minecraft.util.BlockMirror;
import net.minecraft.util.BlockRotation;
import net.minecraft.util.function.BooleanBiFunction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
@@ -25,62 +23,67 @@ import java.util.Map;
import static fr.adrien1106.reframed.util.VoxelHelper.VoxelListBuilder;
import static fr.adrien1106.reframed.util.blocks.BlockProperties.*;
import static fr.adrien1106.reframed.util.blocks.Corner.*;
import static net.minecraft.state.property.Properties.FACING;
import static net.minecraft.state.property.Properties.WATERLOGGED;
public class ReFramedHalfStairBlock extends WaterloggableReFramedBlock {
public static final VoxelShape[] HALF_STAIR_VOXELS;
private record ModelCacheKey(Corner corner, int face) {}
public ReFramedHalfStairBlock(Settings settings) {
super(settings);
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
public int getModelStateCount() {
return 24;
}
@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(builder.add(CORNER,CORNER_FACE));
}
@Override
@SuppressWarnings("deprecation")
public boolean canReplace(BlockState state, ItemPlacementContext context) {
if (context.getPlayer() == null
|| context.getPlayer().isSneaking()
|| !(context.getStack().getItem() instanceof BlockItem block_item)
) return false;
// allow replacing with slab, step, small cube and half stair
Block block = block_item.getBlock();
Corner corner = state.get(CORNER);
Direction dir = corner.getDirection(state.get(CORNER_FACE));
if (block == this || block == ReFramed.STEP)
return ReFramed.HALF_STAIRS_STAIR.matchesShape(
context.getHitPos(),
context.getBlockPos(),
ReFramed.HALF_STAIRS_STAIR.getDefaultState().with(EDGE, corner.getEdge(dir)),
dir.getDirection() == Direction.AxisDirection.POSITIVE ? 1 : 2
);
if (block == ReFramed.SMALL_CUBE)
return ReFramed.SMALL_CUBE.matchesShape(
context.getHitPos(),
context.getBlockPos(),
ReFramed.SMALL_CUBE.getDefaultState().with(CORNER, corner.change(dir))
) || ReFramed.SMALL_CUBE.matchesShape(
context.getHitPos(),
context.getBlockPos(),
ReFramed.SMALL_CUBE.getDefaultState().with(CORNER, corner.getOpposite(dir))
);
if (block == ReFramed.SLAB)
return ReFramed.SLAB.matchesShape(
context.getHitPos(),
context.getBlockPos(),
ReFramed.SLAB.getDefaultState().with(FACING, dir.getOpposite())
);
return false;
Direction dir = state.get(CORNER).getDirection(state.get(CORNER_FACE));
return !(
context.getPlayer().isSneaking()
|| !(context.getStack().getItem() instanceof BlockItem block_item)
|| (
!(
block_item.getBlock() == this
&& ((ReFramedHalfStairsStairBlock) ReFramed.HALF_STAIRS_STAIR)
.matchesShape(
context.getHitPos(),
context.getBlockPos(),
ReFramed.HALF_STAIRS_STAIR.getDefaultState()
.with(EDGE, state.get(CORNER).getEdge(dir)),
dir.getDirection() == Direction.AxisDirection.POSITIVE ? 1 : 2
)
)
&& !(
block_item.getBlock() == ReFramed.SMALL_CUBE
&& BlockHelper.cursorMatchesFace(
ReFramed.SMALL_CUBE.getOutlineShape(
ReFramed.SMALL_CUBE.getDefaultState()
.with(CORNER, state.get(CORNER).getOpposite(state.get(CORNER_FACE))),
context.getWorld(),
context.getBlockPos(),
ShapeContext.absent()
),
BlockHelper.getRelativePos(context.getHitPos(), context.getBlockPos())
)
)
)
);
}
@Override
@@ -98,15 +101,6 @@ public class ReFramedHalfStairBlock extends WaterloggableReFramedBlock {
return ReFramed.HALF_STAIRS_STAIR.getDefaultState()
.with(EDGE, current_state.get(CORNER).getEdge(current_state.get(CORNER).getDirection(current_state.get(CORNER_FACE))))
.with(WATERLOGGED, current_state.get(WATERLOGGED));
if (current_state.isOf(ReFramed.SLAB)) {
Corner corner = BlockHelper.getPlacementCorner(ctx);
Direction face = current_state.get(FACING);
if (!corner.hasDirection(face)) corner = corner.change(face.getOpposite());
return ReFramed.SLABS_INNER_STAIR.getDefaultState()
.with(CORNER, corner)
.with(CORNER_FACE, corner.getDirectionIndex(face))
.with(WATERLOGGED, current_state.get(WATERLOGGED));
}
Corner corner = BlockHelper.getPlacementCorner(ctx);
return super.getPlacementState(ctx)
@@ -115,34 +109,13 @@ public class ReFramedHalfStairBlock extends WaterloggableReFramedBlock {
}
@Override
@SuppressWarnings("deprecation")
public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
return getHalfStairShape(state.get(CORNER), state.get(CORNER_FACE));
}
@Override
@SuppressWarnings("deprecation")
public BlockState rotate(BlockState state, BlockRotation rotation) {
Corner corner = state.get(CORNER).rotate(rotation);
Direction face = state.get(CORNER).getDirection(state.get(CORNER_FACE));
return state.with(CORNER, corner).with(CORNER_FACE, corner.getDirectionIndex(rotation.rotate(face)));
}
@Override
@SuppressWarnings("deprecation")
public BlockState mirror(BlockState state, BlockMirror mirror) {
Corner corner = state.get(CORNER).mirror(mirror);
Direction face = state.get(CORNER).getDirection(state.get(CORNER_FACE));
return state.with(CORNER, corner).with(CORNER_FACE, corner.getDirectionIndex(mirror.apply(face)));
return HALF_STAIR_VOXELS[state.get(CORNER_FACE) + state.get(CORNER).getID() * 3];
}
@Override
public Map<Integer, Integer> getThemeMap(BlockState state, BlockState new_state) {
if (new_state.isOf(ReFramed.HALF_STAIRS_SLAB)
|| new_state.isOf(ReFramed.HALF_STAIRS_CUBE_STAIR)
|| new_state.isOf(ReFramed.HALF_STAIRS_STEP_STAIR)
) return Map.of(1, 1);
if (new_state.isOf(ReFramed.SLABS_INNER_STAIR)) return Map.of(1, 2);
if (new_state.isOf(ReFramed.HALF_STAIRS_SLAB)) return Map.of(1, 1);
if (new_state.isOf(ReFramed.HALF_STAIRS_STAIR))
return Map.of(
1,
@@ -153,10 +126,6 @@ public class ReFramedHalfStairBlock extends WaterloggableReFramedBlock {
return super.getThemeMap(state, new_state);
}
public static VoxelShape getHalfStairShape(Corner corner, int face) {
return HALF_STAIR_VOXELS[face + corner.getID() * 3];
}
static {
final VoxelShape HALF_STAIR = VoxelShapes.combineAndSimplify(
createCuboidShape(8, 0, 0, 16, 16, 8),

View File

@@ -1,48 +0,0 @@
package fr.adrien1106.reframed.block;
import fr.adrien1106.reframed.util.blocks.Corner;
import fr.adrien1106.reframed.util.blocks.Edge;
import fr.adrien1106.reframed.util.blocks.StairShape;
import net.minecraft.block.BlockState;
import net.minecraft.block.ShapeContext;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.world.BlockView;
import static fr.adrien1106.reframed.block.ReFramedHalfStairBlock.getHalfStairShape;
import static fr.adrien1106.reframed.block.ReFramedSmallCubeBlock.getSmallCubeShape;
import static fr.adrien1106.reframed.block.ReFramedStairBlock.getStairShape;
import static fr.adrien1106.reframed.util.blocks.BlockProperties.CORNER;
import static fr.adrien1106.reframed.util.blocks.BlockProperties.CORNER_FACE;
public class ReFramedHalfStairsCubeStairBlock extends CornerDoubleReFramedBlock {
public ReFramedHalfStairsCubeStairBlock(Settings settings) {
super(settings);
}
@Override
public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
Corner corner = state.get(CORNER);
Direction face = corner.getDirection(state.get(CORNER_FACE));
Edge edge = corner.getEdge(face);
return getStairShape(
edge,
face.getDirection() == Direction.AxisDirection.POSITIVE
? StairShape.OUTER_LEFT
: StairShape.OUTER_RIGHT
);
}
@Override
public VoxelShape getShape(BlockState state, int i) {
Corner corner = state.get(CORNER);
Direction face = corner.getDirection(state.get(CORNER_FACE));
if (i == 2) corner = corner.change(face);
return i == 2
? getSmallCubeShape(corner)
: getHalfStairShape(corner, state.get(CORNER_FACE));
}
}

View File

@@ -7,28 +7,38 @@ import net.minecraft.block.BlockState;
import net.minecraft.block.ShapeContext;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.state.StateManager;
import net.minecraft.util.BlockMirror;
import net.minecraft.util.BlockRotation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.world.BlockView;
import org.jetbrains.annotations.Nullable;
import static fr.adrien1106.reframed.block.ReFramedHalfStairBlock.getHalfStairShape;
import static fr.adrien1106.reframed.block.ReFramedHalfStairBlock.HALF_STAIR_VOXELS;
import static fr.adrien1106.reframed.block.ReFramedSlabBlock.getSlabShape;
import static fr.adrien1106.reframed.block.ReFramedSmallCubeBlock.getSmallCubeShape;
import static fr.adrien1106.reframed.block.ReFramedSmallCubeBlock.SMALL_CUBE_VOXELS;
import static fr.adrien1106.reframed.util.blocks.BlockProperties.CORNER;
import static fr.adrien1106.reframed.util.blocks.BlockProperties.CORNER_FACE;
import static fr.adrien1106.reframed.util.blocks.Corner.NORTH_EAST_DOWN;
import static net.minecraft.util.shape.VoxelShapes.empty;
public class ReFramedHalfStairsSlabBlock extends WaterloggableReFramedDoubleBlock {
private record ModelCacheKey(Corner corner, int face) {}
public ReFramedHalfStairsSlabBlock(Settings settings) {
super(settings);
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
public int getModelStateCount() {
return 24;
}
@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(builder.add(CORNER,CORNER_FACE));
@@ -43,33 +53,21 @@ public class ReFramedHalfStairsSlabBlock extends WaterloggableReFramedDoubleBloc
}
@Override
@SuppressWarnings("deprecation")
public VoxelShape getCullingShape(BlockState state, BlockView view, BlockPos pos) {
return isGhost(view, pos) ? empty(): getSlabShape(state.get(CORNER).getDirection(state.get(CORNER_FACE)));
}
@Override
public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
return getSlabShape(state.get(CORNER).getDirection(state.get(CORNER_FACE)));
}
@Override
@SuppressWarnings("deprecation")
public BlockState rotate(BlockState state, BlockRotation rotation) {
Corner corner = state.get(CORNER).rotate(rotation);
Direction face = state.get(CORNER).getDirection(state.get(CORNER_FACE));
return state.with(CORNER, corner).with(CORNER_FACE, corner.getDirectionIndex(rotation.rotate(face)));
}
@Override
@SuppressWarnings("deprecation")
public BlockState mirror(BlockState state, BlockMirror mirror) {
Corner corner = state.get(CORNER).mirror(mirror);
Direction face = state.get(CORNER).getDirection(state.get(CORNER_FACE));
return state.with(CORNER, corner).with(CORNER_FACE, corner.getDirectionIndex(mirror.apply(face)));
}
@Override
public VoxelShape getShape(BlockState state, int i) {
Corner corner = state.get(CORNER);
int face = state.get(CORNER_FACE);
return i == 2
? getSmallCubeShape(corner.getOpposite(face))
: getHalfStairShape(corner, face);
? SMALL_CUBE_VOXELS[corner.getOpposite(face).getID()]
: HALF_STAIR_VOXELS[face + corner.getID() * 3];
}
}

View File

@@ -9,18 +9,17 @@ import net.minecraft.block.BlockState;
import net.minecraft.block.ShapeContext;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.state.StateManager;
import net.minecraft.util.BlockMirror;
import net.minecraft.util.BlockRotation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.world.BlockView;
import org.jetbrains.annotations.Nullable;
import static fr.adrien1106.reframed.block.ReFramedHalfStairBlock.getHalfStairShape;
import static fr.adrien1106.reframed.block.ReFramedHalfStairBlock.HALF_STAIR_VOXELS;
import static fr.adrien1106.reframed.block.ReFramedStairBlock.getStairShape;
import static fr.adrien1106.reframed.util.blocks.BlockProperties.EDGE;
import static fr.adrien1106.reframed.util.blocks.Edge.*;
import static net.minecraft.util.shape.VoxelShapes.empty;
public class ReFramedHalfStairsStairBlock extends WaterloggableReFramedDoubleBlock {
public ReFramedHalfStairsStairBlock(Settings settings) {
@@ -28,6 +27,16 @@ public class ReFramedHalfStairsStairBlock extends WaterloggableReFramedDoubleBlo
setDefaultState(getDefaultState().with(EDGE, NORTH_DOWN));
}
@Override
public Object getModelCacheKey(BlockState state) {
return state.get(EDGE);
}
@Override
public int getModelStateCount() {
return 12;
}
@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(builder.add(EDGE));
@@ -40,23 +49,15 @@ public class ReFramedHalfStairsStairBlock extends WaterloggableReFramedDoubleBlo
}
@Override
@SuppressWarnings("deprecation")
public VoxelShape getCullingShape(BlockState state, BlockView view, BlockPos pos) {
return isGhost(view, pos) ? empty(): getStairShape(state.get(EDGE), StairShape.STRAIGHT);
}
@Override
public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
return getStairShape(state.get(EDGE), StairShape.STRAIGHT);
}
@Override
@SuppressWarnings("deprecation")
public BlockState rotate(BlockState state, BlockRotation rotation) {
return state.with(EDGE, state.get(EDGE).rotate(rotation));
}
@Override
@SuppressWarnings("deprecation")
public BlockState mirror(BlockState state, BlockMirror mirror) {
return state.with(EDGE, state.get(EDGE).mirror(mirror));
}
@Override
public VoxelShape getShape(BlockState state, int i) {
Edge edge = state.get(EDGE);
@@ -69,7 +70,7 @@ public class ReFramedHalfStairsStairBlock extends WaterloggableReFramedDoubleBlo
side
);
return getHalfStairShape(corner, corner.getDirectionIndex(side));
return HALF_STAIR_VOXELS[corner.getID() * 3 + corner.getDirectionIndex(side)];
}
@Override

View File

@@ -1,76 +0,0 @@
package fr.adrien1106.reframed.block;
import fr.adrien1106.reframed.util.blocks.BlockHelper;
import fr.adrien1106.reframed.util.blocks.Corner;
import fr.adrien1106.reframed.util.blocks.Edge;
import fr.adrien1106.reframed.util.blocks.StairShape;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.ShapeContext;
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.world.BlockView;
import org.jetbrains.annotations.Nullable;
import static fr.adrien1106.reframed.block.ReFramedHalfStairBlock.getHalfStairShape;
import static fr.adrien1106.reframed.block.ReFramedStairBlock.getStairShape;
import static fr.adrien1106.reframed.block.ReFramedStepBlock.getStepShape;
import static fr.adrien1106.reframed.util.blocks.BlockProperties.*;
public class ReFramedHalfStairsStepStairBlock extends CornerDoubleReFramedBlock {
public ReFramedHalfStairsStepStairBlock(Settings settings) {
super(settings);
setDefaultState(getDefaultState().with(CORNER_FEATURE, 0));
}
@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(builder.add(CORNER_FEATURE));
}
@Override
public @Nullable BlockState getPlacementState(ItemPlacementContext ctx) {
BlockState state = super.getPlacementState(ctx);
Corner corner = state.get(CORNER);
int face_index = state.get(CORNER_FACE);
Direction face = corner.getDirection(face_index);
face = BlockHelper.getPlacementEdge(ctx).getOtherDirection(face);
int feature_index = corner.getDirectionIndex(face);
return state.with(CORNER_FEATURE, feature_index > face_index ? feature_index - 1 : feature_index);
}
@Override
public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
Corner corner = state.get(CORNER);
int feature_index = state.get(CORNER_FEATURE), face_index = state.get(CORNER_FACE);
Direction feature_face = corner.getDirection(feature_index >= face_index ? feature_index + 1 : feature_index);
Direction face = corner.getDirection(face_index);
Edge edge = Edge.getByDirections(feature_face, face);
return getStairShape(
edge,
corner.getOtherDirection(edge).getDirection() == Direction.AxisDirection.POSITIVE
? edge.getDirectionIndex(face) == 0
? StairShape.FIRST_OUTER_LEFT
: StairShape.SECOND_OUTER_LEFT
: edge.getDirectionIndex(face) == 0
? StairShape.FIRST_OUTER_RIGHT
: StairShape.SECOND_OUTER_RIGHT
);
}
@Override
public VoxelShape getShape(BlockState state, int i) {
Corner corner = state.get(CORNER);
int feature_index = state.get(CORNER_FEATURE), face_index = state.get(CORNER_FACE);
Direction feature_face = corner.getDirection(feature_index >= face_index ? feature_index + 1 : feature_index);
Direction face = corner.getDirection(face_index);
return i == 2
? getStepShape(Edge.getByDirections(face.getOpposite(), feature_face))
: getHalfStairShape(corner, face_index);
}
}

View File

@@ -1,14 +1,12 @@
package fr.adrien1106.reframed.block;
import fr.adrien1106.reframed.ReFramed;
import fr.adrien1106.reframed.util.VoxelHelper;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.ShapeContext;
import net.minecraft.item.BlockItem;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.state.StateManager;
import net.minecraft.util.BlockMirror;
import net.minecraft.util.BlockRotation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.shape.VoxelShape;
@@ -16,59 +14,53 @@ import net.minecraft.world.BlockView;
import org.jetbrains.annotations.Nullable;
import static fr.adrien1106.reframed.util.VoxelHelper.VoxelListBuilder;
import static fr.adrien1106.reframed.util.blocks.BlockProperties.HALF_LAYERS;
import static net.minecraft.state.property.Properties.*;
import static net.minecraft.state.property.Properties.FACING;
import static net.minecraft.state.property.Properties.LAYERS;
public class ReFramedLayerBlock extends LayeredReFramedBlock {
public class ReFramedLayerBlock extends ReFramedSlabBlock {
public static final VoxelShape[] LAYER_VOXELS;
private record ModelCacheKey(Direction face, int layer) {}
public ReFramedLayerBlock(Settings settings) {
super(settings);
setDefaultState(getDefaultState().with(FACING, Direction.DOWN));
setDefaultState(getDefaultState().with(LAYERS, 1));
}
@Override
public Object getModelCacheKey(BlockState state) {
return new ModelCacheKey(state.get(FACING), state.get(LAYERS));
}
@Override
public int getModelStateCount() {
return 48;
}
@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(builder.add(FACING));
super.appendProperties(builder.add(LAYERS));
}
@Override
public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
return getLayerShape(state.get(FACING), state.get(LAYERS));
return LAYER_VOXELS[state.get(FACING).getId() * 8 + state.get(LAYERS) - 1];
}
public static VoxelShape getLayerShape(Direction facing, int layers) {
return LAYER_VOXELS[facing.getId() * 8 + layers - 1];
@Override
public boolean canReplace(BlockState state, ItemPlacementContext context) {
return !(
context.getPlayer().isSneaking()
|| !(context.getStack().getItem() instanceof BlockItem block_item)
|| !(block_item.getBlock() == this && state.get(LAYERS) < 8)
);
}
@Override
public @Nullable BlockState getPlacementState(ItemPlacementContext ctx) {
BlockState previous = ctx.getWorld().getBlockState(ctx.getBlockPos());
BlockState state = super.getPlacementState(ctx);
if (previous.isOf(this)) return state;
if (previous.isOf(ReFramed.SLAB))
return ReFramed.SLABS_LAYER.getDefaultState()
.with(FACING, previous.get(FACING))
.with(WATERLOGGED, previous.get(WATERLOGGED));
if (previous.isOf(ReFramed.SLABS_LAYER))
return previous.with(HALF_LAYERS, previous.get(HALF_LAYERS) + 1);
return state.with(FACING, ctx.getSide().getOpposite());
}
@Override
@SuppressWarnings("deprecation")
public BlockState rotate(BlockState state, BlockRotation rotation) {
return state.with(FACING, rotation.rotate(state.get(FACING)));
}
@Override
@SuppressWarnings("deprecation")
public BlockState mirror(BlockState state, BlockMirror mirror) {
return state.with(FACING, mirror.apply(state.get(FACING)));
if (!previous.isOf(this)) return super.getPlacementState(ctx);
return previous.with(LAYERS, previous.get(LAYERS) + 1);
}
static {

View File

@@ -1,47 +0,0 @@
package fr.adrien1106.reframed.block;
import fr.adrien1106.reframed.util.VoxelHelper;
import net.minecraft.block.BlockState;
import net.minecraft.block.PaneBlock;
import net.minecraft.block.ShapeContext;
import net.minecraft.registry.tag.BlockTags;
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;
public class ReFramedPaneBlock extends ConnectingReFramedBlock {
public static final VoxelShape[] PANE_VOXELS;
public ReFramedPaneBlock(Settings settings) {
super(settings);
}
@Override
public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
VoxelShape shape = PANE_VOXELS[0];
for (Direction dir: Direction.Type.HORIZONTAL) {
if (state.get(getConnectionProperty(dir)))
shape = VoxelShapes.union(shape, PANE_VOXELS[dir.ordinal() - 1]);
}
return shape;
}
@Override
protected boolean connectsTo(BlockState state, boolean fs, Direction dir) {
return !cannotConnect(state) && fs || state.getBlock() instanceof PaneBlock || state.isIn(BlockTags.WALLS);
}
static {
VoxelShape POST = createCuboidShape(7, 0, 7, 9, 16, 9);
VoxelShape SIDE = createCuboidShape(7, 0, 0, 9, 16, 7);
PANE_VOXELS = VoxelHelper.VoxelListBuilder.create(POST, 5)
.add(SIDE)
.add(VoxelHelper::mirrorZ)
.add(VoxelHelper::rotateY)
.add(VoxelHelper::mirrorX)
.build();
}
}

View File

@@ -1,21 +1,61 @@
package fr.adrien1106.reframed.block;
import fr.adrien1106.reframed.util.VoxelHelper;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.ShapeContext;
import net.minecraft.item.BlockItem;
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.world.BlockView;
import org.jetbrains.annotations.Nullable;
import java.util.Map;
import static net.minecraft.state.property.Properties.AXIS;
public class ReFramedPillarBlock extends PillarReFramedBlock {
public class ReFramedPillarBlock extends WaterloggableReFramedBlock {
public static final VoxelShape[] PILLAR_VOXELS;
public ReFramedPillarBlock(Settings settings) {
super(settings);
setDefaultState(getDefaultState().with(AXIS, Direction.Axis.Y));
}
@Override
public Object getModelCacheKey(BlockState state) {
return state.get(AXIS);
}
@Override
public int getModelStateCount() {
return 3;
}
@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(builder.add(AXIS));
}
@Override
public boolean canReplace(BlockState state, ItemPlacementContext context) {
return !(context.getPlayer().isSneaking()
|| !(context.getStack().getItem() instanceof BlockItem block_item)
|| !(
block_item.getBlock() == this
&& state.get(AXIS) != context.getSide().getAxis()
)
);
}
@Override
public @Nullable BlockState getPlacementState(ItemPlacementContext ctx) {
// TODO: PILLARS WALL
return super.getPlacementState(ctx).with(AXIS, ctx.getSide().getAxis());
}
@Override
@@ -27,6 +67,12 @@ public class ReFramedPillarBlock extends PillarReFramedBlock {
return PILLAR_VOXELS[axis.ordinal()];
}
@Override
public Map<Integer, Integer> getThemeMap(BlockState state, BlockState new_state) {
// if (new_state.getBlock() == ReFramed.PILLARS_WALL) return Map.of(1, 1); // TODO: PILLARS WALL
return super.getThemeMap(state, new_state);
}
static {
final VoxelShape PILLAR = createCuboidShape(0, 4, 4, 16, 12, 12);
PILLAR_VOXELS = VoxelHelper.VoxelListBuilder.create(PILLAR, 3)

View File

@@ -1,129 +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.BlockMirror;
import net.minecraft.util.BlockRotation;
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 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
@SuppressWarnings("deprecation")
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
@SuppressWarnings("deprecation")
public BlockState rotate(BlockState state, BlockRotation rotation) {
return Direction.Type.HORIZONTAL.stream().reduce(state, (s, dir) ->
s.with(getWallShape(rotation.rotate(dir)), state.get(getWallShape(dir)))
, (prev, next) -> next);
}
@Override
@SuppressWarnings("deprecation")
public BlockState mirror(BlockState state, BlockMirror mirror) {
return Direction.Type.HORIZONTAL.stream().reduce(state, (s, dir) ->
s.with(getWallShape(mirror.apply(dir)), state.get(getWallShape(dir)))
, (prev, next) -> next);
}
@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

@@ -1,37 +0,0 @@
package fr.adrien1106.reframed.block;
import fr.adrien1106.reframed.util.VoxelHelper;
import net.minecraft.block.BlockState;
import net.minecraft.block.ShapeContext;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.world.BlockView;
import static net.minecraft.state.property.Properties.AXIS;
public class ReFramedPostBlock extends PillarReFramedBlock {
public static final VoxelShape[] POST_VOXELS;
public ReFramedPostBlock(Settings settings) {
super(settings);
}
@Override
public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
return getPillarShape(state.get(AXIS));
}
public static VoxelShape getPillarShape(Direction.Axis axis) {
return POST_VOXELS[axis.ordinal()];
}
static {
final VoxelShape POST = createCuboidShape(0, 6, 6, 16, 10, 10);
POST_VOXELS = VoxelHelper.VoxelListBuilder.create(POST, 3)
.add(VoxelHelper::rotateZ)
.add(VoxelHelper::rotateX)
.build();
}
}

View File

@@ -1,150 +0,0 @@
package fr.adrien1106.reframed.block;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.FenceGateBlock;
import net.minecraft.block.ShapeContext;
import net.minecraft.entity.ai.pathing.NavigationType;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.item.LeadItem;
import net.minecraft.registry.tag.BlockTags;
import net.minecraft.state.StateManager;
import net.minecraft.util.ActionResult;
import net.minecraft.util.BlockMirror;
import net.minecraft.util.BlockRotation;
import net.minecraft.util.Hand;
import net.minecraft.util.hit.BlockHitResult;
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 static fr.adrien1106.reframed.block.ConnectingReFramedBlock.getConnectionProperty;
import static fr.adrien1106.reframed.block.ConnectingReFramedBlock.placementState;
import static fr.adrien1106.reframed.block.ReFramedFenceBlock.FENCE_VOXELS;
import static net.minecraft.state.property.Properties.*;
import static net.minecraft.state.property.Properties.WEST;
public class ReFramedPostFenceBlock extends WaterloggableReFramedDoubleBlock {
public ReFramedPostFenceBlock(Settings settings) {
super(settings);
setDefaultState(getDefaultState()
.with(EAST, false)
.with(NORTH, false)
.with(WEST, false)
.with(SOUTH, false)
);
}
@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(builder.add(EAST, NORTH, SOUTH, WEST));
}
@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;
return placementState(new_state, world, pos, this::connectsTo);
}
@Override
public @Nullable BlockState getPlacementState(ItemPlacementContext ctx) {
BlockState state = super.getPlacementState(ctx);
World world = ctx.getWorld();
BlockPos pos = ctx.getBlockPos();
return placementState(state, world, pos, this::connectsTo);
}
@Override
@SuppressWarnings("deprecation")
public BlockState rotate(BlockState state, BlockRotation rotation) {
return Direction.Type.HORIZONTAL.stream().reduce(state, (s, dir) ->
s.with(getConnectionProperty(rotation.rotate(dir)), state.get(getConnectionProperty(dir)))
, (prev, next) -> next);
}
@Override
@SuppressWarnings("deprecation")
public BlockState mirror(BlockState state, BlockMirror mirror) {
return Direction.Type.HORIZONTAL.stream().reduce(state, (s, dir) ->
s.with(getConnectionProperty(mirror.apply(dir)), state.get(getConnectionProperty(dir)))
, (prev, next) -> next);
}
private boolean connectsTo(BlockState state, boolean fs, Direction dir) {
return fs || state.isIn(BlockTags.FENCES)
|| (state.getBlock() instanceof FenceGateBlock && FenceGateBlock.canWallConnect(state, dir));
}
@Override
public VoxelShape getShape(BlockState state, int i) {
if (i == 1) return FENCE_VOXELS[0];
VoxelShape shape = VoxelShapes.empty();
for (Direction dir: Direction.Type.HORIZONTAL) {
if (state.get(getConnectionProperty(dir)))
shape = VoxelShapes.union(shape, FENCE_VOXELS[dir.ordinal() - 1]);
}
return shape;
}
@Override
@SuppressWarnings("deprecation")
public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
VoxelShape shape = FENCE_VOXELS[0];
for (Direction dir: Direction.Type.HORIZONTAL) {
if (state.get(getConnectionProperty(dir)))
shape = VoxelShapes.union(shape, FENCE_VOXELS[dir.ordinal() - 1]);
}
return shape;
}
@Override
public VoxelShape getCollisionShape(BlockState state, BlockView view, BlockPos pos, ShapeContext ctx) {
VoxelShape shape = FENCE_VOXELS[5];
for (Direction dir: Direction.Type.HORIZONTAL) {
if (state.get(getConnectionProperty(dir)))
shape = VoxelShapes.union(shape, FENCE_VOXELS[dir.ordinal() + 4]);
}
return shape;
}
@Override
@SuppressWarnings("deprecation")
public VoxelShape getCameraCollisionShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
return getOutlineShape(state, world, pos, context);
}
@Override
public VoxelShape getCullingShape(BlockState state, BlockView view, BlockPos pos) {
return getOutlineShape(state, view, pos, ShapeContext.absent());
}
@Override
@SuppressWarnings("deprecation")
public boolean canPathfindThrough(BlockState state, BlockView world, BlockPos pos, NavigationType type) {
return false;
}
public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) {
ActionResult result = super.onUse(state, world, pos, player, hand, hit);
if (result.isAccepted()) return result;
if (world.isClient) {
ItemStack itemStack = player.getStackInHand(hand);
return itemStack.isOf(Items.LEAD) ? ActionResult.SUCCESS : ActionResult.PASS;
} else {
return LeadItem.attachHeldMobsToBlock(player, world, pos);
}
}
}

View File

@@ -1,17 +1,12 @@
package fr.adrien1106.reframed.block;
import fr.adrien1106.reframed.ReFramed;
import fr.adrien1106.reframed.util.blocks.BlockHelper;
import fr.adrien1106.reframed.util.blocks.Corner;
import fr.adrien1106.reframed.util.blocks.Edge;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.ShapeContext;
import net.minecraft.item.BlockItem;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.state.StateManager;
import net.minecraft.util.BlockMirror;
import net.minecraft.util.BlockRotation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.shape.VoxelShape;
@@ -21,8 +16,8 @@ import org.jetbrains.annotations.Nullable;
import java.util.Map;
import static fr.adrien1106.reframed.util.blocks.BlockProperties.*;
import static net.minecraft.state.property.Properties.*;
import static net.minecraft.state.property.Properties.AXIS;
import static net.minecraft.state.property.Properties.FACING;
public class ReFramedSlabBlock extends WaterloggableReFramedBlock {
@@ -37,6 +32,16 @@ public class ReFramedSlabBlock extends WaterloggableReFramedBlock {
super(settings);
setDefaultState(getDefaultState().with(FACING, Direction.DOWN));
}
@Override
public Object getModelCacheKey(BlockState state) {
return state.get(FACING);
}
@Override
public int getModelStateCount() {
return 6;
}
@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
@@ -44,138 +49,39 @@ public class ReFramedSlabBlock extends WaterloggableReFramedBlock {
}
@Override
@SuppressWarnings("deprecation")
public boolean canReplace(BlockState state, ItemPlacementContext context) {
if (context.getPlayer() == null
|| context.getPlayer().isSneaking()
|| !(context.getStack().getItem() instanceof BlockItem block_item)
) return false;
// allow replacing with slab, step, small cube and half stair
Block block = block_item.getBlock();
if (block != this
&& block != ReFramed.STEP
&& block != ReFramed.SMALL_CUBE
&& block != ReFramed.HALF_STAIR
&& block != ReFramed.HALF_LAYER
&& block != ReFramed.LAYER
) return false;
// check if the player is clicking on the inner part of the block
return matchesShape(
context.getHitPos(),
context.getBlockPos(),
state.with(FACING, state.get(FACING).getOpposite())
);
return !(
context.getPlayer().isSneaking()
|| !(context.getStack().getItem() instanceof BlockItem block_item)
|| !(
block_item.getBlock() == this
&& ((ReFramedSlabsCubeBlock) ReFramed.SLABS_CUBE)
.matchesShape(
context.getHitPos(),
context.getBlockPos(),
ReFramed.SLABS_CUBE.getDefaultState().with(AXIS, state.get(FACING).getAxis()),
state.get(FACING).getDirection() == Direction.AxisDirection.POSITIVE ? 1 : 2
)
)
);
}
@Nullable
@Override
public BlockState getPlacementState(ItemPlacementContext ctx) {
BlockState current_state = ctx.getWorld().getBlockState(ctx.getBlockPos());
if (current_state.isOf(this))
return ReFramed.SLABS_CUBE.getDefaultState()
.with(AXIS, current_state.get(FACING).getAxis());
if (current_state.isOf(ReFramed.HALF_LAYER)) {
Edge edge = current_state.get(EDGE);
Direction face = edge.getDirection(current_state.get(EDGE_FACE));
edge = edge.getOpposite(face);
return ReFramed.SLABS_HALF_LAYER.getDefaultState()
.with(EDGE, edge)
.with(EDGE_FACE, edge.getDirectionIndex(edge.getOtherDirection(face)))
.with(LAYERS, current_state.get(LAYERS))
.with(WATERLOGGED, current_state.get(WATERLOGGED));
}
if (current_state.isOf(ReFramed.HALF_STAIR)) {
Corner corner = current_state.get(CORNER);
Direction face = corner.getDirection(current_state.get(CORNER_FACE));
corner = corner.change(face);
return ReFramed.SLABS_INNER_STAIR.getDefaultState()
.with(CORNER, corner)
.with(CORNER_FACE, corner.getDirectionIndex(face.getOpposite()))
.with(WATERLOGGED, current_state.get(WATERLOGGED));
}
if (current_state.isOf(ReFramed.STEP)) {
Edge edge = current_state.get(EDGE),
placed = BlockHelper.getPlacementEdge(ctx),
new_edge;
Direction face = edge.getFirstDirection(),
other = edge.getSecondDirection().getOpposite();
if (!ReFramed.STEP.matchesShape(
ctx.getHitPos(),
ctx.getBlockPos(),
current_state.with(EDGE, new_edge = edge.getOpposite(face))
)
&& ctx.getSide() != other.getOpposite()
&& (placed.getAxis() == edge.getAxis()
|| ctx.getSide() == other
|| !placed.hasDirection(other))
) {
new_edge = edge.getOpposite(edge.getSecondDirection());
other = edge.getFirstDirection().getOpposite();
}
return ReFramed.SLABS_STAIR.getDefaultState()
.with(EDGE, new_edge)
.with(EDGE_FACE, new_edge.getDirectionIndex(other))
.with(WATERLOGGED, current_state.get(WATERLOGGED));
}
if (current_state.isOf(ReFramed.SMALL_CUBE)) {
Corner corner = current_state.get(CORNER);
Edge placed = BlockHelper.getPlacementEdge(ctx);
Direction face;
Corner new_corner;
if (!corner.hasDirection(face = ctx.getSide())) {
int i = 0;
do {
face = corner.getDirection(i);
new_corner = corner.change(face);
} while (!ReFramed.SMALL_CUBE.matchesShape(
ctx.getHitPos(),
ctx.getBlockPos(),
current_state.with(CORNER, new_corner)
) && ++i < 3);
if (i == 3) {
face = placed.getOtherDirection(corner.getMatchingDirection(placed)).getOpposite();
new_corner = corner.change(face);
}
} else new_corner = corner.change(face);
return ReFramed.SLABS_OUTER_STAIR.getDefaultState()
.with(CORNER, new_corner)
.with(CORNER_FACE, new_corner.getDirectionIndex(face.getOpposite()))
.with(WATERLOGGED, current_state.get(WATERLOGGED));
}
return super.getPlacementState(ctx).with(FACING, ctx.getSide().getOpposite());
}
@Override
@SuppressWarnings("deprecation")
public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
return getSlabShape(state.get(FACING));
}
@Override
@SuppressWarnings("deprecation")
public BlockState rotate(BlockState state, BlockRotation rotation) {
return state.with(FACING, rotation.rotate(state.get(FACING)));
}
@Override
@SuppressWarnings("deprecation")
public BlockState mirror(BlockState state, BlockMirror mirror) {
return state.with(FACING, mirror.apply(state.get(FACING)));
}
public static VoxelShape getSlabShape(Direction side) {
return switch (side) {
case DOWN -> DOWN;
@@ -189,11 +95,6 @@ public class ReFramedSlabBlock extends WaterloggableReFramedBlock {
@Override
public Map<Integer, Integer> getThemeMap(BlockState state, BlockState new_state) {
if (new_state.isOf(ReFramed.SLABS_STAIR)
|| new_state.isOf(ReFramed.SLABS_OUTER_STAIR)
|| new_state.isOf(ReFramed.SLABS_INNER_STAIR)
|| new_state.isOf(ReFramed.SLABS_HALF_LAYER)
) return Map.of(1, 1);
if (new_state.isOf(ReFramed.SLABS_CUBE)) return Map.of(1, state.get(FACING).getDirection() == Direction.AxisDirection.POSITIVE ? 2 : 1);
return super.getThemeMap(state, new_state);
}

View File

@@ -4,8 +4,6 @@ import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.state.StateManager;
import net.minecraft.util.BlockMirror;
import net.minecraft.util.BlockRotation;
import net.minecraft.util.math.Direction;
import net.minecraft.util.shape.VoxelShape;
import org.jetbrains.annotations.Nullable;
@@ -20,6 +18,16 @@ public class ReFramedSlabsCubeBlock extends ReFramedDoubleBlock {
setDefaultState(getDefaultState().with(AXIS, Direction.Axis.Y));
}
@Override
public Object getModelCacheKey(BlockState state) {
return state.get(AXIS);
}
@Override
public int getModelStateCount() {
return 3;
}
@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(builder.add(AXIS));
@@ -31,18 +39,6 @@ public class ReFramedSlabsCubeBlock extends ReFramedDoubleBlock {
return super.getPlacementState(ctx).with(AXIS, ctx.getSide().getAxis());
}
@Override
@SuppressWarnings("deprecation")
public BlockState rotate(BlockState state, BlockRotation rotation) {
return state.with(AXIS, rotation.rotate(Direction.get(Direction.AxisDirection.POSITIVE, state.get(AXIS))).getAxis());
}
@Override
@SuppressWarnings("deprecation")
public BlockState mirror(BlockState state, BlockMirror mirror) {
return state.with(AXIS, mirror.apply(Direction.get(Direction.AxisDirection.POSITIVE, state.get(AXIS))).getAxis());
}
@Override
public VoxelShape getShape(BlockState state, int i) {
return switch (state.get(AXIS)) {

View File

@@ -1,62 +0,0 @@
package fr.adrien1106.reframed.block;
import fr.adrien1106.reframed.util.blocks.Edge;
import net.minecraft.block.BlockState;
import net.minecraft.block.ShapeContext;
import net.minecraft.util.function.BooleanBiFunction;
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 static fr.adrien1106.reframed.block.ReFramedHalfLayerBlock.getHalfLayerShape;
import static fr.adrien1106.reframed.block.ReFramedSlabBlock.getSlabShape;
import static fr.adrien1106.reframed.util.blocks.BlockProperties.EDGE;
import static fr.adrien1106.reframed.util.blocks.BlockProperties.EDGE_FACE;
import static net.minecraft.state.property.Properties.LAYERS;
public class ReFramedSlabsHalfLayerBlock extends HalfLayerDoubleReFramedBlock {
private static final VoxelShape[] SLABS_HALF_LAYER_VOXELS = new VoxelShape[196];
public ReFramedSlabsHalfLayerBlock(Settings settings) {
super(settings);
}
@Override
public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
return getSlabsHalfLayerShape(state.get(EDGE), state.get(EDGE_FACE), state.get(LAYERS));
}
public static VoxelShape getSlabsHalfLayerShape(Edge edge, int face, int layers) {
int i = edge.ordinal() * 16 + face * 8 + layers - 1;
VoxelShape shape = SLABS_HALF_LAYER_VOXELS[i];
if (shape == null) {
shape = VoxelShapes.combineAndSimplify(
getShape(edge, edge.getDirection(face), layers, 1),
getShape(edge, edge.getDirection(face), layers, 2),
BooleanBiFunction.OR
);
SLABS_HALF_LAYER_VOXELS[i] = shape;
}
return shape;
}
@Override
public VoxelShape getShape(BlockState state, int i) {
Edge edge = state.get(EDGE);
Direction face = edge.getDirection(state.get(EDGE_FACE));
return getShape(edge, face, state.get(LAYERS), i);
}
private static VoxelShape getShape(Edge edge, Direction face, int layers, int i) {
if (i == 2) {
face = edge.getOtherDirection(face);
edge = edge.getOpposite(face);
}
return i == 2
? getHalfLayerShape(edge, edge.getDirectionIndex(face), layers)
: getSlabShape(face);
}
}

View File

@@ -1,48 +0,0 @@
package fr.adrien1106.reframed.block;
import fr.adrien1106.reframed.util.blocks.Corner;
import fr.adrien1106.reframed.util.blocks.Edge;
import fr.adrien1106.reframed.util.blocks.StairShape;
import net.minecraft.block.BlockState;
import net.minecraft.block.ShapeContext;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.world.BlockView;
import static fr.adrien1106.reframed.block.ReFramedHalfStairBlock.getHalfStairShape;
import static fr.adrien1106.reframed.block.ReFramedSlabBlock.getSlabShape;
import static fr.adrien1106.reframed.block.ReFramedStairBlock.getStairShape;
import static fr.adrien1106.reframed.util.blocks.BlockProperties.CORNER;
import static fr.adrien1106.reframed.util.blocks.BlockProperties.CORNER_FACE;
public class ReFramedSlabsInnerStairBlock extends CornerDoubleReFramedBlock {
public ReFramedSlabsInnerStairBlock(Settings settings) {
super(settings);
}
@Override
public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
Corner corner = state.get(CORNER);
Direction face = corner.getDirection(state.get(CORNER_FACE));
Edge edge = corner.getEdge(face);
return getStairShape(
edge,
face.getDirection() == Direction.AxisDirection.POSITIVE
? StairShape.INNER_LEFT
: StairShape.INNER_RIGHT
);
}
@Override
public VoxelShape getShape(BlockState state, int i) {
Corner corner = state.get(CORNER);
Direction face = corner.getDirection(state.get(CORNER_FACE));
if (i == 2) corner = corner.change(face);
return i == 2
? getHalfStairShape(corner, corner.getDirectionIndex(face.getOpposite()))
: getSlabShape(face);
}
}

View File

@@ -1,96 +0,0 @@
package fr.adrien1106.reframed.block;
import fr.adrien1106.reframed.ReFramed;
import fr.adrien1106.reframed.util.VoxelHelper;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.ShapeContext;
import net.minecraft.item.BlockItem;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.item.ItemStack;
import net.minecraft.loot.context.LootContextParameterSet;
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.world.BlockView;
import java.util.List;
import static fr.adrien1106.reframed.block.ReFramedLayerBlock.getLayerShape;
import static fr.adrien1106.reframed.block.ReFramedSlabBlock.getSlabShape;
import static fr.adrien1106.reframed.util.blocks.BlockProperties.HALF_LAYERS;
import static net.minecraft.state.property.Properties.FACING;
public class ReFramedSlabsLayerBlock extends FacingDoubleReFramedBlock {
public static VoxelShape[] HALF_LAYER_SHAPES;
public ReFramedSlabsLayerBlock(Settings settings) {
super(settings);
setDefaultState(getDefaultState().with(HALF_LAYERS, 1));
}
@Override
@SuppressWarnings("deprecation")
public List<ItemStack> getDroppedStacks(BlockState state, LootContextParameterSet.Builder builder) {
List<ItemStack> drops = super.getDroppedStacks(state, builder);
if (state.get(HALF_LAYERS) > 1)
drops.add(new ItemStack(ReFramed.LAYER, state.get(HALF_LAYERS)-1));
return drops;
}
@Override
@SuppressWarnings("deprecation")
public boolean canReplace(BlockState state, ItemPlacementContext context) {
if (context.getPlayer() == null
|| context.getPlayer().isSneaking()
|| !(context.getStack().getItem() instanceof BlockItem block_item)
) return false;
return block_item.getBlock() == ReFramed.LAYER && state.get(HALF_LAYERS) < 4;
}
@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(builder.add(HALF_LAYERS));
}
@Override
public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
return getLayerShape(state.get(FACING), state.get(HALF_LAYERS) + 4);
}
@Override
public VoxelShape getShape(BlockState state, int i) {
Direction face = state.get(FACING);
return i == 2
? HALF_LAYER_SHAPES[face.getId() * 4 + state.get(HALF_LAYERS)-1]
: getSlabShape(face);
}
static {
VoxelHelper.VoxelListBuilder builder = VoxelHelper.VoxelListBuilder.create(createCuboidShape(0, 8, 0, 16, 10, 16), 24)
.add(createCuboidShape(0, 8, 0, 16, 12, 16))
.add(createCuboidShape(0, 8, 0, 16, 14, 16))
.add(createCuboidShape(0, 8, 0, 16, 16, 16));
for (int i = 0; i < 4; i++) {
builder.add(i, VoxelHelper::mirrorY);
}
for (int i = 0; i < 4; i++) {
builder.add(i, VoxelHelper::rotateX);
}
for (int i = 0; i < 4; i++) {
builder.add(i, VoxelHelper::rotateCX);
}
for (int i = 0; i < 4; i++) {
builder.add(i, VoxelHelper::rotateCZ);
}
for (int i = 0; i < 4; i++) {
builder.add(i, VoxelHelper::rotateZ);
}
HALF_LAYER_SHAPES = builder.build();
}
}

View File

@@ -1,51 +0,0 @@
package fr.adrien1106.reframed.block;
import fr.adrien1106.reframed.util.blocks.Corner;
import fr.adrien1106.reframed.util.blocks.Edge;
import fr.adrien1106.reframed.util.blocks.StairShape;
import net.minecraft.block.BlockState;
import net.minecraft.block.ShapeContext;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.world.BlockView;
import static fr.adrien1106.reframed.block.ReFramedSlabBlock.getSlabShape;
import static fr.adrien1106.reframed.block.ReFramedSmallCubeBlock.getSmallCubeShape;
import static fr.adrien1106.reframed.block.ReFramedStairBlock.getStairShape;
import static fr.adrien1106.reframed.util.blocks.BlockProperties.CORNER;
import static fr.adrien1106.reframed.util.blocks.BlockProperties.CORNER_FACE;
public class ReFramedSlabsOuterStairBlock extends CornerDoubleReFramedBlock {
public ReFramedSlabsOuterStairBlock(Settings settings) {
super(settings);
}
@Override
public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
Corner corner = state.get(CORNER);
Direction face = corner.getDirection(state.get(CORNER_FACE));
Edge edge = corner.getEdgeWith(face);
return getStairShape(
edge,
corner.getOtherDirection(edge).getDirection() == Direction.AxisDirection.POSITIVE
? edge.getDirectionIndex(face) == 1
? StairShape.FIRST_OUTER_LEFT
: StairShape.SECOND_OUTER_LEFT
: edge.getDirectionIndex(face) == 1
? StairShape.FIRST_OUTER_RIGHT
: StairShape.SECOND_OUTER_RIGHT
);
}
@Override
public VoxelShape getShape(BlockState state, int i) {
Corner corner = state.get(CORNER);
Direction face = corner.getDirection(state.get(CORNER_FACE));
return i == 2
? getSmallCubeShape(corner.change(face))
: getSlabShape(face);
}
}

View File

@@ -1,37 +0,0 @@
package fr.adrien1106.reframed.block;
import fr.adrien1106.reframed.util.blocks.Edge;
import fr.adrien1106.reframed.util.blocks.StairShape;
import net.minecraft.block.BlockState;
import net.minecraft.block.ShapeContext;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.world.BlockView;
import static fr.adrien1106.reframed.block.ReFramedSlabBlock.getSlabShape;
import static fr.adrien1106.reframed.block.ReFramedStairBlock.getStairShape;
import static fr.adrien1106.reframed.block.ReFramedStepBlock.getStepShape;
import static fr.adrien1106.reframed.util.blocks.BlockProperties.EDGE;
import static fr.adrien1106.reframed.util.blocks.BlockProperties.EDGE_FACE;
public class ReFramedSlabsStairBlock extends EdgeDoubleReFramedBlock {
public ReFramedSlabsStairBlock(Settings settings) {
super(settings);
}
@Override
public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
return getStairShape(state.get(EDGE), StairShape.STRAIGHT);
}
@Override
public VoxelShape getShape(BlockState state, int i) {
Edge edge = state.get(EDGE);
Direction face = edge.getDirection(state.get(EDGE_FACE));
return i == 2
? getStepShape(edge.getOpposite(edge.getOtherDirection(face)))
: getSlabShape(face);
}
}

View File

@@ -4,16 +4,12 @@ import fr.adrien1106.reframed.ReFramed;
import fr.adrien1106.reframed.util.VoxelHelper;
import fr.adrien1106.reframed.util.blocks.BlockHelper;
import fr.adrien1106.reframed.util.blocks.Corner;
import fr.adrien1106.reframed.util.blocks.Edge;
import fr.adrien1106.reframed.util.blocks.StairShape;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.ShapeContext;
import net.minecraft.item.BlockItem;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.state.StateManager;
import net.minecraft.util.BlockMirror;
import net.minecraft.util.BlockRotation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.Vec3d;
@@ -27,7 +23,6 @@ import java.util.Map;
import static fr.adrien1106.reframed.util.VoxelHelper.VoxelListBuilder;
import static fr.adrien1106.reframed.util.blocks.BlockProperties.*;
import static fr.adrien1106.reframed.util.blocks.Corner.*;
import static net.minecraft.state.property.Properties.FACING;
import static net.minecraft.state.property.Properties.WATERLOGGED;
public class ReFramedSmallCubeBlock extends WaterloggableReFramedBlock {
@@ -39,79 +34,79 @@ public class ReFramedSmallCubeBlock extends WaterloggableReFramedBlock {
setDefaultState(getDefaultState().with(CORNER, NORTH_EAST_DOWN));
}
@Override
public Object getModelCacheKey(BlockState state) {
return state.get(CORNER);
}
@Override
public int getModelStateCount() {
return 8;
}
@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(builder.add(CORNER));
}
@Override
@SuppressWarnings("deprecation")
public boolean canReplace(BlockState state, ItemPlacementContext context) {
if (context.getPlayer() == null
|| context.getPlayer().isSneaking()
|| !(context.getStack().getItem() instanceof BlockItem block_item)
) return false;
Block block = block_item.getBlock();
Corner corner = state.get(CORNER);
if (block == this)
return matchesShape(
context.getHitPos(),
context.getBlockPos(),
getDefaultState().with(CORNER, corner.change(corner.getFirstDirection()))
) || matchesShape(
context.getHitPos(),
context.getBlockPos(),
getDefaultState().with(CORNER, corner.change(corner.getSecondDirection()))
) || matchesShape(
context.getHitPos(),
context.getBlockPos(),
getDefaultState().with(CORNER, corner.change(corner.getThirdDirection()))
);
if (block == ReFramed.HALF_STAIR || block == ReFramed.SLAB) {
corner = corner.getOpposite();
Direction face = corner.getFirstDirection();
Edge edge = corner.getEdge(face);
if (ReFramed.STAIR.matchesShape(
context.getHitPos(),
context.getBlockPos(),
ReFramed.STAIR.getDefaultState()
.with(EDGE, edge)
.with(
STAIR_SHAPE,
face.getDirection() == Direction.AxisDirection.POSITIVE
? StairShape.INNER_LEFT
: StairShape.INNER_RIGHT
return !(
context.getPlayer().isSneaking()
|| !(context.getStack().getItem() instanceof BlockItem block_item)
|| (
!(
block_item.getBlock() == ReFramed.HALF_STAIR
&& !(corner.hasDirection(context.getSide())
|| (corner.hasDirection(context.getSide().getOpposite())
&& BlockHelper.cursorMatchesFace(
getOutlineShape(state, context.getWorld(), context.getBlockPos(), null),
BlockHelper.getRelativePos(context.getHitPos(), context.getBlockPos())
)
)
)
)
)) return block == ReFramed.SLAB || !matchesShape(
context.getHitPos(),
context.getBlockPos(),
getDefaultState().with(CORNER, corner)
);
}
return false;
&& !(
block_item.getBlock() == this
&& (
((ReFramedSmallCubesStepBlock) ReFramed.SMALL_CUBES_STEP)
.matchesShape(
context.getHitPos(),
context.getBlockPos(),
ReFramed.SMALL_CUBES_STEP.getDefaultState().with(EDGE, corner.getEdge(corner.getFirstDirection())),
corner.getFirstDirection().getDirection() == Direction.AxisDirection.POSITIVE ? 1 : 2
)
|| ((ReFramedSmallCubesStepBlock) ReFramed.SMALL_CUBES_STEP)
.matchesShape(
context.getHitPos(),
context.getBlockPos(),
ReFramed.SMALL_CUBES_STEP.getDefaultState().with(EDGE, corner.getEdge(corner.getSecondDirection())),
corner.getSecondDirection().getDirection() == Direction.AxisDirection.POSITIVE ? 1 : 2
)
|| ((ReFramedSmallCubesStepBlock) ReFramed.SMALL_CUBES_STEP)
.matchesShape(
context.getHitPos(),
context.getBlockPos(),
ReFramed.SMALL_CUBES_STEP.getDefaultState().with(EDGE, corner.getEdge(corner.getThirdDirection())),
corner.getThirdDirection().getDirection() == Direction.AxisDirection.POSITIVE ? 1 : 2
)
)
)
)
);
}
@Override
public @Nullable BlockState getPlacementState(ItemPlacementContext ctx) {
BlockPos pos = ctx.getBlockPos();
BlockState current_state = ctx.getWorld().getBlockState(pos);
if (current_state.isOf(ReFramed.HALF_STAIR)) {
BlockState new_state;
Direction face = current_state.get(CORNER).getDirection(current_state.get(CORNER_FACE));
if (matchesShape(
ctx.getHitPos(), pos,
getDefaultState().with(CORNER, current_state.get(CORNER).change(face))
)) new_state = ReFramed.HALF_STAIRS_CUBE_STAIR.getDefaultState();
else new_state = ReFramed.HALF_STAIRS_SLAB.getDefaultState();
return new_state
if (current_state.isOf(ReFramed.HALF_STAIR))
return ReFramed.HALF_STAIRS_SLAB.getDefaultState()
.with(CORNER, current_state.get(CORNER))
.with(CORNER_FACE, current_state.get(CORNER_FACE))
.with(WATERLOGGED, current_state.get(WATERLOGGED));
}
if (current_state.isOf(this)) {
Vec3d hit = ctx.getHitPos();
@@ -132,42 +127,17 @@ public class ReFramedSmallCubeBlock extends WaterloggableReFramedBlock {
return state.with(EDGE, corner.getEdge(corner.getThirdDirection()));
}
if (current_state.isOf(ReFramed.SLAB)) {
Corner corner = BlockHelper.getPlacementCorner(ctx);
Direction face = current_state.get(FACING);
if (!corner.hasDirection(face)) corner = corner.change(face.getOpposite());
return ReFramed.SLABS_OUTER_STAIR.getDefaultState()
.with(CORNER, corner)
.with(CORNER_FACE, corner.getDirectionIndex(face))
.with(WATERLOGGED, current_state.get(WATERLOGGED));
}
return super.getPlacementState(ctx).with(CORNER, BlockHelper.getPlacementCorner(ctx));
}
@Override
@SuppressWarnings("deprecation")
public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
return getSmallCubeShape(state.get(CORNER));
}
@Override
@SuppressWarnings("deprecation")
public BlockState rotate(BlockState state, BlockRotation rotation) {
return state.with(CORNER, state.get(CORNER).rotate(rotation));
}
@Override
@SuppressWarnings("deprecation")
public BlockState mirror(BlockState state, BlockMirror mirror) {
return state.with(CORNER, state.get(CORNER).mirror(mirror));
return SMALL_CUBE_VOXELS[state.get(CORNER).getID()];
}
@Override
public Map<Integer, Integer> getThemeMap(BlockState state, BlockState new_state) {
if (new_state.isOf(ReFramed.HALF_STAIRS_SLAB)
|| new_state.isOf(ReFramed.SLABS_OUTER_STAIR)
) return Map.of(1, 2);
if (new_state.isOf(ReFramed.HALF_STAIRS_SLAB)) return Map.of(1, 2);
if (new_state.isOf(ReFramed.SMALL_CUBES_STEP))
return Map.of(
1,
@@ -178,10 +148,6 @@ public class ReFramedSmallCubeBlock extends WaterloggableReFramedBlock {
return super.getThemeMap(state, new_state);
}
public static VoxelShape getSmallCubeShape(Corner corner) {
return SMALL_CUBE_VOXELS[corner.getID()];
}
static {
final VoxelShape SMALL_CUBE = VoxelShapes.cuboid(.5f, 0f, 0f, 1f, .5f, .5f);

View File

@@ -8,8 +8,6 @@ import net.minecraft.block.BlockState;
import net.minecraft.block.ShapeContext;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.state.StateManager;
import net.minecraft.util.BlockMirror;
import net.minecraft.util.BlockRotation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.world.BlockView;
@@ -18,6 +16,7 @@ import org.jetbrains.annotations.Nullable;
import static fr.adrien1106.reframed.block.ReFramedSmallCubeBlock.SMALL_CUBE_VOXELS;
import static fr.adrien1106.reframed.block.ReFramedStepBlock.getStepShape;
import static fr.adrien1106.reframed.util.blocks.BlockProperties.EDGE;
import static net.minecraft.util.shape.VoxelShapes.empty;
public class ReFramedSmallCubesStepBlock extends WaterloggableReFramedDoubleBlock {
@@ -26,6 +25,16 @@ public class ReFramedSmallCubesStepBlock extends WaterloggableReFramedDoubleBloc
setDefaultState(getDefaultState().with(EDGE, Edge.NORTH_DOWN));
}
@Override
public Object getModelCacheKey(BlockState state) {
return state.get(EDGE);
}
@Override
public int getModelStateCount() {
return 12;
}
@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(builder.add(EDGE));
@@ -38,23 +47,15 @@ public class ReFramedSmallCubesStepBlock extends WaterloggableReFramedDoubleBloc
}
@Override
@SuppressWarnings("deprecation")
public VoxelShape getCullingShape(BlockState state, BlockView view, BlockPos pos) {
return isGhost(view, pos) ? empty(): getStepShape(state.get(EDGE));
}
@Override
public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
return getStepShape(state.get(EDGE));
}
@Override
@SuppressWarnings("deprecation")
public BlockState rotate(BlockState state, BlockRotation rotation) {
return state.with(EDGE, state.get(EDGE).rotate(rotation));
}
@Override
@SuppressWarnings("deprecation")
public BlockState mirror(BlockState state, BlockMirror mirror) {
return state.with(EDGE, state.get(EDGE).mirror(mirror));
}
@Override
public VoxelShape getShape(BlockState state, int i) {
Edge edge = state.get(EDGE);

View File

@@ -11,14 +11,13 @@ import net.minecraft.block.ShapeContext;
import net.minecraft.item.BlockItem;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.state.StateManager;
import net.minecraft.util.BlockMirror;
import net.minecraft.util.BlockRotation;
import net.minecraft.util.function.BooleanBiFunction;
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;
@@ -32,11 +31,22 @@ import static fr.adrien1106.reframed.util.blocks.StairShape.*;
public class ReFramedStairBlock extends WaterloggableReFramedBlock {
public static final VoxelShape[] STAIR_VOXELS;
private record ModelCacheKey(Edge edge, StairShape shape) {}
public ReFramedStairBlock(Settings settings) {
super(settings);
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
public int getModelStateCount() {
return 108; // Has 12 * 9 state combination and 52 models still reduces cache size
}
@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
@@ -44,15 +54,13 @@ public class ReFramedStairBlock extends WaterloggableReFramedBlock {
}
@Override
@SuppressWarnings("deprecation")
public boolean canReplace(BlockState state, ItemPlacementContext context) {
if (context.getPlayer() == null) return false;
return !(
context.getPlayer().isSneaking()
|| !(context.getStack().getItem() instanceof BlockItem block_item)
|| !(
block_item.getBlock() == ReFramed.STEP
&& ReFramed.STAIRS_CUBE
&& ((ReFramedStairsCubeBlock) ReFramed.STAIRS_CUBE)
.matchesShape(
context.getHitPos(),
context.getBlockPos(),
@@ -87,38 +95,17 @@ public class ReFramedStairBlock extends WaterloggableReFramedBlock {
}
@Override
@SuppressWarnings("deprecation")
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 getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
return getStairShape(state.get(EDGE), state.get(STAIR_SHAPE));
}
@Override
@SuppressWarnings("deprecation")
public BlockState rotate(BlockState state, BlockRotation rotation) {
Edge prev_edge = state.get(EDGE);
Edge edge = prev_edge.rotate(rotation);
if (prev_edge.getAxis() == Direction.Axis.Y) return state.with(EDGE, edge);
if (prev_edge.getFace().getDirection() == edge.getFace().getDirection()) // 90° rotations
state = state.with(STAIR_SHAPE, state.get(STAIR_SHAPE).mirror());
else state = state.with(STAIR_SHAPE, state.get(STAIR_SHAPE).flip());
if (prev_edge.getAxis() == edge.getAxis()) // 180° rotation
state = state.with(STAIR_SHAPE, state.get(STAIR_SHAPE).mirror());
return state.with(EDGE, edge);
}
@Override
@SuppressWarnings("deprecation")
public BlockState mirror(BlockState state, BlockMirror mirror) {
Edge prev_edge = state.get(EDGE);
Edge edge = prev_edge.mirror(mirror);
return state
.with(STAIR_SHAPE, prev_edge == edge ? state.get(STAIR_SHAPE).mirror() : state.get(STAIR_SHAPE).flip())
.with(EDGE, edge);
}
public static VoxelShape getStairShape(Edge edge, StairShape shape) {
return STAIR_VOXELS[edge.getID() * 9 + shape.getID()];
}

View File

@@ -7,11 +7,10 @@ import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.state.StateManager;
import net.minecraft.util.BlockMirror;
import net.minecraft.util.BlockRotation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.world.World;
import net.minecraft.world.WorldAccess;
import org.jetbrains.annotations.Nullable;
@@ -23,19 +22,29 @@ import static fr.adrien1106.reframed.util.blocks.BlockProperties.STAIR_SHAPE;
public class ReFramedStairsCubeBlock extends ReFramedDoubleBlock {
private static final VoxelShape[] STAIRS_CUBE_VOXELS = VoxelListBuilder.buildFrom(STAIR_VOXELS);
private record ModelCacheKey(Edge edge, StairShape shape) {}
public ReFramedStairsCubeBlock(Settings settings) {
super(settings);
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
public int getModelStateCount() {
return 108; // Has 12 * 9 state combination and 52 models still reduces cache size
}
@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(builder.add(EDGE, STAIR_SHAPE));
}
@Override
@SuppressWarnings("deprecation")
public BlockState getStateForNeighborUpdate(BlockState state, Direction direction, BlockState neighbor_state, WorldAccess world, BlockPos pos, BlockPos moved) {
return super.getStateForNeighborUpdate(state, direction, neighbor_state, world, pos, moved)
.with(STAIR_SHAPE, BlockHelper.getStairsShape(state.get(EDGE), world, pos));
@@ -50,32 +59,11 @@ public class ReFramedStairsCubeBlock extends ReFramedDoubleBlock {
return super.getPlacementState(ctx).with(EDGE, face).with(STAIR_SHAPE, shape);
}
@Override
@SuppressWarnings("deprecation")
public BlockState rotate(BlockState state, BlockRotation rotation) {
Edge prev_edge = state.get(EDGE);
Edge edge = prev_edge.rotate(rotation);
if (prev_edge.getAxis() == Direction.Axis.Y) return state.with(EDGE, edge);
public void onStateReplaced(BlockState state, World world, BlockPos pos, BlockState newState, boolean moved) {
super.onStateReplaced(state, world, pos, newState, moved);
if (prev_edge.getFace().getDirection() == edge.getFace().getDirection()) // 90° rotations
state = state.with(STAIR_SHAPE, state.get(STAIR_SHAPE).mirror());
else state = state.with(STAIR_SHAPE, state.get(STAIR_SHAPE).flip());
if (prev_edge.getAxis() == edge.getAxis()) // 180° rotation
state = state.with(STAIR_SHAPE, state.get(STAIR_SHAPE).mirror());
return state.with(EDGE, edge);
}
@Override
@SuppressWarnings("deprecation")
public BlockState mirror(BlockState state, BlockMirror mirror) {
Edge prev_edge = state.get(EDGE);
Edge edge = prev_edge.mirror(mirror);
return state
.with(STAIR_SHAPE, prev_edge == edge ? state.get(STAIR_SHAPE).mirror() : state.get(STAIR_SHAPE).flip())
.with(EDGE, edge);
if(!state.isOf(newState.getBlock())) world.removeBlockEntity(pos);
}
@Override

View File

@@ -3,7 +3,6 @@ package fr.adrien1106.reframed.block;
import fr.adrien1106.reframed.ReFramed;
import fr.adrien1106.reframed.util.VoxelHelper;
import fr.adrien1106.reframed.util.blocks.BlockHelper;
import fr.adrien1106.reframed.util.blocks.Corner;
import fr.adrien1106.reframed.util.blocks.Edge;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
@@ -11,8 +10,6 @@ import net.minecraft.block.ShapeContext;
import net.minecraft.item.BlockItem;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.state.StateManager;
import net.minecraft.util.BlockMirror;
import net.minecraft.util.BlockRotation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.Vec3d;
@@ -23,9 +20,10 @@ import org.jetbrains.annotations.Nullable;
import java.util.Map;
import static fr.adrien1106.reframed.util.VoxelHelper.VoxelListBuilder;
import static fr.adrien1106.reframed.util.blocks.BlockProperties.*;
import static fr.adrien1106.reframed.util.blocks.BlockProperties.EDGE;
import static fr.adrien1106.reframed.util.blocks.BlockProperties.STAIR_SHAPE;
import static net.minecraft.state.property.Properties.*;
import static net.minecraft.state.property.Properties.WATERLOGGED;
public class ReFramedStepBlock extends WaterloggableReFramedBlock {
@@ -36,44 +34,64 @@ public class ReFramedStepBlock extends WaterloggableReFramedBlock {
setDefaultState(getDefaultState().with(EDGE, Edge.NORTH_DOWN));
}
@Override
public Object getModelCacheKey(BlockState state) {
return state.get(EDGE);
}
@Override
public int getModelStateCount() {
return 12;
}
@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(builder.add(EDGE));
}
@Override
@SuppressWarnings("deprecation")
public boolean canReplace(BlockState state, ItemPlacementContext context) {
if (context.getPlayer() == null
|| context.getPlayer().isSneaking()
|| !(context.getStack().getItem() instanceof BlockItem block_item)
) return false;
Block block = block_item.getBlock();
Edge edge = state.get(EDGE);
if (block == ReFramed.HALF_LAYER)
return matchesShape(
context.getHitPos(),
context.getBlockPos(),
getDefaultState().with(EDGE, edge.getOpposite(edge.getFirstDirection()))
) || matchesShape(
context.getHitPos(),
context.getBlockPos(),
getDefaultState().with(EDGE, edge.getOpposite(edge.getSecondDirection()))
);
return !(
context.getPlayer().isSneaking()
|| !(context.getStack().getItem() instanceof BlockItem block_item)
|| (
!(
block_item.getBlock() == ReFramed.STAIR
&& ((ReFramedStairsCubeBlock) ReFramed.STAIRS_CUBE)
.matchesShape(
context.getHitPos(),
context.getBlockPos(),
ReFramed.STAIRS_CUBE.getDefaultState().with(EDGE, edge.opposite()),
1
)
// allow replacing with stair
if (block != this
&& block != ReFramed.STAIR
&& block != ReFramed.SLAB
) return false;
return ReFramed.STAIR
.matchesShape(
context.getHitPos(),
context.getBlockPos(),
ReFramed.STAIRS_CUBE.getDefaultState().with(EDGE, edge.opposite())
);
)
&& !(
block_item.getBlock() == this
&& (
((ReFramedStepsSlabBlock) ReFramed.STEPS_SLAB)
.matchesShape(
context.getHitPos(),
context.getBlockPos(),
ReFramed.STEPS_SLAB.getDefaultState()
.with(FACING, edge.getFirstDirection())
.with(AXIS, edge.getSecondDirection().getAxis()),
edge.getSecondDirection().getDirection() == Direction.AxisDirection.POSITIVE ? 1 : 2
)
|| ((ReFramedStepsSlabBlock) ReFramed.STEPS_SLAB)
.matchesShape(
context.getHitPos(),
context.getBlockPos(),
ReFramed.STEPS_SLAB.getDefaultState()
.with(FACING, edge.getSecondDirection())
.with(AXIS, edge.getFirstDirection().getAxis()),
edge.getFirstDirection().getDirection() == Direction.AxisDirection.POSITIVE ? 1 : 2
)
)
)
)
);
}
@Nullable
@@ -81,7 +99,6 @@ public class ReFramedStepBlock extends WaterloggableReFramedBlock {
public BlockState getPlacementState(ItemPlacementContext ctx) {
BlockPos pos = ctx.getBlockPos();
BlockState current_state = ctx.getWorld().getBlockState(pos);
if (current_state.isOf(ReFramed.STAIR))
return ReFramed.STAIRS_CUBE.getDefaultState()
.with(EDGE, current_state.get(EDGE))
@@ -91,106 +108,40 @@ public class ReFramedStepBlock extends WaterloggableReFramedBlock {
if (current_state.isOf(this)) {
Vec3d hit = ctx.getHitPos();
Edge edge = current_state.get(EDGE);
// Steps Slab
if (matchesShape(hit, pos,
current_state.with(EDGE, edge.getOpposite(edge.getFirstDirection()))
)) return ReFramed.STEPS_SLAB.getDefaultState()
.with(FACING, edge.getFirstDirection())
.with(AXIS, edge.getSecondDirection().getAxis())
.with(WATERLOGGED, current_state.get(WATERLOGGED));
else if (matchesShape(hit, pos,
current_state.with(EDGE, edge.getOpposite(edge.getSecondDirection()))
)) return ReFramed.STEPS_SLAB.getDefaultState()
.with(FACING, edge.getSecondDirection())
.with(AXIS, edge.getFirstDirection().getAxis())
.with(WATERLOGGED, current_state.get(WATERLOGGED));
// Steps Cross
return ReFramed.STEPS_CROSS.getDefaultState()
.with(EDGE, edge)
.with(WATERLOGGED, current_state.get(WATERLOGGED));
}
if (current_state.isOf(ReFramed.SLAB)) {
Direction facing = current_state.get(FACING);
Edge edge;
// Slabs Stair
if (ctx.getSide() == facing || ctx.getSide() == facing.getOpposite())
edge = BlockHelper.getPlacementEdge(ctx);
else
edge = Edge.getByDirections(facing, ctx.getSide().getOpposite());
return ReFramed.SLABS_STAIR.getDefaultState()
.with(EDGE, edge)
.with(EDGE_FACE, edge.getDirectionIndex(facing));
}
if (current_state.isOf(ReFramed.HALF_STAIR)) {
Corner corner = current_state.get(CORNER);
int face_index = current_state.get(CORNER_FACE), feature_index;
Direction face = corner.getDirection(current_state.get(CORNER_FACE));
Direction side = ctx.getSide().getOpposite();
if (side.getAxis() == face.getAxis())
side = BlockHelper.getPlacementEdge(ctx).getOtherDirection(face == side ? face : face.getOpposite());
if (side.getAxis() != face.getAxis() && !corner.hasDirection(side))
side = corner.getOtherDirection(Edge.getByDirections(face, side.getOpposite()));
feature_index = corner.getDirectionIndex(side);
return ReFramed.HALF_STAIRS_STEP_STAIR.getDefaultState()
.with(CORNER, corner)
.with(CORNER_FACE, face_index)
.with(CORNER_FEATURE, feature_index > face_index ? feature_index - 1 : feature_index)
.with(WATERLOGGED, current_state.get(WATERLOGGED));
}
if (current_state.isOf(ReFramed.HALF_LAYER)) {
Edge edge = current_state.get(EDGE);
Direction face = edge.getDirection(current_state.get(EDGE_FACE));
edge = edge.getOpposite(face);
return ReFramed.STEPS_HALF_LAYER.getDefaultState()
.with(EDGE, edge)
.with(EDGE_FACE, edge.getDirectionIndex(edge.getOtherDirection(face)))
.with(LAYERS, current_state.get(LAYERS))
Direction dir = edge.getFirstDirection();
ReFramedStepsSlabBlock block = ((ReFramedStepsSlabBlock) ReFramed.STEPS_SLAB);
BlockState state = block.getDefaultState()
.with(FACING, dir)
.with(AXIS, edge.getOtherDirection(dir).getAxis())
.with(WATERLOGGED, current_state.get(WATERLOGGED));
if (!block.matchesShape(
hit, pos,
state,
edge.getOtherDirection(dir).getDirection() == Direction.AxisDirection.POSITIVE ? 1 : 2
)) {
dir = edge.getSecondDirection();
state = state
.with(FACING, dir)
.with(AXIS, edge.getOtherDirection(dir).getAxis());
}
return state;
}
return super.getPlacementState(ctx).with(EDGE, BlockHelper.getPlacementEdge(ctx));
}
@Override
@SuppressWarnings("deprecation")
public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
return getStepShape(state.get(EDGE));
}
@Override
@SuppressWarnings("deprecation")
public BlockState rotate(BlockState state, BlockRotation rotation) {
return state.with(EDGE, state.get(EDGE).rotate(rotation));
}
@Override
@SuppressWarnings("deprecation")
public BlockState mirror(BlockState state, BlockMirror mirror) {
return state.with(EDGE, state.get(EDGE).mirror(mirror));
}
public static VoxelShape getStepShape(Edge edge) {
return STEP_VOXELS[edge.getID()];
}
@Override
public Map<Integer, Integer> getThemeMap(BlockState state, BlockState new_state) {
if (new_state.isOf(ReFramed.STEPS_CROSS)
|| new_state.isOf(ReFramed.STEPS_HALF_LAYER)
) return Map.of(1, 1);
if (new_state.isOf(ReFramed.STAIRS_CUBE)
|| new_state.isOf(ReFramed.SLABS_STAIR)) return Map.of(1, 2);
if (new_state.isOf(ReFramed.STAIRS_CUBE)) return Map.of(1, 2);
if (new_state.isOf(ReFramed.STEPS_SLAB))
return Map.of(
1,

View File

@@ -1,86 +0,0 @@
package fr.adrien1106.reframed.block;
import fr.adrien1106.reframed.util.VoxelHelper;
import fr.adrien1106.reframed.util.blocks.BlockHelper;
import fr.adrien1106.reframed.util.blocks.Edge;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.ShapeContext;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.state.StateManager;
import net.minecraft.util.BlockMirror;
import net.minecraft.util.BlockRotation;
import net.minecraft.util.function.BooleanBiFunction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.util.shape.VoxelShapes;
import net.minecraft.world.BlockView;
import org.jetbrains.annotations.Nullable;
import static fr.adrien1106.reframed.block.ReFramedStepBlock.getStepShape;
import static fr.adrien1106.reframed.util.blocks.BlockProperties.EDGE;
public class ReFramedStepsCrossBlock extends WaterloggableReFramedDoubleBlock {
public static VoxelShape[] STEP_CROSS_VOXELS;
public ReFramedStepsCrossBlock(Settings settings) {
super(settings);
setDefaultState(getDefaultState().with(EDGE, Edge.NORTH_DOWN));
}
@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(builder.add(EDGE));
}
@Override
public @Nullable BlockState getPlacementState(ItemPlacementContext ctx) {
Edge edge = BlockHelper.getPlacementCorner(ctx).getEdge(ctx.getSide().getOpposite());
return super.getPlacementState(ctx).with(EDGE, edge);
}
@Override
@SuppressWarnings("deprecation")
public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
return STEP_CROSS_VOXELS[state.get(EDGE).ordinal()];
}
@Override
@SuppressWarnings("deprecation")
public BlockState rotate(BlockState state, BlockRotation rotation) {
return state.with(EDGE, state.get(EDGE).rotate(rotation));
}
@Override
@SuppressWarnings("deprecation")
public BlockState mirror(BlockState state, BlockMirror mirror) {
return state.with(EDGE, state.get(EDGE).mirror(mirror));
}
@Override
public VoxelShape getShape(BlockState state, int i) {
return getStepShape(i == 1 ? state.get(EDGE): state.get(EDGE).opposite());
}
static {
VoxelShape STEP_CROSS = VoxelShapes.combineAndSimplify(
getStepShape(Edge.NORTH_DOWN),
getStepShape(Edge.SOUTH_UP),
BooleanBiFunction.OR
);
STEP_CROSS_VOXELS = VoxelHelper.VoxelListBuilder.create(STEP_CROSS, 12)
.add(VoxelHelper::rotateX)
.add(VoxelHelper::rotateX)
.add(VoxelHelper::rotateX)
.add(0, VoxelHelper::rotateCY)
.add(VoxelHelper::rotateZ)
.add(VoxelHelper::rotateZ)
.add(VoxelHelper::rotateZ)
.add(0, VoxelHelper::rotateCZ)
.add(VoxelHelper::rotateY)
.add(VoxelHelper::rotateY)
.add(VoxelHelper::rotateY)
.build();
}
}

View File

@@ -1,62 +0,0 @@
package fr.adrien1106.reframed.block;
import fr.adrien1106.reframed.util.blocks.Edge;
import net.minecraft.block.BlockState;
import net.minecraft.block.ShapeContext;
import net.minecraft.util.function.BooleanBiFunction;
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 static fr.adrien1106.reframed.block.ReFramedHalfLayerBlock.getHalfLayerShape;
import static fr.adrien1106.reframed.block.ReFramedStepBlock.getStepShape;
import static fr.adrien1106.reframed.util.blocks.BlockProperties.EDGE;
import static fr.adrien1106.reframed.util.blocks.BlockProperties.EDGE_FACE;
import static net.minecraft.state.property.Properties.LAYERS;
public class ReFramedStepsHalfLayerBlock extends HalfLayerDoubleReFramedBlock {
private static final VoxelShape[] SLABS_HALF_LAYER_VOXELS = new VoxelShape[196];
public ReFramedStepsHalfLayerBlock(Settings settings) {
super(settings);
}
@Override
public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
return getStepsHalfLayerShape(state.get(EDGE), state.get(EDGE_FACE), state.get(LAYERS));
}
public static VoxelShape getStepsHalfLayerShape(Edge edge, int face, int layers) {
int i = edge.ordinal() * 16 + face * 8 + layers - 1;
VoxelShape shape = SLABS_HALF_LAYER_VOXELS[i];
if (shape == null) {
shape = VoxelShapes.combineAndSimplify(
getShape(edge, edge.getDirection(face), layers, 1),
getShape(edge, edge.getDirection(face), layers, 2),
BooleanBiFunction.OR
);
SLABS_HALF_LAYER_VOXELS[i] = shape;
}
return shape;
}
@Override
public VoxelShape getShape(BlockState state, int i) {
Edge edge = state.get(EDGE);
Direction face = edge.getDirection(state.get(EDGE_FACE));
return getShape(edge, face, state.get(LAYERS), i);
}
private static VoxelShape getShape(Edge edge, Direction face, int layers, int i) {
if (i == 2) {
face = edge.getOtherDirection(face);
edge = edge.getOpposite(face);
}
return i == 2
? getHalfLayerShape(edge, edge.getDirectionIndex(face), layers)
: getStepShape(edge);
}
}

View File

@@ -7,8 +7,6 @@ import net.minecraft.block.BlockState;
import net.minecraft.block.ShapeContext;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.state.StateManager;
import net.minecraft.util.BlockMirror;
import net.minecraft.util.BlockRotation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.Direction.Axis;
@@ -21,14 +19,26 @@ import static fr.adrien1106.reframed.block.ReFramedSlabBlock.getSlabShape;
import static fr.adrien1106.reframed.block.ReFramedStepBlock.getStepShape;
import static net.minecraft.state.property.Properties.AXIS;
import static net.minecraft.state.property.Properties.FACING;
import static net.minecraft.util.shape.VoxelShapes.empty;
public class ReFramedStepsSlabBlock extends WaterloggableReFramedDoubleBlock {
private record ModelCacheKey(Direction facing, Axis axis) {}
public ReFramedStepsSlabBlock(Settings settings) {
super(settings);
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
public int getModelStateCount() {
return 18;
}
@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(builder.add(FACING, AXIS));
@@ -43,28 +53,15 @@ public class ReFramedStepsSlabBlock extends WaterloggableReFramedDoubleBlock {
}
@Override
@SuppressWarnings("deprecation")
public VoxelShape getCullingShape(BlockState state, BlockView view, BlockPos pos) {
return isGhost(view, pos) ? empty() : getSlabShape(state.get(FACING));
}
@Override
public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
return getSlabShape(state.get(FACING));
}
@Override
@SuppressWarnings("deprecation")
public BlockState rotate(BlockState state, BlockRotation rotation) {
return state
.with(AXIS, rotation.rotate(Direction.get(Direction.AxisDirection.POSITIVE, state.get(AXIS))).getAxis())
.with(FACING, rotation.rotate(state.get(FACING)));
}
@Override
@SuppressWarnings("deprecation")
public BlockState mirror(BlockState state, BlockMirror mirror) {
if (state.get(FACING).getAxis() != Axis.Y)
return state.with(FACING, mirror.apply(state.get(FACING)));
return state;
}
@Override
public VoxelShape getShape(BlockState state, int i) {
Axis axis = state.get(AXIS);

View File

@@ -1,158 +0,0 @@
package fr.adrien1106.reframed.block;
import fr.adrien1106.reframed.util.VoxelHelper;
import net.minecraft.block.*;
import net.minecraft.block.enums.BlockHalf;
import net.minecraft.entity.ai.pathing.NavigationType;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.fluid.Fluids;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.item.ItemStack;
import net.minecraft.sound.SoundCategory;
import net.minecraft.state.StateManager;
import net.minecraft.util.ActionResult;
import net.minecraft.util.BlockMirror;
import net.minecraft.util.BlockRotation;
import net.minecraft.util.Hand;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.world.BlockView;
import net.minecraft.world.World;
import net.minecraft.world.event.GameEvent;
import net.minecraft.world.explosion.Explosion;
import org.jetbrains.annotations.Nullable;
import java.util.function.BiConsumer;
import static net.minecraft.state.property.Properties.*;
public class ReFramedTrapdoorBlock extends WaterloggableReFramedBlock {
public static final VoxelShape[] TRAPDOOR_VOXELS;
public ReFramedTrapdoorBlock(Settings settings) {
super(settings);
setDefaultState(getDefaultState()
.with(HORIZONTAL_FACING, Direction.NORTH)
.with(BLOCK_HALF, BlockHalf.BOTTOM)
.with(OPEN, false)
.with(POWERED, false)
);
}
@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(builder.add(HORIZONTAL_FACING, BLOCK_HALF, OPEN, POWERED));
}
@Override
@SuppressWarnings("deprecation")
public void neighborUpdate(BlockState state, World world, BlockPos pos, Block source, BlockPos sourcePos, boolean notify) {
if (world.isClient) return;
boolean powered = world.isReceivingRedstonePower(pos);
if (powered != state.get(POWERED)) {
if (state.get(OPEN) != powered) {
state = state.with(OPEN, powered);
playToggleSound(null, world, pos, powered);
}
world.setBlockState(pos, state.with(POWERED, powered), 2);
if (state.get(WATERLOGGED)) {
world.scheduleFluidTick(pos, Fluids.WATER, Fluids.WATER.getTickRate(world));
}
}
}
@Override
public @Nullable BlockState getPlacementState(ItemPlacementContext ctx) {
BlockState state = super.getPlacementState(ctx);
World world = ctx.getWorld();
BlockPos pos = ctx.getBlockPos();
Direction side = ctx.getSide();
if (side.getAxis().isVertical()) state = state
.with(HORIZONTAL_FACING, ctx.getHorizontalPlayerFacing().getOpposite())
.with(BLOCK_HALF, side == Direction.UP ? BlockHalf.BOTTOM : BlockHalf.TOP);
else state = state
.with(HORIZONTAL_FACING, side)
.with(BLOCK_HALF, ctx.getHitPos().getY() - pos.getY() > 0.5 ? BlockHalf.TOP : BlockHalf.BOTTOM);
if (world.isReceivingRedstonePower(pos)) state = state.with(OPEN, true).with(POWERED, true);
return state;
}
@Override
public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) {
ActionResult result = super.onUse(state, world, pos, player, hand, hit);
if (result.isAccepted()) return result;
flip(state, world, pos, player);
return ActionResult.success(world.isClient);
}
@Override
@SuppressWarnings("deprecation")
public boolean canPathfindThrough(BlockState state, BlockView world, BlockPos pos, NavigationType type) {
return switch (type) {
case LAND, AIR -> state.get(OPEN);
case WATER -> state.get(WATERLOGGED);
};
}
@Override
@SuppressWarnings("deprecation")
public void onExploded(BlockState state, World world, BlockPos pos, Explosion explosion, BiConsumer<ItemStack, BlockPos> stack_merger) {
if (explosion.getDestructionType() == Explosion.DestructionType.TRIGGER_BLOCK
&& !world.isClient()
&& !state.get(POWERED)
) flip(state, world, pos, null);
super.onExploded(state, world, pos, explosion, stack_merger);
}
private void flip(BlockState state, World world, BlockPos pos, @Nullable PlayerEntity player) {
state = state.cycle(OPEN);
world.setBlockState(pos, state, 2);
this.playToggleSound(player, world, pos, state.get(OPEN));
}
protected void playToggleSound(@Nullable PlayerEntity player, World world, BlockPos pos, boolean open) {
world.playSound(player, pos, open ? BlockSetType.OAK.trapdoorOpen() : BlockSetType.OAK.trapdoorClose(), SoundCategory.BLOCKS, 1.0F, world.getRandom().nextFloat() * 0.1F + 0.9F);
world.emitGameEvent(player, open ? GameEvent.BLOCK_OPEN : GameEvent.BLOCK_CLOSE, pos);
}
@Override
@SuppressWarnings("deprecation")
public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
int index;
if (!state.get(OPEN)) index = state.get(BLOCK_HALF) == BlockHalf.BOTTOM ? 0 : 1;
else index = state.get(HORIZONTAL_FACING).ordinal();
return TRAPDOOR_VOXELS[index];
}
@Override
@SuppressWarnings("deprecation")
public BlockState rotate(BlockState state, BlockRotation rotation) {
return state.with(HORIZONTAL_FACING, rotation.rotate(state.get(HORIZONTAL_FACING)));
}
@Override
@SuppressWarnings("deprecation")
public BlockState mirror(BlockState state, BlockMirror mirror) {
return state.with(HORIZONTAL_FACING, mirror.apply(state.get(HORIZONTAL_FACING)));
}
static {
VoxelShape SHAPE = createCuboidShape(0, 0, 0, 16, 3, 16);
TRAPDOOR_VOXELS = VoxelHelper.VoxelListBuilder.create(SHAPE, 6)
.add(VoxelHelper::mirrorY)
.add(VoxelHelper::rotateX)
.add(VoxelHelper::mirrorZ)
.add(VoxelHelper::rotateY)
.add(VoxelHelper::mirrorX)
.build();
}
}

View File

@@ -7,8 +7,6 @@ import net.minecraft.item.ItemPlacementContext;
import net.minecraft.registry.tag.BlockTags;
import net.minecraft.state.StateManager;
import net.minecraft.state.property.Property;
import net.minecraft.util.BlockMirror;
import net.minecraft.util.BlockRotation;
import net.minecraft.util.function.BooleanBiFunction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
@@ -17,20 +15,19 @@ import net.minecraft.util.shape.VoxelShapes;
import net.minecraft.world.BlockView;
import net.minecraft.world.World;
import net.minecraft.world.WorldAccess;
import net.minecraft.world.WorldView;
import org.jetbrains.annotations.Nullable;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static net.minecraft.state.property.Properties.*;
public class ReFramedWallBlock extends WaterloggableReFramedBlock {
public class ReframedWallBlock extends WaterloggableReFramedBlock {
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);
setDefaultState(getDefaultState()
.with(UP, true)
@@ -41,6 +38,22 @@ 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
public int getModelStateCount() {
return 162;
}
@Override
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));
@@ -53,13 +66,31 @@ public class ReFramedWallBlock extends WaterloggableReFramedBlock {
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);
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()
.collect(Collectors.toMap(d -> d, d -> {
if (d == dir) return other_state;
return world.getBlockState(pos.offset(d));
}));
new_state = getWallState(new_state, top_state, neighbors, top_shape, fs, world, pos);
boolean side_full = other_state.isSideSolidFullSquare(world, moved, dir.getOpposite());
if (shouldConnectTo(other_state, side_full, dir.getOpposite())) {
new_state = new_state.with(
getWallShape(dir),
fs || 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));
}
@@ -68,19 +99,33 @@ public class ReFramedWallBlock extends WaterloggableReFramedBlock {
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))));
state = getWallState(state, top_state, neighbors, top_shape, fs, world, pos);
for (Direction dir : Direction.Type.HORIZONTAL) {
BlockPos offset = pos.offset(dir);
BlockState neighbor = world.getBlockState(offset);
boolean side_full = neighbor.isSideSolidFullSquare(world, offset, dir.getOpposite());
if (shouldConnectTo(neighbor, side_full, dir.getOpposite())) {
state = state.with(
getWallShape(dir),
fs || shouldUseTall(WALL_VOXELS[dir.ordinal() + 3], top_shape)
? WallShape.TALL
: WallShape.LOW
);
}
}
return state.with(UP, shouldHavePost(state, top_state, top_shape));
}
@Override
@SuppressWarnings("deprecation")
public void onStateReplaced(BlockState state, World world, BlockPos pos, BlockState new_state, boolean moved) {
super.onStateReplaced(state, world, pos, new_state, moved);
if(!state.isOf(new_state.getBlock())) world.removeBlockEntity(pos);
}
@Override
public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
VoxelShape shape = state.get(UP) ? WALL_VOXELS[0]: VoxelShapes.empty();
for (Direction dir : Direction.Type.HORIZONTAL) {
@@ -93,7 +138,6 @@ public class ReFramedWallBlock extends WaterloggableReFramedBlock {
@Override
public VoxelShape getCollisionShape(BlockState state, BlockView view, BlockPos pos, ShapeContext ctx) {
if (isGhost(view, pos)) return VoxelShapes.empty();
VoxelShape shape = state.get(UP) ? WALL_VOXELS[9]: VoxelShapes.empty();
for (Direction dir : Direction.Type.HORIZONTAL) {
if (state.get(getWallShape(dir)) != WallShape.NONE)
@@ -102,45 +146,9 @@ public class ReFramedWallBlock extends WaterloggableReFramedBlock {
return shape;
}
@Override
@SuppressWarnings("deprecation")
public BlockState rotate(BlockState state, BlockRotation rotation) {
return Direction.Type.HORIZONTAL.stream().reduce(state, (s, dir) ->
s.with(getWallShape(rotation.rotate(dir)), state.get(getWallShape(dir)))
, (prev, next) -> next);
}
@Override
@SuppressWarnings("deprecation")
public BlockState mirror(BlockState state, BlockMirror mirror) {
return Direction.Type.HORIZONTAL.stream().reduce(state, (s, dir) ->
s.with(getWallShape(mirror.apply(dir)), state.get(getWallShape(dir)))
, (prev, next) -> next);
}
public static BlockState getWallState(BlockState state, BlockState top_state, Map<Direction, BlockState> neighbors, VoxelShape top_shape, boolean fs, WorldView world, BlockPos pos) {
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) {
private static boolean shouldHavePost(BlockState state, BlockState top_state, VoxelShape top_shape) {
// 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
.anyMatch(dir -> state.get(getWallShape(dir)) != state.get(getWallShape(dir.getOpposite())))
@@ -150,22 +158,23 @@ public class ReFramedWallBlock extends WaterloggableReFramedBlock {
if (Direction.Type.HORIZONTAL.stream().allMatch(dir -> state.get(getWallShape(dir)) == WallShape.NONE))
return true;
// Matching sides
// tall Matching sides
if (Stream.of(Direction.SOUTH, Direction.EAST)
.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 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();
boolean bl = block instanceof FenceGateBlock && FenceGateBlock.canWallConnect(state, side);
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(
self_shape,
other_shape,
@@ -173,7 +182,7 @@ public class ReFramedWallBlock extends WaterloggableReFramedBlock {
);
}
public static Property<WallShape> getWallShape(Direction dir) {
private static Property<WallShape> getWallShape(Direction dir) {
return switch (dir) {
case EAST -> EAST_WALL_SHAPE;
case NORTH -> NORTH_WALL_SHAPE;

View File

@@ -23,13 +23,7 @@ public class WaterloggableReFramedBlock extends ReFramedBlock implements Waterlo
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(builder.add(Properties.WATERLOGGED));
}
@Override
@SuppressWarnings("deprecation")
public boolean hasSidedTransparency(BlockState state) {
return true;
}
@Nullable
@Override
public BlockState getPlacementState(ItemPlacementContext ctx) {
@@ -39,13 +33,10 @@ public class WaterloggableReFramedBlock extends ReFramedBlock implements Waterlo
}
@Override
@SuppressWarnings("deprecation")
public FluidState getFluidState(BlockState state) {
return state.get(Properties.WATERLOGGED) ? Fluids.WATER.getStill(false) : super.getFluidState(state);
}
@Override
@SuppressWarnings("deprecation")
public BlockState getStateForNeighborUpdate(BlockState state, Direction direction, BlockState otherState, WorldAccess world, BlockPos pos, BlockPos moved) {
if(state.get(Properties.WATERLOGGED)) world.scheduleFluidTick(pos, Fluids.WATER, Fluids.WATER.getTickRate(world));
return super.getStateForNeighborUpdate(state, direction, otherState, world, pos, moved);

View File

@@ -33,13 +33,10 @@ public class WaterloggableReFramedDoubleBlock extends ReFramedDoubleBlock implem
}
@Override
@SuppressWarnings("deprecation")
public FluidState getFluidState(BlockState state) {
return state.get(Properties.WATERLOGGED) ? Fluids.WATER.getStill(false) : super.getFluidState(state);
}
@Override
@SuppressWarnings("deprecation")
public BlockState getStateForNeighborUpdate(BlockState state, Direction direction, BlockState otherState, WorldAccess world, BlockPos pos, BlockPos moved) {
if(state.get(Properties.WATERLOGGED)) world.scheduleFluidTick(pos, Fluids.WATER, Fluids.WATER.getTickRate(world));
return super.getStateForNeighborUpdate(state, direction, otherState, world, pos, moved);

View File

@@ -27,235 +27,114 @@ public class ReFramedClient implements ClientModInitializer {
BlockRenderLayerMap.INSTANCE.putBlocks(RenderLayer.getCutout(), ReFramed.BLOCKS.toArray(new Block[0]));
// CUBE
HELPER.addReFramedModel("cube" , HELPER.auto(new Identifier("block/cube")));
HELPER.addReFramedModel("cube" , HELPER.auto(new Identifier("block/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")));
// 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_reverse" , HELPER.autoDouble(ReFramed.id("block/small_cube/step/base"), ReFramed.id("block/small_cube/base")));
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_reverse" , HELPER.autoDouble(ReFramed.id("block/small_cube/step/base"), ReFramed.id("block/small_cube/base")));
// SLAB
HELPER.addReFramedModel("slab" , HELPER.auto(new Identifier("block/slab")));
HELPER.addReFramedModel("slab" , HELPER.auto(new Identifier("block/slab")));
// 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")));
// STAIR
HELPER.addReFramedModel("stair" , HELPER.auto(ReFramed.id("block/stair/straight")));
HELPER.addReFramedModel("outers_stair" , HELPER.auto(ReFramed.id("block/stair/double_outer")));
HELPER.addReFramedModel("inner_stair" , HELPER.auto(ReFramed.id("block/stair/inner")));
HELPER.addReFramedModel("outer_stair" , HELPER.auto(ReFramed.id("block/stair/outer")));
HELPER.addReFramedModel("outer_side_stair" , HELPER.auto(ReFramed.id("block/stair/outer_side")));
HELPER.addReFramedModel("stair" , HELPER.auto(ReFramed.id("block/stair/straight")));
HELPER.addReFramedModel("outers_stair" , HELPER.auto(ReFramed.id("block/stair/double_outer")));
HELPER.addReFramedModel("inner_stair" , HELPER.auto(ReFramed.id("block/stair/inner")));
HELPER.addReFramedModel("outer_stair" , HELPER.auto(ReFramed.id("block/stair/outer")));
HELPER.addReFramedModel("outer_side_stair" , HELPER.auto(ReFramed.id("block/stair/outer_side")));
// STAIRS_CUBE
HELPER.addReFramedModel("stairs_cube" , HELPER.autoDouble(ReFramed.id("block/stair/straight"), ReFramed.id("block/stair/cube/straight")));
HELPER.addReFramedModel("outers_stairs_cube" , HELPER.autoDouble(ReFramed.id("block/stair/double_outer"), ReFramed.id("block/stair/cube/double_outer")));
HELPER.addReFramedModel("inner_stairs_cube" , HELPER.autoDouble(ReFramed.id("block/stair/inner"), ReFramed.id("block/stair/cube/inner")));
HELPER.addReFramedModel("outer_stairs_cube" , HELPER.autoDouble(ReFramed.id("block/stair/outer"), ReFramed.id("block/stair/cube/outer")));
HELPER.addReFramedModel("outer_side_stairs_cube" , HELPER.autoDouble(ReFramed.id("block/stair/outer_side"), ReFramed.id("block/stair/cube/outer_side")));
HELPER.addReFramedModel("stairs_cube" , HELPER.autoDouble(ReFramed.id("block/stair/straight"), ReFramed.id("block/stair/cube/straight")));
HELPER.addReFramedModel("outers_stairs_cube" , HELPER.autoDouble(ReFramed.id("block/stair/double_outer"), ReFramed.id("block/stair/cube/double_outer")));
HELPER.addReFramedModel("inner_stairs_cube" , HELPER.autoDouble(ReFramed.id("block/stair/inner"), ReFramed.id("block/stair/cube/inner")));
HELPER.addReFramedModel("outer_stairs_cube" , HELPER.autoDouble(ReFramed.id("block/stair/outer"), ReFramed.id("block/stair/cube/outer")));
HELPER.addReFramedModel("outer_side_stairs_cube" , HELPER.autoDouble(ReFramed.id("block/stair/outer_side"), ReFramed.id("block/stair/cube/outer_side")));
// HALF_STAIR
HELPER.addReFramedModel("half_stair_down" , HELPER.auto(ReFramed.id("block/half_stair/down")));
HELPER.addReFramedModel("half_stair_side" , HELPER.auto(ReFramed.id("block/half_stair/side")));
HELPER.addReFramedModel("half_stair_down" , HELPER.auto(ReFramed.id("block/half_stair/down")));
HELPER.addReFramedModel("half_stair_side" , HELPER.auto(ReFramed.id("block/half_stair/side")));
// 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_side" , HELPER.autoDouble(ReFramed.id("block/half_stair/side"), ReFramed.id("block/half_stair/slab/side")));
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_side" , HELPER.autoDouble(ReFramed.id("block/half_stair/side"), ReFramed.id("block/half_stair/slab/side")));
// 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_side" , HELPER.autoDouble(ReFramed.id("block/half_stair/side"), ReFramed.id("block/half_stair/stair/side")));
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_down" , HELPER.autoDouble(ReFramed.id("block/half_stair/down"), ReFramed.id("block/half_stair/stair/down")));
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_reverse" , HELPER.autoDouble(ReFramed.id("block/half_stair/stair/side"), ReFramed.id("block/half_stair/side")));
// STEP
HELPER.addReFramedModel("step" , HELPER.auto(ReFramed.id("block/step/down")));
HELPER.addReFramedModel("step" , HELPER.auto(ReFramed.id("block/step/down")));
// STEPS_SLAB
HELPER.addReFramedModel("steps_slab" , HELPER.autoDouble(ReFramed.id("block/step/down"), ReFramed.id("block/step/slab/down")));
HELPER.addReFramedModel("steps_slab_side" , HELPER.autoDouble(ReFramed.id("block/step/side"), ReFramed.id("block/step/slab/side")));
HELPER.addReFramedModel("steps_slab" , HELPER.autoDouble(ReFramed.id("block/step/down"), ReFramed.id("block/step/slab/down")));
HELPER.addReFramedModel("steps_slab_side" , HELPER.autoDouble(ReFramed.id("block/step/side"), ReFramed.id("block/step/slab/side")));
// LAYER
HELPER.addReFramedModel("layer_1" , HELPER.auto(new Identifier("block/snow_height2")));
HELPER.addReFramedModel("layer_2" , HELPER.auto(new Identifier("block/snow_height4")));
HELPER.addReFramedModel("layer_3" , HELPER.auto(new Identifier("block/snow_height6")));
HELPER.addReFramedModel("layer_4" , HELPER.auto(new Identifier("block/snow_height8")));
HELPER.addReFramedModel("layer_5" , HELPER.auto(new Identifier("block/snow_height10")));
HELPER.addReFramedModel("layer_6" , HELPER.auto(new Identifier("block/snow_height12")));
HELPER.addReFramedModel("layer_7" , HELPER.auto(new Identifier("block/snow_height14")));
HELPER.addReFramedModel("layer_8" , HELPER.auto(new Identifier("block/cube")));
HELPER.addReFramedModel("layer_1" , HELPER.auto(new Identifier("block/snow_height2")));
HELPER.addReFramedModel("layer_2" , HELPER.auto(new Identifier("block/snow_height4")));
HELPER.addReFramedModel("layer_3" , HELPER.auto(new Identifier("block/snow_height6")));
HELPER.addReFramedModel("layer_4" , HELPER.auto(new Identifier("block/snow_height8")));
HELPER.addReFramedModel("layer_5" , HELPER.auto(new Identifier("block/snow_height10")));
HELPER.addReFramedModel("layer_6" , HELPER.auto(new Identifier("block/snow_height12")));
HELPER.addReFramedModel("layer_7" , HELPER.auto(new Identifier("block/snow_height14")));
HELPER.addReFramedModel("layer_8" , HELPER.auto(new Identifier("block/cube")));
// PILLAR
HELPER.addReFramedModel("pillar" , HELPER.auto(ReFramed.id("block/pillar")));
HELPER.addReFramedModel("pillar" , HELPER.auto(ReFramed.id("block/pillar")));
// 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")));
// --------------------- pillar
HELPER.addReFramedModel("wall_core" , HELPER.auto(ReFramed.id("block/wall/pillar/core")));
HELPER.addReFramedModel("wall_pillar_low" , HELPER.auto(ReFramed.id("block/wall/pillar/low")));
HELPER.addReFramedModel("wall_pillar_tall" , HELPER.auto(ReFramed.id("block/wall/pillar/tall")));
HELPER.addReFramedModel("wall_pillar_none" , HELPER.auto(ReFramed.id("block/wall/pillar/none")));
HELPER.addReFramedModel("wall_core" , HELPER.auto(ReFramed.id("block/wall/pillar/core")));
HELPER.addReFramedModel("wall_pillar_low" , HELPER.auto(ReFramed.id("block/wall/pillar/low")));
HELPER.addReFramedModel("wall_pillar_tall" , HELPER.auto(ReFramed.id("block/wall/pillar/tall")));
HELPER.addReFramedModel("wall_pillar_none" , HELPER.auto(ReFramed.id("block/wall/pillar/none")));
// --------------------- side
HELPER.addReFramedModel("wall_side_low" , HELPER.auto(ReFramed.id("block/wall/side/low")));
HELPER.addReFramedModel("wall_side_tall" , HELPER.auto(ReFramed.id("block/wall/side/tall")));
HELPER.addReFramedModel("wall_side_low" , HELPER.auto(ReFramed.id("block/wall/side/low")));
HELPER.addReFramedModel("wall_side_tall" , HELPER.auto(ReFramed.id("block/wall/side/tall")));
// --------------------- junction
HELPER.addReFramedModel("wall_low_e" , HELPER.auto(ReFramed.id("block/wall/junction/low")));
HELPER.addReFramedModel("wall_tall_e" , HELPER.auto(ReFramed.id("block/wall/junction/tall")));
HELPER.addReFramedModel("wall_low_e" , HELPER.auto(ReFramed.id("block/wall/junction/low")));
HELPER.addReFramedModel("wall_tall_e" , HELPER.auto(ReFramed.id("block/wall/junction/tall")));
// --------------------- junction_i
HELPER.addReFramedModel("wall_low_i" , HELPER.auto(ReFramed.id("block/wall/junction/low_i")));
HELPER.addReFramedModel("wall_tall_i" , HELPER.auto(ReFramed.id("block/wall/junction/tall_i")));
HELPER.addReFramedModel("wall_low_tall_i" , HELPER.auto(ReFramed.id("block/wall/junction/low_tall_i")));
HELPER.addReFramedModel("wall_low_i" , HELPER.auto(ReFramed.id("block/wall/junction/low_i")));
HELPER.addReFramedModel("wall_tall_i" , HELPER.auto(ReFramed.id("block/wall/junction/tall_i")));
HELPER.addReFramedModel("wall_low_tall_i" , HELPER.auto(ReFramed.id("block/wall/junction/low_tall_i")));
// --------------------- junction_c
HELPER.addReFramedModel("wall_low_c" , HELPER.auto(ReFramed.id("block/wall/junction/low_c")));
HELPER.addReFramedModel("wall_tall_c" , HELPER.auto(ReFramed.id("block/wall/junction/tall_c")));
HELPER.addReFramedModel("wall_low_tall_c" , HELPER.auto(ReFramed.id("block/wall/junction/low_tall_c")));
HELPER.addReFramedModel("wall_tall_low_c" , HELPER.auto(ReFramed.id("block/wall/junction/tall_low_c")));
HELPER.addReFramedModel("wall_low_c" , HELPER.auto(ReFramed.id("block/wall/junction/low_c")));
HELPER.addReFramedModel("wall_tall_c" , HELPER.auto(ReFramed.id("block/wall/junction/tall_c")));
HELPER.addReFramedModel("wall_low_tall_c" , HELPER.auto(ReFramed.id("block/wall/junction/low_tall_c")));
HELPER.addReFramedModel("wall_tall_low_c" , HELPER.auto(ReFramed.id("block/wall/junction/tall_low_c")));
// --------------------- junction_t
HELPER.addReFramedModel("wall_low_t" , HELPER.auto(ReFramed.id("block/wall/junction/low_t")));
HELPER.addReFramedModel("wall_tall_t" , HELPER.auto(ReFramed.id("block/wall/junction/tall_t")));
HELPER.addReFramedModel("wall_tall_low_c_t" , HELPER.auto(ReFramed.id("block/wall/junction/tall_low_c_t")));
HELPER.addReFramedModel("wall_tall_i_low_t" , HELPER.auto(ReFramed.id("block/wall/junction/tall_i_low_t")));
HELPER.addReFramedModel("wall_low_i_tall_t" , HELPER.auto(ReFramed.id("block/wall/junction/low_i_tall_t")));
HELPER.addReFramedModel("wall_low_tall_c_t" , HELPER.auto(ReFramed.id("block/wall/junction/low_tall_c_t")));
HELPER.addReFramedModel("wall_low_c_tall_t" , HELPER.auto(ReFramed.id("block/wall/junction/low_c_tall_t")));
HELPER.addReFramedModel("wall_tall_c_low_t" , HELPER.auto(ReFramed.id("block/wall/junction/tall_c_low_t")));
HELPER.addReFramedModel("wall_low_t" , HELPER.auto(ReFramed.id("block/wall/junction/low_t")));
HELPER.addReFramedModel("wall_tall_t" , HELPER.auto(ReFramed.id("block/wall/junction/tall_t")));
HELPER.addReFramedModel("wall_tall_low_c_t" , HELPER.auto(ReFramed.id("block/wall/junction/tall_low_c_t")));
HELPER.addReFramedModel("wall_tall_i_low_t" , HELPER.auto(ReFramed.id("block/wall/junction/tall_i_low_t")));
HELPER.addReFramedModel("wall_low_i_tall_t" , HELPER.auto(ReFramed.id("block/wall/junction/low_i_tall_t")));
HELPER.addReFramedModel("wall_low_tall_c_t" , HELPER.auto(ReFramed.id("block/wall/junction/low_tall_c_t")));
HELPER.addReFramedModel("wall_low_c_tall_t" , HELPER.auto(ReFramed.id("block/wall/junction/low_c_tall_t")));
HELPER.addReFramedModel("wall_tall_c_low_t" , HELPER.auto(ReFramed.id("block/wall/junction/tall_c_low_t")));
// --------------------- junction_x
HELPER.addReFramedModel("wall_low_x" , HELPER.auto(ReFramed.id("block/wall/junction/low_x")));
HELPER.addReFramedModel("wall_tall_x" , HELPER.auto(ReFramed.id("block/wall/junction/tall_x")));
HELPER.addReFramedModel("wall_tall_i_low_i_x" , HELPER.auto(ReFramed.id("block/wall/junction/tall_i_low_i_x")));
HELPER.addReFramedModel("wall_tall_low_t_x" , HELPER.auto(ReFramed.id("block/wall/junction/tall_low_t_x")));
HELPER.addReFramedModel("wall_tall_c_low_c_x" , HELPER.auto(ReFramed.id("block/wall/junction/tall_c_low_c_x")));
HELPER.addReFramedModel("wall_tall_t_low_x" , HELPER.auto(ReFramed.id("block/wall/junction/tall_t_low_x")));
// 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")));
// PANE
HELPER.addReFramedModel("pane_inventory" , HELPER.auto(ReFramed.id("block/pane")));
HELPER.addReFramedModel("pane_post" , HELPER.auto(new Identifier("block/glass_pane_post")));
HELPER.addReFramedModel("pane_side" , HELPER.auto(new Identifier("block/glass_pane_side")));
HELPER.addReFramedModel("pane_side_alt" , HELPER.auto(new Identifier("block/glass_pane_side_alt")));
HELPER.addReFramedModel("pane_noside" , HELPER.auto(new Identifier("block/glass_pane_noside")));
HELPER.addReFramedModel("pane_noside_alt" , HELPER.auto(new Identifier("block/glass_pane_noside_alt")));
// TRAPDOOR
HELPER.addReFramedModel("trapdoor_open" , HELPER.auto(new Identifier("block/oak_trapdoor_open")));
HELPER.addReFramedModel("trapdoor_bottom" , HELPER.auto(new Identifier("block/oak_trapdoor_bottom")));
HELPER.addReFramedModel("trapdoor_top" , HELPER.auto(new Identifier("block/oak_trapdoor_top")));
// DOOR
HELPER.addReFramedModel("door_inventory" , HELPER.auto(ReFramed.id("block/door")));
// BUTTON
HELPER.addReFramedModel("button_inventory" , HELPER.auto(new Identifier("block/button_inventory")));
HELPER.addReFramedModel("button" , HELPER.auto(new Identifier("block/button")));
HELPER.addReFramedModel("button_pressed" , HELPER.auto(new Identifier("block/button_pressed")));
// POST
HELPER.addReFramedModel("post" , HELPER.auto(ReFramed.id("block/post")));
// FENCE
HELPER.addReFramedModel("fence_inventory" , HELPER.auto(ReFramed.id("block/fence/inventory")));
HELPER.addReFramedModel("fence_core" , HELPER.auto(ReFramed.id("block/fence/core")));
HELPER.addReFramedModel("fence_side_off" , HELPER.auto(ReFramed.id("block/fence/side_off")));
HELPER.addReFramedModel("fence_side_on" , HELPER.auto(ReFramed.id("block/fence/side_on")));
// POST FENCE
HELPER.addReFramedModel("post_fence_inventory" , HELPER.autoDouble(ReFramed.id("block/post"), ReFramed.id("block/fence/full/inventory")));
HELPER.addReFramedModel("post_fence_side" , HELPER.autoDouble(ReFramed.id("block/fence/full/side_core"), ReFramed.id("block/fence/full/side_bars")));
// SLABS STAIR
HELPER.addReFramedModel("slabs_stair" , HELPER.autoDouble(ReFramed.id("block/slabs_stair/slab"), ReFramed.id("block/slabs_stair/step")));
HELPER.addReFramedModel("slabs_stair_side" , HELPER.autoDouble(ReFramed.id("block/slabs_stair/side/slab"), ReFramed.id("block/slabs_stair/side/step")));
// SLABS OUTER STAIR
HELPER.addReFramedModel("slabs_outer_stair" , HELPER.autoDouble(ReFramed.id("block/slabs_stair/outer/slab"), ReFramed.id("block/slabs_stair/outer/cube")));
HELPER.addReFramedModel("slabs_outer_stair_side" , HELPER.autoDouble(ReFramed.id("block/slabs_stair/outer/side/slab"), ReFramed.id("block/slabs_stair/outer/side/cube")));
// SLABS OUTER STAIR
HELPER.addReFramedModel("slabs_inner_stair" , HELPER.autoDouble(ReFramed.id("block/slabs_stair/inner/slab"), ReFramed.id("block/slabs_stair/inner/half_stair")));
HELPER.addReFramedModel("slabs_inner_stair_side" , HELPER.autoDouble(ReFramed.id("block/slabs_stair/inner/side/slab"), ReFramed.id("block/slabs_stair/inner/side/half_stair")));
// SLABS OUTER STAIR
HELPER.addReFramedModel("steps_cross" , HELPER.autoDouble(ReFramed.id("block/step/down"), ReFramed.id("block/step/cross")));
// HALF STAIRS CUBE STAIR
HELPER.addReFramedModel("half_stairs_cube_stair" , HELPER.autoDouble(ReFramed.id("block/half_stair/base"), ReFramed.id("block/half_stair/stair/cube")));
HELPER.addReFramedModel("half_stairs_cube_stair_side" , HELPER.autoDouble(ReFramed.id("block/half_stair/base_side"), ReFramed.id("block/half_stair/stair/cube_side")));
// HALF STAIRS STEP STAIR
HELPER.addReFramedModel("half_stairs_step_stair_1" , HELPER.autoDouble(ReFramed.id("block/half_stair/base"), ReFramed.id("block/half_stair/stair/step_1")));
HELPER.addReFramedModel("half_stairs_step_stair_side_1", HELPER.autoDouble(ReFramed.id("block/half_stair/base_side"), ReFramed.id("block/half_stair/stair/step_side_1")));
HELPER.addReFramedModel("half_stairs_step_stair_2" , HELPER.autoDouble(ReFramed.id("block/half_stair/base"), ReFramed.id("block/half_stair/stair/step_2")));
HELPER.addReFramedModel("half_stairs_step_stair_side_2", HELPER.autoDouble(ReFramed.id("block/half_stair/base_side"), ReFramed.id("block/half_stair/stair/step_side_2")));
// HALF LAYER
// --------------------- east
HELPER.addReFramedModel("half_layer_2" , HELPER.auto(ReFramed.id("block/half_layer/east/layer_2")));
HELPER.addReFramedModel("half_layer_4" , HELPER.auto(ReFramed.id("block/half_layer/east/layer_4")));
HELPER.addReFramedModel("half_layer_6" , HELPER.auto(ReFramed.id("block/half_layer/east/layer_6")));
HELPER.addReFramedModel("half_layer_8" , HELPER.auto(ReFramed.id("block/half_layer/east/layer_8")));
HELPER.addReFramedModel("half_layer_10" , HELPER.auto(ReFramed.id("block/half_layer/east/layer_10")));
HELPER.addReFramedModel("half_layer_12" , HELPER.auto(ReFramed.id("block/half_layer/east/layer_12")));
HELPER.addReFramedModel("half_layer_14" , HELPER.auto(ReFramed.id("block/half_layer/east/layer_14")));
HELPER.addReFramedModel("half_layer_16" , HELPER.auto(ReFramed.id("block/half_layer/east/layer_16")));
// --------------------- side
HELPER.addReFramedModel("half_layer_side_2" , HELPER.auto(ReFramed.id("block/half_layer/side/layer_2")));
HELPER.addReFramedModel("half_layer_side_4" , HELPER.auto(ReFramed.id("block/half_layer/side/layer_4")));
HELPER.addReFramedModel("half_layer_side_6" , HELPER.auto(ReFramed.id("block/half_layer/side/layer_6")));
HELPER.addReFramedModel("half_layer_side_8" , HELPER.auto(ReFramed.id("block/half_layer/side/layer_8")));
HELPER.addReFramedModel("half_layer_side_10" , HELPER.auto(ReFramed.id("block/half_layer/side/layer_10")));
HELPER.addReFramedModel("half_layer_side_12" , HELPER.auto(ReFramed.id("block/half_layer/side/layer_12")));
HELPER.addReFramedModel("half_layer_side_14" , HELPER.auto(ReFramed.id("block/half_layer/side/layer_14")));
HELPER.addReFramedModel("half_layer_side_16" , HELPER.auto(ReFramed.id("block/half_layer/side/layer_16")));
// SLAB HALF LAYER
HELPER.addReFramedModel("slabs_half_inventory" , HELPER.autoDouble(new Identifier("block/slab"), ReFramed.id("block/half_layer/slab/east/layer_4")));
// STEP HALF LAYER
HELPER.addReFramedModel("steps_half_inventory" , HELPER.autoDouble(ReFramed.id("block/step/down"), ReFramed.id("block/half_layer/slab/east/layer_4")));
// --------------------- east
HELPER.addReFramedModel("second_half_layer_2" , HELPER.auto(ReFramed.id("block/half_layer/slab/east/layer_2")).setThemeIndex(2));
HELPER.addReFramedModel("second_half_layer_4" , HELPER.auto(ReFramed.id("block/half_layer/slab/east/layer_4")).setThemeIndex(2));
HELPER.addReFramedModel("second_half_layer_6" , HELPER.auto(ReFramed.id("block/half_layer/slab/east/layer_6")).setThemeIndex(2));
HELPER.addReFramedModel("second_half_layer_8" , HELPER.auto(ReFramed.id("block/half_layer/slab/east/layer_8")).setThemeIndex(2));
HELPER.addReFramedModel("second_half_layer_10" , HELPER.auto(ReFramed.id("block/half_layer/slab/east/layer_10")).setThemeIndex(2));
HELPER.addReFramedModel("second_half_layer_12" , HELPER.auto(ReFramed.id("block/half_layer/slab/east/layer_12")).setThemeIndex(2));
HELPER.addReFramedModel("second_half_layer_14" , HELPER.auto(ReFramed.id("block/half_layer/slab/east/layer_14")).setThemeIndex(2));
HELPER.addReFramedModel("second_half_layer_16" , HELPER.auto(ReFramed.id("block/half_layer/slab/east/layer_16")).setThemeIndex(2));
// --------------------- side
HELPER.addReFramedModel("second_half_layer_side_2" , HELPER.auto(ReFramed.id("block/half_layer/slab/side/layer_2")).setThemeIndex(2));
HELPER.addReFramedModel("second_half_layer_side_4" , HELPER.auto(ReFramed.id("block/half_layer/slab/side/layer_4")).setThemeIndex(2));
HELPER.addReFramedModel("second_half_layer_side_6" , HELPER.auto(ReFramed.id("block/half_layer/slab/side/layer_6")).setThemeIndex(2));
HELPER.addReFramedModel("second_half_layer_side_8" , HELPER.auto(ReFramed.id("block/half_layer/slab/side/layer_8")).setThemeIndex(2));
HELPER.addReFramedModel("second_half_layer_side_10" , HELPER.auto(ReFramed.id("block/half_layer/slab/side/layer_10")).setThemeIndex(2));
HELPER.addReFramedModel("second_half_layer_side_12" , HELPER.auto(ReFramed.id("block/half_layer/slab/side/layer_12")).setThemeIndex(2));
HELPER.addReFramedModel("second_half_layer_side_14" , HELPER.auto(ReFramed.id("block/half_layer/slab/side/layer_14")).setThemeIndex(2));
HELPER.addReFramedModel("second_half_layer_side_16" , HELPER.auto(ReFramed.id("block/half_layer/slab/side/layer_16")).setThemeIndex(2));
// HALF SLAB
HELPER.addReFramedModel("half_slab" , HELPER.auto(ReFramed.id("block/half_slab/default")));
// HALF SLABS SLAB
HELPER.addReFramedModel("half_slabs_slab" , HELPER.autoDouble(ReFramed.id("block/half_slab/default"), ReFramed.id("block/half_slab/complement")));
// SLABS LAYER
HELPER.addReFramedModel("slabs_layer_2" , HELPER.autoDouble(new Identifier("block/slab"), ReFramed.id("block/layer_top/layer_2")));
HELPER.addReFramedModel("slabs_layer_4" , HELPER.autoDouble(new Identifier("block/slab"), ReFramed.id("block/layer_top/layer_4")));
HELPER.addReFramedModel("slabs_layer_6" , HELPER.autoDouble(new Identifier("block/slab"), ReFramed.id("block/layer_top/layer_6")));
HELPER.addReFramedModel("slabs_layer_8" , HELPER.autoDouble(new Identifier("block/slab"), ReFramed.id("block/layer_top/layer_8")));
HELPER.addReFramedModel("wall_low_x" , HELPER.auto(ReFramed.id("block/wall/junction/low_x")));
HELPER.addReFramedModel("wall_tall_x" , HELPER.auto(ReFramed.id("block/wall/junction/tall_x")));
HELPER.addReFramedModel("wall_tall_i_low_i_x" , HELPER.auto(ReFramed.id("block/wall/junction/tall_i_low_i_x")));
HELPER.addReFramedModel("wall_tall_low_t_x" , HELPER.auto(ReFramed.id("block/wall/junction/tall_low_t_x")));
HELPER.addReFramedModel("wall_tall_c_low_c_x" , HELPER.auto(ReFramed.id("block/wall/junction/tall_c_low_c_x")));
HELPER.addReFramedModel("wall_tall_t_low_x" , HELPER.auto(ReFramed.id("block/wall/junction/tall_t_low_x")));
// item model assignments (in lieu of models/item/___.json)
HELPER.assignItemModel("cube" , ReFramed.CUBE);
HELPER.assignItemModel("small_cube" , ReFramed.SMALL_CUBE);
HELPER.assignItemModel("small_cubes_step" , ReFramed.SMALL_CUBES_STEP);
HELPER.assignItemModel("slab" , ReFramed.SLAB);
HELPER.assignItemModel("double_slab" , ReFramed.SLABS_CUBE);
HELPER.assignItemModel("stair" , ReFramed.STAIR);
HELPER.assignItemModel("stairs_cube" , ReFramed.STAIRS_CUBE);
HELPER.assignItemModel("half_stair_down" , ReFramed.HALF_STAIR);
HELPER.assignItemModel("half_stairs_slab_down" , ReFramed.HALF_STAIRS_SLAB);
HELPER.assignItemModel("half_stairs_stair_down" , ReFramed.HALF_STAIRS_STAIR);
HELPER.assignItemModel("step" , ReFramed.STEP);
HELPER.assignItemModel("steps_slab" , ReFramed.STEPS_SLAB);
HELPER.assignItemModel("layer_1" , ReFramed.LAYER);
HELPER.assignItemModel("pillar" , ReFramed.PILLAR);
HELPER.assignItemModel("pillars_wall_inventory" , ReFramed.PILLARS_WALL);
HELPER.assignItemModel("wall_inventory" , ReFramed.WALL);
HELPER.assignItemModel("pane_inventory" , ReFramed.PANE);
HELPER.assignItemModel("trapdoor_bottom" , ReFramed.TRAPDOOR);
HELPER.assignItemModel("door_inventory" , ReFramed.DOOR);
HELPER.assignItemModel("button_inventory" , ReFramed.BUTTON);
HELPER.assignItemModel("post" , ReFramed.POST);
HELPER.assignItemModel("fence_inventory" , ReFramed.FENCE);
HELPER.assignItemModel("post_fence_inventory" , ReFramed.POST_FENCE);
HELPER.assignItemModel("slabs_stair" , ReFramed.SLABS_STAIR);
HELPER.assignItemModel("slabs_outer_stair" , ReFramed.SLABS_OUTER_STAIR);
HELPER.assignItemModel("slabs_inner_stair" , ReFramed.SLABS_INNER_STAIR);
HELPER.assignItemModel("steps_cross" , ReFramed.STEPS_CROSS);
HELPER.assignItemModel("half_stairs_cube_stair" , ReFramed.HALF_STAIRS_CUBE_STAIR);
HELPER.assignItemModel("half_stairs_step_stair_1", ReFramed.HALF_STAIRS_STEP_STAIR);
HELPER.assignItemModel("half_layer_2" , ReFramed.HALF_LAYER);
HELPER.assignItemModel("slabs_half_inventory" , ReFramed.SLABS_HALF_LAYER);
HELPER.assignItemModel("steps_half_inventory" , ReFramed.STEPS_HALF_LAYER);
HELPER.assignItemModel("half_slab" , ReFramed.HALF_SLAB);
HELPER.assignItemModel("half_slabs_slab" , ReFramed.HALF_SLABS_SLAB);
HELPER.assignItemModel("slabs_layer_2" , ReFramed.SLABS_LAYER);
//item model assignments (in lieu of models/item/___.json)
HELPER.assignItemModel("cube" , ReFramed.CUBE);
HELPER.assignItemModel("small_cube" , ReFramed.SMALL_CUBE);
HELPER.assignItemModel("small_cubes_step" , ReFramed.SMALL_CUBES_STEP);
HELPER.assignItemModel("slab" , ReFramed.SLAB);
HELPER.assignItemModel("double_slab" , ReFramed.SLABS_CUBE);
HELPER.assignItemModel("stair" , ReFramed.STAIR);
HELPER.assignItemModel("stairs_cube" , ReFramed.STAIRS_CUBE);
HELPER.assignItemModel("half_stair_down" , ReFramed.HALF_STAIR);
HELPER.assignItemModel("half_stairs_slab_down" , ReFramed.HALF_STAIRS_SLAB);
HELPER.assignItemModel("half_stairs_stair_down", ReFramed.HALF_STAIRS_STAIR);
HELPER.assignItemModel("step" , ReFramed.STEP);
HELPER.assignItemModel("steps_slab" , ReFramed.STEPS_SLAB);
HELPER.assignItemModel("layer_1" , ReFramed.LAYER);
HELPER.assignItemModel("pillar" , ReFramed.PILLAR);
HELPER.assignItemModel("wall_inventory" , ReFramed.WALL);
}
private void privateInit() {
//set up some magic to force chunk re-renders when you change a template (see TemplateEntity)
//set up some magic to force chunk rerenders when you change a template (see TemplateEntity)
ReFramed.chunkRerenderProxy = (world, pos) -> {
if(world == MinecraftClient.getInstance().world) {
MinecraftClient.getInstance().worldRenderer.scheduleBlockRender(

View File

@@ -36,10 +36,7 @@ public class ReFramedClientHelper {
}
public UnbakedModel autoDouble(Identifier first, Identifier second) {
return new UnbakedDoubleRetexturedModel(
auto(first),
auto(second)
);
return new UnbakedDoubleRetexturedModel(auto(first), auto(second));
}
public void addReFramedModel(String id, UnbakedModel unbaked) {

View File

@@ -5,23 +5,20 @@ import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.renderer.v1.model.ForwardingBakedModel;
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
import net.minecraft.block.BlockState;
import net.minecraft.client.render.model.BakedQuad;
import net.minecraft.client.texture.Sprite;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.random.Random;
import net.minecraft.world.BlockRenderView;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Supplier;
@Environment(EnvType.CLIENT)
public class DoubleRetexturingBakedModel extends ForwardingBakedModel implements MultiRetexturableModel {
private final RetexturingBakedModel model_1, model_2;
public DoubleRetexturingBakedModel(RetexturingBakedModel model_1, RetexturingBakedModel model_2) {
private final ForwardingBakedModel model_1, model_2;
public DoubleRetexturingBakedModel(ForwardingBakedModel model_1, ForwardingBakedModel model_2) {
this.wrapped = model_1.getWrappedModel();
this.model_1 = model_1;
this.model_2 = model_2;
@@ -38,17 +35,7 @@ public class DoubleRetexturingBakedModel extends ForwardingBakedModel implements
}
@Override
public List<BakedQuad> getQuads(BlockState blockState, Direction face, Random rand) {
List<BakedQuad> quads = new ArrayList<>(model_1.getQuads(blockState, face, rand));
quads.addAll(model_2.getQuads(blockState, face, rand));
return quads;
}
@Override
public void emitBlockQuads(BlockRenderView world, BlockState state, BlockPos pos, Supplier<Random> randomSupplier, RenderContext context) {
model_1.emitBlockQuads(world, state, pos, randomSupplier, context);
model_2.emitBlockQuads(world, state, pos, randomSupplier, context);
}
public void emitBlockQuads(BlockRenderView world, BlockState state, BlockPos pos, Supplier<Random> randomSupplier, RenderContext context) {}
@Override // models are emitted here because no checks are done on items
public void emitItemQuads(ItemStack stack, Supplier<Random> randomSupplier, RenderContext context) {
@@ -57,7 +44,7 @@ public class DoubleRetexturingBakedModel extends ForwardingBakedModel implements
}
@Override
public List<RetexturingBakedModel> models() {
public List<ForwardingBakedModel> models() {
return List.of(model_1, model_2);
}
}

View File

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

View File

@@ -1,7 +1,6 @@
package fr.adrien1106.reframed.client.model;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import fr.adrien1106.reframed.block.ReFramedBlock;
import fr.adrien1106.reframed.block.ReFramedEntity;
import fr.adrien1106.reframed.client.ReFramedClient;
import fr.adrien1106.reframed.mixin.MinecraftAccessor;
@@ -12,13 +11,11 @@ import fr.adrien1106.reframed.util.blocks.ThemeableBlockEntity;
import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap;
import net.fabricmc.fabric.api.renderer.v1.mesh.*;
import net.fabricmc.fabric.api.renderer.v1.model.ForwardingBakedModel;
import net.fabricmc.fabric.api.renderer.v1.model.ModelHelper;
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.BakedQuad;
import net.minecraft.client.render.model.ModelBakeSettings;
import net.minecraft.client.texture.Sprite;
import net.minecraft.item.ItemStack;
@@ -27,37 +24,44 @@ import net.minecraft.util.math.Direction;
import net.minecraft.util.math.random.Random;
import net.minecraft.world.BlockRenderView;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Supplier;
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, boolean ao) {
this.wrapped = base_model; //field from the superclass; vanilla getQuads etc. will delegate through to this
this.appearance_manager = tam;
this.theme_index = theme_index;
this.uv_lock = settings.isUvLocked();
this.item_state = item_state;
this.ao = ao;
int cache_size = 64; // default is 64 why don't ask me and it should get overwritten
if (item_state.getBlock() instanceof ReFramedBlock frame_block) cache_size = frame_block.getModelStateCount() + 1;
BASE_MESH_CACHE = new Object2ObjectLinkedOpenHashMap<>(cache_size, 0.25f) {
@Override
protected void rehash(int v) {}
};
}
protected final CamoAppearanceManager appearance_manager;
protected final int theme_index;
protected final boolean uv_lock;
protected final boolean ao;
protected final BlockState item_state;
protected record MeshCacheKey(Object state_key, CamoAppearance appearance, int model_id) {}
/** cache that store retextured models */
// self culling cache of the models not made thread local so that it is only computed once
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 */
protected final Object2ObjectLinkedOpenHashMap<Object, Mesh> BASE_MESH_CACHE =
new Object2ObjectLinkedOpenHashMap<>(2, 0.25f) {
protected final Object2ObjectLinkedOpenHashMap<MeshCacheKey, Mesh> RETEXTURED_MESH_CACHE =
new Object2ObjectLinkedOpenHashMap<>(128, 0.25f) {
@Override
protected void rehash(int v) {}
};
/** cache that stores the base meshes which has the size of the amount of models */
protected final Object2ObjectLinkedOpenHashMap<Object, Mesh> BASE_MESH_CACHE;
protected static final Direction[] DIRECTIONS_AND_NULL;
static {
Direction[] values = Direction.values();
@@ -65,7 +69,7 @@ public abstract class RetexturingBakedModel extends ForwardingBakedModel {
System.arraycopy(values, 0, DIRECTIONS_AND_NULL, 0, values.length);
}
protected Mesh getBaseMesh(Object key, BlockState state) {
protected Mesh getBaseMesh(Object key, BlockState state) {
//Convert models to re-texturable Meshes lazily, the first time we encounter each blockstate
if (BASE_MESH_CACHE.containsKey(key)) return BASE_MESH_CACHE.getAndMoveToFirst(key);
Mesh mesh = convertModel(state);
@@ -73,40 +77,7 @@ public abstract class RetexturingBakedModel extends ForwardingBakedModel {
return mesh;
}
private List<BakedQuad>[] quads = null;
@Override
public List<BakedQuad> getQuads(BlockState state, Direction face, Random rand) {
if (quads == null) {
quads = ModelHelper.toQuadLists(
getRetexturedMesh(
new MeshCacheKey(
hashCode(),
appearance_manager.getDefaultAppearance(theme_index),
0
),
state == null ? item_state : state
)
);
}
return quads[ModelHelper.toFaceIndex(face)];
}
public void setCamo(BlockRenderView world, BlockState state, BlockPos pos) {
if (state == null || state.isAir()) {
quads = null;
return;
}
CamoAppearance camo = appearance_manager.getCamoAppearance(world, state, pos, theme_index, false);
MeshCacheKey key = new MeshCacheKey(
hashCode(),
camo,
0
);
quads = ModelHelper.toQuadLists(camo.hashCode() == -1 ? transformMesh(key, state) : getRetexturedMesh(key, state));
}
protected abstract Mesh convertModel(BlockState state);
protected abstract Mesh convertModel(BlockState state);
@Override
public boolean isVanillaAdapter() {
@@ -117,20 +88,17 @@ public abstract class RetexturingBakedModel extends ForwardingBakedModel {
public Sprite getParticleSprite() {
return appearance_manager.getDefaultAppearance(theme_index).getSprites(Direction.UP, 0).get(0).sprite();
}
public int getThemeIndex() {
return theme_index;
}
@Override
public void emitBlockQuads(BlockRenderView world, BlockState state, BlockPos pos, Supplier<Random> randomSupplier, RenderContext context) {
// skip render if block not a frame (which should always be the case
if (!(state.getBlock() instanceof ReFramedBlock frame_block)) return;
BlockState theme = (world.getBlockEntity(pos) instanceof ThemeableBlockEntity s) ? s.getTheme(theme_index) : null;
QuadEmitter quad_emitter = context.getEmitter();
if(theme == null || theme.isAir()) {
getRetexturedMesh(
new MeshCacheKey(
hashCode(),
frame_block.getModelCacheKey(state),
appearance_manager.getDefaultAppearance(theme_index),
0
),
@@ -146,7 +114,7 @@ public abstract class RetexturingBakedModel extends ForwardingBakedModel {
if (camo instanceof WeightedComputedAppearance wca) model_id = wca.getAppearanceIndex(seed);
int tint = 0xFF000000 | MinecraftClient.getInstance().getBlockColors().getColor(theme, world, pos, 0);
MeshCacheKey key = new MeshCacheKey(hashCode(), camo, model_id);
MeshCacheKey key = new MeshCacheKey(frame_block.getModelCacheKey(state), camo, model_id);
// do not clutter the cache with single-use meshes
Mesh untintedMesh = camo.hashCode() == -1 ? transformMesh(key, state) : getRetexturedMesh(key, state);
@@ -187,23 +155,11 @@ public abstract class RetexturingBakedModel extends ForwardingBakedModel {
context.popTransform();
}
}
public boolean useAmbientOcclusion(BlockRenderView view, BlockPos pos) {
if (!(view.getBlockEntity(pos) instanceof ThemeableBlockEntity frame_entity)) return false;
BlockState theme = frame_entity.getTheme(theme_index);
CamoAppearance appearance = appearance_manager
.getCamoAppearance(view, theme, pos, theme_index, false);
long seed = theme.getRenderingSeed(pos);
int model_id = 0;
if (appearance instanceof WeightedComputedAppearance wca) model_id = wca.getAppearanceIndex(seed);
return appearance.getAO(model_id);
}
protected Mesh getRetexturedMesh(MeshCacheKey key, BlockState state) {
if (RETEXTURED_MESH_CACHE.asMap().containsKey(key)) return RETEXTURED_MESH_CACHE.getIfPresent(key);
if (RETEXTURED_MESH_CACHE.containsKey(key)) return RETEXTURED_MESH_CACHE.getAndMoveToFirst(key);
Mesh mesh = transformMesh(key, state);
RETEXTURED_MESH_CACHE.put(key, mesh);
RETEXTURED_MESH_CACHE.putAndMoveToFirst(key, mesh);
return mesh;
}
@@ -216,9 +172,9 @@ public abstract class RetexturingBakedModel extends ForwardingBakedModel {
int i = -1;
do {
emitter.copyFrom(quad);
i = key.appearance.transformQuad(emitter, i, quad_index.get(), key.model_id, uv_lock);
i = key.appearance.transformQuad(emitter, i, quad_index.get(), key.model_id, ao, uv_lock);
} while (i > 0);
// kinda weird to do it like that but other directions don't use the quad_index, so it doesn't matter
// kinda weird to do it like that but other directions don't use the quad_index so it doesn't matter
if (quad.cullFace() == null) quad_index.getAndIncrement();
});

View File

@@ -36,7 +36,8 @@ public class UnbakedAutoRetexturedModel extends UnbakedRetexturedModel {
ReFramedClient.HELPER.getCamoAppearanceManager(texture_getter),
theme_index,
bake_settings,
item_state
item_state,
ao
) {
protected Mesh convertModel(BlockState state) {
Renderer r = ReFramedClient.HELPER.getFabricRenderer();

View File

@@ -1,5 +1,6 @@
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.Baker;
import net.minecraft.client.render.model.ModelBakeSettings;
@@ -40,8 +41,8 @@ public class UnbakedDoubleRetexturedModel implements UnbakedModel {
@Override
public BakedModel bake(Baker baker, Function<SpriteIdentifier, Sprite> texture_getter, ModelBakeSettings model_bake_settings, Identifier identifier) {
return new DoubleRetexturingBakedModel(
(RetexturingBakedModel) model_1.bake(baker, texture_getter, model_bake_settings, identifier),
(RetexturingBakedModel) model_2.bake(baker, texture_getter, model_bake_settings, identifier)
(ForwardingBakedModel) model_1.bake(baker, texture_getter, model_bake_settings, identifier),
(ForwardingBakedModel) model_2.bake(baker, texture_getter, model_bake_settings, identifier)
);
}
}

View File

@@ -44,7 +44,8 @@ public class UnbakedJsonRetexturedModel extends UnbakedRetexturedModel {
ReFramedClient.HELPER.getCamoAppearanceManager(spriteLookup),
theme_index,
bake_settings,
item_state
item_state,
ao
) {
protected Mesh convertModel(BlockState state) {
Renderer r = ReFramedClient.HELPER.getFabricRenderer();

View File

@@ -14,6 +14,7 @@ public abstract class UnbakedRetexturedModel implements UnbakedModel {
protected int theme_index = 1;
protected BlockState item_state;
protected final boolean ao = true;
public UnbakedRetexturedModel(Identifier parent) {
this.parent = parent;

View File

@@ -5,4 +5,4 @@ import net.minecraft.util.math.Direction;
import java.util.List;
import java.util.Map;
public record Appearance(Map<Direction, List<SpriteProperties>> sprites, boolean use_ao) {}
public record Appearance(Map<Direction, List<SpriteProperties>> sprites) {}

View File

@@ -26,13 +26,12 @@ public abstract class CamoAppearance {
public abstract @NotNull List<SpriteProperties> getSprites(Direction dir, int model_id);
public abstract boolean hasColor(Direction dir, int model_id, int index);
public abstract boolean getAO(int model_id);
public @NotNull RenderMaterial getRenderMaterial(boolean ao) {
return ao && ao_material != null? ao_material : material;
}
public int transformQuad(QuadEmitter quad, int i, int quad_index, int model_id, boolean uv_lock) {
public int transformQuad(QuadEmitter quad, int i, int quad_index, int model_id, boolean ao, boolean uv_lock) {
if(quad.tag() == 0) return 0; // Pass the quad through unmodified.
Direction direction = quad.nominalFace();
@@ -45,7 +44,7 @@ public abstract class CamoAppearance {
QuadPosBounds bounds = properties.bounds();
if (bounds == null) { // sprite applies anywhere e.g. default behaviour
quad.material(getRenderMaterial(getAO(model_id)));
quad.material(getRenderMaterial(ao));
quad.spriteBake(
properties.sprite(),
MutableQuadView.BAKE_NORMALIZED
@@ -62,7 +61,7 @@ public abstract class CamoAppearance {
if (!bounds.matches(origin_bounds)) return i;
// apply new quad shape
quad.material(getRenderMaterial(getAO(model_id)));
quad.material(getRenderMaterial(ao));
bounds.intersection(origin_bounds, direction.getAxis()).apply(quad, origin_bounds);
quad.spriteBake( // seems to work without the flags and break with it
properties.sprite(),

View File

@@ -51,7 +51,7 @@ public class CamoAppearanceManager {
for(BlendMode blend : BlendMode.values()) {
finder.clear().disableDiffuse(false).blendMode(blend);
materials.put(blend, finder.ambientOcclusion(TriState.TRUE).find());
materials.put(blend, finder.ambientOcclusion(TriState.FALSE).find());
ao_materials.put(blend, finder.ambientOcclusion(TriState.DEFAULT).find()); //not "true" since that *forces* AO, i just want to *allow* AO
}
@@ -64,12 +64,12 @@ public class CamoAppearanceManager {
this.accent_appearance = new SingleSpriteAppearance(sprite, materials.get(BlendMode.CUTOUT), serial_number.getAndIncrement());
sprite = spriteLookup.apply(BARRIER_SPRITE_ID);
this.barrier_appearance = new SingleSpriteAppearance(sprite, materials.get(BlendMode.CUTOUT), serial_number.getAndIncrement());
this.barrierItemAppearance = new SingleSpriteAppearance(sprite, materials.get(BlendMode.CUTOUT), serial_number.getAndIncrement());
}
private final CamoAppearance default_appearance;
private final CamoAppearance accent_appearance;
private final CamoAppearance barrier_appearance;
private final CamoAppearance barrierItemAppearance;
private final AtomicInteger serial_number = new AtomicInteger(0); //Mutable
@@ -119,7 +119,7 @@ public class CamoAppearanceManager {
// The results are going to be the same, apart from their serialNumbers differing (= their equals & hashCode differing).
// Tiny amount of wasted space in some caches if CamoAppearances are used as a map key, then. IMO it's not a critical issue.
private CamoAppearance computeAppearance(BakedModel model, BlockState state, boolean is_dynamic) {
if(state.getBlock() == Blocks.BARRIER) return barrier_appearance;
if(state.getBlock() == Blocks.BARRIER) return barrierItemAppearance;
if (!(model instanceof WeightedBakedModelAccessor weighted_model)) {
return new ComputedAppearance(
@@ -175,7 +175,7 @@ public class CamoAppearanceManager {
});
});
return new Appearance(sprites, model.useAmbientOcclusion());
return new Appearance(sprites);
}
private static int getBakeFlags(QuadEmitter emitter, Sprite sprite) {

View File

@@ -16,6 +16,7 @@ public class ComputedAppearance extends CamoAppearance {
super(ao_material, material, id);
this.appearance = appearance;
}
@Override
public @NotNull List<SpriteProperties> getSprites(Direction dir, int model_id) {
return appearance.sprites().get(dir);
@@ -28,12 +29,6 @@ public class ComputedAppearance extends CamoAppearance {
return properties.get(index).has_colors();
}
@Override
public boolean getAO(int model_id) {
return appearance.use_ao();
}
@Override
public boolean equals(Object o) {
if(this == o) return true;

View File

@@ -35,12 +35,6 @@ public class SingleSpriteAppearance extends CamoAppearance {
return id == that.id;
}
@Override
public boolean getAO(int model_id) {
return false;
}
@Override
public String toString() {
return "SingleSpriteAppearance[defaultSprite=%s, mat=%s, id=%d]".formatted(defaultSprite, material, id);

View File

@@ -46,12 +46,6 @@ public class WeightedComputedAppearance extends CamoAppearance {
return properties.get(index).has_colors();
}
@Override
public boolean getAO(int model_id) {
return getAppearance(model_id).use_ao();
}
@Override
public boolean equals(Object o) {
if(this == o) return true;

View File

@@ -5,13 +5,13 @@ import com.google.common.cache.CacheBuilder;
import fr.adrien1106.reframed.block.ReFramedBlock;
import fr.adrien1106.reframed.client.ReFramedClient;
import fr.adrien1106.reframed.client.model.QuadPosBounds;
import fr.adrien1106.reframed.client.model.RetexturingBakedModel;
import fr.adrien1106.reframed.util.blocks.ThemeableBlockEntity;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.renderer.v1.Renderer;
import net.fabricmc.fabric.api.renderer.v1.material.RenderMaterial;
import net.fabricmc.fabric.api.renderer.v1.mesh.QuadEmitter;
import net.fabricmc.fabric.api.renderer.v1.model.ForwardingBakedModel;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.util.function.BooleanBiFunction;
@@ -31,19 +31,20 @@ import static net.minecraft.util.shape.VoxelShapes.combine;
@Environment(EnvType.CLIENT)
public class RenderHelper {
// 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 record CullElement(Block block, Object state_key, int model) { }
private static final Cache<CullElement, Integer[]> INNER_CULL_MAP = CacheBuilder.newBuilder().maximumSize(1024).build();
private record CullElement(Block block, Object state_key, int model) {}
/**
* 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 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 (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();
QuadEmitter quad_emitter = r.meshBuilder().getEmitter();
@@ -51,6 +52,8 @@ public class RenderHelper {
Random random = Random.create();
List<List<QuadPosBounds>> model_bounds = models.stream()
.map(ForwardingBakedModel::getWrappedModel)
.filter(Objects::nonNull)
.map(wrapped -> wrapped.getQuads(state, null, random))
.map(quads -> quads.stream().map(quad -> {
quad_emitter.fromVanilla(quad, material, null);
@@ -58,12 +61,12 @@ public class RenderHelper {
}).toList()).toList();
Integer[] cull_array;
for (int self_id = 1; self_id <= model_bounds.size(); self_id++) {
for(int self_id = 1; self_id <= model_bounds.size(); self_id++) {
List<QuadPosBounds> self_bounds = model_bounds.get(self_id - 1);
cull_array = new Integer[self_bounds.size()];
for (int self_quad = 0; self_quad < cull_array.length; self_quad++) {
QuadPosBounds self_bound = self_bounds.get(self_quad);
for (int other_id = 1; other_id <= model_bounds.size(); other_id++) {
for(int other_id = 1; other_id <= model_bounds.size(); other_id++) {
if (other_id == self_id) continue;
if (model_bounds.get(other_id - 1).stream().anyMatch(other_bound -> other_bound.equals(self_bound))) {
cull_array[self_quad] = other_id;
@@ -71,15 +74,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) {
if (!(state.getBlock() instanceof ReFramedBlock frame_block)
public static boolean shouldDrawInnerFace(BlockState state, BlockRenderView view, BlockPos pos, int quad_index, int theme_index) {
if ( !(state.getBlock() instanceof ReFramedBlock frame_block)
|| !(view.getBlockEntity(pos) instanceof ThemeableBlockEntity frame_entity)
) 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;
// needs to be Integer object because array is initialized with null not 0
@@ -89,27 +92,18 @@ public class RenderHelper {
BlockState self_theme = frame_entity.getTheme(theme_index);
BlockState other_theme = frame_entity.getTheme(cull_theme);
try {
if (self_theme.isSideInvisible(other_theme, null)) return false;
} catch (NullPointerException e) { // this can happen if mod haven't thought about inner faces
return true;
}
return self_theme.isOpaque() != other_theme.isOpaque() && self_theme.isOpaque();
if (self_theme.isSideInvisible(other_theme, null)) return false;
return !self_theme.isOpaque() || !other_theme.isOpaque();
}
// Doing this method from scratch as it is simpler to do than injecting everywhere
public static boolean shouldDrawSide(BlockState self_state, BlockView world, BlockPos pos, Direction side, BlockPos other_pos, int theme_index) {
ThemeableBlockEntity self = world.getBlockEntity(pos) instanceof ThemeableBlockEntity e ? e : null;
ThemeableBlockEntity other = world.getBlockEntity(other_pos) instanceof ThemeableBlockEntity e ? e : null;
BlockState other_state = world.getBlockState(other_pos);
ThemeableBlockEntity self = world.getBlockEntity(pos) instanceof ThemeableBlockEntity e
&& self_state.getBlock() instanceof ReFramedBlock
? e : null;
ThemeableBlockEntity other = world.getBlockEntity(other_pos) instanceof ThemeableBlockEntity e
&& other_state.getBlock() instanceof ReFramedBlock
? e : null;
// normal behaviour
if ((theme_index == 0 && self != null) || (self == null && other == null))
return Block.shouldDrawSide(self_state, world, pos, side, other_pos);
if (self == null && other == null) return Block.shouldDrawSide(self_state, world, pos, side, other_pos);
// self is a normal Block
if (self == null && other_state.getBlock() instanceof ReFramedBlock other_block) {
@@ -120,7 +114,7 @@ public class RenderHelper {
VoxelShape other_shape = VoxelShapes.empty();
for (BlockState s: other.getThemes()) {
i++;
if (self_state.isSideInvisible(s, side) || (s.isOpaque() && (other.isSolid() || self_state.isTransparent(world ,pos))))
if (self_state.isSideInvisible(s, side) || s.isOpaque())
other_shape = combine(
other_shape,
other_block
@@ -164,7 +158,7 @@ public class RenderHelper {
VoxelShape other_shape = VoxelShapes.empty();
for (BlockState s: other.getThemes()) {
i++;
if (self_theme.isSideInvisible(s, side) || (s.isOpaque() && (!self.isSolid() || (other.isSolid() == self.isSolid()))))
if (self_theme.isSideInvisible(s, side) || s.isOpaque())
other_shape = combine(
other_shape,
other_block

View File

@@ -14,11 +14,9 @@ import java.util.Map;
public class RebakedModel implements BakedModel {
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.ambient_occlusion = ambient_occlusion;
}
@Override
@@ -28,7 +26,7 @@ public class RebakedModel implements BakedModel {
@Override
public boolean useAmbientOcclusion() {
return ambient_occlusion;
return true;
}
@Override

View File

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

View File

@@ -22,37 +22,17 @@ public class GBlockstate extends FabricModelProvider {
providers.put(ReFramedHalfStairBlock.class, new HalfStair());
providers.put(ReFramedHalfStairsSlabBlock.class, new HalfStairsSlab());
providers.put(ReFramedHalfStairsStairBlock.class, new HalfStairsStair());
providers.put(ReFramedHalfStairsCubeStairBlock.class, new HalfStairsCubeStair());
providers.put(ReFramedHalfStairsStepStairBlock.class, new HalfStairsStepStair());
providers.put(ReFramedLayerBlock.class, new Layer());
providers.put(ReFramedHalfLayerBlock.class, new HalfLayer());
providers.put(ReFramedPillarBlock.class, new Pillar());
providers.put(ReFramedSlabBlock.class, new Slab());
providers.put(ReFramedSlabsCubeBlock.class, new SlabsCube());
providers.put(ReFramedSlabsStairBlock.class, new SlabsStair());
providers.put(ReFramedSlabsOuterStairBlock.class, new SlabsOuterStair());
providers.put(ReFramedSlabsInnerStairBlock.class, new SlabsInnerStair());
providers.put(ReFramedSlabsHalfLayerBlock.class, new SlabsHalfLayer());
providers.put(ReFramedSlabsLayerBlock.class, new SlabsLayer());
providers.put(ReFramedHalfSlabBlock.class, new HalfSlab());
providers.put(ReFramedHalfSlabsSlabBlock.class, new HalfSlabsSlab());
providers.put(ReFramedSmallCubeBlock.class, new SmallCube());
providers.put(ReFramedSmallCubesStepBlock.class, new SmallCubesStep());
providers.put(ReFramedStairBlock.class, new Stair());
providers.put(ReFramedStairsCubeBlock.class, new StairsCube());
providers.put(ReFramedStepBlock.class, new Step());
providers.put(ReFramedStepsSlabBlock.class, new StepsSlab());
providers.put(ReFramedStepsCrossBlock.class, new StepsCross());
providers.put(ReFramedStepsHalfLayerBlock.class, new StepsHalfLayer());
providers.put(ReFramedPillarsWallBlock.class, new PillarsWall());
providers.put(ReFramedWallBlock.class, new Wall());
providers.put(ReFramedPaneBlock.class, new Pane());
providers.put(ReFramedTrapdoorBlock.class, new Trapdoor());
providers.put(ReFramedDoorBlock.class, new Door());
providers.put(ReFramedButtonBlock.class, new Button());
providers.put(ReFramedPostBlock.class, new Post());
providers.put(ReFramedFenceBlock.class, new Fence());
providers.put(ReFramedPostFenceBlock.class, new PostFence());
providers.put(ReframedWallBlock.class, new Wall());
}
public GBlockstate(FabricDataOutput output) {

View File

@@ -24,37 +24,17 @@ public class GRecipe extends FabricRecipeProvider {
providers.put(ReFramedHalfStairBlock.class, new HalfStair());
providers.put(ReFramedHalfStairsSlabBlock.class, new HalfStairsSlab());
providers.put(ReFramedHalfStairsStairBlock.class, new HalfStairsStair());
providers.put(ReFramedHalfStairsCubeStairBlock.class, new HalfStairsCubeStair());
providers.put(ReFramedHalfStairsStepStairBlock.class, new HalfStairsStepStair());
providers.put(ReFramedLayerBlock.class, new Layer());
providers.put(ReFramedHalfLayerBlock.class, new HalfLayer());
providers.put(ReFramedPillarBlock.class, new Pillar());
providers.put(ReFramedSlabBlock.class, new Slab());
providers.put(ReFramedSlabsCubeBlock.class, new SlabsCube());
providers.put(ReFramedSlabsStairBlock.class, new SlabsStair());
providers.put(ReFramedSlabsOuterStairBlock.class, new SlabsOuterStair());
providers.put(ReFramedSlabsInnerStairBlock.class, new SlabsInnerStair());
providers.put(ReFramedSlabsHalfLayerBlock.class, new SlabsHalfLayer());
providers.put(ReFramedSlabsLayerBlock.class, new SlabsLayer());
providers.put(ReFramedHalfSlabBlock.class, new HalfSlab());
providers.put(ReFramedHalfSlabsSlabBlock.class, new HalfSlabsSlab());
providers.put(ReFramedSmallCubeBlock.class, new SmallCube());
providers.put(ReFramedSmallCubesStepBlock.class, new SmallCubesStep());
providers.put(ReFramedStairBlock.class, new Stair());
providers.put(ReFramedStairsCubeBlock.class, new StairsCube());
providers.put(ReFramedStepBlock.class, new Step());
providers.put(ReFramedStepsSlabBlock.class, new StepsSlab());
providers.put(ReFramedStepsCrossBlock.class, new StepsCross());
providers.put(ReFramedStepsHalfLayerBlock.class, new StepsHalfLayer());
providers.put(ReFramedPillarsWallBlock.class, new PillarsWall());
providers.put(ReFramedWallBlock.class, new Wall());
providers.put(ReFramedPaneBlock.class, new Pane());
providers.put(ReFramedTrapdoorBlock.class, new Trapdoor());
providers.put(ReFramedDoorBlock.class, new Door());
providers.put(ReFramedButtonBlock.class, new Button());
providers.put(ReFramedPostBlock.class, new Post());
providers.put(ReFramedFenceBlock.class, new Fence());
providers.put(ReFramedPostFenceBlock.class, new PostFence());
providers.put(ReframedWallBlock.class, new Wall());
providers.put(ReFramedBlueprintItem.class, new Blueprint());
providers.put(ReFramedHammerItem.class, new Hammer());
providers.put(ReFramedScrewdriverItem.class, new Screwdriver());

View File

@@ -1,95 +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 net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider;
import net.minecraft.block.Block;
import net.minecraft.block.enums.BlockFace;
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.util.Identifier;
import net.minecraft.util.math.Direction;
import static net.minecraft.data.client.VariantSettings.Rotation.*;
import static net.minecraft.state.property.Properties.*;
public class Button implements RecipeSetter, BlockStateProvider {
@Override
public void setRecipe(RecipeExporter exporter, ItemConvertible convertible) {
RecipeProvider.offerStonecuttingRecipe(exporter, RecipeCategory.BUILDING_BLOCKS, convertible, ReFramed.CUBE, 8);
ShapelessRecipeJsonBuilder.create(RecipeCategory.BUILDING_BLOCKS, convertible, 1)
.input(ReFramed.CUBE, 1)
.criterion(FabricRecipeProvider.hasItem(ReFramed.CUBE), FabricRecipeProvider.conditionsFromItem(ReFramed.CUBE))
.criterion(FabricRecipeProvider.hasItem(convertible), FabricRecipeProvider.conditionsFromItem(convertible))
.offerTo(exporter);
}
@Override
public BlockStateSupplier getMultipart(Block block) {
Identifier button = ReFramed.id("button_special");
Identifier button_pressed = ReFramed.id("button_pressed_special");
return MultipartBlockStateSupplier.create(block)
// FLOOR OFF
.with(GBlockstate.when(POWERED, false, HORIZONTAL_FACING, Direction.NORTH, BLOCK_FACE, BlockFace.FLOOR),
GBlockstate.variant(button, true, R0, R0))
.with(GBlockstate.when(POWERED, false, HORIZONTAL_FACING, Direction.EAST, BLOCK_FACE, BlockFace.FLOOR),
GBlockstate.variant(button, true, R0, R90))
.with(GBlockstate.when(POWERED, false, HORIZONTAL_FACING, Direction.SOUTH, BLOCK_FACE, BlockFace.FLOOR),
GBlockstate.variant(button, true, R0, R180))
.with(GBlockstate.when(POWERED, false, HORIZONTAL_FACING, Direction.WEST, BLOCK_FACE, BlockFace.FLOOR),
GBlockstate.variant(button, true, R0, R270))
// CEILING OFF
.with(GBlockstate.when(POWERED, false, HORIZONTAL_FACING, Direction.SOUTH, BLOCK_FACE, BlockFace.CEILING),
GBlockstate.variant(button, true, R180, R0))
.with(GBlockstate.when(POWERED, false, HORIZONTAL_FACING, Direction.WEST, BLOCK_FACE, BlockFace.CEILING),
GBlockstate.variant(button, true, R180, R90))
.with(GBlockstate.when(POWERED, false, HORIZONTAL_FACING, Direction.NORTH, BLOCK_FACE, BlockFace.CEILING),
GBlockstate.variant(button, true, R180, R180))
.with(GBlockstate.when(POWERED, false, HORIZONTAL_FACING, Direction.EAST, BLOCK_FACE, BlockFace.CEILING),
GBlockstate.variant(button, true, R180, R270))
// WALL OFF
.with(GBlockstate.when(POWERED, false, HORIZONTAL_FACING, Direction.NORTH, BLOCK_FACE, BlockFace.WALL),
GBlockstate.variant(button, true, R90, R0))
.with(GBlockstate.when(POWERED, false, HORIZONTAL_FACING, Direction.EAST, BLOCK_FACE, BlockFace.WALL),
GBlockstate.variant(button, true, R90, R90))
.with(GBlockstate.when(POWERED, false, HORIZONTAL_FACING, Direction.SOUTH, BLOCK_FACE, BlockFace.WALL),
GBlockstate.variant(button, true, R90, R180))
.with(GBlockstate.when(POWERED, false, HORIZONTAL_FACING, Direction.WEST, BLOCK_FACE, BlockFace.WALL),
GBlockstate.variant(button, true, R90, R270))
// FLOOR ON
.with(GBlockstate.when(POWERED, true, HORIZONTAL_FACING, Direction.NORTH, BLOCK_FACE, BlockFace.FLOOR),
GBlockstate.variant(button_pressed, true, R0, R0))
.with(GBlockstate.when(POWERED, true, HORIZONTAL_FACING, Direction.EAST, BLOCK_FACE, BlockFace.FLOOR),
GBlockstate.variant(button_pressed, true, R0, R90))
.with(GBlockstate.when(POWERED, true, HORIZONTAL_FACING, Direction.SOUTH, BLOCK_FACE, BlockFace.FLOOR),
GBlockstate.variant(button_pressed, true, R0, R180))
.with(GBlockstate.when(POWERED, true, HORIZONTAL_FACING, Direction.WEST, BLOCK_FACE, BlockFace.FLOOR),
GBlockstate.variant(button_pressed, true, R0, R270))
// CEILING ON
.with(GBlockstate.when(POWERED, true, HORIZONTAL_FACING, Direction.SOUTH, BLOCK_FACE, BlockFace.CEILING),
GBlockstate.variant(button_pressed, true, R180, R0))
.with(GBlockstate.when(POWERED, true, HORIZONTAL_FACING, Direction.WEST, BLOCK_FACE, BlockFace.CEILING),
GBlockstate.variant(button_pressed, true, R180, R90))
.with(GBlockstate.when(POWERED, true, HORIZONTAL_FACING, Direction.NORTH, BLOCK_FACE, BlockFace.CEILING),
GBlockstate.variant(button_pressed, true, R180, R180))
.with(GBlockstate.when(POWERED, true, HORIZONTAL_FACING, Direction.EAST, BLOCK_FACE, BlockFace.CEILING),
GBlockstate.variant(button_pressed, true, R180, R270))
// WALL ON
.with(GBlockstate.when(POWERED, true, HORIZONTAL_FACING, Direction.NORTH, BLOCK_FACE, BlockFace.WALL),
GBlockstate.variant(button_pressed, true, R90, R0))
.with(GBlockstate.when(POWERED, true, HORIZONTAL_FACING, Direction.EAST, BLOCK_FACE, BlockFace.WALL),
GBlockstate.variant(button_pressed, true, R90, R90))
.with(GBlockstate.when(POWERED, true, HORIZONTAL_FACING, Direction.SOUTH, BLOCK_FACE, BlockFace.WALL),
GBlockstate.variant(button_pressed, true, R90, R180))
.with(GBlockstate.when(POWERED, true, HORIZONTAL_FACING, Direction.WEST, BLOCK_FACE, BlockFace.WALL),
GBlockstate.variant(button_pressed, true, R90, R270));
}
}

View File

@@ -1,77 +0,0 @@
package fr.adrien1106.reframed.generator.block;
import fr.adrien1106.reframed.ReFramed;
import fr.adrien1106.reframed.generator.GBlockstate;
import fr.adrien1106.reframed.util.blocks.Corner;
import net.minecraft.block.Block;
import net.minecraft.data.client.MultipartBlockStateSupplier;
import net.minecraft.util.Identifier;
import static fr.adrien1106.reframed.util.blocks.BlockProperties.CORNER;
import static fr.adrien1106.reframed.util.blocks.BlockProperties.CORNER_FACE;
import static net.minecraft.data.client.VariantSettings.Rotation.*;
public class CornerDouble {
public static MultipartBlockStateSupplier getMultipart(Block block, String model_name) {
Identifier model_id = ReFramed.id(model_name + "_special");
Identifier side_id = ReFramed.id(model_name + "_side_special");
return MultipartBlockStateSupplier.create(block)
// BOTTOM
.with(GBlockstate.when(CORNER, Corner.EAST_SOUTH_DOWN, CORNER_FACE, 2),
GBlockstate.variant(model_id, true, R0, R0))
.with(GBlockstate.when(CORNER, Corner.SOUTH_WEST_DOWN, CORNER_FACE, 2),
GBlockstate.variant(model_id, true, R0, R90))
.with(GBlockstate.when(CORNER, Corner.WEST_NORTH_DOWN, CORNER_FACE, 2),
GBlockstate.variant(model_id, true, R0, R180))
.with(GBlockstate.when(CORNER, Corner.NORTH_EAST_DOWN, CORNER_FACE, 2),
GBlockstate.variant(model_id, true, R0, R270))
// TOP
.with(GBlockstate.when(CORNER, Corner.NORTH_EAST_UP, CORNER_FACE, 2),
GBlockstate.variant(model_id, true, R180, R0))
.with(GBlockstate.when(CORNER, Corner.EAST_SOUTH_UP, CORNER_FACE, 2),
GBlockstate.variant(model_id, true, R180, R90))
.with(GBlockstate.when(CORNER, Corner.SOUTH_WEST_UP, CORNER_FACE, 2),
GBlockstate.variant(model_id, true, R180, R180))
.with(GBlockstate.when(CORNER, Corner.WEST_NORTH_UP, CORNER_FACE, 2),
GBlockstate.variant(model_id, true, R180, R270))
// EAST
.with(GBlockstate.when(CORNER, Corner.EAST_SOUTH_DOWN, CORNER_FACE, 0),
GBlockstate.variant(side_id, true, R0, R0))
.with(GBlockstate.when(CORNER, Corner.EAST_SOUTH_UP, CORNER_FACE, 0),
GBlockstate.variant(side_id, true, R90, R0))
.with(GBlockstate.when(CORNER, Corner.NORTH_EAST_UP, CORNER_FACE, 1),
GBlockstate.variant(side_id, true, R180, R0))
.with(GBlockstate.when(CORNER, Corner.NORTH_EAST_DOWN, CORNER_FACE, 1),
GBlockstate.variant(side_id, true, R270, R0))
// SOUTH
.with(GBlockstate.when(CORNER, Corner.SOUTH_WEST_DOWN, CORNER_FACE, 0),
GBlockstate.variant(side_id, true, R0, R90))
.with(GBlockstate.when(CORNER, Corner.SOUTH_WEST_UP, CORNER_FACE, 0),
GBlockstate.variant(side_id, true, R90, R90))
.with(GBlockstate.when(CORNER, Corner.EAST_SOUTH_UP, CORNER_FACE, 1),
GBlockstate.variant(side_id, true, R180, R90))
.with(GBlockstate.when(CORNER, Corner.EAST_SOUTH_DOWN, CORNER_FACE, 1),
GBlockstate.variant(side_id, true, R270, R90))
// WEST
.with(GBlockstate.when(CORNER, Corner.WEST_NORTH_DOWN, CORNER_FACE, 0),
GBlockstate.variant(side_id, true, R0, R180))
.with(GBlockstate.when(CORNER, Corner.WEST_NORTH_UP, CORNER_FACE, 0),
GBlockstate.variant(side_id, true, R90, R180))
.with(GBlockstate.when(CORNER, Corner.SOUTH_WEST_UP, CORNER_FACE, 1),
GBlockstate.variant(side_id, true, R180, R180))
.with(GBlockstate.when(CORNER, Corner.SOUTH_WEST_DOWN, CORNER_FACE, 1),
GBlockstate.variant(side_id, true, R270, R180))
// NORTH
.with(GBlockstate.when(CORNER, Corner.NORTH_EAST_DOWN, CORNER_FACE, 0),
GBlockstate.variant(side_id, true, R0, R270))
.with(GBlockstate.when(CORNER, Corner.NORTH_EAST_UP, CORNER_FACE, 0),
GBlockstate.variant(side_id, true, R90, R270))
.with(GBlockstate.when(CORNER, Corner.WEST_NORTH_UP, CORNER_FACE, 1),
GBlockstate.variant(side_id, true, R180, R270))
.with(GBlockstate.when(CORNER, Corner.WEST_NORTH_DOWN, CORNER_FACE, 1),
GBlockstate.variant(side_id, true, R270, R270))
;
}
}

View File

@@ -1,73 +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 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.client.When;
import net.minecraft.data.server.recipe.RecipeExporter;
import net.minecraft.data.server.recipe.RecipeProvider;
import net.minecraft.data.server.recipe.ShapedRecipeJsonBuilder;
import net.minecraft.item.ItemConvertible;
import net.minecraft.recipe.book.RecipeCategory;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.Direction;
import static net.minecraft.block.enums.DoorHinge.*;
import static net.minecraft.data.client.VariantSettings.Rotation.*;
import static net.minecraft.state.property.Properties.*;
public class Door implements RecipeSetter, BlockStateProvider {
@Override
public void setRecipe(RecipeExporter exporter, ItemConvertible convertible) {
RecipeProvider.offerStonecuttingRecipe(exporter, RecipeCategory.BUILDING_BLOCKS, convertible, ReFramed.CUBE, 1);
ShapedRecipeJsonBuilder
.create(RecipeCategory.BUILDING_BLOCKS, convertible, 3)
.pattern("II")
.pattern("II")
.pattern("II")
.input('I', ReFramed.CUBE)
.criterion(FabricRecipeProvider.hasItem(ReFramed.CUBE), FabricRecipeProvider.conditionsFromItem(ReFramed.CUBE))
.criterion(FabricRecipeProvider.hasItem(convertible), FabricRecipeProvider.conditionsFromItem(convertible))
.offerTo(exporter);
}
@Override
public BlockStateSupplier getMultipart(Block block) {
Identifier door = ReFramed.id("trapdoor_open_special");
return MultipartBlockStateSupplier.create(block)
// SOUTH
.with(When.anyOf(
GBlockstate.when(OPEN, false, HORIZONTAL_FACING, Direction.SOUTH),
GBlockstate.when(OPEN, true, HORIZONTAL_FACING, Direction.EAST, DOOR_HINGE, LEFT),
GBlockstate.when(OPEN, true, HORIZONTAL_FACING, Direction.WEST, DOOR_HINGE, RIGHT)
),
GBlockstate.variant(door, true, R0, R0))
// WEST
.with(When.anyOf(
GBlockstate.when(OPEN, false, HORIZONTAL_FACING, Direction.WEST),
GBlockstate.when(OPEN, true, HORIZONTAL_FACING, Direction.SOUTH, DOOR_HINGE, LEFT),
GBlockstate.when(OPEN, true, HORIZONTAL_FACING, Direction.NORTH, DOOR_HINGE, RIGHT)
),
GBlockstate.variant(door, true, R0, R90))
// NORTH
.with(When.anyOf(
GBlockstate.when(OPEN, false, HORIZONTAL_FACING, Direction.NORTH),
GBlockstate.when(OPEN, true, HORIZONTAL_FACING, Direction.WEST, DOOR_HINGE, LEFT),
GBlockstate.when(OPEN, true, HORIZONTAL_FACING, Direction.EAST, DOOR_HINGE, RIGHT)
),
GBlockstate.variant(door, true, R0, R180))
// EAST
.with(When.anyOf(
GBlockstate.when(OPEN, false, HORIZONTAL_FACING, Direction.EAST),
GBlockstate.when(OPEN, true, HORIZONTAL_FACING, Direction.NORTH, DOOR_HINGE, LEFT),
GBlockstate.when(OPEN, true, HORIZONTAL_FACING, Direction.SOUTH, DOOR_HINGE, RIGHT)
),
GBlockstate.variant(door, true, R0, R270));
}
}

View File

@@ -1,73 +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.block.Blocks;
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.ShapedRecipeJsonBuilder;
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.data.client.VariantSettings.Rotation.*;
import static net.minecraft.state.property.Properties.*;
public class Fence implements RecipeSetter, TagGetter, BlockStateProvider {
@Override
public void setRecipe(RecipeExporter exporter, ItemConvertible convertible) {
RecipeProvider.offerStonecuttingRecipe(exporter, RecipeCategory.BUILDING_BLOCKS, convertible, ReFramed.CUBE, 4);
ShapedRecipeJsonBuilder
.create(RecipeCategory.BUILDING_BLOCKS, convertible, 4)
.pattern("I-I")
.pattern("I-I")
.input('I', ReFramed.CUBE)
.input('-', Blocks.BAMBOO)
.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.FENCES, BlockTags.WOODEN_FENCES);
}
@Override
public BlockStateSupplier getMultipart(Block block) {
Identifier side_on = ReFramed.id("fence_side_on_special");
Identifier side_off = ReFramed.id("fence_side_off_special");
return MultipartBlockStateSupplier.create(block)
.with(GBlockstate.variant(ReFramed.id("fence_core_special"), true, R0, R0))
// SIDE ON
.with(GBlockstate.when(NORTH, true),
GBlockstate.variant(side_on, true, R0, R0))
.with(GBlockstate.when(EAST, true),
GBlockstate.variant(side_on, true, R0, R90))
.with(GBlockstate.when(SOUTH, true),
GBlockstate.variant(side_on, true, R0, R180))
.with(GBlockstate.when(WEST, true),
GBlockstate.variant(side_on, true, R0, R270))
// SIDE OFF
.with(GBlockstate.when(NORTH, false),
GBlockstate.variant(side_off, true, R0, R0))
.with(GBlockstate.when(EAST, false),
GBlockstate.variant(side_off, true, R0, R90))
.with(GBlockstate.when(SOUTH, false),
GBlockstate.variant(side_off, true, R0, R180))
.with(GBlockstate.when(WEST, false),
GBlockstate.variant(side_off, true, R0, R270));
}
}

View File

@@ -1,171 +0,0 @@
package fr.adrien1106.reframed.generator.block;
import fr.adrien1106.reframed.ReFramed;
import fr.adrien1106.reframed.generator.BlockStateProvider;
import fr.adrien1106.reframed.generator.RecipeSetter;
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.util.Identifier;
import java.util.Map;
import static fr.adrien1106.reframed.generator.GBlockstate.variant;
import static fr.adrien1106.reframed.generator.GBlockstate.when;
import static fr.adrien1106.reframed.util.blocks.BlockProperties.EDGE;
import static fr.adrien1106.reframed.util.blocks.BlockProperties.EDGE_FACE;
import static fr.adrien1106.reframed.util.blocks.Edge.*;
import static net.minecraft.data.client.VariantSettings.Rotation.*;
import static net.minecraft.state.property.Properties.LAYERS;
public class HalfLayer implements RecipeSetter, BlockStateProvider {
@Override
public void setRecipe(RecipeExporter exporter, ItemConvertible convertible) {
RecipeProvider.offerStonecuttingRecipe(exporter, RecipeCategory.BUILDING_BLOCKS, convertible, ReFramed.CUBE, 16);
ShapelessRecipeJsonBuilder
.create(RecipeCategory.BUILDING_BLOCKS, convertible, 2)
.input(ReFramed.LAYER)
.criterion(FabricRecipeProvider.hasItem(ReFramed.CUBE), FabricRecipeProvider.conditionsFromItem(ReFramed.CUBE))
.criterion(FabricRecipeProvider.hasItem(convertible), FabricRecipeProvider.conditionsFromItem(convertible))
.offerTo(exporter);
}
@Override
public BlockStateSupplier getMultipart(Block block) {
return getMultipart(block, "half_layer");
}
public static MultipartBlockStateSupplier getMultipart(Block block, String layer) {
Map<Integer, Identifier> layer_model = Map.of(
1, ReFramed.id(layer + "_2_special"),
2, ReFramed.id(layer + "_4_special"),
3, ReFramed.id(layer + "_6_special"),
4, ReFramed.id(layer + "_8_special"),
5, ReFramed.id(layer + "_10_special"),
6, ReFramed.id(layer + "_12_special"),
7, ReFramed.id(layer + "_14_special"),
8, ReFramed.id(layer + "_16_special")
);
Map<Integer, Identifier> layer_side = Map.of(
1, ReFramed.id(layer + "_side_2_special"),
2, ReFramed.id(layer + "_side_4_special"),
3, ReFramed.id(layer + "_side_6_special"),
4, ReFramed.id(layer + "_side_8_special"),
5, ReFramed.id(layer + "_side_10_special"),
6, ReFramed.id(layer + "_side_12_special"),
7, ReFramed.id(layer + "_side_14_special"),
8, ReFramed.id(layer + "_side_16_special")
);
MultipartBlockStateSupplier supplier = MultipartBlockStateSupplier.create(block);
// DOWN
layer_model.forEach((i, model) ->
supplier.with(when(EDGE, DOWN_EAST, EDGE_FACE, 0, LAYERS, i),
variant(model, true, R0, R0))
);
layer_model.forEach((i, model) ->
supplier.with(when(EDGE, DOWN_SOUTH, EDGE_FACE, 0, LAYERS, i),
variant(model, true, R0, R90))
);
layer_model.forEach((i, model) ->
supplier.with(when(EDGE, WEST_DOWN, EDGE_FACE, 1, LAYERS, i),
variant(model, true, R0, R180))
);
layer_model.forEach((i, model) ->
supplier.with(when(EDGE, NORTH_DOWN, EDGE_FACE, 1, LAYERS, i),
variant(model, true, R0, R270))
);
// UP
layer_model.forEach((i, model) ->
supplier.with(when(EDGE, EAST_UP, EDGE_FACE, 1, LAYERS, i),
variant(model, true, R180, R0))
);
layer_model.forEach((i, model) ->
supplier.with(when(EDGE, SOUTH_UP, EDGE_FACE, 1, LAYERS, i),
variant(model, true, R180, R90))
);
layer_model.forEach((i, model) ->
supplier.with(when(EDGE, UP_WEST, EDGE_FACE, 0, LAYERS, i),
variant(model, true, R180, R180))
);
layer_model.forEach((i, model) ->
supplier.with(when(EDGE, UP_NORTH, EDGE_FACE, 0, LAYERS, i),
variant(model, true, R180, R270))
);
// EAST
layer_side.forEach((i, model) ->
supplier.with(when(EDGE, EAST_SOUTH, EDGE_FACE, 0, LAYERS, i),
variant(model, true, R0, R0))
);
layer_side.forEach((i, model) ->
supplier.with(when(EDGE, EAST_UP, EDGE_FACE, 0, LAYERS, i),
variant(model, true, R90, R0))
);
layer_side.forEach((i, model) ->
supplier.with(when(EDGE, NORTH_EAST, EDGE_FACE, 1, LAYERS, i),
variant(model, true, R180, R0))
);
layer_side.forEach((i, model) ->
supplier.with(when(EDGE, DOWN_EAST, EDGE_FACE, 1, LAYERS, i),
variant(model, true, R270, R0))
);
// SOUTH
layer_side.forEach((i, model) ->
supplier.with(when(EDGE, SOUTH_WEST, EDGE_FACE, 0, LAYERS, i),
variant(model, true, R0, R90))
);
layer_side.forEach((i, model) ->
supplier.with(when(EDGE, SOUTH_UP, EDGE_FACE, 0, LAYERS, i),
variant(model, true, R90, R90))
);
layer_side.forEach((i, model) ->
supplier.with(when(EDGE, EAST_SOUTH, EDGE_FACE, 1, LAYERS, i),
variant(model, true, R180, R90))
);
layer_side.forEach((i, model) ->
supplier.with(when(EDGE, DOWN_SOUTH, EDGE_FACE, 1, LAYERS, i),
variant(model, true, R270, R90))
);
// WEST
layer_side.forEach((i, model) ->
supplier.with(when(EDGE, WEST_NORTH, EDGE_FACE, 0, LAYERS, i),
variant(model, true, R0, R180))
);
layer_side.forEach((i, model) ->
supplier.with(when(EDGE, UP_WEST, EDGE_FACE, 1, LAYERS, i),
variant(model, true, R90, R180))
);
layer_side.forEach((i, model) ->
supplier.with(when(EDGE, SOUTH_WEST, EDGE_FACE, 1, LAYERS, i),
variant(model, true, R180, R180))
);
layer_side.forEach((i, model) ->
supplier.with(when(EDGE, WEST_DOWN, EDGE_FACE, 0, LAYERS, i),
variant(model, true, R270, R180))
);
// NORTH
layer_side.forEach((i, model) ->
supplier.with(when(EDGE, NORTH_EAST, EDGE_FACE, 0, LAYERS, i),
variant(model, true, R0, R270))
);
layer_side.forEach((i, model) ->
supplier.with(when(EDGE, UP_NORTH, EDGE_FACE, 1, LAYERS, i),
variant(model, true, R90, R270))
);
layer_side.forEach((i, model) ->
supplier.with(when(EDGE, WEST_NORTH, EDGE_FACE, 1, LAYERS, i),
variant(model, true, R180, R270))
);
layer_side.forEach((i, model) ->
supplier.with(when(EDGE, NORTH_DOWN, EDGE_FACE, 0, LAYERS, i),
variant(model, true, R270, R270))
);
return supplier;
}
}

View File

@@ -1,34 +0,0 @@
package fr.adrien1106.reframed.generator.block;
import fr.adrien1106.reframed.ReFramed;
import fr.adrien1106.reframed.generator.BlockStateProvider;
import fr.adrien1106.reframed.generator.RecipeSetter;
import net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider;
import net.minecraft.block.Block;
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;
public class HalfSlab implements RecipeSetter, BlockStateProvider {
@Override
public void setRecipe(RecipeExporter exporter, ItemConvertible convertible) {
RecipeProvider.offerStonecuttingRecipe(exporter, RecipeCategory.BUILDING_BLOCKS, convertible, ReFramed.CUBE, 4);
ShapelessRecipeJsonBuilder
.create(RecipeCategory.BUILDING_BLOCKS, convertible, 2)
.input(ReFramed.SLAB)
.criterion(FabricRecipeProvider.hasItem(ReFramed.CUBE), FabricRecipeProvider.conditionsFromItem(ReFramed.CUBE))
.criterion(FabricRecipeProvider.hasItem(convertible), FabricRecipeProvider.conditionsFromItem(convertible))
.offerTo(exporter);
}
@Override
public MultipartBlockStateSupplier getMultipart(Block block) {
return Slab.getMultipart(block, "half_slab");
}
}

View File

@@ -1,34 +0,0 @@
package fr.adrien1106.reframed.generator.block;
import fr.adrien1106.reframed.ReFramed;
import fr.adrien1106.reframed.generator.BlockStateProvider;
import fr.adrien1106.reframed.generator.RecipeSetter;
import net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider;
import net.minecraft.block.Block;
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;
public class HalfSlabsSlab implements RecipeSetter, BlockStateProvider {
@Override
public void setRecipe(RecipeExporter exporter, ItemConvertible convertible) {
RecipeProvider.offerStonecuttingRecipe(exporter, RecipeCategory.BUILDING_BLOCKS, convertible, ReFramed.CUBE, 2);
ShapelessRecipeJsonBuilder
.create(RecipeCategory.BUILDING_BLOCKS, convertible, 1)
.input(ReFramed.HALF_SLAB, 2)
.criterion(FabricRecipeProvider.hasItem(ReFramed.CUBE), FabricRecipeProvider.conditionsFromItem(ReFramed.CUBE))
.criterion(FabricRecipeProvider.hasItem(convertible), FabricRecipeProvider.conditionsFromItem(convertible))
.offerTo(exporter);
}
@Override
public MultipartBlockStateSupplier getMultipart(Block block) {
return Slab.getMultipart(block, "half_slabs_slab");
}
}

View File

@@ -1,33 +0,0 @@
package fr.adrien1106.reframed.generator.block;
import fr.adrien1106.reframed.ReFramed;
import fr.adrien1106.reframed.generator.BlockStateProvider;
import fr.adrien1106.reframed.generator.RecipeSetter;
import net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider;
import net.minecraft.block.Block;
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;
public class HalfStairsCubeStair implements RecipeSetter, BlockStateProvider {
@Override
public void setRecipe(RecipeExporter exporter, ItemConvertible convertible) {
RecipeProvider.offerStonecuttingRecipe(exporter, RecipeCategory.BUILDING_BLOCKS, convertible, ReFramed.CUBE);
ShapelessRecipeJsonBuilder
.create(RecipeCategory.BUILDING_BLOCKS, convertible)
.input(ReFramed.SMALL_CUBE)
.input(ReFramed.HALF_STAIR)
.criterion(FabricRecipeProvider.hasItem(ReFramed.CUBE), FabricRecipeProvider.conditionsFromItem(ReFramed.CUBE))
.criterion(FabricRecipeProvider.hasItem(convertible), FabricRecipeProvider.conditionsFromItem(convertible))
.offerTo(exporter);
}
@Override
public MultipartBlockStateSupplier getMultipart(Block block) {
return CornerDouble.getMultipart(block, "half_stairs_cube_stair");
}
}

View File

@@ -1,159 +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.util.blocks.Corner;
import net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider;
import net.minecraft.block.Block;
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.util.Identifier;
import static fr.adrien1106.reframed.util.blocks.BlockProperties.*;
import static net.minecraft.data.client.VariantSettings.Rotation.*;
import static net.minecraft.data.client.VariantSettings.Rotation.R270;
public class HalfStairsStepStair implements RecipeSetter, BlockStateProvider {
@Override
public void setRecipe(RecipeExporter exporter, ItemConvertible convertible) {
RecipeProvider.offerStonecuttingRecipe(exporter, RecipeCategory.BUILDING_BLOCKS, convertible, ReFramed.CUBE);
ShapelessRecipeJsonBuilder
.create(RecipeCategory.BUILDING_BLOCKS, convertible)
.input(ReFramed.SMALL_CUBE)
.input(ReFramed.HALF_STAIR)
.criterion(FabricRecipeProvider.hasItem(ReFramed.CUBE), FabricRecipeProvider.conditionsFromItem(ReFramed.CUBE))
.criterion(FabricRecipeProvider.hasItem(convertible), FabricRecipeProvider.conditionsFromItem(convertible))
.offerTo(exporter);
}
@Override
public MultipartBlockStateSupplier getMultipart(Block block) {
Identifier model_1_id = ReFramed.id("half_stairs_step_stair_1_special");
Identifier side_1_id = ReFramed.id("half_stairs_step_stair_side_1_special");
Identifier model_2_id = ReFramed.id("half_stairs_step_stair_2_special");
Identifier side_2_id = ReFramed.id("half_stairs_step_stair_side_2_special");
return MultipartBlockStateSupplier.create(block)
// BOTTOM
// --- 1 ---
.with(GBlockstate.when(CORNER, Corner.EAST_SOUTH_DOWN, CORNER_FACE, 2, CORNER_FEATURE, 0),
GBlockstate.variant(model_1_id, true, R0, R0))
.with(GBlockstate.when(CORNER, Corner.SOUTH_WEST_DOWN, CORNER_FACE, 2, CORNER_FEATURE, 0),
GBlockstate.variant(model_1_id, true, R0, R90))
.with(GBlockstate.when(CORNER, Corner.WEST_NORTH_DOWN, CORNER_FACE, 2, CORNER_FEATURE, 0),
GBlockstate.variant(model_1_id, true, R0, R180))
.with(GBlockstate.when(CORNER, Corner.NORTH_EAST_DOWN, CORNER_FACE, 2, CORNER_FEATURE, 0),
GBlockstate.variant(model_1_id, true, R0, R270))
// --- 2 ---
.with(GBlockstate.when(CORNER, Corner.EAST_SOUTH_DOWN, CORNER_FACE, 2, CORNER_FEATURE, 1),
GBlockstate.variant(model_2_id, true, R0, R0))
.with(GBlockstate.when(CORNER, Corner.SOUTH_WEST_DOWN, CORNER_FACE, 2, CORNER_FEATURE, 1),
GBlockstate.variant(model_2_id, true, R0, R90))
.with(GBlockstate.when(CORNER, Corner.WEST_NORTH_DOWN, CORNER_FACE, 2, CORNER_FEATURE, 1),
GBlockstate.variant(model_2_id, true, R0, R180))
.with(GBlockstate.when(CORNER, Corner.NORTH_EAST_DOWN, CORNER_FACE, 2, CORNER_FEATURE, 1),
GBlockstate.variant(model_2_id, true, R0, R270))
// TOP
// --- 1 ---
.with(GBlockstate.when(CORNER, Corner.NORTH_EAST_UP, CORNER_FACE, 2, CORNER_FEATURE, 1),
GBlockstate.variant(model_1_id, true, R180, R0))
.with(GBlockstate.when(CORNER, Corner.EAST_SOUTH_UP, CORNER_FACE, 2, CORNER_FEATURE, 1),
GBlockstate.variant(model_1_id, true, R180, R90))
.with(GBlockstate.when(CORNER, Corner.SOUTH_WEST_UP, CORNER_FACE, 2, CORNER_FEATURE, 1),
GBlockstate.variant(model_1_id, true, R180, R180))
.with(GBlockstate.when(CORNER, Corner.WEST_NORTH_UP, CORNER_FACE, 2, CORNER_FEATURE, 1),
GBlockstate.variant(model_1_id, true, R180, R270))
// --- 2 ---
.with(GBlockstate.when(CORNER, Corner.NORTH_EAST_UP, CORNER_FACE, 2, CORNER_FEATURE, 0),
GBlockstate.variant(model_2_id, true, R180, R0))
.with(GBlockstate.when(CORNER, Corner.EAST_SOUTH_UP, CORNER_FACE, 2, CORNER_FEATURE, 0),
GBlockstate.variant(model_2_id, true, R180, R90))
.with(GBlockstate.when(CORNER, Corner.SOUTH_WEST_UP, CORNER_FACE, 2, CORNER_FEATURE, 0),
GBlockstate.variant(model_2_id, true, R180, R180))
.with(GBlockstate.when(CORNER, Corner.WEST_NORTH_UP, CORNER_FACE, 2, CORNER_FEATURE, 0),
GBlockstate.variant(model_2_id, true, R180, R270))
// EAST
// --- 1 ---
.with(GBlockstate.when(CORNER, Corner.EAST_SOUTH_DOWN, CORNER_FACE, 0, CORNER_FEATURE, 0),
GBlockstate.variant(side_1_id, true, R0, R0))
.with(GBlockstate.when(CORNER, Corner.EAST_SOUTH_UP, CORNER_FACE, 0, CORNER_FEATURE, 1),
GBlockstate.variant(side_1_id, true, R90, R0))
.with(GBlockstate.when(CORNER, Corner.NORTH_EAST_UP, CORNER_FACE, 1, CORNER_FEATURE, 0),
GBlockstate.variant(side_1_id, true, R180, R0))
.with(GBlockstate.when(CORNER, Corner.NORTH_EAST_DOWN, CORNER_FACE, 1, CORNER_FEATURE, 1),
GBlockstate.variant(side_1_id, true, R270, R0))
// --- 2 ---
.with(GBlockstate.when(CORNER, Corner.EAST_SOUTH_DOWN, CORNER_FACE, 0, CORNER_FEATURE, 1),
GBlockstate.variant(side_2_id, true, R0, R0))
.with(GBlockstate.when(CORNER, Corner.EAST_SOUTH_UP, CORNER_FACE, 0, CORNER_FEATURE, 0),
GBlockstate.variant(side_2_id, true, R90, R0))
.with(GBlockstate.when(CORNER, Corner.NORTH_EAST_UP, CORNER_FACE, 1, CORNER_FEATURE, 1),
GBlockstate.variant(side_2_id, true, R180, R0))
.with(GBlockstate.when(CORNER, Corner.NORTH_EAST_DOWN, CORNER_FACE, 1, CORNER_FEATURE, 0),
GBlockstate.variant(side_2_id, true, R270, R0))
// SOUTH
// --- 1 ---
.with(GBlockstate.when(CORNER, Corner.SOUTH_WEST_DOWN, CORNER_FACE, 0, CORNER_FEATURE, 0),
GBlockstate.variant(side_1_id, true, R0, R90))
.with(GBlockstate.when(CORNER, Corner.SOUTH_WEST_UP, CORNER_FACE, 0, CORNER_FEATURE, 1),
GBlockstate.variant(side_1_id, true, R90, R90))
.with(GBlockstate.when(CORNER, Corner.EAST_SOUTH_UP, CORNER_FACE, 1, CORNER_FEATURE, 0),
GBlockstate.variant(side_1_id, true, R180, R90))
.with(GBlockstate.when(CORNER, Corner.EAST_SOUTH_DOWN, CORNER_FACE, 1, CORNER_FEATURE, 1),
GBlockstate.variant(side_1_id, true, R270, R90))
// --- 2 ---
.with(GBlockstate.when(CORNER, Corner.SOUTH_WEST_DOWN, CORNER_FACE, 0, CORNER_FEATURE, 1),
GBlockstate.variant(side_2_id, true, R0, R90))
.with(GBlockstate.when(CORNER, Corner.SOUTH_WEST_UP, CORNER_FACE, 0, CORNER_FEATURE, 0),
GBlockstate.variant(side_2_id, true, R90, R90))
.with(GBlockstate.when(CORNER, Corner.EAST_SOUTH_UP, CORNER_FACE, 1, CORNER_FEATURE, 1),
GBlockstate.variant(side_2_id, true, R180, R90))
.with(GBlockstate.when(CORNER, Corner.EAST_SOUTH_DOWN, CORNER_FACE, 1, CORNER_FEATURE, 0),
GBlockstate.variant(side_2_id, true, R270, R90))
// WEST
// --- 1 ---
.with(GBlockstate.when(CORNER, Corner.WEST_NORTH_DOWN, CORNER_FACE, 0, CORNER_FEATURE, 0),
GBlockstate.variant(side_1_id, true, R0, R180))
.with(GBlockstate.when(CORNER, Corner.WEST_NORTH_UP, CORNER_FACE, 0, CORNER_FEATURE, 1),
GBlockstate.variant(side_1_id, true, R90, R180))
.with(GBlockstate.when(CORNER, Corner.SOUTH_WEST_UP, CORNER_FACE, 1, CORNER_FEATURE, 0),
GBlockstate.variant(side_1_id, true, R180, R180))
.with(GBlockstate.when(CORNER, Corner.SOUTH_WEST_DOWN, CORNER_FACE, 1, CORNER_FEATURE, 1),
GBlockstate.variant(side_1_id, true, R270, R180))
// --- 2 ---
.with(GBlockstate.when(CORNER, Corner.WEST_NORTH_DOWN, CORNER_FACE, 0, CORNER_FEATURE, 1),
GBlockstate.variant(side_2_id, true, R0, R180))
.with(GBlockstate.when(CORNER, Corner.WEST_NORTH_UP, CORNER_FACE, 0, CORNER_FEATURE, 0),
GBlockstate.variant(side_2_id, true, R90, R180))
.with(GBlockstate.when(CORNER, Corner.SOUTH_WEST_UP, CORNER_FACE, 1, CORNER_FEATURE, 1),
GBlockstate.variant(side_2_id, true, R180, R180))
.with(GBlockstate.when(CORNER, Corner.SOUTH_WEST_DOWN, CORNER_FACE, 1, CORNER_FEATURE, 0),
GBlockstate.variant(side_2_id, true, R270, R180))
// NORTH
// --- 1 ---
.with(GBlockstate.when(CORNER, Corner.NORTH_EAST_DOWN, CORNER_FACE, 0, CORNER_FEATURE, 0),
GBlockstate.variant(side_1_id, true, R0, R270))
.with(GBlockstate.when(CORNER, Corner.NORTH_EAST_UP, CORNER_FACE, 0, CORNER_FEATURE, 1),
GBlockstate.variant(side_1_id, true, R90, R270))
.with(GBlockstate.when(CORNER, Corner.WEST_NORTH_UP, CORNER_FACE, 1, CORNER_FEATURE, 0),
GBlockstate.variant(side_1_id, true, R180, R270))
.with(GBlockstate.when(CORNER, Corner.WEST_NORTH_DOWN, CORNER_FACE, 1, CORNER_FEATURE, 1),
GBlockstate.variant(side_1_id, true, R270, R270))
// --- 2 ---
.with(GBlockstate.when(CORNER, Corner.NORTH_EAST_DOWN, CORNER_FACE, 0, CORNER_FEATURE, 1),
GBlockstate.variant(side_2_id, true, R0, R270))
.with(GBlockstate.when(CORNER, Corner.NORTH_EAST_UP, CORNER_FACE, 0, CORNER_FEATURE, 0),
GBlockstate.variant(side_2_id, true, R90, R270))
.with(GBlockstate.when(CORNER, Corner.WEST_NORTH_UP, CORNER_FACE, 1, CORNER_FEATURE, 1),
GBlockstate.variant(side_2_id, true, R180, R270))
.with(GBlockstate.when(CORNER, Corner.WEST_NORTH_DOWN, CORNER_FACE, 1, CORNER_FEATURE, 0),
GBlockstate.variant(side_2_id, true, R270, R270))
;
}
}

View File

@@ -1,76 +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.ShapedRecipeJsonBuilder;
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.data.client.VariantSettings.Rotation.*;
import static net.minecraft.state.property.Properties.*;
public class Pane implements RecipeSetter, TagGetter, BlockStateProvider {
@Override
public void setRecipe(RecipeExporter exporter, ItemConvertible convertible) {
RecipeProvider.offerStonecuttingRecipe(exporter, RecipeCategory.BUILDING_BLOCKS, convertible, ReFramed.CUBE, 4);
ShapedRecipeJsonBuilder
.create(RecipeCategory.BUILDING_BLOCKS, convertible, 32)
.pattern("III")
.pattern("I I")
.pattern("III")
.input('I', ReFramed.CUBE)
.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
pane_side = ReFramed.id("pane_side_special"),
pane_side_alt = ReFramed.id("pane_side_alt_special"),
pane_noside = ReFramed.id("pane_noside_special"),
pane_noside_alt = ReFramed.id("pane_noside_alt_special");
return MultipartBlockStateSupplier.create(block)
// PILLAR CORE
.with(GBlockstate.variant(ReFramed.id("pane_post_special"), true, R0, R0))
// SIDE
.with(GBlockstate.when(NORTH, true),
GBlockstate.variant(pane_side, true, R0, R0))
.with(GBlockstate.when(EAST, true),
GBlockstate.variant(pane_side, true, R0, R90))
.with(GBlockstate.when(SOUTH, true),
GBlockstate.variant(pane_side_alt, true, R0, R0))
.with(GBlockstate.when(WEST, true),
GBlockstate.variant(pane_side_alt, true, R0, R90))
// NOSIDE
.with(GBlockstate.when(NORTH, false),
GBlockstate.variant(pane_noside, true, R0, R0))
.with(GBlockstate.when(EAST, false),
GBlockstate.variant(pane_noside_alt, true, R0, R0))
.with(GBlockstate.when(SOUTH, false),
GBlockstate.variant(pane_noside_alt, true, R0, R90))
.with(GBlockstate.when(WEST, false),
GBlockstate.variant(pane_noside, true, R0, R270));
}
}

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

@@ -1,50 +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 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.ShapedRecipeJsonBuilder;
import net.minecraft.item.ItemConvertible;
import net.minecraft.recipe.book.RecipeCategory;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.Direction;
import static net.minecraft.data.client.VariantSettings.Rotation.R0;
import static net.minecraft.data.client.VariantSettings.Rotation.R90;
import static net.minecraft.state.property.Properties.AXIS;
public class Post implements RecipeSetter, BlockStateProvider {
@Override
public void setRecipe(RecipeExporter exporter, ItemConvertible convertible) {
RecipeProvider.offerStonecuttingRecipe(exporter, RecipeCategory.BUILDING_BLOCKS, convertible, ReFramed.CUBE, 6);
ShapedRecipeJsonBuilder
.create(RecipeCategory.BUILDING_BLOCKS, convertible, 12)
.pattern("I")
.pattern("I")
.pattern("I")
.input('I', ReFramed.CUBE)
.criterion(FabricRecipeProvider.hasItem(ReFramed.CUBE), FabricRecipeProvider.conditionsFromItem(ReFramed.CUBE))
.criterion(FabricRecipeProvider.hasItem(convertible), FabricRecipeProvider.conditionsFromItem(convertible))
.offerTo(exporter);
}
@Override
public BlockStateSupplier getMultipart(Block block) {
Identifier model_id = ReFramed.id("post_special");
return MultipartBlockStateSupplier.create(block)
.with(GBlockstate.when(AXIS, Direction.Axis.X),
GBlockstate.variant(model_id, true, R90, R90))
.with(GBlockstate.when(AXIS, Direction.Axis.Y),
GBlockstate.variant(model_id, true, R0, R0))
.with(GBlockstate.when(AXIS, Direction.Axis.Z),
GBlockstate.variant(model_id, true, R90, R0));
}
}

View File

@@ -1,69 +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.data.client.VariantSettings.Rotation.*;
import static net.minecraft.state.property.Properties.*;
public class PostFence implements RecipeSetter, TagGetter, BlockStateProvider {
@Override
public void setRecipe(RecipeExporter exporter, ItemConvertible convertible) {
RecipeProvider.offerStonecuttingRecipe(exporter, RecipeCategory.BUILDING_BLOCKS, convertible, ReFramed.FENCE, 1);
ShapelessRecipeJsonBuilder
.create(RecipeCategory.BUILDING_BLOCKS, convertible, 2)
.input(ReFramed.FENCE, 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.FENCES, BlockTags.WOODEN_FENCES);
}
@Override
public BlockStateSupplier getMultipart(Block block) {
Identifier side_on = ReFramed.id("post_fence_side_special");
Identifier side_off = ReFramed.id("fence_side_off_special");
return MultipartBlockStateSupplier.create(block)
.with(GBlockstate.variant(ReFramed.id("fence_core_special"), true, R0, R0))
// SIDE ON
.with(GBlockstate.when(NORTH, true),
GBlockstate.variant(side_on, true, R0, R0))
.with(GBlockstate.when(EAST, true),
GBlockstate.variant(side_on, true, R0, R90))
.with(GBlockstate.when(SOUTH, true),
GBlockstate.variant(side_on, true, R0, R180))
.with(GBlockstate.when(WEST, true),
GBlockstate.variant(side_on, true, R0, R270))
// SIDE OFF
.with(GBlockstate.when(NORTH, false),
GBlockstate.variant(side_off, true, R0, R0))
.with(GBlockstate.when(EAST, false),
GBlockstate.variant(side_off, true, R0, R90))
.with(GBlockstate.when(SOUTH, false),
GBlockstate.variant(side_off, true, R0, R180))
.with(GBlockstate.when(WEST, false),
GBlockstate.variant(side_off, true, R0, R270));
}
}

View File

@@ -34,11 +34,7 @@ public class Slab implements RecipeSetter, BlockStateProvider {
@Override
public MultipartBlockStateSupplier getMultipart(Block block) {
return getMultipart(block, "slab");
}
public static MultipartBlockStateSupplier getMultipart(Block block, String model_name) {
Identifier model_id = ReFramed.id(model_name + "_special");
Identifier model_id = ReFramed.id("slab_special");
return MultipartBlockStateSupplier.create(block)
.with(GBlockstate.when(FACING, Direction.DOWN),
GBlockstate.variant(model_id, true, R0, R0))
@@ -53,6 +49,4 @@ public class Slab implements RecipeSetter, BlockStateProvider {
.with(GBlockstate.when(FACING, Direction.EAST),
GBlockstate.variant(model_id, true, R90, R270));
}
}

View File

@@ -1,93 +0,0 @@
package fr.adrien1106.reframed.generator.block;
import fr.adrien1106.reframed.ReFramed;
import fr.adrien1106.reframed.generator.BlockStateProvider;
import fr.adrien1106.reframed.generator.RecipeSetter;
import net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider;
import net.minecraft.block.Block;
import net.minecraft.data.client.BlockStateSupplier;
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.util.Identifier;
import static fr.adrien1106.reframed.generator.GBlockstate.variant;
import static fr.adrien1106.reframed.generator.GBlockstate.when;
import static fr.adrien1106.reframed.util.blocks.BlockProperties.EDGE;
import static fr.adrien1106.reframed.util.blocks.BlockProperties.EDGE_FACE;
import static fr.adrien1106.reframed.util.blocks.Edge.*;
import static net.minecraft.data.client.VariantSettings.Rotation.*;
import static net.minecraft.data.client.When.anyOf;
public class SlabsHalfLayer implements RecipeSetter, BlockStateProvider {
@Override
public void setRecipe(RecipeExporter exporter, ItemConvertible convertible) {
RecipeProvider.offerStonecuttingRecipe(exporter, RecipeCategory.BUILDING_BLOCKS, convertible, ReFramed.CUBE, 2);
ShapelessRecipeJsonBuilder
.create(RecipeCategory.BUILDING_BLOCKS, convertible)
.input(ReFramed.HALF_LAYER)
.input(ReFramed.SLAB)
.criterion(FabricRecipeProvider.hasItem(ReFramed.CUBE), FabricRecipeProvider.conditionsFromItem(ReFramed.CUBE))
.criterion(FabricRecipeProvider.hasItem(convertible), FabricRecipeProvider.conditionsFromItem(convertible))
.offerTo(exporter);
}
@Override
public BlockStateSupplier getMultipart(Block block) {
Identifier slab_model = ReFramed.id("slab_special");
return HalfLayer.getMultipart(block, "second_half_layer")
.with(
anyOf(
when(EDGE, DOWN_EAST, EDGE_FACE, 0),
when(EDGE, DOWN_SOUTH, EDGE_FACE, 0),
when(EDGE, WEST_DOWN, EDGE_FACE, 1),
when(EDGE, NORTH_DOWN, EDGE_FACE, 1)
),
variant(slab_model, true, R0, R0))
.with(
anyOf(
when(EDGE, EAST_SOUTH, EDGE_FACE, 1),
when(EDGE, DOWN_SOUTH, EDGE_FACE, 1),
when(EDGE, SOUTH_WEST, EDGE_FACE, 0),
when(EDGE, SOUTH_UP, EDGE_FACE, 0)
),
variant(slab_model, true, R90, R0))
.with(
anyOf(
when(EDGE, UP_WEST, EDGE_FACE, 0),
when(EDGE, UP_NORTH, EDGE_FACE, 0),
when(EDGE, EAST_UP, EDGE_FACE, 1),
when(EDGE, SOUTH_UP, EDGE_FACE, 1)
),
variant(slab_model, true, R180, R0))
.with(
anyOf(
when(EDGE, WEST_NORTH, EDGE_FACE, 1),
when(EDGE, UP_NORTH, EDGE_FACE, 1),
when(EDGE, NORTH_EAST, EDGE_FACE, 0),
when(EDGE, NORTH_DOWN, EDGE_FACE, 0)
),
variant(slab_model, true, R270, R0))
.with(
anyOf(
when(EDGE, SOUTH_WEST, EDGE_FACE, 1),
when(EDGE, UP_WEST, EDGE_FACE, 1),
when(EDGE, WEST_NORTH, EDGE_FACE, 0),
when(EDGE, WEST_DOWN, EDGE_FACE, 0)
),
variant(slab_model, true, R90, R90))
.with(
anyOf(
when(EDGE, NORTH_EAST, EDGE_FACE, 1),
when(EDGE, DOWN_EAST, EDGE_FACE, 1),
when(EDGE, EAST_SOUTH, EDGE_FACE, 0),
when(EDGE, EAST_UP, EDGE_FACE, 0)
),
variant(slab_model, true, R90, R270))
;
}
}

View File

@@ -1,33 +0,0 @@
package fr.adrien1106.reframed.generator.block;
import fr.adrien1106.reframed.ReFramed;
import fr.adrien1106.reframed.generator.BlockStateProvider;
import fr.adrien1106.reframed.generator.RecipeSetter;
import net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider;
import net.minecraft.block.Block;
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;
public class SlabsInnerStair implements RecipeSetter, BlockStateProvider {
@Override
public void setRecipe(RecipeExporter exporter, ItemConvertible convertible) {
RecipeProvider.offerStonecuttingRecipe(exporter, RecipeCategory.BUILDING_BLOCKS, convertible, ReFramed.CUBE);
ShapelessRecipeJsonBuilder
.create(RecipeCategory.BUILDING_BLOCKS, convertible)
.input(ReFramed.HALF_STAIR)
.input(ReFramed.SLAB)
.criterion(FabricRecipeProvider.hasItem(ReFramed.CUBE), FabricRecipeProvider.conditionsFromItem(ReFramed.CUBE))
.criterion(FabricRecipeProvider.hasItem(convertible), FabricRecipeProvider.conditionsFromItem(convertible))
.offerTo(exporter);
}
@Override
public MultipartBlockStateSupplier getMultipart(Block block) {
return CornerDouble.getMultipart(block, "slabs_inner_stair");
}
}

View File

@@ -1,58 +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 net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider;
import net.minecraft.block.Block;
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.util.Identifier;
import net.minecraft.util.math.Direction;
import static fr.adrien1106.reframed.util.blocks.BlockProperties.HALF_LAYERS;
import static net.minecraft.data.client.VariantSettings.Rotation.*;
import static net.minecraft.state.property.Properties.FACING;
public class SlabsLayer implements RecipeSetter, BlockStateProvider {
@Override
public void setRecipe(RecipeExporter exporter, ItemConvertible convertible) {
RecipeProvider.offerStonecuttingRecipe(exporter, RecipeCategory.BUILDING_BLOCKS, convertible, ReFramed.CUBE, 2);
ShapelessRecipeJsonBuilder
.create(RecipeCategory.BUILDING_BLOCKS, convertible, 1)
.input(ReFramed.SLAB)
.input(ReFramed.LAYER)
.criterion(FabricRecipeProvider.hasItem(ReFramed.CUBE), FabricRecipeProvider.conditionsFromItem(ReFramed.CUBE))
.criterion(FabricRecipeProvider.hasItem(convertible), FabricRecipeProvider.conditionsFromItem(convertible))
.offerTo(exporter);
}
@Override
public MultipartBlockStateSupplier getMultipart(Block block) {
String model_pattern = "slabs_layer_x_special";
MultipartBlockStateSupplier supplier = MultipartBlockStateSupplier.create(block);
for (int i = 1; i <= 4; i++) {
Identifier model = ReFramed.id(model_pattern.replace("x", i * 2 + ""));
supplier
.with(GBlockstate.when(FACING, Direction.DOWN, HALF_LAYERS, i),
GBlockstate.variant(model, true, R0, R0))
.with(GBlockstate.when(FACING, Direction.SOUTH, HALF_LAYERS, i),
GBlockstate.variant(model, true, R90, R0))
.with(GBlockstate.when(FACING, Direction.UP, HALF_LAYERS, i),
GBlockstate.variant(model, true, R180, R0))
.with(GBlockstate.when(FACING, Direction.NORTH, HALF_LAYERS, i),
GBlockstate.variant(model, true, R270, R0))
.with(GBlockstate.when(FACING, Direction.WEST, HALF_LAYERS, i),
GBlockstate.variant(model, true, R90, R90))
.with(GBlockstate.when(FACING, Direction.EAST, HALF_LAYERS, i),
GBlockstate.variant(model, true, R90, R270));
}
return supplier;
}
}

View File

@@ -1,33 +0,0 @@
package fr.adrien1106.reframed.generator.block;
import fr.adrien1106.reframed.ReFramed;
import fr.adrien1106.reframed.generator.BlockStateProvider;
import fr.adrien1106.reframed.generator.RecipeSetter;
import net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider;
import net.minecraft.block.Block;
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;
public class SlabsOuterStair implements RecipeSetter, BlockStateProvider {
@Override
public void setRecipe(RecipeExporter exporter, ItemConvertible convertible) {
RecipeProvider.offerStonecuttingRecipe(exporter, RecipeCategory.BUILDING_BLOCKS, convertible, ReFramed.CUBE);
ShapelessRecipeJsonBuilder
.create(RecipeCategory.BUILDING_BLOCKS, convertible)
.input(ReFramed.SMALL_CUBE)
.input(ReFramed.SLAB)
.criterion(FabricRecipeProvider.hasItem(ReFramed.CUBE), FabricRecipeProvider.conditionsFromItem(ReFramed.CUBE))
.criterion(FabricRecipeProvider.hasItem(convertible), FabricRecipeProvider.conditionsFromItem(convertible))
.offerTo(exporter);
}
@Override
public MultipartBlockStateSupplier getMultipart(Block block) {
return CornerDouble.getMultipart(block, "slabs_outer_stair");
}
}

View File

@@ -1,97 +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.util.blocks.Edge;
import net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider;
import net.minecraft.block.Block;
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.util.Identifier;
import static fr.adrien1106.reframed.util.blocks.BlockProperties.EDGE;
import static fr.adrien1106.reframed.util.blocks.BlockProperties.EDGE_FACE;
import static net.minecraft.data.client.VariantSettings.Rotation.*;
public class SlabsStair implements RecipeSetter, BlockStateProvider {
@Override
public void setRecipe(RecipeExporter exporter, ItemConvertible convertible) {
RecipeProvider.offerStonecuttingRecipe(exporter, RecipeCategory.BUILDING_BLOCKS, convertible, ReFramed.CUBE);
ShapelessRecipeJsonBuilder
.create(RecipeCategory.BUILDING_BLOCKS, convertible)
.input(ReFramed.STEP)
.input(ReFramed.SLAB)
.criterion(FabricRecipeProvider.hasItem(ReFramed.CUBE), FabricRecipeProvider.conditionsFromItem(ReFramed.CUBE))
.criterion(FabricRecipeProvider.hasItem(convertible), FabricRecipeProvider.conditionsFromItem(convertible))
.offerTo(exporter);
}
@Override
public MultipartBlockStateSupplier getMultipart(Block block) {
Identifier model_id = ReFramed.id("slabs_stair_special");
Identifier side_id = ReFramed.id("slabs_stair_side_special");
return MultipartBlockStateSupplier.create(block)
// BOTTOM
.with(GBlockstate.when(EDGE, Edge.DOWN_EAST, EDGE_FACE, 0),
GBlockstate.variant(model_id, true, R0, R0))
.with(GBlockstate.when(EDGE, Edge.DOWN_SOUTH, EDGE_FACE, 0),
GBlockstate.variant(model_id, true, R0, R90))
.with(GBlockstate.when(EDGE, Edge.WEST_DOWN, EDGE_FACE, 1),
GBlockstate.variant(model_id, true, R0, R180))
.with(GBlockstate.when(EDGE, Edge.NORTH_DOWN, EDGE_FACE, 1),
GBlockstate.variant(model_id, true, R0, R270))
// TOP
.with(GBlockstate.when(EDGE, Edge.EAST_UP, EDGE_FACE, 1),
GBlockstate.variant(model_id, true, R180, R0))
.with(GBlockstate.when(EDGE, Edge.SOUTH_UP, EDGE_FACE, 1),
GBlockstate.variant(model_id, true, R180, R90))
.with(GBlockstate.when(EDGE, Edge.UP_WEST, EDGE_FACE, 0),
GBlockstate.variant(model_id, true, R180, R180))
.with(GBlockstate.when(EDGE, Edge.UP_NORTH, EDGE_FACE, 0),
GBlockstate.variant(model_id, true, R180, R270))
// EAST
.with(GBlockstate.when(EDGE, Edge.EAST_SOUTH, EDGE_FACE, 0),
GBlockstate.variant(side_id, true, R0, R0))
.with(GBlockstate.when(EDGE, Edge.EAST_UP, EDGE_FACE, 0),
GBlockstate.variant(side_id, true, R90, R0))
.with(GBlockstate.when(EDGE, Edge.NORTH_EAST, EDGE_FACE, 1),
GBlockstate.variant(side_id, true, R180, R0))
.with(GBlockstate.when(EDGE, Edge.DOWN_EAST, EDGE_FACE, 1),
GBlockstate.variant(side_id, true, R270, R0))
// SOUTH
.with(GBlockstate.when(EDGE, Edge.SOUTH_WEST, EDGE_FACE, 0),
GBlockstate.variant(side_id, true, R0, R90))
.with(GBlockstate.when(EDGE, Edge.SOUTH_UP, EDGE_FACE, 0),
GBlockstate.variant(side_id, true, R90, R90))
.with(GBlockstate.when(EDGE, Edge.EAST_SOUTH, EDGE_FACE, 1),
GBlockstate.variant(side_id, true, R180, R90))
.with(GBlockstate.when(EDGE, Edge.DOWN_SOUTH, EDGE_FACE, 1),
GBlockstate.variant(side_id, true, R270, R90))
// WEST
.with(GBlockstate.when(EDGE, Edge.WEST_NORTH, EDGE_FACE, 0),
GBlockstate.variant(side_id, true, R0, R180))
.with(GBlockstate.when(EDGE, Edge.UP_WEST, EDGE_FACE, 1),
GBlockstate.variant(side_id, true, R90, R180))
.with(GBlockstate.when(EDGE, Edge.SOUTH_WEST, EDGE_FACE, 1),
GBlockstate.variant(side_id, true, R180, R180))
.with(GBlockstate.when(EDGE, Edge.WEST_DOWN, EDGE_FACE, 0),
GBlockstate.variant(side_id, true, R270, R180))
// NORTH
.with(GBlockstate.when(EDGE, Edge.NORTH_EAST, EDGE_FACE, 0),
GBlockstate.variant(side_id, true, R0, R270))
.with(GBlockstate.when(EDGE, Edge.UP_NORTH, EDGE_FACE, 1),
GBlockstate.variant(side_id, true, R90, R270))
.with(GBlockstate.when(EDGE, Edge.WEST_NORTH, EDGE_FACE, 1),
GBlockstate.variant(side_id, true, R180, R270))
.with(GBlockstate.when(EDGE, Edge.NORTH_DOWN, EDGE_FACE, 0),
GBlockstate.variant(side_id, true, R270, R270))
;
}
}

View File

@@ -2,15 +2,23 @@ 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 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.util.Identifier;
import static fr.adrien1106.reframed.util.blocks.BlockProperties.EDGE;
import static fr.adrien1106.reframed.util.blocks.Edge.*;
import static fr.adrien1106.reframed.util.blocks.Edge.SOUTH_UP;
import static net.minecraft.data.client.VariantSettings.Rotation.*;
public class SmallCubesStep implements RecipeSetter, BlockStateProvider {
@@ -27,6 +35,35 @@ public class SmallCubesStep implements RecipeSetter, BlockStateProvider {
@Override
public BlockStateSupplier getMultipart(Block block) {
return Step.getMultipart(block, "small_cubes_step", "small_cubes_step_reverse");
Identifier model_id = ReFramed.id("small_cubes_step_special");
Identifier reverse_model_id = ReFramed.id("small_cubes_step_reverse_special");
return MultipartBlockStateSupplier.create(block)
/* X AXIS */
.with(GBlockstate.when(EDGE, DOWN_EAST),
GBlockstate.variant(model_id, true, R0, R0))
.with(GBlockstate.when(EDGE, EAST_UP),
GBlockstate.variant(reverse_model_id, true, R180, R0))
.with(GBlockstate.when(EDGE, UP_WEST),
GBlockstate.variant(model_id, true, R180, R180))
.with(GBlockstate.when(EDGE, WEST_DOWN),
GBlockstate.variant(reverse_model_id, true, R0, R180))
/* Y AXIS */
.with(GBlockstate.when(EDGE, EAST_SOUTH),
GBlockstate.variant(model_id, true, R90, R0))
.with(GBlockstate.when(EDGE, SOUTH_WEST),
GBlockstate.variant(model_id, true, R90, R90))
.with(GBlockstate.when(EDGE, WEST_NORTH),
GBlockstate.variant(model_id, true, R90, R180))
.with(GBlockstate.when(EDGE, NORTH_EAST),
GBlockstate.variant(model_id, true, R90, R270))
/* Z AXIS */
.with(GBlockstate.when(EDGE, DOWN_SOUTH),
GBlockstate.variant(reverse_model_id, true, R0, R90))
.with(GBlockstate.when(EDGE, NORTH_DOWN),
GBlockstate.variant(model_id, true, R0, R270))
.with(GBlockstate.when(EDGE, UP_NORTH),
GBlockstate.variant(reverse_model_id, true, R180, R270))
.with(GBlockstate.when(EDGE, SOUTH_UP),
GBlockstate.variant(model_id, true, R180, R90));
}
}

View File

@@ -36,26 +36,17 @@ public class Step implements RecipeSetter, BlockStateProvider {
@Override
public BlockStateSupplier getMultipart(Block block) {
return getMultipart(block, "step");
}
public static BlockStateSupplier getMultipart(Block block, String model_name) {
return getMultipart(block, model_name, model_name);
}
public static BlockStateSupplier getMultipart(Block block, String model_name, String reverse_model_name) {
Identifier model_id = ReFramed.id(model_name + "_special");
Identifier reverse_model_id = ReFramed.id(reverse_model_name + "_special");
Identifier model_id = ReFramed.id("step_special");
return MultipartBlockStateSupplier.create(block)
/* X AXIS */
.with(GBlockstate.when(EDGE, DOWN_EAST),
GBlockstate.variant(model_id, true, R0, R0))
.with(GBlockstate.when(EDGE, EAST_UP),
GBlockstate.variant(reverse_model_id, true, R180, R0))
GBlockstate.variant(model_id, true, R180, R0))
.with(GBlockstate.when(EDGE, UP_WEST),
GBlockstate.variant(model_id, true, R180, R180))
.with(GBlockstate.when(EDGE, WEST_DOWN),
GBlockstate.variant(reverse_model_id, true, R0, R180))
GBlockstate.variant(model_id, true, R0, R180))
/* Y AXIS */
.with(GBlockstate.when(EDGE, EAST_SOUTH),
GBlockstate.variant(model_id, true, R90, R0))
@@ -67,11 +58,11 @@ public class Step implements RecipeSetter, BlockStateProvider {
GBlockstate.variant(model_id, true, R90, R270))
/* Z AXIS */
.with(GBlockstate.when(EDGE, DOWN_SOUTH),
GBlockstate.variant(reverse_model_id, true, R0, R90))
GBlockstate.variant(model_id, true, R0, R90))
.with(GBlockstate.when(EDGE, NORTH_DOWN),
GBlockstate.variant(model_id, true, R0, R270))
.with(GBlockstate.when(EDGE, UP_NORTH),
GBlockstate.variant(reverse_model_id, true, R180, R270))
GBlockstate.variant(model_id, true, R180, R270))
.with(GBlockstate.when(EDGE, SOUTH_UP),
GBlockstate.variant(model_id, true, R180, R90));
}

View File

@@ -1,34 +0,0 @@
package fr.adrien1106.reframed.generator.block;
import fr.adrien1106.reframed.ReFramed;
import fr.adrien1106.reframed.generator.BlockStateProvider;
import fr.adrien1106.reframed.generator.RecipeSetter;
import net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider;
import net.minecraft.block.Block;
import net.minecraft.data.client.BlockStateSupplier;
import net.minecraft.data.server.recipe.RecipeExporter;
import net.minecraft.data.server.recipe.RecipeProvider;
import net.minecraft.data.server.recipe.ShapedRecipeJsonBuilder;
import net.minecraft.item.ItemConvertible;
import net.minecraft.recipe.book.RecipeCategory;
public class StepsCross implements RecipeSetter, BlockStateProvider {
@Override
public void setRecipe(RecipeExporter exporter, ItemConvertible convertible) {
RecipeProvider.offerStonecuttingRecipe(exporter, RecipeCategory.BUILDING_BLOCKS, convertible, ReFramed.CUBE, 2);
ShapedRecipeJsonBuilder
.create(RecipeCategory.BUILDING_BLOCKS, convertible, 8)
.pattern(" I")
.pattern("I ")
.input('I', ReFramed.STEP)
.criterion(FabricRecipeProvider.hasItem(ReFramed.CUBE), FabricRecipeProvider.conditionsFromItem(ReFramed.CUBE))
.criterion(FabricRecipeProvider.hasItem(convertible), FabricRecipeProvider.conditionsFromItem(convertible))
.offerTo(exporter);
}
@Override
public BlockStateSupplier getMultipart(Block block) {
return Step.getMultipart(block, "steps_cross");
}
}

View File

@@ -1,69 +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 net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider;
import net.minecraft.block.Block;
import net.minecraft.data.client.BlockStateSupplier;
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.util.Identifier;
import static fr.adrien1106.reframed.util.blocks.BlockProperties.EDGE;
import static fr.adrien1106.reframed.util.blocks.Edge.*;
import static net.minecraft.data.client.VariantSettings.Rotation.*;
public class StepsHalfLayer implements RecipeSetter, BlockStateProvider {
@Override
public void setRecipe(RecipeExporter exporter, ItemConvertible convertible) {
RecipeProvider.offerStonecuttingRecipe(exporter, RecipeCategory.BUILDING_BLOCKS, convertible, ReFramed.CUBE, 4);
ShapelessRecipeJsonBuilder
.create(RecipeCategory.BUILDING_BLOCKS, convertible)
.input(ReFramed.HALF_LAYER)
.input(ReFramed.STEP)
.criterion(FabricRecipeProvider.hasItem(ReFramed.CUBE), FabricRecipeProvider.conditionsFromItem(ReFramed.CUBE))
.criterion(FabricRecipeProvider.hasItem(convertible), FabricRecipeProvider.conditionsFromItem(convertible))
.offerTo(exporter);
}
@Override
public BlockStateSupplier getMultipart(Block block) {
Identifier step_model = ReFramed.id("step_special");
return HalfLayer.getMultipart(block, "second_half_layer")
/* X AXIS */
.with(GBlockstate.when(EDGE, DOWN_EAST),
GBlockstate.variant(step_model, true, R0, R0))
.with(GBlockstate.when(EDGE, EAST_UP),
GBlockstate.variant(step_model, true, R180, R0))
.with(GBlockstate.when(EDGE, UP_WEST),
GBlockstate.variant(step_model, true, R180, R180))
.with(GBlockstate.when(EDGE, WEST_DOWN),
GBlockstate.variant(step_model, true, R0, R180))
/* Y AXIS */
.with(GBlockstate.when(EDGE, EAST_SOUTH),
GBlockstate.variant(step_model, true, R90, R0))
.with(GBlockstate.when(EDGE, SOUTH_WEST),
GBlockstate.variant(step_model, true, R90, R90))
.with(GBlockstate.when(EDGE, WEST_NORTH),
GBlockstate.variant(step_model, true, R90, R180))
.with(GBlockstate.when(EDGE, NORTH_EAST),
GBlockstate.variant(step_model, true, R90, R270))
/* Z AXIS */
.with(GBlockstate.when(EDGE, DOWN_SOUTH),
GBlockstate.variant(step_model, true, R0, R90))
.with(GBlockstate.when(EDGE, NORTH_DOWN),
GBlockstate.variant(step_model, true, R0, R270))
.with(GBlockstate.when(EDGE, UP_NORTH),
GBlockstate.variant(step_model, true, R180, R270))
.with(GBlockstate.when(EDGE, SOUTH_UP),
GBlockstate.variant(step_model, true, R180, R90))
;
}
}

View File

@@ -9,7 +9,7 @@ import net.minecraft.block.Block;
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.ShapedRecipeJsonBuilder;
import net.minecraft.data.server.recipe.ShapelessRecipeJsonBuilder;
import net.minecraft.item.ItemConvertible;
import net.minecraft.recipe.book.RecipeCategory;
import net.minecraft.util.Identifier;
@@ -25,10 +25,9 @@ public class StepsSlab implements RecipeSetter, BlockStateProvider {
@Override
public void setRecipe(RecipeExporter exporter, ItemConvertible convertible) {
RecipeProvider.offerStonecuttingRecipe(exporter, RecipeCategory.BUILDING_BLOCKS, convertible, ReFramed.CUBE, 2);
ShapedRecipeJsonBuilder
ShapelessRecipeJsonBuilder
.create(RecipeCategory.BUILDING_BLOCKS, convertible)
.pattern("II")
.input('I', ReFramed.STEP)
.input(ReFramed.STEP, 2)
.criterion(FabricRecipeProvider.hasItem(ReFramed.CUBE), FabricRecipeProvider.conditionsFromItem(ReFramed.CUBE))
.criterion(FabricRecipeProvider.hasItem(convertible), FabricRecipeProvider.conditionsFromItem(convertible))
.offerTo(exporter);

View File

@@ -1,56 +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 net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider;
import net.minecraft.block.Block;
import net.minecraft.block.enums.BlockHalf;
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.ShapedRecipeJsonBuilder;
import net.minecraft.item.ItemConvertible;
import net.minecraft.recipe.book.RecipeCategory;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.Direction;
import static net.minecraft.data.client.VariantSettings.Rotation.*;
import static net.minecraft.state.property.Properties.*;
public class Trapdoor implements RecipeSetter, BlockStateProvider {
@Override
public void setRecipe(RecipeExporter exporter, ItemConvertible convertible) {
RecipeProvider.offerStonecuttingRecipe(exporter, RecipeCategory.BUILDING_BLOCKS, convertible, ReFramed.CUBE, 2);
ShapedRecipeJsonBuilder
.create(RecipeCategory.BUILDING_BLOCKS, convertible, 2)
.pattern(" I")
.pattern("III")
.pattern("II ")
.input('I', ReFramed.CUBE)
.criterion(FabricRecipeProvider.hasItem(ReFramed.CUBE), FabricRecipeProvider.conditionsFromItem(ReFramed.CUBE))
.criterion(FabricRecipeProvider.hasItem(convertible), FabricRecipeProvider.conditionsFromItem(convertible))
.offerTo(exporter);
}
@Override
public BlockStateSupplier getMultipart(Block block) {
Identifier open = ReFramed.id("trapdoor_open_special");
return MultipartBlockStateSupplier.create(block)
.with(GBlockstate.when(OPEN, false, BLOCK_HALF, BlockHalf.BOTTOM),
GBlockstate.variant(ReFramed.id("trapdoor_bottom_special"), true, R0, R0))
.with(GBlockstate.when(OPEN, false, BLOCK_HALF, BlockHalf.TOP),
GBlockstate.variant(ReFramed.id("trapdoor_top_special"), true, R0, R0))
.with(GBlockstate.when(OPEN, true, HORIZONTAL_FACING, Direction.NORTH),
GBlockstate.variant(open, true, R0, R0))
.with(GBlockstate.when(OPEN, true, HORIZONTAL_FACING, Direction.EAST),
GBlockstate.variant(open, true, R0, R90))
.with(GBlockstate.when(OPEN, true, HORIZONTAL_FACING, Direction.SOUTH),
GBlockstate.variant(open, true, R0, R180))
.with(GBlockstate.when(OPEN, true, HORIZONTAL_FACING, Direction.WEST),
GBlockstate.variant(open, true, R0, R270));
}
}

View File

@@ -74,14 +74,7 @@ public class ReFramedBlueprintWrittenItem extends Item {
stacks.stream().map(inventory::getSlotWithStack).forEach(index -> inventory.removeStack(index, 1));
player.playSound(SoundEvents.ENTITY_ITEM_PICKUP, 0.5f, 0.5f);
}
for (int i = 1; tag.contains(BLOCKSTATE_KEY + i); i++) {
BlockState state = NbtHelper.toBlockState(
Registries.BLOCK.getReadOnlyWrapper(),
tag.getCompound(BLOCKSTATE_KEY + i)
);
frame_entity.setTheme(state, i);
}
if (world.isClient) ReFramed.chunkRerenderProxy.accept(world, pos);
frame_entity.readNbt(tag);
world.playSound(player, player.getBlockPos(), SoundEvents.ITEM_BOOK_PAGE_TURN, SoundCategory.PLAYERS);
return ActionResult.SUCCESS;

View File

@@ -43,7 +43,7 @@ public class ReFramedHammerItem extends Item {
world.playSound(player, pos, SoundEvents.ENTITY_ITEM_PICKUP, SoundCategory.BLOCKS, 1f, 1.1f);
}
frame_entity.setTheme(Blocks.AIR.getDefaultState(), theme_index);
if (world.isClient) ReFramed.chunkRerenderProxy.accept(world, pos);
ReFramed.chunkRerenderProxy.accept(world, pos);
return ActionResult.SUCCESS;
}
}

View File

@@ -52,7 +52,7 @@ public class ReFramedScrewdriverItem extends Item {
case Z -> Direction.Axis.X;
}
), theme_index);
if (world.isClient) ReFramed.chunkRerenderProxy.accept(world, pos);
ReFramed.chunkRerenderProxy.accept(world, pos);
return ActionResult.SUCCESS;
}
}

Some files were not shown because too many files have changed in this diff Show More