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.blockentitydata; 7 8 import voxelman.math; 9 10 enum BlockEntityType : ubyte 11 { 12 localBlockEntity, 13 foreignBlockEntity, 14 //componentId 15 } 16 17 enum ENTITY_DATA_MASK = (1UL << 46) - 1; 18 enum PAYLOAD_MASK = (1UL << 62) - 1; 19 20 // 3 bytes from LSB side 21 enum MAIN_OFFSET_BITS = 8*3; 22 enum MAIN_OFFSET_MASK = (1 << MAIN_OFFSET_BITS) - 1; 23 // ushort for block index 24 enum MAIN_BLOCK_INDEX_MASK = ushort.max; 25 26 /// Layout (bit fields, MSB -> LSB) 27 /// 2: type; 16 id + 46 entityData = 62 payload 28 /// data is: 29 /// localBlockEntity: entity id + data in payload 30 /// foreignBlockEntity: position of localBlockEntity (relative to current entity) 31 /// componentId: id in component system 32 struct BlockEntityData 33 { 34 ulong storage; 35 36 this(ulong data) { 37 storage = data; 38 } 39 this(BlockEntityType type, ushort id, ulong entityData) { 40 storage = cast(ulong)type << 62 | cast(ulong)id << 46 | 41 entityData & ENTITY_DATA_MASK; 42 } 43 this(BlockEntityType type, ushort id, ubyte[3] mainOffset, ushort blockIndex) { 44 storage = 45 cast(ulong)type << 62 | 46 cast(ulong)id << 46 | 47 (cast(ulong)blockIndex << MAIN_OFFSET_BITS) | 48 (cast(ulong)mainOffset[0]) | 49 (cast(ulong)mainOffset[1] << 8) | 50 (cast(ulong)mainOffset[2] << 16); 51 } 52 this(BlockEntityType type, ulong payload) { 53 storage = cast(ulong)type << 62 | 54 payload & PAYLOAD_MASK; 55 } 56 57 BlockEntityType type() { return cast(BlockEntityType)(storage >> 62); } 58 ushort id() { return cast(ushort)(storage >> 46); } 59 ulong entityData() { return storage & ENTITY_DATA_MASK; } 60 ulong payload() { return storage & PAYLOAD_MASK; } 61 MainChunkPointer mainChunkPointer() { 62 MainChunkPointer res; 63 res.entityId = id; 64 65 ulong offData = storage & MAIN_OFFSET_MASK; 66 res.mainChunkOffset = ivec3(*cast(ubyte[3]*)&offData); 67 res.blockIndex = (storage >> MAIN_OFFSET_BITS) & MAIN_BLOCK_INDEX_MASK; 68 69 return res; 70 } 71 } 72 73 ivec3 entityDataToSize(ulong entityData) { 74 enum MASK_8_BIT = (1<<8) - 1; 75 uint x = entityData & MASK_8_BIT; 76 uint y = (entityData >> 8) & MASK_8_BIT; 77 uint z = (entityData >> 16) & MASK_8_BIT; 78 return ivec3(x, y, z); 79 } 80 81 ulong sizeToEntityData(ivec3 size) { 82 enum MASK_8_BIT = (1<<8) - 1; 83 ulong x = cast(ulong)size.x & MASK_8_BIT; 84 ulong y = (cast(ulong)size.y & MASK_8_BIT) << 8; 85 ulong z = (cast(ulong)size.z & MASK_8_BIT) << 16; 86 return x | y | z; 87 } 88 89 // data assigned to foreign chunk of multichunk entity. 90 struct MainChunkPointer 91 { 92 // offset in chunk coords from main chunk that contains entity data. 93 // mainChunkOffset = otherPos - mainPos; 94 // mainPos = otherPos - mainChunkOffset 95 ivec3 mainChunkOffset; 96 // block index in main chunk. Can be used as key to entity map in main chunk. 97 ushort blockIndex; 98 // id of the whole block entity. 99 ushort entityId; 100 }