mirror of
https://github.com/mat-1/azalea.git
synced 2024-09-19 22:52:32 +00:00
Merge branch 'main' of https://github.com/mat-1/azalea into main
This commit is contained in:
commit
ca00dbab12
44 changed files with 258 additions and 163 deletions
|
@ -1,5 +1,4 @@
|
|||
//! Tell Mojang you're joining a multiplayer server.
|
||||
//!
|
||||
use serde::Deserialize;
|
||||
use serde_json::json;
|
||||
use thiserror::Error;
|
||||
|
|
|
@ -324,7 +324,8 @@ pub fn make_block_states(input: TokenStream) -> TokenStream {
|
|||
|
||||
let mut properties_with_name: Vec<PropertyWithNameAndDefault> =
|
||||
Vec::with_capacity(block.properties_and_defaults.len());
|
||||
// Used to determine the index of the property so we can optionally add a number to it
|
||||
// Used to determine the index of the property so we can optionally add a number
|
||||
// to it
|
||||
let mut previous_names: Vec<String> = Vec::new();
|
||||
for property in &block.properties_and_defaults {
|
||||
let index: Option<usize> = if block
|
||||
|
@ -343,10 +344,12 @@ pub fn make_block_states(input: TokenStream) -> TokenStream {
|
|||
} else {
|
||||
None
|
||||
};
|
||||
// ```ignore
|
||||
// let mut property_name = property_struct_names_to_names
|
||||
// .get(&property.property_type.to_string())
|
||||
// .unwrap_or_else(|| panic!("Property '{}' is bad", property.property_type))
|
||||
// .clone();
|
||||
// ```
|
||||
let mut property_name = property_struct_names_to_names
|
||||
.get(&property.name.to_string())
|
||||
.cloned()
|
||||
|
|
|
@ -260,7 +260,8 @@ impl<S> CommandDispatcher<S> {
|
|||
// consumer.on_command_complete(context, true, value);
|
||||
successful_forks += 1;
|
||||
|
||||
// TODO: allow context_command to error and handle those errors
|
||||
// TODO: allow context_command to error and handle those
|
||||
// errors
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -45,14 +45,16 @@ impl<S> Clone for CommandNode<S> {
|
|||
}
|
||||
|
||||
impl<S> CommandNode<S> {
|
||||
/// Gets the literal, or panics. You should use match if you're not certain about the type.
|
||||
/// Gets the literal, or panics. You should use match if you're not certain
|
||||
/// about the type.
|
||||
pub fn literal(&self) -> &Literal {
|
||||
match self.value {
|
||||
ArgumentBuilderType::Literal(ref literal) => literal,
|
||||
_ => panic!("CommandNode::literal() called on non-literal node"),
|
||||
}
|
||||
}
|
||||
/// Gets the argument, or panics. You should use match if you're not certain about the type.
|
||||
/// Gets the argument, or panics. You should use match if you're not certain
|
||||
/// about the type.
|
||||
pub fn argument(&self) -> &Argument {
|
||||
match self.value {
|
||||
ArgumentBuilderType::Argument(ref argument) => argument,
|
||||
|
|
|
@ -92,7 +92,8 @@ fn read_utf_with_len(buf: &mut Cursor<&[u8]>, max_length: u32) -> Result<String,
|
|||
}
|
||||
|
||||
// fast varints modified from https://github.com/luojia65/mc-varint/blob/master/src/lib.rs#L67
|
||||
/// Read a single varint from the reader and return the value, along with the number of bytes read
|
||||
/// Read a single varint from the reader and return the value, along with the
|
||||
/// number of bytes read
|
||||
// pub async fn read_varint_async(
|
||||
// reader: &mut (dyn AsyncRead + Unpin + Send),
|
||||
// ) -> Result<i32, BufReadError> {
|
||||
|
|
|
@ -61,8 +61,8 @@ impl Component {
|
|||
/// [ANSI string](https://en.wikipedia.org/wiki/ANSI_escape_code), so you
|
||||
/// can print it to your terminal and get styling.
|
||||
///
|
||||
/// This is technically a shortcut for [`Component::to_ansi_custom_style`] with a
|
||||
/// default [`Style`] colored white.
|
||||
/// This is technically a shortcut for [`Component::to_ansi_custom_style`]
|
||||
/// with a default [`Style`] colored white.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -166,8 +166,9 @@ impl<'de> Deserialize<'de> for Component {
|
|||
.ok_or_else(|| de::Error::custom("\"with\" must be an array"))?;
|
||||
let mut with_array = Vec::with_capacity(with.len());
|
||||
for item in with {
|
||||
// if it's a string component with no styling and no siblings, just add a string to with_array
|
||||
// otherwise add the component to the array
|
||||
// if it's a string component with no styling and no siblings, just add a
|
||||
// string to with_array otherwise add the component
|
||||
// to the array
|
||||
let c = Component::deserialize(item).map_err(de::Error::custom)?;
|
||||
if let Component::Text(text_component) = c {
|
||||
if text_component.base.siblings.is_empty()
|
||||
|
@ -253,7 +254,8 @@ impl<'de> Deserialize<'de> for Component {
|
|||
));
|
||||
}
|
||||
let json_array = json.as_array().unwrap();
|
||||
// the first item in the array is the one that we're gonna return, the others are siblings
|
||||
// the first item in the array is the one that we're gonna return, the others
|
||||
// are siblings
|
||||
let mut component = Component::deserialize(&json_array[0]).map_err(de::Error::custom)?;
|
||||
for i in 1..json_array.len() {
|
||||
component.append(
|
||||
|
|
|
@ -435,7 +435,8 @@ impl Style {
|
|||
if !before.underlined.unwrap_or(false) && after.underlined.unwrap_or(false) {
|
||||
ansi_codes.push_str(Ansi::UNDERLINED);
|
||||
}
|
||||
// if strikethrough used to be false/default and now it's true, set strikethrough
|
||||
// if strikethrough used to be false/default and now it's true, set
|
||||
// strikethrough
|
||||
if !before.strikethrough.unwrap_or(false) && after.strikethrough.unwrap_or(false) {
|
||||
ansi_codes.push_str(Ansi::STRIKETHROUGH);
|
||||
}
|
||||
|
|
|
@ -27,13 +27,16 @@ impl Serialize for TextComponent {
|
|||
const LEGACY_FORMATTING_CODE_SYMBOL: char = '§';
|
||||
|
||||
/// Convert a legacy color code string into a Component
|
||||
/// Technically in Minecraft this is done when displaying the text, but AFAIK it's the same as just doing it in TextComponent
|
||||
/// Technically in Minecraft this is done when displaying the text, but AFAIK
|
||||
/// it's the same as just doing it in TextComponent
|
||||
pub fn legacy_color_code_to_text_component(legacy_color_code: &str) -> TextComponent {
|
||||
let mut components: Vec<TextComponent> = Vec::with_capacity(1);
|
||||
// iterate over legacy_color_code, if it starts with LEGACY_COLOR_CODE_SYMBOL then read the next character and get the style from that
|
||||
// otherwise, add the character to the text
|
||||
// iterate over legacy_color_code, if it starts with LEGACY_COLOR_CODE_SYMBOL
|
||||
// then read the next character and get the style from that otherwise, add
|
||||
// the character to the text
|
||||
|
||||
// we don't use a normal for loop since we need to be able to skip after reading the formatter code symbol
|
||||
// we don't use a normal for loop since we need to be able to skip after reading
|
||||
// the formatter code symbol
|
||||
let mut i = 0;
|
||||
while i < legacy_color_code.chars().count() {
|
||||
if legacy_color_code.chars().nth(i).unwrap() == LEGACY_FORMATTING_CODE_SYMBOL {
|
||||
|
@ -72,7 +75,8 @@ pub fn legacy_color_code_to_text_component(legacy_color_code: &str) -> TextCompo
|
|||
return TextComponent::new("".to_string());
|
||||
}
|
||||
|
||||
// create the final component by using the first one as the base, and then adding the rest as siblings
|
||||
// create the final component by using the first one as the base, and then
|
||||
// adding the rest as siblings
|
||||
let mut final_component = components.remove(0);
|
||||
for component in components {
|
||||
final_component.base.siblings.push(component.get());
|
||||
|
|
|
@ -104,7 +104,8 @@ impl Account {
|
|||
AuthOpts::Microsoft { email } => {
|
||||
let new_account = Account::microsoft(email).await?;
|
||||
let access_token = self
|
||||
.access_token.as_ref()
|
||||
.access_token
|
||||
.as_ref()
|
||||
.expect("Access token should always be set for Microsoft accounts");
|
||||
let new_access_token = new_account
|
||||
.access_token
|
||||
|
|
|
@ -112,7 +112,8 @@ pub struct Client {
|
|||
|
||||
#[derive(Default)]
|
||||
pub struct PhysicsState {
|
||||
/// Minecraft only sends a movement packet either after 20 ticks or if the player moved enough. This is that tick counter.
|
||||
/// Minecraft only sends a movement packet either after 20 ticks or if the
|
||||
/// player moved enough. This is that tick counter.
|
||||
pub position_remainder: u32,
|
||||
pub was_sprinting: bool,
|
||||
// Whether we're going to try to start sprinting this tick. Equivalent to
|
||||
|
@ -383,8 +384,8 @@ impl Client {
|
|||
/// Start the protocol and game tick loop.
|
||||
#[doc(hidden)]
|
||||
pub fn start_tasks(&self, tx: Sender<Event>) {
|
||||
// if you get an error right here that means you're doing something with locks wrong
|
||||
// read the error to see where the issue is
|
||||
// if you get an error right here that means you're doing something with locks
|
||||
// wrong read the error to see where the issue is
|
||||
// you might be able to just drop the lock or put it in its own scope to fix
|
||||
|
||||
let mut tasks = self.tasks.lock();
|
||||
|
@ -789,7 +790,8 @@ impl Client {
|
|||
if let Some(mut entity) = world.entity_mut(p.id) {
|
||||
entity.apply_metadata(&p.packed_items.0);
|
||||
} else {
|
||||
// warn!("Server sent an entity data packet for an entity id ({}) that we don't know about", p.id);
|
||||
// warn!("Server sent an entity data packet for an entity id
|
||||
// ({}) that we don't know about", p.id);
|
||||
}
|
||||
}
|
||||
ClientboundGamePacket::UpdateAttributes(_p) => {
|
||||
|
@ -1041,7 +1043,8 @@ impl Client {
|
|||
/// of the client's world.
|
||||
///
|
||||
/// # Panics
|
||||
/// Panics if the client has not received the login packet yet. You can check this with [`Client::logged_in`].
|
||||
/// Panics if the client has not received the login packet yet. You can
|
||||
/// check this with [`Client::logged_in`].
|
||||
pub fn world(&self) -> Arc<WeakWorld> {
|
||||
let world_name = self.world_name.read();
|
||||
let world_name = world_name
|
||||
|
@ -1086,8 +1089,9 @@ impl Client {
|
|||
self.world_name.read().is_some()
|
||||
}
|
||||
|
||||
/// Tell the server we changed our game options (i.e. render distance, main hand).
|
||||
/// If this is not set before the login packet, the default will be sent.
|
||||
/// Tell the server we changed our game options (i.e. render distance, main
|
||||
/// hand). If this is not set before the login packet, the default will
|
||||
/// be sent.
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// # use azalea_client::{Client, ClientInformation};
|
||||
|
|
|
@ -37,8 +37,8 @@ impl Client {
|
|||
pub(crate) async fn send_position(&mut self) -> Result<(), MovePlayerError> {
|
||||
let packet = {
|
||||
self.send_sprinting_if_needed().await?;
|
||||
// TODO: the camera being able to be controlled by other entities isn't implemented yet
|
||||
// if !self.is_controlled_camera() { return };
|
||||
// TODO: the camera being able to be controlled by other entities isn't
|
||||
// implemented yet if !self.is_controlled_camera() { return };
|
||||
|
||||
let mut physics_state = self.physics_state.lock();
|
||||
|
||||
|
@ -54,7 +54,8 @@ impl Client {
|
|||
|
||||
physics_state.position_remainder += 1;
|
||||
|
||||
// boolean sendingPosition = Mth.lengthSquared(xDelta, yDelta, zDelta) > Mth.square(2.0E-4D) || this.positionReminder >= 20;
|
||||
// boolean sendingPosition = Mth.lengthSquared(xDelta, yDelta, zDelta) >
|
||||
// Mth.square(2.0E-4D) || this.positionReminder >= 20;
|
||||
let sending_position = ((x_delta.powi(2) + y_delta.powi(2) + z_delta.powi(2))
|
||||
> 2.0e-4f64.powi(2))
|
||||
|| physics_state.position_remainder >= 20;
|
||||
|
@ -155,7 +156,8 @@ impl Client {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
// Set our current position to the provided Vec3, potentially clipping through blocks.
|
||||
// Set our current position to the provided Vec3, potentially clipping through
|
||||
// blocks.
|
||||
pub async fn set_position(&mut self, new_pos: Vec3) -> Result<(), MovePlayerError> {
|
||||
let player_entity_id = *self.entity_id.read();
|
||||
let mut world_lock = self.world.write();
|
||||
|
@ -198,7 +200,8 @@ impl Client {
|
|||
}
|
||||
|
||||
// TODO: food data and abilities
|
||||
// let has_enough_food_to_sprint = self.food_data().food_level || self.abilities().may_fly;
|
||||
// let has_enough_food_to_sprint = self.food_data().food_level ||
|
||||
// self.abilities().may_fly;
|
||||
let has_enough_food_to_sprint = true;
|
||||
|
||||
// TODO: double tapping w to sprint i think
|
||||
|
@ -223,7 +226,8 @@ impl Client {
|
|||
player_entity.ai_step();
|
||||
}
|
||||
|
||||
/// Update the impulse from self.move_direction. The multipler is used for sneaking.
|
||||
/// Update the impulse from self.move_direction. The multipler is used for
|
||||
/// sneaking.
|
||||
pub(crate) fn tick_controls(&mut self, multiplier: Option<f32>) {
|
||||
let mut physics_state = self.physics_state.lock();
|
||||
|
||||
|
|
|
@ -77,7 +77,8 @@ impl BitSet {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns the maximum potential items in the BitSet. This will be divisible by 64.
|
||||
/// Returns the maximum potential items in the BitSet. This will be
|
||||
/// divisible by 64.
|
||||
fn len(&self) -> usize {
|
||||
self.data.len() * 64
|
||||
}
|
||||
|
|
|
@ -49,7 +49,8 @@ impl GameType {
|
|||
}
|
||||
|
||||
pub fn short_name(&self) -> &'static str {
|
||||
// TODO: these should be translated TranslatableComponent("selectWorld.gameMode." + string2)
|
||||
// TODO: these should be translated
|
||||
// TranslatableComponent("selectWorld.gameMode." + string2)
|
||||
match self {
|
||||
GameType::Survival => "Survival",
|
||||
GameType::Creative => "Creative",
|
||||
|
@ -59,7 +60,8 @@ impl GameType {
|
|||
}
|
||||
|
||||
pub fn long_name(&self) -> &'static str {
|
||||
// TODO: These should be translated TranslatableComponent("gameMode." + string2);
|
||||
// TODO: These should be translated TranslatableComponent("gameMode." +
|
||||
// string2);
|
||||
match self {
|
||||
GameType::Survival => "Survival Mode",
|
||||
GameType::Creative => "Creative Mode",
|
||||
|
@ -92,7 +94,8 @@ impl McBufWritable for GameType {
|
|||
}
|
||||
}
|
||||
|
||||
/// Rust doesn't let us `impl McBufReadable for Option<GameType>` so we have to make a new type :(
|
||||
/// Rust doesn't let us `impl McBufReadable for Option<GameType>` so we have to
|
||||
/// make a new type :(
|
||||
#[derive(Hash, Copy, Clone, Debug)]
|
||||
pub struct OptionalGameType(Option<GameType>);
|
||||
|
||||
|
|
|
@ -126,7 +126,8 @@ pub struct BlockPos {
|
|||
vec3_impl!(BlockPos, i32);
|
||||
|
||||
impl BlockPos {
|
||||
/// Get the absolute center of a block position by adding 0.5 to each coordinate.
|
||||
/// Get the absolute center of a block position by adding 0.5 to each
|
||||
/// coordinate.
|
||||
pub fn center(&self) -> Vec3 {
|
||||
Vec3 {
|
||||
x: self.x as f64 + 0.5,
|
||||
|
@ -176,7 +177,8 @@ impl ChunkBlockPos {
|
|||
}
|
||||
}
|
||||
|
||||
/// The coordinates of a block inside a chunk section. Each coordinate must be in the range [0, 15].
|
||||
/// The coordinates of a block inside a chunk section. Each coordinate must be
|
||||
/// in the range [0, 15].
|
||||
#[derive(Clone, Debug, Default, PartialEq, Eq)]
|
||||
pub struct ChunkSectionBlockPos {
|
||||
pub x: u8,
|
||||
|
|
|
@ -45,7 +45,8 @@ pub fn encrypt(public_key: &[u8], nonce: &[u8]) -> Result<EncryptResult, String>
|
|||
// generate a random 16-byte shared secret, to be used with the AES/CFB8
|
||||
// stream cipher.
|
||||
let secret_key = generate_secret_key();
|
||||
// let hash = hex_digest(&digest_data(server_id.as_bytes(), public_key, &secret_key));
|
||||
// let hash = hex_digest(&digest_data(server_id.as_bytes(), public_key,
|
||||
// &secret_key));
|
||||
|
||||
// this.keybytes = Crypt.encryptUsingKey(publicKey, secretKey.getEncoded());
|
||||
// this.nonce = Crypt.encryptUsingKey(publicKey, arrby);
|
||||
|
|
|
@ -18,8 +18,8 @@ use std::{collections::HashMap, fs::File};
|
|||
// let mut file = File::open("en_us.json").unwrap();
|
||||
// let mut contents = String::new();
|
||||
// file.read_to_string(&mut contents).unwrap();
|
||||
// let en_us: HashMap<String, String> = serde_json::from_str(&contents).unwrap();
|
||||
// Language { storage: en_us }
|
||||
// let en_us: HashMap<String, String> =
|
||||
// serde_json::from_str(&contents).unwrap(); Language { storage: en_us }
|
||||
// }
|
||||
|
||||
// pub fn get(&self, key: &str) -> Option<&str> {
|
||||
|
|
|
@ -36,25 +36,29 @@ pub trait MovableEntity {
|
|||
impl HasCollision for World {
|
||||
// private Vec3 collide(Vec3 var1) {
|
||||
// AABB var2 = this.getBoundingBox();
|
||||
// List var3 = this.level.getEntityCollisions(this, var2.expandTowards(var1));
|
||||
// Vec3 var4 = var1.lengthSqr() == 0.0D ? var1 : collideBoundingBox(this, var1, var2, this.level, var3);
|
||||
// List var3 = this.level.getEntityCollisions(this,
|
||||
// var2.expandTowards(var1)); Vec3 var4 = var1.lengthSqr() == 0.0D ?
|
||||
// var1 : collideBoundingBox(this, var1, var2, this.level, var3);
|
||||
// boolean var5 = var1.x != var4.x;
|
||||
// boolean var6 = var1.y != var4.y;
|
||||
// boolean var7 = var1.z != var4.z;
|
||||
// boolean var8 = this.onGround || var6 && var1.y < 0.0D;
|
||||
// if (this.maxUpStep > 0.0F && var8 && (var5 || var7)) {
|
||||
// Vec3 var9 = collideBoundingBox(this, new Vec3(var1.x, (double)this.maxUpStep, var1.z), var2, this.level, var3);
|
||||
// Vec3 var10 = collideBoundingBox(this, new Vec3(0.0D, (double)this.maxUpStep, 0.0D), var2.expandTowards(var1.x, 0.0D, var1.z), this.level, var3);
|
||||
// Vec3 var9 = collideBoundingBox(this, new Vec3(var1.x,
|
||||
// (double)this.maxUpStep, var1.z), var2, this.level, var3); Vec3
|
||||
// var10 = collideBoundingBox(this, new Vec3(0.0D, (double)this.maxUpStep,
|
||||
// 0.0D), var2.expandTowards(var1.x, 0.0D, var1.z), this.level, var3);
|
||||
// if (var10.y < (double)this.maxUpStep) {
|
||||
// Vec3 var11 = collideBoundingBox(this, new Vec3(var1.x, 0.0D, var1.z), var2.move(var10), this.level, var3).add(var10);
|
||||
// if (var11.horizontalDistanceSqr() > var9.horizontalDistanceSqr()) {
|
||||
// Vec3 var11 = collideBoundingBox(this, new Vec3(var1.x, 0.0D,
|
||||
// var1.z), var2.move(var10), this.level, var3).add(var10); if
|
||||
// (var11.horizontalDistanceSqr() > var9.horizontalDistanceSqr()) {
|
||||
// var9 = var11;
|
||||
// }
|
||||
// }
|
||||
|
||||
// if (var9.horizontalDistanceSqr() > var4.horizontalDistanceSqr()) {
|
||||
// return var9.add(collideBoundingBox(this, new Vec3(0.0D, -var9.y + var1.y, 0.0D), var2.move(var9), this.level, var3));
|
||||
// }
|
||||
// return var9.add(collideBoundingBox(this, new Vec3(0.0D, -var9.y +
|
||||
// var1.y, 0.0D), var2.move(var9), this.level, var3)); }
|
||||
// }
|
||||
|
||||
// return var4;
|
||||
|
@ -62,7 +66,8 @@ impl HasCollision for World {
|
|||
fn collide(&self, movement: &Vec3, entity: &EntityData) -> Vec3 {
|
||||
let entity_bounding_box = entity.bounding_box;
|
||||
// TODO: get_entity_collisions
|
||||
// let entity_collisions = world.get_entity_collisions(self, entity_bounding_box.expand_towards(movement));
|
||||
// let entity_collisions = world.get_entity_collisions(self,
|
||||
// entity_bounding_box.expand_towards(movement));
|
||||
let entity_collisions = Vec::new();
|
||||
if movement.length_sqr() == 0.0 {
|
||||
*movement
|
||||
|
@ -144,7 +149,8 @@ impl<D: DerefMut<Target = World>> MovableEntity for Entity<'_, D> {
|
|||
// .get_block_state(&block_pos_below)
|
||||
// .expect("Couldn't get block state below");
|
||||
|
||||
// self.check_fall_damage(collide_result.y, on_ground, block_state_below, block_pos_below);
|
||||
// self.check_fall_damage(collide_result.y, on_ground, block_state_below,
|
||||
// block_pos_below);
|
||||
|
||||
// if self.isRemoved() { return; }
|
||||
|
||||
|
@ -159,12 +165,14 @@ impl<D: DerefMut<Target = World>> MovableEntity for Entity<'_, D> {
|
|||
|
||||
if vertical_collision {
|
||||
// blockBelow.updateEntityAfterFallOn(this.level, this);
|
||||
// the default implementation of updateEntityAfterFallOn sets the y movement to 0
|
||||
// the default implementation of updateEntityAfterFallOn sets the y movement to
|
||||
// 0
|
||||
self.delta.y = 0.;
|
||||
}
|
||||
|
||||
if on_ground {
|
||||
// blockBelow.stepOn(this.level, blockPosBelow, blockStateBelow, this);
|
||||
// blockBelow.stepOn(this.level, blockPosBelow, blockStateBelow,
|
||||
// this);
|
||||
}
|
||||
|
||||
// sounds
|
||||
|
@ -172,21 +180,22 @@ impl<D: DerefMut<Target = World>> MovableEntity for Entity<'_, D> {
|
|||
// this.tryCheckInsideBlocks();
|
||||
|
||||
// float var25 = this.getBlockSpeedFactor();
|
||||
// this.setDeltaMovement(this.getDeltaMovement().multiply((double)var25, 1.0D, (double)var25));
|
||||
// if (this.level.getBlockStatesIfLoaded(this.getBoundingBox().deflate(1.0E-6D)).noneMatch((var0) -> {
|
||||
// this.setDeltaMovement(this.getDeltaMovement().multiply((double)var25, 1.0D,
|
||||
// (double)var25)); if (this.level.getBlockStatesIfLoaded(this.
|
||||
// getBoundingBox().deflate(1.0E-6D)).noneMatch((var0) -> {
|
||||
// return var0.is(BlockTags.FIRE) || var0.is(Blocks.LAVA);
|
||||
// })) {
|
||||
// if (this.remainingFireTicks <= 0) {
|
||||
// this.setRemainingFireTicks(-this.getFireImmuneTicks());
|
||||
// }
|
||||
|
||||
// if (this.wasOnFire && (this.isInPowderSnow || this.isInWaterRainOrBubble())) {
|
||||
// this.playEntityOnFireExtinguishedSound();
|
||||
// }
|
||||
// if (this.wasOnFire && (this.isInPowderSnow ||
|
||||
// this.isInWaterRainOrBubble())) { this.
|
||||
// playEntityOnFireExtinguishedSound(); }
|
||||
// }
|
||||
|
||||
// if (this.isOnFire() && (this.isInPowderSnow || this.isInWaterRainOrBubble())) {
|
||||
// this.setRemainingFireTicks(-this.getFireImmuneTicks());
|
||||
// if (this.isOnFire() && (this.isInPowderSnow || this.isInWaterRainOrBubble()))
|
||||
// { this.setRemainingFireTicks(-this.getFireImmuneTicks());
|
||||
// }
|
||||
|
||||
Ok(())
|
||||
|
|
|
@ -143,11 +143,17 @@ impl Shapes {
|
|||
if b.is_empty() {
|
||||
return if op_true_false { a } else { empty_shape() };
|
||||
}
|
||||
// IndexMerger var5 = createIndexMerger(1, a.getCoords(Direction.Axis.X), b.getCoords(Direction.Axis.X), var3, var4);
|
||||
// IndexMerger var6 = createIndexMerger(var5.size() - 1, a.getCoords(Direction.Axis.Y), b.getCoords(Direction.Axis.Y), var3, var4);
|
||||
// IndexMerger var7 = createIndexMerger((var5.size() - 1) * (var6.size() - 1), a.getCoords(Direction.Axis.Z), b.getCoords(Direction.Axis.Z), var3, var4);
|
||||
// BitSetDiscreteVoxelShape var8 = BitSetDiscreteVoxelShape.join(a.shape, b.shape, var5, var6, var7, op);
|
||||
// return (VoxelShape)(var5 instanceof DiscreteCubeMerger && var6 instanceof DiscreteCubeMerger && var7 instanceof DiscreteCubeMerger ? new CubeVoxelShape(var8) : new ArrayVoxelShape(var8, var5.getList(), var6.getList(), var7.getList()));
|
||||
// IndexMerger var5 = createIndexMerger(1, a.getCoords(Direction.Axis.X),
|
||||
// b.getCoords(Direction.Axis.X), var3, var4); IndexMerger var6 =
|
||||
// createIndexMerger(var5.size() - 1, a.getCoords(Direction.Axis.Y),
|
||||
// b.getCoords(Direction.Axis.Y), var3, var4); IndexMerger var7 =
|
||||
// createIndexMerger((var5.size() - 1) * (var6.size() - 1),
|
||||
// a.getCoords(Direction.Axis.Z), b.getCoords(Direction.Axis.Z), var3, var4);
|
||||
// BitSetDiscreteVoxelShape var8 = BitSetDiscreteVoxelShape.join(a.shape,
|
||||
// b.shape, var5, var6, var7, op); return (VoxelShape)(var5 instanceof
|
||||
// DiscreteCubeMerger && var6 instanceof DiscreteCubeMerger && var7 instanceof
|
||||
// DiscreteCubeMerger ? new CubeVoxelShape(var8) : new ArrayVoxelShape(var8,
|
||||
// var5.getList(), var6.getList(), var7.getList()));
|
||||
let var5 = Self::create_index_merger(
|
||||
1,
|
||||
a.get_coords(Axis::X),
|
||||
|
@ -266,8 +272,8 @@ impl Shapes {
|
|||
) -> IndexMerger {
|
||||
let var5 = var1.len() - 1;
|
||||
let var6 = var2.len() - 1;
|
||||
// if (&var1 as &dyn Any).is::<CubePointRange>() && (&var2 as &dyn Any).is::<CubePointRange>()
|
||||
// {
|
||||
// if (&var1 as &dyn Any).is::<CubePointRange>() && (&var2 as &dyn
|
||||
// Any).is::<CubePointRange>() {
|
||||
// return new DiscreteCubeMerger(var0, var5, var6, var3, var4);
|
||||
// let var7: i64 = lcm(var5 as u32, var6 as u32).try_into().unwrap();
|
||||
// // if ((long)var0 * var7 <= 256L) {
|
||||
|
@ -305,8 +311,8 @@ pub enum VoxelShape {
|
|||
impl VoxelShape {
|
||||
// public double min(Direction.Axis var1) {
|
||||
// int var2 = this.shape.firstFull(var1);
|
||||
// return var2 >= this.shape.getSize(var1) ? 1.0D / 0.0 : this.get(var1, var2);
|
||||
// }
|
||||
// return var2 >= this.shape.getSize(var1) ? 1.0D / 0.0 : this.get(var1,
|
||||
// var2); }
|
||||
// public double max(Direction.Axis var1) {
|
||||
// int var2 = this.shape.lastFull(var1);
|
||||
// return var2 <= 0 ? -1.0D / 0.0 : this.get(var1, var2);
|
||||
|
@ -467,8 +473,8 @@ impl VoxelShape {
|
|||
// public VoxelShape optimize() {
|
||||
// VoxelShape[] var1 = new VoxelShape[]{Shapes.empty()};
|
||||
// this.forAllBoxes((var1x, var3, var5, var7, var9, var11) -> {
|
||||
// var1[0] = Shapes.joinUnoptimized(var1[0], Shapes.box(var1x, var3, var5, var7, var9, var11), BooleanOp.OR);
|
||||
// });
|
||||
// var1[0] = Shapes.joinUnoptimized(var1[0], Shapes.box(var1x, var3,
|
||||
// var5, var7, var9, var11), BooleanOp.OR); });
|
||||
// return var1[0];
|
||||
// }
|
||||
fn optimize(&self) -> VoxelShape {
|
||||
|
@ -497,8 +503,9 @@ impl VoxelShape {
|
|||
// DoubleList var3 = this.getCoords(Direction.Axis.Y);
|
||||
// DoubleList var4 = this.getCoords(Direction.Axis.Z);
|
||||
// this.shape.forAllBoxes((var4x, var5, var6, var7, var8, var9) -> {
|
||||
// var1.consume(var2.getDouble(var4x), var3.getDouble(var5), var4.getDouble(var6), var2.getDouble(var7), var3.getDouble(var8), var4.getDouble(var9));
|
||||
// }, true);
|
||||
// var1.consume(var2.getDouble(var4x), var3.getDouble(var5),
|
||||
// var4.getDouble(var6), var2.getDouble(var7), var3.getDouble(var8),
|
||||
// var4.getDouble(var9)); }, true);
|
||||
// }
|
||||
pub fn for_all_boxes(&self, mut consumer: impl FnMut(f64, f64, f64, f64, f64, f64))
|
||||
where
|
||||
|
|
|
@ -69,8 +69,8 @@ impl<'a> BlockCollisions<'a> {
|
|||
// if (this.cachedBlockGetter != null && this.cachedBlockGetterPos == var5) {
|
||||
// return this.cachedBlockGetter;
|
||||
// } else {
|
||||
// BlockGetter var7 = this.collisionGetter.getChunkForCollisions(chunkX, chunkZ);
|
||||
// this.cachedBlockGetter = var7;
|
||||
// BlockGetter var7 = this.collisionGetter.getChunkForCollisions(chunkX,
|
||||
// chunkZ); this.cachedBlockGetter = var7;
|
||||
// this.cachedBlockGetterPos = chunkPosLong;
|
||||
// return var7;
|
||||
// }
|
||||
|
@ -100,7 +100,8 @@ impl<'a> Iterator for BlockCollisions<'a> {
|
|||
.get(&(&pos).into(), self.world.min_y())
|
||||
.unwrap_or(BlockState::Air);
|
||||
|
||||
// TODO: continue if self.only_suffocating_blocks and the block is not suffocating
|
||||
// TODO: continue if self.only_suffocating_blocks and the block is not
|
||||
// suffocating
|
||||
|
||||
let block_shape = block_state.shape();
|
||||
|
||||
|
|
|
@ -61,8 +61,8 @@ impl<D: DerefMut<Target = World>> HasPhysics for Entity<'_, D> {
|
|||
// if (this.shouldDiscardFriction()) {
|
||||
// this.setDeltaMovement(movement.x, yMovement, movement.z);
|
||||
// } else {
|
||||
// this.setDeltaMovement(movement.x * (double)inertia, yMovement * 0.9800000190734863D, movement.z * (double)inertia);
|
||||
// }
|
||||
// this.setDeltaMovement(movement.x * (double)inertia, yMovement *
|
||||
// 0.9800000190734863D, movement.z * (double)inertia); }
|
||||
|
||||
// if should_discard_friction(self) {
|
||||
if false {
|
||||
|
@ -79,7 +79,8 @@ impl<D: DerefMut<Target = World>> HasPhysics for Entity<'_, D> {
|
|||
/// applies air resistance, calls self.travel(), and some other random
|
||||
/// stuff.
|
||||
fn ai_step(&mut self) {
|
||||
// vanilla does movement interpolation here, doesn't really matter much for a bot though
|
||||
// vanilla does movement interpolation here, doesn't really matter much for a
|
||||
// bot though
|
||||
|
||||
if self.delta.x.abs() < 0.003 {
|
||||
self.delta.x = 0.;
|
||||
|
@ -157,17 +158,18 @@ fn handle_relative_friction_and_calculate_movement<D: DerefMut<Target = World>>(
|
|||
.expect("Entity should exist.");
|
||||
// let delta_movement = entity.delta;
|
||||
// ladders
|
||||
// if ((entity.horizontalCollision || entity.jumping) && (entity.onClimbable() || entity.getFeetBlockState().is(Blocks.POWDER_SNOW) && PowderSnowBlock.canEntityWalkOnPowderSnow(entity))) {
|
||||
// var3 = new Vec3(var3.x, 0.2D, var3.z);
|
||||
// }
|
||||
// if ((entity.horizontalCollision || entity.jumping) && (entity.onClimbable()
|
||||
// || entity.getFeetBlockState().is(Blocks.POWDER_SNOW) &&
|
||||
// PowderSnowBlock.canEntityWalkOnPowderSnow(entity))) { var3 = new
|
||||
// Vec3(var3.x, 0.2D, var3.z); }
|
||||
// TODO: powdered snow
|
||||
|
||||
entity.delta
|
||||
}
|
||||
|
||||
// private float getFrictionInfluencedSpeed(float friction) {
|
||||
// return this.onGround ? this.getSpeed() * (0.21600002F / (friction * friction * friction)) : this.flyingSpeed;
|
||||
// }
|
||||
// return this.onGround ? this.getSpeed() * (0.21600002F / (friction *
|
||||
// friction * friction)) : this.flyingSpeed; }
|
||||
fn get_friction_influenced_speed(entity: &EntityData, friction: f32) -> f32 {
|
||||
// TODO: have speed & flying_speed fields in entity
|
||||
if entity.on_ground {
|
||||
|
@ -207,8 +209,8 @@ fn block_jump_factor<D: DerefMut<Target = World>>(entity: &Entity<D>) -> f32 {
|
|||
// return 0.42F * this.getBlockJumpFactor();
|
||||
// }
|
||||
// public double getJumpBoostPower() {
|
||||
// return this.hasEffect(MobEffects.JUMP) ? (double)(0.1F * (float)(this.getEffect(MobEffects.JUMP).getAmplifier() + 1)) : 0.0D;
|
||||
// }
|
||||
// return this.hasEffect(MobEffects.JUMP) ? (double)(0.1F *
|
||||
// (float)(this.getEffect(MobEffects.JUMP).getAmplifier() + 1)) : 0.0D; }
|
||||
fn jump_power<D: DerefMut<Target = World>>(entity: &Entity<D>) -> f32 {
|
||||
0.42 * block_jump_factor(entity)
|
||||
}
|
||||
|
|
|
@ -226,12 +226,14 @@ impl Connection<ClientboundHandshakePacket, ServerboundHandshakePacket> {
|
|||
})
|
||||
}
|
||||
|
||||
/// Change our state from handshake to login. This is the state that is used for logging in.
|
||||
/// Change our state from handshake to login. This is the state that is used
|
||||
/// for logging in.
|
||||
pub fn login(self) -> Connection<ClientboundLoginPacket, ServerboundLoginPacket> {
|
||||
Connection::from(self)
|
||||
}
|
||||
|
||||
/// Change our state from handshake to status. This is the state that is used for pinging the server.
|
||||
/// Change our state from handshake to status. This is the state that is
|
||||
/// used for pinging the server.
|
||||
pub fn status(self) -> Connection<ClientboundStatusPacket, ServerboundStatusPacket> {
|
||||
Connection::from(self)
|
||||
}
|
||||
|
@ -252,14 +254,16 @@ impl Connection<ClientboundLoginPacket, ServerboundLoginPacket> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Set the encryption key that is used to encrypt and decrypt packets. It's the same for both reading and writing.
|
||||
/// Set the encryption key that is used to encrypt and decrypt packets. It's
|
||||
/// the same for both reading and writing.
|
||||
pub fn set_encryption_key(&mut self, key: [u8; 16]) {
|
||||
let (enc_cipher, dec_cipher) = azalea_crypto::create_cipher(&key);
|
||||
self.reader.dec_cipher = Some(dec_cipher);
|
||||
self.writer.enc_cipher = Some(enc_cipher);
|
||||
}
|
||||
|
||||
/// Change our state from login to game. This is the state that's used when you're actually in the game.
|
||||
/// Change our state from login to game. This is the state that's used when
|
||||
/// you're actually in the game.
|
||||
pub fn game(self) -> Connection<ClientboundGamePacket, ServerboundGamePacket> {
|
||||
Connection::from(self)
|
||||
}
|
||||
|
@ -342,7 +346,8 @@ where
|
|||
R1: ProtocolPacket + Debug,
|
||||
W1: ProtocolPacket + Debug,
|
||||
{
|
||||
/// Creates a `Connection` of a type from a `Connection` of another type. Useful for servers or custom packets.
|
||||
/// Creates a `Connection` of a type from a `Connection` of another type.
|
||||
/// Useful for servers or custom packets.
|
||||
pub fn from<R2, W2>(connection: Connection<R1, W1>) -> Connection<R2, W2>
|
||||
where
|
||||
R2: ProtocolPacket + Debug,
|
||||
|
|
|
@ -44,7 +44,8 @@ pub struct ServerAddress {
|
|||
impl<'a> TryFrom<&'a str> for ServerAddress {
|
||||
type Error = String;
|
||||
|
||||
/// Convert a Minecraft server address (host:port, the port is optional) to a ServerAddress
|
||||
/// Convert a Minecraft server address (host:port, the port is optional) to
|
||||
/// a ServerAddress
|
||||
fn try_from(string: &str) -> Result<Self, Self::Error> {
|
||||
if string.is_empty() {
|
||||
return Err("Empty string".to_string());
|
||||
|
|
|
@ -4,7 +4,8 @@ use azalea_protocol_macros::ClientboundGamePacket;
|
|||
use azalea_world::entity::{metadata, EntityData, EntityMetadata};
|
||||
use uuid::Uuid;
|
||||
|
||||
/// This packet is sent by the server when a player comes into visible range, not when a player joins.
|
||||
/// This packet is sent by the server when a player comes into visible range,
|
||||
/// not when a player joins.
|
||||
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
|
||||
pub struct ClientboundAddPlayerPacket {
|
||||
#[var]
|
||||
|
|
|
@ -73,7 +73,8 @@ impl<T: McBufWritable> McBufWritable for BrigadierNumber<T> {
|
|||
pub enum BrigadierString {
|
||||
/// Reads a single word
|
||||
SingleWord = 0,
|
||||
// If it starts with a ", keeps reading until another " (allowing escaping with \). Otherwise behaves the same as SINGLE_WORD
|
||||
// If it starts with a ", keeps reading until another " (allowing escaping with \). Otherwise
|
||||
// behaves the same as SINGLE_WORD
|
||||
QuotablePhrase = 1,
|
||||
// Reads the rest of the content after the cursor. Quotes will not be removed.
|
||||
GreedyPhrase = 2,
|
||||
|
|
|
@ -73,7 +73,8 @@ pub struct MapDecoration {
|
|||
pub decoration_type: DecorationType,
|
||||
pub x: i8,
|
||||
pub y: i8,
|
||||
/// Minecraft does & 15 on this value, azalea-protocol doesn't. I don't think it matters.
|
||||
/// Minecraft does & 15 on this value, azalea-protocol doesn't. I don't
|
||||
/// think it matters.
|
||||
pub rot: i8,
|
||||
pub name: Option<Component>,
|
||||
}
|
||||
|
|
|
@ -83,8 +83,8 @@ pub struct MessageSignatureCache {
|
|||
// }
|
||||
|
||||
// impl PackedSignedMessageBody {
|
||||
// pub fn unpack(&self, unpacker: impl Fn(u32) -> Option<SignedMessageBody>) {}
|
||||
// }
|
||||
// pub fn unpack(&self, unpacker: impl Fn(u32) -> Option<SignedMessageBody>)
|
||||
// {} }
|
||||
|
||||
impl ClientboundPlayerChatPacket {
|
||||
/// Returns the content of the message. If you want to get the Component
|
||||
|
@ -176,7 +176,8 @@ mod tests {
|
|||
use super::*;
|
||||
use std::backtrace::Backtrace;
|
||||
|
||||
// you can remove or update this test if it breaks because mojang changed the structure of the packet again
|
||||
// you can remove or update this test if it breaks because mojang changed the
|
||||
// structure of the packet again
|
||||
#[test]
|
||||
fn test_player_chat_packet() {
|
||||
let data: [u8; 295] = [
|
||||
|
|
|
@ -133,9 +133,9 @@ pub struct CriterionProgress {
|
|||
// parent_id: None,
|
||||
// display: Some(DisplayInfo {
|
||||
// title: Component::from("title".to_string()),
|
||||
// description: Component::from("description".to_string()),
|
||||
// icon: Slot::Empty,
|
||||
// frame: FrameType::Task,
|
||||
// description:
|
||||
// Component::from("description".to_string()), icon:
|
||||
// Slot::Empty, frame: FrameType::Task,
|
||||
// show_toast: true,
|
||||
// hidden: false,
|
||||
// background: None,
|
||||
|
@ -164,7 +164,7 @@ pub struct CriterionProgress {
|
|||
// .collect(),
|
||||
// };
|
||||
// packet.write_into(&mut buf).unwrap();
|
||||
// let packet = ClientboundUpdateAdvancementsPacket::read_from(&mut buf).unwrap();
|
||||
// assert_eq!(packet.reset, true);
|
||||
// let packet = ClientboundUpdateAdvancementsPacket::read_from(&mut
|
||||
// buf).unwrap(); assert_eq!(packet.reset, true);
|
||||
// }
|
||||
// }
|
||||
|
|
|
@ -15,7 +15,8 @@ pub struct ServerboundSetJigsawBlockPacket {
|
|||
pub target: ResourceLocation,
|
||||
pub pool: ResourceLocation,
|
||||
pub final_state: String,
|
||||
pub joint: String, // TODO: Does JigsawBlockEntity$JointType::getSerializedName, may not be implemented
|
||||
pub joint: String, /* TODO: Does JigsawBlockEntity$JointType::getSerializedName, may not be
|
||||
* implemented */
|
||||
}
|
||||
|
||||
pub enum JointType {
|
||||
|
|
|
@ -7,7 +7,8 @@ use crate::read::ReadPacketError;
|
|||
use azalea_buf::{BufReadError, McBufVarReadable, McBufVarWritable, McBufWritable};
|
||||
use std::io::{Cursor, Write};
|
||||
|
||||
// TODO: rename the packet files to just like clientbound_add_entity instead of clientbound_add_entity_packet
|
||||
// TODO: rename the packet files to just like clientbound_add_entity instead of
|
||||
// clientbound_add_entity_packet
|
||||
|
||||
pub const PROTOCOL_VERSION: u32 = 761;
|
||||
|
||||
|
|
|
@ -261,27 +261,30 @@ where
|
|||
// #[cfg(test)]
|
||||
// mod tests {
|
||||
// use super::*;
|
||||
// use crate::packets::game::{clientbound_player_chat_packet::ChatType, ClientboundGamePacket};
|
||||
// use std::io::Cursor;
|
||||
// use crate::packets::game::{clientbound_player_chat_packet::ChatType,
|
||||
// ClientboundGamePacket}; use std::io::Cursor;
|
||||
|
||||
// #[tokio::test]
|
||||
// async fn test_read_packet() {
|
||||
// let mut buf: Cursor<&[u8]> = Cursor::new(&[
|
||||
// 51, 0, 12, 177, 250, 155, 132, 106, 60, 218, 161, 217, 90, 157, 105, 57, 206, 20, 0, 5,
|
||||
// 104, 101, 108, 108, 111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 116,
|
||||
// 123, 34, 101, 120, 116, 114, 97, 34, 58, 91, 123, 34, 99, 111, 108, 111, 114, 34, 58,
|
||||
// 34, 103, 114, 97, 121, 34, 44, 34, 116, 101, 120, 116, 34, 58, 34, 91, 77, 69, 77, 66,
|
||||
// 69, 82, 93, 32, 112, 108, 97, 121, 101, 114, 49, 34, 125, 44, 123, 34, 116, 101, 120,
|
||||
// 116, 34, 58, 34, 32, 34, 125, 44, 123, 34, 99, 111, 108, 111, 114, 34, 58, 34, 103,
|
||||
// 114, 97, 121, 34, 44, 34, 116, 101, 120, 116, 34, 58, 34, 92, 117, 48, 48, 51, 101, 32,
|
||||
// 104, 101, 108, 108, 111, 34, 125, 93, 44, 34, 116, 101, 120, 116, 34, 58, 34, 34, 125,
|
||||
// 0, 7, 64, 123, 34, 101, 120, 116, 114, 97, 34, 58, 91, 123, 34, 99, 111, 108, 111, 114,
|
||||
// 34, 58, 34, 103, 114, 97, 121, 34, 44, 34, 116, 101, 120, 116, 34, 58, 34, 91, 77, 69,
|
||||
// 77, 66, 69, 82, 93, 32, 112, 108, 97, 121, 101, 114, 49, 34, 125, 93, 44, 34, 116, 101,
|
||||
// 120, 116, 34, 58, 34, 34, 125, 0,
|
||||
// ]);
|
||||
// let packet = packet_decoder::<ClientboundGamePacket>(&mut buf).unwrap();
|
||||
// match &packet {
|
||||
// 51, 0, 12, 177, 250, 155, 132, 106, 60, 218, 161, 217, 90, 157,
|
||||
// 105, 57, 206, 20, 0, 5, 104, 101, 108, 108, 111, 0, 0, 0, 0, 0,
|
||||
// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 116, 123, 34, 101, 120,
|
||||
// 116, 114, 97, 34, 58, 91, 123, 34, 99, 111, 108, 111, 114, 34, 58,
|
||||
// 34, 103, 114, 97, 121, 34, 44, 34, 116, 101, 120, 116, 34, 58,
|
||||
// 34, 91, 77, 69, 77, 66, 69, 82, 93, 32, 112, 108, 97, 121, 101,
|
||||
// 114, 49, 34, 125, 44, 123, 34, 116, 101, 120, 116, 34, 58, 34,
|
||||
// 32, 34, 125, 44, 123, 34, 99, 111, 108, 111, 114, 34, 58, 34, 103,
|
||||
// 114, 97, 121, 34, 44, 34, 116, 101, 120, 116, 34, 58, 34, 92,
|
||||
// 117, 48, 48, 51, 101, 32, 104, 101, 108, 108, 111, 34, 125, 93,
|
||||
// 44, 34, 116, 101, 120, 116, 34, 58, 34, 34, 125, 0, 7, 64, 123,
|
||||
// 34, 101, 120, 116, 114, 97, 34, 58, 91, 123, 34, 99, 111, 108, 111, 114,
|
||||
// 34, 58, 34, 103, 114, 97, 121, 34, 44, 34, 116, 101, 120, 116,
|
||||
// 34, 58, 34, 91, 77, 69, 77, 66, 69, 82, 93, 32, 112, 108, 97,
|
||||
// 121, 101, 114, 49, 34, 125, 93, 44, 34, 116, 101, 120, 116, 34,
|
||||
// 58, 34, 34, 125, 0, ]);
|
||||
// let packet = packet_decoder::<ClientboundGamePacket>(&mut
|
||||
// buf).unwrap(); match &packet {
|
||||
// ClientboundGamePacket::PlayerChat(m) => {
|
||||
// assert_eq!(
|
||||
// m.chat_type.chat_type,
|
||||
|
|
|
@ -26,7 +26,9 @@ pub async fn resolve_address(address: &ServerAddress) -> Result<SocketAddr, Reso
|
|||
return Ok(SocketAddr::new(ip, address.port));
|
||||
}
|
||||
|
||||
// we specify Cloudflare instead of the default resolver because trust_dns_resolver has an issue on Windows where it's really slow using the default resolver
|
||||
// we specify Cloudflare instead of the default resolver because
|
||||
// trust_dns_resolver has an issue on Windows where it's really slow using the
|
||||
// default resolver
|
||||
let resolver =
|
||||
TokioAsyncResolver::tokio(ResolverConfig::cloudflare(), ResolverOpts::default()).unwrap();
|
||||
|
||||
|
@ -35,7 +37,8 @@ pub async fn resolve_address(address: &ServerAddress) -> Result<SocketAddr, Reso
|
|||
.srv_lookup(format!("_minecraft._tcp.{}", address.host).as_str())
|
||||
.await;
|
||||
|
||||
// if it resolves that means it's a redirect so we call resolve_address again with the new host
|
||||
// if it resolves that means it's a redirect so we call resolve_address again
|
||||
// with the new host
|
||||
if let Ok(redirect_result) = srv_redirect_result {
|
||||
let redirect_srv = redirect_result
|
||||
.iter()
|
||||
|
|
|
@ -50,9 +50,9 @@ pub struct ChunkStorage {
|
|||
pub chunks: HashMap<ChunkPos, Arc<Mutex<Chunk>>>,
|
||||
}
|
||||
|
||||
/// A single chunk in a world (16*?*16 blocks). This only contains the blocks and biomes. You
|
||||
/// can derive the height of the chunk from the number of sections, but you
|
||||
/// need a [`ChunkStorage`] to get the minimum Y coordinate.
|
||||
/// A single chunk in a world (16*?*16 blocks). This only contains the blocks
|
||||
/// and biomes. You can derive the height of the chunk from the number of
|
||||
/// sections, but you need a [`ChunkStorage`] to get the minimum Y coordinate.
|
||||
#[derive(Debug)]
|
||||
pub struct Chunk {
|
||||
pub sections: Vec<Section>,
|
||||
|
|
|
@ -53,7 +53,8 @@ impl<'d, D: DerefMut<Target = World>> Entity<'d, D> {
|
|||
pub fn set_rotation(&mut self, y_rot: f32, x_rot: f32) {
|
||||
self.y_rot = y_rot % 360.0;
|
||||
self.x_rot = x_rot.clamp(-90.0, 90.0) % 360.0;
|
||||
// TODO: minecraft also sets yRotO and xRotO to xRot and yRot ... but idk what they're used for so
|
||||
// TODO: minecraft also sets yRotO and xRotO to xRot and yRot ... but
|
||||
// idk what they're used for so
|
||||
}
|
||||
|
||||
pub fn move_relative(&mut self, speed: f32, acceleration: &Vec3) {
|
||||
|
@ -116,8 +117,8 @@ impl<'d, D: Deref<Target = World>> Entity<'d, D> {
|
|||
// if (this.level.getBlockState(var5).isAir()) {
|
||||
// BlockPos var6 = var5.below();
|
||||
// BlockState var7 = this.level.getBlockState(var6);
|
||||
// if (var7.is(BlockTags.FENCES) || var7.is(BlockTags.WALLS) || var7.getBlock() instanceof FenceGateBlock) {
|
||||
// return var6;
|
||||
// if (var7.is(BlockTags.FENCES) || var7.is(BlockTags.WALLS) ||
|
||||
// var7.getBlock() instanceof FenceGateBlock) { return var6;
|
||||
// }
|
||||
// }
|
||||
// return var5;
|
||||
|
@ -181,7 +182,8 @@ impl<D: Deref<Target = World>> Deref for Entity<'_, D> {
|
|||
pub struct EntityData {
|
||||
pub uuid: Uuid,
|
||||
/// The position of the entity right now.
|
||||
/// This can be changde with unsafe_move, but the correct way is with world.move_entity
|
||||
/// This can be changde with unsafe_move, but the correct way is with
|
||||
/// world.move_entity
|
||||
pos: Vec3,
|
||||
/// The position of the entity last tick.
|
||||
pub last_pos: Vec3,
|
||||
|
@ -205,7 +207,8 @@ pub struct EntityData {
|
|||
|
||||
/// The width and height of the entity.
|
||||
pub dimensions: EntityDimensions,
|
||||
/// The bounding box of the entity. This is more than just width and height, unlike dimensions.
|
||||
/// The bounding box of the entity. This is more than just width and height,
|
||||
/// unlike dimensions.
|
||||
pub bounding_box: AABB,
|
||||
|
||||
/// Whether the entity will try to jump every tick
|
||||
|
@ -258,7 +261,8 @@ impl EntityData {
|
|||
metadata,
|
||||
|
||||
attributes: AttributeModifiers {
|
||||
// TODO: do the correct defaults for everything, some entities have different defaults
|
||||
// TODO: do the correct defaults for everything, some entities have different
|
||||
// defaults
|
||||
speed: AttributeInstance::new(0.1),
|
||||
},
|
||||
}
|
||||
|
|
|
@ -11,13 +11,20 @@ use uuid::Uuid;
|
|||
|
||||
// How entity updates are processed (to avoid issues with shared worlds)
|
||||
// - each bot contains a map of { entity id: updates received }
|
||||
// - the shared world also contains a canonical "true" updates received for each entity
|
||||
// - when a client loads an entity, its "updates received" is set to the same as the global "updates received"
|
||||
// - when the shared world sees an entity for the first time, the "updates received" is set to 1.
|
||||
// - clients can force the shared "updates received" to 0 to make it so certain entities (i.e. other bots in our swarm) don't get confused and updated by other bots
|
||||
// - when a client gets an update to an entity, we check if our "updates received" is the same as the shared world's "updates received":
|
||||
// if it is, then process the update and increment the client's and shared world's "updates received"
|
||||
// if not, then we simply increment our local "updates received" and do nothing else
|
||||
// - the shared world also contains a canonical "true" updates received for each
|
||||
// entity
|
||||
// - when a client loads an entity, its "updates received" is set to the same as
|
||||
// the global "updates received"
|
||||
// - when the shared world sees an entity for the first time, the "updates
|
||||
// received" is set to 1.
|
||||
// - clients can force the shared "updates received" to 0 to make it so certain
|
||||
// entities (i.e. other bots in our swarm) don't get confused and updated by
|
||||
// other bots
|
||||
// - when a client gets an update to an entity, we check if our "updates
|
||||
// received" is the same as the shared world's "updates received": if it is,
|
||||
// then process the update and increment the client's and shared world's
|
||||
// "updates received" if not, then we simply increment our local "updates
|
||||
// received" and do nothing else
|
||||
|
||||
/// Store a map of entities by ID. To get an iterator over all entities, use
|
||||
/// `storage.shared.read().entities` [`WeakEntityStorage::entities`].
|
||||
|
@ -125,7 +132,8 @@ impl PartialEntityStorage {
|
|||
self.shared.read().data_by_id.contains_key(id)
|
||||
}
|
||||
|
||||
/// Get a reference to an entity by its id, if it's being loaded by this storage.
|
||||
/// Get a reference to an entity by its id, if it's being loaded by this
|
||||
/// storage.
|
||||
#[inline]
|
||||
pub fn limited_get_by_id(&self, id: u32) -> Option<&Arc<EntityData>> {
|
||||
self.data_by_id.get(&id)
|
||||
|
@ -138,10 +146,11 @@ impl PartialEntityStorage {
|
|||
self.data_by_id.get_mut(&id)
|
||||
}
|
||||
|
||||
/// Returns whether we're allowed to update this entity (to prevent two clients in
|
||||
/// a shared world updating it twice), and acknowleges that we WILL update
|
||||
/// it if it's true. Don't call this unless you actually got an entity
|
||||
/// update that all other clients within render distance will get too.
|
||||
/// Returns whether we're allowed to update this entity (to prevent two
|
||||
/// clients in a shared world updating it twice), and acknowleges that
|
||||
/// we WILL update it if it's true. Don't call this unless you actually
|
||||
/// got an entity update that all other clients within render distance
|
||||
/// will get too.
|
||||
pub fn maybe_update(&mut self, id: u32) -> bool {
|
||||
let this_client_updates_received = self.updates_received.get(&id).copied();
|
||||
let shared_updates_received = self.shared.read().updates_received.get(&id).copied();
|
||||
|
@ -302,7 +311,8 @@ impl WeakEntityStorage {
|
|||
);
|
||||
}
|
||||
if self.updates_received.remove(&id).is_none() {
|
||||
// if this happens it means we weren't tracking the updates_received for the client (bad)
|
||||
// if this happens it means we weren't tracking the updates_received for the
|
||||
// client (bad)
|
||||
warn!(
|
||||
"Tried to remove entity with id {id} from updates_received but it was not found."
|
||||
);
|
||||
|
|
|
@ -83,7 +83,8 @@ impl PalettedContainer {
|
|||
.get_and_set(self.get_index(x, y, z), paletted_value as u64) as u32
|
||||
}
|
||||
|
||||
/// Sets the id at the given index and return the previous id. You probably want `.set` instead.
|
||||
/// Sets the id at the given index and return the previous id. You probably
|
||||
/// want `.set` instead.
|
||||
pub fn set_at_index(&mut self, index: usize, value: u32) {
|
||||
let paletted_value = self.id_for(value);
|
||||
self.storage.set(index, paletted_value as u64)
|
||||
|
@ -110,7 +111,8 @@ impl PalettedContainer {
|
|||
// sanity check
|
||||
debug_assert_eq!(storage.size(), self.container_type.size());
|
||||
|
||||
// let palette = new_palette_type.as_empty_palette(1usize << (bits_per_entry as usize));
|
||||
// let palette = new_palette_type.as_empty_palette(1usize << (bits_per_entry as
|
||||
// usize));
|
||||
let palette = new_palette_type.as_empty_palette();
|
||||
PalettedContainer {
|
||||
bits_per_entry,
|
||||
|
@ -197,7 +199,8 @@ pub enum PaletteType {
|
|||
pub enum Palette {
|
||||
/// ID of the corresponding entry in its global palette
|
||||
SingleValue(u32),
|
||||
// in vanilla this keeps a `size` field that might be less than the length, but i'm not sure it's actually needed?
|
||||
// in vanilla this keeps a `size` field that might be less than the length, but i'm not sure
|
||||
// it's actually needed?
|
||||
Linear(Vec<u32>),
|
||||
Hashmap(Vec<u32>),
|
||||
Global,
|
||||
|
|
|
@ -11,7 +11,8 @@ use std::{backtrace::Backtrace, fmt::Debug};
|
|||
use std::{fmt::Formatter, io::Cursor, sync::Arc};
|
||||
use uuid::Uuid;
|
||||
|
||||
/// A world is a collection of chunks and entities. They're called "levels" in Minecraft's source code.
|
||||
/// A world is a collection of chunks and entities. They're called "levels" in
|
||||
/// Minecraft's source code.
|
||||
#[derive(Default)]
|
||||
pub struct World {
|
||||
// we just need to keep a strong reference to `shared` so it doesn't get
|
||||
|
@ -22,7 +23,8 @@ pub struct World {
|
|||
pub entity_storage: PartialEntityStorage,
|
||||
}
|
||||
|
||||
/// A world where the chunks are stored as weak pointers. This is used for shared worlds.
|
||||
/// A world where the chunks are stored as weak pointers. This is used for
|
||||
/// shared worlds.
|
||||
#[derive(Default)]
|
||||
pub struct WeakWorld {
|
||||
pub chunk_storage: Arc<RwLock<WeakChunkStorage>>,
|
||||
|
|
|
@ -38,7 +38,8 @@ const WALK_ONE_BLOCK_COST: f32 = 1.0;
|
|||
|
||||
pub trait Move {
|
||||
fn cost(&self, world: &World, node: &Node) -> f32;
|
||||
/// Returns by how much the entity's position should be changed when this move is executed.
|
||||
/// Returns by how much the entity's position should be changed when this
|
||||
/// move is executed.
|
||||
fn offset(&self) -> BlockPos;
|
||||
fn next_node(&self, node: &Node) -> Node {
|
||||
Node {
|
||||
|
|
|
@ -20,7 +20,8 @@ pub struct MTDStarLite<
|
|||
PredecessorsFn: Fn(&N) -> Vec<Edge<N, W>>,
|
||||
SuccessFn: Fn(&N) -> bool,
|
||||
> {
|
||||
/// Returns a rough estimate of how close we are to the goal. Lower = closer.
|
||||
/// Returns a rough estimate of how close we are to the goal. Lower =
|
||||
/// closer.
|
||||
pub heuristic: HeuristicFn,
|
||||
/// Returns the nodes that can be reached from the given node.
|
||||
pub successors: SuccessorsFn,
|
||||
|
@ -29,7 +30,8 @@ pub struct MTDStarLite<
|
|||
/// can be the same as `successors`.
|
||||
pub predecessors: PredecessorsFn,
|
||||
/// Returns true if the given node is at the goal.
|
||||
/// A simple implementation is to check if the given node is equal to the goal.
|
||||
/// A simple implementation is to check if the given node is equal to the
|
||||
/// goal.
|
||||
pub success: SuccessFn,
|
||||
|
||||
start: N,
|
||||
|
@ -43,7 +45,8 @@ pub struct MTDStarLite<
|
|||
node_states: HashMap<N, NodeState<N, W>>,
|
||||
updated_edge_costs: Vec<ChangedEdge<N, W>>,
|
||||
|
||||
/// This only exists so it can be referenced by `state()` when there's no state.
|
||||
/// This only exists so it can be referenced by `state()` when there's no
|
||||
/// state.
|
||||
default_state: NodeState<N, W>,
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
//! The Azalea prelude. Things that are necessary for a bare-bones bot are re-exported here.
|
||||
//! The Azalea prelude. Things that are necessary for a bare-bones bot are
|
||||
//! re-exported here.
|
||||
|
||||
pub use crate::bot::BotTrait;
|
||||
pub use crate::pathfinder::Trait;
|
||||
|
|
|
@ -86,8 +86,8 @@ pub enum StartError {
|
|||
Join(#[from] azalea_client::JoinError),
|
||||
}
|
||||
|
||||
/// Join a server and start handling events. This function will run forever until
|
||||
/// it gets disconnected from the server.
|
||||
/// Join a server and start handling events. This function will run forever
|
||||
/// until it gets disconnected from the server.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
|
|
@ -111,7 +111,8 @@ impl SwarmState {
|
|||
where
|
||||
S: Send + Sync + Clone + 'static,
|
||||
{
|
||||
// it should never be locked unless we reused the same plugin for two swarms (bad)
|
||||
// it should never be locked unless we reused the same plugin for two swarms
|
||||
// (bad)
|
||||
let mut rx = self.rx.lock().await;
|
||||
while let Some(m) = rx.recv().await {
|
||||
swarm.swarm_tx.send(SwarmEvent::Chat(m)).unwrap();
|
||||
|
|
|
@ -18,8 +18,8 @@ use std::{future::Future, net::SocketAddr, sync::Arc, time::Duration};
|
|||
use thiserror::Error;
|
||||
use tokio::sync::mpsc::{self, UnboundedSender};
|
||||
|
||||
/// A helper macro that generates a [`SwarmPlugins`] struct from a list of objects
|
||||
/// that implement [`SwarmPlugin`].
|
||||
/// A helper macro that generates a [`SwarmPlugins`] struct from a list of
|
||||
/// objects that implement [`SwarmPlugin`].
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// swarm_plugins![azalea_pathfinder::Plugin];
|
||||
|
@ -111,7 +111,8 @@ where
|
|||
pub swarm_state: SS,
|
||||
/// The function that's called every time a bot receives an [`Event`].
|
||||
pub handle: HandleFn<Fut, S>,
|
||||
/// The function that's called every time the swarm receives a [`SwarmEvent`].
|
||||
/// The function that's called every time the swarm receives a
|
||||
/// [`SwarmEvent`].
|
||||
pub swarm_handle: SwarmHandleFn<SwarmFut, S, SS>,
|
||||
|
||||
/// How long we should wait between each bot joining the server. Set to
|
||||
|
@ -342,7 +343,8 @@ impl<S> Swarm<S>
|
|||
where
|
||||
S: Send + Sync + Clone + 'static,
|
||||
{
|
||||
/// Add a new account to the swarm. You can remove it later by calling [`Client::disconnect`].
|
||||
/// Add a new account to the swarm. You can remove it later by calling
|
||||
/// [`Client::disconnect`].
|
||||
pub async fn add(&mut self, account: &Account, state: S) -> Result<Client, JoinError> {
|
||||
let conn = Connection::new(&self.resolved_address).await?;
|
||||
let (conn, game_profile) = Client::handshake(conn, account, &self.address.clone()).await?;
|
||||
|
|
|
@ -13,7 +13,8 @@ type U64Hasher = BuildHasherDefault<NoHashHasher<u64>>;
|
|||
/// A map of plugin ids to [`SwarmPlugin`] trait objects. The client stores
|
||||
/// this so we can keep the state for our [`Swarm`] plugins.
|
||||
///
|
||||
/// If you're using azalea, you should generate this from the `swarm_plugins!` macro.
|
||||
/// If you're using azalea, you should generate this from the `swarm_plugins!`
|
||||
/// macro.
|
||||
#[derive(Clone, Default)]
|
||||
pub struct SwarmPlugins<S> {
|
||||
map: Option<HashMap<TypeId, Box<dyn SwarmPlugin<S>>, U64Hasher>>,
|
||||
|
|
1
rustfmt.toml
Normal file
1
rustfmt.toml
Normal file
|
@ -0,0 +1 @@
|
|||
wrap_comments = true
|
Loading…
Reference in a new issue