1 /** 2 Copyright: Copyright (c) 2016-2018 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 voxelman.graphics; 9 import voxelman.log; 10 import voxelman.math; 11 import std.array : array; 12 import cbor; 13 import pluginlib; 14 import voxelman.core.config : BlockId; 15 import voxelman.world.storage; 16 import voxelman.world.block; 17 import voxelman.utils.mapping; 18 import voxelman.globalconfig; 19 20 import voxelman.world.serverworld; 21 import voxelman.world.clientworld; 22 23 enum TEX_TILE_SIZE = 32; 24 enum TEX_TILE_SIZE_VEC = ivec2(TEX_TILE_SIZE, TEX_TILE_SIZE); 25 26 final class BlockManager : IResourceManager 27 { 28 private: 29 Mapping!BlockInfo blockMapping; 30 31 public: 32 override string id() @property { return "voxelman.block.blockmanager"; } 33 override void preInit() 34 { 35 regBaseBlocks(®Block); 36 sideTable = sideIntersectionTable(NUM_SIDE_MASKS); 37 setSideTable(sideTable); 38 } 39 40 BlockInfoSetter regBlock(string name) 41 { 42 size_t id = blockMapping.put(BlockInfo(name)); 43 assert(id <= BlockId.max); 44 return BlockInfoSetter(&blockMapping, id); 45 } 46 47 BlockInfoTable getBlocks() 48 { 49 return BlockInfoTable(cast(immutable)blockMapping.infoArray, sideTable); 50 } 51 52 // returns size_t.max if not found 53 size_t getId(string name) 54 { 55 return blockMapping.id(name); 56 } 57 58 SideIntersectionTable sideTable; 59 } 60 61 mixin template BlockPluginCommonImpl() 62 { 63 private BlockManager bm; 64 auto dbKey = IoKey("voxelman.block.block_mapping"); 65 66 override void registerResourceManagers(void delegate(IResourceManager) registerHandler) 67 { 68 registerHandler(bm = new BlockManager); 69 } 70 71 BlockInfoTable getBlocks() 72 { 73 return bm.getBlocks; 74 } 75 } 76 77 final class BlockPluginClient : IPlugin 78 { 79 mixin BlockPluginCommonImpl; 80 // IPlugin stuff 81 mixin IdAndSemverFrom!"voxelman.block.plugininfo"; 82 TextureAtlas texAtlas; 83 84 override void preInit() 85 { 86 texAtlas = new TextureAtlas(256); 87 } 88 89 override void init(IPluginManager pluginman) 90 { 91 auto clientWorld = pluginman.getPlugin!ClientWorld; 92 clientWorld.idMapManager.regIdMapHandler(dbKey.str, &handleBlockMap); 93 loadTextures(); 94 } 95 96 void loadTextures() 97 { 98 // fill 0 texture with white color 99 texAtlas.insert(TEX_TILE_SIZE_VEC, Color4ub(255, 255, 255)); 100 101 SpriteRef[string] texMap = loadNamedSpriteSheet(BUILD_TO_ROOT_PATH~"res/tex/blocks", texAtlas, TEX_TILE_SIZE_VEC); 102 103 Sprite sprite; 104 SpriteRef missingTexture = texMap.get("missing-texture", null); 105 106 if (missingTexture is null) 107 { 108 ivec2 atlasPos = texAtlas.insert(TEX_TILE_SIZE_VEC, Color4ub(0, 255, 255)); 109 sprite.atlasRect = irect(atlasPos, TEX_TILE_SIZE_VEC); 110 missingTexture = &sprite; 111 } 112 113 irect getAtlasRect(string name) { 114 return texMap.get(name, missingTexture).atlasRect; 115 } 116 117 foreach(ref BlockInfo binfo; bm.blockMapping.infoArray) 118 { 119 irect rect = getAtlasRect(binfo.name); 120 ubyte[2] uv = [cast(ubyte)(rect.x / TEX_TILE_SIZE), cast(ubyte)(rect.y / TEX_TILE_SIZE)]; 121 binfo.uv = uv; 122 infof("%s uv: %s", binfo.name, uv); 123 } 124 } 125 126 void handleBlockMap(string[] blocks) 127 { 128 bm.blockMapping.setMapping(blocks); 129 } 130 } 131 132 final class BlockPluginServer : IPlugin 133 { 134 mixin BlockPluginCommonImpl; 135 // IPlugin stuff 136 mixin IdAndSemverFrom!"voxelman.block.plugininfo"; 137 138 override void registerResources(IResourceManagerRegistry resmanRegistry) 139 { 140 auto ioman = resmanRegistry.getResourceManager!IoManager; 141 ioman.registerWorldLoadSaveHandlers(&readBlockMap, &writeBlockMap); 142 } 143 144 override void init(IPluginManager pluginman) 145 { 146 auto serverWorld = pluginman.getPlugin!ServerWorld; 147 serverWorld.idMapManager.regIdMapHandler(dbKey.str, () => bm.blockMapping.nameRange.array); 148 } 149 150 void readBlockMap(ref PluginDataLoader loader) 151 { 152 loader.readMapping(dbKey, bm.blockMapping); 153 } 154 155 void writeBlockMap(ref PluginDataSaver saver) 156 { 157 saver.writeMapping(dbKey, bm.blockMapping); 158 } 159 }