alex/beta-minecraft-rust
Minecraft Beta 1.7.3 Rewrite
BRANCH main
SNAPSHOT Draw terrain GPU-driven from packed per-section buffers with GPU occlusion culling, add a render distance slider (2-128) with a quad/disk shape, cut chunk bookkeeping at high render distances, and fix a light underflow at y=0
DOWNLOAD
root crates server src spawn.rs
use common::entity::Entity;
use common::math::floor_f64;
use common::world::{Block, ChunkPos};
use crate::level::Level;
/// Port of `World.getInitialSpawnLocation`: walks randomly from the origin until the
/// surface is sand. The search loads and populates chunks on the way, like the original.
pub fn find(level: &mut Level) -> (i32, i32) {
let (mut x, mut z) = (0, 0);
while first_uncovered(level, x, z) != Block::SAND {
x += level.rand.next_int(64) - level.rand.next_int(64);
z += level.rand.next_int(64) - level.rand.next_int(64);
}
(x, z)
}
/// `Entity.preparePlayerToSpawn`: raises the player until nothing collides.
pub fn prepare_player(level: &mut Level, entity: &mut Entity) {
while entity.pos.y > 0.0 {
entity.set_position(entity.pos);
let region = entity.bb;
let (x0, x1) = (floor_f64(region.min.x) >> 4, floor_f64(region.max.x) >> 4);
let (z0, z1) = (floor_f64(region.min.z) >> 4, floor_f64(region.max.z) >> 4);
for cx in x0..=x1 {
for cz in z0..=z1 {
level.load_chunk(ChunkPos::new(cx, cz));
}
}
if level.block_boxes(®ion).is_empty() {
break;
}
entity.pos.y += 1.0;
}
entity.motion = glam::DVec3::ZERO;
entity.pitch = 0.0;
}
/// `World.setSpawnLocation`, before a singleplayer respawn: moves the spawn off columns
/// without ground.
pub fn repair(level: &mut Level, [mut x, mut y, mut z]: [i32; 3]) -> [i32; 3] {
if y <= 0 {
y = 64;
}
while first_uncovered(level, x, z) == Block::AIR {
x += level.rand.next_int(8) - level.rand.next_int(8);
z += level.rand.next_int(8) - level.rand.next_int(8);
}
[x, y, z]
}
/// The `EntityPlayerMP` constructor: somewhere in the 20 by 20 square around the spawn.
pub fn multiplayer(level: &mut Level, entity: &mut Entity, [mut x, mut y, mut z]: [i32; 3]) {
if level.has_sky() {
x += entity.rand.next_int(20) - 10;
y = top_solid(level, x, z);
z += entity.rand.next_int(20) - 10;
}
let pos = glam::DVec3::new(f64::from(x) + 0.5, f64::from(y), f64::from(z) + 0.5);
entity.set_location_and_angles(pos, 0.0, 0.0);
}
/// `World.findTopSolidBlock` of the server: one above the highest solid block, or -1.
fn top_solid(level: &mut Level, x: i32, z: i32) -> i32 {
(1..128)
.rev()
.find(|&y| level.block(x, y, z).material().is_solid())
.map_or(-1, |y| y + 1)
}
/// `World.getFirstUncoveredBlock`.
fn first_uncovered(level: &mut Level, x: i32, z: i32) -> Block {
let mut y = 63;
while !level.is_air(x, y + 1, z) {
y += 1;
}
level.block(x, y, z)
}