diff options
author | daniel0916 <theschokolps@gmail.com> | 2014-04-07 20:12:17 +0200 |
---|---|---|
committer | daniel0916 <theschokolps@gmail.com> | 2014-04-07 20:12:17 +0200 |
commit | 2e9754ac1cf0537c12ab7974cf55c451c0724540 (patch) | |
tree | 713c5b8c8f22f77893b30b9c8cefca4a7c491483 /src/Generating | |
parent | Fixed merge conflict (diff) | |
parent | Fixed some more minor issues with the redstone simulator. (diff) | |
download | cuberite-2e9754ac1cf0537c12ab7974cf55c451c0724540.tar cuberite-2e9754ac1cf0537c12ab7974cf55c451c0724540.tar.gz cuberite-2e9754ac1cf0537c12ab7974cf55c451c0724540.tar.bz2 cuberite-2e9754ac1cf0537c12ab7974cf55c451c0724540.tar.lz cuberite-2e9754ac1cf0537c12ab7974cf55c451c0724540.tar.xz cuberite-2e9754ac1cf0537c12ab7974cf55c451c0724540.tar.zst cuberite-2e9754ac1cf0537c12ab7974cf55c451c0724540.zip |
Diffstat (limited to 'src/Generating')
32 files changed, 5027 insertions, 228 deletions
diff --git a/src/Generating/BioGen.cpp b/src/Generating/BioGen.cpp index f89b1800d..32a687201 100644 --- a/src/Generating/BioGen.cpp +++ b/src/Generating/BioGen.cpp @@ -97,7 +97,7 @@ void cBioGenConstant::InitializeBiomeGen(cIniFile & a_IniFile) { AString Biome = a_IniFile.GetValueSet("Generator", "ConstantBiome", "Plains"); m_Biome = StringToBiome(Biome); - if (m_Biome == -1) + if (m_Biome == biInvalidBiome) { LOGWARN("[Generator]::ConstantBiome value \"%s\" not recognized, using \"Plains\".", Biome.c_str()); m_Biome = biPlains; @@ -233,7 +233,7 @@ void cBiomeGenList::InitializeBiomes(const AString & a_Biomes) } } EMCSBiome Biome = StringToBiome(Split2[0]); - if (Biome != -1) + if (Biome != biInvalidBiome) { for (int i = 0; i < Count; i++) { @@ -371,8 +371,8 @@ void cBioGenDistortedVoronoi::GenBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::B Distort(BaseX + x * 4, BaseZ + z * 4, DistortX[4 * x][4 * z], DistortZ[4 * x][4 * z]); } - LinearUpscale2DArrayInPlace(&DistortX[0][0], cChunkDef::Width + 1, cChunkDef::Width + 1, 4, 4); - LinearUpscale2DArrayInPlace(&DistortZ[0][0], cChunkDef::Width + 1, cChunkDef::Width + 1, 4, 4); + LinearUpscale2DArrayInPlace<cChunkDef::Width + 1, cChunkDef::Width + 1, 4, 4>(&DistortX[0][0]); + LinearUpscale2DArrayInPlace<cChunkDef::Width + 1, cChunkDef::Width + 1, 4, 4>(&DistortZ[0][0]); for (int z = 0; z < cChunkDef::Width; z++) { @@ -477,8 +477,8 @@ void cBioGenMultiStepMap::DecideOceanLandMushroom(int a_ChunkX, int a_ChunkZ, cC { Distort(BaseX + x * 4, BaseZ + z * 4, DistortX[4 * x][4 * z], DistortZ[4 * x][4 * z], DistortSize); } - LinearUpscale2DArrayInPlace(&DistortX[0][0], cChunkDef::Width + 1, cChunkDef::Width + 1, 4, 4); - LinearUpscale2DArrayInPlace(&DistortZ[0][0], cChunkDef::Width + 1, cChunkDef::Width + 1, 4, 4); + LinearUpscale2DArrayInPlace<cChunkDef::Width + 1, cChunkDef::Width + 1, 4, 4>(&DistortX[0][0]); + LinearUpscale2DArrayInPlace<cChunkDef::Width + 1, cChunkDef::Width + 1, 4, 4>(&DistortZ[0][0]); // Prepare a 9x9 area of neighboring cell seeds // (assuming that 7x7 cell area is larger than a chunk being generated) @@ -500,7 +500,7 @@ void cBioGenMultiStepMap::DecideOceanLandMushroom(int a_ChunkX, int a_ChunkZ, cC int OffsetZ = (m_Noise4.IntNoise3DInt(RealCellX, 32 * RealCellX - 16 * RealCellZ, RealCellZ) / 8) % m_OceanCellSize; SeedX[xc][zc] = CellBlockX + OffsetX; SeedZ[xc][zc] = CellBlockZ + OffsetZ; - SeedV[xc][zc] = (((m_Noise6.IntNoise3DInt(RealCellX, RealCellX - RealCellZ + 1000, RealCellZ) / 11) % 256) > 90) ? biOcean : ((EMCSBiome)(-1)); + SeedV[xc][zc] = (((m_Noise6.IntNoise3DInt(RealCellX, RealCellX - RealCellZ + 1000, RealCellZ) / 11) % 256) > 90) ? biOcean : (biInvalidBiome); } // for z } // for x @@ -573,7 +573,7 @@ void cBioGenMultiStepMap::AddRivers(int a_ChunkX, int a_ChunkZ, cChunkDef::Biome float NoiseCoordZ = (float)(a_ChunkZ * cChunkDef::Width + z) / m_RiverCellSize; for (int x = 0; x < cChunkDef::Width; x++) { - if (cChunkDef::GetBiome(a_BiomeMap, x, z) != -1) + if (cChunkDef::GetBiome(a_BiomeMap, x, z) != biInvalidBiome) { // Biome already set, skip this column continue; @@ -651,8 +651,8 @@ void cBioGenMultiStepMap::BuildTemperatureHumidityMaps(int a_ChunkX, int a_Chunk HumidityMap[x + 17 * z] = NoiseH; } // for x } // for z - LinearUpscale2DArrayInPlace(TemperatureMap, 17, 17, 8, 8); - LinearUpscale2DArrayInPlace(HumidityMap, 17, 17, 8, 8); + LinearUpscale2DArrayInPlace<17, 17, 8, 8>(TemperatureMap); + LinearUpscale2DArrayInPlace<17, 17, 8, 8>(HumidityMap); // Re-map into integral values in [0 .. 255] range: for (size_t idx = 0; idx < ARRAYCOUNT(a_TemperatureMap); idx++) @@ -693,7 +693,7 @@ void cBioGenMultiStepMap::DecideLandBiomes(cChunkDef::BiomeMap & a_BiomeMap, con int idxZ = 17 * z; for (int x = 0; x < cChunkDef::Width; x++) { - if (cChunkDef::GetBiome(a_BiomeMap, x, z) != -1) + if (cChunkDef::GetBiome(a_BiomeMap, x, z) != biInvalidBiome) { // Already set before continue; @@ -778,8 +778,8 @@ void cBioGenTwoLevel::GenBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap DistortZ[4 * x][4 * z] = BlockZ + (int)(64 * NoiseZ); } - LinearUpscale2DArrayInPlace(&DistortX[0][0], cChunkDef::Width + 1, cChunkDef::Width + 1, 4, 4); - LinearUpscale2DArrayInPlace(&DistortZ[0][0], cChunkDef::Width + 1, cChunkDef::Width + 1, 4, 4); + LinearUpscale2DArrayInPlace<cChunkDef::Width + 1, cChunkDef::Width + 1, 4, 4>(&DistortX[0][0]); + LinearUpscale2DArrayInPlace<cChunkDef::Width + 1, cChunkDef::Width + 1, 4, 4>(&DistortZ[0][0]); // Apply distortion to each block coord, then query the voronoi maps for biome group and biome index and choose biome based on that: for (int z = 0; z < cChunkDef::Width; z++) diff --git a/src/Generating/CMakeLists.txt b/src/Generating/CMakeLists.txt index e1ba299fc..1147744c0 100644 --- a/src/Generating/CMakeLists.txt +++ b/src/Generating/CMakeLists.txt @@ -9,3 +9,5 @@ file(GLOB SOURCE ) add_library(Generating ${SOURCE}) + +target_link_libraries(Generating OSSupport iniFile Blocks) diff --git a/src/Generating/Caves.cpp b/src/Generating/Caves.cpp index 2571e6b77..98b7c8681 100644 --- a/src/Generating/Caves.cpp +++ b/src/Generating/Caves.cpp @@ -762,7 +762,7 @@ void cStructGenWormNestCaves::ClearCache(void) -void cStructGenWormNestCaves::GenStructures(cChunkDesc & a_ChunkDesc) +void cStructGenWormNestCaves::GenFinish(cChunkDesc & a_ChunkDesc) { int ChunkX = a_ChunkDesc.GetChunkX(); int ChunkZ = a_ChunkDesc.GetChunkZ(); @@ -902,7 +902,7 @@ static float GetMarbleNoise( float x, float y, float z, cNoise & a_Noise ) -void cStructGenMarbleCaves::GenStructures(cChunkDesc & a_ChunkDesc) +void cStructGenMarbleCaves::GenFinish(cChunkDesc & a_ChunkDesc) { cNoise Noise(m_Seed); for (int z = 0; z < cChunkDef::Width; z++) @@ -938,7 +938,7 @@ void cStructGenMarbleCaves::GenStructures(cChunkDesc & a_ChunkDesc) /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // cStructGenDualRidgeCaves: -void cStructGenDualRidgeCaves::GenStructures(cChunkDesc & a_ChunkDesc) +void cStructGenDualRidgeCaves::GenFinish(cChunkDesc & a_ChunkDesc) { for (int z = 0; z < cChunkDef::Width; z++) { diff --git a/src/Generating/Caves.h b/src/Generating/Caves.h index ea7f10bf4..7c45c056b 100644 --- a/src/Generating/Caves.h +++ b/src/Generating/Caves.h @@ -20,7 +20,7 @@ class cStructGenMarbleCaves : - public cStructureGen + public cFinishGen { public: cStructGenMarbleCaves(int a_Seed) : m_Seed(a_Seed) {} @@ -29,8 +29,8 @@ protected: int m_Seed; - // cStructureGen override: - virtual void GenStructures(cChunkDesc & a_ChunkDesc) override; + // cFinishGen override: + virtual void GenFinish(cChunkDesc & a_ChunkDesc) override; } ; @@ -38,7 +38,7 @@ protected: class cStructGenDualRidgeCaves : - public cStructureGen + public cFinishGen { public: cStructGenDualRidgeCaves(int a_Seed, float a_Threshold) : @@ -55,8 +55,8 @@ protected: int m_Seed; float m_Threshold; - // cStructureGen override: - virtual void GenStructures(cChunkDesc & a_ChunkDesc) override; + // cFinishGen override: + virtual void GenFinish(cChunkDesc & a_ChunkDesc) override; } ; @@ -64,7 +64,7 @@ protected: class cStructGenWormNestCaves : - public cStructureGen + public cFinishGen { public: cStructGenWormNestCaves(int a_Seed, int a_Size = 64, int a_Grid = 96, int a_MaxOffset = 128) : @@ -94,7 +94,7 @@ protected: void GetCavesForChunk(int a_ChunkX, int a_ChunkZ, cCaveSystems & a_Caves); // cStructGen override: - virtual void GenStructures(cChunkDesc & a_ChunkDesc) override; + virtual void GenFinish(cChunkDesc & a_ChunkDesc) override; } ; diff --git a/src/Generating/ChunkDesc.cpp b/src/Generating/ChunkDesc.cpp index af1a8a6c7..7711723fc 100644 --- a/src/Generating/ChunkDesc.cpp +++ b/src/Generating/ChunkDesc.cpp @@ -118,9 +118,9 @@ void cChunkDesc::SetBlockMeta(int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_B -void cChunkDesc::SetBiome(int a_RelX, int a_RelZ, int a_BiomeID) +void cChunkDesc::SetBiome(int a_RelX, int a_RelZ, EMCSBiome a_BiomeID) { - cChunkDef::SetBiome(m_BiomeMap, a_RelX, a_RelZ, (EMCSBiome)a_BiomeID); + cChunkDef::SetBiome(m_BiomeMap, a_RelX, a_RelZ, a_BiomeID); } @@ -209,6 +209,7 @@ bool cChunkDesc::IsUsingDefaultComposition(void) const void cChunkDesc::SetUseDefaultStructures(bool a_bUseDefaultStructures) { + LOGWARNING("%s: Structures are no longer accounted for, use Finishers instead", __FUNCTION__); m_bUseDefaultStructures = a_bUseDefaultStructures; } @@ -218,6 +219,7 @@ void cChunkDesc::SetUseDefaultStructures(bool a_bUseDefaultStructures) bool cChunkDesc::IsUsingDefaultStructures(void) const { + LOGWARNING("%s: Structures are no longer accounted for, use Finishers instead", __FUNCTION__); return m_bUseDefaultStructures; } @@ -341,9 +343,9 @@ void cChunkDesc::ReadBlockArea(cBlockArea & a_Dest, int a_MinRelX, int a_MaxRelX int SizeY = a_MaxRelY - a_MinRelY; int SizeZ = a_MaxRelZ - a_MinRelZ; a_Dest.Clear(); - a_Dest.m_OriginX = m_ChunkX * cChunkDef::Width + a_MinRelX; - a_Dest.m_OriginY = a_MinRelY; - a_Dest.m_OriginZ = m_ChunkZ * cChunkDef::Width + a_MinRelZ; + 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++) @@ -562,6 +564,31 @@ cBlockEntity * cChunkDesc::GetBlockEntity(int a_RelX, int a_RelY, int a_RelZ) +void cChunkDesc::UpdateHeightmap(void) +{ + for (int x = 0; x < cChunkDef::Width; x++) + { + for (int z = 0; z < cChunkDef::Width; z++) + { + int Height = 0; + for (int y = cChunkDef::Height - 1; y > 0; y--) + { + BLOCKTYPE BlockType = GetBlockType(x, y, z); + if (BlockType != E_BLOCK_AIR) + { + Height = y; + break; + } + } // for y + SetHeight(x, z, Height); + } // for z + } // for x +} + + + + + void cChunkDesc::CompressBlockMetas(cChunkDef::BlockNibbles & a_DestMetas) { const NIBBLETYPE * AreaMetas = m_BlockArea.GetBlockMetas(); diff --git a/src/Generating/ChunkDesc.h b/src/Generating/ChunkDesc.h index e130c463f..8edc2800b 100644 --- a/src/Generating/ChunkDesc.h +++ b/src/Generating/ChunkDesc.h @@ -30,7 +30,7 @@ class cChunkDesc public: // tolua_end - /// Uncompressed block metas, 1 meta per byte + /** Uncompressed block metas, 1 meta per byte */ typedef NIBBLETYPE BlockNibbleBytes[cChunkDef::NumBlocks]; cChunkDesc(int a_ChunkX, int a_ChunkZ); @@ -53,9 +53,11 @@ public: void SetBlockMeta(int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_BlockMeta); NIBBLETYPE GetBlockMeta(int a_RelX, int a_RelY, int a_RelZ); - void SetBiome(int a_RelX, int a_RelZ, int a_BiomeID); + void SetBiome(int a_RelX, int a_RelZ, EMCSBiome a_BiomeID); EMCSBiome GetBiome(int a_RelX, int a_RelZ); + // These operate on the heightmap, so they could get out of sync with the data + // Use UpdateHeightmap() to re-sync void SetHeight(int a_RelX, int a_RelZ, int a_Height); int GetHeight(int a_RelX, int a_RelZ); @@ -71,16 +73,16 @@ public: void SetUseDefaultFinish(bool a_bUseDefaultFinish); bool IsUsingDefaultFinish(void) const; - /// Writes the block area into the chunk, with its origin set at the specified relative coords. Area's data overwrite everything in the chunk. + /** Writes the block area into the chunk, with its origin set at the specified relative coords. Area's data overwrite everything in the chunk. */ void WriteBlockArea(const cBlockArea & a_BlockArea, int a_RelX, int a_RelY, int a_RelZ, cBlockArea::eMergeStrategy a_MergeStrategy = cBlockArea::msOverwrite); - /// Reads an area from the chunk into a cBlockArea, blocktypes and blockmetas + /** Reads an area from the chunk into a cBlockArea, blocktypes and blockmetas */ void ReadBlockArea(cBlockArea & a_Dest, int a_MinRelX, int a_MaxRelX, int a_MinRelY, int a_MaxRelY, int a_MinRelZ, int a_MaxRelZ); - /// Returns the maximum height value in the heightmap + /** Returns the maximum height value in the heightmap */ HEIGHTTYPE GetMaxHeight(void) const; - /// Fills the relative cuboid with specified block; allows cuboid out of range of this chunk + /** Fills the relative cuboid with specified block; allows cuboid out of range of this chunk */ void FillRelCuboid( int a_MinX, int a_MaxX, int a_MinY, int a_MaxY, @@ -88,7 +90,7 @@ public: BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta ); - /// Fills the relative cuboid with specified block; allows cuboid out of range of this chunk + /** Fills the relative cuboid with specified block; allows cuboid out of range of this chunk */ void FillRelCuboid(const cCuboid & a_RelCuboid, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) { FillRelCuboid( @@ -99,7 +101,7 @@ public: ); } - /// Replaces the specified src blocks in the cuboid by the dst blocks; allows cuboid out of range of this chunk + /** Replaces the specified src blocks in the cuboid by the dst blocks; allows cuboid out of range of this chunk */ void ReplaceRelCuboid( int a_MinX, int a_MaxX, int a_MinY, int a_MaxY, @@ -108,7 +110,7 @@ public: BLOCKTYPE a_DstType, NIBBLETYPE a_DstMeta ); - /// Replaces the specified src blocks in the cuboid by the dst blocks; allows cuboid out of range of this chunk + /** Replaces the specified src blocks in the cuboid by the dst blocks; allows cuboid out of range of this chunk */ void ReplaceRelCuboid( const cCuboid & a_RelCuboid, BLOCKTYPE a_SrcType, NIBBLETYPE a_SrcMeta, @@ -124,7 +126,7 @@ public: ); } - /// Replaces the blocks in the cuboid by the dst blocks if they are considered non-floor (air, water); allows cuboid out of range of this chunk + /** Replaces the blocks in the cuboid by the dst blocks if they are considered non-floor (air, water); allows cuboid out of range of this chunk */ void FloorRelCuboid( int a_MinX, int a_MaxX, int a_MinY, int a_MaxY, @@ -132,7 +134,7 @@ public: BLOCKTYPE a_DstType, NIBBLETYPE a_DstMeta ); - /// Replaces the blocks in the cuboid by the dst blocks if they are considered non-floor (air, water); allows cuboid out of range of this chunk + /** Replaces the blocks in the cuboid by the dst blocks if they are considered non-floor (air, water); allows cuboid out of range of this chunk */ void FloorRelCuboid( const cCuboid & a_RelCuboid, BLOCKTYPE a_DstType, NIBBLETYPE a_DstMeta @@ -146,7 +148,7 @@ public: ); } - /// Fills the relative cuboid with specified block with a random chance; allows cuboid out of range of this chunk + /** Fills the relative cuboid with specified block with a random chance; allows cuboid out of range of this chunk */ void RandomFillRelCuboid( int a_MinX, int a_MaxX, int a_MinY, int a_MaxY, @@ -155,7 +157,7 @@ public: int a_RandomSeed, int a_ChanceOutOf10k ); - /// Fills the relative cuboid with specified block with a random chance; allows cuboid out of range of this chunk + /** Fills the relative cuboid with specified block with a random chance; allows cuboid out of range of this chunk */ void RandomFillRelCuboid( const cCuboid & a_RelCuboid, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_RandomSeed, int a_ChanceOutOf10k @@ -170,11 +172,15 @@ public: ); } - /// Returns the block entity at the specified coords. - /// If there is no block entity at those coords, tries to create one, based on the block type - /// If the blocktype doesn't support a block entity, returns NULL. + /** Returns the block entity at the specified coords. + If there is no block entity at those coords, tries to create one, based on the block type + If the blocktype doesn't support a block entity, returns NULL. */ cBlockEntity * GetBlockEntity(int a_RelX, int a_RelY, int a_RelZ); + /** Updates the heightmap to match the current contents. + Useful for plugins when writing custom block areas into the chunk */ + void UpdateHeightmap(void); + // tolua_end // Accessors used by cChunkGenerator::Generator descendants: @@ -187,11 +193,11 @@ public: inline cEntityList & GetEntities (void) { return m_Entities; } inline cBlockEntityList & GetBlockEntities (void) { return m_BlockEntities; } - /// Compresses the metas from the BlockArea format (1 meta per byte) into regular format (2 metas per byte) + /** Compresses the metas from the BlockArea format (1 meta per byte) into regular format (2 metas per byte) */ void CompressBlockMetas(cChunkDef::BlockNibbles & a_DestMetas); #ifdef _DEBUG - /// Verifies that the heightmap corresponds to blocktype contents; if not, asserts on that column + /** Verifies that the heightmap corresponds to blocktype contents; if not, asserts on that column */ void VerifyHeightmap(void); #endif // _DEBUG diff --git a/src/Generating/ChunkGenerator.cpp b/src/Generating/ChunkGenerator.cpp index baa5b76b8..73f0223e8 100644 --- a/src/Generating/ChunkGenerator.cpp +++ b/src/Generating/ChunkGenerator.cpp @@ -116,7 +116,7 @@ void cChunkGenerator::QueueGenerateChunk(int a_ChunkX, int a_ChunkY, int a_Chunk // Add to queue, issue a warning if too many: if (m_Queue.size() >= QUEUE_WARNING_LIMIT) { - LOGWARN("WARNING: Adding chunk [%i, %i] to generation queue; Queue is too big! (%i)", a_ChunkX, a_ChunkZ, m_Queue.size()); + LOGWARN("WARNING: Adding chunk [%i, %i] to generation queue; Queue is too big! (" SIZE_T_FMT ")", a_ChunkX, a_ChunkZ, m_Queue.size()); } m_Queue.push_back(cChunkCoords(a_ChunkX, a_ChunkY, a_ChunkZ)); } @@ -180,7 +180,7 @@ BLOCKTYPE cChunkGenerator::GetIniBlock(cIniFile & a_IniFile, const AString & a_S BLOCKTYPE Block = BlockStringToType(BlockType); if (Block < 0) { - LOGWARN("[&s].%s Could not parse block value \"%s\". Using default: \"%s\".", a_SectionName.c_str(), a_ValueName.c_str(), BlockType.c_str(),a_Default.c_str()); + LOGWARN("[%s].%s Could not parse block value \"%s\". Using default: \"%s\".", a_SectionName.c_str(), a_ValueName.c_str(), BlockType.c_str(),a_Default.c_str()); return BlockStringToType(a_Default); } return Block; @@ -201,7 +201,7 @@ void cChunkGenerator::Execute(void) while (!m_ShouldTerminate) { cCSLock Lock(m_CS); - while (m_Queue.size() == 0) + while (m_Queue.empty()) { if ((NumChunksGenerated > 16) && (clock() - LastReportTick > CLOCKS_PER_SEC)) { @@ -221,6 +221,13 @@ void cChunkGenerator::Execute(void) LastReportTick = clock(); } + if (m_Queue.empty()) + { + // Sometimes the queue remains empty + // If so, we can't do any front() operations on it! + continue; + } + cChunkCoords coords = m_Queue.front(); // Get next coord from queue m_Queue.erase( m_Queue.begin() ); // Remove coordinate from queue bool SkipEnabled = (m_Queue.size() > QUEUE_SKIP_LIMIT); diff --git a/src/Generating/CompoGen.cpp b/src/Generating/CompoGen.cpp index 60356fe46..578bb2481 100644 --- a/src/Generating/CompoGen.cpp +++ b/src/Generating/CompoGen.cpp @@ -566,7 +566,7 @@ void cCompoGenNether::ComposeTerrain(cChunkDesc & a_ChunkDesc) m_Noise2.IntNoise3DInt(BaseX + INTERPOL_X * x, 0, BaseZ + INTERPOL_Z * z) / 256; } // for x, z - FloorLo[] - LinearUpscale2DArrayInPlace(FloorLo, 17, 17, INTERPOL_X, INTERPOL_Z); + LinearUpscale2DArrayInPlace<17, 17, INTERPOL_X, INTERPOL_Z>(FloorLo); // Interpolate segments: for (int Segment = 0; Segment < MaxHeight; Segment += SEGMENT_HEIGHT) @@ -579,7 +579,7 @@ void cCompoGenNether::ComposeTerrain(cChunkDesc & a_ChunkDesc) m_Noise2.IntNoise3DInt(BaseX + INTERPOL_Z * x, Segment + SEGMENT_HEIGHT, BaseZ + INTERPOL_Z * z) / 256; } // for x, z - FloorLo[] - LinearUpscale2DArrayInPlace(FloorHi, 17, 17, INTERPOL_X, INTERPOL_Z); + LinearUpscale2DArrayInPlace<17, 17, INTERPOL_X, INTERPOL_Z>(FloorHi); // Interpolate between FloorLo and FloorHi: for (int z = 0; z < 16; z++) for (int x = 0; x < 16; x++) diff --git a/src/Generating/ComposableGenerator.cpp b/src/Generating/ComposableGenerator.cpp index cfa7e9c6f..2e886336f 100644 --- a/src/Generating/ComposableGenerator.cpp +++ b/src/Generating/ComposableGenerator.cpp @@ -21,7 +21,9 @@ #include "DistortedHeightmap.h" #include "EndGen.h" #include "MineShafts.h" +#include "NetherFortGen.h" #include "Noise3DGenerator.h" +#include "POCPieceGenerator.h" #include "Ravines.h" @@ -133,11 +135,6 @@ cComposableGenerator::~cComposableGenerator() delete *itr; } m_FinishGens.clear(); - for (cStructureGenList::const_iterator itr = m_StructureGens.begin(); itr != m_StructureGens.end(); ++itr) - { - delete *itr; - } - m_StructureGens.clear(); delete m_CompositionGen; m_CompositionGen = NULL; @@ -164,7 +161,6 @@ void cComposableGenerator::Initialize(cIniFile & a_IniFile) InitBiomeGen(a_IniFile); InitHeightGen(a_IniFile); InitCompositionGen(a_IniFile); - InitStructureGens(a_IniFile); InitFinishGens(a_IniFile); } @@ -196,25 +192,25 @@ void cComposableGenerator::DoGenerate(int a_ChunkX, int a_ChunkZ, cChunkDesc & a m_HeightGen->GenHeightMap(a_ChunkX, a_ChunkZ, a_ChunkDesc.GetHeightMap()); } + bool ShouldUpdateHeightmap = false; if (a_ChunkDesc.IsUsingDefaultComposition()) { m_CompositionGen->ComposeTerrain(a_ChunkDesc); + ShouldUpdateHeightmap = true; } - if (a_ChunkDesc.IsUsingDefaultStructures()) - { - for (cStructureGenList::iterator itr = m_StructureGens.begin(); itr != m_StructureGens.end(); ++itr) - { - (*itr)->GenStructures(a_ChunkDesc); - } // for itr - m_StructureGens[] - } - if (a_ChunkDesc.IsUsingDefaultFinish()) { for (cFinishGenList::iterator itr = m_FinishGens.begin(); itr != m_FinishGens.end(); ++itr) { (*itr)->GenFinish(a_ChunkDesc); } // for itr - m_FinishGens[] + ShouldUpdateHeightmap = true; + } + + if (ShouldUpdateHeightmap) + { + a_ChunkDesc.UpdateHeightmap(); } } @@ -290,35 +286,69 @@ void cComposableGenerator::InitCompositionGen(cIniFile & a_IniFile) -void cComposableGenerator::InitStructureGens(cIniFile & a_IniFile) +void cComposableGenerator::InitFinishGens(cIniFile & a_IniFile) { - AString Structures = a_IniFile.GetValueSet("Generator", "Structures", "Ravines, WormNestCaves, WaterLakes, LavaLakes, OreNests, Trees"); - int Seed = m_ChunkGenerator.GetSeed(); - AStringVector Str = StringSplitAndTrim(Structures, ","); + eDimension Dimension = StringToDimension(a_IniFile.GetValue("General", "Dimension", "Overworld")); + + // Older configuration used "Structures" in addition to "Finishers"; we don't distinguish between the two anymore (#398) + // Therefore, we load Structures from the ini file for compatibility, but move its contents over to Finishers: + AString Structures = a_IniFile.GetValue("Generator", "Structures", ""); + AString Finishers = a_IniFile.GetValueSet("Generator", "Finishers", "Ravines, WormNestCaves, WaterLakes, LavaLakes, OreNests, Trees, SprinkleFoliage, Ice, Snow, Lilypads, BottomLava, DeadBushes, PreSimulator"); + if (!Structures.empty()) + { + LOGINFO("[Generator].Structures is deprecated, moving the contents to [Generator].Finishers."); + // Structures used to generate before Finishers, so place them first: + Structures.append(", "); + Finishers = Structures + Finishers; + a_IniFile.SetValue("Generator", "Finishers", Finishers); + } + a_IniFile.DeleteValue("Generator", "Structures"); + + // Create all requested finishers: + AStringVector Str = StringSplitAndTrim(Finishers, ","); for (AStringVector::const_iterator itr = Str.begin(); itr != Str.end(); ++itr) { - if (NoCaseCompare(*itr, "DualRidgeCaves") == 0) + // Finishers, alpha-sorted: + if (NoCaseCompare(*itr, "BottomLava") == 0) { - float Threshold = (float)a_IniFile.GetValueSetF("Generator", "DualRidgeCavesThreshold", 0.3); - m_StructureGens.push_back(new cStructGenDualRidgeCaves(Seed, Threshold)); + int DefaultBottomLavaLevel = (Dimension == dimNether) ? 30 : 10; + int BottomLavaLevel = a_IniFile.GetValueSetI("Generator", "BottomLavaLevel", DefaultBottomLavaLevel); + m_FinishGens.push_back(new cFinishGenBottomLava(BottomLavaLevel)); + } + else if (NoCaseCompare(*itr, "DeadBushes") == 0) + { + m_FinishGens.push_back(new cFinishGenSingleBiomeSingleTopBlock(Seed, E_BLOCK_DEAD_BUSH, biDesert, 2, E_BLOCK_SAND, E_BLOCK_SAND)); } else if (NoCaseCompare(*itr, "DirectOverhangs") == 0) { - m_StructureGens.push_back(new cStructGenDirectOverhangs(Seed)); + m_FinishGens.push_back(new cStructGenDirectOverhangs(Seed)); } else if (NoCaseCompare(*itr, "DistortedMembraneOverhangs") == 0) { - m_StructureGens.push_back(new cStructGenDistortedMembraneOverhangs(Seed)); + m_FinishGens.push_back(new cStructGenDistortedMembraneOverhangs(Seed)); + } + else if (NoCaseCompare(*itr, "DualRidgeCaves") == 0) + { + float Threshold = (float)a_IniFile.GetValueSetF("Generator", "DualRidgeCavesThreshold", 0.3); + m_FinishGens.push_back(new cStructGenDualRidgeCaves(Seed, Threshold)); + } + else if (NoCaseCompare(*itr, "Ice") == 0) + { + m_FinishGens.push_back(new cFinishGenIce); } else if (NoCaseCompare(*itr, "LavaLakes") == 0) { int Probability = a_IniFile.GetValueSetI("Generator", "LavaLakesProbability", 10); - m_StructureGens.push_back(new cStructGenLakes(Seed * 5 + 16873, E_BLOCK_STATIONARY_LAVA, *m_HeightGen, Probability)); + m_FinishGens.push_back(new cStructGenLakes(Seed * 5 + 16873, E_BLOCK_STATIONARY_LAVA, *m_HeightGen, Probability)); + } + else if (NoCaseCompare(*itr, "LavaSprings") == 0) + { + m_FinishGens.push_back(new cFinishGenFluidSprings(Seed, E_BLOCK_LAVA, a_IniFile, Dimension)); } else if (NoCaseCompare(*itr, "MarbleCaves") == 0) { - m_StructureGens.push_back(new cStructGenMarbleCaves(Seed)); + m_FinishGens.push_back(new cStructGenMarbleCaves(Seed)); } else if (NoCaseCompare(*itr, "MineShafts") == 0) { @@ -327,94 +357,69 @@ void cComposableGenerator::InitStructureGens(cIniFile & a_IniFile) int ChanceCorridor = a_IniFile.GetValueSetI("Generator", "MineShaftsChanceCorridor", 600); int ChanceCrossing = a_IniFile.GetValueSetI("Generator", "MineShaftsChanceCrossing", 200); int ChanceStaircase = a_IniFile.GetValueSetI("Generator", "MineShaftsChanceStaircase", 200); - m_StructureGens.push_back(new cStructGenMineShafts( - Seed, GridSize, MaxSystemSize, + m_FinishGens.push_back(new cStructGenMineShafts( + Seed, GridSize, MaxSystemSize, ChanceCorridor, ChanceCrossing, ChanceStaircase )); } - else if (NoCaseCompare(*itr, "OreNests") == 0) - { - m_StructureGens.push_back(new cStructGenOreNests(Seed)); - } - else if (NoCaseCompare(*itr, "Ravines") == 0) - { - m_StructureGens.push_back(new cStructGenRavines(Seed, 128)); - } - else if (NoCaseCompare(*itr, "Trees") == 0) + else if (NoCaseCompare(*itr, "Lilypads") == 0) { - m_StructureGens.push_back(new cStructGenTrees(Seed, m_BiomeGen, m_HeightGen, m_CompositionGen)); + m_FinishGens.push_back(new cFinishGenSingleBiomeSingleTopBlock(Seed, E_BLOCK_LILY_PAD, biSwampland, 4, E_BLOCK_WATER, E_BLOCK_STATIONARY_WATER)); } - else if (NoCaseCompare(*itr, "WaterLakes") == 0) + else if (NoCaseCompare(*itr, "NetherClumpFoliage") == 0) { - int Probability = a_IniFile.GetValueSetI("Generator", "WaterLakesProbability", 25); - m_StructureGens.push_back(new cStructGenLakes(Seed * 3 + 652, E_BLOCK_STATIONARY_WATER, *m_HeightGen, Probability)); + m_FinishGens.push_back(new cFinishGenNetherClumpFoliage(Seed)); } - else if (NoCaseCompare(*itr, "WormNestCaves") == 0) + else if (NoCaseCompare(*itr, "NetherForts") == 0) { - m_StructureGens.push_back(new cStructGenWormNestCaves(Seed)); + int GridSize = a_IniFile.GetValueSetI("Generator", "NetherFortsGridSize", 512); + int MaxDepth = a_IniFile.GetValueSetI("Generator", "NetherFortsMaxDepth", 12); + m_FinishGens.push_back(new cNetherFortGen(Seed, GridSize, MaxDepth)); } - else + else if (NoCaseCompare(*itr, "OreNests") == 0) { - LOGWARNING("Unknown structure generator: \"%s\". Ignoring.", itr->c_str()); + m_FinishGens.push_back(new cStructGenOreNests(Seed)); } - } // for itr - Str[] -} - - - - - -void cComposableGenerator::InitFinishGens(cIniFile & a_IniFile) -{ - int Seed = m_ChunkGenerator.GetSeed(); - eDimension Dimension = StringToDimension(a_IniFile.GetValue("General", "Dimension", "Overworld")); - - AString Finishers = a_IniFile.GetValueSet("Generator", "Finishers", "SprinkleFoliage,Ice,Snow,Lilypads,BottomLava,DeadBushes,PreSimulator"); - AStringVector Str = StringSplitAndTrim(Finishers, ","); - for (AStringVector::const_iterator itr = Str.begin(); itr != Str.end(); ++itr) - { - // Finishers, alpha-sorted: - if (NoCaseCompare(*itr, "BottomLava") == 0) + else if (NoCaseCompare(*itr, "POCPieces") == 0) { - int DefaultBottomLavaLevel = (Dimension == dimNether) ? 30 : 10; - int BottomLavaLevel = a_IniFile.GetValueSetI("Generator", "BottomLavaLevel", DefaultBottomLavaLevel); - m_FinishGens.push_back(new cFinishGenBottomLava(BottomLavaLevel)); + m_FinishGens.push_back(new cPOCPieceGenerator(Seed)); } - else if (NoCaseCompare(*itr, "DeadBushes") == 0) + else if (NoCaseCompare(*itr, "PreSimulator") == 0) { - m_FinishGens.push_back(new cFinishGenSingleBiomeSingleTopBlock(Seed, E_BLOCK_DEAD_BUSH, biDesert, 2, E_BLOCK_SAND, E_BLOCK_SAND)); + m_FinishGens.push_back(new cFinishGenPreSimulator); } - else if (NoCaseCompare(*itr, "Ice") == 0) + else if (NoCaseCompare(*itr, "Ravines") == 0) { - m_FinishGens.push_back(new cFinishGenIce); + m_FinishGens.push_back(new cStructGenRavines(Seed, 128)); } - else if (NoCaseCompare(*itr, "LavaSprings") == 0) + else if (NoCaseCompare(*itr, "Snow") == 0) { - m_FinishGens.push_back(new cFinishGenFluidSprings(Seed, E_BLOCK_LAVA, a_IniFile, Dimension)); + m_FinishGens.push_back(new cFinishGenSnow); } - else if (NoCaseCompare(*itr, "Lilypads") == 0) + else if (NoCaseCompare(*itr, "SprinkleFoliage") == 0) { - m_FinishGens.push_back(new cFinishGenSingleBiomeSingleTopBlock(Seed, E_BLOCK_LILY_PAD, biSwampland, 4, E_BLOCK_WATER, E_BLOCK_STATIONARY_WATER)); + m_FinishGens.push_back(new cFinishGenSprinkleFoliage(Seed)); } - else if (NoCaseCompare(*itr, "NetherClumpFoliage") == 0) + else if (NoCaseCompare(*itr, "Trees") == 0) { - m_FinishGens.push_back(new cFinishGenNetherClumpFoliage(Seed)); + m_FinishGens.push_back(new cStructGenTrees(Seed, m_BiomeGen, m_HeightGen, m_CompositionGen)); } - else if (NoCaseCompare(*itr, "PreSimulator") == 0) + else if (NoCaseCompare(*itr, "WaterLakes") == 0) { - m_FinishGens.push_back(new cFinishGenPreSimulator); + int Probability = a_IniFile.GetValueSetI("Generator", "WaterLakesProbability", 25); + m_FinishGens.push_back(new cStructGenLakes(Seed * 3 + 652, E_BLOCK_STATIONARY_WATER, *m_HeightGen, Probability)); } - else if (NoCaseCompare(*itr, "Snow") == 0) + else if (NoCaseCompare(*itr, "WaterSprings") == 0) { - m_FinishGens.push_back(new cFinishGenSnow); + m_FinishGens.push_back(new cFinishGenFluidSprings(Seed, E_BLOCK_WATER, a_IniFile, Dimension)); } - else if (NoCaseCompare(*itr, "SprinkleFoliage") == 0) + else if (NoCaseCompare(*itr, "WormNestCaves") == 0) { - m_FinishGens.push_back(new cFinishGenSprinkleFoliage(Seed)); + m_FinishGens.push_back(new cStructGenWormNestCaves(Seed)); } - else if (NoCaseCompare(*itr, "WaterSprings") == 0) + else { - m_FinishGens.push_back(new cFinishGenFluidSprings(Seed, E_BLOCK_WATER, a_IniFile, Dimension)); + LOGWARNING("Unknown Finisher in the [Generator] section: \"%s\". Ignoring.", itr->c_str()); } } // for itr - Str[] } diff --git a/src/Generating/ComposableGenerator.h b/src/Generating/ComposableGenerator.h index 29add0636..6b7627d2e 100644 --- a/src/Generating/ComposableGenerator.h +++ b/src/Generating/ComposableGenerator.h @@ -43,16 +43,16 @@ class cBiomeGen public: virtual ~cBiomeGen() {} // Force a virtual destructor in descendants - /// Generates biomes for the given chunk + /** Generates biomes for the given chunk */ virtual void GenBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap & a_BiomeMap) = 0; - /// Reads parameters from the ini file, prepares generator for use. + /** Reads parameters from the ini file, prepares generator for use. */ virtual void InitializeBiomeGen(cIniFile & a_IniFile) {} - /// Creates the correct BiomeGen descendant based on the ini file settings and the seed provided. - /// a_CacheOffByDefault gets set to whether the cache should be disabled by default - /// Used in BiomeVisualiser, too. - /// Implemented in BioGen.cpp! + /** Creates the correct BiomeGen descendant based on the ini file settings and the seed provided. + a_CacheOffByDefault gets set to whether the cache should be disabled by default. + Used in BiomeVisualiser, too. + Implemented in BioGen.cpp! */ static cBiomeGen * CreateBiomeGen(cIniFile & a_IniFile, int a_Seed, bool & a_CacheOffByDefault); } ; @@ -72,10 +72,10 @@ class cTerrainHeightGen public: virtual ~cTerrainHeightGen() {} // Force a virtual destructor in descendants - /// Generates heightmap for the given chunk + /** Generates heightmap for the given chunk */ virtual void GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap & a_HeightMap) = 0; - /// Reads parameters from the ini file, prepares generator for use. + /** Reads parameters from the ini file, prepares generator for use. */ virtual void InitializeHeightGen(cIniFile & a_IniFile) {} /** Creates the correct TerrainHeightGen descendant based on the ini file settings and the seed provided. @@ -102,7 +102,7 @@ public: virtual void ComposeTerrain(cChunkDesc & a_ChunkDesc) = 0; - /// Reads parameters from the ini file, prepares generator for use. + /** Reads parameters from the ini file, prepares generator for use. */ virtual void InitializeCompoGen(cIniFile & a_IniFile) {} /** Creates the correct TerrainCompositionGen descendant based on the ini file settings and the seed provided. @@ -116,28 +116,12 @@ public: -/** The interface that a structure generator must implement -Structures are generated after the terrain composition took place. It should modify the blocktype data to account -for whatever structures the generator is generating. -Note that ores are considered structures too, at least from the interface point of view. -Also note that a worldgenerator may contain multiple structure generators, one for each type of structure -*/ -class cStructureGen -{ -public: - virtual ~cStructureGen() {} // Force a virtual destructor in descendants - - virtual void GenStructures(cChunkDesc & a_ChunkDesc) = 0; -} ; - -typedef std::list<cStructureGen *> cStructureGenList; - - - - - /** The interface that a finisher must implement -Finisher implements small additions after all structures have been generated. +Finisher implements changes to the chunk after the rough terrain has been generated. +Examples of finishers are trees, snow, ore, lilypads and others. +Note that a worldgenerator may contain multiple finishers. +Also note that previously we used to distinguish between a structuregen and a finisher; this distinction is +no longer relevant, all structure generators are considered finishers now (#398) */ class cFinishGen { @@ -171,7 +155,6 @@ protected: cBiomeGen * m_BiomeGen; cTerrainHeightGen * m_HeightGen; cTerrainCompositionGen * m_CompositionGen; - cStructureGenList m_StructureGens; cFinishGenList m_FinishGens; // Generators underlying the caches: @@ -180,19 +163,16 @@ protected: cTerrainCompositionGen * m_UnderlyingCompositionGen; - /// Reads the biome gen settings from the ini and initializes m_BiomeGen accordingly + /** Reads the biome gen settings from the ini and initializes m_BiomeGen accordingly */ void InitBiomeGen(cIniFile & a_IniFile); - /// Reads the HeightGen settings from the ini and initializes m_HeightGen accordingly + /** Reads the HeightGen settings from the ini and initializes m_HeightGen accordingly */ void InitHeightGen(cIniFile & a_IniFile); - /// Reads the CompositionGen settings from the ini and initializes m_CompositionGen accordingly + /** Reads the CompositionGen settings from the ini and initializes m_CompositionGen accordingly */ void InitCompositionGen(cIniFile & a_IniFile); - /// Reads the structures to generate from the ini and initializes m_StructureGens accordingly - void InitStructureGens(cIniFile & a_IniFile); - - /// Reads the finishers from the ini and initializes m_FinishGens accordingly + /** Reads the finishers from the ini and initializes m_FinishGens accordingly */ void InitFinishGens(cIniFile & a_IniFile); } ; diff --git a/src/Generating/FinishGen.cpp b/src/Generating/FinishGen.cpp index 02045f76a..f2d66af70 100644 --- a/src/Generating/FinishGen.cpp +++ b/src/Generating/FinishGen.cpp @@ -88,7 +88,7 @@ void cFinishGenNetherClumpFoliage::GenFinish(cChunkDesc & a_ChunkDesc) { continue; } - if (!g_BlockIsSolid[a_ChunkDesc.GetBlockType(PosX, y - 1, PosZ)]) // Only place on solid blocks + if (!cBlockInfo::IsSolid(a_ChunkDesc.GetBlockType(PosX, y - 1, PosZ))) // Only place on solid blocks { continue; } @@ -131,7 +131,7 @@ void cFinishGenNetherClumpFoliage::TryPlaceClump(cChunkDesc & a_ChunkDesc, int a } BLOCKTYPE BlockBelow = a_ChunkDesc.GetBlockType(x, y - 1, z); - if (!g_BlockIsSolid[BlockBelow]) // Only place on solid blocks + if (!cBlockInfo::IsSolid(BlockBelow)) // Only place on solid blocks { continue; } @@ -329,7 +329,7 @@ void cFinishGenSnow::GenFinish(cChunkDesc & a_ChunkDesc) case biFrozenOcean: { int Height = a_ChunkDesc.GetHeight(x, z); - if (g_BlockIsSnowable[a_ChunkDesc.GetBlockType(x, Height, z)]) + if (cBlockInfo::IsSnowable(a_ChunkDesc.GetBlockType(x, Height, z))) { a_ChunkDesc.SetBlockType(x, Height + 1, z, E_BLOCK_SNOW); a_ChunkDesc.SetHeight(x, z, Height + 1); diff --git a/src/Generating/HeiGen.cpp b/src/Generating/HeiGen.cpp index 10710b4a1..3621421c2 100644 --- a/src/Generating/HeiGen.cpp +++ b/src/Generating/HeiGen.cpp @@ -428,7 +428,7 @@ void cHeiGenBiomal::GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMa Height[x + 17 * z] = GetHeightAt(x, z, a_ChunkX, a_ChunkZ, Biomes); } } - LinearUpscale2DArrayInPlace(Height, 17, 17, STEPX, STEPZ); + LinearUpscale2DArrayInPlace<17, 17, STEPX, STEPZ>(Height); // Copy into the heightmap for (int z = 0; z < cChunkDef::Width; z++) diff --git a/src/Generating/MineShafts.cpp b/src/Generating/MineShafts.cpp index cc39cef7b..231295c3f 100644 --- a/src/Generating/MineShafts.cpp +++ b/src/Generating/MineShafts.cpp @@ -69,6 +69,8 @@ public: m_BoundingBox(a_BoundingBox) { } + + virtual ~cMineShaft() {} /// Returns true if this mineshaft intersects the specified cuboid bool DoesIntersect(const cCuboid & a_Other) @@ -1338,7 +1340,7 @@ void cStructGenMineShafts::GetMineShaftSystemsForChunk( BaseX -= NEIGHBORHOOD_SIZE / 2; BaseZ -= NEIGHBORHOOD_SIZE / 2; - // Walk the cache, move each cave system that we want into a_Caves: + // Walk the cache, move each cave system that we want into a_Mineshafts: int StartX = BaseX * m_GridSize; int EndX = (BaseX + NEIGHBORHOOD_SIZE + 1) * m_GridSize; int StartZ = BaseZ * m_GridSize; @@ -1407,7 +1409,7 @@ void cStructGenMineShafts::GetMineShaftSystemsForChunk( -void cStructGenMineShafts::GenStructures(cChunkDesc & a_ChunkDesc) +void cStructGenMineShafts::GenFinish(cChunkDesc & a_ChunkDesc) { int ChunkX = a_ChunkDesc.GetChunkX(); int ChunkZ = a_ChunkDesc.GetChunkZ(); diff --git a/src/Generating/MineShafts.h b/src/Generating/MineShafts.h index c53d3bc53..ba32e75ad 100644 --- a/src/Generating/MineShafts.h +++ b/src/Generating/MineShafts.h @@ -17,7 +17,7 @@ class cStructGenMineShafts : - public cStructureGen + public cFinishGen { public: cStructGenMineShafts( @@ -52,8 +52,8 @@ protected: */ void GetMineShaftSystemsForChunk(int a_ChunkX, int a_ChunkZ, cMineShaftSystems & a_MineShaftSystems); - // cStructureGen overrides: - virtual void GenStructures(cChunkDesc & a_ChunkDesc) override; + // cFinishGen overrides: + virtual void GenFinish(cChunkDesc & a_ChunkDesc) override; } ; diff --git a/src/Generating/NetherFortGen.cpp b/src/Generating/NetherFortGen.cpp new file mode 100644 index 000000000..02779a8a3 --- /dev/null +++ b/src/Generating/NetherFortGen.cpp @@ -0,0 +1,275 @@ + +// NetherFortGen.cpp + +// Implements the cNetherFortGen class representing the nether fortress generator + +#include "Globals.h" +#include "NetherFortGen.h" +#include "Prefabs/NetherFortPrefabs.h" + + + + + +static const int NEIGHBORHOOD_SIZE = 3; + + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// cNetherFortGen::cNetherFort: + +class cNetherFortGen::cNetherFort +{ +public: + cNetherFortGen & m_ParentGen; + int m_BlockX, m_BlockZ; + int m_GridSize; + int m_Seed; + cPlacedPieces m_Pieces; + + + cNetherFort(cNetherFortGen & a_ParentGen, int a_BlockX, int a_BlockZ, int a_GridSize, int a_MaxDepth, int a_Seed) : + m_ParentGen(a_ParentGen), + m_BlockX(a_BlockX), + m_BlockZ(a_BlockZ), + m_GridSize(a_GridSize), + m_Seed(a_Seed) + { + // TODO: Proper Y-coord placement + int BlockY = 64; + + // Generate pieces: + for (int i = 0; m_Pieces.size() < (size_t)(a_MaxDepth * a_MaxDepth / 8 + a_MaxDepth); i++) + { + cBFSPieceGenerator pg(m_ParentGen, a_Seed + i); + pg.PlacePieces(a_BlockX, BlockY, a_BlockZ, a_MaxDepth, m_Pieces); + } + } + + + ~cNetherFort() + { + cPieceGenerator::FreePieces(m_Pieces); + } + + + /** Carves the system into the chunk data */ + void ProcessChunk(cChunkDesc & a_Chunk) + { + for (cPlacedPieces::const_iterator itr = m_Pieces.begin(), end = m_Pieces.end(); itr != end; ++itr) + { + const cPrefab & Prefab = (const cPrefab &)((*itr)->GetPiece()); + Prefab.Draw(a_Chunk, *itr); + } // for itr - m_PlacedPieces[] + } +}; + + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// cNetherFortGen: + +cNetherFortGen::cNetherFortGen(int a_Seed, int a_GridSize, int a_MaxDepth) : + m_Seed(a_Seed), + m_Noise(a_Seed), + m_GridSize(a_GridSize), + m_MaxDepth(a_MaxDepth) +{ + // Initialize the prefabs: + for (size_t i = 0; i < g_NetherFortPrefabs1Count; i++) + { + cPrefab * Prefab = new cPrefab(g_NetherFortPrefabs1[i]); + m_AllPieces.push_back(Prefab); + if (Prefab->HasConnectorType(0)) + { + m_OuterPieces.push_back(Prefab); + } + if (Prefab->HasConnectorType(1)) + { + m_InnerPieces.push_back(Prefab); + } + } + + // Initialize the starting piece prefabs: + for (size_t i = 0; i < g_NetherFortStartingPrefabs1Count; i++) + { + m_StartingPieces.push_back(new cPrefab(g_NetherFortStartingPrefabs1[i])); + } + + // DEBUG: Try one round of placement: + cPlacedPieces Pieces; + cBFSPieceGenerator pg(*this, a_Seed); + pg.PlacePieces(0, 64, 0, a_MaxDepth, Pieces); +} + + + + + +cNetherFortGen::~cNetherFortGen() +{ + ClearCache(); + for (cPieces::iterator itr = m_AllPieces.begin(), end = m_AllPieces.end(); itr != end; ++itr) + { + delete *itr; + } // for itr - m_AllPieces[] + m_AllPieces.clear(); +} + + + + + +void cNetherFortGen::ClearCache(void) +{ + // TODO +} + + + + + +void cNetherFortGen::GetFortsForChunk(int a_ChunkX, int a_ChunkZ, cNetherForts & a_Forts) +{ + int BaseX = a_ChunkX * cChunkDef::Width / m_GridSize; + int BaseZ = a_ChunkZ * cChunkDef::Width / m_GridSize; + if (BaseX < 0) + { + --BaseX; + } + if (BaseZ < 0) + { + --BaseZ; + } + BaseX -= NEIGHBORHOOD_SIZE / 2; + BaseZ -= NEIGHBORHOOD_SIZE / 2; + + // Walk the cache, move each cave system that we want into a_Forts: + int StartX = BaseX * m_GridSize; + int EndX = (BaseX + NEIGHBORHOOD_SIZE + 1) * m_GridSize; + int StartZ = BaseZ * m_GridSize; + int EndZ = (BaseZ + NEIGHBORHOOD_SIZE + 1) * m_GridSize; + for (cNetherForts::iterator itr = m_Cache.begin(), end = m_Cache.end(); itr != end;) + { + if ( + ((*itr)->m_BlockX >= StartX) && ((*itr)->m_BlockX < EndX) && + ((*itr)->m_BlockZ >= StartZ) && ((*itr)->m_BlockZ < EndZ) + ) + { + // want + a_Forts.push_back(*itr); + itr = m_Cache.erase(itr); + } + else + { + // don't want + ++itr; + } + } // for itr - m_Cache[] + + // Create those forts that haven't been in the cache: + for (int x = 0; x < NEIGHBORHOOD_SIZE; x++) + { + int RealX = (BaseX + x) * m_GridSize; + for (int z = 0; z < NEIGHBORHOOD_SIZE; z++) + { + int RealZ = (BaseZ + z) * m_GridSize; + bool Found = false; + for (cNetherForts::const_iterator itr = a_Forts.begin(), end = a_Forts.end(); itr != end; ++itr) + { + if (((*itr)->m_BlockX == RealX) && ((*itr)->m_BlockZ == RealZ)) + { + Found = true; + break; + } + } // for itr - a_Mineshafts + if (!Found) + { + a_Forts.push_back(new cNetherFort(*this, RealX, RealZ, m_GridSize, m_MaxDepth, m_Seed)); + } + } // for z + } // for x + + // Copy a_Forts into m_Cache to the beginning: + cNetherForts FortsCopy (a_Forts); + m_Cache.splice(m_Cache.begin(), FortsCopy, FortsCopy.begin(), FortsCopy.end()); + + // Trim the cache if it's too long: + if (m_Cache.size() > 100) + { + cNetherForts::iterator itr = m_Cache.begin(); + std::advance(itr, 100); + for (cNetherForts::iterator end = m_Cache.end(); itr != end; ++itr) + { + delete *itr; + } + itr = m_Cache.begin(); + std::advance(itr, 100); + m_Cache.erase(itr, m_Cache.end()); + } +} + + + + + +void cNetherFortGen::GenFinish(cChunkDesc & a_ChunkDesc) +{ + int ChunkX = a_ChunkDesc.GetChunkX(); + int ChunkZ = a_ChunkDesc.GetChunkZ(); + cNetherForts Forts; + GetFortsForChunk(ChunkX, ChunkZ, Forts); + for (cNetherForts::const_iterator itr = Forts.begin(); itr != Forts.end(); ++itr) + { + (*itr)->ProcessChunk(a_ChunkDesc); + } // for itr - Forts[] +} + + + + + +cPieces cNetherFortGen::GetPiecesWithConnector(int a_ConnectorType) +{ + switch (a_ConnectorType) + { + case 0: return m_OuterPieces; + case 1: return m_InnerPieces; + default: return cPieces(); + } +} + + + + + +cPieces cNetherFortGen::GetStartingPieces(void) +{ + return m_StartingPieces; +} + + + + + +void cNetherFortGen::PiecePlaced(const cPiece & a_Piece) +{ + UNUSED(a_Piece); +} + + + + + +void cNetherFortGen::Reset(void) +{ + // Nothing needed +} + + + + diff --git a/src/Generating/NetherFortGen.h b/src/Generating/NetherFortGen.h new file mode 100644 index 000000000..10ba01396 --- /dev/null +++ b/src/Generating/NetherFortGen.h @@ -0,0 +1,86 @@ + +// NetherFortGen.h + +// Declares the cNetherFortGen class representing the nether fortress generator + + + + + +#pragma once + +#include "ComposableGenerator.h" +#include "PieceGenerator.h" + + + + + +class cNetherFortGen : + public cFinishGen, + public cPiecePool +{ +public: + cNetherFortGen(int a_Seed, int a_GridSize, int a_MaxDepth); + + virtual ~cNetherFortGen(); + +protected: + class cNetherFort; // fwd: NetherFortGen.cpp + typedef std::list<cNetherFort *> cNetherForts; + + + /** The seed used for generating*/ + int m_Seed; + + /** The noise used for generating */ + cNoise m_Noise; + + /** Average spacing between the fortresses*/ + int m_GridSize; + + /** Maximum depth of the piece-generator tree */ + int m_MaxDepth; + + /** Cache of the most recently used systems. MoveToFront used. */ + cNetherForts m_Cache; + + /** All the pieces that are allowed for building. + This is the list that's used for memory allocation and deallocation for the pieces. */ + cPieces m_AllPieces; + + /** The pieces that are used as starting pieces. + This list is not shared and the pieces need deallocation. */ + cPieces m_StartingPieces; + + /** The pieces that have an "outer" connector. + The pieces are copies out of m_AllPieces and shouldn't be ever delete-d. */ + cPieces m_OuterPieces; + + /** The pieces that have an "inner" connector. + The pieces are copies out of m_AllPieces and shouldn't be ever delete-d. */ + cPieces m_InnerPieces; + + + /** Clears everything from the cache. + Also invalidates the forst returned by GetFortsForChunk(). */ + void ClearCache(void); + + /** Returns all forts that *may* intersect the given chunk. + The returned forts live within m_Cache.They are valid until the next call + to this function (which may delete some of the pointers). */ + void GetFortsForChunk(int a_ChunkX, int a_ChunkZ, cNetherForts & a_Forts); + + // cFinishGen overrides: + virtual void GenFinish(cChunkDesc & a_ChunkDesc) override; + + // cPiecePool overrides: + virtual cPieces GetPiecesWithConnector(int a_ConnectorType) override; + virtual cPieces GetStartingPieces(void) override; + virtual void PiecePlaced(const cPiece & a_Piece) override; + virtual void Reset(void) override; +} ; + + + + diff --git a/src/Generating/Noise3DGenerator.cpp b/src/Generating/Noise3DGenerator.cpp index afa40c647..15a588d45 100644 --- a/src/Generating/Noise3DGenerator.cpp +++ b/src/Generating/Noise3DGenerator.cpp @@ -420,7 +420,7 @@ void cNoise3DComposable::GenerateNoiseArrayIfNeeded(int a_ChunkX, int a_ChunkZ) } } // Linear-interpolate this XZ floor: - LinearUpscale2DArrayInPlace(CurFloor, 17, 17, UPSCALE_X, UPSCALE_Z); + LinearUpscale2DArrayInPlace<17, 17, UPSCALE_X, UPSCALE_Z>(CurFloor); } // Finish the 3D linear interpolation by interpolating between each XZ-floors on the Y axis diff --git a/src/Generating/POCPieceGenerator.cpp b/src/Generating/POCPieceGenerator.cpp new file mode 100644 index 000000000..9ed4b565e --- /dev/null +++ b/src/Generating/POCPieceGenerator.cpp @@ -0,0 +1,270 @@ + +// POCPieceGenerator.cpp + +// Implements the cPOCPieceGenerator class representing a Proof-Of_Concept structure generator using the cPieceGenerator technique +// The generator generates a maze of rooms at {0, 50, 0} + +#include "Globals.h" +#include "POCPieceGenerator.h" +#include "ChunkDesc.h" + + + + + +/** POC pieces are simple boxes that have connectors in the middle of their walls. +Each wall has one connector, there are 3 connector types that get assigned semi-randomly. +The piece also knows how to imprint itself in a cChunkDesc, each piece has a different color glass +and each connector is uses a different color wool frame. */ +class cPOCPiece : + public cPiece +{ +public: + cPOCPiece(int a_SizeXZ, int a_Height) : + m_SizeXZ(a_SizeXZ), + m_Height(a_Height) + { + m_Connectors.push_back(cConnector(m_SizeXZ / 2, a_Height / 2, 0, 0, BLOCK_FACE_ZM)); + m_Connectors.push_back(cConnector(m_SizeXZ / 2, a_Height / 2, m_SizeXZ - 1, 1, BLOCK_FACE_ZP)); + m_Connectors.push_back(cConnector(0, a_Height / 2, m_SizeXZ / 2, 2, BLOCK_FACE_XM)); + m_Connectors.push_back(cConnector(m_SizeXZ - 1, a_Height - 1, m_SizeXZ / 2, m_SizeXZ % 3, BLOCK_FACE_XP)); + } + + + /** Imprints the piece in the specified chunk. Assumes they intersect. */ + void ImprintInChunk(cChunkDesc & a_ChunkDesc, const Vector3i & a_Pos, int a_NumCCWRotations) + { + int BlockX = a_ChunkDesc.GetChunkX() * cChunkDef::Width; + int BlockZ = a_ChunkDesc.GetChunkZ() * cChunkDef::Width; + Vector3i Min = a_Pos; + Min.Move(-BlockX, 0, -BlockZ); + Vector3i Max = Min; + Max.Move(m_SizeXZ - 1, m_Height - 1, m_SizeXZ - 1); + ASSERT(Min.x < cChunkDef::Width); + ASSERT(Min.z < cChunkDef::Width); + ASSERT(Max.x >= 0); + ASSERT(Max.z >= 0); + if (Min.x >= 0) + { + // Draw the XM wall: + a_ChunkDesc.FillRelCuboid(Min.x, Min.x, Min.y, Max.y, Min.z, Max.z, E_BLOCK_STAINED_GLASS, m_SizeXZ % 16); + } + if (Min.z >= 0) + { + // Draw the ZM wall: + a_ChunkDesc.FillRelCuboid(Min.x, Max.x, Min.y, Max.y, Min.z, Min.z, E_BLOCK_STAINED_GLASS, m_SizeXZ % 16); + } + if (Max.x < cChunkDef::Width) + { + // Draw the XP wall: + a_ChunkDesc.FillRelCuboid(Max.x, Max.x, Min.y, Max.y, Min.z, Max.z, E_BLOCK_STAINED_GLASS, m_SizeXZ % 16); + } + if (Max.z < cChunkDef::Width) + { + // Draw the ZP wall: + a_ChunkDesc.FillRelCuboid(Min.x, Max.x, Min.y, Max.y, Max.z, Max.z, E_BLOCK_STAINED_GLASS, m_SizeXZ % 16); + } + + // Draw all the connectors: + for (cConnectors::const_iterator itr = m_Connectors.begin(), end = m_Connectors.end(); itr != end; ++itr) + { + cConnector Conn = cPiece::RotateMoveConnector(*itr, a_NumCCWRotations, a_Pos.x, a_Pos.y, a_Pos.z); + Conn.m_Pos.Move(-BlockX, 0, -BlockZ); + if ( + (Conn.m_Pos.x >= 0) && (Conn.m_Pos.x < cChunkDef::Width) && + (Conn.m_Pos.z >= 0) && (Conn.m_Pos.z < cChunkDef::Width) + ) + { + a_ChunkDesc.SetBlockTypeMeta(Conn.m_Pos.x, Conn.m_Pos.y, Conn.m_Pos.z, E_BLOCK_WOOL, itr->m_Type % 16); + } + + /* + // TODO: Frame the connectors + switch (itr->m_Direction) + { + case BLOCK_FACE_XM: + case BLOCK_FACE_XP: + { + // TODO + break; + } + + case BLOCK_FACE_ZM: + case BLOCK_FACE_ZP: + { + // TODO + break; + } + } + */ + } // for itr - m_Connectors[] + } + +protected: + int m_SizeXZ; + int m_Height; + cConnectors m_Connectors; + + // cPiece overrides: + virtual cConnectors GetConnectors(void) const override + { + return m_Connectors; + } + + virtual Vector3i GetSize(void) const override + { + return Vector3i(m_SizeXZ, m_Height, m_SizeXZ); + } + + virtual cCuboid GetHitBox(void) const override + { + return cCuboid(0, 0, 0, m_SizeXZ - 1, m_Height - 1, m_SizeXZ - 1); + } + + virtual bool CanRotateCCW(int a_NumRotations) const override + { + return true; + } +}; + + + + + +/* +static void DebugPieces(const cPlacedPieces & a_Pieces) +{ + size_t idx = 0; + for (cPlacedPieces::const_iterator itr = a_Pieces.begin(), end = a_Pieces.end(); itr != end; ++itr, ++idx) + { + const cCuboid & HitBox = (*itr)->GetHitBox(); + printf(" %u: %d rotations, {%d - %d, %d - %d}\n", + idx, (*itr)->GetNumCCWRotations(), + HitBox.p1.x, HitBox.p2.x, HitBox.p1.z, HitBox.p2.z + ); + } // for itr - a_Pieces[] +} +//*/ + + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// cPOCPieceGenerator: + +cPOCPieceGenerator::cPOCPieceGenerator(int a_Seed) : + m_Seed(a_Seed) +{ + // Prepare a vector of available pieces: + m_AvailPieces.push_back(new cPOCPiece(5, 3)); + m_AvailPieces.push_back(new cPOCPiece(7, 5)); + m_AvailPieces.push_back(new cPOCPiece(9, 5)); + m_AvailPieces.push_back(new cPOCPiece(5, 7)); + + // Generate the structure: + cBFSPieceGenerator Gen(*this, a_Seed); + Gen.PlacePieces(0, 50, 0, 6, m_Pieces); + + // DebugPieces(m_Pieces); + + // Get the smallest cuboid encompassing the entire generated structure: + cCuboid Bounds(0, 50, 0, 0, 50, 0); + for (cPlacedPieces::const_iterator itr = m_Pieces.begin(), end = m_Pieces.end(); itr != end; ++itr) + { + Vector3i MinCoords = (*itr)->GetCoords(); + Bounds.Engulf(MinCoords); + Bounds.Engulf(MinCoords + (*itr)->GetPiece().GetSize()); + } // for itr - m_Pieces[] + m_Bounds = Bounds; +} + + + + + +cPOCPieceGenerator::~cPOCPieceGenerator() +{ + cPieceGenerator::FreePieces(m_Pieces); +} + + + + + +void cPOCPieceGenerator::GenFinish(cChunkDesc & a_ChunkDesc) +{ + int BlockX = a_ChunkDesc.GetChunkX() * cChunkDef::Width; + int BlockZ = a_ChunkDesc.GetChunkZ() * cChunkDef::Width; + if ( + (BlockX + 16 < m_Bounds.p1.x) || (BlockX > m_Bounds.p2.x) || // X coords out of bounds of the generated structure + (BlockZ + 16 < m_Bounds.p1.z) || (BlockZ > m_Bounds.p2.z) // Z coords out of bounds of the generated structure + ) + { + return; + } + + // Imprint each piece in the chunk: + for (cPlacedPieces::const_iterator itr = m_Pieces.begin(), end = m_Pieces.end(); itr != end; ++itr) + { + const Vector3i & Pos = (*itr)->GetCoords(); + Vector3i Size = (*itr)->GetPiece().GetSize(); + if (((*itr)->GetNumCCWRotations() % 2) == 1) + { + std::swap(Size.x, Size.z); + } + if ( + (Pos.x >= BlockX + 16) || (Pos.x + Size.x - 1 < BlockX) || + (Pos.z >= BlockZ + 16) || (Pos.z + Size.z - 1 < BlockZ) + ) + { + // This piece doesn't intersect the chunk + continue; + } + + ((cPOCPiece &)(*itr)->GetPiece()).ImprintInChunk(a_ChunkDesc, Pos, (*itr)->GetNumCCWRotations()); + } // for itr - m_Pieces[] + a_ChunkDesc.UpdateHeightmap(); +} + + + + + +cPieces cPOCPieceGenerator::GetPiecesWithConnector(int a_ConnectorType) +{ + // Each piece has each connector + return m_AvailPieces; +} + + + + + +cPieces cPOCPieceGenerator::GetStartingPieces(void) +{ + // Any piece can be a starting piece + return m_AvailPieces; +} + + + + + +void cPOCPieceGenerator::PiecePlaced(const cPiece & a_Piece) +{ + UNUSED(a_Piece); +} + + + + + +void cPOCPieceGenerator::Reset(void) +{ + // Nothing needed +} + + + + diff --git a/src/Generating/POCPieceGenerator.h b/src/Generating/POCPieceGenerator.h new file mode 100644 index 000000000..de3114ce0 --- /dev/null +++ b/src/Generating/POCPieceGenerator.h @@ -0,0 +1,54 @@ + +// POCPieceGenerator.h + +// Declares the cPOCPieceGenerator class representing a Proof-Of_Concept structure generator using the cPieceGenerator technique +// The generator generates a maze of rooms at {0, 100, 0} + + + + + +#pragma once + +#include "PieceGenerator.h" +#include "ComposableGenerator.h" + + + + + +class cPOCPieceGenerator : + public cFinishGen, + protected cPiecePool +{ +public: + cPOCPieceGenerator(int a_Seed); + ~cPOCPieceGenerator(); + +protected: + int m_Seed; + + /** The pieces from which the generated structure is built. */ + cPieces m_AvailPieces; + + /** The placed pieces of the generated structure. */ + cPlacedPieces m_Pieces; + + /** Bounds of the complete structure, to save on processing outside chunks. */ + cCuboid m_Bounds; + + + // cFinishGen overrides: + virtual void GenFinish(cChunkDesc & a_ChunkDesc) override; + + // cPiecePool overrides: + virtual cPieces GetPiecesWithConnector(int a_ConnectorType) override; + virtual cPieces GetStartingPieces(void) override; + virtual void PiecePlaced(const cPiece & a_Piece) override; + virtual void Reset(void) override; +} ; + + + + + diff --git a/src/Generating/PieceGenerator.cpp b/src/Generating/PieceGenerator.cpp new file mode 100644 index 000000000..8999a5ff7 --- /dev/null +++ b/src/Generating/PieceGenerator.cpp @@ -0,0 +1,625 @@ + +// PieceGenerator.cpp + +// Implements the cBFSPieceGenerator class and cDFSPieceGenerator class +// representing base classes for generating structures composed of individual "pieces" + +#include "Globals.h" +#include "PieceGenerator.h" + + + + + +#ifdef SELF_TEST + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Self-test: + +static class cPieceGeneratorSelfTest : + public cPiecePool +{ +public: + cPieceGeneratorSelfTest(void) + { + // Prepare the internal state: + InitializePieces(); + + // Generate: + cBFSPieceGenerator Gen(*this, 0); + cPlacedPieces OutPieces; + Gen.PlacePieces(500, 50, 500, 3, OutPieces); + + // Print out the pieces: + printf("OutPieces.size() = " SIZE_T_FMT "\n", OutPieces.size()); + size_t idx = 0; + for (cPlacedPieces::const_iterator itr = OutPieces.begin(), end = OutPieces.end(); itr != end; ++itr, ++idx) + { + const Vector3i & Coords = (*itr)->GetCoords(); + cCuboid Hitbox = (*itr)->GetHitBox(); + Hitbox.Sort(); + printf(SIZE_T_FMT ": {%d, %d, %d}, rot %d, hitbox {%d, %d, %d} - {%d, %d, %d} (%d * %d * %d)\n", idx, + Coords.x, Coords.y, Coords.z, + (*itr)->GetNumCCWRotations(), + Hitbox.p1.x, Hitbox.p1.y, Hitbox.p1.z, + Hitbox.p2.x, Hitbox.p2.y, Hitbox.p2.z, + Hitbox.DifX() + 1, Hitbox.DifY() + 1, Hitbox.DifZ() + 1 + ); + } // itr - OutPieces[] + printf("Done.\n"); + + // Free the placed pieces properly: + Gen.FreePieces(OutPieces); + } + + ~cPieceGeneratorSelfTest() + { + // Dealloc all the pieces: + for (cPieces::iterator itr = m_Pieces.begin(), end = m_Pieces.end(); itr != end; ++itr) + { + delete *itr; + } + m_Pieces.clear(); + } + +protected: + class cTestPiece : + public cPiece + { + int m_Size; + public: + cTestPiece(int a_Size) : + m_Size(a_Size) + { + } + + virtual cConnectors GetConnectors(void) const override + { + // Each piece has 4 connectors, one of each type, plus one extra, at the center of its walls: + cConnectors res; + res.push_back(cConnector(m_Size / 2, 1, 0, 0, BLOCK_FACE_ZM)); + res.push_back(cConnector(m_Size / 2, 1, m_Size - 1, 1, BLOCK_FACE_ZP)); + res.push_back(cConnector(0, 1, m_Size / 2, 2, BLOCK_FACE_XM)); + res.push_back(cConnector(m_Size - 1, 1, m_Size / 2, m_Size % 3, BLOCK_FACE_XP)); + return res; + } + + virtual Vector3i GetSize(void) const override + { + return Vector3i(m_Size, 5, m_Size); + } + + virtual cCuboid GetHitBox(void) const override + { + return cCuboid(0, 0, 0, m_Size - 1, 4, m_Size - 1); + } + + virtual bool CanRotateCCW(int a_NumCCWRotations) const override + { + return true; + } + }; + + cPieces m_Pieces; + + virtual cPieces GetPiecesWithConnector(int a_ConnectorType) override + { + // Each piece contains each connector + return m_Pieces; + } + + + virtual cPieces GetStartingPieces(void) override + { + return m_Pieces; + } + + + virtual void PiecePlaced(const cPiece & a_Piece) override + { + UNUSED(a_Piece); + } + + + virtual void Reset(void) override + { + } + + + void InitializePieces(void) + { + m_Pieces.push_back(new cTestPiece(5)); + m_Pieces.push_back(new cTestPiece(7)); + m_Pieces.push_back(new cTestPiece(9)); + } +} g_Test; + +#endif // SELF_TEST + + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// cPiece: + + +Vector3i cPiece::RotatePos(const Vector3i & a_Pos, int a_NumCCWRotations) const +{ + Vector3i Size = GetSize(); + switch (a_NumCCWRotations) + { + case 0: + { + // No rotation needed + return a_Pos; + } + case 1: + { + // 1 CCW rotation: + return Vector3i(a_Pos.z, a_Pos.y, Size.x - a_Pos.x - 1); + } + case 2: + { + // 2 rotations ( = axis flip): + return Vector3i(Size.x - a_Pos.x - 1, a_Pos.y, Size.z - a_Pos.z - 1); + } + case 3: + { + // 1 CW rotation: + return Vector3i(Size.z - a_Pos.z - 1, a_Pos.y, a_Pos.x); + } + } + ASSERT(!"Unhandled rotation"); + return a_Pos; +} + + + + + +cPiece::cConnector cPiece::RotateMoveConnector(const cConnector & a_Connector, int a_NumCCWRotations, int a_MoveX, int a_MoveY, int a_MoveZ) const +{ + cPiece::cConnector res(a_Connector); + + // Rotate the res connector: + switch (a_NumCCWRotations) + { + case 0: + { + // No rotation needed + break; + } + case 1: + { + // 1 CCW rotation: + res.m_Direction = RotateBlockFaceCCW(res.m_Direction); + break; + } + case 2: + { + // 2 rotations ( = axis flip): + res.m_Direction = MirrorBlockFaceY(res.m_Direction); + break; + } + case 3: + { + // 1 CW rotation: + res.m_Direction = RotateBlockFaceCW(res.m_Direction); + break; + } + } + res.m_Pos = RotatePos(a_Connector.m_Pos, a_NumCCWRotations); + + // Move the res connector: + res.m_Pos.x += a_MoveX; + res.m_Pos.y += a_MoveY; + res.m_Pos.z += a_MoveZ; + + return res; +} + + + + + +cCuboid cPiece::RotateHitBoxToConnector( + const cPiece::cConnector & a_MyConnector, + const Vector3i & a_ToConnectorPos, + int a_NumCCWRotations +) const +{ + ASSERT(a_NumCCWRotations == (a_NumCCWRotations % 4)); + Vector3i ConnPos = RotatePos(a_MyConnector.m_Pos, a_NumCCWRotations); + ConnPos = a_ToConnectorPos - ConnPos; + return RotateMoveHitBox(a_NumCCWRotations, ConnPos.x, ConnPos.y, ConnPos.z); +} + + + + + +cCuboid cPiece::RotateMoveHitBox(int a_NumCCWRotations, int a_MoveX, int a_MoveY, int a_MoveZ) const +{ + ASSERT(a_NumCCWRotations == (a_NumCCWRotations % 4)); + cCuboid res = GetHitBox(); + res.p1 = RotatePos(res.p1, a_NumCCWRotations); + res.p2 = RotatePos(res.p2, a_NumCCWRotations); + res.p1.Move(a_MoveX, a_MoveY, a_MoveZ); + res.p2.Move(a_MoveX, a_MoveY, a_MoveZ); + return res; +} + + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// cPiece::cConnector: + +cPiece::cConnector::cConnector(int a_X, int a_Y, int a_Z, int a_Type, eBlockFace a_Direction) : + m_Pos(a_X, a_Y, a_Z), + m_Type(a_Type), + m_Direction(a_Direction) +{ +} + + + + + +cPiece::cConnector::cConnector(const Vector3i & a_Pos, int a_Type, eBlockFace a_Direction) : + m_Pos(a_Pos), + m_Type(a_Type), + m_Direction(a_Direction) +{ +} + + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// cPlacedPiece: + +cPlacedPiece::cPlacedPiece(const cPlacedPiece * a_Parent, const cPiece & a_Piece, const Vector3i & a_Coords, int a_NumCCWRotations) : + m_Parent(a_Parent), + m_Piece(&a_Piece), + m_Coords(a_Coords), + m_NumCCWRotations(a_NumCCWRotations) +{ + m_Depth = (m_Parent == NULL) ? 0 : (m_Parent->GetDepth() + 1); + m_HitBox = a_Piece.RotateMoveHitBox(a_NumCCWRotations, a_Coords.x, a_Coords.y, a_Coords.z); + m_HitBox.Sort(); +} + + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// cPieceGenerator: + +cPieceGenerator::cPieceGenerator(cPiecePool & a_PiecePool, int a_Seed) : + m_PiecePool(a_PiecePool), + m_Noise(a_Seed), + m_Seed(a_Seed) +{ +} + + + + + +void cPieceGenerator::FreePieces(cPlacedPieces & a_PlacedPieces) +{ + for (cPlacedPieces::iterator itr = a_PlacedPieces.begin(), end = a_PlacedPieces.end(); itr != end; ++itr) + { + delete *itr; + } // for itr - a_PlacedPieces[] + a_PlacedPieces.clear(); +} + + + + + +cPlacedPiece * cPieceGenerator::PlaceStartingPiece(int a_BlockX, int a_BlockY, int a_BlockZ, cFreeConnectors & a_OutConnectors) +{ + m_PiecePool.Reset(); + int rnd = m_Noise.IntNoise3DInt(a_BlockX, a_BlockY, a_BlockZ) / 7; + + // Choose a random one of the starting pieces: + cPieces StartingPieces = m_PiecePool.GetStartingPieces(); + cPiece * StartingPiece = StartingPieces[rnd % StartingPieces.size()]; + rnd = rnd >> 16; + + // Choose a random supported rotation: + int Rotations[4] = {0}; + int NumRotations = 1; + for (size_t i = 1; i < ARRAYCOUNT(Rotations); i++) + { + if (StartingPiece->CanRotateCCW(i)) + { + Rotations[NumRotations] = i; + NumRotations += 1; + } + } + int Rotation = Rotations[rnd % NumRotations]; + + cPlacedPiece * res = new cPlacedPiece(NULL, *StartingPiece, Vector3i(a_BlockX, a_BlockY, a_BlockZ), Rotation); + + // Place the piece's connectors into a_OutConnectors: + const cPiece::cConnectors & Conn = StartingPiece->GetConnectors(); + for (cPiece::cConnectors::const_iterator itr = Conn.begin(), end = Conn.end(); itr != end; ++itr) + { + a_OutConnectors.push_back( + cFreeConnector(res, StartingPiece->RotateMoveConnector(*itr, Rotation, a_BlockX, a_BlockY, a_BlockZ)) + ); + } + + return res; +} + + + + + +bool cPieceGenerator::TryPlacePieceAtConnector( + const cPlacedPiece & a_ParentPiece, + const cPiece::cConnector & a_Connector, + cPlacedPieces & a_OutPieces, + cPieceGenerator::cFreeConnectors & a_OutConnectors +) +{ + // Translation of direction - direction -> number of CCW rotations needed: + // You need DirectionRotationTable[rot1][rot2] CCW turns to connect rot1 to rot2 (they are opposite) + static const int DirectionRotationTable[6][6] = + { + /* YM, YP, ZM, ZP, XM, XP */ + /* YM */ { 0, 0, 0, 0, 0, 0}, + /* YP */ { 0, 0, 0, 0, 0, 0}, + /* ZM */ { 0, 0, 2, 0, 1, 3}, + /* ZP */ { 0, 0, 0, 2, 3, 1}, + /* XM */ { 0, 0, 3, 1, 2, 0}, + /* XP */ { 0, 0, 1, 3, 0, 2}, + }; + + // Get a list of available connections: + const int * RotTable = DirectionRotationTable[a_Connector.m_Direction]; + cConnections Connections; + cPieces AvailablePieces = m_PiecePool.GetPiecesWithConnector(a_Connector.m_Type); + Connections.reserve(AvailablePieces.size()); + Vector3i ConnPos = a_Connector.m_Pos; // The position at which the new connector should be placed - 1 block away from the connector + AddFaceDirection(ConnPos.x, ConnPos.y, ConnPos.z, a_Connector.m_Direction); + + /* + // DEBUG: + printf("Placing piece at connector pos {%d, %d, %d}, direction %s\n", ConnPos.x, ConnPos.y, ConnPos.z, BlockFaceToString(a_Connector.m_Direction).c_str()); + //*/ + + for (cPieces::iterator itrP = AvailablePieces.begin(), endP = AvailablePieces.end(); itrP != endP; ++itrP) + { + cPiece::cConnectors Connectors = (*itrP)->GetConnectors(); + for (cPiece::cConnectors::iterator itrC = Connectors.begin(), endC = Connectors.end(); itrC != endC; ++itrC) + { + if (itrC->m_Type != a_Connector.m_Type) + { + continue; + } + // This is a same-type connector, find out how to rotate to it: + int NumCCWRotations = RotTable[itrC->m_Direction]; + if (!(*itrP)->CanRotateCCW(NumCCWRotations)) + { + // Doesn't support this rotation + continue; + } + if (!CheckConnection(a_Connector, ConnPos, **itrP, *itrC, NumCCWRotations, a_OutPieces)) + { + // Doesn't fit in this rotation + continue; + } + Connections.push_back(cConnection(**itrP, *itrC, NumCCWRotations)); + } // for itrC - Connectors[] + } // for itrP - AvailablePieces[] + if (Connections.empty()) + { + // No available connections, bail out + return false; + } + + // Choose a random connection from the list: + int rnd = m_Noise.IntNoise3DInt(a_Connector.m_Pos.x, a_Connector.m_Pos.y, a_Connector.m_Pos.z) / 7; + cConnection & Conn = Connections[rnd % Connections.size()]; + + // Place the piece: + /* + // DEBUG + printf("Chosen connector at {%d, %d, %d}, direction %s, needs %d rotations\n", + Conn.m_Connector.m_Pos.x, Conn.m_Connector.m_Pos.y, Conn.m_Connector.m_Pos.z, + BlockFaceToString(Conn.m_Connector.m_Direction).c_str(), + Conn.m_NumCCWRotations + ); + //*/ + + Vector3i NewPos = Conn.m_Piece->RotatePos(Conn.m_Connector.m_Pos, Conn.m_NumCCWRotations); + ConnPos -= NewPos; + cPlacedPiece * PlacedPiece = new cPlacedPiece(&a_ParentPiece, *(Conn.m_Piece), ConnPos, Conn.m_NumCCWRotations); + a_OutPieces.push_back(PlacedPiece); + + // Add the new piece's connectors to the list of free connectors: + cPiece::cConnectors Connectors = Conn.m_Piece->GetConnectors(); + + /* + // DEBUG: + printf("Adding %u connectors to the pool\n", Connectors.size() - 1); + //*/ + + for (cPiece::cConnectors::const_iterator itr = Connectors.begin(), end = Connectors.end(); itr != end; ++itr) + { + if (itr->m_Pos.Equals(Conn.m_Connector.m_Pos)) + { + // This is the connector through which we have been connected to the parent, don't add + continue; + } + a_OutConnectors.push_back(cFreeConnector(PlacedPiece, Conn.m_Piece->RotateMoveConnector(*itr, Conn.m_NumCCWRotations, ConnPos.x, ConnPos.y, ConnPos.z))); + } + + return true; +} + + + + + +bool cPieceGenerator::CheckConnection( + const cPiece::cConnector & a_ExistingConnector, + const Vector3i & a_ToPos, + const cPiece & a_Piece, + const cPiece::cConnector & a_NewConnector, + int a_NumCCWRotations, + const cPlacedPieces & a_OutPieces +) +{ + // For each placed piece, test the hitbox against the new piece: + cCuboid RotatedHitBox = a_Piece.RotateHitBoxToConnector(a_NewConnector, a_ToPos, a_NumCCWRotations); + RotatedHitBox.Sort(); + for (cPlacedPieces::const_iterator itr = a_OutPieces.begin(), end = a_OutPieces.end(); itr != end; ++itr) + { + if ((*itr)->GetHitBox().DoesIntersect(RotatedHitBox)) + { + return false; + } + } + return true; +} + + + + + +//* +// DEBUG: +void cPieceGenerator::DebugConnectorPool(const cPieceGenerator::cFreeConnectors & a_ConnectorPool, size_t a_NumProcessed) +{ + printf(" Connector pool: " SIZE_T_FMT " items\n", a_ConnectorPool.size() - a_NumProcessed); + size_t idx = 0; + for (cPieceGenerator::cFreeConnectors::const_iterator itr = a_ConnectorPool.begin() + a_NumProcessed, end = a_ConnectorPool.end(); itr != end; ++itr, ++idx) + { + printf(" " SIZE_T_FMT ": {%d, %d, %d}, type %d, direction %s, depth %d\n", + idx, + itr->m_Connector.m_Pos.x, itr->m_Connector.m_Pos.y, itr->m_Connector.m_Pos.z, + itr->m_Connector.m_Type, + BlockFaceToString(itr->m_Connector.m_Direction).c_str(), + itr->m_Piece->GetDepth() + ); + } // for itr - a_ConnectorPool[] +} +//*/ + + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// cPieceGenerator::cConnection: + +cPieceGenerator::cConnection::cConnection(cPiece & a_Piece, cPiece::cConnector & a_Connector, int a_NumCCWRotations) : + m_Piece(&a_Piece), + m_Connector(a_Connector), + m_NumCCWRotations(a_NumCCWRotations) +{ +} + + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// cPieceGenerator::cFreeConnector: + +cPieceGenerator::cFreeConnector::cFreeConnector(cPlacedPiece * a_Piece, const cPiece::cConnector & a_Connector) : + m_Piece(a_Piece), + m_Connector(a_Connector) +{ +} + + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// cBFSPieceGenerator: + +cBFSPieceGenerator::cBFSPieceGenerator(cPiecePool & a_PiecePool, int a_Seed) : + super(a_PiecePool, a_Seed) +{ +} + + + + + +void cBFSPieceGenerator::PlacePieces(int a_BlockX, int a_BlockY, int a_BlockZ, int a_MaxDepth, cPlacedPieces & a_OutPieces) +{ + a_OutPieces.clear(); + cFreeConnectors ConnectorPool; + + // Place the starting piece: + a_OutPieces.push_back(PlaceStartingPiece(a_BlockX, a_BlockY, a_BlockZ, ConnectorPool)); + + /* + // DEBUG: + printf("Placed the starting piece at {%d, %d, %d}\n", a_BlockX, a_BlockY, a_BlockZ); + cCuboid Hitbox = a_OutPieces[0]->GetHitBox(); + Hitbox.Sort(); + printf(" Hitbox: {%d, %d, %d} - {%d, %d, %d} (%d * %d * %d)\n", + Hitbox.p1.x, Hitbox.p1.y, Hitbox.p1.z, + Hitbox.p2.x, Hitbox.p2.y, Hitbox.p2.z, + Hitbox.DifX() + 1, Hitbox.DifY() + 1, Hitbox.DifZ() + 1 + ); + DebugConnectorPool(ConnectorPool, 0); + //*/ + + // Place pieces at the available connectors: + /* + Instead of removing them one by one from the pool, we process them sequentially and take note of the last + processed one. To save on memory, once the number of processed connectors reaches a big number, a chunk + of the connectors is removed. + */ + size_t NumProcessed = 0; + while (ConnectorPool.size() > NumProcessed) + { + cFreeConnector & Conn = ConnectorPool[NumProcessed]; + if (Conn.m_Piece->GetDepth() < a_MaxDepth) + { + if (TryPlacePieceAtConnector(*Conn.m_Piece, Conn.m_Connector, a_OutPieces, ConnectorPool)) + { + /* + // DEBUG: + const cPlacedPiece * NewPiece = a_OutPieces.back(); + const Vector3i & Coords = NewPiece->GetCoords(); + printf("Placed a new piece at {%d, %d, %d}, rotation %d\n", Coords.x, Coords.y, Coords.z, NewPiece->GetNumCCWRotations()); + cCuboid Hitbox = NewPiece->GetHitBox(); + Hitbox.Sort(); + printf(" Hitbox: {%d, %d, %d} - {%d, %d, %d} (%d * %d * %d)\n", + Hitbox.p1.x, Hitbox.p1.y, Hitbox.p1.z, + Hitbox.p2.x, Hitbox.p2.y, Hitbox.p2.z, + Hitbox.DifX() + 1, Hitbox.DifY() + 1, Hitbox.DifZ() + 1 + ); + DebugConnectorPool(ConnectorPool, NumProcessed + 1); + //*/ + } + } + NumProcessed++; + if (NumProcessed > 1000) + { + ConnectorPool.erase(ConnectorPool.begin(), ConnectorPool.begin() + NumProcessed); + NumProcessed = 0; + } + } +} + + + + diff --git a/src/Generating/PieceGenerator.h b/src/Generating/PieceGenerator.h new file mode 100644 index 000000000..bef9d3463 --- /dev/null +++ b/src/Generating/PieceGenerator.h @@ -0,0 +1,247 @@ + +// PieceGenerator.h + +// Declares the cBFSPieceGenerator class and cDFSPieceGenerator class +// representing base classes for generating structures composed of individual "pieces" + +/* +Each uses a slightly different approach to generating: + - DFS extends pieces one by one until it hits the configured depth (or can't connect another piece anymore), + then starts looking at adjacent connectors (like depth-first search). + - BFS keeps a pool of currently-open connectors, chooses one at random and tries to place a piece on it, + thus possibly extending the pool of open connectors (like breadth-first search). +*/ + + + + + +#pragma once + +#include "../Defines.h" +#include "../Cuboid.h" +#include "../Noise.h" + + + + + +/** Represents a single piece. Can have multiple connectors of different types where other pieces can connect. */ +class cPiece +{ +public: + // Force a virtual destructor in all descendants + virtual ~cPiece() {} + + struct cConnector + { + /** Position relative to the piece */ + Vector3i m_Pos; + + /** Type of the connector. Any arbitrary number; the generator connects only connectors of the same type. */ + int m_Type; + + /** Direction in which the connector is facing. + Will be matched by the opposite direction for the connecting connector. */ + eBlockFace m_Direction; + + cConnector(int a_X, int a_Y, int a_Z, int a_Type, eBlockFace a_Direction); + cConnector(const Vector3i & a_Pos, int a_Type, eBlockFace a_Direction); + }; + + typedef std::vector<cConnector> cConnectors; + + /** Returns all of the available connectors that the piece has. + Each connector has a (relative) position in the piece, and a type associated with it. */ + virtual cConnectors GetConnectors(void) const = 0; + + /** Returns the dimensions of this piece. + The dimensions cover the entire piece, there is no block that the piece generates outside of this size. */ + virtual Vector3i GetSize(void) const = 0; + + /** Returns the "hitbox" of this piece. + A hitbox is what is compared and must not intersect other pieces' hitboxes when generating. */ + virtual cCuboid GetHitBox(void) const = 0; + + /** Returns true if the piece can be rotated CCW the specific number of 90-degree turns. */ + virtual bool CanRotateCCW(int a_NumRotations) const = 0; + + /** Returns a copy of the a_Pos after rotating the piece the specified number of CCW rotations. */ + Vector3i RotatePos(const Vector3i & a_Pos, int a_NumCCWRotations) const; + + /** Returns a copy of the connector that is rotated and then moved by the specified amounts. */ + cConnector RotateMoveConnector(const cConnector & a_Connector, int a_NumCCWRotations, int a_MoveX, int a_MoveY, int a_MoveZ) const; + + /** Returns the hitbox after the specified number of rotations and moved so that a_MyConnector is placed at a_ToConnectorPos. */ + cCuboid RotateHitBoxToConnector(const cConnector & a_MyConnector, const Vector3i & a_ToConnectorPos, int a_NumCCWRotations) const; + + /** Returns the hitbox after the specified number of CCW rotations and moved by the specified amounts. */ + cCuboid RotateMoveHitBox(int a_NumCCWRotations, int a_MoveX, int a_MoveY, int a_MoveZ) const; +}; + +typedef std::vector<cPiece *> cPieces; + + + + + +/** This class is an interface that provides pieces for the generator. It can keep track of what pieces were +placed and adjust the returned piece vectors. */ +class cPiecePool +{ +public: + // Force a virtual destructor in all descendants: + virtual ~cPiecePool() {} + + /** Returns a list of pieces that contain the specified connector type. + The cPiece pointers returned are managed by the pool and the caller doesn't free them. */ + virtual cPieces GetPiecesWithConnector(int a_ConnectorType) = 0; + + /** Returns the pieces that should be used as the starting point. + Multiple starting points are supported, one of the returned piece will be chosen. */ + virtual cPieces GetStartingPieces(void) = 0; + + /** Called after a piece is placed, to notify the pool that it has been used. + The pool may adjust the pieces it will return the next time. */ + virtual void PiecePlaced(const cPiece & a_Piece) = 0; + + /** Called when the pool has finished the current structure and should reset any piece-counters it has + for a new structure. */ + virtual void Reset(void) = 0; +}; + + + + + +/** Represents a single piece that has been placed to specific coords in the world. */ +class cPlacedPiece +{ +public: + cPlacedPiece(const cPlacedPiece * a_Parent, const cPiece & a_Piece, const Vector3i & a_Coords, int a_NumCCWRotations); + + const cPiece & GetPiece (void) const { return *m_Piece; } + const Vector3i & GetCoords (void) const { return m_Coords; } + int GetNumCCWRotations(void) const { return m_NumCCWRotations; } + const cCuboid & GetHitBox (void) const { return m_HitBox; } + int GetDepth (void) const { return m_Depth; } + +protected: + const cPlacedPiece * m_Parent; + const cPiece * m_Piece; + Vector3i m_Coords; + int m_NumCCWRotations; + cCuboid m_HitBox; + int m_Depth; +}; + +typedef std::vector<cPlacedPiece *> cPlacedPieces; + + + + + +class cPieceGenerator +{ +public: + cPieceGenerator(cPiecePool & a_PiecePool, int a_Seed); + + /** Cleans up all the memory used by the placed pieces. + Call this utility function instead of freeing the items on your own. */ + static void FreePieces(cPlacedPieces & a_PlacedPieces); + +protected: + /** The type used for storing a connection from one piece to another, while building the piece tree. */ + struct cConnection + { + cPiece * m_Piece; // The piece being connected + cPiece::cConnector m_Connector; // The piece's connector being used (relative non-rotated coords) + int m_NumCCWRotations; // Number of rotations necessary to match the two connectors + + cConnection(cPiece & a_Piece, cPiece::cConnector & a_Connector, int a_NumCCWRotations); + }; + typedef std::vector<cConnection> cConnections; + + /** The type used for storing a pool of connectors that will be attempted to expand by another piece. */ + struct cFreeConnector + { + cPlacedPiece * m_Piece; + cPiece::cConnector m_Connector; + + cFreeConnector(cPlacedPiece * a_Piece, const cPiece::cConnector & a_Connector); + }; + typedef std::vector<cFreeConnector> cFreeConnectors; + + + cPiecePool & m_PiecePool; + cNoise m_Noise; + int m_Seed; + + + /** Selects a starting piece and places it, including the rotations. + Also puts the piece's connectors in a_OutConnectors. */ + cPlacedPiece * PlaceStartingPiece(int a_BlockX, int a_BlockY, int a_BlockZ, cFreeConnectors & a_OutConnectors); + + /** Tries to place a new piece at the specified (placed) connector. Returns true if successful. */ + bool TryPlacePieceAtConnector( + const cPlacedPiece & a_ParentPiece, // The existing piece to a new piece should be placed + const cPiece::cConnector & a_Connector, // The existing connector (world-coords) to which a new piece should be placed + cPlacedPieces & a_OutPieces, // Already placed pieces, to be checked for intersections + cFreeConnectors & a_OutConnectors // List of free connectors to which the new connectors will be placed + ); + + /** Checks if the specified piece would fit with the already-placed pieces, using the specified connector + and number of CCW rotations. + a_ExistingConnector is in world-coords and is already rotated properly + a_ToPos is the world-coords position on which the new connector should be placed (1 block away from a_ExistingConnector, in its Direction) + a_NewConnector is in the original (non-rotated) coords. + Returns true if the piece fits, false if not. */ + bool CheckConnection( + const cPiece::cConnector & a_ExistingConnector, // The existing connector + const Vector3i & a_ToPos, // The position on which the new connector should be placed + const cPiece & a_Piece, // The new piece + const cPiece::cConnector & a_NewConnector, // The connector of the new piece + int a_NumCCWRotations, // Number of rotations for the new piece to align the connector + const cPlacedPieces & a_OutPieces // All the already-placed pieces to check + ); + + /** DEBUG: Outputs all the connectors in the pool into stdout. + a_NumProcessed signals the number of connectors from the pool that should be considered processed (not listed). */ + void DebugConnectorPool(const cPieceGenerator::cFreeConnectors & a_ConnectorPool, size_t a_NumProcessed); +} ; + + + + + +class cBFSPieceGenerator : + public cPieceGenerator +{ + typedef cPieceGenerator super; + +public: + cBFSPieceGenerator(cPiecePool & a_PiecePool, int a_Seed); + + /** Generates a placement for pieces at the specified coords. + Caller must free each individual cPlacedPiece in a_OutPieces. */ + void PlacePieces(int a_BlockX, int a_BlockY, int a_BlockZ, int a_MaxDepth, cPlacedPieces & a_OutPieces); +}; + + + + + +class cDFSPieceGenerator : + public cPieceGenerator +{ +public: + cDFSPieceGenerator(cPiecePool & a_PiecePool, int a_Seed); + + /** Generates a placement for pieces at the specified coords. + Caller must free each individual cPlacedPiece in a_OutPieces. */ + void PlacePieces(int a_BlockX, int a_BlockY, int a_BlockZ, cPlacedPieces & a_OutPieces); +}; + + + + diff --git a/src/Generating/Prefab.cpp b/src/Generating/Prefab.cpp new file mode 100644 index 000000000..131b6acb2 --- /dev/null +++ b/src/Generating/Prefab.cpp @@ -0,0 +1,316 @@ + +// Prefab.cpp + +/* +Implements the cPrefab class, representing a cPiece descendant for the cPieceGenerator that +uses a prefabricate in a cBlockArea for drawing itself. +*/ + +#include "Globals.h" +#include "Prefab.h" +#include "../WorldStorage/SchematicFileSerializer.h" +#include "ChunkDesc.h" + + + + + +#ifdef SELF_TEST + +// Create one static prefab to test the parser: +static const cPrefab::sDef g_TestPrefabDef = +{ + // Size: + 7, 6, 7, // SizeX = 7, SizeY = 6, SizeZ = 7 + + // Block definitions: + ".: 0: 0\n" /* 0 */ + "a:112: 0\n" /* netherbrick */ + "b:113: 0\n" /* netherbrickfence */, + + // Block data: + // Level 1 + "aaaaaaa" + "aaaaaaa" + "aaaaaaa" + "aaaaaaa" + "aaaaaaa" + "aaaaaaa" + "aaaaaaa" + + // Level 2 + "aa...aa" + "a.....a" + "......." + "......." + "......." + "a.....a" + "aa...aa" + + // Level 3 + "aa...aa" + "a.....a" + "......." + "......." + "......." + "a.....a" + "aa...aa" + + // Level 4 + "aa...aa" + "a.....a" + "......." + "......." + "......." + "a.....a" + "aa...aa" + + // Level 5 + "aabbbaa" + "a.....a" + "b.....b" + "b.....b" + "b.....b" + "a.....a" + "aabbbaa" + + // Level 6 + "aaaaaaa" + "a.....a" + "a.....a" + "a.....a" + "a.....a" + "a.....a" + "aaaaaaa", + + // Connections: + "0: 0, 3, 2: 4\n" + "0: 2, 3, 0: 2\n", + + // AllowedRotations: + 7, /* 1, 2, 3 CCW rotations */ + + // Merge strategy: + cBlockArea::msImprint +}; + +static cPrefab g_TestPrefab(g_TestPrefabDef); +#endif + + + + + +cPrefab::cPrefab(const cPrefab::sDef & a_Def) : + m_Size(a_Def.m_SizeX, a_Def.m_SizeY, a_Def.m_SizeZ), + m_HitBox(0, 0, 0, a_Def.m_SizeX - 1, a_Def.m_SizeY - 1, a_Def.m_SizeZ - 1), + m_AllowedRotations(a_Def.m_AllowedRotations), + m_MergeStrategy(a_Def.m_MergeStrategy) +{ + m_BlockArea[0].Create(m_Size); + CharMap cm; + ParseCharMap(cm, a_Def.m_CharMap); + ParseBlockImage(cm, a_Def.m_Image); + ParseConnectors(a_Def.m_Connectors); + + // 1 CCW rotation: + if ((m_AllowedRotations & 0x01) != 0) + { + m_BlockArea[1].CopyFrom(m_BlockArea[0]); + m_BlockArea[1].RotateCCW(); + } + + // 2 rotations are the same as mirroring twice; mirroring is faster because it has no reallocations + if ((m_AllowedRotations & 0x02) != 0) + { + m_BlockArea[2].CopyFrom(m_BlockArea[0]); + m_BlockArea[2].MirrorXY(); + m_BlockArea[2].MirrorYZ(); + } + + // 3 CCW rotations = 1 CW rotation: + if ((m_AllowedRotations & 0x04) != 0) + { + m_BlockArea[3].CopyFrom(m_BlockArea[0]); + m_BlockArea[3].RotateCW(); + } +} + + + + + +void cPrefab::Draw(cChunkDesc & a_Dest, const cPlacedPiece * a_Placement) const +{ + Vector3i Placement = a_Placement->GetCoords(); + int ChunkStartX = a_Dest.GetChunkX() * cChunkDef::Width; + int ChunkStartZ = a_Dest.GetChunkZ() * cChunkDef::Width; + Placement.Move(-ChunkStartX, 0, -ChunkStartZ); + a_Dest.WriteBlockArea(m_BlockArea[a_Placement->GetNumCCWRotations()], Placement.x, Placement.y, Placement.z, m_MergeStrategy); + +} + + + + + +bool cPrefab::HasConnectorType(int a_ConnectorType) const +{ + for (cConnectors::const_iterator itr = m_Connectors.begin(), end = m_Connectors.end(); itr != end; ++itr) + { + if (itr->m_Type == a_ConnectorType) + { + return true; + } + } // for itr - m_Connectors[] + return false; +} + + + + + +void cPrefab::ParseCharMap(CharMap & a_CharMapOut, const char * a_CharMapDef) +{ + ASSERT(a_CharMapDef != NULL); + + // Initialize the charmap to all-invalid values: + for (size_t i = 0; i < ARRAYCOUNT(a_CharMapOut); i++) + { + a_CharMapOut[i].m_BlockType = 0; + a_CharMapOut[i].m_BlockMeta = 16; // Mark unassigned entries with a meta that is impossible otherwise + } + + // Process the lines in the definition: + AStringVector Lines = StringSplitAndTrim(a_CharMapDef, "\n"); + for (AStringVector::const_iterator itr = Lines.begin(), end = Lines.end(); itr != end; ++itr) + { + AStringVector CharDef = StringSplitAndTrim(*itr, ":"); + size_t NumElements = CharDef.size(); + if ((NumElements < 2) || CharDef[0].empty() || CharDef[1].empty()) + { + LOGWARNING("Bad prefab CharMap definition line: \"%s\", skipping.", itr->c_str()); + continue; + } + unsigned char Src = (unsigned char)CharDef[0][0]; + ASSERT(a_CharMapOut[Src].m_BlockMeta == 16); // This letter has not been assigned yet? + a_CharMapOut[Src].m_BlockType = (BLOCKTYPE)atoi(CharDef[1].c_str()); + NIBBLETYPE BlockMeta = 0; + if ((NumElements >= 3) && !CharDef[2].empty()) + { + BlockMeta = (NIBBLETYPE)atoi(CharDef[2].c_str()); + ASSERT((BlockMeta >= 0) && (BlockMeta <= 15)); + } + a_CharMapOut[Src].m_BlockMeta = BlockMeta; + } // for itr - Lines[] +} + + + + + +void cPrefab::ParseBlockImage(const CharMap & a_CharMap, const char * a_BlockImage) +{ + // Map each letter in the a_BlockImage (from the in-source definition) to real blocktype / blockmeta: + for (int y = 0; y < m_Size.y; y++) + { + for (int z = 0; z < m_Size.z; z++) + { + const unsigned char * BlockImage = (const unsigned char *)a_BlockImage + y * m_Size.x * m_Size.z + z * m_Size.x; + for (int x = 0; x < m_Size.x; x++) + { + const sBlockTypeDef & MappedValue = a_CharMap[BlockImage[x]]; + ASSERT(MappedValue.m_BlockMeta != 16); // Using a letter not defined in the CharMap? + m_BlockArea[0].SetRelBlockTypeMeta(x, y, z, MappedValue.m_BlockType, MappedValue.m_BlockMeta); + } + } + } +} + + + + + +void cPrefab::ParseConnectors(const char * a_ConnectorsDef) +{ + ASSERT(a_ConnectorsDef != NULL); + + AStringVector Lines = StringSplitAndTrim(a_ConnectorsDef, "\n"); + for (AStringVector::const_iterator itr = Lines.begin(), end = Lines.end(); itr != end; ++itr) + { + if (itr->empty()) + { + continue; + } + // Split into components: "Type: X, Y, Z: Face": + AStringVector Defs = StringSplitAndTrim(*itr, ":"); + if (Defs.size() != 3) + { + LOGWARNING("Bad prefab Connector definition line: \"%s\", skipping.", itr->c_str()); + continue; + } + AStringVector Coords = StringSplitAndTrim(Defs[1], ","); + if (Coords.size() != 3) + { + LOGWARNING("Bad prefab Connector coords definition: \"%s\", skipping.", Defs[1].c_str()); + continue; + } + + // Check that the BlockFace is within range: + int BlockFace = atoi(Defs[2].c_str()); + if ((BlockFace < 0) || (BlockFace >= 6)) + { + LOGWARNING("Bad prefab Connector Blockface: \"%s\", skipping.", Defs[2].c_str()); + continue; + } + + // Add the connector: + m_Connectors.push_back(cPiece::cConnector( + atoi(Coords[0].c_str()), atoi(Coords[1].c_str()), atoi(Coords[2].c_str()), // Connector pos + atoi(Defs[0].c_str()), // Connector type + (eBlockFace)BlockFace + )); + } // for itr - Lines[] +} + + + + + +cPiece::cConnectors cPrefab::GetConnectors(void) const +{ + return m_Connectors; +} + + + + + +Vector3i cPrefab::GetSize(void) const +{ + return m_Size; +} + + + + + +cCuboid cPrefab::GetHitBox(void) const +{ + return m_HitBox; +} + + + + + +bool cPrefab::CanRotateCCW(int a_NumRotations) const +{ + // Either zero rotations + // Or the proper bit in m_AllowedRotations is set + return (a_NumRotations == 0) || ((m_AllowedRotations & (1 << ((a_NumRotations + 3) % 4))) != 0); +} + + + + diff --git a/src/Generating/Prefab.h b/src/Generating/Prefab.h new file mode 100644 index 000000000..04c4f09da --- /dev/null +++ b/src/Generating/Prefab.h @@ -0,0 +1,105 @@ + +// Prefab.h + +/* +Declares the cPrefab class, representing a cPiece descendant for the cPieceGenerator that +uses a prefabricate in a cBlockArea for drawing itself. +The class can be constructed from data that is stored directly in the executable, in a sPrefabDef structure +declared in this file as well; the Gallery server exports areas in this format. +*/ + + + + + +#pragma once + +#include "PieceGenerator.h" +#include "../BlockArea.h" + + + + + +// fwd: +class cChunkDesc; + + + + + +class cPrefab : + public cPiece +{ +public: + struct sDef + { + int m_SizeX; + int m_SizeY; + int m_SizeZ; + const char * m_CharMap; + const char * m_Image; + const char * m_Connectors; + int m_AllowedRotations; + cBlockArea::eMergeStrategy m_MergeStrategy; + }; + + cPrefab(const sDef & a_Def); + + /** Draws the prefab into the specified chunk, according to the placement stored in the PlacedPiece. */ + void Draw(cChunkDesc & a_Dest, const cPlacedPiece * a_Placement) const; + + /** Returns true if the prefab has any connector of the specified type. */ + bool HasConnectorType(int a_ConnectorType) const; + +protected: + /** Packs complete definition of a single block, for per-letter assignment. */ + struct sBlockTypeDef + { + BLOCKTYPE m_BlockType; + NIBBLETYPE m_BlockMeta; + }; + + /** Maps letters in the sDef::m_Image onto a number, BlockType * 16 | BlockMeta */ + typedef sBlockTypeDef CharMap[256]; + + + /** The cBlockArea that contains the block definitions for the prefab. + The index identifies the number of CCW rotations applied (0 = no rotation, 1 = 1 CCW rotation, ...). */ + cBlockArea m_BlockArea[4]; + + /** The size of the prefab */ + Vector3i m_Size; + + /** The hitbox of the prefab. In first version is the same as the m_BlockArea dimensions */ + cCuboid m_HitBox; + + /** The connectors through which the piece connects to other pieces */ + cConnectors m_Connectors; + + /** Bitmask, bit N set -> N rotations CCW supported */ + int m_AllowedRotations; + + /** The merge strategy to use when drawing the prefab into a block area */ + cBlockArea::eMergeStrategy m_MergeStrategy; + + + // cPiece overrides: + virtual cConnectors GetConnectors(void) const override; + virtual Vector3i GetSize(void) const override; + virtual cCuboid GetHitBox(void) const override; + virtual bool CanRotateCCW(int a_NumRotations) const override; + + /** Parses the CharMap in the definition into a CharMap binary data used for translating the definition into BlockArea. */ + void ParseCharMap(CharMap & a_CharMapOut, const char * a_CharMapDef); + + /** Parses the Image in the definition into m_BlockArea[0]'s block types and metas, using the specified CharMap. */ + void ParseBlockImage(const CharMap & a_CharMap, const char * a_BlockImage); + + /** Parses the connectors definition text into m_Connectors member. */ + void ParseConnectors(const char * a_ConnectorsDef); +}; + + + + diff --git a/src/Generating/Prefabs/CMakeLists.txt b/src/Generating/Prefabs/CMakeLists.txt new file mode 100644 index 000000000..1e60447e7 --- /dev/null +++ b/src/Generating/Prefabs/CMakeLists.txt @@ -0,0 +1,13 @@ + +cmake_minimum_required (VERSION 2.6) +project (MCServer) + +include_directories ("${PROJECT_SOURCE_DIR}/../../") + +file(GLOB SOURCE + "*.cpp" +) + +add_library(Generating_Prefabs ${SOURCE}) + +target_link_libraries(Generating_Prefabs OSSupport iniFile Blocks) diff --git a/src/Generating/Prefabs/NetherFortPrefabs.cpp b/src/Generating/Prefabs/NetherFortPrefabs.cpp new file mode 100644 index 000000000..5e8685e32 --- /dev/null +++ b/src/Generating/Prefabs/NetherFortPrefabs.cpp @@ -0,0 +1,2758 @@ + +// NetherFortPrefabs.cpp + +// Defines all the prefabs for nether forts + +#include "Globals.h" +#include "NetherFortPrefabs.h" + + + + + +/* +The nether fortress has two types of connectors, Outer and Inner. Outer is Type 0, Inner is Type 1. +*/ + + + + + +const cPrefab::sDef g_NetherFortPrefabs1[] = +{ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // BalconyCorridor: + // The data has been exported from gallery Nether, area index 37, ID 288 + { + // Size: + 13, 7, 9, // SizeX = 13, SizeY = 7, SizeZ = 9 + + // Block definitions: + "a:112: 0\n" /* netherbrick */ + "b: 19: 0\n" /* sponge */ + "c:114: 4\n" /* netherbrickstairs */ + "d:114: 7\n" /* netherbrickstairs */ + "e:114: 5\n" /* netherbrickstairs */ + "f: 44: 6\n" /* step */ + "g:113: 0\n" /* netherbrickfence */ + "h:114: 2\n" /* netherbrickstairs */ + "i:114: 3\n" /* netherbrickstairs */ + "j:114: 0\n" /* netherbrickstairs */ + "k:114: 1\n" /* netherbrickstairs */ + ".: 0: 0\n" /* air */, + + // Block data: + // Level 1 + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "bbbbaaaaabbbb" + "bbbbbbbbbbbbb" + "bbbbbbbbbbbbb" + "bbbbbbbbbbbbb" + + // Level 2 + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "aaaa.aaa.aaaa" + "bbcdaaaaadebb" + "bbbcdddddebbb" + "bbbbbbbbbbbbb" + "bbbbbbbbbbbbb" + + // Level 3 + "aaaaaaaaaaaaa" + "............." + "............." + "............." + "aaaa.fff.aaaa" + "bbaaaaaaaaabb" + "bbaaaaaaaaabb" + "bbaaaaaaaaabb" + "bbaaaaaaaaabb" + + // Level 4 + "agagagagagaga" + "............." + "............." + "............." + "agaa.....aaga" + "bbaaa...aaabb" + "bbg.......gbb" + "bbg.......gbb" + "bbgggggggggbb" + + // Level 5 + "agagagagagaga" + "............." + "............." + "............." + "agaa.....aaga" + "bbaaa...aaabb" + "bb.........bb" + "bb.........bb" + "bb.........bb" + + // Level 6 + "agagagagagaga" + "............." + "............." + "............." + "agaa.....aaga" + "bbaaa...aaabb" + "bb.........bb" + "bb.........bb" + "bb.........bb" + + // Level 7 + "hhhhhhhhhhhhh" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "iijaaaaaaaiii" + "bbjiiiiiiikbb" + "bbbbbbbbbbbbb" + "bbbbbbbbbbbbb" + "bbbbbbbbbbbbb", + + // Connections: + "1: 0, 2, 2: 4\n" /* Type 1, BLOCK_FACE_XM */ + "1: 12, 2, 2: 5\n" /* Type 1, BLOCK_FACE_XP */, + + // AllowedRotations: + 7, /* 1, 2, 3 CCW rotations */ + + // Merge strategy: + cBlockArea::msSpongePrint, + }, // BalconyCorridor + + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // BalconyTee2: + // The data has been exported from gallery Nether, area index 38, ID 289 + { + // Size: + 13, 7, 11, // SizeX = 13, SizeY = 7, SizeZ = 11 + + // Block definitions: + "a: 19: 0\n" /* sponge */ + "b:112: 0\n" /* netherbrick */ + "c:114: 4\n" /* netherbrickstairs */ + "d:114: 7\n" /* netherbrickstairs */ + "e:114: 5\n" /* netherbrickstairs */ + "f: 44: 6\n" /* step */ + "g:113: 0\n" /* netherbrickfence */ + "h:114: 0\n" /* netherbrickstairs */ + "i:114: 1\n" /* netherbrickstairs */ + "j:114: 2\n" /* netherbrickstairs */ + "k:114: 3\n" /* netherbrickstairs */ + ".: 0: 0\n" /* air */, + + // Block data: + // Level 1 + "aaaabbbbbaaaa" + "aaaabbbbbaaaa" + "bbbbbbbbbbbbb" + "bbbbbbbbbbbbb" + "bbbbbbbbbbbbb" + "bbbbbbbbbbbbb" + "bbbbbbbbbbbbb" + "aaaabbbbbaaaa" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + + // Level 2 + "aaaabbbbbaaaa" + "aaaabbbbbaaaa" + "bbbbbbbbbbbbb" + "bbbbbbbbbbbbb" + "bbbbbbbbbbbbb" + "bbbbbbbbbbbbb" + "bbbb.bbb.bbbb" + "aacdbbbbbdeaa" + "aaacdddddeaaa" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + + // Level 3 + "aaaab...baaaa" + "aaaab...baaaa" + "bbbbb...bbbbb" + "............." + "............." + "............." + "bbbb.fff.bbbb" + "aabbbbbbbbbaa" + "aabbbbbbbbbaa" + "aabbbbbbbbbaa" + "aabbbbbbbbbaa" + + // Level 4 + "aaaab...baaaa" + "aaaag...gaaaa" + "bgbgb...bgbgb" + "............." + "............." + "............." + "bgbb.....bbgb" + "aabbb...bbbaa" + "aag.......gaa" + "aag.......gaa" + "aagggggggggaa" + + // Level 5 + "aaaab...baaaa" + "aaaag...gaaaa" + "bgbgb...bgbgb" + "............." + "............." + "............." + "bgbb.....bbgb" + "aabbb...bbbaa" + "aa.........aa" + "aa.........aa" + "aa.........aa" + + // Level 6 + "aaaab...baaaa" + "aaaag...gaaaa" + "bgbgb...bgbgb" + "............." + "............." + "............." + "bgbb.....bbgb" + "aabbb...bbbaa" + "aa.........aa" + "aa.........aa" + "aa.........aa" + + // Level 7 + "aaaahbbbiaaaa" + "aaaahbbbiaaaa" + "jjjjjbbbjjjjj" + "bbbbbbbbbbbbb" + "bbbbbbbbbbbbb" + "bbbbbbbbbbbbb" + "kkhbbbbbbbkkk" + "aahkkkkkkkiaa" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa", + + // Connections: + "1: 0, 2, 4: 4\n" /* Type 1, BLOCK_FACE_XM */ + "1: 12, 2, 4: 5\n" /* Type 1, BLOCK_FACE_XP */ + "1: 6, 2, 0: 2\n" /* Type 1, BLOCK_FACE_ZM */, + + // AllowedRotations: + 7, /* 1, 2, 3 CCW rotations */ + + // Merge strategy: + cBlockArea::msSpongePrint, + }, // BalconyTee2 + + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // BlazePlatform + // The data has been exported from gallery Nether, area index 26, ID 276 + { + // Size: + 10, 7, 7, // SizeX = 10, SizeY = 7, SizeZ = 7 + + // Block definitions: + ".: 0: 0\n" /* air */ + "a:112: 0\n" /* netherbrick */ + "b: 52: 0\n" /* mobspawner */ + "c:113: 0\n" /* netherbrickfence */, + + // Block data: + // Level 1 + ".........." + "aaaaaaaaaa" + "aaaaaaaaaa" + "aaaaaaaaaa" + "aaaaaaaaaa" + "aaaaaaaaaa" + ".........." + + // Level 2 + ".........." + "aaaaaaaaaa" + "..aaaaaaaa" + "..aaaaaaaa" + "..aaaaaaaa" + "aaaaaaaaaa" + ".........." + + // Level 3 + "....aaaaaa" + "aaaaaaaaaa" + "...aaaaaaa" + "...aaaaaaa" + "...aaaaaaa" + "aaaaaaaaaa" + "....aaaaaa" + + // Level 4 + "....aaaaaa" + "..aaa....a" + ".........a" + "......b..a" + ".........a" + "..aaa....a" + "....aaaaaa" + + // Level 5 + "....cccccc" + "...cc....c" + ".........c" + ".........c" + ".........c" + "...cc....c" + "....cccccc" + + // Level 6 + ".........." + ".........c" + ".........c" + ".........c" + ".........c" + ".........c" + ".........." + + // Level 7 + ".........." + ".........." + ".........c" + ".........c" + ".........c" + ".........." + "..........", + + // Connections: + "0: 0, 1, 3: 4\n" /* Type 0, BLOCK_FACE_XM */, + + // AllowedRotations: + 7, /* 1, 2, 3 CCW rotations */ + + // Merge strategy: + cBlockArea::msSpongePrint, + }, // BlazePlatform + + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // BlazePlatformOverhang: + // The data has been exported from gallery Nether, area index 20, ID 162 + { + // Size: + 14, 9, 7, // SizeX = 14, SizeY = 9, SizeZ = 7 + + // Block definitions: + ".: 0: 0\n" /* air */ + "a:112: 0\n" /* netherbrick */ + "b:114: 5\n" /* netherbrickstairs */ + "c: 44:14\n" /* step */ + "d:114: 6\n" /* netherbrickstairs */ + "e:114: 7\n" /* netherbrickstairs */ + "f:114: 0\n" /* netherbrickstairs */ + "g:114: 4\n" /* netherbrickstairs */ + "h:113: 0\n" /* netherbrickfence */ + "i: 52: 0\n" /* mobspawner */ + "m: 19: 0\n" /* sponge */, + + // Block data: + // Level 1 + "mmmmmmmmmmmmmm" + "mmmmmmmmmmmmmm" + "aammmmmmmmmmmm" + "aammmmmmmmmmmm" + "aammmmmmmmmmmm" + "mmmmmmmmmmmmmm" + "mmmmmmmmmmmmmm" + + // Level 2 + "mmmmmmmmmmmmmm" + "mmmmmmmmmmmmmm" + "aabcmmmmmmmmmm" + "aabcmmmmmmmmmm" + "aabcmmmmmmmmmm" + "mmmmmmmmmmmmmm" + "mmmmmmmmmmmmmm" + + // Level 3 + "mmmmmmmmmmmmmm" + "mmmmmmmmmmmmmm" + "aaaaabmmmmmmmm" + "aaaaabmmmmmmmm" + "aaaaabmmmmmmmm" + "mmmmmmmmmmmmmm" + "mmmmmmmmmmmmmm" + + // Level 4 + "mmmmmmmmmmmmmm" + "dddddddmmmmmmm" + "aaaaaabmmmmmmm" + "aaaaaabmmmmmmm" + "aaaaaabmmmmmmm" + "eeeeeeemmmmmmm" + "mmmmmmmmmmmmmm" + + // Level 5 + "mmmmmmmmmmmmmm" + "aaaaaaadmmmmmm" + "aaaaaaabmmmmmm" + "aaaaaaabmmmmmm" + "aaaaaaabmmmmmm" + "aaaaaaaemmmmmm" + "mmmmmmmmmmmmmm" + + // Level 6 + "mmmmmmmmmmmmmm" + "aaaaaaaabddddm" + "......faaaaabm" + "......faaaaabm" + "......faaaaabm" + "aaaaaaaaabeebm" + "mmmmmmmmmmmmmm" + + // Level 7 + "mmmmmmmmgdddbm" + "......aaaaaaad" + ".......faaaaab" + ".......faaaaab" + ".......faaaaab" + "......aaaaaaae" + "mmmmmmmmgeeebm" + + // Level 8 + "mmmmmmmmaaaaam" + "......haa...aa" + ".............a" + "..........i..a" + ".............a" + "......haa...aa" + "mmmmmmmmaaaaam" + + // Level 9 + "mmmmmmmmhhhhhm" + "......hhh...hh" + ".............h" + ".............h" + ".............h" + "......hhh...hh" + "mmmmmmmmhhhhhm", + + // Connections: + "0: 0, 5, 3: 4\n" /* Type 0, BLOCK_FACE_XM */, + + // AllowedRotations: + 7, /* 1, 2, 3 CCW rotations */ + + // Merge strategy: + cBlockArea::msSpongePrint, + }, // BlazePlatformOverhang + + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // BridgeCrossing: + // The data has been exported from gallery Nether, area index 17, ID 159 + { + // Size: + 15, 8, 15, // SizeX = 15, SizeY = 8, SizeZ = 15 + + // Block definitions: + ".: 0: 0\n" /* air */ + "a:112: 0\n" /* netherbrick */ + "b:114: 7\n" /* netherbrickstairs */ + "c:114: 5\n" /* netherbrickstairs */ + "d:114: 4\n" /* netherbrickstairs */ + "e:114: 6\n" /* netherbrickstairs */ + "f: 44:14\n" /* step */ + "m: 19: 0\n" /* sponge */, + + // Block data: + // Level 1 + "mmmmmmaaammmmmm" + "mmmmmmaaammmmmm" + "mmmmmmmmmmmmmmm" + "mmmmmmmmmmmmmmm" + "mmmmmmmmmmmmmmm" + "mmmmmmmmmmmmmmm" + "aammmmmmmmmmmaa" + "aammmmmmmmmmmaa" + "aammmmmmmmmmmaa" + "mmmmmmmmmmmmmmm" + "mmmmmmmmmmmmmmm" + "mmmmmmmmmmmmmmm" + "mmmmmmmmmmmmmmm" + "mmmmmmaaammmmmm" + "mmmmmmaaammmmmm" + + // Level 2 + "mmmmmmaaammmmmm" + "mmmmmmaaammmmmm" + "mmmmmmbbbmmmmmm" + "mmmmmmmmmmmmmmm" + "mmmmmmmmmmmmmmm" + "mmmmmmmmmmmmmmm" + "aacmmmmmmmmmdaa" + "aacmmmmmmmmmdaa" + "aacmmmmmmmmmdaa" + "mmmmmmmmmmmmmmm" + "mmmmmmmmmmmmmmm" + "mmmmmmmmmmmmmmm" + "mmmmmmeeemmmmmm" + "mmmmmmaaammmmmm" + "mmmmmmaaammmmmm" + + // Level 3 + "mmmmmmaaammmmmm" + "mmmmmmaaammmmmm" + "mmmmmmaaammmmmm" + "mmmmmmbbbmmmmmm" + "mmmmmmfffmmmmmm" + "mmmmmmmmmmmmmmm" + "aaacfmmmmmfdaaa" + "aaacfmmmmmfdaaa" + "aaacfmmmmmfdaaa" + "mmmmmmmmmmmmmmm" + "mmmmmmfffmmmmmm" + "mmmmmmeeemmmmmm" + "mmmmmmaaammmmmm" + "mmmmmmaaammmmmm" + "mmmmmmaaammmmmm" + + // Level 4 + "mmmmmdaaacmmmmm" + "mmmmmdaaacmmmmm" + "mmmmmdaaacmmmmm" + "mmmmmdaaacmmmmm" + "mmmmmdaaacmmmmm" + "eeeeeeaaaeeeeee" + "aaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaa" + "bbbbbdaaacbbbbb" + "mmmmmdaaacmmmmm" + "mmmmmdaaacmmmmm" + "mmmmmdaaacmmmmm" + "mmmmmdaaacmmmmm" + "mmmmmdaaacmmmmm" + + // Level 5 + "mmmmmaaaaammmmm" + "mmmmmaaaaammmmm" + "mmmmmaaaaammmmm" + "mmmmmaaaaammmmm" + "mmmmmaaaaammmmm" + "aaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaa" + "mmmmmaaaaammmmm" + "mmmmmaaaaammmmm" + "mmmmmaaaaammmmm" + "mmmmmaaaaammmmm" + "mmmmmaaaaammmmm" + + // Level 6 + "mmmmma...ammmmm" + "mmmmma...ammmmm" + "mmmmma...ammmmm" + "mmmmma...ammmmm" + "mmmmma...ammmmm" + "aaaaaa...aaaaaa" + "..............." + "..............." + "..............." + "aaaaaa...aaaaaa" + "mmmmma...ammmmm" + "mmmmma...ammmmm" + "mmmmma...ammmmm" + "mmmmma...ammmmm" + "mmmmma...ammmmm" + + // Level 7 + "mmmmmm...mmmmmm" + "mmmmmm...mmmmmm" + "mmmmmm...mmmmmm" + "mmmmmm...mmmmmm" + "mmmmmm...mmmmmm" + "mmmmmm...mmmmmm" + "..............." + "..............." + "..............." + "mmmmmm...mmmmmm" + "mmmmmm...mmmmmm" + "mmmmmm...mmmmmm" + "mmmmmm...mmmmmm" + "mmmmmm...mmmmmm" + "mmmmmm...mmmmmm" + + // Level 8 + "mmmmmm...mmmmmm" + "mmmmmm...mmmmmm" + "mmmmmm...mmmmmm" + "mmmmmm...mmmmmm" + "mmmmmm...mmmmmm" + "mmmmmm...mmmmmm" + "..............." + "..............." + "..............." + "mmmmmm...mmmmmm" + "mmmmmm...mmmmmm" + "mmmmmm...mmmmmm" + "mmmmmm...mmmmmm" + "mmmmmm...mmmmmm" + "mmmmmm...mmmmmm", + + // Connections: + "0: 0, 5, 7: 4\n" /* Type 0, BLOCK_FACE_XM */ + "0: 7, 5, 0: 2\n" /* Type 0, BLOCK_FACE_ZM */ + "0: 14, 5, 7: 5\n" /* Type 0, BLOCK_FACE_XP */ + "0: 7, 5, 14: 3\n" /* Type 0, BLOCK_FACE_ZP */, + + // AllowedRotations: + 7, /* 1, 2, 3 CCW rotations */ + + // Merge strategy: + cBlockArea::msSpongePrint, + }, // BridgeCrossing + + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // BridgeCrumble1: + // The data has been exported from gallery Nether, area index 19, ID 161 + { + // Size: + 9, 6, 5, // SizeX = 9, SizeY = 6, SizeZ = 5 + + // Block definitions: + ".: 19: 0\n" /* sponge */ + "a:112: 0\n" /* netherbrick */ + "b:114: 5\n" /* netherbrickstairs */ + "c: 44:14\n" /* step */ + "d:114: 6\n" /* netherbrickstairs */ + "e:114: 7\n" /* netherbrickstairs */, + + // Block data: + // Level 1 + "........." + "aa......." + "aa......." + "aa......." + "........." + + // Level 2 + "........." + "aab......" + "aab......" + "aab......" + "........." + + // Level 3 + "........." + "aaabc...." + "aaabc...." + "aaabc...." + "........." + + // Level 4 + "ddddddd.." + "aaaaaaaa." + "aaaaaaaaa" + "aaaaaaa.." + "eeeee...." + + // Level 5 + "aaaaaaaaa" + "aaaaa...." + "aaaaaa..." + "aaaaaa..." + "aaaaaaaa." + + // Level 6 + "aaaaaa..." + "........." + "........." + "........." + "aaaaaaa..", + + // Connections: + "0: 0, 5, 2: 4\n" /* Type 0, BLOCK_FACE_XM */, + + // AllowedRotations: + 7, /* 1, 2, 3 CCW rotations */ + + // Merge strategy: + cBlockArea::msSpongePrint, + }, // BridgeCrumble1 + + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // BridgeCrumble2 + // The data has been exported from gallery Nether, area index 18, ID 160 + { + // Size: + 13, 6, 5, // SizeX = 13, SizeY = 6, SizeZ = 5 + + // Block definitions: + ".: 19: 0\n" /* sponge */ + "a:112: 0\n" /* netherbrick */ + "b:114: 5\n" /* netherbrickstairs */ + "c: 44:14\n" /* step */ + "d:114: 6\n" /* netherbrickstairs */ + "e:114: 7\n" /* netherbrickstairs */, + + // Block data: + // Level 1 + "............." + "aa..........." + "aa..........." + "aa..........." + "............." + + // Level 2 + "............." + "aab.........." + "aab.........." + "aab.........." + "............." + + // Level 3 + "............." + "aaabc........" + "aaabc........" + "aaabc........" + "............." + + // Level 4 + "ddddddddd...." + "aaaaaaaaaaaaa" + "aaaaaaaaa...." + "aaaaaaaaaaaa." + "eeeeeeeee...." + + // Level 5 + "aaaaaaaaaaaa." + "aaaaaaaaaa..." + "aaaaaaaaaaa.." + "aaaaaaaaa...." + "aaaaaaaaaaaaa" + + // Level 6 + "aaaaaaaaa...." + "............." + "............." + "............." + "aaaaaaaaaa...", + + // Connections: + "0: 0, 5, 2: 4\n" /* Type 0, BLOCK_FACE_XM */, + + // AllowedRotations: + 7, /* 1, 2, 3 CCW rotations */ + + // Merge strategy: + cBlockArea::msSpongePrint, + }, // BridgeCrumble2 + + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // BridgeSegment: + // The data has been exported from gallery Nether, area index 16, ID 158 + { + // Size: + 15, 8, 5, // SizeX = 15, SizeY = 8, SizeZ = 5 + + // Block definitions: + ".: 0: 0\n" /* air */ + "a:112: 0\n" /* netherbrick */ + "b:114: 5\n" /* netherbrickstairs */ + "c:114: 4\n" /* netherbrickstairs */ + "d: 44:14\n" /* step */ + "e:114: 6\n" /* netherbrickstairs */ + "f:114: 7\n" /* netherbrickstairs */ + "m: 19: 0\n" /* sponge */, + + // Block data: + // Level 1 + "mmmmmmmmmmmmmmm" + "aammmmmmmmmmmaa" + "aammmmmmmmmmmaa" + "aammmmmmmmmmmaa" + "mmmmmmmmmmmmmmm" + + // Level 2 + "mmmmmmmmmmmmmmm" + "aabmmmmmmmmmcaa" + "aabmmmmmmmmmcaa" + "aabmmmmmmmmmcaa" + "mmmmmmmmmmmmmmm" + + // Level 3 + "mmmmmmmmmmmmmmm" + "aaabdmmmmmdcaaa" + "aaabdmmmmmdcaaa" + "aaabdmmmmmdcaaa" + "mmmmmmmmmmmmmmm" + + // Level 4 + "eeeeeeeeeeeeeee" + "aaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaa" + "fffffffffffffff" + + // Level 5 + "aaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaa" + + // Level 6 + "aaaaaaaaaaaaaaa" + "..............." + "..............." + "..............." + "aaaaaaaaaaaaaaa" + + // Level 7 + "mmmmmmmmmmmmmmm" + "..............." + "..............." + "..............." + "mmmmmmmmmmmmmmm" + + // Level 8 + "mmmmmmmmmmmmmmm" + "..............." + "..............." + "..............." + "mmmmmmmmmmmmmmm", + + // Connections: + "0: 0, 5, 2: 4\n" /* Type 0, BLOCK_FACE_XM */ + "0: 14, 5, 2: 5\n" /* Type 0, BLOCK_FACE_XP */, + + // AllowedRotations: + 7, /* 1, 2, 3 CCW rotations */ + + // Merge strategy: + cBlockArea::msSpongePrint, + }, // BridgeSegment + + + // BridgeTee: + // The data has been exported from gallery Nether, area index 39, ID 290 + { + // Size: + 15, 8, 10, // SizeX = 15, SizeY = 8, SizeZ = 10 + + // Block definitions: + ".: 0: 0\n" /* air */ + "a:112: 0\n" /* netherbrick */ + "b:114: 5\n" /* netherbrickstairs */ + "c:114: 4\n" /* netherbrickstairs */ + "d:114: 6\n" /* netherbrickstairs */ + "e: 44:14\n" /* step */ + "f:114: 7\n" /* netherbrickstairs */ + "m: 19: 0\n" /* sponge */, + + // Block data: + // Level 1 + "mmmmmmmmmmmmmmm" + "aammmmmmmmmmmaa" + "aammmmmmmmmmmaa" + "aammmmmmmmmmmaa" + "mmmmmmmmmmmmmmm" + "mmmmmmmmmmmmmmm" + "mmmmmmmmmmmmmmm" + "mmmmmmmmmmmmmmm" + "mmmmmmaaammmmmm" + "mmmmmmaaammmmmm" + + // Level 2 + "mmmmmmmmmmmmmmm" + "aabmmmmmmmmmcaa" + "aabmmmmmmmmmcaa" + "aabmmmmmmmmmcaa" + "mmmmmmmmmmmmmmm" + "mmmmmmmmmmmmmmm" + "mmmmmmmmmmmmmmm" + "mmmmmmdddmmmmmm" + "mmmmmmaaammmmmm" + "mmmmmmaaammmmmm" + + // Level 3 + "mmmmmmmmmmmmmmm" + "aaabemmmmmecaaa" + "aaabemmmmmecaaa" + "aaabemmmmmecaaa" + "mmmmmmmmmmmmmmm" + "mmmmmmeeemmmmmm" + "mmmmmmdddmmmmmm" + "mmmmmmaaammmmmm" + "mmmmmmaaammmmmm" + "mmmmmmaaammmmmm" + + // Level 4 + "ddddddddddddddd" + "aaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaa" + "fffffcaaabfffff" + "mmmmmcaaabmmmmm" + "mmmmmcaaabmmmmm" + "mmmmmcaaabmmmmm" + "mmmmmcaaabmmmmm" + "mmmmmcaaabmmmmm" + + // Level 5 + "aaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaa" + "mmmmmaaaaammmmm" + "mmmmmaaaaammmmm" + "mmmmmaaaaammmmm" + "mmmmmaaaaammmmm" + "mmmmmaaaaammmmm" + + // Level 6 + "aaaaaaaaaaaaaaa" + "..............." + "..............." + "..............." + "aaaaaa...aaaaaa" + "mmmmma...ammmmm" + "mmmmma...ammmmm" + "mmmmma...ammmmm" + "mmmmma...ammmmm" + "mmmmma...ammmmm" + + // Level 7 + "mmmmmmmmmmmmmmm" + "..............." + "..............." + "..............." + "mmmmmm...mmmmmm" + "mmmmmm...mmmmmm" + "mmmmmm...mmmmmm" + "mmmmmm...mmmmmm" + "mmmmmm...mmmmmm" + "mmmmmm...mmmmmm" + + // Level 8 + "mmmmmmmmmmmmmmm" + "..............." + "..............." + "..............." + "mmmmmm...mmmmmm" + "mmmmmm...mmmmmm" + "mmmmmm...mmmmmm" + "mmmmmm...mmmmmm" + "mmmmmm...mmmmmm" + "mmmmmm...mmmmmm", + + // Connections: + "0: 0, 5, 2: 4\n" /* Type 0, BLOCK_FACE_XM */ + "0: 14, 5, 2: 5\n" /* Type 0, BLOCK_FACE_XP */ + "0: 7, 5, 9: 3\n" /* Type 0, BLOCK_FACE_ZP */, + + // AllowedRotations: + 7, /* 1, 2, 3 CCW rotations */ + + // Merge strategy: + cBlockArea::msSpongePrint, + }, // BridgeTee + + + // Corridor11: + // The data has been exported from gallery Nether, area index 36, ID 287 + { + // Size: + 11, 6, 5, // SizeX = 11, SizeY = 6, SizeZ = 5 + + // Block definitions: + ".: 0: 0\n" /* air */ + "a:112: 0\n" /* netherbrick */ + "b:113: 0\n" /* netherbrickfence */ + "c:114: 2\n" /* netherbrickstairs */ + "d:114: 3\n" /* netherbrickstairs */, + + // Block data: + // Level 1 + "aaaaaaaaaaa" + "aaaaaaaaaaa" + "aaaaaaaaaaa" + "aaaaaaaaaaa" + "aaaaaaaaaaa" + + // Level 2 + "aaaaaaaaaaa" + "..........." + "..........." + "..........." + "aaaaaaaaaaa" + + // Level 3 + "abababababa" + "..........." + "..........." + "..........." + "abababababa" + + // Level 4 + "abababababa" + "..........." + "..........." + "..........." + "abababababa" + + // Level 5 + "abababababa" + "..........." + "..........." + "..........." + "abababababa" + + // Level 6 + "ccccccccccc" + "aaaaaaaaaaa" + "aaaaaaaaaaa" + "aaaaaaaaaaa" + "ddddddddddd", + + // Connections: + "1: 0, 1, 2: 4\n" /* Type 1, BLOCK_FACE_XM */ + "1: 10, 1, 2: 5\n" /* Type 1, BLOCK_FACE_XP */, + + // AllowedRotations: + 7, /* 1, 2, 3 CCW rotations */ + + // Merge strategy: + cBlockArea::msSpongePrint, + }, // Corridor11 + + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // Corridor13: + // The data has been exported from gallery Nether, area index 35, ID 286 + { + // Size: + 13, 6, 5, // SizeX = 13, SizeY = 6, SizeZ = 5 + + // Block definitions: + "a:112: 0\n" /* netherbrick */ + ".: 0: 0\n" /* air */ + "c:113: 0\n" /* netherbrickfence */ + "d:114: 2\n" /* netherbrickstairs */ + "e:114: 3\n" /* netherbrickstairs */, + + // Block data: + // Level 1 + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + + // Level 2 + "aaaaaaaaaaaaa" + "............." + "............." + "............." + "aaaaaaaaaaaaa" + + // Level 3 + "acacacacacaca" + "............." + "............." + "............." + "acacacacacaca" + + // Level 4 + "acacacacacaca" + "............." + "............." + "............." + "acacacacacaca" + + // Level 5 + "acacacacacaca" + "............." + "............." + "............." + "acacacacacaca" + + // Level 6 + "ddddddddddddd" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "eeeeeeeeeeeee", + + // Connections: + "1: 0, 1, 2: 4\n" /* Type 1, BLOCK_FACE_XM */ + "1: 12, 1, 2: 5\n" /* Type 1, BLOCK_FACE_XP */, + + // AllowedRotations: + 7, /* 1, 2, 3 CCW rotations */ + + // Merge strategy: + cBlockArea::msSpongePrint, + }, // Corridor13 + + + // CorridorCorner5: + // The data has been exported from gallery Nether, area index 10, ID 40 + { + // Size: + 11, 6, 11, // SizeX = 11, SizeY = 6, SizeZ = 11 + + // Block definitions: + ".: 0: 0\n" /* air */ + "a:112: 0\n" /* netherbrick */ + "b:113: 0\n" /* netherbrickfence */ + "c:114: 2\n" /* netherbrickstairs */ + "d:114: 0\n" /* netherbrickstairs */ + "e:114: 3\n" /* netherbrickstairs */ + "f:114: 1\n" /* netherbrickstairs */ + "m: 19: 0\n" /* sponge */, + + // Block data: + // Level 1 + "aaaaaaaaaaa" + "aaaaaaaaaaa" + "aaaaaaaaaaa" + "aaaaaaaaaaa" + "aaaaaaaaaaa" + "aaaaammmmmm" + "aaaaammmmmm" + "aaaaammmmmm" + "aaaaammmmmm" + "aaaaammmmmm" + "aaaaammmmmm" + + // Level 2 + "aaaaaaaaaaa" + "a.........." + "a.........." + "a.........." + "a...aaaaaaa" + "a...ammmmmm" + "a...ammmmmm" + "a...ammmmmm" + "a...ammmmmm" + "a...ammmmmm" + "a...ammmmmm" + + // Level 3 + "abababababa" + "b.........." + "a.........." + "b.........." + "a...abababa" + "b...bmmmmmm" + "a...ammmmmm" + "b...bmmmmmm" + "a...ammmmmm" + "b...bmmmmmm" + "a...ammmmmm" + + // Level 4 + "abababababa" + "b.........." + "a.........." + "b.........." + "a...abababa" + "b...bmmmmmm" + "a...ammmmmm" + "b...bmmmmmm" + "a...ammmmmm" + "b...bmmmmmm" + "a...ammmmmm" + + // Level 5 + "abababababa" + "b.........." + "a.........." + "b.........." + "a...abababa" + "b...bmmmmmm" + "a...ammmmmm" + "b...bmmmmmm" + "a...ammmmmm" + "b...bmmmmmm" + "a...ammmmmm" + + // Level 6 + "ccccccccccc" + "daaaaaaaaaa" + "daaaaaaaaaa" + "daaaaaaaaaa" + "daaaeeeeeee" + "daaafmmmmmm" + "daaafmmmmmm" + "daaafmmmmmm" + "daaafmmmmmm" + "daaafmmmmmm" + "daaafmmmmmm", + + // Connections: + "1: 10, 1, 2: 5\n" /* Type 1, BLOCK_FACE_XP */ + "1: 2, 1, 10: 3\n" /* Type 1, BLOCK_FACE_ZP */, + + // AllowedRotations: + 7, /* 1, 2, 3 CCW rotations */ + + // Merge strategy: + cBlockArea::msSpongePrint, + }, // CorridorCorner5 + + + // CorridorCorner5: + // The data has been exported from gallery Nether, area index 10, ID 40 + { + // Size: + 11, 6, 11, // SizeX = 11, SizeY = 6, SizeZ = 11 + + // Block definitions: + ".: 0: 0\n" /* air */ + "a:112: 0\n" /* netherbrick */ + "b:113: 0\n" /* netherbrickfence */ + "c:114: 2\n" /* netherbrickstairs */ + "d:114: 0\n" /* netherbrickstairs */ + "e:114: 3\n" /* netherbrickstairs */ + "f:114: 1\n" /* netherbrickstairs */ + "g: 54: 5\n" /* chest */ + "m: 19: 0\n" /* sponge */, + + // Block data: + // Level 1 + "aaaaaaaaaaa" + "aaaaaaaaaaa" + "aaaaaaaaaaa" + "aaaaaaaaaaa" + "aaaaaaaaaaa" + "aaaaammmmmm" + "aaaaammmmmm" + "aaaaammmmmm" + "aaaaammmmmm" + "aaaaammmmmm" + "aaaaammmmmm" + + // Level 2 + "aaaaaaaaaaa" + "ag........." + "a.........." + "a.........." + "a...aaaaaaa" + "a...ammmmmm" + "a...ammmmmm" + "a...ammmmmm" + "a...ammmmmm" + "a...ammmmmm" + "a...ammmmmm" + + // Level 3 + "abababababa" + "b.........." + "a.........." + "b.........." + "a...abababa" + "b...bmmmmmm" + "a...ammmmmm" + "b...bmmmmmm" + "a...ammmmmm" + "b...bmmmmmm" + "a...ammmmmm" + + // Level 4 + "abababababa" + "b.........." + "a.........." + "b.........." + "a...abababa" + "b...bmmmmmm" + "a...ammmmmm" + "b...bmmmmmm" + "a...ammmmmm" + "b...bmmmmmm" + "a...ammmmmm" + + // Level 5 + "abababababa" + "b.........." + "a.........." + "b.........." + "a...abababa" + "b...bmmmmmm" + "a...ammmmmm" + "b...bmmmmmm" + "a...ammmmmm" + "b...bmmmmmm" + "a...ammmmmm" + + // Level 6 + "ccccccccccc" + "daaaaaaaaaa" + "daaaaaaaaaa" + "daaaaaaaaaa" + "daaaeeeeeee" + "daaafmmmmmm" + "daaafmmmmmm" + "daaafmmmmmm" + "daaafmmmmmm" + "daaafmmmmmm" + "daaafmmmmmm", + + // Connections: + "1: 10, 1, 2: 5\n" /* Type 1, BLOCK_FACE_XP */ + "1: 2, 1, 10: 3\n" /* Type 1, BLOCK_FACE_ZP */, + + // AllowedRotations: + 7, /* 1, 2, 3 CCW rotations */ + + // Merge strategy: + cBlockArea::msSpongePrint, + }, // CorridorCorner5Chest + + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // CorridorStairs: + // The data has been exported from gallery Nether, area index 12, ID 42 + { + // Size: + 9, 13, 5, // SizeX = 9, SizeY = 13, SizeZ = 5 + + // Block definitions: + ".: 0: 0\n" /* air */ + "a:112: 0\n" /* netherbrick */ + "b:114: 0\n" /* netherbrickstairs */ + "c:113: 0\n" /* netherbrickfence */ + "d:114: 2\n" /* netherbrickstairs */ + "e:114: 3\n" /* netherbrickstairs */ + "f: 19: 0\n" /* sponge */, + + // Block data: + // Level 1 + "aaaaaaaaa" + "aaaaaaaaa" + "aaaaaaaaa" + "aaaaaaaaa" + "aaaaaaaaa" + + // Level 2 + "aaaaaaaaa" + ".baaaaaaa" + ".baaaaaaa" + ".baaaaaaa" + "aaaaaaaaa" + + // Level 3 + "acaaaaaaa" + "..baaaaaa" + "..baaaaaa" + "..baaaaaa" + "acaaaaaaa" + + // Level 4 + "acaaaaaaa" + "...baaaaa" + "...baaaaa" + "...baaaaa" + "acaaaaaaa" + + // Level 5 + "acacaaaaa" + "....baaaa" + "....baaaa" + "....baaaa" + "acacaaaaa" + + // Level 6 + "aaacaaaaa" + ".....baaa" + ".....baaa" + ".....baaa" + "aaacaaaaa" + + // Level 7 + "daacacaaa" + "a.....baa" + "a.....baa" + "a.....baa" + "eaacacaaa" + + // Level 8 + "fdaaacaaa" + "fa.....ba" + "fa.....ba" + "fa.....ba" + "feaaacaaa" + + // Level 9 + "ffdaacaca" + "ffa......" + "ffa......" + "ffa......" + "ffeaacaca" + + // Level 10 + "fffdaaaca" + "fffa....." + "fffa....." + "fffa....." + "fffeaaaca" + + // Level 11 + "ffffdaaca" + "ffffa...." + "ffffa...." + "ffffa...." + "ffffeaaca" + + // Level 12 + "fffffdaaa" + "fffffa..." + "fffffa..." + "fffffa..." + "fffffeaaa" + + // Level 13 + "ffffffddd" + "ffffffaaa" + "ffffffaaa" + "ffffffaaa" + "ffffffeee", + + // Connections: + "1: 0, 1, 2: 4\n" /* Type 1, BLOCK_FACE_XM */ + "1: 8, 8, 2: 5\n" /* Type 1, BLOCK_FACE_XP */, + + // AllowedRotations: + 7, /* 1, 2, 3 CCW rotations */ + + // Merge strategy: + cBlockArea::msSpongePrint, + }, // CorridorStairs + + + // LavaStaircase: + // The data has been exported from gallery Nether, area index 28, ID 278 + { + // Size: + 15, 11, 15, // SizeX = 15, SizeY = 11, SizeZ = 15 + + // Block definitions: + ".: 0: 0\n" /* air */ + "a:112: 0\n" /* netherbrick */ + "b:113: 0\n" /* netherbrickfence */ + "c: 11: 0\n" /* lava */, + + // Block data: + // Level 1 + "aaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaa" + + // Level 2 + "aaaaaaaa...aaaa" + "aaaaa.........a" + "aaaaa.........a" + "aaaaab........a" + "accca...aaaa..a" + "accca...acca..a" + "acccaaaaacca..a" + "acccccccccca..a" + "acccaaaaacca..a" + "accca...acca..a" + "accca...aaaa..a" + "aaaaab........a" + "aaaaa.........a" + "aaaaa.........a" + "aaaaaaaa...aaaa" + + // Level 3 + "aaaaaaaa...aaaa" + "aaaa..........a" + "aaaa..........a" + "aaaabb........a" + "aaaa..........a" + "a.............a" + "a.............a" + "a.............a" + "a.............a" + "a.............a" + "aaaa..........a" + "aaaabb........a" + "aaaa..........a" + "aaaa..........a" + "aaaaaaaa...aaaa" + + // Level 4 + "aaaaaaaa...aaaa" + "a.............a" + "a.............a" + "a..bb.........a" + "aaaa..........a" + "aaaa..........a" + "a.............a" + "a.............a" + "a.............a" + "aaaa..........a" + "aaaa..........a" + "a..bb.........a" + "a.............a" + "a.............a" + "aaaaaaaa...aaaa" + + // Level 5 + "aaaaaaaabbbaaaa" + "a.............a" + "a.............a" + "a..b..........a" + "a..b..........a" + "aaaa..........a" + "aaaa..........a" + "a.............a" + "aaaa..........a" + "aaaa..........a" + "a..b..........a" + "a..b..........a" + "a.............a" + "a.............a" + "aaaaaaaabbbaaaa" + + // Level 6 + "aaaaaaaaaaaaaaa" + "a.............a" + "a.............a" + "a.............a" + "a..b..........a" + "a..b..........a" + "aaaa..........a" + "aaaa..........a" + "aaaa..........a" + "a..b..........a" + "a..b..........a" + "a.............a" + "a.............a" + "a.............a" + "aaaaaaaaaaaaaaa" + + // Level 7 + "aaaaaaaaaaaaaaa" + "a.............a" + "a.............a" + "a.............a" + "a.............a" + "a..b..........a" + "...b..........a" + "...b..........a" + "...b..........a" + "a..b..........a" + "a.............a" + "a.............a" + "a.............a" + "a.............a" + "aaaaaaaaaaaaaaa" + + // Level 8 + "aababababababaa" + "a.............a" + "b.............b" + "a.............a" + "b.............b" + "a.............a" + "..............b" + "..............a" + "..............b" + "a.............a" + "b.............b" + "a.............a" + "b.............b" + "a.............a" + "aababababababaa" + + // Level 9 + "aababababababaa" + "a.............a" + "b.............b" + "a.............a" + "b.............b" + "a.............a" + "..............b" + "..............a" + "..............b" + "a.............a" + "b.............b" + "a.............a" + "b.............b" + "a.............a" + "aababababababaa" + + // Level 10 + "aababababababaa" + "a.............a" + "b.............b" + "a.............a" + "b.............b" + "a.............a" + "..............b" + "..............a" + "..............b" + "a.............a" + "b.............b" + "a.............a" + "b.............b" + "a.............a" + "aababababababaa" + + // Level 11 + "aaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaa", + + // Connections: + "1: 0, 6, 7: 4\n" /* Type 1, BLOCK_FACE_XM */ + "0: 9, 1, 0: 2\n" /* Type 0, BLOCK_FACE_ZM */ + "0: 9, 1, 14: 3\n" /* Type 0, BLOCK_FACE_ZP */, + + // AllowedRotations: + 7, /* 1, 2, 3 CCW rotations */ + + // Merge strategy: + cBlockArea::msSpongePrint, + }, // LavaStaircase + + + // LavaStaircaseBig: + // The data has been exported from gallery Nether, area index 31, ID 282 + { + // Size: + 12, 15, 15, // SizeX = 12, SizeY = 15, SizeZ = 15 + + // Block definitions: + ".: 0: 0\n" /* air */ + "a:112: 0\n" /* netherbrick */ + "b: 10: 0\n" /* lava */ + "c:113: 0\n" /* netherbrickfence */, + + // Block data: + // Level 1 + "aaaaaaaaaaaa" + "aaaaaaaaaaaa" + "aaaaaaaaaaaa" + "aaaaaaaaaaaa" + "aaaaaaaaaaaa" + "aaaaaaaaaaaa" + "aaaaaaaaaaaa" + "aaaaaaaaaaaa" + "aaaaaaaaaaaa" + "aaaaaaaaaaaa" + "aaaaaaaaaaaa" + "aaaaaaaaaaaa" + "aaaaaaaaaaaa" + "aaaaaaaaaaaa" + "aaaaaaaaaaaa" + + // Level 2 + "aaaaaaaaaaaa" + "aaaaaaaaaaaa" + "aaaaaaaaaaaa" + "aaaaaaaaaaaa" + "abbbbbaaaaaa" + "abbbbbbaaaaa" + "abbbbbba...." + "abbbbbba...." + "abbbbbba...." + "abbbbbbaaaaa" + "abbbbb.aaaaa" + "aaaaaaaaaaaa" + "aaaaaaaaaaaa" + "aaaaaaaaaaaa" + "aaaaaaaaaaaa" + + // Level 3 + "aaaaaaaaaaaa" + "aaaaaaaaaaaa" + "aaaaaaaaaaaa" + "aaaaaaaaaaaa" + "abbbbbaaaaaa" + "abbbbbba...a" + "abbbbbba...." + "abbbbbba...." + "abbbbbba...." + "abbbbbba...a" + "abbbbb.aaaaa" + "aaaaaaaaaaaa" + "aaaaaaaaaaaa" + "aaaaaaaaaaaa" + "aaaaaaaaaaaa" + + // Level 4 + "aaaaaaaaaaaa" + "aaaaaaaaaaaa" + "aaaaaaaaaaaa" + "aaaaaaaaaaaa" + "abbbbbaa...a" + "abbbbbba...a" + "abbbbbba...." + "abbbbbba...." + "abbbbbba...." + "abbbbbba...a" + "abbbbbaa...a" + "aaaaaaaaaaaa" + "aaaaaaaaaaaa" + "aaaaaaaaaaaa" + "aaaaaaaaaaaa" + + // Level 5 + "aaaaaaaaaaaa" + "aaaaa......a" + "aaaaa......a" + "aaaaacc....a" + "a.....cc...a" + "a......c...a" + "a......c...." + "a......c...." + "a......c...." + "a......c...a" + "a.....cc...a" + "aaaaacc....a" + "aaaaa......a" + "aaaaa......a" + "aaaaaaaaaaaa" + + // Level 6 + "aaaaaaaaaaaa" + "aaaa.......a" + "aaaa.......a" + "aaaacc.....a" + "aaaa.......a" + "a..........a" + "a..........a" + "a..........a" + "a..........a" + "a..........a" + "aaaa.......a" + "aaaacc.....a" + "aaaa.......a" + "aaaa.......a" + "aaaaaaaaaaaa" + + // Level 7 + "aaaaaaaaaaaa" + "a..........a" + "a..........a" + "a..cc......a" + "aaaa.......a" + "aaaa.......a" + "a..........a" + "a..........a" + "a..........a" + "aaaa.......a" + "aaaa.......a" + "a..cc......a" + "a..........a" + "a..........a" + "aaaaaaaaaaaa" + + // Level 8 + "aaaaaaaaaaaa" + "a..........a" + "a..........a" + "a..c.......a" + "a..c.......a" + "aaaa.......a" + "aaaa.......a" + "a..........a" + "aaaa.......a" + "aaaa.......a" + "a..c.......a" + "a..c.......a" + "a..........a" + "a..........a" + "aaaaaaaaaaaa" + + // Level 9 + "aaaaaaaaaaaa" + "a..........a" + "a..........a" + "a..........a" + "a..c.......a" + "a..c.......a" + "aaaa.......a" + "aaaa.......a" + "aaaa.......a" + "a..c.......a" + "a..c.......a" + "a..........a" + "a..........a" + "a..........a" + "aaaaaaaaaaaa" + + // Level 10 + "aaaaaaaaaaaa" + "a..........a" + "a..........a" + "a..........a" + "a..........a" + "a..c.......a" + "...c.......a" + "...c.......a" + "...c.......a" + "a..c.......a" + "a..........a" + "a..........a" + "a..........a" + "a..........a" + "aaaaaaaaaaaa" + + // Level 11 + "aaaaaaaaaaaa" + "a..........a" + "a..........a" + "a..........a" + "a..........a" + "a..........a" + "...........a" + "...........a" + "...........a" + "a..........a" + "a..........a" + "a..........a" + "a..........a" + "a..........a" + "aaaaaaaaaaaa" + + // Level 12 + "aaaaaaaaaaaa" + "a..........a" + "a..........a" + "a..........a" + "a..........a" + "a..........a" + "...........a" + "...........a" + "...........a" + "a..........a" + "a..........a" + "a..........a" + "a..........a" + "a..........a" + "aaaaaaaaaaaa" + + // Level 13 + "aaaaaaaaaaaa" + "a..........a" + "a..........a" + "a..........a" + "a..........a" + "a..........a" + "...........a" + "...........a" + "...........a" + "a..........a" + "a..........a" + "a..........a" + "a..........a" + "a..........a" + "aaaaaaaaaaaa" + + // Level 14 + "aaaaaaaaaaaa" + "aaaaaaaaaaaa" + "aaaaaaaaaaaa" + "aaaaaaaaaaaa" + "aaaaaaaaaaaa" + "aaaaaaaaaaaa" + "aaaaaaaaaaaa" + "aaaaaaaaaaaa" + "aaaaaaaaaaaa" + "aaaaaaaaaaaa" + "aaaaaaaaaaaa" + "aaaaaaaaaaaa" + "aaaaaaaaaaaa" + "aaaaaaaaaaaa" + "aaaaaaaaaaaa" + + // Level 15 + "aaaaaaaaaaaa" + "abbbbbbbbbba" + "abbbbbbbbbba" + "abbbbbbbbbba" + "abbbbbbbbbba" + "abbbbbbbbbba" + "abbbbbbbbbba" + "abbbbbbbbbba" + "abbbbbbbbbba" + "abbbbbbbbbba" + "abbbbbbbbbba" + "abbbbbbbbbba" + "abbbbbbbbbba" + "abbbbbbbbbba" + "aaaaaaaaaaaa", + + // Connections: + "1: 0, 9, 7: 4\n" /* Type 1, BLOCK_FACE_XM */ + "1: 11, 1, 7: 5\n" /* Type 1, BLOCK_FACE_XP */, + + // AllowedRotations: + 7, /* 1, 2, 3 CCW rotations */ + + // Merge strategy: + cBlockArea::msSpongePrint, + }, // LavaStaircaseBig + + + // MidStaircase: + // The data has been exported from gallery Nether, area index 23, ID 165 + { + // Size: + 13, 8, 13, // SizeX = 13, SizeY = 8, SizeZ = 13 + + // Block definitions: + ".: 0: 0\n" /* air */ + "a:112: 0\n" /* netherbrick */ + "b: 88: 0\n" /* soulsand */ + "c:115: 7\n" /* netherwartblock */ + "d:114: 3\n" /* netherbrickstairs */ + "e:114: 0\n" /* netherbrickstairs */ + "f:114: 1\n" /* netherbrickstairs */ + "g:114: 2\n" /* netherbrickstairs */ + "h: 10: 0\n" /* lava */ + "i:113: 0\n" /* netherbrickfence */, + + // Block data: + // Level 1 + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "aaaabbbbbaaaa" + "aaaabbbbbaaaa" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "aaaabbbbbaaaa" + "aaaabbbbbaaaa" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + + // Level 2 + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "aaaacccccaaaa" + "addecccccfdda" + "...eaaaaad..." + "...eaaaaa...." + "...eaaaaag..." + "agggcccccfgga" + "aaaacccccaaaa" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + + // Level 3 + "aaaaaaaaaaaaa" + "aha.......aha" + "aaa.......aaa" + "a...........a" + "a...........a" + "....eaaaa...." + "....eaaaa...." + "....eaaaa...." + "a...........a" + "a...........a" + "aaa.......aaa" + "aha.......aha" + "aaaaaaaaaaaaa" + + // Level 4 + "aaaiiaaaiiaaa" + "a...........a" + "a...........a" + "a...........a" + "a...........a" + ".....eaaa...." + ".....eaaa...." + ".....eaaa...." + "a...........a" + "a...........a" + "a...........a" + "a...........a" + "aaaiiaaaiiaaa" + + // Level 5 + "aaaiiaaaiiaaa" + "a...........a" + "a...........a" + "a...........a" + "a...........a" + "......eaa...." + "......eaa...." + "......eaa...." + "a...........a" + "a...........a" + "a...........a" + "a...........a" + "aaaiiaaaiiaaa" + + // Level 6 + "aaaaaaaaaaaaa" + "a...........a" + "a...........a" + "a...........a" + "a...........a" + "a......ea...a" + "a......ea...a" + "a......ea...a" + "a...........a" + "a...........a" + "a...........a" + "a...........a" + "aaaaaaaaaaaaa" + + // Level 7 + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "aaaa....eaaaa" + "aaaa....eaaaa" + "aaaa....eaaaa" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + + // Level 8 + "iaiaiaiaiaiai" + "a...........a" + "i...........i" + "a...........a" + "i...........i" + "a............" + "i............" + "a............" + "i...........i" + "a...........a" + "i...........i" + "a...........a" + "iaiaiaiaiaiai", + + // Connections: + "1: 0, 1, 6: 4\n" /* Type 1, BLOCK_FACE_XM */ + "1: 12, 1, 6: 5\n" /* Type 1, BLOCK_FACE_XP */ + "1: 12, 7, 6: 5\n" /* Type 1, BLOCK_FACE_XP */, + + // AllowedRotations: + 7, /* 1, 2, 3 CCW rotations */ + + // Merge strategy: + cBlockArea::msSpongePrint, + }, // MidStaircase + + + // StairsToOpen1: + // The data has been exported from gallery Nether, area index 27, ID 277 + { + // Size: + 7, 10, 7, // SizeX = 7, SizeY = 10, SizeZ = 7 + + // Block definitions: + ".: 0: 0\n" /* air */ + "a:112: 0\n" /* netherbrick */ + "b:113: 0\n" /* netherbrickfence */ + "m: 19: 0\n" /* sponge */, + + // Block data: + // Level 1 + "aaaaaaa" + "aaaaaaa" + "aaaaaaa" + "aaaaaaa" + "aaaaaaa" + "aaaaaaa" + "aaaaaaa" + + // Level 2 + "aa...aa" + "a.....a" + "a.....a" + "a.....a" + "a.....a" + "aaaaaaa" + "aaaaaaa" + + // Level 3 + "aa...aa" + "a.....a" + "b.....b" + "a.....a" + "b.....b" + "a.aaaaa" + "aabaaba" + + // Level 4 + "aa...aa" + "a.....a" + "b.....b" + "a.....a" + "b.....b" + "a..aaaa" + "aabaaba" + + // Level 5 + "aabbbaa" + "a.....a" + "b.....b" + "a.....a" + "b.....b" + "a...aaa" + "aabaaba" + + // Level 6 + "aaaaaaa" + "a.....a" + "a.....a" + "a.....a" + "a.....a" + "a....aa" + "aaaaaaa" + + // Level 7 + "aaaaaaa" + "aaaaaaa" + "aaaaaaa" + "aaaaaaa" + "aaaaaaa" + "a.....a" + "aaaaaaa" + + // Level 8 + "aaaaaaa" + "a.....a" + "a......" + "a......" + "a......" + "a.....a" + "aaaaaaa" + + // Level 9 + "mmmmmmm" + "m.....m" + "m......" + "m......" + "m......" + "m.....m" + "mmmmmmm" + + // Level 10 + "mmmmmmm" + "m.....m" + "m......" + "m......" + "m......" + "m.....m" + "mmmmmmm", + + // Connections: + "0: 3, 1, 0: 2\n" /* Type 0, BLOCK_FACE_ZM */ + "0: 6, 7, 3: 5\n" /* Type 0, BLOCK_FACE_XP */, + + // AllowedRotations: + 7, /* 1, 2, 3 CCW rotations */ + + // Merge strategy: + cBlockArea::msSpongePrint, + }, // StairsToOpen1 + + + // StairsToOpen2: + // The data has been exported from gallery Nether, area index 8, ID 35 + { + // Size: + 7, 10, 7, // SizeX = 7, SizeY = 10, SizeZ = 7 + + // Block definitions: + ".: 0: 0\n" /* air */ + "a:112: 0\n" /* netherbrick */ + "b:113: 0\n" /* netherbrickfence */ + "m: 19: 0\n" /* sponge */, + + // Block data: + // Level 1 + "aaaaaaa" + "aaaaaaa" + "aaaaaaa" + "aaaaaaa" + "aaaaaaa" + "aaaaaaa" + "aaaaaaa" + + // Level 2 + "aa...aa" + "a.....a" + "a.....a" + "a.....a" + "a.....a" + "aaaaaaa" + "aaaaaaa" + + // Level 3 + "aa...aa" + "a.....a" + "b.....b" + "a.....a" + "b.....b" + "a.aaaaa" + "aabaaba" + + // Level 4 + "aa...aa" + "a.....a" + "b.....b" + "a.....a" + "b.....b" + "a..aaaa" + "aabaaba" + + // Level 5 + "aabbbaa" + "a.....a" + "b.....b" + "a.....a" + "b.....b" + "a...aaa" + "aabaaba" + + // Level 6 + "aaaaaaa" + "a.....a" + "a.....a" + "a.....a" + "a.....a" + "a....aa" + "aaaaaaa" + + // Level 7 + "aaaaaaa" + "aaaaaaa" + "aaaaaaa" + "aaaaaaa" + "aaaaaaa" + "a.....a" + "aaaaaaa" + + // Level 8 + "aaaaaaa" + "a.....a" + "......a" + "......a" + "......a" + "a.....a" + "aaaaaaa" + + // Level 9 + "mmmmmmm" + "m.....m" + "......m" + "......m" + "......m" + "m.....m" + "mmmmmmm" + + // Level 10 + "mmmmmmm" + "m.....m" + "......m" + "......m" + "......m" + "m.....m" + "mmmmmmm", + + // Connections: + "0: 3, 1, 0: 2\n" /* Type 0, BLOCK_FACE_ZM */ + "0: 0, 7, 3: 4\n" /* Type 0, BLOCK_FACE_XM */, + + // AllowedRotations: + 7, /* 1, 2, 3 CCW rotations */ + + // Merge strategy: + cBlockArea::msSpongePrint, + }, // StairsToOpen2 + + + // Tee2x4: + // The data has been exported from gallery Nether, area index 40, ID 291 + { + // Size: + 13, 6, 7, // SizeX = 13, SizeY = 6, SizeZ = 7 + + // Block definitions: + ".: 0: 0\n" /* air */ + "a:112: 0\n" /* netherbrick */ + "b:113: 0\n" /* netherbrickfence */ + "c:114: 0\n" /* netherbrickstairs */ + "d:114: 1\n" /* netherbrickstairs */ + "e:114: 2\n" /* netherbrickstairs */ + "f:114: 3\n" /* netherbrickstairs */ + "m: 19: 0\n" /* sponge */, + + // Block data: + // Level 1 + "mmmmaaaaammmm" + "mmmmaaaaammmm" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + + // Level 2 + "mmmma...ammmm" + "mmmma...ammmm" + "aaaaa...aaaaa" + "............." + "............." + "............." + "aaaaaaaaaaaaa" + + // Level 3 + "mmmma...ammmm" + "mmmmb...bmmmm" + "ababa...ababa" + "............." + "............." + "............." + "ababababababa" + + // Level 4 + "mmmma...ammmm" + "mmmmb...bmmmm" + "ababa...ababa" + "............." + "............." + "............." + "ababababababa" + + // Level 5 + "mmmma...ammmm" + "mmmmb...bmmmm" + "ababa...ababa" + "............." + "............." + "............." + "ababababababa" + + // Level 6 + "mmmmcaaadmmmm" + "mmmmcaaadmmmm" + "eeeecaaadeeee" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "fffffffffffff", + + // Connections: + "1: 0, 1, 4: 4\n" /* Type 1, BLOCK_FACE_XM */ + "1: 6, 1, 0: 2\n" /* Type 1, BLOCK_FACE_ZM */ + "1: 12, 1, 4: 5\n" /* Type 1, BLOCK_FACE_XP */, + + // AllowedRotations: + 7, /* 1, 2, 3 CCW rotations */ + + // Merge strategy: + cBlockArea::msSpongePrint, + }, // Tee2x4 + + + // Tee4x4: + // The data has been exported from gallery Nether, area index 41, ID 292 + { + // Size: + 13, 6, 9, // SizeX = 13, SizeY = 6, SizeZ = 9 + + // Block definitions: + ".: 0: 0\n" /* air */ + "a:112: 0\n" /* netherbrick */ + "b:113: 0\n" /* netherbrickfence */ + "c:114: 0\n" /* netherbrickstairs */ + "d:114: 1\n" /* netherbrickstairs */ + "e:114: 2\n" /* netherbrickstairs */ + "f:114: 3\n" /* netherbrickstairs */ + "m: 19: 0\n" /* sponge */, + + // Block data: + // Level 1 + "mmmmaaaaammmm" + "mmmmaaaaammmm" + "mmmmaaaaammmm" + "mmmmaaaaammmm" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + + // Level 2 + "mmmma...ammmm" + "mmmma...ammmm" + "mmmma...ammmm" + "mmmma...ammmm" + "aaaaa...aaaaa" + "............." + "............." + "............." + "aaaaaaaaaaaaa" + + // Level 3 + "mmmma...ammmm" + "mmmmb...bmmmm" + "mmmma...ammmm" + "mmmmb...bmmmm" + "ababa...ababa" + "............." + "............." + "............." + "ababababababa" + + // Level 4 + "mmmma...ammmm" + "mmmmb...bmmmm" + "mmmma...ammmm" + "mmmmb...bmmmm" + "ababa...ababa" + "............." + "............." + "............." + "ababababababa" + + // Level 5 + "mmmma...ammmm" + "mmmmb...bmmmm" + "mmmma...ammmm" + "mmmmb...bmmmm" + "ababa...ababa" + "............." + "............." + "............." + "ababababababa" + + // Level 6 + "mmmmcaaadmmmm" + "mmmmcaaadmmmm" + "mmmmcaaadmmmm" + "mmmmcaaadmmmm" + "eeeecaaadeeee" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "fffffffffffff", + + // Connections: + "1: 0, 1, 6: 4\n" /* Type 1, BLOCK_FACE_XM */ + "1: 12, 1, 6: 5\n" /* Type 1, BLOCK_FACE_XP */ + "1: 6, 1, 0: 2\n" /* Type 1, BLOCK_FACE_ZM */, + + // AllowedRotations: + 7, /* 1, 2, 3 CCW rotations */ + + // Merge strategy: + cBlockArea::msSpongePrint, + }, // Tee4x4 + + // Turret: + // The data has been exported from gallery Nether, area index 7, ID 34 + { + // Size: + 7, 6, 7, // SizeX = 7, SizeY = 6, SizeZ = 7 + + // Block definitions: + ".: 0: 0\n" /* air */ + "a:112: 0\n" /* netherbrick */ + "b:113: 0\n" /* netherbrickfence */, + + // Block data: + // Level 1 + "aaaaaaa" + "aaaaaaa" + "aaaaaaa" + "aaaaaaa" + "aaaaaaa" + "aaaaaaa" + "aaaaaaa" + + // Level 2 + "aa...aa" + "a.....a" + "......." + "......." + "......." + "a.....a" + "aa...aa" + + // Level 3 + "aa...aa" + "a.....a" + "......." + "......." + "......." + "a.....a" + "aa...aa" + + // Level 4 + "aa...aa" + "a.....a" + "......." + "......." + "......." + "a.....a" + "aa...aa" + + // Level 5 + "aabbbaa" + "a.....a" + "b.....b" + "b.....b" + "b.....b" + "a.....a" + "aabbbaa" + + // Level 6 + "aaaaaaa" + "a.....a" + "a.....a" + "a.....a" + "a.....a" + "a.....a" + "aaaaaaa", + + // Connections: + "0: 0, 1, 3: 4\n" /* Type 0, BLOCK_FACE_XM */ + "0: 3, 1, 0: 2\n" /* Type 0, BLOCK_FACE_ZM */ + "0: 6, 1, 3: 5\n" /* Type 0, BLOCK_FACE_XP */ + "0: 3, 1, 6: 3\n" /* Type 0, BLOCK_FACE_ZP */, + + // AllowedRotations: + 7, /* 1, 2, 3 CCW rotations */ + + // Merge strategy: + cBlockArea::msSpongePrint, + }, // Turret + +} ; // g_NetherFortPrefabs1 + + + + + +const cPrefab::sDef g_NetherFortStartingPrefabs1[] = +{ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // CentralRoom: + // The data has been exported from gallery Nether, area index 22, ID 164 + { + // Size: + 13, 9, 13, // SizeX = 13, SizeY = 9, SizeZ = 13 + + // Block definitions: + "a:112: 0\n" /* netherbrick */ + "b: 0: 0\n" /* air */ + "c: 10: 0\n" /* lava */ + "d:113: 0\n" /* netherbrickfence */, + + // Block data: + // Level 1 + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + + // Level 2 + "aaaaabbbaaaaa" + "aaaaabbbaaaaa" + "aabbbbbbbbbaa" + "aabbbbbbbbbaa" + "aabbbbbbbbbaa" + "aabbbaaabbbaa" + "aabbbacabbbaa" + "aabbbaaabbbaa" + "aabbbbbbbbbaa" + "aabbbbbbbbbaa" + "aabbbbbbbbbaa" + "aaaaabbbaaaaa" + "aaaaabbbaaaaa" + + // Level 3 + "aaaaabbbaaaaa" + "aaadabbbadaaa" + "aabbbbbbbbbaa" + "adbbbbbbbbbda" + "aabbbbbbbbbaa" + "adbbbbbbbbbda" + "aabbbbbbbbbaa" + "adbbbbbbbbbda" + "aabbbbbbbbbaa" + "adbbbbbbbbbda" + "aabbbbbbbbbaa" + "aaadabbbadaaa" + "aaaaabbbaaaaa" + + // Level 4 + "aaaaabbbaaaaa" + "aaadabbbadaaa" + "aabbbbbbbbbaa" + "adbbbbbbbbbda" + "aabbbbbbbbbaa" + "adbbbbbbbbbda" + "aabbbbbbbbbaa" + "adbbbbbbbbbda" + "aabbbbbbbbbaa" + "adbbbbbbbbbda" + "aabbbbbbbbbaa" + "aaadabbbadaaa" + "aaaaabbbaaaaa" + + // Level 5 + "adadadddadada" + "daaaabbbaaaad" + "aabbbbbbbbbaa" + "dabbbbbbbbbad" + "aabbbbbbbbbaa" + "dabbbbbbbbbad" + "aabbbbbbbbbaa" + "dabbbbbbbbbad" + "aabbbbbbbbbaa" + "dabbbbbbbbbad" + "aabbbbbbbbbaa" + "daaaabbbaaaad" + "adadabbbadada" + + // Level 6 + "adadaaaaadada" + "daaaaaaaaaaad" + "aabbbbbbbbbaa" + "dabbbbbbbbbad" + "aabbbbbbbbbaa" + "dabbbbbbbbbad" + "aabbbbbbbbbaa" + "dabbbbbbbbbad" + "aabbbbbbbbbaa" + "dabbbbbbbbbad" + "aabbbbbbbbbaa" + "daaaaaaaaaaad" + "adadaaaaadada" + + // Level 7 + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + + // Level 8 + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + "aaaaaaaaaaaaa" + + // Level 9 + "dadadadadadad" + "abbbbbbbbbbba" + "dbbbbbbbbbbbd" + "abbbbbbbbbbba" + "dbbbbbbbbbbbd" + "abbbbbbbbbbba" + "dbbbbbbbbbbbd" + "abbbbbbbbbbba" + "dbbbbbbbbbbbd" + "abbbbbbbbbbba" + "dbbbbbbbbbbbd" + "abbbbbbbbbbba" + "dadadadadadad", + + // Connections: + "0: 6, 1, 0: 2\n" /* Type 0, BLOCK_FACE_ZM */ + "1: 6, 1, 12: 3\n" /* Type 1, BLOCK_FACE_ZP */, + + // AllowedRotations: + 7, /* 1, 2, 3 CCW rotations */ + + // Merge strategy: + cBlockArea::msSpongePrint, + }, +} ; // g_NetherFortStartingPrefabs1 + +const size_t g_NetherFortPrefabs1Count = ARRAYCOUNT(g_NetherFortPrefabs1); +const size_t g_NetherFortStartingPrefabs1Count = ARRAYCOUNT(g_NetherFortStartingPrefabs1); + + + + diff --git a/src/Generating/Prefabs/NetherFortPrefabs.h b/src/Generating/Prefabs/NetherFortPrefabs.h new file mode 100644 index 000000000..37a91689d --- /dev/null +++ b/src/Generating/Prefabs/NetherFortPrefabs.h @@ -0,0 +1,15 @@ + +// NetherFortPrefabs.h + +// Declares the data used for nether fortress prefabs + +#include "../Prefab.h" + + + + + +extern const cPrefab::sDef g_NetherFortPrefabs1[]; +extern const cPrefab::sDef g_NetherFortStartingPrefabs1[]; +extern const size_t g_NetherFortPrefabs1Count; +extern const size_t g_NetherFortStartingPrefabs1Count; diff --git a/src/Generating/Ravines.cpp b/src/Generating/Ravines.cpp index cfda47e32..e64f55214 100644 --- a/src/Generating/Ravines.cpp +++ b/src/Generating/Ravines.cpp @@ -117,7 +117,7 @@ void cStructGenRavines::ClearCache(void) -void cStructGenRavines::GenStructures(cChunkDesc & a_ChunkDesc) +void cStructGenRavines::GenFinish(cChunkDesc & a_ChunkDesc) { int ChunkX = a_ChunkDesc.GetChunkX(); int ChunkZ = a_ChunkDesc.GetChunkZ(); diff --git a/src/Generating/Ravines.h b/src/Generating/Ravines.h index 05164a5b2..c76b9f19f 100644 --- a/src/Generating/Ravines.h +++ b/src/Generating/Ravines.h @@ -17,7 +17,7 @@ class cStructGenRavines : - public cStructureGen + public cFinishGen { public: cStructGenRavines(int a_Seed, int a_Size); @@ -37,8 +37,8 @@ protected: /// Returns all ravines that *may* intersect the given chunk. All the ravines are valid until the next call to this function. void GetRavinesForChunk(int a_ChunkX, int a_ChunkZ, cRavines & a_Ravines); - // cStructureGen override: - virtual void GenStructures(cChunkDesc & a_ChunkDesc) override; + // cFinishGen override: + virtual void GenFinish(cChunkDesc & a_ChunkDesc) override; } ; diff --git a/src/Generating/StructGen.cpp b/src/Generating/StructGen.cpp index da6227801..db9d5578c 100644 --- a/src/Generating/StructGen.cpp +++ b/src/Generating/StructGen.cpp @@ -51,28 +51,10 @@ const int NEST_SIZE_GRAVEL = 32; -template <typename T> T Clamp(T a_Value, T a_Min, T a_Max) -{ - return (a_Value < a_Min) ? a_Min : ((a_Value > a_Max) ? a_Max : a_Value); -} - - - - - -static bool SortTreeBlocks(const sSetBlock & a_First, const sSetBlock & a_Second) -{ - return (a_First.BlockType == E_BLOCK_LOG) && (a_Second.BlockType != E_BLOCK_LOG); -} - - - - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // cStructGenTrees: -void cStructGenTrees::GenStructures(cChunkDesc & a_ChunkDesc) +void cStructGenTrees::GenFinish(cChunkDesc & a_ChunkDesc) { int ChunkX = a_ChunkDesc.GetChunkX(); int ChunkZ = a_ChunkDesc.GetChunkZ(); @@ -324,7 +306,7 @@ int cStructGenTrees::GetNumTrees( /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // cStructGenOreNests: -void cStructGenOreNests::GenStructures(cChunkDesc & a_ChunkDesc) +void cStructGenOreNests::GenFinish(cChunkDesc & a_ChunkDesc) { int ChunkX = a_ChunkDesc.GetChunkX(); int ChunkZ = a_ChunkDesc.GetChunkZ(); @@ -431,7 +413,7 @@ void cStructGenOreNests::GenerateOre(int a_ChunkX, int a_ChunkZ, BLOCKTYPE a_Ore /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // cStructGenLakes: -void cStructGenLakes::GenStructures(cChunkDesc & a_ChunkDesc) +void cStructGenLakes::GenFinish(cChunkDesc & a_ChunkDesc) { int ChunkX = a_ChunkDesc.GetChunkX(); int ChunkZ = a_ChunkDesc.GetChunkZ(); @@ -563,7 +545,7 @@ cStructGenDirectOverhangs::cStructGenDirectOverhangs(int a_Seed) : -void cStructGenDirectOverhangs::GenStructures(cChunkDesc & a_ChunkDesc) +void cStructGenDirectOverhangs::GenFinish(cChunkDesc & a_ChunkDesc) { // If there is no column of the wanted biome, bail out: if (!HasWantedBiome(a_ChunkDesc)) @@ -596,7 +578,7 @@ void cStructGenDirectOverhangs::GenStructures(cChunkDesc & a_ChunkDesc) m_Noise2.IntNoise3DInt(BaseX + INTERPOL_X * x, BaseY, BaseZ + INTERPOL_Z * z) / 256; } // for x, z - FloorLo[] - LinearUpscale2DArrayInPlace(FloorLo, 17, 17, INTERPOL_X, INTERPOL_Z); + LinearUpscale2DArrayInPlace<17, 17, INTERPOL_X, INTERPOL_Z>(FloorLo); // Interpolate segments: for (int Segment = BaseY; Segment < MaxHeight; Segment += SEGMENT_HEIGHT) @@ -609,7 +591,7 @@ void cStructGenDirectOverhangs::GenStructures(cChunkDesc & a_ChunkDesc) m_Noise2.IntNoise3DInt(BaseX + INTERPOL_Z * x, Segment + SEGMENT_HEIGHT, BaseZ + INTERPOL_Z * z) / 256; } // for x, z - FloorLo[] - LinearUpscale2DArrayInPlace(FloorHi, 17, 17, INTERPOL_X, INTERPOL_Z); + LinearUpscale2DArrayInPlace<17, 17, INTERPOL_X, INTERPOL_Z>(FloorHi); // Interpolate between FloorLo and FloorHi: for (int z = 0; z < 16; z++) for (int x = 0; x < 16; x++) @@ -683,7 +665,7 @@ cStructGenDistortedMembraneOverhangs::cStructGenDistortedMembraneOverhangs(int a -void cStructGenDistortedMembraneOverhangs::GenStructures(cChunkDesc & a_ChunkDesc) +void cStructGenDistortedMembraneOverhangs::GenFinish(cChunkDesc & a_ChunkDesc) { const NOISE_DATATYPE Frequency = (NOISE_DATATYPE)16; const NOISE_DATATYPE Amount = (NOISE_DATATYPE)1; diff --git a/src/Generating/StructGen.h b/src/Generating/StructGen.h index 853748bb8..9176bc192 100644 --- a/src/Generating/StructGen.h +++ b/src/Generating/StructGen.h @@ -21,7 +21,7 @@ class cStructGenTrees : - public cStructureGen + public cFinishGen { public: cStructGenTrees(int a_Seed, cBiomeGen * a_BiomeGen, cTerrainHeightGen * a_HeightGen, cTerrainCompositionGen * a_CompositionGen) : @@ -64,8 +64,8 @@ protected: const cChunkDef::BiomeMap & a_Biomes ); - // cStructureGen override: - virtual void GenStructures(cChunkDesc & a_ChunkDesc) override; + // cFinishGen override: + virtual void GenFinish(cChunkDesc & a_ChunkDesc) override; } ; @@ -73,7 +73,7 @@ protected: class cStructGenOreNests : - public cStructureGen + public cFinishGen { public: cStructGenOreNests(int a_Seed) : m_Noise(a_Seed), m_Seed(a_Seed) {} @@ -82,8 +82,8 @@ protected: cNoise m_Noise; int m_Seed; - // cStructureGen override: - virtual void GenStructures(cChunkDesc & a_ChunkDesc) override; + // cFinishGen override: + virtual void GenFinish(cChunkDesc & a_ChunkDesc) override; void GenerateOre(int a_ChunkX, int a_ChunkZ, BLOCKTYPE a_OreType, int a_MaxHeight, int a_NumNests, int a_NestSize, cChunkDef::BlockTypes & a_BlockTypes, int a_Seq); } ; @@ -93,7 +93,7 @@ protected: class cStructGenLakes : - public cStructureGen + public cFinishGen { public: cStructGenLakes(int a_Seed, BLOCKTYPE a_Fluid, cTerrainHeightGen & a_HeiGen, int a_Probability) : @@ -112,8 +112,8 @@ protected: cTerrainHeightGen & m_HeiGen; int m_Probability; ///< Chance, 0 .. 100, of a chunk having the lake - // cStructureGen override: - virtual void GenStructures(cChunkDesc & a_ChunkDesc) override; + // cFinishGen override: + virtual void GenFinish(cChunkDesc & a_ChunkDesc) override; /// Creates a lake image for the specified chunk into a_Lake void CreateLakeImage(int a_ChunkX, int a_ChunkZ, cBlockArea & a_Lake); @@ -125,7 +125,7 @@ protected: class cStructGenDirectOverhangs : - public cStructureGen + public cFinishGen { public: cStructGenDirectOverhangs(int a_Seed); @@ -134,8 +134,8 @@ protected: cNoise m_Noise1; cNoise m_Noise2; - // cStructureGen override: - virtual void GenStructures(cChunkDesc & a_ChunkDesc) override; + // cFinishGen override: + virtual void GenFinish(cChunkDesc & a_ChunkDesc) override; bool HasWantedBiome(cChunkDesc & a_ChunkDesc) const; } ; @@ -145,7 +145,7 @@ protected: class cStructGenDistortedMembraneOverhangs : - public cStructureGen + public cFinishGen { public: cStructGenDistortedMembraneOverhangs(int a_Seed); @@ -156,8 +156,8 @@ protected: cNoise m_NoiseZ; cNoise m_NoiseH; - // cStructureGen override: - virtual void GenStructures(cChunkDesc & a_ChunkDesc) override; + // cFinishGen override: + virtual void GenFinish(cChunkDesc & a_ChunkDesc) override; } ; diff --git a/src/Generating/Trees.cpp b/src/Generating/Trees.cpp index 7e8a3c75f..4909587b1 100644 --- a/src/Generating/Trees.cpp +++ b/src/Generating/Trees.cpp @@ -382,6 +382,24 @@ void GetBirchTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Nois +void GetAcaciaTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks) +{ + // TODO +} + + + + + +void GetDarkoakTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks) +{ + // TODO +} + + + + + void GetTallBirchTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks) { int Height = 9 + (a_Noise.IntNoise3DInt(a_BlockX + 64 * a_Seq, a_BlockY, a_BlockZ) % 3); @@ -577,7 +595,7 @@ void GetPineTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Noise { break; } - ASSERT(LayerSize < ARRAYCOUNT(BigOs)); + ASSERT((size_t)LayerSize < ARRAYCOUNT(BigOs)); PushCoordBlocks(a_BlockX, h, a_BlockZ, a_OtherBlocks, BigOs[LayerSize].Coords, BigOs[LayerSize].Count, E_BLOCK_LEAVES, E_META_LEAVES_CONIFER); h--; } diff --git a/src/Generating/Trees.h b/src/Generating/Trees.h index 514158eb7..00f343a3d 100644 --- a/src/Generating/Trees.h +++ b/src/Generating/Trees.h @@ -63,6 +63,12 @@ void GetLargeAppleTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a /// Generates an image of a random birch tree void GetBirchTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks); +/// Generates an image of a random acacia tree +void GetAcaciaTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks); + +/// Generates an image of a random darkoak tree +void GetDarkoakTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks); + /// Generates an image of a random large birch tree void GetTallBirchTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks,sSetBlockVector & a_OtherBlocks); |