Collisions and normal style movement
This commit is contained in:
parent
be49342dbc
commit
75eb62c975
|
@ -753,7 +753,7 @@ impl Conn {
|
||||||
if self.compression_threshold >= 0 && extra == 1 {
|
if self.compression_threshold >= 0 && extra == 1 {
|
||||||
try!(VarInt(0).write_to(self));
|
try!(VarInt(0).write_to(self));
|
||||||
}
|
}
|
||||||
try!(self.write_all(&buf.into_boxed_slice()));
|
try!(self.write_all(&buf));
|
||||||
|
|
||||||
Result::Ok(())
|
Result::Ok(())
|
||||||
}
|
}
|
||||||
|
|
326
src/server.rs
326
src/server.rs
|
@ -25,7 +25,8 @@ use openssl;
|
||||||
use console;
|
use console;
|
||||||
use render;
|
use render;
|
||||||
use auth;
|
use auth;
|
||||||
use cgmath::{self, Vector};
|
use cgmath::{self, Vector, Point, Point3};
|
||||||
|
use collision::{Aabb, Aabb3};
|
||||||
use sdl2::keyboard::Keycode;
|
use sdl2::keyboard::Keycode;
|
||||||
|
|
||||||
pub struct Server {
|
pub struct Server {
|
||||||
|
@ -43,14 +44,61 @@ pub struct Server {
|
||||||
version: usize,
|
version: usize,
|
||||||
|
|
||||||
pub position: cgmath::Vector3<f64>,
|
pub position: cgmath::Vector3<f64>,
|
||||||
|
last_position: cgmath::Vector3<f64>,
|
||||||
pub yaw: f64,
|
pub yaw: f64,
|
||||||
pub pitch: f64,
|
pub pitch: f64,
|
||||||
|
bounds: Aabb3<f64>,
|
||||||
|
gamemode: Gamemode,
|
||||||
|
flying: bool,
|
||||||
|
on_ground: bool,
|
||||||
|
did_touch_ground: bool,
|
||||||
|
v_speed: f64,
|
||||||
|
|
||||||
pressed_keys: HashMap<Keycode, bool>,
|
pressed_keys: HashMap<Keycode, bool>,
|
||||||
|
|
||||||
tick_timer: f64,
|
tick_timer: f64,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
pub enum Gamemode {
|
||||||
|
Survival = 0,
|
||||||
|
Creative = 1,
|
||||||
|
Adventure = 2,
|
||||||
|
Spectator = 3,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Gamemode {
|
||||||
|
pub fn from_int(val: i32) -> Gamemode {
|
||||||
|
match val {
|
||||||
|
3 => Gamemode::Spectator,
|
||||||
|
2 => Gamemode::Adventure,
|
||||||
|
1 => Gamemode::Creative,
|
||||||
|
0 | _ => Gamemode::Survival,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn can_fly(&self) -> bool {
|
||||||
|
match *self {
|
||||||
|
Gamemode::Creative | Gamemode::Spectator => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn always_fly(&self) -> bool {
|
||||||
|
match *self {
|
||||||
|
Gamemode::Spectator => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn noclip(&self) -> bool {
|
||||||
|
match *self {
|
||||||
|
Gamemode::Spectator => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! handle_packet {
|
macro_rules! handle_packet {
|
||||||
($s:ident $pck:ident {
|
($s:ident $pck:ident {
|
||||||
$($packet:ident => $func:ident,)*
|
$($packet:ident => $func:ident,)*
|
||||||
|
@ -147,48 +195,35 @@ impl Server {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let version = resources.read().unwrap().version();
|
Ok(Server::new(resources, console, Some(write), Some(rx)))
|
||||||
Ok(Server {
|
|
||||||
conn: Some(write),
|
|
||||||
read_queue: Some(rx),
|
|
||||||
|
|
||||||
world: world::World::new(),
|
|
||||||
world_age: 0,
|
|
||||||
world_time: 0.0,
|
|
||||||
world_time_target: 0.0,
|
|
||||||
tick_time: true,
|
|
||||||
|
|
||||||
resources: resources,
|
|
||||||
console: console,
|
|
||||||
version: version,
|
|
||||||
|
|
||||||
pressed_keys: HashMap::new(),
|
|
||||||
|
|
||||||
position: cgmath::Vector3::zero(),
|
|
||||||
yaw: 0.0,
|
|
||||||
pitch: 0.0,
|
|
||||||
|
|
||||||
tick_timer: 0.0,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dummy_server(resources: Arc<RwLock<resources::Manager>>, console: Arc<Mutex<console::Console>>) -> Server {
|
pub fn dummy_server(resources: Arc<RwLock<resources::Manager>>, console: Arc<Mutex<console::Console>>) -> Server {
|
||||||
let mut world = world::World::new();
|
let mut server = Server::new(resources, console, None, None);
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
for x in -7*16 .. 7*16 {
|
for x in -7*16 .. 7*16 {
|
||||||
for z in -7*16 .. 7*16 {
|
for z in -7*16 .. 7*16 {
|
||||||
let h = rng.gen_range(3, 10);
|
let h = rng.gen_range(3, 10);
|
||||||
for y in 0 .. h {
|
for y in 0 .. h {
|
||||||
world.set_block(x, y, z, block::Dirt{});
|
server.world.set_block(x, y, z, block::Dirt{});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
server.gamemode = Gamemode::Spectator;
|
||||||
|
server.flying = false;
|
||||||
|
server
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new(
|
||||||
|
resources: Arc<RwLock<resources::Manager>>, console: Arc<Mutex<console::Console>>,
|
||||||
|
conn: Option<protocol::Conn>, read_queue: Option<mpsc::Receiver<Result<packet::Packet, protocol::Error>>>
|
||||||
|
) -> Server {
|
||||||
let version = resources.read().unwrap().version();
|
let version = resources.read().unwrap().version();
|
||||||
Server {
|
Server {
|
||||||
conn: None,
|
conn: conn,
|
||||||
read_queue: None,
|
read_queue: read_queue,
|
||||||
|
|
||||||
world: world,
|
world: world::World::new(),
|
||||||
world_age: 0,
|
world_age: 0,
|
||||||
world_time: 0.0,
|
world_time: 0.0,
|
||||||
world_time_target: 0.0,
|
world_time_target: 0.0,
|
||||||
|
@ -201,8 +236,18 @@ impl Server {
|
||||||
pressed_keys: HashMap::new(),
|
pressed_keys: HashMap::new(),
|
||||||
|
|
||||||
position: cgmath::Vector3::new(0.5, 13.2, 0.5),
|
position: cgmath::Vector3::new(0.5, 13.2, 0.5),
|
||||||
|
last_position: cgmath::Vector3::zero(),
|
||||||
yaw: 0.0,
|
yaw: 0.0,
|
||||||
pitch: 0.0,
|
pitch: 0.0,
|
||||||
|
bounds: Aabb3::new(
|
||||||
|
Point3::new(-0.3, 0.0, -0.3),
|
||||||
|
Point3::new(0.3, 1.8, 0.3)
|
||||||
|
),
|
||||||
|
gamemode: Gamemode::Survival,
|
||||||
|
flying: false,
|
||||||
|
on_ground: false,
|
||||||
|
did_touch_ground: false,
|
||||||
|
v_speed: 0.0,
|
||||||
|
|
||||||
tick_timer: 0.0,
|
tick_timer: 0.0,
|
||||||
}
|
}
|
||||||
|
@ -224,11 +269,14 @@ impl Server {
|
||||||
match pck {
|
match pck {
|
||||||
Ok(pck) => handle_packet!{
|
Ok(pck) => handle_packet!{
|
||||||
self pck {
|
self pck {
|
||||||
|
JoinGame => on_game_join,
|
||||||
|
Respawn => on_respawn,
|
||||||
KeepAliveClientbound => on_keep_alive,
|
KeepAliveClientbound => on_keep_alive,
|
||||||
ChunkData => on_chunk_data,
|
ChunkData => on_chunk_data,
|
||||||
ChunkUnload => on_chunk_unload,
|
ChunkUnload => on_chunk_unload,
|
||||||
TeleportPlayer => on_teleport,
|
TeleportPlayer => on_teleport,
|
||||||
TimeUpdate => on_time_update,
|
TimeUpdate => on_time_update,
|
||||||
|
ChangeGameState => on_game_state_change,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Err(err) => panic!("Err: {:?}", err),
|
Err(err) => panic!("Err: {:?}", err),
|
||||||
|
@ -237,14 +285,15 @@ impl Server {
|
||||||
self.read_queue = Some(rx);
|
self.read_queue = Some(rx);
|
||||||
}
|
}
|
||||||
|
|
||||||
let (forward, yaw) = self.calculate_movement();
|
self.flying |= self.gamemode.always_fly();
|
||||||
|
self.last_position = self.position;
|
||||||
if self.world.is_chunk_loaded((self.position.x as i32) >> 4, (self.position.z as i32) >> 4) {
|
if self.world.is_chunk_loaded((self.position.x as i32) >> 4, (self.position.z as i32) >> 4) {
|
||||||
let mut speed = 4.317 / 60.0;
|
let (forward, yaw) = self.calculate_movement();
|
||||||
if self.is_key_pressed(Keycode::LShift) {
|
let mut speed = 4.317 / 60.0;
|
||||||
speed = 5.612 / 60.0;
|
if self.is_key_pressed(Keycode::LShift) {
|
||||||
}
|
speed = 5.612 / 60.0;
|
||||||
// TODO: only do this for flying
|
}
|
||||||
|
if self.flying {
|
||||||
speed *= 2.5;
|
speed *= 2.5;
|
||||||
|
|
||||||
if self.is_key_pressed(Keycode::Space) {
|
if self.is_key_pressed(Keycode::Space) {
|
||||||
|
@ -253,8 +302,85 @@ impl Server {
|
||||||
if self.is_key_pressed(Keycode::LCtrl) {
|
if self.is_key_pressed(Keycode::LCtrl) {
|
||||||
self.position.y -= speed * delta;
|
self.position.y -= speed * delta;
|
||||||
}
|
}
|
||||||
self.position.x += forward * yaw.cos() * delta * speed;
|
} else {
|
||||||
self.position.z -= forward * yaw.sin() * delta * speed;
|
if self.on_ground {
|
||||||
|
if self.is_key_pressed(Keycode::Space) {
|
||||||
|
self.v_speed = 0.15;
|
||||||
|
} else {
|
||||||
|
self.v_speed = 0.0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.v_speed -= 0.01 * delta;
|
||||||
|
if self.v_speed < -0.3 {
|
||||||
|
self.v_speed = -0.3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.position.x += forward * yaw.cos() * delta * speed;
|
||||||
|
self.position.z -= forward * yaw.sin() * delta * speed;
|
||||||
|
self.position.y += self.v_speed * delta;
|
||||||
|
}
|
||||||
|
|
||||||
|
if !self.gamemode.noclip() {
|
||||||
|
let mut target = self.position;
|
||||||
|
self.position.y = self.last_position.y;
|
||||||
|
self.position.z = self.last_position.z;
|
||||||
|
|
||||||
|
// We handle each axis separately to allow for a sliding
|
||||||
|
// effect when pushing up against walls.
|
||||||
|
|
||||||
|
let (bounds, xhit) = self.check_collisions(self.bounds);
|
||||||
|
self.position.x = bounds.min.x + 0.3;
|
||||||
|
self.last_position.x = self.position.x;
|
||||||
|
|
||||||
|
self.position.z = target.z;
|
||||||
|
let (bounds, zhit) = self.check_collisions(self.bounds);
|
||||||
|
self.position.z = bounds.min.z + 0.3;
|
||||||
|
self.last_position.z = self.position.z;
|
||||||
|
|
||||||
|
// Half block jumps
|
||||||
|
// Minecraft lets you 'jump' up 0.5 blocks
|
||||||
|
// for slabs and stairs (or smaller blocks).
|
||||||
|
// Currently we implement this as a teleport to the
|
||||||
|
// top of the block if we could move there
|
||||||
|
// but this isn't smooth.
|
||||||
|
if (xhit || zhit) && self.on_ground {
|
||||||
|
let mut ox = self.position.x;
|
||||||
|
let mut oz = self.position.z;
|
||||||
|
self.position.x = target.x;
|
||||||
|
self.position.z = target.z;
|
||||||
|
for offset in 1 .. 9 {
|
||||||
|
let mini = self.bounds.add_v(cgmath::Vector3::new(0.0, offset as f64 / 16.0, 0.0));
|
||||||
|
let (_, hit) = self.check_collisions(mini);
|
||||||
|
if !hit {
|
||||||
|
target.y += offset as f64 / 16.0;
|
||||||
|
ox = target.x;
|
||||||
|
oz = target.z;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.position.x = ox;
|
||||||
|
self.position.z = oz;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.position.y = target.y;
|
||||||
|
let (bounds, yhit) = self.check_collisions(self.bounds);
|
||||||
|
self.position.y = bounds.min.y;
|
||||||
|
self.last_position.y = self.position.y;
|
||||||
|
if yhit {
|
||||||
|
self.v_speed = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
let ground = Aabb3::new(
|
||||||
|
Point3::new(-0.3, -0.05, -0.3),
|
||||||
|
Point3::new(0.3, 0.0, 0.3)
|
||||||
|
);
|
||||||
|
let prev = self.on_ground;
|
||||||
|
let (_, hit) = self.check_collisions(ground);
|
||||||
|
self.on_ground = hit;
|
||||||
|
if !prev && self.on_ground {
|
||||||
|
self.did_touch_ground = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.tick_timer += delta;
|
self.tick_timer += delta;
|
||||||
|
@ -266,7 +392,7 @@ impl Server {
|
||||||
self.update_time(renderer, delta);
|
self.update_time(renderer, delta);
|
||||||
|
|
||||||
// Copy to camera
|
// Copy to camera
|
||||||
renderer.camera.pos = cgmath::Point::from_vec(self.position + cgmath::Vector3::new(0.0, 1.8, 0.0));
|
renderer.camera.pos = cgmath::Point::from_vec(self.position + cgmath::Vector3::new(0.0, 1.62, 0.0));
|
||||||
renderer.camera.yaw = self.yaw;
|
renderer.camera.yaw = self.yaw;
|
||||||
renderer.camera.pitch = self.pitch;
|
renderer.camera.pitch = self.pitch;
|
||||||
}
|
}
|
||||||
|
@ -312,6 +438,37 @@ impl Server {
|
||||||
offset * 0.8 + 0.2
|
offset * 0.8 + 0.2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn check_collisions(&self, bounds: Aabb3<f64>) -> (Aabb3<f64>, bool) {
|
||||||
|
let mut bounds = bounds.add_v(self.position);
|
||||||
|
|
||||||
|
let dir = self.position - self.last_position;
|
||||||
|
|
||||||
|
let min_x = (bounds.min.x - 1.0) as i32;
|
||||||
|
let min_y = (bounds.min.y - 1.0) as i32;
|
||||||
|
let min_z = (bounds.min.z - 1.0) as i32;
|
||||||
|
let max_x = (bounds.max.x + 1.0) as i32;
|
||||||
|
let max_y = (bounds.max.y + 1.0) as i32;
|
||||||
|
let max_z = (bounds.max.z + 1.0) as i32;
|
||||||
|
|
||||||
|
let mut hit = false;
|
||||||
|
for y in min_y .. max_y {
|
||||||
|
for z in min_z .. max_z {
|
||||||
|
for x in min_x .. max_x {
|
||||||
|
let block = self.world.get_block(x, y, z);
|
||||||
|
for bb in block.get_collision_boxes() {
|
||||||
|
let bb = bb.add_v(cgmath::Vector3::new(x as f64, y as f64, z as f64));
|
||||||
|
if bb.collides(&bounds) {
|
||||||
|
bounds = bounds.move_out_of(bb, dir);
|
||||||
|
hit = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(bounds, hit)
|
||||||
|
}
|
||||||
|
|
||||||
fn calculate_movement(&self) -> (f64, f64) {
|
fn calculate_movement(&self) -> (f64, f64) {
|
||||||
use std::f64::consts::PI;
|
use std::f64::consts::PI;
|
||||||
let mut forward = 0.0f64;
|
let mut forward = 0.0f64;
|
||||||
|
@ -342,15 +499,25 @@ impl Server {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn minecraft_tick(&mut self) {
|
pub fn minecraft_tick(&mut self) {
|
||||||
|
// Force the server to know when touched the ground
|
||||||
|
// otherwise if it happens between ticks the server
|
||||||
|
// will think we are flying.
|
||||||
|
let on_ground = if self.did_touch_ground {
|
||||||
|
self.did_touch_ground = false;
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
self.on_ground
|
||||||
|
};
|
||||||
|
|
||||||
// Sync our position to the server
|
// Sync our position to the server
|
||||||
|
// Use the smaller packets when possible
|
||||||
let packet = packet::play::serverbound::PlayerPositionLook {
|
let packet = packet::play::serverbound::PlayerPositionLook {
|
||||||
x: self.position.x,
|
x: self.position.x,
|
||||||
y: self.position.y,
|
y: self.position.y,
|
||||||
z: self.position.z,
|
z: self.position.z,
|
||||||
yaw: self.yaw as f32,
|
yaw: self.yaw as f32,
|
||||||
pitch: self.pitch as f32,
|
pitch: self.pitch as f32,
|
||||||
on_ground: false,
|
on_ground: on_ground,
|
||||||
};
|
};
|
||||||
self.write_packet(packet);
|
self.write_packet(packet);
|
||||||
}
|
}
|
||||||
|
@ -373,6 +540,19 @@ impl Server {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn on_game_join(&mut self, join: packet::play::clientbound::JoinGame) {
|
||||||
|
self.gamemode = Gamemode::from_int((join.gamemode & 0x7) as i32);
|
||||||
|
// TODO: Temp
|
||||||
|
self.flying = self.gamemode.can_fly();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn on_respawn(&mut self, respawn: packet::play::clientbound::Respawn) {
|
||||||
|
self.world = world::World::new();
|
||||||
|
self.gamemode = Gamemode::from_int((respawn.gamemode & 0x7) as i32);
|
||||||
|
// TODO: Temp
|
||||||
|
self.flying = self.gamemode.can_fly();
|
||||||
|
}
|
||||||
|
|
||||||
fn on_time_update(&mut self, time_update: packet::play::clientbound::TimeUpdate) {
|
fn on_time_update(&mut self, time_update: packet::play::clientbound::TimeUpdate) {
|
||||||
self.world_age = time_update.time_of_day;
|
self.world_age = time_update.time_of_day;
|
||||||
self.world_time_target = (time_update.time_of_day % 24000) as f64;
|
self.world_time_target = (time_update.time_of_day % 24000) as f64;
|
||||||
|
@ -384,6 +564,17 @@ impl Server {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn on_game_state_change(&mut self, game_state: packet::play::clientbound::ChangeGameState) {
|
||||||
|
match game_state.reason {
|
||||||
|
3 => {
|
||||||
|
self.gamemode = Gamemode::from_int(game_state.value as i32);
|
||||||
|
// TODO: Temp
|
||||||
|
self.flying = self.gamemode.can_fly();
|
||||||
|
},
|
||||||
|
_ => {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn on_teleport(&mut self, teleport: packet::play::clientbound::TeleportPlayer) {
|
fn on_teleport(&mut self, teleport: packet::play::clientbound::TeleportPlayer) {
|
||||||
// TODO: relative teleports
|
// TODO: relative teleports
|
||||||
self.position.x = teleport.x;
|
self.position.x = teleport.x;
|
||||||
|
@ -411,3 +602,58 @@ impl Server {
|
||||||
self.world.unload_chunk(chunk_unload.x, chunk_unload.z);
|
self.world.unload_chunk(chunk_unload.x, chunk_unload.z);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trait Collidable<T> {
|
||||||
|
fn collides(&self, t: &T) -> bool;
|
||||||
|
fn move_out_of(self, other: Self, dir: cgmath::Vector3<f64>) -> Self;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Collidable<Aabb3<f64>> for Aabb3<f64> {
|
||||||
|
fn collides(&self, t: &Aabb3<f64>) -> bool {
|
||||||
|
!(
|
||||||
|
t.min.x >= self.max.x ||
|
||||||
|
t.max.x <= self.min.x ||
|
||||||
|
t.min.y >= self.max.y ||
|
||||||
|
t.max.y <= self.min.y ||
|
||||||
|
t.min.z >= self.max.z ||
|
||||||
|
t.max.z <= self.min.z
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn move_out_of(mut self, other: Self, dir: cgmath::Vector3<f64>) -> Self {
|
||||||
|
if dir.x != 0.0 {
|
||||||
|
if dir.x > 0.0 {
|
||||||
|
let ox = self.max.x;
|
||||||
|
self.max.x = other.min.x - 0.0001;
|
||||||
|
self.min.x += self.max.x - ox;
|
||||||
|
} else {
|
||||||
|
let ox = self.min.x;
|
||||||
|
self.min.x = other.max.x + 0.0001;
|
||||||
|
self.max.x += self.min.x - ox;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if dir.y != 0.0 {
|
||||||
|
if dir.y > 0.0 {
|
||||||
|
let oy = self.max.y;
|
||||||
|
self.max.y = other.min.y - 0.0001;
|
||||||
|
self.min.y += self.max.y - oy;
|
||||||
|
} else {
|
||||||
|
let oy = self.min.y;
|
||||||
|
self.min.y = other.max.y + 0.0001;
|
||||||
|
self.max.y += self.min.y - oy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if dir.z != 0.0 {
|
||||||
|
if dir.z > 0.0 {
|
||||||
|
let oz = self.max.z;
|
||||||
|
self.max.z = other.min.z - 0.0001;
|
||||||
|
self.min.z += self.max.z - oz;
|
||||||
|
} else {
|
||||||
|
let oz = self.min.z;
|
||||||
|
self.min.z = other.max.z + 0.0001;
|
||||||
|
self.max.z += self.min.z - oz;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
|
|
||||||
use std::fmt::{Display, Formatter, Error};
|
use std::fmt::{Display, Formatter, Error};
|
||||||
|
use collision::{Aabb, Aabb3};
|
||||||
|
use cgmath::{Point3, Point};
|
||||||
|
|
||||||
pub use self::Block::*;
|
pub use self::Block::*;
|
||||||
|
|
||||||
|
@ -36,6 +38,7 @@ macro_rules! define_blocks {
|
||||||
model $model:expr,
|
model $model:expr,
|
||||||
$(variant $variant:expr,)*
|
$(variant $variant:expr,)*
|
||||||
$(tint $tint:expr,)*
|
$(tint $tint:expr,)*
|
||||||
|
$(collision $collision:expr,)*
|
||||||
}
|
}
|
||||||
)+
|
)+
|
||||||
) => (
|
) => (
|
||||||
|
@ -188,6 +191,23 @@ macro_rules! define_blocks {
|
||||||
)+
|
)+
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(unused_variables, unreachable_code)]
|
||||||
|
pub fn get_collision_boxes(&self) -> Vec<Aabb3<f64>> {
|
||||||
|
match *self {
|
||||||
|
$(
|
||||||
|
Block::$name {
|
||||||
|
$($fname,)*
|
||||||
|
} => {
|
||||||
|
$(return $collision;)*
|
||||||
|
return vec![Aabb3::new(
|
||||||
|
Point3::new(0.0, 0.0, 0.0),
|
||||||
|
Point3::new(1.0, 1.0, 1.0)
|
||||||
|
)];
|
||||||
|
}
|
||||||
|
)+
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
|
@ -235,6 +255,7 @@ define_blocks! {
|
||||||
transparent: false,
|
transparent: false,
|
||||||
},
|
},
|
||||||
model { ("minecraft", "air" ) },
|
model { ("minecraft", "air" ) },
|
||||||
|
collision vec![],
|
||||||
}
|
}
|
||||||
Stone {
|
Stone {
|
||||||
props {
|
props {
|
||||||
|
|
|
@ -209,7 +209,7 @@ impl World {
|
||||||
biomes: vec![0; (w * d) as usize],
|
biomes: vec![0; (w * d) as usize],
|
||||||
|
|
||||||
x: x, y: y, z: z,
|
x: x, y: y, z: z,
|
||||||
w: w, h: h, d: d,
|
w: w, _h: h, d: d,
|
||||||
};
|
};
|
||||||
for i in 0 .. (w * h * d) as usize {
|
for i in 0 .. (w * h * d) as usize {
|
||||||
snapshot.sky_light.set(i, 0xF);
|
snapshot.sky_light.set(i, 0xF);
|
||||||
|
@ -383,7 +383,7 @@ pub struct Snapshot {
|
||||||
y: i32,
|
y: i32,
|
||||||
z: i32,
|
z: i32,
|
||||||
w: i32,
|
w: i32,
|
||||||
h: i32,
|
_h: i32,
|
||||||
d: i32,
|
d: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue