39 Commits
v1.5.10 ... dev

Author SHA1 Message Date
e872fe046c Update dependencies 2025-10-08 22:37:13 +02:00
fd26f5da4a feat: new version for publish 2025-05-14 18:15:00 +02:00
dbcb79f992 improved: removed unnecessary check + inner cull improvement 2025-05-14 18:13:35 +02:00
8d8a0e3654 fix: broken inner collision due to bad model 2025-05-14 18:13:18 +02:00
5c6fbff52e fix: visual issue always showing the suffocation texture 2025-05-14 18:13:06 +02:00
2f9cf1e57d feat: new version for publish 2025-05-14 02:45:42 +02:00
a470724d81 fix: render issue with water and reframed blocks + missing mixin in mixin config + shading improvement prep 2025-05-14 02:43:46 +02:00
b825959626 fix: render issue with non collidable reframed + culling issue with vanilla blocks + Fixed #22 2025-05-14 02:25:15 +02:00
083d39562a fix: added additional check for placing event see #19 2025-04-13 20:09:08 +02:00
e592db1ea2 feat: updated version 2024-07-01 23:31:09 +02:00
1fa55064c7 feat: added slabs layer block 2024-07-01 23:29:18 +02:00
e8c06a7fb3 feat: better additivity support 2024-07-01 22:31:52 +02:00
d7ae1f646f fix: bad rotating / mirroring logic on corner double frame 2024-07-01 15:16:50 +02:00
e3dac8a77f fix: wrong Step Cross shape 2024-07-01 02:19:34 +02:00
5281f84a2a fix: useAO out of bounds because not using model id 2024-07-01 02:11:49 +02:00
eac948bf5d feat: updated version 2024-06-19 14:36:00 +02:00
12924579a5 feat: added half slab and half slabs slab 2024-06-19 14:26:43 +02:00
48c7c4e538 fix: made frames properly update on every client when using blueprint/screwdriver/hammer 2024-06-19 13:20:12 +02:00
d325e3c5a5 feat: added 3 blocks and some refactoring 2024-06-19 02:42:03 +02:00
4d353bab27 refactor: changed method to non depreciated version 2024-06-18 15:23:59 +02:00
6f8304d638 feat: added HalfStairsCubeStair and HalfStairsStepStair 2024-06-18 14:56:46 +02:00
3bf9fc2268 feat: added StepCross 2024-06-17 21:10:57 +02:00
5812812bd9 feat: added missing models 2024-06-17 19:19:36 +02:00
1e6cab04cc feat: added SlabsInnerStair and SlabsOuterStair with additive logic + depreciation warning suppressing on AbstractBlock Methods 2024-06-17 19:19:13 +02:00
d7ad6ed0c1 feat: added and improved logic to merge step with slabs 2024-06-17 10:52:21 +02:00
8a9fbd9109 feat: added SlabsStair block 2024-06-16 18:17:04 +02:00
a76714d54d fix: render issue with items in axiom 2024-06-16 15:17:48 +02:00
b99f315c6f docs: updated objectives for publish 2024-06-14 17:46:47 +02:00
7df46a4b76 fix: more checks on ThemedEntity Class 2024-06-14 17:16:53 +02:00
42049047f7 fix: more injection fix + bad culling 2024-06-14 16:51:25 +02:00
ddffd45a44 fix: injection remapping issues fixed + additional check 2024-06-14 00:35:13 +02:00
fcf02b68e6 feat: version was missing in previous commit 2024-06-13 22:55:51 +02:00
b88a4abfe5 feat: more axiom support (connected textures and culling in selections) + newer version 2024-06-13 22:51:05 +02:00
ce650abc76 feat: added connected texture support on Axiom selection (includes blueprint previews etc) 2024-06-13 02:50:16 +02:00
535fd6151e feat: added post fence and postfence frames 2024-06-13 01:28:28 +02:00
1061431af7 feat: added button frame 2024-06-12 18:59:08 +02:00
520430d5bc feat: Axiom now renders frames in selections properly 2024-06-12 00:13:38 +02:00
52fb6840ad fix: added check in injections and fixed modifiers interactions and Layer drops 2024-06-12 00:12:07 +02:00
5430016be4 feat: added support for ReFramed block entities with axiom 2024-05-23 12:33:54 +02:00
185 changed files with 7431 additions and 708 deletions

View File

@@ -21,12 +21,7 @@ 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:
- Fence
- Button
- Pressure Plate
- Carpet (maybe redundant with Layer)
- 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 '1.6-SNAPSHOT'
id 'fabric-loom' version "${loom_version}"
id 'maven-publish'
}
@@ -36,9 +36,9 @@ base {
sourceSets {
main {
resources {
srcDirs += {
srcDirs += [
'src/generated'
}
]
}
}
}
@@ -84,6 +84,9 @@ repositories {
includeGroup "maven.modrinth"
}
}
maven {
url = "https://jitpack.io"
}
mavenCentral()
// Add repositories to retrieve artifacts from in here.
@@ -118,6 +121,10 @@ 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}"
}

View File

@@ -5,18 +5,19 @@ 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.15.11
loader_version=0.17.2
# Mod Properties
modrinth_id = jCpoCBpn
mod_version = 1.5.10
mod_version = 1.6.9-SNAPSHOT
maven_group = fr.adrien1106
archives_base_name = ReFramed
mod_id = reframed
# Dependencies
# check this on https://modmuss50.me/fabric.html
fabric_version=0.97.0+1.20.4
fabric_version=0.97.3+1.20.4
loom_version=1.11-SNAPSHOT
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-8.6-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-9.1.0-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME

View File

@@ -7,7 +7,6 @@ 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;
@@ -28,16 +27,28 @@ import java.util.stream.Stream;
import static fr.adrien1106.reframed.util.blocks.BlockProperties.LIGHT;
/**
* 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 Dynamic Ambient Occlusion -> not scheduled
* TODO better connected textures -> not scheduled
* TODO support continuity overlays -> not scheduled
* TODO slopes -> thinking about it
*/
public class ReFramed implements ModInitializer {
public static final String MODID = "reframed";
public static final ArrayList<Block> BLOCKS = new ArrayList<>();
public static Block CUBE, SMALL_CUBE, SMALL_CUBES_STEP, STAIR, HALF_STAIR, STAIRS_CUBE, HALF_STAIRS_SLAB, HALF_STAIRS_STAIR, SLAB, SLABS_CUBE, STEP, STEPS_SLAB, LAYER, PILLAR, PILLARS_WALL, WALL, PANE, TRAPDOOR, DOOR;
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 final ArrayList<Item> ITEMS = new ArrayList<>();
public static Item HAMMER, SCREWDRIVER, BLUEPRINT, BLUEPRINT_WRITTEN;
@@ -51,33 +62,50 @@ 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)));
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)));
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)));
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)));
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"),
FabricBlockEntityTypeBuilder.create(
BlockEntityType.Builder.create(
(pos, state) -> new ReFramedEntity(REFRAMED_BLOCK_ENTITY, pos, state),
BLOCKS.stream()
.filter(block -> !(block instanceof ReFramedDoubleBlock))
@@ -85,7 +113,7 @@ public class ReFramed implements ModInitializer {
);
REFRAMED_DOUBLE_BLOCK_ENTITY = Registry.register(Registries.BLOCK_ENTITY_TYPE, id("double_camo"),
FabricBlockEntityTypeBuilder.create(
BlockEntityType.Builder.create(
(pos, state) -> new ReFramedDoubleEntity(REFRAMED_DOUBLE_BLOCK_ENTITY, pos, state),
BLOCKS.stream()
.filter(block -> block instanceof ReFramedDoubleBlock)
@@ -107,11 +135,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((a,b,c) -> false)
.blockVision((a,b,c) -> false);
.suffocates(Blocks::never)
.solidBlock(Blocks::always);
// .blockVision(Blocks::always);
}
private static <I extends Item> I registerItem(String path, I item) {

View File

@@ -0,0 +1,100 @@
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

@@ -0,0 +1,70 @@
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

@@ -0,0 +1,64 @@
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

@@ -0,0 +1,57 @@
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

@@ -0,0 +1,46 @@
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

@@ -0,0 +1,64 @@
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

@@ -0,0 +1,49 @@
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,14 +2,15 @@ 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;
@@ -18,9 +19,11 @@ 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;
@@ -31,6 +34,7 @@ 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;
@@ -39,10 +43,26 @@ import static fr.adrien1106.reframed.util.blocks.BlockProperties.LIGHT;
public class ReFramedBlock extends Block implements BlockEntityProvider {
public ReFramedBlock(Settings settings) {
super(settings);
super(settings.dynamicBounds());
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;
}
@Override
@SuppressWarnings("deprecation")
public boolean canPathfindThrough(BlockState state, BlockView world, BlockPos pos, NavigationType type) {
return false;
}
@Override
public @Nullable BlockEntity createBlockEntity(BlockPos pos, BlockState state) {
return ReFramed.REFRAMED_BLOCK_ENTITY.instantiate(pos, state);
@@ -60,6 +80,7 @@ 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;
ActionResult result = BlockHelper.useUpgrade(state, world, pos, player, hand);
@@ -73,8 +94,11 @@ public class ReFramedBlock extends Block implements BlockEntityProvider {
}
@Override
public void onStateReplaced(BlockState state, World world, BlockPos pos, BlockState newState, boolean moved) {
if(!(newState.getBlock() instanceof ReFramedBlock) &&
@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) &&
world.getBlockEntity(pos) instanceof ReFramedEntity frame_entity &&
world.getGameRules().getBoolean(GameRules.DO_TILE_DROPS)
) {
@@ -85,19 +109,9 @@ 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, newState, moved);
super.onStateReplaced(state, world, pos, new_state, moved);
}
public void onPlaced(World world, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack stack, BlockState old_state, BlockEntity old_entity) {
@@ -146,8 +160,22 @@ 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()
@@ -155,12 +183,14 @@ 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);
@@ -171,11 +201,13 @@ 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);
}
@@ -196,4 +228,17 @@ 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

@@ -0,0 +1,245 @@
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

@@ -57,6 +57,7 @@ public class ReFramedDoorBlock extends WaterloggableReFramedBlock {
}
@Override
@SuppressWarnings("deprecation")
public boolean canPlaceAt(BlockState state, WorldView world, BlockPos pos) {
BlockPos pos_down = pos.down();
BlockState state_down = world.getBlockState(pos_down);
@@ -64,6 +65,7 @@ public class ReFramedDoorBlock extends WaterloggableReFramedBlock {
}
@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)
@@ -113,7 +115,7 @@ public class ReFramedDoorBlock extends WaterloggableReFramedBlock {
@Override
public BlockState onBreak(World world, BlockPos pos, BlockState state, PlayerEntity player) {
if (!world.isClient() && (player.isCreative() || !player.canHarvest(state))) {
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);
@@ -126,13 +128,6 @@ public class ReFramedDoorBlock extends WaterloggableReFramedBlock {
return super.onBreak(world, pos, state, player);
}
@Override
public void onStateReplaced(BlockState state, World world, BlockPos pos, BlockState newState, boolean moved) {
super.onStateReplaced(state, world, pos, newState, moved);
if(!state.isOf(newState.getBlock())) world.removeBlockEntity(pos);
}
@Override
public BlockState getStateForNeighborUpdate(BlockState state, Direction direction, BlockState other, WorldAccess world, BlockPos pos, BlockPos moved) {
if (direction.getAxis() == Direction.Axis.Y
@@ -162,6 +157,7 @@ public class ReFramedDoorBlock extends WaterloggableReFramedBlock {
}
@Override
@SuppressWarnings("deprecation")
public boolean canPathfindThrough(BlockState state, BlockView world, BlockPos pos, NavigationType type) {
return switch (type) {
case LAND, AIR -> state.get(OPEN);
@@ -170,6 +166,7 @@ public class ReFramedDoorBlock extends WaterloggableReFramedBlock {
}
@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()
@@ -192,6 +189,7 @@ public class ReFramedDoorBlock extends WaterloggableReFramedBlock {
}
@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)) {
@@ -202,16 +200,19 @@ public class ReFramedDoorBlock extends WaterloggableReFramedBlock {
}
@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());
}

View File

@@ -19,7 +19,6 @@ 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) {
@@ -49,14 +48,6 @@ 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
@@ -69,7 +60,7 @@ public abstract class ReFramedDoubleBlock extends ReFramedBlock {
@Override
public VoxelShape getCollisionShape(BlockState state, BlockView view, BlockPos pos, ShapeContext ctx) {
return isGhost(view, pos) ? empty() : fullCube();
return isGhost(view, pos) ? empty() : getOutlineShape(state, view, pos, ctx);
}
@Override

View File

@@ -57,6 +57,6 @@ public class ReFramedDoubleEntity extends ReFramedEntity {
public void writeNbt(NbtCompound nbt) {
super.writeNbt(nbt);
if(second_state != Blocks.AIR.getDefaultState()) nbt.put(BLOCKSTATE_KEY + 2, NbtHelper.fromBlockState(second_state));
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;
protected static final byte LIGHT_MASK = 0b001;
protected static final byte REDSTONE_MASK = 0b010;
protected static final byte SOLIDITY_MASK = 0b100;
public static final byte LIGHT_MASK = 0b001;
public static final byte REDSTONE_MASK = 0b010;
public static final byte SOLIDITY_MASK = 0b100;
public static final String BLOCKSTATE_KEY = "s";
protected static final String BITFIELD_KEY = "b";
public static final String BITFIELD_KEY = "b";
public ReFramedEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
super(type, pos, state);
@@ -52,16 +52,15 @@ 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);
if(first_state != Blocks.AIR.getDefaultState()) nbt.put(BLOCKSTATE_KEY + 1, NbtHelper.fromBlockState(first_state));
nbt.put(BLOCKSTATE_KEY + 1, NbtHelper.fromBlockState(first_state));
if(bit_field != SOLIDITY_MASK) nbt.putByte(BITFIELD_KEY, bit_field);
}
@@ -113,7 +112,7 @@ public class ReFramedEntity extends BlockEntity implements ThemeableBlockEntity
}
public void setTheme(BlockState new_state, int i) {
if(!Objects.equals(first_state, new_state)) {
if(!Objects.equals(first_state, new_state) && i == 1) {
first_state = new_state;
markDirtyAndDispatch();
}
@@ -146,7 +145,10 @@ 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());
if(world != null) {
world.setBlockState(pos, getCachedState());
ReFramed.chunkRerenderProxy.accept(world, pos);
}
markDirtyAndDispatch();
}

View File

@@ -0,0 +1,108 @@
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

@@ -0,0 +1,188 @@
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

@@ -0,0 +1,86 @@
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

@@ -0,0 +1,45 @@
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

@@ -25,6 +25,7 @@ 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 {
@@ -42,39 +43,44 @@ public class ReFramedHalfStairBlock extends WaterloggableReFramedBlock {
}
@Override
@SuppressWarnings("deprecation")
public boolean canReplace(BlockState state, ItemPlacementContext context) {
if (context.getPlayer() == null) 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())
)
)
)
);
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;
}
@Override
@@ -92,6 +98,15 @@ 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)
@@ -100,11 +115,13 @@ public class ReFramedHalfStairBlock extends WaterloggableReFramedBlock {
}
@Override
@SuppressWarnings("deprecation")
public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
return HALF_STAIR_VOXELS[state.get(CORNER_FACE) + state.get(CORNER).getID() * 3];
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));
@@ -112,6 +129,7 @@ public class ReFramedHalfStairBlock extends WaterloggableReFramedBlock {
}
@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));
@@ -120,7 +138,11 @@ public class ReFramedHalfStairBlock extends WaterloggableReFramedBlock {
@Override
public Map<Integer, Integer> getThemeMap(BlockState state, BlockState new_state) {
if (new_state.isOf(ReFramed.HALF_STAIRS_SLAB)) return Map.of(1, 1);
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_STAIR))
return Map.of(
1,
@@ -131,6 +153,10 @@ 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

@@ -0,0 +1,48 @@
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

@@ -15,13 +15,12 @@ import net.minecraft.util.shape.VoxelShape;
import net.minecraft.world.BlockView;
import org.jetbrains.annotations.Nullable;
import static fr.adrien1106.reframed.block.ReFramedHalfStairBlock.HALF_STAIR_VOXELS;
import static fr.adrien1106.reframed.block.ReFramedHalfStairBlock.getHalfStairShape;
import static fr.adrien1106.reframed.block.ReFramedSlabBlock.getSlabShape;
import static fr.adrien1106.reframed.block.ReFramedSmallCubeBlock.SMALL_CUBE_VOXELS;
import static fr.adrien1106.reframed.block.ReFramedSmallCubeBlock.getSmallCubeShape;
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 {
@@ -44,16 +43,13 @@ public class ReFramedHalfStairsSlabBlock extends WaterloggableReFramedDoubleBloc
}
@Override
public VoxelShape getCollisionShape(BlockState state, BlockView view, BlockPos pos, ShapeContext ctx) {
return isGhost(view, pos) ? empty(): getSlabShape(state.get(CORNER).getDirection(state.get(CORNER_FACE)));
}
@Override
@SuppressWarnings("deprecation")
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));
@@ -61,6 +57,7 @@ public class ReFramedHalfStairsSlabBlock extends WaterloggableReFramedDoubleBloc
}
@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));
@@ -72,7 +69,7 @@ public class ReFramedHalfStairsSlabBlock extends WaterloggableReFramedDoubleBloc
Corner corner = state.get(CORNER);
int face = state.get(CORNER_FACE);
return i == 2
? SMALL_CUBE_VOXELS[corner.getOpposite(face).getID()]
: HALF_STAIR_VOXELS[face + corner.getID() * 3];
? getSmallCubeShape(corner.getOpposite(face))
: getHalfStairShape(corner, face);
}
}

View File

@@ -17,11 +17,10 @@ import net.minecraft.util.shape.VoxelShape;
import net.minecraft.world.BlockView;
import org.jetbrains.annotations.Nullable;
import static fr.adrien1106.reframed.block.ReFramedHalfStairBlock.HALF_STAIR_VOXELS;
import static fr.adrien1106.reframed.block.ReFramedHalfStairBlock.getHalfStairShape;
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) {
@@ -41,21 +40,19 @@ public class ReFramedHalfStairsStairBlock extends WaterloggableReFramedDoubleBlo
}
@Override
public VoxelShape getCollisionShape(BlockState state, BlockView view, BlockPos pos, ShapeContext ctx) {
return isGhost(view, pos) ? empty(): getStairShape(state.get(EDGE), StairShape.STRAIGHT);
}
@Override
@SuppressWarnings("deprecation")
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));
}
@@ -72,7 +69,7 @@ public class ReFramedHalfStairsStairBlock extends WaterloggableReFramedDoubleBlo
side
);
return HALF_STAIR_VOXELS[corner.getID() * 3 + corner.getDirectionIndex(side)];
return getHalfStairShape(corner, corner.getDirectionIndex(side));
}
@Override

View File

@@ -0,0 +1,76 @@
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,65 +1,72 @@
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;
import net.minecraft.world.BlockView;
import org.jetbrains.annotations.Nullable;
import static fr.adrien1106.reframed.util.VoxelHelper.VoxelListBuilder;
import static net.minecraft.state.property.Properties.FACING;
import static net.minecraft.state.property.Properties.LAYERS;
import static fr.adrien1106.reframed.util.blocks.BlockProperties.HALF_LAYERS;
import static net.minecraft.state.property.Properties.*;
public class ReFramedLayerBlock extends ReFramedSlabBlock {
public class ReFramedLayerBlock extends LayeredReFramedBlock {
public static final VoxelShape[] LAYER_VOXELS;
public ReFramedLayerBlock(Settings settings) {
super(settings);
setDefaultState(getDefaultState().with(LAYERS, 1));
setDefaultState(getDefaultState().with(FACING, Direction.DOWN));
}
@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(builder.add(LAYERS));
super.appendProperties(builder.add(FACING));
}
@Override
public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
return LAYER_VOXELS[state.get(FACING).getId() * 8 + state.get(LAYERS) - 1];
return getLayerShape(state.get(FACING), state.get(LAYERS));
}
@Override
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)
);
public static VoxelShape getLayerShape(Direction facing, int layers) {
return LAYER_VOXELS[facing.getId() * 8 + layers - 1];
}
@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);
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)));
}

View File

@@ -1,122 +1,39 @@
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.PaneBlock;
import net.minecraft.block.ShapeContext;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.registry.tag.BlockTags;
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.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 net.minecraft.state.property.Properties.*;
public class ReFramedPaneBlock extends WaterloggableReFramedBlock {
public class ReFramedPaneBlock extends ConnectingReFramedBlock {
public static final VoxelShape[] PANE_VOXELS;
public ReFramedPaneBlock(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;
for (Direction side: Direction.Type.HORIZONTAL) {
BlockState neighbor = world.getBlockState(pos.offset(side));
new_state = new_state.with(getPaneProperty(side), connectsTo(
neighbor,
neighbor.isSideSolidFullSquare(world, pos.offset(side), side.getOpposite())
));
}
return new_state;
}
@Override
public @Nullable BlockState getPlacementState(ItemPlacementContext ctx) {
BlockState state = super.getPlacementState(ctx);
World world = ctx.getWorld();
BlockPos pos = ctx.getBlockPos();
for (Direction dir: Direction.Type.HORIZONTAL) {
BlockState neighbor = world.getBlockState(pos.offset(dir));
state = state.with(getPaneProperty(dir), connectsTo(
neighbor,
neighbor.isSideSolidFullSquare(world, pos.offset(dir), dir.getOpposite())
));
}
return state;
}
@Override
public void onStateReplaced(BlockState state, World world, BlockPos pos, BlockState newState, boolean moved) {
super.onStateReplaced(state, world, pos, newState, moved);
if(!state.isOf(newState.getBlock())) world.removeBlockEntity(pos);
}
@Override
public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
VoxelShape shape = PANE_VOXELS[0];
for (Direction dir: Direction.Type.HORIZONTAL) {
if (state.get(getPaneProperty(dir)))
if (state.get(getConnectionProperty(dir)))
shape = VoxelShapes.union(shape, PANE_VOXELS[dir.ordinal() - 1]);
}
return shape;
}
@Override
public BlockState rotate(BlockState state, BlockRotation rotation) {
return Direction.Type.HORIZONTAL.stream().reduce(state, (s, dir) ->
s.with(getPaneProperty(rotation.rotate(dir)), state.get(getPaneProperty(dir)))
, (prev, next) -> next);
}
@Override
public BlockState mirror(BlockState state, BlockMirror mirror) {
return Direction.Type.HORIZONTAL.stream().reduce(state, (s, dir) ->
s.with(getPaneProperty(mirror.apply(dir)), state.get(getPaneProperty(dir)))
, (prev, next) -> next);
}
public static boolean connectsTo(BlockState state, boolean fs) {
protected boolean connectsTo(BlockState state, boolean fs, Direction dir) {
return !cannotConnect(state) && fs || state.getBlock() instanceof PaneBlock || state.isIn(BlockTags.WALLS);
}
public static BooleanProperty getPaneProperty(Direction dir) {
return switch (dir) {
case NORTH -> NORTH;
case EAST -> EAST;
case SOUTH -> SOUTH;
case WEST -> WEST;
default -> null;
};
}
static {
VoxelShape POST = createCuboidShape(7, 0, 7, 9, 16, 9);
VoxelShape SIDE = createCuboidShape(7, 0, 0, 9, 16, 7);

View File

@@ -1,38 +1,21 @@
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.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 class ReFramedPillarBlock extends WaterloggableReFramedBlock {
public class ReFramedPillarBlock extends PillarReFramedBlock {
public static final VoxelShape[] PILLAR_VOXELS;
public ReFramedPillarBlock(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
@@ -44,16 +27,6 @@ public class ReFramedPillarBlock extends WaterloggableReFramedBlock {
return PILLAR_VOXELS[axis.ordinal()];
}
@Override
public BlockState rotate(BlockState state, BlockRotation rotation) {
return state.with(AXIS, rotation.rotate(Direction.get(Direction.AxisDirection.POSITIVE, state.get(AXIS))).getAxis());
}
@Override
public BlockState mirror(BlockState state, BlockMirror mirror) {
return state.with(AXIS, mirror.apply(Direction.get(Direction.AxisDirection.POSITIVE, state.get(AXIS))).getAxis());
}
static {
final VoxelShape PILLAR = createCuboidShape(0, 4, 4, 16, 12, 12);
PILLAR_VOXELS = VoxelHelper.VoxelListBuilder.create(PILLAR, 3)

View File

@@ -71,13 +71,6 @@ public class ReFramedPillarsWallBlock extends WaterloggableReFramedDoubleBlock {
return getWallState(state, top_state, neighbors, top_shape, fs, world, pos);
}
@Override
public void onStateReplaced(BlockState state, World world, BlockPos pos, BlockState newState, boolean moved) {
super.onStateReplaced(state, world, pos, newState, moved);
if(!state.isOf(newState.getBlock())) world.removeBlockEntity(pos);
}
@Override
public VoxelShape getCollisionShape(BlockState state, BlockView view, BlockPos pos, ShapeContext ctx) {
if (isGhost(view, pos)) return empty();
@@ -95,6 +88,7 @@ public class ReFramedPillarsWallBlock extends WaterloggableReFramedDoubleBlock {
}
@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) {
@@ -106,6 +100,7 @@ public class ReFramedPillarsWallBlock extends WaterloggableReFramedDoubleBlock {
}
@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)))
@@ -113,6 +108,7 @@ public class ReFramedPillarsWallBlock extends WaterloggableReFramedDoubleBlock {
}
@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)))

View File

@@ -0,0 +1,37 @@
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

@@ -0,0 +1,150 @@
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,6 +1,9 @@
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;
@@ -18,8 +21,8 @@ import org.jetbrains.annotations.Nullable;
import java.util.Map;
import static net.minecraft.state.property.Properties.AXIS;
import static net.minecraft.state.property.Properties.FACING;
import static fr.adrien1106.reframed.util.blocks.BlockProperties.*;
import static net.minecraft.state.property.Properties.*;
public class ReFramedSlabBlock extends WaterloggableReFramedBlock {
@@ -41,46 +44,134 @@ public class ReFramedSlabBlock 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() == 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
)
)
);
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())
);
}
@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)));
}
@@ -98,6 +189,11 @@ 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

@@ -11,7 +11,6 @@ import net.minecraft.util.shape.VoxelShape;
import org.jetbrains.annotations.Nullable;
import static fr.adrien1106.reframed.block.ReFramedSlabBlock.*;
import static fr.adrien1106.reframed.util.blocks.BlockProperties.EDGE;
import static net.minecraft.state.property.Properties.AXIS;
public class ReFramedSlabsCubeBlock extends ReFramedDoubleBlock {
@@ -33,11 +32,13 @@ public class ReFramedSlabsCubeBlock extends ReFramedDoubleBlock {
}
@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

@@ -0,0 +1,62 @@
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

@@ -0,0 +1,48 @@
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

@@ -0,0 +1,96 @@
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

@@ -0,0 +1,51 @@
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

@@ -0,0 +1,37 @@
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,6 +4,8 @@ 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;
@@ -25,6 +27,7 @@ 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 {
@@ -42,64 +45,73 @@ public class ReFramedSmallCubeBlock extends WaterloggableReFramedBlock {
}
@Override
@SuppressWarnings("deprecation")
public boolean canReplace(BlockState state, ItemPlacementContext context) {
if (context.getPlayer() == null) return false;
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);
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())
)
)
)
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
)
&& !(
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
)
)
)
)
);
)) return block == ReFramed.SLAB || !matchesShape(
context.getHitPos(),
context.getBlockPos(),
getDefaultState().with(CORNER, corner)
);
}
return false;
}
@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))
return ReFramed.HALF_STAIRS_SLAB.getDefaultState()
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
.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();
@@ -120,27 +132,42 @@ 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 SMALL_CUBE_VOXELS[state.get(CORNER).getID()];
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));
}
@Override
public Map<Integer, Integer> getThemeMap(BlockState state, BlockState new_state) {
if (new_state.isOf(ReFramed.HALF_STAIRS_SLAB)) return Map.of(1, 2);
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.SMALL_CUBES_STEP))
return Map.of(
1,
@@ -151,6 +178,10 @@ 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

@@ -18,7 +18,6 @@ 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 {
@@ -39,21 +38,19 @@ public class ReFramedSmallCubesStepBlock extends WaterloggableReFramedDoubleBloc
}
@Override
public VoxelShape getCollisionShape(BlockState state, BlockView view, BlockPos pos, ShapeContext ctx) {
return isGhost(view, pos) ? empty(): getStepShape(state.get(EDGE));
}
@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));
}

View File

@@ -19,7 +19,6 @@ 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;
@@ -45,6 +44,7 @@ public class ReFramedStairBlock extends WaterloggableReFramedBlock {
}
@Override
@SuppressWarnings("deprecation")
public boolean canReplace(BlockState state, ItemPlacementContext context) {
if (context.getPlayer() == null) return false;
return !(
@@ -52,7 +52,7 @@ public class ReFramedStairBlock extends WaterloggableReFramedBlock {
|| !(context.getStack().getItem() instanceof BlockItem block_item)
|| !(
block_item.getBlock() == ReFramed.STEP
&& ((ReFramedStairsCubeBlock) ReFramed.STAIRS_CUBE)
&& ReFramed.STAIRS_CUBE
.matchesShape(
context.getHitPos(),
context.getBlockPos(),
@@ -87,18 +87,13 @@ public class ReFramedStairBlock extends WaterloggableReFramedBlock {
}
@Override
public void onStateReplaced(BlockState state, World world, BlockPos pos, BlockState newState, boolean moved) {
super.onStateReplaced(state, world, pos, newState, moved);
if(!state.isOf(newState.getBlock())) world.removeBlockEntity(pos);
}
@Override
@SuppressWarnings("deprecation")
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);
@@ -115,6 +110,7 @@ public class ReFramedStairBlock extends WaterloggableReFramedBlock {
}
@Override
@SuppressWarnings("deprecation")
public BlockState mirror(BlockState state, BlockMirror mirror) {
Edge prev_edge = state.get(EDGE);
Edge edge = prev_edge.mirror(mirror);

View File

@@ -12,7 +12,6 @@ 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;
@@ -36,6 +35,7 @@ public class ReFramedStairsCubeBlock extends ReFramedDoubleBlock {
}
@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));
@@ -52,6 +52,7 @@ public class ReFramedStairsCubeBlock extends ReFramedDoubleBlock {
@Override
@SuppressWarnings("deprecation")
public BlockState rotate(BlockState state, BlockRotation rotation) {
Edge prev_edge = state.get(EDGE);
Edge edge = prev_edge.rotate(rotation);
@@ -68,6 +69,7 @@ public class ReFramedStairsCubeBlock extends ReFramedDoubleBlock {
}
@Override
@SuppressWarnings("deprecation")
public BlockState mirror(BlockState state, BlockMirror mirror) {
Edge prev_edge = state.get(EDGE);
Edge edge = prev_edge.mirror(mirror);
@@ -76,13 +78,6 @@ public class ReFramedStairsCubeBlock extends ReFramedDoubleBlock {
.with(EDGE, edge);
}
@Override
public void onStateReplaced(BlockState state, World world, BlockPos pos, BlockState newState, boolean moved) {
super.onStateReplaced(state, world, pos, newState, moved);
if(!state.isOf(newState.getBlock())) world.removeBlockEntity(pos);
}
@Override
public VoxelShape getShape(BlockState state, int i) {
Edge edge = state.get(EDGE);

View File

@@ -3,6 +3,7 @@ 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;
@@ -22,10 +23,9 @@ 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.*;
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 {
@@ -42,49 +42,38 @@ public class ReFramedStepBlock extends WaterloggableReFramedBlock {
}
@Override
@SuppressWarnings("deprecation")
public boolean canReplace(BlockState state, ItemPlacementContext context) {
if (context.getPlayer() == null) return false;
Edge edge = state.get(EDGE);
return !(
context.getPlayer().isSneaking()
if (context.getPlayer() == null
|| 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
)
) return false;
)
&& !(
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
)
)
)
)
);
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()))
);
// 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())
);
}
@Nullable
@@ -92,6 +81,7 @@ 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))
@@ -101,39 +91,91 @@ public class ReFramedStepBlock extends WaterloggableReFramedBlock {
if (current_state.isOf(this)) {
Vec3d hit = ctx.getHitPos();
Edge edge = current_state.get(EDGE);
Direction dir = edge.getFirstDirection();
ReFramedStepsSlabBlock block = ((ReFramedStepsSlabBlock) ReFramed.STEPS_SLAB);
BlockState state = block.getDefaultState()
.with(FACING, dir)
.with(AXIS, edge.getOtherDirection(dir).getAxis())
// 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))
.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));
}
@@ -144,7 +186,11 @@ public class ReFramedStepBlock extends WaterloggableReFramedBlock {
@Override
public Map<Integer, Integer> getThemeMap(BlockState state, BlockState new_state) {
if (new_state.isOf(ReFramed.STAIRS_CUBE)) return Map.of(1, 2);
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.STEPS_SLAB))
return Map.of(
1,

View File

@@ -0,0 +1,86 @@
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

@@ -0,0 +1,62 @@
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

@@ -21,7 +21,6 @@ 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 {
@@ -44,16 +43,13 @@ public class ReFramedStepsSlabBlock extends WaterloggableReFramedDoubleBlock {
}
@Override
public VoxelShape getCollisionShape(BlockState state, BlockView view, BlockPos pos, ShapeContext ctx) {
return isGhost(view, pos) ? empty() : getSlabShape(state.get(FACING));
}
@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(AXIS, rotation.rotate(Direction.get(Direction.AxisDirection.POSITIVE, state.get(AXIS))).getAxis())
@@ -61,6 +57,7 @@ public class ReFramedStepsSlabBlock extends WaterloggableReFramedDoubleBlock {
}
@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)));

View File

@@ -48,6 +48,7 @@ public class ReFramedTrapdoorBlock extends WaterloggableReFramedBlock {
}
@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);
@@ -83,13 +84,6 @@ public class ReFramedTrapdoorBlock extends WaterloggableReFramedBlock {
return state;
}
@Override
public void onStateReplaced(BlockState state, World world, BlockPos pos, BlockState newState, boolean moved) {
super.onStateReplaced(state, world, pos, newState, moved);
if(!state.isOf(newState.getBlock())) world.removeBlockEntity(pos);
}
@Override
public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) {
ActionResult result = super.onUse(state, world, pos, player, hand, hit);
@@ -99,6 +93,7 @@ public class ReFramedTrapdoorBlock extends WaterloggableReFramedBlock {
}
@Override
@SuppressWarnings("deprecation")
public boolean canPathfindThrough(BlockState state, BlockView world, BlockPos pos, NavigationType type) {
return switch (type) {
case LAND, AIR -> state.get(OPEN);
@@ -107,6 +102,7 @@ public class ReFramedTrapdoorBlock extends WaterloggableReFramedBlock {
}
@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()
@@ -129,6 +125,7 @@ public class ReFramedTrapdoorBlock extends WaterloggableReFramedBlock {
}
@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;
@@ -137,11 +134,13 @@ public class ReFramedTrapdoorBlock extends WaterloggableReFramedBlock {
}
@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)));
}

View File

@@ -80,13 +80,7 @@ public class ReFramedWallBlock extends WaterloggableReFramedBlock {
}
@Override
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
@SuppressWarnings("deprecation")
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) {
@@ -109,6 +103,7 @@ public class ReFramedWallBlock extends WaterloggableReFramedBlock {
}
@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)))
@@ -116,6 +111,7 @@ public class ReFramedWallBlock extends WaterloggableReFramedBlock {
}
@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)))

View File

@@ -23,7 +23,13 @@ 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) {
@@ -33,10 +39,13 @@ 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,10 +33,13 @@ 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,131 +27,231 @@ 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")));
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")));
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")));
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")));
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")));
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")));
//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);
// 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);
}
private void privateInit() {

View File

@@ -5,12 +5,15 @@ 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;
@@ -35,7 +38,17 @@ public class DoubleRetexturingBakedModel extends ForwardingBakedModel implements
}
@Override
public void emitBlockQuads(BlockRenderView world, BlockState state, BlockPos pos, Supplier<Random> randomSupplier, RenderContext context) {}
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);
}
@Override // models are emitted here because no checks are done on items
public void emitItemQuads(ItemStack stack, Supplier<Random> randomSupplier, RenderContext context) {

View File

@@ -12,11 +12,13 @@ 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;
@@ -25,6 +27,7 @@ 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;
@@ -62,7 +65,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);
@@ -70,7 +73,40 @@ public abstract class RetexturingBakedModel extends ForwardingBakedModel {
return mesh;
}
protected abstract Mesh convertModel(BlockState state);
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);
@Override
public boolean isVanillaAdapter() {
@@ -89,6 +125,7 @@ public abstract class RetexturingBakedModel extends ForwardingBakedModel {
@Override
public void emitBlockQuads(BlockRenderView world, BlockState state, BlockPos pos, Supplier<Random> randomSupplier, RenderContext context) {
BlockState theme = (world.getBlockEntity(pos) instanceof ThemeableBlockEntity s) ? s.getTheme(theme_index) : null;
QuadEmitter quad_emitter = context.getEmitter();
if(theme == null || theme.isAir()) {
getRetexturedMesh(
@@ -153,9 +190,14 @@ public abstract class RetexturingBakedModel extends ForwardingBakedModel {
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, frame_entity.getTheme(theme_index), pos, theme_index, false);
return appearance.getAO(theme_index);
.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) {
@@ -176,7 +218,7 @@ public abstract class RetexturingBakedModel extends ForwardingBakedModel {
emitter.copyFrom(quad);
i = key.appearance.transformQuad(emitter, i, quad_index.get(), key.model_id, 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

@@ -51,7 +51,7 @@ public class CamoAppearanceManager {
for(BlendMode blend : BlendMode.values()) {
finder.clear().disableDiffuse(false).blendMode(blend);
materials.put(blend, finder.ambientOcclusion(TriState.FALSE).find());
materials.put(blend, finder.ambientOcclusion(TriState.TRUE).find());
ao_materials.put(blend, finder.ambientOcclusion(TriState.DEFAULT).find()); //not "true" since that *forces* AO, i just want to *allow* AO
}

View File

@@ -12,7 +12,6 @@ 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;
@@ -52,8 +51,6 @@ 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);
@@ -92,18 +89,27 @@ public class RenderHelper {
BlockState self_theme = frame_entity.getTheme(theme_index);
BlockState other_theme = frame_entity.getTheme(cull_theme);
if (self_theme.isSideInvisible(other_theme, null)) return false;
return !self_theme.isOpaque() || !other_theme.isOpaque();
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();
}
// 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 (self == null && other == null) return Block.shouldDrawSide(self_state, world, pos, side, other_pos);
if ((theme_index == 0 && self != null) || (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) {
@@ -114,7 +120,7 @@ public class RenderHelper {
VoxelShape other_shape = VoxelShapes.empty();
for (BlockState s: other.getThemes()) {
i++;
if (self_state.isSideInvisible(s, side) || s.isOpaque())
if (self_state.isSideInvisible(s, side) || (s.isOpaque() && (other.isSolid() || self_state.isTransparent(world ,pos))))
other_shape = combine(
other_shape,
other_block
@@ -158,7 +164,7 @@ public class RenderHelper {
VoxelShape other_shape = VoxelShapes.empty();
for (BlockState s: other.getThemes()) {
i++;
if (self_theme.isSideInvisible(s, side) || s.isOpaque())
if (self_theme.isSideInvisible(s, side) || (s.isOpaque() && (!self.isSolid() || (other.isSolid() == self.isSolid()))))
other_shape = combine(
other_shape,
other_block

View File

@@ -19,6 +19,8 @@ public class GBlockTag extends BlockTagProvider {
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());
}
public GBlockTag(FabricDataOutput output, CompletableFuture<WrapperLookup> registries) {

View File

@@ -22,21 +22,37 @@ 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());
}
public GBlockstate(FabricDataOutput output) {

View File

@@ -24,21 +24,37 @@ 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(ReFramedBlueprintItem.class, new Blueprint());
providers.put(ReFramedHammerItem.class, new Hammer());
providers.put(ReFramedScrewdriverItem.class, new Screwdriver());

View File

@@ -0,0 +1,95 @@
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

@@ -0,0 +1,77 @@
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

@@ -0,0 +1,73 @@
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

@@ -0,0 +1,171 @@
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

@@ -0,0 +1,34 @@
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

@@ -0,0 +1,34 @@
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

@@ -0,0 +1,33 @@
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

@@ -0,0 +1,159 @@
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

@@ -0,0 +1,50 @@
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

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

View File

@@ -0,0 +1,93 @@
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

@@ -0,0 +1,33 @@
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

@@ -0,0 +1,58 @@
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

@@ -0,0 +1,33 @@
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

@@ -0,0 +1,97 @@
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,23 +2,15 @@ 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 {
@@ -35,35 +27,6 @@ public class SmallCubesStep implements RecipeSetter, BlockStateProvider {
@Override
public BlockStateSupplier getMultipart(Block block) {
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));
return Step.getMultipart(block, "small_cubes_step", "small_cubes_step_reverse");
}
}

View File

@@ -36,17 +36,26 @@ public class Step implements RecipeSetter, BlockStateProvider {
@Override
public BlockStateSupplier getMultipart(Block block) {
Identifier model_id = ReFramed.id("step_special");
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");
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(model_id, true, R180, R0))
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(model_id, true, R0, R180))
GBlockstate.variant(reverse_model_id, true, R0, R180))
/* Y AXIS */
.with(GBlockstate.when(EDGE, EAST_SOUTH),
GBlockstate.variant(model_id, true, R90, R0))
@@ -58,11 +67,11 @@ public class Step implements RecipeSetter, BlockStateProvider {
GBlockstate.variant(model_id, true, R90, R270))
/* Z AXIS */
.with(GBlockstate.when(EDGE, DOWN_SOUTH),
GBlockstate.variant(model_id, true, R0, R90))
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(model_id, true, R180, R270))
GBlockstate.variant(reverse_model_id, true, R180, R270))
.with(GBlockstate.when(EDGE, SOUTH_UP),
GBlockstate.variant(model_id, true, R180, R90));
}

View File

@@ -0,0 +1,34 @@
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

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

View File

@@ -74,7 +74,14 @@ 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);
}
frame_entity.readNbt(tag);
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);
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);
ReFramed.chunkRerenderProxy.accept(world, pos);
if (world.isClient) 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);
ReFramed.chunkRerenderProxy.accept(world, pos);
if (world.isClient) ReFramed.chunkRerenderProxy.accept(world, pos);
return ActionResult.SUCCESS;
}
}

View File

@@ -2,6 +2,7 @@ package fr.adrien1106.reframed.mixin;
import com.llamalad7.mixinextras.sugar.Local;
import com.llamalad7.mixinextras.sugar.ref.LocalRef;
import fr.adrien1106.reframed.block.ReFramedBlock;
import net.minecraft.block.Block;
import net.minecraft.block.BlockEntityProvider;
import net.minecraft.entity.player.PlayerEntity;
@@ -9,6 +10,7 @@ import net.minecraft.item.BlockItem;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.nbt.NbtHelper;
import net.minecraft.state.property.Properties;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import org.spongepowered.asm.mixin.Mixin;
@@ -30,10 +32,15 @@ public class BlockItemMixin {
)
)
private static void placeBlockWithOffHandCamo(World world, PlayerEntity player, BlockPos pos, ItemStack stack, CallbackInfoReturnable<Boolean> cir, @Local LocalRef<NbtCompound> compound) {
if (compound.get() != null
if (player == null
|| compound.get() != null
|| player.getOffHandStack().isEmpty()
|| player.getMainHandStack().isEmpty()
|| !(player.getMainHandStack().getItem() instanceof BlockItem frame)
|| !(frame.getBlock() instanceof ReFramedBlock)
|| !(player.getOffHandStack().getItem() instanceof BlockItem block)
|| block.getBlock() instanceof BlockEntityProvider
|| (world.getBlockState(pos).contains(Properties.LAYERS) && world.getBlockState(pos).get(Properties.LAYERS) > 1)
|| !Block.isShapeFullCube(block.getBlock().getDefaultState().getCollisionShape(world, pos))
) return;
NbtCompound new_comp = new NbtCompound();

View File

@@ -17,7 +17,7 @@ public class CompatMixinPlugin implements IMixinConfigPlugin {
private static final FabricLoader LOADER = FabricLoader.getInstance();
private static final Logger LOGGER = LoggerFactory.getLogger("ReFramed MIXIN");
private static final List<String> COMPAT_MOD = List.of("athena", "indium", "sodium", "special-model-loader", "continuity");
private static final List<String> COMPAT_MOD = List.of("athena", "indium", "sodium", "special-model-loader", "continuity", "axiom");
private static final Map<String, Supplier<Boolean>> CONDITIONS = new HashMap<>();
static {
CONDITIONS.put("fr.adrien1106.reframed.mixin.compat.AthenaBakedModelMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(0)));
@@ -26,13 +26,26 @@ public class CompatMixinPlugin implements IMixinConfigPlugin {
CONDITIONS.put("fr.adrien1106.reframed.mixin.render.BlockRenderInfoMixin", () -> !LOADER.isModLoaded(COMPAT_MOD.get(1)));
CONDITIONS.put("fr.adrien1106.reframed.mixin.render.AbstractBlockRenderContextMixin", () -> !LOADER.isModLoaded(COMPAT_MOD.get(1)));
CONDITIONS.put("fr.adrien1106.reframed.mixin.compat.IndiumTerrainRenderContextMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(1)));
CONDITIONS.put("fr.adrien1106.reframed.mixin.compat.IndiumTerrainBlockRenderInfoMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(1)));
CONDITIONS.put("fr.adrien1106.reframed.mixin.compat.IndiumAbstractBlockRenderContextMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(1)));
CONDITIONS.put("fr.adrien1106.reframed.mixin.compat.IndiumBlockRenderInfoMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(1)));
CONDITIONS.put("fr.adrien1106.reframed.mixin.compat.IndiumNonTerrainBlockRenderContextMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(1)));
CONDITIONS.put("fr.adrien1106.reframed.mixin.render.BlockRenderContextMixin", () -> !LOADER.isModLoaded(COMPAT_MOD.get(1)));
CONDITIONS.put("fr.adrien1106.reframed.mixin.compat.SodiumBlockOcclusionCacheMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(2)));
CONDITIONS.put("fr.adrien1106.reframed.mixin.render.FluidRendererMixin", () -> !LOADER.isModLoaded(COMPAT_MOD.get(2)));
CONDITIONS.put("fr.adrien1106.reframed.mixin.compat.SodiumFluidRendererMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(2)));
CONDITIONS.put("fr.adrien1106.reframed.mixin.compat.ContinuityConnectionPredicateMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(4)));
CONDITIONS.put("fr.adrien1106.reframed.mixin.compat.ContinuityCTMBakedModelMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(4)));
CONDITIONS.put("fr.adrien1106.reframed.mixin.compat.ContinuityCTMQuadTransformMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(4)));
CONDITIONS.put("fr.adrien1106.reframed.mixin.compat.ContinuityModelWrappingHandlerMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(4)));
CONDITIONS.put("fr.adrien1106.reframed.mixin.compat.AxiomChunkedBlockRegionMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(5)));
CONDITIONS.put("fr.adrien1106.reframed.mixin.compat.AxiomClientBlockEntitySerializerMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(5)));
CONDITIONS.put("fr.adrien1106.reframed.mixin.compat.AxiomClipboardMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(5)));
CONDITIONS.put("fr.adrien1106.reframed.mixin.compat.AxiomCloneBuilderToolMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(5)));
CONDITIONS.put("fr.adrien1106.reframed.mixin.compat.AxiomPlacementMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(5)));
CONDITIONS.put("fr.adrien1106.reframed.mixin.compat.AxiomMappedBlockAndTintGetterMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(5)));
CONDITIONS.put("fr.adrien1106.reframed.mixin.compat.AxiomMoveBuilderToolMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(5)));
CONDITIONS.put("fr.adrien1106.reframed.mixin.compat.AxiomScale3xMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(5)));
CONDITIONS.put("fr.adrien1106.reframed.mixin.compat.AxiomRotSpriteMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(5)));
}

View File

@@ -0,0 +1,166 @@
package fr.adrien1106.reframed.mixin.compat;
import com.llamalad7.mixinextras.sugar.Local;
import com.moulberry.axiom.render.regions.ChunkedBlockRegion;
import com.moulberry.axiom.utils.IntMatrix;
import com.moulberry.axiom.world_modification.CompressedBlockEntity;
import fr.adrien1106.reframed.client.model.MultiRetexturableModel;
import fr.adrien1106.reframed.client.model.RetexturingBakedModel;
import fr.adrien1106.reframed.util.DefaultList;
import fr.adrien1106.reframed.util.mixin.IAxiomChunkedBlockRegionMixin;
import fr.adrien1106.reframed.util.mixin.IMultipartBakedModelMixin;
import fr.adrien1106.reframed.util.mixin.ThemedBlockEntity;
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.client.render.BufferBuilder;
import net.minecraft.client.render.Camera;
import net.minecraft.client.render.OverlayTexture;
import net.minecraft.client.render.block.BlockRenderManager;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.random.Random;
import net.minecraft.world.BlockRenderView;
import org.jetbrains.annotations.Nullable;
import org.joml.Matrix4f;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.util.List;
import java.util.stream.Stream;
import static fr.adrien1106.reframed.block.ReFramedEntity.BLOCKSTATE_KEY;
@Mixin(ChunkedBlockRegion.class) // TODO: Look here for better rotation/flip support
public abstract class AxiomChunkedBlockRegionMixin implements IAxiomChunkedBlockRegionMixin {
@Shadow public abstract BlockState getBlockState(BlockPos pos);
@Shadow public abstract @Nullable BlockEntity getBlockEntity(BlockPos pos);
@Unique
private IntMatrix transform;
@Unique
private IntMatrix inverse_transform;
@Unique
private Long2ObjectMap<CompressedBlockEntity> block_entities;
@Unique
private static boolean isFrameModel(BakedModel model) {
return model instanceof RetexturingBakedModel || model instanceof MultiRetexturableModel;
}
@Unique
private static List<BakedModel> getModels(BakedModel model, BlockState state) {
if (isFrameModel(model))
return List.of(model);
else if (model instanceof IMultipartBakedModelMixin mpm)
return mpm.getModels(state).stream().filter(AxiomChunkedBlockRegionMixin::isFrameModel).toList();
else
return List.of();
}
@Inject(
method = "renderBlock",
at = @At(
value = "INVOKE_ASSIGN",
target = "Lnet/minecraft/client/render/block/BlockRenderManager;getModel(Lnet/minecraft/block/BlockState;)Lnet/minecraft/client/render/model/BakedModel;",
shift = At.Shift.AFTER
),
cancellable = true)
private static void onRenderBlock(BufferBuilder blockBuilder, BlockRenderManager renderer, BlockPos.Mutable pos, Random rand, MatrixStack matrices, BlockRenderView world, Matrix4f currentPoseMatrix, Matrix4f basePoseMatrix, int x, int y, int z, BlockState state, boolean useAmbientOcclusion, CallbackInfo ci, @Local BakedModel model) {
List<BakedModel> models;
if ((models = getModels(model, state)).isEmpty()) return;
DefaultList<BlockState> themes = new DefaultList<>(
Blocks.AIR.getDefaultState(),
world.getBlockEntity(pos) instanceof ThemedBlockEntity themed
? themed.getThemes()
: List.of()
);
models.stream().flatMap(m -> m instanceof MultiRetexturableModel mm
? mm.models().stream()
: Stream.of((RetexturingBakedModel)m)
).forEach(m -> {
m.setCamo(world, themes.get(m.getThemeIndex() - 1), pos);
if (useAmbientOcclusion && state.getLuminance() == 0 && m.useAmbientOcclusion()) renderer.getModelRenderer()
.renderSmooth(world, m, state, pos, matrices, blockBuilder, true, rand, state.getRenderingSeed(pos), OverlayTexture.DEFAULT_UV);
else renderer.getModelRenderer()
.renderFlat(world, m, state, pos, matrices, blockBuilder, true, rand, state.getRenderingSeed(pos), OverlayTexture.DEFAULT_UV);
});
ci.cancel();
}
@Inject(
method = "getBlockEntity",
at = @At("HEAD"),
cancellable = true
)
private void onGetBlockEntity(BlockPos pos, CallbackInfoReturnable<BlockEntity> cir) {
if (inverse_transform == null || block_entities == null) return;
long key = BlockPos.asLong(
inverse_transform.transformX(pos.getX(), pos.getY(), pos.getZ()),
inverse_transform.transformY(pos.getX(), pos.getY(), pos.getZ()),
inverse_transform.transformZ(pos.getX(), pos.getY(), pos.getZ())
);
NbtCompound compound;
if (!block_entities.containsKey(key)
|| !(compound = block_entities.get(key).decompress()).contains(BLOCKSTATE_KEY + 1)
) return;
cir.setReturnValue(new ThemedBlockEntity(compound, pos, getBlockState(pos)));
}
@Inject(
method = "uploadDirty",
at = @At("HEAD")
)
private void onUploadDirty(Camera camera, Vec3d translation, boolean canResort, boolean canUseAmbientOcclusion, CallbackInfo ci) {
if (transform == null) inverse_transform = new IntMatrix();
else inverse_transform = transform.copy();
inverse_transform.invert();
}
@Inject(
method = "flip",
at = @At("RETURN")
)
private void onFlip(Direction.Axis axis, CallbackInfoReturnable<ChunkedBlockRegion> cir) {
((IAxiomChunkedBlockRegionMixin) cir.getReturnValue()).setTransform(transform, block_entities);
}
@Inject(
method = "rotate",
at = @At("RETURN")
)
private void onRotate(Direction.Axis axis, int count, CallbackInfoReturnable<ChunkedBlockRegion> cir) {
((IAxiomChunkedBlockRegionMixin) cir.getReturnValue()).setTransform(transform, block_entities);
}
@Override
public void setTransform(IntMatrix transform, Long2ObjectMap<CompressedBlockEntity> block_entities) {
this.transform = transform;
this.block_entities = block_entities;
}
@Override
public IntMatrix getTransform() {
return transform;
}
@Override
public Long2ObjectMap<CompressedBlockEntity> getBlockEntities() {
return block_entities;
}
}

View File

@@ -0,0 +1,26 @@
package fr.adrien1106.reframed.mixin.compat;
import com.moulberry.axiom.world_modification.ClientBlockEntitySerializer;
import fr.adrien1106.reframed.util.blocks.ThemeableBlockEntity;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.registry.RegistryWrapper;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(ClientBlockEntitySerializer.class)
public class AxiomClientBlockEntitySerializerMixin {
@Inject(
method = "serialize",
at = @At("HEAD"),
remap = false,
cancellable = true
)
private static void serialize(BlockEntity blockEntity, RegistryWrapper.WrapperLookup provider, CallbackInfoReturnable<NbtCompound> cir) {
if (!(blockEntity instanceof ThemeableBlockEntity)) return;
cir.setReturnValue(blockEntity.createNbt());
}
}

View File

@@ -0,0 +1,25 @@
package fr.adrien1106.reframed.mixin.compat;
import com.moulberry.axiom.clipboard.Clipboard;
import com.moulberry.axiom.clipboard.ClipboardObject;
import com.moulberry.axiom.utils.IntMatrix;
import fr.adrien1106.reframed.util.mixin.IAxiomChunkedBlockRegionMixin;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(Clipboard.class)
public class AxiomClipboardMixin {
@Inject(
method = "setClipboard(Lcom/moulberry/axiom/clipboard/ClipboardObject;)I",
at = @At(
value = "TAIL"
),
remap = false
)
private void onInit(ClipboardObject object, CallbackInfoReturnable<Integer> cir) {
((IAxiomChunkedBlockRegionMixin) object.blockRegion()).setTransform(new IntMatrix(), object.blockEntities());
}
}

View File

@@ -0,0 +1,38 @@
package fr.adrien1106.reframed.mixin.compat;
import com.moulberry.axiom.buildertools.CloneBuilderTool;
import com.moulberry.axiom.clipboard.SelectionBuffer;
import com.moulberry.axiom.render.regions.ChunkedBlockRegion;
import com.moulberry.axiom.utils.IntMatrix;
import com.moulberry.axiom.world_modification.CompressedBlockEntity;
import fr.adrien1106.reframed.util.mixin.IAxiomChunkedBlockRegionMixin;
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(CloneBuilderTool.class)
public class AxiomCloneBuilderToolMixin {
@Shadow(remap = false) private ChunkedBlockRegion blockRegion;
@Shadow(remap = false) @Final private IntMatrix transformMatrix;
@Shadow(remap = false) private Long2ObjectMap<CompressedBlockEntity> blockEntities;
@Inject(
method = "lambda$initiateClone$0",
at = @At(
value = "INVOKE_ASSIGN",
target = "Lcom/moulberry/axiom/clipboard/SelectionBuffer$CopyResult;blockEntities()Lit/unimi/dsi/fastutil/longs/Long2ObjectMap;",
shift = At.Shift.AFTER
),
remap = false
)
private void onInitiateClone(int copyId, int offsetX, int offsetY, int offsetZ, SelectionBuffer.CopyResult copyResult, CallbackInfo ci) {
((IAxiomChunkedBlockRegionMixin) blockRegion).setTransform(transformMatrix, blockEntities);
}
}

View File

@@ -0,0 +1,31 @@
package fr.adrien1106.reframed.mixin.compat;
import fr.adrien1106.reframed.block.ReFramedEntity;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(targets = "com.moulberry.axiom.render.ChunkRenderOverrider$MappedBlockAndTintGetter")
public class AxiomMappedBlockAndTintGetterMixin {
@Shadow @Final private World level;
@Inject(
method = "getBlockEntity",
at = @At(
value = "RETURN"
),
cancellable = true
)
private void onGetBlockEntity(BlockPos pos, CallbackInfoReturnable<BlockEntity> cir) {
if (!(level.getBlockEntity(pos) instanceof ReFramedEntity frame_entity)) return;
cir.setReturnValue(frame_entity);
}
}

View File

@@ -0,0 +1,38 @@
package fr.adrien1106.reframed.mixin.compat;
import com.moulberry.axiom.buildertools.MoveBuilderTool;
import com.moulberry.axiom.clipboard.SelectionBuffer;
import com.moulberry.axiom.render.regions.ChunkedBlockRegion;
import com.moulberry.axiom.utils.IntMatrix;
import com.moulberry.axiom.world_modification.CompressedBlockEntity;
import fr.adrien1106.reframed.util.mixin.IAxiomChunkedBlockRegionMixin;
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(MoveBuilderTool.class)
public class AxiomMoveBuilderToolMixin {
@Shadow(remap = false) private ChunkedBlockRegion blockRegion;
@Shadow(remap = false) @Final private IntMatrix transformMatrix;
@Shadow(remap = false) private Long2ObjectMap<CompressedBlockEntity> blockEntities;
@Inject(
method = "lambda$initiateMovement$1",
at = @At(
value = "INVOKE_ASSIGN",
target = "Lcom/moulberry/axiom/clipboard/SelectionBuffer$CopyResult;blockEntities()Lit/unimi/dsi/fastutil/longs/Long2ObjectMap;",
shift = At.Shift.AFTER
),
remap = false
)
private void onInitiateClone(int copyId, int offsetX, int offsetY, int offsetZ, SelectionBuffer.CopyResult copyResult, CallbackInfo ci) {
((IAxiomChunkedBlockRegionMixin) blockRegion).setTransform(transformMatrix, blockEntities);
}
}

View File

@@ -0,0 +1,38 @@
package fr.adrien1106.reframed.mixin.compat;
import com.moulberry.axiom.clipboard.Placement;
import com.moulberry.axiom.render.regions.ChunkedBlockRegion;
import com.moulberry.axiom.utils.IntMatrix;
import com.moulberry.axiom.world_modification.CompressedBlockEntity;
import fr.adrien1106.reframed.util.mixin.IAxiomChunkedBlockRegionMixin;
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
import net.minecraft.util.math.BlockPos;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(Placement.class)
public class AxiomPlacementMixin {
@Shadow(remap = false) private Long2ObjectMap<CompressedBlockEntity> blockEntities;
@Inject(
method = "replacePlacement(Lcom/moulberry/axiom/render/regions/ChunkedBlockRegion;Ljava/lang/String;)V",
at = @At("HEAD"),
remap = false
)
private void onReplacePlacement(ChunkedBlockRegion region, String description, CallbackInfo ci) {
((IAxiomChunkedBlockRegionMixin) region).setTransform(new IntMatrix(), blockEntities);
}
@Inject(
method = "startPlacement(Lnet/minecraft/util/math/BlockPos;Lcom/moulberry/axiom/render/regions/ChunkedBlockRegion;Lit/unimi/dsi/fastutil/longs/Long2ObjectMap;Ljava/lang/String;)I",
at = @At("HEAD")
)
private void onStartPlacement(BlockPos target, ChunkedBlockRegion region, Long2ObjectMap<CompressedBlockEntity> entities, String description, CallbackInfoReturnable<Integer> cir) {
((IAxiomChunkedBlockRegionMixin) region).setTransform(new IntMatrix(), entities);
}
}

View File

@@ -0,0 +1,27 @@
package fr.adrien1106.reframed.mixin.compat;
import com.moulberry.axiom.render.regions.ChunkedBlockRegion;
import com.moulberry.axiom.scaling.RotSprite;
import fr.adrien1106.reframed.util.mixin.IAxiomChunkedBlockRegionMixin;
import org.joml.Matrix4f;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(RotSprite.class)
public class AxiomRotSpriteMixin {
@Inject(
method = "rotateCachedWithOutput",
at = @At(
value = "HEAD"
),
remap = false
)
private static void onRotateCachedWithOutput(ChunkedBlockRegion in, Matrix4f matrix4f, ChunkedBlockRegion out, int x, int y, int z, CallbackInfoReturnable<ChunkedBlockRegion> cir) {
IAxiomChunkedBlockRegionMixin iin = (IAxiomChunkedBlockRegionMixin) in;
((IAxiomChunkedBlockRegionMixin) out).setTransform(iin.getTransform(), iin.getBlockEntities());
}
}

View File

@@ -0,0 +1,29 @@
package fr.adrien1106.reframed.mixin.compat;
import com.llamalad7.mixinextras.sugar.Local;
import com.moulberry.axiom.render.regions.ChunkedBlockRegion;
import com.moulberry.axiom.scaling.Scale3x;
import fr.adrien1106.reframed.util.mixin.IAxiomChunkedBlockRegionMixin;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(Scale3x.class)
public class AxiomScale3xMixin {
@Inject(
method = "scale3x",
at = @At(
value = "INVOKE_ASSIGN",
target = "Lcom/moulberry/axiom/render/regions/ChunkedBlockRegion;<init>()V",
shift = At.Shift.AFTER
),
remap = false
)
private static void onInit(ChunkedBlockRegion in, boolean postProcessing, CallbackInfoReturnable<ChunkedBlockRegion> cir, @Local(ordinal = 1) ChunkedBlockRegion out) {
IAxiomChunkedBlockRegionMixin iin = (IAxiomChunkedBlockRegionMixin) in;
((IAxiomChunkedBlockRegionMixin) out).setTransform(iin.getTransform(), iin.getBlockEntities());
}
}

View File

@@ -0,0 +1,63 @@
package fr.adrien1106.reframed.mixin.compat;
import fr.adrien1106.reframed.client.util.RenderHelper;
import fr.adrien1106.reframed.util.blocks.ThemeableBlockEntity;
import fr.adrien1106.reframed.util.mixin.IBlockRenderInfoMixin;
import link.infra.indium.renderer.render.BlockRenderInfo;
import net.minecraft.block.BlockState;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.BlockRenderView;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(BlockRenderInfo.class)
public abstract class IndiumBlockRenderInfoMixin implements IBlockRenderInfoMixin {
@Shadow public abstract void prepareForBlock(BlockState blockState, BlockPos blockPos, long seed, boolean modelAo);
@Shadow public BlockPos blockPos;
@Shadow public BlockRenderView blockView;
@Shadow public BlockState blockState;
@Unique private int theme_index = 0;
@Unique private int model_hash = 0;
@Inject(
method = "shouldDrawFace",
at = @At(
value = "INVOKE_ASSIGN",
target = "Lnet/minecraft/util/math/Direction;getId()I",
shift = At.Shift.AFTER
),
cancellable = true
)
private void shouldDrawInnerFace(Direction face, CallbackInfoReturnable<Boolean> cir) {
BlockPos other_pos = blockPos.offset(face);
if (!(blockView.getBlockEntity(blockPos) instanceof ThemeableBlockEntity
|| blockView.getBlockEntity(other_pos) instanceof ThemeableBlockEntity)
) return;
cir.setReturnValue(RenderHelper.shouldDrawSide(blockState, blockView, blockPos, face, other_pos, theme_index));
}
@Override
public void prepareForBlock(BlockState blockState, BlockPos blockPos, long seed, boolean modelAo, int theme_index, int model_hash) {
this.theme_index = theme_index;
this.model_hash = model_hash;
prepareForBlock(blockState, blockPos, seed, modelAo);
}
@Override
public int getThemeIndex() {
return theme_index;
}
@Override
public int getModelHash() {
return model_hash;
}
}

View File

@@ -0,0 +1,83 @@
package fr.adrien1106.reframed.mixin.compat;
import fr.adrien1106.reframed.client.model.MultiRetexturableModel;
import fr.adrien1106.reframed.client.model.RetexturingBakedModel;
import fr.adrien1106.reframed.client.util.RenderHelper;
import fr.adrien1106.reframed.util.mixin.IBlockRenderInfoMixin;
import fr.adrien1106.reframed.util.mixin.IMultipartBakedModelMixin;
import link.infra.indium.renderer.aocalc.AoCalculator;
import link.infra.indium.renderer.render.AbstractBlockRenderContext;
import link.infra.indium.renderer.render.BlockRenderInfo;
import link.infra.indium.renderer.render.NonTerrainBlockRenderContext;
import link.infra.indium.renderer.render.SingleBlockLightDataCache;
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
import net.minecraft.block.BlockState;
import net.minecraft.client.render.VertexConsumer;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.random.Random;
import net.minecraft.world.BlockRenderView;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.List;
@Mixin(NonTerrainBlockRenderContext.class)
public abstract class IndiumNonTerrainBlockRenderContextMixin extends AbstractBlockRenderContext {
@Shadow(remap = false) @Final private SingleBlockLightDataCache lightCache;
@Shadow private VertexConsumer vertexConsumer;
@Inject(
method = "render",
at = @At(
value = "INVOKE",
target = "Llink/infra/indium/renderer/render/BlockRenderInfo;prepareForWorld(Lnet/minecraft/world/BlockRenderView;Z)V",
shift = At.Shift.AFTER
),
cancellable = true
)
private void renderMultipleModels(BlockRenderView blockView, BakedModel wrapper, BlockState state, BlockPos pos, MatrixStack matrixStack, VertexConsumer buffer, boolean cull, Random random, long seed, int overlay, CallbackInfo ci) {
if (!(wrapper instanceof IMultipartBakedModelMixin wrapped)) return;
List<BakedModel> models = wrapped.getModels(state);
if (models.stream().noneMatch(bakedModel ->
bakedModel instanceof MultiRetexturableModel
|| bakedModel instanceof RetexturingBakedModel
)) return;
models.forEach(model -> {
if (model instanceof MultiRetexturableModel multi_model) {
RenderHelper.computeInnerCull(state, multi_model.models(), model.hashCode());
multi_model.models().forEach(rexteruable_model ->
renderModel(state, pos, seed, rexteruable_model, aoCalc, blockInfo, this, model.hashCode())
);
} else if (model instanceof RetexturingBakedModel rexteruable_model)
renderModel(state, pos, seed, rexteruable_model, aoCalc, blockInfo, this, model.hashCode());
else model.emitBlockQuads(blockInfo.blockView, blockInfo.blockState, blockInfo.blockPos, blockInfo.randomSupplier, this);
});
blockInfo.release();
lightCache.release();
vertexConsumer = null;
ci.cancel();
}
@Unique
private static void renderModel(BlockState state, BlockPos pos, long seed, RetexturingBakedModel model, AoCalculator aoCalc, BlockRenderInfo block_info, RenderContext context, int model_hash) {
aoCalc.clear();
((IBlockRenderInfoMixin) block_info).prepareForBlock(
state, pos, seed,
model.useAmbientOcclusion(block_info.blockView, pos),
model.getThemeIndex(), model_hash
);
model.emitBlockQuads(block_info.blockView, block_info.blockState, block_info.blockPos, block_info.randomSupplier, context);
}
}

View File

@@ -1,55 +0,0 @@
package fr.adrien1106.reframed.mixin.compat;
import fr.adrien1106.reframed.client.util.RenderHelper;
import fr.adrien1106.reframed.util.mixin.IBlockRenderInfoMixin;
import fr.adrien1106.reframed.util.blocks.ThemeableBlockEntity;
import link.infra.indium.renderer.render.BlockRenderInfo;
import link.infra.indium.renderer.render.TerrainBlockRenderInfo;
import me.jellysquid.mods.sodium.client.render.chunk.compile.pipeline.BlockOcclusionCache;
import net.minecraft.block.BlockState;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.BlockView;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(TerrainBlockRenderInfo.class)
public abstract class IndiumTerrainBlockRenderInfoMixin extends BlockRenderInfo implements IBlockRenderInfoMixin {
@Unique private int theme_index = 0;
@Unique private int model_hash = 0;
@Redirect(
method = "shouldDrawFaceInner",
at = @At(
value = "INVOKE",
target = "Lme/jellysquid/mods/sodium/client/render/chunk/compile/pipeline/BlockOcclusionCache;shouldDrawSide(Lnet/minecraft/block/BlockState;Lnet/minecraft/world/BlockView;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/util/math/Direction;)Z"
)
)
private boolean shouldDrawCamoSide(BlockOcclusionCache instance, BlockState state, BlockView view, BlockPos pos, Direction face) {
BlockPos other_pos = pos.offset(face);
if (!(view.getBlockEntity(pos) instanceof ThemeableBlockEntity
|| view.getBlockEntity(other_pos) instanceof ThemeableBlockEntity))
return instance.shouldDrawSide(state, view, pos, face);
return RenderHelper.shouldDrawSide(state, view, pos, face, other_pos, theme_index);
}
@Override
public void prepareForBlock(BlockState blockState, BlockPos blockPos, long seed, boolean modelAo, int theme_index, int model_hash) {
this.theme_index = theme_index;
this.model_hash = model_hash;
prepareForBlock(blockState, blockPos, seed, modelAo);
}
@Override
public int getThemeIndex() {
return theme_index;
}
@Override
public int getModelHash() {
return model_hash;
}
}

View File

@@ -0,0 +1,62 @@
package fr.adrien1106.reframed.mixin.compat;
import com.llamalad7.mixinextras.sugar.Local;
import fr.adrien1106.reframed.block.ReFramedBlock;
import fr.adrien1106.reframed.util.blocks.ThemeableBlockEntity;
import me.jellysquid.mods.sodium.client.render.chunk.compile.pipeline.FluidRenderer;
import me.jellysquid.mods.sodium.client.world.WorldSlice;
import net.fabricmc.fabric.api.client.render.fluid.v1.FluidRenderHandlerRegistry;
import net.minecraft.block.*;
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 org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(FluidRenderer.class)
public abstract class SodiumFluidRendererMixin {
@Redirect(
method = "isSideExposed",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/block/BlockState;isOpaque()Z"
)
)
private boolean isSideOpaqueExposed(BlockState state) {
if (!(state.getBlock() instanceof ReFramedBlock)) return state.isOpaque();
return true; // forces to compute correct shape
}
@Redirect(
method = "isSideExposed",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/block/BlockState;getCullingShape(Lnet/minecraft/world/BlockView;Lnet/minecraft/util/math/BlockPos;)Lnet/minecraft/util/shape/VoxelShape;"
)
)
private VoxelShape isSideShapeExposed(BlockState state, BlockView world, BlockPos pos) {
if (!(state.getBlock() instanceof ReFramedBlock block)) return state.getCullingShape(world, pos);
return block.getShadingShape(state, world, pos);
}
@Redirect(
method = "render",
at = @At(
value = "INVOKE",
target = "Lnet/fabricmc/fabric/api/client/render/fluid/v1/FluidRenderHandlerRegistry;isBlockTransparent(Lnet/minecraft/block/Block;)Z"
)
)
private boolean getThemeState(FluidRenderHandlerRegistry fluid_handler, Block block, @Local(argsOnly = true) WorldSlice world, @Local(ordinal = 2) BlockPos pos, @Local BlockState state, @Local Direction dir) {
if (!(block instanceof ReFramedBlock rfblock && world.getBlockEntity(pos) instanceof ThemeableBlockEntity framed_entity)) return fluid_handler.isBlockTransparent(block);
return !VoxelShapes.isSideCovered(VoxelShapes.fullCube(), rfblock.getShadingShape(state, world, pos), dir)
&& framed_entity.getThemes().stream()
.anyMatch(s -> s.getBlock() instanceof LeavesBlock
|| s.getBlock() instanceof TranslucentBlock
|| s.getBlock() instanceof AirBlock
);
}
}

View File

@@ -0,0 +1,27 @@
package fr.adrien1106.reframed.mixin.render;
import fr.adrien1106.reframed.client.util.RenderHelper;
import fr.adrien1106.reframed.util.blocks.ThemeableBlockEntity;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.BlockView;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(Block.class)
public abstract class BlockMixin {
@Inject(
method = "shouldDrawSide",
at = @At("HEAD"),
cancellable = true
) // serves as a safety sometimes mods implements culling cache and hence will break some injections...
private static void shouldDrawSide(BlockState state, BlockView world, BlockPos pos, Direction side, BlockPos other_pos, CallbackInfoReturnable<Boolean> cir) {
if (!(world.getBlockEntity(other_pos) instanceof ThemeableBlockEntity)) return;
cir.setReturnValue(RenderHelper.shouldDrawSide(state, world, pos, side, other_pos, 0));
}
}

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