Add block targeting
This commit is contained in:
parent
d719e117ad
commit
98422678a3
|
@ -27,7 +27,7 @@ use render;
|
||||||
use settings::Stevenkey;
|
use settings::Stevenkey;
|
||||||
use ecs;
|
use ecs;
|
||||||
use entity;
|
use entity;
|
||||||
use cgmath;
|
use cgmath::{self, Point};
|
||||||
use collision::Aabb;
|
use collision::Aabb;
|
||||||
use types::Gamemode;
|
use types::Gamemode;
|
||||||
use shared::{Axis, Position};
|
use shared::{Axis, Position};
|
||||||
|
@ -35,6 +35,7 @@ use format;
|
||||||
|
|
||||||
mod sun;
|
mod sun;
|
||||||
pub mod plugin_messages;
|
pub mod plugin_messages;
|
||||||
|
pub mod target;
|
||||||
|
|
||||||
pub struct Server {
|
pub struct Server {
|
||||||
username: String,
|
username: String,
|
||||||
|
@ -74,6 +75,7 @@ pub struct Server {
|
||||||
entity_tick_timer: f64,
|
entity_tick_timer: f64,
|
||||||
|
|
||||||
sun_model: Option<sun::SunModel>,
|
sun_model: Option<sun::SunModel>,
|
||||||
|
target_info: target::Info,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct PlayerInfo {
|
pub struct PlayerInfo {
|
||||||
|
@ -293,6 +295,8 @@ impl Server {
|
||||||
tick_timer: 0.0,
|
tick_timer: 0.0,
|
||||||
entity_tick_timer: 0.0,
|
entity_tick_timer: 0.0,
|
||||||
sun_model: None,
|
sun_model: None,
|
||||||
|
|
||||||
|
target_info: target::Info::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -343,6 +347,12 @@ impl Server {
|
||||||
}
|
}
|
||||||
|
|
||||||
self.world.tick(&mut self.entities);
|
self.world.tick(&mut self.entities);
|
||||||
|
|
||||||
|
if let Some((pos, bl)) = target::trace_ray(&self.world, 4.0, renderer.camera.pos.to_vec(), renderer.view_vector.cast(), target::test_block) {
|
||||||
|
self.target_info.update(renderer, pos, bl);
|
||||||
|
} else {
|
||||||
|
self.target_info.clear(renderer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn entity_tick(&mut self, renderer: &mut render::Renderer, delta: f64) {
|
fn entity_tick(&mut self, renderer: &mut render::Renderer, delta: f64) {
|
||||||
|
|
|
@ -0,0 +1,256 @@
|
||||||
|
|
||||||
|
use world;
|
||||||
|
use world::block;
|
||||||
|
use shared::Position;
|
||||||
|
use cgmath;
|
||||||
|
use render;
|
||||||
|
use render::model;
|
||||||
|
use collision::{self, Aabb};
|
||||||
|
|
||||||
|
pub struct Info {
|
||||||
|
model: Option<model::ModelKey>,
|
||||||
|
last_block: block::Block,
|
||||||
|
last_pos: Position,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Info {
|
||||||
|
pub fn new() -> Info {
|
||||||
|
Info {
|
||||||
|
model: None,
|
||||||
|
last_block: block::Air{},
|
||||||
|
last_pos: Position::new(0, 0, 0),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clear(&mut self, renderer: &mut render::Renderer) {
|
||||||
|
self.last_block = block::Air{};
|
||||||
|
if let Some(model) = self.model.take() {
|
||||||
|
renderer.model.remove_model(model);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update(&mut self, renderer: &mut render::Renderer, pos: Position, bl: block::Block) {
|
||||||
|
if self.last_block == bl && self.last_pos == pos {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
self.last_block = bl;
|
||||||
|
self.last_pos = pos;
|
||||||
|
if let Some(model) = self.model.take() {
|
||||||
|
renderer.model.remove_model(model);
|
||||||
|
}
|
||||||
|
let mut parts = vec![];
|
||||||
|
|
||||||
|
const LINE_SIZE: f64 = 1.0 / 128.0;
|
||||||
|
let tex = render::Renderer::get_texture(renderer.get_textures_ref(), "steven:solid");
|
||||||
|
|
||||||
|
for bound in bl.get_collision_boxes() {
|
||||||
|
let bound = bound.add_v(cgmath::Vector3::new(pos.x as f64, pos.y as f64, pos.z as f64));
|
||||||
|
for point in [
|
||||||
|
(bound.min.x, bound.min.z),
|
||||||
|
(bound.min.x, bound.max.z),
|
||||||
|
(bound.max.x, bound.min.z),
|
||||||
|
(bound.max.x, bound.max.z),
|
||||||
|
].into_iter() {
|
||||||
|
model::append_box(&mut parts,
|
||||||
|
(point.0-LINE_SIZE) as f32, (bound.min.y-LINE_SIZE) as f32, (point.1-LINE_SIZE) as f32,
|
||||||
|
(LINE_SIZE*2.0) as f32, ((bound.max.y-bound.min.y)+LINE_SIZE*2.0) as f32, (LINE_SIZE*2.0) as f32,
|
||||||
|
[
|
||||||
|
Some(tex.clone()),
|
||||||
|
Some(tex.clone()),
|
||||||
|
Some(tex.clone()),
|
||||||
|
Some(tex.clone()),
|
||||||
|
Some(tex.clone()),
|
||||||
|
Some(tex.clone()),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for point in [
|
||||||
|
(bound.min.x, bound.min.z, bound.max.x, bound.min.z),
|
||||||
|
(bound.min.x, bound.max.z, bound.max.x, bound.max.z),
|
||||||
|
(bound.min.x, bound.min.z, bound.min.x, bound.max.z),
|
||||||
|
(bound.max.x, bound.min.z, bound.max.x, bound.max.z),
|
||||||
|
].into_iter() {
|
||||||
|
model::append_box(&mut parts,
|
||||||
|
(point.0-LINE_SIZE) as f32, (bound.min.y-LINE_SIZE) as f32, (point.1-LINE_SIZE) as f32,
|
||||||
|
((point.2-point.0)+(LINE_SIZE*2.0)) as f32, (LINE_SIZE*2.0) as f32, ((point.3-point.1)+(LINE_SIZE*2.0)) as f32,
|
||||||
|
[
|
||||||
|
Some(tex.clone()),
|
||||||
|
Some(tex.clone()),
|
||||||
|
Some(tex.clone()),
|
||||||
|
Some(tex.clone()),
|
||||||
|
Some(tex.clone()),
|
||||||
|
Some(tex.clone()),
|
||||||
|
]);
|
||||||
|
model::append_box(&mut parts,
|
||||||
|
(point.0-LINE_SIZE) as f32, (bound.max.y-LINE_SIZE) as f32, (point.1-LINE_SIZE) as f32,
|
||||||
|
((point.2-point.0)+(LINE_SIZE*2.0)) as f32, (LINE_SIZE*2.0) as f32, ((point.3-point.1)+(LINE_SIZE*2.0)) as f32,
|
||||||
|
[
|
||||||
|
Some(tex.clone()),
|
||||||
|
Some(tex.clone()),
|
||||||
|
Some(tex.clone()),
|
||||||
|
Some(tex.clone()),
|
||||||
|
Some(tex.clone()),
|
||||||
|
Some(tex.clone()),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for part in &mut parts {
|
||||||
|
part.r = 0;
|
||||||
|
part.g = 0;
|
||||||
|
part.b = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.model = Some(renderer.model.create_model(model::DEFAULT, vec![parts]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn test_block(world: &world::World, pos: Position, s: cgmath::Vector3<f64>, d: cgmath::Vector3<f64>) -> (bool, Option<(Position, block::Block)>) {
|
||||||
|
let block = world.get_block(pos);
|
||||||
|
for bound in block.get_collision_boxes() {
|
||||||
|
let bound = bound.add_v(cgmath::Vector3::new(pos.x as f64, pos.y as f64, pos.z as f64));
|
||||||
|
if let Some(hit) = intersects_line(bound, s, d) {
|
||||||
|
// TODO: Face/cursor
|
||||||
|
let _ = hit;
|
||||||
|
return (true, Some((pos, block)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(false, None)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn intersects_line(bound: collision::Aabb3<f64>, origin: cgmath::Vector3<f64>, dir: cgmath::Vector3<f64>) -> Option<cgmath::Vector3<f64>> {
|
||||||
|
const RIGHT: usize = 0;
|
||||||
|
const LEFT: usize = 1;
|
||||||
|
const MIDDLE: usize = 2;
|
||||||
|
let mut quadrant = [0, 0, 0];
|
||||||
|
let mut candidate_plane = [0.0, 0.0, 0.0];
|
||||||
|
let mut max_t = [0.0, 0.0, 0.0];
|
||||||
|
let mut inside = true;
|
||||||
|
for i in 0 .. 3 {
|
||||||
|
if origin[i] < bound.min[i] {
|
||||||
|
quadrant[i] = LEFT;
|
||||||
|
candidate_plane[i] = bound.min[i];
|
||||||
|
inside = false;
|
||||||
|
} else if origin[i] > bound.max[i] {
|
||||||
|
quadrant[i] = RIGHT;
|
||||||
|
candidate_plane[i] = bound.max[i];
|
||||||
|
inside = false;
|
||||||
|
} else {
|
||||||
|
quadrant[i] = MIDDLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if inside {
|
||||||
|
return Some(origin);
|
||||||
|
}
|
||||||
|
|
||||||
|
for i in 0 .. 3 {
|
||||||
|
if quadrant[i] != MIDDLE && dir[i] != 0.0 {
|
||||||
|
max_t[i] = (candidate_plane[i] - origin[i]) / dir[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let mut which_plane = 0;
|
||||||
|
for i in 1 .. 3 {
|
||||||
|
if max_t[which_plane] < max_t[i] {
|
||||||
|
which_plane = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if max_t[which_plane] < 0.0 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut coord = cgmath::Vector3::new(0.0, 0.0, 0.0);
|
||||||
|
for i in 0 .. 3 {
|
||||||
|
if which_plane != i {
|
||||||
|
coord[i] = origin[i] + max_t[which_plane] * dir[i];
|
||||||
|
if coord[i] < bound.min[i] || coord[i] > bound.max[i] {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
coord[i] = candidate_plane[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some(coord)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn trace_ray<F, R>(world: &world::World, max: f64, s: cgmath::Vector3<f64>, d: cgmath::Vector3<f64>, collide_func: F) -> Option<R>
|
||||||
|
where F: Fn(&world::World, Position, cgmath::Vector3<f64>, cgmath::Vector3<f64>,) -> (bool, Option<R>) {
|
||||||
|
struct Gen {
|
||||||
|
count: i32,
|
||||||
|
base: f64,
|
||||||
|
d: f64,
|
||||||
|
}
|
||||||
|
impl Gen {
|
||||||
|
fn new(start: f64, mut d: f64) -> Gen {
|
||||||
|
let base = if d > 0.0 {
|
||||||
|
(start.ceil() - start) / d
|
||||||
|
} else if d < 0.0 {
|
||||||
|
d = d.abs();
|
||||||
|
(start - start.floor()) / d
|
||||||
|
} else {
|
||||||
|
0.0
|
||||||
|
};
|
||||||
|
Gen {
|
||||||
|
count: 0,
|
||||||
|
base: base,
|
||||||
|
d: d,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn next(&mut self) -> f64 {
|
||||||
|
self.count += 1;
|
||||||
|
if self.d == 0.0 {
|
||||||
|
::std::f64::INFINITY
|
||||||
|
} else {
|
||||||
|
self.base + ((self.count as f64 - 1.0) / self.d)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut x_gen = Gen::new(s.x, d.x);
|
||||||
|
let mut y_gen = Gen::new(s.y, d.y);
|
||||||
|
let mut z_gen = Gen::new(s.z, d.z);
|
||||||
|
let mut next_nx = x_gen.next();
|
||||||
|
let mut next_ny = y_gen.next();
|
||||||
|
let mut next_nz = z_gen.next();
|
||||||
|
|
||||||
|
let mut x = s.x.floor() as i32;
|
||||||
|
let mut y = s.y.floor() as i32;
|
||||||
|
let mut z = s.z.floor() as i32;
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let (hit, ret) = collide_func(&world, Position::new(x, y, z), s, d);
|
||||||
|
if hit {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
let next_n = if next_nx <= next_ny {
|
||||||
|
if next_nx <= next_nz {
|
||||||
|
let old = next_nx;
|
||||||
|
next_nx = x_gen.next();
|
||||||
|
x += d.x.signum() as i32;
|
||||||
|
old
|
||||||
|
} else {
|
||||||
|
let old = next_nz;
|
||||||
|
next_nz = z_gen.next();
|
||||||
|
z += d.z.signum() as i32;
|
||||||
|
old
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if next_ny <= next_nz {
|
||||||
|
let old = next_ny;
|
||||||
|
next_ny = y_gen.next();
|
||||||
|
y += d.y.signum() as i32;
|
||||||
|
old
|
||||||
|
} else {
|
||||||
|
let old = next_nz;
|
||||||
|
next_nz = z_gen.next();
|
||||||
|
z += d.z.signum() as i32;
|
||||||
|
old
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if next_n > max {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
Loading…
Reference in New Issue