mirror of
https://github.com/italicsjenga/valence.git
synced 2025-01-11 07:11:30 +11:00
Improve entity event API
This commit is contained in:
parent
0f8b906265
commit
fcda380f2a
313
build/entity.rs
313
build/entity.rs
File diff suppressed because it is too large
Load diff
|
@ -10,7 +10,7 @@ use rayon::iter::{IndexedParallelIterator, IntoParallelRefMutIterator, ParallelI
|
|||
use valence::client::{ClientEvent, ClientId, GameMode};
|
||||
use valence::config::{Config, ServerListPing};
|
||||
use valence::entity::meta::Pose;
|
||||
use valence::entity::EntityMeta;
|
||||
use valence::entity::EntityData;
|
||||
use valence::text::Color;
|
||||
use valence::{
|
||||
async_trait, ident, Biome, BlockState, Dimension, DimensionId, EntityId, EntityType, Server,
|
||||
|
@ -197,30 +197,30 @@ impl Config for Game {
|
|||
player.set_on_ground(client.on_ground());
|
||||
}
|
||||
ClientEvent::StartSneaking => {
|
||||
if let EntityMeta::Player(e) = player.meta_mut() {
|
||||
if let EntityData::Player(e) = player.data_mut() {
|
||||
e.set_crouching(true);
|
||||
e.set_pose(Pose::Sneaking);
|
||||
}
|
||||
}
|
||||
ClientEvent::StopSneaking => {
|
||||
if let EntityMeta::Player(e) = player.meta_mut() {
|
||||
if let EntityData::Player(e) = player.data_mut() {
|
||||
e.set_pose(Pose::Standing);
|
||||
e.set_crouching(false);
|
||||
}
|
||||
}
|
||||
ClientEvent::StartSprinting => {
|
||||
if let EntityMeta::Player(e) = player.meta_mut() {
|
||||
if let EntityData::Player(e) = player.data_mut() {
|
||||
e.set_sprinting(true);
|
||||
}
|
||||
}
|
||||
ClientEvent::StopSprinting => {
|
||||
if let EntityMeta::Player(e) = player.meta_mut() {
|
||||
if let EntityData::Player(e) = player.data_mut() {
|
||||
e.set_sprinting(false);
|
||||
}
|
||||
}
|
||||
ClientEvent::ArmSwing(_) => {
|
||||
if let EntityMeta::Player(_) = player.meta_mut() {
|
||||
// TODO: swing arm.
|
||||
if let EntityData::Player(e) = player.data_mut() {
|
||||
e.trigger_swing_main_arm();
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
|
|
112
src/client.rs
112
src/client.rs
|
@ -13,31 +13,30 @@ use vek::Vec3;
|
|||
|
||||
use crate::biome::{Biome, BiomeGrassColorModifier, BiomePrecipitation};
|
||||
use crate::dimension::{Dimension, DimensionEffects};
|
||||
use crate::entity::types::Player;
|
||||
use crate::entity::data::Player;
|
||||
use crate::entity::{velocity_to_packet_units, EntityType};
|
||||
use crate::player_textures::SignedPlayerTextures;
|
||||
use crate::protocol::packets::play::c2s::{
|
||||
C2sPlayPacket, DiggingStatus, InteractType, PlayerCommandId,
|
||||
};
|
||||
pub use crate::protocol::packets::play::s2c::EntityEvent;
|
||||
use crate::protocol::packets::play::s2c::{
|
||||
Biome as BiomeRegistryBiome, BiomeAdditionsSound, BiomeEffects, BiomeMoodSound, BiomeMusic,
|
||||
BiomeParticle, BiomeParticleOptions, BiomeProperty, BiomeRegistry, BlockChangeAck, ChatType,
|
||||
ChatTypeChat, ChatTypeNarration, ChatTypeRegistry, ChatTypeRegistryEntry, DimensionType,
|
||||
DimensionTypeRegistry, DimensionTypeRegistryEntry, Disconnect, DoEntityEvent, ForgetLevelChunk,
|
||||
GameEvent, GameEventReason, KeepAlive, Login, MoveEntityPosition,
|
||||
Animate, Biome as BiomeRegistryBiome, BiomeAdditionsSound, BiomeEffects, BiomeMoodSound,
|
||||
BiomeMusic, BiomeParticle, BiomeParticleOptions, BiomeProperty, BiomeRegistry, BlockChangeAck,
|
||||
ChatType, ChatTypeChat, ChatTypeNarration, ChatTypeRegistry, ChatTypeRegistryEntry,
|
||||
DimensionType, DimensionTypeRegistry, DimensionTypeRegistryEntry, Disconnect, EntityEvent,
|
||||
ForgetLevelChunk, GameEvent, GameEventReason, KeepAlive, Login, MoveEntityPosition,
|
||||
MoveEntityPositionAndRotation, MoveEntityRotation, PlayerPosition, PlayerPositionFlags,
|
||||
RegistryCodec, RemoveEntities, Respawn, RotateHead, S2cPlayPacket, SetChunkCacheCenter,
|
||||
SetChunkCacheRadius, SetEntityMetadata, SetEntityMotion, SpawnPosition, SystemChat,
|
||||
TeleportEntity,
|
||||
TeleportEntity, ENTITY_EVENT_MAX_BOUND,
|
||||
};
|
||||
use crate::protocol::{BoundedInt, ByteAngle, Nbt, RawBytes, VarInt};
|
||||
use crate::server::C2sPacketChannels;
|
||||
use crate::slotmap::{Key, SlotMap};
|
||||
use crate::util::{chunks_in_view_distance, is_chunk_in_view_distance};
|
||||
use crate::{
|
||||
ident, BlockPos, ChunkPos, DimensionId, Entities, EntityId, NewClientData, SharedServer, Text,
|
||||
Ticks, WorldId, Worlds, LIBRARY_NAMESPACE,
|
||||
ident, BlockPos, ChunkPos, DimensionId, Entities, Entity, EntityId, NewClientData,
|
||||
SharedServer, Text, Ticks, WorldId, Worlds, LIBRARY_NAMESPACE,
|
||||
};
|
||||
|
||||
pub struct Clients {
|
||||
|
@ -101,7 +100,7 @@ impl ClientId {
|
|||
/// Represents a client connected to the server after logging in.
|
||||
pub struct Client {
|
||||
/// Setting this to `None` disconnects the client.
|
||||
send: Option<Sender<S2cPlayPacket>>,
|
||||
send: SendOpt,
|
||||
recv: Receiver<C2sPlayPacket>,
|
||||
/// The tick this client was created.
|
||||
created_tick: Ticks,
|
||||
|
@ -139,10 +138,9 @@ pub struct Client {
|
|||
settings: Option<Settings>,
|
||||
dug_blocks: Vec<i32>,
|
||||
msgs_to_send: Vec<Text>,
|
||||
entity_events: Vec<EntityEvent>,
|
||||
flags: ClientFlags,
|
||||
/// The metadata for the client's own player entity.
|
||||
player_meta: Player,
|
||||
/// The data for the client's own player entity.
|
||||
player_data: Player,
|
||||
}
|
||||
|
||||
#[bitfield(u8)]
|
||||
|
@ -197,11 +195,10 @@ impl Client {
|
|||
settings: None,
|
||||
dug_blocks: Vec::new(),
|
||||
msgs_to_send: Vec::new(),
|
||||
entity_events: Vec::new(),
|
||||
flags: ClientFlags::new()
|
||||
.with_modified_spawn_position(true)
|
||||
.with_got_keepalive(true),
|
||||
player_meta: Player::new(),
|
||||
player_data: Player::new(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -325,10 +322,6 @@ impl Client {
|
|||
self.events.pop_front()
|
||||
}
|
||||
|
||||
pub fn push_entity_event(&mut self, event: EntityEvent) {
|
||||
self.entity_events.push(event);
|
||||
}
|
||||
|
||||
/// The current view distance of this client measured in chunks.
|
||||
pub fn view_distance(&self) -> u8 {
|
||||
self.settings
|
||||
|
@ -368,12 +361,12 @@ impl Client {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn meta(&self) -> &Player {
|
||||
&self.player_meta
|
||||
pub fn data(&self) -> &Player {
|
||||
&self.player_data
|
||||
}
|
||||
|
||||
pub fn meta_mut(&mut self) -> &mut Player {
|
||||
&mut self.player_meta
|
||||
pub fn data_mut(&mut self) -> &mut Player {
|
||||
&mut self.player_data
|
||||
}
|
||||
|
||||
/// Attempts to enqueue a play packet to be sent to this client. The client
|
||||
|
@ -971,15 +964,7 @@ impl Client {
|
|||
)
|
||||
}
|
||||
|
||||
for &e in entity.events() {
|
||||
send_packet(
|
||||
&mut self.send,
|
||||
DoEntityEvent {
|
||||
entity_id: id.to_network_id(),
|
||||
entity_status: e,
|
||||
},
|
||||
);
|
||||
}
|
||||
send_entity_events(&mut self.send, id, entity);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -997,7 +982,7 @@ impl Client {
|
|||
|
||||
// Update the client's own player metadata.
|
||||
let mut data = Vec::new();
|
||||
self.player_meta.updated_metadata(&mut data);
|
||||
self.player_data.updated_metadata(&mut data);
|
||||
|
||||
if !data.is_empty() {
|
||||
data.push(0xff);
|
||||
|
@ -1007,7 +992,7 @@ impl Client {
|
|||
metadata: RawBytes(data),
|
||||
});
|
||||
}
|
||||
self.player_meta.clear_modifications();
|
||||
self.player_data.clear_modifications();
|
||||
|
||||
// Spawn new entities within the view distance.
|
||||
let pos = self.position();
|
||||
|
@ -1031,29 +1016,24 @@ impl Client {
|
|||
self.send_packet(meta);
|
||||
}
|
||||
|
||||
for &e in entity.events() {
|
||||
send_packet(
|
||||
&mut self.send,
|
||||
DoEntityEvent {
|
||||
entity_id: id.to_network_id(),
|
||||
entity_status: e,
|
||||
},
|
||||
);
|
||||
}
|
||||
send_entity_events(&mut self.send, id, entity);
|
||||
}
|
||||
None
|
||||
},
|
||||
);
|
||||
|
||||
// Send entity events for the client's own player entity.
|
||||
for event in self.entity_events.drain(..) {
|
||||
send_packet(
|
||||
&mut self.send,
|
||||
DoEntityEvent {
|
||||
entity_id: 0,
|
||||
entity_status: event,
|
||||
},
|
||||
);
|
||||
for &code in self.player_data.event_codes() {
|
||||
if code <= ENTITY_EVENT_MAX_BOUND as u8 {
|
||||
send_packet(
|
||||
&mut self.send,
|
||||
EntityEvent {
|
||||
entity_id: 0,
|
||||
entity_status: BoundedInt(code),
|
||||
},
|
||||
);
|
||||
}
|
||||
// Don't bother sending animations since it shouldn't be visible to
|
||||
// the client.
|
||||
}
|
||||
|
||||
self.old_position = self.new_position;
|
||||
|
@ -1061,7 +1041,9 @@ impl Client {
|
|||
}
|
||||
}
|
||||
|
||||
fn send_packet(send_opt: &mut Option<Sender<S2cPlayPacket>>, pkt: impl Into<S2cPlayPacket>) {
|
||||
type SendOpt = Option<Sender<S2cPlayPacket>>;
|
||||
|
||||
fn send_packet(send_opt: &mut SendOpt, pkt: impl Into<S2cPlayPacket>) {
|
||||
if let Some(send) = send_opt {
|
||||
match send.try_send(pkt.into()) {
|
||||
Err(TrySendError::Full(_)) => {
|
||||
|
@ -1076,6 +1058,28 @@ fn send_packet(send_opt: &mut Option<Sender<S2cPlayPacket>>, pkt: impl Into<S2cP
|
|||
}
|
||||
}
|
||||
|
||||
fn send_entity_events(send_opt: &mut SendOpt, id: EntityId, entity: &Entity) {
|
||||
for &code in entity.data().event_codes() {
|
||||
if code <= ENTITY_EVENT_MAX_BOUND as u8 {
|
||||
send_packet(
|
||||
send_opt,
|
||||
EntityEvent {
|
||||
entity_id: id.to_network_id(),
|
||||
entity_status: BoundedInt(code),
|
||||
},
|
||||
);
|
||||
} else {
|
||||
send_packet(
|
||||
send_opt,
|
||||
Animate {
|
||||
entity_id: VarInt(id.to_network_id()),
|
||||
animation: BoundedInt(code - ENTITY_EVENT_MAX_BOUND as u8 - 1),
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn make_dimension_codec(shared: &SharedServer) -> RegistryCodec {
|
||||
let mut dims = Vec::new();
|
||||
for (id, dim) in shared.dimensions() {
|
||||
|
|
286
src/entity.rs
286
src/entity.rs
|
@ -1,5 +1,5 @@
|
|||
pub mod data;
|
||||
pub mod meta;
|
||||
pub mod types;
|
||||
|
||||
use std::collections::hash_map::Entry;
|
||||
use std::collections::HashMap;
|
||||
|
@ -7,12 +7,11 @@ use std::iter::FusedIterator;
|
|||
use std::num::NonZeroU32;
|
||||
|
||||
use bitfield_struct::bitfield;
|
||||
pub use data::{EntityData, EntityType};
|
||||
use rayon::iter::ParallelIterator;
|
||||
pub use types::{EntityMeta, EntityType};
|
||||
use uuid::Uuid;
|
||||
use vek::{Aabb, Vec3};
|
||||
|
||||
pub use crate::protocol::packets::play::s2c::EntityEvent;
|
||||
use crate::protocol::packets::play::s2c::{
|
||||
AddEntity, AddExperienceOrb, AddPlayer, S2cPlayPacket, SetEntityMetadata,
|
||||
};
|
||||
|
@ -58,7 +57,7 @@ impl Entities {
|
|||
Entry::Vacant(ve) => {
|
||||
let (k, e) = self.sm.insert(Entity {
|
||||
flags: EntityFlags(0),
|
||||
meta: EntityMeta::new(typ),
|
||||
data: EntityData::new(typ),
|
||||
world: None,
|
||||
new_position: Vec3::default(),
|
||||
old_position: Vec3::default(),
|
||||
|
@ -67,7 +66,6 @@ impl Entities {
|
|||
head_yaw: 0.0,
|
||||
velocity: Vec3::default(),
|
||||
uuid,
|
||||
events: Vec::new(),
|
||||
});
|
||||
|
||||
// TODO check for overflowing version?
|
||||
|
@ -161,8 +159,7 @@ impl Entities {
|
|||
pub(crate) fn update(&mut self) {
|
||||
for (_, e) in self.iter_mut() {
|
||||
e.old_position = e.new_position;
|
||||
e.meta.clear_modifications();
|
||||
e.events.clear();
|
||||
e.data.clear_modifications();
|
||||
|
||||
e.flags.set_yaw_or_pitch_modified(false);
|
||||
e.flags.set_head_yaw_modified(false);
|
||||
|
@ -184,7 +181,7 @@ impl EntityId {
|
|||
|
||||
pub struct Entity {
|
||||
flags: EntityFlags,
|
||||
meta: EntityMeta,
|
||||
data: EntityData,
|
||||
world: Option<WorldId>,
|
||||
new_position: Vec3<f64>,
|
||||
old_position: Vec3<f64>,
|
||||
|
@ -193,7 +190,6 @@ pub struct Entity {
|
|||
head_yaw: f32,
|
||||
velocity: Vec3<f32>,
|
||||
uuid: Uuid,
|
||||
events: Vec<EntityEvent>,
|
||||
}
|
||||
|
||||
/// Contains a bit for certain fields in [`Entity`] to track if they have been
|
||||
|
@ -213,19 +209,19 @@ impl Entity {
|
|||
self.flags
|
||||
}
|
||||
|
||||
/// Returns a reference to this entity's [`EntityMeta`].
|
||||
pub fn meta(&self) -> &EntityMeta {
|
||||
&self.meta
|
||||
/// Returns a reference to this entity's [`EntityData`].
|
||||
pub fn data(&self) -> &EntityData {
|
||||
&self.data
|
||||
}
|
||||
|
||||
/// Returns a mutable reference to this entity's [`EntityMeta`].
|
||||
pub fn meta_mut(&mut self) -> &mut EntityMeta {
|
||||
&mut self.meta
|
||||
/// Returns a mutable reference to this entity's [`EntityData`].
|
||||
pub fn data_mut(&mut self) -> &mut EntityData {
|
||||
&mut self.data
|
||||
}
|
||||
|
||||
/// Returns the [`EntityType`] of this entity.
|
||||
pub fn typ(&self) -> EntityType {
|
||||
self.meta.typ()
|
||||
self.data.typ()
|
||||
}
|
||||
|
||||
pub fn world(&self) -> Option<WorldId> {
|
||||
|
@ -317,27 +313,19 @@ impl Entity {
|
|||
self.uuid
|
||||
}
|
||||
|
||||
pub fn push_event(&mut self, event: EntityEvent) {
|
||||
self.events.push(event);
|
||||
}
|
||||
|
||||
pub(crate) fn events(&self) -> &[EntityEvent] {
|
||||
&self.events
|
||||
}
|
||||
|
||||
pub fn hitbox(&self) -> Aabb<f64> {
|
||||
let dims = match &self.meta {
|
||||
EntityMeta::Allay(_) => [0.6, 0.35, 0.6],
|
||||
EntityMeta::ChestBoat(_) => [1.375, 0.5625, 1.375],
|
||||
EntityMeta::Frog(_) => [0.5, 0.5, 0.5],
|
||||
EntityMeta::Tadpole(_) => [0.4, 0.3, 0.4],
|
||||
EntityMeta::Warden(_) => [0.9, 2.9, 0.9],
|
||||
EntityMeta::AreaEffectCloud(e) => [
|
||||
let dims = match &self.data {
|
||||
EntityData::Allay(_) => [0.6, 0.35, 0.6],
|
||||
EntityData::ChestBoat(_) => [1.375, 0.5625, 1.375],
|
||||
EntityData::Frog(_) => [0.5, 0.5, 0.5],
|
||||
EntityData::Tadpole(_) => [0.4, 0.3, 0.4],
|
||||
EntityData::Warden(_) => [0.9, 2.9, 0.9],
|
||||
EntityData::AreaEffectCloud(e) => [
|
||||
e.get_radius() as f64 * 2.0,
|
||||
0.5,
|
||||
e.get_radius() as f64 * 2.0,
|
||||
],
|
||||
EntityMeta::ArmorStand(e) => {
|
||||
EntityData::ArmorStand(e) => {
|
||||
if e.get_marker() {
|
||||
[0.0, 0.0, 0.0]
|
||||
} else if e.get_small() {
|
||||
|
@ -346,123 +334,123 @@ impl Entity {
|
|||
[0.5, 1.975, 0.5]
|
||||
}
|
||||
}
|
||||
EntityMeta::Arrow(_) => [0.5, 0.5, 0.5],
|
||||
EntityMeta::Axolotl(_) => [1.3, 0.6, 1.3],
|
||||
EntityMeta::Bat(_) => [0.5, 0.9, 0.5],
|
||||
EntityMeta::Bee(_) => [0.7, 0.6, 0.7], // TODO: baby size?
|
||||
EntityMeta::Blaze(_) => [0.6, 1.8, 0.6],
|
||||
EntityMeta::Boat(_) => [1.375, 0.5625, 1.375],
|
||||
EntityMeta::Cat(_) => [0.6, 0.7, 0.6],
|
||||
EntityMeta::CaveSpider(_) => [0.7, 0.5, 0.7],
|
||||
EntityMeta::Chicken(_) => [0.4, 0.7, 0.4], // TODO: baby size?
|
||||
EntityMeta::Cod(_) => [0.5, 0.3, 0.5],
|
||||
EntityMeta::Cow(_) => [0.9, 1.4, 0.9], // TODO: baby size?
|
||||
EntityMeta::Creeper(_) => [0.6, 1.7, 0.6],
|
||||
EntityMeta::Dolphin(_) => [0.9, 0.6, 0.9],
|
||||
EntityMeta::Donkey(_) => [1.5, 1.39648, 1.5], // TODO: baby size?
|
||||
EntityMeta::DragonFireball(_) => [1.0, 1.0, 1.0],
|
||||
EntityMeta::Drowned(_) => [0.6, 1.95, 0.6], // TODO: baby size?
|
||||
EntityMeta::ElderGuardian(_) => [1.9975, 1.9975, 1.9975],
|
||||
EntityMeta::EndCrystal(_) => [2.0, 2.0, 2.0],
|
||||
EntityMeta::EnderDragon(_) => [16.0, 8.0, 16.0],
|
||||
EntityMeta::Enderman(_) => [0.6, 2.9, 0.6],
|
||||
EntityMeta::Endermite(_) => [0.4, 0.3, 0.4],
|
||||
EntityMeta::Evoker(_) => [0.6, 1.95, 0.6],
|
||||
EntityMeta::EvokerFangs(_) => [0.5, 0.8, 0.5],
|
||||
EntityMeta::ExperienceOrb(_) => [0.5, 0.5, 0.5],
|
||||
EntityMeta::EyeOfEnder(_) => [0.25, 0.25, 0.25],
|
||||
EntityMeta::FallingBlock(_) => [0.98, 0.98, 0.98],
|
||||
EntityMeta::FireworkRocket(_) => [0.25, 0.25, 0.25],
|
||||
EntityMeta::Fox(_) => [0.6, 0.7, 0.6], // TODO: baby size?
|
||||
EntityMeta::Ghast(_) => [4.0, 4.0, 4.0],
|
||||
EntityMeta::Giant(_) => [3.6, 12.0, 3.6],
|
||||
EntityMeta::GlowItemFrame(_) => todo!("account for rotation"),
|
||||
EntityMeta::GlowSquid(_) => [0.8, 0.8, 0.8],
|
||||
EntityMeta::Goat(_) => [1.3, 0.9, 1.3], // TODO: baby size?
|
||||
EntityMeta::Guardian(_) => [0.85, 0.85, 0.85],
|
||||
EntityMeta::Hoglin(_) => [1.39648, 1.4, 1.39648], // TODO: baby size?
|
||||
EntityMeta::Horse(_) => [1.39648, 1.6, 1.39648], // TODO: baby size?
|
||||
EntityMeta::Husk(_) => [0.6, 1.95, 0.6], // TODO: baby size?
|
||||
EntityMeta::Illusioner(_) => [0.6, 1.95, 0.6],
|
||||
EntityMeta::IronGolem(_) => [1.4, 2.7, 1.4],
|
||||
EntityMeta::Item(_) => [0.25, 0.25, 0.25],
|
||||
EntityMeta::ItemFrame(_) => todo!("account for rotation"),
|
||||
EntityMeta::Fireball(_) => [1.0, 1.0, 1.0],
|
||||
EntityMeta::LeashKnot(_) => [0.375, 0.5, 0.375],
|
||||
EntityMeta::LightningBolt(_) => [0.0, 0.0, 0.0],
|
||||
EntityMeta::Llama(_) => [0.9, 1.87, 0.9], // TODO: baby size?
|
||||
EntityMeta::LlamaSpit(_) => [0.25, 0.25, 0.25],
|
||||
EntityMeta::MagmaCube(e) => {
|
||||
EntityData::Arrow(_) => [0.5, 0.5, 0.5],
|
||||
EntityData::Axolotl(_) => [1.3, 0.6, 1.3],
|
||||
EntityData::Bat(_) => [0.5, 0.9, 0.5],
|
||||
EntityData::Bee(_) => [0.7, 0.6, 0.7], // TODO: baby size?
|
||||
EntityData::Blaze(_) => [0.6, 1.8, 0.6],
|
||||
EntityData::Boat(_) => [1.375, 0.5625, 1.375],
|
||||
EntityData::Cat(_) => [0.6, 0.7, 0.6],
|
||||
EntityData::CaveSpider(_) => [0.7, 0.5, 0.7],
|
||||
EntityData::Chicken(_) => [0.4, 0.7, 0.4], // TODO: baby size?
|
||||
EntityData::Cod(_) => [0.5, 0.3, 0.5],
|
||||
EntityData::Cow(_) => [0.9, 1.4, 0.9], // TODO: baby size?
|
||||
EntityData::Creeper(_) => [0.6, 1.7, 0.6],
|
||||
EntityData::Dolphin(_) => [0.9, 0.6, 0.9],
|
||||
EntityData::Donkey(_) => [1.5, 1.39648, 1.5], // TODO: baby size?
|
||||
EntityData::DragonFireball(_) => [1.0, 1.0, 1.0],
|
||||
EntityData::Drowned(_) => [0.6, 1.95, 0.6], // TODO: baby size?
|
||||
EntityData::ElderGuardian(_) => [1.9975, 1.9975, 1.9975],
|
||||
EntityData::EndCrystal(_) => [2.0, 2.0, 2.0],
|
||||
EntityData::EnderDragon(_) => [16.0, 8.0, 16.0],
|
||||
EntityData::Enderman(_) => [0.6, 2.9, 0.6],
|
||||
EntityData::Endermite(_) => [0.4, 0.3, 0.4],
|
||||
EntityData::Evoker(_) => [0.6, 1.95, 0.6],
|
||||
EntityData::EvokerFangs(_) => [0.5, 0.8, 0.5],
|
||||
EntityData::ExperienceOrb(_) => [0.5, 0.5, 0.5],
|
||||
EntityData::EyeOfEnder(_) => [0.25, 0.25, 0.25],
|
||||
EntityData::FallingBlock(_) => [0.98, 0.98, 0.98],
|
||||
EntityData::FireworkRocket(_) => [0.25, 0.25, 0.25],
|
||||
EntityData::Fox(_) => [0.6, 0.7, 0.6], // TODO: baby size?
|
||||
EntityData::Ghast(_) => [4.0, 4.0, 4.0],
|
||||
EntityData::Giant(_) => [3.6, 12.0, 3.6],
|
||||
EntityData::GlowItemFrame(_) => todo!("account for rotation"),
|
||||
EntityData::GlowSquid(_) => [0.8, 0.8, 0.8],
|
||||
EntityData::Goat(_) => [1.3, 0.9, 1.3], // TODO: baby size?
|
||||
EntityData::Guardian(_) => [0.85, 0.85, 0.85],
|
||||
EntityData::Hoglin(_) => [1.39648, 1.4, 1.39648], // TODO: baby size?
|
||||
EntityData::Horse(_) => [1.39648, 1.6, 1.39648], // TODO: baby size?
|
||||
EntityData::Husk(_) => [0.6, 1.95, 0.6], // TODO: baby size?
|
||||
EntityData::Illusioner(_) => [0.6, 1.95, 0.6],
|
||||
EntityData::IronGolem(_) => [1.4, 2.7, 1.4],
|
||||
EntityData::Item(_) => [0.25, 0.25, 0.25],
|
||||
EntityData::ItemFrame(_) => todo!("account for rotation"),
|
||||
EntityData::Fireball(_) => [1.0, 1.0, 1.0],
|
||||
EntityData::LeashKnot(_) => [0.375, 0.5, 0.375],
|
||||
EntityData::LightningBolt(_) => [0.0, 0.0, 0.0],
|
||||
EntityData::Llama(_) => [0.9, 1.87, 0.9], // TODO: baby size?
|
||||
EntityData::LlamaSpit(_) => [0.25, 0.25, 0.25],
|
||||
EntityData::MagmaCube(e) => {
|
||||
let s = e.get_size() as f64 * 0.51000005;
|
||||
[s, s, s]
|
||||
}
|
||||
EntityMeta::Marker(_) => [0.0, 0.0, 0.0],
|
||||
EntityMeta::Minecart(_) => [0.98, 0.7, 0.98],
|
||||
EntityMeta::ChestMinecart(_) => [0.98, 0.7, 0.98],
|
||||
EntityMeta::CommandBlockMinecart(_) => [0.98, 0.7, 0.98],
|
||||
EntityMeta::FurnaceMinecart(_) => [0.98, 0.7, 0.98],
|
||||
EntityMeta::HopperMinecart(_) => [0.98, 0.7, 0.98],
|
||||
EntityMeta::SpawnerMinecart(_) => [0.98, 0.7, 0.98],
|
||||
EntityMeta::TntMinecart(_) => [0.98, 0.7, 0.98],
|
||||
EntityMeta::Mule(_) => [1.39648, 1.6, 1.39648], // TODO: baby size?
|
||||
EntityMeta::Mooshroom(_) => [0.9, 1.4, 0.9], // TODO: baby size?
|
||||
EntityMeta::Ocelot(_) => [0.6, 0.7, 0.6], // TODO: baby size?
|
||||
EntityMeta::Painting(_) => todo!("account for rotation and type"),
|
||||
EntityMeta::Panda(_) => [0.6, 0.7, 0.6], // TODO: baby size?
|
||||
EntityMeta::Parrot(_) => [0.5, 0.9, 0.5],
|
||||
EntityMeta::Phantom(_) => [0.9, 0.5, 0.9],
|
||||
EntityMeta::Pig(_) => [0.9, 0.9, 0.9], // TODO: baby size?
|
||||
EntityMeta::Piglin(_) => [0.6, 1.95, 0.6], // TODO: baby size?
|
||||
EntityMeta::PiglinBrute(_) => [0.6, 1.95, 0.6],
|
||||
EntityMeta::Pillager(_) => [0.6, 1.95, 0.6],
|
||||
EntityMeta::PolarBear(_) => [1.4, 1.4, 1.4], // TODO: baby size?
|
||||
EntityMeta::Tnt(_) => [0.98, 0.98, 0.98],
|
||||
EntityMeta::Pufferfish(_) => [0.7, 0.7, 0.7],
|
||||
EntityMeta::Rabbit(_) => [0.4, 0.5, 0.4], // TODO: baby size?
|
||||
EntityMeta::Ravager(_) => [1.95, 2.2, 1.95],
|
||||
EntityMeta::Salmon(_) => [0.7, 0.4, 0.7],
|
||||
EntityMeta::Sheep(_) => [0.9, 1.3, 0.9], // TODO: baby size?
|
||||
EntityMeta::Shulker(_) => [1.0, 1.0, 1.0], // TODO: how is height calculated?
|
||||
EntityMeta::ShulkerBullet(_) => [0.3125, 0.3125, 0.3125],
|
||||
EntityMeta::Silverfish(_) => [0.4, 0.3, 0.4],
|
||||
EntityMeta::Skeleton(_) => [0.6, 1.99, 0.6],
|
||||
EntityMeta::SkeletonHorse(_) => [1.39648, 1.6, 1.39648], // TODO: baby size?
|
||||
EntityMeta::Slime(e) => {
|
||||
EntityData::Marker(_) => [0.0, 0.0, 0.0],
|
||||
EntityData::Minecart(_) => [0.98, 0.7, 0.98],
|
||||
EntityData::ChestMinecart(_) => [0.98, 0.7, 0.98],
|
||||
EntityData::CommandBlockMinecart(_) => [0.98, 0.7, 0.98],
|
||||
EntityData::FurnaceMinecart(_) => [0.98, 0.7, 0.98],
|
||||
EntityData::HopperMinecart(_) => [0.98, 0.7, 0.98],
|
||||
EntityData::SpawnerMinecart(_) => [0.98, 0.7, 0.98],
|
||||
EntityData::TntMinecart(_) => [0.98, 0.7, 0.98],
|
||||
EntityData::Mule(_) => [1.39648, 1.6, 1.39648], // TODO: baby size?
|
||||
EntityData::Mooshroom(_) => [0.9, 1.4, 0.9], // TODO: baby size?
|
||||
EntityData::Ocelot(_) => [0.6, 0.7, 0.6], // TODO: baby size?
|
||||
EntityData::Painting(_) => todo!("account for rotation and type"),
|
||||
EntityData::Panda(_) => [0.6, 0.7, 0.6], // TODO: baby size?
|
||||
EntityData::Parrot(_) => [0.5, 0.9, 0.5],
|
||||
EntityData::Phantom(_) => [0.9, 0.5, 0.9],
|
||||
EntityData::Pig(_) => [0.9, 0.9, 0.9], // TODO: baby size?
|
||||
EntityData::Piglin(_) => [0.6, 1.95, 0.6], // TODO: baby size?
|
||||
EntityData::PiglinBrute(_) => [0.6, 1.95, 0.6],
|
||||
EntityData::Pillager(_) => [0.6, 1.95, 0.6],
|
||||
EntityData::PolarBear(_) => [1.4, 1.4, 1.4], // TODO: baby size?
|
||||
EntityData::Tnt(_) => [0.98, 0.98, 0.98],
|
||||
EntityData::Pufferfish(_) => [0.7, 0.7, 0.7],
|
||||
EntityData::Rabbit(_) => [0.4, 0.5, 0.4], // TODO: baby size?
|
||||
EntityData::Ravager(_) => [1.95, 2.2, 1.95],
|
||||
EntityData::Salmon(_) => [0.7, 0.4, 0.7],
|
||||
EntityData::Sheep(_) => [0.9, 1.3, 0.9], // TODO: baby size?
|
||||
EntityData::Shulker(_) => [1.0, 1.0, 1.0], // TODO: how is height calculated?
|
||||
EntityData::ShulkerBullet(_) => [0.3125, 0.3125, 0.3125],
|
||||
EntityData::Silverfish(_) => [0.4, 0.3, 0.4],
|
||||
EntityData::Skeleton(_) => [0.6, 1.99, 0.6],
|
||||
EntityData::SkeletonHorse(_) => [1.39648, 1.6, 1.39648], // TODO: baby size?
|
||||
EntityData::Slime(e) => {
|
||||
let s = 0.51000005 * e.get_size() as f64;
|
||||
[s, s, s]
|
||||
}
|
||||
EntityMeta::SmallFireball(_) => [0.3125, 0.3125, 0.3125],
|
||||
EntityMeta::SnowGolem(_) => [0.7, 1.9, 0.7],
|
||||
EntityMeta::Snowball(_) => [0.25, 0.25, 0.25],
|
||||
EntityMeta::SpectralArrow(_) => [0.5, 0.5, 0.5],
|
||||
EntityMeta::Spider(_) => [1.4, 0.9, 1.4],
|
||||
EntityMeta::Squid(_) => [0.8, 0.8, 0.8],
|
||||
EntityMeta::Stray(_) => [0.6, 1.99, 0.6],
|
||||
EntityMeta::Strider(_) => [0.9, 1.7, 0.9], // TODO: baby size?
|
||||
EntityMeta::Egg(_) => [0.25, 0.25, 0.25],
|
||||
EntityMeta::EnderPearl(_) => [0.25, 0.25, 0.25],
|
||||
EntityMeta::ExperienceBottle(_) => [0.25, 0.25, 0.25],
|
||||
EntityMeta::Potion(_) => [0.25, 0.25, 0.25],
|
||||
EntityMeta::Trident(_) => [0.5, 0.5, 0.5],
|
||||
EntityMeta::TraderLlama(_) => [0.9, 1.87, 0.9],
|
||||
EntityMeta::TropicalFish(_) => [0.5, 0.4, 0.5],
|
||||
EntityMeta::Turtle(_) => [1.2, 0.4, 1.2], // TODO: baby size?
|
||||
EntityMeta::Vex(_) => [0.4, 0.8, 0.4],
|
||||
EntityMeta::Villager(_) => [0.6, 1.95, 0.6], // TODO: baby size?
|
||||
EntityMeta::Vindicator(_) => [0.6, 1.95, 0.6],
|
||||
EntityMeta::WanderingTrader(_) => [0.6, 1.95, 0.6],
|
||||
EntityMeta::Witch(_) => [0.6, 1.95, 0.6],
|
||||
EntityMeta::Wither(_) => [0.9, 3.5, 0.9],
|
||||
EntityMeta::WitherSkeleton(_) => [0.7, 2.4, 0.7],
|
||||
EntityMeta::WitherSkull(_) => [0.3125, 0.3125, 0.3125],
|
||||
EntityMeta::Wolf(_) => [0.6, 0.85, 0.6], // TODO: baby size?
|
||||
EntityMeta::Zoglin(_) => [1.39648, 1.4, 1.39648], // TODO: baby size?
|
||||
EntityMeta::Zombie(_) => [0.6, 1.95, 0.6], // TODO: baby size?
|
||||
EntityMeta::ZombieHorse(_) => [1.39648, 1.6, 1.39648], // TODO: baby size?
|
||||
EntityMeta::ZombieVillager(_) => [0.6, 1.95, 0.6], // TODO: baby size?
|
||||
EntityMeta::ZombifiedPiglin(_) => [0.6, 1.95, 0.6], // TODO: baby size?
|
||||
EntityMeta::Player(_) => [0.6, 1.8, 0.6], // TODO: changes depending on the pose.
|
||||
EntityMeta::FishingBobber(_) => [0.25, 0.25, 0.25],
|
||||
EntityData::SmallFireball(_) => [0.3125, 0.3125, 0.3125],
|
||||
EntityData::SnowGolem(_) => [0.7, 1.9, 0.7],
|
||||
EntityData::Snowball(_) => [0.25, 0.25, 0.25],
|
||||
EntityData::SpectralArrow(_) => [0.5, 0.5, 0.5],
|
||||
EntityData::Spider(_) => [1.4, 0.9, 1.4],
|
||||
EntityData::Squid(_) => [0.8, 0.8, 0.8],
|
||||
EntityData::Stray(_) => [0.6, 1.99, 0.6],
|
||||
EntityData::Strider(_) => [0.9, 1.7, 0.9], // TODO: baby size?
|
||||
EntityData::Egg(_) => [0.25, 0.25, 0.25],
|
||||
EntityData::EnderPearl(_) => [0.25, 0.25, 0.25],
|
||||
EntityData::ExperienceBottle(_) => [0.25, 0.25, 0.25],
|
||||
EntityData::Potion(_) => [0.25, 0.25, 0.25],
|
||||
EntityData::Trident(_) => [0.5, 0.5, 0.5],
|
||||
EntityData::TraderLlama(_) => [0.9, 1.87, 0.9],
|
||||
EntityData::TropicalFish(_) => [0.5, 0.4, 0.5],
|
||||
EntityData::Turtle(_) => [1.2, 0.4, 1.2], // TODO: baby size?
|
||||
EntityData::Vex(_) => [0.4, 0.8, 0.4],
|
||||
EntityData::Villager(_) => [0.6, 1.95, 0.6], // TODO: baby size?
|
||||
EntityData::Vindicator(_) => [0.6, 1.95, 0.6],
|
||||
EntityData::WanderingTrader(_) => [0.6, 1.95, 0.6],
|
||||
EntityData::Witch(_) => [0.6, 1.95, 0.6],
|
||||
EntityData::Wither(_) => [0.9, 3.5, 0.9],
|
||||
EntityData::WitherSkeleton(_) => [0.7, 2.4, 0.7],
|
||||
EntityData::WitherSkull(_) => [0.3125, 0.3125, 0.3125],
|
||||
EntityData::Wolf(_) => [0.6, 0.85, 0.6], // TODO: baby size?
|
||||
EntityData::Zoglin(_) => [1.39648, 1.4, 1.39648], // TODO: baby size?
|
||||
EntityData::Zombie(_) => [0.6, 1.95, 0.6], // TODO: baby size?
|
||||
EntityData::ZombieHorse(_) => [1.39648, 1.6, 1.39648], // TODO: baby size?
|
||||
EntityData::ZombieVillager(_) => [0.6, 1.95, 0.6], // TODO: baby size?
|
||||
EntityData::ZombifiedPiglin(_) => [0.6, 1.95, 0.6], // TODO: baby size?
|
||||
EntityData::Player(_) => [0.6, 1.8, 0.6], // TODO: changes depending on the pose.
|
||||
EntityData::FishingBobber(_) => [0.25, 0.25, 0.25],
|
||||
};
|
||||
|
||||
aabb_from_bottom_and_size(self.new_position, dims.into())
|
||||
|
@ -473,7 +461,7 @@ impl Entity {
|
|||
///
|
||||
/// Is `None` if there is no initial metadata.
|
||||
pub(crate) fn initial_metadata_packet(&self, this_id: EntityId) -> Option<SetEntityMetadata> {
|
||||
self.meta.initial_metadata().map(|meta| SetEntityMetadata {
|
||||
self.data.initial_metadata().map(|meta| SetEntityMetadata {
|
||||
entity_id: VarInt(this_id.to_network_id()),
|
||||
metadata: RawBytes(meta),
|
||||
})
|
||||
|
@ -483,23 +471,23 @@ impl Entity {
|
|||
///
|
||||
/// Is `None` if this entity's metadata has not been modified.
|
||||
pub(crate) fn updated_metadata_packet(&self, this_id: EntityId) -> Option<SetEntityMetadata> {
|
||||
self.meta.updated_metadata().map(|meta| SetEntityMetadata {
|
||||
self.data.updated_metadata().map(|meta| SetEntityMetadata {
|
||||
entity_id: VarInt(this_id.to_network_id()),
|
||||
metadata: RawBytes(meta),
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn spawn_packet(&self, this_id: EntityId) -> Option<EntitySpawnPacket> {
|
||||
match &self.meta {
|
||||
EntityMeta::Marker(_) => None,
|
||||
EntityMeta::ExperienceOrb(_) => {
|
||||
match &self.data {
|
||||
EntityData::Marker(_) => None,
|
||||
EntityData::ExperienceOrb(_) => {
|
||||
Some(EntitySpawnPacket::SpawnExperienceOrb(AddExperienceOrb {
|
||||
entity_id: VarInt(this_id.to_network_id()),
|
||||
position: self.new_position,
|
||||
count: 0, // TODO
|
||||
}))
|
||||
}
|
||||
EntityMeta::Player(_) => Some(EntitySpawnPacket::SpawnPlayer(AddPlayer {
|
||||
EntityData::Player(_) => Some(EntitySpawnPacket::SpawnPlayer(AddPlayer {
|
||||
entity_id: VarInt(this_id.to_network_id()),
|
||||
player_uuid: self.uuid,
|
||||
position: self.new_position,
|
||||
|
|
|
@ -272,6 +272,16 @@ impl Decode for Box<str> {
|
|||
#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
|
||||
pub struct BoundedInt<T, const MIN: i64, const MAX: i64>(pub T);
|
||||
|
||||
impl<T, const MIN: i64, const MAX: i64> BoundedInt<T, MIN, MAX> {
|
||||
pub const fn min_bound(&self) -> i64 {
|
||||
MIN
|
||||
}
|
||||
|
||||
pub const fn max_bound(&self) -> i64 {
|
||||
MAX
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, const MIN: i64, const MAX: i64> From<T> for BoundedInt<T, MIN, MAX> {
|
||||
fn from(t: T) -> Self {
|
||||
Self(t)
|
||||
|
@ -334,6 +344,16 @@ impl Decode for String {
|
|||
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Default, Hash, Debug)]
|
||||
pub struct BoundedString<const MIN: usize, const MAX: usize>(pub String);
|
||||
|
||||
impl<const MIN: usize, const MAX: usize> BoundedString<MIN, MAX> {
|
||||
pub const fn min_bound(&self) -> usize {
|
||||
MIN
|
||||
}
|
||||
|
||||
pub const fn max_bound(&self) -> usize {
|
||||
MAX
|
||||
}
|
||||
}
|
||||
|
||||
impl<const MIN: usize, const MAX: usize> Encode for BoundedString<MIN, MAX> {
|
||||
fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> {
|
||||
encode_string_bounded(&self.0, MIN, MAX, w)
|
||||
|
|
|
@ -619,18 +619,7 @@ pub mod play {
|
|||
def_struct! {
|
||||
Animate 0x03 {
|
||||
entity_id: VarInt,
|
||||
animation: Animation,
|
||||
}
|
||||
}
|
||||
|
||||
def_enum! {
|
||||
Animation: u8 {
|
||||
SwingMainArm = 0,
|
||||
TakeDamage = 1,
|
||||
LeaveBed = 2,
|
||||
SwingOffhand = 3,
|
||||
CriticalEffect = 4,
|
||||
MagicCriticalEffect = 5,
|
||||
animation: BoundedInt<u8, 0, 5>,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -741,78 +730,12 @@ pub mod play {
|
|||
}
|
||||
}
|
||||
|
||||
def_struct! {
|
||||
DoEntityEvent 0x18 {
|
||||
entity_id: i32,
|
||||
entity_status: EntityEvent,
|
||||
}
|
||||
}
|
||||
pub const ENTITY_EVENT_MAX_BOUND: i64 = 62;
|
||||
|
||||
def_enum! {
|
||||
#[derive(Copy, PartialEq, Eq)]
|
||||
EntityEvent: u8 {
|
||||
Jump = 1,
|
||||
Hurt = 2,
|
||||
Death = 3,
|
||||
StartAttacking = 4,
|
||||
StopAttacking = 5,
|
||||
TamingFailed = 6,
|
||||
TamingSucceeded = 7,
|
||||
ShakeWetness = 8,
|
||||
UseItemComplete = 9,
|
||||
EatGrass = 10,
|
||||
OfferFlower = 11,
|
||||
LoveHearts = 12,
|
||||
VillagerAngry = 13,
|
||||
VillagerHappy = 14,
|
||||
WitchHatMagic = 15,
|
||||
ZombieConverting = 16,
|
||||
FireworksExplode = 17,
|
||||
InLoveHearts = 18,
|
||||
SquidAnimSynch = 19,
|
||||
SilverfishMergeAnim = 20,
|
||||
GuardianAttackSound = 21,
|
||||
ReducedDebugInfo = 22,
|
||||
FullDebugInfo = 23,
|
||||
PermissionLevelAll = 24,
|
||||
PermissionLevelModerators = 25,
|
||||
PermissionLevelGamemasters = 26,
|
||||
PermissionLevelAdmins = 27,
|
||||
PermissionLevelOwners = 28,
|
||||
AttackBlocked = 29,
|
||||
ShieldDisabled = 30,
|
||||
FishingRodReelIn = 31,
|
||||
ArmorstandWobble = 32,
|
||||
Thorned = 33,
|
||||
StopOfferFlower = 34,
|
||||
TalismanActivate = 35,
|
||||
Drowned = 36,
|
||||
Burned = 37,
|
||||
DolphinLookingForTreasure = 38,
|
||||
RavagerStunned = 39,
|
||||
TrustingFailed = 40,
|
||||
TrustingSucceeded = 41,
|
||||
VillagerSweat = 42,
|
||||
BadOmenTriggered = 43,
|
||||
Poked = 44,
|
||||
FoxEat = 45,
|
||||
Teleport = 46,
|
||||
MainhandBreak = 47,
|
||||
OffhandBreak = 48,
|
||||
HeadBreak = 49,
|
||||
ChestBreak = 50,
|
||||
LegsBreak = 51,
|
||||
FeetBreak = 52,
|
||||
HoneySlide = 53,
|
||||
HoneyJump = 54,
|
||||
SwapHands = 55,
|
||||
CancelShakeWetness = 56,
|
||||
Frozen = 57,
|
||||
StartRam = 58,
|
||||
EndRam = 59,
|
||||
Poof = 60,
|
||||
TendrilsShiver = 61,
|
||||
SonicCharge = 62,
|
||||
def_struct! {
|
||||
EntityEvent 0x18 {
|
||||
entity_id: i32,
|
||||
entity_status: BoundedInt<u8, 1, ENTITY_EVENT_MAX_BOUND>,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1294,7 +1217,7 @@ pub mod play {
|
|||
BlockUpdate,
|
||||
BossEvent,
|
||||
Disconnect,
|
||||
DoEntityEvent,
|
||||
EntityEvent,
|
||||
ForgetLevelChunk,
|
||||
GameEvent,
|
||||
KeepAlive,
|
||||
|
|
Loading…
Reference in a new issue