mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
build is working. to add and remove blocks.
This commit is contained in:
parent
48cc5d3b08
commit
84f19b408f
@ -488,13 +488,15 @@ impl PlayState for SessionState {
|
||||
|
||||
match input {
|
||||
GameInput::Primary => {
|
||||
if is_mining && is_nearest_target(mine_target) {
|
||||
self.inputs.select_pos = mine_target.map(|t| t.position);
|
||||
entity_event_handler!(InputKind::Primary, state);
|
||||
} else if state && can_build && is_nearest_target(build_target) {
|
||||
// mine and build targets can be the same block. make building take
|
||||
// precedence.
|
||||
if state && can_build && is_nearest_target(build_target) {
|
||||
self.inputs.select_pos = build_target.map(|t| t.position);
|
||||
let mut client = self.client.borrow_mut();
|
||||
client.remove_block(build_target.unwrap().position_int());
|
||||
} else if is_mining && is_nearest_target(mine_target) {
|
||||
self.inputs.select_pos = mine_target.map(|t| t.position);
|
||||
entity_event_handler!(InputKind::Primary, state);
|
||||
} else {
|
||||
entity_event_handler!(InputKind::Primary, state);
|
||||
}
|
||||
@ -504,10 +506,11 @@ impl PlayState for SessionState {
|
||||
if let Some(build_target) = build_target {
|
||||
self.inputs.select_pos = Some(build_target.position);
|
||||
let mut client = self.client.borrow_mut();
|
||||
client.place_block(
|
||||
build_target.position_int(),
|
||||
self.selected_block,
|
||||
);
|
||||
if let Some(pos) =
|
||||
build_target.build_above_position(&client)
|
||||
{
|
||||
client.place_block(pos, self.selected_block);
|
||||
};
|
||||
}
|
||||
} else {
|
||||
entity_event_handler!(InputKind::Secondary, state);
|
||||
|
@ -16,7 +16,7 @@ use common_base::span;
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum TargetType {
|
||||
Build(Vec3<f32>),
|
||||
Build,
|
||||
Collectable,
|
||||
Entity(specs::Entity),
|
||||
Mine,
|
||||
@ -32,6 +32,26 @@ pub struct Target {
|
||||
impl Target {
|
||||
pub fn position_int(self) -> Vec3<i32> { self.position.map(|p| p.floor() as i32) }
|
||||
|
||||
pub fn build_above_position(self, client: &Client) -> Option<Vec3<i32>> {
|
||||
match self.typed {
|
||||
TargetType::Build => {
|
||||
let mut pos_above = self.position;
|
||||
pos_above.z += 1.0;
|
||||
let pos_above = pos_above.map(|p| p.floor() as i32);
|
||||
if let Ok(block) = client.state().terrain().get(pos_above) {
|
||||
if block.is_air() {
|
||||
Some(pos_above)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
},
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn make_interactable(self, client: &Client) -> Option<Interactable> {
|
||||
match self.typed {
|
||||
TargetType::Collectable => client
|
||||
@ -49,7 +69,7 @@ impl Target {
|
||||
.ok()
|
||||
.copied()
|
||||
.map(|b| Interactable::Block(b, self.position_int(), None)),
|
||||
TargetType::Build(_) => None,
|
||||
TargetType::Build => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -99,7 +119,6 @@ pub(super) fn targets_under_cursor(
|
||||
) -> impl FnMut(
|
||||
fn(Block) -> bool,
|
||||
) -> (
|
||||
Option<Vec3<f32>>,
|
||||
Option<Vec3<f32>>,
|
||||
(f32, Result<Option<Block>, VolGrid2dError<TerrainChunk>>),
|
||||
) + 'a {
|
||||
@ -117,23 +136,19 @@ pub(super) fn targets_under_cursor(
|
||||
cam_ray.1,
|
||||
Ok(Some(_)) if player_cylinder.min_distance(*cam_pos + *cam_dir * (cam_dist + 0.01)) <= MAX_PICKUP_RANGE
|
||||
) {
|
||||
(
|
||||
Some(*cam_pos + *cam_dir * cam_dist),
|
||||
Some(*cam_pos + *cam_dir * (cam_dist - 0.01)),
|
||||
cam_ray,
|
||||
)
|
||||
(Some(*cam_pos + *cam_dir * cam_dist), cam_ray)
|
||||
} else {
|
||||
(None, None, cam_ray)
|
||||
(None, cam_ray)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut find_pos = curry_find_pos(client, &cam_pos, &cam_dir, &player_cylinder);
|
||||
|
||||
let (collect_pos, _, cam_ray_0) = find_pos(|b: Block| b.is_collectible());
|
||||
let (mine_pos, _, cam_ray_1) = find_pos(|b: Block| b.mine_tool().is_some());
|
||||
let (collect_pos, cam_ray_0) = find_pos(|b: Block| b.is_collectible());
|
||||
let (mine_pos, cam_ray_1) = find_pos(|b: Block| b.mine_tool().is_some());
|
||||
// FIXME: the `solid_pos` is used in the remove_block(). is this correct?
|
||||
let (solid_pos, build_pos, cam_ray_2) = find_pos(|b: Block| b.is_solid());
|
||||
let (solid_pos, cam_ray_2) = find_pos(|b: Block| b.is_solid());
|
||||
|
||||
// find shortest cam_dist of non-entity targets
|
||||
// note that some of these targets can technically be in Air, such as the
|
||||
@ -224,9 +239,9 @@ pub(super) fn targets_under_cursor(
|
||||
} else { None }
|
||||
});
|
||||
|
||||
let build_target = if let (true, Some(position), Some(bp)) = (can_build, solid_pos, build_pos) {
|
||||
let build_target = if let (true, Some(position)) = (can_build, solid_pos) {
|
||||
Some(Target {
|
||||
typed: TargetType::Build(bp),
|
||||
typed: TargetType::Build,
|
||||
distance: cam_ray_2.0,
|
||||
position,
|
||||
})
|
||||
|
Loading…
Reference in New Issue
Block a user