@@ -315,7 +315,7 @@ record StructureIterationState(MemorySegment structureConfig, StructureChecks.Ge
315315 })
316316 .collect (Collectors .toList ());
317317
318- Map < String , MemorySegment > lootTableContextCache = new HashMap <>( );
318+ MemorySegment ltcPtr = arena . allocate ( Cubiomes . C_POINTER );
319319 // count how many loot tables each structure has
320320 Map <Integer , Integer > lootTableCount = structureStates .stream ()
321321 .collect (Collectors .toMap (state -> (int ) StructureConfig .structType (state .structureConfig ), state -> Cubiomes .getLootTableCountForStructure (StructureConfig .structType (state .structureConfig ), version )));
@@ -328,123 +328,117 @@ record StructureIterationState(MemorySegment structureConfig, StructureChecks.Ge
328328 MemorySegment structureSaltConfig = StructureSaltConfig .allocate (arena );
329329 int [] found = {0 };
330330
331- try {
332- /*
333- * To locate loot closest to the player, all structures
334- * must be considered. That means we must cycle over
335- * the structures and incrementally find the desired
336- * loot. However, structures have different region
337- * sizes. That means some structures appear more often
338- * than others. To this end, the below code intends to
339- * loop over structures with smaller region sizes more
340- * often.
341- */
342- for (int stateIndex = 0 , radius = 0 ;; stateIndex ++) {
343- if (structureStates .isEmpty ()) {
344- throw CommandExceptions .LOOT_NOT_AVAILABLE_EXCEPTION .create ();
345- }
346- if (stateIndex >= structureStates .size ()) {
347- stateIndex = 0 ;
348- radius ++;
331+ /*
332+ * To locate loot closest to the player, all structures
333+ * must be considered. That means we must cycle over
334+ * the structures and incrementally find the desired
335+ * loot. However, structures have different region
336+ * sizes. That means some structures appear more often
337+ * than others. To this end, the below code intends to
338+ * loop over structures with smaller region sizes more
339+ * often.
340+ */
341+ for (int stateIndex = 0 , radius = 0 ;; stateIndex ++) {
342+ if (structureStates .isEmpty ()) {
343+ throw CommandExceptions .LOOT_NOT_AVAILABLE_EXCEPTION .create ();
344+ }
345+ if (stateIndex >= structureStates .size ()) {
346+ stateIndex = 0 ;
347+ radius ++;
348+ }
349+ StructureIterationState state = structureStates .get (stateIndex );
350+ MemorySegment structureConfig = state .structureConfig ;
351+ int structure = StructureConfig .structType (structureConfig );
352+
353+ int regionSize = StructureConfig .regionSize (structureConfig ) << 4 ;
354+ int maxRegionSize = StructureConfig .regionSize (structureStates .getLast ().structureConfig ) << 4 ;
355+
356+ int previouslyFound = found [0 ];
357+ List <BlockPos > aggregatedLootPositions = new ArrayList <>();
358+ while (true ) {
359+ if (state .iterator .getX () * regionSize > center .getX () + radius * maxRegionSize
360+ || state .iterator .getZ () * regionSize > center .getZ () + radius * maxRegionSize ) {
361+ break ;
349362 }
350- StructureIterationState state = structureStates .get (stateIndex );
351- MemorySegment structureConfig = state .structureConfig ;
352- int structure = StructureConfig .structType (structureConfig );
353-
354- int regionSize = StructureConfig .regionSize (structureConfig ) << 4 ;
355- int maxRegionSize = StructureConfig .regionSize (structureStates .getLast ().structureConfig ) << 4 ;
356-
357- int previouslyFound = found [0 ];
358- List <BlockPos > aggregatedLootPositions = new ArrayList <>();
359- while (true ) {
360- if (state .iterator .getX () * regionSize > center .getX () + radius * maxRegionSize
361- || state .iterator .getZ () * regionSize > center .getZ () + radius * maxRegionSize ) {
362- break ;
363- }
364363
365- boolean exhausted = !state .iterator .tryAdvance (pos -> {
366- if (!state .generationCheck .check (generator , surfaceNoise , pos .x (), pos .z (), structurePos )) {
367- return ;
368- }
369- int posX = Pos .x (structurePos );
370- int posZ = Pos .z (structurePos );
371- int biome = Cubiomes .getBiomeAt (generator , 4 , posX >> 2 , 320 >> 2 , posZ >> 2 );
372- Cubiomes .getVariant (structureVariant , structure , version , seed , posX , posZ , biome );
373- biome = StructureVariant .biome (structureVariant ) != -1 ? StructureVariant .biome (structureVariant ) : biome ;
374- if (Cubiomes .getStructureSaltConfig (structure , version , biome , structureSaltConfig ) == 0 ) {
375- return ;
376- }
377- int numPieces = Cubiomes .getStructurePieces (pieces , StructureChecks .MAX_END_CITY_AND_FORTRESS_PIECES , structure , structureSaltConfig , structureVariant , version , seed , posX , posZ );
378- if (numPieces <= 0 ) {
379- return ;
364+ boolean exhausted = !state .iterator .tryAdvance (pos -> {
365+ if (!state .generationCheck .check (generator , surfaceNoise , pos .x (), pos .z (), structurePos )) {
366+ return ;
367+ }
368+ int posX = Pos .x (structurePos );
369+ int posZ = Pos .z (structurePos );
370+ int biome = Cubiomes .getBiomeAt (generator , 4 , posX >> 2 , 320 >> 2 , posZ >> 2 );
371+ Cubiomes .getVariant (structureVariant , structure , version , seed , posX , posZ , biome );
372+ biome = StructureVariant .biome (structureVariant ) != -1 ? StructureVariant .biome (structureVariant ) : biome ;
373+ if (Cubiomes .getStructureSaltConfig (structure , version , biome , structureSaltConfig ) == 0 ) {
374+ return ;
375+ }
376+ int numPieces = Cubiomes .getStructurePieces (pieces , StructureChecks .MAX_END_CITY_AND_FORTRESS_PIECES , structure , structureSaltConfig , structureVariant , version , seed , posX , posZ );
377+ if (numPieces <= 0 ) {
378+ return ;
379+ }
380+ int foundInStructure = 0 ;
381+ for (int i = 0 ; i < numPieces ; i ++) {
382+ MemorySegment piece = Piece .asSlice (pieces , i );
383+ int chestCount = Piece .chestCount (piece );
384+ if (chestCount == 0 ) {
385+ continue ;
380386 }
381- int foundInStructure = 0 ;
382- for (int i = 0 ; i < numPieces ; i ++) {
383- MemorySegment piece = Piece .asSlice (pieces , i );
384- int chestCount = Piece .chestCount (piece );
385- if (chestCount == 0 ) {
386- continue ;
387+ MemorySegment lootTables = Piece .lootTables (piece );
388+ MemorySegment lootSeeds = Piece .lootSeeds (piece );
389+ for (int j = 0 ; j < chestCount ; j ++) {
390+ MemorySegment lootTable = lootTables .getAtIndex (ValueLayout .ADDRESS , j ).reinterpret (Long .MAX_VALUE );
391+ MemorySegment lootTableContext ;
392+ if (Cubiomes .init_loot_table_name (ltcPtr , lootTable , version ) == 0 ) {
393+ lootTableContext = null ;
394+ } else {
395+ lootTableContext = ltcPtr .get (ValueLayout .ADDRESS , 0 ).reinterpret (LootTableContext .sizeof ());
387396 }
388- MemorySegment lootTables = Piece .lootTables (piece );
389- MemorySegment lootSeeds = Piece .lootSeeds (piece );
390- for (int j = 0 ; j < chestCount ; j ++) {
391- MemorySegment lootTable = lootTables .getAtIndex (ValueLayout .ADDRESS , j ).reinterpret (Long .MAX_VALUE );
392- String lootTableString = lootTable .getString (0 );
393- MemorySegment lootTableContext = lootTableContextCache .computeIfAbsent (lootTableString , _ -> {
394- MemorySegment ltc = LootTableContext .allocate (arena );
395- if (Cubiomes .init_loot_table_name (ltc , lootTable , version ) == 0 ) {
396- return null ;
397- }
398- return ltc ;
399- });
400- if (lootTableContext == null || Cubiomes .has_item (lootTableContext , itemPredicate .item ()) == 0 ) {
401- Set <String > structureIgnoredLootTables = ignoredLootTables .computeIfAbsent (structure , _ -> new HashSet <>());
402- structureIgnoredLootTables .add (lootTableString );
403- // if structure has no loot tables with the desired item, remove structure from state loop
404- if (structureIgnoredLootTables .size () == lootTableCount .get (structure )) {
405- return ;
406- }
407- continue ;
397+ if (lootTableContext == null || Cubiomes .has_item (lootTableContext , itemPredicate .item ()) == 0 ) {
398+ Set <String > structureIgnoredLootTables = ignoredLootTables .computeIfAbsent (structure , _ -> new HashSet <>());
399+ structureIgnoredLootTables .add (lootTable .getString (0 ));
400+ // if structure has no loot tables with the desired item, remove structure from state loop
401+ if (structureIgnoredLootTables .size () == lootTableCount .get (structure )) {
402+ return ;
408403 }
409- Cubiomes .set_loot_seed (lootTableContext , lootSeeds .getAtIndex (Cubiomes .C_LONG_LONG , j ));
410- Cubiomes .generate_loot (lootTableContext );
411- int lootCount = LootTableContext .generated_item_count (lootTableContext );
412- for (int k = 0 ; k < lootCount ; k ++) {
413- MemorySegment itemStack = ItemStack .asSlice (LootTableContext .generated_items (lootTableContext ), k );
414- if (Cubiomes .get_global_item_id (lootTableContext , ItemStack .item (itemStack )) == itemPredicate .item () && itemPredicate .enchantmensPredicate ().test (itemStack )) {
415- foundInStructure += ItemStack .count (itemStack );
416- }
404+ continue ;
405+ }
406+ Cubiomes .set_loot_seed (lootTableContext , lootSeeds .getAtIndex (Cubiomes .C_LONG_LONG , j ));
407+ Cubiomes .generate_loot (lootTableContext );
408+ int lootCount = LootTableContext .generated_item_count (lootTableContext );
409+ for (int k = 0 ; k < lootCount ; k ++) {
410+ MemorySegment itemStack = ItemStack .asSlice (LootTableContext .generated_items (lootTableContext ), k );
411+ if (Cubiomes .get_global_item_id (lootTableContext , ItemStack .item (itemStack )) == itemPredicate .item () && itemPredicate .enchantmensPredicate ().test (itemStack )) {
412+ foundInStructure += ItemStack .count (itemStack );
417413 }
418414 }
419415 }
420- if (foundInStructure > 0 ) {
421- found [0 ] += foundInStructure ;
422- aggregatedLootPositions .add (new BlockPos (posX , 0 , posZ ));
423- }
424- });
425- if (exhausted ) {
426- structureStates .remove (stateIndex );
427- break ;
428- }
429- if (ignoredLootTables .getOrDefault (structure , Collections .emptySet ()).size () == lootTableCount .get (structure )) {
430- structureStates .remove (stateIndex );
431- break ;
432416 }
433- if (found [0 ] >= amount ) {
434- break ;
417+ if (foundInStructure > 0 ) {
418+ found [0 ] += foundInStructure ;
419+ aggregatedLootPositions .add (new BlockPos (posX , 0 , posZ ));
435420 }
421+ });
422+ if (exhausted ) {
423+ structureStates .remove (stateIndex );
424+ break ;
436425 }
437- int newlyFound = found [0 ] - previouslyFound ;
438- if (newlyFound > 0 ) {
439- String structureName = Cubiomes .struct2str (StructureConfig .structType (structureConfig )).getString (0 );
440- source .getClient ().schedule (() -> source .sendFeedback (Component .translatable ("command.locate.loot.foundAtStructure" , accent (String .valueOf (newlyFound )), structureName , ComponentUtils .formatXZCollection (aggregatedLootPositions ))));
426+ if (ignoredLootTables .getOrDefault (structure , Collections .emptySet ()).size () == lootTableCount .get (structure )) {
427+ structureStates .remove (stateIndex );
428+ break ;
441429 }
442430 if (found [0 ] >= amount ) {
443431 break ;
444432 }
445433 }
446- } finally {
447- lootTableContextCache .values ().forEach (Cubiomes ::free_loot_table_pools );
434+ int newlyFound = found [0 ] - previouslyFound ;
435+ if (newlyFound > 0 ) {
436+ String structureName = Cubiomes .struct2str (StructureConfig .structType (structureConfig )).getString (0 );
437+ source .getClient ().schedule (() -> source .sendFeedback (Component .translatable ("command.locate.loot.foundAtStructure" , accent (String .valueOf (newlyFound )), structureName , ComponentUtils .formatXZCollection (aggregatedLootPositions ))));
438+ }
439+ if (found [0 ] >= amount ) {
440+ break ;
441+ }
448442 }
449443 String itemName = Cubiomes .global_id2item_name (itemPredicate .item (), version ).getString (0 );
450444 source .getClient ().schedule (() -> source .sendFeedback (Component .translatable ("command.locate.loot.totalFound" , accent (String .valueOf (found [0 ])), itemName )));
0 commit comments