1+ using System . Collections . Concurrent ;
12using System . Collections . Generic ;
23using System . Linq ;
34using Nitrox . Model . DataStructures ;
@@ -37,34 +38,28 @@ internal sealed class BatchEntitySpawner(
3738 private readonly XorRandom random = randomFactory . GetUnityLikeRandom ( ) ;
3839 private readonly SubnauticaUweWorldEntityFactory worldEntityFactory = worldEntityFactory ;
3940
40- private readonly Lock parsedBatchesLock = new ( ) ;
41+ private readonly ConcurrentDictionary < NitroxInt3 , Lazy < Task < List < Entity > > > > batchLoadTasks = new ( ) ;
4142 private readonly Lock emptyBatchesLock = new ( ) ;
42- private HashSet < NitroxInt3 > parsedBatches = [ ] ;
4343
4444 public List < NitroxInt3 > SerializableParsedBatches
4545 {
4646 get
4747 {
48- List < NitroxInt3 > parsed ;
4948 List < NitroxInt3 > empty ;
5049
51- lock ( parsedBatchesLock )
52- {
53- parsed = [ .. parsedBatches ] ;
54- }
55-
5650 lock ( emptyBatchesLock )
5751 {
5852 empty = [ .. emptyBatches ] ;
5953 }
6054
61- return [ .. parsed . Except ( empty ) ] ;
55+ return [ .. batchLoadTasks . Keys . Except ( empty ) ] ;
6256 }
6357 set
6458 {
65- lock ( parsedBatchesLock )
59+ batchLoadTasks . Clear ( ) ;
60+ foreach ( NitroxInt3 batchId in value )
6661 {
67- parsedBatches = [ .. value ] ;
62+ batchLoadTasks . TryAdd ( batchId , new Lazy < Task < List < Entity > > > ( ( ) => Task . FromResult ( new List < Entity > ( ) ) ) ) ;
6863 }
6964 }
7065 }
@@ -73,22 +68,16 @@ public List<NitroxInt3> SerializableParsedBatches
7368
7469 public bool IsBatchSpawned ( NitroxInt3 batchId )
7570 {
76- lock ( parsedBatches )
77- {
78- return parsedBatches . Contains ( batchId ) ;
79- }
71+ return batchLoadTasks . ContainsKey ( batchId ) ;
8072 }
8173
82- public async Task < List < Entity > > LoadUnspawnedEntitiesAsync ( NitroxInt3 batchId , bool fullCacheCreation = false )
74+ public Task < List < Entity > > LoadUnspawnedEntitiesAsync ( NitroxInt3 batchId , bool fullCacheCreation = false )
8375 {
84- lock ( parsedBatches )
85- {
86- if ( ! parsedBatches . Add ( batchId ) )
87- {
88- return [ ] ;
89- }
90- }
76+ return batchLoadTasks . GetOrAdd ( batchId , id => new Lazy < Task < List < Entity > > > ( ( ) => LoadBatchInternalAsync ( id , fullCacheCreation ) ) ) . Value ;
77+ }
9178
79+ private async Task < List < Entity > > LoadBatchInternalAsync ( NitroxInt3 batchId , bool fullCacheCreation )
80+ {
9281 DeterministicGenerator deterministicBatchGenerator = new ( options . Value . Seed , batchId . ToString ( ) ) ;
9382 List < EntitySpawnPoint > spawnPoints = batchCellsParser . ParseBatchData ( batchId ) ;
9483 List < Entity > entities = await SpawnEntitiesAsync ( spawnPoints , deterministicBatchGenerator ) ;
@@ -105,7 +94,7 @@ public async Task<List<Entity>> LoadUnspawnedEntitiesAsync(NitroxInt3 batchId, b
10594 logger . ZLogInformation ( $ "Spawning { entities . Count } entities from { spawnPoints . Count } spawn points in batch { batchId } ") ;
10695 }
10796
108- for ( int x = 0 ; x < entities . Count ; x ++ ) // Throws on duplicate Entities already but nice to know which ones
97+ for ( int x = 0 ; x < entities . Count ; x ++ )
10998 {
11099 for ( int y = 0 ; y < entities . Count ; y ++ )
111100 {
0 commit comments