Performance optimizations: sound caching, renderer culling, entity and lighting improvements

- Sound engine: cache filesystem probe results to avoid repeated file existence checks; add MA_SOUND_FLAG_DECODE for pre-decoded playback
- Level renderer: column-level frustum culling, compact visible chunk lists to skip empty iteration, lightweight second-pass render path, early-out for non-dirty chunks, scaled recheck period at high render distances
- Entity: cache shared_from_this() to reduce reference counting overhead in move() and checkInsideTiles()
- Level: skip checkLight() when tile light properties unchanged; enable entity locking on all platforms (not just Vita)
- LevelChunk: only rescan min height when the minimum column changes; defer lightGap processing
- LivingEntity: use raw pointer cast instead of dynamic_pointer_cast; cache friction tile lookup
- ServerPlayerGameMode: return whether block was destroyed to avoid redundant tile update packets
This commit is contained in:
Revela committed 2026-03-18 17:22:04 -05:00
1 parent 80ba2e0762
commit 0ba923f085
12 files changed
+311 -170

No files matched your search

+10 -7
View File
@@ -705,6 +705,8 @@ void Entity::move(double xa, double ya, double za, bool noEntityCubes) // 4J -
return;
}
auto self = shared_from_this();
ySlideOffset *= 0.4f;
double xo = x;
@@ -734,21 +736,21 @@ void Entity::move(double xa, double ya, double za, bool noEntityCubes) // 4J -
if (isPlayerSneaking)
{
double d = 0.05;
while (xa != 0 && level->getCubes(shared_from_this(), bb->cloneMove(xa, -1.0, 0))->empty())
while (xa != 0 && level->getCubes(self, bb->cloneMove(xa, -1.0, 0), true)->empty())
{
if (xa < d && xa >= -d) xa = 0;
else if (xa > 0) xa -= d;
else xa += d;
xaOrg = xa;
}
while (za != 0 && level->getCubes(shared_from_this(), bb->cloneMove(0, -1.0, za))->empty())
while (za != 0 && level->getCubes(self, bb->cloneMove(0, -1.0, za), true)->empty())
{
if (za < d && za >= -d) za = 0;
else if (za > 0) za -= d;
else za += d;
zaOrg = za;
}
while (xa != 0 && za != 0 && level->getCubes(shared_from_this(), bb->cloneMove(xa, -1.0, za))->empty())
while (xa != 0 && za != 0 && level->getCubes(self, bb->cloneMove(xa, -1.0, za), true)->empty())
{
if (xa < d && xa >= -d) xa = 0;
else if (xa > 0) xa -= d;
@@ -761,7 +763,7 @@ void Entity::move(double xa, double ya, double za, bool noEntityCubes) // 4J -
}
}
AABBList *aABBs = level->getCubes(shared_from_this(), bb->expand(xa, ya, za), noEntityCubes, true);
AABBList *aABBs = level->getCubes(self, bb->expand(xa, ya, za), noEntityCubes, true);
// 4J Stu - Particles (and possibly other entities) don't have xChunk and zChunk set, so calculate the chunk instead
@@ -816,7 +818,7 @@ void Entity::move(double xa, double ya, double za, bool noEntityCubes) // 4J -
bb->set(bbOrg);
// 4J - added extra expand, as if we don't move up by footSize by hitting a block above us, then overall we could be trying to move as much as footSize downwards,
// so we'd better include cubes under our feet in this list of things we might possibly collide with
aABBs = level->getCubes(shared_from_this(), bb->expand(xa, ya, za)->expand(0,-ya,0),false,true);
aABBs = level->getCubes(self, bb->expand(xa, ya, za)->expand(0,-ya,0),false,true);
if(!level->isClientSide || level->reallyHasChunk(xc, zc))
{
@@ -926,7 +928,7 @@ void Entity::move(double xa, double ya, double za, bool noEntityCubes) // 4J -
playSound(eSoundType_LIQUID_SWIM, speed, 1 + (random->nextFloat() - random->nextFloat()) * 0.4f);
}
playStepSound(xt, yt, zt, t);
Tile::tiles[t]->stepOn(level, xt, yt, zt, shared_from_this());
Tile::tiles[t]->stepOn(level, xt, yt, zt, self);
}
}
@@ -969,6 +971,7 @@ void Entity::checkInsideTiles()
if (level->hasChunksAt(x0, y0, z0, x1, y1, z1))
{
auto self = shared_from_this();
for (int x = x0; x <= x1; x++)
for (int y = y0; y <= y1; y++)
for (int z = z0; z <= z1; z++)
@@ -976,7 +979,7 @@ void Entity::checkInsideTiles()
int t = level->getTile(x, y, z);
if (t > 0)
{
Tile::tiles[t]->entityInside(level, x, y, z, shared_from_this());
Tile::tiles[t]->entityInside(level, x, y, z, self);
}
}
}
+6 -9
View File
@@ -932,6 +932,7 @@ bool Level::setTileAndData(int x, int y, int z, int tile, int data, int updateFl
int old = c->getTile(x & 15, y, z & 15);
int olddata = c->getData( x & 15, y, z & 15);
#endif
int prevTile = c->getTile(x & 15, y, z & 15);
result = c->setTileAndData(x & 15, y, z & 15, tile, data);
if( updateFlags != Tile::UPDATE_INVISIBLE_NO_LIGHT)
{
@@ -939,7 +940,11 @@ bool Level::setTileAndData(int x, int y, int z, int tile, int data, int updateFl
PIXBeginNamedEvent(0,"Checking light %d %d %d",x,y,z);
PIXBeginNamedEvent(0,"was %d, %d now %d, %d",old,olddata,tile,data);
#endif
checkLight(x, y, z);
if (Tile::lightBlock[tile & 0xff] != Tile::lightBlock[prevTile & 0xff] ||
Tile::lightEmission[tile & 0xff] != Tile::lightEmission[prevTile & 0xff])
{
checkLight(x, y, z);
}
PIXEndNamedEvent();
PIXEndNamedEvent();
}
@@ -3687,13 +3692,11 @@ vector<shared_ptr<Entity> > *Level::getEntities(shared_ptr<Entity> except, AABB
int zc0 = Mth::floor((bb->z0 - 2) / 16);
int zc1 = Mth::floor((bb->z1 + 2) / 16);
#ifdef __PSVITA__
#ifdef _ENTITIES_RW_SECTION
// AP - RW critical sections are expensive so enter it here so we only have to call it once instead of X times
EnterCriticalRWSection(&LevelChunk::m_csEntities, false);
#else
EnterCriticalSection(&LevelChunk::m_csEntities);
#endif
#endif
for (int xc = xc0; xc <= xc1; xc++)
@@ -3706,12 +3709,10 @@ vector<shared_ptr<Entity> > *Level::getEntities(shared_ptr<Entity> except, AABB
}
MemSect(0);
#ifdef __PSVITA__
#ifdef _ENTITIES_RW_SECTION
LeaveCriticalRWSection(&LevelChunk::m_csEntities, false);
#else
LeaveCriticalSection(&LevelChunk::m_csEntities);
#endif
#endif
return &es;
@@ -3730,13 +3731,11 @@ vector<shared_ptr<Entity> > *Level::getEntitiesOfClass(const type_info& baseClas
int zc1 = Mth::floor((bb->z1 + 2) / 16);
vector<shared_ptr<Entity> > *es = new vector<shared_ptr<Entity> >();
#ifdef __PSVITA__
#ifdef _ENTITIES_RW_SECTION
// AP - RW critical sections are expensive so enter it here so we only have to call it once instead of X times
EnterCriticalRWSection(&LevelChunk::m_csEntities, false);
#else
EnterCriticalSection(&LevelChunk::m_csEntities);
#endif
#endif
for (int xc = xc0; xc <= xc1; xc++)
@@ -3750,12 +3749,10 @@ vector<shared_ptr<Entity> > *Level::getEntitiesOfClass(const type_info& baseClas
}
}
#ifdef __PSVITA__
#ifdef _ENTITIES_RW_SECTION
LeaveCriticalRWSection(&LevelChunk::m_csEntities, false);
#else
LeaveCriticalSection(&LevelChunk::m_csEntities);
#endif
#endif
return es;
+14 -20
View File
@@ -817,8 +817,9 @@ void LevelChunk::recalcHeight(int x, int yStart, int z)
{
minHeight = y;
}
else
else if (yOld == minHeight)
{
// Only rescan when the column that was at the minimum changed height
int min = Level::maxBuildHeight - 1;
for (int _x = 0; _x < 16; _x++)
for (int _z = 0; _z < 16; _z++)
@@ -886,11 +887,16 @@ void LevelChunk::recalcHeight(int x, int yStart, int z)
if (!level->dimension->hasCeiling)
{
PIXBeginNamedEvent(0,"Light gaps");
lightGap(xOffs - 1, zOffs, y1, y2);
lightGap(xOffs + 1, zOffs, y1, y2);
lightGap(xOffs, zOffs - 1, y1, y2);
lightGap(xOffs, zOffs + 1, y1, y2);
lightGap(xOffs, zOffs, y1, y2);
// Flag columns for gap rechecking — processed by recheckGaps() on next tick
auto flagGap = [&](int wx, int wz) {
LevelChunk *c = level->getChunkAt(wx, wz);
if (c && !c->isEmpty()) c->lightGaps(wx & 15, wz & 15);
};
flagGap(xOffs - 1, zOffs);
flagGap(xOffs + 1, zOffs);
flagGap(xOffs, zOffs - 1);
flagGap(xOffs, zOffs + 1);
flagGap(xOffs, zOffs);
PIXEndNamedEvent();
}
@@ -1643,10 +1649,7 @@ void LevelChunk::getEntities(shared_ptr<Entity> except, AABB *bb, vector<shared_
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
// Lock is now always held by Level::getEntities()
for (int yc = yc0; yc <= yc1; yc++)
{
vector<shared_ptr<Entity> > *entities = entityBlocks[yc];
@@ -1671,9 +1674,6 @@ void LevelChunk::getEntities(shared_ptr<Entity> except, AABB *bb, vector<shared_
}
}
}
#ifndef __PSVITA__
LeaveCriticalSection(&m_csEntities);
#endif
}
void LevelChunk::getEntitiesOfClass(const type_info& ec, AABB *bb, vector<shared_ptr<Entity> > &es, const EntitySelector *selector)
@@ -1698,10 +1698,7 @@ void LevelChunk::getEntitiesOfClass(const type_info& ec, AABB *bb, vector<shared
yc1 = 0;
}
#ifndef __PSVITA__
// AP - RW critical sections are expensive so enter once in Level::getEntitiesOfClass
EnterCriticalSection(&m_csEntities);
#endif
// Lock is now always held by Level::getEntitiesOfClass()
for (int yc = yc0; yc <= yc1; yc++)
{
vector<shared_ptr<Entity> > *entities = entityBlocks[yc];
@@ -1729,9 +1726,6 @@ void LevelChunk::getEntitiesOfClass(const type_info& ec, AABB *bb, vector<shared
// 4J - note needs to be equivalent to baseClass.isAssignableFrom(e.getClass())
}
}
#ifndef __PSVITA__
LeaveCriticalSection(&m_csEntities);
#endif
}
int LevelChunk::countEntities()
+8 -12
View File
@@ -1380,16 +1380,12 @@ void LivingEntity::jumpFromGround()
void LivingEntity::travel(float xa, float ya)
{
#ifdef __PSVITA__
// AP - dynamic_pointer_cast is a non-trivial call
// AP - dynamic_pointer_cast is a non-trivial call, use raw pointer instead
Player *thisPlayer = nullptr;
if( this->instanceof(eTYPE_PLAYER) )
if (this->instanceof(eTYPE_PLAYER))
{
thisPlayer = (Player*) this;
}
#else
shared_ptr<Player> thisPlayer = dynamic_pointer_cast<Player>(shared_from_this());
#endif
if (isInWater() && !(thisPlayer && thisPlayer->abilities.flying) )
{
double yo = y;
@@ -1424,13 +1420,14 @@ void LivingEntity::travel(float xa, float ya)
else
{
float friction = 0.91f;
int frictionTile = 0;
if (onGround)
{
frictionTile = level->getTile(Mth::floor(x), Mth::floor(bb->y0) - 1, Mth::floor(z));
friction = 0.6f * 0.91f;
int t = level->getTile(Mth::floor(x), Mth::floor(bb->y0) - 1, Mth::floor(z));
if (t > 0)
if (frictionTile > 0)
{
friction = Tile::tiles[t]->friction * 0.91f;
friction = Tile::tiles[frictionTile]->friction * 0.91f;
}
}
@@ -1452,10 +1449,9 @@ void LivingEntity::travel(float xa, float ya)
if (onGround)
{
friction = 0.6f * 0.91f;
int t = level->getTile( Mth::floor(x), Mth::floor(bb->y0) - 1, Mth::floor(z));
if (t > 0)
if (frictionTile > 0)
{
friction = Tile::tiles[t]->friction * 0.91f;
friction = Tile::tiles[frictionTile]->friction * 0.91f;
}
}
if (onLadder())