@@ -128,7 +128,14 @@ public void render(IRecipeLogicMachine rlm, float partialTick, PoseStack poseSta
128128 if (mode == GrowthMode .AGE_4 && GrowthMode .PICKLES .predicate ().test (growing )) {
129129 // special case the pickles property to work if using age_4
130130 mode = GrowthMode .PICKLES ;
131+ } else if (mode == GrowthMode .AGE_4 && GrowthMode .FLOWER_AMOUNT .predicate ().test (growing )) {
132+ // special case the flower amount property to work if using age_4
133+ mode = GrowthMode .FLOWER_AMOUNT ;
134+ } else if (mode == GrowthMode .AGE_7 && GrowthMode .STEM .predicate ().test (growing )) {
135+ // special case stem plants to show stems
136+ mode = GrowthMode .STEM ;
131137 } else {
138+ // generic incompatibility, use default mode
132139 mode = GrowthMode .SCALE ;
133140 }
134141 }
@@ -212,27 +219,32 @@ protected GrowthMode getGrowthModeForBlock(Block block) {
212219 if (block instanceof GrowingPlantBlock ) {
213220 return GrowthMode .GROWING_PLANT ;
214221 }
222+ if (block instanceof StemBlock ) {
223+ return GrowthMode .STEM ;
224+ }
225+
215226 BlockState state = block .defaultBlockState ();
227+ IntegerProperty ageProp = findAgeProperty (state .getProperties ());
228+ if (ageProp != null ) {
229+ GrowthMode mode = GrowthMode .MODE_BY_PROPERTY .get (ageProp );
230+ if (mode != null ) return mode ;
231+ }
232+
216233 if (state .hasProperty (BlockStateProperties .DOUBLE_BLOCK_HALF ) ||
217234 state .hasProperty (BlockStateProperties .HALF ) ||
218235 state .is (CustomTags .TALL_PLANTS )) {
219236 return GrowthMode .DOUBLE_TRANSLATE ;
220237 } else if (state .is (BlockTags .FLOWERS )) {
221238 return GrowthMode .TRANSLATE ;
222239 }
223-
224- IntegerProperty ageProp = findAgeProperty (state .getProperties ());
225- if (ageProp != null ) {
226- GrowthMode mode = GrowthMode .MODE_BY_PROPERTY .get (ageProp );
227- if (mode != null ) return mode ;
228- }
229240 // default to SCALE
230241 return GrowthMode .SCALE ;
231242 }
232243
233244 public static @ Nullable IntegerProperty findAgeProperty (Collection <Property <?>> properties ) {
234245 for (Property <?> prop : properties ) {
235- if ((prop .getName ().equals ("age" ) || prop .getName ().equals ("pickles" )) &&
246+ if ((prop .getName ().equals ("age" ) || prop .getName ().equals ("pickles" ) ||
247+ prop .getName ().equals ("flower_amount" )) &&
236248 prop instanceof IntegerProperty intProp ) {
237249 return intProp ;
238250 }
@@ -256,6 +268,9 @@ public record GrowthMode(String name,
256268 public static final GrowthMode GROWING_PLANT = new GrowthMode ("growing_plant" ,
257269 block -> block instanceof GrowingPlantBlock , RenderFunction .GROWING_PLANT );
258270
271+ public static final GrowthMode STEM = new GrowthMode ("stem" , block -> block instanceof StemBlock ,
272+ RenderFunction .STEM );
273+
259274 // all the different age properties. not going to add extras, though.
260275 public static final GrowthMode AGE_1 = ofIntegerProperty ("age_1" , BlockStateProperties .AGE_1 );
261276 public static final GrowthMode AGE_2 = ofIntegerProperty ("age_2" , BlockStateProperties .AGE_2 );
@@ -267,6 +282,8 @@ public record GrowthMode(String name,
267282 public static final GrowthMode AGE_25 = ofIntegerProperty ("age_25" , BlockStateProperties .AGE_25 );
268283
269284 public static final GrowthMode PICKLES = ofIntegerProperty ("pickles" , BlockStateProperties .PICKLES , 0 , 4 );
285+ public static final GrowthMode FLOWER_AMOUNT = ofIntegerProperty ("flower_amount" ,
286+ BlockStateProperties .FLOWER_AMOUNT , 0 , 4 );
270287
271288 private static final Codec <GrowthMode > CODEC = Codec .STRING .comapFlatMap (name -> {
272289 GrowthMode mode = VALUES .get (name );
@@ -287,13 +304,15 @@ public GrowthMode(String name, RenderFunction renderFunction) {
287304 }
288305
289306 public static GrowthMode ofIntegerProperty (String name , IntegerProperty property ) {
290- IntegerPropertyAccessor accessor = (IntegerPropertyAccessor ) property ;
291- final int min = accessor .gtceu$getMin ();
292- final int max = accessor .gtceu$getMax ();
293- return ofIntegerProperty (name , property , min , max );
307+ return ofIntegerProperty (name , property , OptionalInt .empty (), OptionalInt .empty ());
294308 }
295309
296310 public static GrowthMode ofIntegerProperty (String name , IntegerProperty property , int min , int max ) {
311+ return ofIntegerProperty (name , property , OptionalInt .of (min ), OptionalInt .of (max ));
312+ }
313+
314+ public static GrowthMode ofIntegerProperty (String name , IntegerProperty property , OptionalInt min ,
315+ OptionalInt max ) {
297316 GrowthMode mode = new GrowthMode (name ,
298317 block -> block .getStateDefinition ().getProperties ().contains (property ),
299318 RenderFunction .byIntegerProperty (property , min , max ));
@@ -410,23 +429,52 @@ public Collection<StateWithOffset> configureState(BlockAndTintGetter level, Bloc
410429 }
411430 };
412431
413- TriFunction <IntegerProperty , Integer , Integer , ConfigureOnly > PROPERTY_FUNCTION_CACHE = GTMemoizer
414- .memoize ((property , min , max ) -> {
432+ RenderFunction .ConfigureOnly STEM = (level , state , progress ) -> {
433+ final StemBlock block = (StemBlock ) state .getBlock ();
434+ final int growthStage = GTMath .lerpInt (progress , 0 , StemBlock .MAX_AGE + 2 );
435+ if (growthStage > StemBlock .MAX_AGE )
436+ return List .of (new StateWithOffset (block .getFruit ().defaultBlockState ()));
437+ state = state .trySetValue (StemBlock .AGE , growthStage );
438+ return List .of (new StateWithOffset (state ));
439+ };
440+
441+ TriFunction <IntegerProperty , OptionalInt , OptionalInt , ConfigureOnly > PROPERTY_FUNCTION_CACHE = GTMemoizer
442+ .memoize ((property , setMin , setMax ) -> {
415443 IntegerPropertyAccessor accessor = (IntegerPropertyAccessor ) property ;
416- final int minValue = accessor .gtceu$getMin ();
417- final int maxValue = accessor .gtceu$getMax ();
444+ final int presumedMinValue = accessor .gtceu$getMin ();
445+ final int presumedMaxValue = accessor .gtceu$getMax ();
418446 return (level , state , progress ) -> {
447+ final int min = setMin .orElse (presumedMinValue );
448+ final int betterMaxValue = state .getBlock () instanceof CropBlock crop ?
449+ Math .max (presumedMaxValue , crop .getMaxAge ()) : presumedMaxValue ;
450+ final int max = setMax .orElse (betterMaxValue );
419451 int growthStage = GTMath .lerpInt (progress , min , max + 1 );
420- if (growthStage < minValue ) {
452+ if (growthStage < presumedMinValue ) {
421453 return Collections .emptySet ();
422454 }
423- state = state .trySetValue (property , Math .min (growthStage , maxValue ));
455+ if (state .getBlock () instanceof CropBlock crop ) {
456+ state = crop .getStateForAge (Math .min (growthStage , betterMaxValue ));
457+ } else {
458+ state = state .trySetValue (property , Math .min (growthStage , betterMaxValue ));
459+ }
460+ if (state .hasProperty (BlockStateProperties .DOUBLE_BLOCK_HALF )) {
461+ final var topState = state .trySetValue (BlockStateProperties .DOUBLE_BLOCK_HALF ,
462+ DoubleBlockHalf .UPPER );
463+ return List .of (new StateWithOffset (state ),
464+ new StateWithOffset (topState , new Vector3f (0 , 1 , 0 )));
465+ }
466+ if (state .hasProperty (BlockStateProperties .HALF )) {
467+ final var topState = state .trySetValue (BlockStateProperties .HALF , Half .TOP );
468+ return List .of (new StateWithOffset (state ),
469+ new StateWithOffset (topState , new Vector3f (0 , 1 , 0 )));
470+ }
424471
425472 return List .of (new StateWithOffset (state ));
426473 };
427474 });
428475
429- static RenderFunction .ConfigureOnly byIntegerProperty (IntegerProperty property , int min , int max ) {
476+ static RenderFunction .ConfigureOnly byIntegerProperty (IntegerProperty property , OptionalInt min ,
477+ OptionalInt max ) {
430478 return PROPERTY_FUNCTION_CACHE .apply (property , min , max );
431479 }
432480
0 commit comments