4jcraft/Minecraft.World/Blocks/LiquidTile.cpp
Nikita Edel a006cc5aa0 uninitialized vptr
the vptr to isSolidRender() is not known before contruction of the Tile. Its true by default. if false, need to pass false. that is what i did. i verfied what isSolidRender() is in every file. and did exactly what isSolidRender() would return
2026-03-10 23:22:34 +01:00

419 lines
12 KiB
C++

#include "../Platform/stdafx.h"
#include "../Util/JavaMath.h"
#include "../Headers/net.minecraft.world.level.h"
#include "../Headers/net.minecraft.world.level.biome.h"
#include "../Headers/net.minecraft.world.h"
#include "LiquidTile.h"
#include "../Util/Facing.h"
#include "../Util/SoundTypes.h"
const std::wstring LiquidTile::TEXTURE_LAVA_STILL = L"lava";
const std::wstring LiquidTile::TEXTURE_WATER_STILL = L"water";
const std::wstring LiquidTile::TEXTURE_WATER_FLOW = L"water_flow";
const std::wstring LiquidTile::TEXTURE_LAVA_FLOW = L"lava_flow";
LiquidTile::LiquidTile(int id, Material *material) : Tile(id, material, false)
{
float yo = 0;
float e = 0;
setShape(0 + e, 0 + yo, 0 + e, 1 + e, 1 + yo, 1 + e);
setTicking(true);
}
bool LiquidTile::isPathfindable(LevelSource *level, int x, int y, int z)
{
return material != Material::lava;
}
int LiquidTile::getColor() const
{
return 0xffffff;
}
int LiquidTile::getColor(LevelSource *level, int x, int y, int z)
{
return getColor(level, x, y, z, 0);
}
int LiquidTile::getColor(LevelSource *level, int x, int y, int z, int d)
{
if (material == Material::water)
{
int totalRed = 0;
int totalGreen = 0;
int totalBlue = 0;
for (int oz = -1; oz <= 1; oz++)
{
for (int ox = -1; ox <= 1; ox++)
{
int waterColor = level->getBiome(x + ox, z + oz)->getWaterColor();
totalRed += (waterColor & 0xff0000) >> 16;
totalGreen += (waterColor & 0xff00) >> 8;
totalBlue += (waterColor & 0xff);
}
}
return (((totalRed / 9) & 0xFF) << 16) | (((totalGreen / 9) & 0xFF) << 8) | (((totalBlue / 9) & 0xFF));
}
return 0xffffff;
}
float LiquidTile::getHeight(int d)
{
if (d >= 8) d = 0;
return (d + 1) / 9.0f;
}
Icon *LiquidTile::getTexture(int face, int data)
{
if (face == Facing::DOWN || face == Facing::UP)
{
return icons[0];
}
else
{
return icons[1];
}
}
int LiquidTile::getDepth(Level *level, int x, int y, int z)
{
if (level->getMaterial(x, y, z) == material) return level->getData(x, y, z);
else return -1;
}
int LiquidTile::getRenderedDepth(LevelSource *level, int x, int y, int z)
{
if (level->getMaterial(x, y, z) != material) return -1;
int d = level->getData(x, y, z);
if (d >= 8) d = 0;
return d;
}
bool LiquidTile::isCubeShaped()
{
return false;
}
bool LiquidTile::isSolidRender(bool isServerLevel)
{
return false;
}
bool LiquidTile::mayPick(int data, bool liquid)
{
return liquid && data == 0;
}
bool LiquidTile::isSolidFace(LevelSource *level, int x, int y, int z, int face)
{
Material *m = level->getMaterial(x, y, z);
if (m == this->material) return false;
if (face == Facing::UP) return true;
if (m == Material::ice) return false;
return Tile::isSolidFace(level, x, y, z, face);
}
bool LiquidTile::shouldRenderFace(LevelSource *level, int x, int y, int z, int face)
{
Material *m = level->getMaterial(x, y, z);
if (m == this->material) return false;
if (face == Facing::UP) return true;
if (m == Material::ice) return false;
return Tile::shouldRenderFace(level, x, y, z, face);
}
AABB *LiquidTile::getAABB(Level *level, int x, int y, int z)
{
return NULL;
}
int LiquidTile::getRenderShape()
{
return Tile::SHAPE_WATER;
}
int LiquidTile::getResource(int data, Random *random, int playerBonusLevel)
{
return 0;
}
int LiquidTile::getResourceCount(Random *random)
{
return 0;
}
Vec3 *LiquidTile::getFlow(LevelSource *level, int x, int y, int z)
{
Vec3 *flow = Vec3::newTemp(0,0,0);
int mid = getRenderedDepth(level, x, y, z);
for (int d = 0; d < 4; d++)
{
int xt = x;
int yt = y;
int zt = z;
if (d == 0) xt--;
if (d == 1) zt--;
if (d == 2) xt++;
if (d == 3) zt++;
int t = getRenderedDepth(level, xt, yt, zt);
if (t < 0)
{
if (!level->getMaterial(xt, yt, zt)->blocksMotion())
{
t = getRenderedDepth(level, xt, yt - 1, zt);
if (t >= 0)
{
int dir = t - (mid - 8);
flow = flow->add((xt - x) * dir, (yt - y) * dir, (zt - z) * dir);
}
}
} else
{
if (t >= 0)
{
int dir = t - mid;
flow = flow->add((xt - x) * dir, (yt - y) * dir, (zt - z) * dir);
}
}
}
if (level->getData(x, y, z) >= 8)
{
bool ok = false;
if (ok || isSolidFace(level, x, y, z - 1, 2)) ok = true;
if (ok || isSolidFace(level, x, y, z + 1, 3)) ok = true;
if (ok || isSolidFace(level, x - 1, y, z, 4)) ok = true;
if (ok || isSolidFace(level, x + 1, y, z, 5)) ok = true;
if (ok || isSolidFace(level, x, y + 1, z - 1, 2)) ok = true;
if (ok || isSolidFace(level, x, y + 1, z + 1, 3)) ok = true;
if (ok || isSolidFace(level, x - 1, y + 1, z, 4)) ok = true;
if (ok || isSolidFace(level, x + 1, y + 1, z, 5)) ok = true;
if (ok) flow = flow->normalize()->add(0, -6, 0);
}
flow = flow->normalize();
return flow;
}
void LiquidTile::handleEntityInside(Level *level, int x, int y, int z, std::shared_ptr<Entity> e, Vec3 *current)
{
Vec3 *flow = getFlow(level, x, y, z);
current->x += flow->x;
current->y += flow->y;
current->z += flow->z;
}
int LiquidTile::getTickDelay()
{
if (material == Material::water) return 5;
if (material == Material::lava) return 30;
return 0;
}
// 4J - change brought forward from 1.8.2
int LiquidTile::getLightColor(LevelSource *level, int x, int y, int z, int tileId/*=-1*/)
{
// 4J - note that this code seems to basically be a hack to fix a problem where post-processed things like lakes aren't getting lit properly
int a = level->getLightColor(x, y, z, 0, tileId);
int b = level->getLightColor(x, y + 1, z, 0, tileId);
int aa = a & 0xff;
int ba = b & 0xff;
int ab = (a >> 16) & 0xff;
int bb = (b >> 16) & 0xff;
return (aa > ba ? aa : ba) | ((ab > bb ? ab : bb) << 16);
}
float LiquidTile::getBrightness(LevelSource *level, int x, int y, int z)
{
float a = level->getBrightness(x, y, z);
float b = level->getBrightness(x, y + 1, z);
return a > b ? a : b;
}
int LiquidTile::getRenderLayer()
{
return material == Material::water ? 1 : 0;
}
void LiquidTile::animateTick(Level *level, int x, int y, int z, Random *random)
{
if (material == Material::water)
{
if (random->nextInt(10) == 0)
{
int d = level->getData(x, y, z);
if (d <= 0 || d >= 8)
{
level->addParticle(eParticleType_suspended, x + random->nextFloat(), y + random->nextFloat(), z + random->nextFloat(), 0, 0, 0);
}
}
// 4J-PB - this loop won't run!
for (int i = 0; i < 0; i++)
{ // This was an attempt to add foam to
// the bottoms of waterfalls. It
// didn't went ok.
int dir = random->nextInt(4);
int xt = x;
int zt = z;
if (dir == 0) xt--;
if (dir == 1) xt++;
if (dir == 2) zt--;
if (dir == 3) zt++;
if (level->getMaterial(xt, y, zt) == Material::air && (level->getMaterial(xt, y - 1, zt)->blocksMotion() || level->getMaterial(xt, y - 1, zt)->isLiquid()))
{
float r = 1 / 16.0f;
double xx = x + random->nextFloat();
double yy = y + random->nextFloat();
double zz = z + random->nextFloat();
if (dir == 0) xx = x - r;
if (dir == 1) xx = x + 1 + r;
if (dir == 2) zz = z - r;
if (dir == 3) zz = z + 1 + r;
double xd = 0;
double zd = 0;
if (dir == 0) xd = -r;
if (dir == 1) xd = +r;
if (dir == 2) zd = -r;
if (dir == 3) zd = +r;
level->addParticle(eParticleType_splash, xx, yy, zz, xd, 0, zd);
}
}
}
if (material == Material::water && random->nextInt(64) == 0)
{
int d = level->getData(x, y, z);
if (d > 0 && d < 8)
{
level->playLocalSound(x + 0.5f, y + 0.5f, z + 0.5f, eSoundType_LIQUID_WATER, random->nextFloat() * 0.25f + 0.75f, random->nextFloat() * 1.0f + 0.5f);
}
}
if (material == Material::lava)
{
if (level->getMaterial(x, y + 1, z) == Material::air && !level->isSolidRenderTile(x, y + 1, z))
{
if (random->nextInt(100) == 0)
{
ThreadStorage *tls = (ThreadStorage *)TlsGetValue(Tile::tlsIdxShape);
double xx = x + random->nextFloat();
double yy = y + tls->yy1;
double zz = z + random->nextFloat();
level->addParticle(eParticleType_lava, xx, yy, zz, 0, 0, 0);
// 4J - new sound brought forward from 1.2.3
level->playLocalSound(xx, yy, zz, eSoundType_LIQUID_LAVA_POP, 0.2f + random->nextFloat() * 0.2f, 0.9f + random->nextFloat() * 0.15f);
}
// 4J - new sound brought forward from 1.2.3
if (random->nextInt(200) == 0)
{
level->playLocalSound(x, y, z, eSoundType_LIQUID_LAVA, 0.2f + random->nextFloat() * 0.2f, 0.9f + random->nextFloat() * 0.15f);
}
}
}
if (random->nextInt(10) == 0)
{
if (level->isTopSolidBlocking(x, y - 1, z) && !level->getMaterial(x, y - 2, z)->blocksMotion())
{
double xx = x + random->nextFloat();
double yy = y - 1.05;
double zz = z + random->nextFloat();
if (material == Material::water) level->addParticle(eParticleType_dripWater, xx, yy, zz, 0, 0, 0);
else level->addParticle(eParticleType_dripLava, xx, yy, zz, 0, 0, 0);
}
}
}
double LiquidTile::getSlopeAngle(LevelSource *level, int x, int y, int z, Material *m)
{
Vec3 *flow = NULL;
if (m == Material::water) flow = ((LiquidTile *) Tile::water)->getFlow(level, x, y, z);
if (m == Material::lava) flow = ((LiquidTile *) Tile::lava)->getFlow(level, x, y, z);
if (flow->x == 0 && flow->z == 0) return -1000;
return atan2(flow->z, flow->x) - PI / 2;
}
void LiquidTile::onPlace(Level *level, int x, int y, int z)
{
updateLiquid(level, x, y, z);
}
void LiquidTile::neighborChanged(Level *level, int x, int y, int z, int type)
{
updateLiquid(level, x, y, z);
}
void LiquidTile::updateLiquid(Level *level, int x, int y, int z)
{
if (level->getTile(x, y, z) != id) return;
if (material == Material::lava)
{
bool water = false;
if (water || level->getMaterial(x, y, z - 1) == Material::water) water = true;
if (water || level->getMaterial(x, y, z + 1) == Material::water) water = true;
if (water || level->getMaterial(x - 1, y, z) == Material::water) water = true;
if (water || level->getMaterial(x + 1, y, z) == Material::water) water = true;
if (water || level->getMaterial(x, y + 1, z) == Material::water) water = true;
if (water)
{
int data = level->getData(x, y, z);
if (data == 0)
{
level->setTile(x, y, z, Tile::obsidian_Id);
}
else if (data <= 4)
{
level->setTile(x, y, z, Tile::stoneBrick_Id);
}
fizz(level, x, y, z);
}
}
}
void LiquidTile::fizz(Level *level, int x, int y, int z)
{
MemSect(31);
level->playSound(x + 0.5f, y + 0.5f, z + 0.5f, eSoundType_RANDOM_FIZZ, 0.5f, 2.6f + (level->random->nextFloat() - level->random->nextFloat()) * 0.8f);
MemSect(0);
for (int i = 0; i < 8; i++)
{
level->addParticle(eParticleType_largesmoke, x +Math::random(), y + 1.2, z + Math::random(), 0, 0, 0);
}
}
void LiquidTile::registerIcons(IconRegister *iconRegister)
{
if (material == Material::lava)
{
icons[0] = iconRegister->registerIcon(TEXTURE_LAVA_STILL);
icons[1] = iconRegister->registerIcon(TEXTURE_LAVA_FLOW);
}
else
{
icons[0] = iconRegister->registerIcon(TEXTURE_WATER_STILL);
icons[1] = iconRegister->registerIcon(TEXTURE_WATER_FLOW);
}
}
Icon *LiquidTile::getTexture(const std::wstring &name)
{
if (name.compare(TEXTURE_WATER_STILL)==0) return Tile::water->icons[0];
if (name.compare(TEXTURE_WATER_FLOW)==0) return Tile::water->icons[1];
if (name.compare(TEXTURE_LAVA_STILL)==0) return Tile::lava->icons[0];
if (name.compare(TEXTURE_LAVA_FLOW)==0) return Tile::lava->icons[1];
return NULL;
}