static int _try_block (world &w, int x, int y, int z) { int prev_id = w.get_final_block (x, y, z).id; if (!w.in_bounds (x, y, z) || !_is_water (prev_id)) return -1; w.queue_update (x, y, z, BT_SHARK); return prev_id; }
static bool _try_door_lock (world &w, int x, int y, int z, block_data bd) { if (bd.ex != BE_DOOR) return false; w.queue_update (x, y, z, BT_AIR); w.queue_physics (x, y, z, bd.id | (bd.meta << 12), nullptr, DOOR_TICK_RATE, nullptr, _door_tick); return true; }
void _door_tick (world &w, int x, int y, int z, int data, std::minstd_rand& rnd) { int id = data & 0xFFF; int meta = (data >> 12) & 0xF; int elapsed = data >> 16; if (elapsed == 0) { _try_door_lock (w, x - 1, y, z, w.get_block (x - 1, y, z)); _try_door_lock (w, x + 1, y, z, w.get_block (x + 1, y, z)); _try_door_lock (w, x, y, z - 1, w.get_block (x, y, z - 1)); _try_door_lock (w, x, y, z + 1, w.get_block (x, y, z + 1)); if (y > 0) _try_door_lock (w, x, y - 1, z, w.get_block (x, y - 1, z)); if (y < 255) _try_door_lock (w, x, y + 1, z, w.get_block (x, y + 1, z)); } ++ elapsed; if (elapsed == (5 * 4)) // 4 seconds w.queue_update (x, y, z, id, meta, BE_DOOR); else w.queue_physics (x, y, z, id | (meta << 12) | (elapsed << 16), nullptr, DOOR_TICK_RATE, nullptr, _door_tick); }
void snow::tick (world &w, int x, int y, int z, int extra, void *ptr, std::minstd_rand& rnd) { if (y <= 0) { w.queue_update (x, y, z, BT_AIR); return; } if (w.get_final_block (x, y, z).id != BT_SNOW_BLOCK) return; int below = w.get_final_block (x, y - 1, z).id; if (w.get_final_block (x, y - 1, z).id != BT_AIR) { if (below == BT_SNOW_BLOCK || below == BT_SNOW_COVER) w.queue_update (x, y, z, BT_AIR); else w.queue_update (x, y, z, BT_SNOW_COVER); } else { w.queue_update (x, y, z, BT_AIR); int nx = x, nz = z; std::uniform_int_distribution<> dis (1, 4); int d = dis (rnd); switch (d) { case 1: ++ nx; break; case 2: -- nx; break; case 3: ++ nz; break; case 4: -- nz; break; } if (w.get_final_block (nx, y - 1, nz) == BT_AIR) w.queue_update (nx, y - 1, nz, BT_SNOW_BLOCK); else w.queue_update (x, y - 1, z, BT_SNOW_BLOCK); } }
void sand::tick (world &w, int x, int y, int z, int extra, void *ptr) { if (y <= 0) { w.queue_update (x, y, z, BT_AIR); return; } if (w.get_final_block (x, y, z).id != BT_SAND) return; int below = w.get_final_block (x, y - 1, z).id; if (below == BT_AIR) { w.queue_update (x, y, z, BT_AIR); w.queue_update (x, y - 1, z, BT_SAND); } else { if (w.get_final_block (x - 1, y - 1, z).id == BT_AIR && w.get_final_block (x - 1, y, z).id == BT_AIR) { w.queue_update (x, y, z, BT_AIR); w.queue_update (x - 1, y - 1, z, BT_SAND); } else if (w.get_final_block (x + 1, y - 1, z).id == BT_AIR && w.get_final_block (x + 1, y, z).id == BT_AIR) { w.queue_update (x, y, z, BT_AIR); w.queue_update (x + 1, y - 1, z, BT_SAND); } else if (w.get_final_block (x, y - 1, z - 1).id == BT_AIR && w.get_final_block (x, y, z - 1).id == BT_AIR) { w.queue_update (x, y, z, BT_AIR); w.queue_update (x, y - 1, z - 1, BT_SAND); } else if (w.get_final_block (x, y - 1, z + 1).id == BT_AIR && w.get_final_block (x, y, z + 1).id == BT_AIR) { w.queue_update (x, y, z, BT_AIR); w.queue_update (x, y - 1, z + 1, BT_SAND); } } }
void shark::tick (world &w, int x, int y, int z, int data, void *ptr, std::minstd_rand& rnd) { if (y <= 0) { w.queue_update (x, y, z, BT_AIR); return; } if (w.get_final_block (x, y, z).id != BT_SHARK) return; int below = w.get_final_block (x, y - 1, z).id; if (below == BT_AIR || (_is_water (below) && (w.get_final_block (x, y + 1, z).id == BT_AIR))) { w.queue_update (x, y, z, _sur_water (w, x, y, z)); w.queue_update (x, y - 1, z, BT_SHARK); } else { int nx = x, ny = y, nz = z; // find closest player player *target = nullptr; w.get_players ().all ( [x, y, z, &target] (player *pl) { double dx = x - pl->pos.x; double dy = y - pl->pos.y; double dz = z - pl->pos.z; double dm = dx*dx + dy*dy + dz*dz; if (dm > 6*6) return; if (!target) target = pl; else { double pdx = x - target->pos.x; double pdy = y - target->pos.y; double pdz = z - target->pos.z; if (dm < (pdx*pdx + pdy*pdy + pdz*pdz)) target = pl; } }); if (!target) { // move around in a random fashion std::uniform_int_distribution<> dis (0, 5); switch (dis (rnd)) { case 0: -- ny; break; case 1: ++ ny; break; case 2: -- nz; break; case 3: ++ nz; break; case 4: -- nx; break; case 5: ++ nx; break; } } else { if (x < target->pos.x) { if (_is_water (w.get_final_block (x + 1, ny, nz).id)) ++ nx; } else if (x > target->pos.x) { if (_is_water (w.get_final_block (x - 1, ny, nz).id)) -- nx; } if (y < target->pos.y) { if (_is_water (w.get_final_block (nx, y + 1, nz).id)) ++ ny; } else if (y > target->pos.y) { if (_is_water (w.get_final_block (nx, y - 1, nz).id)) -- ny; } if (z < target->pos.z) { if (_is_water (w.get_final_block (nx, ny, z + 1).id)) ++ nz; } else if (z > target->pos.z) { if (_is_water (w.get_final_block (nx, ny, z - 1).id)) -- nz; } } int prev = _try_block (w, nx, ny, nz); if (prev == -1) w.queue_physics (x, y, z, 0, nullptr, this->tick_rate ()); else w.queue_update (x, y, z, prev, 0, 0, 0, nullptr, nullptr, false); } }