@@ -220,6 +220,13 @@ public enum ShapeMode
220220 private final SliderSetting renderHeight = new SliderSetting (
221221 "Render-Height" , 0 , -64 , 319 , 1 , ValueDisplay .INTEGER );
222222
223+ private final CheckboxSetting useMinimumClassificationY =
224+ new CheckboxSetting ("Use Minimum-Classification-Y" ,
225+ "Only classifies blocks above the specified Y level." , false );
226+
227+ private final SliderSetting minimumClassificationY = new SliderSetting (
228+ "Minimum-Classification-Y" , 16 , -64 , 319 , 1 , ValueDisplay .INTEGER );
229+
223230 private final EnumSetting <ShapeMode > shapeMode =
224231 new EnumSetting <>("Shape Mode" , ShapeMode .values (), ShapeMode .Both );
225232
@@ -344,7 +351,8 @@ private enum AlarmType
344351 }
345352
346353 private record ChunkClassification (boolean isNewChunk ,
347- boolean isOldGeneration , boolean chunkIsBeingUpdated )
354+ boolean isOldGeneration , boolean chunkIsBeingUpdated ,
355+ boolean hasUsableEvidence )
348356 {}
349357
350358 private static Set <Block > createNewNetherBlocks ()
@@ -528,6 +536,8 @@ public NewerNewChunksHack()
528536 addSetting (deleteChunkData );
529537 addSetting (renderDistance );
530538 addSetting (renderHeight );
539+ addSetting (useMinimumClassificationY );
540+ addSetting (minimumClassificationY );
531541 addSetting (shapeMode );
532542 addSetting (newChunksSideColor );
533543 addSetting (newChunksLineColor );
@@ -773,33 +783,37 @@ public void afterLoadChunk(int x, int z)
773783 if (paletteExploit .isChecked ())
774784 {
775785 ChunkClassification classification = classifyChunk (chunk );
776- boolean isNewChunk = classification .isNewChunk ();
777- boolean isOldGeneration = classification .isOldGeneration ();
778- boolean chunkIsBeingUpdated = classification .chunkIsBeingUpdated ();
779- boolean allowNew = isEnd () ? isNewChunk : !isOldGeneration ;
780-
781- if (isNewChunk && !chunkIsBeingUpdated && allowNew )
782- {
783- markNew (chunkPos );
784- return ;
785- }
786-
787- if (!isNewChunk && !chunkIsBeingUpdated && isOldGeneration )
788- {
789- markOldGeneration (chunkPos );
790- return ;
791- }
792-
793- if (chunkIsBeingUpdated )
794- {
795- markBeingUpdated (chunkPos );
796- return ;
797- }
798-
799- if (!isNewChunk )
786+ if (classification .hasUsableEvidence ())
800787 {
801- markOld (chunkPos );
802- return ;
788+ boolean isNewChunk = classification .isNewChunk ();
789+ boolean isOldGeneration = classification .isOldGeneration ();
790+ boolean chunkIsBeingUpdated =
791+ classification .chunkIsBeingUpdated ();
792+ boolean allowNew = isEnd () ? isNewChunk : !isOldGeneration ;
793+
794+ if (isNewChunk && !chunkIsBeingUpdated && allowNew )
795+ {
796+ markNew (chunkPos );
797+ return ;
798+ }
799+
800+ if (!isNewChunk && !chunkIsBeingUpdated && isOldGeneration )
801+ {
802+ markOldGeneration (chunkPos );
803+ return ;
804+ }
805+
806+ if (chunkIsBeingUpdated )
807+ {
808+ markBeingUpdated (chunkPos );
809+ return ;
810+ }
811+
812+ if (!isNewChunk )
813+ {
814+ markOld (chunkPos );
815+ return ;
816+ }
803817 }
804818 }
805819
@@ -812,6 +826,7 @@ private ChunkClassification classifyChunk(LevelChunk chunk)
812826 boolean isNewChunk = false ;
813827 boolean isOldGeneration = false ;
814828 boolean chunkIsBeingUpdated = false ;
829+ boolean hasUsableEvidence = false ;
815830 LevelChunkSection [] sections = chunk .getSections ();
816831
817832 if (overworldOldChunksDetector .isChecked () && isOverworld ())
@@ -831,16 +846,20 @@ && isNether())
831846 int newChunkQuantifier = 0 ;
832847 int oldChunkQuantifier = 0 ;
833848
834- for (LevelChunkSection section : sections )
849+ for (int sectionIndex =
850+ 0 ; sectionIndex < sections .length ; sectionIndex ++)
835851 {
836- if (section == null )
852+ LevelChunkSection section = sections [sectionIndex ];
853+ if (section == null
854+ || !shouldUseSectionForClassification (chunk , sectionIndex ))
837855 continue ;
838856
839857 int isNewSection = 0 ;
840858 int isBeingUpdatedSection = 0 ;
841859
842860 if (!section .hasOnlyAir ())
843861 {
862+ hasUsableEvidence = true ;
844863 PalettedContainer <BlockState > blockStates =
845864 section .getStates ();
846865 List <BlockState > paletteEntries =
@@ -924,7 +943,30 @@ && isNether())
924943 }
925944
926945 return new ChunkClassification (isNewChunk , isOldGeneration ,
927- chunkIsBeingUpdated );
946+ chunkIsBeingUpdated , hasUsableEvidence || isOldGeneration );
947+ }
948+
949+ private int getClassificationMinY ()
950+ {
951+ if (!useMinimumClassificationY .isChecked ())
952+ return Integer .MIN_VALUE ;
953+ return minimumClassificationY .getValueI ();
954+ }
955+
956+ private int getSectionMinY (LevelChunk chunk , int sectionIndex )
957+ {
958+ return chunk .getMinY () + sectionIndex * 16 ;
959+ }
960+
961+ private int getSectionMaxY (LevelChunk chunk , int sectionIndex )
962+ {
963+ return getSectionMinY (chunk , sectionIndex ) + 15 ;
964+ }
965+
966+ private boolean shouldUseSectionForClassification (LevelChunk chunk ,
967+ int sectionIndex )
968+ {
969+ return getSectionMaxY (chunk , sectionIndex ) >= getClassificationMinY ();
928970 }
929971
930972 public void afterUpdateBlock (BlockPos pos )
@@ -947,6 +989,9 @@ public void afterChunkDeltaUpdate(BlockPos pos, BlockState state)
947989 private void handleBlockLikeUpdate (BlockPos pos , BlockState state ,
948990 boolean allowTickExploit )
949991 {
992+ if (pos .getY () < getClassificationMinY ())
993+ return ;
994+
950995 ChunkPos chunkPos = ChunkPos .containing (pos );
951996 if (allowTickExploit && blockUpdateExploit .isChecked ()
952997 && !containsAny (chunkPos ))
@@ -1818,7 +1863,7 @@ private void confirmDeleteChunkData()
18181863
18191864 private boolean hasFlowingFluid (LevelChunk chunk )
18201865 {
1821- int minY = chunk .getMinY ();
1866+ int minY = Math . max ( chunk .getMinY (), getClassificationMinY () );
18221867 int maxY = chunk .getMaxY ();
18231868 BlockPos .MutableBlockPos pos = new BlockPos .MutableBlockPos ();
18241869 for (int cx = 0 ; cx < 16 ; cx ++)
@@ -1909,25 +1954,32 @@ private boolean isOverworldOldGeneration(LevelChunk chunk)
19091954 int safeSections = Math .min (17 , sections .length );
19101955 boolean foundAnyOre = false ;
19111956 boolean hasNewOverworldGeneration = false ;
1957+ int minY = getClassificationMinY ();
19121958
19131959 for (int i = 0 ; i < safeSections ; i ++)
19141960 {
19151961 LevelChunkSection section = sections [i ];
1916- if (section == null || section .hasOnlyAir ())
1962+ if (section == null || section .hasOnlyAir ()
1963+ || !shouldUseSectionForClassification (chunk , i ))
19171964 continue ;
19181965
1966+ int sectionMinY = getSectionMinY (chunk , i );
19191967 for (int x = 0 ; x < 16 ; x ++)
19201968 for (int y = 0 ; y < 16 ; y ++)
19211969 for (int z = 0 ; z < 16 ; z ++)
19221970 {
1971+ int blockY = sectionMinY + y ;
1972+ if (blockY < minY )
1973+ continue ;
1974+
19231975 Block block = section .getBlockState (x , y , z ).getBlock ();
19241976 if (!foundAnyOre && ORE_BLOCKS .contains (block ))
19251977 foundAnyOre = true ;
19261978
19271979 if (hasNewOverworldGeneration )
19281980 continue ;
19291981
1930- boolean inModernRange = ( i == 4 && y >= 5 ) || i > 4 ;
1982+ boolean inModernRange = blockY >= 5 ;
19311983 if (inModernRange
19321984 && (NEW_OVERWORLD_BLOCKS .contains (block )
19331985 || DEEPSLATE_BLOCKS .contains (block )))
@@ -1943,24 +1995,32 @@ private boolean isNetherOldGeneration(LevelChunk chunk)
19431995 {
19441996 LevelChunkSection [] sections = chunk .getSections ();
19451997 int safeSections = Math .min (8 , sections .length );
1998+ int minY = getClassificationMinY ();
1999+ boolean foundUsableSection = false ;
19462000
19472001 for (int i = 0 ; i < safeSections ; i ++)
19482002 {
19492003 LevelChunkSection section = sections [i ];
1950- if (section == null || section .hasOnlyAir ())
2004+ if (section == null || section .hasOnlyAir ()
2005+ || !shouldUseSectionForClassification (chunk , i ))
19512006 continue ;
19522007
2008+ foundUsableSection = true ;
2009+ int sectionMinY = getSectionMinY (chunk , i );
19532010 for (int x = 0 ; x < 16 ; x ++)
19542011 for (int y = 0 ; y < 16 ; y ++)
19552012 for (int z = 0 ; z < 16 ; z ++)
19562013 {
2014+ if (sectionMinY + y < minY )
2015+ continue ;
2016+
19572017 Block block = section .getBlockState (x , y , z ).getBlock ();
19582018 if (NEW_NETHER_BLOCKS .contains (block ))
19592019 return false ;
19602020 }
19612021 }
19622022
1963- return true ;
2023+ return foundUsableSection ;
19642024 }
19652025
19662026 private boolean hasEndBiome (LevelChunk chunk )
0 commit comments