void cBlockArea::CopyTo(cBlockArea & a_Into) const { if (&a_Into == this) { LOGWARNING("Trying to copy a cBlockArea into self, ignoring."); return; } a_Into.Clear(); a_Into.SetSize(m_SizeX, m_SizeY, m_SizeZ, GetDataTypes()); a_Into.m_OriginX = m_OriginX; a_Into.m_OriginY = m_OriginY; a_Into.m_OriginZ = m_OriginZ; int BlockCount = GetBlockCount(); if (HasBlockTypes()) { memcpy(a_Into.m_BlockTypes, m_BlockTypes, BlockCount * sizeof(BLOCKTYPE)); } if (HasBlockMetas()) { memcpy(a_Into.m_BlockMetas, m_BlockMetas, BlockCount * sizeof(NIBBLETYPE)); } if (HasBlockLights()) { memcpy(a_Into.m_BlockLight, m_BlockLight, BlockCount * sizeof(NIBBLETYPE)); } if (HasBlockSkyLights()) { memcpy(a_Into.m_BlockSkyLight, m_BlockSkyLight, BlockCount * sizeof(NIBBLETYPE)); } }
void cChunkDesc::ReadBlockArea(cBlockArea & a_Dest, int a_MinRelX, int a_MaxRelX, int a_MinRelY, int a_MaxRelY, int a_MinRelZ, int a_MaxRelZ) { // Normalize the coords: if (a_MinRelX > a_MaxRelX) { std::swap(a_MinRelX, a_MaxRelX); } if (a_MinRelY > a_MaxRelY) { std::swap(a_MinRelY, a_MaxRelY); } if (a_MinRelZ > a_MaxRelZ) { std::swap(a_MinRelZ, a_MaxRelZ); } // Include the Max coords: a_MaxRelX += 1; a_MaxRelY += 1; a_MaxRelZ += 1; // Check coords validity: if (a_MinRelX < 0) { LOGWARNING("%s: MinRelX less than zero, adjusting to zero", __FUNCTION__); a_MinRelX = 0; } else if (a_MinRelX >= cChunkDef::Width) { LOGWARNING("%s: MinRelX more than chunk width, adjusting to chunk width", __FUNCTION__); a_MinRelX = cChunkDef::Width - 1; } if (a_MaxRelX < 0) { LOGWARNING("%s: MaxRelX less than zero, adjusting to zero", __FUNCTION__); a_MaxRelX = 0; } else if (a_MaxRelX > cChunkDef::Width) { LOGWARNING("%s: MaxRelX more than chunk width, adjusting to chunk width", __FUNCTION__); a_MaxRelX = cChunkDef::Width; } if (a_MinRelY < 0) { LOGWARNING("%s: MinRelY less than zero, adjusting to zero", __FUNCTION__); a_MinRelY = 0; } else if (a_MinRelY >= cChunkDef::Height) { LOGWARNING("%s: MinRelY more than chunk height, adjusting to chunk height", __FUNCTION__); a_MinRelY = cChunkDef::Height - 1; } if (a_MaxRelY < 0) { LOGWARNING("%s: MaxRelY less than zero, adjusting to zero", __FUNCTION__); a_MaxRelY = 0; } else if (a_MaxRelY > cChunkDef::Height) { LOGWARNING("%s: MaxRelY more than chunk height, adjusting to chunk height", __FUNCTION__); a_MaxRelY = cChunkDef::Height; } if (a_MinRelZ < 0) { LOGWARNING("%s: MinRelZ less than zero, adjusting to zero", __FUNCTION__); a_MinRelZ = 0; } else if (a_MinRelZ >= cChunkDef::Width) { LOGWARNING("%s: MinRelZ more than chunk width, adjusting to chunk width", __FUNCTION__); a_MinRelZ = cChunkDef::Width - 1; } if (a_MaxRelZ < 0) { LOGWARNING("%s: MaxRelZ less than zero, adjusting to zero", __FUNCTION__); a_MaxRelZ = 0; } else if (a_MaxRelZ > cChunkDef::Width) { LOGWARNING("%s: MaxRelZ more than chunk width, adjusting to chunk width", __FUNCTION__); a_MaxRelZ = cChunkDef::Width; } // Prepare the block area: int SizeX = a_MaxRelX - a_MinRelX; int SizeY = a_MaxRelY - a_MinRelY; int SizeZ = a_MaxRelZ - a_MinRelZ; a_Dest.Clear(); a_Dest.m_Origin.x = m_ChunkX * cChunkDef::Width + a_MinRelX; a_Dest.m_Origin.y = a_MinRelY; a_Dest.m_Origin.z = m_ChunkZ * cChunkDef::Width + a_MinRelZ; a_Dest.SetSize(SizeX, SizeY, SizeZ, cBlockArea::baTypes | cBlockArea::baMetas); for (int y = 0; y < SizeY; y++) { int CDY = a_MinRelY + y; for (int z = 0; z < SizeZ; z++) { int CDZ = a_MinRelZ + z; for (int x = 0; x < SizeX; x++) { int CDX = a_MinRelX + x; BLOCKTYPE BlockType; NIBBLETYPE BlockMeta; GetBlockTypeMeta(CDX, CDY, CDZ, BlockType, BlockMeta); a_Dest.SetRelBlockTypeMeta(x, y, z, BlockType, BlockMeta); } // for x } // for z } // for y }
bool cSchematicFileSerializer::LoadFromSchematicNBT(cBlockArea & a_BlockArea, cParsedNBT & a_NBT) { int TMaterials = a_NBT.FindChildByName(a_NBT.GetRoot(), "Materials"); if ((TMaterials > 0) && (a_NBT.GetType(TMaterials) == TAG_String)) { AString Materials = a_NBT.GetString(TMaterials); if (Materials.compare("Alpha") != 0) { LOG("Materials tag is present and \"%s\" instead of \"Alpha\". Possibly a wrong-format schematic file.", Materials.c_str()); return false; } } int TSizeX = a_NBT.FindChildByName(a_NBT.GetRoot(), "Width"); int TSizeY = a_NBT.FindChildByName(a_NBT.GetRoot(), "Height"); int TSizeZ = a_NBT.FindChildByName(a_NBT.GetRoot(), "Length"); if ( (TSizeX < 0) || (TSizeY < 0) || (TSizeZ < 0) || (a_NBT.GetType(TSizeX) != TAG_Short) || (a_NBT.GetType(TSizeY) != TAG_Short) || (a_NBT.GetType(TSizeZ) != TAG_Short) ) { LOG("Dimensions are missing from the schematic file (%d, %d, %d), (%d, %d, %d)", TSizeX, TSizeY, TSizeZ, (TSizeX >= 0) ? a_NBT.GetType(TSizeX) : -1, (TSizeY >= 0) ? a_NBT.GetType(TSizeY) : -1, (TSizeZ >= 0) ? a_NBT.GetType(TSizeZ) : -1 ); return false; } int SizeX = a_NBT.GetShort(TSizeX); int SizeY = a_NBT.GetShort(TSizeY); int SizeZ = a_NBT.GetShort(TSizeZ); if ((SizeX < 1) || (SizeX > 65535) || (SizeY < 1) || (SizeY > cChunkDef::Height) || (SizeZ < 1) || (SizeZ > 65535)) { LOG("Dimensions are invalid in the schematic file: %d, %d, %d", SizeX, SizeY, SizeZ); return false; } int TBlockTypes = a_NBT.FindChildByName(a_NBT.GetRoot(), "Blocks"); int TBlockMetas = a_NBT.FindChildByName(a_NBT.GetRoot(), "Data"); if ((TBlockTypes < 0) || (a_NBT.GetType(TBlockTypes) != TAG_ByteArray)) { LOG("BlockTypes are invalid in the schematic file: %d", TBlockTypes); return false; } bool AreMetasPresent = (TBlockMetas > 0) && (a_NBT.GetType(TBlockMetas) == TAG_ByteArray); a_BlockArea.Clear(); a_BlockArea.SetSize(SizeX, SizeY, SizeZ, AreMetasPresent ? (cBlockArea::baTypes | cBlockArea::baMetas) : cBlockArea::baTypes); int TOffsetX = a_NBT.FindChildByName(a_NBT.GetRoot(), "WEOffsetX"); int TOffsetY = a_NBT.FindChildByName(a_NBT.GetRoot(), "WEOffsetY"); int TOffsetZ = a_NBT.FindChildByName(a_NBT.GetRoot(), "WEOffsetZ"); if ( (TOffsetX < 0) || (TOffsetY < 0) || (TOffsetZ < 0) || (a_NBT.GetType(TOffsetX) != TAG_Int) || (a_NBT.GetType(TOffsetY) != TAG_Int) || (a_NBT.GetType(TOffsetZ) != TAG_Int) ) { // Not every schematic file has an offset, so we shoudn't give a warn message. a_BlockArea.SetWEOffset(0, 0, 0); } else { a_BlockArea.SetWEOffset(a_NBT.GetInt(TOffsetX), a_NBT.GetInt(TOffsetY), a_NBT.GetInt(TOffsetZ)); } // Copy the block types and metas: size_t NumTypeBytes = a_BlockArea.GetBlockCount(); if (a_NBT.GetDataLength(TBlockTypes) < NumTypeBytes) { LOG("BlockTypes truncated in the schematic file (exp %u, got %u bytes). Loading partial.", static_cast<unsigned>(NumTypeBytes), static_cast<unsigned>(a_NBT.GetDataLength(TBlockTypes)) ); NumTypeBytes = a_NBT.GetDataLength(TBlockTypes); } memcpy(a_BlockArea.GetBlockTypes(), a_NBT.GetData(TBlockTypes), NumTypeBytes); if (AreMetasPresent) { size_t NumMetaBytes = a_BlockArea.GetBlockCount(); if (a_NBT.GetDataLength(TBlockMetas) < NumMetaBytes) { LOG("BlockMetas truncated in the schematic file (exp %u, got %u bytes). Loading partial.", static_cast<unsigned>(NumMetaBytes), static_cast<unsigned>(a_NBT.GetDataLength(TBlockMetas)) ); NumMetaBytes = a_NBT.GetDataLength(TBlockMetas); } memcpy(a_BlockArea.GetBlockMetas(), a_NBT.GetData(TBlockMetas), NumMetaBytes); } return true; }