the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
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}