Files
minecraft-pe-0.6.1/src/world/level/LightUpdate.cpp
2026-03-02 22:04:18 +03:00

194 lines
5.4 KiB
C++
Executable File

#include "Level.h"
#include "LightUpdate.h"
#include "tile/Tile.h"
//LightUpdate::LightUpdate()
//:
// layer(&LightLayer::Sky),
// x0(0),
// y0(0),
// z0(0),
// x1(1),
// y1(1),
// z1(1)
//{} // for using std::set
LightUpdate::LightUpdate(const LightUpdate* t)
:
layer(t->layer),
x0(t->x0),
y0(t->y0),
z0(t->z0),
x1(t->x1),
y1(t->y1),
z1(t->z1)
{
}
LightUpdate::LightUpdate(const LightUpdate& t)
:
layer(t.layer),
x0(t.x0),
y0(t.y0),
z0(t.z0),
x1(t.x1),
y1(t.y1),
z1(t.z1)
{
}
LightUpdate::LightUpdate(const LightLayer& _layer, int _x0, int _y0, int _z0, int _x1, int _y1, int _z1)
:
layer(&_layer),
x0(_x0),
y0(_y0),
z0(_z0),
x1(_x1),
y1(_y1),
z1(_z1)
{
}
void LightUpdate::operator=(const LightUpdate* t)
{
layer = t->layer;
x0 = t->x0;
y0 = t->y0;
z0 = t->z0;
x1 = t->x1;
y1 = t->y1;
z1 = t->z1;
}
void LightUpdate::update(Level* level)
{
int xd = (x1 - x0) + 1;
int yd = (y1 - y0) + 1;
int zd = (z1 - z0) + 1;
int size = xd * yd * zd;
if (size > 16 * 16 * 128) {
//System.out.println("Light too large, skipping!");
return;
}
int lastxc = 0;
int lastzc = 0;
bool hasLast = false;
bool lastOk = false;
for (int x = x0; x <= x1; x++)
for (int z = z0; z <= z1; z++) {
int xc = x >> 4;
int zc = z >> 4;
bool ok = false;
if (hasLast && xc == lastxc && zc == lastzc) {
ok = lastOk;
} else {
ok = level->hasChunksAt(x, 0, z, 1);
if (ok) {
LevelChunk* lc = level->getChunk(x >> 4, z >> 4);
if (lc->isEmpty()) ok = false;
}
lastOk = ok;
lastxc = xc;
lastzc = zc;
}
if (ok) {
if (y0 < 0) y0 = 0;
if (y1 >= Level::DEPTH) y1 = Level::DEPTH - 1;
for (int y = y0; y <= y1; y++) {
int old = level->getBrightness(*layer, x, y, z);
int target = 0;
int tile = level->getTile(x, y, z);
int block = Tile::lightBlock[tile];
if (block == 0) block = 1;
int emit = 0;
if (layer == &LightLayer::Sky) {
if (level->isSkyLit(x, y, z)) emit = 15;
} else if (layer == &LightLayer::Block) {
emit = Tile::lightEmission[tile];
}
if (block >= 15 && emit == 0) {
target = 0;
} else {
int d0 = level->getBrightness(*layer, x - 1, y, z);
int d1 = level->getBrightness(*layer, x + 1, y, z);
int d2 = level->getBrightness(*layer, x, y - 1, z);
int d3 = level->getBrightness(*layer, x, y + 1, z);
int d4 = level->getBrightness(*layer, x, y, z - 1);
int d5 = level->getBrightness(*layer, x, y, z + 1);
target = d0;
if (d1 > target) target = d1;
if (d2 > target) target = d2;
if (d3 > target) target = d3;
if (d4 > target) target = d4;
if (d5 > target) target = d5;
target -= block;
if (target < 0) target = 0;
if (emit > target) target = emit;
}
if (old != target) {
level->setBrightness(*layer, x, y, z, target);
int t = target - 1;
if (t < 0) t = 0;
level->updateLightIfOtherThan(*layer, x - 1, y, z, t);
level->updateLightIfOtherThan(*layer, x, y - 1, z, t);
level->updateLightIfOtherThan(*layer, x, y, z - 1, t);
if (x + 1 >= x1) level->updateLightIfOtherThan(*layer, x + 1, y, z, t);
if (y + 1 >= y1) level->updateLightIfOtherThan(*layer, x, y + 1, z, t);
if (z + 1 >= z1) level->updateLightIfOtherThan(*layer, x, y, z + 1, t);
}
}
}
}
}
bool LightUpdate::expandToContain(int _x0, int _y0, int _z0, int _x1, int _y1, int _z1) {
if (_x0 >= x0 && _y0 >= y0 && _z0 >= z0 && _x1 <= x1 && _y1 <= y1 && _z1 <= z1) return true;
int r = 1;
if (_x0 >= x0 - r && _y0 >= y0 - r && _z0 >= z0 - r && _x1 <= x1 + r && _y1 <= y1 + r && _z1 <= z1 + r) {
int xs = x1 - x0;
int ys = y1 - y0;
int zs = z1 - z0;
if (_x0 > x0) _x0 = x0;
if (_y0 > y0) _y0 = y0;
if (_z0 > z0) _z0 = z0;
if (_x1 < x1) _x1 = x1;
if (_y1 < y1) _y1 = y1;
if (_z1 < z1) _z1 = z1;
int _xs = _x1 - _x0;
int _ys = _y1 - _y0;
int _zs = _z1 - _z0;
int os = xs * ys * zs;
int ns = _xs * _ys * _zs;
if (ns - os <= 2) {
x0 = _x0;
y0 = _y0;
z0 = _z0;
x1 = _x1;
y1 = _y1;
z1 = _z1;
return true;
}
}
return false;
}