the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
at main 264 lines 8.0 kB view raw
1#include "stdafx.h" 2#include "File.h" 3#include "ByteBuffer.h" 4#include "net.minecraft.world.entity.h" 5#include "net.minecraft.world.level.h" 6#include "net.minecraft.world.level.tile.entity.h" 7#include "net.minecraft.world.level.chunk.h" 8#include "ZonedChunkStorage.h" 9#include "ZoneFile.h" 10 11// 4J Stu - There are changes to this class for 1.8.2, but since we never use it anyway lets not worry about it 12 13const int ZonedChunkStorage::BIT_TERRAIN_POPULATED = 0x0000001; 14 15const int ZonedChunkStorage::CHUNKS_PER_ZONE_BITS = 5; // = 32 16const int ZonedChunkStorage::CHUNKS_PER_ZONE = 1 << ZonedChunkStorage::CHUNKS_PER_ZONE_BITS; // ^2 17 18const int ZonedChunkStorage::CHUNK_WIDTH = 16; 19 20const int ZonedChunkStorage::CHUNK_HEADER_SIZE = 256; 21const int ZonedChunkStorage::CHUNK_SIZE = ZonedChunkStorage::CHUNK_WIDTH * ZonedChunkStorage::CHUNK_WIDTH * Level::DEPTH; 22const int ZonedChunkStorage::CHUNK_LAYERS = 3; 23const int ZonedChunkStorage::CHUNK_SIZE_BYTES = ZonedChunkStorage::CHUNK_SIZE * ZonedChunkStorage::CHUNK_LAYERS + ZonedChunkStorage::CHUNK_HEADER_SIZE; 24 25const ByteOrder ZonedChunkStorage::BYTEORDER = BIGENDIAN; 26 27ZonedChunkStorage::ZonedChunkStorage(File dir) 28{ 29 tickCount = 0; 30 31 //this->dir = dir; 32 this->dir = File( dir, wstring( L"data" ) ); 33 if( !this->dir.exists() ) this->dir.mkdirs(); 34} 35 36 37int ZonedChunkStorage::getSlot(int x, int z) 38{ 39 int xZone = x >> CHUNKS_PER_ZONE_BITS; 40 int zZone = z >> CHUNKS_PER_ZONE_BITS; 41 int xOffs = x - (xZone << CHUNKS_PER_ZONE_BITS); 42 int zOffs = z - (zZone << CHUNKS_PER_ZONE_BITS); 43 int slot = xOffs + zOffs * CHUNKS_PER_ZONE; 44 return slot; 45} 46 47ZoneFile *ZonedChunkStorage::getZoneFile(int x, int z, bool create) 48{ 49 int slot = getSlot(x, z); 50 51 int xZone = x >> CHUNKS_PER_ZONE_BITS; 52 int zZone = z >> CHUNKS_PER_ZONE_BITS; 53 __int64 key = xZone + (zZone << 20l); 54 // 4J - was !zoneFiles.containsKey(key) 55 if (zoneFiles.find(key) == zoneFiles.end()) 56 { 57 wchar_t xRadix36[64]; 58 wchar_t zRadix36[64]; 59 _itow(x,xRadix36,36); 60 _itow(z,zRadix36,36); 61 File file = File(dir, wstring( L"zone_") + _toString( xRadix36 ) + L"_" + _toString( zRadix36 ) + L".dat" ); 62 63 if ( !file.exists() ) 64 { 65 if (!create) return NULL; 66 HANDLE ch = CreateFile(wstringtofilename(file.getPath()), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 67 CloseHandle(ch); 68 } 69 70 File entityFile = File(dir, wstring( L"entities_") + _toString( xRadix36 ) + L"_" + _toString( zRadix36 ) + L".dat" ); 71 72 zoneFiles[key] = new ZoneFile(key, file, entityFile); 73 } 74 75 ZoneFile *zoneFile = zoneFiles[key]; 76 zoneFile->lastUse = tickCount; 77 if (!zoneFile->containsSlot(slot)) 78 { 79 if (!create) return NULL; 80 } 81 return zoneFile; 82 83} 84 85ZoneIo *ZonedChunkStorage::getBuffer(int x, int z, bool create) 86{ 87 ZoneFile *zoneFile = getZoneFile(x, z, create); 88 if (zoneFile == NULL) return NULL; 89 return zoneFile->getZoneIo(getSlot(x, z)); 90} 91 92LevelChunk *ZonedChunkStorage::load(Level *level, int x, int z) 93{ 94 ZoneIo *zoneIo = getBuffer(x, z, false); 95 if (zoneIo == NULL) return NULL; 96 97 LevelChunk *lc = new LevelChunk(level, x, z); 98 lc->unsaved = false; 99 100 ByteBuffer *header = zoneIo->read(CHUNK_HEADER_SIZE); 101 lc->blocks = zoneIo->read(CHUNK_SIZE)->array(); 102 lc->data = new DataLayer(zoneIo->read(CHUNK_SIZE / 2)->array()); 103 lc->skyLight = new DataLayer(zoneIo->read(CHUNK_SIZE / 2)->array()); 104 lc->blockLight = new DataLayer(zoneIo->read(CHUNK_SIZE / 2)->array()); 105 lc->heightmap = zoneIo->read(CHUNK_WIDTH * CHUNK_WIDTH)->array(); 106 107 header->flip(); 108 int xOrg = header->getInt(); 109 int zOrg = header->getInt(); 110 __int64 time = header->getLong(); 111 __int64 flags = header->getLong(); 112 113 lc->terrainPopulated = (flags & BIT_TERRAIN_POPULATED) != 0; 114 115 loadEntities(level, lc); 116 117 lc->fixBlocks(); 118 return lc; 119 120} 121 122void ZonedChunkStorage::save(Level *level, LevelChunk *lc) 123{ 124 __int64 flags = 0; 125 if (lc->terrainPopulated) flags |= BIT_TERRAIN_POPULATED; 126 127 ByteBuffer *header = ByteBuffer::allocate(CHUNK_HEADER_SIZE); 128 header->order(ZonedChunkStorage::BYTEORDER); 129 header->putInt(lc->x); 130 header->putInt(lc->z); 131 header->putLong(level->getTime()); 132 header->putLong(flags); 133 header->flip(); 134 135 ZoneIo *zoneIo = getBuffer(lc->x, lc->z, true); 136 zoneIo->write(header, CHUNK_HEADER_SIZE); 137 zoneIo->write(lc->blocks, CHUNK_SIZE); 138 zoneIo->write(lc->data->data, CHUNK_SIZE / 2); 139 zoneIo->write(lc->skyLight->data, CHUNK_SIZE / 2); 140 zoneIo->write(lc->blockLight->data, CHUNK_SIZE / 2); 141 zoneIo->write(lc->heightmap, CHUNK_WIDTH * CHUNK_WIDTH); 142 zoneIo->flush(); 143} 144 145void ZonedChunkStorage::tick() 146{ 147 tickCount++; 148 if (tickCount % (20 * 10) == 4) 149 { 150 vector<__int64> toClose; 151 152 AUTO_VAR(itEndZF, zoneFiles.end()); 153 for( unordered_map<__int64, ZoneFile *>::iterator it = zoneFiles.begin(); it != itEndZF; it++ ) 154 { 155 ZoneFile *zoneFile = it->second; 156 if (tickCount - zoneFile->lastUse > 20 * 60) 157 { 158 toClose.push_back(zoneFile->key); 159 } 160 } 161 162 AUTO_VAR(itEndTC, toClose.end()); 163 for (AUTO_VAR(it, toClose.begin()); it != itEndTC; it++) 164 { 165 __int64 key = *it ; //toClose[i]; 166 // 4J - removed try/catch 167// try { 168 char buf[256]; 169 sprintf(buf,"Closing zone %I64d\n",key); 170 app.DebugPrintf(buf); 171 zoneFiles[key]->close(); 172 zoneFiles.erase(zoneFiles.find(key)); 173// } catch (IOException e) { 174// e.printStackTrace(); 175// } 176 } 177 } 178} 179 180 181void ZonedChunkStorage::flush() 182{ 183 AUTO_VAR(itEnd, zoneFiles.end()); 184 for( unordered_map<__int64, ZoneFile *>::iterator it = zoneFiles.begin(); it != itEnd; it++ ) 185 { 186 ZoneFile *zoneFile = it->second; 187 // 4J - removed try/catch 188// try { 189 zoneFile->close(); 190// } catch (IOException e) { 191// e.printStackTrace(); 192// } 193 } 194 zoneFiles.clear(); 195} 196 197void ZonedChunkStorage::loadEntities(Level *level, LevelChunk *lc) 198{ 199 int slot = getSlot(lc->x, lc->z); 200 ZoneFile *zoneFile = getZoneFile(lc->x, lc->z, true); 201 vector<CompoundTag *> *tags = zoneFile->entityFile->readAll(slot); 202 203 AUTO_VAR(itEnd, tags->end()); 204 for (AUTO_VAR(it, tags->begin()); it != itEnd; it++) 205 { 206 CompoundTag *tag = *it; //tags->at(i); 207 int type = tag->getInt(L"_TYPE"); 208 if (type == 0) 209 { 210 shared_ptr<Entity> e = EntityIO::loadStatic(tag, level); 211 if (e != NULL) lc->addEntity(e); 212 } 213 else if (type == 1) 214 { 215 shared_ptr<TileEntity> te = TileEntity::loadStatic(tag); 216 if (te != NULL) lc->addTileEntity(te); 217 } 218 } 219} 220 221void ZonedChunkStorage::saveEntities(Level *level, LevelChunk *lc) 222{ 223 int slot = getSlot(lc->x, lc->z); 224 ZoneFile *zoneFile = getZoneFile(lc->x, lc->z, true); 225 226 vector<CompoundTag *> tags; 227 228#ifdef _ENTITIES_RW_SECTION 229 EnterCriticalRWSection(&lc->m_csEntities, true); 230#else 231 EnterCriticalSection(&lc->m_csEntities); 232#endif 233 for (int i = 0; i < LevelChunk::ENTITY_BLOCKS_LENGTH; i++) 234 { 235 vector<shared_ptr<Entity> > *entities = lc->entityBlocks[i]; 236 237 AUTO_VAR(itEndTags, entities->end()); 238 for (AUTO_VAR(it, entities->begin()); it != itEndTags; it++) 239 { 240 shared_ptr<Entity> e = *it; //entities->at(j); 241 CompoundTag *cp = new CompoundTag(); 242 cp->putInt(L"_TYPE", 0); 243 e->save(cp); 244 tags.push_back(cp); 245 } 246 } 247#ifdef _ENTITIES_RW_SECTION 248 LeaveCriticalRWSection(&lc->m_csEntities, true); 249#else 250 LeaveCriticalSection(&lc->m_csEntities); 251#endif 252 253 for( unordered_map<TilePos, shared_ptr<TileEntity> , TilePosKeyHash, TilePosKeyEq>::iterator it = lc->tileEntities.begin(); 254 it != lc->tileEntities.end(); it++) 255 { 256 shared_ptr<TileEntity> te = it->second; 257 CompoundTag *cp = new CompoundTag(); 258 cp->putInt(L"_TYPE", 1); 259 te->save(cp); 260 tags.push_back(cp); 261 } 262 263 zoneFile->entityFile->replaceSlot(slot, &tags); 264}