undo macro use for DRY on client event handler, and handle edge detection in mining so that we don't get Empty interactables.

This commit is contained in:
anomaluridae 2021-08-11 02:38:39 -07:00
parent 309447dced
commit ba4af5ee8e
3 changed files with 84 additions and 77 deletions

View File

@ -45,7 +45,18 @@ impl Interactable {
.get(target.position_int())
.ok()
.copied()
.map(|b| Interactable::Block(b, target.position_int(), None)),
.and_then(|b| {
// Handling edge detection. sometimes the casting (in Target mod) returns a
// position which is actually empty, which we do not want labeled as an
// interactable. We are only returning the mineable air
// elements (e.g. minerals). The mineable weakrock are used
// in the terrain selected_pos, but is not an interactable.
if b.mine_tool().is_some() && b.is_air() {
Some(Interactable::Block(b, target.position_int(), None))
} else {
None
}
}),
TargetType::Build => None,
}
}

View File

@ -411,26 +411,20 @@ impl PlayState for SessionState {
.map_or(false, |tool| tool.kind == ToolKind::Pick)
&& client.is_wielding() == Some(true);
drop(client);
// Check to see whether we're aiming at anything
let (build_target, collect_target, entity_target, mine_target, shortest_dist) =
targets_under_cursor(
&self.client.borrow(),
cam_pos,
cam_dir,
can_build,
is_mining,
);
targets_under_cursor(&client, cam_pos, cam_dir, can_build, is_mining);
self.interactable = select_interactable(
&self.client.borrow(),
&client,
collect_target,
entity_target,
mine_target,
&self.scene,
);
drop(client);
let is_nearest_target = |target: Option<Target>| {
target
.map(|t| (t.distance <= shortest_dist))
@ -448,25 +442,12 @@ impl PlayState for SessionState {
}
// Throw out distance info, it will be useful in the future
let entity_under_target =
if let Some(TargetType::Entity(e)) = entity_target.map(|t| t.typed) {
Some(e)
} else {
None
};
self.target_entity = entity_under_target;
macro_rules! entity_event_handler {
($input: expr, $pressed: expr) => {
let mut client = self.client.borrow_mut();
client.handle_input(
$input,
$pressed,
self.inputs.select_pos,
entity_under_target,
);
};
}
self.target_entity = if let Some(TargetType::Entity(e)) = entity_target.map(|t| t.typed)
{
Some(e)
} else {
None
};
// Handle window events.
for event in events {
@ -488,40 +469,54 @@ impl PlayState for SessionState {
match input {
GameInput::Primary => {
let mut client = self.client.borrow_mut();
// 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);
if is_mining && is_nearest_target(mine_target) {
self.inputs.select_pos = mine_target.map(|t| t.position);
}
client.handle_input(
InputKind::Primary,
state,
self.inputs.select_pos,
self.target_entity,
);
}
},
GameInput::Secondary => {
let mut client = self.client.borrow_mut();
if state && can_build && is_nearest_target(build_target) {
if let Some(build_target) = build_target {
self.inputs.select_pos = Some(build_target.position);
let mut client = self.client.borrow_mut();
if let Some(pos) =
build_target.build_above_position(&client)
{
client.place_block(pos, self.selected_block);
};
client.place_block(
build_target.position_int(),
self.selected_block,
);
}
} else {
entity_event_handler!(InputKind::Secondary, state);
client.handle_input(
InputKind::Secondary,
state,
self.inputs.select_pos,
self.target_entity,
);
}
},
GameInput::Block => {
entity_event_handler!(InputKind::Block, state);
self.client.borrow_mut().handle_input(
InputKind::Block,
state,
self.inputs.select_pos,
self.target_entity,
);
},
GameInput::Roll => {
let mut client = self.client.borrow_mut();
if can_build {
let client = self.client.borrow_mut();
if state {
if let Some(block) = build_target.and_then(|bt| {
client
@ -537,7 +532,12 @@ impl PlayState for SessionState {
}
}
} else {
entity_event_handler!(InputKind::Roll, state);
client.handle_input(
InputKind::Roll,
state,
self.inputs.select_pos,
self.target_entity,
);
}
},
GameInput::Respawn => {
@ -547,7 +547,12 @@ impl PlayState for SessionState {
}
},
GameInput::Jump => {
entity_event_handler!(InputKind::Jump, state);
self.client.borrow_mut().handle_input(
InputKind::Jump,
state,
self.inputs.select_pos,
self.target_entity,
);
},
GameInput::SwimUp => {
self.key_state.swim_up = state;
@ -617,7 +622,12 @@ impl PlayState for SessionState {
// Syncing of inputs between mounter and mountee
// broke with controller change
self.key_state.fly ^= state;
entity_event_handler!(InputKind::Fly, self.key_state.fly);
self.client.borrow_mut().handle_input(
InputKind::Fly,
self.key_state.fly,
self.inputs.select_pos,
self.target_entity,
);
},
GameInput::Climb => {
self.key_state.climb_up = state;
@ -1112,12 +1122,10 @@ impl PlayState for SessionState {
},
HudEvent::RemoveBuff(buff_id) => {
let mut client = self.client.borrow_mut();
client.remove_buff(buff_id);
self.client.borrow_mut().remove_buff(buff_id);
},
HudEvent::UnlockSkill(skill) => {
let mut client = self.client.borrow_mut();
client.unlock_skill(skill);
self.client.borrow_mut().unlock_skill(skill);
},
HudEvent::UseSlot {
slot,
@ -1343,19 +1351,27 @@ impl PlayState for SessionState {
info!("Event! -> ChangedHotbarState")
},
HudEvent::TradeAction(action) => {
let mut client = self.client.borrow_mut();
client.perform_trade_action(action);
self.client.borrow_mut().perform_trade_action(action);
},
HudEvent::Ability3(state) => {
entity_event_handler!(InputKind::Ability(0), state);
self.client.borrow_mut().handle_input(
InputKind::Ability(0),
state,
self.inputs.select_pos,
self.target_entity,
);
},
HudEvent::Ability4(state) => {
entity_event_handler!(InputKind::Ability(1), state);
self.client.borrow_mut().handle_input(
InputKind::Ability(1),
state,
self.inputs.select_pos,
self.target_entity,
);
},
HudEvent::RequestSiteInfo(id) => {
let mut client = self.client.borrow_mut();
client.request_site_economy(id);
self.client.borrow_mut().request_site_economy(id);
},
HudEvent::CraftRecipe {

View File

@ -28,26 +28,6 @@ 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,
}
}
}
/// Max distance an entity can be "targeted"