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.world.gen.generatorman; 7 8 import cbor; 9 import voxelman.world.gen.generator; 10 import voxelman.world.storage; 11 12 struct GeneratorFactory 13 { 14 TypeInfo_Class[string] nameToType; 15 TypeInfo_Class[uint] idToType; 16 uint[TypeInfo_Class] typeToId; 17 18 void registerGenerator(T : IGenerator)() { 19 assert(T.name !in nameToType); 20 nameToType[T.name] = T.classinfo; 21 } 22 23 IGenerator create(uint id) { 24 if (auto type = id in idToType) 25 { 26 return cast(IGenerator)((*type).create()); 27 } 28 return null; 29 } 30 31 uint getId(IGenerator generator) { 32 return typeToId[generator.classinfo]; 33 } 34 35 void load(ref PluginDataLoader loader) { 36 foreach(pair; nameToType.byKeyValue) 37 { 38 IoKey ioKey = IoKey(pair.key); 39 loader.stringMap.get(ioKey); 40 idToType[ioKey.id] = pair.value; 41 typeToId[pair.value] = ioKey.id; 42 } 43 } 44 } 45 46 47 struct GeneratorManager 48 { 49 auto ioKey = IoKey("voxelman.world.gen.generatormanager"); 50 IGenerator[DimensionId] generators; 51 GeneratorFactory factory; 52 53 IGenerator opIndex(DimensionId dimensionId) 54 { 55 return generators.get(dimensionId, null); 56 } 57 58 void opIndexAssign(IGenerator generator, DimensionId dimensionId) 59 { 60 generators[dimensionId] = generator; 61 } 62 63 void load(ref PluginDataLoader loader) { 64 factory.load(loader); 65 66 ubyte[] data = loader.readEntryRaw(ioKey); 67 if (data.length == 0) return; 68 69 CborToken token = decodeCborToken(data); 70 if (token.type == CborTokenType.mapHeader) { 71 size_t lengthToRead = cast(size_t)token.uinteger; 72 //generators.reserve(lengthToRead); 73 while (lengthToRead > 0) { 74 auto dimId = decodeCborSingle!DimensionId(data); 75 auto generatorId = decodeCborSingle!uint(data); 76 IGenerator generator = factory.create(generatorId); 77 generator.load(data); 78 generators[dimId] = generator; 79 --lengthToRead; 80 } 81 } 82 } 83 84 void save(ref PluginDataSaver saver) { 85 if (generators.length == 0) return; 86 auto sink = saver.beginWrite(); 87 encodeCborMapHeader(sink, generators.length); 88 foreach(dimId, generator; generators) { 89 encodeCbor(sink, dimId); 90 encodeCbor(sink, factory.getId(generator)); 91 generator.save(sink); 92 } 93 saver.endWrite(ioKey); 94 } 95 }