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.storage.iomanager;
7 
8 import voxelman.log;
9 import std.experimental.allocator.mallocator;
10 import std.bitmanip;
11 
12 import cbor;
13 import pluginlib;
14 import voxelman.core.config;
15 import voxelman.config.configmanager : ConfigOption, ConfigManager;
16 import voxelman.world.worlddb;
17 import voxelman.utils.mapping;
18 import voxelman.serialization;
19 
20 
21 alias SaveHandler = void delegate(ref PluginDataSaver);
22 alias LoadHandler = void delegate(ref PluginDataLoader);
23 
24 final class IoManager : IResourceManager
25 {
26 	package(voxelman.world) LoadHandler[] worldLoadHandlers;
27 	package(voxelman.world) SaveHandler[] worldSaveHandlers;
28 	StringMap stringMap;
29 
30 private:
31 	ConfigOption saveDirOpt;
32 	ConfigOption worldNameOpt;
33 
34 	void delegate(string) onPostInit;
35 
36 	auto dbKey = IoKey(null);
37 	void loadStringKeys(ref PluginDataLoader loader) {
38 		stringMap.load(loader.readEntryDecoded!(string[])(dbKey));
39 		if (stringMap.strings.length == 0) {
40 			stringMap.put(null); // reserve 0 index for string map
41 		}
42 	}
43 
44 	void saveStringKeys(ref PluginDataSaver saver) {
45 		saver.writeEntryEncoded(dbKey, stringMap.strings);
46 	}
47 
48 public:
49 	this(void delegate(string) onPostInit)
50 	{
51 		this.onPostInit = onPostInit;
52 		stringMap.put(null); // reserve 0 index for string map
53 		worldLoadHandlers ~= &loadStringKeys;
54 		worldSaveHandlers ~= &saveStringKeys;
55 	}
56 
57 	override string id() @property { return "voxelman.world.iomanager"; }
58 
59 	override void init(IResourceManagerRegistry resmanRegistry) {
60 		ConfigManager config = resmanRegistry.getResourceManager!ConfigManager;
61 		saveDirOpt = config.registerOption!string("save_dir", "../../saves");
62 		worldNameOpt = config.registerOption!string("world_name", "world");
63 	}
64 	override void postInit() {
65 		import std.path : buildPath;
66 		import std.file : mkdirRecurse;
67 		auto saveFilename = buildPath(saveDirOpt.get!string, worldNameOpt.get!string~".db");
68 		mkdirRecurse(saveDirOpt.get!string);
69 		onPostInit(saveFilename);
70 	}
71 
72 	StringMap* getStringMap() {
73 		return &stringMap;
74 	}
75 
76 	void registerWorldLoadSaveHandlers(LoadHandler loadHandler, SaveHandler saveHandler)
77 	{
78 		worldLoadHandlers ~= loadHandler;
79 		worldSaveHandlers ~= saveHandler;
80 	}
81 }