Search in sources :

Example 1 with BeforeChunkUnload

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;
}
Also used : BeforeChunkUnload(org.terasology.engine.world.chunks.event.BeforeChunkUnload) Chunk(org.terasology.engine.world.chunks.Chunk)

Example 2 with BeforeChunkUnload

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");
}
Also used : ChunkImpl(org.terasology.engine.world.chunks.internal.ChunkImpl) BeforeEach(org.junit.jupiter.api.BeforeEach) TimeoutException(java.util.concurrent.TimeoutException) Block(org.terasology.engine.world.block.Block) OnAddedBlocks(org.terasology.engine.world.block.OnAddedBlocks) Future(java.util.concurrent.Future) Vector3ic(org.joml.Vector3ic) ArgumentCaptor(org.mockito.ArgumentCaptor) Event(org.terasology.engine.entitySystem.event.Event) Vector3i(org.joml.Vector3i) Chunk(org.terasology.engine.world.chunks.Chunk) Duration(java.time.Duration) Map(java.util.Map) Mockito.atLeast(org.mockito.Mockito.atLeast) OnChunkGenerated(org.terasology.engine.world.chunks.event.OnChunkGenerated) OnActivatedBlocks(org.terasology.engine.world.block.OnActivatedBlocks) BlockRegion(org.terasology.engine.world.block.BlockRegion) TestWorldGenerator(org.terasology.fixtures.TestWorldGenerator) TestBlockManager(org.terasology.fixtures.TestBlockManager) EntityManager(org.terasology.engine.entitySystem.entity.EntityManager) BeforeDeactivateBlocks(org.terasology.engine.world.block.BeforeDeactivateBlocks) OnChunkLoaded(org.terasology.engine.world.chunks.event.OnChunkLoaded) Maps(com.google.common.collect.Maps) TestStorageManager(org.terasology.fixtures.TestStorageManager) Mockito.verify(org.mockito.Mockito.verify) Test(org.junit.jupiter.api.Test) ExecutionException(java.util.concurrent.ExecutionException) TimeUnit(java.util.concurrent.TimeUnit) AfterEach(org.junit.jupiter.api.AfterEach) BeforeChunkUnload(org.terasology.engine.world.chunks.event.BeforeChunkUnload) ChronoUnit(java.time.temporal.ChronoUnit) ExtraBlockDataManager(org.terasology.engine.world.chunks.blockdata.ExtraBlockDataManager) EntityRef(org.terasology.engine.entitySystem.entity.EntityRef) BlockManager(org.terasology.engine.world.block.BlockManager) Assertions(org.junit.jupiter.api.Assertions) Optional(java.util.Optional) BlockEntityRegistry(org.terasology.engine.world.BlockEntityRegistry) TestChunkStore(org.terasology.fixtures.TestChunkStore) Mockito.mock(org.mockito.Mockito.mock) BeforeChunkUnload(org.terasology.engine.world.chunks.event.BeforeChunkUnload) Vector3i(org.joml.Vector3i) Event(org.terasology.engine.entitySystem.event.Event) EntityRef(org.terasology.engine.entitySystem.entity.EntityRef) BeforeDeactivateBlocks(org.terasology.engine.world.block.BeforeDeactivateBlocks) Test(org.junit.jupiter.api.Test)

Example 3 with BeforeChunkUnload

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();
    }
}
Also used : BeforeChunkUnload(org.terasology.engine.world.chunks.event.BeforeChunkUnload) LightMerger(org.terasology.engine.world.propagation.light.LightMerger) Vector3ic(org.joml.Vector3ic) ChunkRelevanceRegion(org.terasology.engine.world.chunks.internal.ChunkRelevanceRegion) Vector3i(org.joml.Vector3i) PurgeWorldEvent(org.terasology.engine.world.chunks.event.PurgeWorldEvent) ChunkProcessingPipeline(org.terasology.engine.world.chunks.pipeline.ChunkProcessingPipeline) Chunk(org.terasology.engine.world.chunks.Chunk)

Example 4 with BeforeChunkUnload

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();
        }
    }
}
Also used : BeforeChunkUnload(org.terasology.engine.world.chunks.event.BeforeChunkUnload) Vector3ic(org.joml.Vector3ic) Chunk(org.terasology.engine.world.chunks.Chunk)

Aggregations

Chunk (org.terasology.engine.world.chunks.Chunk)4 BeforeChunkUnload (org.terasology.engine.world.chunks.event.BeforeChunkUnload)4 Vector3ic (org.joml.Vector3ic)3 Vector3i (org.joml.Vector3i)2 Maps (com.google.common.collect.Maps)1 Duration (java.time.Duration)1 ChronoUnit (java.time.temporal.ChronoUnit)1 Map (java.util.Map)1 Optional (java.util.Optional)1 ExecutionException (java.util.concurrent.ExecutionException)1 Future (java.util.concurrent.Future)1 TimeUnit (java.util.concurrent.TimeUnit)1 TimeoutException (java.util.concurrent.TimeoutException)1 AfterEach (org.junit.jupiter.api.AfterEach)1 Assertions (org.junit.jupiter.api.Assertions)1 BeforeEach (org.junit.jupiter.api.BeforeEach)1 Test (org.junit.jupiter.api.Test)1 ArgumentCaptor (org.mockito.ArgumentCaptor)1 Mockito.atLeast (org.mockito.Mockito.atLeast)1 Mockito.mock (org.mockito.Mockito.mock)1