use of org.terasology.engine.world.chunks.event.BeforeChunkUnload in project Terasology by MovingBlocks.
the class LocalChunkProvider method unloadChunkInternal.
private boolean unloadChunkInternal(Vector3ic pos) {
if (loadingPipeline.isPositionProcessing(pos)) {
// Chunk hasn't been finished or changed, so just drop it.
loadingPipeline.stopProcessingAt(pos);
return false;
}
Chunk chunk = chunkCache.get(pos);
if (chunk == null) {
return false;
}
worldEntity.send(new BeforeChunkUnload(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;
}
use of org.terasology.engine.world.chunks.event.BeforeChunkUnload in project Terasology by MovingBlocks.
the class LocalChunkProviderTest method testUnloadChunkAndDeactivationBlock.
@Test
void testUnloadChunkAndDeactivationBlock() throws InterruptedException, TimeoutException, ExecutionException {
Vector3i chunkPosition = new Vector3i(0, 0, 0);
blockAtBlockManager.setLifecycleEventsRequired(true);
blockAtBlockManager.setEntity(mock(EntityRef.class));
requestCreatingOrLoadingArea(chunkPosition).get(WAIT_CHUNK_IS_READY_IN_SECONDS, TimeUnit.SECONDS);
// Wait BeforeDeactivateBlocks event
Assertions.assertTimeoutPreemptively(Duration.of(WAIT_CHUNK_IS_READY_IN_SECONDS, ChronoUnit.SECONDS), () -> {
ArgumentCaptor<Event> blockEventCaptor = ArgumentCaptor.forClass(Event.class);
while (!blockEventCaptor.getAllValues().stream().filter((e) -> e instanceof BeforeDeactivateBlocks).map((e) -> (BeforeDeactivateBlocks) e).findFirst().isPresent()) {
chunkProvider.update();
blockEventCaptor = ArgumentCaptor.forClass(Event.class);
verify(blockAtBlockManager.getEntity(), atLeast(1)).send(blockEventCaptor.capture());
}
});
final ArgumentCaptor<Event> eventArgumentCaptor = ArgumentCaptor.forClass(Event.class);
verify(worldEntity, atLeast(1)).send(eventArgumentCaptor.capture());
Optional<BeforeChunkUnload> beforeChunkUnload = eventArgumentCaptor.getAllValues().stream().filter((e) -> e instanceof BeforeChunkUnload).map((e) -> (BeforeChunkUnload) e).findFirst();
Assertions.assertTrue(beforeChunkUnload.isPresent(), "World events must have BeforeChunkUnload event when chunk was unload");
Assertions.assertEquals(chunkPosition, beforeChunkUnload.get().getChunkPos(), "Chunk position at event not expected");
// TODO, it is not clear if the activate/addedBlocks event logic is correct.
// See https://github.com/MovingBlocks/Terasology/issues/3244
final ArgumentCaptor<Event> blockEventCaptor = ArgumentCaptor.forClass(Event.class);
verify(blockAtBlockManager.getEntity(), atLeast(2)).send(blockEventCaptor.capture());
Optional<BeforeDeactivateBlocks> beforeDeactivateBlocks = blockEventCaptor.getAllValues().stream().filter((e) -> e instanceof BeforeDeactivateBlocks).map((e) -> (BeforeDeactivateBlocks) e).findFirst();
Assertions.assertTrue(beforeDeactivateBlocks.isPresent(), "World events must have BeforeDeactivateBlocks event when chunk with lifecycle blocks was unload");
Assertions.assertTrue(beforeDeactivateBlocks.get().blockCount() > 0, "BeforeDeactivateBlocks must have block count more then zero");
}
use of org.terasology.engine.world.chunks.event.BeforeChunkUnload in project Terasology by MovingBlocks.
the class LocalChunkProvider method purgeWorld.
@Override
public void purgeWorld() {
ChunkMonitor.fireChunkProviderDisposed(this);
loadingPipeline.shutdown();
unloadRequestTaskMaster.shutdown(new ChunkUnloadRequest(), true);
getAllChunks().stream().filter(Chunk::isReady).forEach(chunk -> {
worldEntity.send(new BeforeChunkUnload(chunk.getPosition(new Vector3i())));
storageManager.deactivateChunk(chunk);
chunk.dispose();
});
chunkCache.clear();
storageManager.deleteWorld();
worldEntity.send(new PurgeWorldEvent());
loadingPipeline = new ChunkProcessingPipeline(this::getChunk, relevanceSystem.createChunkTaskComporator());
loadingPipeline.addStage(ChunkTaskProvider.create("Chunk generate internal lightning", (Consumer<Chunk>) InternalLightProcessor::generateInternalLighting)).addStage(ChunkTaskProvider.create("Chunk deflate", Chunk::deflate)).addStage(ChunkTaskProvider.createMulti("Light merging", chunks -> {
Chunk[] localChunks = chunks.toArray(new Chunk[0]);
return LightMerger.merge(localChunks);
}, LightMerger::requiredChunks)).addStage(ChunkTaskProvider.create("Chunk ready", readyChunks::add));
unloadRequestTaskMaster = TaskMaster.createFIFOTaskMaster("Chunk-Unloader", 8);
ChunkMonitor.fireChunkProviderInitialized(this);
for (ChunkRelevanceRegion chunkRelevanceRegion : relevanceSystem.getRegions()) {
for (Vector3ic pos : chunkRelevanceRegion.getCurrentRegion()) {
createOrLoadChunk(pos);
}
chunkRelevanceRegion.setUpToDate();
}
}
use of org.terasology.engine.world.chunks.event.BeforeChunkUnload in project Terasology by MovingBlocks.
the class RemoteChunkProvider method checkForUnload.
private void checkForUnload() {
List<Vector3ic> positions = Lists.newArrayListWithCapacity(invalidateChunks.size());
invalidateChunks.drainTo(positions);
for (Vector3ic pos : positions) {
Chunk removed = chunkCache.remove(pos);
if (removed != null && !removed.isReady()) {
worldEntity.send(new BeforeChunkUnload(pos));
removed.dispose();
}
}
}
Aggregations