Cuberite
A lightweight, fast and extensible game server for Minecraft
StructGen.cpp
Go to the documentation of this file.
1 
2 // StructGen.h
3 
4 #include "Globals.h"
5 #include "StructGen.h"
6 #include "Trees.h"
7 #include "../BlockArea.h"
8 #include "../LinearUpscale.h"
9 
10 
11 
12 
13 
15 // cStructGenTrees:
16 
18 {
19  int ChunkX = a_ChunkDesc.GetChunkX();
20  int ChunkZ = a_ChunkDesc.GetChunkZ();
21 
22  cChunkDesc WorkerDesc({ChunkX, ChunkZ});
23 
24  // Generate trees:
25  for (int x = 0; x <= 2; x++)
26  {
27  int BaseX = ChunkX + x - 1;
28  for (int z = 0; z <= 2; z++)
29  {
30  int BaseZ = ChunkZ + z - 1;
31 
32  cChunkDesc * Dest;
33 
34  if ((x != 1) || (z != 1))
35  {
36  Dest = &WorkerDesc;
37  WorkerDesc.SetChunkCoords({BaseX, BaseZ});
38 
39  // TODO: This may cause a lot of wasted calculations, instead of pulling data out of a single (cChunkDesc) cache
40 
41  cChunkDesc::Shape workerShape;
42  m_BiomeGen->GenBiomes ({BaseX, BaseZ}, WorkerDesc.GetBiomeMap());
43  m_ShapeGen->GenShape ({BaseX, BaseZ}, workerShape);
44  WorkerDesc.SetHeightFromShape (workerShape);
45  m_CompositionGen->ComposeTerrain(WorkerDesc, workerShape);
46  }
47  else
48  {
49  Dest = &a_ChunkDesc;
50  }
51 
52  int NumTrees = GetNumTrees(BaseX, BaseZ, Dest->GetBiomeMap());
53 
54  sSetBlockVector OutsideLogs, OutsideOther;
55  for (int i = 0; i < NumTrees; i++)
56  {
57  GenerateSingleTree(BaseX, BaseZ, i, *Dest, OutsideLogs, OutsideOther);
58  }
59 
60  sSetBlockVector IgnoredOverflow;
61  IgnoredOverflow.reserve(OutsideOther.size());
62  ApplyTreeImage(ChunkX, ChunkZ, a_ChunkDesc, OutsideOther, IgnoredOverflow);
63  IgnoredOverflow.clear();
64  IgnoredOverflow.reserve(OutsideLogs.size());
65  ApplyTreeImage(ChunkX, ChunkZ, a_ChunkDesc, OutsideLogs, IgnoredOverflow);
66  } // for z
67  } // for x
68 
69  a_ChunkDesc.UpdateHeightmap();
70 }
71 
72 
73 
74 
75 
77  int a_ChunkX, int a_ChunkZ, int a_Seq,
78  cChunkDesc & a_ChunkDesc,
79  sSetBlockVector & a_OutsideLogs,
80  sSetBlockVector & a_OutsideOther
81 )
82 {
83  int x = (m_Noise.IntNoise3DInt(a_ChunkX + a_ChunkZ, a_ChunkZ, a_Seq) / 19) % cChunkDef::Width;
84  int z = (m_Noise.IntNoise3DInt(a_ChunkX - a_ChunkZ, a_Seq, a_ChunkZ) / 19) % cChunkDef::Width;
85 
86  int Height = a_ChunkDesc.GetHeight(x, z);
87 
88  if ((Height <= 0) || (Height >= 230))
89  {
90  return;
91  }
92 
93  // Check the block underneath the tree:
94  BLOCKTYPE TopBlock = a_ChunkDesc.GetBlockType(x, Height, z);
95  if ((TopBlock != E_BLOCK_DIRT) && (TopBlock != E_BLOCK_GRASS) && (TopBlock != E_BLOCK_FARMLAND))
96  {
97  return;
98  }
99 
100  sSetBlockVector TreeLogs, TreeOther;
102  { a_ChunkX * cChunkDef::Width + x, Height + 1, a_ChunkZ * cChunkDef::Width + z },
103  m_Noise, a_Seq,
104  a_ChunkDesc.GetBiome(x, z),
105  TreeLogs, TreeOther
106  );
107 
108  // Check if the generated image fits the terrain. Only the logs are checked:
109  for (sSetBlockVector::const_iterator itr = TreeLogs.begin(); itr != TreeLogs.end(); ++itr)
110  {
111  if ((itr->m_ChunkX != a_ChunkX) || (itr->m_ChunkZ != a_ChunkZ))
112  {
113  // Outside the chunk
114  continue;
115  }
116  if (itr->m_RelY >= cChunkDef::Height)
117  {
118  // Above the chunk, cut off (this shouldn't happen too often, we're limiting trees to y < 230)
119  continue;
120  }
121 
122  BLOCKTYPE Block = a_ChunkDesc.GetBlockType(itr->m_RelX, itr->m_RelY, itr->m_RelZ);
123  switch (Block)
124  {
126  {
127  break;
128  }
129  default:
130  {
131  // There's something in the way, abort this tree altogether
132  return;
133  }
134  }
135  }
136 
137  ApplyTreeImage(a_ChunkX, a_ChunkZ, a_ChunkDesc, TreeOther, a_OutsideOther);
138  ApplyTreeImage(a_ChunkX, a_ChunkZ, a_ChunkDesc, TreeLogs, a_OutsideLogs);
139 }
140 
141 
142 
143 
144 
146  int a_ChunkX, int a_ChunkZ,
147  cChunkDesc & a_ChunkDesc,
148  const sSetBlockVector & a_Image,
149  sSetBlockVector & a_Overflow
150 )
151 {
152  // Put the generated image into a_BlockTypes, push things outside this chunk into a_Blocks
153  for (sSetBlockVector::const_iterator itr = a_Image.begin(), end = a_Image.end(); itr != end; ++itr)
154  {
155  if ((itr->m_ChunkX == a_ChunkX) && (itr->m_ChunkZ == a_ChunkZ) && (itr->m_RelY < cChunkDef::Height))
156  {
157  // Inside this chunk, integrate into a_ChunkDesc:
158  switch (a_ChunkDesc.GetBlockType(itr->m_RelX, itr->m_RelY, itr->m_RelZ))
159  {
160  case E_BLOCK_NEW_LEAVES:
161  case E_BLOCK_LEAVES:
162  {
163  if ((itr->m_BlockType != E_BLOCK_LOG) && (itr->m_BlockType != E_BLOCK_NEW_LOG))
164  {
165  break;
166  }
167  // fallthrough:
168  }
170  {
171  a_ChunkDesc.SetBlockTypeMeta(itr->m_RelX, itr->m_RelY, itr->m_RelZ, itr->m_BlockType, itr->m_BlockMeta);
172  // If grass is below our tree, turn it to dirt
173  if (
174  (cBlockInfo::IsSolid(itr->m_BlockType)) &&
175  (a_ChunkDesc.GetBlockType(itr->m_RelX, itr->m_RelY - 1, itr->m_RelZ) == E_BLOCK_GRASS)
176  )
177  {
178  a_ChunkDesc.SetBlockType(itr->m_RelX, itr->m_RelY - 1, itr->m_RelZ, E_BLOCK_DIRT);
179  }
180  break;
181  }
182 
183  } // switch (GetBlock())
184  continue;
185  }
186 
187  // Outside the chunk, push into a_Overflow.
188  // Don't check if already present there, by separating logs and others we don't need the checks anymore:
189  a_Overflow.push_back(*itr);
190  }
191 }
192 
193 
194 
195 
196 
198  int a_ChunkX, int a_ChunkZ,
199  const cChunkDef::BiomeMap & a_Biomes
200 )
201 {
202  auto BiomeTrees = [](EMCSBiome a_Biome)
203  {
204  switch (a_Biome)
205  {
206  case biOcean: return 2;
207  case biPlains: return 1;
208  case biDesert: return 0;
209  case biExtremeHills: return 3;
210  case biForest: return 30;
211  case biTaiga: return 30;
212  case biSwampland: return 8;
213  case biRiver: return 0;
214  case biNether: return 0;
215  case biEnd: return 0;
216  case biFrozenOcean: return 0;
217  case biFrozenRiver: return 0;
218  case biIcePlains: return 1;
219  case biIceMountains: return 1;
220  case biMushroomIsland: return 3;
221  case biMushroomShore: return 3;
222  case biBeach: return 0;
223  case biDesertHills: return 0;
224  case biForestHills: return 20;
225  case biTaigaHills: return 20;
226  case biExtremeHillsEdge: return 5;
227  case biJungle: return 120;
228  case biJungleHills: return 90;
229  case biJungleEdge: return 90;
230  case biDeepOcean: return 0;
231  case biStoneBeach: return 0;
232  case biColdBeach: return 0;
233  case biBirchForest: return 30;
234  case biBirchForestHills: return 20;
235  case biRoofedForest: return 50;
236  case biColdTaiga: return 20;
237  case biColdTaigaHills: return 15;
238  case biMegaTaiga: return 30;
239  case biMegaTaigaHills: return 25;
240  case biExtremeHillsPlus: return 3;
241  case biSavanna: return 8;
242  case biSavannaPlateau: return 12;
243  case biMesa: return 2;
244  case biMesaPlateauF: return 8;
245  case biMesaPlateau: return 8;
246  // Biome variants
247  case biSunflowerPlains: return 1;
248  case biDesertM: return 0;
249  case biExtremeHillsM: return 4;
250  case biFlowerForest: return 30;
251  case biTaigaM: return 30;
252  case biSwamplandM: return 8;
253  case biIcePlainsSpikes: return 1;
254  case biJungleM: return 120;
255  case biJungleEdgeM: return 90;
256  case biBirchForestM: return 30;
257  case biBirchForestHillsM: return 20;
258  case biRoofedForestM: return 40;
259  case biColdTaigaM: return 30;
260  case biMegaSpruceTaiga: return 30;
261  case biMegaSpruceTaigaHills: return 30;
262  case biExtremeHillsPlusM: return 4;
263  case biSavannaM: return 8;
264  case biSavannaPlateauM: return 12;
265  case biMesaBryce: return 4;
266  case biMesaPlateauFM: return 12;
267  case biMesaPlateauM: return 12;
268  // Non-biomes
269  case biInvalidBiome:
270  case biNumBiomes:
271  case biVariant:
272  case biNumVariantBiomes:
273  {
274  ASSERT(!"Invalid biome in cStructGenTrees::GetNumTrees");
275  return 0;
276  }
277  }
278  UNREACHABLE("Unsupported biome");
279  };
280 
281  int NumTrees = 0;
282  for (auto Biome : a_Biomes)
283  {
284  NumTrees += BiomeTrees(Biome);
285  }
286  return NumTrees / 1024;
287 }
288 
289 
290 
291 
292 
294 // cStructGenLakes:
295 
297 {
298  int ChunkX = a_ChunkDesc.GetChunkX();
299  int ChunkZ = a_ChunkDesc.GetChunkZ();
300 
301  for (int z = -1; z < 2; z++) for (int x = -1; x < 2; x++)
302  {
303  if (((m_Noise.IntNoise2DInt(ChunkX + x, ChunkZ + z) / 17) % 100) > m_Probability)
304  {
305  continue;
306  }
307 
308  cBlockArea Lake;
309  CreateLakeImage(ChunkX + x, ChunkZ + z, a_ChunkDesc.GetMinHeight(), Lake);
310 
311  int OfsX = Lake.GetOriginX() + x * cChunkDef::Width;
312  int OfsZ = Lake.GetOriginZ() + z * cChunkDef::Width;
313 
314  // Merge the lake into the current data
315  a_ChunkDesc.WriteBlockArea(Lake, OfsX, Lake.GetOriginY(), OfsZ, cBlockArea::msLake);
316  } // for x, z - neighbor chunks
317 }
318 
319 
320 
321 
322 
323 void cStructGenLakes::CreateLakeImage(int a_ChunkX, int a_ChunkZ, int a_MaxLakeHeight, cBlockArea & a_Lake)
324 {
325  a_Lake.Create(16, 8, 16);
326  a_Lake.Fill(cBlockArea::baTypes, E_BLOCK_SPONGE); // Sponge is the NOP blocktype for lake merging strategy
327 
328  // Make a random position in the chunk by using a random 16 block XZ offset and random height up to chunk's max height minus 6
329  int MinHeight = std::max(a_MaxLakeHeight - 6, 2);
330  int Rnd = m_Noise.IntNoise3DInt(a_ChunkX, 128, a_ChunkZ) / 11;
331  // Random offset [-8 .. 8], with higher probability around 0; add up four three-bit-wide randoms [0 .. 28], divide and subtract to get range
332  int OffsetX = 4 * ((Rnd & 0x07) + ((Rnd & 0x38) >> 3) + ((Rnd & 0x1c0) >> 6) + ((Rnd & 0xe00) >> 9)) / 7 - 8;
333  Rnd >>= 12;
334  // Random offset [-8 .. 8], with higher probability around 0; add up four three-bit-wide randoms [0 .. 28], divide and subtract to get range
335  int OffsetZ = 4 * ((Rnd & 0x07) + ((Rnd & 0x38) >> 3) + ((Rnd & 0x1c0) >> 6) + ((Rnd & 0xe00) >> 9)) / 7 - 8;
336  Rnd = m_Noise.IntNoise3DInt(a_ChunkX, 512, a_ChunkZ) / 13;
337  // Random height [1 .. MinHeight] with preference to center heights
338  int HeightY = 1 + (((Rnd & 0x1ff) % MinHeight) + (((Rnd >> 9) & 0x1ff) % MinHeight)) / 2;
339 
340  a_Lake.SetOrigin(OffsetX, HeightY, OffsetZ);
341 
342  // Hollow out a few bubbles inside the blockarea:
343  int NumBubbles = 4 + ((Rnd >> 18) & 0x03); // 4 .. 7 bubbles
344  BLOCKTYPE * BlockTypes = a_Lake.GetBlockTypes();
345  for (int i = 0; i < NumBubbles; i++)
346  {
347  int BubbleRnd = m_Noise.IntNoise3DInt(a_ChunkX, i, a_ChunkZ) / 13;
348  const int BubbleR = 2 + (BubbleRnd & 0x03); // 2 .. 5
349  const int Range = 16 - 2 * BubbleR;
350  const int BubbleX = BubbleR + (BubbleRnd % Range);
351  BubbleRnd >>= 4;
352  const int BubbleY = 4 + (BubbleRnd & 0x01); // 4 .. 5
353  BubbleRnd >>= 1;
354  const int BubbleZ = BubbleR + (BubbleRnd % Range);
355  const int HalfR = BubbleR / 2; // 1 .. 2
356  const int RSquared = BubbleR * BubbleR;
357  for (int y = -HalfR; y <= HalfR; y++)
358  {
359  // BubbleY + y is in the [0, 7] bounds
360  int DistY = 4 * y * y / 3;
361  int IdxY = (BubbleY + y) * 16 * 16;
362  for (int z = -BubbleR; z <= BubbleR; z++)
363  {
364  int DistYZ = DistY + z * z;
365  if (DistYZ >= RSquared)
366  {
367  continue;
368  }
369  int IdxYZ = BubbleX + IdxY + (BubbleZ + z) * 16;
370  for (int x = -BubbleR; x <= BubbleR; x++)
371  {
372  if (x * x + DistYZ < RSquared)
373  {
374  BlockTypes[x + IdxYZ] = E_BLOCK_AIR;
375  }
376  } // for x
377  } // for z
378  } // for y
379  } // for i - bubbles
380 
381  // Turn air in the bottom half into liquid:
382  for (int y = 0; y < 4; y++)
383  {
384  for (int z = 0; z < 16; z++) for (int x = 0; x < 16; x++)
385  {
386  if (BlockTypes[x + z * 16 + y * 16 * 16] == E_BLOCK_AIR)
387  {
388  BlockTypes[x + z * 16 + y * 16 * 16] = m_Fluid;
389  }
390  } // for z, x
391  } // for y
392 
393  // TODO: Turn sponge next to lava into stone
394 
395  // a_Lake.SaveToSchematicFile(Printf("Lake_%d_%d.schematic", a_ChunkX, a_ChunkZ));
396 }
397 
398 
399 
400 
401 
403 // cStructGenDirectOverhangs:
404 
406  m_Noise1(a_Seed),
407  m_Noise2(a_Seed + 1000)
408 {
409 }
410 
411 
412 
413 
414 
416 {
417  // If there is no column of the wanted biome, bail out:
418  if (!HasWantedBiome(a_ChunkDesc))
419  {
420  return;
421  }
422 
423  HEIGHTTYPE MaxHeight = a_ChunkDesc.GetMaxHeight();
424 
425  const int SEGMENT_HEIGHT = 8;
426  const int INTERPOL_X = 16; // Must be a divisor of 16
427  const int INTERPOL_Z = 16; // Must be a divisor of 16
428  // Interpolate the chunk in 16 * SEGMENT_HEIGHT * 16 "segments", each SEGMENT_HEIGHT blocks high and each linearly interpolated separately.
429  // Have two buffers, one for the lowest floor and one for the highest floor, so that Y-interpolation can be done between them
430  // Then swap the buffers and use the previously-top one as the current-bottom, without recalculating it.
431 
432  int FloorBuf1[17 * 17];
433  int FloorBuf2[17 * 17];
434  int * FloorHi = FloorBuf1;
435  int * FloorLo = FloorBuf2;
436  int BaseX = a_ChunkDesc.GetChunkX() * cChunkDef::Width;
437  int BaseZ = a_ChunkDesc.GetChunkZ() * cChunkDef::Width;
438  int BaseY = 63;
439 
440  // Interpolate the lowest floor:
441  for (int z = 0; z <= 16 / INTERPOL_Z; z++) for (int x = 0; x <= 16 / INTERPOL_X; x++)
442  {
443  FloorLo[INTERPOL_X * x + 17 * INTERPOL_Z * z] =
444  m_Noise1.IntNoise3DInt(BaseX + INTERPOL_X * x, BaseY, BaseZ + INTERPOL_Z * z) *
445  m_Noise2.IntNoise3DInt(BaseX + INTERPOL_X * x, BaseY, BaseZ + INTERPOL_Z * z) /
446  256;
447  } // for x, z - FloorLo[]
448  LinearUpscale2DArrayInPlace<17, 17, INTERPOL_X, INTERPOL_Z>(FloorLo);
449 
450  // Interpolate segments:
451  for (int Segment = BaseY; Segment < MaxHeight; Segment += SEGMENT_HEIGHT)
452  {
453  // First update the high floor:
454  for (int z = 0; z <= 16 / INTERPOL_Z; z++) for (int x = 0; x <= 16 / INTERPOL_X; x++)
455  {
456  FloorHi[INTERPOL_X * x + 17 * INTERPOL_Z * z] = (
457  m_Noise1.IntNoise3DInt(BaseX + INTERPOL_X * x, Segment + SEGMENT_HEIGHT, BaseZ + INTERPOL_Z * z) *
458  m_Noise2.IntNoise3DInt(BaseX + INTERPOL_Z * x, Segment + SEGMENT_HEIGHT, BaseZ + INTERPOL_Z * z) / 256
459  );
460  } // for x, z - FloorLo[]
461  LinearUpscale2DArrayInPlace<17, 17, INTERPOL_X, INTERPOL_Z>(FloorHi);
462 
463  // Interpolate between FloorLo and FloorHi:
464  for (int z = 0; z < 16; z++) for (int x = 0; x < 16; x++)
465  {
466  EMCSBiome biome = a_ChunkDesc.GetBiome(x, z);
467 
468  if ((biome == biExtremeHills) || (biome == biExtremeHillsEdge))
469  {
470  int Lo = FloorLo[x + 17 * z] / 256;
471  int Hi = FloorHi[x + 17 * z] / 256;
472  for (int y = 0; y < SEGMENT_HEIGHT; y++)
473  {
474  int Val = Lo + (Hi - Lo) * y / SEGMENT_HEIGHT;
475  if (Val < 0)
476  {
477  a_ChunkDesc.SetBlockType(x, y + Segment, z, E_BLOCK_AIR);
478  }
479  } // for y
480  break;
481  } // if (biome)
482  } // for z, x
483 
484  // Swap the floors:
485  std::swap(FloorLo, FloorHi);
486  }
487 }
488 
489 
490 
491 
492 
494 {
495  cChunkDef::BiomeMap & Biomes = a_ChunkDesc.GetBiomeMap();
496  for (size_t i = 0; i < ARRAYCOUNT(Biomes); i++)
497  {
498  switch (Biomes[i])
499  {
500  case biExtremeHills:
501  case biExtremeHillsEdge:
502  {
503  return true;
504  }
505  default:
506  {
507  break;
508  }
509  }
510  } // for i
511  return false;
512 }
513 
514 
515 
516 
517 
519 // cStructGenDistortedMembraneOverhangs:
520 
522  m_NoiseX(a_Seed + 1000),
523  m_NoiseY(a_Seed + 2000),
524  m_NoiseZ(a_Seed + 3000),
525  m_NoiseH(a_Seed + 4000)
526 {
527 }
528 
529 
530 
531 
532 
534 {
535  const NOISE_DATATYPE Frequency = static_cast<NOISE_DATATYPE>(16);
536  const NOISE_DATATYPE Amount = static_cast<NOISE_DATATYPE>(1);
537  for (int y = 50; y < 128; y++)
538  {
539  NOISE_DATATYPE NoiseY = static_cast<NOISE_DATATYPE>(y) / 32;
540  // TODO: proper water level - where to get?
541  BLOCKTYPE ReplacementBlock = (y > 62) ? E_BLOCK_AIR : E_BLOCK_STATIONARY_WATER;
542  for (int z = 0; z < cChunkDef::Width; z++)
543  {
544  NOISE_DATATYPE NoiseZ = static_cast<NOISE_DATATYPE>(a_ChunkDesc.GetChunkZ() * cChunkDef::Width + z) / Frequency;
545  for (int x = 0; x < cChunkDef::Width; x++)
546  {
547  NOISE_DATATYPE NoiseX = static_cast<NOISE_DATATYPE>(a_ChunkDesc.GetChunkX() * cChunkDef::Width + x) / Frequency;
548  NOISE_DATATYPE DistortX = m_NoiseX.CubicNoise3D(NoiseX, NoiseY, NoiseZ) * Amount;
549  NOISE_DATATYPE DistortY = m_NoiseY.CubicNoise3D(NoiseX, NoiseY, NoiseZ) * Amount;
550  NOISE_DATATYPE DistortZ = m_NoiseZ.CubicNoise3D(NoiseX, NoiseY, NoiseZ) * Amount;
551  int MembraneHeight = 96 - static_cast<int>((DistortY + m_NoiseH.CubicNoise2D(NoiseX + DistortX, NoiseZ + DistortZ)) * 30);
552  if (MembraneHeight < y)
553  {
554  a_ChunkDesc.SetBlockType(x, y, z, ReplacementBlock);
555  }
556  } // for y
557  } // for x
558  } // for z
559 }
560 
561 
562 
563 
HEIGHTTYPE GetMaxHeight(void) const
Returns the maximum height value in the heightmap.
Definition: ChunkDesc.cpp:397
int GetChunkZ() const
Definition: ChunkDesc.h:50
Byte Shape[256 *16 *16]
The datatype used to represent the entire chunk worth of shape.
Definition: ChunkDesc.h:36
void SetBlockType(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType)
Definition: ChunkDesc.cpp:81
#define CASE_TREE_ALLOWED_BLOCKS
Definition: Trees.h:27
int GetOriginZ(void) const
Definition: BlockArea.h:353
void Fill(int a_DataTypes, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta=0, NIBBLETYPE a_BlockLight=0, NIBBLETYPE a_BlockSkyLight=0x0f)
Fills the entire block area with the specified data.
Definition: BlockArea.cpp:785
int IntNoise2DInt(int a_X, int a_Y) const
Definition: Noise.h:243
static bool IsSolid(BLOCKTYPE a_Type)
Definition: BlockInfo.h:48
unsigned char BLOCKTYPE
The datatype used by blockdata.
Definition: ChunkDef.h:42
cTerrainCompositionGenPtr m_CompositionGen
Definition: StructGen.h:41
static const int Width
Definition: ChunkDef.h:134
Definition: BiomeDef.h:37
cNoise m_Noise
Definition: StructGen.h:38
virtual void GenFinish(cChunkDesc &a_ChunkDesc) override
Definition: StructGen.cpp:533
EMCSBiome GetBiome(int a_RelX, int a_RelZ) const
Definition: ChunkDesc.cpp:126
int IntNoise3DInt(int a_X, int a_Y, int a_Z) const
Definition: Noise.h:254
EMCSBiome
Biome IDs The first batch corresponds to the clientside biomes, used by MineCraft.
Definition: BiomeDef.h:21
void CreateLakeImage(int a_ChunkX, int a_ChunkZ, int a_MaxLakeHeight, cBlockArea &a_Lake)
Creates a lake image for the specified chunk into a_Lake.
Definition: StructGen.cpp:323
unsigned char HEIGHTTYPE
The type used by the heightmap.
Definition: ChunkDef.h:48
virtual void GenFinish(cChunkDesc &a_ChunkDesc) override
Definition: StructGen.cpp:296
void WriteBlockArea(const cBlockArea &a_BlockArea, int a_RelX, int a_RelY, int a_RelZ, cBlockArea::eMergeStrategy a_MergeStrategy=cBlockArea::msOverwrite)
Writes the block area into the chunk, with its origin set at the specified relative coords...
Definition: ChunkDesc.cpp:271
virtual void GenFinish(cChunkDesc &a_ChunkDesc) override
Definition: StructGen.cpp:415
void UpdateHeightmap(void)
Updates the heightmap to match the current contents.
Definition: ChunkDesc.cpp:612
static const int Height
Definition: ChunkDef.h:135
BLOCKTYPE GetBlockType(int a_RelX, int a_RelY, int a_RelZ) const
Definition: ChunkDesc.cpp:90
int GetOriginY(void) const
Definition: BlockArea.h:352
virtual void GenFinish(cChunkDesc &a_ChunkDesc) override
Definition: StructGen.cpp:17
void GetTreeImageByBiome(Vector3i a_BlockPos, cNoise &a_Noise, int a_Seq, EMCSBiome a_Biome, sSetBlockVector &a_LogBlocks, sSetBlockVector &a_OtherBlocks)
Fills a_LogBlocks and a_OtherBlocks (dirt & leaves) with the blocks required to form a tree at the sp...
Definition: Trees.cpp:227
float NOISE_DATATYPE
The datatype used by all the noise generators.
Definition: Noise.h:9
#define ASSERT(x)
Definition: Globals.h:335
cBiomeGenPtr m_BiomeGen
Definition: StructGen.h:39
HEIGHTTYPE GetHeight(int a_RelX, int a_RelZ) const
Definition: ChunkDesc.cpp:144
HEIGHTTYPE GetMinHeight(void) const
Returns the minimum height value in the heightmap.
Definition: ChunkDesc.cpp:414
cStructGenDirectOverhangs(int a_Seed)
Definition: StructGen.cpp:405
int GetNumTrees(int a_ChunkX, int a_ChunkZ, const cChunkDef::BiomeMap &a_Biomes)
Definition: StructGen.cpp:197
cTerrainShapeGenPtr m_ShapeGen
Definition: StructGen.h:40
NOISE_DATATYPE CubicNoise3D(NOISE_DATATYPE a_X, NOISE_DATATYPE a_Y, NOISE_DATATYPE a_Z) const
Definition: Noise.cpp:621
void ApplyTreeImage(int a_ChunkX, int a_ChunkZ, cChunkDesc &a_ChunkDesc, const sSetBlockVector &a_Image, sSetBlockVector &a_Overflow)
Applies an image into chunk blockdata; all blocks outside the chunk will be appended to a_Overflow...
Definition: StructGen.cpp:145
void SetChunkCoords(cChunkCoords a_Coords)
Definition: ChunkDesc.cpp:45
int GetOriginX(void) const
Definition: BlockArea.h:351
BLOCKTYPE * GetBlockTypes(void) const
Returns the internal pointer to the block types.
Definition: BlockArea.h:386
int GetChunkX() const
Definition: ChunkDesc.h:49
void Create(int a_SizeX, int a_SizeY, int a_SizeZ, int a_DataTypes=baTypes|baMetas|baBlockEntities)
Creates a new area of the specified size and contents.
Definition: BlockArea.cpp:336
void SetOrigin(int a_OriginX, int a_OriginY, int a_OriginZ)
Resets the origin.
Definition: BlockArea.cpp:385
NOISE_DATATYPE CubicNoise2D(NOISE_DATATYPE a_X, NOISE_DATATYPE a_Y) const
Definition: Noise.cpp:593
void GenerateSingleTree(int a_ChunkX, int a_ChunkZ, int a_Seq, cChunkDesc &a_ChunkDesc, sSetBlockVector &a_OutsideLogs, sSetBlockVector &a_OutsideOther)
Generates and applies an image of a single tree.
Definition: StructGen.cpp:76
EMCSBiome BiomeMap[Width *Width]
The type used for any biomemap operations and storage inside Cuberite, using Cuberite biomes (need no...
Definition: ChunkDef.h:147
#define ARRAYCOUNT(X)
Evaluates to the number of elements in an array (compile-time!)
Definition: Globals.h:290
#define CASE_TREE_OVERWRITTEN_BLOCKS
Definition: Trees.h:38
#define UNREACHABLE(x)
Use to mark code that should be impossible to reach.
Definition: Globals.h:344
void SetBlockTypeMeta(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
Definition: ChunkDesc.cpp:63
std::vector< sSetBlock > sSetBlockVector
Definition: ChunkDef.h:564
cChunkDef::BiomeMap & GetBiomeMap(void)
Definition: ChunkDesc.h:216
bool HasWantedBiome(cChunkDesc &a_ChunkDesc) const
Definition: StructGen.cpp:493