mirror of
https://github.com/italicsjenga/valence.git
synced 2025-01-10 06:41:30 +11:00
Hitboxes (#330)
## Description Added Hitbox component, a crate for it and systems which update hitboxes. Issue: https://github.com/valence-rs/valence/issues/299 ## Test Plan Use example "entity_hitbox"
This commit is contained in:
parent
161d523018
commit
8897eeacb9
146
crates/valence/examples/entity_hitbox.rs
Normal file
146
crates/valence/examples/entity_hitbox.rs
Normal file
|
@ -0,0 +1,146 @@
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use bevy_app::App;
|
||||||
|
use bevy_ecs::prelude::Entity;
|
||||||
|
use rand::Rng;
|
||||||
|
use valence::prelude::*;
|
||||||
|
use valence_entity::entity::NameVisible;
|
||||||
|
use valence_entity::hoglin::HoglinEntityBundle;
|
||||||
|
use valence_entity::pig::PigEntityBundle;
|
||||||
|
use valence_entity::sheep::SheepEntityBundle;
|
||||||
|
use valence_entity::warden::WardenEntityBundle;
|
||||||
|
use valence_entity::zombie::ZombieEntityBundle;
|
||||||
|
use valence_entity::zombie_horse::ZombieHorseEntityBundle;
|
||||||
|
use valence_entity::{entity, Pose};
|
||||||
|
|
||||||
|
pub fn main() {
|
||||||
|
App::new()
|
||||||
|
.add_plugins(DefaultPlugins)
|
||||||
|
.add_startup_system(setup)
|
||||||
|
.add_system(init_clients)
|
||||||
|
.add_systems((spawn_entity, intersections))
|
||||||
|
.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn setup(
|
||||||
|
mut commands: Commands,
|
||||||
|
server: Res<Server>,
|
||||||
|
dimensions: Query<&DimensionType>,
|
||||||
|
biomes: Query<&Biome>,
|
||||||
|
) {
|
||||||
|
let mut instance = Instance::new(ident!("overworld"), &dimensions, &biomes, &server);
|
||||||
|
|
||||||
|
for z in -5..5 {
|
||||||
|
for x in -5..5 {
|
||||||
|
instance.insert_chunk([x, z], Chunk::default());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for z in -25..25 {
|
||||||
|
for x in -25..25 {
|
||||||
|
instance.set_block([x, 64, z], BlockState::GRASS_BLOCK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
commands.spawn(instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn init_clients(
|
||||||
|
mut clients: Query<(&mut Location, &mut Position, &mut GameMode, &mut Client), Added<Client>>,
|
||||||
|
instances: Query<Entity, With<Instance>>,
|
||||||
|
) {
|
||||||
|
for (mut loc, mut pos, mut game_mode, mut client) in &mut clients {
|
||||||
|
loc.0 = instances.single();
|
||||||
|
pos.set([0.5, 65.0, 0.5]);
|
||||||
|
*game_mode = GameMode::Creative;
|
||||||
|
client.send_message("To spawn an entity, press shift. F3 + B to activate hitboxes");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn spawn_entity(
|
||||||
|
mut commands: Commands,
|
||||||
|
mut sneaking: EventReader<Sneaking>,
|
||||||
|
client_query: Query<(&Position, &Location)>,
|
||||||
|
) {
|
||||||
|
for sneaking in sneaking.iter() {
|
||||||
|
if sneaking.state == SneakState::Start {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let (position, location) = client_query.get(sneaking.client).unwrap();
|
||||||
|
|
||||||
|
let position = *position;
|
||||||
|
let location = *location;
|
||||||
|
|
||||||
|
match rand::thread_rng().gen_range(0..7) {
|
||||||
|
0 => commands.spawn(SheepEntityBundle {
|
||||||
|
position,
|
||||||
|
location,
|
||||||
|
entity_name_visible: NameVisible(true),
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
1 => commands.spawn(PigEntityBundle {
|
||||||
|
position,
|
||||||
|
location,
|
||||||
|
entity_name_visible: NameVisible(true),
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
2 => commands.spawn(ZombieEntityBundle {
|
||||||
|
position,
|
||||||
|
location,
|
||||||
|
entity_name_visible: NameVisible(true),
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
3 => commands.spawn(ZombieHorseEntityBundle {
|
||||||
|
position,
|
||||||
|
location,
|
||||||
|
entity_name_visible: NameVisible(true),
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
4 => commands.spawn(WardenEntityBundle {
|
||||||
|
position,
|
||||||
|
location,
|
||||||
|
entity_name_visible: NameVisible(true),
|
||||||
|
entity_pose: entity::Pose(Pose::Digging),
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
5 => commands.spawn(WardenEntityBundle {
|
||||||
|
position,
|
||||||
|
location,
|
||||||
|
entity_name_visible: NameVisible(true),
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
6 => commands.spawn(HoglinEntityBundle {
|
||||||
|
position,
|
||||||
|
location,
|
||||||
|
entity_name_visible: NameVisible(true),
|
||||||
|
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn intersections(query: Query<(Entity, &Hitbox)>, mut name_query: Query<&mut entity::CustomName>) {
|
||||||
|
// This code only to show how hitboxes can be used
|
||||||
|
let mut intersections = HashMap::new();
|
||||||
|
|
||||||
|
for [(entity1, hitbox1), (entity2, hitbox2)] in query.iter_combinations() {
|
||||||
|
let aabb1 = hitbox1.get();
|
||||||
|
let aabb2 = hitbox2.get();
|
||||||
|
|
||||||
|
let _ = *intersections.entry(entity1).or_insert(0);
|
||||||
|
let _ = *intersections.entry(entity2).or_insert(0);
|
||||||
|
|
||||||
|
if aabb1.intersects(aabb2) {
|
||||||
|
*intersections.get_mut(&entity1).unwrap() += 1;
|
||||||
|
*intersections.get_mut(&entity2).unwrap() += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (entity, value) in intersections {
|
||||||
|
let Ok(mut name) = name_query.get_mut(entity) else { continue; };
|
||||||
|
name.0 = Some(format!("{value}").into());
|
||||||
|
}
|
||||||
|
}
|
|
@ -105,6 +105,7 @@ pub mod prelude {
|
||||||
pub use valence_core::ident; // Export the `ident!` macro.
|
pub use valence_core::ident; // Export the `ident!` macro.
|
||||||
pub use valence_core::uuid::UniqueId;
|
pub use valence_core::uuid::UniqueId;
|
||||||
pub use valence_core::{translation_key, CoreSettings, Server};
|
pub use valence_core::{translation_key, CoreSettings, Server};
|
||||||
|
pub use valence_entity::hitbox::{Hitbox, HitboxShape};
|
||||||
|
|
||||||
pub use super::DefaultPlugins;
|
pub use super::DefaultPlugins;
|
||||||
use super::*;
|
use super::*;
|
||||||
|
@ -127,6 +128,7 @@ impl PluginGroup for DefaultPlugins {
|
||||||
.add(valence_biome::BiomePlugin)
|
.add(valence_biome::BiomePlugin)
|
||||||
.add(valence_dimension::DimensionPlugin)
|
.add(valence_dimension::DimensionPlugin)
|
||||||
.add(valence_entity::EntityPlugin)
|
.add(valence_entity::EntityPlugin)
|
||||||
|
.add(valence_entity::hitbox::HitboxPlugin)
|
||||||
.add(valence_instance::InstancePlugin)
|
.add(valence_instance::InstancePlugin)
|
||||||
.add(valence_client::ClientPlugin);
|
.add(valence_client::ClientPlugin);
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ use bevy_ecs::system::SystemState;
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use tracing::{debug, warn};
|
use tracing::{debug, warn};
|
||||||
use valence_core::packet::{Decode, Packet};
|
use valence_core::packet::{Decode, Packet};
|
||||||
|
use valence_entity::hitbox::HitboxUpdateSet;
|
||||||
|
|
||||||
use crate::{Client, SpawnClientsSet};
|
use crate::{Client, SpawnClientsSet};
|
||||||
|
|
||||||
|
@ -14,7 +15,8 @@ pub(super) fn build(app: &mut App) {
|
||||||
app.configure_set(
|
app.configure_set(
|
||||||
RunEventLoopSet
|
RunEventLoopSet
|
||||||
.in_base_set(CoreSet::PreUpdate)
|
.in_base_set(CoreSet::PreUpdate)
|
||||||
.after(SpawnClientsSet),
|
.after(SpawnClientsSet)
|
||||||
|
.after(HitboxUpdateSet),
|
||||||
)
|
)
|
||||||
.add_system(run_event_loop.in_set(RunEventLoopSet))
|
.add_system(run_event_loop.in_set(RunEventLoopSet))
|
||||||
.add_event::<PacketEvent>();
|
.add_event::<PacketEvent>();
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
use std::ops::Add;
|
||||||
|
|
||||||
use glam::DVec3;
|
use glam::DVec3;
|
||||||
|
|
||||||
/// An axis-aligned bounding box. `min` is expected to be <= `max`
|
/// An axis-aligned bounding box. `min` is expected to be <= `max`
|
||||||
|
@ -35,4 +37,32 @@ impl Aabb {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn intersects(&self, second: Aabb) -> bool {
|
||||||
|
self.max.x >= second.min.x
|
||||||
|
&& second.max.x >= self.min.x
|
||||||
|
&& self.max.y >= second.min.y
|
||||||
|
&& second.max.y >= self.min.y
|
||||||
|
&& self.max.z >= second.min.z
|
||||||
|
&& second.max.z >= self.min.z
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Add<DVec3> for Aabb {
|
||||||
|
type Output = Aabb;
|
||||||
|
|
||||||
|
fn add(self, rhs: DVec3) -> Self::Output {
|
||||||
|
Self {
|
||||||
|
min: self.min + rhs,
|
||||||
|
max: self.max + rhs,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Add<Aabb> for DVec3 {
|
||||||
|
type Output = Aabb;
|
||||||
|
|
||||||
|
fn add(self, rhs: Aabb) -> Self::Output {
|
||||||
|
rhs + self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,143 +1,468 @@
|
||||||
// TODO: Make a `Hitbox` component and plugin.
|
#![allow(clippy::type_complexity)]
|
||||||
|
|
||||||
/*
|
use bevy_app::{App, CoreSet, Plugin};
|
||||||
/// Returns the hitbox of this entity.
|
use bevy_ecs::prelude::{Component, Entity, SystemSet};
|
||||||
///
|
use bevy_ecs::query::{Added, Changed, Or, With};
|
||||||
/// The hitbox describes the space that an entity occupies. Clients interact
|
use bevy_ecs::schedule::{IntoSystemConfig, IntoSystemConfigs, IntoSystemSetConfig};
|
||||||
/// with this space to create an [interact event].
|
use bevy_ecs::system::{Commands, Query};
|
||||||
///
|
use glam::{DVec3, UVec3, Vec3Swizzles};
|
||||||
/// The hitbox of an entity is determined by its position, entity type, and
|
use valence_core::aabb::Aabb;
|
||||||
/// other state specific to that type.
|
use valence_core::direction::Direction;
|
||||||
///
|
|
||||||
/// [interact event]: crate::client::event::PlayerInteract
|
use crate::*;
|
||||||
pub fn hitbox(&self) -> Aabb {
|
|
||||||
fn baby(is_baby: bool, adult_hitbox: [f64; 3]) -> [f64; 3] {
|
#[derive(SystemSet, Clone, Copy, Debug, Hash, PartialEq, Eq)]
|
||||||
if is_baby {
|
pub struct HitboxShapeUpdateSet;
|
||||||
adult_hitbox.map(|a| a / 2.0)
|
|
||||||
} else {
|
#[derive(SystemSet, Clone, Copy, Debug, Hash, PartialEq, Eq)]
|
||||||
adult_hitbox
|
pub struct HitboxComponentsAddSet;
|
||||||
|
|
||||||
|
#[derive(SystemSet, Clone, Copy, Debug, Hash, PartialEq, Eq)]
|
||||||
|
pub struct HitboxUpdateSet;
|
||||||
|
|
||||||
|
pub struct HitboxPlugin;
|
||||||
|
|
||||||
|
#[derive(Resource)]
|
||||||
|
/// Settings for hitbox plugin
|
||||||
|
pub struct EntityHitboxSettings {
|
||||||
|
/// Controls if a plugin should add hitbox component on each created entity.
|
||||||
|
/// Otherwise you should add hitbox component by yourself in order to use
|
||||||
|
/// it.
|
||||||
|
pub add_hitbox_component: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for EntityHitboxSettings {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
add_hitbox_component: true,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn item_frame(pos: DVec3, rotation: i32) -> Aabb {
|
impl Plugin for HitboxPlugin {
|
||||||
let mut center_pos = pos + 0.5;
|
fn build(&self, app: &mut App) {
|
||||||
|
app.init_resource::<EntityHitboxSettings>()
|
||||||
|
.configure_set(HitboxShapeUpdateSet.in_base_set(CoreSet::PreUpdate))
|
||||||
|
.add_systems(
|
||||||
|
(
|
||||||
|
update_constant_hitbox,
|
||||||
|
update_warden_hitbox,
|
||||||
|
update_area_effect_cloud_hitbox,
|
||||||
|
update_armor_stand_hitbox,
|
||||||
|
update_passive_child_hitbox,
|
||||||
|
update_zombie_hitbox,
|
||||||
|
update_piglin_hitbox,
|
||||||
|
update_zoglin_hitbox,
|
||||||
|
update_player_hitbox,
|
||||||
|
update_item_frame_hitbox,
|
||||||
|
update_slime_hitbox,
|
||||||
|
update_painting_hitbox,
|
||||||
|
update_shulker_hitbox,
|
||||||
|
)
|
||||||
|
.in_set(HitboxShapeUpdateSet),
|
||||||
|
)
|
||||||
|
.configure_set(HitboxComponentsAddSet.in_base_set(CoreSet::PostUpdate))
|
||||||
|
.add_system(add_hitbox_component.in_set(HitboxComponentsAddSet))
|
||||||
|
.configure_set(
|
||||||
|
HitboxUpdateSet
|
||||||
|
.in_base_set(CoreSet::PreUpdate)
|
||||||
|
.after(HitboxShapeUpdateSet),
|
||||||
|
)
|
||||||
|
.add_system(update_hitbox.in_set(HitboxUpdateSet));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
match rotation {
|
/// Size of hitbox. The only way to manipulate it without losing it on the next
|
||||||
0 => center_pos.y += 0.46875,
|
/// tick is using a marker entity. Marker entity's hitbox is never updated.
|
||||||
1 => center_pos.y -= 0.46875,
|
#[derive(Component, Debug, PartialEq)]
|
||||||
2 => center_pos.z += 0.46875,
|
pub struct HitboxShape(pub Aabb);
|
||||||
3 => center_pos.z -= 0.46875,
|
|
||||||
4 => center_pos.x += 0.46875,
|
|
||||||
5 => center_pos.x -= 0.46875,
|
|
||||||
_ => center_pos.y -= 0.46875,
|
|
||||||
};
|
|
||||||
|
|
||||||
let bounds = DVec3::from(match rotation {
|
#[derive(Component, Debug)]
|
||||||
0 | 1 => [0.75, 0.0625, 0.75],
|
/// Hitbox, aabb of which is calculated each tick using it's position and
|
||||||
2 | 3 => [0.75, 0.75, 0.0625],
|
/// [`Hitbox`]. In order to change size of this hitbox you need to change
|
||||||
4 | 5 => [0.0625, 0.75, 0.75],
|
/// [`Hitbox`]
|
||||||
_ => [0.75, 0.0625, 0.75],
|
pub struct Hitbox(Aabb);
|
||||||
|
|
||||||
|
impl HitboxShape {
|
||||||
|
pub const ZERO: HitboxShape = HitboxShape(Aabb {
|
||||||
|
min: DVec3::ZERO,
|
||||||
|
max: DVec3::ZERO,
|
||||||
});
|
});
|
||||||
|
|
||||||
Aabb {
|
pub fn get(&self) -> Aabb {
|
||||||
min: center_pos - bounds / 2.0,
|
self.0
|
||||||
max: center_pos + bounds / 2.0,
|
}
|
||||||
|
|
||||||
|
pub(crate) fn centered(&mut self, size: DVec3) {
|
||||||
|
self.0 = Aabb::from_bottom_size(DVec3::ZERO, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn in_world(&self, pos: DVec3) -> Aabb {
|
||||||
|
self.0 + pos
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let dimensions = match &self.data {
|
impl Hitbox {
|
||||||
TrackedData::Allay(_) => [0.6, 0.35, 0.6],
|
pub fn get(&self) -> Aabb {
|
||||||
TrackedData::ChestBoat(_) => [1.375, 0.5625, 1.375],
|
self.0
|
||||||
TrackedData::Frog(_) => [0.5, 0.5, 0.5],
|
}
|
||||||
TrackedData::Tadpole(_) => [0.4, 0.3, 0.4],
|
}
|
||||||
TrackedData::Warden(e) => match e.get_pose() {
|
|
||||||
|
fn add_hitbox_component(
|
||||||
|
settings: Res<EntityHitboxSettings>,
|
||||||
|
mut commands: Commands,
|
||||||
|
query: Query<(Entity, &Position), Added<entity::Entity>>,
|
||||||
|
alt_query: Query<(Entity, &Position, &HitboxShape), Added<HitboxShape>>,
|
||||||
|
) {
|
||||||
|
if settings.add_hitbox_component {
|
||||||
|
for (entity, pos) in query.iter() {
|
||||||
|
commands
|
||||||
|
.entity(entity)
|
||||||
|
.insert(HitboxShape::ZERO)
|
||||||
|
.insert(Hitbox(HitboxShape::ZERO.in_world(pos.0)));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (entity, pos, hitbox) in alt_query.iter() {
|
||||||
|
commands
|
||||||
|
.entity(entity)
|
||||||
|
.insert(Hitbox(hitbox.in_world(pos.0)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_hitbox(
|
||||||
|
mut hitbox_query: Query<
|
||||||
|
(&mut Hitbox, &HitboxShape, &Position),
|
||||||
|
Or<(Changed<HitboxShape>, Changed<Position>)>,
|
||||||
|
>,
|
||||||
|
) {
|
||||||
|
for (mut in_world, hitbox, pos) in hitbox_query.iter_mut() {
|
||||||
|
in_world.0 = hitbox.in_world(pos.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_constant_hitbox(
|
||||||
|
mut hitbox_query: Query<
|
||||||
|
(&mut HitboxShape, &EntityKind),
|
||||||
|
Or<(Changed<EntityKind>, Added<HitboxShape>)>,
|
||||||
|
>,
|
||||||
|
) {
|
||||||
|
for (mut hitbox, entity_kind) in hitbox_query.iter_mut() {
|
||||||
|
let size = match *entity_kind {
|
||||||
|
EntityKind::ALLAY => [0.6, 0.35, 0.6],
|
||||||
|
EntityKind::CHEST_BOAT | EntityKind::BOAT => [1.375, 0.5625, 1.375],
|
||||||
|
EntityKind::FROG => [0.5, 0.5, 0.5],
|
||||||
|
EntityKind::TADPOLE => [0.4, 0.3, 0.4],
|
||||||
|
EntityKind::SPECTRAL_ARROW | EntityKind::ARROW => [0.5, 0.5, 0.5],
|
||||||
|
EntityKind::AXOLOTL => [1.3, 0.6, 1.3],
|
||||||
|
EntityKind::BAT => [0.5, 0.9, 0.5],
|
||||||
|
EntityKind::BLAZE => [0.6, 1.8, 0.6],
|
||||||
|
EntityKind::CAT => [0.6, 0.7, 0.6],
|
||||||
|
EntityKind::CAVE_SPIDER => [0.7, 0.5, 0.7],
|
||||||
|
EntityKind::COD => [0.5, 0.3, 0.5],
|
||||||
|
EntityKind::CREEPER => [0.6, 1.7, 0.6],
|
||||||
|
EntityKind::DOLPHIN => [0.9, 0.6, 0.9],
|
||||||
|
EntityKind::DRAGON_FIREBALL => [1.0, 1.0, 1.0],
|
||||||
|
EntityKind::ELDER_GUARDIAN => [1.9975, 1.9975, 1.9975],
|
||||||
|
EntityKind::END_CRYSTAL => [2.0, 2.0, 2.0],
|
||||||
|
EntityKind::ENDER_DRAGON => [16.0, 8.0, 16.0],
|
||||||
|
EntityKind::ENDERMAN => [0.6, 2.9, 0.6],
|
||||||
|
EntityKind::ENDERMITE => [0.4, 0.3, 0.4],
|
||||||
|
EntityKind::EVOKER => [0.6, 1.95, 0.6],
|
||||||
|
EntityKind::EVOKER_FANGS => [0.5, 0.8, 0.5],
|
||||||
|
EntityKind::EXPERIENCE_ORB => [0.5, 0.5, 0.5],
|
||||||
|
EntityKind::EYE_OF_ENDER => [0.25, 0.25, 0.25],
|
||||||
|
EntityKind::FALLING_BLOCK => [0.98, 0.98, 0.98],
|
||||||
|
EntityKind::FIREWORK_ROCKET => [0.25, 0.25, 0.25],
|
||||||
|
EntityKind::GHAST => [4.0, 4.0, 4.0],
|
||||||
|
EntityKind::GIANT => [3.6, 12.0, 3.6],
|
||||||
|
EntityKind::GLOW_SQUID | EntityKind::SQUID => [0.8, 0.8, 0.8],
|
||||||
|
EntityKind::GUARDIAN => [0.85, 0.85, 0.85],
|
||||||
|
EntityKind::ILLUSIONER => [0.6, 1.95, 0.6],
|
||||||
|
EntityKind::IRON_GOLEM => [1.4, 2.7, 1.4],
|
||||||
|
EntityKind::ITEM => [0.25, 0.25, 0.25],
|
||||||
|
EntityKind::FIREBALL => [1.0, 1.0, 1.0],
|
||||||
|
EntityKind::LEASH_KNOT => [0.375, 0.5, 0.375],
|
||||||
|
EntityKind::LIGHTNING /* | EntityKind::MARKER - marker hitbox */ => [0.0; 3],
|
||||||
|
EntityKind::LLAMA_SPIT => [0.25, 0.25, 0.25],
|
||||||
|
EntityKind::MINECART
|
||||||
|
| EntityKind::CHEST_MINECART
|
||||||
|
| EntityKind::TNT_MINECART
|
||||||
|
| EntityKind::HOPPER_MINECART
|
||||||
|
| EntityKind::FURNACE_MINECART
|
||||||
|
| EntityKind::SPAWNER_MINECART
|
||||||
|
| EntityKind::COMMAND_BLOCK_MINECART => [0.98, 0.7, 0.98],
|
||||||
|
EntityKind::PARROT => [0.5, 0.9, 0.5],
|
||||||
|
EntityKind::PHANTOM => [0.9, 0.5, 0.9],
|
||||||
|
EntityKind::PIGLIN_BRUTE => [0.6, 1.95, 0.6],
|
||||||
|
EntityKind::PILLAGER => [0.6, 1.95, 0.6],
|
||||||
|
EntityKind::TNT => [0.98, 0.98, 0.98],
|
||||||
|
EntityKind::PUFFERFISH => [0.7, 0.7, 0.7],
|
||||||
|
EntityKind::RAVAGER => [1.95, 2.2, 1.95],
|
||||||
|
EntityKind::SALMON => [0.7, 0.4, 0.7],
|
||||||
|
EntityKind::SHULKER_BULLET => [0.3125, 0.3125, 0.3125],
|
||||||
|
EntityKind::SILVERFISH => [0.4, 0.3, 0.4],
|
||||||
|
EntityKind::SMALL_FIREBALL => [0.3125, 0.3125, 0.3125],
|
||||||
|
EntityKind::SNOW_GOLEM => [0.7, 1.9, 0.7],
|
||||||
|
EntityKind::SPIDER => [1.4, 0.9, 1.4],
|
||||||
|
EntityKind::STRAY => [0.6, 1.99, 0.6],
|
||||||
|
EntityKind::EGG => [0.25, 0.25, 0.25],
|
||||||
|
EntityKind::ENDER_PEARL => [0.25, 0.25, 0.25],
|
||||||
|
EntityKind::EXPERIENCE_BOTTLE => [0.25, 0.25, 0.25],
|
||||||
|
EntityKind::POTION => [0.25, 0.25, 0.25],
|
||||||
|
EntityKind::TRIDENT => [0.5, 0.5, 0.5],
|
||||||
|
EntityKind::TRADER_LLAMA => [0.9, 1.87, 0.9],
|
||||||
|
EntityKind::TROPICAL_FISH => [0.5, 0.4, 0.5],
|
||||||
|
EntityKind::VEX => [0.4, 0.8, 0.4],
|
||||||
|
EntityKind::VINDICATOR => [0.6, 1.95, 0.6],
|
||||||
|
EntityKind::WITHER => [0.9, 3.5, 0.9],
|
||||||
|
EntityKind::WITHER_SKELETON => [0.7, 2.4, 0.7],
|
||||||
|
EntityKind::WITHER_SKULL => [0.3125, 0.3125, 0.3125],
|
||||||
|
EntityKind::FISHING_BOBBER => [0.25, 0.25, 0.25],
|
||||||
|
_ => {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.into();
|
||||||
|
hitbox.centered(size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_warden_hitbox(
|
||||||
|
mut query: Query<
|
||||||
|
(&mut HitboxShape, &entity::Pose),
|
||||||
|
(
|
||||||
|
Or<(Changed<entity::Pose>, Added<HitboxShape>)>,
|
||||||
|
With<warden::WardenEntity>,
|
||||||
|
),
|
||||||
|
>,
|
||||||
|
) {
|
||||||
|
for (mut hitbox, entity_pose) in query.iter_mut() {
|
||||||
|
hitbox.centered(
|
||||||
|
match entity_pose.0 {
|
||||||
Pose::Emerging | Pose::Digging => [0.9, 1.0, 0.9],
|
Pose::Emerging | Pose::Digging => [0.9, 1.0, 0.9],
|
||||||
_ => [0.9, 2.9, 0.9],
|
_ => [0.9, 2.9, 0.9],
|
||||||
},
|
}
|
||||||
TrackedData::AreaEffectCloud(e) => [
|
.into(),
|
||||||
e.get_radius() as f64 * 2.0,
|
);
|
||||||
0.5,
|
}
|
||||||
e.get_radius() as f64 * 2.0,
|
}
|
||||||
],
|
|
||||||
TrackedData::ArmorStand(e) => {
|
fn update_area_effect_cloud_hitbox(
|
||||||
if e.get_marker() {
|
mut query: Query<
|
||||||
[0.0, 0.0, 0.0]
|
(&mut HitboxShape, &area_effect_cloud::Radius),
|
||||||
} else if e.get_small() {
|
Or<(Changed<area_effect_cloud::Radius>, Added<HitboxShape>)>,
|
||||||
|
>,
|
||||||
|
) {
|
||||||
|
for (mut hitbox, cloud_radius) in query.iter_mut() {
|
||||||
|
let diameter = cloud_radius.0 as f64 * 2.0;
|
||||||
|
hitbox.centered([diameter, 0.5, diameter].into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_armor_stand_hitbox(
|
||||||
|
mut query: Query<
|
||||||
|
(&mut HitboxShape, &armor_stand::ArmorStandFlags),
|
||||||
|
Or<(Changed<armor_stand::ArmorStandFlags>, Added<HitboxShape>)>,
|
||||||
|
>,
|
||||||
|
) {
|
||||||
|
for (mut hitbox, stand_flags) in query.iter_mut() {
|
||||||
|
hitbox.centered(
|
||||||
|
if stand_flags.0 & 16 != 0 {
|
||||||
|
// Marker armor stand
|
||||||
|
[0.0; 3]
|
||||||
|
} else if stand_flags.0 & 1 != 0 {
|
||||||
|
// Small armor stand
|
||||||
[0.5, 0.9875, 0.5]
|
[0.5, 0.9875, 0.5]
|
||||||
} else {
|
} else {
|
||||||
[0.5, 1.975, 0.5]
|
[0.5, 1.975, 0.5]
|
||||||
}
|
}
|
||||||
|
.into(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
TrackedData::Arrow(_) => [0.5, 0.5, 0.5],
|
}
|
||||||
TrackedData::Axolotl(_) => [1.3, 0.6, 1.3],
|
|
||||||
TrackedData::Bat(_) => [0.5, 0.9, 0.5],
|
fn child_hitbox(child: bool, v: DVec3) -> DVec3 {
|
||||||
TrackedData::Bee(e) => baby(e.get_child(), [0.7, 0.6, 0.7]),
|
if child {
|
||||||
TrackedData::Blaze(_) => [0.6, 1.8, 0.6],
|
v / 2.0
|
||||||
TrackedData::Boat(_) => [1.375, 0.5625, 1.375],
|
|
||||||
TrackedData::Camel(e) => baby(e.get_child(), [1.7, 2.375, 1.7]),
|
|
||||||
TrackedData::Cat(_) => [0.6, 0.7, 0.6],
|
|
||||||
TrackedData::CaveSpider(_) => [0.7, 0.5, 0.7],
|
|
||||||
TrackedData::Chicken(e) => baby(e.get_child(), [0.4, 0.7, 0.4]),
|
|
||||||
TrackedData::Cod(_) => [0.5, 0.3, 0.5],
|
|
||||||
TrackedData::Cow(e) => baby(e.get_child(), [0.9, 1.4, 0.9]),
|
|
||||||
TrackedData::Creeper(_) => [0.6, 1.7, 0.6],
|
|
||||||
TrackedData::Dolphin(_) => [0.9, 0.6, 0.9],
|
|
||||||
TrackedData::Donkey(e) => baby(e.get_child(), [1.5, 1.39648, 1.5]),
|
|
||||||
TrackedData::DragonFireball(_) => [1.0, 1.0, 1.0],
|
|
||||||
TrackedData::Drowned(e) => baby(e.get_baby(), [0.6, 1.95, 0.6]),
|
|
||||||
TrackedData::ElderGuardian(_) => [1.9975, 1.9975, 1.9975],
|
|
||||||
TrackedData::EndCrystal(_) => [2.0, 2.0, 2.0],
|
|
||||||
TrackedData::EnderDragon(_) => [16.0, 8.0, 16.0],
|
|
||||||
TrackedData::Enderman(_) => [0.6, 2.9, 0.6],
|
|
||||||
TrackedData::Endermite(_) => [0.4, 0.3, 0.4],
|
|
||||||
TrackedData::Evoker(_) => [0.6, 1.95, 0.6],
|
|
||||||
TrackedData::EvokerFangs(_) => [0.5, 0.8, 0.5],
|
|
||||||
TrackedData::ExperienceOrb(_) => [0.5, 0.5, 0.5],
|
|
||||||
TrackedData::EyeOfEnder(_) => [0.25, 0.25, 0.25],
|
|
||||||
TrackedData::FallingBlock(_) => [0.98, 0.98, 0.98],
|
|
||||||
TrackedData::FireworkRocket(_) => [0.25, 0.25, 0.25],
|
|
||||||
TrackedData::Fox(e) => baby(e.get_child(), [0.6, 0.7, 0.6]),
|
|
||||||
TrackedData::Ghast(_) => [4.0, 4.0, 4.0],
|
|
||||||
TrackedData::Giant(_) => [3.6, 12.0, 3.6],
|
|
||||||
TrackedData::GlowItemFrame(e) => return item_frame(self.position, e.get_rotation()),
|
|
||||||
TrackedData::GlowSquid(_) => [0.8, 0.8, 0.8],
|
|
||||||
TrackedData::Goat(e) => {
|
|
||||||
if e.get_pose() == Pose::LongJumping {
|
|
||||||
baby(e.get_child(), [0.63, 0.91, 0.63])
|
|
||||||
} else {
|
} else {
|
||||||
baby(e.get_child(), [0.9, 1.3, 0.9])
|
v
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TrackedData::Guardian(_) => [0.85, 0.85, 0.85],
|
|
||||||
TrackedData::Hoglin(e) => baby(e.get_child(), [1.39648, 1.4, 1.39648]),
|
fn update_passive_child_hitbox(
|
||||||
TrackedData::Horse(e) => baby(e.get_child(), [1.39648, 1.6, 1.39648]),
|
mut query: Query<
|
||||||
TrackedData::Husk(e) => baby(e.get_baby(), [0.6, 1.95, 0.6]),
|
(Entity, &mut HitboxShape, &EntityKind, &passive::Child),
|
||||||
TrackedData::Illusioner(_) => [0.6, 1.95, 0.6],
|
Or<(Changed<passive::Child>, Added<HitboxShape>)>,
|
||||||
TrackedData::IronGolem(_) => [1.4, 2.7, 1.4],
|
>,
|
||||||
TrackedData::Item(_) => [0.25, 0.25, 0.25],
|
pose_query: Query<&entity::Pose>,
|
||||||
TrackedData::ItemFrame(e) => return item_frame(self.position, e.get_rotation()),
|
) {
|
||||||
TrackedData::Fireball(_) => [1.0, 1.0, 1.0],
|
for (entity, mut hitbox, entity_kind, child) in query.iter_mut() {
|
||||||
TrackedData::LeashKnot(_) => [0.375, 0.5, 0.375],
|
let big_s = match *entity_kind {
|
||||||
TrackedData::Lightning(_) => [0.0, 0.0, 0.0],
|
EntityKind::BEE => [0.7, 0.6, 0.7],
|
||||||
TrackedData::Llama(e) => baby(e.get_child(), [0.9, 1.87, 0.9]),
|
EntityKind::CAMEL => [1.7, 2.375, 1.7],
|
||||||
TrackedData::LlamaSpit(_) => [0.25, 0.25, 0.25],
|
EntityKind::CHICKEN => [0.4, 0.7, 0.4],
|
||||||
TrackedData::MagmaCube(e) => {
|
EntityKind::DONKEY => [1.5, 1.39648, 1.5],
|
||||||
let s = 0.5202 * e.get_slime_size() as f64;
|
EntityKind::FOX => [0.6, 0.7, 0.6],
|
||||||
[s, s, s]
|
EntityKind::GOAT => {
|
||||||
|
if pose_query
|
||||||
|
.get(entity)
|
||||||
|
.map_or(false, |v| v.0 == Pose::LongJumping)
|
||||||
|
{
|
||||||
|
[0.63, 0.91, 0.63]
|
||||||
|
} else {
|
||||||
|
[0.9, 1.3, 0.9]
|
||||||
}
|
}
|
||||||
TrackedData::Marker(_) => [0.0, 0.0, 0.0],
|
}
|
||||||
TrackedData::Minecart(_) => [0.98, 0.7, 0.98],
|
EntityKind::HOGLIN => [1.39648, 1.4, 1.39648],
|
||||||
TrackedData::ChestMinecart(_) => [0.98, 0.7, 0.98],
|
EntityKind::HORSE | EntityKind::SKELETON_HORSE | EntityKind::ZOMBIE_HORSE => {
|
||||||
TrackedData::CommandBlockMinecart(_) => [0.98, 0.7, 0.98],
|
[1.39648, 1.6, 1.39648]
|
||||||
TrackedData::FurnaceMinecart(_) => [0.98, 0.7, 0.98],
|
}
|
||||||
TrackedData::HopperMinecart(_) => [0.98, 0.7, 0.98],
|
EntityKind::LLAMA => [0.9, 1.87, 0.9],
|
||||||
TrackedData::SpawnerMinecart(_) => [0.98, 0.7, 0.98],
|
EntityKind::MULE => [1.39648, 1.6, 1.39648],
|
||||||
TrackedData::TntMinecart(_) => [0.98, 0.7, 0.98],
|
EntityKind::MOOSHROOM => [0.9, 1.4, 0.9],
|
||||||
TrackedData::Mule(e) => baby(e.get_child(), [1.39648, 1.6, 1.39648]),
|
EntityKind::OCELOT => [0.6, 0.7, 0.6],
|
||||||
TrackedData::Mooshroom(e) => baby(e.get_child(), [0.9, 1.4, 0.9]),
|
EntityKind::PANDA => [1.3, 1.25, 1.3],
|
||||||
TrackedData::Ocelot(e) => baby(e.get_child(), [0.6, 0.7, 0.6]),
|
EntityKind::PIG => [0.9, 0.9, 0.9],
|
||||||
TrackedData::Painting(e) => {
|
EntityKind::POLAR_BEAR => [1.4, 1.4, 1.4],
|
||||||
let bounds: UVec3 = match e.get_variant() {
|
EntityKind::RABBIT => [0.4, 0.5, 0.4],
|
||||||
|
EntityKind::SHEEP => [0.9, 1.3, 0.9],
|
||||||
|
EntityKind::TURTLE => {
|
||||||
|
hitbox.centered(
|
||||||
|
if child.0 {
|
||||||
|
[0.36, 0.12, 0.36]
|
||||||
|
} else {
|
||||||
|
[1.2, 0.4, 1.2]
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
EntityKind::VILLAGER => [0.6, 1.95, 0.6],
|
||||||
|
EntityKind::WOLF => [0.6, 0.85, 0.6],
|
||||||
|
_ => {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
hitbox.centered(child_hitbox(child.0, big_s.into()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_zombie_hitbox(
|
||||||
|
mut query: Query<
|
||||||
|
(&mut HitboxShape, &zombie::Baby),
|
||||||
|
Or<(Changed<zombie::Baby>, Added<HitboxShape>)>,
|
||||||
|
>,
|
||||||
|
) {
|
||||||
|
for (mut hitbox, baby) in query.iter_mut() {
|
||||||
|
hitbox.centered(child_hitbox(baby.0, [0.6, 1.95, 0.6].into()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_piglin_hitbox(
|
||||||
|
mut query: Query<
|
||||||
|
(&mut HitboxShape, &piglin::Baby),
|
||||||
|
Or<(Changed<piglin::Baby>, Added<HitboxShape>)>,
|
||||||
|
>,
|
||||||
|
) {
|
||||||
|
for (mut hitbox, baby) in query.iter_mut() {
|
||||||
|
hitbox.centered(child_hitbox(baby.0, [0.6, 1.95, 0.6].into()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_zoglin_hitbox(
|
||||||
|
mut query: Query<
|
||||||
|
(&mut HitboxShape, &zoglin::Baby),
|
||||||
|
Or<(Changed<zoglin::Baby>, Added<HitboxShape>)>,
|
||||||
|
>,
|
||||||
|
) {
|
||||||
|
for (mut hitbox, baby) in query.iter_mut() {
|
||||||
|
hitbox.centered(child_hitbox(baby.0, [1.39648, 1.4, 1.39648].into()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_player_hitbox(
|
||||||
|
mut query: Query<
|
||||||
|
(&mut HitboxShape, &entity::Pose),
|
||||||
|
(
|
||||||
|
Or<(Changed<entity::Pose>, Added<HitboxShape>)>,
|
||||||
|
With<player::PlayerEntity>,
|
||||||
|
),
|
||||||
|
>,
|
||||||
|
) {
|
||||||
|
for (mut hitbox, pose) in query.iter_mut() {
|
||||||
|
hitbox.centered(
|
||||||
|
match pose.0 {
|
||||||
|
Pose::Sleeping | Pose::Dying => [0.2, 0.2, 0.2],
|
||||||
|
Pose::FallFlying | Pose::Swimming | Pose::SpinAttack => [0.6, 0.6, 0.6],
|
||||||
|
Pose::Sneaking => [0.6, 1.5, 0.6],
|
||||||
|
_ => [0.6, 1.8, 0.6],
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_item_frame_hitbox(
|
||||||
|
mut query: Query<
|
||||||
|
(&mut HitboxShape, &item_frame::Rotation),
|
||||||
|
Or<(Changed<item_frame::Rotation>, Added<HitboxShape>)>,
|
||||||
|
>,
|
||||||
|
) {
|
||||||
|
for (mut hitbox, rotation) in query.iter_mut() {
|
||||||
|
let mut center_pos = DVec3::splat(0.5);
|
||||||
|
|
||||||
|
const A: f64 = 0.46875;
|
||||||
|
|
||||||
|
match rotation.0 {
|
||||||
|
0 => center_pos.y += A,
|
||||||
|
1 => center_pos.y -= A,
|
||||||
|
2 => center_pos.z += A,
|
||||||
|
3 => center_pos.z -= A,
|
||||||
|
4 => center_pos.x += A,
|
||||||
|
5 => center_pos.x -= A,
|
||||||
|
_ => center_pos.y -= A,
|
||||||
|
}
|
||||||
|
|
||||||
|
const BOUNDS23: DVec3 = DVec3::new(0.375, 0.375, 0.03125);
|
||||||
|
|
||||||
|
let bounds = match rotation.0 {
|
||||||
|
2 | 3 => BOUNDS23,
|
||||||
|
4 | 5 => BOUNDS23.zxy(),
|
||||||
|
_ => BOUNDS23.zxy(),
|
||||||
|
};
|
||||||
|
|
||||||
|
hitbox.0 = Aabb {
|
||||||
|
min: center_pos - bounds,
|
||||||
|
max: center_pos + bounds,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_slime_hitbox(
|
||||||
|
mut query: Query<
|
||||||
|
(&mut HitboxShape, &slime::SlimeSize),
|
||||||
|
Or<(Changed<slime::SlimeSize>, Added<HitboxShape>)>,
|
||||||
|
>,
|
||||||
|
) {
|
||||||
|
for (mut hitbox, slime_size) in query.iter_mut() {
|
||||||
|
let s = 0.5202 * slime_size.0 as f64;
|
||||||
|
hitbox.centered([s, s, s].into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_painting_hitbox(
|
||||||
|
mut query: Query<
|
||||||
|
(&mut HitboxShape, &painting::Variant, &Look),
|
||||||
|
Or<(
|
||||||
|
Changed<Look>,
|
||||||
|
Changed<painting::Variant>,
|
||||||
|
Added<HitboxShape>,
|
||||||
|
)>,
|
||||||
|
>,
|
||||||
|
) {
|
||||||
|
for (mut hitbox, painting_variant, look) in query.iter_mut() {
|
||||||
|
let bounds: UVec3 = match painting_variant.0 {
|
||||||
PaintingKind::Kebab => [1, 1, 1],
|
PaintingKind::Kebab => [1, 1, 1],
|
||||||
PaintingKind::Aztec => [1, 1, 1],
|
PaintingKind::Aztec => [1, 1, 1],
|
||||||
PaintingKind::Alban => [1, 1, 1],
|
PaintingKind::Alban => [1, 1, 1],
|
||||||
|
@ -171,10 +496,10 @@ pub fn hitbox(&self) -> Aabb {
|
||||||
}
|
}
|
||||||
.into();
|
.into();
|
||||||
|
|
||||||
let mut center_pos = self.position + 0.5;
|
let mut center_pos = DVec3::splat(0.5);
|
||||||
|
|
||||||
let (facing_x, facing_z, cc_facing_x, cc_facing_z) =
|
let (facing_x, facing_z, cc_facing_x, cc_facing_z) =
|
||||||
match ((self.yaw + 45.0).rem_euclid(360.0) / 90.0) as u8 {
|
match ((look.yaw + 45.0).rem_euclid(360.0) / 90.0) as u8 {
|
||||||
0 => (0, 1, 1, 0), // South
|
0 => (0, 1, 1, 0), // South
|
||||||
1 => (-1, 0, 0, 1), // West
|
1 => (-1, 0, 0, 1), // West
|
||||||
2 => (0, -1, -1, 0), // North
|
2 => (0, -1, -1, 0), // North
|
||||||
|
@ -193,102 +518,45 @@ pub fn hitbox(&self) -> Aabb {
|
||||||
_ => DVec3::new(bounds.x as f64, bounds.y as f64, 0.0625),
|
_ => DVec3::new(bounds.x as f64, bounds.y as f64, 0.0625),
|
||||||
};
|
};
|
||||||
|
|
||||||
return Aabb {
|
hitbox.0 = Aabb {
|
||||||
min: center_pos - bounds / 2.0,
|
min: center_pos - bounds / 2.0,
|
||||||
max: center_pos + bounds / 2.0,
|
max: center_pos + bounds / 2.0,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
TrackedData::Panda(e) => baby(e.get_child(), [1.3, 1.25, 1.3]),
|
}
|
||||||
TrackedData::Parrot(_) => [0.5, 0.9, 0.5],
|
|
||||||
TrackedData::Phantom(_) => [0.9, 0.5, 0.9],
|
|
||||||
TrackedData::Pig(e) => baby(e.get_child(), [0.9, 0.9, 0.9]),
|
|
||||||
TrackedData::Piglin(e) => baby(e.get_baby(), [0.6, 1.95, 0.6]),
|
|
||||||
TrackedData::PiglinBrute(_) => [0.6, 1.95, 0.6],
|
|
||||||
TrackedData::Pillager(_) => [0.6, 1.95, 0.6],
|
|
||||||
TrackedData::PolarBear(e) => baby(e.get_child(), [1.4, 1.4, 1.4]),
|
|
||||||
TrackedData::Tnt(_) => [0.98, 0.98, 0.98],
|
|
||||||
TrackedData::Pufferfish(_) => [0.7, 0.7, 0.7],
|
|
||||||
TrackedData::Rabbit(e) => baby(e.get_child(), [0.4, 0.5, 0.4]),
|
|
||||||
TrackedData::Ravager(_) => [1.95, 2.2, 1.95],
|
|
||||||
TrackedData::Salmon(_) => [0.7, 0.4, 0.7],
|
|
||||||
TrackedData::Sheep(e) => baby(e.get_child(), [0.9, 1.3, 0.9]),
|
|
||||||
TrackedData::Shulker(e) => {
|
|
||||||
const PI: f64 = std::f64::consts::PI;
|
|
||||||
|
|
||||||
let pos = self.position + 0.5;
|
fn update_shulker_hitbox(
|
||||||
|
mut query: Query<
|
||||||
|
(
|
||||||
|
&mut HitboxShape,
|
||||||
|
&shulker::PeekAmount,
|
||||||
|
&shulker::AttachedFace,
|
||||||
|
),
|
||||||
|
Or<(
|
||||||
|
Changed<shulker::PeekAmount>,
|
||||||
|
Changed<shulker::AttachedFace>,
|
||||||
|
Added<HitboxShape>,
|
||||||
|
)>,
|
||||||
|
>,
|
||||||
|
) {
|
||||||
|
use std::f64::consts::PI;
|
||||||
|
|
||||||
|
for (mut hitbox, peek_amount, attached_face) in query.iter_mut() {
|
||||||
|
let pos = DVec3::splat(0.5);
|
||||||
let mut min = pos - 0.5;
|
let mut min = pos - 0.5;
|
||||||
let mut max = pos + 0.5;
|
let mut max = pos + 0.5;
|
||||||
|
|
||||||
let peek = 0.5 - f64::cos(e.get_peek_amount() as f64 * 0.01 * PI) * 0.5;
|
let peek = 0.5 - f64::cos(peek_amount.0 as f64 * 0.01 * PI) * 0.5;
|
||||||
|
|
||||||
match e.get_attached_face() {
|
match attached_face.0 {
|
||||||
Facing::Down => max.y += peek,
|
Direction::Down => max.y += peek,
|
||||||
Facing::Up => min.y -= peek,
|
Direction::Up => min.y -= peek,
|
||||||
Facing::North => max.z += peek,
|
Direction::North => max.z += peek,
|
||||||
Facing::South => min.z -= peek,
|
Direction::South => min.z -= peek,
|
||||||
Facing::West => max.x += peek,
|
Direction::West => max.x += peek,
|
||||||
Facing::East => min.x -= peek,
|
Direction::East => min.x -= peek,
|
||||||
}
|
}
|
||||||
|
|
||||||
return Aabb { min, max };
|
hitbox.0 = Aabb { min, max };
|
||||||
}
|
|
||||||
TrackedData::ShulkerBullet(_) => [0.3125, 0.3125, 0.3125],
|
|
||||||
TrackedData::Silverfish(_) => [0.4, 0.3, 0.4],
|
|
||||||
TrackedData::Skeleton(_) => [0.6, 1.99, 0.6],
|
|
||||||
TrackedData::SkeletonHorse(e) => baby(e.get_child(), [1.39648, 1.6, 1.39648]),
|
|
||||||
TrackedData::Slime(e) => {
|
|
||||||
let s = 0.5202 * e.get_slime_size() as f64;
|
|
||||||
[s, s, s]
|
|
||||||
}
|
|
||||||
TrackedData::SmallFireball(_) => [0.3125, 0.3125, 0.3125],
|
|
||||||
TrackedData::SnowGolem(_) => [0.7, 1.9, 0.7],
|
|
||||||
TrackedData::Snowball(_) => [0.25, 0.25, 0.25],
|
|
||||||
TrackedData::SpectralArrow(_) => [0.5, 0.5, 0.5],
|
|
||||||
TrackedData::Spider(_) => [1.4, 0.9, 1.4],
|
|
||||||
TrackedData::Squid(_) => [0.8, 0.8, 0.8],
|
|
||||||
TrackedData::Stray(_) => [0.6, 1.99, 0.6],
|
|
||||||
TrackedData::Strider(e) => baby(e.get_child(), [0.9, 1.7, 0.9]),
|
|
||||||
TrackedData::Egg(_) => [0.25, 0.25, 0.25],
|
|
||||||
TrackedData::EnderPearl(_) => [0.25, 0.25, 0.25],
|
|
||||||
TrackedData::ExperienceBottle(_) => [0.25, 0.25, 0.25],
|
|
||||||
TrackedData::Potion(_) => [0.25, 0.25, 0.25],
|
|
||||||
TrackedData::Trident(_) => [0.5, 0.5, 0.5],
|
|
||||||
TrackedData::TraderLlama(_) => [0.9, 1.87, 0.9],
|
|
||||||
TrackedData::TropicalFish(_) => [0.5, 0.4, 0.5],
|
|
||||||
TrackedData::Turtle(e) => {
|
|
||||||
if e.get_child() {
|
|
||||||
[0.36, 0.12, 0.36]
|
|
||||||
} else {
|
|
||||||
[1.2, 0.4, 1.2]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TrackedData::Vex(_) => [0.4, 0.8, 0.4],
|
|
||||||
TrackedData::Villager(e) => baby(e.get_child(), [0.6, 1.95, 0.6]),
|
|
||||||
TrackedData::Vindicator(_) => [0.6, 1.95, 0.6],
|
|
||||||
TrackedData::WanderingTrader(_) => [0.6, 1.95, 0.6],
|
|
||||||
TrackedData::Witch(_) => [0.6, 1.95, 0.6],
|
|
||||||
TrackedData::Wither(_) => [0.9, 3.5, 0.9],
|
|
||||||
TrackedData::WitherSkeleton(_) => [0.7, 2.4, 0.7],
|
|
||||||
TrackedData::WitherSkull(_) => [0.3125, 0.3125, 0.3125],
|
|
||||||
TrackedData::Wolf(e) => baby(e.get_child(), [0.6, 0.85, 0.6]),
|
|
||||||
TrackedData::Zoglin(e) => baby(e.get_baby(), [1.39648, 1.4, 1.39648]),
|
|
||||||
TrackedData::Zombie(e) => baby(e.get_baby(), [0.6, 1.95, 0.6]),
|
|
||||||
TrackedData::ZombieHorse(e) => baby(e.get_child(), [1.39648, 1.6, 1.39648]),
|
|
||||||
TrackedData::ZombieVillager(e) => baby(e.get_baby(), [0.6, 1.95, 0.6]),
|
|
||||||
TrackedData::ZombifiedPiglin(e) => baby(e.get_baby(), [0.6, 1.95, 0.6]),
|
|
||||||
TrackedData::Player(e) => match e.get_pose() {
|
|
||||||
Pose::Standing => [0.6, 1.8, 0.6],
|
|
||||||
Pose::Sleeping => [0.2, 0.2, 0.2],
|
|
||||||
Pose::FallFlying => [0.6, 0.6, 0.6],
|
|
||||||
Pose::Swimming => [0.6, 0.6, 0.6],
|
|
||||||
Pose::SpinAttack => [0.6, 0.6, 0.6],
|
|
||||||
Pose::Sneaking => [0.6, 1.5, 0.6],
|
|
||||||
Pose::Dying => [0.2, 0.2, 0.2],
|
|
||||||
_ => [0.6, 1.8, 0.6],
|
|
||||||
},
|
|
||||||
TrackedData::FishingBobber(_) => [0.25, 0.25, 0.25],
|
|
||||||
};
|
|
||||||
|
|
||||||
Aabb::from_bottom_size(self.position, dimensions)
|
|
||||||
}
|
|
||||||
*/
|
|
|
@ -17,6 +17,8 @@
|
||||||
clippy::dbg_macro
|
clippy::dbg_macro
|
||||||
)]
|
)]
|
||||||
|
|
||||||
|
pub mod hitbox;
|
||||||
|
|
||||||
use std::num::Wrapping;
|
use std::num::Wrapping;
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
|
|
||||||
|
@ -35,7 +37,6 @@ use valence_core::uuid::UniqueId;
|
||||||
use valence_core::DEFAULT_TPS;
|
use valence_core::DEFAULT_TPS;
|
||||||
|
|
||||||
include!(concat!(env!("OUT_DIR"), "/entity.rs"));
|
include!(concat!(env!("OUT_DIR"), "/entity.rs"));
|
||||||
|
|
||||||
pub struct EntityPlugin;
|
pub struct EntityPlugin;
|
||||||
|
|
||||||
/// When new Minecraft entities are initialized and added to
|
/// When new Minecraft entities are initialized and added to
|
||||||
|
|
Loading…
Reference in a new issue