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.blockentity.blockentitymap;
7 
8 import voxelman.log;
9 import voxelman.container.hash.map;
10 import std.experimental.allocator.mallocator;
11 import voxelman.world.storage.chunk.layer;
12 
13 alias BlockEntityMap = HashMap!(ushort, ulong, ushort.max, ushort.max-1, BlockEntityMapAllocator);
14 
15 void setLayerMap(Layer)(ref Layer layer, BlockEntityMap map)
16 {
17 	void[] arr = map.getStorage();
18 
19 	void* dataPtr = arr.ptr - ExtraMapData.sizeof;
20 	size_t dataLength = arr.length + ExtraMapData.sizeof;
21 
22 	auto extraMapData = cast(ExtraMapData*)dataPtr;
23 	extraMapData.length = cast(ushort)map.length;
24 	extraMapData.occupiedBuckets = cast(ushort)map.occupiedBuckets;
25 
26 	layer.dataPtr = dataPtr;
27 	layer.dataLength = cast(LayerDataLenType)dataLength;
28 }
29 
30 BlockEntityMap getHashMapFromLayer(Layer)(const ref Layer layer)
31 {
32 	BlockEntityMap result;
33 
34 	if (layer.type == StorageType.fullArray)
35 	{
36 		ubyte[] data = layer.getArray!ubyte;
37 		if (data.length >= ExtraMapData.sizeof)
38 		{
39 			auto extraMapData = cast(ExtraMapData*)data.ptr;
40 			void[] mapData = data[ExtraMapData.sizeof..$];
41 			result.setStorage(mapData, extraMapData.length, extraMapData.occupiedBuckets);
42 		}
43 	}
44 	else if (layer.type == StorageType.compressedArray)
45 	{
46 		assert(false, "Cannot get map from compressed chunk layer");
47 	}
48 
49 	return result;
50 }
51 
52 struct ExtraMapData
53 {
54 	ushort length;
55 	ushort occupiedBuckets;
56 }
57 
58 struct BlockEntityMapAllocator
59 {
60 	@trusted @nogc nothrow
61 	void[] allocate(size_t bytes) shared
62 	{
63 		void[] buffer = Mallocator.instance.allocate(bytes + ExtraMapData.sizeof);
64 		return buffer[ExtraMapData.sizeof..$];
65 	}
66 
67 	@system @nogc nothrow
68 	bool deallocate(void[] b) shared
69 	{
70 		void* ptr = b.ptr-ExtraMapData.sizeof;
71 		Mallocator.instance.deallocate(ptr[0..b.length + ExtraMapData.sizeof]);
72 		return true;
73 	}
74 
75 	static shared BlockEntityMapAllocator instance;
76 }