1717import dev .xpple .seedmapper .SeedMapper ;
1818import dev .xpple .seedmapper .command .CommandExceptions ;
1919import dev .xpple .seedmapper .command .CustomClientCommandSource ;
20+ import dev .xpple .seedmapper .command .arguments .OreArgument ;
2021import dev .xpple .seedmapper .config .Configs ;
21- import dev .xpple .seedmapper .feature .OreTypes ;
2222import dev .xpple .seedmapper .render .RenderManager ;
2323import dev .xpple .seedmapper .render .esp .EspStyle ;
2424import dev .xpple .seedmapper .util .BaritoneIntegration ;
4545import java .util .HashSet ;
4646import java .util .List ;
4747import java .util .Map ;
48- import java .util .Objects ;
4948import java .util .Set ;
5049import java .util .stream .Collectors ;
5150import java .util .stream .IntStream ;
5453import static dev .xpple .seedmapper .command .arguments .BlockArgument .*;
5554import static dev .xpple .seedmapper .command .arguments .CanyonCarverArgument .*;
5655import static dev .xpple .seedmapper .command .arguments .CaveCarverArgument .*;
56+ import static dev .xpple .seedmapper .command .arguments .OreArgument .*;
5757import static dev .xpple .seedmapper .thread .LocatorThreadHelper .*;
5858import static dev .xpple .seedmapper .util .ChatBuilder .*;
5959import static net .fabricmc .fabric .api .client .command .v2 .ClientCommands .*;
@@ -67,6 +67,12 @@ public static void register(CommandDispatcher<FabricClientCommandSource> dispatc
6767 .executes (ctx -> highlightBlock (CustomClientCommandSource .of (ctx .getSource ()), getBlock (ctx , "block" )))
6868 .then (argument ("chunks" , integer (0 , 20 ))
6969 .executes (ctx -> submit (() -> highlightBlock (CustomClientCommandSource .of (ctx .getSource ()), getBlock (ctx , "block" ), getInteger (ctx , "chunks" )))))))
70+ .then (literal ("ore" )
71+ .requires (_ -> Configs .DevMode )
72+ .then (argument ("ore" , ore ())
73+ .executes (ctx -> highlightOre (CustomClientCommandSource .of (ctx .getSource ()), getOre (ctx , "ore" ).intValue ()))
74+ .then (argument ("chunks" , integer (0 , 20 ))
75+ .executes (ctx -> submit (() -> highlightOre (CustomClientCommandSource .of (ctx .getSource ()), getOre (ctx , "ore" ).intValue (), getInteger (ctx , "chunks" )))))))
7076 .then (literal ("orevein" )
7177 .executes (ctx -> submit (() -> highlightOreVein (CustomClientCommandSource .of (ctx .getSource ()))))
7278 .then (argument ("chunks" , integer (0 , 20 ))
@@ -96,6 +102,7 @@ private static int highlightBlock(CustomClientCommandSource source, Pair<Integer
96102
97103 private static int highlightBlock (CustomClientCommandSource source , Pair <Integer , Integer > blockPair , int chunkRange ) throws CommandSyntaxException {
98104 RenderManager .clear ();
105+ int block = blockPair .getFirst ();
99106 SeedIdentifier seed = source .getSeed ().getSecond ();
100107 int version = source .getVersion ();
101108 int dimension = source .getDimension ();
@@ -124,7 +131,7 @@ private static int highlightBlock(CustomClientCommandSource source, Pair<Integer
124131 .boxed ()
125132 .toList ();
126133 }
127- OreTypes . ORE_TYPES .stream ()
134+ OreArgument . ORES . values () .stream ()
128135 .filter (oreType -> biomes .stream ().anyMatch (biome -> Cubiomes .isViableOreBiome (version , oreType , biome ) != 0 ))
129136 .<MemorySegment >mapMulti ((oreType , consumer ) -> {
130137 MemorySegment oreConfig = OreConfig .allocate (arena );
@@ -145,10 +152,11 @@ private static int highlightBlock(CustomClientCommandSource source, Pair<Integer
145152 for (int i = 0 ; i < size ; i ++) {
146153 MemorySegment pos3 = Pos3 .asSlice (pos3s , i );
147154 BlockPos pos = new BlockPos (Pos3 .x (pos3 ), Pos3 .y (pos3 ), Pos3 .z (pos3 ));
148- if (doAirCheck && isAirOrLava ( chunk , pos )) {
155+ if (doAirCheck && ! chunk . getBlockState ( pos ). canOcclude ( )) {
149156 continue ;
150157 }
151158 Integer previouslyGeneratedOre = generatedOres .get (pos );
159+ // if there is already an ore at this position, check if this ore can replace it
152160 if (previouslyGeneratedOre != null ) {
153161 boolean contains = false ;
154162 for (int j = 0 ; j < numReplaceBlocks ; j ++) {
@@ -169,15 +177,14 @@ private static int highlightBlock(CustomClientCommandSource source, Pair<Integer
169177 }
170178 });
171179
172- int block = blockPair .getFirst ();
173- int colour = blockPair .getSecond ();
180+ int color = Configs .BlockColors .getOrDefault (block , 0xFFFFFF );
174181 List <BlockPos > blockOres = generatedOres .entrySet ().stream ()
175182 .filter (entry -> entry .getValue () == block )
176183 .map (Map .Entry ::getKey )
177184 .toList ();
178185 count [0 ] += blockOres .size ();
179186 source .getClient ().schedule (() -> {
180- RenderManager .drawBoxes (blockOres , Configs . BlockHighlightESP , colour );
187+ RenderManager .drawBoxes (blockOres , color );
181188 if (SeedMapper .BARITONE_AVAILABLE && Configs .AutoMine ) {
182189 BaritoneIntegration .addGoals (blockOres );
183190 }
@@ -192,6 +199,70 @@ private static int highlightBlock(CustomClientCommandSource source, Pair<Integer
192199 }
193200 }
194201
202+ private static int highlightOre (CustomClientCommandSource source , int ore ) throws CommandSyntaxException {
203+ return highlightOre (source , ore , 0 );
204+ }
205+
206+ private static int highlightOre (CustomClientCommandSource source , int ore , int chunkRange ) throws CommandSyntaxException {
207+ SeedIdentifier seed = source .getSeed ().getSecond ();
208+ int version = source .getVersion ();
209+ int dimension = source .getDimension ();
210+
211+ try (Arena arena = Arena .ofConfined ()) {
212+ MemorySegment generator = Generator .allocate (arena );
213+ Cubiomes .setupGenerator (generator , version , source .getGeneratorFlags ());
214+ Cubiomes .applySeed (generator , dimension , seed .seed ());
215+ MemorySegment surfaceNoise = SurfaceNoise .allocate (arena );
216+ Cubiomes .initSurfaceNoise (surfaceNoise , dimension , seed .seed ());
217+
218+ ChunkPos center = ChunkPos .containing (BlockPos .containing (source .getPosition ()));
219+
220+ int [] count = {0 };
221+ SpiralLoop .spiral (center .x (), center .z (), chunkRange , (chunkX , chunkZ ) -> {
222+ List <Integer > biomes ;
223+ if (version <= Cubiomes .MC_1_17 ()) {
224+ biomes = List .of (Cubiomes .getBiomeForOreGen (generator , chunkX , chunkZ , 0 ));
225+ } else {
226+ // check certain Y-coordinates that matter for ore generation
227+ // Minecraft checks _all_ biomes in a 3x3 square of chunks, which is not necessary
228+ biomes = IntStream .of (-30 , 64 , 120 )
229+ .map (y -> Cubiomes .getBiomeForOreGen (generator , chunkX , chunkZ , y ))
230+ .boxed ()
231+ .toList ();
232+ }
233+
234+ if (biomes .stream ().noneMatch (biome -> Cubiomes .isViableOreBiome (version , ore , biome ) != 0 )) {
235+ return false ;
236+ }
237+
238+ MemorySegment oreConfig = OreConfig .allocate (arena );
239+ // just do biomes.getFirst() because in 1.17 there is only one, and in 1.18 it does not matter
240+ if (Cubiomes .getOreConfig (ore , version , biomes .getFirst (), oreConfig ) == 0 ) {
241+ return false ;
242+ }
243+
244+ Set <BlockPos > ores = new HashSet <>();
245+ MemorySegment pos3List = Cubiomes .generateOres (arena , generator , surfaceNoise , oreConfig , chunkX , chunkZ );
246+ try {
247+ MemorySegment pos3s = Pos3List .pos3s (pos3List );
248+ for (int i = 0 ; i < Pos3List .size (pos3List ); i ++) {
249+ MemorySegment pos3 = Pos3 .asSlice (pos3s , i );
250+ ores .add (new BlockPos (Pos3 .x (pos3 ), Pos3 .y (pos3 ), Pos3 .z (pos3 )));
251+ }
252+ } finally {
253+ Cubiomes .freePos3List (pos3List );
254+ }
255+ count [0 ] += ores .size ();
256+ RenderManager .drawBoxes (ores , Configs .BlockColors .getOrDefault (OreConfig .oreBlock (oreConfig ), 0xFFFFFF ));
257+ source .sendFeedback (Component .translatable ("command.highlight.block.chunkSuccess" , accent (String .valueOf (ores .size ())), ComponentUtils .formatXZ (chunkX , chunkZ )));
258+ return false ;
259+ });
260+
261+ source .getClient ().schedule (() -> source .sendFeedback (Component .translatable ("command.highlight.block.success" , accent (String .valueOf (count [0 ])))));
262+ return count [0 ];
263+ }
264+ }
265+
195266 private static int highlightOreVein (CustomClientCommandSource source ) throws CommandSyntaxException {
196267 return highlightOreVein (source , 0 );
197268 }
@@ -240,8 +311,8 @@ private static int highlightOreVein(CustomClientCommandSource source, int chunkR
240311 return ;
241312 }
242313 count [0 ] += positions .size ();
243- int colour = BLOCKS . values (). stream (). filter ( pair -> Objects . equals ( block , pair . getFirst ())). findAny (). orElseThrow (). getSecond ( );
244- RenderManager .drawBoxes (positions , Configs . OreVeinESP , colour );
314+ int color = Configs . BlockColors . getOrDefault ( block , 0xFFFFFF );
315+ RenderManager .drawBoxes (positions , color );
245316 if (SeedMapper .BARITONE_AVAILABLE && Configs .AutoMine ) {
246317 BaritoneIntegration .addGoals (positions );
247318 }
0 commit comments