diff options
Diffstat (limited to 'source/BlockArea.cpp')
-rw-r--r-- | source/BlockArea.cpp | 2124 |
1 files changed, 0 insertions, 2124 deletions
diff --git a/source/BlockArea.cpp b/source/BlockArea.cpp deleted file mode 100644 index 5c15adfef..000000000 --- a/source/BlockArea.cpp +++ /dev/null @@ -1,2124 +0,0 @@ - -// BlockArea.cpp - -// Implements the cBlockArea object representing an area of block data that can be queried from cWorld and then accessed again without further queries -// The object also supports writing the blockdata back into cWorld, even into other coords - -#include "Globals.h" -#include "BlockArea.h" -#include "World.h" -#include "OSSupport/GZipFile.h" -#include "WorldStorage/FastNBT.h" -#include "Blocks/BlockHandler.h" - - - - - -// This wild construct allows us to pass a function argument and still have it inlined by the compiler :) -/// Merges two blocktypes and blockmetas of the specified sizes and offsets using the specified combinator function -template<typename Combinator> void InternalMergeBlocks( - BLOCKTYPE * a_DstTypes, const BLOCKTYPE * a_SrcTypes, - NIBBLETYPE * a_DstMetas, const NIBBLETYPE * a_SrcMetas, - int a_SizeX, int a_SizeY, int a_SizeZ, - int a_SrcOffX, int a_SrcOffY, int a_SrcOffZ, - int a_DstOffX, int a_DstOffY, int a_DstOffZ, - int a_SrcSizeX, int a_SrcSizeY, int a_SrcSizeZ, - int a_DstSizeX, int a_DstSizeY, int a_DstSizeZ, - Combinator a_Combinator -) -{ - for (int y = 0; y < a_SizeY; y++) - { - int SrcBaseY = (y + a_SrcOffY) * a_SrcSizeX * a_SrcSizeZ; - int DstBaseY = (y + a_DstOffY) * a_DstSizeX * a_DstSizeZ; - for (int z = 0; z < a_SizeZ; z++) - { - int SrcBaseZ = SrcBaseY + (z + a_SrcOffZ) * a_SrcSizeX; - int DstBaseZ = DstBaseY + (z + a_DstOffZ) * a_DstSizeX; - int SrcIdx = SrcBaseZ + a_SrcOffX; - int DstIdx = DstBaseZ + a_DstOffX; - for (int x = 0; x < a_SizeX; x++) - { - a_Combinator(a_DstTypes[DstIdx], a_SrcTypes[SrcIdx], a_DstMetas[DstIdx], a_SrcMetas[SrcIdx]); - ++DstIdx; - ++SrcIdx; - } // for x - } // for z - } // for y -} - - - - - -/// Combinator used for cBlockArea::msOverwrite merging -static void MergeCombinatorOverwrite(BLOCKTYPE & a_DstType, BLOCKTYPE a_SrcType, NIBBLETYPE & a_DstMeta, NIBBLETYPE a_SrcMeta) -{ - a_DstType = a_SrcType; - a_DstMeta = a_SrcMeta; -} - - - - - -/// Combinator used for cBlockArea::msFillAir merging -static void MergeCombinatorFillAir(BLOCKTYPE & a_DstType, BLOCKTYPE a_SrcType, NIBBLETYPE & a_DstMeta, NIBBLETYPE a_SrcMeta) -{ - if (a_DstType == E_BLOCK_AIR) - { - a_DstType = a_SrcType; - a_DstMeta = a_SrcMeta; - } - // "else" is the default, already in place -} - - - - - -/// Combinator used for cBlockArea::msImprint merging -static void MergeCombinatorImprint(BLOCKTYPE & a_DstType, BLOCKTYPE a_SrcType, NIBBLETYPE & a_DstMeta, NIBBLETYPE a_SrcMeta) -{ - if (a_SrcType != E_BLOCK_AIR) - { - a_DstType = a_SrcType; - a_DstMeta = a_SrcMeta; - } - // "else" is the default, already in place -} - - - - - -/// Combinator used for cBlockArea::msLake merging -static void MergeCombinatorLake(BLOCKTYPE & a_DstType, BLOCKTYPE a_SrcType, NIBBLETYPE & a_DstMeta, NIBBLETYPE a_SrcMeta) -{ - // Sponge is the NOP block - if (a_SrcType == E_BLOCK_SPONGE) - { - return; - } - - // Air is always hollowed out - if (a_SrcType == E_BLOCK_AIR) - { - a_DstType = E_BLOCK_AIR; - a_DstMeta = 0; - return; - } - - // Water and lava are never overwritten - switch (a_DstType) - { - case E_BLOCK_WATER: - case E_BLOCK_STATIONARY_WATER: - case E_BLOCK_LAVA: - case E_BLOCK_STATIONARY_LAVA: - { - return; - } - } - - // Water and lava always overwrite - switch (a_SrcType) - { - case E_BLOCK_WATER: - case E_BLOCK_STATIONARY_WATER: - case E_BLOCK_LAVA: - case E_BLOCK_STATIONARY_LAVA: - { - a_DstType = a_SrcType; - a_DstMeta = a_DstMeta; - return; - } - } - - if (a_SrcType == E_BLOCK_STONE) - { - switch (a_DstType) - { - case E_BLOCK_DIRT: - case E_BLOCK_GRASS: - case E_BLOCK_MYCELIUM: - { - a_DstType = E_BLOCK_STONE; - a_DstMeta = 0; - return; - } - } - } - // Everything else is left as it is -} - - - - - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// cBlockArea: - -cBlockArea::cBlockArea(void) : - m_SizeX(0), - m_SizeY(0), - m_SizeZ(0), - m_BlockTypes(NULL), - m_BlockMetas(NULL), - m_BlockLight(NULL), - m_BlockSkyLight(NULL) -{ -} - - - - - -cBlockArea::~cBlockArea() -{ - Clear(); -} - - - - - -void cBlockArea::Clear(void) -{ - delete[] m_BlockTypes; m_BlockTypes = NULL; - delete[] m_BlockMetas; m_BlockMetas = NULL; - delete[] m_BlockLight; m_BlockLight = NULL; - delete[] m_BlockSkyLight; m_BlockSkyLight = NULL; - m_SizeX = 0; - m_SizeY = 0; - m_SizeZ = 0; -} - - - - - -void cBlockArea::Create(int a_SizeX, int a_SizeY, int a_SizeZ, int a_DataTypes) -{ - Clear(); - int BlockCount = a_SizeX * a_SizeY * a_SizeZ; - if ((a_DataTypes & baTypes) != 0) - { - m_BlockTypes = new BLOCKTYPE[BlockCount]; - for (int i = 0; i < BlockCount; i++) - { - m_BlockTypes[i] = E_BLOCK_AIR; - } - } - if ((a_DataTypes & baMetas) != 0) - { - m_BlockMetas = new NIBBLETYPE[BlockCount]; - for (int i = 0; i < BlockCount; i++) - { - m_BlockMetas[i] = 0; - } - } - if ((a_DataTypes & baLight) != 0) - { - m_BlockLight = new NIBBLETYPE[BlockCount]; - for (int i = 0; i < BlockCount; i++) - { - m_BlockLight[i] = 0; - } - } - if ((a_DataTypes & baSkyLight) != 0) - { - m_BlockSkyLight = new NIBBLETYPE[BlockCount]; - for (int i = 0; i < BlockCount; i++) - { - m_BlockSkyLight[i] = 0x0f; - } - } - m_SizeX = a_SizeX; - m_SizeY = a_SizeY; - m_SizeZ = a_SizeZ; - m_OriginX = 0; - m_OriginY = 0; - m_OriginZ = 0; -} - - - - - -void cBlockArea::SetOrigin(int a_OriginX, int a_OriginY, int a_OriginZ) -{ - m_OriginX = a_OriginX; - m_OriginY = a_OriginY; - m_OriginZ = a_OriginZ; -} - - - - - -bool cBlockArea::Read(cWorld * a_World, int a_MinBlockX, int a_MaxBlockX, int a_MinBlockY, int a_MaxBlockY, int a_MinBlockZ, int a_MaxBlockZ, int a_DataTypes) -{ - // Normalize the coords: - if (a_MinBlockX > a_MaxBlockX) - { - std::swap(a_MinBlockX, a_MaxBlockX); - } - if (a_MinBlockY > a_MaxBlockY) - { - std::swap(a_MinBlockY, a_MaxBlockY); - } - if (a_MinBlockZ > a_MaxBlockZ) - { - std::swap(a_MinBlockZ, a_MaxBlockZ); - } - - // Include the Max coords: - a_MaxBlockX += 1; - a_MaxBlockY += 1; - a_MaxBlockZ += 1; - - // Check coords validity: - if (a_MinBlockY < 0) - { - LOGWARNING("%s: MinBlockY less than zero, adjusting to zero", __FUNCTION__); - a_MinBlockY = 0; - } - else if (a_MinBlockY >= cChunkDef::Height) - { - LOGWARNING("%s: MinBlockY more than chunk height, adjusting to chunk height", __FUNCTION__); - a_MinBlockY = cChunkDef::Height - 1; - } - if (a_MaxBlockY < 0) - { - LOGWARNING("%s: MaxBlockY less than zero, adjusting to zero", __FUNCTION__); - a_MaxBlockY = 0; - } - else if (a_MaxBlockY >= cChunkDef::Height) - { - LOGWARNING("%s: MaxBlockY more than chunk height, adjusting to chunk height", __FUNCTION__); - a_MaxBlockY = cChunkDef::Height - 1; - } - - // Allocate the needed memory: - Clear(); - if (!SetSize(a_MaxBlockX - a_MinBlockX, a_MaxBlockY - a_MinBlockY, a_MaxBlockZ - a_MinBlockZ, a_DataTypes)) - { - return false; - } - m_OriginX = a_MinBlockX; - m_OriginY = a_MinBlockY; - m_OriginZ = a_MinBlockZ; - cChunkReader Reader(*this); - - // Convert block coords to chunks coords: - int MinChunkX, MaxChunkX; - int MinChunkZ, MaxChunkZ; - cChunkDef::AbsoluteToRelative(a_MinBlockX, a_MinBlockY, a_MinBlockZ, MinChunkX, MinChunkZ); - cChunkDef::AbsoluteToRelative(a_MaxBlockX, a_MaxBlockY, a_MaxBlockZ, MaxChunkX, MaxChunkZ); - - // Query block data: - if (!a_World->ForEachChunkInRect(MinChunkX, MaxChunkX, MinChunkZ, MaxChunkZ, Reader)) - { - Clear(); - return false; - } - - return true; -} - - - - - -bool cBlockArea::Write(cWorld * a_World, int a_MinBlockX, int a_MinBlockY, int a_MinBlockZ, int a_DataTypes) -{ - ASSERT((a_DataTypes & GetDataTypes()) == a_DataTypes); // Are you requesting only the data that I have? - a_DataTypes = a_DataTypes & GetDataTypes(); // For release builds, silently cut off the datatypes that I don't have - - // Check coords validity: - if (a_MinBlockY < 0) - { - LOGWARNING("%s: MinBlockY less than zero, adjusting to zero", __FUNCTION__); - a_MinBlockY = 0; - } - else if (a_MinBlockY >= cChunkDef::Height - m_SizeY) - { - LOGWARNING("%s: MinBlockY + m_SizeY more than chunk height, adjusting to chunk height", __FUNCTION__); - a_MinBlockY = cChunkDef::Height - m_SizeY - 1; - } - - return a_World->WriteBlockArea(*this, a_MinBlockX, a_MinBlockY, a_MinBlockZ, a_DataTypes); -} - - - - - -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 cBlockArea::CopyFrom(const cBlockArea & a_From) -{ - a_From.CopyTo(*this); -} - - - - - -void cBlockArea::DumpToRawFile(const AString & a_FileName) -{ - cFile f; - if (!f.Open(a_FileName, cFile::fmWrite)) - { - LOGWARNING("cBlockArea: Cannot open file \"%s\" for raw dump", a_FileName.c_str()); - return; - } - UInt32 SizeX = ntohl(m_SizeX); - UInt32 SizeY = ntohl(m_SizeY); - UInt32 SizeZ = ntohl(m_SizeZ); - f.Write(&SizeX, 4); - f.Write(&SizeY, 4); - f.Write(&SizeZ, 4); - unsigned char DataTypes = GetDataTypes(); - f.Write(&DataTypes, 1); - int NumBlocks = GetBlockCount(); - if (HasBlockTypes()) - { - f.Write(m_BlockTypes, NumBlocks * sizeof(BLOCKTYPE)); - } - if (HasBlockMetas()) - { - f.Write(m_BlockMetas, NumBlocks); - } - if (HasBlockLights()) - { - f.Write(m_BlockLight, NumBlocks); - } - if (HasBlockSkyLights()) - { - f.Write(m_BlockSkyLight, NumBlocks); - } -} - - - - - -bool cBlockArea::LoadFromSchematicFile(const AString & a_FileName) -{ - // Un-GZip the contents: - AString Contents; - cGZipFile File; - if (!File.Open(a_FileName, cGZipFile::fmRead)) - { - LOG("Cannot open the schematic file \"%s\".", a_FileName.c_str()); - return false; - } - int NumBytesRead = File.ReadRestOfFile(Contents); - if (NumBytesRead < 0) - { - LOG("Cannot read GZipped data in the schematic file \"%s\", error %d", a_FileName.c_str(), NumBytesRead); - return false; - } - File.Close(); - - // Parse the NBT: - cParsedNBT NBT(Contents.data(), Contents.size()); - if (!NBT.IsValid()) - { - LOG("Cannot parse the NBT in the schematic file \"%s\".", a_FileName.c_str()); - return false; - } - - return LoadFromSchematicNBT(NBT); -} - - - - - -bool cBlockArea::SaveToSchematicFile(const AString & a_FileName) -{ - cFastNBTWriter Writer("Schematic"); - Writer.AddShort("Width", m_SizeX); - Writer.AddShort("Height", m_SizeY); - Writer.AddShort("Length", m_SizeZ); - Writer.AddString("Materials", "Alpha"); - if (HasBlockTypes()) - { - Writer.AddByteArray("Blocks", (const char *)m_BlockTypes, GetBlockCount()); - } - else - { - AString Dummy(GetBlockCount(), 0); - Writer.AddByteArray("Blocks", Dummy.data(), Dummy.size()); - } - if (HasBlockMetas()) - { - Writer.AddByteArray("Data", (const char *)m_BlockMetas, GetBlockCount()); - } - else - { - AString Dummy(GetBlockCount(), 0); - Writer.AddByteArray("Data", Dummy.data(), Dummy.size()); - } - // TODO: Save entities and block entities - Writer.BeginList("Entities", TAG_Compound); - Writer.EndList(); - Writer.BeginList("TileEntities", TAG_Compound); - Writer.EndList(); - Writer.Finish(); - - // Save to file - cGZipFile File; - if (!File.Open(a_FileName, cGZipFile::fmWrite)) - { - LOG("Cannot open file \"%s\" for writing.", a_FileName.c_str()); - return false; - } - if (!File.Write(Writer.GetResult())) - { - LOG("Cannot write data to file \"%s\".", a_FileName.c_str()); - return false; - } - return true; -} - - - - - -void cBlockArea::Crop(int a_AddMinX, int a_SubMaxX, int a_AddMinY, int a_SubMaxY, int a_AddMinZ, int a_SubMaxZ) -{ - if ( - (a_AddMinX + a_SubMaxX >= m_SizeX) || - (a_AddMinY + a_SubMaxY >= m_SizeY) || - (a_AddMinZ + a_SubMaxZ >= m_SizeZ) - ) - { - LOGWARNING("cBlockArea:Crop called with more croping than the dimensions: %d x %d x %d with cropping %d, %d and %d", - m_SizeX, m_SizeY, m_SizeZ, - a_AddMinX + a_SubMaxX, a_AddMinY + a_SubMaxY, a_AddMinZ + a_SubMaxZ - ); - return; - } - - if (HasBlockTypes()) - { - CropBlockTypes(a_AddMinX, a_SubMaxX, a_AddMinY, a_SubMaxY, a_AddMinZ, a_SubMaxZ); - } - if (HasBlockMetas()) - { - CropNibbles(m_BlockMetas, a_AddMinX, a_SubMaxX, a_AddMinY, a_SubMaxY, a_AddMinZ, a_SubMaxZ); - } - if (HasBlockLights()) - { - CropNibbles(m_BlockLight, a_AddMinX, a_SubMaxX, a_AddMinY, a_SubMaxY, a_AddMinZ, a_SubMaxZ); - } - if (HasBlockSkyLights()) - { - CropNibbles(m_BlockSkyLight, a_AddMinX, a_SubMaxX, a_AddMinY, a_SubMaxY, a_AddMinZ, a_SubMaxZ); - } - m_OriginX += a_AddMinX; - m_OriginY += a_AddMinY; - m_OriginZ += a_AddMinZ; - m_SizeX -= a_AddMinX + a_SubMaxX; - m_SizeY -= a_AddMinY + a_SubMaxY; - m_SizeZ -= a_AddMinZ + a_SubMaxZ; -} - - - - - -void cBlockArea::Expand(int a_SubMinX, int a_AddMaxX, int a_SubMinY, int a_AddMaxY, int a_SubMinZ, int a_AddMaxZ) -{ - if (HasBlockTypes()) - { - ExpandBlockTypes(a_SubMinX, a_AddMaxX, a_SubMinY, a_AddMaxY, a_SubMinZ, a_AddMaxZ); - } - if (HasBlockMetas()) - { - ExpandNibbles(m_BlockMetas, a_SubMinX, a_AddMaxX, a_SubMinY, a_AddMaxY, a_SubMinZ, a_AddMaxZ); - } - if (HasBlockLights()) - { - ExpandNibbles(m_BlockLight, a_SubMinX, a_AddMaxX, a_SubMinY, a_AddMaxY, a_SubMinZ, a_AddMaxZ); - } - if (HasBlockSkyLights()) - { - ExpandNibbles(m_BlockSkyLight, a_SubMinX, a_AddMaxX, a_SubMinY, a_AddMaxY, a_SubMinZ, a_AddMaxZ); - } - m_OriginX -= a_SubMinX; - m_OriginY -= a_SubMinY; - m_OriginZ -= a_SubMinZ; - m_SizeX += a_SubMinX + a_AddMaxX; - m_SizeY += a_SubMinY + a_AddMaxY; - m_SizeZ += a_SubMinZ + a_AddMaxZ; -} - - - - - -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::Fill(int a_DataTypes, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, NIBBLETYPE a_BlockLight, NIBBLETYPE a_BlockSkyLight) -{ - if ((a_DataTypes & GetDataTypes()) != a_DataTypes) - { - LOGWARNING("%s: requested datatypes that are not present in the BlockArea object, trimming those away (req 0x%x, stor 0x%x)", - __FUNCTION__, a_DataTypes, GetDataTypes() - ); - a_DataTypes = a_DataTypes & GetDataTypes(); - } - - int BlockCount = GetBlockCount(); - if ((a_DataTypes & baTypes) != 0) - { - for (int i = 0; i < BlockCount; i++) - { - m_BlockTypes[i] = a_BlockType; - } - } - if ((a_DataTypes & baMetas) != 0) - { - for (int i = 0; i < BlockCount; i++) - { - m_BlockMetas[i] = a_BlockMeta; - } - } - if ((a_DataTypes & baLight) != 0) - { - for (int i = 0; i < BlockCount; i++) - { - m_BlockLight[i] = a_BlockLight; - } - } - if ((a_DataTypes & baSkyLight) != 0) - { - for (int i = 0; i < BlockCount; i++) - { - m_BlockSkyLight[i] = a_BlockSkyLight; - } - } -} - - - - - -void cBlockArea::FillRelCuboid(int a_MinRelX, int a_MaxRelX, int a_MinRelY, int a_MaxRelY, int a_MinRelZ, int a_MaxRelZ, - int a_DataTypes, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, - NIBBLETYPE a_BlockLight, NIBBLETYPE a_BlockSkyLight -) -{ - if ((a_DataTypes & GetDataTypes()) != a_DataTypes) - { - LOGWARNING("%s: requested datatypes that are not present in the BlockArea object, trimming those away (req 0x%x, stor 0x%x)", - __FUNCTION__, a_DataTypes, GetDataTypes() - ); - a_DataTypes = a_DataTypes & GetDataTypes(); - } - - if ((a_DataTypes & baTypes) != 0) - { - for (int y = a_MinRelY; y <= a_MaxRelY; y++) for (int z = a_MinRelZ; z <= a_MaxRelZ; z++) for (int x = a_MinRelX; x <= a_MaxRelX; x++) - { - m_BlockTypes[MakeIndex(x, y, z)] = a_BlockType; - } // for x, z, y - } - if ((a_DataTypes & baMetas) != 0) - { - for (int y = a_MinRelY; y <= a_MaxRelY; y++) for (int z = a_MinRelZ; z <= a_MaxRelZ; z++) for (int x = a_MinRelX; x <= a_MaxRelX; x++) - { - m_BlockMetas[MakeIndex(x, y, z)] = a_BlockMeta; - } // for x, z, y - } - if ((a_DataTypes & baLight) != 0) - { - for (int y = a_MinRelY; y <= a_MaxRelY; y++) for (int z = a_MinRelZ; z <= a_MaxRelZ; z++) for (int x = a_MinRelX; x <= a_MaxRelX; x++) - { - m_BlockLight[MakeIndex(x, y, z)] = a_BlockLight; - } // for x, z, y - } - if ((a_DataTypes & baSkyLight) != 0) - { - for (int y = a_MinRelY; y <= a_MaxRelY; y++) for (int z = a_MinRelZ; z <= a_MaxRelZ; z++) for (int x = a_MinRelX; x <= a_MaxRelX; x++) - { - m_BlockSkyLight[MakeIndex(x, y, z)] = a_BlockSkyLight; - } // for x, z, y - } -} - - - - - -void cBlockArea::RelLine(int a_RelX1, int a_RelY1, int a_RelZ1, int a_RelX2, int a_RelY2, int a_RelZ2, - int a_DataTypes, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, - NIBBLETYPE a_BlockLight, NIBBLETYPE a_BlockSkyLight -) -{ - // Bresenham-3D algorithm for drawing lines: - int dx = abs(a_RelX2 - a_RelX1); - int dy = abs(a_RelY2 - a_RelY1); - int dz = abs(a_RelZ2 - a_RelZ1); - int sx = (a_RelX1 < a_RelX2) ? 1 : -1; - int sy = (a_RelY1 < a_RelY2) ? 1 : -1; - int sz = (a_RelZ1 < a_RelZ2) ? 1 : -1; - int err = dx - dz; - - if (dx >= std::max(dy, dz)) // x dominant - { - int yd = dy - dx / 2; - int zd = dz - dx / 2; - - while (true) - { - RelSetData(a_RelX1, a_RelY1, a_RelZ1, a_DataTypes, a_BlockType, a_BlockMeta, a_BlockLight, a_BlockSkyLight); - - if (a_RelX1 == a_RelX2) - { - break; - } - - if (yd >= 0) // move along y - { - a_RelY1 += sy; - yd -= dx; - } - - if (zd >= 0) // move along z - { - a_RelZ1 += sz; - zd -= dx; - } - - // move along x - a_RelX1 += sx; - yd += dy; - zd += dz; - } - } - else if (dy >= std::max(dx, dz)) // y dominant - { - int xd = dx - dy / 2; - int zd = dz - dy / 2; - - while (true) - { - RelSetData(a_RelX1, a_RelY1, a_RelZ1, a_DataTypes, a_BlockType, a_BlockMeta, a_BlockLight, a_BlockSkyLight); - - if (a_RelY1 == a_RelY2) - { - break; - } - - if (xd >= 0) // move along x - { - a_RelX1 += sx; - xd -= dy; - } - - if (zd >= 0) // move along z - { - a_RelZ1 += sz; - zd -= dy; - } - - // move along y - a_RelY1 += sy; - xd += dx; - zd += dz; - } - } - else - { - // z dominant - ASSERT(dz >= std::max(dx, dy)); - int xd = dx - dz / 2; - int yd = dy - dz / 2; - - while (true) - { - RelSetData(a_RelX1, a_RelY1, a_RelZ1, a_DataTypes, a_BlockType, a_BlockMeta, a_BlockLight, a_BlockSkyLight); - - if (a_RelZ1 == a_RelZ2) - { - break; - } - - if (xd >= 0) // move along x - { - a_RelX1 += sx; - xd -= dz; - } - - if (yd >= 0) // move along y - { - a_RelY1 += sy; - yd -= dz; - } - - // move along z - a_RelZ1 += sz; - xd += dx; - yd += dy; - } - } // if (which dimension is dominant) -} - - - - - -void cBlockArea::RotateCCW(void) -{ - if (!HasBlockTypes()) - { - LOGWARNING("cBlockArea: Cannot rotate blockmeta without blocktypes!"); - return; - } - - if (!HasBlockMetas()) - { - // There are no blockmetas to rotate, just use the NoMeta function - RotateCCWNoMeta(); - return; - } - - // We are guaranteed that both blocktypes and blockmetas exist; rotate both at the same time: - BLOCKTYPE * NewTypes = new BLOCKTYPE[m_SizeX * m_SizeY * m_SizeZ]; - NIBBLETYPE * NewMetas = new NIBBLETYPE[m_SizeX * m_SizeY * m_SizeZ]; - for (int x = 0; x < m_SizeX; x++) - { - int NewZ = m_SizeX - x - 1; - for (int z = 0; z < m_SizeZ; z++) - { - int NewX = z; - for (int y = 0; y < m_SizeY; y++) - { - int NewIdx = NewX + NewZ * m_SizeX + y * m_SizeX * m_SizeZ; - int OldIdx = MakeIndex(x, y, z); - NewTypes[NewIdx] = m_BlockTypes[OldIdx]; - NewMetas[NewIdx] = BlockHandler(m_BlockTypes[OldIdx])->MetaRotateCCW(m_BlockMetas[OldIdx]); - } // for y - } // for z - } // for x - std::swap(m_BlockTypes, NewTypes); - std::swap(m_BlockMetas, NewMetas); - delete[] NewTypes; - delete[] NewMetas; - - std::swap(m_SizeX, m_SizeZ); -} - - - - - -void cBlockArea::RotateCW(void) -{ - if (!HasBlockTypes()) - { - LOGWARNING("cBlockArea: Cannot rotate blockmeta without blocktypes!"); - return; - } - - if (!HasBlockMetas()) - { - // There are no blockmetas to rotate, just use the NoMeta function - RotateCWNoMeta(); - return; - } - - // We are guaranteed that both blocktypes and blockmetas exist; rotate both at the same time: - BLOCKTYPE * NewTypes = new BLOCKTYPE[m_SizeX * m_SizeY * m_SizeZ]; - NIBBLETYPE * NewMetas = new NIBBLETYPE[m_SizeX * m_SizeY * m_SizeZ]; - for (int x = 0; x < m_SizeX; x++) - { - int NewZ = x; - for (int z = 0; z < m_SizeZ; z++) - { - int NewX = m_SizeZ - z - 1; - for (int y = 0; y < m_SizeY; y++) - { - int NewIdx = NewX + NewZ * m_SizeX + y * m_SizeX * m_SizeZ; - int OldIdx = MakeIndex(x, y, z); - NewTypes[NewIdx] = m_BlockTypes[OldIdx]; - NewMetas[NewIdx] = BlockHandler(m_BlockTypes[OldIdx])->MetaRotateCW(m_BlockMetas[OldIdx]); - } // for y - } // for z - } // for x - std::swap(m_BlockTypes, NewTypes); - std::swap(m_BlockMetas, NewMetas); - delete[] NewTypes; - delete[] NewMetas; - - std::swap(m_SizeX, m_SizeZ); -} - - - - - -void cBlockArea::MirrorXY(void) -{ - if (!HasBlockTypes()) - { - LOGWARNING("cBlockArea: Cannot mirror meta without blocktypes!"); - return; - } - - if (!HasBlockMetas()) - { - // There are no blockmetas to mirror, just use the NoMeta function - MirrorXYNoMeta(); - return; - } - - // We are guaranteed that both blocktypes and blockmetas exist; mirror both at the same time: - int HalfZ = m_SizeZ / 2; - int MaxZ = m_SizeZ - 1; - for (int y = 0; y < m_SizeY; y++) - { - for (int z = 0; z < HalfZ; z++) - { - for (int x = 0; x < m_SizeX; x++) - { - int Idx1 = MakeIndex(x, y, z); - int Idx2 = MakeIndex(x, y, MaxZ - z); - std::swap(m_BlockTypes[Idx1], m_BlockTypes[Idx2]); - NIBBLETYPE Meta1 = BlockHandler(m_BlockTypes[Idx2])->MetaMirrorXY(m_BlockMetas[Idx1]); - NIBBLETYPE Meta2 = BlockHandler(m_BlockTypes[Idx1])->MetaMirrorXY(m_BlockMetas[Idx2]); - m_BlockMetas[Idx1] = Meta2; - m_BlockMetas[Idx2] = Meta1; - } // for x - } // for z - } // for y -} - - - - - -void cBlockArea::MirrorXZ(void) -{ - if (!HasBlockTypes()) - { - LOGWARNING("cBlockArea: Cannot mirror meta without blocktypes!"); - return; - } - - if (!HasBlockMetas()) - { - // There are no blockmetas to mirror, just use the NoMeta function - MirrorXZNoMeta(); - return; - } - - // We are guaranteed that both blocktypes and blockmetas exist; mirror both at the same time: - int HalfY = m_SizeY / 2; - int MaxY = m_SizeY - 1; - for (int y = 0; y < HalfY; y++) - { - for (int z = 0; z < m_SizeZ; z++) - { - for (int x = 0; x < m_SizeX; x++) - { - int Idx1 = MakeIndex(x, y, z); - int Idx2 = MakeIndex(x, MaxY - y, z); - std::swap(m_BlockTypes[Idx1], m_BlockTypes[Idx2]); - NIBBLETYPE Meta1 = BlockHandler(m_BlockTypes[Idx2])->MetaMirrorXZ(m_BlockMetas[Idx1]); - NIBBLETYPE Meta2 = BlockHandler(m_BlockTypes[Idx1])->MetaMirrorXZ(m_BlockMetas[Idx2]); - m_BlockMetas[Idx1] = Meta2; - m_BlockMetas[Idx2] = Meta1; - } // for x - } // for z - } // for y -} - - - - - -void cBlockArea::MirrorYZ(void) -{ - if (!HasBlockTypes()) - { - LOGWARNING("cBlockArea: Cannot mirror meta without blocktypes!"); - return; - } - - if (!HasBlockMetas()) - { - // There are no blockmetas to mirror, just use the NoMeta function - MirrorYZNoMeta(); - return; - } - - // We are guaranteed that both blocktypes and blockmetas exist; mirror both at the same time: - int HalfX = m_SizeX / 2; - int MaxX = m_SizeX - 1; - for (int y = 0; y < m_SizeY; y++) - { - for (int z = 0; z < m_SizeZ; z++) - { - for (int x = 0; x < HalfX; x++) - { - int Idx1 = MakeIndex(x, y, z); - int Idx2 = MakeIndex(MaxX - x, y, z); - std::swap(m_BlockTypes[Idx1], m_BlockTypes[Idx2]); - NIBBLETYPE Meta1 = BlockHandler(m_BlockTypes[Idx2])->MetaMirrorYZ(m_BlockMetas[Idx1]); - NIBBLETYPE Meta2 = BlockHandler(m_BlockTypes[Idx1])->MetaMirrorYZ(m_BlockMetas[Idx2]); - m_BlockMetas[Idx1] = Meta2; - m_BlockMetas[Idx2] = Meta1; - } // for x - } // for z - } // for y -} - - - - - -void cBlockArea::RotateCCWNoMeta(void) -{ - if (HasBlockTypes()) - { - BLOCKTYPE * NewTypes = new BLOCKTYPE[m_SizeX * m_SizeY * m_SizeZ]; - for (int x = 0; x < m_SizeX; x++) - { - int NewZ = m_SizeX - x - 1; - for (int z = 0; z < m_SizeZ; z++) - { - int NewX = z; - for (int y = 0; y < m_SizeY; y++) - { - NewTypes[NewX + NewZ * m_SizeX + y * m_SizeX * m_SizeZ] = m_BlockTypes[MakeIndex(x, y, z)]; - } // for y - } // for z - } // for x - std::swap(m_BlockTypes, NewTypes); - delete[] NewTypes; - } - if (HasBlockMetas()) - { - NIBBLETYPE * NewMetas = new NIBBLETYPE[m_SizeX * m_SizeY * m_SizeZ]; - for (int x = 0; x < m_SizeX; x++) - { - int NewZ = m_SizeX - x - 1; - for (int z = 0; z < m_SizeZ; z++) - { - int NewX = z; - for (int y = 0; y < m_SizeY; y++) - { - NewMetas[NewX + NewZ * m_SizeX + y * m_SizeX * m_SizeZ] = m_BlockMetas[MakeIndex(x, y, z)]; - } // for y - } // for z - } // for x - std::swap(m_BlockMetas, NewMetas); - delete[] NewMetas; - } - std::swap(m_SizeX, m_SizeZ); -} - - - - - -void cBlockArea::RotateCWNoMeta(void) -{ - if (HasBlockTypes()) - { - BLOCKTYPE * NewTypes = new BLOCKTYPE[m_SizeX * m_SizeY * m_SizeZ]; - for (int z = 0; z < m_SizeZ; z++) - { - int NewX = m_SizeZ - z - 1; - for (int x = 0; x < m_SizeX; x++) - { - int NewZ = x; - for (int y = 0; y < m_SizeY; y++) - { - NewTypes[NewX + NewZ * m_SizeX + y * m_SizeX * m_SizeZ] = m_BlockTypes[MakeIndex(x, y, z)]; - } // for y - } // for x - } // for z - std::swap(m_BlockTypes, NewTypes); - delete[] NewTypes; - } - if (HasBlockMetas()) - { - NIBBLETYPE * NewMetas = new NIBBLETYPE[m_SizeX * m_SizeY * m_SizeZ]; - for (int z = 0; z < m_SizeZ; z++) - { - int NewX = m_SizeZ - z - 1; - for (int x = 0; x < m_SizeX; x++) - { - int NewZ = x; - for (int y = 0; y < m_SizeY; y++) - { - NewMetas[NewX + NewZ * m_SizeX + y * m_SizeX * m_SizeZ] = m_BlockMetas[MakeIndex(x, y, z)]; - } // for y - } // for x - } // for z - std::swap(m_BlockMetas, NewMetas); - delete[] NewMetas; - } - std::swap(m_SizeX, m_SizeZ); -} - - - - - -void cBlockArea::MirrorXYNoMeta(void) -{ - int HalfZ = m_SizeZ / 2; - int MaxZ = m_SizeZ - 1; - if (HasBlockTypes()) - { - for (int y = 0; y < m_SizeY; y++) - { - for (int z = 0; z < HalfZ; z++) - { - for (int x = 0; x < m_SizeX; x++) - { - std::swap(m_BlockTypes[MakeIndex(x, y, z)], m_BlockTypes[MakeIndex(x, y, MaxZ - z)]); - } // for x - } // for z - } // for y - } // if (HasBlockTypes) - - if (HasBlockMetas()) - { - for (int y = 0; y < m_SizeY; y++) - { - for (int z = 0; z < HalfZ; z++) - { - for (int x = 0; x < m_SizeX; x++) - { - std::swap(m_BlockMetas[MakeIndex(x, y, z)], m_BlockMetas[MakeIndex(x, y, MaxZ - z)]); - } // for x - } // for z - } // for y - } // if (HasBlockMetas) -} - - - - - -void cBlockArea::MirrorXZNoMeta(void) -{ - int HalfY = m_SizeY / 2; - int MaxY = m_SizeY - 1; - if (HasBlockTypes()) - { - for (int y = 0; y < HalfY; y++) - { - for (int z = 0; z < m_SizeZ; z++) - { - for (int x = 0; x < m_SizeX; x++) - { - std::swap(m_BlockTypes[MakeIndex(x, y, z)], m_BlockTypes[MakeIndex(x, MaxY - y, z)]); - } // for x - } // for z - } // for y - } // if (HasBlockTypes) - - if (HasBlockMetas()) - { - for (int y = 0; y < HalfY; y++) - { - for (int z = 0; z < m_SizeZ; z++) - { - for (int x = 0; x < m_SizeX; x++) - { - std::swap(m_BlockMetas[MakeIndex(x, y, z)], m_BlockMetas[MakeIndex(x, MaxY - y, z)]); - } // for x - } // for z - } // for y - } // if (HasBlockMetas) -} - - - - - -void cBlockArea::MirrorYZNoMeta(void) -{ - int HalfX = m_SizeX / 2; - int MaxX = m_SizeX - 1; - if (HasBlockTypes()) - { - for (int y = 0; y < m_SizeY; y++) - { - for (int z = 0; z < m_SizeZ; z++) - { - for (int x = 0; x < HalfX; x++) - { - std::swap(m_BlockTypes[MakeIndex(x, y, z)], m_BlockTypes[MakeIndex(MaxX - x, y, z)]); - } // for x - } // for z - } // for y - } // if (HasBlockTypes) - - if (HasBlockMetas()) - { - for (int y = 0; y < m_SizeY; y++) - { - for (int z = 0; z < m_SizeZ; z++) - { - for (int x = 0; x < HalfX; x++) - { - std::swap(m_BlockMetas[MakeIndex(x, y, z)], m_BlockMetas[MakeIndex(MaxX - x, y, z)]); - } // for x - } // for z - } // for y - } // if (HasBlockMetas) -} - - - - - -void cBlockArea::SetRelBlockType(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType) -{ - if (m_BlockTypes == NULL) - { - LOGWARNING("cBlockArea: BlockTypes have not been read!"); - return; - } - m_BlockTypes[MakeIndex(a_RelX, a_RelY, a_RelZ)] = a_BlockType; -} - - - - - -void cBlockArea::SetBlockType(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType) -{ - SetRelBlockType(a_BlockX - m_OriginX, a_BlockY - m_OriginY, a_BlockZ - m_OriginZ, a_BlockType); -} - - - - - -void cBlockArea::SetRelBlockMeta(int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_BlockMeta) -{ - SetRelNibble(a_RelX, a_RelY, a_RelZ, a_BlockMeta, m_BlockMetas); -} - - - - - -void cBlockArea::SetBlockMeta(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_BlockMeta) -{ - SetNibble(a_BlockX, a_BlockY, a_BlockZ, a_BlockMeta, m_BlockMetas); -} - - - - - -void cBlockArea::SetRelBlockLight(int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_BlockLight) -{ - SetRelNibble(a_RelX, a_RelY, a_RelZ, a_BlockLight, m_BlockLight); -} - - - - - -void cBlockArea::SetBlockLight(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_BlockLight) -{ - SetNibble(a_BlockX, a_BlockY, a_BlockZ, a_BlockLight, m_BlockLight); -} - - - - - -void cBlockArea::SetRelBlockSkyLight(int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_BlockSkyLight) -{ - SetRelNibble(a_RelX, a_RelY, a_RelZ, a_BlockSkyLight, m_BlockSkyLight); -} - - - - - -void cBlockArea::SetBlockSkyLight(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_BlockSkyLight) -{ - SetNibble(a_BlockX, a_BlockY, a_BlockZ, a_BlockSkyLight, m_BlockSkyLight); -} - - - - - -BLOCKTYPE cBlockArea::GetRelBlockType(int a_RelX, int a_RelY, int a_RelZ) const -{ - if (m_BlockTypes == NULL) - { - LOGWARNING("cBlockArea: BlockTypes have not been read!"); - return E_BLOCK_AIR; - } - return m_BlockTypes[MakeIndex(a_RelX, a_RelY, a_RelZ)]; -} - - - - - -BLOCKTYPE cBlockArea::GetBlockType(int a_BlockX, int a_BlockY, int a_BlockZ) const -{ - return GetRelBlockType(a_BlockX - m_OriginX, a_BlockY - m_OriginY, a_BlockZ - m_OriginZ); -} - - - - - -NIBBLETYPE cBlockArea::GetRelBlockMeta(int a_RelX, int a_RelY, int a_RelZ) const -{ - return GetRelNibble(a_RelX, a_RelY, a_RelZ, m_BlockMetas); -} - - - - - -NIBBLETYPE cBlockArea::GetBlockMeta(int a_BlockX, int a_BlockY, int a_BlockZ) const -{ - return GetNibble(a_BlockX, a_BlockY, a_BlockZ, m_BlockMetas); -} - - - - - -NIBBLETYPE cBlockArea::GetRelBlockLight(int a_RelX, int a_RelY, int a_RelZ) const -{ - return GetRelNibble(a_RelX, a_RelY, a_RelZ, m_BlockLight); -} - - - - - -NIBBLETYPE cBlockArea::GetBlockLight(int a_BlockX, int a_BlockY, int a_BlockZ) const -{ - return GetNibble(a_BlockX, a_BlockY, a_BlockZ, m_BlockLight); -} - - - - - -NIBBLETYPE cBlockArea::GetRelBlockSkyLight(int a_RelX, int a_RelY, int a_RelZ) const -{ - return GetRelNibble(a_RelX, a_RelY, a_RelZ, m_BlockSkyLight); -} - - - - - -NIBBLETYPE cBlockArea::GetBlockSkyLight(int a_BlockX, int a_BlockY, int a_BlockZ) const -{ - return GetNibble(a_BlockX, a_BlockY, a_BlockZ, m_BlockSkyLight); -} - - - - - -void cBlockArea::SetBlockTypeMeta(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) -{ - SetRelBlockTypeMeta(a_BlockX - m_OriginX, a_BlockY - m_OriginY, a_BlockZ - m_OriginZ, a_BlockType, a_BlockMeta); -} - - - - - -void cBlockArea::SetRelBlockTypeMeta(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) -{ - int idx = MakeIndex(a_RelX, a_RelY, a_RelZ); - if (m_BlockTypes == NULL) - { - LOGWARNING("%s: BlockTypes not available but requested to be written to.", __FUNCTION__); - } - else - { - m_BlockTypes[idx] = a_BlockType; - } - if (m_BlockMetas == NULL) - { - LOGWARNING("%s: BlockMetas not available but requested to be written to.", __FUNCTION__); - } - else - { - m_BlockMetas[idx] = a_BlockMeta; - } -} - - - - - -void cBlockArea::GetBlockTypeMeta(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta) const -{ - return GetRelBlockTypeMeta(a_BlockX - m_OriginX, a_BlockY - m_OriginY, a_BlockZ - m_OriginZ, a_BlockType, a_BlockMeta); -} - - - - - -void cBlockArea::GetRelBlockTypeMeta(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta) const -{ - int idx = MakeIndex(a_RelX, a_RelY, a_RelZ); - if (m_BlockTypes == NULL) - { - LOGWARNING("cBlockArea: BlockTypes have not been read!"); - a_BlockType = E_BLOCK_AIR; - } - else - { - a_BlockType = m_BlockTypes[idx]; - } - - if (m_BlockMetas == NULL) - { - LOGWARNING("cBlockArea: BlockMetas have not been read!"); - a_BlockMeta = 0; - } - else - { - a_BlockMeta = m_BlockMetas[idx]; - } -} - - - - - -int cBlockArea::GetDataTypes(void) const -{ - int res = 0; - if (m_BlockTypes != NULL) - { - res |= baTypes; - } - if (m_BlockMetas != NULL) - { - res |= baMetas; - } - if (m_BlockLight != NULL) - { - res |= baLight; - } - if (m_BlockSkyLight != NULL) - { - res |= baSkyLight; - } - return res; -} - - - - - -bool cBlockArea::SetSize(int a_SizeX, int a_SizeY, int a_SizeZ, int a_DataTypes) -{ - ASSERT(m_BlockTypes == NULL); // Has been cleared - - if (a_DataTypes & baTypes) - { - m_BlockTypes = new BLOCKTYPE[a_SizeX * a_SizeY * a_SizeZ]; - if (m_BlockTypes == NULL) - { - return false; - } - } - if (a_DataTypes & baMetas) - { - m_BlockMetas = new NIBBLETYPE[a_SizeX * a_SizeY * a_SizeZ]; - if (m_BlockMetas == NULL) - { - delete[] m_BlockTypes; - return false; - } - } - if (a_DataTypes & baLight) - { - m_BlockLight = new NIBBLETYPE[a_SizeX * a_SizeY * a_SizeZ]; - if (m_BlockLight == NULL) - { - delete[] m_BlockMetas; - delete[] m_BlockTypes; - return false; - } - } - if (a_DataTypes & baSkyLight) - { - m_BlockSkyLight = new NIBBLETYPE[a_SizeX * a_SizeY * a_SizeZ]; - if (m_BlockSkyLight == NULL) - { - delete[] m_BlockLight; - delete[] m_BlockMetas; - delete[] m_BlockTypes; - return false; - } - } - m_SizeX = a_SizeX; - m_SizeY = a_SizeY; - m_SizeZ = a_SizeZ; - return true; -} - - - - - -int cBlockArea::MakeIndex(int a_RelX, int a_RelY, int a_RelZ) const -{ - ASSERT(a_RelX >= 0); - ASSERT(a_RelX < m_SizeX); - ASSERT(a_RelY >= 0); - ASSERT(a_RelY < m_SizeY); - ASSERT(a_RelZ >= 0); - ASSERT(a_RelZ < m_SizeZ); - - return a_RelX + a_RelZ * m_SizeX + a_RelY * m_SizeX * m_SizeZ; -} - - - - - -void cBlockArea::SetRelNibble(int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_Value, NIBBLETYPE * a_Array) -{ - if (a_Array == NULL) - { - LOGWARNING("cBlockArea: datatype has not been read!"); - return; - } - a_Array[MakeIndex(a_RelX, a_RelY, a_RelZ)] = a_Value; -} - - - - - -void cBlockArea::SetNibble(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_Value, NIBBLETYPE * a_Array) -{ - SetRelNibble(a_BlockX - m_OriginX, a_BlockY - m_OriginY, a_BlockZ - m_OriginZ, a_Value, a_Array); -} - - - - - -NIBBLETYPE cBlockArea::GetRelNibble(int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE * a_Array) const -{ - if (a_Array == NULL) - { - LOGWARNING("cBlockArea: datatype has not been read!"); - return 16; - } - return a_Array[MakeIndex(a_RelX, a_RelY, a_RelZ)]; -} - - - - - -NIBBLETYPE cBlockArea::GetNibble(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE * a_Array) const -{ - return GetRelNibble(a_BlockX - m_OriginX, a_BlockY - m_OriginY, a_BlockZ - m_OriginZ, a_Array); -} - - - - - - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// cBlockArea::cChunkReader: - -cBlockArea::cChunkReader::cChunkReader(cBlockArea & a_Area) : - m_Area(a_Area), - m_OriginX(a_Area.m_OriginX), - m_OriginY(a_Area.m_OriginY), - m_OriginZ(a_Area.m_OriginZ) -{ -} - - - - - -void cBlockArea::cChunkReader::CopyNibbles(NIBBLETYPE * a_AreaDst, const NIBBLETYPE * a_ChunkSrc) -{ - int SizeY = m_Area.m_SizeY; - int MinY = m_OriginY; - - // SizeX, SizeZ are the dmensions of the block data to copy from the current chunk (size of the geometric union) - // OffX, OffZ are the offsets of the current chunk data from the area origin - // BaseX, BaseZ are the offsets of the area data within the current chunk from the chunk borders - int SizeX = cChunkDef::Width; - int SizeZ = cChunkDef::Width; - int OffX, OffZ; - int BaseX, BaseZ; - OffX = m_CurrentChunkX * cChunkDef::Width - m_OriginX; - if (OffX < 0) - { - BaseX = -OffX; - SizeX += OffX; // SizeX is decreased, OffX is negative - OffX = 0; - } - else - { - BaseX = 0; - } - OffZ = m_CurrentChunkZ * cChunkDef::Width - m_OriginZ; - if (OffZ < 0) - { - BaseZ = -OffZ; - SizeZ += OffZ; // SizeZ is decreased, OffZ is negative - OffZ = 0; - } - else - { - BaseZ = 0; - } - // If the chunk extends beyond the area in the X or Z axis, cut off the Size: - if ((m_CurrentChunkX + 1) * cChunkDef::Width > m_OriginX + m_Area.m_SizeX) - { - SizeX -= (m_CurrentChunkX + 1) * cChunkDef::Width - (m_OriginX + m_Area.m_SizeX); - } - if ((m_CurrentChunkZ + 1) * cChunkDef::Width > m_OriginZ + m_Area.m_SizeZ) - { - SizeZ -= (m_CurrentChunkZ + 1) * cChunkDef::Width - (m_OriginZ + m_Area.m_SizeZ); - } - - for (int y = 0; y < SizeY; y++) - { - int ChunkY = MinY + y; - int AreaY = y; - for (int z = 0; z < SizeZ; z++) - { - int ChunkZ = BaseZ + z; - int AreaZ = OffZ + z; - for (int x = 0; x < SizeX; x++) - { - int ChunkX = BaseX + x; - int AreaX = OffX + x; - a_AreaDst[m_Area.MakeIndex(AreaX, AreaY, AreaZ)] = cChunkDef::GetNibble(a_ChunkSrc, ChunkX, ChunkY, ChunkZ); - } // for x - } // for z - } // for y -} - - - - - -bool cBlockArea::cChunkReader::Coords(int a_ChunkX, int a_ChunkZ) -{ - m_CurrentChunkX = a_ChunkX; - m_CurrentChunkZ = a_ChunkZ; - return true; -} - - - - - -void cBlockArea::cChunkReader::BlockTypes(const BLOCKTYPE * a_BlockTypes) -{ - if (m_Area.m_BlockTypes == NULL) - { - // Don't want BlockTypes - return; - } - - int SizeY = m_Area.m_SizeY; - int MinY = m_OriginY; - - // SizeX, SizeZ are the dmensions of the block data to copy from the current chunk (size of the geometric union) - // OffX, OffZ are the offsets of the current chunk data from the area origin - // BaseX, BaseZ are the offsets of the area data within the current chunk from the chunk borders - int SizeX = cChunkDef::Width; - int SizeZ = cChunkDef::Width; - int OffX, OffZ; - int BaseX, BaseZ; - OffX = m_CurrentChunkX * cChunkDef::Width - m_OriginX; - if (OffX < 0) - { - BaseX = -OffX; - SizeX += OffX; // SizeX is decreased, OffX is negative - OffX = 0; - } - else - { - BaseX = 0; - } - OffZ = m_CurrentChunkZ * cChunkDef::Width - m_OriginZ; - if (OffZ < 0) - { - BaseZ = -OffZ; - SizeZ += OffZ; // SizeZ is decreased, OffZ is negative - OffZ = 0; - } - else - { - BaseZ = 0; - } - // If the chunk extends beyond the area in the X or Z axis, cut off the Size: - if ((m_CurrentChunkX + 1) * cChunkDef::Width > m_OriginX + m_Area.m_SizeX) - { - SizeX -= (m_CurrentChunkX + 1) * cChunkDef::Width - (m_OriginX + m_Area.m_SizeX); - } - if ((m_CurrentChunkZ + 1) * cChunkDef::Width > m_OriginZ + m_Area.m_SizeZ) - { - SizeZ -= (m_CurrentChunkZ + 1) * cChunkDef::Width - (m_OriginZ + m_Area.m_SizeZ); - } - - for (int y = 0; y < SizeY; y++) - { - int ChunkY = MinY + y; - int AreaY = y; - for (int z = 0; z < SizeZ; z++) - { - int ChunkZ = BaseZ + z; - int AreaZ = OffZ + z; - for (int x = 0; x < SizeX; x++) - { - int ChunkX = BaseX + x; - int AreaX = OffX + x; - m_Area.m_BlockTypes[m_Area.MakeIndex(AreaX, AreaY, AreaZ)] = cChunkDef::GetBlock(a_BlockTypes, ChunkX, ChunkY, ChunkZ); - } // for x - } // for z - } // for y -} - - - - - -void cBlockArea::cChunkReader::BlockMeta(const NIBBLETYPE * a_BlockMetas) -{ - if (m_Area.m_BlockMetas == NULL) - { - // Don't want metas - return; - } - CopyNibbles(m_Area.m_BlockMetas, a_BlockMetas); -} - - - - - -void cBlockArea::cChunkReader::BlockLight(const NIBBLETYPE * a_BlockLight) -{ - if (m_Area.m_BlockLight == NULL) - { - // Don't want light - return; - } - CopyNibbles(m_Area.m_BlockLight, a_BlockLight); -} - - - - - -void cBlockArea::cChunkReader::BlockSkyLight(const NIBBLETYPE * a_BlockSkyLight) -{ - if (m_Area.m_BlockSkyLight == NULL) - { - // Don't want skylight - return; - } - CopyNibbles(m_Area.m_BlockSkyLight, a_BlockSkyLight); -} - - - - - -void cBlockArea::CropBlockTypes(int a_AddMinX, int a_SubMaxX, int a_AddMinY, int a_SubMaxY, int a_AddMinZ, int a_SubMaxZ) -{ - int NewSizeX = GetSizeX() - a_AddMinX - a_SubMaxX; - int NewSizeY = GetSizeY() - a_AddMinY - a_SubMaxY; - int NewSizeZ = GetSizeZ() - a_AddMinZ - a_SubMaxZ; - BLOCKTYPE * NewBlockTypes = new BLOCKTYPE[NewSizeX * NewSizeY * NewSizeZ]; - int idx = 0; - for (int y = 0; y < NewSizeY; y++) - { - for (int z = 0; z < NewSizeZ; z++) - { - for (int x = 0; x < NewSizeX; x++) - { - int OldIndex = MakeIndex(x + a_AddMinX, y + a_AddMinY, z + a_AddMinZ); - NewBlockTypes[idx++] = m_BlockTypes[OldIndex]; - } // for x - } // for z - } // for y - delete m_BlockTypes; - m_BlockTypes = NewBlockTypes; -} - - - - - -void cBlockArea::CropNibbles(NIBBLEARRAY & a_Array, int a_AddMinX, int a_SubMaxX, int a_AddMinY, int a_SubMaxY, int a_AddMinZ, int a_SubMaxZ) -{ - int NewSizeX = GetSizeX() - a_AddMinX - a_SubMaxX; - int NewSizeY = GetSizeY() - a_AddMinY - a_SubMaxY; - int NewSizeZ = GetSizeZ() - a_AddMinZ - a_SubMaxZ; - NIBBLETYPE * NewNibbles = new NIBBLETYPE[NewSizeX * NewSizeY * NewSizeZ]; - int idx = 0; - for (int y = 0; y < NewSizeY; y++) - { - for (int z = 0; z < NewSizeZ; z++) - { - for (int x = 0; x < NewSizeX; x++) - { - NewNibbles[idx++] = a_Array[MakeIndex(x + a_AddMinX, y + a_AddMinY, z + a_AddMinZ)]; - } // for x - } // for z - } // for y - delete a_Array; - a_Array = NewNibbles; -} - - - - - -void cBlockArea::ExpandBlockTypes(int a_SubMinX, int a_AddMaxX, int a_SubMinY, int a_AddMaxY, int a_SubMinZ, int a_AddMaxZ) -{ - int NewSizeX = m_SizeX + a_SubMinX + a_AddMaxX; - int NewSizeY = m_SizeY + a_SubMinY + a_AddMaxY; - int NewSizeZ = m_SizeZ + a_SubMinZ + a_AddMaxZ; - int BlockCount = NewSizeX * NewSizeY * NewSizeZ; - BLOCKTYPE * NewBlockTypes = new BLOCKTYPE[BlockCount]; - memset(NewBlockTypes, 0, BlockCount * sizeof(BLOCKTYPE)); - int OldIndex = 0; - for (int y = 0; y < m_SizeY; y++) - { - int IndexBaseY = (y + a_SubMinY) * m_SizeX * m_SizeZ; - for (int z = 0; z < m_SizeZ; z++) - { - int IndexBaseZ = IndexBaseY + (z + a_SubMinZ) * m_SizeX; - int idx = IndexBaseZ + a_SubMinX; - for (int x = 0; x < m_SizeX; x++) - { - NewBlockTypes[idx++] = m_BlockTypes[OldIndex++]; - } // for x - } // for z - } // for y - delete m_BlockTypes; - m_BlockTypes = NewBlockTypes; -} - - - - - -void cBlockArea::ExpandNibbles(NIBBLEARRAY & a_Array, int a_SubMinX, int a_AddMaxX, int a_SubMinY, int a_AddMaxY, int a_SubMinZ, int a_AddMaxZ) -{ - int NewSizeX = m_SizeX + a_SubMinX + a_AddMaxX; - int NewSizeY = m_SizeY + a_SubMinY + a_AddMaxY; - int NewSizeZ = m_SizeZ + a_SubMinZ + a_AddMaxZ; - int BlockCount = NewSizeX * NewSizeY * NewSizeZ; - NIBBLETYPE * NewNibbles = new NIBBLETYPE[BlockCount]; - memset(NewNibbles, 0, BlockCount * sizeof(NIBBLETYPE)); - int OldIndex = 0; - for (int y = 0; y < m_SizeY; y++) - { - int IndexBaseY = (y + a_SubMinY) * m_SizeX * m_SizeZ; - for (int z = 0; z < m_SizeZ; z++) - { - int IndexBaseZ = IndexBaseY + (z + a_SubMinZ) * m_SizeX; - int idx = IndexBaseZ + a_SubMinX; - for (int x = 0; x < m_SizeX; x++) - { - NewNibbles[idx++] = a_Array[OldIndex++]; - } // for x - } // for z - } // for y - delete a_Array; - a_Array = NewNibbles; -} - - - - - -bool cBlockArea::LoadFromSchematicNBT(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, - a_NBT.GetType(TSizeX), a_NBT.GetType(TSizeY), a_NBT.GetType(TSizeZ) - ); - return false; - } - - int SizeX = a_NBT.GetShort(TSizeX); - int SizeY = a_NBT.GetShort(TSizeY); - int SizeZ = a_NBT.GetShort(TSizeZ); - if ((SizeX < 1) || (SizeY < 1) || (SizeZ < 1)) - { - 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); - - Clear(); - SetSize(SizeX, SizeY, SizeZ, AreMetasPresent ? (baTypes | baMetas) : baTypes); - - // Copy the block types and metas: - int NumBytes = m_SizeX * m_SizeY * m_SizeZ; - if (a_NBT.GetDataLength(TBlockTypes) < NumBytes) - { - LOG("BlockTypes truncated in the schematic file (exp %d, got %d bytes). Loading partial.", - NumBytes, a_NBT.GetDataLength(TBlockTypes) - ); - NumBytes = a_NBT.GetDataLength(TBlockTypes); - } - memcpy(m_BlockTypes, a_NBT.GetData(TBlockTypes), NumBytes); - - if (AreMetasPresent) - { - int NumBytes = m_SizeX * m_SizeY * m_SizeZ; - if (a_NBT.GetDataLength(TBlockMetas) < NumBytes) - { - LOG("BlockMetas truncated in the schematic file (exp %d, got %d bytes). Loading partial.", - NumBytes, a_NBT.GetDataLength(TBlockMetas) - ); - NumBytes = a_NBT.GetDataLength(TBlockMetas); - } - memcpy(m_BlockMetas, a_NBT.GetData(TBlockMetas), NumBytes); - } - - return true; -} - - - - -void cBlockArea::RelSetData( - int a_RelX, int a_RelY, int a_RelZ, - int a_DataTypes, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, - NIBBLETYPE a_BlockLight, NIBBLETYPE a_BlockSkyLight -) -{ - int Index = MakeIndex(a_RelX, a_RelY, a_RelZ); - if ((a_DataTypes & baTypes) != 0) - { - m_BlockTypes[Index] = a_BlockType; - } - if ((a_DataTypes & baMetas) != 0) - { - m_BlockMetas[Index] = a_BlockMeta; - } - if ((a_DataTypes & baLight) != 0) - { - m_BlockLight[Index] = a_BlockLight; - } - if ((a_DataTypes & baSkyLight) != 0) - { - m_BlockSkyLight[Index] = a_BlockSkyLight; - } -} - - - - |