Files
mcpe/source/world/level/levelgen/feature/TreeFeature.cpp
2023-12-02 21:04:21 +03:00

109 lines
2.5 KiB
C++

/********************************************************************
Minecraft: Pocket Edition - Decompilation Project
Copyright (C) 2023 iProgramInCpp
The following code is licensed under the BSD 1 clause license.
SPDX-License-Identifier: BSD-1-Clause
********************************************************************/
#include "Feature.hpp"
#include "world/level/Level.hpp"
bool TreeFeature::place(Level* level, Random* random, int x, int y, int z)
{
if (y <= C_MIN_Y)
return false;
int treeHeight = int(random->nextInt(3) + 4); // Between 4 and 6 blocks tall.
if (y + treeHeight >= C_MAX_Y)
return false;
// Ensure that we can place this tree
bool bCanPlace = true;
for (int ay = y; ay <= y + treeHeight; ay++)
{
int x1 = 1;
if (y + treeHeight - 1 <= ay)
x1 = 2;
else if (ay == y)
x1 = 0;
for (int ax = x - x1; ax <= x + x1 && bCanPlace; ax++)
{
for (int az = z - x1; az <= z + x1 && bCanPlace; az++)
{
if (ay < C_MIN_Y || ay >= C_MAX_Y)
{
bCanPlace = false;
break;
}
TileID tile = level->getTile(ax, ay, az);
// other trees can overlap with this one, apparently
if (tile != TILE_AIR && tile != Tile::leaves->m_ID)
{
bCanPlace = false;
break;
}
}
}
}
// If not, let our caller know.
if (!bCanPlace)
return false;
TileID tileBelow = level->getTile(x, y - 1, z);
// If grass or dirt aren't below us, we can't possibly grow!
if (tileBelow != Tile::grass->m_ID && tileBelow != Tile::dirt->m_ID)
return false;
// @NOTE: Redundant check
if (y >= C_MAX_Y - treeHeight)
return false;
level->setTileNoUpdate(x, y - 1, z, Tile::dirt->m_ID);
int upperY = y + treeHeight;
int lowerY = y + treeHeight - 3;
int diff = lowerY - upperY;
for (int i = lowerY; i <= upperY; i++, diff = i - upperY)
{
int c1 = 1 - diff / 2;
//int c2 = diff / 2 - 1;
for (int ax = x - c1; ax <= x + c1; ax++)
{
//int c3 = c2;
int c4 = diff / 2 - 1;
//if (c2 < 0)
// c3 = -c2;
//int c5 = c3;
for (int az = z - c1; az <= z + c1; az++, c4++)
{
if ((abs(ax - x) != c1 || abs(az - z) != c1 || (random->nextInt(2) != 0 && diff != 0)) && !Tile::solid[level->getTile(ax, i, az)])
{
level->setTileNoUpdate(ax, i, az, Tile::leaves->m_ID);
}
}
}
}
for (int i = 0; i < treeHeight; i++)
{
//int y1 = i + y;
TileID tile = level->getTile(x, y + i, z);
if (tile && tile != Tile::leaves->m_ID)
continue;
level->setTileNoUpdate(x, y + i, z, Tile::treeTrunk->m_ID);
}
return true;
}