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 }