the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
at main 83 lines 4.2 kB view raw
1#pragma once 2#include <stdint.h> 3 4// 4J added - Storage for block & sky light data. Lighting data is normally stored as 4-bits per tile, in a DataLayer class of 16384 bytes ( 128 x 16 x 16 x 0.5 ) 5// This class provides more economical storage for such data by taking into consideration that it is quite common for large parts of the lighting data in a level to 6// be very compressible (large amounts of 0 for block lights, 0 and 15 for sky lights). 7// We are aiming here to balance performance (lighting data is accessed very frequently) against size. 8 9// Details of storage method: 10 11// 1. Lighting is split into horizontal planes, of which there are 128, and each taking up 128 bytes (16 x 16 x 0.5) 12// 2. Each of these layers has a permanently allocated index in this class (planeIndices). 13// 3. Data for allocatedPlaneCount planes worth of data is allocated in the data array ( allocatedPlaneCount * 128 bytes ) 14// 4. If a plane index for a layer is < 128, then the data for that layer is at data[ index * 128 ] 15// 5. If a plane index for a layer is 128, then all values for that plane are 0 16// 6. If a plane index for a layer is 129, then all values for that plane are 15 17 18// This class needs to be thread safe as there are times where chunk (and light) data are shared between server & main threads. Light values are queried 19// very regularly so this needs to be as light-weight as possible. 20 21// To meet these requirements, this class is now implemented using a lock-free system, implemented using a read-copy-update (RCU) type algorithm. Some details... 22 23// (1) The storage details for the class are now packed into a single __int64, which contains both a pointer to the data that is required and a count of how many planes worth 24// of storage are allocated. This allows the full storage to be updated atomically using compare and exchange operations (implemented with InterlockedCompareExchangeRelease64). 25// (2) The data pointer referenced in this __int64 points to an area of memory which is 128 + 128 * plane_count bytes long, where the first 128 bytes stoere the plane indices, and 26// the rest of the data is variable in size to accomodate however many planes are required to be stored 27// (3) The RCU bit of the algorithm means that any read operations don't need to do any checks or locks at all. When the data needs to be updated, a copy of it is made and updated, 28// then an attempt is made to swap the new data in - if this succeeds then the old data pointer is deleted later at some point where we know nothing will be reading from it anymore. 29// This is achieved by putting the delete request in a queue which means it won't actually get deleted until 2 game ticks after the last time its reference existed, which should give 30// us a large margin of safety. If the attempt to swap the new data in fails, then the whole write operation has to be attempted again - this is the only time there is really a 31// high cost for this algorithm and such write collisions should be rare. 32 33//#define LIGHT_COMPRESSION_STATS 34 35class SparseLightStorage_SPU 36{ 37private: 38// unsigned char planeIndices[128]; 39 unsigned char* m_pData; 40 41// unsigned char *data; 42// unsigned int allocatedPlaneCount; 43 44 static const int ALL_0_INDEX = 128; 45 static const int ALL_15_INDEX = 129; 46public: 47 SparseLightStorage_SPU(unsigned char* data) : m_pData(data) {} 48 49 unsigned char* getDataPtr() { return m_pData; } 50 51 inline int get(int x, int y, int z) // Get an individual lighting value 52 { 53 unsigned char *planeIndices, *data; 54 getPlaneIndicesAndData(&planeIndices, &data); 55 56 if( planeIndices[y] == ALL_0_INDEX ) 57 { 58 return 0; 59 } 60 else if ( planeIndices[y] == ALL_15_INDEX ) 61 { 62 return 15; 63 } 64 else 65 { 66 int planeIndex = x * 16 + z; // Index within this xz plane 67 int byteIndex = planeIndex / 2; // Byte index within the plane (2 tiles stored per byte) 68 int shift = ( planeIndex & 1 ) * 4; // Bit shift within the byte 69 int retval = ( data[ planeIndices[y] * 128 + byteIndex ] >> shift ) & 15; 70 71 return retval; 72 } 73 } 74 75 76 inline void getPlaneIndicesAndData(unsigned char **planeIndices, unsigned char **data) 77 { 78 *planeIndices = m_pData; 79 *data = m_pData + 128; 80 } 81 82}; 83