fix: tu31 tutorial world crashes

This commit is contained in:
Fireblade 2026-05-02 21:30:34 -04:00
parent 02f1be3bb7
commit 229d22ab7b
10 changed files with 58 additions and 24 deletions

View file

@ -111,7 +111,9 @@ int Camera::getBlockAt(Level *level, shared_ptr<LivingEntity> player, float alph
Vec3 *p = Camera::getCameraPos(player, alpha);
TilePos tp = TilePos(p);
int t = level->getTile(tp.x, tp.y, tp.z);
if (t != 0 && Tile::tiles[t]->material->isLiquid())
Tile *tile = Tile::tiles[t];
if (tile == nullptr) return 0; // tu31 tutorial world fix
if (t != 0 && tile->material->isLiquid())
{
float hh = LiquidTile::getHeight(level->getData(tp.x, tp.y, tp.z)) - 1 / 9.0f;
float h = tp.y + 1 - hh;

View file

@ -213,9 +213,11 @@ void EntityRenderer::renderShadow(shared_ptr<Entity> e, double x, double y, doub
for (int zt = z0; zt <= z1; zt++)
{
int t = level->getTile(xt, yt - 1, zt);
Tile *tile = Tile::tiles[t];
if (tile == nullptr) continue; // tu31 tutorial world fix
if (t > 0 && level->getRawBrightness(xt, yt, zt) > 3)
{
renderTileShadow(Tile::tiles[t], x, y + e->getShadowHeightOffs() + fYLocalPlayerShadowOffset, z, xt, yt , zt, pow, r, xo, yo + e->getShadowHeightOffs() + fYLocalPlayerShadowOffset, zo);
renderTileShadow(tile, x, y + e->getShadowHeightOffs() + fYLocalPlayerShadowOffset, z, xt, yt , zt, pow, r, xo, yo + e->getShadowHeightOffs() + fYLocalPlayerShadowOffset, zo);
}
}
tt->end();

View file

@ -721,13 +721,15 @@ void MultiPlayerLevel::animateTickDoWork()
int y = cy + random->nextInt(8);
int z = cz + random->nextInt(8);
int t = getTile(x, y, z);
Tile *tile = Tile::tiles[t];
if (tile == nullptr) return; // tu31 tutorial world fix
if (random->nextInt(8) > y && t == 0 && dimension->hasBedrockFog()) // 4J - test for bedrock fog brought forward from 1.2.3
{
addParticle(eParticleType_depthsuspend, x + random->nextFloat(), y + random->nextFloat(), z + random->nextFloat(), 0, 0, 0);
}
else if (t > 0)
{
Tile::tiles[t]->animateTick(this, x, y, z, animateRandom);
tile->animateTick(this, x, y, z, animateRandom);
}
}
}

View file

@ -8,6 +8,7 @@
TerrainParticle::TerrainParticle(Level *level, double x, double y, double z, double xa, double ya, double za, Tile *tile, int face, int data, Textures *textures) : Particle(level, x, y, z, xa, ya, za)
{
this->tile = tile;
if (tile == nullptr) return; // tu31 tutorial world fix
this->setTex(textures, tile->getTexture(0, data)); // 4J - change brought forward from 1.8.2 to fix purple particles on door damage
this->gravity = tile->gravity;
rCol = gCol = bCol = 0.6f;
@ -16,6 +17,7 @@ TerrainParticle::TerrainParticle(Level *level, double x, double y, double z, dou
shared_ptr<TerrainParticle> TerrainParticle::init(int x, int y, int z, int data) // 4J - added data parameter
{
if (tile == nullptr) return nullptr; // tu31 tutorial world fix
if (tile == Tile::grass) return dynamic_pointer_cast<TerrainParticle>( shared_from_this() );
int col = tile->getColor(level, x, y, z, data); // 4J - added data parameter
rCol *= ((col >> 16) & 0xff) / 255.0f;
@ -26,6 +28,7 @@ shared_ptr<TerrainParticle> TerrainParticle::init(int x, int y, int z, int data)
shared_ptr<TerrainParticle> TerrainParticle::init(int data)
{
if (tile == nullptr) return nullptr; // tu31 tutorial world fix
if (tile == Tile::grass) return dynamic_pointer_cast<TerrainParticle>( shared_from_this() );
int col = tile->getColor(data);
rCol *= ((col >> 16) & 0xff) / 255.0f;

View file

@ -932,7 +932,9 @@ 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, self);
Tile *tile = Tile::tiles[t];
if (tile == nullptr && t != 0) return; // tu31 tutorial world fix
tile->stepOn(level, xt, yt, zt, self);
}
}
@ -981,9 +983,10 @@ void Entity::checkInsideTiles()
for (int z = z0; z <= z1; z++)
{
int t = level->getTile(x, y, z);
if (t > 0)
Tile *tile = Tile::tiles[t];
if (t > 0 && tile != nullptr) // tu31 tutorial world fix
{
Tile::tiles[t]->entityInside(level, x, y, z, self);
tile->entityInside(level, x, y, z, self);
}
}
}
@ -992,6 +995,8 @@ void Entity::checkInsideTiles()
void Entity::playStepSound(int xt, int yt, int zt, int t)
{
Tile *tile = Tile::tiles[t];
if (tile == nullptr && t != 0) return; // tu31 tutorial world fix
const Tile::SoundType *soundType = Tile::tiles[t]->soundType;
MemSect(31);
@ -1122,7 +1127,9 @@ bool Entity::isUnderLiquid(Material *material)
int yt = Mth::floor(yp); // 4J - this used to be a nested pair of floors for some reason
int zt = Mth::floor(z);
int t = level->getTile(xt, yt, zt);
if (t != 0 && Tile::tiles[t]->material == material) {
Tile *tile = Tile::tiles[t];
if (tile == nullptr) return false; // tu31 tutorial world fix
if (t != 0 && tile->material == material) {
float hh = LiquidTile::getHeight(level->getData(xt, yt, zt)) - 1 / 9.0f;
float h = yt + 1 - hh;
return yp < h;

View file

@ -1518,7 +1518,7 @@ HitResult *Level::clip(Vec3 *a, Vec3 *b, bool liquid, bool solidOnly)
// No collision
}
else if (t > 0 && tile->mayPick(data, liquid))
else if (t > 0 && tile != nullptr && tile->mayPick(data, liquid))
{
HitResult *r = tile->clip(this, xTile0, yTile0, zTile0, a, b);
if (r != nullptr) return r;
@ -1620,7 +1620,7 @@ HitResult *Level::clip(Vec3 *a, Vec3 *b, bool liquid, bool solidOnly)
// No collision
}
else if (t > 0 && tile->mayPick(data, liquid))
else if (t > 0 && tile != nullptr && tile->mayPick(data, liquid))
{
HitResult *r = tile->clip(this, xTile0, yTile0, zTile0, a, b);
if (r != nullptr) return r;
@ -3993,7 +3993,9 @@ int Level::getDirectSignal(int x, int y, int z, int dir)
{
int t = getTile(x, y, z);
if (t == 0) return Redstone::SIGNAL_NONE;
return Tile::tiles[t]->getDirectSignal(this, x, y, z, dir);
Tile *tile = Tile::tiles[t];
if (tile == nullptr) return Redstone::SIGNAL_NONE; // tu31 tutorial world fix
return tile->getDirectSignal(this, x, y, z, dir);
}
int Level::getDirectSignalTo(int x, int y, int z)
@ -4026,8 +4028,9 @@ int Level::getSignal(int x, int y, int z, int dir)
return getDirectSignalTo(x, y, z);
}
int t = getTile(x, y, z);
if (t == 0) return Redstone::SIGNAL_NONE;
return Tile::tiles[t]->getSignal(this, x, y, z, dir);
Tile *tile = Tile::tiles[t];
if (t == 0 || tile == nullptr) return Redstone::SIGNAL_NONE;
return tile->getSignal(this, x, y, z, dir);
}
bool Level::hasNeighborSignal(int x, int y, int z)

View file

@ -949,9 +949,12 @@ bool LevelChunk::setTileAndData(int x, int y, int z, int _tile, int _data)
}
int xOffs = this->x * 16 + x;
int zOffs = this->z * 16 + z;
Tile *oldTile = Tile::tiles[old];
if (oldTile == nullptr & old != 0) return false; // tu31 tutorial world fix
if (old != 0 && !level->isClientSide)
{
Tile::tiles[old]->onRemoving(level, xOffs, y, zOffs, oldData);
oldTile->onRemoving(level, xOffs, y, zOffs, oldData);
}
PIXBeginNamedEvent(0,"Chunk setting tile");
blocks->set(x,y % Level::COMPRESSED_CHUNK_SECTION_HEIGHT,z,tile);
@ -1329,7 +1332,9 @@ shared_ptr<TileEntity> LevelChunk::getTileEntity(int x, int y, int z)
if(level->m_bDisableAddNewTileEntities) return nullptr;
int t = getTile(x, y, z);
if (t <= 0 || !Tile::tiles[t]->isEntityTile()) return nullptr;
Tile *tile = Tile::tiles[t];
if (tile == nullptr) return nullptr; // tu31 tutorial world fix
if (t <= 0 || !tile->isEntityTile()) return nullptr;
// 4J-PB changed from this in 1.7.3
//EntityTile *et = (EntityTile *) Tile::tiles[t];
@ -1337,7 +1342,7 @@ shared_ptr<TileEntity> LevelChunk::getTileEntity(int x, int y, int z)
//if (tileEntity == nullptr)
//{
tileEntity = dynamic_cast<EntityTile *>(Tile::tiles[t])->newTileEntity(level);
tileEntity = dynamic_cast<EntityTile *>(tile)->newTileEntity(level);
level->setTileEntity(this->x * 16 + x, y, this->z * 16 + z, tileEntity);
//}

View file

@ -179,7 +179,8 @@ void LivingEntity::checkFallDamage(double ya, bool onGround)
}
}
if (t > 0)
Tile *tile = Tile::tiles[t];
if (t > 0 && tile != nullptr) // tu31 tutorial world fix
{
Tile::tiles[t]->fallOn(level, xt, yt, zt, shared_from_this(), fallDistance);
}
@ -1560,10 +1561,12 @@ void LivingEntity::travel(float xa, float ya)
if (onGround)
{
frictionTile = level->getTile(Mth::floor(x), Mth::floor(bb->y0) - 1, Mth::floor(z));
Tile *tile = Tile::tiles[frictionTile];
friction = 0.6f * 0.91f;
if (frictionTile > 0)
{
friction = Tile::tiles[frictionTile]->friction * 0.91f;
if (tile == nullptr) tile = Tile::tiles[1];
friction = tile->friction * 0.91f;
}
}
@ -1586,8 +1589,10 @@ void LivingEntity::travel(float xa, float ya)
{
friction = 0.6f * 0.91f;
if (frictionTile > 0)
{
friction = Tile::tiles[frictionTile]->friction * 0.91f;
{
Tile *tile = Tile::tiles[frictionTile];
if (tile == nullptr) tile = Tile::tiles[1];
friction = tile->friction * 0.91f;
}
}
if (onLadder())

View file

@ -502,6 +502,9 @@ int PistonBaseTile::getNewFacing(Level *level, int x, int y, int z, shared_ptr<L
bool PistonBaseTile::isPushable(int block, Level *level, int cx, int cy, int cz, bool allowDestroyable)
{
Tile *tile = Tile::tiles[block];
if (tile == nullptr) return false; // tu31 tutorial world fix
// special case for obsidian
if (block == Tile::obsidian_Id)
{
@ -518,17 +521,17 @@ bool PistonBaseTile::isPushable(int block, Level *level, int cx, int cy, int cz,
}
else
{
if (Tile::tiles[block]->getDestroySpeed(level, cx, cy, cz) == Tile::INDESTRUCTIBLE_DESTROY_TIME)
if (tile->getDestroySpeed(level, cx, cy, cz) == Tile::INDESTRUCTIBLE_DESTROY_TIME)
{
return false;
}
if (Tile::tiles[block]->getPistonPushReaction() == Material::PUSH_BLOCK)
if (tile->getPistonPushReaction() == Material::PUSH_BLOCK)
{
return false;
}
if (Tile::tiles[block]->getPistonPushReaction() == Material::PUSH_DESTROY)
if (tile->getPistonPushReaction() == Material::PUSH_DESTROY)
{
if(!allowDestroyable)
{
@ -538,7 +541,7 @@ bool PistonBaseTile::isPushable(int block, Level *level, int cx, int cy, int cz,
}
}
if( Tile::tiles[block]->isEntityTile() ) // 4J - java uses instanceof EntityTile here
if( tile->isEntityTile() ) // 4J - java uses instanceof EntityTile here
{
// may not push tile entities
return false;

View file

@ -1230,7 +1230,9 @@ bool Tile::mayPlace(Level *level, int x, int y, int z, int face)
bool Tile::mayPlace(Level *level, int x, int y, int z)
{
int t = level->getTile(x, y, z);
return t == 0 || Tile::tiles[t]->material->isReplaceable();
Tile *tile = Tile::tiles[t];
if (tile == nullptr && t != 0) return false;
return t == 0 || tile->material->isReplaceable();
}
// 4J-PB - Adding a TestUse for tooltip display