1
2
Fork 0
mirror of https://github.com/mat-1/azalea.git synced 2025-08-02 14:26:04 +00:00

update some physics code and fix ChatType

This commit is contained in:
mat 2024-11-27 06:52:35 +00:00
parent 5825871dfc
commit c8891dca1f
16 changed files with 149 additions and 166 deletions

View file

@ -49,10 +49,6 @@ impl Vec3 {
}
}
pub fn length_squared(&self) -> f64 {
self.x * self.x + self.y * self.y + self.z * self.z
}
pub fn normalize(&self) -> Vec3 {
let length = f64::sqrt(self.x * self.x + self.y * self.y + self.z * self.z);
if length < 1e-4 {

View file

@ -8,11 +8,9 @@ use std::{
hash::Hash,
io::{Cursor, Write},
ops::{Add, AddAssign, Mul, Rem, Sub},
str::FromStr,
};
use azalea_buf::{AzBuf, AzaleaRead, AzaleaWrite, BufReadError};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use crate::resource_location::ResourceLocation;
@ -28,25 +26,25 @@ macro_rules! vec3_impl {
/// Get the distance of this vector to the origin by doing `x^2 + y^2 +
/// z^2`.
#[inline]
pub fn length_sqr(&self) -> $type {
pub fn length_squared(&self) -> $type {
self.x * self.x + self.y * self.y + self.z * self.z
}
/// Get the squared distance from this position to another position.
/// Equivalent to `(self - other).length_sqr()`.
/// Equivalent to `(self - other).length_squared()`.
#[inline]
pub fn distance_to_sqr(&self, other: &Self) -> $type {
(self - other).length_sqr()
pub fn distance_squared_to(&self, other: &Self) -> $type {
(self - other).length_squared()
}
#[inline]
pub fn horizontal_distance_sqr(&self) -> $type {
pub fn horizontal_distance_squared(&self) -> $type {
self.x * self.x + self.z * self.z
}
#[inline]
pub fn horizontal_distance_to_sqr(&self, other: &Self) -> $type {
(self - other).horizontal_distance_sqr()
pub fn horizontal_distance_squared_to(&self, other: &Self) -> $type {
(self - other).horizontal_distance_squared()
}
/// Return a new instance of this position with the y coordinate
@ -272,6 +270,46 @@ impl BlockPos {
pub fn length_manhattan(&self) -> u32 {
(self.x.abs() + self.y.abs() + self.z.abs()) as u32
}
/// Make a new BlockPos with the lower coordinates for each axis.
///
/// ```
/// # use azalea_core::position::BlockPos;
/// assert_eq!(
/// BlockPos::min(
/// &BlockPos::new(1, 20, 300),
/// &BlockPos::new(50, 40, 30),
/// ),
/// BlockPos::new(1, 20, 30),
/// );
/// ```
pub fn min(&self, other: &Self) -> Self {
Self {
x: self.x.min(other.x),
y: self.y.min(other.y),
z: self.z.min(other.z),
}
}
/// Make a new BlockPos with the higher coordinates for each axis.
///
/// ```
/// # use azalea_core::position::BlockPos;
/// assert_eq!(
/// BlockPos::max(
/// &BlockPos::new(1, 20, 300),
/// &BlockPos::new(50, 40, 30),
/// ),
/// BlockPos::new(50, 40, 300),
/// );
/// ```
pub fn max(&self, other: &Self) -> Self {
Self {
x: self.x.max(other.x),
y: self.y.max(other.y),
z: self.z.max(other.z),
}
}
}
/// Chunk coordinates are used to represent where a chunk is in the world. You
@ -645,51 +683,6 @@ impl AzaleaWrite for ChunkSectionPos {
}
}
fn parse_three_values<T>(s: &str) -> Result<[T; 3], &'static str>
where
T: FromStr,
<T as FromStr>::Err: fmt::Debug,
{
let parts = s.split_whitespace().collect::<Vec<_>>();
if parts.len() != 3 {
return Err("Expected three values");
}
let x = parts[0].parse().map_err(|_| "Invalid X value")?;
let y = parts[1].parse().map_err(|_| "Invalid Y value")?;
let z = parts[2].parse().map_err(|_| "Invalid Z value")?;
Ok([x, y, z])
}
/// Parses a string in the format "X Y Z" into a BlockPos.
///
/// The input string should contain three integer values separated by spaces,
/// representing the x, y, and z components of the vector respectively.
/// This can be used to parse user input or from `BlockPos::to_string`.
impl FromStr for BlockPos {
type Err = &'static str;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let [x, y, z] = parse_three_values::<i32>(s)?;
Ok(BlockPos { x, y, z })
}
}
/// Parses a string in the format "X Y Z" into a Vec3.
///
/// The input string should contain three floating-point values separated by
/// spaces, representing the x, y, and z components of the vector respectively.
/// This can be used to parse user input or from `Vec3::to_string`.
impl FromStr for Vec3 {
type Err = &'static str;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let [x, y, z] = parse_three_values::<f64>(s)?;
Ok(Vec3 { x, y, z })
}
}
#[cfg(test)]
mod tests {
use super::*;

View file

@ -62,21 +62,15 @@ pub fn clip(chunk_storage: &ChunkStorage, context: ClipContext) -> BlockHitResul
context.from,
context.to,
context,
|context, block_pos| {
|ctx, block_pos| {
let block_state = chunk_storage.get_block_state(block_pos).unwrap_or_default();
// TODO: add fluid stuff to this (see getFluidState in vanilla source)
let block_shape = context.block_shape(block_state);
clip_with_interaction_override(
&context.from,
&context.to,
block_pos,
block_shape,
&block_state,
)
let block_shape = ctx.block_shape(block_state);
clip_with_interaction_override(&ctx.from, &ctx.to, block_pos, block_shape, &block_state)
// let block_distance = if let Some(block_hit_result) =
// block_hit_result { context.from.distance_to_sqr(&
// block_hit_result { context.from.distance_squared_to(&
// block_hit_result.location) } else {
// f64::MAX
// f64::INFINITY
// };
},
|context| {
@ -90,19 +84,6 @@ pub fn clip(chunk_storage: &ChunkStorage, context: ClipContext) -> BlockHitResul
)
}
// default BlockHitResult clipWithInteractionOverride(Vec3 world, Vec3 from,
// BlockPos to, VoxelShape shape, BlockState block) {
// BlockHitResult blockHitResult = shape.clip(world, from, to);
// if (blockHitResult != null) {
// BlockHitResult var7 = block.getInteractionShape(this, to).clip(world,
// from, to); if (var7 != null
// && var7.getLocation().subtract(world).lengthSqr() <
// blockHitResult.getLocation().subtract(world).lengthSqr()) { return
// blockHitResult.withDirection(var7.getDirection()); }
// }
// return blockHitResult;
// }
fn clip_with_interaction_override(
from: &Vec3,
to: &Vec3,
@ -119,8 +100,8 @@ fn clip_with_interaction_override(
let interaction_shape = block_state.shape();
let interaction_hit_result = interaction_shape.clip(from, to, block_pos);
if let Some(interaction_hit_result) = interaction_hit_result {
if interaction_hit_result.location.distance_to_sqr(from)
< block_hit_result.location.distance_to_sqr(from)
if interaction_hit_result.location.distance_squared_to(from)
< block_hit_result.location.distance_squared_to(from)
{
return Some(block_hit_result.with_direction(interaction_hit_result.direction));
}

View file

@ -58,7 +58,7 @@ fn collide(movement: &Vec3, world: &Instance, physics: &azalea_entity::Physics)
// let entity_collisions = world.get_entity_collisions(self,
// entity_bounding_box.expand_towards(movement));
let entity_collisions = Vec::new();
let collided_delta = if movement.length_sqr() == 0.0 {
let collided_delta = if movement.length_squared() == 0.0 {
*movement
} else {
collide_bounding_box(
@ -109,12 +109,16 @@ fn collide(movement: &Vec3, world: &Instance, physics: &azalea_entity::Physics)
entity_collisions.clone(),
)
.add(directly_up_delta);
if target_movement.horizontal_distance_sqr() > step_to_delta.horizontal_distance_sqr() {
if target_movement.horizontal_distance_squared()
> step_to_delta.horizontal_distance_squared()
{
step_to_delta = target_movement;
}
}
if step_to_delta.horizontal_distance_sqr() > collided_delta.horizontal_distance_sqr() {
if step_to_delta.horizontal_distance_squared()
> collided_delta.horizontal_distance_squared()
{
return step_to_delta.add(collide_bounding_box(
&Vec3 {
x: 0.,
@ -162,7 +166,7 @@ pub fn move_colliding(
let collide_result = collide(movement, world, physics);
let move_distance = collide_result.length_sqr();
let move_distance = collide_result.length_squared();
if move_distance > EPSILON {
// TODO: fall damage

View file

@ -423,7 +423,7 @@ impl VoxelShape {
return None;
}
let vector = to - from;
if vector.length_sqr() < EPSILON {
if vector.length_squared() < EPSILON {
return None;
}
let right_after_start = from + &(vector * 0.0001);

View file

@ -370,7 +370,7 @@ impl Connection<ClientboundLoginPacket, ServerboundLoginPacket> {
/// use azalea_protocol::connect::Connection;
/// use azalea_protocol::packets::login::{
/// ClientboundLoginPacket,
/// s_key::ServerboundKey
/// ServerboundKey
/// };
/// use uuid::Uuid;
/// # use azalea_protocol::ServerAddress;

View file

@ -8,6 +8,7 @@ use azalea_chat::{
use azalea_core::bitset::BitSet;
use azalea_crypto::MessageSignature;
use azalea_protocol_macros::ClientboundGamePacket;
use azalea_registry::{ChatType, OptionalRegistry};
use uuid::Uuid;
#[derive(Clone, Debug, AzBuf, ClientboundGamePacket, PartialEq)]
@ -51,23 +52,35 @@ pub enum FilterMask {
PartiallyFiltered(BitSet),
}
#[derive(Copy, Clone, Debug, AzBuf, PartialEq, Eq)]
pub enum ChatType {
Chat = 0,
SayCommand = 1,
MsgCommandIncoming = 2,
MsgCommandOutgoing = 3,
TeamMsgCommandIncoming = 4,
TeamMsgCommandOutgoing = 5,
EmoteCommand = 6,
}
#[derive(Clone, Debug, AzBuf, PartialEq)]
#[derive(Clone, Debug, PartialEq)]
pub struct ChatTypeBound {
pub chat_type: ChatType,
pub name: FormattedText,
pub target_name: Option<FormattedText>,
}
impl AzaleaRead for ChatTypeBound {
fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
let Some(chat_type) = OptionalRegistry::<ChatType>::azalea_read(buf)?.0 else {
return Err(BufReadError::Custom("ChatType cannot be None".to_owned()));
};
let name = FormattedText::azalea_read(buf)?;
let target_name = Option::<FormattedText>::azalea_read(buf)?;
Ok(ChatTypeBound {
chat_type,
name,
target_name,
})
}
}
impl AzaleaWrite for ChatTypeBound {
fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
OptionalRegistry(Some(self.chat_type)).azalea_write(buf)?;
self.name.azalea_write(buf)?;
self.target_name.azalea_write(buf)?;
Ok(())
}
}
// must be in Client
#[derive(Clone, Debug, PartialEq)]
@ -119,29 +132,6 @@ impl ClientboundPlayerChat {
}
}
impl ChatType {
#[must_use]
pub fn chat_translation_key(&self) -> &'static str {
match self {
ChatType::Chat => "chat.type.text",
ChatType::SayCommand => "chat.type.announcement",
ChatType::MsgCommandIncoming => "commands.message.display.incoming",
ChatType::MsgCommandOutgoing => "commands.message.display.outgoing",
ChatType::TeamMsgCommandIncoming => "chat.type.team.text",
ChatType::TeamMsgCommandOutgoing => "chat.type.team.sent",
ChatType::EmoteCommand => "chat.type.emote",
}
}
#[must_use]
pub fn narrator_translation_key(&self) -> &'static str {
match self {
ChatType::EmoteCommand => "chat.type.emote",
_ => "chat.type.text.narrate",
}
}
}
impl AzaleaRead for PackedMessageSignature {
fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
let id = u32::azalea_read_var(buf)?;
@ -168,33 +158,3 @@ impl AzaleaWrite for PackedMessageSignature {
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_read_player_chat_packet() {
let mut bytes = Cursor::new(
&[
55, 186, 28, 76, 92, 167, 177, 75, 188, 158, 200, 179, 191, 227, 16, 171, 145, 0,
0, 4, 116, 101, 115, 116, 0, 0, 1, 140, 178, 225, 89, 103, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 10, 10, 0, 10, 104, 111, 118, 101, 114, 69, 118, 101, 110, 116, 10, 0,
8, 99, 111, 110, 116, 101, 110, 116, 115, 8, 0, 4, 110, 97, 109, 101, 0, 12, 75,
97, 115, 117, 109, 105, 77, 97, 114, 105, 115, 97, 11, 0, 2, 105, 100, 0, 0, 0, 4,
186, 28, 76, 92, 167, 177, 75, 188, 158, 200, 179, 191, 227, 16, 171, 145, 8, 0, 4,
116, 121, 112, 101, 0, 16, 109, 105, 110, 101, 99, 114, 97, 102, 116, 58, 112, 108,
97, 121, 101, 114, 0, 8, 0, 6, 97, 99, 116, 105, 111, 110, 0, 11, 115, 104, 111,
119, 95, 101, 110, 116, 105, 116, 121, 0, 10, 0, 10, 99, 108, 105, 99, 107, 69,
118, 101, 110, 116, 8, 0, 6, 97, 99, 116, 105, 111, 110, 0, 15, 115, 117, 103, 103,
101, 115, 116, 95, 99, 111, 109, 109, 97, 110, 100, 8, 0, 5, 118, 97, 108, 117,
101, 0, 19, 47, 116, 101, 108, 108, 32, 75, 97, 115, 117, 109, 105, 77, 97, 114,
105, 115, 97, 32, 0, 9, 0, 5, 101, 120, 116, 114, 97, 8, 0, 0, 0, 3, 0, 0, 0, 12,
75, 97, 115, 117, 109, 105, 77, 97, 114, 105, 115, 97, 0, 0, 8, 0, 9, 105, 110,
115, 101, 114, 116, 105, 111, 110, 0, 12, 75, 97, 115, 117, 109, 105, 77, 97, 114,
105, 115, 97, 8, 0, 4, 116, 101, 120, 116, 0, 0, 0, 0,
][..],
);
let _packet = ClientboundPlayerChat::azalea_read(&mut bytes).unwrap();
}
}

View file

@ -26,6 +26,7 @@ pub struct PlayerInfoEntry {
pub game_mode: GameMode,
pub display_name: Option<FormattedText>,
pub list_order: i32,
pub update_hat: bool,
pub chat_session: Option<RemoteChatSessionData>,
}
@ -56,6 +57,10 @@ pub struct UpdateDisplayNameAction {
pub display_name: Option<FormattedText>,
}
#[derive(Clone, Debug, AzBuf)]
pub struct UpdateHatAction {
pub update_hat: bool,
}
#[derive(Clone, Debug, AzBuf)]
pub struct UpdateListOrderAction {
#[var]
pub list_order: i32,
@ -97,6 +102,10 @@ impl AzaleaRead for ClientboundPlayerInfoUpdate {
let action = UpdateDisplayNameAction::azalea_read(buf)?;
entry.display_name = action.display_name;
}
if actions.update_hat {
let action = UpdateHatAction::azalea_read(buf)?;
entry.update_hat = action.update_hat;
}
if actions.update_list_order {
let action = UpdateListOrderAction::azalea_read(buf)?;
entry.list_order = action.list_order;
@ -168,6 +177,7 @@ pub struct ActionEnumSet {
pub update_listed: bool,
pub update_latency: bool,
pub update_display_name: bool,
pub update_hat: bool,
pub update_list_order: bool,
}
@ -181,7 +191,8 @@ impl AzaleaRead for ActionEnumSet {
update_listed: set.index(3),
update_latency: set.index(4),
update_display_name: set.index(5),
update_list_order: set.index(6),
update_hat: set.index(6),
update_list_order: set.index(7),
})
}
}
@ -207,9 +218,12 @@ impl AzaleaWrite for ActionEnumSet {
if self.update_display_name {
set.set(5);
}
if self.update_list_order {
if self.update_hat {
set.set(6);
}
if self.update_list_order {
set.set(7);
}
set.azalea_write(buf)?;
Ok(())
}
@ -228,6 +242,7 @@ mod tests {
update_listed: false,
update_latency: true,
update_display_name: false,
update_hat: false,
update_list_order: true,
};
let mut buf = Vec::new();

View file

@ -351,7 +351,7 @@ where
}
if log::log_enabled!(log::Level::Trace) {
const DO_NOT_CUT_OFF_PACKET_LOGS: bool = false;
const DO_NOT_CUT_OFF_PACKET_LOGS: bool = true;
let buf_string: String = {
if !DO_NOT_CUT_OFF_PACKET_LOGS && buf.len() > 500 {

View file

@ -97,3 +97,37 @@ enum JukeboxSong {
CreatorMusicBox => "creator_music_box",
}
}
registry! {
enum ChatType {
Chat => "chat",
SayCommand => "say_command",
MsgCommandIncoming => "msg_command_incoming",
MsgCommandOutgoing => "msg_command_outgoing",
TeamMsgCommandIncoming => "team_msg_command_incoming",
TeamMsgCommandOutgoing => "team_msg_command_outgoing",
EmoteCommand => "emote_command",
}
}
impl ChatType {
#[must_use]
pub fn chat_translation_key(self) -> &'static str {
match self {
ChatType::Chat => "chat.type.text",
ChatType::SayCommand => "chat.type.announcement",
ChatType::MsgCommandIncoming => "commands.message.display.incoming",
ChatType::MsgCommandOutgoing => "commands.message.display.outgoing",
ChatType::TeamMsgCommandIncoming => "chat.type.team.text",
ChatType::TeamMsgCommandOutgoing => "chat.type.team.sent",
ChatType::EmoteCommand => "chat.type.emote",
}
}
#[must_use]
pub fn narrator_translation_key(self) -> &'static str {
match self {
ChatType::EmoteCommand => "chat.type.emote",
_ => "chat.type.text.narrate",
}
}
}

View file

@ -26,7 +26,7 @@ where
/// A registry that might not be present. This is transmitted as a single
/// varint in the protocol.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct OptionalRegistry<T: Registry>(Option<T>);
pub struct OptionalRegistry<T: Registry>(pub Option<T>);
impl<T: Registry> AzaleaRead for OptionalRegistry<T> {
fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {

View file

@ -60,7 +60,7 @@ pub fn debug_render_path_with_particles(
let start_vec3 = start.center();
let end_vec3 = end.center();
let step_count = (start_vec3.distance_to_sqr(&end_vec3).sqrt() * 4.0) as usize;
let step_count = (start_vec3.distance_squared_to(&end_vec3).sqrt() * 4.0) as usize;
let target_block_state = chunks.get_block_state(&movement.target).unwrap_or_default();
let above_target_block_state = chunks

View file

@ -200,7 +200,7 @@ impl Goal for ReachBlockPosGoal {
let max_pick_range = 6;
let actual_pick_range = 4.5;
let distance = (self.pos - n).length_sqr();
let distance = (self.pos - n).length_squared();
if distance > max_pick_range * max_pick_range {
return false;
}

View file

@ -453,7 +453,7 @@ pub fn timeout_movement(
// don't timeout if we're mining
if let Some(mining) = mining {
// also make sure we're close enough to the block that's being mined
if mining.pos.distance_to_sqr(&BlockPos::from(position)) < 6_i32.pow(2) {
if mining.pos.distance_squared_to(&BlockPos::from(position)) < 6_i32.pow(2) {
// also reset the last_node_reached_at so we don't timeout after we finish
// mining
executing_path.last_node_reached_at = Instant::now();

View file

@ -228,9 +228,9 @@ fn execute_descend_move(mut ctx: ExecuteCtx) {
let start_center = start.center();
let center = target.center();
let horizontal_distance_from_target = (center - position).horizontal_distance_sqr().sqrt();
let horizontal_distance_from_target = (center - position).horizontal_distance_squared().sqrt();
let horizontal_distance_from_start =
(start.center() - position).horizontal_distance_sqr().sqrt();
(start.center() - position).horizontal_distance_squared().sqrt();
let dest_ahead = Vec3::new(
start_center.x + (center.x - start_center.x) * 1.5,
@ -402,7 +402,7 @@ fn execute_downward_move(mut ctx: ExecuteCtx) {
let target_center = target.center();
let horizontal_distance_from_target =
(target_center - position).horizontal_distance_sqr().sqrt();
(target_center - position).horizontal_distance_squared().sqrt();
if horizontal_distance_from_target > 0.25 {
ctx.look_at(target_center);

View file

@ -157,7 +157,7 @@ impl ExecuteCtx<'_, '_, '_, '_, '_, '_, '_> {
/// of the current node first.
pub fn mine_while_at_start(&mut self, block: BlockPos) -> bool {
let horizontal_distance_from_start = (self.start.center() - self.position)
.horizontal_distance_sqr()
.horizontal_distance_squared()
.sqrt();
let at_start_position =
BlockPos::from(self.position) == self.start && horizontal_distance_from_start < 0.25;