1 /** 2 Copyright: Copyright (c) 2013-2017 Andrey Penechko. 3 License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0). 4 Authors: Andrey Penechko. 5 */ 6 module voxelman.world.gen.worker; 7 8 import voxelman.log; 9 10 import voxelman.container.sharedhashset; 11 import voxelman.world.block; 12 import voxelman.core.config; 13 import voxelman.utils.worker; 14 import voxelman.world.storage.coordinates; 15 import voxelman.world.storage.chunk; 16 import voxelman.world.storage.chunkprovider : TaskId, TASK_CANCELED_METADATA; 17 18 import voxelman.world.gen.utils; 19 import voxelman.world.gen.generator; 20 21 //version = DBG_OUT; 22 void chunkGenWorkerThread( 23 shared(Worker)* workerInfo, 24 shared SharedHashSet!TaskId canceledTasks, 25 BlockInfoTable blockInfos) 26 { 27 import std.array : uninitializedArray; 28 29 ubyte[] compressBuffer = uninitializedArray!(ubyte[])(CHUNK_SIZE_CUBE*BlockId.sizeof); 30 try 31 { 32 while (workerInfo.needsToRun) 33 { 34 workerInfo.waitForNotify(); 35 36 if (!workerInfo.taskQueue.empty) 37 { 38 TaskId taskId = workerInfo.taskQueue.popItem!TaskId(); 39 ulong _cwp = workerInfo.taskQueue.popItem!ulong(); 40 ChunkWorldPos cwp = ChunkWorldPos(_cwp); 41 IGenerator generator = workerInfo.taskQueue.popItem!IGenerator(); 42 43 if (canceledTasks[taskId]) 44 { 45 workerInfo.resultQueue.startMessage(); 46 workerInfo.resultQueue.pushMessagePart(taskId); 47 workerInfo.resultQueue.pushMessagePart(ChunkHeaderItem(cwp, 0, TASK_CANCELED_METADATA)); 48 workerInfo.resultQueue.endMessage(); 49 50 continue; 51 } 52 53 genChunk(taskId, cwp, &workerInfo.resultQueue, 54 generator, blockInfos, compressBuffer); 55 } 56 } 57 } 58 catch(Throwable t) 59 { 60 import std.conv : to; 61 infof("%s from gen worker", t.to!string); 62 throw t; 63 } 64 version(DBG_OUT)infof("Gen worker stopped"); 65 } 66 67 //version = DBG_COMPR; 68 void genChunk( 69 TaskId taskId, 70 ChunkWorldPos cwp, 71 shared(SharedQueue)* resultQueue, 72 IGenerator generator, 73 BlockInfoTable blockInfos, 74 ubyte[] compressBuffer) 75 { 76 BlockId[CHUNK_SIZE_CUBE] blocks; 77 ChunkGeneratorResult chunk = generator.generateChunk( 78 cwp.xyz, blocks); 79 80 enum layerId = BLOCK_LAYER; 81 enum timestamp = 0; 82 enum numLayers = 1; 83 84 resultQueue.startMessage(); 85 resultQueue.pushMessagePart(taskId); 86 resultQueue.pushMessagePart(ChunkHeaderItem(cwp, numLayers)); 87 88 if(chunk.uniform) 89 { 90 ushort metadata = calcChunkFullMetadata(chunk.uniformBlockId, blockInfos); 91 auto layer = ChunkLayerItem(layerId, 92 BLOCKID_UNIFORM_FILL_BITS, timestamp, 93 chunk.uniformBlockId, metadata); 94 resultQueue.pushMessagePart(layer); 95 } 96 else 97 { 98 ushort metadata = calcChunkFullMetadata(blocks, blockInfos); 99 ubyte[] compactBlocks = compressLayerData(cast(ubyte[])blocks, compressBuffer); 100 StorageType storageType = StorageType.compressedArray; 101 ubyte[] data = allocLayerArray(compactBlocks); 102 103 auto layer = ChunkLayerItem(storageType, layerId, timestamp, data, metadata); 104 resultQueue.pushMessagePart(layer); 105 } 106 resultQueue.endMessage(); 107 }