1 /** 2 Copyright: Copyright (c) 2016 Andrey Penechko. 3 License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0). 4 Authors: Andrey Penechko. 5 */ 6 module voxelman.block.plugin; 7 8 import std.experimental.logger; 9 import std.array : array; 10 import cbor; 11 import pluginlib; 12 import voxelman.core.config : BlockId; 13 import voxelman.world.storage.coordinates; 14 import voxelman.block.utils; 15 import voxelman.utils.mapping; 16 17 import voxelman.world.plugin; 18 import voxelman.world.clientworld; 19 20 final class BlockManager : IResourceManager 21 { 22 private: 23 Mapping!BlockInfo blockMapping; 24 25 public: 26 override string id() @property { return "voxelman.block.blockmanager"; } 27 override void preInit() 28 { 29 regBaseBlocks(®Block); 30 } 31 32 BlockInfoSetter regBlock(string name) { 33 size_t id = blockMapping.put(BlockInfo(name)); 34 assert(id <= BlockId.max); 35 return BlockInfoSetter(&blockMapping, id); 36 } 37 } 38 39 mixin template BlockPluginCommonImpl() 40 { 41 private BlockManager bm; 42 immutable string blockMappingKey = "voxelman.block.block_mapping"; 43 44 override void registerResourceManagers(void delegate(IResourceManager) registerHandler) 45 { 46 registerHandler(bm = new BlockManager); 47 } 48 49 override void registerResources(IResourceManagerRegistry resmanRegistry) 50 { 51 registerResourcesImpl(resmanRegistry); 52 } 53 54 BlockInfoTable getBlocks() 55 { 56 return BlockInfoTable(cast(immutable)bm.blockMapping.infoArray); 57 } 58 } 59 60 final class BlockPluginClient : IPlugin 61 { 62 mixin BlockPluginCommonImpl; 63 // IPlugin stuff 64 mixin IdAndSemverFrom!(voxelman.block.plugininfo); 65 66 override void init(IPluginManager pluginman) 67 { 68 auto clientWorld = pluginman.getPlugin!ClientWorld; 69 clientWorld.idMapManager.regIdMapHandler(blockMappingKey, &handleBlockMap); 70 } 71 72 void handleBlockMap(string[] blocks) 73 { 74 bm.blockMapping.setMapping(blocks); 75 } 76 77 void registerResourcesImpl(IResourceManagerRegistry resmanRegistry){} 78 } 79 80 final class BlockPluginServer : IPlugin 81 { 82 mixin BlockPluginCommonImpl; 83 // IPlugin stuff 84 mixin IdAndSemverFrom!(voxelman.block.plugininfo); 85 86 void registerResourcesImpl(IResourceManagerRegistry resmanRegistry) 87 { 88 auto ioman = resmanRegistry.getResourceManager!IoManager; 89 ioman.registerWorldLoadSaveHandlers(&readBlockMap, &writeBlockMap); 90 } 91 92 override void init(IPluginManager pluginman) 93 { 94 auto serverWorld = pluginman.getPlugin!ServerWorld; 95 serverWorld.idMapManager.regIdMap(blockMappingKey, bm.blockMapping.nameRange.array); 96 } 97 98 void readBlockMap(ref PluginDataLoader loader) 99 { 100 ubyte[] data = loader.readEntry(blockMappingKey); 101 102 if (data.length) 103 { 104 string[] blocks = decodeCborSingleDup!(string[])(data); 105 bm.blockMapping.setMapping(blocks); 106 } 107 } 108 109 void writeBlockMap(ref PluginDataSaver saver) 110 { 111 auto sink = saver.tempBuffer; 112 size_t size = 0; 113 auto blockInfos = bm.blockMapping.infoArray; 114 size = encodeCborArrayHeader(sink[], blockInfos.length); 115 foreach(info; blockInfos) 116 size += encodeCbor(sink[size..$], info.name); 117 saver.writeEntry(blockMappingKey, size); 118 } 119 }