@@ -66,8 +66,6 @@ public class MCAWorld implements World {
6666 private static final Grid CHUNK_GRID = new Grid (16 );
6767 private static final Grid REGION_GRID = new Grid (32 ).multiply (CHUNK_GRID );
6868
69- private static final Vector2iCache VECTOR_2_I_CACHE = new Vector2iCache ();
70-
7169 private final String id ;
7270 private final Path worldFolder ;
7371 private final Key dimension ;
@@ -77,23 +75,8 @@ public class MCAWorld implements World {
7775 private final DimensionType dimensionType ;
7876 private final Vector3i spawnPoint ;
7977 private final Path dimensionFolder ;
80- private final Path regionFolder ;
8178
82- private final MCAChunkLoader chunkLoader = new MCAChunkLoader (this );
83- private final LoadingCache <Vector2i , Region <Chunk >> regionCache = Caffeine .newBuilder ()
84- .executor (BlueMap .THREAD_POOL )
85- .softValues ()
86- .maximumSize (32 )
87- .expireAfterWrite (10 , TimeUnit .MINUTES )
88- .expireAfterAccess (1 , TimeUnit .MINUTES )
89- .build (this ::loadRegion );
90- private final LoadingCache <Vector2i , Chunk > chunkCache = Caffeine .newBuilder ()
91- .executor (BlueMap .THREAD_POOL )
92- .softValues ()
93- .maximumSize (10240 ) // 10 regions worth of chunks
94- .expireAfterWrite (10 , TimeUnit .MINUTES )
95- .expireAfterAccess (1 , TimeUnit .MINUTES )
96- .build (this ::loadChunk );
79+ private final ChunkGrid <Chunk > blockChunkGrid ;
9780
9881 private MCAWorld (Path worldFolder , Key dimension , DataPack dataPack , LevelData levelData ) {
9982 this .id = World .id (worldFolder , dimension );
@@ -121,7 +104,9 @@ private MCAWorld(Path worldFolder, Key dimension, DataPack dataPack, LevelData l
121104 levelData .getData ().getSpawnZ ()
122105 );
123106 this .dimensionFolder = resolveDimensionFolder (worldFolder , dimension );
124- this .regionFolder = dimensionFolder .resolve ("region" );
107+
108+ this .blockChunkGrid = new ChunkGrid <>(new MCAChunkLoader (this ), dimensionFolder .resolve ("region" ));
109+
125110 }
126111
127112 @ Override
@@ -146,129 +131,44 @@ public Chunk getChunkAtBlock(int x, int z) {
146131
147132 @ Override
148133 public Chunk getChunk (int x , int z ) {
149- return getChunk (VECTOR_2_I_CACHE .get (x , z ));
150- }
151-
152- private Chunk getChunk (Vector2i pos ) {
153- return chunkCache .get (pos );
134+ return blockChunkGrid .getChunk (x , z );
154135 }
155136
156137 @ Override
157138 public Region <Chunk > getRegion (int x , int z ) {
158- return getRegion (VECTOR_2_I_CACHE .get (x , z ));
159- }
160-
161- private Region <Chunk > getRegion (Vector2i pos ) {
162- return regionCache .get (pos );
139+ return blockChunkGrid .getRegion (x , z );
163140 }
164141
165142 @ Override
166143 public Collection <Vector2i > listRegions () {
167- if (!Files .exists (regionFolder )) return Collections .emptyList ();
168- try (Stream <Path > stream = Files .list (regionFolder )) {
169- return stream
170- .map (file -> {
171- try {
172- if (Files .size (file ) <= 0 ) return null ;
173- return RegionType .regionForFileName (file .getFileName ().toString ());
174- } catch (IOException ex ) {
175- Logger .global .logError ("Failed to read region-file: " + file , ex );
176- return null ;
177- }
178- })
179- .filter (Objects ::nonNull )
180- .toList ();
181- } catch (IOException ex ) {
182- Logger .global .logError ("Failed to list regions for world: '" + getId () + "'" , ex );
183- return List .of ();
184- }
144+ return blockChunkGrid .listRegions ();
185145 }
186146
187147 @ Override
188148 public WatchService <Vector2i > createRegionWatchService () throws IOException {
189- return new MCAWorldRegionWatchService ( this . regionFolder );
149+ return blockChunkGrid . createRegionWatchService ( );
190150 }
191151
192152 @ Override
193153 public void preloadRegionChunks (int x , int z , Predicate <Vector2i > chunkFilter ) {
194- try {
195- getRegion (x , z ).iterateAllChunks (new ChunkConsumer <>() {
196- @ Override
197- public boolean filter (int chunkX , int chunkZ , int lastModified ) {
198- Vector2i chunkPos = VECTOR_2_I_CACHE .get (chunkX , chunkZ );
199- return chunkFilter .test (chunkPos );
200- }
201-
202- @ Override
203- public void accept (int chunkX , int chunkZ , Chunk chunk ) {
204- Vector2i chunkPos = VECTOR_2_I_CACHE .get (chunkX , chunkZ );
205- chunkCache .put (chunkPos , chunk );
206- }
207- });
208- } catch (IOException ex ) {
209- Logger .global .logDebug ("Unexpected exception trying to load preload region (x:" + x + ", z:" + z + "): " + ex );
210- }
154+ blockChunkGrid .preloadRegionChunks (x , z , chunkFilter );
211155 }
212156
213157 @ Override
214158 public void invalidateChunkCache () {
215- regionCache .invalidateAll ();
216- chunkCache .invalidateAll ();
159+ blockChunkGrid .invalidateChunkCache ();
217160 }
218161
219162 @ Override
220163 public void invalidateChunkCache (int x , int z ) {
221- regionCache .invalidate (VECTOR_2_I_CACHE .get (x >> 5 , z >> 5 ));
222- chunkCache .invalidate (VECTOR_2_I_CACHE .get (x , z ));
164+ blockChunkGrid .invalidateChunkCache (x , z );
223165 }
224166
225167 @ Override
226168 public void iterateEntities (int minX , int minZ , int maxX , int maxZ , Consumer <Entity > entityConsumer ) {
227169 //TODO
228170 }
229171
230- private Region <Chunk > loadRegion (Vector2i regionPos ) {
231- return loadRegion (regionPos .getX (), regionPos .getY ());
232- }
233-
234- private Region <Chunk > loadRegion (int x , int z ) {
235- return RegionType .loadRegion (chunkLoader , getRegionFolder (), x , z );
236- }
237-
238- private Chunk loadChunk (Vector2i chunkPos ) {
239- return loadChunk (chunkPos .getX (), chunkPos .getY ());
240- }
241-
242- private Chunk loadChunk (int x , int z ) {
243- final int tries = 3 ;
244- final int tryInterval = 1000 ;
245-
246- Exception loadException = null ;
247- for (int i = 0 ; i < tries ; i ++) {
248- try {
249- return getRegion (x >> 5 , z >> 5 )
250- .loadChunk (x , z );
251- } catch (IOException | RuntimeException e ) {
252- if (loadException != null && loadException != e )
253- e .addSuppressed (loadException );
254-
255- loadException = e ;
256-
257- if (i + 1 < tries ) {
258- try {
259- Thread .sleep (tryInterval );
260- } catch (InterruptedException ex ) {
261- Thread .currentThread ().interrupt ();
262- break ;
263- }
264- }
265- }
266- }
267-
268- Logger .global .logDebug ("Unexpected exception trying to load chunk (x:" + x + ", z:" + z + "): " + loadException );
269- return Chunk .ERRORED_CHUNK ;
270- }
271-
272172 public static MCAWorld load (Path worldFolder , Key dimension , DataPack dataPack ) throws IOException , InterruptedException {
273173
274174 // load level.dat
0 commit comments