diff --git a/src/main/java/fr/adrien1106/reframedtemplates/Templates.java b/src/main/java/fr/adrien1106/reframedtemplates/Templates.java index 41cba35..3263956 100644 --- a/src/main/java/fr/adrien1106/reframedtemplates/Templates.java +++ b/src/main/java/fr/adrien1106/reframedtemplates/Templates.java @@ -30,17 +30,13 @@ import java.util.stream.Collectors; */ public class Templates implements ModInitializer { public static final String MODID = "reframedtemplates"; - - //addon devs: *Don't* add your blocks to this collection, it's just for my registration convenience since Templates adds a lot of blocks... - @ApiStatus.Internal static final ArrayList INTERNAL_TEMPLATES = new ArrayList<>(); - @ApiStatus.Internal static Block CUBE, STAIRS, SLAB, POST, FENCE, FENCE_GATE, DOOR, TRAPDOOR, IRON_DOOR, IRON_TRAPDOOR, PRESSURE_PLATE, BUTTON, LEVER, WALL, CARPET, PANE, CANDLE; - - //For addon devs: Please don't stuff more blocks into this BlockEntityType, and register your own. - //You can even re-register the same TemplateEntity class under your own ID if you like. (It's an extensible block entity.) - @ApiStatus.Internal public static BlockEntityType TEMPLATE_BLOCK_ENTITY; - - //Changed in TemplatesClient (which is safe since client initializers load after common initializers) - @ApiStatus.Internal public static BiConsumer chunkRerenderProxy = (world, pos) -> {}; + + protected static final ArrayList INTERNAL_TEMPLATES = new ArrayList<>(); + public static Block CUBE, STAIRS, SLAB, POST, FENCE, FENCE_GATE, DOOR, TRAPDOOR, IRON_DOOR, IRON_TRAPDOOR, PRESSURE_PLATE, BUTTON, LEVER, WALL, CARPET, PANE, CANDLE; + + public static BlockEntityType TEMPLATE_BLOCK_ENTITY; + + public static BiConsumer chunkRerenderProxy = (world, pos) -> {}; @Override public void onInitialize() { @@ -69,7 +65,7 @@ public class Templates implements ModInitializer { //The block entity is still called templates:slope; this is a bit of a legacy mistake. TEMPLATE_BLOCK_ENTITY = Registry.register(Registries.BLOCK_ENTITY_TYPE, id("slope"), - FabricBlockEntityTypeBuilder.create((pos, state) -> new TemplateEntity(TEMPLATE_BLOCK_ENTITY, pos, state), INTERNAL_TEMPLATES.toArray(new Block[0])).build(null) + FabricBlockEntityTypeBuilder.create((pos, state) -> new FramedEntity(TEMPLATE_BLOCK_ENTITY, pos, state), INTERNAL_TEMPLATES.toArray(new Block[0])).build(null) ); Registry.register(Registries.ITEM_GROUP, id("tab"), FabricItemGroup.builder() @@ -78,8 +74,7 @@ public class Templates implements ModInitializer { .entries((ctx, e) -> e.addAll(INTERNAL_TEMPLATES.stream().map(ItemStack::new).collect(Collectors.toList()))).build() ); } - - //purely to shorten this call :p + private static AbstractBlock.Settings cp(Block base) { return TemplateInteractionUtil.configureSettings(AbstractBlock.Settings.copy(base)); } diff --git a/src/main/java/fr/adrien1106/reframedtemplates/TemplatesClient.java b/src/main/java/fr/adrien1106/reframedtemplates/TemplatesClient.java index 4146d3f..669edab 100644 --- a/src/main/java/fr/adrien1106/reframedtemplates/TemplatesClient.java +++ b/src/main/java/fr/adrien1106/reframedtemplates/TemplatesClient.java @@ -58,8 +58,9 @@ public class TemplatesClient implements ClientModInitializer { api.addTemplateModel(Templates.id("glass_pane_noside_alt_special"), api.auto(new Identifier("block/glass_pane_noside_alt"))); api.addTemplateModel(Templates.id("pressure_plate_up_special") , api.auto(new Identifier("block/pressure_plate_up"))); api.addTemplateModel(Templates.id("pressure_plate_down_special") , api.auto(new Identifier("block/pressure_plate_down"))); - api.addTemplateModel(Templates.id("slab_special") , api.auto(new Identifier("block/slab"))); + api.addTemplateModel(Templates.id("slab_special") , api.auto(new Identifier("block/slab"))); api.addTemplateModel(Templates.id("stairs_special") , api.auto(new Identifier("block/stairs"))); + api.addTemplateModel(Templates.id("double_outer_stairs_special") , api.auto(Templates.id("block/double_outer_stairs"))); api.addTemplateModel(Templates.id("inner_stairs_special") , api.auto(new Identifier("block/inner_stairs"))); api.addTemplateModel(Templates.id("outer_stairs_special") , api.auto(new Identifier("block/outer_stairs"))); api.addTemplateModel(Templates.id("trapdoor_bottom_special") , api.auto(new Identifier("block/template_trapdoor_bottom"))); @@ -92,7 +93,7 @@ public class TemplatesClient implements ClientModInitializer { api.assignItemModel(Templates.id("trapdoor_bottom_special") , Templates.IRON_TRAPDOOR); api.assignItemModel(Templates.id("fence_post_inventory_special") , Templates.POST); api.assignItemModel(Templates.id("pressure_plate_up_special") , Templates.PRESSURE_PLATE); - api.assignItemModel(Templates.id("slab_bottom_special") , Templates.SLAB); + api.assignItemModel(Templates.id("slab_special") , Templates.SLAB); api.assignItemModel(Templates.id("stairs_special") , Templates.STAIRS); api.assignItemModel(Templates.id("trapdoor_bottom_special") , Templates.TRAPDOOR); api.assignItemModel(Templates.id("wall_inventory_special") , Templates.WALL); diff --git a/src/main/java/fr/adrien1106/reframedtemplates/api/TemplateInteractionUtil.java b/src/main/java/fr/adrien1106/reframedtemplates/api/TemplateInteractionUtil.java index 2324ac9..1b4ad5f 100644 --- a/src/main/java/fr/adrien1106/reframedtemplates/api/TemplateInteractionUtil.java +++ b/src/main/java/fr/adrien1106/reframedtemplates/api/TemplateInteractionUtil.java @@ -1,6 +1,6 @@ package fr.adrien1106.reframedtemplates.api; -import fr.adrien1106.reframedtemplates.block.TemplateEntity; +import fr.adrien1106.reframedtemplates.block.FramedEntity; import net.minecraft.block.AbstractBlock; import net.minecraft.block.Block; import net.minecraft.block.BlockEntityProvider; @@ -61,11 +61,11 @@ public class TemplateInteractionUtil { } public static @Nullable BlockState modifyPlacementState(@Nullable BlockState in, ItemPlacementContext ctx) { - return TemplateEntity.weirdNbtLightLevelStuff(in, ctx.getStack()); + return FramedEntity.weirdNbtLightLevelStuff(in, ctx.getStack()); } public static ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) { - if(!(world.getBlockEntity(pos) instanceof TemplateEntity be)) return ActionResult.PASS; + if(!(world.getBlockEntity(pos) instanceof FramedEntity be)) return ActionResult.PASS; if(!player.canModifyBlocks() || !world.canPlayerModifyAt(player, pos)) return ActionResult.PASS; ItemStack held = player.getStackInHand(hand); @@ -132,7 +132,7 @@ public class TemplateInteractionUtil { //Maybe an odd spot to put this logic but it's consistent w/ vanilla chests, barrels, etc public static void onStateReplaced(BlockState state, World world, BlockPos pos, BlockState newState, boolean moved) { if(!state.isOf(newState.getBlock()) && - world.getBlockEntity(pos) instanceof TemplateEntity template && + world.getBlockEntity(pos) instanceof FramedEntity template && world.getGameRules().getBoolean(GameRules.DO_TILE_DROPS) ) { DefaultedList drops = DefaultedList.of(); @@ -152,7 +152,7 @@ public class TemplateInteractionUtil { public static void onPlaced(World world, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack stack) { //Load the BlockEntityTag clientside, which fixes the template briefly showing its default state when placing it. //I'm surprised this doesn't happen by default; the BlockEntityTag stuff is only done serverside. - if(world.isClient && world.getBlockEntity(pos) instanceof TemplateEntity be) { + if(world.isClient && world.getBlockEntity(pos) instanceof FramedEntity be) { NbtCompound tag = BlockItem.getBlockEntityNbt(stack); if(tag != null) be.readNbt(tag); } @@ -160,7 +160,7 @@ public class TemplateInteractionUtil { //Returns "null" to signal "no opinion". Imagine it like an InteractionResult.PASS. public static @Nullable VoxelShape getCollisionShape(BlockState state, BlockView view, BlockPos pos, ShapeContext ctx) { - return view.getBlockEntity(pos) instanceof TemplateEntity be && !be.isSolid() ? VoxelShapes.empty() : null; + return view.getBlockEntity(pos) instanceof FramedEntity be && !be.isSolid() ? VoxelShapes.empty() : null; } public static boolean emitsRedstonePower(BlockState state) { @@ -169,11 +169,11 @@ public class TemplateInteractionUtil { } public static int getWeakRedstonePower(BlockState state, BlockView view, BlockPos pos, Direction dir) { - return view.getBlockEntity(pos) instanceof TemplateEntity be && be.emitsRedstone() ? 15 : 0; + return view.getBlockEntity(pos) instanceof FramedEntity be && be.emitsRedstone() ? 15 : 0; } public static int getStrongRedstonePower(BlockState state, BlockView view, BlockPos pos, Direction dir) { - return view.getBlockEntity(pos) instanceof TemplateEntity be && be.emitsRedstone() ? 15 : 0; + return view.getBlockEntity(pos) instanceof FramedEntity be && be.emitsRedstone() ? 15 : 0; } public static int luminance(BlockState state) { diff --git a/src/main/java/fr/adrien1106/reframedtemplates/block/TemplateEntity.java b/src/main/java/fr/adrien1106/reframedtemplates/block/FramedEntity.java similarity index 98% rename from src/main/java/fr/adrien1106/reframedtemplates/block/TemplateEntity.java rename to src/main/java/fr/adrien1106/reframedtemplates/block/FramedEntity.java index 3d9fe5e..1db358c 100644 --- a/src/main/java/fr/adrien1106/reframedtemplates/block/TemplateEntity.java +++ b/src/main/java/fr/adrien1106/reframedtemplates/block/FramedEntity.java @@ -26,7 +26,7 @@ import java.util.Objects; //Keeping the weight of this block entity down, both in terms of memory consumption and NBT sync traffic, //is pretty important since players might place a lot of them. There were tons and tons of these at Blanketcon. //To that end, most of the state has been crammed into a bitfield. -public class TemplateEntity extends BlockEntity implements ThemeableBlockEntity { +public class FramedEntity extends BlockEntity implements ThemeableBlockEntity { protected BlockState renderedState = Blocks.AIR.getDefaultState(); protected byte bitfield = DEFAULT_BITFIELD; @@ -43,7 +43,7 @@ public class TemplateEntity extends BlockEntity implements ThemeableBlockEntity protected static final String BLOCKSTATE_KEY = "s"; protected static final String BITFIELD_KEY = "b"; - public TemplateEntity(BlockEntityType type, BlockPos pos, BlockState state) { + public FramedEntity(BlockEntityType type, BlockPos pos, BlockState state) { super(type, pos, state); } diff --git a/src/main/java/fr/adrien1106/reframedtemplates/block/TemplateStairsBlock.java b/src/main/java/fr/adrien1106/reframedtemplates/block/TemplateStairsBlock.java index 013e094..d51b411 100644 --- a/src/main/java/fr/adrien1106/reframedtemplates/block/TemplateStairsBlock.java +++ b/src/main/java/fr/adrien1106/reframedtemplates/block/TemplateStairsBlock.java @@ -1,96 +1,393 @@ package fr.adrien1106.reframedtemplates.block; -import com.google.common.base.MoreObjects; import fr.adrien1106.reframedtemplates.Templates; -import fr.adrien1106.reframedtemplates.api.TemplateInteractionUtil; +import fr.adrien1106.reframedtemplates.generator.GBlockstate; +import fr.adrien1106.reframedtemplates.generator.MultipartBlockStateProvider; +import fr.adrien1106.reframedtemplates.util.VoxelHelper; +import fr.adrien1106.reframedtemplates.util.property.StairDirection; +import fr.adrien1106.reframedtemplates.util.property.StairShape; import net.minecraft.block.Block; -import net.minecraft.block.BlockEntityProvider; import net.minecraft.block.BlockState; -import net.minecraft.block.Blocks; import net.minecraft.block.ShapeContext; -import net.minecraft.block.StairsBlock; -import net.minecraft.block.entity.BlockEntity; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.data.client.*; import net.minecraft.item.ItemPlacementContext; -import net.minecraft.item.ItemStack; import net.minecraft.state.StateManager; -import net.minecraft.util.ActionResult; -import net.minecraft.util.Hand; -import net.minecraft.util.hit.BlockHitResult; +import net.minecraft.state.property.EnumProperty; +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.math.Direction.Axis; +import net.minecraft.util.math.Vec3d; 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; -public class TemplateStairsBlock extends StairsBlock implements BlockEntityProvider { - public TemplateStairsBlock(BlockState blockState, Settings settings) { - super(blockState, settings); - setDefaultState(TemplateInteractionUtil.setDefaultStates(getDefaultState())); - } - +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Stream; + +import static fr.adrien1106.reframedtemplates.util.property.StairShape.*; +import static net.minecraft.data.client.VariantSettings.Rotation.*; +import static fr.adrien1106.reframedtemplates.util.property.StairDirection.*; + +public class TemplateStairsBlock extends WaterloggableTemplateBlock implements MultipartBlockStateProvider { + + public static final EnumProperty FACING = EnumProperty.of("facing", StairDirection.class); + public static final EnumProperty SHAPE = EnumProperty.of("shape", StairShape.class); + private static final List VOXEL_LIST= new ArrayList<>(); + public TemplateStairsBlock(Settings settings) { - this(Blocks.OAK_PLANKS.getDefaultState(), settings); - } - - @Nullable - @Override - public BlockEntity createBlockEntity(BlockPos pos, BlockState state) { - return Templates.TEMPLATE_BLOCK_ENTITY.instantiate(pos, state); + super(settings); + setDefaultState(getDefaultState().with(FACING, StairDirection.NORTH_DOWN).with(SHAPE, STRAIGHT)); } @Override protected void appendProperties(StateManager.Builder builder) { - super.appendProperties(TemplateInteractionUtil.appendProperties(builder)); + super.appendProperties(builder.add(FACING).add(SHAPE)); } - + + @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) + .with(SHAPE, getPlacementShape(state.get(FACING), world, pos)); + } + @Nullable - @Override + @Override // Pretty happy of how clean it is (also got it on first try :) ) public BlockState getPlacementState(ItemPlacementContext ctx) { - return TemplateInteractionUtil.modifyPlacementState(super.getPlacementState(ctx), ctx); + BlockState state = super.getPlacementState(ctx); + Direction side = ctx.getSide().getOpposite(); + BlockPos block_pos = ctx.getBlockPos(); + Vec3d hit_pos = ctx.getHitPos(); + Vec3d pos = new Vec3d( + hit_pos.getX() - block_pos.getX() - .5d, + hit_pos.getY() - block_pos.getY() - .5d, + hit_pos.getZ() - block_pos.getZ() - .5d + ); + + Stream axes = Stream.of(Axis.values()).filter(axis -> !axis.equals(side.getAxis())); + Axis axis = axes.reduce((axis_1, axis_2) -> + Math.abs(axis_1.choose(pos.x, pos.y, pos.z)) > Math.abs(axis_2.choose(pos.x, pos.y, pos.z)) + ? axis_1 + : axis_2 + ).get(); + + Direction part_direction = Direction.from( + axis, + axis.choose(pos.x, pos.y, pos.z) > 0 + ? Direction.AxisDirection.POSITIVE + : Direction.AxisDirection.NEGATIVE + ); + + return state.with(FACING, StairDirection.getByDirections(side, part_direction)); } - - @Override - public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) { - ActionResult r = TemplateInteractionUtil.onUse(state, world, pos, player, hand, hit); - if(!r.isAccepted()) r = super.onUse(state, world, pos, player, hand, hit); - return r; - } - + @Override public void onStateReplaced(BlockState state, World world, BlockPos pos, BlockState newState, boolean moved) { - TemplateInteractionUtil.onStateReplaced(state, world, pos, newState, moved); super.onStateReplaced(state, world, pos, newState, moved); - + //StairsBlock onStateReplaced is Weird! it doesn't delegate to regular block onStateReplaced! if(!state.isOf(newState.getBlock())) world.removeBlockEntity(pos); } - + + /* ---------------------------------- DON'T GO FURTHER IF YOU LIKE HAVING EYES ---------------------------------- */ @Override - public void onPlaced(World world, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack stack) { - TemplateInteractionUtil.onPlaced(world, pos, state, placer, stack); - super.onPlaced(world, pos, state, placer, stack); + public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) { + StairShape shape = state.get(SHAPE); + StairDirection direction = state.get(FACING); + return switch (shape) { + case STRAIGHT -> + switch (direction) { + case DOWN_SOUTH -> VOXEL_LIST.get(0); + case NORTH_DOWN -> VOXEL_LIST.get(1); + case UP_NORTH -> VOXEL_LIST.get(2); + case SOUTH_UP -> VOXEL_LIST.get(3); + case DOWN_EAST -> VOXEL_LIST.get(4); + case WEST_DOWN -> VOXEL_LIST.get(5); + case UP_WEST -> VOXEL_LIST.get(6); + case EAST_UP -> VOXEL_LIST.get(7); + case NORTH_EAST -> VOXEL_LIST.get(8); + case EAST_SOUTH -> VOXEL_LIST.get(9); + case SOUTH_WEST -> VOXEL_LIST.get(10); + case WEST_NORTH -> VOXEL_LIST.get(11); + }; + case INNER_LEFT -> + switch (direction) { + case WEST_DOWN, NORTH_DOWN -> VOXEL_LIST.get(44); + case DOWN_EAST -> VOXEL_LIST.get(45); + case DOWN_SOUTH -> VOXEL_LIST.get(47); + case UP_WEST, UP_NORTH, WEST_NORTH -> VOXEL_LIST.get(48); + case EAST_UP, NORTH_EAST -> VOXEL_LIST.get(49); + case EAST_SOUTH -> VOXEL_LIST.get(50); + case SOUTH_UP, SOUTH_WEST -> VOXEL_LIST.get(51); + }; + case INNER_RIGHT -> + switch (direction) { + case WEST_NORTH -> VOXEL_LIST.get(44); + case NORTH_DOWN, NORTH_EAST -> VOXEL_LIST.get(45); + case DOWN_EAST, DOWN_SOUTH, EAST_SOUTH -> VOXEL_LIST.get(46); + case WEST_DOWN, SOUTH_WEST -> VOXEL_LIST.get(47); + case UP_NORTH -> VOXEL_LIST.get(49); + case EAST_UP, SOUTH_UP -> VOXEL_LIST.get(50); + case UP_WEST -> VOXEL_LIST.get(51); + }; + case OUTER_LEFT -> + switch (direction) { + case DOWN_EAST -> VOXEL_LIST.get(43); + case WEST_DOWN, NORTH_DOWN -> VOXEL_LIST.get(42); + case DOWN_SOUTH -> VOXEL_LIST.get(41); + case EAST_UP, NORTH_EAST -> VOXEL_LIST.get(39); + case UP_WEST, UP_NORTH, WEST_NORTH -> VOXEL_LIST.get(38); + case SOUTH_UP, SOUTH_WEST -> VOXEL_LIST.get(37); + case EAST_SOUTH -> VOXEL_LIST.get(36); + }; + case OUTER_RIGHT -> + switch (direction) { + case NORTH_DOWN, NORTH_EAST -> VOXEL_LIST.get(43); + case WEST_NORTH -> VOXEL_LIST.get(42); + case WEST_DOWN, SOUTH_WEST -> VOXEL_LIST.get(41); + case DOWN_EAST, DOWN_SOUTH, EAST_SOUTH -> VOXEL_LIST.get(40); + case UP_NORTH -> VOXEL_LIST.get(39); + case UP_WEST -> VOXEL_LIST.get(37); + case EAST_UP, SOUTH_UP -> VOXEL_LIST.get(36); + }; + case FIRST_OUTER_LEFT -> + switch (direction) { + case WEST_DOWN, NORTH_DOWN -> VOXEL_LIST.get(14); + case SOUTH_UP -> VOXEL_LIST.get(17); + case EAST_UP -> VOXEL_LIST.get(19); + case EAST_SOUTH -> VOXEL_LIST.get(20); + case DOWN_SOUTH -> VOXEL_LIST.get(22); + case UP_NORTH, WEST_NORTH -> VOXEL_LIST.get(25); + case SOUTH_WEST -> VOXEL_LIST.get(28); + case UP_WEST -> VOXEL_LIST.get(31); + case DOWN_EAST -> VOXEL_LIST.get(34); + case NORTH_EAST -> VOXEL_LIST.get(35); + }; + case FIRST_OUTER_RIGHT -> + switch (direction) { + case NORTH_DOWN -> VOXEL_LIST.get(15); + case SOUTH_UP, EAST_UP -> VOXEL_LIST.get(16); + case WEST_DOWN -> VOXEL_LIST.get(13); + case DOWN_SOUTH, EAST_SOUTH -> VOXEL_LIST.get(23); + case UP_NORTH -> VOXEL_LIST.get(24); + case WEST_NORTH -> VOXEL_LIST.get(26); + case UP_WEST -> VOXEL_LIST.get(28); + case SOUTH_WEST -> VOXEL_LIST.get(29); + case DOWN_EAST -> VOXEL_LIST.get(33); + case NORTH_EAST -> VOXEL_LIST.get(34); + }; + case SECOND_OUTER_LEFT -> + switch (direction) { + case DOWN_EAST -> VOXEL_LIST.get(15); + case DOWN_SOUTH -> VOXEL_LIST.get(13); + case UP_WEST, UP_NORTH -> VOXEL_LIST.get(18); + case SOUTH_UP, SOUTH_WEST -> VOXEL_LIST.get(21); + case NORTH_EAST -> VOXEL_LIST.get(24); + case NORTH_DOWN -> VOXEL_LIST.get(26); + case WEST_DOWN -> VOXEL_LIST.get(30); + case WEST_NORTH -> VOXEL_LIST.get(31); + case EAST_SOUTH -> VOXEL_LIST.get(32); + case EAST_UP -> VOXEL_LIST.get(35); + }; + case SECOND_OUTER_RIGHT -> + switch (direction) { + case DOWN_SOUTH, DOWN_EAST -> VOXEL_LIST.get(12); + case UP_WEST -> VOXEL_LIST.get(17); + case UP_NORTH -> VOXEL_LIST.get(19); + case SOUTH_UP -> VOXEL_LIST.get(20); + case SOUTH_WEST -> VOXEL_LIST.get(22); + case NORTH_EAST, NORTH_DOWN -> VOXEL_LIST.get(27); + case WEST_DOWN -> VOXEL_LIST.get(29); + case WEST_NORTH -> VOXEL_LIST.get(30); + case EAST_UP -> VOXEL_LIST.get(32); + case EAST_SOUTH -> VOXEL_LIST.get(33); + }; + }; } - - @Override - public VoxelShape getCollisionShape(BlockState state, BlockView view, BlockPos pos, ShapeContext ctx) { - return MoreObjects.firstNonNull(TemplateInteractionUtil.getCollisionShape(state, view, pos, ctx), super.getCollisionShape(state, view, pos, ctx)); + + private static String getNeighborPos(StairDirection face, Direction direction, Boolean reverse, Direction reference, BlockView world, BlockPos pos) { + BlockState block_state = world.getBlockState( + pos.offset(reverse ? direction.getOpposite() : direction) + ); + + if (block_state.getBlock() instanceof TemplateStairsBlock && block_state.get(FACING).hasDirection(reference)) { + if (block_state.get(FACING).hasDirection(face.getLeftDirection())) return "left"; + else if (block_state.get(FACING).hasDirection(face.getRightDirection())) return "right"; + } + return ""; } - - @Override - public boolean emitsRedstonePower(BlockState state) { - return TemplateInteractionUtil.emitsRedstonePower(state); + + private static StairShape getPlacementShape(StairDirection face, BlockView world, BlockPos pos) { + StairShape shape = STRAIGHT; + + String sol = getNeighborPos(face, face.getFirstDirection(), true, face.getSecondDirection(), world, pos); + switch (sol) { + case "right": return INNER_RIGHT; + case "left": return INNER_LEFT; + } + + sol = getNeighborPos(face, face.getSecondDirection(), true, face.getFirstDirection(), world, pos); + switch (sol) { + case "right": return INNER_RIGHT; + case "left": return INNER_LEFT; + } + + sol = getNeighborPos(face, face.getFirstDirection(), false, face.getSecondDirection(), world, pos); + switch (sol) { + case "right" -> shape = FIRST_OUTER_RIGHT; + case "left" -> shape = FIRST_OUTER_LEFT; + } + + sol = getNeighborPos(face, face.getSecondDirection(), false, face.getFirstDirection(), world, pos); + switch (sol) { + case "right" -> { + if (shape.equals(STRAIGHT)) shape = SECOND_OUTER_RIGHT; + else if (shape.equals(FIRST_OUTER_RIGHT)) shape = OUTER_RIGHT; + } + case "left" -> { + if (shape.equals(STRAIGHT)) shape = SECOND_OUTER_LEFT; + else if (shape.equals(FIRST_OUTER_LEFT)) shape = OUTER_LEFT; + } + } + + return shape; } - + @Override - public int getWeakRedstonePower(BlockState state, BlockView view, BlockPos pos, Direction dir) { - return TemplateInteractionUtil.getWeakRedstonePower(state, view, pos, dir); + public MultipartBlockStateSupplier getMultipart() { + Identifier straight_id = Templates.id("stairs_special"); + Identifier double_outer_id = Templates.id("double_outer_stairs_special"); + Identifier inner_id = Templates.id("inner_stairs_special"); + Identifier outer_id = Templates.id("outer_stairs_special"); + return MultipartBlockStateSupplier.create(this) + /* STRAIGHT X AXIS */ + .with(GBlockstate.when(FACING, DOWN_EAST, SHAPE, STRAIGHT), + GBlockstate.variant(straight_id, true, R0, R0)) + .with(GBlockstate.when(FACING, EAST_UP, SHAPE, STRAIGHT), + GBlockstate.variant(straight_id, true, R180, R0)) + .with(GBlockstate.when(FACING, UP_WEST, SHAPE, STRAIGHT), + GBlockstate.variant(straight_id, true, R180, R180)) + .with(GBlockstate.when(FACING, WEST_DOWN, SHAPE, STRAIGHT), + GBlockstate.variant(straight_id, true, R0, R180)) + /* STRAIGHT Y AXIS */ + .with(GBlockstate.when(FACING, EAST_SOUTH, SHAPE, STRAIGHT), + GBlockstate.variant(straight_id, true, R90, R0)) + .with(GBlockstate.when(FACING, SOUTH_WEST, SHAPE, STRAIGHT), + GBlockstate.variant(straight_id, true, R90, R90)) + .with(GBlockstate.when(FACING, WEST_NORTH, SHAPE, STRAIGHT), + GBlockstate.variant(straight_id, true, R90, R180)) + .with(GBlockstate.when(FACING, NORTH_EAST, SHAPE, STRAIGHT), + GBlockstate.variant(straight_id, true, R90, R270)) + /* STRAIGHT Z AXIS */ + .with(GBlockstate.when(FACING, DOWN_SOUTH, SHAPE, STRAIGHT), + GBlockstate.variant(straight_id, true, R0, R90)) + .with(GBlockstate.when(FACING, NORTH_DOWN, SHAPE, STRAIGHT), + GBlockstate.variant(straight_id, true, R0, R270)) + .with(GBlockstate.when(FACING, UP_NORTH, SHAPE, STRAIGHT), + GBlockstate.variant(straight_id, true, R180, R270)) + .with(GBlockstate.when(FACING, SOUTH_UP, SHAPE, STRAIGHT), + GBlockstate.variant(straight_id, true, R180, R90)) + /* OUTER X AXIS */ + .with(GBlockstate.when(FACING, DOWN_EAST, SHAPE, FIRST_OUTER_RIGHT), + GBlockstate.variant(outer_id, true, R0, R0)) + .with(GBlockstate.when(FACING, DOWN_EAST, SHAPE, INNER_LEFT), + GBlockstate.variant(inner_id, true, R0, R270)) + /* OUTER DOUBLE */ + .with(GBlockstate.when(FACING, NORTH_DOWN, SHAPE, OUTER_LEFT), + GBlockstate.variant(double_outer_id, true, R0, R180)) + .with(GBlockstate.when(FACING, NORTH_DOWN, SHAPE, OUTER_RIGHT), + GBlockstate.variant(double_outer_id, true, R0, R270)); } - - @Override - public int getStrongRedstonePower(BlockState state, BlockView view, BlockPos pos, Direction dir) { - return TemplateInteractionUtil.getStrongRedstonePower(state, view, pos, dir); + + static { + final VoxelShape STRAIGHT = Stream.of( + VoxelShapes.cuboid(0.0f, 0.0f, 0.0f, 1.0f, 0.5f, 1.0f), + VoxelShapes.cuboid(0.0f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f) + ).reduce((previous, current) -> VoxelShapes.combineAndSimplify(previous, current, BooleanBiFunction.OR)).get(); + final VoxelShape JUNCTION = Stream.of( + VoxelShapes.cuboid(0.0f, 0.0f, 0.0f, 1.0f, 0.5f, 1.0f), + VoxelShapes.cuboid(0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f) + ).reduce((previous, current) -> VoxelShapes.combineAndSimplify(previous, current, BooleanBiFunction.OR)).get(); + final VoxelShape INNER = Stream.of( + VoxelShapes.cuboid(0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f), + VoxelShapes.cuboid(0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 0.5f), + VoxelShapes.cuboid(0.0f, 0.5f, 0.5f, 0.5f, 1.0f, 1.0f), + VoxelShapes.cuboid(0.5f, 0.0f, 0.5f, 1.0f, 0.5f, 1.0f) + ).reduce((previous, current) -> VoxelShapes.combineAndSimplify(previous, current, BooleanBiFunction.OR)).get(); + final VoxelShape OUTER = Stream.of( + VoxelShapes.cuboid(0.0f, 0.0f, 0.0f, 1.0f, 0.5f, 1.0f), + VoxelShapes.cuboid(0.0f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f), + VoxelShapes.cuboid(0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 0.5f) + ).reduce((previous, current) -> VoxelShapes.combineAndSimplify(previous, current, BooleanBiFunction.OR)).get(); + + VOXEL_LIST.add(STRAIGHT); + VOXEL_LIST.add(VoxelHelper.mirror(STRAIGHT, Axis.Z)); + VOXEL_LIST.add(VoxelHelper.mirror(VoxelHelper.rotateCounterClockwise(STRAIGHT, Axis.X), Axis.Z)); + VOXEL_LIST.add(VoxelHelper.rotateCounterClockwise(STRAIGHT, Axis.X)); + + VOXEL_LIST.add(VoxelHelper.rotateCounterClockwise(STRAIGHT, Axis.Y)); + VOXEL_LIST.add(VoxelHelper.mirror(VoxelHelper.rotateCounterClockwise(STRAIGHT, Axis.Y), Axis.X)); + VOXEL_LIST.add(VoxelHelper.mirror(VoxelHelper.rotateClockwise(VoxelHelper.rotateCounterClockwise(STRAIGHT, Axis.Y), Axis.Z), Axis.X)); + VOXEL_LIST.add(VoxelHelper.rotateClockwise(VoxelHelper.rotateCounterClockwise(STRAIGHT, Axis.Y), Axis.Z)); + + VOXEL_LIST.add(VoxelHelper.rotateCounterClockwise(VoxelHelper.rotateClockwise(STRAIGHT, Axis.Z), Axis.Y)); + VOXEL_LIST.add(VoxelHelper.rotateClockwise(STRAIGHT, Axis.Z)); + VOXEL_LIST.add(VoxelHelper.rotateClockwise(VoxelHelper.rotateClockwise(STRAIGHT, Axis.Z), Axis.Y)); + VOXEL_LIST.add(VoxelHelper.mirror(VoxelHelper.rotateClockwise(VoxelHelper.rotateClockwise(STRAIGHT, Axis.Z), Axis.Y), Axis.Z)); + + VOXEL_LIST.add(JUNCTION); + VOXEL_LIST.add(VoxelHelper.rotateClockwise(JUNCTION, Axis.Y)); + VOXEL_LIST.add(VoxelHelper.rotateClockwise(VoxelHelper.rotateClockwise(JUNCTION, Axis.Y), Axis.Y)); + VOXEL_LIST.add(VoxelHelper.rotateCounterClockwise(JUNCTION, Axis.Y)); + + VOXEL_LIST.add(VoxelHelper.mirror(JUNCTION, Axis.Y)); + VOXEL_LIST.add(VoxelHelper.rotateClockwise(VoxelHelper.mirror(JUNCTION, Axis.Y), Axis.Y)); + VOXEL_LIST.add(VoxelHelper.rotateClockwise(VoxelHelper.rotateClockwise(VoxelHelper.mirror(JUNCTION, Axis.Y), Axis.Y), Axis.Y)); + VOXEL_LIST.add(VoxelHelper.rotateCounterClockwise(VoxelHelper.mirror(JUNCTION, Axis.Y), Axis.Y)); + + VOXEL_LIST.add(VoxelHelper.rotateCounterClockwise(JUNCTION, Axis.X)); + VOXEL_LIST.add(VoxelHelper.rotateClockwise(VoxelHelper.rotateCounterClockwise(JUNCTION, Axis.X), Axis.Z)); + VOXEL_LIST.add(VoxelHelper.rotateClockwise(VoxelHelper.rotateClockwise(VoxelHelper.rotateCounterClockwise(JUNCTION, Axis.X), Axis.Z), Axis.Z)); + VOXEL_LIST.add(VoxelHelper.rotateCounterClockwise(VoxelHelper.rotateCounterClockwise(JUNCTION, Axis.X), Axis.Z)); + + VOXEL_LIST.add(VoxelHelper.mirror(VoxelHelper.rotateCounterClockwise(JUNCTION, Axis.X), Axis.Z)); + VOXEL_LIST.add(VoxelHelper.rotateClockwise(VoxelHelper.mirror(VoxelHelper.rotateCounterClockwise(JUNCTION, Axis.X), Axis.Z), Axis.Z)); + VOXEL_LIST.add(VoxelHelper.rotateClockwise(VoxelHelper.rotateClockwise(VoxelHelper.mirror(VoxelHelper.rotateCounterClockwise(JUNCTION, Axis.X), Axis.Z), Axis.Z), Axis.Z)); + VOXEL_LIST.add(VoxelHelper.rotateCounterClockwise(VoxelHelper.mirror(VoxelHelper.rotateCounterClockwise(JUNCTION, Axis.X), Axis.Z), Axis.Z)); + + VOXEL_LIST.add(VoxelHelper.rotateClockwise(VoxelHelper.rotateCounterClockwise(JUNCTION, Axis.X), Axis.Y)); + VOXEL_LIST.add(VoxelHelper.rotateClockwise(VoxelHelper.rotateClockwise(VoxelHelper.rotateCounterClockwise(JUNCTION, Axis.X), Axis.Y), Axis.X)); + VOXEL_LIST.add(VoxelHelper.rotateClockwise(VoxelHelper.rotateClockwise(VoxelHelper.rotateClockwise(VoxelHelper.rotateCounterClockwise(JUNCTION, Axis.X), Axis.Y), Axis.X), Axis.X)); + VOXEL_LIST.add(VoxelHelper.rotateCounterClockwise(VoxelHelper.rotateClockwise(VoxelHelper.rotateCounterClockwise(JUNCTION, Axis.X), Axis.Y), Axis.X)); + + VOXEL_LIST.add(VoxelHelper.mirror(VoxelHelper.rotateClockwise(VoxelHelper.rotateCounterClockwise(JUNCTION, Axis.X), Axis.Y), Axis.X)); + VOXEL_LIST.add(VoxelHelper.rotateClockwise(VoxelHelper.mirror(VoxelHelper.rotateClockwise(VoxelHelper.rotateCounterClockwise(JUNCTION, Axis.X), Axis.Y), Axis.X), Axis.X)); + VOXEL_LIST.add(VoxelHelper.rotateClockwise(VoxelHelper.rotateClockwise(VoxelHelper.mirror(VoxelHelper.rotateClockwise(VoxelHelper.rotateCounterClockwise(JUNCTION, Axis.X), Axis.Y), Axis.X), Axis.X), Axis.X)); + VOXEL_LIST.add(VoxelHelper.rotateCounterClockwise(VoxelHelper.mirror(VoxelHelper.rotateClockwise(VoxelHelper.rotateCounterClockwise(JUNCTION, Axis.X), Axis.Y), Axis.X), Axis.X)); + + VOXEL_LIST.add(INNER); + VOXEL_LIST.add(VoxelHelper.rotateClockwise(INNER, Axis.Y)); + VOXEL_LIST.add(VoxelHelper.rotateCounterClockwise(VoxelHelper.rotateCounterClockwise(INNER, Axis.Y), Axis.Y)); + VOXEL_LIST.add(VoxelHelper.rotateCounterClockwise(INNER, Axis.Y)); + + VOXEL_LIST.add(VoxelHelper.mirror(INNER, Axis.Y)); + VOXEL_LIST.add(VoxelHelper.rotateClockwise(VoxelHelper.mirror(INNER, Axis.Y), Axis.Y)); + VOXEL_LIST.add(VoxelHelper.rotateCounterClockwise(VoxelHelper.rotateCounterClockwise(VoxelHelper.mirror(INNER, Axis.Y), Axis.Y), Axis.Y)); + VOXEL_LIST.add(VoxelHelper.rotateCounterClockwise(VoxelHelper.mirror(INNER, Axis.Y), Axis.Y)); + + VOXEL_LIST.add(OUTER); + VOXEL_LIST.add(VoxelHelper.rotateClockwise(OUTER, Axis.Y)); + VOXEL_LIST.add(VoxelHelper.rotateCounterClockwise(VoxelHelper.rotateCounterClockwise(OUTER, Axis.Y), Axis.Y)); + VOXEL_LIST.add(VoxelHelper.rotateCounterClockwise(OUTER, Axis.Y)); + + VOXEL_LIST.add(VoxelHelper.mirror(OUTER, Axis.Y)); + VOXEL_LIST.add(VoxelHelper.rotateClockwise(VoxelHelper.mirror(OUTER, Axis.Y), Axis.Y)); + VOXEL_LIST.add(VoxelHelper.rotateCounterClockwise(VoxelHelper.rotateCounterClockwise(VoxelHelper.mirror(OUTER, Axis.Y), Axis.Y), Axis.Y)); + VOXEL_LIST.add(VoxelHelper.rotateCounterClockwise(VoxelHelper.mirror(OUTER, Axis.Y), Axis.Y)); } } diff --git a/src/main/java/fr/adrien1106/reframedtemplates/model/RetexturingBakedModel.java b/src/main/java/fr/adrien1106/reframedtemplates/model/RetexturingBakedModel.java index 751acfe..ee09b87 100644 --- a/src/main/java/fr/adrien1106/reframedtemplates/model/RetexturingBakedModel.java +++ b/src/main/java/fr/adrien1106/reframedtemplates/model/RetexturingBakedModel.java @@ -1,6 +1,6 @@ package fr.adrien1106.reframedtemplates.model; -import fr.adrien1106.reframedtemplates.block.TemplateEntity; +import fr.adrien1106.reframedtemplates.block.FramedEntity; import fr.adrien1106.reframedtemplates.mixin.MinecraftAccessor; import fr.adrien1106.reframedtemplates.model.apperance.TemplateAppearance; import fr.adrien1106.reframedtemplates.model.apperance.TemplateAppearanceManager; @@ -100,7 +100,7 @@ public abstract class RetexturingBakedModel extends ForwardingBakedModel { //none of this is accessible unless you're in creative mode doing ctrl-pick btw TemplateAppearance nbtAppearance; int tint; - BlockState theme = TemplateEntity.readStateFromItem(stack); + BlockState theme = FramedEntity.readStateFromItem(stack); if(!theme.isAir()) { nbtAppearance = tam.getTemplateAppearance(theme); tint = 0xFF000000 | ((MinecraftAccessor) MinecraftClient.getInstance()).templates$getItemColors().getColor(new ItemStack(theme.getBlock()), 0); diff --git a/src/main/java/fr/adrien1106/reframedtemplates/util/VoxelHelper.java b/src/main/java/fr/adrien1106/reframedtemplates/util/VoxelHelper.java new file mode 100644 index 0000000..123be5f --- /dev/null +++ b/src/main/java/fr/adrien1106/reframedtemplates/util/VoxelHelper.java @@ -0,0 +1,72 @@ +package fr.adrien1106.reframedtemplates.util; + +import net.minecraft.util.function.BooleanBiFunction; +import net.minecraft.util.math.Direction; +import net.minecraft.util.shape.VoxelShape; +import net.minecraft.util.shape.VoxelShapes; + +public class VoxelHelper { + public static VoxelShape rotateClockwise(VoxelShape shape, Direction.Axis axis) { + VoxelShape[] buffer = new VoxelShape[]{ shape, VoxelShapes.empty() }; + switch (axis) { + case Y: + buffer[0].forEachBox((minX, minY, minZ, maxX, maxY, maxZ) -> buffer[1] = VoxelShapes.combineAndSimplify( buffer[1], VoxelShapes.cuboid( 1 - maxZ, minY, minX, 1 - minZ, maxY, maxX), BooleanBiFunction.OR)); + break; + case X: + buffer[0].forEachBox((minX, minY, minZ, maxX, maxY, maxZ) -> buffer[1] = VoxelShapes.combineAndSimplify( buffer[1], VoxelShapes.cuboid( minX, 1 - maxZ, minY, maxX, 1 - minZ, maxY), BooleanBiFunction.OR)); + break; + case Z: + buffer[0].forEachBox((minX, minY, minZ, maxX, maxY, maxZ) -> buffer[1] = VoxelShapes.combineAndSimplify( buffer[1], VoxelShapes.cuboid( 1 - maxY, minX, minZ, 1 - minY, maxX, maxZ), BooleanBiFunction.OR)); + break; + } + return buffer[1]; + } + + public static VoxelShape rotateCounterClockwise(VoxelShape shape, Direction.Axis axis) { + VoxelShape[] buffer = new VoxelShape[]{ shape, VoxelShapes.empty() }; + switch (axis) { + case Y: + buffer[0].forEachBox((minX, minY, minZ, maxX, maxY, maxZ) -> buffer[1] = VoxelShapes.combineAndSimplify( buffer[1], VoxelShapes.cuboid( minZ, minY, 1 - maxX, maxZ, maxY, 1 - minX), BooleanBiFunction.OR)); + break; + case X: + buffer[0].forEachBox((minX, minY, minZ, maxX, maxY, maxZ) -> buffer[1] = VoxelShapes.combineAndSimplify( buffer[1], VoxelShapes.cuboid( minX, minZ, 1 - maxY, maxX, maxZ, 1 - minY), BooleanBiFunction.OR)); + break; + case Z: + buffer[0].forEachBox((minX, minY, minZ, maxX, maxY, maxZ) -> buffer[1] = VoxelShapes.combineAndSimplify( buffer[1], VoxelShapes.cuboid( minY, 1 - maxX, minZ, maxY, 1 - minX, maxZ), BooleanBiFunction.OR)); + break; + } + return buffer[1]; + } + + public static VoxelShape mirror(VoxelShape shape, Direction.Axis axis) { + VoxelShape[] buffer = new VoxelShape[]{ shape, VoxelShapes.empty() }; + switch (axis) { + case Y: + buffer[0].forEachBox((minX, minY, minZ, maxX, maxY, maxZ) -> buffer[1] = VoxelShapes.combineAndSimplify( buffer[1], VoxelShapes.cuboid( minX, 1 - maxY, minZ, maxX, 1 - minY, maxZ), BooleanBiFunction.OR)); + break; + case X: + buffer[0].forEachBox((minX, minY, minZ, maxX, maxY, maxZ) -> buffer[1] = VoxelShapes.combineAndSimplify( buffer[1], VoxelShapes.cuboid( 1 - maxX, minY, minZ, 1 - minX, maxY, maxZ), BooleanBiFunction.OR)); + break; + case Z: + buffer[0].forEachBox((minX, minY, minZ, maxX, maxY, maxZ) -> buffer[1] = VoxelShapes.combineAndSimplify( buffer[1], VoxelShapes.cuboid( minX, minY, 1 - maxZ, maxX, maxY, 1 - minZ), BooleanBiFunction.OR)); + break; + } + return buffer[1]; + } + + public static VoxelShape offset(VoxelShape shape, Direction.Axis axis, float offset) { + VoxelShape[] buffer = new VoxelShape[]{ shape, VoxelShapes.empty() }; + switch (axis) { + case Y: + buffer[0].forEachBox((minX, minY, minZ, maxX, maxY, maxZ) -> buffer[1] = VoxelShapes.combineAndSimplify( buffer[1], VoxelShapes.cuboid( minX, offset + minY, minZ, maxX, offset + maxY, maxZ), BooleanBiFunction.OR)); + break; + case X: + buffer[0].forEachBox((minX, minY, minZ, maxX, maxY, maxZ) -> buffer[1] = VoxelShapes.combineAndSimplify( buffer[1], VoxelShapes.cuboid( offset + minX, minY, minZ, offset + maxX, maxY, maxZ), BooleanBiFunction.OR)); + break; + case Z: + buffer[0].forEachBox((minX, minY, minZ, maxX, maxY, maxZ) -> buffer[1] = VoxelShapes.combineAndSimplify( buffer[1], VoxelShapes.cuboid( minX, minY, offset + minZ, maxX, maxY, offset + maxZ), BooleanBiFunction.OR)); + break; + } + return buffer[1]; + } +} diff --git a/src/main/java/fr/adrien1106/reframedtemplates/util/property/StairDirection.java b/src/main/java/fr/adrien1106/reframedtemplates/util/property/StairDirection.java new file mode 100644 index 0000000..869153f --- /dev/null +++ b/src/main/java/fr/adrien1106/reframedtemplates/util/property/StairDirection.java @@ -0,0 +1,87 @@ +package fr.adrien1106.reframedtemplates.util.property; + +import net.minecraft.util.StringIdentifiable; +import net.minecraft.util.math.Direction; + +import java.util.Arrays; +import java.util.Map; + +public enum StairDirection implements StringIdentifiable { + NORTH_DOWN("north_down", Direction.NORTH, Direction.DOWN, Direction.EAST, 0), + DOWN_SOUTH("down_south", Direction.DOWN, Direction.SOUTH, Direction.EAST, 1), + SOUTH_UP("south_up", Direction.SOUTH, Direction.UP, Direction.EAST, 2), + UP_NORTH("up_north", Direction.UP, Direction.NORTH, Direction.EAST, 3), + WEST_DOWN("west_down", Direction.WEST, Direction.DOWN, Direction.SOUTH, 4), + DOWN_EAST("down_east", Direction.DOWN, Direction.EAST, Direction.SOUTH, 5), + EAST_UP("east_up", Direction.EAST, Direction.UP, Direction.SOUTH, 6), + UP_WEST("up_west", Direction.UP, Direction.WEST, Direction.SOUTH, 7), + WEST_NORTH("west_north", Direction.WEST, Direction.NORTH, Direction.DOWN, 8), + NORTH_EAST("north_east", Direction.NORTH, Direction.EAST, Direction.DOWN, 9), + EAST_SOUTH("east_south", Direction.EAST, Direction.SOUTH, Direction.DOWN, 10), + SOUTH_WEST("south_west", Direction.SOUTH, Direction.WEST, Direction.DOWN, 11); + + private final String name; + private final Direction first_direction; + private final Direction second_direction; + private final Direction right_direction; + private final Direction left_direction; + private final int ID; + + StairDirection(String name, Direction first_direction, Direction second_direction, Direction right_direction, int id) { + this.name = name; + this.first_direction = first_direction; + this.second_direction = second_direction; + this.right_direction = right_direction; + this.left_direction = right_direction.getOpposite(); + this.ID = id; + } + + public String asString() { + return this.name; + } + + public String toString() { + return asString(); + } + + public Direction getFirstDirection() { + return first_direction; + } + + public Direction getSecondDirection() { + return second_direction; + } + public Direction getRightDirection() { + return right_direction; + } + public Direction getLeftDirection() { + return left_direction; + } + + public boolean hasDirection(Direction direction) { + return this.first_direction.equals(direction) + || this.second_direction.equals(direction); + } + + public int getID() { + return this.ID; + } + + public static StairDirection getByDirections(Direction direction_1, Direction direction_2) { + return Arrays.stream(StairDirection.values()) + .filter(value -> value.hasDirection(direction_1) && value.hasDirection(direction_2)) + .findFirst().orElse(StairDirection.NORTH_DOWN); + } + + public static StairDirection fromId(int id) { + return Arrays.stream(StairDirection.values()) + .filter(value -> value.getID() == id) + .findFirst().orElse(StairDirection.NORTH_DOWN); + } + + public static StairDirection fromName(String name) { + return Arrays.stream(StairDirection.values()) + .filter(value -> value.name().equals(name)) + .findFirst().orElse(StairDirection.NORTH_DOWN); + } +} diff --git a/src/main/java/fr/adrien1106/reframedtemplates/util/property/StairShape.java b/src/main/java/fr/adrien1106/reframedtemplates/util/property/StairShape.java new file mode 100644 index 0000000..a7327aa --- /dev/null +++ b/src/main/java/fr/adrien1106/reframedtemplates/util/property/StairShape.java @@ -0,0 +1,51 @@ +package fr.adrien1106.reframedtemplates.util.property; + +import net.minecraft.util.StringIdentifiable; + +import java.util.Arrays; + +public enum StairShape implements StringIdentifiable { + STRAIGHT("straight", 0), + INNER_RIGHT("inner_right", 1), + INNER_LEFT("inner_left", 2), + OUTER_RIGHT("outer_right", 3), + OUTER_LEFT("outer_left", 4), + FIRST_OUTER_RIGHT("first_outer_right", 5), + FIRST_OUTER_LEFT("first_outer_left", 6), + SECOND_OUTER_RIGHT("second_outer_right", 7), + SECOND_OUTER_LEFT("second_outer_left", 8); + + + private final String name; + private final int ID; + + StairShape(String name, int id) { + this.name = name; + this.ID = id; + } + + public String asString() { + return this.name; + } + + public String toString() { + return asString(); + } + + public int getID() { + return this.ID; + } + + public static StairShape fromId(int id) { + return Arrays.stream(StairShape.values()) + .filter(value -> value.getID() == id) + .findFirst().orElse(StairShape.STRAIGHT); + } + + public static StairShape fromName(String name) { + return Arrays.stream(StairShape.values()) + .filter(value -> value.name().equals(name)) + .findFirst().orElse(StairShape.STRAIGHT); + } + +} diff --git a/src/main/resources/assets/reframedtemplates/models/block/double_outer_stairs.json b/src/main/resources/assets/reframedtemplates/models/block/double_outer_stairs.json new file mode 100644 index 0000000..afe8136 --- /dev/null +++ b/src/main/resources/assets/reframedtemplates/models/block/double_outer_stairs.json @@ -0,0 +1,54 @@ +{ + "parent": "minecraft:block/block", + "textures": { + "particle": "#side" + }, + "elements": [ + { + "from": [0, 0, 0], + "to": [16, 8, 16], + "faces": { + "north": {"uv": [0, 8, 16, 16], "texture": "#side", "cullface": "north"}, + "east": {"uv": [0, 8, 16, 16], "texture": "#side", "cullface": "east"}, + "south": {"uv": [0, 8, 16, 16], "texture": "#side", "cullface": "south"}, + "west": {"uv": [0, 8, 16, 16], "texture": "#side", "cullface": "west"}, + "up": {"uv": [0, 0, 16, 16], "texture": "#top"}, + "down": {"uv": [0, 0, 16, 16], "texture": "#bottom", "cullface": "down"} + } + }, + { + "from": [8, 0, 0], + "to": [16, 8, 16], + "faces": { + "north": {"uv": [0, 8, 8, 16], "texture": "#side", "cullface": "north"}, + "east": {"uv": [0, 8, 16, 16], "texture": "#side", "cullface": "east"}, + "south": {"uv": [8, 8, 16, 16], "texture": "#side", "cullface": "south"}, + "west": {"uv": [0, 8, 16, 16], "texture": "#side"}, + "up": {"uv": [8, 0, 16, 16], "texture": "#top", "cullface": "up"}, + "down": {"uv": [8, 0, 16, 16], "texture": "#bottom"} + } + }, + { + "from": [8, 8, 8], + "to": [16, 16, 16], + "faces": { + "north": {"uv": [0, 0, 8, 8], "texture": "#side"}, + "east": {"uv": [0, 0, 8, 8], "texture": "#side"}, + "south": {"uv": [8, 0, 16, 8], "texture": "#side", "cullface": "south"}, + "west": {"uv": [8, 0, 16, 8], "texture": "#side", "cullface": "west"}, + "up": {"uv": [8, 8, 16, 16], "texture": "#top", "cullface": "up"} + } + }, + { + "from": [0, 0, 8], + "to": [8, 8, 16], + "faces": { + "north": {"uv": [8, 8, 16, 16], "texture": "#side"}, + "south": {"uv": [0, 8, 8, 16], "texture": "#side", "cullface": "south"}, + "west": {"uv": [8, 8, 16, 16], "texture": "#side", "cullface": "west"}, + "up": {"uv": [0, 8, 8, 16], "texture": "#top", "cullface": "up"}, + "down": {"uv": [0, 0, 8, 8], "texture": "#bottom"} + } + } + ] +} \ No newline at end of file