1 /**
2 Copyright: Copyright (c) 2016-2017 Andrey Penechko.
3 License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0).
4 Authors: Andrey Penechko.
5 */
6 module voxelman.session.clientdb;
7 
8 import netlib : SessionId;
9 import datadriven;
10 import std.typecons : Nullable;
11 import voxelman.world.storage;
12 
13 struct ClientDb
14 {
15 	private auto ioKey = IoKey("voxelman.session.clientdb.nameToKeyMap");
16 
17 	private EntityId[string] nameToKeyMap;
18 	EntityManager* eman;
19 
20 	EntityId getOrCreate(string name, out bool createdNew) {
21 		auto idPtr = name in nameToKeyMap;
22 		createdNew = false;
23 		if (idPtr)
24 			return *idPtr;
25 		else
26 		{
27 			createdNew = true;
28 			auto newId = eman.eidMan.nextEntityId;
29 			nameToKeyMap[name] = newId;
30 			return newId;
31 		}
32 	}
33 
34 	// returns 0 if doesn't exist
35 	EntityId getIdForName(string name) {
36 		return nameToKeyMap.get(name, 0);
37 	}
38 
39 	// hasConflict returns true if there is conflict
40 	string resolveNameConflict(string conflictingName,
41 		bool delegate(string) hasConflict)
42 	{
43 		import std.regex : matchFirst, regex;
44 		import std.conv : to;
45 		import voxelman.utils.textformatter;
46 
47 		auto re = regex(`(.*)(\d+)$`, "m");
48 		auto captures = matchFirst(conflictingName, re);
49 
50 		string firstNamePart = conflictingName;
51 		int counter = 1;
52 		if (!captures.empty)
53 		{
54 			firstNamePart = captures[1];
55 			counter = to!int(captures[2]);
56 		}
57 
58 		const(char)[] newName;
59 
60 		do
61 		{
62 			newName = makeFormattedText("%s%s", firstNamePart, counter);
63 			++counter;
64 		}
65 		while(hasConflict(cast(string)newName));
66 
67 		return newName.idup;
68 	}
69 
70 	// forward methods of eman
71 	bool has(C)(EntityId eid) { return eman.has!C(eid); }
72 	void set(C...)(C c) { eman.set(c); }
73 	C* get(C)(EntityId eid) { return eman.get!C(eid); }
74 	C* getOrCreate(C)(EntityId eid) { return eman.getOrCreate!C(eid); }
75 	void remove(C)(EntityId eid) { eman.remove!C(eid); }
76 
77 	void load(ref PluginDataLoader loader)
78 	{
79 		loader.readEntryDecoded(ioKey, nameToKeyMap);
80 	}
81 
82 	void save(ref PluginDataSaver saver)
83 	{
84 		saver.writeEntryEncoded(ioKey, nameToKeyMap);
85 	}
86 }