mirror of
https://github.com/horizon-rust/horizon.git
synced 2026-11-07 11:06:11 -10:00
Add explosion knockback hook for players
This commit is contained in:
1 parent
c5c8a33a8a
commit
e1084abe75
4 files changed
+41
-2
No files matched your search
@@ -397,6 +397,7 @@ impl Game<'_> {
|
||||
exploding: Option<u32>,
|
||||
attacker: Option<&(u32, Text)>,
|
||||
cause: Option<&horizon_client::advancements::EntityView>,
|
||||
blocks: &[[i32; 3]],
|
||||
) -> Option<[f64; 3]> {
|
||||
let diameter = f64::from(radius * 2.0);
|
||||
// Blast protection: `EXPLOSION_KNOCKBACK_RESISTANCE` (0.15 per level and
|
||||
@@ -450,6 +451,10 @@ impl Game<'_> {
|
||||
let flying = self.player.as_ref().is_some_and(|p| p.flying);
|
||||
let mut outcome = horizon_client::health::BlockOutcome::default();
|
||||
let mut pushed = None;
|
||||
let mut push = [dir[0] * power, dir[1] * power, dir[2] * power];
|
||||
if !spectator && !(creative && flying) {
|
||||
self.native_explosion_knockback(self.dim.id(), center, blocks, None, &mut push);
|
||||
}
|
||||
// The death message names the blast's causing entity. It goes to this
|
||||
// player's tracker, the host's or a guest's.
|
||||
if let Some((id, name)) = attacker.filter(|_| !creative && !spectator && hurtable) {
|
||||
@@ -482,7 +487,6 @@ impl Game<'_> {
|
||||
}
|
||||
}
|
||||
if !spectator && !(creative && flying) {
|
||||
let push = [dir[0] * power, dir[1] * power, dir[2] * power];
|
||||
p.velocity = Vec3::new(
|
||||
p.velocity.x + push[0],
|
||||
p.velocity.y + push[1],
|
||||
@@ -544,6 +548,7 @@ impl Game<'_> {
|
||||
radius: f32,
|
||||
damage_type: &str,
|
||||
interaction: BlockInteraction,
|
||||
blocks: &[[i32; 3]],
|
||||
) -> Vec<(u32, [f64; 3])> {
|
||||
if radius < 1.0e-5 {
|
||||
return Vec::new();
|
||||
@@ -575,6 +580,7 @@ impl Game<'_> {
|
||||
exploding,
|
||||
attacker.as_ref(),
|
||||
blast_source.as_ref(),
|
||||
blocks,
|
||||
);
|
||||
let mut pushed: Vec<_> = self.lan_acting.zip(own).into_iter().collect();
|
||||
if let Some(mut host) = self.lan.take() {
|
||||
@@ -594,6 +600,7 @@ impl Game<'_> {
|
||||
exploding,
|
||||
attacker.as_ref(),
|
||||
blast_source.as_ref(),
|
||||
blocks,
|
||||
)
|
||||
});
|
||||
if let Some(Some(push)) = push {
|
||||
@@ -871,7 +878,7 @@ impl Game<'_> {
|
||||
let mut targets = self.exploded_positions(center, radius, resists);
|
||||
let dimension = self.dim.id();
|
||||
self.native_explosion_detonate(dimension, center, &mut targets);
|
||||
let pushed = self.explosion_hurt_entities(center, radius, damage_type, interaction);
|
||||
let pushed = self.explosion_hurt_entities(center, radius, damage_type, interaction, &targets);
|
||||
if interaction != BlockInteraction::Keep {
|
||||
// Util.shuffle(list, level.random)
|
||||
for i in (2..=targets.len()).rev() {
|
||||
|
||||
@@ -5293,6 +5293,18 @@ impl Game<'_> {
|
||||
) {
|
||||
mod_api::dispatch_explosion_detonate(self, mod_api::mods(), dimension, center, blocks);
|
||||
}
|
||||
/// Server explosion knockback for `entity` (None for the acting player).
|
||||
/// Replace the velocity added to its existing velocity. API @API:explosion_knockback@.
|
||||
pub(super) fn native_explosion_knockback(
|
||||
&mut self,
|
||||
dimension: &str,
|
||||
center: [f64; 3],
|
||||
blocks: &[[i32; 3]],
|
||||
entity: Option<u32>,
|
||||
knockback_velocity: &mut [f64; 3],
|
||||
) {
|
||||
let _ = (dimension, center, blocks, entity, knockback_velocity);
|
||||
}
|
||||
/// A player fills (`stack` an empty bucket) or empties a bucket at `pos`:
|
||||
/// `BucketItem.use`, where it asks `Level.mayInteract`. Set `canceled`
|
||||
/// and the bucket does nothing. Server-side, for every player of the
|
||||
|
||||
@@ -1735,6 +1735,9 @@ For mods that run where the world is simulated: a dedicated server, a LAN host,
|
||||
that is still there (`ServerLevel.tickBlock`), before its own `tick`; the same contract as `native_random_tick`.
|
||||
- **`native_explosion_detonate(dimension, center, blocks)`** (API 22): the positions an explosion is about to break,
|
||||
before any is hit; take out the ones to spare. Entities are hurt as before.
|
||||
- **`native_explosion_knockback(dimension, center, blocks, entity, knockback_velocity)`**: a server explosion's
|
||||
calculated velocity, before it is added to the entity. Replace `knockback_velocity` to change the push;
|
||||
`entity` is None for the acting player. The player packet uses the same replacement.
|
||||
- **`native_fill_bucket(stack, pos, canceled)`** and **`native_attack_entity(entity, kind, pos, canceled)`** (API 22):
|
||||
a player's bucket at a block, and their blow on an entity, with the acting player swapped in. Canceled, the bucket
|
||||
does nothing and the blow does no harm.
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"hooks": [
|
||||
{
|
||||
"name": "explosion_knockback",
|
||||
"target": "horizon_client::game::native_hooks::Game<'_>::native_explosion_knockback",
|
||||
"neoforge": "ExplosionKnockbackEvent",
|
||||
"side": "server",
|
||||
"cancellable": false,
|
||||
"mod_api": {
|
||||
"contract": "replace",
|
||||
"out": "knockback_velocity"
|
||||
}
|
||||
}
|
||||
],
|
||||
"rust_summary": "Explosion velocity replacement (`native_explosion_knockback`).",
|
||||
"doc_summary": "A server explosion calculates an entity's added velocity: `native_explosion_knockback(dimension, center, blocks, entity, knockback_velocity)` can replace it. Bundles need \"hooks\": @API:explosion_knockback@."
|
||||
}
|
||||
Reference in new issue
Block a user