ChunkRelevanceRegion region = regions.get(entity); if (region != null) { region.setRelevanceDistance(distance); return; regionLock.readLock().unlock(); ChunkRelevanceRegion region = new ChunkRelevanceRegion(entity, distance); if (listener != null) { region.setListener(listener); regionLock.writeLock().unlock(); for (Vector3i pos : region.getCurrentRegion()) { Chunk chunk = getChunk(pos); if (chunk != null) { region.checkIfChunkIsRelevant(chunk); } else { createOrLoadChunk(pos);
public void update() { if (!isValid()) { dirty = false; } else { Vector3i newCenter = calculateCenter(); if (!newCenter.equals(center)) { dirty = true; center.set(newCenter); currentRegion = calculateRegion(); reviewRelevantChunks(relevanceDistance); } } }
private int score(Vector3i chunk) { int score = Integer.MAX_VALUE; regionLock.readLock().lock(); try { for (ChunkRelevanceRegion region : regions.values()) { int dist = distFromRegion(chunk, region.getCenter()); if (dist < score) { score = dist; } } return score; } finally { regionLock.readLock().unlock(); } }
private void updateRelevance() { for (ChunkRelevanceRegion chunkRelevanceRegion : regions.values()) { chunkRelevanceRegion.update(); if (chunkRelevanceRegion.isDirty()) { for (Vector3i pos : chunkRelevanceRegion.getNeededChunks()) { Chunk chunk = chunkCache.get(pos); if (chunk != null) { chunkRelevanceRegion.checkIfChunkIsRelevant(chunk); } else { createOrLoadChunk(pos); } } chunkRelevanceRegion.setUpToDate(); } } }
public void setRelevanceDistance(Vector3i distance) { if (!distance.equals(this.relevanceDistance)) { reviewRelevantChunks(distance); this.relevanceDistance.set(distance); this.currentRegion = calculateRegion(); dirty = true; } }
@Override public void purgeWorld() { ChunkMonitor.fireChunkProviderDisposed(this); pipeline.shutdown(); unloadRequestTaskMaster.shutdown(new ChunkUnloadRequest(), true); chunkFinalizer.shutdown(); chunkCache.getAllChunks().stream().filter(ManagedChunk::isReady).forEach(chunk -> { worldEntity.send(new BeforeChunkUnload(chunk.getPosition())); storageManager.deactivateChunk(chunk); chunk.dispose(); }); chunkCache.clear(); readyChunks.clear(); sortedReadyChunks.clear(); storageManager.deleteWorld(); preparingChunks.clear(); worldEntity.send(new PurgeWorldEvent()); pipeline = new ChunkGenerationPipeline(new ChunkTaskRelevanceComparator()); unloadRequestTaskMaster = TaskMaster.createFIFOTaskMaster("Chunk-Unloader", 8); chunkFinalizer = chunkFinalizerSupplier.get(); chunkFinalizer.initialize(this); chunkFinalizer.restart(); ChunkMonitor.fireChunkProviderInitialized(this); for (ChunkRelevanceRegion chunkRelevanceRegion : regions.values()) { for (Vector3i pos : chunkRelevanceRegion.getCurrentRegion()) { createOrLoadChunk(pos); } chunkRelevanceRegion.setUpToDate(); } }
private void updateRelevanceRegionsWithNewChunks(List<ReadyChunkInfo> newReadyChunks) { for (ReadyChunkInfo readyChunkInfo : newReadyChunks) { for (ChunkRelevanceRegion region : regions.values()) { region.checkIfChunkIsRelevant(readyChunkInfo.getChunk()); } } }
private void checkForUnload() { PerformanceMonitor.startActivity("Unloading irrelevant chunks"); int unloaded = 0; logger.debug("Compacting cache"); Iterator<Vector3i> iterator = chunkCache.iterateChunkPositions(); while (iterator.hasNext()) { Vector3i pos = iterator.next(); boolean keep = false; for (ChunkRelevanceRegion region : regions.values()) { if (region.getCurrentRegion().expand(UNLOAD_LEEWAY).encompasses(pos)) { keep = true; break; } } if (!keep) { // TODO: need some way to not dispose chunks being edited or processed (or do so safely) // Note: Above won't matter if all changes are on the main thread if (unloadChunkInternal(pos)) { iterator.remove(); if (++unloaded >= UNLOAD_PER_FRAME) { break; } } } } PerformanceMonitor.endActivity(); }
public ChunkRelevanceRegion(EntityRef entity, Vector3i relevanceDistance) { this.entity = entity; this.relevanceDistance.set(relevanceDistance); LocationComponent loc = entity.getComponent(LocationComponent.class); if (loc == null) { dirty = false; } else { center.set(ChunkMath.calcChunkPos(loc.getWorldPosition())); currentRegion = calculateRegion(); dirty = true; } }
private boolean unloadChunkInternal(Vector3i pos) { Chunk chunk = chunkCache.get(pos); if (!chunk.isReady()) { // Chunk hasn't been finished or changed, so just drop it. Iterator<ReadyChunkInfo> infoIterator = sortedReadyChunks.iterator(); while (infoIterator.hasNext()) { ReadyChunkInfo next = infoIterator.next(); if (next.getPos().equals(chunk.getPosition())) { infoIterator.remove(); break; } } return true; } worldEntity.send(new BeforeChunkUnload(pos)); for (ChunkRelevanceRegion region : regions.values()) { region.chunkUnloaded(pos); } storageManager.deactivateChunk(chunk); chunk.dispose(); try { unloadRequestTaskMaster.put(new ChunkUnloadRequest(chunk, this)); } catch (InterruptedException e) { logger.error("Failed to enqueue unload request for {}", chunk.getPosition(), e); } return true; }
private int score(Vector3i chunk) { int score = Integer.MAX_VALUE; regionLock.readLock().lock(); try { for (ChunkRelevanceRegion region : regions.values()) { int dist = distFromRegion(chunk, region.getCenter()); if (dist < score) { score = dist; } } return score; } finally { regionLock.readLock().unlock(); } }