diff options
| author | daoge <3523206925@qq.com> | 2026-03-03 03:04:10 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-03-03 03:04:10 +0800 |
| commit | b3feddfef372618c8a9d7a0abcaf18cfad866c18 (patch) | |
| tree | 267761c3bb39241ba5c347bfbe2254d06686e287 /Minecraft.World/LevelChunk.cpp | |
| parent | 84c31a2331f7a0ec85b9d438992e244f60e5020f (diff) | |
feat: TU19 (Dec 2014) Features & Content (#155)
* try to resolve merge conflict
* feat: TU19 (Dec 2014) Features & Content (#32)
* December 2014 files
* Working release build
* Fix compilation issues
* Add sound to Windows64Media
* Add DLC content and force Tutorial DLC
* Revert "Add DLC content and force Tutorial DLC"
This reverts commit 97a43994725008e35fceb984d5549df9c8cea470.
* Disable broken light packing
* Disable breakpoint during DLC texture map load
Allows DLC loading but the DLC textures are still broken
* Fix post build not working
* ...
* fix vs2022 build
* fix cmake build
---------
Co-authored-by: Loki <lokirautio@gmail.com>
Diffstat (limited to 'Minecraft.World/LevelChunk.cpp')
| -rw-r--r-- | Minecraft.World/LevelChunk.cpp | 851 |
1 files changed, 472 insertions, 379 deletions
diff --git a/Minecraft.World/LevelChunk.cpp b/Minecraft.World/LevelChunk.cpp index 823c7c4c..920fdfc1 100644 --- a/Minecraft.World/LevelChunk.cpp +++ b/Minecraft.World/LevelChunk.cpp @@ -11,10 +11,13 @@ #include "SparseLightStorage.h" #include "BlockReplacements.h" #include "LevelChunk.h" +#include "BasicTypeContainers.h" #include "..\Minecraft.Client\MinecraftServer.h" #include "..\Minecraft.Client\ServerLevel.h" #include "..\Minecraft.Client\ServerChunkCache.h" #include "..\Minecraft.Client\GameRenderer.h" +#include "ItemEntity.h" +#include "Minecart.h" #ifdef __PS3__ #include "C4JSpursJob.h" @@ -25,10 +28,10 @@ CRITICAL_SECTION LevelChunk::m_csSharing; #endif #ifdef _ENTITIES_RW_SECTION - // AP - use a RW critical section so we can have multiple threads reading the same data to avoid a clash - CRITICAL_RW_SECTION LevelChunk::m_csEntities; +// AP - use a RW critical section so we can have multiple threads reading the same data to avoid a clash +CRITICAL_RW_SECTION LevelChunk::m_csEntities; #else - CRITICAL_SECTION LevelChunk::m_csEntities; +CRITICAL_SECTION LevelChunk::m_csEntities; #endif CRITICAL_SECTION LevelChunk::m_csTileEntities; bool LevelChunk::touchedSky = false; @@ -78,11 +81,11 @@ void LevelChunk::init(Level *level, int x, int z) // 4J Stu - Not using this checkLightPosition = 0; //LIGHT_CHECK_MAX_POS; - this->level = level; - this->x = x; - this->z = z; + this->level = level; + this->x = x; + this->z = z; MemSect(1); - heightmap = byteArray(16 * 16); + heightmap = byteArray(16 * 16); #ifdef _ENTITIES_RW_SECTION EnterCriticalRWSection(&m_csEntities, true); #else @@ -90,8 +93,8 @@ void LevelChunk::init(Level *level, int x, int z) #endif for (int i = 0; i < ENTITY_BLOCKS_LENGTH; i++) { - entityBlocks[i] = new vector<shared_ptr<Entity> >(); - } + entityBlocks[i] = new vector<shared_ptr<Entity> >(); + } #ifdef _ENTITIES_RW_SECTION LeaveCriticalRWSection(&m_csEntities, true); #else @@ -100,6 +103,9 @@ void LevelChunk::init(Level *level, int x, int z) MemSect(0); + lowestHeightmap = 256; + inhabitedTime = 0; + // Optimisation brought forward from 1.8.2, change from int to unsigned char & this special value changed from -999 to 255 for(int i = 0; i < 16 * 16; i++ ) { @@ -124,11 +130,11 @@ void LevelChunk::init(Level *level, int x, int z) // This ctor is used for loading a save into LevelChunk::LevelChunk(Level *level, int x, int z) : ENTITY_BLOCKS_LENGTH( Level::maxBuildHeight/16 ) { - init(level, x, z); + init(level, x, z); lowerBlocks = new CompressedTileStorage(); - lowerData = NULL; - lowerSkyLight = NULL; - lowerBlockLight = NULL; + lowerData = NULL; + lowerSkyLight = NULL; + lowerBlockLight = NULL; serverTerrainPopulated = NULL; if(Level::maxBuildHeight > Level::COMPRESSED_CHUNK_SECTION_HEIGHT) @@ -180,8 +186,8 @@ LevelChunk::LevelChunk(Level *level, byteArray blocks, int x, int z) : ENTITY_BL lowerSkyLight = new SparseLightStorage(true); lowerBlockLight = new SparseLightStorage(false); } -// skyLight = new DataLayer(blocks.length, level->depthBits); -// blockLight = new DataLayer(blocks.length, level->depthBits); + // skyLight = new DataLayer(blocks.length, level->depthBits); + // blockLight = new DataLayer(blocks.length, level->depthBits); if(Level::maxBuildHeight > Level::COMPRESSED_CHUNK_SECTION_HEIGHT) { @@ -209,16 +215,16 @@ LevelChunk::LevelChunk(Level *level, byteArray blocks, int x, int z) : ENTITY_BL // The original version this is shared from owns all the data that is shared into this copy, so it isn't deleted in the dtor. LevelChunk::LevelChunk(Level *level, int x, int z, LevelChunk *lc) : ENTITY_BLOCKS_LENGTH( Level::maxBuildHeight/16 ) { - init(level, x, z); + init(level, x, z); // 4J Stu - Copy over the biome data memcpy(biomes.data,lc->biomes.data,biomes.length); #ifdef SHARING_ENABLED - lowerBlocks = lc->lowerBlocks; - lowerData = lc->lowerData; - lowerSkyLight = new SparseLightStorage( lc->lowerSkyLight ); - lowerBlockLight = new SparseLightStorage( lc->lowerBlockLight ); + lowerBlocks = lc->lowerBlocks; + lowerData = lc->lowerData; + lowerSkyLight = new SparseLightStorage( lc->lowerSkyLight ); + lowerBlockLight = new SparseLightStorage( lc->lowerBlockLight ); upperBlocks = lc->upperBlocks; upperData = lc->upperData; upperSkyLight = new SparseLightStorage( lc->upperSkyLight ); @@ -454,12 +460,12 @@ LevelChunk::~LevelChunk() bool LevelChunk::isAt(int x, int z) { - return x == this->x && z == this->z; + return x == this->x && z == this->z; } int LevelChunk::getHeightmap(int x, int z) { - return heightmap[z << 4 | x] & 0xff; + return heightmap[z << 4 | x] & 0xff; } int LevelChunk::getHighestSectionPosition() @@ -499,7 +505,7 @@ void LevelChunk::recalcHeightmapOnly() #ifdef __PSVITA__ int Index = ( x << 11 ) + ( z << 7 ); int offset = Level::COMPRESSED_CHUNK_SECTION_TILES; - y = 127; + y = 127; while (y > 0 && Tile::lightBlock[blockData[Index + offset + (y - 1)]] == 0) // 4J - was blocks->get() was blocks[p + y - 1] { y--; @@ -533,7 +539,7 @@ void LevelChunk::recalcHeightmapOnly() this->setUnsaved(true); #ifdef __PSVITA__ - delete blockData.data; + delete blockData.data; #endif } @@ -544,18 +550,19 @@ void LevelChunk::recalcHeightmap() byteArray blockData = byteArray(Level::CHUNK_TILE_COUNT); getBlockData(blockData); #endif + lowestHeightmap = Integer::MAX_VALUE; - int min = Level::maxBuildHeight - 1; - for (int x = 0; x < 16; x++) - for (int z = 0; z < 16; z++) + int min = Level::maxBuildHeight - 1; + for (int x = 0; x < 16; x++) + for (int z = 0; z < 16; z++) { - int y = Level::maxBuildHeight - 1; -// int p = x << level->depthBitsPlusFour | z << level->depthBits; // 4J - removed - + int y = Level::maxBuildHeight - 1; + // int p = x << level->depthBitsPlusFour | z << level->depthBits; // 4J - removed + #ifdef __PSVITA__ int Index = ( x << 11 ) + ( z << 7 ); int offset = Level::COMPRESSED_CHUNK_SECTION_TILES; - y = 127; + y = 127; while (y > 0 && Tile::lightBlock[blockData[Index + offset + (y - 1)]] == 0) // 4J - was blocks->get() was blocks[p + y - 1] { y--; @@ -575,32 +582,33 @@ void LevelChunk::recalcHeightmap() } #else CompressedTileStorage *blocks = (y-1) >= Level::COMPRESSED_CHUNK_SECTION_HEIGHT?upperBlocks : lowerBlocks; - while (y > 0 && Tile::lightBlock[blocks->get(x,(y-1) % Level::COMPRESSED_CHUNK_SECTION_HEIGHT,z) & 0xff] == 0) // 4J - was blocks->get() was blocks[p + y - 1] + while (y > 0 && Tile::lightBlock[blocks->get(x,(y-1) % Level::COMPRESSED_CHUNK_SECTION_HEIGHT,z) & 0xff] == 0) // 4J - was blocks->get() was blocks[p + y - 1] { - y--; + y--; blocks = (y-1) >= Level::COMPRESSED_CHUNK_SECTION_HEIGHT?upperBlocks : lowerBlocks; } #endif - heightmap[z << 4 | x] = (byte) y; - if (y < min) min = y; + heightmap[z << 4 | x] = (byte) y; + if (y < min) min = y; + if (y < lowestHeightmap) lowestHeightmap = y; - if (!level->dimension->hasCeiling) + if (!level->dimension->hasCeiling) { - int br = Level::MAX_BRIGHTNESS; + int br = Level::MAX_BRIGHTNESS; int yy = Level::maxBuildHeight - 1; #ifdef __PSVITA__ int offset = Level::COMPRESSED_CHUNK_SECTION_TILES; SparseLightStorage *skyLight = upperSkyLight; yy = 127; - do + do { - br -= Tile::lightBlock[blockData[Index + offset + yy]]; // 4J - blocks->get() was blocks[p + yy] - if (br > 0) + br -= Tile::lightBlock[blockData[Index + offset + yy]]; // 4J - blocks->get() was blocks[p + yy] + if (br > 0) { - skyLight->set(x, yy, z, br); - } - yy--; - } while (yy > 0 && br > 0); + skyLight->set(x, yy, z, br); + } + yy--; + } while (yy > 0 && br > 0); if( yy == 0 && br > 0 ) { @@ -620,33 +628,33 @@ void LevelChunk::recalcHeightmap() #else CompressedTileStorage *blocks = yy >= Level::COMPRESSED_CHUNK_SECTION_HEIGHT?upperBlocks : lowerBlocks; SparseLightStorage *skyLight = yy >= Level::COMPRESSED_CHUNK_SECTION_HEIGHT? upperSkyLight : lowerSkyLight; - do + do { - br -= Tile::lightBlock[blocks->get(x,(yy % Level::COMPRESSED_CHUNK_SECTION_HEIGHT),z) & 0xff]; // 4J - blocks->get() was blocks[p + yy] - if (br > 0) + br -= Tile::lightBlock[blocks->get(x,(yy % Level::COMPRESSED_CHUNK_SECTION_HEIGHT),z) & 0xff]; // 4J - blocks->get() was blocks[p + yy] + if (br > 0) { - skyLight->set(x, (yy % Level::COMPRESSED_CHUNK_SECTION_HEIGHT), z, br); - } - yy--; + skyLight->set(x, (yy % Level::COMPRESSED_CHUNK_SECTION_HEIGHT), z, br); + } + yy--; blocks = yy >= Level::COMPRESSED_CHUNK_SECTION_HEIGHT?upperBlocks : lowerBlocks; skyLight = yy >= Level::COMPRESSED_CHUNK_SECTION_HEIGHT? upperSkyLight : lowerSkyLight; - } while (yy > 0 && br > 0); + } while (yy > 0 && br > 0); #endif - } - } + } + } - this->minHeight = min; + this->minHeight = min; - for (int x = 0; x < 16; x++) - for (int z = 0; z < 16; z++) - { - lightGaps(x, z); - } + for (int x = 0; x < 16; x++) + for (int z = 0; z < 16; z++) + { + lightGaps(x, z); + } - this->setUnsaved(true); + this->setUnsaved(true); #ifdef __PSVITA__ - delete blockData.data; + delete blockData.data; #endif } @@ -656,11 +664,11 @@ void LevelChunk::recalcHeightmap() void LevelChunk::lightLava() { if( !emissiveAdded ) return; - + for (int x = 0; x < 16; x++) for (int z = 0; z < 16; z++) { -// int p = x << 11 | z << 7; // 4J - removed + // int p = x << 11 | z << 7; // 4J - removed int ymax = getHeightmap(x,z); for (int y = 0; y < Level::COMPRESSED_CHUNK_SECTION_HEIGHT; y++) { @@ -668,7 +676,7 @@ void LevelChunk::lightLava() int emit = Tile::lightEmission[blocks->get(x,y,z)]; // 4J - blocks->get() was blocks[p + y] if( emit > 0 ) { -// printf("(%d,%d,%d)",this->x * 16 + x, y, this->z * 16 + z); + // printf("(%d,%d,%d)",this->x * 16 + x, y, this->z * 16 + z); // We'll be calling this function for a lot of chunks as they are post-processed. For every chunk that is // post-processed we're calling this for each of its neighbours in case some post-processing also created something // that needed lighting outside the starting chunk. Because of this, do a quick test on any emissive blocks that have @@ -681,7 +689,7 @@ void LevelChunk::lightLava() } } } - emissiveAdded = false; + emissiveAdded = false; } void LevelChunk::lightGaps(int x, int z) @@ -704,19 +712,19 @@ void LevelChunk::recheckGaps(bool bForce) int maxXZ = (level->dimension->getXZSize() * 16 ) / 2 - 1; // 4J - note - this test will currently return true for chunks at the edge of our world. Making further checks inside the loop now to address this issue. - if (level->hasChunksAt(x * 16 + 8, Level::maxBuildHeight / 2, z * 16 + 8, 16)) + if (level->hasChunksAt(x * 16 + 8, Level::maxBuildHeight / 2, z * 16 + 8, 16)) { - for (int x = 0; x < 16; x++) - for (int z = 0; z < 16; z++) + for (int x = 0; x < 16; x++) + for (int z = 0; z < 16; z++) { int slot = ( x >> 1 ) | (z * 8); int shift = ( x & 1 ) * 4; - if (bForce || ( columnFlags[slot] & ( eColumnFlag_recheck << shift ) ) ) + if (bForce || ( columnFlags[slot] & ( eColumnFlag_recheck << shift ) ) ) { - columnFlags[slot] &= ~( eColumnFlag_recheck << shift ); - int height = getHeightmap(x, z); - int xOffs = (this->x * 16) + x; - int zOffs = (this->z * 16) + z; + columnFlags[slot] &= ~( eColumnFlag_recheck << shift ); + int height = getHeightmap(x, z); + int xOffs = (this->x * 16) + x; + int zOffs = (this->z * 16) + z; // 4J - rewritten this to make sure that the minimum neighbour height which is calculated doesn't involve getting any heights from beyond the edge of the world, // which can lead to large, very expensive, non-existent cliff edges to be lit @@ -741,7 +749,7 @@ void LevelChunk::recheckGaps(bool bForce) int n = level->getHeightmap(xOffs, zOffs + 1); if ( n < nmin ) nmin = n; } - lightGap(xOffs, zOffs, nmin); + lightGap(xOffs, zOffs, nmin); if( !bForce ) // 4J - if doing a full forced thing over every single column, we don't need to do these offset checks too { @@ -751,77 +759,77 @@ void LevelChunk::recheckGaps(bool bForce) if( zOffs + 1 <= maxXZ ) lightGap(xOffs, zOffs + 1, height); } hasGapsToCheck = false; - } - } - } + } + } + } } void LevelChunk::lightGap(int x, int z, int source) { - int height = level->getHeightmap(x, z); + int height = level->getHeightmap(x, z); - if (height > source) + if (height > source) { - lightGap(x, z, source, height + 1); - } + lightGap(x, z, source, height + 1); + } else if (height < source) { - lightGap(x, z, height, source + 1); - } + lightGap(x, z, height, source + 1); + } } void LevelChunk::lightGap(int x, int z, int y1, int y2) { - if (y2 > y1) + if (y2 > y1) { - if (level->hasChunksAt(x, Level::maxBuildHeight / 2, z, 16)) + if (level->hasChunksAt(x, Level::maxBuildHeight / 2, z, 16)) { - for (int y = y1; y < y2; y++) + for (int y = y1; y < y2; y++) { - level->checkLight(LightLayer::Sky, x, y, z); - } - this->setUnsaved(true); - } - } + level->checkLight(LightLayer::Sky, x, y, z); + } + this->setUnsaved(true); + } + } } 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 yOld = heightmap[z << 4 | x] & 0xff; + int y = yOld; + if (yStart > yOld) y = yStart; + + // int p = x << level->depthBitsPlusFour | z << level->depthBits; // 4J - removed -// int p = x << level->depthBitsPlusFour | z << level->depthBits; // 4J - removed - CompressedTileStorage *blocks = (y-1) >= Level::COMPRESSED_CHUNK_SECTION_HEIGHT?upperBlocks : lowerBlocks; while (y > 0 && Tile::lightBlock[blocks->get(x,(y-1) % Level::COMPRESSED_CHUNK_SECTION_HEIGHT,z) & 0xff] == 0) // 4J - blocks->get() was blocks[p + y - 1] { - y--; + y--; blocks = (y-1) >= Level::COMPRESSED_CHUNK_SECTION_HEIGHT?upperBlocks : lowerBlocks; } - if (y == yOld) return; + if (y == yOld) return; -// level->lightColumnChanged(x, z, y, yOld); // 4J - this call moved below & corrected - see comment further down - heightmap[z << 4 | x] = (byte) y; + // level->lightColumnChanged(x, z, y, yOld); // 4J - this call moved below & corrected - see comment further down + heightmap[z << 4 | x] = (byte) y; - if (y < minHeight) + if (y < minHeight) { - minHeight = y; - } + minHeight = y; + } else { - int min = Level::maxBuildHeight - 1; - for (int _x = 0; _x < 16; _x++) - for (int _z = 0; _z < 16; _z++) + int min = Level::maxBuildHeight - 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 ((heightmap[_z << 4 | _x] & 0xff) < min) min = (heightmap[_z << 4 | _x] & 0xff); + } + this->minHeight = min; + } - int xOffs = (this->x * 16) + x; - int zOffs = (this->z * 16) + z; + int xOffs = (this->x * 16) + x; + int zOffs = (this->z * 16) + z; if (!level->dimension->hasCeiling) { if (y < yOld) @@ -835,7 +843,7 @@ void LevelChunk::recalcHeight(int x, int yStart, int z) } else { // 4J - lighting change brought forward from 1.8.2 - // level->updateLight(LightLayer::Sky, xOffs, yOld, zOffs, xOffs, y, zOffs); + // level->updateLight(LightLayer::Sky, xOffs, yOld, zOffs, xOffs, y, zOffs); SparseLightStorage *skyLight = y >= Level::COMPRESSED_CHUNK_SECTION_HEIGHT? upperSkyLight : lowerSkyLight; for (int yy = yOld; yy < y; yy++) { @@ -845,7 +853,7 @@ void LevelChunk::recalcHeight(int x, int yStart, int z) } int br = 15; - + SparseLightStorage *skyLight = y >= Level::COMPRESSED_CHUNK_SECTION_HEIGHT? upperSkyLight : lowerSkyLight; while (y > 0 && br > 0) { @@ -857,7 +865,7 @@ void LevelChunk::recalcHeight(int x, int yStart, int z) if (br < 0) br = 0; skyLight->set(x, (y % Level::COMPRESSED_CHUNK_SECTION_HEIGHT), z, br); // level.updateLightIfOtherThan(LightLayer.Sky, xOffs, y, zOffs, - // -1); + // -1); } } // 4J - changed to use xOffs and zOffs rather than the (incorrect) x and z it used to, and also moved so that it happens after all the lighting should be @@ -865,15 +873,16 @@ void LevelChunk::recalcHeight(int x, int yStart, int z) level->lightColumnChanged(xOffs, zOffs, y, yOld); // 4J - lighting changes brought forward from 1.8.2 - int height = heightmap[z << 4 | x]; - int y1 = yOld; - int y2 = height; - if (y2 < y1) - { - int tmp = y1; - y1 = y2; - y2 = tmp; - } + int height = heightmap[z << 4 | x]; + int y1 = yOld; + int y2 = height; + if (y2 < y1) + { + int tmp = y1; + y1 = y2; + y2 = tmp; + } + if (height < lowestHeightmap) lowestHeightmap = height; if (!level->dimension->hasCeiling) { PIXBeginNamedEvent(0,"Light gaps"); @@ -885,7 +894,7 @@ void LevelChunk::recalcHeight(int x, int yStart, int z) PIXEndNamedEvent(); } - this->setUnsaved(true); + this->setUnsaved(true); } /** @@ -910,25 +919,35 @@ int LevelChunk::getTile(int x, int y, int z) bool LevelChunk::setTileAndData(int x, int y, int z, int _tile, int _data) { - byte tile = (byte) _tile; + byte tile = (byte) _tile; // Optimisation brought forward from 1.8.2, change from int to unsigned char & this special value changed from -999 to 255 - int slot = z << 4 | x; + int slot = z << 4 | x; - if (y >= ((int)rainHeights[slot]) - 1) + if (y >= ((int)rainHeights[slot]) - 1) { - rainHeights[slot] = 255; - } + rainHeights[slot] = 255; + } + + int oldHeight = heightmap[slot] & 0xff; - int oldHeight = heightmap[slot] & 0xff; - CompressedTileStorage *blocks = y >= Level::COMPRESSED_CHUNK_SECTION_HEIGHT ? upperBlocks : lowerBlocks; SparseDataStorage *data = y >= Level::COMPRESSED_CHUNK_SECTION_HEIGHT ? upperData : lowerData; int old = blocks->get(x,y % Level::COMPRESSED_CHUNK_SECTION_HEIGHT,z); int oldData = data->get(x, y % Level::COMPRESSED_CHUNK_SECTION_HEIGHT, z); - if (old == _tile && oldData == _data) return false; - int xOffs = this->x * 16 + x; - int zOffs = this->z * 16 + z; + if (old == _tile && oldData == _data) + { + // 4J Stu - Need to do this here otherwise double chests don't always work correctly + shared_ptr<TileEntity> te = getTileEntity(x, y, z); + if (te != NULL) + { + te->clearCache(); + } + + return false; + } + int xOffs = this->x * 16 + x; + int zOffs = this->z * 16 + z; if (old != 0 && !level->isClientSide) { Tile::tiles[old]->onRemoving(level, xOffs, y, zOffs, oldData); @@ -936,9 +955,9 @@ bool LevelChunk::setTileAndData(int x, int y, int z, int _tile, int _data) PIXBeginNamedEvent(0,"Chunk setting tile"); blocks->set(x,y % Level::COMPRESSED_CHUNK_SECTION_HEIGHT,z,tile); PIXEndNamedEvent(); - if (old != 0) + if (old != 0) { - if (!level->isClientSide) + if (!level->isClientSide) { Tile::tiles[old]->onRemove(level, xOffs, y, zOffs, old, oldData); } @@ -946,7 +965,7 @@ bool LevelChunk::setTileAndData(int x, int y, int z, int _tile, int _data) { level->removeTileEntity(xOffs, y, zOffs); } - } + } PIXBeginNamedEvent(0,"Chunk setting data"); data->set(x, y % Level::COMPRESSED_CHUNK_SECTION_HEIGHT, z, _data); PIXEndNamedEvent(); @@ -984,14 +1003,14 @@ bool LevelChunk::setTileAndData(int x, int y, int z, int _tile, int _data) } // level.updateLight(LightLayer.Carried, xOffs, y, zOffs, xOffs, y, - // zOffs); + // zOffs); PIXBeginNamedEvent(0,"Lighting gaps"); lightGaps(x, z); PIXEndNamedEvent(); } PIXEndNamedEvent(); data->set(x, y % Level::COMPRESSED_CHUNK_SECTION_HEIGHT, z, _data); - if (_tile != 0) + if (_tile != 0) { if (!level->isClientSide) { @@ -1008,18 +1027,18 @@ bool LevelChunk::setTileAndData(int x, int y, int z, int _tile, int _data) if(!Tile::tiles[_tile]->mayPlace(level, xOffs, y, zOffs )) { blocks->set(x,y % Level::COMPRESSED_CHUNK_SECTION_HEIGHT,z,0); -// blocks[x << level->depthBitsPlusFour | z << level->depthBits | y] = 0; + // blocks[x << level->depthBitsPlusFour | z << level->depthBits | y] = 0; } } } // AP - changed the method of EntityTile detection cos it's well slow on Vita mate -// if (_tile > 0 && dynamic_cast<EntityTile *>(Tile::tiles[_tile]) != NULL) + // if (_tile > 0 && dynamic_cast<EntityTile *>(Tile::tiles[_tile]) != NULL) if (_tile > 0 && Tile::tiles[_tile] != NULL && Tile::tiles[_tile]->isEntityTile()) { shared_ptr<TileEntity> te = getTileEntity(x, y, z); if (te == NULL) { - te = ((EntityTile *) Tile::tiles[_tile])->newTileEntity(level); + te = dynamic_cast<EntityTile *>(Tile::tiles[_tile])->newTileEntity(level); //app.DebugPrintf("%s: Setting tile id %d, created tileEntity type %d\n", level->isClientSide?"Client":"Server", _tile, te->GetType()); level->setTileEntity(xOffs, y, zOffs, te); } @@ -1031,7 +1050,7 @@ bool LevelChunk::setTileAndData(int x, int y, int z, int _tile, int _data) } } // AP - changed the method of EntityTile detection cos it's well slow on Vita mate -// else if (old > 0 && dynamic_cast<EntityTile *>(Tile::tiles[old]) != NULL) + // else if (old > 0 && dynamic_cast<EntityTile *>(Tile::tiles[old]) != NULL) else if (old > 0 && Tile::tiles[_tile] != NULL && Tile::tiles[_tile]->isEntityTile()) { shared_ptr<TileEntity> te = getTileEntity(x, y, z); @@ -1039,10 +1058,10 @@ bool LevelChunk::setTileAndData(int x, int y, int z, int _tile, int _data) { te->clearCache(); } - } + } - this->setUnsaved(true); - return true; + this->setUnsaved(true); + return true; } bool LevelChunk::setTile(int x, int y, int z, int _tile) @@ -1060,17 +1079,17 @@ int LevelChunk::getData(int x, int y, int z) bool LevelChunk::setData(int x, int y, int z, int val, int mask, bool *maskedBitsChanged) { SparseDataStorage *data = y >= Level::COMPRESSED_CHUNK_SECTION_HEIGHT ? upperData : lowerData; - this->setUnsaved(true); + this->setUnsaved(true); int old = data->get(x, y % Level::COMPRESSED_CHUNK_SECTION_HEIGHT, z); *maskedBitsChanged = ( ( old & mask ) != ( val & mask ) ); - if (old == val) + if (old == val) { - return false; - } + return false; + } - data->set(x, y % Level::COMPRESSED_CHUNK_SECTION_HEIGHT, z, val); + data->set(x, y % Level::COMPRESSED_CHUNK_SECTION_HEIGHT, z, val); int _tile = getTile(x, y, z); if (_tile > 0 && dynamic_cast<EntityTile *>( Tile::tiles[_tile] ) != NULL) { @@ -1086,19 +1105,23 @@ bool LevelChunk::setData(int x, int y, int z, int val, int mask, bool *maskedBit int LevelChunk::getBrightness(LightLayer::variety layer, int x, int y, int z) { - if (layer == LightLayer::Sky) + if (layer == LightLayer::Sky) { + if (level->dimension->hasCeiling) + { + return 0; + } SparseLightStorage *skyLight = y >= Level::COMPRESSED_CHUNK_SECTION_HEIGHT ? upperSkyLight : lowerSkyLight; if(!skyLight) return 0; return skyLight->get(x, y % Level::COMPRESSED_CHUNK_SECTION_HEIGHT, z); } - else if (layer == LightLayer::Block) + else if (layer == LightLayer::Block) { SparseLightStorage *blockLight = y >= Level::COMPRESSED_CHUNK_SECTION_HEIGHT ? upperBlockLight : lowerBlockLight; if(!blockLight) return 0; return blockLight->get(x, y % Level::COMPRESSED_CHUNK_SECTION_HEIGHT, z); } - else return 0; + else return 0; } // 4J added @@ -1116,12 +1139,12 @@ void LevelChunk::getNeighbourBrightnesses(int *brightnesses, LightLayer::variety brightnesses[5] = light->get(x, y % Level::COMPRESSED_CHUNK_SECTION_HEIGHT, z + 1); } - + if( layer == LightLayer::Sky ) light = (y-1) >= Level::COMPRESSED_CHUNK_SECTION_HEIGHT ? upperSkyLight : lowerSkyLight; else light = (y-1) >= Level::COMPRESSED_CHUNK_SECTION_HEIGHT ? upperBlockLight : lowerBlockLight; if(light) brightnesses[2] = light->get(x, (y - 1) % Level::COMPRESSED_CHUNK_SECTION_HEIGHT, z); - + if( layer == LightLayer::Sky ) light = (y+1) >= Level::COMPRESSED_CHUNK_SECTION_HEIGHT ? upperSkyLight : lowerSkyLight; else light = (y+1) >= Level::COMPRESSED_CHUNK_SECTION_HEIGHT ? upperBlockLight : lowerBlockLight; if(light) brightnesses[3] = light->get(x, (y + 1) % Level::COMPRESSED_CHUNK_SECTION_HEIGHT, z); @@ -1129,8 +1152,8 @@ void LevelChunk::getNeighbourBrightnesses(int *brightnesses, LightLayer::variety void LevelChunk::setBrightness(LightLayer::variety layer, int x, int y, int z, int brightness) { - this->setUnsaved(true); - if (layer == LightLayer::Sky) + this->setUnsaved(true); + if (layer == LightLayer::Sky) { if(!level->dimension->hasCeiling) { @@ -1138,7 +1161,7 @@ void LevelChunk::setBrightness(LightLayer::variety layer, int x, int y, int z, i skyLight->set(x, y % Level::COMPRESSED_CHUNK_SECTION_HEIGHT, z, brightness); } } - else if (layer == LightLayer::Block) + else if (layer == LightLayer::Block) { SparseLightStorage *blockLight = y >= Level::COMPRESSED_CHUNK_SECTION_HEIGHT ? upperBlockLight : lowerBlockLight; blockLight->set(x, y % Level::COMPRESSED_CHUNK_SECTION_HEIGHT, z, brightness); @@ -1149,42 +1172,42 @@ int LevelChunk::getRawBrightness(int x, int y, int z, int skyDampen) { SparseLightStorage *skyLight = y >= Level::COMPRESSED_CHUNK_SECTION_HEIGHT ? upperSkyLight : lowerSkyLight; int light = level->dimension->hasCeiling ? 0 : skyLight->get(x, y % Level::COMPRESSED_CHUNK_SECTION_HEIGHT, z); - if (light > 0) LevelChunk::touchedSky = true; - light -= skyDampen; + if (light > 0) touchedSky = true; + light -= skyDampen; SparseLightStorage *blockLight = y >= Level::COMPRESSED_CHUNK_SECTION_HEIGHT ? upperBlockLight : lowerBlockLight; int block = blockLight->get(x, y % Level::COMPRESSED_CHUNK_SECTION_HEIGHT, z); - if (block > light) light = block; + if (block > light) light = block; - /* - * int xd = (absFloor(level.player.x-(this->x*16+x))); int yd = - * (absFloor(level.player.y-(y))); int zd = - * (absFloor(level.player.z-(this->z*16+z))); int dd = xd+yd+zd; if - * (dd<15){ int carried = 15-dd; if (carried<0) carried = 0; if - * (carried>15) carried = 15; if (carried > light) light = carried; } - */ + /* + * int xd = (absFloor(level.player.x-(this->x*16+x))); int yd = + * (absFloor(level.player.y-(y))); int zd = + * (absFloor(level.player.z-(this->z*16+z))); int dd = xd+yd+zd; if + * (dd<15){ int carried = 15-dd; if (carried<0) carried = 0; if + * (carried>15) carried = 15; if (carried > light) light = carried; } + */ - return light; + return light; } void LevelChunk::addEntity(shared_ptr<Entity> e) { - lastSaveHadEntities = true; + lastSaveHadEntities = true; - int xc = Mth::floor(e->x / 16); - int zc = Mth::floor(e->z / 16); - if (xc != this->x || zc != this->z) + int xc = Mth::floor(e->x / 16); + int zc = Mth::floor(e->z / 16); + if (xc != this->x || zc != this->z) { app.DebugPrintf("Wrong location!"); -// System.out.println("Wrong location! " + e); -// Thread.dumpStack(); - } - int yc = Mth::floor(e->y / 16); - if (yc < 0) yc = 0; + // System.out.println("Wrong location! " + e); + // Thread.dumpStack(); + } + int yc = Mth::floor(e->y / 16); + if (yc < 0) yc = 0; if (yc >= ENTITY_BLOCKS_LENGTH) yc = ENTITY_BLOCKS_LENGTH - 1; - e->inChunk = true; - e->xChunk = x; - e->yChunk = yc; - e->zChunk = z; + e->inChunk = true; + e->xChunk = x; + e->yChunk = yc; + e->zChunk = z; #ifdef _ENTITIES_RW_SECTION EnterCriticalRWSection(&m_csEntities, true); @@ -1202,13 +1225,13 @@ void LevelChunk::addEntity(shared_ptr<Entity> e) void LevelChunk::removeEntity(shared_ptr<Entity> e) { - removeEntity(e, e->yChunk); + removeEntity(e, e->yChunk); } void LevelChunk::removeEntity(shared_ptr<Entity> e, int yc) { - if (yc < 0) yc = 0; - if (yc >= ENTITY_BLOCKS_LENGTH) yc = ENTITY_BLOCKS_LENGTH - 1; + if (yc < 0) yc = 0; + if (yc >= ENTITY_BLOCKS_LENGTH) yc = ENTITY_BLOCKS_LENGTH - 1; #ifdef _ENTITIES_RW_SECTION EnterCriticalRWSection(&m_csEntities, true); @@ -1246,27 +1269,27 @@ void LevelChunk::removeEntity(shared_ptr<Entity> e, int yc) bool LevelChunk::isSkyLit(int x, int y, int z) { - return y >= (heightmap[z << 4 | x] & 0xff); + return y >= (heightmap[z << 4 | x] & 0xff); } void LevelChunk::skyBrightnessChanged() { - int x0 = this->x * 16; - int y0 = this->minHeight - 16; - int z0 = this->z * 16; - int x1 = this->x * 16 + 16; - int y1 = Level::maxBuildHeight - 1; - int z1 = this->z * 16 + 16; + int x0 = this->x * 16; + int y0 = this->minHeight - 16; + int z0 = this->z * 16; + int x1 = this->x * 16 + 16; + int y1 = Level::maxBuildHeight - 1; + int z1 = this->z * 16 + 16; - level->setTilesDirty(x0, y0, z0, x1, y1, z1); + level->setTilesDirty(x0, y0, z0, x1, y1, z1); } shared_ptr<TileEntity> LevelChunk::getTileEntity(int x, int y, int z) { - TilePos pos(x, y, z); + TilePos pos(x, y, z); // 4J Stu - Changed as we should not be using the [] accessor (causes an insert when we don't want one) - //shared_ptr<TileEntity> tileEntity = tileEntities[pos]; + //shared_ptr<TileEntity> tileEntity = tileEntities[pos]; EnterCriticalSection(&m_csTileEntities); shared_ptr<TileEntity> tileEntity = nullptr; AUTO_VAR(it, tileEntities.find(pos)); @@ -1280,20 +1303,20 @@ shared_ptr<TileEntity> LevelChunk::getTileEntity(int x, int y, int z) // which then causes new tile entities to be created if the neighbour has already been destroyed if(level->m_bDisableAddNewTileEntities) return nullptr; - int t = getTile(x, y, z); - if (t <= 0 || !Tile::tiles[t]->isEntityTile()) return nullptr; - + int t = getTile(x, y, z); + if (t <= 0 || !Tile::tiles[t]->isEntityTile()) return nullptr; + // 4J-PB changed from this in 1.7.3 //EntityTile *et = (EntityTile *) Tile::tiles[t]; - //et->onPlace(level, this->x * 16 + x, y, this->z * 16 + z); + //et->onPlace(level, this->x * 16 + x, y, this->z * 16 + z); //if (tileEntity == NULL) //{ - tileEntity = ((EntityTile *) Tile::tiles[t])->newTileEntity(level); - level->setTileEntity(this->x * 16 + x, y, this->z * 16 + z, tileEntity); + tileEntity = dynamic_cast<EntityTile *>(Tile::tiles[t])->newTileEntity(level); + level->setTileEntity(this->x * 16 + x, y, this->z * 16 + z, tileEntity); //} - //tileEntity = tileEntities[pos]; // 4J - TODO - this doesn't seem right - assignment wrong way? Check + //tileEntity = tileEntities[pos]; // 4J - TODO - this doesn't seem right - assignment wrong way? Check // 4J Stu - It should have been inserted by now, but check to be sure EnterCriticalSection(&m_csTileEntities); @@ -1303,29 +1326,29 @@ shared_ptr<TileEntity> LevelChunk::getTileEntity(int x, int y, int z) tileEntity = newIt->second; } LeaveCriticalSection(&m_csTileEntities); - } + } else { tileEntity = it->second; LeaveCriticalSection(&m_csTileEntities); } - if (tileEntity != NULL && tileEntity->isRemoved()) + if (tileEntity != NULL && tileEntity->isRemoved()) { EnterCriticalSection(&m_csTileEntities); - tileEntities.erase(pos); + tileEntities.erase(pos); LeaveCriticalSection(&m_csTileEntities); - return nullptr; - } - - return tileEntity; + return nullptr; + } + + return tileEntity; } void LevelChunk::addTileEntity(shared_ptr<TileEntity> te) { - int xx = (int)(te->x - this->x * 16); - int yy = (int)te->y; - int zz = (int)(te->z - this->z * 16); - setTileEntity(xx, yy, zz, te); + int xx = (int)(te->x - this->x * 16); + int yy = (int)te->y; + int zz = (int)(te->z - this->z * 16); + setTileEntity(xx, yy, zz, te); if( loaded ) { EnterCriticalSection(&level->m_tileEntityListCS); @@ -1336,37 +1359,39 @@ void LevelChunk::addTileEntity(shared_ptr<TileEntity> te) void LevelChunk::setTileEntity(int x, int y, int z, shared_ptr<TileEntity> tileEntity) { - TilePos pos(x, y, z); + TilePos pos(x, y, z); - tileEntity->setLevel(level); - tileEntity->x = this->x * 16 + x; - tileEntity->y = y; - tileEntity->z = this->z * 16 + z; + tileEntity->setLevel(level); + tileEntity->x = this->x * 16 + x; + tileEntity->y = y; + tileEntity->z = this->z * 16 + z; if (getTile(x, y, z) == 0 || !Tile::tiles[getTile(x, y, z)]->isEntityTile()) // 4J - was !(Tile.tiles[getTile(x, y, z)] instanceof EntityTile)) { - app.DebugPrintf("Attempted to place a tile entity where there was no entity tile!\n"); - return; - } + app.DebugPrintf("Attempted to place a tile entity where there was no entity tile!\n"); + return; + } + AUTO_VAR(it, tileEntities.find(pos) ); + if(it != tileEntities.end()) it->second->setRemoved(); tileEntity->clearRemoved(); EnterCriticalSection(&m_csTileEntities); - tileEntities[pos] = tileEntity; + tileEntities[pos] = tileEntity; LeaveCriticalSection(&m_csTileEntities); } void LevelChunk::removeTileEntity(int x, int y, int z) { - TilePos pos(x, y, z); + TilePos pos(x, y, z); if (loaded) { // 4J - was: // TileEntity removeThis = tileEntities.remove(pos); - // if (removeThis != null) { - // removeThis.setRemoved(); - // } + // if (removeThis != null) { + // removeThis.setRemoved(); + // } EnterCriticalSection(&m_csTileEntities); AUTO_VAR(it, tileEntities.find(pos)); if( it != tileEntities.end() ) @@ -1401,10 +1426,11 @@ void LevelChunk::load() for (int i = 0; i < entityTags->size(); i++) { CompoundTag *teTag = entityTags->get(i); - shared_ptr<Entity> te = EntityIO::loadStatic(teTag, level); - if (te != NULL) + shared_ptr<Entity> ent = EntityIO::loadStatic(teTag, level); + if (ent != NULL) { - addEntity(te); + ent->onLoadedFromSave(); + addEntity(ent); } } } @@ -1462,13 +1488,13 @@ void LevelChunk::load() void LevelChunk::unload(bool unloadTileEntities) // 4J - added parameter { - loaded = false; + loaded = false; if( unloadTileEntities ) { EnterCriticalSection(&m_csTileEntities); for( AUTO_VAR(it, tileEntities.begin()); it != tileEntities.end(); it++ ) { - // 4J-PB -m 1.7.3 was it->second->setRemoved(); + // 4J-PB -m 1.7.3 was it->second->setRemoved(); level->markForRemoval(it->second); } LeaveCriticalSection(&m_csTileEntities); @@ -1502,12 +1528,12 @@ void LevelChunk::unload(bool unloadTileEntities) // 4J - added parameter PIXBeginNamedEvent(0,"Saving entities"); ListTag<CompoundTag> *entityTags = new ListTag<CompoundTag>(); - EnterCriticalSection(&m_csEntities); + EnterCriticalSection(&m_csEntities); for (int i = 0; i < ENTITY_BLOCKS_LENGTH; i++) { AUTO_VAR(itEnd, entityBlocks[i]->end()); for( vector<shared_ptr<Entity> >::iterator it = entityBlocks[i]->begin(); it != itEnd; it++ ) - { + { shared_ptr<Entity> e = *it; CompoundTag *teTag = new CompoundTag(); if (e->save(teTag)) @@ -1520,7 +1546,7 @@ void LevelChunk::unload(bool unloadTileEntities) // 4J - added parameter // Clear out this list entityBlocks[i]->clear(); } - LeaveCriticalSection(&m_csEntities); + LeaveCriticalSection(&m_csEntities); m_unloadedEntitiesTag->put(L"Entities", entityTags); PIXEndNamedEvent(); @@ -1547,6 +1573,37 @@ void LevelChunk::unload(bool unloadTileEntities) // 4J - added parameter #endif } +bool LevelChunk::containsPlayer() +{ +#ifdef _ENTITIES_RW_SECTION + EnterCriticalRWSection(&m_csEntities, true); +#else + EnterCriticalSection(&m_csEntities); +#endif + for (int i = 0; i < ENTITY_BLOCKS_LENGTH; i++) + { + vector<shared_ptr<Entity> > *vecEntity = entityBlocks[i]; + for( int j = 0; j < vecEntity->size(); j++ ) + { + if(vecEntity->at(j)->GetType() == eTYPE_SERVERPLAYER ) + { +#ifdef _ENTITIES_RW_SECTION + LeaveCriticalRWSection(&m_csEntities, true); +#else + LeaveCriticalSection(&m_csEntities); +#endif + return true; + } + } + } +#ifdef _ENTITIES_RW_SECTION + LeaveCriticalRWSection(&m_csEntities, true); +#else + LeaveCriticalSection(&m_csEntities); +#endif + return false; +} + #ifdef _LARGE_WORLDS bool LevelChunk::isUnloaded() { @@ -1556,98 +1613,108 @@ bool LevelChunk::isUnloaded() void LevelChunk::markUnsaved() { - this->setUnsaved(true); + this->setUnsaved(true); } -void LevelChunk::getEntities(shared_ptr<Entity> except, AABB *bb, vector<shared_ptr<Entity> > &es) +void LevelChunk::getEntities(shared_ptr<Entity> except, AABB *bb, vector<shared_ptr<Entity> > &es, const EntitySelector *selector) { - int yc0 = Mth::floor((bb->y0 - 2) / 16); - int yc1 = Mth::floor((bb->y1 + 2) / 16); - if (yc0 < 0) yc0 = 0; - if (yc1 >= ENTITY_BLOCKS_LENGTH) yc1 = ENTITY_BLOCKS_LENGTH - 1; + int yc0 = Mth::floor((bb->y0 - 2) / 16); + int yc1 = Mth::floor((bb->y1 + 2) / 16); + if (yc0 < 0) yc0 = 0; + if (yc1 >= ENTITY_BLOCKS_LENGTH) yc1 = ENTITY_BLOCKS_LENGTH - 1; #ifndef __PSVITA__ // AP - RW critical sections are expensive so enter once in Level::getEntities EnterCriticalSection(&m_csEntities); #endif - for (int yc = yc0; yc <= yc1; yc++) + for (int yc = yc0; yc <= yc1; yc++) { - vector<shared_ptr<Entity> > *entities = entityBlocks[yc]; + vector<shared_ptr<Entity> > *entities = entityBlocks[yc]; AUTO_VAR(itEnd, entities->end()); for (AUTO_VAR(it, entities->begin()); it != itEnd; it++) { - shared_ptr<Entity> e = *it; //entities->at(i); - if (e != except && e->bb->intersects(bb)) + shared_ptr<Entity> e = *it; //entities->at(i); + if (e != except && e->bb->intersects(bb) && (selector == NULL || selector->matches(e))) { es.push_back(e); - vector<shared_ptr<Entity> > *subs = e->getSubEntities(); - if (subs != NULL) + vector<shared_ptr<Entity> > *subs = e->getSubEntities(); + if (subs != NULL) { - for (int j = 0; j < subs->size(); j++) + for (int j = 0; j < subs->size(); j++) { - e = subs->at(j); - if (e != except && e->bb->intersects(bb)) + e = subs->at(j); + if (e != except && e->bb->intersects(bb) && (selector == NULL || selector->matches(e))) { - es.push_back(e); - } - } - } + es.push_back(e); + } + } + } } - } - } + } + } #ifndef __PSVITA__ LeaveCriticalSection(&m_csEntities); #endif } -void LevelChunk::getEntitiesOfClass(const type_info& ec, AABB *bb, vector<shared_ptr<Entity> > &es) +void LevelChunk::getEntitiesOfClass(const type_info& ec, AABB *bb, vector<shared_ptr<Entity> > &es, const EntitySelector *selector) { - int yc0 = Mth::floor((bb->y0 - 2) / 16); - int yc1 = Mth::floor((bb->y1 + 2) / 16); + int yc0 = Mth::floor((bb->y0 - 2) / 16); + int yc1 = Mth::floor((bb->y1 + 2) / 16); - if (yc0 < 0) + if (yc0 < 0) { - yc0 = 0; - } + yc0 = 0; + } else if (yc0 >= ENTITY_BLOCKS_LENGTH) { - yc0 = ENTITY_BLOCKS_LENGTH - 1; - } - if (yc1 >= ENTITY_BLOCKS_LENGTH) + yc0 = ENTITY_BLOCKS_LENGTH - 1; + } + if (yc1 >= ENTITY_BLOCKS_LENGTH) { - yc1 = ENTITY_BLOCKS_LENGTH - 1; - } + yc1 = ENTITY_BLOCKS_LENGTH - 1; + } else if (yc1 < 0) { - yc1 = 0; - } + yc1 = 0; + } #ifndef __PSVITA__ // AP - RW critical sections are expensive so enter once in Level::getEntitiesOfClass EnterCriticalSection(&m_csEntities); #endif - for (int yc = yc0; yc <= yc1; yc++) + for (int yc = yc0; yc <= yc1; yc++) { - vector<shared_ptr<Entity> > *entities = entityBlocks[yc]; - + vector<shared_ptr<Entity> > *entities = entityBlocks[yc]; + AUTO_VAR(itEnd, entities->end()); for (AUTO_VAR(it, entities->begin()); it != itEnd; it++) { - shared_ptr<Entity> e = *it; //entities->at(i); + shared_ptr<Entity> e = *it; //entities->at(i); bool isAssignableFrom = false; // Some special cases where the base class is a general type that our class may be derived from, otherwise do a direct comparison of type_info - if( ec == typeid(Player) ) { if( dynamic_pointer_cast<Player>(e) != NULL ) isAssignableFrom = true; } - else if ( ec == typeid(Mob) ) { if( dynamic_pointer_cast<Mob>(e) != NULL ) isAssignableFrom = true; } - else if ( ec == typeid(Monster) ) { if( dynamic_pointer_cast<Monster>(e) != NULL ) isAssignableFrom = true; } - else if ( ec == typeid(Zombie) ) { if( dynamic_pointer_cast<Zombie>(e) != NULL ) isAssignableFrom = true; } + if ( ec==typeid(Player) ) isAssignableFrom = e->instanceof(eTYPE_PLAYER); + else if ( ec==typeid(Entity) ) isAssignableFrom = e->instanceof(eTYPE_ENTITY); + else if ( ec==typeid(Mob) ) isAssignableFrom = e->instanceof(eTYPE_MOB); + else if ( ec==typeid(LivingEntity) ) isAssignableFrom = e->instanceof(eTYPE_LIVINGENTITY); + else if ( ec==typeid(ItemEntity) ) isAssignableFrom = e->instanceof(eTYPE_ITEMENTITY); + else if ( ec==typeid(Minecart) ) isAssignableFrom = e->instanceof(eTYPE_MINECART); + else if ( ec==typeid(Monster) ) isAssignableFrom = e->instanceof(eTYPE_MONSTER); + else if ( ec==typeid(Zombie) ) isAssignableFrom = e->instanceof(eTYPE_ZOMBIE); else if(e != NULL && ec == typeid(*(e.get())) ) isAssignableFrom = true; - if (isAssignableFrom && e->bb->intersects(bb)) es.push_back(e); + if (isAssignableFrom && e->bb->intersects(bb)) + { + if (selector == NULL || selector->matches(e)) + { + es.push_back(e); + } + } // 4J - note needs to be equivalent to baseClass.isAssignableFrom(e.getClass()) - } - } + } + } #ifndef __PSVITA__ LeaveCriticalSection(&m_csEntities); #endif @@ -1655,16 +1722,16 @@ void LevelChunk::getEntitiesOfClass(const type_info& ec, AABB *bb, vector<shared int LevelChunk::countEntities() { - int entityCount = 0; + int entityCount = 0; #ifdef _ENTITIES_RW_SECTION EnterCriticalRWSection(&m_csEntities, false); #else EnterCriticalSection(&m_csEntities); #endif - for (int yc = 0; yc < ENTITY_BLOCKS_LENGTH; yc++) + for (int yc = 0; yc < ENTITY_BLOCKS_LENGTH; yc++) { - entityCount += (int)entityBlocks[yc]->size(); - } + entityCount += (int)entityBlocks[yc]->size(); + } #ifdef _ENTITIES_RW_SECTION LeaveCriticalRWSection(&m_csEntities, false); #else @@ -1675,22 +1742,27 @@ int LevelChunk::countEntities() bool LevelChunk::shouldSave(bool force) { - if (dontSave) return false; - if (force) + if (dontSave) return false; + if (force) + { + if ((lastSaveHadEntities && level->getGameTime() != lastSaveTime) || m_unsaved) + { + return true; + } + } + else { - if (lastSaveHadEntities && level->getTime() != lastSaveTime) return true; - } else { - if (lastSaveHadEntities && level->getTime() >= lastSaveTime + 20 * 30) return true; - } + if (lastSaveHadEntities && level->getGameTime() >= lastSaveTime + 20 * 30) return true; + } - return m_unsaved; + return m_unsaved; } int LevelChunk::getBlocksAndData(byteArray *data, int x0, int y0, int z0, int x1, int y1, int z1, int p, bool includeLighting/* = true*/) { - int xs = x1 - x0; - int ys = y1 - y0; - int zs = z1 - z0; + int xs = x1 - x0; + int ys = y1 - y0; + int zs = z1 - z0; // 4J Stu - Added this because some "min" functions don't let us use our constants :( int compressedHeight = Level::COMPRESSED_CHUNK_SECTION_HEIGHT; @@ -1714,26 +1786,26 @@ int LevelChunk::getBlocksAndData(byteArray *data, int x0, int y0, int z0, int x1 } /* - for (int x = x0; x < x1; x++) - for (int z = z0; z < z1; z++) - { - int slot = (x << level->depthBitsPlusFour | z << level->depthBits | y0) >> 1; - int len = (y1 - y0) / 2; - System::arraycopy(blockLight->data, slot, data, p, len); - p += len; - } - - for (int x = x0; x < x1; x++) - for (int z = z0; z < z1; z++) - { - int slot = (x << level->depthBitsPlusFour | z << level->depthBits | y0) >> 1; - int len = (y1 - y0) / 2; - System::arraycopy(skyLight->data, slot, data, p, len); - p += len; - } - */ + for (int x = x0; x < x1; x++) + for (int z = z0; z < z1; z++) + { + int slot = (x << level->depthBitsPlusFour | z << level->depthBits | y0) >> 1; + int len = (y1 - y0) / 2; + System::arraycopy(blockLight->data, slot, data, p, len); + p += len; + } + + for (int x = x0; x < x1; x++) + for (int z = z0; z < z1; z++) + { + int slot = (x << level->depthBitsPlusFour | z << level->depthBits | y0) >> 1; + int len = (y1 - y0) / 2; + System::arraycopy(skyLight->data, slot, data, p, len); + p += len; + } + */ - return p; + return p; } // 4J added - return true if setBlocksAndData would change any blocks @@ -1791,16 +1863,16 @@ int LevelChunk::setBlocksAndData(byteArray data, int x0, int y0, int z0, int x1, if(y0 < Level::COMPRESSED_CHUNK_SECTION_HEIGHT) p += lowerBlocks->setDataRegion( data, x0, y0, z0, x1, min(compressedHeight, y1), z1, p, includeLighting ? NULL : tileUpdatedCallback, this, 0 ); if(y1 > Level::COMPRESSED_CHUNK_SECTION_HEIGHT) p += upperBlocks->setDataRegion( data, x0, max(y0-compressedHeight,0), z0, x1, y1-Level::COMPRESSED_CHUNK_SECTION_HEIGHT, z1, p, includeLighting ? NULL : tileUpdatedCallback, this, Level::COMPRESSED_CHUNK_SECTION_HEIGHT ); /* - for (int x = x0; x < x1; x++) - for (int z = z0; z < z1; z++) - { - int slot = x << level->depthBitsPlusFour | z << level->depthBits | y0; - int len = y1 - y0; - System::arraycopy(data, p, &blocks, slot, len); - p += len; - }*/ + for (int x = x0; x < x1; x++) + for (int z = z0; z < z1; z++) + { + int slot = x << level->depthBitsPlusFour | z << level->depthBits | y0; + int len = y1 - y0; + System::arraycopy(data, p, &blocks, slot, len); + p += len; + }*/ - recalcHeightmapOnly(); + recalcHeightmapOnly(); // 4J - replaced data storage as now uses SparseDataStorage if(y0 < Level::COMPRESSED_CHUNK_SECTION_HEIGHT) p += lowerData->setDataRegion( data, x0, y0, z0, x1, min(compressedHeight, y1), z1, p, includeLighting ? NULL : tileUpdatedCallback, this, 0 ); @@ -1838,30 +1910,30 @@ int LevelChunk::setBlocksAndData(byteArray data, int x0, int y0, int z0, int x1, } /* - for (int x = x0; x < x1; x++) - for (int z = z0; z < z1; z++) - { - int slot = (x << level->depthBitsPlusFour | z << level->depthBits | y0) >> 1; - int len = (y1 - y0) / 2; - System::arraycopy(data, p, &blockLight->data, slot, len); - p += len; - } - - for (int x = x0; x < x1; x++) - for (int z = z0; z < z1; z++) - { - int slot = (x << level->depthBitsPlusFour | z << level->depthBits | y0) >> 1; - int len = (y1 - y0) / 2; - System::arraycopy(data, p, &skyLight->data, slot, len); - p += len; - } - */ + for (int x = x0; x < x1; x++) + for (int z = z0; z < z1; z++) + { + int slot = (x << level->depthBitsPlusFour | z << level->depthBits | y0) >> 1; + int len = (y1 - y0) / 2; + System::arraycopy(data, p, &blockLight->data, slot, len); + p += len; + } + + for (int x = x0; x < x1; x++) + for (int z = z0; z < z1; z++) + { + int slot = (x << level->depthBitsPlusFour | z << level->depthBits | y0) >> 1; + int len = (y1 - y0) / 2; + System::arraycopy(data, p, &skyLight->data, slot, len); + p += len; + } + */ for(AUTO_VAR(it, tileEntities.begin()); it != tileEntities.end(); ++it) { it->second->clearCache(); } -// recalcHeightmap(); + // recalcHeightmap(); // If the includeLighting flag is set, then this is a full chunk's worth of data. This is a good time to compress everything that we've just set up. if( includeLighting ) @@ -1871,7 +1943,7 @@ int LevelChunk::setBlocksAndData(byteArray data, int x0, int y0, int z0, int x1, compressData(); } - return p; + return p; } void LevelChunk::setCheckAllLight() @@ -1881,26 +1953,26 @@ void LevelChunk::setCheckAllLight() Random *LevelChunk::getRandom(__int64 l) { - return new Random((level->getSeed() + x * x * 4987142 + x * 5947611 + z * z * 4392871l + z * 389711) ^ l); + return new Random((level->getSeed() + x * x * 4987142 + x * 5947611 + z * z * 4392871l + z * 389711) ^ l); } bool LevelChunk::isEmpty() { - return false; + return false; } void LevelChunk::attemptCompression() { // 4J - removed #if 0 - try { - ByteArrayOutputStream *baos = new ByteArrayOutputStream(); - GZIPOutputStream *gzos = new GZIPOutputStream(baos); - DataOutputStream *dos = new DataOutputStream(gzos); - dos.close(); - System.out.println("Compressed size: " + baos.toByteArray().length); - } catch (Exception e) { - - } + try { + ByteArrayOutputStream *baos = new ByteArrayOutputStream(); + GZIPOutputStream *gzos = new GZIPOutputStream(baos); + DataOutputStream *dos = new DataOutputStream(gzos); + dos.close(); + System.out.println("Compressed size: " + baos.toByteArray().length); + } catch (Exception e) { + + } #endif } @@ -1955,7 +2027,7 @@ void LevelChunk::tick() ChunkPos *LevelChunk::getPos() { - return new ChunkPos(x, z); + return new ChunkPos(x, z); } bool LevelChunk::isYSpaceEmpty(int y1, int y2) @@ -1963,20 +2035,34 @@ bool LevelChunk::isYSpaceEmpty(int y1, int y2) return false; // 4J Unused /*if (y1 < 0) { - y1 = 0; + y1 = 0; } if (y2 >= Level.maxBuildHeight) { - y2 = Level.maxBuildHeight - 1; + y2 = Level.maxBuildHeight - 1; } for (int y = y1; y <= y2; y += 16) { - LevelChunkSection section = sections[y >> 4]; - if (section != null && !section.isEmpty()) { - return false; - } + LevelChunkSection section = sections[y >> 4]; + if (section != null && !section.isEmpty()) { + return false; + } } return true;*/ } +// 4J Added +void LevelChunk::reloadBiomes() +{ + BiomeSource *biomeSource = level->dimension->biomeSource; + for(unsigned int x = 0; x < 16; ++x) + { + for(unsigned int z = 0; z < 16; ++z) + { + Biome *biome = biomeSource->getBiome((this->x << 4) + x, (this->z << 4) + z); + biomes[(z << 4) | x] = (byte) ( (biome->id) & 0xff); + } + } +} + Biome *LevelChunk::getBiome(int x, int z, BiomeSource *biomeSource) { int value = biomes[(z << 4) | x] & 0xff; @@ -2007,33 +2093,33 @@ void LevelChunk::setBiomes(byteArray biomes) // 4J - optimisation brought forward from 1.8.2 int LevelChunk::getTopRainBlock(int x, int z) { - int slot = x | (z << 4); - int h = rainHeights[slot]; + int slot = x | (z << 4); + int h = rainHeights[slot]; - if (h == 255) + if (h == 255) { - int y = Level::maxBuildHeight - 1; - h = -1; - while (y > 0 && h == -1) + int y = Level::maxBuildHeight - 1; + h = -1; + while (y > 0 && h == -1) { - int t = getTile(x, y, z); - Material *m = t == 0 ? Material::air : Tile::tiles[t]->material; - if (!m->blocksMotion() && !m->isLiquid()) + int t = getTile(x, y, z); + Material *m = t == 0 ? Material::air : Tile::tiles[t]->material; + if (!m->blocksMotion() && !m->isLiquid()) { - y--; - } + y--; + } else { - h = y + 1; - } - } + h = y + 1; + } + } // 255 indicates that the rain height needs recalculated. If the rain height ever actually Does get to 255, then it will just keep not being cached, so // probably better just to let the rain height be 254 in this instance and suffer a slightly incorrect results if( h == 255 ) h = 254; rainHeights[slot] = h; - } + } - return h; + return h; } // 4J added as optimisation, these biome checks are expensive so caching through flags in levelchunk @@ -2313,7 +2399,14 @@ int LevelChunk::getBlocksAllocatedSize(int *count0, int *count1, int *count2, in int LevelChunk::getHighestNonEmptyY() { int highestNonEmptyY = -1; - if(upperBlocks) highestNonEmptyY = upperBlocks->getHighestNonEmptyY() + Level::COMPRESSED_CHUNK_SECTION_HEIGHT; + if(upperBlocks) + { + int upperNonEmpty = upperBlocks->getHighestNonEmptyY(); + if( upperNonEmpty >= 0 ) + { + highestNonEmptyY = upperNonEmpty + Level::COMPRESSED_CHUNK_SECTION_HEIGHT; + } + } if(highestNonEmptyY < 0) highestNonEmptyY = lowerBlocks->getHighestNonEmptyY(); if(highestNonEmptyY < 0) highestNonEmptyY = 0; @@ -2400,7 +2493,7 @@ void LevelChunk::reorderBlocksAndDataToXZY(int y0, int xs, int ys, int zs, byteA int y1 = y0 + ys; unsigned int tileCount = xs * ys * zs; unsigned int halfTileCount = tileCount/2; - + int sectionHeight = Level::COMPRESSED_CHUNK_SECTION_HEIGHT; int lowerYSpan = min(y1, sectionHeight) - y0; int upperYSpan = ys - lowerYSpan; |
