mirror of
https://github.com/italicsjenga/valence.git
synced 2024-12-23 14:31:30 +11:00
Rewrite the entity generator
This commit is contained in:
parent
f97c67d42a
commit
2e22946ffc
|
@ -7,9 +7,9 @@ use proc_macro2::TokenStream;
|
|||
use quote::quote;
|
||||
use serde::Deserialize;
|
||||
|
||||
use crate::{ident, write_to_out_path};
|
||||
use crate::ident;
|
||||
|
||||
pub fn build() -> anyhow::Result<()> {
|
||||
pub fn build() -> anyhow::Result<TokenStream> {
|
||||
let blocks = parse_blocks_json()?;
|
||||
|
||||
let max_block_state = blocks.iter().map(|b| b.max_state_id).max().unwrap();
|
||||
|
@ -297,7 +297,7 @@ pub fn build() -> anyhow::Result<()> {
|
|||
|
||||
let property_name_count = prop_values.len();
|
||||
|
||||
let finished = quote! {
|
||||
Ok(quote! {
|
||||
/// Represents the state of a block, not including block entity data such as
|
||||
/// the text on a sign, the design on a banner, or the content of a spawner.
|
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default, Hash)]
|
||||
|
@ -551,9 +551,7 @@ pub fn build() -> anyhow::Result<()> {
|
|||
Self::from_bool(b)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
write_to_out_path("block.rs", &finished.to_string())
|
||||
})
|
||||
}
|
||||
|
||||
struct Block {
|
||||
|
|
2831
build/entity.rs
2831
build/entity.rs
File diff suppressed because it is too large
Load diff
66
build/entity_event.rs
Normal file
66
build/entity_event.rs
Normal file
|
@ -0,0 +1,66 @@
|
|||
use std::collections::BTreeMap;
|
||||
|
||||
use heck::ToPascalCase;
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::quote;
|
||||
use serde::Deserialize;
|
||||
|
||||
use crate::ident;
|
||||
|
||||
#[derive(Deserialize, Clone, Debug)]
|
||||
struct EntityData {
|
||||
statuses: BTreeMap<String, u8>,
|
||||
animations: BTreeMap<String, u8>,
|
||||
}
|
||||
|
||||
pub fn build() -> anyhow::Result<TokenStream> {
|
||||
let entity_data: EntityData =
|
||||
serde_json::from_str(include_str!("../extracted/entity_data.json"))?;
|
||||
|
||||
let mut statuses: Vec<_> = entity_data.statuses.into_iter().collect();
|
||||
statuses.sort_by_key(|(_, id)| *id);
|
||||
|
||||
let mut animations: Vec<_> = entity_data.animations.into_iter().collect();
|
||||
animations.sort_by_key(|(_, id)| *id);
|
||||
|
||||
let event_variants = statuses
|
||||
.iter()
|
||||
.chain(animations.iter())
|
||||
.map(|(name, _)| ident(name.to_pascal_case()));
|
||||
|
||||
let status_arms = statuses.iter().map(|(name, code)| {
|
||||
let name = ident(name.to_pascal_case());
|
||||
quote! {
|
||||
Self::#name => StatusOrAnimation::Status(#code),
|
||||
}
|
||||
});
|
||||
|
||||
let animation_arms = animations.iter().map(|(name, code)| {
|
||||
let name = ident(name.to_pascal_case());
|
||||
quote! {
|
||||
Self::#name => StatusOrAnimation::Animation(#code),
|
||||
}
|
||||
});
|
||||
|
||||
Ok(quote! {
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
|
||||
pub enum Event {
|
||||
#(#event_variants,)*
|
||||
}
|
||||
|
||||
impl Event {
|
||||
pub(crate) fn status_or_animation(self) -> StatusOrAnimation {
|
||||
match self {
|
||||
#(#status_arms)*
|
||||
#(#animation_arms)*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||
pub(crate) enum StatusOrAnimation {
|
||||
Status(u8),
|
||||
Animation(u8),
|
||||
}
|
||||
})
|
||||
}
|
|
@ -7,35 +7,38 @@ use proc_macro2::{Ident, Span};
|
|||
|
||||
mod block;
|
||||
mod entity;
|
||||
mod entity_event;
|
||||
|
||||
pub fn main() -> anyhow::Result<()> {
|
||||
for file in ["blocks.json", "entities.json"] {
|
||||
println!("cargo:rerun-if-changed=data/{file}");
|
||||
}
|
||||
let generators = [
|
||||
(entity::build as fn() -> _, "entity.rs"),
|
||||
(entity_event::build, "entity_event.rs"),
|
||||
(block::build, "block.rs"),
|
||||
];
|
||||
|
||||
block::build()?;
|
||||
entity::build()?;
|
||||
let out_dir = env::var_os("OUT_DIR").context("can't get OUT_DIR env var")?;
|
||||
|
||||
for (g, file_name) in generators {
|
||||
println!("cargo:rerun-if-changed=extracted/{file_name}");
|
||||
|
||||
let path = Path::new(&out_dir).join(file_name);
|
||||
let code = g()?.to_string();
|
||||
fs::write(&path, &code)?;
|
||||
|
||||
// Format the output for debugging purposes.
|
||||
// Doesn't matter if rustfmt is unavailable.
|
||||
let _ = Command::new("rustfmt").arg(path).output();
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn ident(s: impl AsRef<str>) -> Ident {
|
||||
let s = s.as_ref().trim();
|
||||
if s.starts_with(char::is_numeric) {
|
||||
Ident::new(&format!("_{s}"), Span::call_site())
|
||||
} else {
|
||||
Ident::new(s, Span::call_site())
|
||||
|
||||
match s.as_bytes() {
|
||||
// TODO: check for the other rust keywords.
|
||||
[b'0'..=b'9', ..] | b"type" => Ident::new(&format!("_{s}"), Span::call_site()),
|
||||
_ => Ident::new(s, Span::call_site()),
|
||||
}
|
||||
}
|
||||
|
||||
fn write_to_out_path(file_name: impl AsRef<str>, content: impl AsRef<str>) -> anyhow::Result<()> {
|
||||
let out_dir = env::var_os("OUT_DIR").context("can't get OUT_DIR env var")?;
|
||||
let path = Path::new(&out_dir).join(file_name.as_ref());
|
||||
|
||||
fs::write(&path, &content.as_ref())?;
|
||||
|
||||
// Format the output for debugging purposes.
|
||||
// Doesn't matter if rustfmt is unavailable.
|
||||
let _ = Command::new("rustfmt").arg(path).output();
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -3,12 +3,11 @@ use std::sync::atomic::{AtomicUsize, Ordering};
|
|||
|
||||
use log::LevelFilter;
|
||||
use valence::block::{BlockPos, BlockState};
|
||||
use valence::client::Event::{self};
|
||||
use valence::client::{ClientId, GameMode, Hand, InteractWithEntityKind};
|
||||
use valence::client::{ClientId, Event, GameMode, Hand, InteractWithEntityKind};
|
||||
use valence::config::{Config, ServerListPing};
|
||||
use valence::dimension::DimensionId;
|
||||
use valence::entity::state::Pose;
|
||||
use valence::entity::{EntityId, EntityKind, EntityState};
|
||||
use valence::entity::data::Pose;
|
||||
use valence::entity::{EntityEnum, EntityId, EntityKind, Event as EntityEvent};
|
||||
use valence::server::{Server, SharedServer, ShutdownResult};
|
||||
use valence::text::{Color, TextFormat};
|
||||
use valence::{async_trait, Ticks};
|
||||
|
@ -37,7 +36,7 @@ struct ClientData {
|
|||
/// The client's player entity.
|
||||
player: EntityId,
|
||||
/// The extra knockback on the first hit while sprinting.
|
||||
has_extra_knockback: bool,
|
||||
extra_knockback: bool,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
|
@ -67,7 +66,6 @@ impl Config for Game {
|
|||
}
|
||||
|
||||
fn online_mode(&self) -> bool {
|
||||
// You'll want this to be true on real servers.
|
||||
false
|
||||
}
|
||||
|
||||
|
@ -160,7 +158,7 @@ impl Config for Game {
|
|||
.unwrap();
|
||||
|
||||
client.data.player = player_id;
|
||||
client.data.has_extra_knockback = true;
|
||||
client.data.extra_knockback = true;
|
||||
|
||||
player.data.client = client_id;
|
||||
player.data.last_attack_time = 0;
|
||||
|
@ -181,7 +179,7 @@ impl Config for Game {
|
|||
while let Some(event) = client.pop_event() {
|
||||
match event {
|
||||
Event::StartSprinting => {
|
||||
client.data.has_extra_knockback = true;
|
||||
client.data.extra_knockback = true;
|
||||
}
|
||||
Event::InteractWithEntity {
|
||||
id,
|
||||
|
@ -195,21 +193,18 @@ impl Config for Game {
|
|||
{
|
||||
target.data.attacked = true;
|
||||
target.data.attacker_pos = client.position();
|
||||
target.data.extra_knockback = client.data.has_extra_knockback;
|
||||
target.data.extra_knockback = client.data.extra_knockback;
|
||||
target.data.last_attack_time = current_tick;
|
||||
|
||||
client.data.has_extra_knockback = false;
|
||||
client.data.extra_knockback = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Event::ArmSwing(hand) => {
|
||||
let player = server.entities.get_mut(client.data.player).unwrap();
|
||||
|
||||
if let EntityState::Player(e) = &mut player.state {
|
||||
match hand {
|
||||
Hand::Main => e.trigger_swing_main_arm(),
|
||||
Hand::Off => e.trigger_swing_offhand(),
|
||||
}
|
||||
Hand::Main => player.trigger_event(EntityEvent::SwingMainHand),
|
||||
Hand::Off => player.trigger_event(EntityEvent::SwingOffHand),
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
|
@ -237,7 +232,7 @@ impl Config for Game {
|
|||
player.set_pitch(client.pitch());
|
||||
player.set_on_ground(client.on_ground());
|
||||
|
||||
if let EntityState::Player(player) = &mut player.state {
|
||||
if let EntityEnum::Player(player) = player.view_mut() {
|
||||
if client.is_sneaking() {
|
||||
player.set_pose(Pose::Sneaking);
|
||||
} else {
|
||||
|
@ -266,12 +261,10 @@ impl Config for Game {
|
|||
|
||||
victim.set_velocity(victim.velocity() / 2.0 + vel.as_());
|
||||
|
||||
if let EntityState::Player(e) = &mut e.state {
|
||||
e.trigger_take_damage();
|
||||
e.trigger_hurt();
|
||||
}
|
||||
victim.player_mut().trigger_take_damage();
|
||||
victim.player_mut().trigger_hurt();
|
||||
e.trigger_event(EntityEvent::DamageFromGenericSource);
|
||||
e.trigger_event(EntityEvent::Damage);
|
||||
victim.trigger_entity_event(EntityEvent::DamageFromGenericSource);
|
||||
victim.trigger_entity_event(EntityEvent::Damage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,8 +10,8 @@ use valence::block::BlockState;
|
|||
use valence::client::{Event, Hand};
|
||||
use valence::config::{Config, ServerListPing};
|
||||
use valence::dimension::{Dimension, DimensionId};
|
||||
use valence::entity::state::Pose;
|
||||
use valence::entity::{EntityId, EntityKind, EntityState};
|
||||
use valence::entity::data::Pose;
|
||||
use valence::entity::{EntityEnum, EntityId, EntityKind, Event as EntityEvent};
|
||||
use valence::server::{Server, SharedServer, ShutdownResult};
|
||||
use valence::text::{Color, TextFormat};
|
||||
use valence::{async_trait, ident};
|
||||
|
@ -179,14 +179,10 @@ impl Config for Game {
|
|||
true;
|
||||
}
|
||||
}
|
||||
Event::ArmSwing(hand) => {
|
||||
if let EntityState::Player(e) = &mut player.state {
|
||||
match hand {
|
||||
Hand::Main => e.trigger_swing_main_arm(),
|
||||
Hand::Off => e.trigger_swing_offhand(),
|
||||
}
|
||||
}
|
||||
}
|
||||
Event::ArmSwing(hand) => match hand {
|
||||
Hand::Main => player.trigger_event(EntityEvent::SwingMainHand),
|
||||
Hand::Off => player.trigger_event(EntityEvent::SwingOffHand),
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
@ -198,7 +194,7 @@ impl Config for Game {
|
|||
player.set_pitch(client.pitch());
|
||||
player.set_on_ground(client.on_ground());
|
||||
|
||||
if let EntityState::Player(player) = &mut player.state {
|
||||
if let EntityEnum::Player(player) = player.view_mut() {
|
||||
if client.is_sneaking() {
|
||||
player.set_pose(Pose::Sneaking);
|
||||
} else {
|
||||
|
|
|
@ -7,7 +7,7 @@ use valence::block::{BlockPos, BlockState};
|
|||
use valence::client::GameMode;
|
||||
use valence::config::{Config, ServerListPing};
|
||||
use valence::dimension::DimensionId;
|
||||
use valence::entity::{EntityKind, EntityState};
|
||||
use valence::entity::{EntityEnum, EntityKind};
|
||||
use valence::server::{Server, SharedServer, ShutdownResult};
|
||||
use valence::spatial_index::RaycastHit;
|
||||
use valence::text::{Color, TextFormat};
|
||||
|
@ -166,11 +166,12 @@ impl Config for Game {
|
|||
});
|
||||
|
||||
for (_, e) in server.entities.iter_mut() {
|
||||
if let EntityState::Sheep(sheep) = &mut e.state {
|
||||
if e.data {
|
||||
sheep.set_sheep_state(5);
|
||||
let intersected = e.data;
|
||||
if let EntityEnum::Sheep(sheep) = &mut e.view_mut() {
|
||||
if intersected {
|
||||
sheep.set_color(5);
|
||||
} else {
|
||||
sheep.set_sheep_state(0);
|
||||
sheep.set_color(0);
|
||||
}
|
||||
}
|
||||
e.data = false;
|
||||
|
|
|
@ -117,10 +117,8 @@ impl Config for Game {
|
|||
);
|
||||
|
||||
client.send_message("Welcome to the terrain example!".italic());
|
||||
client.send_message(
|
||||
"This demonstrates how to create infinite procedurally generated terrain."
|
||||
.italic(),
|
||||
);
|
||||
client
|
||||
.send_message("Explore this infinite procedurally generated terrain.".italic());
|
||||
}
|
||||
|
||||
if client.is_disconnected() {
|
||||
|
|
2436
extracted/entities.json
Normal file
2436
extracted/entities.json
Normal file
File diff suppressed because it is too large
Load diff
509
extracted/entity_data.json
Normal file
509
extracted/entity_data.json
Normal file
|
@ -0,0 +1,509 @@
|
|||
{
|
||||
"types": {
|
||||
"allay": 0,
|
||||
"area_effect_cloud": 1,
|
||||
"armor_stand": 2,
|
||||
"arrow": 3,
|
||||
"axolotl": 4,
|
||||
"bat": 5,
|
||||
"bee": 6,
|
||||
"blaze": 7,
|
||||
"boat": 8,
|
||||
"chest_boat": 9,
|
||||
"cat": 10,
|
||||
"cave_spider": 11,
|
||||
"chicken": 12,
|
||||
"cod": 13,
|
||||
"cow": 14,
|
||||
"creeper": 15,
|
||||
"dolphin": 16,
|
||||
"donkey": 17,
|
||||
"dragon_fireball": 18,
|
||||
"drowned": 19,
|
||||
"elder_guardian": 20,
|
||||
"end_crystal": 21,
|
||||
"ender_dragon": 22,
|
||||
"enderman": 23,
|
||||
"endermite": 24,
|
||||
"evoker": 25,
|
||||
"evoker_fangs": 26,
|
||||
"experience_orb": 27,
|
||||
"eye_of_ender": 28,
|
||||
"falling_block": 29,
|
||||
"firework_rocket": 30,
|
||||
"fox": 31,
|
||||
"frog": 32,
|
||||
"ghast": 33,
|
||||
"giant": 34,
|
||||
"glow_item_frame": 35,
|
||||
"glow_squid": 36,
|
||||
"goat": 37,
|
||||
"guardian": 38,
|
||||
"hoglin": 39,
|
||||
"horse": 40,
|
||||
"husk": 41,
|
||||
"illusioner": 42,
|
||||
"iron_golem": 43,
|
||||
"item": 44,
|
||||
"item_frame": 45,
|
||||
"fireball": 46,
|
||||
"leash_knot": 47,
|
||||
"lightning_bolt": 48,
|
||||
"llama": 49,
|
||||
"llama_spit": 50,
|
||||
"magma_cube": 51,
|
||||
"marker": 52,
|
||||
"minecart": 53,
|
||||
"chest_minecart": 54,
|
||||
"command_block_minecart": 55,
|
||||
"furnace_minecart": 56,
|
||||
"hopper_minecart": 57,
|
||||
"spawner_minecart": 58,
|
||||
"tnt_minecart": 59,
|
||||
"mule": 60,
|
||||
"mooshroom": 61,
|
||||
"ocelot": 62,
|
||||
"painting": 63,
|
||||
"panda": 64,
|
||||
"parrot": 65,
|
||||
"phantom": 66,
|
||||
"pig": 67,
|
||||
"piglin": 68,
|
||||
"piglin_brute": 69,
|
||||
"pillager": 70,
|
||||
"polar_bear": 71,
|
||||
"tnt": 72,
|
||||
"pufferfish": 73,
|
||||
"rabbit": 74,
|
||||
"ravager": 75,
|
||||
"salmon": 76,
|
||||
"sheep": 77,
|
||||
"shulker": 78,
|
||||
"shulker_bullet": 79,
|
||||
"silverfish": 80,
|
||||
"skeleton": 81,
|
||||
"skeleton_horse": 82,
|
||||
"slime": 83,
|
||||
"small_fireball": 84,
|
||||
"snow_golem": 85,
|
||||
"snowball": 86,
|
||||
"spectral_arrow": 87,
|
||||
"spider": 88,
|
||||
"squid": 89,
|
||||
"stray": 90,
|
||||
"strider": 91,
|
||||
"tadpole": 92,
|
||||
"egg": 93,
|
||||
"ender_pearl": 94,
|
||||
"experience_bottle": 95,
|
||||
"potion": 96,
|
||||
"trident": 97,
|
||||
"trader_llama": 98,
|
||||
"tropical_fish": 99,
|
||||
"turtle": 100,
|
||||
"vex": 101,
|
||||
"villager": 102,
|
||||
"vindicator": 103,
|
||||
"wandering_trader": 104,
|
||||
"warden": 105,
|
||||
"witch": 106,
|
||||
"wither": 107,
|
||||
"wither_skeleton": 108,
|
||||
"wither_skull": 109,
|
||||
"wolf": 110,
|
||||
"zoglin": 111,
|
||||
"zombie": 112,
|
||||
"zombie_horse": 113,
|
||||
"zombie_villager": 114,
|
||||
"zombified_piglin": 115,
|
||||
"player": 116,
|
||||
"fishing_bobber": 117
|
||||
},
|
||||
"statuses": {
|
||||
"add_sprinting_particles_or_reset_spawner_minecart_spawn_delay": 1,
|
||||
"damage_from_generic_source": 2,
|
||||
"play_death_sound_or_add_projectile_hit_particles": 3,
|
||||
"play_attack_sound": 4,
|
||||
"stop_attack": 5,
|
||||
"add_negative_player_reaction_particles": 6,
|
||||
"add_positive_player_reaction_particles": 7,
|
||||
"shake_off_water": 8,
|
||||
"consume_item": 9,
|
||||
"set_sheep_eat_grass_timer_or_prime_tnt_minecart": 10,
|
||||
"look_at_villager": 11,
|
||||
"add_villager_heart_particles": 12,
|
||||
"add_villager_angry_particles": 13,
|
||||
"add_villager_happy_particles": 14,
|
||||
"add_witch_particles": 15,
|
||||
"play_cure_zombie_villager_sound": 16,
|
||||
"explode_firework_client": 17,
|
||||
"add_breeding_particles": 18,
|
||||
"reset_squid_thrust_timer": 19,
|
||||
"play_spawn_effects": 20,
|
||||
"play_guardian_attack_sound": 21,
|
||||
"use_reduced_debug_info": 22,
|
||||
"use_full_debug_info": 23,
|
||||
"set_op_level_0": 24,
|
||||
"set_op_level_1": 25,
|
||||
"set_op_level_2": 26,
|
||||
"set_op_level_3": 27,
|
||||
"set_op_level_4": 28,
|
||||
"block_with_shield": 29,
|
||||
"break_shield": 30,
|
||||
"pull_hooked_entity": 31,
|
||||
"hit_armor_stand": 32,
|
||||
"damage_from_thorns": 33,
|
||||
"stop_looking_at_villager": 34,
|
||||
"use_totem_of_undying": 35,
|
||||
"damage_from_drowning": 36,
|
||||
"damage_from_fire": 37,
|
||||
"add_dolphin_happy_villager_particles": 38,
|
||||
"stun_ravager": 39,
|
||||
"tame_ocelot_failed": 40,
|
||||
"tame_ocelot_success": 41,
|
||||
"add_splash_particles": 42,
|
||||
"add_cloud_particles": 43,
|
||||
"damage_from_berry_bush": 44,
|
||||
"create_eating_particles": 45,
|
||||
"add_portal_particles": 46,
|
||||
"break_mainhand": 47,
|
||||
"break_offhand": 48,
|
||||
"break_head": 49,
|
||||
"break_chest": 50,
|
||||
"break_legs": 51,
|
||||
"break_feet": 52,
|
||||
"drip_honey": 53,
|
||||
"drip_rich_honey": 54,
|
||||
"swap_hands": 55,
|
||||
"reset_wolf_shake": 56,
|
||||
"damage_from_freezing": 57,
|
||||
"prepare_ram": 58,
|
||||
"finish_ram": 59,
|
||||
"add_death_particles": 60,
|
||||
"ears_twitch": 61,
|
||||
"sonic_boom": 62
|
||||
},
|
||||
"animations": {
|
||||
"swing_main_hand": 0,
|
||||
"damage": 1,
|
||||
"wake_up": 2,
|
||||
"swing_off_hand": 3,
|
||||
"crit": 4,
|
||||
"enchanted_hit": 5
|
||||
},
|
||||
"villager_types": {
|
||||
"desert": 0,
|
||||
"jungle": 1,
|
||||
"plains": 2,
|
||||
"savanna": 3,
|
||||
"snow": 4,
|
||||
"swamp": 5,
|
||||
"taiga": 6
|
||||
},
|
||||
"villager_professions": {
|
||||
"none": 0,
|
||||
"armorer": 1,
|
||||
"butcher": 2,
|
||||
"cartographer": 3,
|
||||
"cleric": 4,
|
||||
"farmer": 5,
|
||||
"fisherman": 6,
|
||||
"fletcher": 7,
|
||||
"leatherworker": 8,
|
||||
"librarian": 9,
|
||||
"mason": 10,
|
||||
"nitwit": 11,
|
||||
"shepherd": 12,
|
||||
"toolsmith": 13,
|
||||
"weaponsmith": 14
|
||||
},
|
||||
"cat_variants": {
|
||||
"tabby": 0,
|
||||
"black": 1,
|
||||
"red": 2,
|
||||
"siamese": 3,
|
||||
"british_shorthair": 4,
|
||||
"calico": 5,
|
||||
"persian": 6,
|
||||
"ragdoll": 7,
|
||||
"white": 8,
|
||||
"jellie": 9,
|
||||
"all_black": 10
|
||||
},
|
||||
"frog_variants": {
|
||||
"temperate": 0,
|
||||
"warm": 1,
|
||||
"cold": 2
|
||||
},
|
||||
"painting_variants": {
|
||||
"kebab": {
|
||||
"id": 0,
|
||||
"width": 16,
|
||||
"height": 16
|
||||
},
|
||||
"aztec": {
|
||||
"id": 1,
|
||||
"width": 16,
|
||||
"height": 16
|
||||
},
|
||||
"alban": {
|
||||
"id": 2,
|
||||
"width": 16,
|
||||
"height": 16
|
||||
},
|
||||
"aztec2": {
|
||||
"id": 3,
|
||||
"width": 16,
|
||||
"height": 16
|
||||
},
|
||||
"bomb": {
|
||||
"id": 4,
|
||||
"width": 16,
|
||||
"height": 16
|
||||
},
|
||||
"plant": {
|
||||
"id": 5,
|
||||
"width": 16,
|
||||
"height": 16
|
||||
},
|
||||
"wasteland": {
|
||||
"id": 6,
|
||||
"width": 16,
|
||||
"height": 16
|
||||
},
|
||||
"pool": {
|
||||
"id": 7,
|
||||
"width": 32,
|
||||
"height": 16
|
||||
},
|
||||
"courbet": {
|
||||
"id": 8,
|
||||
"width": 32,
|
||||
"height": 16
|
||||
},
|
||||
"sea": {
|
||||
"id": 9,
|
||||
"width": 32,
|
||||
"height": 16
|
||||
},
|
||||
"sunset": {
|
||||
"id": 10,
|
||||
"width": 32,
|
||||
"height": 16
|
||||
},
|
||||
"creebet": {
|
||||
"id": 11,
|
||||
"width": 32,
|
||||
"height": 16
|
||||
},
|
||||
"wanderer": {
|
||||
"id": 12,
|
||||
"width": 16,
|
||||
"height": 32
|
||||
},
|
||||
"graham": {
|
||||
"id": 13,
|
||||
"width": 16,
|
||||
"height": 32
|
||||
},
|
||||
"match": {
|
||||
"id": 14,
|
||||
"width": 32,
|
||||
"height": 32
|
||||
},
|
||||
"bust": {
|
||||
"id": 15,
|
||||
"width": 32,
|
||||
"height": 32
|
||||
},
|
||||
"stage": {
|
||||
"id": 16,
|
||||
"width": 32,
|
||||
"height": 32
|
||||
},
|
||||
"void": {
|
||||
"id": 17,
|
||||
"width": 32,
|
||||
"height": 32
|
||||
},
|
||||
"skull_and_roses": {
|
||||
"id": 18,
|
||||
"width": 32,
|
||||
"height": 32
|
||||
},
|
||||
"wither": {
|
||||
"id": 19,
|
||||
"width": 32,
|
||||
"height": 32
|
||||
},
|
||||
"fighters": {
|
||||
"id": 20,
|
||||
"width": 64,
|
||||
"height": 32
|
||||
},
|
||||
"pointer": {
|
||||
"id": 21,
|
||||
"width": 64,
|
||||
"height": 64
|
||||
},
|
||||
"pigscene": {
|
||||
"id": 22,
|
||||
"width": 64,
|
||||
"height": 64
|
||||
},
|
||||
"burning_skull": {
|
||||
"id": 23,
|
||||
"width": 64,
|
||||
"height": 64
|
||||
},
|
||||
"skeleton": {
|
||||
"id": 24,
|
||||
"width": 64,
|
||||
"height": 48
|
||||
},
|
||||
"earth": {
|
||||
"id": 25,
|
||||
"width": 32,
|
||||
"height": 32
|
||||
},
|
||||
"wind": {
|
||||
"id": 26,
|
||||
"width": 32,
|
||||
"height": 32
|
||||
},
|
||||
"water": {
|
||||
"id": 27,
|
||||
"width": 32,
|
||||
"height": 32
|
||||
},
|
||||
"fire": {
|
||||
"id": 28,
|
||||
"width": 32,
|
||||
"height": 32
|
||||
},
|
||||
"donkey_kong": {
|
||||
"id": 29,
|
||||
"width": 64,
|
||||
"height": 48
|
||||
}
|
||||
},
|
||||
"facing": {
|
||||
"down": 0,
|
||||
"up": 1,
|
||||
"north": 2,
|
||||
"south": 3,
|
||||
"west": 4,
|
||||
"east": 5
|
||||
},
|
||||
"poses": {
|
||||
"standing": 0,
|
||||
"fall_flying": 1,
|
||||
"sleeping": 2,
|
||||
"swimming": 3,
|
||||
"spin_attack": 4,
|
||||
"crouching": 5,
|
||||
"long_jumping": 6,
|
||||
"dying": 7,
|
||||
"croaking": 8,
|
||||
"using_tongue": 9,
|
||||
"roaring": 10,
|
||||
"sniffing": 11,
|
||||
"emerging": 12,
|
||||
"digging": 13
|
||||
},
|
||||
"particle_types": {
|
||||
"ambient_entity_effect": 0,
|
||||
"angry_villager": 1,
|
||||
"block": 2,
|
||||
"block_marker": 3,
|
||||
"bubble": 4,
|
||||
"cloud": 5,
|
||||
"crit": 6,
|
||||
"damage_indicator": 7,
|
||||
"dragon_breath": 8,
|
||||
"dripping_lava": 9,
|
||||
"falling_lava": 10,
|
||||
"landing_lava": 11,
|
||||
"dripping_water": 12,
|
||||
"falling_water": 13,
|
||||
"dust": 14,
|
||||
"dust_color_transition": 15,
|
||||
"effect": 16,
|
||||
"elder_guardian": 17,
|
||||
"enchanted_hit": 18,
|
||||
"enchant": 19,
|
||||
"end_rod": 20,
|
||||
"entity_effect": 21,
|
||||
"explosion_emitter": 22,
|
||||
"explosion": 23,
|
||||
"sonic_boom": 24,
|
||||
"falling_dust": 25,
|
||||
"firework": 26,
|
||||
"fishing": 27,
|
||||
"flame": 28,
|
||||
"sculk_soul": 29,
|
||||
"sculk_charge": 30,
|
||||
"sculk_charge_pop": 31,
|
||||
"soul_fire_flame": 32,
|
||||
"soul": 33,
|
||||
"flash": 34,
|
||||
"happy_villager": 35,
|
||||
"composter": 36,
|
||||
"heart": 37,
|
||||
"instant_effect": 38,
|
||||
"item": 39,
|
||||
"vibration": 40,
|
||||
"item_slime": 41,
|
||||
"item_snowball": 42,
|
||||
"large_smoke": 43,
|
||||
"lava": 44,
|
||||
"mycelium": 45,
|
||||
"note": 46,
|
||||
"poof": 47,
|
||||
"portal": 48,
|
||||
"rain": 49,
|
||||
"smoke": 50,
|
||||
"sneeze": 51,
|
||||
"spit": 52,
|
||||
"squid_ink": 53,
|
||||
"sweep_attack": 54,
|
||||
"totem_of_undying": 55,
|
||||
"underwater": 56,
|
||||
"splash": 57,
|
||||
"witch": 58,
|
||||
"bubble_pop": 59,
|
||||
"current_down": 60,
|
||||
"bubble_column_up": 61,
|
||||
"nautilus": 62,
|
||||
"dolphin": 63,
|
||||
"campfire_cosy_smoke": 64,
|
||||
"campfire_signal_smoke": 65,
|
||||
"dripping_honey": 66,
|
||||
"falling_honey": 67,
|
||||
"landing_honey": 68,
|
||||
"falling_nectar": 69,
|
||||
"falling_spore_blossom": 70,
|
||||
"ash": 71,
|
||||
"crimson_spore": 72,
|
||||
"warped_spore": 73,
|
||||
"spore_blossom_air": 74,
|
||||
"dripping_obsidian_tear": 75,
|
||||
"falling_obsidian_tear": 76,
|
||||
"landing_obsidian_tear": 77,
|
||||
"reverse_portal": 78,
|
||||
"white_ash": 79,
|
||||
"small_flame": 80,
|
||||
"snowflake": 81,
|
||||
"dripping_dripstone_lava": 82,
|
||||
"falling_dripstone_lava": 83,
|
||||
"dripping_dripstone_water": 84,
|
||||
"falling_dripstone_water": 85,
|
||||
"glow_squid_ink": 86,
|
||||
"glow": 87,
|
||||
"wax_on": 88,
|
||||
"wax_off": 89,
|
||||
"electric_spark": 90,
|
||||
"scrape": 91,
|
||||
"shriek": 92
|
||||
}
|
||||
}
|
|
@ -290,9 +290,16 @@ public class Entities implements Main.Extractor {
|
|||
|
||||
var parent = entityClass.getSuperclass();
|
||||
var hasParent = parent != null && Entity.class.isAssignableFrom(parent);
|
||||
entityJson.addProperty("parent", hasParent ? parent.getSimpleName() : null);
|
||||
|
||||
entityJson.add("translation_key", entityType != null ? new JsonPrimitive(entityType.getTranslationKey()) : null);
|
||||
if (hasParent) {
|
||||
entityJson.addProperty("parent", parent.getSimpleName());
|
||||
}
|
||||
|
||||
if (entityType != null) {
|
||||
entityJson.addProperty("type", Registry.ENTITY_TYPE.getId(entityType).getPath());
|
||||
|
||||
entityJson.add("translation_key", new JsonPrimitive(entityType.getTranslationKey()));
|
||||
}
|
||||
|
||||
var fieldsJson = new JsonArray();
|
||||
for (var entityField : entityClass.getDeclaredFields()) {
|
||||
|
|
|
@ -22,6 +22,12 @@ public class EntityData implements Main.Extractor {
|
|||
public JsonElement extract() throws Exception {
|
||||
var dataJson = new JsonObject();
|
||||
|
||||
var typesJson = new JsonObject();
|
||||
for (var type : Registry.ENTITY_TYPE) {
|
||||
typesJson.addProperty(Registry.ENTITY_TYPE.getId(type).getPath(), Registry.ENTITY_TYPE.getRawId(type));
|
||||
}
|
||||
dataJson.add("types", typesJson);
|
||||
|
||||
var statusesJson = new JsonObject();
|
||||
for (var field : EntityStatuses.class.getDeclaredFields()) {
|
||||
if (field.canAccess(null) && field.get(null) instanceof Byte code) {
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
//! Connections to the server after logging in.
|
||||
|
||||
/// Contains the [`Event`] enum and related data types.
|
||||
mod event;
|
||||
use std::collections::{HashSet, VecDeque};
|
||||
use std::iter::FusedIterator;
|
||||
use std::time::Duration;
|
||||
|
@ -18,8 +16,11 @@ use crate::block_pos::BlockPos;
|
|||
use crate::chunk_pos::ChunkPos;
|
||||
use crate::config::Config;
|
||||
use crate::dimension::DimensionId;
|
||||
use crate::entity::types::Player;
|
||||
use crate::entity::{velocity_to_packet_units, Entities, Entity, EntityId, EntityKind};
|
||||
use crate::entity::kinds::Player;
|
||||
use crate::entity::{
|
||||
velocity_to_packet_units, Entities, EntityId, EntityKind, Event as EntityEvent,
|
||||
StatusOrAnimation,
|
||||
};
|
||||
use crate::player_textures::SignedPlayerTextures;
|
||||
use crate::protocol_inner::packets::play::c2s::{
|
||||
C2sPlayPacket, DiggingStatus, InteractKind, PlayerCommandId,
|
||||
|
@ -28,12 +29,12 @@ pub use crate::protocol_inner::packets::play::s2c::SetTitleAnimationTimes as Tit
|
|||
use crate::protocol_inner::packets::play::s2c::{
|
||||
Animate, BiomeRegistry, BlockChangeAck, ChatType, ChatTypeChat, ChatTypeNarration,
|
||||
ChatTypeRegistry, ChatTypeRegistryEntry, ClearTitles, DimensionTypeRegistry,
|
||||
DimensionTypeRegistryEntry, Disconnect, EntityEvent, ForgetLevelChunk, GameEvent,
|
||||
DimensionTypeRegistryEntry, Disconnect, EntityStatus, ForgetLevelChunk, GameEvent,
|
||||
GameEventReason, KeepAlive, Login, MoveEntityPosition, MoveEntityPositionAndRotation,
|
||||
MoveEntityRotation, PlayerPosition, PlayerPositionFlags, RegistryCodec, RemoveEntities,
|
||||
Respawn, RotateHead, S2cPlayPacket, SetChunkCacheCenter, SetChunkCacheRadius,
|
||||
SetEntityMetadata, SetEntityMotion, SetSubtitleText, SetTitleText, SpawnPosition, SystemChat,
|
||||
TeleportEntity, UpdateAttributes, UpdateAttributesProperty, ENTITY_EVENT_MAX_BOUND,
|
||||
TeleportEntity, UpdateAttributes, UpdateAttributesProperty,
|
||||
};
|
||||
use crate::protocol_inner::{BoundedInt, ByteAngle, Nbt, RawBytes, VarInt};
|
||||
use crate::server::{C2sPacketChannels, NewClientData, SharedServer};
|
||||
|
@ -43,6 +44,9 @@ use crate::util::{chunks_in_view_distance, is_chunk_in_view_distance};
|
|||
use crate::world::{WorldId, Worlds};
|
||||
use crate::{ident, Ticks, LIBRARY_NAMESPACE, STANDARD_TPS};
|
||||
|
||||
/// Contains the [`Event`] enum and related data types.
|
||||
mod event;
|
||||
|
||||
/// A container for all [`Client`]s on a [`Server`](crate::server::Server).
|
||||
///
|
||||
/// New clients are automatically inserted into this container but
|
||||
|
@ -211,6 +215,7 @@ pub struct Client<C: Config> {
|
|||
flags: ClientFlags,
|
||||
/// The data for the client's own player entity.
|
||||
player_data: Player,
|
||||
entity_events: Vec<EntityEvent>,
|
||||
}
|
||||
|
||||
#[bitfield(u16)]
|
||||
|
@ -280,6 +285,7 @@ impl<C: Config> Client<C> {
|
|||
.with_modified_spawn_position(true)
|
||||
.with_got_keepalive(true),
|
||||
player_data: Player::new(),
|
||||
entity_events: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -522,6 +528,10 @@ impl<C: Config> Client<C> {
|
|||
self.events.pop_front()
|
||||
}
|
||||
|
||||
pub fn trigger_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
|
||||
|
@ -1193,7 +1203,7 @@ impl<C: Config> Client<C> {
|
|||
if let Some(entity) = entities.get(id) {
|
||||
debug_assert!(entity.kind() != EntityKind::Marker);
|
||||
if self.new_position.distance(entity.position()) <= view_dist as f64 * 16.0 {
|
||||
if let Some(meta) = entity.updated_metadata_packet(id) {
|
||||
if let Some(meta) = entity.updated_tracked_data_packet(id) {
|
||||
send_packet(&mut self.send, meta);
|
||||
}
|
||||
|
||||
|
@ -1273,7 +1283,7 @@ impl<C: Config> Client<C> {
|
|||
)
|
||||
}
|
||||
|
||||
send_entity_events(&mut self.send, id, entity);
|
||||
send_entity_events(&mut self.send, id.to_network_id(), entity.events());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1291,7 +1301,7 @@ impl<C: Config> Client<C> {
|
|||
|
||||
// Update the client's own player metadata.
|
||||
let mut data = Vec::new();
|
||||
self.player_data.updated_metadata(&mut data);
|
||||
self.player_data.updated_tracked_data(&mut data);
|
||||
|
||||
if !data.is_empty() {
|
||||
data.push(0xff);
|
||||
|
@ -1320,29 +1330,18 @@ impl<C: Config> Client<C> {
|
|||
.expect("should not be a marker entity"),
|
||||
);
|
||||
|
||||
if let Some(meta) = entity.initial_metadata_packet(id) {
|
||||
if let Some(meta) = entity.initial_tracked_data_packet(id) {
|
||||
self.send_packet(meta);
|
||||
}
|
||||
|
||||
send_entity_events(&mut self.send, id, entity);
|
||||
send_entity_events(&mut self.send, id.to_network_id(), entity.events());
|
||||
}
|
||||
None
|
||||
},
|
||||
);
|
||||
|
||||
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 for self since it shouldn't have
|
||||
// any effect.
|
||||
}
|
||||
send_entity_events(&mut self.send, 0, &self.entity_events);
|
||||
self.entity_events.clear();
|
||||
|
||||
self.player_data.clear_modifications();
|
||||
self.old_position = self.new_position;
|
||||
|
@ -1366,24 +1365,23 @@ fn send_packet(send_opt: &mut SendOpt, pkt: impl Into<S2cPlayPacket>) {
|
|||
}
|
||||
}
|
||||
|
||||
fn send_entity_events<C: Config>(send_opt: &mut SendOpt, id: EntityId, entity: &Entity<C>) {
|
||||
for &code in entity.state.event_codes() {
|
||||
if code <= ENTITY_EVENT_MAX_BOUND as u8 {
|
||||
send_packet(
|
||||
fn send_entity_events(send_opt: &mut SendOpt, entity_id: i32, events: &[EntityEvent]) {
|
||||
for &event in events {
|
||||
match event.status_or_animation() {
|
||||
StatusOrAnimation::Status(code) => send_packet(
|
||||
send_opt,
|
||||
EntityEvent {
|
||||
entity_id: id.to_network_id(),
|
||||
entity_status: BoundedInt(code),
|
||||
EntityStatus {
|
||||
entity_id,
|
||||
entity_status: code,
|
||||
},
|
||||
);
|
||||
} else {
|
||||
send_packet(
|
||||
),
|
||||
StatusOrAnimation::Animation(code) => send_packet(
|
||||
send_opt,
|
||||
Animate {
|
||||
entity_id: VarInt(id.to_network_id()),
|
||||
animation: BoundedInt(code - ENTITY_EVENT_MAX_BOUND as u8 - 1),
|
||||
entity_id: VarInt(entity_id),
|
||||
animation: code,
|
||||
},
|
||||
)
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
317
src/entity.rs
317
src/entity.rs
|
@ -1,16 +1,13 @@
|
|||
//! Dynamic actors in a world.
|
||||
|
||||
pub mod state;
|
||||
pub mod types;
|
||||
|
||||
use std::collections::hash_map::Entry;
|
||||
use std::collections::HashMap;
|
||||
use std::iter::FusedIterator;
|
||||
use std::num::NonZeroU32;
|
||||
|
||||
use bitfield_struct::bitfield;
|
||||
pub use kinds::{EntityEnum, EntityKind};
|
||||
use rayon::iter::ParallelIterator;
|
||||
pub use types::{EntityKind, EntityState};
|
||||
use uuid::Uuid;
|
||||
use vek::{Aabb, Vec3};
|
||||
|
||||
|
@ -24,6 +21,11 @@ use crate::util::aabb_from_bottom_and_size;
|
|||
use crate::world::WorldId;
|
||||
use crate::STANDARD_TPS;
|
||||
|
||||
pub mod data;
|
||||
pub mod kinds;
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/entity_event.rs"));
|
||||
|
||||
/// A container for all [`Entity`]s on a [`Server`](crate::server::Server).
|
||||
///
|
||||
/// # Spawning Player Entities
|
||||
|
@ -72,7 +74,8 @@ impl<C: Config> Entities<C> {
|
|||
Entry::Vacant(ve) => {
|
||||
let (k, e) = self.sm.insert(Entity {
|
||||
data,
|
||||
state: EntityState::new(kind),
|
||||
variants: EntityEnum::new(kind),
|
||||
events: Vec::new(),
|
||||
flags: EntityFlags(0),
|
||||
world: WorldId::NULL,
|
||||
new_position: Vec3::default(),
|
||||
|
@ -197,7 +200,8 @@ impl<C: Config> Entities<C> {
|
|||
pub(crate) fn update(&mut self) {
|
||||
for (_, e) in self.iter_mut() {
|
||||
e.old_position = e.new_position;
|
||||
e.state.clear_modifications();
|
||||
e.variants.clear_modifications();
|
||||
e.events.clear();
|
||||
|
||||
e.flags.set_yaw_or_pitch_modified(false);
|
||||
e.flags.set_head_yaw_modified(false);
|
||||
|
@ -239,9 +243,9 @@ impl EntityId {
|
|||
pub struct Entity<C: Config> {
|
||||
/// Custom data.
|
||||
pub data: C::EntityData,
|
||||
/// Kind-specific state for this entity.
|
||||
pub state: EntityState,
|
||||
variants: EntityEnum,
|
||||
flags: EntityFlags,
|
||||
events: Vec<Event>,
|
||||
world: WorldId,
|
||||
new_position: Vec3<f64>,
|
||||
old_position: Vec3<f64>,
|
||||
|
@ -267,9 +271,25 @@ impl<C: Config> Entity<C> {
|
|||
self.flags
|
||||
}
|
||||
|
||||
pub fn view(&self) -> &EntityEnum {
|
||||
&self.variants
|
||||
}
|
||||
|
||||
pub fn view_mut(&mut self) -> &mut EntityEnum {
|
||||
&mut self.variants
|
||||
}
|
||||
|
||||
/// Gets the [`EntityKind`] of this entity.
|
||||
pub fn kind(&self) -> EntityKind {
|
||||
self.state.kind()
|
||||
self.variants.kind()
|
||||
}
|
||||
|
||||
pub fn trigger_event(&mut self, event: Event) {
|
||||
self.events.push(event);
|
||||
}
|
||||
|
||||
pub(crate) fn events(&self) -> &[Event] {
|
||||
&self.events
|
||||
}
|
||||
|
||||
/// Gets the [`WorldId`](crate::world::WorldId) of the world this entity is
|
||||
|
@ -387,18 +407,18 @@ impl<C: Config> Entity<C> {
|
|||
///
|
||||
/// [interact event]: crate::client::Event::InteractWithEntity
|
||||
pub fn hitbox(&self) -> Aabb<f64> {
|
||||
let dims = match &self.state {
|
||||
EntityState::Allay(_) => [0.6, 0.35, 0.6],
|
||||
EntityState::ChestBoat(_) => [1.375, 0.5625, 1.375],
|
||||
EntityState::Frog(_) => [0.5, 0.5, 0.5],
|
||||
EntityState::Tadpole(_) => [0.4, 0.3, 0.4],
|
||||
EntityState::Warden(_) => [0.9, 2.9, 0.9],
|
||||
EntityState::AreaEffectCloud(e) => [
|
||||
let dims = match &self.variants {
|
||||
EntityEnum::Allay(_) => [0.6, 0.35, 0.6],
|
||||
EntityEnum::ChestBoat(_) => [1.375, 0.5625, 1.375],
|
||||
EntityEnum::Frog(_) => [0.5, 0.5, 0.5],
|
||||
EntityEnum::Tadpole(_) => [0.4, 0.3, 0.4],
|
||||
EntityEnum::Warden(_) => [0.9, 2.9, 0.9],
|
||||
EntityEnum::AreaEffectCloud(e) => [
|
||||
e.get_radius() as f64 * 2.0,
|
||||
0.5,
|
||||
e.get_radius() as f64 * 2.0,
|
||||
],
|
||||
EntityState::ArmorStand(e) => {
|
||||
EntityEnum::ArmorStand(e) => {
|
||||
if e.get_marker() {
|
||||
[0.0, 0.0, 0.0]
|
||||
} else if e.get_small() {
|
||||
|
@ -407,160 +427,171 @@ impl<C: Config> Entity<C> {
|
|||
[0.5, 1.975, 0.5]
|
||||
}
|
||||
}
|
||||
EntityState::Arrow(_) => [0.5, 0.5, 0.5],
|
||||
EntityState::Axolotl(_) => [1.3, 0.6, 1.3],
|
||||
EntityState::Bat(_) => [0.5, 0.9, 0.5],
|
||||
EntityState::Bee(_) => [0.7, 0.6, 0.7], // TODO: baby size?
|
||||
EntityState::Blaze(_) => [0.6, 1.8, 0.6],
|
||||
EntityState::Boat(_) => [1.375, 0.5625, 1.375],
|
||||
EntityState::Cat(_) => [0.6, 0.7, 0.6],
|
||||
EntityState::CaveSpider(_) => [0.7, 0.5, 0.7],
|
||||
EntityState::Chicken(_) => [0.4, 0.7, 0.4], // TODO: baby size?
|
||||
EntityState::Cod(_) => [0.5, 0.3, 0.5],
|
||||
EntityState::Cow(_) => [0.9, 1.4, 0.9], // TODO: baby size?
|
||||
EntityState::Creeper(_) => [0.6, 1.7, 0.6],
|
||||
EntityState::Dolphin(_) => [0.9, 0.6, 0.9],
|
||||
EntityState::Donkey(_) => [1.5, 1.39648, 1.5], // TODO: baby size?
|
||||
EntityState::DragonFireball(_) => [1.0, 1.0, 1.0],
|
||||
EntityState::Drowned(_) => [0.6, 1.95, 0.6], // TODO: baby size?
|
||||
EntityState::ElderGuardian(_) => [1.9975, 1.9975, 1.9975],
|
||||
EntityState::EndCrystal(_) => [2.0, 2.0, 2.0],
|
||||
EntityState::EnderDragon(_) => [16.0, 8.0, 16.0],
|
||||
EntityState::Enderman(_) => [0.6, 2.9, 0.6],
|
||||
EntityState::Endermite(_) => [0.4, 0.3, 0.4],
|
||||
EntityState::Evoker(_) => [0.6, 1.95, 0.6],
|
||||
EntityState::EvokerFangs(_) => [0.5, 0.8, 0.5],
|
||||
EntityState::ExperienceOrb(_) => [0.5, 0.5, 0.5],
|
||||
EntityState::EyeOfEnder(_) => [0.25, 0.25, 0.25],
|
||||
EntityState::FallingBlock(_) => [0.98, 0.98, 0.98],
|
||||
EntityState::FireworkRocket(_) => [0.25, 0.25, 0.25],
|
||||
EntityState::Fox(_) => [0.6, 0.7, 0.6], // TODO: baby size?
|
||||
EntityState::Ghast(_) => [4.0, 4.0, 4.0],
|
||||
EntityState::Giant(_) => [3.6, 12.0, 3.6],
|
||||
EntityState::GlowItemFrame(_) => todo!("account for rotation"),
|
||||
EntityState::GlowSquid(_) => [0.8, 0.8, 0.8],
|
||||
EntityState::Goat(_) => [1.3, 0.9, 1.3], // TODO: baby size?
|
||||
EntityState::Guardian(_) => [0.85, 0.85, 0.85],
|
||||
EntityState::Hoglin(_) => [1.39648, 1.4, 1.39648], // TODO: baby size?
|
||||
EntityState::Horse(_) => [1.39648, 1.6, 1.39648], // TODO: baby size?
|
||||
EntityState::Husk(_) => [0.6, 1.95, 0.6], // TODO: baby size?
|
||||
EntityState::Illusioner(_) => [0.6, 1.95, 0.6],
|
||||
EntityState::IronGolem(_) => [1.4, 2.7, 1.4],
|
||||
EntityState::Item(_) => [0.25, 0.25, 0.25],
|
||||
EntityState::ItemFrame(_) => todo!("account for rotation"),
|
||||
EntityState::Fireball(_) => [1.0, 1.0, 1.0],
|
||||
EntityState::LeashKnot(_) => [0.375, 0.5, 0.375],
|
||||
EntityState::LightningBolt(_) => [0.0, 0.0, 0.0],
|
||||
EntityState::Llama(_) => [0.9, 1.87, 0.9], // TODO: baby size?
|
||||
EntityState::LlamaSpit(_) => [0.25, 0.25, 0.25],
|
||||
EntityState::MagmaCube(e) => {
|
||||
let s = e.get_size() as f64 * 0.51000005;
|
||||
EntityEnum::Arrow(_) => [0.5, 0.5, 0.5],
|
||||
EntityEnum::Axolotl(_) => [1.3, 0.6, 1.3],
|
||||
EntityEnum::Bat(_) => [0.5, 0.9, 0.5],
|
||||
EntityEnum::Bee(_) => [0.7, 0.6, 0.7], // TODO: baby size?
|
||||
EntityEnum::Blaze(_) => [0.6, 1.8, 0.6],
|
||||
EntityEnum::Boat(_) => [1.375, 0.5625, 1.375],
|
||||
EntityEnum::Cat(_) => [0.6, 0.7, 0.6],
|
||||
EntityEnum::CaveSpider(_) => [0.7, 0.5, 0.7],
|
||||
EntityEnum::Chicken(_) => [0.4, 0.7, 0.4], // TODO: baby size?
|
||||
EntityEnum::Cod(_) => [0.5, 0.3, 0.5],
|
||||
EntityEnum::Cow(_) => [0.9, 1.4, 0.9], // TODO: baby size?
|
||||
EntityEnum::Creeper(_) => [0.6, 1.7, 0.6],
|
||||
EntityEnum::Dolphin(_) => [0.9, 0.6, 0.9],
|
||||
EntityEnum::Donkey(_) => [1.5, 1.39648, 1.5], // TODO: baby size?
|
||||
EntityEnum::DragonFireball(_) => [1.0, 1.0, 1.0],
|
||||
EntityEnum::Drowned(_) => [0.6, 1.95, 0.6], // TODO: baby size?
|
||||
EntityEnum::ElderGuardian(_) => [1.9975, 1.9975, 1.9975],
|
||||
EntityEnum::EndCrystal(_) => [2.0, 2.0, 2.0],
|
||||
EntityEnum::EnderDragon(_) => [16.0, 8.0, 16.0],
|
||||
EntityEnum::Enderman(_) => [0.6, 2.9, 0.6],
|
||||
EntityEnum::Endermite(_) => [0.4, 0.3, 0.4],
|
||||
EntityEnum::Evoker(_) => [0.6, 1.95, 0.6],
|
||||
EntityEnum::EvokerFangs(_) => [0.5, 0.8, 0.5],
|
||||
EntityEnum::ExperienceOrb(_) => [0.5, 0.5, 0.5],
|
||||
EntityEnum::EyeOfEnder(_) => [0.25, 0.25, 0.25],
|
||||
EntityEnum::FallingBlock(_) => [0.98, 0.98, 0.98],
|
||||
EntityEnum::FireworkRocket(_) => [0.25, 0.25, 0.25],
|
||||
EntityEnum::Fox(_) => [0.6, 0.7, 0.6], // TODO: baby size?
|
||||
EntityEnum::Ghast(_) => [4.0, 4.0, 4.0],
|
||||
EntityEnum::Giant(_) => [3.6, 12.0, 3.6],
|
||||
EntityEnum::GlowItemFrame(_) => todo!("account for rotation"),
|
||||
EntityEnum::GlowSquid(_) => [0.8, 0.8, 0.8],
|
||||
EntityEnum::Goat(_) => [1.3, 0.9, 1.3], // TODO: baby size?
|
||||
EntityEnum::Guardian(_) => [0.85, 0.85, 0.85],
|
||||
EntityEnum::Hoglin(_) => [1.39648, 1.4, 1.39648], // TODO: baby size?
|
||||
EntityEnum::Horse(_) => [1.39648, 1.6, 1.39648], // TODO: baby size?
|
||||
EntityEnum::Husk(_) => [0.6, 1.95, 0.6], // TODO: baby size?
|
||||
EntityEnum::Illusioner(_) => [0.6, 1.95, 0.6],
|
||||
EntityEnum::IronGolem(_) => [1.4, 2.7, 1.4],
|
||||
EntityEnum::Item(_) => [0.25, 0.25, 0.25],
|
||||
EntityEnum::ItemFrame(_) => todo!("account for rotation"),
|
||||
EntityEnum::Fireball(_) => [1.0, 1.0, 1.0],
|
||||
EntityEnum::LeashKnot(_) => [0.375, 0.5, 0.375],
|
||||
EntityEnum::Lightning(_) => [0.0, 0.0, 0.0],
|
||||
EntityEnum::Llama(_) => [0.9, 1.87, 0.9], // TODO: baby size?
|
||||
EntityEnum::LlamaSpit(_) => [0.25, 0.25, 0.25],
|
||||
EntityEnum::MagmaCube(e) => {
|
||||
let s = e.get_slime_size() as f64 * 0.51000005;
|
||||
[s, s, s]
|
||||
}
|
||||
EntityState::Marker(_) => [0.0, 0.0, 0.0],
|
||||
EntityState::Minecart(_) => [0.98, 0.7, 0.98],
|
||||
EntityState::ChestMinecart(_) => [0.98, 0.7, 0.98],
|
||||
EntityState::CommandBlockMinecart(_) => [0.98, 0.7, 0.98],
|
||||
EntityState::FurnaceMinecart(_) => [0.98, 0.7, 0.98],
|
||||
EntityState::HopperMinecart(_) => [0.98, 0.7, 0.98],
|
||||
EntityState::SpawnerMinecart(_) => [0.98, 0.7, 0.98],
|
||||
EntityState::TntMinecart(_) => [0.98, 0.7, 0.98],
|
||||
EntityState::Mule(_) => [1.39648, 1.6, 1.39648], // TODO: baby size?
|
||||
EntityState::Mooshroom(_) => [0.9, 1.4, 0.9], // TODO: baby size?
|
||||
EntityState::Ocelot(_) => [0.6, 0.7, 0.6], // TODO: baby size?
|
||||
EntityState::Painting(_) => todo!("account for rotation and type"),
|
||||
EntityState::Panda(_) => [0.6, 0.7, 0.6], // TODO: baby size?
|
||||
EntityState::Parrot(_) => [0.5, 0.9, 0.5],
|
||||
EntityState::Phantom(_) => [0.9, 0.5, 0.9],
|
||||
EntityState::Pig(_) => [0.9, 0.9, 0.9], // TODO: baby size?
|
||||
EntityState::Piglin(_) => [0.6, 1.95, 0.6], // TODO: baby size?
|
||||
EntityState::PiglinBrute(_) => [0.6, 1.95, 0.6],
|
||||
EntityState::Pillager(_) => [0.6, 1.95, 0.6],
|
||||
EntityState::PolarBear(_) => [1.4, 1.4, 1.4], // TODO: baby size?
|
||||
EntityState::Tnt(_) => [0.98, 0.98, 0.98],
|
||||
EntityState::Pufferfish(_) => [0.7, 0.7, 0.7],
|
||||
EntityState::Rabbit(_) => [0.4, 0.5, 0.4], // TODO: baby size?
|
||||
EntityState::Ravager(_) => [1.95, 2.2, 1.95],
|
||||
EntityState::Salmon(_) => [0.7, 0.4, 0.7],
|
||||
EntityState::Sheep(_) => [0.9, 1.3, 0.9], // TODO: baby size?
|
||||
EntityState::Shulker(_) => [1.0, 1.0, 1.0], // TODO: how is height calculated?
|
||||
EntityState::ShulkerBullet(_) => [0.3125, 0.3125, 0.3125],
|
||||
EntityState::Silverfish(_) => [0.4, 0.3, 0.4],
|
||||
EntityState::Skeleton(_) => [0.6, 1.99, 0.6],
|
||||
EntityState::SkeletonHorse(_) => [1.39648, 1.6, 1.39648], // TODO: baby size?
|
||||
EntityState::Slime(e) => {
|
||||
let s = 0.51000005 * e.get_size() as f64;
|
||||
EntityEnum::Marker(_) => [0.0, 0.0, 0.0],
|
||||
EntityEnum::Minecart(_) => [0.98, 0.7, 0.98],
|
||||
EntityEnum::ChestMinecart(_) => [0.98, 0.7, 0.98],
|
||||
EntityEnum::CommandBlockMinecart(_) => [0.98, 0.7, 0.98],
|
||||
EntityEnum::FurnaceMinecart(_) => [0.98, 0.7, 0.98],
|
||||
EntityEnum::HopperMinecart(_) => [0.98, 0.7, 0.98],
|
||||
EntityEnum::SpawnerMinecart(_) => [0.98, 0.7, 0.98],
|
||||
EntityEnum::TntMinecart(_) => [0.98, 0.7, 0.98],
|
||||
EntityEnum::Mule(_) => [1.39648, 1.6, 1.39648], // TODO: baby size?
|
||||
EntityEnum::Mooshroom(_) => [0.9, 1.4, 0.9], // TODO: baby size?
|
||||
EntityEnum::Ocelot(_) => [0.6, 0.7, 0.6], // TODO: baby size?
|
||||
EntityEnum::Painting(_) => todo!("account for rotation and type"),
|
||||
EntityEnum::Panda(_) => [0.6, 0.7, 0.6], // TODO: baby size?
|
||||
EntityEnum::Parrot(_) => [0.5, 0.9, 0.5],
|
||||
EntityEnum::Phantom(_) => [0.9, 0.5, 0.9],
|
||||
EntityEnum::Pig(_) => [0.9, 0.9, 0.9], // TODO: baby size?
|
||||
EntityEnum::Piglin(_) => [0.6, 1.95, 0.6], // TODO: baby size?
|
||||
EntityEnum::PiglinBrute(_) => [0.6, 1.95, 0.6],
|
||||
EntityEnum::Pillager(_) => [0.6, 1.95, 0.6],
|
||||
EntityEnum::PolarBear(_) => [1.4, 1.4, 1.4], // TODO: baby size?
|
||||
EntityEnum::Tnt(_) => [0.98, 0.98, 0.98],
|
||||
EntityEnum::Pufferfish(_) => [0.7, 0.7, 0.7],
|
||||
EntityEnum::Rabbit(_) => [0.4, 0.5, 0.4], // TODO: baby size?
|
||||
EntityEnum::Ravager(_) => [1.95, 2.2, 1.95],
|
||||
EntityEnum::Salmon(_) => [0.7, 0.4, 0.7],
|
||||
EntityEnum::Sheep(_) => [0.9, 1.3, 0.9], // TODO: baby size?
|
||||
EntityEnum::Shulker(_) => [1.0, 1.0, 1.0], // TODO: how is height calculated?
|
||||
EntityEnum::ShulkerBullet(_) => [0.3125, 0.3125, 0.3125],
|
||||
EntityEnum::Silverfish(_) => [0.4, 0.3, 0.4],
|
||||
EntityEnum::Skeleton(_) => [0.6, 1.99, 0.6],
|
||||
EntityEnum::SkeletonHorse(_) => [1.39648, 1.6, 1.39648], // TODO: baby size?
|
||||
EntityEnum::Slime(e) => {
|
||||
let s = 0.51000005 * e.get_slime_size() as f64;
|
||||
[s, s, s]
|
||||
}
|
||||
EntityState::SmallFireball(_) => [0.3125, 0.3125, 0.3125],
|
||||
EntityState::SnowGolem(_) => [0.7, 1.9, 0.7],
|
||||
EntityState::Snowball(_) => [0.25, 0.25, 0.25],
|
||||
EntityState::SpectralArrow(_) => [0.5, 0.5, 0.5],
|
||||
EntityState::Spider(_) => [1.4, 0.9, 1.4],
|
||||
EntityState::Squid(_) => [0.8, 0.8, 0.8],
|
||||
EntityState::Stray(_) => [0.6, 1.99, 0.6],
|
||||
EntityState::Strider(_) => [0.9, 1.7, 0.9], // TODO: baby size?
|
||||
EntityState::Egg(_) => [0.25, 0.25, 0.25],
|
||||
EntityState::EnderPearl(_) => [0.25, 0.25, 0.25],
|
||||
EntityState::ExperienceBottle(_) => [0.25, 0.25, 0.25],
|
||||
EntityState::Potion(_) => [0.25, 0.25, 0.25],
|
||||
EntityState::Trident(_) => [0.5, 0.5, 0.5],
|
||||
EntityState::TraderLlama(_) => [0.9, 1.87, 0.9],
|
||||
EntityState::TropicalFish(_) => [0.5, 0.4, 0.5],
|
||||
EntityState::Turtle(_) => [1.2, 0.4, 1.2], // TODO: baby size?
|
||||
EntityState::Vex(_) => [0.4, 0.8, 0.4],
|
||||
EntityState::Villager(_) => [0.6, 1.95, 0.6], // TODO: baby size?
|
||||
EntityState::Vindicator(_) => [0.6, 1.95, 0.6],
|
||||
EntityState::WanderingTrader(_) => [0.6, 1.95, 0.6],
|
||||
EntityState::Witch(_) => [0.6, 1.95, 0.6],
|
||||
EntityState::Wither(_) => [0.9, 3.5, 0.9],
|
||||
EntityState::WitherSkeleton(_) => [0.7, 2.4, 0.7],
|
||||
EntityState::WitherSkull(_) => [0.3125, 0.3125, 0.3125],
|
||||
EntityState::Wolf(_) => [0.6, 0.85, 0.6], // TODO: baby size?
|
||||
EntityState::Zoglin(_) => [1.39648, 1.4, 1.39648], // TODO: baby size?
|
||||
EntityState::Zombie(_) => [0.6, 1.95, 0.6], // TODO: baby size?
|
||||
EntityState::ZombieHorse(_) => [1.39648, 1.6, 1.39648], // TODO: baby size?
|
||||
EntityState::ZombieVillager(_) => [0.6, 1.95, 0.6], // TODO: baby size?
|
||||
EntityState::ZombifiedPiglin(_) => [0.6, 1.95, 0.6], // TODO: baby size?
|
||||
EntityState::Player(_) => [0.6, 1.8, 0.6], // TODO: changes depending on the pose.
|
||||
EntityState::FishingBobber(_) => [0.25, 0.25, 0.25],
|
||||
EntityEnum::SmallFireball(_) => [0.3125, 0.3125, 0.3125],
|
||||
EntityEnum::SnowGolem(_) => [0.7, 1.9, 0.7],
|
||||
EntityEnum::Snowball(_) => [0.25, 0.25, 0.25],
|
||||
EntityEnum::SpectralArrow(_) => [0.5, 0.5, 0.5],
|
||||
EntityEnum::Spider(_) => [1.4, 0.9, 1.4],
|
||||
EntityEnum::Squid(_) => [0.8, 0.8, 0.8],
|
||||
EntityEnum::Stray(_) => [0.6, 1.99, 0.6],
|
||||
EntityEnum::Strider(_) => [0.9, 1.7, 0.9], // TODO: baby size?
|
||||
EntityEnum::Egg(_) => [0.25, 0.25, 0.25],
|
||||
EntityEnum::EnderPearl(_) => [0.25, 0.25, 0.25],
|
||||
EntityEnum::ExperienceBottle(_) => [0.25, 0.25, 0.25],
|
||||
EntityEnum::Potion(_) => [0.25, 0.25, 0.25],
|
||||
EntityEnum::Trident(_) => [0.5, 0.5, 0.5],
|
||||
EntityEnum::TraderLlama(_) => [0.9, 1.87, 0.9],
|
||||
EntityEnum::TropicalFish(_) => [0.5, 0.4, 0.5],
|
||||
EntityEnum::Turtle(_) => [1.2, 0.4, 1.2], // TODO: baby size?
|
||||
EntityEnum::Vex(_) => [0.4, 0.8, 0.4],
|
||||
EntityEnum::Villager(_) => [0.6, 1.95, 0.6], // TODO: baby size?
|
||||
EntityEnum::Vindicator(_) => [0.6, 1.95, 0.6],
|
||||
EntityEnum::WanderingTrader(_) => [0.6, 1.95, 0.6],
|
||||
EntityEnum::Witch(_) => [0.6, 1.95, 0.6],
|
||||
EntityEnum::Wither(_) => [0.9, 3.5, 0.9],
|
||||
EntityEnum::WitherSkeleton(_) => [0.7, 2.4, 0.7],
|
||||
EntityEnum::WitherSkull(_) => [0.3125, 0.3125, 0.3125],
|
||||
EntityEnum::Wolf(_) => [0.6, 0.85, 0.6], // TODO: baby size?
|
||||
EntityEnum::Zoglin(_) => [1.39648, 1.4, 1.39648], // TODO: baby size?
|
||||
EntityEnum::Zombie(_) => [0.6, 1.95, 0.6], // TODO: baby size?
|
||||
EntityEnum::ZombieHorse(_) => [1.39648, 1.6, 1.39648], // TODO: baby size?
|
||||
EntityEnum::ZombieVillager(_) => [0.6, 1.95, 0.6], // TODO: baby size?
|
||||
EntityEnum::ZombifiedPiglin(_) => [0.6, 1.95, 0.6], // TODO: baby size?
|
||||
EntityEnum::Player(_) => [0.6, 1.8, 0.6], // TODO: changes depending on the pose.
|
||||
EntityEnum::FishingBobber(_) => [0.25, 0.25, 0.25],
|
||||
};
|
||||
|
||||
aabb_from_bottom_and_size(self.new_position, dims.into())
|
||||
}
|
||||
|
||||
/// Gets the metadata packet to send to clients after this entity has been
|
||||
/// spawned.
|
||||
/// Gets the tracked data packet to send to clients after this entity has
|
||||
/// been spawned.
|
||||
///
|
||||
/// Is `None` if there is no initial metadata.
|
||||
pub(crate) fn initial_metadata_packet(&self, this_id: EntityId) -> Option<SetEntityMetadata> {
|
||||
self.state.initial_metadata().map(|meta| SetEntityMetadata {
|
||||
/// Returns `None` if all the tracked data is at its default values.
|
||||
pub(crate) fn initial_tracked_data_packet(
|
||||
&self,
|
||||
this_id: EntityId,
|
||||
) -> Option<SetEntityMetadata> {
|
||||
self.variants
|
||||
.initial_tracked_data()
|
||||
.map(|meta| SetEntityMetadata {
|
||||
entity_id: VarInt(this_id.to_network_id()),
|
||||
metadata: RawBytes(meta),
|
||||
})
|
||||
}
|
||||
|
||||
/// Gets the metadata packet to send to clients when the entity is modified.
|
||||
/// Gets the tracked data packet to send to clients when the entity is
|
||||
/// modified.
|
||||
///
|
||||
/// Is `None` if this entity's metadata has not been modified.
|
||||
pub(crate) fn updated_metadata_packet(&self, this_id: EntityId) -> Option<SetEntityMetadata> {
|
||||
self.state.updated_metadata().map(|meta| SetEntityMetadata {
|
||||
/// Returns `None` if this entity's tracked data has not been modified.
|
||||
pub(crate) fn updated_tracked_data_packet(
|
||||
&self,
|
||||
this_id: EntityId,
|
||||
) -> Option<SetEntityMetadata> {
|
||||
self.variants
|
||||
.updated_tracked_data()
|
||||
.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.state {
|
||||
EntityState::Marker(_) => None,
|
||||
EntityState::ExperienceOrb(_) => {
|
||||
match &self.variants {
|
||||
EntityEnum::Marker(_) => None,
|
||||
EntityEnum::ExperienceOrb(_) => {
|
||||
Some(EntitySpawnPacket::ExperienceOrb(AddExperienceOrb {
|
||||
entity_id: VarInt(this_id.to_network_id()),
|
||||
position: self.new_position,
|
||||
count: 0, // TODO
|
||||
}))
|
||||
}
|
||||
EntityState::Player(_) => Some(EntitySpawnPacket::Player(AddPlayer {
|
||||
EntityEnum::Player(_) => Some(EntitySpawnPacket::Player(AddPlayer {
|
||||
entity_id: VarInt(this_id.to_network_id()),
|
||||
player_uuid: self.uuid,
|
||||
position: self.new_position,
|
||||
|
|
|
@ -1,35 +1,63 @@
|
|||
//! Types used in [`EntityData`](crate::entity::EntityData).
|
||||
//! Primitive types used in getters and setters on entities.
|
||||
|
||||
use std::io::Write;
|
||||
use std::io::{Read, Write};
|
||||
|
||||
use crate::protocol_inner::{Encode, VarInt};
|
||||
use crate::protocol_inner::{Decode, Encode, VarInt};
|
||||
|
||||
#[derive(Clone, Copy, Default, PartialEq, PartialOrd, Debug)]
|
||||
pub struct ArmorStandRotations {
|
||||
/// Rotation on the X axis in degrees.
|
||||
pub x: f32,
|
||||
/// Rotation on the Y axis in degrees.
|
||||
pub y: f32,
|
||||
/// Rotation on the Z axis in degrees.
|
||||
pub z: f32,
|
||||
}
|
||||
/// Represents an optional `u32` value excluding [`u32::MAX`].
|
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Debug)]
|
||||
pub struct OptionalInt(u32);
|
||||
|
||||
impl ArmorStandRotations {
|
||||
pub fn new(x: f32, y: f32, z: f32) -> Self {
|
||||
Self { x, y, z }
|
||||
impl OptionalInt {
|
||||
/// Returns `None` iff `n` is Some(u32::MAX).
|
||||
pub fn new(n: impl Into<Option<u32>>) -> Option<Self> {
|
||||
match n.into() {
|
||||
None => Some(Self(0)),
|
||||
Some(u32::MAX) => None,
|
||||
Some(n) => Some(Self(n + 1)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get(self) -> Option<u32> {
|
||||
self.0.checked_sub(1)
|
||||
}
|
||||
}
|
||||
|
||||
impl Encode for ArmorStandRotations {
|
||||
impl Encode for OptionalInt {
|
||||
fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> {
|
||||
self.x.encode(w)?;
|
||||
self.y.encode(w)?;
|
||||
self.z.encode(w)
|
||||
VarInt(self.0 as i32).encode(w)
|
||||
}
|
||||
}
|
||||
|
||||
impl Decode for OptionalInt {
|
||||
fn decode(r: &mut impl Read) -> anyhow::Result<Self> {
|
||||
Ok(Self(VarInt::decode(r)?.0 as u32))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, PartialOrd, Debug)]
|
||||
pub struct EulerAngle {
|
||||
pub pitch: f32,
|
||||
pub yaw: f32,
|
||||
pub roll: f32,
|
||||
}
|
||||
|
||||
impl EulerAngle {
|
||||
pub fn new(pitch: f32, yaw: f32, roll: f32) -> Self {
|
||||
Self { pitch, yaw, roll }
|
||||
}
|
||||
}
|
||||
|
||||
impl Encode for EulerAngle {
|
||||
fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> {
|
||||
self.pitch.encode(w)?;
|
||||
self.yaw.encode(w)?;
|
||||
self.roll.encode(w)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
|
||||
pub enum Direction {
|
||||
pub enum Facing {
|
||||
Down,
|
||||
Up,
|
||||
North,
|
||||
|
@ -38,7 +66,7 @@ pub enum Direction {
|
|||
East,
|
||||
}
|
||||
|
||||
impl Encode for Direction {
|
||||
impl Encode for Facing {
|
||||
fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> {
|
||||
VarInt(*self as i32).encode(w)
|
||||
}
|
||||
|
@ -206,7 +234,7 @@ impl Encode for FrogKind {
|
|||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Debug)]
|
||||
pub enum PaintingKind {
|
||||
#[default]
|
||||
Default, // TODO
|
||||
Kebab, // TODO
|
||||
}
|
||||
|
||||
impl Encode for PaintingKind {
|
||||
|
@ -214,3 +242,15 @@ impl Encode for PaintingKind {
|
|||
VarInt(*self as i32).encode(w)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO
|
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
|
||||
pub enum Particle {
|
||||
EntityEffect = 21,
|
||||
}
|
||||
|
||||
impl Encode for Particle {
|
||||
fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> {
|
||||
VarInt(*self as i32).encode(w)
|
||||
}
|
||||
}
|
|
@ -1,10 +1,9 @@
|
|||
//! Contains a struct for each variant in [`EntityKind`].
|
||||
//! Contains the [`EntityEnum`] and the types for each variant.
|
||||
|
||||
#![allow(clippy::all, missing_docs)]
|
||||
#![allow(clippy::all, missing_docs, trivial_numeric_casts)]
|
||||
|
||||
use crate::block::{BlockPos, BlockState};
|
||||
use crate::entity::state::*;
|
||||
use crate::entity::EntityId;
|
||||
use crate::entity::data::*;
|
||||
use crate::protocol_inner::{Encode, VarInt};
|
||||
use crate::text::Text;
|
||||
use crate::uuid::Uuid;
|
|
@ -618,7 +618,7 @@ pub mod play {
|
|||
def_struct! {
|
||||
Animate 0x03 {
|
||||
entity_id: VarInt,
|
||||
animation: BoundedInt<u8, 0, 5>,
|
||||
animation: u8,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -735,12 +735,10 @@ pub mod play {
|
|||
}
|
||||
}
|
||||
|
||||
pub const ENTITY_EVENT_MAX_BOUND: i64 = 62;
|
||||
|
||||
def_struct! {
|
||||
EntityEvent 0x18 {
|
||||
EntityStatus 0x18 {
|
||||
entity_id: i32,
|
||||
entity_status: BoundedInt<u8, 1, ENTITY_EVENT_MAX_BOUND>,
|
||||
entity_status: u8,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1270,7 +1268,7 @@ pub mod play {
|
|||
BossEvent,
|
||||
ClearTitles,
|
||||
Disconnect,
|
||||
EntityEvent,
|
||||
EntityStatus,
|
||||
ForgetLevelChunk,
|
||||
GameEvent,
|
||||
KeepAlive,
|
||||
|
|
Loading…
Reference in a new issue