mirror of
https://github.com/horizon-rust/horizon.git
synced 2026-11-07 11:06:11 -10:00
Merge pull request #10272 from MSedgeMC/fix/item-interact-start
Starting an item use posts item_interact_start
This commit is contained in:
2 files changed
+96
-8
No files matched your search
@@ -7532,12 +7532,13 @@ impl Game<'_> {
|
||||
/// game event from the player, at its feet.
|
||||
pub(super) fn stop_using_item(&mut self, stack: &ItemStack) {
|
||||
self.using = None;
|
||||
self.use_vibration(stack);
|
||||
self.use_vibration(stack, "minecraft:item_interact_finish");
|
||||
}
|
||||
/// `ItemStack.causeUseVibration` for `stack` used by the player: an
|
||||
/// `ITEM_INTERACT_FINISH` game event from the player, at its feet, when the
|
||||
/// stack's use effects ask for interaction vibrations (the default).
|
||||
pub(super) fn use_vibration(&mut self, stack: &ItemStack) {
|
||||
/// `ItemStack.causeUseVibration` for `stack` used by the player: the
|
||||
/// `event` game event (`ITEM_INTERACT_START` when the use begins,
|
||||
/// `ITEM_INTERACT_FINISH` when it ends) from the player, at its feet, when
|
||||
/// the stack's use effects ask for interaction vibrations (the default).
|
||||
pub(super) fn use_vibration(&mut self, stack: &ItemStack, event: &'static str) {
|
||||
if !self
|
||||
.items()
|
||||
.get(&stack.item)
|
||||
@@ -7549,7 +7550,7 @@ impl Game<'_> {
|
||||
return;
|
||||
};
|
||||
let ctx = self.player_context(None);
|
||||
self.post_game_event("minecraft:item_interact_finish", [p.x, p.y, p.z], ctx);
|
||||
self.post_game_event(event, [p.x, p.y, p.z], ctx);
|
||||
}
|
||||
/// `ServerPlayerGameMode.tick` while a player digs: level event 2020 every
|
||||
/// fourth tick since the START (the hit sound), else 2019 (the crack only),
|
||||
|
||||
@@ -32,6 +32,9 @@ impl Game<'_> {
|
||||
self.using = Some((self.held_slot(), 0));
|
||||
self.use_duration = duration;
|
||||
self.use_ticks_set = ticks_set;
|
||||
// `LivingEntity.startUsingItem`: `causeUseVibration(ITEM_INTERACT_START)`
|
||||
// when the use effects of the stack ask for interaction vibrations.
|
||||
self.use_vibration(&stack, "minecraft:item_interact_start");
|
||||
// A new charge hears the crossbow's loading sounds again
|
||||
// (`game/crossbow.rs`).
|
||||
self.crossbow_sounds = [false; 2];
|
||||
@@ -100,7 +103,7 @@ impl Game<'_> {
|
||||
// a potion is drunk (no last tick of its own: a mod's tick ran it out).
|
||||
if self.finish_drinking(slot, stack) {
|
||||
self.use_item_finished(stack);
|
||||
self.use_vibration(stack);
|
||||
self.use_vibration(stack, "minecraft:item_interact_finish");
|
||||
return;
|
||||
}
|
||||
self.using = None;
|
||||
@@ -113,7 +116,7 @@ impl Game<'_> {
|
||||
}
|
||||
self.use_item_finished(stack);
|
||||
// `LivingEntity.completeUsingItem` ends with `stopUsingItem`.
|
||||
self.use_vibration(stack);
|
||||
self.use_vibration(stack, "minecraft:item_interact_finish");
|
||||
}
|
||||
/// `LivingEntityUseItemEvent.Finish` after `finishUsingItem` of `stack`
|
||||
/// (no ticks left): the hand holds what a mod made the result.
|
||||
@@ -449,3 +452,87 @@ mod tests {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod interact_vibration_tests {
|
||||
use super::*;
|
||||
|
||||
/// Runs `f` on a windowless game built from the prepared resources with
|
||||
/// `held` in the main hand and returns the game events it posted;
|
||||
/// `None` without the resources.
|
||||
fn with_game(held: &str, f: impl FnOnce(&mut Game<'_>)) -> Option<Vec<String>> {
|
||||
use crate::game::{Audio, Options, Progress, Settings, load_resources};
|
||||
let root = std::path::PathBuf::from(std::env::var_os("HORIZON_TEST_RESOURCES")?);
|
||||
let settings = Settings::default();
|
||||
let loaded = load_resources(
|
||||
root.clone(),
|
||||
None,
|
||||
&root,
|
||||
&settings,
|
||||
std::time::Instant::now(),
|
||||
false,
|
||||
true,
|
||||
&Progress::new(),
|
||||
&mut |_, _| unreachable!(),
|
||||
)
|
||||
.ok()?;
|
||||
let mut options = Options::parse(std::iter::empty()).unwrap().unwrap();
|
||||
options.resources = root.clone();
|
||||
options.execution_role = crate::game::execution_role::ExecutionRole::IntegratedServer;
|
||||
let mut game = Game::new(
|
||||
&loaded.resources,
|
||||
loaded.pack,
|
||||
loaded.gui.unwrap(),
|
||||
options,
|
||||
settings,
|
||||
Audio::silent(&root),
|
||||
None,
|
||||
)
|
||||
.unwrap();
|
||||
game.player = Some(
|
||||
horizon_client::motion::PlayerMotion::new(
|
||||
game.motion,
|
||||
horizon_core::geometry::Vec3::new(10.5, 64.0, -3.25),
|
||||
)
|
||||
.unwrap(),
|
||||
);
|
||||
*game.held_mut() = Some(ItemStack::new(held, 1));
|
||||
crate::game::dispense_fixture::start_recording();
|
||||
f(&mut game);
|
||||
Some(crate::game::dispense_fixture::stop_recording())
|
||||
}
|
||||
|
||||
/// `LivingEntity.startUsingItem` ends with
|
||||
/// `this.useItem.causeUseVibration(this, GameEvent.ITEM_INTERACT_START)`,
|
||||
/// and `ItemStack.causeUseVibration` posts only when the stack's use effects
|
||||
/// ask for interaction vibrations (the default). `stopUsingItem` posts the
|
||||
/// finish the same way, which Horizon already did, so a use is a pair of
|
||||
/// vibrations and an item that turns them off is neither.
|
||||
#[test]
|
||||
#[ignore = "needs prepared resources in HORIZON_TEST_RESOURCES"]
|
||||
fn a_use_start_is_an_item_interact_start_vibration() {
|
||||
let bow = || ItemStack::new("minecraft:bow", 1);
|
||||
let Some(lines) = with_game("minecraft:bow", |game| {
|
||||
assert!(game.start_using_item(), "the bow's use starts");
|
||||
game.stop_using_item(&bow());
|
||||
}) else {
|
||||
return;
|
||||
};
|
||||
assert_eq!(
|
||||
lines,
|
||||
vec![
|
||||
"G 10,64,-4 minecraft:item_interact_start".to_owned(),
|
||||
"G 10,64,-4 minecraft:item_interact_finish".to_owned(),
|
||||
]
|
||||
);
|
||||
// A spear's use effects set `interact_vibrations` false: no vibration.
|
||||
let spear = || ItemStack::new("minecraft:iron_spear", 1);
|
||||
let Some(lines) = with_game("minecraft:iron_spear", |game| {
|
||||
assert!(game.start_using_item(), "the spear's use starts");
|
||||
game.stop_using_item(&spear());
|
||||
}) else {
|
||||
return;
|
||||
};
|
||||
assert!(lines.is_empty(), "{lines:?}");
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user