diff options
Diffstat (limited to 'source/Generating/FinishGen.cpp')
-rw-r--r-- | source/Generating/FinishGen.cpp | 664 |
1 files changed, 0 insertions, 664 deletions
diff --git a/source/Generating/FinishGen.cpp b/source/Generating/FinishGen.cpp deleted file mode 100644 index 8899e4bd0..000000000 --- a/source/Generating/FinishGen.cpp +++ /dev/null @@ -1,664 +0,0 @@ - -// FinishGen.cpp - -/* Implements the various finishing generators: - - cFinishGenSnow - - cFinishGenIce - - cFinishGenSprinkleFoliage -*/ - -#include "Globals.h" - -#include "FinishGen.h" -#include "../Noise.h" -#include "../BlockID.h" -#include "../Simulator/FluidSimulator.h" // for cFluidSimulator::CanWashAway() -#include "../World.h" - - - - - -#define DEF_NETHER_WATER_SPRINGS "0, 1; 255, 1" -#define DEF_NETHER_LAVA_SPRINGS "0, 0; 30, 0; 31, 50; 120, 50; 127, 0" -#define DEF_OVERWORLD_WATER_SPRINGS "0, 0; 10, 10; 11, 75; 16, 83; 20, 83; 24, 78; 32, 62; 40, 40; 44, 15; 48, 7; 56, 2; 64, 1; 255, 0" -#define DEF_OVERWORLD_LAVA_SPRINGS "0, 0; 10, 5; 11, 45; 48, 2; 64, 1; 255, 0" -#define DEF_END_WATER_SPRINGS "0, 1; 255, 1" -#define DEF_END_LAVA_SPRINGS "0, 1; 255, 1" - - - - - -static inline bool IsWater(BLOCKTYPE a_BlockType) -{ - return (a_BlockType == E_BLOCK_STATIONARY_WATER) || (a_BlockType == E_BLOCK_WATER); -} - - - - - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// cFinishGenSprinkleFoliage: - -bool cFinishGenSprinkleFoliage::TryAddSugarcane(cChunkDesc & a_ChunkDesc, int a_RelX, int a_RelY, int a_RelZ) -{ - // We'll be doing comparison to neighbors, so require the coords to be 1 block away from the chunk edges: - if ( - (a_RelX < 1) || (a_RelX >= cChunkDef::Width - 1) || - (a_RelY < 1) || (a_RelY >= cChunkDef::Height - 2) || - (a_RelZ < 1) || (a_RelZ >= cChunkDef::Width - 1) - ) - { - return false; - } - - // Only allow dirt, grass or sand below sugarcane: - switch (a_ChunkDesc.GetBlockType(a_RelX, a_RelY, a_RelZ)) - { - case E_BLOCK_DIRT: - case E_BLOCK_GRASS: - case E_BLOCK_SAND: - { - break; - } - default: - { - return false; - } - } - - // Water is required next to the block below the sugarcane: - if ( - !IsWater(a_ChunkDesc.GetBlockType(a_RelX - 1, a_RelY, a_RelZ)) && - !IsWater(a_ChunkDesc.GetBlockType(a_RelX + 1, a_RelY, a_RelZ)) && - !IsWater(a_ChunkDesc.GetBlockType(a_RelX , a_RelY, a_RelZ - 1)) && - !IsWater(a_ChunkDesc.GetBlockType(a_RelX , a_RelY, a_RelZ + 1)) - ) - { - return false; - } - - // All conditions met, place a sugarcane here: - a_ChunkDesc.SetBlockType(a_RelX, a_RelY + 1, a_RelZ, E_BLOCK_SUGARCANE); - return true; -} - - - - - -void cFinishGenSprinkleFoliage::GenFinish(cChunkDesc & a_ChunkDesc) -{ - // Generate small foliage (1-block): - - // TODO: Update heightmap with 1-block-tall foliage - for (int z = 0; z < cChunkDef::Width; z++) - { - int BlockZ = a_ChunkDesc.GetChunkZ() * cChunkDef::Width + z; - const float zz = (float)BlockZ; - for (int x = 0; x < cChunkDef::Width; x++) - { - int BlockX = a_ChunkDesc.GetChunkX() * cChunkDef::Width + x; - if (((m_Noise.IntNoise2DInt(BlockX, BlockZ) / 8) % 128) < 124) - { - continue; - } - int Top = a_ChunkDesc.GetHeight(x, z); - if (Top > 250) - { - // Nothing grows above Y=250 - continue; - } - if (a_ChunkDesc.GetBlockType(x, Top + 1, z) != E_BLOCK_AIR) - { - // Space already taken by something else, don't grow here - // WEIRD, since we're using heightmap, so there should NOT be anything above it - continue; - } - - const float xx = (float)BlockX; - float val1 = m_Noise.CubicNoise2D(xx * 0.1f, zz * 0.1f ); - float val2 = m_Noise.CubicNoise2D(xx * 0.01f, zz * 0.01f ); - switch (a_ChunkDesc.GetBlockType(x, Top, z)) - { - case E_BLOCK_GRASS: - { - float val3 = m_Noise.CubicNoise2D(xx * 0.01f + 10, zz * 0.01f + 10 ); - float val4 = m_Noise.CubicNoise2D(xx * 0.05f + 20, zz * 0.05f + 20 ); - if (val1 + val2 > 0.2f) - { - a_ChunkDesc.SetBlockType(x, ++Top, z, E_BLOCK_YELLOW_FLOWER); - } - else if (val2 + val3 > 0.2f) - { - a_ChunkDesc.SetBlockType(x, ++Top, z, E_BLOCK_RED_ROSE); - } - else if (val3 + val4 > 0.2f) - { - a_ChunkDesc.SetBlockType(x, ++Top, z, E_BLOCK_RED_MUSHROOM); - } - else if (val1 + val4 > 0.2f) - { - a_ChunkDesc.SetBlockType(x, ++Top, z, E_BLOCK_BROWN_MUSHROOM); - } - else if (val1 + val2 + val3 + val4 < -0.1) - { - a_ChunkDesc.SetBlockTypeMeta(x, ++Top, z, E_BLOCK_TALL_GRASS, E_META_TALL_GRASS_GRASS); - } - else if (TryAddSugarcane(a_ChunkDesc, x, Top, z)) - { - ++Top; - } - else if ((val1 > 0.5) && (val2 < -0.5)) - { - a_ChunkDesc.SetBlockTypeMeta(x, ++Top, z, E_BLOCK_PUMPKIN, (int)(val3 * 8) % 4); - } - break; - } // case E_BLOCK_GRASS - - case E_BLOCK_SAND: - { - int y = Top + 1; - if ( - (x > 0) && (x < cChunkDef::Width - 1) && - (z > 0) && (z < cChunkDef::Width - 1) && - (val1 + val2 > 0.5f) && - (a_ChunkDesc.GetBlockType(x + 1, y, z) == E_BLOCK_AIR) && - (a_ChunkDesc.GetBlockType(x - 1, y, z) == E_BLOCK_AIR) && - (a_ChunkDesc.GetBlockType(x, y, z + 1) == E_BLOCK_AIR) && - (a_ChunkDesc.GetBlockType(x, y, z - 1) == E_BLOCK_AIR) - ) - { - a_ChunkDesc.SetBlockType(x, ++Top, z, E_BLOCK_CACTUS); - } - else if (TryAddSugarcane(a_ChunkDesc, x, Top, z)) - { - ++Top; - } - break; - } - } // switch (TopBlock) - a_ChunkDesc.SetHeight(x, z, Top); - } // for y - } // for z -} - - - - - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// cFinishGenSnow: - -void cFinishGenSnow::GenFinish(cChunkDesc & a_ChunkDesc) -{ - // Add a snow block in snowy biomes onto blocks that can be snowed over - for (int z = 0; z < cChunkDef::Width; z++) - { - for (int x = 0; x < cChunkDef::Width; x++) - { - switch (a_ChunkDesc.GetBiome(x, z)) - { - case biIcePlains: - case biIceMountains: - case biTaiga: - case biTaigaHills: - case biFrozenRiver: - case biFrozenOcean: - { - int Height = a_ChunkDesc.GetHeight(x, z); - if (g_BlockIsSnowable[a_ChunkDesc.GetBlockType(x, Height, z)]) - { - a_ChunkDesc.SetBlockType(x, Height + 1, z, E_BLOCK_SNOW); - a_ChunkDesc.SetHeight(x, z, Height + 1); - } - break; - } - } - } - } // for z -} - - - - - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// cFinishGenIce: - -void cFinishGenIce::GenFinish(cChunkDesc & a_ChunkDesc) -{ - // Turn surface water into ice in icy biomes - for (int z = 0; z < cChunkDef::Width; z++) - { - for (int x = 0; x < cChunkDef::Width; x++) - { - switch (a_ChunkDesc.GetBiome(x, z)) - { - case biIcePlains: - case biIceMountains: - case biTaiga: - case biTaigaHills: - case biFrozenRiver: - case biFrozenOcean: - { - int Height = a_ChunkDesc.GetHeight(x, z); - switch (a_ChunkDesc.GetBlockType(x, Height, z)) - { - case E_BLOCK_WATER: - case E_BLOCK_STATIONARY_WATER: - { - a_ChunkDesc.SetBlockType(x, Height, z, E_BLOCK_ICE); - break; - } - } - break; - } - } - } - } // for z -} - - - - - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// cFinishGenLilypads: - -int cFinishGenSingleBiomeSingleTopBlock::GetNumToGen(const cChunkDef::BiomeMap & a_BiomeMap) -{ - int res = 0; - for (int i = 0; i < ARRAYCOUNT(a_BiomeMap); i++) - { - if (a_BiomeMap[i] == m_Biome) - { - res++; - } - } // for i - a_BiomeMap[] - return m_Amount * res / 256; -} - - - - - -void cFinishGenSingleBiomeSingleTopBlock::GenFinish(cChunkDesc & a_ChunkDesc) -{ - // Add Lilypads on top of water surface in Swampland - - int NumToGen = GetNumToGen(a_ChunkDesc.GetBiomeMap()); - int ChunkX = a_ChunkDesc.GetChunkX(); - int ChunkZ = a_ChunkDesc.GetChunkZ(); - for (int i = 0; i < NumToGen; i++) - { - int x = (m_Noise.IntNoise3DInt(ChunkX + ChunkZ, ChunkZ, i) / 13) % cChunkDef::Width; - int z = (m_Noise.IntNoise3DInt(ChunkX - ChunkZ, i, ChunkZ) / 11) % cChunkDef::Width; - - // Place the block at {x, z} if possible: - if (a_ChunkDesc.GetBiome(x, z) != m_Biome) - { - // Incorrect biome - continue; - } - int Height = a_ChunkDesc.GetHeight(x, z); - if (Height >= cChunkDef::Height) - { - // Too high up - continue; - } - if (a_ChunkDesc.GetBlockType(x, Height + 1, z) != E_BLOCK_AIR) - { - // Not an empty block - continue; - } - BLOCKTYPE BlockBelow = a_ChunkDesc.GetBlockType(x, Height, z); - if ((BlockBelow == m_AllowedBelow1) || (BlockBelow == m_AllowedBelow2)) - { - a_ChunkDesc.SetBlockType(x, Height + 1, z, m_BlockType); - a_ChunkDesc.SetHeight(x, z, Height + 1); - } - } // for i -} - - - - - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// cFinishGenBottomLava: - -void cFinishGenBottomLava::GenFinish(cChunkDesc & a_ChunkDesc) -{ - cChunkDef::BlockTypes & BlockTypes = a_ChunkDesc.GetBlockTypes(); - for (int y = m_Level; y > 0; y--) - { - for (int z = 0; z < cChunkDef::Width; z++) for (int x = 0; x < cChunkDef::Width; x++) - { - int Index = cChunkDef::MakeIndexNoCheck(x, y, z); - if (BlockTypes[Index] == E_BLOCK_AIR) - { - BlockTypes[Index] = E_BLOCK_STATIONARY_LAVA; - } - } // for x, for z - } // for y -} - - - - - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// cFinishGenPreSimulator: - -cFinishGenPreSimulator::cFinishGenPreSimulator(void) -{ - // Nothing needed yet -} - - - - - -void cFinishGenPreSimulator::GenFinish(cChunkDesc & a_ChunkDesc) -{ - CollapseSandGravel(a_ChunkDesc.GetBlockTypes(), a_ChunkDesc.GetHeightMap()); - StationarizeFluid(a_ChunkDesc.GetBlockTypes(), a_ChunkDesc.GetHeightMap(), E_BLOCK_WATER, E_BLOCK_STATIONARY_WATER); - StationarizeFluid(a_ChunkDesc.GetBlockTypes(), a_ChunkDesc.GetHeightMap(), E_BLOCK_LAVA, E_BLOCK_STATIONARY_LAVA); - // TODO: other operations -} - - - - - -void cFinishGenPreSimulator::CollapseSandGravel( - cChunkDef::BlockTypes & a_BlockTypes, // Block types to read and change - cChunkDef::HeightMap & a_HeightMap // Height map to update by the current data -) -{ - for (int z = 0; z < cChunkDef::Width; z++) - { - for (int x = 0; x < cChunkDef::Width; x++) - { - int LastY = -1; - int HeightY = 0; - for (int y = 0; y < cChunkDef::Height; y++) - { - BLOCKTYPE Block = cChunkDef::GetBlock(a_BlockTypes, x, y, z); - switch (Block) - { - default: - { - // Set the last block onto which stuff can fall to this height: - LastY = y; - HeightY = y; - break; - } - case E_BLOCK_AIR: - { - // Do nothing - break; - } - case E_BLOCK_FIRE: - case E_BLOCK_WATER: - case E_BLOCK_STATIONARY_WATER: - case E_BLOCK_LAVA: - case E_BLOCK_STATIONARY_LAVA: - { - // Do nothing, only remember this height as potentially highest - HeightY = y; - break; - } - case E_BLOCK_SAND: - case E_BLOCK_GRAVEL: - { - if (LastY < y - 1) - { - cChunkDef::SetBlock(a_BlockTypes, x, LastY + 1, z, Block); - cChunkDef::SetBlock(a_BlockTypes, x, y, z, E_BLOCK_AIR); - } - LastY++; - if (LastY > HeightY) - { - HeightY = LastY; - } - break; - } - } // switch (GetBlock) - } // for y - cChunkDef::SetHeight(a_HeightMap, x, z, HeightY); - } // for x - } // for z -} - - - - - -void cFinishGenPreSimulator::StationarizeFluid( - cChunkDef::BlockTypes & a_BlockTypes, // Block types to read and change - cChunkDef::HeightMap & a_HeightMap, // Height map to read - BLOCKTYPE a_Fluid, - BLOCKTYPE a_StationaryFluid -) -{ - // Turn fluid in the middle to stationary, unless it has air or washable block next to it: - for (int z = 1; z < cChunkDef::Width - 1; z++) - { - for (int x = 1; x < cChunkDef::Width - 1; x++) - { - for (int y = cChunkDef::GetHeight(a_HeightMap, x, z); y >= 0; y--) - { - BLOCKTYPE Block = cChunkDef::GetBlock(a_BlockTypes, x, y, z); - if ((Block != a_Fluid) && (Block != a_StationaryFluid)) - { - continue; - } - static const struct - { - int x, y, z; - } Coords[] = - { - {1, 0, 0}, - {-1, 0, 0}, - {0, 0, 1}, - {0, 0, -1}, - {0, -1, 0} - } ; - BLOCKTYPE BlockToSet = a_StationaryFluid; // By default, don't simulate this block - for (int i = 0; i < ARRAYCOUNT(Coords); i++) - { - if ((y == 0) && (Coords[i].y < 0)) - { - continue; - } - BLOCKTYPE Neighbor = cChunkDef::GetBlock(a_BlockTypes, x + Coords[i].x, y + Coords[i].y, z + Coords[i].z); - if ((Neighbor == E_BLOCK_AIR) || cFluidSimulator::CanWashAway(Neighbor)) - { - // There is an air / washable neighbor, simulate this block - BlockToSet = a_Fluid; - break; - } - } // for i - Coords[] - cChunkDef::SetBlock(a_BlockTypes, x, y, z, BlockToSet); - } // for y - } // for x - } // for z - - // Turn fluid at the chunk edges into non-stationary fluid: - for (int y = 0; y < cChunkDef::Height; y++) - { - for (int i = 0; i < cChunkDef::Width; i++) // i stands for both x and z here - { - if (cChunkDef::GetBlock(a_BlockTypes, 0, y, i) == a_StationaryFluid) - { - cChunkDef::SetBlock(a_BlockTypes, 0, y, i, a_Fluid); - } - if (cChunkDef::GetBlock(a_BlockTypes, i, y, 0) == a_StationaryFluid) - { - cChunkDef::SetBlock(a_BlockTypes, i, y, 0, a_Fluid); - } - if (cChunkDef::GetBlock(a_BlockTypes, cChunkDef::Width - 1, y, i) == a_StationaryFluid) - { - cChunkDef::SetBlock(a_BlockTypes, cChunkDef::Width - 1, y, i, a_Fluid); - } - if (cChunkDef::GetBlock(a_BlockTypes, i, y, cChunkDef::Width - 1) == a_StationaryFluid) - { - cChunkDef::SetBlock(a_BlockTypes, i, y, cChunkDef::Width - 1, a_Fluid); - } - } - } -} - - - - - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// cFinishGenFluidSprings: - -cFinishGenFluidSprings::cFinishGenFluidSprings(int a_Seed, BLOCKTYPE a_Fluid, cIniFile & a_IniFile, const cWorld & a_World) : - m_Noise(a_Seed + a_Fluid * 100), // Need to take fluid into account, otherwise water and lava springs generate next to each other - m_HeightDistribution(255), - m_Fluid(a_Fluid) -{ - bool IsWater = (a_Fluid == E_BLOCK_WATER); - AString SectionName = IsWater ? "WaterSprings" : "LavaSprings"; - AString DefaultHeightDistribution; - int DefaultChance; - switch (a_World.GetDimension()) - { - case dimNether: - { - DefaultHeightDistribution = IsWater ? DEF_NETHER_WATER_SPRINGS : DEF_NETHER_LAVA_SPRINGS; - DefaultChance = IsWater ? 0 : 15; - break; - } - case dimOverworld: - { - DefaultHeightDistribution = IsWater ? DEF_OVERWORLD_WATER_SPRINGS : DEF_OVERWORLD_LAVA_SPRINGS; - DefaultChance = IsWater ? 24 : 9; - break; - } - case dimEnd: - { - DefaultHeightDistribution = IsWater ? DEF_END_WATER_SPRINGS : DEF_END_LAVA_SPRINGS; - DefaultChance = 0; - break; - } - default: - { - ASSERT(!"Unhandled world dimension"); - break; - } - } // switch (dimension) - AString HeightDistribution = a_IniFile.GetValueSet(SectionName, "HeightDistribution", DefaultHeightDistribution); - if (!m_HeightDistribution.SetDefString(HeightDistribution) || (m_HeightDistribution.GetSum() <= 0)) - { - LOGWARNING("[%sSprings]: HeightDistribution is invalid, using the default of \"%s\".", - (a_Fluid == E_BLOCK_WATER) ? "Water" : "Lava", - DefaultHeightDistribution.c_str() - ); - m_HeightDistribution.SetDefString(DefaultHeightDistribution); - } - m_Chance = a_IniFile.GetValueSetI(SectionName, "Chance", DefaultChance); -} - - - - - -void cFinishGenFluidSprings::GenFinish(cChunkDesc & a_ChunkDesc) -{ - int ChanceRnd = (m_Noise.IntNoise3DInt(128 * a_ChunkDesc.GetChunkX(), 512, 256 * a_ChunkDesc.GetChunkZ()) / 13) % 100; - if (ChanceRnd > m_Chance) - { - // Not in this chunk - return; - } - - // Get the height at which to try: - int Height = m_Noise.IntNoise3DInt(128 * a_ChunkDesc.GetChunkX(), 1024, 256 * a_ChunkDesc.GetChunkZ()) / 11; - Height %= m_HeightDistribution.GetSum(); - Height = m_HeightDistribution.MapValue(Height); - - // Try adding the spring at the height, if unsuccessful, move lower: - for (int y = Height; y > 1; y--) - { - // TODO: randomize the order in which the coords are being checked - for (int z = 1; z < cChunkDef::Width - 1; z++) - { - for (int x = 1; x < cChunkDef::Width - 1; x++) - { - switch (a_ChunkDesc.GetBlockType(x, y, z)) - { - case E_BLOCK_NETHERRACK: - case E_BLOCK_STONE: - { - if (TryPlaceSpring(a_ChunkDesc, x, y, z)) - { - // Succeeded, bail out - return; - } - } - } // switch (BlockType) - } // for x - } // for y - } // for y -} - - - - - -bool cFinishGenFluidSprings::TryPlaceSpring(cChunkDesc & a_ChunkDesc, int x, int y, int z) -{ - // In order to place a spring, it needs exactly one of the XZ neighbors or a below neighbor to be air - // Also, its neighbor on top of it must be non-air - if (a_ChunkDesc.GetBlockType(x, y + 1, z) == E_BLOCK_AIR) - { - return false; - } - - static const struct - { - int x, y, z; - } Coords[] = - { - {-1, 0, 0}, - { 1, 0, 0}, - { 0, -1, 0}, - { 0, 0, -1}, - { 0, 0, 1}, - } ; - int NumAirNeighbors = 0; - for (int i = 0; i < ARRAYCOUNT(Coords); i++) - { - switch (a_ChunkDesc.GetBlockType(x + Coords[i].x, y + Coords[i].y, z + Coords[i].z)) - { - case E_BLOCK_AIR: - { - NumAirNeighbors += 1; - if (NumAirNeighbors > 1) - { - return false; - } - } - } - } - if (NumAirNeighbors == 0) - { - return false; - } - - // Has exactly one air neighbor, place a spring: - a_ChunkDesc.SetBlockTypeMeta(x, y, z, m_Fluid, 0); - return true; -} - - - - |