mirror of
https://gitea.sffempire.ru/Kolyah35/minecraft-pe-0.6.1.git
synced 2026-04-07 07:53:32 +00:00
Added 3 Fog Choices (Pocket) (Java) (Unknown that was unused) Restored Java Beta Sky Color code that was unused that depends on biome temperature (choosable using Java fog) Tile Shadows and Entity Shadows that appear beneath them have been restored and fixed from the unused code, toggleable by turning fancy graphics on or off Entities will now render flames on themselves when on fire, including the player Added option to use Java Style Item Count text and position in tweaks - fileshredder
714 lines
19 KiB
C++
Executable File
714 lines
19 KiB
C++
Executable File
#include "LevelChunk.h"
|
|
#include "../LightLayer.h"
|
|
#include "../tile/Tile.h"
|
|
#include "../Level.h"
|
|
#include "../dimension/Dimension.h"
|
|
#include "../../phys/AABB.h"
|
|
#include "../../entity/Entity.h"
|
|
#include "../TilePos.h"
|
|
#include "../tile/entity/TileEntity.h"
|
|
#include "../tile/EntityTile.h"
|
|
#include "../LevelConstants.h"
|
|
|
|
/*static*/
|
|
bool LevelChunk::touchedSky = false;
|
|
|
|
LevelChunk::LevelChunk( Level* level, int x, int z )
|
|
: level(level),
|
|
x(x),
|
|
z(z),
|
|
xt(x * CHUNK_WIDTH),
|
|
zt(z * CHUNK_DEPTH)
|
|
{
|
|
init();
|
|
}
|
|
|
|
LevelChunk::LevelChunk( Level* level, unsigned char* blocks, int x, int z )
|
|
: level(level),
|
|
x(x),
|
|
z(z),
|
|
xt(x * CHUNK_WIDTH),
|
|
zt(z * CHUNK_DEPTH),
|
|
blocks(blocks),
|
|
data(ChunkBlockCount),
|
|
skyLight(ChunkBlockCount),
|
|
blockLight(ChunkBlockCount),
|
|
blocksLength(ChunkBlockCount)
|
|
{
|
|
init();
|
|
}
|
|
|
|
LevelChunk::~LevelChunk()
|
|
{
|
|
//delete blocks;
|
|
}
|
|
|
|
void LevelChunk::init()
|
|
{
|
|
terrainPopulated = false;
|
|
dontSave = false;
|
|
unsaved = false;
|
|
lastSaveHadEntities = false;
|
|
createdFromSave = false;
|
|
lastSaveTime = 0;
|
|
memset(heightmap, 0, 256);
|
|
memset(updateMap, 0, 256);
|
|
}
|
|
|
|
/*public*/
|
|
bool LevelChunk::setTileAndData(int x, int y, int z, int tile_, int data_) {
|
|
|
|
int tile = tile_ & 0xff;
|
|
|
|
int oldHeight = heightmap[z << 4 | x];
|
|
|
|
int old = blocks[x << 11 | z << 7 | y];
|
|
if (old == tile && data.get(x, y, z) == data_) return false;
|
|
int xOffs = xt + x;
|
|
int zOffs = zt + z;
|
|
blocks[x << 11 | z << 7 | y] = (unsigned char) tile;
|
|
if (old != 0) {
|
|
if (!level->isClientSide) {
|
|
Tile::tiles[old]->onRemove(level, xOffs, y, zOffs);
|
|
} else if (old != tile && Tile::isEntityTile[old]) {
|
|
level->removeTileEntity(xOffs, y, zOffs);
|
|
}
|
|
}
|
|
data.set(x, y, z, data_);
|
|
|
|
if (!level->dimension->hasCeiling) {
|
|
if (Tile::lightBlock[tile] != 0) {
|
|
if (y >= oldHeight) {
|
|
recalcHeight(x, y + 1, z);
|
|
}
|
|
} else {
|
|
if (y == oldHeight - 1) {
|
|
recalcHeight(x, y, z);
|
|
}
|
|
}
|
|
level->updateLight(LightLayer::Sky, xOffs, y, zOffs, xOffs, y, zOffs);
|
|
}
|
|
|
|
level->updateLight(LightLayer::Block, xOffs, y, zOffs, xOffs, y, zOffs);
|
|
lightGaps(x, z);
|
|
|
|
if (!level->isClientSide && tile != 0) {
|
|
Tile::tiles[tile]->onPlace(level, xOffs, y, zOffs);
|
|
}
|
|
|
|
this->unsaved = true;
|
|
this->updateMap[x | (z << 4)] |= (1 << (y >> UpdateMapBitShift));
|
|
return true;
|
|
}
|
|
|
|
|
|
/*public*/
|
|
bool LevelChunk::setTile(int x, int y, int z, int tile_) {
|
|
|
|
int tile = tile_ & 0xff;
|
|
int oldHeight = heightmap[z << 4 | x] & 0xff;
|
|
|
|
int old = blocks[x << 11 | z << 7 | y] & 0xff;
|
|
if (old == tile_) return false;
|
|
int xOffs = xt + x;
|
|
int zOffs = zt + z;
|
|
blocks[x << 11 | z << 7 | y] = (unsigned char) (tile & 0xff);
|
|
if (old != 0) {
|
|
Tile::tiles[old]->onRemove(level, xOffs, y, zOffs);
|
|
}
|
|
data.set(x, y, z, 0);
|
|
|
|
if (Tile::lightBlock[tile & 0xff] != 0) {
|
|
if (y >= oldHeight) {
|
|
recalcHeight(x, y + 1, z);
|
|
}
|
|
} else {
|
|
if (y == oldHeight - 1) {
|
|
recalcHeight(x, y, z);
|
|
}
|
|
}
|
|
|
|
level->updateLight(LightLayer::Sky, xOffs, y, zOffs, xOffs, y, zOffs);
|
|
level->updateLight(LightLayer::Block, xOffs, y, zOffs, xOffs, y, zOffs);
|
|
lightGaps(x, z);
|
|
|
|
if (tile_ != 0) {
|
|
if (!level->isClientSide) Tile::tiles[tile_]->onPlace(level, xOffs, y, zOffs);
|
|
}
|
|
|
|
this->unsaved = true;
|
|
this->updateMap[x | (z << 4)] |= (1 << (y >> UpdateMapBitShift));
|
|
return true;
|
|
}
|
|
|
|
void LevelChunk::setTileRaw(int x, int y, int z, int tile) {
|
|
blocks[x << 11 | z << 7 | y] = tile;
|
|
}
|
|
|
|
/*public*/
|
|
int LevelChunk::getData(int x, int y, int z) {
|
|
return data.get(x, y, z);
|
|
}
|
|
|
|
/*public*/
|
|
void LevelChunk::recalcHeightmapOnly() {
|
|
int min = Level::DEPTH - 1;
|
|
for (int x = 0; x < 16; x++)
|
|
for (int z = 0; z < 16; z++) {
|
|
int y = Level::DEPTH - 1;
|
|
int p = x << 11 | z << 7;
|
|
while (y > 0 && Tile::lightBlock[blocks[p + y - 1] & 0xff] == 0)
|
|
y--;
|
|
heightmap[z << 4 | x] = (char) y;
|
|
if (y < min) min = y;
|
|
}
|
|
|
|
this->minHeight = min;
|
|
//this->unsaved = true;
|
|
}
|
|
|
|
/*public?*/
|
|
void LevelChunk::recalcHeightmap() {
|
|
int min = Level::DEPTH - 1;
|
|
for (int x = 0; x < 16; x++)
|
|
for (int z = 0; z < 16; z++) {
|
|
int y = Level::DEPTH - 1;
|
|
int p = x << 11 | z << 7;
|
|
while (y > 0 && Tile::lightBlock[blocks[p + y - 1] & 0xff] == 0)
|
|
y--;
|
|
heightmap[z << 4 | x] = (char) y;
|
|
if (y < min) min = y;
|
|
|
|
if (!level->dimension->hasCeiling) {
|
|
int br = Level::MAX_BRIGHTNESS;
|
|
int yy = Level::DEPTH - 1;
|
|
do {
|
|
br -= Tile::lightBlock[blocks[p + yy] & 0xff];
|
|
if (br > 0) {
|
|
skyLight.set(x, yy, z, br);
|
|
}
|
|
yy--;
|
|
} while (yy > 0 && br > 0);
|
|
|
|
}
|
|
}
|
|
|
|
this->minHeight = min;
|
|
|
|
for (int x = 0; x < 16; x++)
|
|
for (int z = 0; z < 16; z++) {
|
|
lightGaps(x, z);
|
|
}
|
|
|
|
//this->unsaved = true;
|
|
}
|
|
|
|
/*private*/
|
|
void LevelChunk::recalcHeight(int x, int yStart, int z) {
|
|
int yOld = heightmap[z << 4 | x] & 0xff;
|
|
int y = yOld;
|
|
if (yStart > yOld) y = yStart;
|
|
|
|
int p = x << 11 | z << 7;
|
|
while (y > 0 && Tile::lightBlock[blocks[p + y - 1] & 0xff] == 0)
|
|
y--;
|
|
if (y == yOld) return;
|
|
|
|
const int xOffs = xt + x;
|
|
const int zOffs = zt + z;
|
|
level->lightColumnChanged(xOffs, zOffs, y, yOld);
|
|
heightmap[z << 4 | x] = (char) y;
|
|
|
|
if (y < minHeight) {
|
|
minHeight = y;
|
|
} else {
|
|
int min = Level::DEPTH - 1;
|
|
for (int _x = 0; _x < 16; _x++)
|
|
for (int _z = 0; _z < 16; _z++) {
|
|
if ((heightmap[_z << 4 | _x] & 0xff) < min) min = (heightmap[_z << 4 | _x] & 0xff);
|
|
}
|
|
this->minHeight = min;
|
|
}
|
|
|
|
if (y < yOld) {
|
|
for (int yy = y; yy < yOld; yy++) {
|
|
skyLight.set(x, yy, z, 15);
|
|
}
|
|
} else {
|
|
level->updateLight(LightLayer::Sky, xOffs, yOld, zOffs, xOffs, y, zOffs);
|
|
for (int yy = yOld; yy < y; yy++) {
|
|
skyLight.set(x, yy, z, 0);
|
|
}
|
|
}
|
|
|
|
int br = 15;
|
|
int y0 = y;
|
|
while (y > 0 && br > 0) {
|
|
y--;
|
|
int block = Tile::lightBlock[getTile(x, y, z)];
|
|
if (block == 0) block = 1;
|
|
br -= block;
|
|
if (br < 0) br = 0;
|
|
skyLight.set(x, y, z, br);
|
|
}
|
|
while (y > 0 && Tile::lightBlock[getTile(x, y - 1, z)] == 0)
|
|
y--;
|
|
if (y != y0) {
|
|
level->updateLight(LightLayer::Sky, xOffs - 1, y, zOffs - 1, xOffs + 1, y0, zOffs + 1);
|
|
}
|
|
|
|
//this->unsaved = true;
|
|
}
|
|
|
|
/*public*/
|
|
void LevelChunk::skyBrightnessChanged() {
|
|
int x0 = xt;
|
|
int y0 = this->minHeight - 16;
|
|
int z0 = zt;
|
|
int x1 = xt + 16;
|
|
int y1 = Level::DEPTH - 1;
|
|
int z1 = zt + 16;
|
|
|
|
level->setTilesDirty(x0, y0, z0, x1, y1, z1);
|
|
}
|
|
|
|
/*public*/
|
|
bool LevelChunk::shouldSave(bool force) {
|
|
if (dontSave) return false;
|
|
/*
|
|
if (force) {
|
|
if (lastSaveHadEntities && level->getTime() != lastSaveTime) return true;
|
|
} else {
|
|
if (lastSaveHadEntities && level->getTime() >= lastSaveTime + 20 * 30) return true;
|
|
}
|
|
*/
|
|
|
|
return unsaved;
|
|
}
|
|
|
|
/*public*/
|
|
void LevelChunk::setBlocks(unsigned char* newBlocks, int sub) { //@byte[]
|
|
LOGI("LevelChunk::setBlocks\n");
|
|
for (int i = 0; i < 128 * 16 * 4; i++) {
|
|
blocks[sub * 128 * 16 * 4 + i] = newBlocks[i];
|
|
}
|
|
|
|
for (int x = sub * 4; x < sub * 4 + 4; x++) {
|
|
for (int z = 0; z < 16; z++) {
|
|
recalcHeight(x, 0, z);
|
|
}
|
|
}
|
|
|
|
level->updateLight(LightLayer::Sky, xt + sub * 4, 0, zt, xt + sub * 4 + 4, 128, zt + 16);
|
|
level->updateLight(LightLayer::Block, xt + sub * 4, 0, zt, xt + sub * 4 + 4, 128, zt + 16);
|
|
|
|
//for (int x = sub * 4; x < sub * 4 + 4; x++) {
|
|
// for (int z = 0; z < 16; z++) {
|
|
// lightGaps(x, z);
|
|
// }
|
|
//}
|
|
level->setTilesDirty(xt + sub * 4, 0, zt, xt + sub * 4 + 4, 128, zt);
|
|
}
|
|
|
|
/*public*/
|
|
Random LevelChunk::getRandom(long l) {
|
|
return /*new*/ Random((level->getSeed() + x * x * 4987142 + x * 5947611 + z * z * 4392871l + z * 389711) ^ l);
|
|
}
|
|
|
|
/*private*/
|
|
void LevelChunk::lightGap( int x, int z, int source )
|
|
{
|
|
int height = level->getHeightmap(x, z);
|
|
if (height > source) {
|
|
level->updateLight(LightLayer::Sky, x, source, z, x, height, z);
|
|
} else if (height < source) {
|
|
level->updateLight(LightLayer::Sky, x, height, z, x, source, z);
|
|
}
|
|
}
|
|
|
|
void LevelChunk::clearUpdateMap()
|
|
{
|
|
memset(updateMap, 0x0, 256);
|
|
unsaved = false;
|
|
}
|
|
|
|
void LevelChunk::deleteBlockData()
|
|
{
|
|
delete [] blocks;
|
|
blocks = NULL;
|
|
}
|
|
|
|
bool LevelChunk::isAt( int x, int z )
|
|
{
|
|
return x == this->x && z == this->z;
|
|
}
|
|
|
|
int LevelChunk::getHeightmap( int x, int z )
|
|
{
|
|
return heightmap[z << 4 | x] & 0xff;
|
|
}
|
|
|
|
void LevelChunk::recalcBlockLights()
|
|
{
|
|
|
|
}
|
|
|
|
void LevelChunk::lightGaps( int x, int z )
|
|
{
|
|
int height = getHeightmap(x, z);
|
|
|
|
int xOffs = xt + x;
|
|
int zOffs = zt + z;
|
|
lightGap(xOffs - 1, zOffs, height);
|
|
lightGap(xOffs + 1, zOffs, height);
|
|
lightGap(xOffs, zOffs - 1, height);
|
|
lightGap(xOffs, zOffs + 1, height);
|
|
}
|
|
|
|
int LevelChunk::getTile( int x, int y, int z )
|
|
{
|
|
return blocks[x << 11 | z << 7 | y] & 0xff;
|
|
}
|
|
|
|
void LevelChunk::setData( int x, int y, int z, int val )
|
|
{
|
|
//this->unsaved = true;
|
|
data.set(x, y, z, val);
|
|
}
|
|
|
|
int LevelChunk::getBrightness( const LightLayer& layer, int x, int y, int z )
|
|
{
|
|
if (&layer == &LightLayer::Sky) return skyLight.get(x, y, z);
|
|
else if (&layer == &LightLayer::Block) return blockLight.get(x, y, z);
|
|
else return 0;
|
|
}
|
|
|
|
void LevelChunk::setBrightness( const LightLayer& layer, int x, int y, int z, int brightness )
|
|
{
|
|
//this->unsaved = true;
|
|
if (&layer == &LightLayer::Sky) skyLight.set(x, y, z, brightness);
|
|
else if (&layer == &LightLayer::Block) blockLight.set(x, y, z, brightness);
|
|
else return;
|
|
}
|
|
|
|
int LevelChunk::getRawBrightness( int x, int y, int z, int skyDampen )
|
|
{
|
|
int light = skyLight.get(x, y, z);
|
|
if (light > 0) LevelChunk::touchedSky = true;
|
|
light -= skyDampen;
|
|
int block = blockLight.get(x, y, z);
|
|
if (block > light) light = block;
|
|
|
|
return light;
|
|
}
|
|
|
|
void LevelChunk::addEntity( Entity* e )
|
|
{
|
|
lastSaveHadEntities = true;
|
|
|
|
int xc = Mth::floor(e->x / 16);
|
|
int zc = Mth::floor(e->z / 16);
|
|
if (xc != this->x || zc != this->z) {
|
|
LOGE("ERR: WRONG LOCATION : %d, %d, %d, %d", xc, x, zc, z);
|
|
//Thread.dumpStack();
|
|
}
|
|
int yc = Mth::floor(e->y / 16);
|
|
if (yc < 0) yc = 0;
|
|
if (yc >= EntityBlocksArraySize) yc = EntityBlocksArraySize - 1;
|
|
e->inChunk = true;
|
|
e->xChunk = x;
|
|
e->yChunk = yc;
|
|
e->zChunk = z;
|
|
entityBlocks[yc].push_back(e);
|
|
}
|
|
|
|
void LevelChunk::removeEntity( Entity* e )
|
|
{
|
|
removeEntity(e, e->yChunk);
|
|
}
|
|
|
|
void LevelChunk::removeEntity( Entity* e, int yc )
|
|
{
|
|
if (yc < 0) yc = 0;
|
|
if (yc >= EntityBlocksArraySize) yc = EntityBlocksArraySize - 1;
|
|
|
|
EntityList::iterator newEnd = std::remove( entityBlocks[yc].begin(), entityBlocks[yc].end(), e);
|
|
entityBlocks[yc].erase(newEnd, entityBlocks[yc].end());
|
|
}
|
|
|
|
bool LevelChunk::isSkyLit( int x, int y, int z )
|
|
{
|
|
return y >= (heightmap[z << 4 | x] & 0xff);
|
|
}
|
|
|
|
void LevelChunk::load()
|
|
{
|
|
loaded = true;
|
|
/* level->tileEntityList.addAll(tileEntities.values());
|
|
for (int i = 0; i < entityBlocks.length; i++) {
|
|
level->addEntities(entityBlocks[i]);
|
|
}
|
|
*/
|
|
}
|
|
|
|
void LevelChunk::unload()
|
|
{
|
|
loaded = false;
|
|
/* level->tileEntityList.removeAll(tileEntities.values());
|
|
for (int i = 0; i < entityBlocks.length; i++) {
|
|
level->removeEntities(entityBlocks[i]);
|
|
}
|
|
*/
|
|
}
|
|
|
|
void LevelChunk::markUnsaved()
|
|
{
|
|
this->unsaved = true;
|
|
}
|
|
|
|
void LevelChunk::getEntities( Entity* except, const AABB& bb, std::vector<Entity*>& es )
|
|
{
|
|
int yc0 = Mth::floor((bb.y0 - 2) / 16);
|
|
int yc1 = Mth::floor((bb.y1 + 2) / 16);
|
|
if (yc0 < 0) yc0 = 0;
|
|
if (yc1 >= EntityBlocksArraySize) yc1 = EntityBlocksArraySize - 1;
|
|
for (int yc = yc0; yc <= yc1; yc++) {
|
|
std::vector<Entity*>& entities = entityBlocks[yc];
|
|
for (unsigned int i = 0; i < entities.size(); i++) {
|
|
Entity* e = entities[i];
|
|
if (e != except && e->bb.intersects(bb)){
|
|
es.push_back(e);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void LevelChunk::getEntitiesOfType( int entityType, const AABB& bb, EntityList& list )
|
|
{
|
|
int yc0 = Mth::floor((bb.y0 - 2) / 16);
|
|
int yc1 = Mth::floor((bb.y1 + 2) / 16);
|
|
if (yc0 < 0) {
|
|
yc0 = 0;
|
|
} else if (yc0 >= EntityBlocksArraySize) {
|
|
yc0 = EntityBlocksArraySize - 1;
|
|
}
|
|
if (yc1 >= EntityBlocksArraySize) {
|
|
yc1 = EntityBlocksArraySize - 1;
|
|
} else if (yc1 < 0) {
|
|
yc1 = 0;
|
|
}
|
|
for (int yc = yc0; yc <= yc1; yc++) {
|
|
std::vector<Entity*>& entities = entityBlocks[yc];
|
|
for (unsigned int i = 0; i < entities.size(); i++) {
|
|
Entity* e = entities[i];
|
|
if (e->getEntityTypeId() == entityType)
|
|
list.push_back(e);
|
|
//if (baseClass.isAssignableFrom(e.getClass()) && e.bb.intersects(bb)) es.add(e);
|
|
}
|
|
}
|
|
}
|
|
|
|
void LevelChunk::getEntitiesOfClass( int type, const AABB& bb, EntityList& list )
|
|
{
|
|
int yc0 = Mth::floor((bb.y0 - 2) / 16);
|
|
int yc1 = Mth::floor((bb.y1 + 2) / 16);
|
|
if (yc0 < 0) {
|
|
yc0 = 0;
|
|
} else if (yc0 >= EntityBlocksArraySize) {
|
|
yc0 = EntityBlocksArraySize - 1;
|
|
}
|
|
if (yc1 >= EntityBlocksArraySize) {
|
|
yc1 = EntityBlocksArraySize - 1;
|
|
} else if (yc1 < 0) {
|
|
yc1 = 0;
|
|
}
|
|
for (int yc = yc0; yc <= yc1; yc++) {
|
|
std::vector<Entity*>& entities = entityBlocks[yc];
|
|
for (unsigned int i = 0; i < entities.size(); i++) {
|
|
Entity* e = entities[i];
|
|
if (e->getCreatureBaseType() == type)
|
|
list.push_back(e);
|
|
//if (baseClass.isAssignableFrom(e.getClass()) && e.bb.intersects(bb)) es.add(e);
|
|
}
|
|
}
|
|
}
|
|
|
|
int LevelChunk::countEntities()
|
|
{
|
|
int entityCount = 0;
|
|
for (int yc = 0; yc < EntityBlocksArraySize; yc++) {
|
|
entityCount += entityBlocks[yc].size();
|
|
}
|
|
return entityCount;
|
|
}
|
|
|
|
//@note: @todo @te Verify
|
|
TileEntity* LevelChunk::getTileEntity(int x, int y, int z) {
|
|
TilePos pos(x, y, z);
|
|
TEMap::iterator cit = tileEntities.find(pos);
|
|
TileEntity* tileEntity = NULL;
|
|
//bool ex = cit != tileEntities.end();
|
|
//LOGI("Getting tile entity @ %d, %d, %d. Already existing? %d (%p)\n", x, y, z, ex, ex?cit->second:0);
|
|
if (cit == tileEntities.end())
|
|
{
|
|
int t = getTile(x, y, z);
|
|
if (t <= 0 || !Tile::isEntityTile[t])
|
|
return NULL;
|
|
|
|
if (tileEntity == NULL) {
|
|
tileEntity = ((EntityTile*) Tile::tiles[t])->newTileEntity();
|
|
level->setTileEntity(xt + x, y, zt + z, tileEntity);
|
|
}
|
|
// @attn @bug @fix: Don't go via level->setTileEntity since we
|
|
// know this tile is loaded if we are here
|
|
//cit = tileEntities.find(pos);
|
|
//tileEntity = (cit != tileEntities.end())? cit->second : NULL;
|
|
}
|
|
else {
|
|
tileEntity = cit->second;
|
|
}
|
|
if (tileEntity != NULL && tileEntity->isRemoved()) {
|
|
tileEntities.erase(cit);
|
|
return NULL;
|
|
}
|
|
|
|
return tileEntity;
|
|
}
|
|
|
|
bool LevelChunk::hasTileEntityAt( int x, int y, int z )
|
|
{
|
|
return tileEntities.find(TilePos(x, y, z)) != tileEntities.end();
|
|
}
|
|
bool LevelChunk::hasTileEntityAt( TileEntity* te )
|
|
{
|
|
return tileEntities.find(TilePos(te->x & 15, te->y, te->z & 15)) != tileEntities.end();
|
|
}
|
|
|
|
void LevelChunk::addTileEntity(TileEntity* te) {
|
|
|
|
int xx = te->x - xt;
|
|
int yy = te->y;
|
|
int zz = te->z - zt;
|
|
setTileEntity(xx, yy, zz, te);
|
|
if (loaded) {
|
|
level->tileEntities.push_back(te);
|
|
}
|
|
}
|
|
|
|
void LevelChunk::setTileEntity(int x, int y, int z, TileEntity* tileEntity)
|
|
{
|
|
tileEntity->setLevelAndPos(level, xt + x, y, zt + z);
|
|
int t = getTile(x, y, z);
|
|
if (t == 0 || !Tile::isEntityTile[t]) {
|
|
LOGW("Attempted to place a tile entity where there was no entity tile! %d, %d, %d\n",
|
|
tileEntity->x, tileEntity->y, tileEntity->z);
|
|
return;
|
|
}
|
|
|
|
tileEntity->clearRemoved();
|
|
tileEntities.insert(std::make_pair(TilePos(x, y, z), tileEntity));
|
|
}
|
|
|
|
void LevelChunk::removeTileEntity(int x, int y, int z) {
|
|
if (loaded) {
|
|
TilePos pos(x, y, z);
|
|
TEMap::iterator cit = tileEntities.find(pos);
|
|
if (cit != tileEntities.end()) {
|
|
cit->second->setRemoved();
|
|
|
|
if (!level->isClientSide) {
|
|
for (unsigned int i = 0; i < level->players.size(); ++i) {
|
|
level->players[i]->tileEntityDestroyed(cit->second->runningId);
|
|
}
|
|
}
|
|
tileEntities.erase(cit);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
int LevelChunk::getBlocksAndData( unsigned char* data, int x0, int y0, int z0, int x1, int y1, int z1, int p )
|
|
{
|
|
int len = y1 - y0;
|
|
for (int x = x0; x < x1; x++)
|
|
for (int z = z0; z < z1; z++) {
|
|
int slot = x << 11 | z << 7 | y0;
|
|
memcpy(data + p, blocks + slot, len); //System.arraycopy(blocks, slot, data, p, len);
|
|
p += len;
|
|
}
|
|
|
|
len = (y1 - y0) / 2;
|
|
for (int x = x0; x < x1; x++)
|
|
for (int z = z0; z < z1; z++) {
|
|
int slot = (x << 11 | z << 7 | y0) >> 1;
|
|
memcpy(data + p, this->data.data + slot, len); //System.arraycopy(this->data.data, slot, data, p, len);
|
|
p += len;
|
|
}
|
|
|
|
//len = (y1 - y0) / 2;
|
|
for (int x = x0; x < x1; x++)
|
|
for (int z = z0; z < z1; z++) {
|
|
int slot = (x << 11 | z << 7 | y0) >> 1;
|
|
memcpy(data + p, blockLight.data + slot, len); //System.arraycopy(blockLight.data, slot, data, p, len);
|
|
p += len;
|
|
}
|
|
|
|
//len = (y1 - y0) / 2;
|
|
for (int x = x0; x < x1; x++)
|
|
for (int z = z0; z < z1; z++) {
|
|
int slot = (x << 11 | z << 7 | y0) >> 1;
|
|
memcpy(data + p, skyLight.data + slot, len); //System.arraycopy(skyLight.data, slot, data, p, len);
|
|
p += len;
|
|
}
|
|
|
|
return p;
|
|
}
|
|
|
|
int LevelChunk::setBlocksAndData( unsigned char* data, int x0, int y0, int z0, int x1, int y1, int z1, int p )
|
|
{
|
|
int len = y1 - y0;
|
|
for (int x = x0; x < x1; x++)
|
|
for (int z = z0; z < z1; z++) {
|
|
int slot = x << 11 | z << 7 | y0;
|
|
memcpy(blocks + slot, data + p, len); //System.arraycopy(data, p, blocks, slot, len);
|
|
p += len;
|
|
}
|
|
|
|
recalcHeightmapOnly();
|
|
|
|
len = (y1 - y0) / 2;
|
|
for (int x = x0; x < x1; x++)
|
|
for (int z = z0; z < z1; z++) {
|
|
int slot = (x << 11 | z << 7 | y0) >> 1;
|
|
memcpy(this->data.data + slot, data + p, len); //System.arraycopy(data, p, this->data.data, slot, len);
|
|
p += len;
|
|
}
|
|
|
|
//len = (y1 - y0) / 2;
|
|
for (int x = x0; x < x1; x++)
|
|
for (int z = z0; z < z1; z++) {
|
|
int slot = (x << 11 | z << 7 | y0) >> 1;
|
|
memcpy(blockLight.data + slot, data + p, len); //System.arraycopy(data, p, blockLight.data, slot, len);
|
|
p += len;
|
|
}
|
|
|
|
//len = (y1 - y0) / 2;
|
|
for (int x = x0; x < x1; x++)
|
|
for (int z = z0; z < z1; z++) {
|
|
int slot = (x << 11 | z << 7 | y0) >> 1;
|
|
memcpy(skyLight.data + slot, data + p, len); //System.arraycopy(data, p, skyLight.data, slot, len);
|
|
p += len;
|
|
}
|
|
|
|
return p;
|
|
}
|
|
|
|
bool LevelChunk::isEmpty()
|
|
{
|
|
return false;
|
|
}
|
|
|
|
const LevelChunk::TEMap& LevelChunk::getTileEntityMap() const {
|
|
return tileEntities;
|
|
}
|