//------------------------------------------------------------------------ bool PresetFile::writeChunkList () { // Update list offset TSize pos = 0; stream->tell (&pos); if (!(seekTo (kListOffsetPos) && writeSize (pos) && seekTo (pos))) return false; // Write list if (!writeID (getChunkID (kChunkList))) return false; if (!writeInt32 (entryCount)) return false; for (int32 i = 0; i < entryCount; i++) { Entry& e = entries[i]; if (!(writeID (e.id) && writeSize (e.offset) && writeSize (e.size))) return false; } return true; }
//------------------------------------------------------------------------ const PresetFile::Entry* PresetFile::getEntry (ChunkType which) const { const ChunkID& id = getChunkID (which); for (int32 i = 0; i < entryCount; i++) if (isEqualID (entries[i].id, id)) return &entries[i]; return 0; }
//------------------------------------------------------------------------ bool PresetFile::readChunkList () { seekTo (0); entryCount = 0; char8 classString[kClassIDSize + 1] = {0}; // Read header int32 version = 0; TSize listOffset = 0; if (!(readEqualID (getChunkID (kHeader)) && readInt32 (version) && verify (stream->read (classString, kClassIDSize)) && readSize (listOffset) && listOffset > 0 && seekTo (listOffset))) return false; classID.fromString (classString); // Read list int32 count = 0; if (!readEqualID (getChunkID (kChunkList))) return false; if (!readInt32 (count)) return false; if (count > kMaxEntries) count = kMaxEntries; for (int32 i = 0; i < count; i++) { Entry& e = entries[i]; if (!(readID (e.id) && readSize (e.offset) && readSize (e.size))) break; entryCount++; } return entryCount > 0; }
//------------------------------------------------------------------------ bool PresetFile::beginChunk (Entry& e, ChunkType which) { if (entryCount >= kMaxEntries) return false; const ChunkID& id = getChunkID (which); memcpy (e.id, &id, sizeof (ChunkID)); stream->tell (&e.offset); e.size = 0; return true; }
//------------------------------------------------------------------------ bool PresetFile::writeHeader () { // header id + version + class id + list offset (unknown yet) char8 classString[kClassIDSize + 1] = {0}; classID.toString (classString); return seekTo (0) && writeID (getChunkID (kHeader)) && writeInt32 (kFormatVersion) && verify (stream->write (classString, kClassIDSize)) && writeSize (0); }
void chunk::build(){ //生成地形 int x, y, z, height, h, sh; if (cy < 0) { memset(pbrightness, sizeof(pbrightness), BRIGHTNESSMIN); isEmptyChunk = true; return; } auto iter = CHMs.find(getChunkID(cx, 0, cz)); //Height Map if (iter == CHMs.end()) { //没找到可用的HeightMap chunkHeightMap CHM(cx, cz); //新建一个 CHM.build(); iter = CHMs.insert(CHM).first; //指向新加入的Height Map } bool EmptyChunk = true; for (x = 0; x != 16; x++){ for (z = 0; z != 16; z++){ if (cy <= 4 && cy >= 0) { h = iter->terrain[x][z]; sh = WorldGen::WaterLevel + 2; } for (y = 0; y != 16; y++){ if (cy > 4) { pblocks[x][y][z]= blocks::AIR; pbrightness[x][y][z] = skylight; } else { height = cy * 16 + y; pbrightness[x][y][z] = 0; if (height == 0) pblocks[x][y][z] = blocks::BEDROCK; else if (height == h && height > sh && height > WorldGen::WaterLevel + 1) pblocks[x][y][z] = blocks::GRASS; else if (height<h && height>sh && height > WorldGen::WaterLevel + 1) pblocks[x][y][z] = blocks::DIRT; else if ((height >= sh - 5 || height >= h - 5) && height <= h && (height <= sh || height <= WorldGen::WaterLevel + 1)) pblocks[x][y][z] = blocks::SAND; else if ((height < sh - 5 && height < h - 5) && height >= 1 && height <= h) pblocks[x][y][z] = blocks::ROCK; else { if (height <= WorldGen::WaterLevel) { pblocks[x][y][z] = blocks::WATER; if (skylight - (WorldGen::WaterLevel - height) * 2 < BRIGHTNESSMIN) pbrightness[x][y][z] = BRIGHTNESSMIN; else pbrightness[x][y][z] = skylight - (brightness)((WorldGen::WaterLevel - height) * 2); } else { pblocks[x][y][z] = blocks::AIR; pbrightness[x][y][z] = skylight; } } } if (pblocks[x][y][z] != blocks::AIR) EmptyChunk = false; } } } isEmptyChunk = EmptyChunk; }