diff options
Diffstat (limited to 'Minecraft.World/LiquidTileDynamic.cpp')
| -rw-r--r-- | Minecraft.World/LiquidTileDynamic.cpp | 343 |
1 files changed, 176 insertions, 167 deletions
diff --git a/Minecraft.World/LiquidTileDynamic.cpp b/Minecraft.World/LiquidTileDynamic.cpp index 14a93b93..2c7c74f4 100644 --- a/Minecraft.World/LiquidTileDynamic.cpp +++ b/Minecraft.World/LiquidTileDynamic.cpp @@ -6,8 +6,8 @@ LiquidTileDynamic::LiquidTileDynamic(int id, Material *material) : LiquidTile(id, material) { maxCount = 0; - result = new bool[4]; - dist = new int[4]; + result = new bool[4]; + dist = new int[4]; m_iterativeInstatick = false; } @@ -19,9 +19,8 @@ LiquidTileDynamic::~LiquidTileDynamic() void LiquidTileDynamic::setStatic(Level *level, int x, int y, int z) { - int d = level->getData(x, y, z); - level->setTileAndDataNoUpdate(x, y, z, id + 1, d); - level->setTilesDirty(x, y, z, x, y, z); + int d = level->getData(x, y, z); + level->setTileAndData(x, y, z, id + 1, d, Tile::UPDATE_CLIENTS); } bool LiquidTileDynamic::isPathfindable(LevelSource *level, int x, int y, int z) @@ -32,13 +31,16 @@ bool LiquidTileDynamic::isPathfindable(LevelSource *level, int x, int y, int z) void LiquidTileDynamic::iterativeTick(Level *level, int x, int y, int z, Random *random) { m_tilesToTick.push_back(LiquidTickData(level, x,y,z,random)); - - while(m_tilesToTick.size() > 0) + + int failsafe = 100; + while((m_tilesToTick.size() > 0) && ( failsafe > 0 ) ) { LiquidTickData tickData = m_tilesToTick.front(); m_tilesToTick.pop_front(); mainTick(tickData.level, tickData.x, tickData.y, tickData.z, tickData.random); + failsafe--; } + m_tilesToTick.clear(); } void LiquidTileDynamic::tick(Level *level, int x, int y, int z, Random *random) @@ -63,117 +65,119 @@ void LiquidTileDynamic::tick(Level *level, int x, int y, int z, Random *random) // This is to fix the stack overflow that occurs sometimes when instaticking on level gen. void LiquidTileDynamic::mainTick(Level *level, int x, int y, int z, Random *random) { - int depth = getDepth(level, x, y, z); + int depth = getDepth(level, x, y, z); - int dropOff = 1; - if (material == Material::lava && !level->dimension->ultraWarm) dropOff = 2; + int dropOff = 1; + if (material == Material::lava && !level->dimension->ultraWarm) dropOff = 2; - bool becomeStatic = true; - if (depth > 0) + bool becomeStatic = true; + int tickDelay = getTickDelay(level); + if (depth > 0) { - int highest = -100; - maxCount = 0; - highest = getHighest(level, x - 1, y, z, highest); - highest = getHighest(level, x + 1, y, z, highest); - highest = getHighest(level, x, y, z - 1, highest); - highest = getHighest(level, x, y, z + 1, highest); + int highest = -100; + maxCount = 0; + highest = getHighest(level, x - 1, y, z, highest); + highest = getHighest(level, x + 1, y, z, highest); + highest = getHighest(level, x, y, z - 1, highest); + highest = getHighest(level, x, y, z + 1, highest); - int newDepth = highest + dropOff; - if (newDepth >= 8 || highest < 0) + int newDepth = highest + dropOff; + if (newDepth >= 8 || highest < 0) { - newDepth = -1; - } - if (getDepth(level, x, y + 1, z) >= 0) + newDepth = -1; + } + if (getDepth(level, x, y + 1, z) >= 0) { - int above = getDepth(level, x, y + 1, z); - if (above >= 8) newDepth = above; - else newDepth = above + 8; - } - if (maxCount >= 2 && material == Material::water) + int above = getDepth(level, x, y + 1, z); + if (above >= 8) newDepth = above; + else newDepth = above + 8; + } + if (maxCount >= 2 && material == Material::water) { - // Only spread spring if it's on top of an existing spring, or + // Only spread spring if it's on top of an existing spring, or // on top of solid ground. - if (level->getMaterial(x, y - 1, z)->isSolid()) + if (level->getMaterial(x, y - 1, z)->isSolid()) { - newDepth = 0; - } + newDepth = 0; + } else if (level->getMaterial(x, y - 1, z) == material && level->getData(x, y - 1, z) == 0) { - newDepth = 0; - } - } - if (material == Material::lava) + newDepth = 0; + } + } + if (material == Material::lava) { - if (depth < 8 && newDepth < 8) + if (depth < 8 && newDepth < 8) { - if (newDepth > depth) + if (newDepth > depth) { - if (random->nextInt(4) != 0) + if (random->nextInt(4) != 0) { - newDepth = depth; - becomeStatic = false; - } - } - } - } - if (newDepth == depth) + tickDelay = tickDelay * 4; + } + } + } + } + if (newDepth == depth) { - if (becomeStatic) + if (becomeStatic) { setStatic(level, x, y, z); } - } + } else { - depth = newDepth; - if (depth < 0) + depth = newDepth; + if (depth < 0) { - level->setTile(x, y, z, 0); - } else + level->removeTile(x, y, z); + } + else { - level->setData(x, y, z, depth); - level->addToTickNextTick(x, y, z, id, getTickDelay()); - level->updateNeighborsAt(x, y, z, id); - } - } - } else + level->setData(x, y, z, depth, Tile::UPDATE_CLIENTS); + level->addToTickNextTick(x, y, z, id, tickDelay); + level->updateNeighborsAt(x, y, z, id); + } + } + } + else { - setStatic(level, x, y, z); - } - if (canSpreadTo(level, x, y - 1, z)) + setStatic(level, x, y, z); + } + if (canSpreadTo(level, x, y - 1, z)) { - if (material == Material::lava) + if (material == Material::lava) { - if (level->getMaterial(x, y - 1, z) == Material::water) + if (level->getMaterial(x, y - 1, z) == Material::water) { - level->setTile(x, y - 1, z, Tile::rock_Id); - fizz(level, x, y - 1, z); - return; - } - } + level->setTileAndUpdate(x, y - 1, z, Tile::stone_Id); + fizz(level, x, y - 1, z); + return; + } + } - if (depth >= 8) trySpreadTo(level, x, y - 1, z, depth); - else trySpreadTo(level, x, y - 1, z, depth + 8); - } + if (depth >= 8) trySpreadTo(level, x, y - 1, z, depth); + else trySpreadTo(level, x, y - 1, z, depth + 8); + } else if (depth >= 0 && (depth == 0 || isWaterBlocking(level, x, y - 1, z))) { - bool *spreads = getSpread(level, x, y, z); - int neighbor = depth + dropOff; - if (depth >= 8) + bool *spreads = getSpread(level, x, y, z); + int neighbor = depth + dropOff; + if (depth >= 8) { - neighbor = 1; - } - if (neighbor >= 8) return; - if (spreads[0]) trySpreadTo(level, x - 1, y, z, neighbor); - if (spreads[1]) trySpreadTo(level, x + 1, y, z, neighbor); - if (spreads[2]) trySpreadTo(level, x, y, z - 1, neighbor); - if (spreads[3]) trySpreadTo(level, x, y, z + 1, neighbor); - } + neighbor = 1; + } + if (neighbor >= 8) return; + if (spreads[0]) trySpreadTo(level, x - 1, y, z, neighbor); + if (spreads[1]) trySpreadTo(level, x + 1, y, z, neighbor); + if (spreads[2]) trySpreadTo(level, x, y, z - 1, neighbor); + if (spreads[3]) trySpreadTo(level, x, y, z + 1, neighbor); + } } void LiquidTileDynamic::trySpreadTo(Level *level, int x, int y, int z, int neighbor) { - if (canSpreadTo(level, x, y, z)) + if (canSpreadTo(level, x, y, z)) { { int old = level->getTile(x, y, z); @@ -189,129 +193,129 @@ void LiquidTileDynamic::trySpreadTo(Level *level, int x, int y, int z, int neigh } } } - level->setTileAndData(x, y, z, id, neighbor); - } + level->setTileAndData(x, y, z, id, neighbor, Tile::UPDATE_ALL); + } } int LiquidTileDynamic::getSlopeDistance(Level *level, int x, int y, int z, int pass, int from) { - int lowest = 1000; - for (int d = 0; d < 4; d++) + int lowest = 1000; + for (int d = 0; d < 4; d++) { - if (d == 0 && from == 1) continue; - if (d == 1 && from == 0) continue; - if (d == 2 && from == 3) continue; - if (d == 3 && from == 2) continue; + if (d == 0 && from == 1) continue; + if (d == 1 && from == 0) continue; + if (d == 2 && from == 3) continue; + if (d == 3 && from == 2) continue; - int xx = x; - int yy = y; - int zz = z; + int xx = x; + int yy = y; + int zz = z; - if (d == 0) xx--; - if (d == 1) xx++; - if (d == 2) zz--; - if (d == 3) zz++; + if (d == 0) xx--; + if (d == 1) xx++; + if (d == 2) zz--; + if (d == 3) zz++; - if (isWaterBlocking(level, xx, yy, zz)) + if (isWaterBlocking(level, xx, yy, zz)) { - continue; - } else if (level->getMaterial(xx, yy, zz) == material && level->getData(xx, yy, zz) == 0) + continue; + } else if (level->getMaterial(xx, yy, zz) == material && level->getData(xx, yy, zz) == 0) { - continue; - } + continue; + } else { - if (isWaterBlocking(level, xx, yy - 1, zz)) + if (isWaterBlocking(level, xx, yy - 1, zz)) { - if (pass < 4) + if (pass < 4) { - int v = getSlopeDistance(level, xx, yy, zz, pass + 1, d); - if (v < lowest) lowest = v; - } - } + int v = getSlopeDistance(level, xx, yy, zz, pass + 1, d); + if (v < lowest) lowest = v; + } + } else { - return pass; - } - } - } - return lowest; + return pass; + } + } + } + return lowest; } bool *LiquidTileDynamic::getSpread(Level *level, int x, int y, int z) { - for (int d = 0; d < 4; d++) + for (int d = 0; d < 4; d++) { - dist[d] = 1000; - int xx = x; - int yy = y; - int zz = z; + dist[d] = 1000; + int xx = x; + int yy = y; + int zz = z; - if (d == 0) xx--; - if (d == 1) xx++; - if (d == 2) zz--; - if (d == 3) zz++; - if (isWaterBlocking(level, xx, yy, zz)) + if (d == 0) xx--; + if (d == 1) xx++; + if (d == 2) zz--; + if (d == 3) zz++; + if (isWaterBlocking(level, xx, yy, zz)) { - continue; - } + continue; + } else if (level->getMaterial(xx, yy, zz) == material && level->getData(xx, yy, zz) == 0) { - continue; - } + continue; + } { - if (isWaterBlocking(level, xx, yy - 1, zz)) + if (isWaterBlocking(level, xx, yy - 1, zz)) { - dist[d] = getSlopeDistance(level, xx, yy, zz, 1, d); - } + dist[d] = getSlopeDistance(level, xx, yy, zz, 1, d); + } else { - dist[d] = 0; - } - } - } + dist[d] = 0; + } + } + } - int lowest = dist[0]; - for (int d = 1; d < 4; d++) + int lowest = dist[0]; + for (int d = 1; d < 4; d++) { - if (dist[d] < lowest) lowest = dist[d]; - } + if (dist[d] < lowest) lowest = dist[d]; + } - for (int d = 0; d < 4; d++) + for (int d = 0; d < 4; d++) { - result[d] = (dist[d] == lowest); - } - return result; + result[d] = (dist[d] == lowest); + } + return result; } bool LiquidTileDynamic::isWaterBlocking(Level *level, int x, int y, int z) { - int t = level->getTile(x, y, z); - if (t == Tile::door_wood_Id || t == Tile::door_iron_Id || t == Tile::sign_Id || t == Tile::ladder_Id || t == Tile::reeds_Id) + int t = level->getTile(x, y, z); + if (t == Tile::door_wood_Id || t == Tile::door_iron_Id || t == Tile::sign_Id || t == Tile::ladder_Id || t == Tile::reeds_Id) { - return true; - } - if (t == 0) return false; - Material *m = Tile::tiles[t]->material; - if (m == Material::portal) return true; - if (m->blocksMotion()) return true; - return false; + return true; + } + if (t == 0) return false; + Material *m = Tile::tiles[t]->material; + if (m == Material::portal) return true; + if (m->blocksMotion()) return true; + return false; } int LiquidTileDynamic::getHighest(Level *level, int x, int y, int z, int current) { - int d = getDepth(level, x, y, z); - if (d < 0) return current; - if (d == 0) maxCount++; - if (d >= 8) + int d = getDepth(level, x, y, z); + if (d < 0) return current; + if (d == 0) maxCount++; + if (d >= 8) { - d = 0; - } - return current < 0 || d < current ? d : current; + d = 0; + } + return current < 0 || d < current ? d : current; } bool LiquidTileDynamic::canSpreadTo(Level *level, int x, int y, int z) @@ -326,17 +330,22 @@ bool LiquidTileDynamic::canSpreadTo(Level *level, int x, int y, int z) if( ( ix < 0 ) || ( ix >= level->chunkSourceXZSize ) ) return false; if( ( iz < 0 ) || ( iz >= level->chunkSourceXZSize ) ) return false; - Material *target = level->getMaterial(x, y, z); - if (target == material) return false; - if (target == Material::lava) return false; - return !isWaterBlocking(level, x, y, z); + Material *target = level->getMaterial(x, y, z); + if (target == material) return false; + if (target == Material::lava) return false; + return !isWaterBlocking(level, x, y, z); } void LiquidTileDynamic::onPlace(Level *level, int x, int y, int z) { - LiquidTile::onPlace(level, x, y, z); - if (level->getTile(x, y, z) == id) + LiquidTile::onPlace(level, x, y, z); + if (level->getTile(x, y, z) == id) { - level->addToTickNextTick(x, y, z, id, getTickDelay()); - } + level->addToTickNextTick(x, y, z, id, getTickDelay(level)); + } } + +bool LiquidTileDynamic::canInstantlyTick() +{ + return true; +}
\ No newline at end of file |
