1+ package com .tcm .MineTale .block .workbenches ;
2+
3+ import net .minecraft .core .BlockPos ;
4+ import net .minecraft .core .Direction ;
5+ import net .minecraft .util .RandomSource ;
6+ import net .minecraft .world .entity .LivingEntity ;
7+ import net .minecraft .world .item .ItemStack ;
8+ import net .minecraft .world .item .context .BlockPlaceContext ;
9+ import net .minecraft .world .level .Level ;
10+ import net .minecraft .world .level .LevelReader ;
11+ import net .minecraft .world .level .ScheduledTickAccess ;
12+ import net .minecraft .world .level .block .BaseEntityBlock ;
13+ import net .minecraft .world .level .block .Block ;
14+ import net .minecraft .world .level .block .Blocks ;
15+ import net .minecraft .world .level .block .HorizontalDirectionalBlock ;
16+ import net .minecraft .world .level .block .entity .BlockEntity ;
17+ import net .minecraft .world .level .block .entity .BlockEntityType ;
18+ import net .minecraft .world .level .block .state .BlockState ;
19+ import net .minecraft .world .level .block .state .StateDefinition ;
20+ import net .minecraft .world .level .block .state .properties .*;
21+ import org .jetbrains .annotations .Nullable ;
22+
23+ import java .util .function .Supplier ;
24+
25+ public abstract class AbstractWorkbench <E extends BlockEntity > extends BaseEntityBlock {
26+ public static final EnumProperty <Direction > FACING = HorizontalDirectionalBlock .FACING ;
27+ public static final EnumProperty <DoubleBlockHalf > HALF = BlockStateProperties .DOUBLE_BLOCK_HALF ;
28+ public static final EnumProperty <ChestType > TYPE = BlockStateProperties .CHEST_TYPE ;
29+
30+ protected final Supplier <BlockEntityType <? extends E >> blockEntityType ;
31+ protected final boolean isWide ;
32+ protected final boolean isTall ;
33+
34+ protected AbstractWorkbench (Properties properties , Supplier <BlockEntityType <? extends E >> supplier , boolean isWide , boolean isTall ) {
35+ super (properties );
36+ this .blockEntityType = supplier ;
37+ this .isWide = isWide ;
38+ this .isTall = isTall ;
39+ this .registerDefaultState (this .stateDefinition .any ()
40+ .setValue (FACING , Direction .NORTH )
41+ .setValue (HALF , DoubleBlockHalf .LOWER )
42+ .setValue (TYPE , ChestType .SINGLE ));
43+ }
44+
45+ @ Override
46+ @ Nullable
47+ public BlockState getStateForPlacement (BlockPlaceContext context ) {
48+ BlockPos pos = context .getClickedPos ();
49+ Level level = context .getLevel ();
50+ Direction facing = context .getHorizontalDirection ().getOpposite ();
51+
52+ // Check horizontal space
53+ if (isWide ) {
54+ BlockPos sidePos = pos .relative (facing .getClockWise ());
55+ if (!level .getBlockState (sidePos ).canBeReplaced (context )) return null ;
56+ if (isTall && !level .getBlockState (sidePos .above ()).canBeReplaced (context )) return null ;
57+ }
58+
59+ // Check vertical space
60+ if (isTall ) {
61+ if (!level .getBlockState (pos .above ()).canBeReplaced (context )) return null ;
62+ }
63+
64+ return this .defaultBlockState ().setValue (FACING , facing ).setValue (TYPE , isWide ? ChestType .LEFT : ChestType .SINGLE );
65+ }
66+
67+ @ Override
68+ public void setPlacedBy (Level level , BlockPos pos , BlockState state , @ Nullable LivingEntity placer , ItemStack stack ) {
69+ Direction facing = state .getValue (FACING );
70+
71+ if (isWide ) {
72+ BlockPos sidePos = pos .relative (facing .getClockWise ());
73+ // Place Right Side
74+ level .setBlock (sidePos , state .setValue (TYPE , ChestType .RIGHT ), 3 );
75+
76+ if (isTall ) {
77+ // Place Upper Row
78+ level .setBlock (pos .above (), state .setValue (HALF , DoubleBlockHalf .UPPER ).setValue (TYPE , ChestType .LEFT ), 3 );
79+ level .setBlock (sidePos .above (), state .setValue (HALF , DoubleBlockHalf .UPPER ).setValue (TYPE , ChestType .RIGHT ), 3 );
80+ }
81+ } else if (isTall ) {
82+ level .setBlock (pos .above (), state .setValue (HALF , DoubleBlockHalf .UPPER ), 3 );
83+ }
84+ }
85+
86+ @ Override
87+ protected BlockState updateShape (BlockState blockState , LevelReader levelReader , ScheduledTickAccess scheduledTickAccess , BlockPos blockPos , Direction direction , BlockPos blockPos2 , BlockState blockState2 , RandomSource randomSource ) {
88+ if (isWide || isTall ) {
89+ if (isNeighborRequired (blockState , direction )) {
90+ // If the neighbor we depend on is gone or is no longer a workbench part, break this block
91+ if (!blockState2 .is (this ) || !isCompatiblePart (blockState , blockState2 )) {
92+ return Blocks .AIR .defaultBlockState ();
93+ }
94+ }
95+ }
96+ return super .updateShape (blockState , levelReader , scheduledTickAccess , blockPos , direction , blockPos2 , blockState2 , randomSource );
97+ }
98+
99+ /**
100+ * Determines if a specific direction is "required" for this block's survival.
101+ */
102+ private boolean isNeighborRequired (BlockState state , Direction direction ) {
103+ DoubleBlockHalf half = state .getValue (HALF );
104+ ChestType type = state .getValue (TYPE );
105+ Direction facing = state .getValue (FACING );
106+
107+ // If I am LOWER, I need the block ABOVE (if tall)
108+ if (isTall && half == DoubleBlockHalf .LOWER && direction == Direction .UP ) return true ;
109+ // If I am UPPER, I need the block BELOW
110+ if (half == DoubleBlockHalf .UPPER && direction == Direction .DOWN ) return true ;
111+ // If I am LEFT, I need the block to my RIGHT
112+ if (type == ChestType .LEFT && direction == facing .getClockWise ()) return true ;
113+ // If I am RIGHT, I need the block to my LEFT
114+ if (type == ChestType .RIGHT && direction == facing .getCounterClockWise ()) return true ;
115+
116+ return false ;
117+ }
118+
119+ /**
120+ * Checks if the neighbor state is actually the correct "other half" of this multi-block.
121+ */
122+ private boolean isCompatiblePart (BlockState current , BlockState neighbor ) {
123+ // Ensure they face the same way
124+ if (current .getValue (FACING ) != neighbor .getValue (FACING )) return false ;
125+
126+ // Additional checks could go here (e.g. matching half/type logic)
127+ return true ;
128+ }
129+
130+ @ Override
131+ protected void createBlockStateDefinition (StateDefinition .Builder <Block , BlockState > builder ) {
132+ builder .add (FACING , HALF , TYPE );
133+ }
134+ }
0 commit comments