the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
at main 84 lines 5.1 kB view raw
1#pragma once 2#include "xmcore.h" 3 4// 4J added - Storage for data (ie the extra per tile storage). 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 data to be very compressible (ie zero). 6// We are aiming here to balance performance (this data is accessed very frequently) against size. 7 8// Details of storage method: 9 10// 1. Data is split into horizontal planes, of which there are 128, and each taking up 128 bytes (16 x 16 x 0.5) 11// 2. Each of these layers has a permanently allocated index in this class (planeIndices). 12// 3. Data for allocatedPlaneCount planes worth of data is allocated in the data array ( allocatedPlaneCount * 128 bytes ) 13// 4. If a plane index for a layer is < 128, then the data for that layer is at data[ index * 128 ] 14// 5. If a plane index for a layer is 128, then all values for that plane are 0 15 16// This class needs to be thread safe as there are times where chunk data is shared between server & main threads. Data values are queried 17// very regularly so this needs to be as light-weight as possible. 18 19// 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... 20 21// (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 22// of storage are allocated. This allows the full storage to be updated atomically using compare and exchange operations (implemented with InterlockedCompareExchangeRelease64). 23// (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 24// the rest of the data is variable in size to accomodate however many planes are required to be stored 25// (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, 26// 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. 27// 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 28// 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 29// high cost for this algorithm and such write collisions should be rare. 30 31//#define DATA_COMPRESSION_STATS 32class TileCompressData_SPU; 33 34class SparseDataStorage 35{ 36 friend class TileCompressData_SPU; 37private: 38// unsigned char planeIndices[128]; 39 __int64 dataAndCount; // Contains packed-together data pointer (lower 48-bits), and count of lines used (upper 16-bits) 40 41// unsigned char *data; 42// unsigned int allocatedPlaneCount; 43 44 static const int ALL_0_INDEX = 128; 45 46#ifdef _XBOX 47 static const unsigned int MM_PHYSICAL_4KB_BASE = 0xE0000000; // Start of where 4KB page sized physical allocations are made 48#endif 49public: 50 SparseDataStorage(); 51 SparseDataStorage(bool isUpper); 52 SparseDataStorage(SparseDataStorage *copyFrom); // ctor with deep copy 53 ~SparseDataStorage(); 54 55 void setData(byteArray dataIn, unsigned int inOffset); // Set all data values from a data array of length 16384 (128 x 16 x 16 x 0.5). 56 void getData(byteArray retArray, unsigned int retOffset); // Gets all data values into an array of length 16384. 57 int get(int x, int y, int z); // Get an individual data value 58 void set(int x, int y, int z, int val); // Set an individual data value 59 typedef void (*tileUpdatedCallback)(int x, int y , int z, void *param, int yparam); 60 int setDataRegion(byteArray dataIn, int x0, int y0, int z0, int x1, int y1, int z1, int offset, tileUpdatedCallback callback, void *param, int yparam); // Sets a region of data values with the data at offset position in the array dataIn - external ordering compatible with java DataLayer 61 int getDataRegion(byteArray dataInOut, int x0, int y0, int z0, int x1, int y1, int z1, int offset); // Updates the data at offset position dataInOut with a region of data information - external ordering compatible with java DataLayer 62 63 static void staticCtor(); 64 65 void addNewPlane(int y); 66 void getPlaneIndicesAndData(unsigned char **planeIndices, unsigned char **data); 67 void updateDataAndCount(__int64 newDataAndCount); 68 int compress(); 69 70 bool isCompressed(); 71 void queueForDelete(unsigned char *data); 72 73 static void tick(); 74 static int deleteQueueIndex; 75 static XLockFreeStack <unsigned char> deleteQueue[3]; 76 77#ifdef DATA_COMPRESSION_STATS 78 int count; 79#endif 80 81 void write(DataOutputStream *dos); 82 void read(DataInputStream *dis); 83}; 84