Compare commits

..

2 Commits

19 changed files with 523 additions and 98 deletions

View File

@ -210,6 +210,7 @@ modrinth {
required.project "fabric-api"
optional.version "b1ZV3DIJ", "${project.athena_version}"
optional.version "Orvt0mRa", "${project.indium_version}+mc${project.minecraft_version}"
optional.version "1IjD5062", "${project.continuity_version}"
}
}

View File

@ -28,7 +28,6 @@ import java.util.stream.Stream;
import static fr.adrien1106.reframed.util.blocks.BlockProperties.LIGHT;
/**
* TODO make block pairable by right click -> for v1.6
* 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 ?

View File

@ -15,7 +15,9 @@ 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.recipe.book.RecipeCategory;
import net.minecraft.registry.Registries;
import net.minecraft.state.StateManager;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
@ -31,8 +33,12 @@ import net.minecraft.world.GameRules;
import net.minecraft.world.World;
import org.jetbrains.annotations.Nullable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.stream.IntStream;
import static fr.adrien1106.reframed.block.ReFramedEntity.BLOCKSTATE_KEY;
import static fr.adrien1106.reframed.util.blocks.BlockProperties.LIGHT;
public class ReFramedBlock extends Block implements BlockEntityProvider, RecipeSetter {
@ -97,7 +103,7 @@ public class ReFramedBlock extends Block implements BlockEntityProvider, RecipeS
@Override
public void onStateReplaced(BlockState state, World world, BlockPos pos, BlockState newState, boolean moved) {
if(!state.isOf(newState.getBlock()) &&
if(!(newState.getBlock() instanceof ReFramedBlock) &&
world.getBlockEntity(pos) instanceof ReFramedEntity frame_entity &&
world.getGameRules().getBoolean(GameRules.DO_TILE_DROPS)
) {
@ -122,14 +128,52 @@ public class ReFramedBlock extends Block implements BlockEntityProvider, RecipeS
}
super.onStateReplaced(state, world, pos, newState, moved);
}
@Override
public void onPlaced(World world, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack stack) {
if(world.isClient && world.getBlockEntity(pos) instanceof ReFramedEntity be) {
NbtCompound tag = BlockItem.getBlockEntityNbt(stack);
if(tag != null) be.readNbt(tag);
public void onPlaced(World world, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack stack, BlockState old_state, BlockEntity old_entity) {
if (!(world.getBlockEntity(pos) instanceof ReFramedEntity frame_entity)) {
onPlaced(world, pos, state, placer, stack);
return;
}
super.onPlaced(world, pos, state, placer, stack);
// apply state change keeping the old information
if (old_state.getBlock() instanceof ReFramedBlock old_frame_block
&& old_entity instanceof ReFramedEntity old_frame_entity) {
Map<Integer, Integer> theme_map = old_frame_block.getThemeMap(old_state, state);
theme_map.forEach((self, other) ->
frame_entity.setTheme(old_frame_entity.getTheme(self), other)
);
// apply any changes needed to keep previous properties
if (old_frame_entity.emitsLight() && !frame_entity.emitsLight()) {
frame_entity.toggleLight();
world.setBlockState(pos, state.with(LIGHT, true));
}
if (old_frame_entity.emitsRedstone() && !frame_entity.emitsRedstone()) {
frame_entity.toggleRedstone();
world.updateNeighbors(pos, this);
}
if (old_frame_entity.isSolid() && !frame_entity.isSolid()) frame_entity.toggleSolidity();
// apply themes from item
NbtCompound tag = BlockItem.getBlockEntityNbt(stack);
if(tag != null) {
// determine a list of themes than can be used
Iterator<Integer> free_themes = IntStream
.rangeClosed(1, frame_entity.getThemes().size())
.filter(value -> !theme_map.containsValue(value))
.iterator();
// apply all the themes possible from item
for (int i = 1; tag.contains(BLOCKSTATE_KEY + i) && free_themes.hasNext(); i++) {
BlockState theme = NbtHelper.toBlockState(Registries.BLOCK.getReadOnlyWrapper(), tag.getCompound(BLOCKSTATE_KEY + i));
if (theme == null || theme.getBlock() == Blocks.AIR) continue;
frame_entity.setTheme(theme, free_themes.next());
}
}
} else if(world.isClient) { // prevents flashing with default texture before server sends the update
NbtCompound tag = BlockItem.getBlockEntityNbt(stack);
if(tag != null) frame_entity.readNbt(tag);
}
onPlaced(world, pos, state, placer, stack);
}
@Override
@ -165,10 +209,23 @@ public class ReFramedBlock extends Block implements BlockEntityProvider, RecipeS
return getWeakRedstonePower(state, view, pos, dir);
}
/**
* @param state - the block state to get the top theme index from
* @return the index of the top theme to use for the block
*/
public int getTopThemeIndex(BlockState state) {
return 1;
}
/**
* @param state - the block state of the block that is being replaced
* @param new_state - the block state of the block that is replacing the block
* @return a map of the theme indexes to map when changing state so that the themes are preserved
*/
public Map<Integer, Integer> getThemeMap(BlockState state, BlockState new_state) {
return Map.of();
}
@Override
public void setRecipe(RecipeExporter exporter) {
ShapedRecipeJsonBuilder

View File

@ -7,6 +7,7 @@ import net.minecraft.block.BlockState;
import net.minecraft.block.ShapeContext;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.state.property.Property;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.hit.BlockHitResult;
@ -49,6 +50,29 @@ public abstract class ReFramedDoubleBlock extends ReFramedBlock {
return 0;
}
@SafeVarargs
public final <T extends Comparable<T>> boolean matchesAnyOutline(Vec3d hit, BlockPos pos, Property<T> property, T... values) {
for (T value : values)
if (matchesOutline(hit, pos, property, value)) return true;
return false;
}
public <T extends Comparable<T>> boolean matchesOutline(Vec3d hit, BlockPos pos, Property<T> property, T value) {
Vec3d rel = BlockHelper.getRelativePos(hit, pos);
return BlockHelper.cursorMatchesFace(
getOutlineShape(getDefaultState().with(property, value), null, null, null),
rel
);
}
public <T extends Comparable<T>> 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

View File

@ -15,20 +15,23 @@ 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.BlockItem;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.recipe.book.RecipeCategory;
import net.minecraft.state.StateManager;
import net.minecraft.util.Identifier;
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 org.jetbrains.annotations.Nullable;
import java.util.Map;
import static fr.adrien1106.reframed.util.VoxelHelper.VoxelListBuilder;
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.BlockProperties.*;
import static fr.adrien1106.reframed.util.blocks.Corner.*;
import static net.minecraft.data.client.VariantSettings.Rotation.*;
@ -58,8 +61,32 @@ public class ReFramedHalfStairBlock extends WaterloggableReFramedBlock implement
super.appendProperties(builder.add(CORNER,CORNER_FACE));
}
@Override
public boolean canReplace(BlockState state, ItemPlacementContext context) {
return !(
context.getPlayer().isSneaking()
|| !(context.getStack().getItem() instanceof BlockItem block_item)
|| (
block_item.getBlock() != this
&& block_item.getBlock() != ReFramed.SMALL_CUBE
)
);
}
@Override
public @Nullable BlockState getPlacementState(ItemPlacementContext ctx) {
BlockState current_state = ctx.getWorld().getBlockState(ctx.getBlockPos());
if (current_state.isOf(ReFramed.SMALL_CUBE)) {
Corner corner = current_state.get(CORNER).getOpposite(ctx.getSide().getOpposite());
return ReFramed.HALF_STAIRS_SLAB.getDefaultState()
.with(CORNER, corner)
.with(CORNER_FACE, corner.getDirectionIndex(ctx.getSide().getOpposite()));
}
if (current_state.isOf(this))
return ReFramed.HALF_STAIRS_STAIR.getDefaultState()
.with(EDGE, current_state.get(CORNER).getEdge(current_state.get(CORNER).getDirection(current_state.get(CORNER_FACE))));
Corner corner = BlockHelper.getPlacementCorner(ctx);
return super.getPlacementState(ctx)
.with(CORNER, corner)
@ -71,6 +98,19 @@ public class ReFramedHalfStairBlock extends WaterloggableReFramedBlock implement
return HALF_STAIR_VOXELS[state.get(CORNER_FACE) + state.get(CORNER).getID() * 3];
}
@Override
public Map<Integer, Integer> getThemeMap(BlockState state, BlockState new_state) {
if (new_state.isOf(ReFramed.HALF_STAIRS_SLAB)) return Map.of(1, 1);
if (new_state.isOf(ReFramed.HALF_STAIRS_STAIR))
return Map.of(
1,
state.get(CORNER)
.getDirection(state.get(CORNER_FACE))
.getDirection() == Direction.AxisDirection.POSITIVE ? 2 : 1
);
return super.getThemeMap(state, new_state);
}
@Override
public BlockStateSupplier getMultipart() {
return getHalfStairMultipart(

View File

@ -116,13 +116,13 @@ public class ReFramedHalfStairsStairBlock extends WaterloggableReFramedDoubleBlo
GBlockstate.variant(model_id, true, R0, R270))
/* Z AXIS */
.with(GBlockstate.when(EDGE, DOWN_EAST),
GBlockstate.variant(side_model_id, true, R0, R90))
GBlockstate.variant(reverse_model_id, true, R0, R90))
.with(GBlockstate.when(EDGE, EAST_UP),
GBlockstate.variant(reverse_model_id, true, R180, R270))
GBlockstate.variant(side_model_id, true, R180, R270))
.with(GBlockstate.when(EDGE, UP_WEST),
GBlockstate.variant(side_model_id, true, R180, R90))
GBlockstate.variant(reverse_model_id, true, R180, R90))
.with(GBlockstate.when(EDGE, WEST_DOWN),
GBlockstate.variant(reverse_model_id, true, R0, R270));
GBlockstate.variant(side_model_id, true, R0, R270));
}
@Override

View File

@ -11,6 +11,7 @@ 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.BlockItem;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.recipe.book.RecipeCategory;
import net.minecraft.state.StateManager;
@ -22,7 +23,10 @@ import net.minecraft.util.shape.VoxelShapes;
import net.minecraft.world.BlockView;
import org.jetbrains.annotations.Nullable;
import java.util.Map;
import static net.minecraft.data.client.VariantSettings.Rotation.*;
import static net.minecraft.state.property.Properties.AXIS;
import static net.minecraft.state.property.Properties.FACING;
public class ReFramedSlabBlock extends WaterloggableReFramedBlock implements BlockStateProvider {
@ -53,10 +57,24 @@ public class ReFramedSlabBlock extends WaterloggableReFramedBlock implements Blo
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(builder.add(FACING));
}
@Override
public boolean canReplace(BlockState state, ItemPlacementContext context) {
return !(
context.getPlayer().isSneaking()
|| !(context.getStack().getItem() instanceof BlockItem block_item)
|| block_item.getBlock() != this
);
}
@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());
return super.getPlacementState(ctx).with(FACING, ctx.getSide().getOpposite());
}
@ -76,6 +94,12 @@ public class ReFramedSlabBlock extends WaterloggableReFramedBlock implements Blo
};
}
@Override
public Map<Integer, Integer> getThemeMap(BlockState state, BlockState new_state) {
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);
}
@Override
public MultipartBlockStateSupplier getMultipart() {
Identifier model_id = ReFramed.id("slab_special");

View File

@ -19,8 +19,7 @@ import net.minecraft.util.shape.VoxelShape;
import org.jetbrains.annotations.Nullable;
import static fr.adrien1106.reframed.block.ReFramedSlabBlock.*;
import static net.minecraft.data.client.VariantSettings.Rotation.R0;
import static net.minecraft.data.client.VariantSettings.Rotation.R90;
import static net.minecraft.data.client.VariantSettings.Rotation.*;
import static net.minecraft.state.property.Properties.AXIS;
public class ReFramedSlabsCubeBlock extends ReFramedDoubleBlock implements BlockStateProvider {
@ -55,15 +54,14 @@ public class ReFramedSlabsCubeBlock extends ReFramedDoubleBlock implements Block
public VoxelShape getShape(BlockState state, int i) {
return switch (state.get(AXIS)) {
case Y -> i == 2 ? UP : DOWN;
case Z -> i == 2 ? NORTH : SOUTH;
case Z -> i == 2 ? SOUTH : NORTH;
case X -> i == 2 ? EAST : WEST;
};
}
@Override
public int getTopThemeIndex(BlockState state) {
// when the side is shared just return one
return state.get(AXIS) == Direction.Axis.Y ? 2: super.getTopThemeIndex(state);
return 2;
}
@Override
@ -73,7 +71,7 @@ public class ReFramedSlabsCubeBlock extends ReFramedDoubleBlock implements Block
.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))
GBlockstate.variant(model_id, true, R270, R0))
.with(GBlockstate.when(AXIS, Direction.Axis.X),
GBlockstate.variant(model_id, true, R90, R90));
}

View File

@ -5,6 +5,7 @@ import fr.adrien1106.reframed.generator.BlockStateProvider;
import fr.adrien1106.reframed.generator.GBlockstate;
import fr.adrien1106.reframed.util.VoxelHelper;
import fr.adrien1106.reframed.util.blocks.BlockHelper;
import fr.adrien1106.reframed.util.blocks.Corner;
import net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
@ -14,18 +15,23 @@ 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.BlockItem;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.recipe.book.RecipeCategory;
import net.minecraft.state.StateManager;
import net.minecraft.util.Identifier;
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;
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.CORNER;
import static fr.adrien1106.reframed.util.blocks.BlockProperties.*;
import static fr.adrien1106.reframed.util.blocks.Corner.*;
import static net.minecraft.data.client.VariantSettings.Rotation.*;
@ -53,8 +59,73 @@ public class ReFramedSmallCubeBlock extends WaterloggableReFramedBlock implement
super.appendProperties(builder.add(CORNER));
}
@Override
public boolean canReplace(BlockState state, ItemPlacementContext context) {
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())
)
)
)
)
&& !(
block_item.getBlock() == this
&& !(
corner.hasDirection(context.getSide())
&& BlockHelper.cursorMatchesFace(
getOutlineShape(state, context.getWorld(), context.getBlockPos(), null),
BlockHelper.getRelativePos(context.getHitPos(), context.getBlockPos())
)
)
&& ((ReFramedSmallCubesStepBlock) ReFramed.SMALL_CUBES_STEP)
.matchesAnyOutline(
context.getHitPos(),
context.getBlockPos(),
EDGE,
corner.getEdge(corner.getFirstDirection()),
corner.getEdge(corner.getSecondDirection()),
corner.getEdge(corner.getThirdDirection())
)
)
)
);
}
@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()
.with(CORNER, current_state.get(CORNER))
.with(CORNER_FACE, current_state.get(CORNER_FACE));
if (current_state.isOf(this)) {
Vec3d hit = ctx.getHitPos();
Corner corner = current_state.get(CORNER);
ReFramedSmallCubesStepBlock block = ((ReFramedSmallCubesStepBlock) ReFramed.SMALL_CUBES_STEP);
BlockState state = block.getDefaultState().with(EDGE, corner.getEdge(corner.getFirstDirection()));
if (!block.matchesShape(
hit, pos, state,
corner.getFirstDirection().getDirection() == Direction.AxisDirection.POSITIVE ? 1 : 2
)) state = state.with(EDGE, corner.getEdge(corner.getSecondDirection()));
if (!block.matchesShape(
hit, pos, state,
corner.getSecondDirection().getDirection() == Direction.AxisDirection.POSITIVE ? 1 : 2
)) state = state.with(EDGE, corner.getEdge(corner.getThirdDirection()));
return state;
}
return super.getPlacementState(ctx).with(CORNER, BlockHelper.getPlacementCorner(ctx));
}
@ -63,6 +134,19 @@ public class ReFramedSmallCubeBlock extends WaterloggableReFramedBlock implement
return SMALL_CUBE_VOXELS[state.get(CORNER).getID()];
}
@Override
public Map<Integer, Integer> getThemeMap(BlockState state, BlockState new_state) {
if (new_state.isOf(ReFramed.HALF_STAIRS_SLAB)) return Map.of(1, 2);
if (new_state.isOf(ReFramed.SMALL_CUBES_STEP))
return Map.of(
1,
state.get(CORNER)
.getOtherDirection(new_state.get(EDGE))
.getDirection() == Direction.AxisDirection.POSITIVE ? 2 : 1
);
return super.getThemeMap(state, new_state);
}
@Override
public BlockStateSupplier getMultipart() {
Identifier small_cube_id = ReFramed.id("small_cube_special");

View File

@ -93,13 +93,13 @@ public class ReFramedSmallCubesStepBlock extends WaterloggableReFramedDoubleBloc
return MultipartBlockStateSupplier.create(this)
/* X AXIS */
.with(GBlockstate.when(EDGE, DOWN_EAST),
GBlockstate.variant(reverse_model_id, true, R0, R0))
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(reverse_model_id, true, R180, R180))
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))

View File

@ -16,6 +16,7 @@ import net.minecraft.data.client.When;
import net.minecraft.data.server.recipe.RecipeExporter;
import net.minecraft.data.server.recipe.RecipeProvider;
import net.minecraft.data.server.recipe.ShapedRecipeJsonBuilder;
import net.minecraft.item.BlockItem;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.recipe.book.RecipeCategory;
import net.minecraft.state.StateManager;
@ -30,6 +31,7 @@ import net.minecraft.world.World;
import net.minecraft.world.WorldAccess;
import org.jetbrains.annotations.Nullable;
import java.util.Map;
import java.util.stream.Stream;
import static fr.adrien1106.reframed.util.VoxelHelper.VoxelListBuilder;
@ -63,6 +65,15 @@ public class ReFramedStairBlock extends WaterloggableReFramedBlock implements Bl
super.appendProperties(builder.add(EDGE, STAIR_SHAPE));
}
@Override
public boolean canReplace(BlockState state, ItemPlacementContext context) {
return !(
context.getPlayer().isSneaking()
|| !(context.getStack().getItem() instanceof BlockItem block_item)
|| block_item.getBlock() != ReFramed.STEP
);
}
@Override
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)
@ -70,11 +81,20 @@ public class ReFramedStairBlock extends WaterloggableReFramedBlock implements Bl
}
@Nullable
@Override // Pretty happy of how clean it is (also got it on first try :) )
@Override
public BlockState getPlacementState(ItemPlacementContext ctx) {
Edge face = BlockHelper.getPlacementEdge(ctx);
StairShape shape = BlockHelper.getStairsShape(face, ctx.getWorld(), ctx.getBlockPos());
return super.getPlacementState(ctx).with(EDGE, face).with(STAIR_SHAPE, shape);
BlockState current_state = ctx.getWorld().getBlockState(ctx.getBlockPos());
if (current_state.isOf(ReFramed.STEP)) {
Edge edge = current_state.get(EDGE).opposite();
StairShape shape = BlockHelper.getStairsShape(edge, ctx.getWorld(), ctx.getBlockPos());
return ReFramed.STAIRS_CUBE.getDefaultState()
.with(EDGE, edge)
.with(STAIR_SHAPE, shape);
}
Edge edge = BlockHelper.getPlacementEdge(ctx);
StairShape shape = BlockHelper.getStairsShape(edge, ctx.getWorld(), ctx.getBlockPos());
return super.getPlacementState(ctx).with(EDGE, edge).with(STAIR_SHAPE, shape);
}
@Override
@ -93,6 +113,12 @@ public class ReFramedStairBlock extends WaterloggableReFramedBlock implements Bl
return STAIR_VOXELS[edge.getID() * 9 + shape.getID()];
}
@Override
public Map<Integer, Integer> getThemeMap(BlockState state, BlockState new_state) {
if (new_state.isOf(ReFramed.STAIRS_CUBE)) return Map.of(1, 1);
return super.getThemeMap(state, new_state);
}
@Override
public MultipartBlockStateSupplier getMultipart() {
return getStairMultipart(this, false);
@ -137,94 +163,94 @@ public class ReFramedStairBlock extends WaterloggableReFramedBlock implements Bl
.with(When.anyOf(
GBlockstate.when(EDGE, NORTH_DOWN, STAIR_SHAPE, INNER_RIGHT),
GBlockstate.when(EDGE, WEST_NORTH, STAIR_SHAPE, INNER_RIGHT),
GBlockstate.when(EDGE, WEST_DOWN, STAIR_SHAPE, INNER_LEFT)),
GBlockstate.when(EDGE, WEST_DOWN, STAIR_SHAPE, INNER_RIGHT)),
GBlockstate.variant(inner_id, true, R0, R180))
.with(When.anyOf(
GBlockstate.when(EDGE, NORTH_DOWN, STAIR_SHAPE, INNER_LEFT),
GBlockstate.when(EDGE, NORTH_EAST, STAIR_SHAPE, INNER_RIGHT),
GBlockstate.when(EDGE, DOWN_EAST, STAIR_SHAPE, INNER_LEFT)),
GBlockstate.when(EDGE, DOWN_EAST, STAIR_SHAPE, INNER_RIGHT)),
GBlockstate.variant(inner_id, true, R0, R270))
.with(When.anyOf(
GBlockstate.when(EDGE, DOWN_SOUTH, STAIR_SHAPE, INNER_LEFT),
GBlockstate.when(EDGE, EAST_SOUTH, STAIR_SHAPE, INNER_RIGHT),
GBlockstate.when(EDGE, DOWN_EAST, STAIR_SHAPE, INNER_RIGHT)),
GBlockstate.when(EDGE, DOWN_EAST, STAIR_SHAPE, INNER_LEFT)),
GBlockstate.variant(inner_id, true, R0, R0))
.with(When.anyOf(
GBlockstate.when(EDGE, DOWN_SOUTH, STAIR_SHAPE, INNER_RIGHT),
GBlockstate.when(EDGE, SOUTH_WEST, STAIR_SHAPE, INNER_RIGHT),
GBlockstate.when(EDGE, WEST_DOWN, STAIR_SHAPE, INNER_RIGHT)),
GBlockstate.when(EDGE, WEST_DOWN, STAIR_SHAPE, INNER_LEFT)),
GBlockstate.variant(inner_id, true, R0, R90))
/* INNER TOP */
.with(When.anyOf(
GBlockstate.when(EDGE, EAST_UP, STAIR_SHAPE, INNER_LEFT),
GBlockstate.when(EDGE, EAST_UP, STAIR_SHAPE, INNER_RIGHT),
GBlockstate.when(EDGE, NORTH_EAST, STAIR_SHAPE, INNER_LEFT),
GBlockstate.when(EDGE, UP_NORTH, STAIR_SHAPE, INNER_LEFT)),
GBlockstate.variant(inner_id, true, R180, R0))
.with(When.anyOf(
GBlockstate.when(EDGE, EAST_UP, STAIR_SHAPE, INNER_RIGHT),
GBlockstate.when(EDGE, EAST_UP, STAIR_SHAPE, INNER_LEFT),
GBlockstate.when(EDGE, EAST_SOUTH, STAIR_SHAPE, INNER_LEFT),
GBlockstate.when(EDGE, SOUTH_UP, STAIR_SHAPE, INNER_LEFT)),
GBlockstate.variant(inner_id, true, R180, R90))
.with(When.anyOf(
GBlockstate.when(EDGE, SOUTH_UP, STAIR_SHAPE, INNER_RIGHT),
GBlockstate.when(EDGE, SOUTH_WEST, STAIR_SHAPE, INNER_LEFT),
GBlockstate.when(EDGE, UP_WEST, STAIR_SHAPE, INNER_RIGHT)),
GBlockstate.when(EDGE, UP_WEST, STAIR_SHAPE, INNER_LEFT)),
GBlockstate.variant(inner_id, true, R180, R180))
.with(When.anyOf(
GBlockstate.when(EDGE, UP_NORTH, STAIR_SHAPE, INNER_RIGHT),
GBlockstate.when(EDGE, WEST_NORTH, STAIR_SHAPE, INNER_LEFT),
GBlockstate.when(EDGE, UP_WEST, STAIR_SHAPE, INNER_LEFT)),
GBlockstate.when(EDGE, UP_WEST, STAIR_SHAPE, INNER_RIGHT)),
GBlockstate.variant(inner_id, true, R180, R270))
/* OUTER BOTTOM */
.with(When.anyOf(
GBlockstate.when(EDGE, DOWN_SOUTH, STAIR_SHAPE, SECOND_OUTER_LEFT),
GBlockstate.when(EDGE, DOWN_EAST, STAIR_SHAPE, SECOND_OUTER_RIGHT)),
GBlockstate.when(EDGE, DOWN_EAST, STAIR_SHAPE, SECOND_OUTER_LEFT)),
GBlockstate.variant(outer_id, true, R0, R0))
.with(When.anyOf(
GBlockstate.when(EDGE, DOWN_SOUTH, STAIR_SHAPE, SECOND_OUTER_RIGHT),
GBlockstate.when(EDGE, WEST_DOWN, STAIR_SHAPE, FIRST_OUTER_RIGHT)),
GBlockstate.when(EDGE, WEST_DOWN, STAIR_SHAPE, FIRST_OUTER_LEFT)),
GBlockstate.variant(outer_id, true, R0, R90))
.with(When.anyOf(
GBlockstate.when(EDGE, NORTH_DOWN, STAIR_SHAPE, FIRST_OUTER_RIGHT),
GBlockstate.when(EDGE, WEST_DOWN, STAIR_SHAPE, FIRST_OUTER_LEFT)),
GBlockstate.when(EDGE, WEST_DOWN, STAIR_SHAPE, FIRST_OUTER_RIGHT)),
GBlockstate.variant(outer_id, true, R0, R180))
.with(When.anyOf(
GBlockstate.when(EDGE, NORTH_DOWN, STAIR_SHAPE, FIRST_OUTER_LEFT),
GBlockstate.when(EDGE, DOWN_EAST, STAIR_SHAPE, SECOND_OUTER_LEFT)),
GBlockstate.when(EDGE, DOWN_EAST, STAIR_SHAPE, SECOND_OUTER_RIGHT)),
GBlockstate.variant(outer_id, true, R0, R270))
/* OUTER TOP */
.with(When.anyOf(
GBlockstate.when(EDGE, UP_NORTH, STAIR_SHAPE, SECOND_OUTER_LEFT),
GBlockstate.when(EDGE, EAST_UP, STAIR_SHAPE, FIRST_OUTER_LEFT)),
GBlockstate.when(EDGE, EAST_UP, STAIR_SHAPE, FIRST_OUTER_RIGHT)),
GBlockstate.variant(outer_id, true, R180, R0))
.with(When.anyOf(
GBlockstate.when(EDGE, SOUTH_UP, STAIR_SHAPE, FIRST_OUTER_LEFT),
GBlockstate.when(EDGE, EAST_UP, STAIR_SHAPE, FIRST_OUTER_RIGHT)),
GBlockstate.when(EDGE, EAST_UP, STAIR_SHAPE, FIRST_OUTER_LEFT)),
GBlockstate.variant(outer_id, true, R180, R90))
.with(When.anyOf(
GBlockstate.when(EDGE, SOUTH_UP, STAIR_SHAPE, FIRST_OUTER_RIGHT),
GBlockstate.when(EDGE, UP_WEST, STAIR_SHAPE, SECOND_OUTER_RIGHT)),
GBlockstate.when(EDGE, UP_WEST, STAIR_SHAPE, SECOND_OUTER_LEFT)),
GBlockstate.variant(outer_id, true, R180, R180))
.with(When.anyOf(
GBlockstate.when(EDGE, UP_NORTH, STAIR_SHAPE, SECOND_OUTER_RIGHT),
GBlockstate.when(EDGE, UP_WEST, STAIR_SHAPE, SECOND_OUTER_LEFT)),
GBlockstate.when(EDGE, UP_WEST, STAIR_SHAPE, SECOND_OUTER_RIGHT)),
GBlockstate.variant(outer_id, true, R180, R270))
/* OUTER EAST */
.with(When.anyOf(
GBlockstate.when(EDGE, EAST_SOUTH, STAIR_SHAPE, SECOND_OUTER_RIGHT),
GBlockstate.when(EDGE, DOWN_EAST, STAIR_SHAPE, FIRST_OUTER_RIGHT)),
GBlockstate.when(EDGE, DOWN_EAST, STAIR_SHAPE, FIRST_OUTER_LEFT)),
GBlockstate.variant(outer_side_id, true, R0, R0))
.with(When.anyOf(
GBlockstate.when(EDGE, EAST_SOUTH, STAIR_SHAPE, SECOND_OUTER_LEFT),
GBlockstate.when(EDGE, EAST_UP, STAIR_SHAPE, SECOND_OUTER_RIGHT)),
GBlockstate.when(EDGE, EAST_UP, STAIR_SHAPE, SECOND_OUTER_LEFT)),
GBlockstate.variant(outer_side_id, true, R90, R0))
.with(When.anyOf(
GBlockstate.when(EDGE, NORTH_EAST, STAIR_SHAPE, FIRST_OUTER_LEFT),
GBlockstate.when(EDGE, EAST_UP, STAIR_SHAPE, SECOND_OUTER_LEFT)),
GBlockstate.when(EDGE, EAST_UP, STAIR_SHAPE, SECOND_OUTER_RIGHT)),
GBlockstate.variant(outer_side_id, true, R180, R0))
.with(When.anyOf(
GBlockstate.when(EDGE, NORTH_EAST, STAIR_SHAPE, FIRST_OUTER_RIGHT),
GBlockstate.when(EDGE, DOWN_EAST, STAIR_SHAPE, FIRST_OUTER_LEFT)),
GBlockstate.when(EDGE, DOWN_EAST, STAIR_SHAPE, FIRST_OUTER_RIGHT)),
GBlockstate.variant(outer_side_id, true, R270, R0))
/* OUTER SOUTH */
.with(When.anyOf(
@ -246,19 +272,19 @@ public class ReFramedStairBlock extends WaterloggableReFramedBlock implements Bl
/* OUTER WEST */
.with(When.anyOf(
GBlockstate.when(EDGE, WEST_NORTH, STAIR_SHAPE, SECOND_OUTER_RIGHT),
GBlockstate.when(EDGE, WEST_DOWN, STAIR_SHAPE, SECOND_OUTER_LEFT)),
GBlockstate.when(EDGE, WEST_DOWN, STAIR_SHAPE, SECOND_OUTER_RIGHT)),
GBlockstate.variant(outer_side_id, true, R0, R180))
.with(When.anyOf(
GBlockstate.when(EDGE, WEST_NORTH, STAIR_SHAPE, SECOND_OUTER_LEFT),
GBlockstate.when(EDGE, UP_WEST, STAIR_SHAPE, FIRST_OUTER_LEFT)),
GBlockstate.when(EDGE, UP_WEST, STAIR_SHAPE, FIRST_OUTER_RIGHT)),
GBlockstate.variant(outer_side_id, true, R90, R180))
.with(When.anyOf(
GBlockstate.when(EDGE, SOUTH_WEST, STAIR_SHAPE, FIRST_OUTER_LEFT),
GBlockstate.when(EDGE, UP_WEST, STAIR_SHAPE, FIRST_OUTER_RIGHT)),
GBlockstate.when(EDGE, UP_WEST, STAIR_SHAPE, FIRST_OUTER_LEFT)),
GBlockstate.variant(outer_side_id, true, R180, R180))
.with(When.anyOf(
GBlockstate.when(EDGE, SOUTH_WEST, STAIR_SHAPE, FIRST_OUTER_RIGHT),
GBlockstate.when(EDGE, WEST_DOWN, STAIR_SHAPE, SECOND_OUTER_RIGHT)),
GBlockstate.when(EDGE, WEST_DOWN, STAIR_SHAPE, SECOND_OUTER_LEFT)),
GBlockstate.variant(outer_side_id, true, R270, R180))
/* OUTER NORTH */
.with(When.anyOf(
@ -280,43 +306,43 @@ public class ReFramedStairBlock extends WaterloggableReFramedBlock implements Bl
/* OUTER BOTTOM */
.with(When.anyOf(
GBlockstate.when(EDGE, DOWN_SOUTH, STAIR_SHAPE, OUTER_LEFT),
GBlockstate.when(EDGE, DOWN_EAST, STAIR_SHAPE, OUTER_RIGHT),
GBlockstate.when(EDGE, DOWN_EAST, STAIR_SHAPE, OUTER_LEFT),
GBlockstate.when(EDGE, EAST_SOUTH, STAIR_SHAPE, OUTER_RIGHT)),
GBlockstate.variant(double_outer_id, true, R0, R0))
.with(When.anyOf(
GBlockstate.when(EDGE, DOWN_SOUTH, STAIR_SHAPE, OUTER_RIGHT),
GBlockstate.when(EDGE, WEST_DOWN, STAIR_SHAPE, OUTER_RIGHT),
GBlockstate.when(EDGE, WEST_DOWN, STAIR_SHAPE, OUTER_LEFT),
GBlockstate.when(EDGE, SOUTH_WEST, STAIR_SHAPE, OUTER_RIGHT)),
GBlockstate.variant(double_outer_id, true, R0, R90))
.with(When.anyOf(
GBlockstate.when(EDGE, NORTH_DOWN, STAIR_SHAPE, OUTER_RIGHT),
GBlockstate.when(EDGE, WEST_DOWN, STAIR_SHAPE, OUTER_LEFT),
GBlockstate.when(EDGE, WEST_DOWN, STAIR_SHAPE, OUTER_RIGHT),
GBlockstate.when(EDGE, WEST_NORTH, STAIR_SHAPE, OUTER_RIGHT)),
GBlockstate.variant(double_outer_id, true, R0, R180))
.with(When.anyOf(
GBlockstate.when(EDGE, NORTH_DOWN, STAIR_SHAPE, OUTER_LEFT),
GBlockstate.when(EDGE, DOWN_EAST, STAIR_SHAPE, OUTER_LEFT),
GBlockstate.when(EDGE, DOWN_EAST, STAIR_SHAPE, OUTER_RIGHT),
GBlockstate.when(EDGE, NORTH_EAST, STAIR_SHAPE, OUTER_RIGHT)),
GBlockstate.variant(double_outer_id, true, R0, R270))
/* OUTER TOP */
.with(When.anyOf(
GBlockstate.when(EDGE, UP_NORTH, STAIR_SHAPE, OUTER_LEFT),
GBlockstate.when(EDGE, EAST_UP, STAIR_SHAPE, OUTER_LEFT),
GBlockstate.when(EDGE, EAST_UP, STAIR_SHAPE, OUTER_RIGHT),
GBlockstate.when(EDGE, NORTH_EAST, STAIR_SHAPE, OUTER_LEFT)),
GBlockstate.variant(double_outer_id, true, R180, R0))
.with(When.anyOf(
GBlockstate.when(EDGE, SOUTH_UP, STAIR_SHAPE, OUTER_LEFT),
GBlockstate.when(EDGE, EAST_UP, STAIR_SHAPE, OUTER_RIGHT),
GBlockstate.when(EDGE, EAST_UP, STAIR_SHAPE, OUTER_LEFT),
GBlockstate.when(EDGE, EAST_SOUTH, STAIR_SHAPE, OUTER_LEFT)),
GBlockstate.variant(double_outer_id, true, R180, R90))
.with(When.anyOf(
GBlockstate.when(EDGE, SOUTH_UP, STAIR_SHAPE, OUTER_RIGHT),
GBlockstate.when(EDGE, UP_WEST, STAIR_SHAPE, OUTER_RIGHT),
GBlockstate.when(EDGE, UP_WEST, STAIR_SHAPE, OUTER_LEFT),
GBlockstate.when(EDGE, SOUTH_WEST, STAIR_SHAPE, OUTER_LEFT)),
GBlockstate.variant(double_outer_id, true, R180, R180))
.with(When.anyOf(
GBlockstate.when(EDGE, UP_NORTH, STAIR_SHAPE, OUTER_RIGHT),
GBlockstate.when(EDGE, UP_WEST, STAIR_SHAPE, OUTER_LEFT),
GBlockstate.when(EDGE, UP_WEST, STAIR_SHAPE, OUTER_RIGHT),
GBlockstate.when(EDGE, WEST_NORTH, STAIR_SHAPE, OUTER_LEFT)),
GBlockstate.variant(double_outer_id, true, R180, R270));
}
@ -382,51 +408,51 @@ public class ReFramedStairBlock extends WaterloggableReFramedBlock implements Bl
.add(25, VoxelHelper::rotateCX).add(26, VoxelHelper::rotateCX)
// WEST_DOWN
.add(0, VoxelHelper::rotateCY)
.add(10).add(1)
.add(12).add(3)
.add(16).add(5)
.add(7, VoxelHelper::rotateCY).add(8, VoxelHelper::rotateCY)
.add(1).add(10)
.add(3).add(12)
.add(5).add(16)
.add(8, VoxelHelper::rotateCY).add(7, VoxelHelper::rotateCY)
// DOWN_EAST
.add(36, VoxelHelper::rotateZ)
.add(11).add(2)
.add(13).add(4)
.add(2).add(11)
.add(4).add(13)
.add(41, VoxelHelper::rotateZ).add(42, VoxelHelper::rotateZ)
.add(17).add(6)
.add(6).add(17)
// EAST_UP
.add(45, VoxelHelper::rotateZ)
.add(20).add(29)
.add(22).add(31)
.add(24).add(35)
.add(29).add(20)
.add(31).add(22)
.add(35).add(24)
.add(52, VoxelHelper::rotateZ).add(53, VoxelHelper::rotateZ)
// UP_WEST
.add(54, VoxelHelper::rotateZ)
.add(19).add(28)
.add(21).add(30)
.add(28).add(19)
.add(30).add(21)
.add(59, VoxelHelper::rotateZ).add(60, VoxelHelper::rotateZ)
.add(23).add(34)
.add(34).add(23)
// WEST_NORTH
.add(0, VoxelHelper::rotateCZ)
.add(1).add(28)
.add(3).add(30)
.add(7).add(32)
.add(44).add(69)
.add(43).add(68)
// NORTH_EAST
.add(72, VoxelHelper::rotateY)
.add(2).add(29)
.add(4).add(31)
.add(51).add(62)
.add(50).add(61)
.add(8).add(33)
// EAST_SOUTH
.add(81, VoxelHelper::rotateY)
.add(11).add(20)
.add(13).add(22)
.add(15).add(26)
.add(50).add(61)
.add(51).add(62)
// SOUTH_WEST
.add(90, VoxelHelper::rotateY)
.add(10).add(19)
.add(12).add(21)
.add(43).add(68)
.add(44).add(69)
.add(14).add(25)
.build();
}

View File

@ -15,19 +15,27 @@ 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.BlockItem;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.recipe.book.RecipeCategory;
import net.minecraft.state.StateManager;
import net.minecraft.util.Identifier;
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.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.STAIR_SHAPE;
import static fr.adrien1106.reframed.util.blocks.Edge.*;
import static net.minecraft.data.client.VariantSettings.Rotation.*;
import static net.minecraft.state.property.Properties.AXIS;
import static net.minecraft.state.property.Properties.FACING;
public class ReFramedStepBlock extends WaterloggableReFramedBlock implements BlockStateProvider {
@ -53,9 +61,68 @@ public class ReFramedStepBlock extends WaterloggableReFramedBlock implements Blo
super.appendProperties(builder.add(EDGE));
}
@Override
public boolean canReplace(BlockState state, ItemPlacementContext context) {
Edge edge = state.get(EDGE);
return !(
context.getPlayer().isSneaking()
|| !(context.getStack().getItem() instanceof BlockItem block_item)
|| (
block_item.getBlock() != ReFramed.STAIR
&& !(
block_item.getBlock() == this
&& !(
(edge.isSide(context.getSide()) || edge.hasDirection(context.getSide()))
&& BlockHelper.cursorMatchesFace(
getOutlineShape(state, context.getWorld(), context.getBlockPos(), null),
BlockHelper.getRelativePos(context.getHitPos(), context.getBlockPos())
)
)
&& ((ReFramedStepsSlabBlock) ReFramed.STEPS_SLAB)
.matchesAnyOutline(
context.getHitPos(),
context.getBlockPos(),
FACING,
edge.getFirstDirection(),
edge.getSecondDirection()
)
)
)
);
}
@Nullable
@Override
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))
.with(STAIR_SHAPE, current_state.get(STAIR_SHAPE));
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());
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));
}
@ -68,6 +135,19 @@ public class ReFramedStepBlock extends WaterloggableReFramedBlock implements Blo
return STEP_VOXELS[edge.getID()];
}
@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_SLAB))
return Map.of(
1,
state.get(EDGE)
.getOtherDirection(new_state.get(FACING))
.getDirection() == Direction.AxisDirection.POSITIVE ? 2 : 1
);
return super.getThemeMap(state, new_state);
}
@Override
public BlockStateSupplier getMultipart() {
Identifier model_id = ReFramed.id("step_special");

View File

@ -81,7 +81,7 @@ public class ReFramedStepsSlabBlock extends WaterloggableReFramedDoubleBlock imp
switch (axis) {
case X -> i == 1 ? Direction.WEST : Direction.EAST;
case Y -> i == 1 ? Direction.DOWN : Direction.UP;
case Z -> i == 1 ? Direction.SOUTH : Direction.NORTH;
case Z -> i == 1 ? Direction.NORTH : Direction.SOUTH;
}
));
}
@ -99,14 +99,14 @@ public class ReFramedStepsSlabBlock extends WaterloggableReFramedDoubleBlock imp
.with(GBlockstate.when(FACING, Direction.DOWN, AXIS, Axis.X),
GBlockstate.variant(step_id, true, R0, R180))
.with(GBlockstate.when(FACING, Direction.DOWN, AXIS, Axis.Z),
GBlockstate.variant(step_id, true, R0, R90))
GBlockstate.variant(step_id, true, R0, R270))
.with(GBlockstate.when(FACING, Direction.UP, AXIS, Axis.X),
GBlockstate.variant(step_id, true, R180, R180))
.with(GBlockstate.when(FACING, Direction.UP, AXIS, Axis.Z),
GBlockstate.variant(step_id, true, R180, R90))
GBlockstate.variant(step_id, true, R180, R270))
.with(GBlockstate.when(FACING, Direction.EAST, AXIS, Axis.Z),
GBlockstate.variant(step_side_id, true, R180, R0))
GBlockstate.variant(step_side_id, true, R0, R0))
.with(GBlockstate.when(FACING, Direction.EAST, AXIS, Axis.Y),
GBlockstate.variant(step_side_id, true, R90, R0))
.with(GBlockstate.when(FACING, Direction.SOUTH, AXIS, Axis.X),
@ -114,7 +114,7 @@ public class ReFramedStepsSlabBlock extends WaterloggableReFramedDoubleBlock imp
.with(GBlockstate.when(FACING, Direction.SOUTH, AXIS, Axis.Y),
GBlockstate.variant(step_side_id, true, R90, R90))
.with(GBlockstate.when(FACING, Direction.WEST, AXIS, Axis.Z),
GBlockstate.variant(step_side_id, true, R0, R180))
GBlockstate.variant(step_side_id, true, R180, R180))
.with(GBlockstate.when(FACING, Direction.WEST, AXIS, Axis.Y),
GBlockstate.variant(step_side_id, true, R90, R180))
.with(GBlockstate.when(FACING, Direction.NORTH, AXIS, Axis.X),

View File

@ -16,6 +16,7 @@ import org.jetbrains.annotations.Nullable;
public class WaterloggableReFramedDoubleBlock extends ReFramedDoubleBlock implements Waterloggable {
public WaterloggableReFramedDoubleBlock(Settings settings) {
super(settings);
setDefaultState(getDefaultState().with(Properties.WATERLOGGED, false));
}
@Override

View File

@ -0,0 +1,57 @@
package fr.adrien1106.reframed.mixin.logic;
import fr.adrien1106.reframed.block.ReFramedBlock;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.item.BlockItem;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ActionResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
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.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(BlockItem.class)
public class BlockItemMixin {
@Unique private final ThreadLocal<BlockState> old_state = new ThreadLocal<>();
@Unique private final ThreadLocal<BlockEntity> old_entity = new ThreadLocal<>();
@Redirect(
method = "place(Lnet/minecraft/item/ItemPlacementContext;)Lnet/minecraft/util/ActionResult;",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/block/Block;onPlaced(Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;Lnet/minecraft/entity/LivingEntity;Lnet/minecraft/item/ItemStack;)V"
)
)
private void placeMoreInfo(Block block, World world, BlockPos pos, BlockState state, LivingEntity placer, ItemStack itemStack) {
if (!(block instanceof ReFramedBlock frame_block)) {
block.onPlaced(world, pos, state, placer, itemStack);
return;
}
frame_block.onPlaced(world, pos, state, placer, itemStack, old_state.get(), old_entity.get());
}
@Inject(
method = "place(Lnet/minecraft/item/ItemPlacementContext;)Lnet/minecraft/util/ActionResult;",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/item/BlockItem;place(Lnet/minecraft/item/ItemPlacementContext;Lnet/minecraft/block/BlockState;)Z",
shift = At.Shift.BEFORE
)
)
private void savePreviousInfo(ItemPlacementContext context, CallbackInfoReturnable<ActionResult> cir) {
World world = context.getWorld();
BlockPos pos = context.getBlockPos();
old_state.set(world.getBlockState(pos));
old_entity.set(world.getBlockEntity(pos));
}
}

View File

@ -130,14 +130,14 @@ public class BlockHelper {
return shape;
}
public static String getNeighborPos(Edge face, Direction direction, Boolean reverse, Direction reference, BlockView world, BlockPos pos) {
public static String getNeighborPos(Edge edge, Direction direction, Boolean reverse, Direction reference, BlockView world, BlockPos pos) {
BlockState block_state = world.getBlockState(
pos.offset(reverse ? direction.getOpposite() : direction)
);
if (isStair(block_state) && block_state.get(EDGE).hasDirection(reference)) {
if (block_state.get(EDGE).hasDirection(face.getLeftDirection())) return "left";
else if (block_state.get(EDGE).hasDirection(face.getRightDirection())) return "right";
if (block_state.get(EDGE).hasDirection(edge.getLeftDirection())) return "left";
else if (block_state.get(EDGE).hasDirection(edge.getRightDirection())) return "right";
}
return "";
}

View File

@ -37,6 +37,18 @@ public enum Corner implements StringIdentifiable {
return asString();
}
public Direction getFirstDirection() {
return first_direction;
}
public Direction getSecondDirection() {
return second_direction;
}
public Direction getThirdDirection() {
return third_direction;
}
public boolean hasDirection(Direction direction) {
return this.first_direction.equals(direction)
|| this.second_direction.equals(direction)
@ -94,4 +106,17 @@ public enum Corner implements StringIdentifiable {
Direction other_2 = second_direction == direction || first_direction == direction ? third_direction : second_direction;
return getByDirections(direction, other_1.getOpposite(), other_2.getOpposite());
}
public Edge getEdge(Direction direction) {
return Edge.getByDirections(
first_direction == direction ? second_direction : first_direction,
second_direction == direction || first_direction == direction ? third_direction : second_direction
);
}
public Direction getOtherDirection(Edge edge) {
if (edge.getFirstDirection() != second_direction && edge.getSecondDirection() != second_direction) return second_direction;
if (edge.getFirstDirection() != third_direction && edge.getSecondDirection() != third_direction) return third_direction;
return first_direction;
}
}

View File

@ -49,18 +49,10 @@ public enum Edge implements StringIdentifiable {
return second_direction;
}
public Direction getRightDirection() {
return switch (axis) {
case X -> Direction.WEST;
case Y -> Direction.DOWN;
case Z -> Direction.SOUTH;
};
return Direction.from(axis, Direction.AxisDirection.NEGATIVE);
}
public Direction getLeftDirection() {
return switch (axis) {
case X -> Direction.EAST;
case Y -> Direction.UP;
case Z -> Direction.NORTH;
};
return Direction.from(axis, Direction.AxisDirection.POSITIVE);
}
public boolean hasDirection(Direction direction) {
@ -68,16 +60,32 @@ public enum Edge implements StringIdentifiable {
|| this.second_direction.equals(direction);
}
public Direction.Axis getAxis() {
return this.axis;
}
public int getID() {
return this.ID;
}
public Edge opposite() {
return getByDirections(first_direction.getOpposite(), second_direction.getOpposite());
}
public static Edge getByDirections(Direction direction_1, Direction direction_2) {
return Arrays.stream(Edge.values())
.filter(value -> value.hasDirection(direction_1) && value.hasDirection(direction_2))
.findFirst().orElse(Edge.NORTH_DOWN);
}
public boolean isSide(Direction side) {
return getRightDirection() == side || getLeftDirection() == side;
}
public Direction getOtherDirection(Direction direction) {
return first_direction == direction ? second_direction : first_direction;
}
public static Edge fromId(int id) {
return Arrays.stream(Edge.values())
.filter(value -> value.getID() == id)

View File

@ -6,6 +6,7 @@
"mixins": [
"BlockItemMixin",
"WallBlockAccessor",
"logic.BlockItemMixin",
"particles.MixinEntity",
"particles.MixinLivingEntity"
],