AString cSchematicFileSerializer::SaveToSchematicNBT(const cBlockArea & a_BlockArea) { cFastNBTWriter Writer("Schematic"); Writer.AddShort("Width", static_cast<Int16>(a_BlockArea.m_Size.x)); Writer.AddShort("Height", static_cast<Int16>(a_BlockArea.m_Size.y)); Writer.AddShort("Length", static_cast<Int16>(a_BlockArea.m_Size.z)); Writer.AddString("Materials", "Alpha"); if (a_BlockArea.HasBlockTypes()) { Writer.AddByteArray("Blocks", reinterpret_cast<const char *>(a_BlockArea.GetBlockTypes()), a_BlockArea.GetBlockCount()); } else { AString Dummy(a_BlockArea.GetBlockCount(), 0); Writer.AddByteArray("Blocks", Dummy.data(), Dummy.size()); } if (a_BlockArea.HasBlockMetas()) { Writer.AddByteArray("Data", reinterpret_cast<const char *>(a_BlockArea.GetBlockMetas()), a_BlockArea.GetBlockCount()); } else { AString Dummy(a_BlockArea.GetBlockCount(), 0); Writer.AddByteArray("Data", Dummy.data(), Dummy.size()); } Writer.AddInt("WEOffsetX", a_BlockArea.m_WEOffset.x); Writer.AddInt("WEOffsetY", a_BlockArea.m_WEOffset.y); Writer.AddInt("WEOffsetZ", a_BlockArea.m_WEOffset.z); // TODO: Save entities and block entities Writer.BeginList("Entities", TAG_Compound); Writer.EndList(); Writer.BeginList("TileEntities", TAG_Compound); Writer.EndList(); Writer.Finish(); return Writer.GetResult(); }
void cBlockArea::Merge(const cBlockArea & a_Src, int a_RelX, int a_RelY, int a_RelZ, eMergeStrategy a_Strategy) { // Block types are compulsory, block metas are voluntary if (!HasBlockTypes() || !a_Src.HasBlockTypes()) { LOGWARNING("%s: cannot merge because one of the areas doesn't have blocktypes.", __FUNCTION__); return; } // Dst is *this, Src is a_Src int SrcOffX = std::max(0, -a_RelX); // Offset in Src where to start reading int DstOffX = std::max(0, a_RelX); // Offset in Dst where to start writing int SizeX = std::min(a_Src.GetSizeX() - SrcOffX, GetSizeX() - DstOffX); // How many blocks to copy int SrcOffY = std::max(0, -a_RelY); // Offset in Src where to start reading int DstOffY = std::max(0, a_RelY); // Offset in Dst where to start writing int SizeY = std::min(a_Src.GetSizeY() - SrcOffY, GetSizeY() - DstOffY); // How many blocks to copy int SrcOffZ = std::max(0, -a_RelZ); // Offset in Src where to start reading int DstOffZ = std::max(0, a_RelZ); // Offset in Dst where to start writing int SizeZ = std::min(a_Src.GetSizeZ() - SrcOffZ, GetSizeZ() - DstOffZ); // How many blocks to copy const NIBBLETYPE * SrcMetas = a_Src.GetBlockMetas(); NIBBLETYPE * DstMetas = m_BlockMetas; bool IsDummyMetas = ((SrcMetas == NULL) || (DstMetas == NULL)); if (IsDummyMetas) { SrcMetas = new NIBBLETYPE[a_Src.GetBlockCount()]; DstMetas = new NIBBLETYPE[GetBlockCount()]; } switch (a_Strategy) { case msOverwrite: { InternalMergeBlocks( m_BlockTypes, a_Src.GetBlockTypes(), DstMetas, SrcMetas, SizeX, SizeY, SizeZ, SrcOffX, SrcOffY, SrcOffZ, DstOffX, DstOffY, DstOffZ, a_Src.GetSizeX(), a_Src.GetSizeY(), a_Src.GetSizeZ(), m_SizeX, m_SizeY, m_SizeZ, MergeCombinatorOverwrite ); break; } // case msOverwrite case msFillAir: { InternalMergeBlocks( m_BlockTypes, a_Src.GetBlockTypes(), DstMetas, SrcMetas, SizeX, SizeY, SizeZ, SrcOffX, SrcOffY, SrcOffZ, DstOffX, DstOffY, DstOffZ, a_Src.GetSizeX(), a_Src.GetSizeY(), a_Src.GetSizeZ(), m_SizeX, m_SizeY, m_SizeZ, MergeCombinatorFillAir ); break; } // case msFillAir case msImprint: { InternalMergeBlocks( m_BlockTypes, a_Src.GetBlockTypes(), DstMetas, SrcMetas, SizeX, SizeY, SizeZ, SrcOffX, SrcOffY, SrcOffZ, DstOffX, DstOffY, DstOffZ, a_Src.GetSizeX(), a_Src.GetSizeY(), a_Src.GetSizeZ(), m_SizeX, m_SizeY, m_SizeZ, MergeCombinatorImprint ); break; } // case msImprint case msLake: { InternalMergeBlocks( m_BlockTypes, a_Src.GetBlockTypes(), DstMetas, SrcMetas, SizeX, SizeY, SizeZ, SrcOffX, SrcOffY, SrcOffZ, DstOffX, DstOffY, DstOffZ, a_Src.GetSizeX(), a_Src.GetSizeY(), a_Src.GetSizeZ(), m_SizeX, m_SizeY, m_SizeZ, MergeCombinatorLake ); break; } // case msLake default: { LOGWARNING("Unknown block area merge strategy: %d", a_Strategy); ASSERT(!"Unknown block area merge strategy"); break; } } // switch (a_Strategy) if (IsDummyMetas) { delete[] SrcMetas; delete[] DstMetas; } }
void cBlockArea::MergeByStrategy(const cBlockArea & a_Src, int a_RelX, int a_RelY, int a_RelZ, eMergeStrategy a_Strategy, const NIBBLETYPE * SrcMetas, NIBBLETYPE * DstMetas) { // Block types are compulsory, block metas are voluntary if (!HasBlockTypes() || !a_Src.HasBlockTypes()) { LOGWARNING("%s: cannot merge because one of the areas doesn't have blocktypes.", __FUNCTION__); return; } // Dst is *this, Src is a_Src int SrcOffX = std::max(0, -a_RelX); // Offset in Src where to start reading int DstOffX = std::max(0, a_RelX); // Offset in Dst where to start writing int SizeX = std::min(a_Src.GetSizeX() - SrcOffX, GetSizeX() - DstOffX); // How many blocks to copy int SrcOffY = std::max(0, -a_RelY); // Offset in Src where to start reading int DstOffY = std::max(0, a_RelY); // Offset in Dst where to start writing int SizeY = std::min(a_Src.GetSizeY() - SrcOffY, GetSizeY() - DstOffY); // How many blocks to copy int SrcOffZ = std::max(0, -a_RelZ); // Offset in Src where to start reading int DstOffZ = std::max(0, a_RelZ); // Offset in Dst where to start writing int SizeZ = std::min(a_Src.GetSizeZ() - SrcOffZ, GetSizeZ() - DstOffZ); // How many blocks to copy switch (a_Strategy) { case cBlockArea::msOverwrite: { InternalMergeBlocks<MetasValid, MergeCombinatorOverwrite<MetasValid> >( m_BlockTypes, a_Src.GetBlockTypes(), DstMetas, SrcMetas, SizeX, SizeY, SizeZ, SrcOffX, SrcOffY, SrcOffZ, DstOffX, DstOffY, DstOffZ, a_Src.GetSizeX(), a_Src.GetSizeY(), a_Src.GetSizeZ(), m_Size.x, m_Size.y, m_Size.z ); return; } // case msOverwrite case cBlockArea::msFillAir: { InternalMergeBlocks<MetasValid, MergeCombinatorFillAir<MetasValid> >( m_BlockTypes, a_Src.GetBlockTypes(), DstMetas, SrcMetas, SizeX, SizeY, SizeZ, SrcOffX, SrcOffY, SrcOffZ, DstOffX, DstOffY, DstOffZ, a_Src.GetSizeX(), a_Src.GetSizeY(), a_Src.GetSizeZ(), m_Size.x, m_Size.y, m_Size.z ); return; } // case msFillAir case cBlockArea::msImprint: { InternalMergeBlocks<MetasValid, MergeCombinatorImprint<MetasValid> >( m_BlockTypes, a_Src.GetBlockTypes(), DstMetas, SrcMetas, SizeX, SizeY, SizeZ, SrcOffX, SrcOffY, SrcOffZ, DstOffX, DstOffY, DstOffZ, a_Src.GetSizeX(), a_Src.GetSizeY(), a_Src.GetSizeZ(), m_Size.x, m_Size.y, m_Size.z ); return; } // case msImprint case cBlockArea::msLake: { InternalMergeBlocks<MetasValid, MergeCombinatorLake<MetasValid> >( m_BlockTypes, a_Src.GetBlockTypes(), DstMetas, SrcMetas, SizeX, SizeY, SizeZ, SrcOffX, SrcOffY, SrcOffZ, DstOffX, DstOffY, DstOffZ, a_Src.GetSizeX(), a_Src.GetSizeY(), a_Src.GetSizeZ(), m_Size.x, m_Size.y, m_Size.z ); return; } // case msLake case cBlockArea::msSpongePrint: { InternalMergeBlocks<MetasValid, MergeCombinatorSpongePrint<MetasValid> >( m_BlockTypes, a_Src.GetBlockTypes(), DstMetas, SrcMetas, SizeX, SizeY, SizeZ, SrcOffX, SrcOffY, SrcOffZ, DstOffX, DstOffY, DstOffZ, a_Src.GetSizeX(), a_Src.GetSizeY(), a_Src.GetSizeZ(), m_Size.x, m_Size.y, m_Size.z ); return; } // case msSpongePrint case cBlockArea::msDifference: { InternalMergeBlocks<MetasValid, MergeCombinatorDifference<MetasValid> >( m_BlockTypes, a_Src.GetBlockTypes(), DstMetas, SrcMetas, SizeX, SizeY, SizeZ, SrcOffX, SrcOffY, SrcOffZ, DstOffX, DstOffY, DstOffZ, a_Src.GetSizeX(), a_Src.GetSizeY(), a_Src.GetSizeZ(), m_Size.x, m_Size.y, m_Size.z ); return; } // case msDifference case cBlockArea::msMask: { InternalMergeBlocks<MetasValid, MergeCombinatorMask<MetasValid> >( m_BlockTypes, a_Src.GetBlockTypes(), DstMetas, SrcMetas, SizeX, SizeY, SizeZ, SrcOffX, SrcOffY, SrcOffZ, DstOffX, DstOffY, DstOffZ, a_Src.GetSizeX(), a_Src.GetSizeY(), a_Src.GetSizeZ(), m_Size.x, m_Size.y, m_Size.z ); return; } // case msMask } // switch (a_Strategy) LOGWARNING("Unknown block area merge strategy: %d", a_Strategy); ASSERT(!"Unknown block area merge strategy"); return; }