mirror of
https://github.com/mat-1/azalea.git
synced 2025-08-02 14:26:04 +00:00
fix some clippy::pedantic warnings lol
This commit is contained in:
parent
f924a06e4b
commit
4a6d518473
31 changed files with 103 additions and 106 deletions
|
@ -71,7 +71,7 @@ impl Parse for PropertyWithNameAndDefault {
|
||||||
is_enum = true;
|
is_enum = true;
|
||||||
property_type = first_ident;
|
property_type = first_ident;
|
||||||
let variant = input.parse::<Ident>()?;
|
let variant = input.parse::<Ident>()?;
|
||||||
property_default.extend(quote! { ::#variant })
|
property_default.extend(quote! { ::#variant });
|
||||||
} else if first_ident_string == "true" || first_ident_string == "false" {
|
} else if first_ident_string == "true" || first_ident_string == "false" {
|
||||||
property_type = Ident::new("bool", first_ident.span());
|
property_type = Ident::new("bool", first_ident.span());
|
||||||
} else {
|
} else {
|
||||||
|
@ -386,7 +386,7 @@ pub fn make_block_states(input: TokenStream) -> TokenStream {
|
||||||
// Ident::new(&property.to_string(), proc_macro2::Span::call_site());
|
// Ident::new(&property.to_string(), proc_macro2::Span::call_site());
|
||||||
block_struct_fields.extend(quote! {
|
block_struct_fields.extend(quote! {
|
||||||
pub #name: #struct_name,
|
pub #name: #struct_name,
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let block_name_pascal_case = Ident::new(
|
let block_name_pascal_case = Ident::new(
|
||||||
|
@ -418,8 +418,7 @@ pub fn make_block_states(input: TokenStream) -> TokenStream {
|
||||||
combination
|
combination
|
||||||
.iter()
|
.iter()
|
||||||
.map(|v| v[0..1].to_uppercase() + &v[1..])
|
.map(|v| v[0..1].to_uppercase() + &v[1..])
|
||||||
.collect::<Vec<String>>()
|
.collect::<String>()
|
||||||
.join("")
|
|
||||||
),
|
),
|
||||||
proc_macro2::Span::call_site(),
|
proc_macro2::Span::call_site(),
|
||||||
);
|
);
|
||||||
|
@ -507,20 +506,20 @@ pub fn make_block_states(input: TokenStream) -> TokenStream {
|
||||||
..
|
..
|
||||||
} in properties_with_name
|
} in properties_with_name
|
||||||
{
|
{
|
||||||
block_default_fields.extend(quote! {#name: #property_default,})
|
block_default_fields.extend(quote! { #name: #property_default, });
|
||||||
}
|
}
|
||||||
|
|
||||||
let block_behavior = &block.behavior;
|
let block_behavior = &block.behavior;
|
||||||
let block_id = block.name.to_string();
|
let block_id = block.name.to_string();
|
||||||
|
|
||||||
let from_block_to_state_match = if !block.properties_and_defaults.is_empty() {
|
let from_block_to_state_match = if block.properties_and_defaults.is_empty() {
|
||||||
|
quote! { BlockState::#block_name_pascal_case }
|
||||||
|
} else {
|
||||||
quote! {
|
quote! {
|
||||||
match b {
|
match b {
|
||||||
#from_block_to_state_match_inner
|
#from_block_to_state_match_inner
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
quote! { BlockState::#block_name_pascal_case }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let block_struct = quote! {
|
let block_struct = quote! {
|
||||||
|
|
|
@ -136,7 +136,7 @@ impl<S> CommandDispatcher<S> {
|
||||||
return Ordering::Greater;
|
return Ordering::Greater;
|
||||||
};
|
};
|
||||||
Ordering::Equal
|
Ordering::Equal
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
let best_potential = potentials.into_iter().next().unwrap();
|
let best_potential = potentials.into_iter().next().unwrap();
|
||||||
return Ok(best_potential);
|
return Ok(best_potential);
|
||||||
|
@ -195,7 +195,7 @@ impl<S> CommandDispatcher<S> {
|
||||||
let mut node = self.root.clone();
|
let mut node = self.root.clone();
|
||||||
for name in path {
|
for name in path {
|
||||||
if let Some(child) = node.clone().borrow().child(name) {
|
if let Some(child) = node.clone().borrow().child(name) {
|
||||||
node = child
|
node = child;
|
||||||
} else {
|
} else {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
@ -228,7 +228,7 @@ impl<S> CommandDispatcher<S> {
|
||||||
let mut next: Vec<CommandContext<S>> = vec![];
|
let mut next: Vec<CommandContext<S>> = vec![];
|
||||||
|
|
||||||
while !contexts.is_empty() {
|
while !contexts.is_empty() {
|
||||||
for context in contexts.iter() {
|
for context in &contexts {
|
||||||
let child = &context.child;
|
let child = &context.child;
|
||||||
if let Some(child) = child {
|
if let Some(child) = child {
|
||||||
forked |= child.forks;
|
forked |= child.forks;
|
||||||
|
|
|
@ -31,7 +31,7 @@ impl<M: Clone> Suggestion<M> {
|
||||||
}
|
}
|
||||||
result.push_str(&self.text);
|
result.push_str(&self.text);
|
||||||
if self.range.end() < input.len() {
|
if self.range.end() < input.len() {
|
||||||
result.push_str(&input[self.range.end()..])
|
result.push_str(&input[self.range.end()..]);
|
||||||
}
|
}
|
||||||
|
|
||||||
result
|
result
|
||||||
|
|
|
@ -65,7 +65,9 @@ impl<S> CommandNode<S> {
|
||||||
pub fn get_relevant_nodes(&self, input: &mut StringReader) -> Vec<Rc<RefCell<CommandNode<S>>>> {
|
pub fn get_relevant_nodes(&self, input: &mut StringReader) -> Vec<Rc<RefCell<CommandNode<S>>>> {
|
||||||
let literals = &self.literals;
|
let literals = &self.literals;
|
||||||
|
|
||||||
if !literals.is_empty() {
|
if literals.is_empty() {
|
||||||
|
self.arguments.values().cloned().collect()
|
||||||
|
} else {
|
||||||
let cursor = input.cursor();
|
let cursor = input.cursor();
|
||||||
while input.can_read() && input.peek() != ' ' {
|
while input.can_read() && input.peek() != ' ' {
|
||||||
input.skip();
|
input.skip();
|
||||||
|
@ -83,8 +85,6 @@ impl<S> CommandNode<S> {
|
||||||
} else {
|
} else {
|
||||||
self.arguments.values().cloned().collect()
|
self.arguments.values().cloned().collect()
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
self.arguments.values().cloned().collect()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,9 +39,8 @@ fn read_named_fields(
|
||||||
pub fn create_impl_mcbufreadable(ident: &Ident, data: &Data) -> proc_macro2::TokenStream {
|
pub fn create_impl_mcbufreadable(ident: &Ident, data: &Data) -> proc_macro2::TokenStream {
|
||||||
match data {
|
match data {
|
||||||
syn::Data::Struct(syn::DataStruct { fields, .. }) => {
|
syn::Data::Struct(syn::DataStruct { fields, .. }) => {
|
||||||
let FieldsNamed { named, .. } = match fields {
|
let syn::Fields::Named(FieldsNamed { named, .. }) = fields else {
|
||||||
syn::Fields::Named(f) => f,
|
panic!("#[derive(McBuf)] can only be used on structs with named fields")
|
||||||
_ => panic!("#[derive(McBuf)] can only be used on structs with named fields"),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let (read_fields, read_field_names) = read_named_fields(named);
|
let (read_fields, read_field_names) = read_named_fields(named);
|
||||||
|
@ -102,11 +101,11 @@ pub fn create_impl_mcbufreadable(ident: &Ident, data: &Data) -> proc_macro2::Tok
|
||||||
if f.attrs.iter().any(|attr| attr.path.is_ident("var")) {
|
if f.attrs.iter().any(|attr| attr.path.is_ident("var")) {
|
||||||
reader_code.extend(quote! {
|
reader_code.extend(quote! {
|
||||||
Self::#variant_name(azalea_buf::McBufVarReadable::var_read_from(buf)?),
|
Self::#variant_name(azalea_buf::McBufVarReadable::var_read_from(buf)?),
|
||||||
})
|
});
|
||||||
} else {
|
} else {
|
||||||
reader_code.extend(quote! {
|
reader_code.extend(quote! {
|
||||||
Self::#variant_name(azalea_buf::McBufReadable::read_from(buf)?),
|
Self::#variant_name(azalea_buf::McBufReadable::read_from(buf)?),
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
quote! { Ok(#reader_code) }
|
quote! { Ok(#reader_code) }
|
||||||
|
|
|
@ -40,9 +40,8 @@ fn write_named_fields(
|
||||||
pub fn create_impl_mcbufwritable(ident: &Ident, data: &Data) -> proc_macro2::TokenStream {
|
pub fn create_impl_mcbufwritable(ident: &Ident, data: &Data) -> proc_macro2::TokenStream {
|
||||||
match data {
|
match data {
|
||||||
syn::Data::Struct(syn::DataStruct { fields, .. }) => {
|
syn::Data::Struct(syn::DataStruct { fields, .. }) => {
|
||||||
let FieldsNamed { named, .. } = match fields {
|
let syn::Fields::Named(FieldsNamed { named, .. }) = fields else {
|
||||||
syn::Fields::Named(f) => f,
|
panic!("#[derive(McBuf)] can only be used on structs with named fields")
|
||||||
_ => panic!("#[derive(McBuf)] can only be used on structs with named fields"),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let write_fields =
|
let write_fields =
|
||||||
|
@ -137,11 +136,11 @@ pub fn create_impl_mcbufwritable(ident: &Ident, data: &Data) -> proc_macro2::Tok
|
||||||
if f.attrs.iter().any(|attr| attr.path.is_ident("var")) {
|
if f.attrs.iter().any(|attr| attr.path.is_ident("var")) {
|
||||||
writers_code.extend(quote! {
|
writers_code.extend(quote! {
|
||||||
azalea_buf::McBufVarWritable::var_write_into(#param_ident, buf)?;
|
azalea_buf::McBufVarWritable::var_write_into(#param_ident, buf)?;
|
||||||
})
|
});
|
||||||
} else {
|
} else {
|
||||||
writers_code.extend(quote! {
|
writers_code.extend(quote! {
|
||||||
azalea_buf::McBufWritable::write_into(#param_ident, buf)?;
|
azalea_buf::McBufWritable::write_into(#param_ident, buf)?;
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
match_arms.extend(quote! {
|
match_arms.extend(quote! {
|
||||||
|
|
|
@ -216,9 +216,7 @@ impl<'de> Deserialize<'de> for FormattedText {
|
||||||
"keybind text components aren't yet supported",
|
"keybind text components aren't yet supported",
|
||||||
));
|
));
|
||||||
} else {
|
} else {
|
||||||
let _nbt = if let Some(nbt) = json.get("nbt") {
|
let Some(_nbt) = json.get("nbt") else {
|
||||||
nbt
|
|
||||||
} else {
|
|
||||||
return Err(de::Error::custom(
|
return Err(de::Error::custom(
|
||||||
format!("Don't know how to turn {json} into a FormattedText").as_str(),
|
format!("Don't know how to turn {json} into a FormattedText").as_str(),
|
||||||
));
|
));
|
||||||
|
@ -236,9 +234,8 @@ impl<'de> Deserialize<'de> for FormattedText {
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
if let Some(extra) = json.get("extra") {
|
if let Some(extra) = json.get("extra") {
|
||||||
let extra = match extra.as_array() {
|
let Some(extra) = extra.as_array() else {
|
||||||
Some(r) => r,
|
return Err(de::Error::custom("Extra isn't an array"));
|
||||||
None => return Err(de::Error::custom("Extra isn't an array")),
|
|
||||||
};
|
};
|
||||||
if extra.is_empty() {
|
if extra.is_empty() {
|
||||||
return Err(de::Error::custom("Unexpected empty array of components"));
|
return Err(de::Error::custom("Unexpected empty array of components"));
|
||||||
|
|
|
@ -41,12 +41,9 @@ pub fn legacy_color_code_to_text_component(legacy_color_code: &str) -> TextCompo
|
||||||
while i < legacy_color_code.chars().count() {
|
while i < legacy_color_code.chars().count() {
|
||||||
if legacy_color_code.chars().nth(i).unwrap() == LEGACY_FORMATTING_CODE_SYMBOL {
|
if legacy_color_code.chars().nth(i).unwrap() == LEGACY_FORMATTING_CODE_SYMBOL {
|
||||||
let formatting_code = legacy_color_code.chars().nth(i + 1);
|
let formatting_code = legacy_color_code.chars().nth(i + 1);
|
||||||
let formatting_code = match formatting_code {
|
let Some(formatting_code) = formatting_code else {
|
||||||
Some(formatting_code) => formatting_code,
|
i += 1;
|
||||||
None => {
|
continue;
|
||||||
i += 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
if let Some(formatter) = ChatFormatting::from_code(formatting_code) {
|
if let Some(formatter) = ChatFormatting::from_code(formatting_code) {
|
||||||
if components.is_empty() || !components.last().unwrap().text.is_empty() {
|
if components.is_empty() || !components.last().unwrap().text.is_empty() {
|
||||||
|
|
|
@ -57,12 +57,9 @@ impl TranslatableComponent {
|
||||||
|
|
||||||
while i < template.len() {
|
while i < template.len() {
|
||||||
if template.chars().nth(i).unwrap() == '%' {
|
if template.chars().nth(i).unwrap() == '%' {
|
||||||
let char_after = match template.chars().nth(i + 1) {
|
let Some(char_after) = template.chars().nth(i + 1) else {
|
||||||
Some(c) => c,
|
built_text.push(template.chars().nth(i).unwrap());
|
||||||
None => {
|
break;
|
||||||
built_text.push(template.chars().nth(i).unwrap());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
i += 1;
|
i += 1;
|
||||||
match char_after {
|
match char_after {
|
||||||
|
@ -111,7 +108,7 @@ impl TranslatableComponent {
|
||||||
built_text.push(template.chars().nth(i).unwrap());
|
built_text.push(template.chars().nth(i).unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
i += 1
|
i += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if components.is_empty() {
|
if components.is_empty() {
|
||||||
|
|
|
@ -338,7 +338,7 @@ impl Client {
|
||||||
/// Write a packet directly to the server.
|
/// Write a packet directly to the server.
|
||||||
pub fn write_packet(&self, packet: ServerboundGamePacket) {
|
pub fn write_packet(&self, packet: ServerboundGamePacket) {
|
||||||
self.local_player_mut(&mut self.ecs.lock())
|
self.local_player_mut(&mut self.ecs.lock())
|
||||||
.write_packet(packet)
|
.write_packet(packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Disconnect this client from the server by ending all tasks.
|
/// Disconnect this client from the server by ending all tasks.
|
||||||
|
|
|
@ -111,7 +111,7 @@ impl LocalPlayer {
|
||||||
/// The OwnedReadHalf for the TCP connection is in one of the tasks, so it
|
/// The OwnedReadHalf for the TCP connection is in one of the tasks, so it
|
||||||
/// automatically closes the connection when that's dropped.
|
/// automatically closes the connection when that's dropped.
|
||||||
pub fn disconnect(&self) {
|
pub fn disconnect(&self) {
|
||||||
for task in self.tasks.iter() {
|
for task in &self.tasks {
|
||||||
task.abort();
|
task.abort();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,12 +2,14 @@ use std::{collections::HashSet, io::Cursor, sync::Arc};
|
||||||
|
|
||||||
use azalea_core::{ChunkPos, ResourceLocation, Vec3};
|
use azalea_core::{ChunkPos, ResourceLocation, Vec3};
|
||||||
use azalea_ecs::{
|
use azalea_ecs::{
|
||||||
|
app::{App, Plugin},
|
||||||
component::Component,
|
component::Component,
|
||||||
ecs::Ecs,
|
ecs::Ecs,
|
||||||
|
entity::Entity,
|
||||||
|
event::EventWriter,
|
||||||
query::Changed,
|
query::Changed,
|
||||||
schedule::{IntoSystemDescriptor, SystemSet},
|
schedule::{IntoSystemDescriptor, SystemSet},
|
||||||
system::{Commands, Query, ResMut, SystemState},
|
system::{Commands, Query, ResMut, SystemState},
|
||||||
app::{App, Plugin}, event::EventWriter, entity::Entity,
|
|
||||||
};
|
};
|
||||||
use azalea_protocol::{
|
use azalea_protocol::{
|
||||||
connect::{ReadConnection, WriteConnection},
|
connect::{ReadConnection, WriteConnection},
|
||||||
|
@ -114,7 +116,7 @@ fn handle_packets(ecs: &mut Ecs) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (player_entity, packets) in events_owned {
|
for (player_entity, packets) in events_owned {
|
||||||
for packet in packets.iter() {
|
for packet in &packets {
|
||||||
match packet {
|
match packet {
|
||||||
ClientboundGamePacket::Login(p) => {
|
ClientboundGamePacket::Login(p) => {
|
||||||
debug!("Got login packet");
|
debug!("Got login packet");
|
||||||
|
@ -631,7 +633,7 @@ fn handle_packets(ecs: &mut Ecs) {
|
||||||
partial_world: local_player.partial_world.clone(),
|
partial_world: local_player.partial_world.clone(),
|
||||||
update: Box::new(move |entity| {
|
update: Box::new(move |entity| {
|
||||||
let mut position = entity.get_mut::<Position>().unwrap();
|
let mut position = entity.get_mut::<Position>().unwrap();
|
||||||
**position = new_position
|
**position = new_position;
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
@ -661,7 +663,7 @@ fn handle_packets(ecs: &mut Ecs) {
|
||||||
partial_world: local_player.partial_world.clone(),
|
partial_world: local_player.partial_world.clone(),
|
||||||
update: Box::new(move |entity| {
|
update: Box::new(move |entity| {
|
||||||
let mut position = entity.get_mut::<Position>().unwrap();
|
let mut position = entity.get_mut::<Position>().unwrap();
|
||||||
**position = position.with_delta(&delta)
|
**position = position.with_delta(&delta);
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
@ -690,7 +692,7 @@ fn handle_packets(ecs: &mut Ecs) {
|
||||||
partial_world: local_player.partial_world.clone(),
|
partial_world: local_player.partial_world.clone(),
|
||||||
update: Box::new(move |entity| {
|
update: Box::new(move |entity| {
|
||||||
let mut position = entity.get_mut::<Position>().unwrap();
|
let mut position = entity.get_mut::<Position>().unwrap();
|
||||||
**position = position.with_delta(&delta)
|
**position = position.with_delta(&delta);
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -26,9 +26,7 @@ pub fn get_lit_str(attr_name: Symbol, lit: &syn::Lit) -> syn::Result<&syn::LitSt
|
||||||
} else {
|
} else {
|
||||||
Err(syn::Error::new_spanned(
|
Err(syn::Error::new_spanned(
|
||||||
lit,
|
lit,
|
||||||
format!(
|
format!("expected {attr_name} attribute to be a string: `{attr_name} = \"...\"`"),
|
||||||
"expected {attr_name} attribute to be a string: `{attr_name} = \"...\"`"
|
|
||||||
),
|
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
use proc_macro::Span;
|
use proc_macro::Span;
|
||||||
use syn::{Data, DataStruct, Error, Fields, FieldsNamed};
|
use syn::{Data, DataStruct, Error, Fields, FieldsNamed};
|
||||||
|
|
||||||
/// Get the fields of a data structure if that structure is a struct with named fields;
|
/// Get the fields of a data structure if that structure is a struct with named
|
||||||
/// otherwise, return a compile error that points to the site of the macro invocation.
|
/// fields; otherwise, return a compile error that points to the site of the
|
||||||
|
/// macro invocation.
|
||||||
pub fn get_named_struct_fields(data: &syn::Data) -> syn::Result<&FieldsNamed> {
|
pub fn get_named_struct_fields(data: &syn::Data) -> syn::Result<&FieldsNamed> {
|
||||||
match data {
|
match data {
|
||||||
Data::Struct(DataStruct {
|
Data::Struct(DataStruct {
|
||||||
|
|
|
@ -28,62 +28,62 @@ fn write_compound(
|
||||||
Tag::Byte(value) => {
|
Tag::Byte(value) => {
|
||||||
writer.write_u8(1)?;
|
writer.write_u8(1)?;
|
||||||
write_string(writer, key)?;
|
write_string(writer, key)?;
|
||||||
writer.write_i8(*value)?
|
writer.write_i8(*value)?;
|
||||||
}
|
}
|
||||||
Tag::Short(value) => {
|
Tag::Short(value) => {
|
||||||
writer.write_u8(2)?;
|
writer.write_u8(2)?;
|
||||||
write_string(writer, key)?;
|
write_string(writer, key)?;
|
||||||
writer.write_i16::<BE>(*value)?
|
writer.write_i16::<BE>(*value)?;
|
||||||
}
|
}
|
||||||
Tag::Int(value) => {
|
Tag::Int(value) => {
|
||||||
writer.write_u8(3)?;
|
writer.write_u8(3)?;
|
||||||
write_string(writer, key)?;
|
write_string(writer, key)?;
|
||||||
writer.write_i32::<BE>(*value)?
|
writer.write_i32::<BE>(*value)?;
|
||||||
}
|
}
|
||||||
Tag::Long(value) => {
|
Tag::Long(value) => {
|
||||||
writer.write_u8(4)?;
|
writer.write_u8(4)?;
|
||||||
write_string(writer, key)?;
|
write_string(writer, key)?;
|
||||||
writer.write_i64::<BE>(*value)?
|
writer.write_i64::<BE>(*value)?;
|
||||||
}
|
}
|
||||||
Tag::Float(value) => {
|
Tag::Float(value) => {
|
||||||
writer.write_u8(5)?;
|
writer.write_u8(5)?;
|
||||||
write_string(writer, key)?;
|
write_string(writer, key)?;
|
||||||
writer.write_f32::<BE>(*value)?
|
writer.write_f32::<BE>(*value)?;
|
||||||
}
|
}
|
||||||
Tag::Double(value) => {
|
Tag::Double(value) => {
|
||||||
writer.write_u8(6)?;
|
writer.write_u8(6)?;
|
||||||
write_string(writer, key)?;
|
write_string(writer, key)?;
|
||||||
writer.write_f64::<BE>(*value)?
|
writer.write_f64::<BE>(*value)?;
|
||||||
}
|
}
|
||||||
Tag::ByteArray(value) => {
|
Tag::ByteArray(value) => {
|
||||||
writer.write_u8(7)?;
|
writer.write_u8(7)?;
|
||||||
write_string(writer, key)?;
|
write_string(writer, key)?;
|
||||||
write_bytearray(writer, value)?
|
write_bytearray(writer, value)?;
|
||||||
}
|
}
|
||||||
Tag::String(value) => {
|
Tag::String(value) => {
|
||||||
writer.write_u8(8)?;
|
writer.write_u8(8)?;
|
||||||
write_string(writer, key)?;
|
write_string(writer, key)?;
|
||||||
write_string(writer, value)?
|
write_string(writer, value)?;
|
||||||
}
|
}
|
||||||
Tag::List(value) => {
|
Tag::List(value) => {
|
||||||
writer.write_u8(9)?;
|
writer.write_u8(9)?;
|
||||||
write_string(writer, key)?;
|
write_string(writer, key)?;
|
||||||
write_list(writer, value)?
|
write_list(writer, value)?;
|
||||||
}
|
}
|
||||||
Tag::Compound(value) => {
|
Tag::Compound(value) => {
|
||||||
writer.write_u8(10)?;
|
writer.write_u8(10)?;
|
||||||
write_string(writer, key)?;
|
write_string(writer, key)?;
|
||||||
write_compound(writer, value, true)?
|
write_compound(writer, value, true)?;
|
||||||
}
|
}
|
||||||
Tag::IntArray(value) => {
|
Tag::IntArray(value) => {
|
||||||
writer.write_u8(11)?;
|
writer.write_u8(11)?;
|
||||||
write_string(writer, key)?;
|
write_string(writer, key)?;
|
||||||
write_intarray(writer, value)?
|
write_intarray(writer, value)?;
|
||||||
}
|
}
|
||||||
Tag::LongArray(value) => {
|
Tag::LongArray(value) => {
|
||||||
writer.write_u8(12)?;
|
writer.write_u8(12)?;
|
||||||
write_string(writer, key)?;
|
write_string(writer, key)?;
|
||||||
write_longarray(writer, value)?
|
write_longarray(writer, value)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,7 +64,7 @@ impl DiscreteVoxelShape {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn for_all_boxes(&self, consumer: impl IntLineConsumer, swap: bool) {
|
pub fn for_all_boxes(&self, consumer: impl IntLineConsumer, swap: bool) {
|
||||||
BitSetDiscreteVoxelShape::for_all_boxes(self, consumer, swap)
|
BitSetDiscreteVoxelShape::for_all_boxes(self, consumer, swap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -539,7 +539,7 @@ impl VoxelShape {
|
||||||
x_coords[var7 as usize],
|
x_coords[var7 as usize],
|
||||||
y_coords[var8 as usize],
|
y_coords[var8 as usize],
|
||||||
z_coords[var9 as usize],
|
z_coords[var9 as usize],
|
||||||
)
|
);
|
||||||
},
|
},
|
||||||
true,
|
true,
|
||||||
);
|
);
|
||||||
|
|
|
@ -71,9 +71,8 @@ impl<'a> Iterator for BlockCollisions<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let chunk = self.get_chunk(item.pos.x, item.pos.z);
|
let chunk = self.get_chunk(item.pos.x, item.pos.z);
|
||||||
let chunk = match chunk {
|
let Some(chunk) = chunk else {
|
||||||
Some(chunk) => chunk,
|
continue
|
||||||
None => continue,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let pos = item.pos;
|
let pos = item.pos;
|
||||||
|
|
|
@ -3,19 +3,17 @@ use quote::quote;
|
||||||
use syn::{
|
use syn::{
|
||||||
self, braced,
|
self, braced,
|
||||||
parse::{Parse, ParseStream, Result},
|
parse::{Parse, ParseStream, Result},
|
||||||
parse_macro_input, DeriveInput, FieldsNamed, Ident, LitInt, Token,
|
parse_macro_input, DeriveInput, Ident, LitInt, Token,
|
||||||
};
|
};
|
||||||
|
|
||||||
fn as_packet_derive(input: TokenStream, state: proc_macro2::TokenStream) -> TokenStream {
|
fn as_packet_derive(input: TokenStream, state: proc_macro2::TokenStream) -> TokenStream {
|
||||||
let DeriveInput { ident, data, .. } = parse_macro_input!(input);
|
let DeriveInput { ident, data, .. } = parse_macro_input!(input);
|
||||||
|
|
||||||
let fields = match &data {
|
let syn::Data::Struct(syn::DataStruct { fields, .. }) = &data else {
|
||||||
syn::Data::Struct(syn::DataStruct { fields, .. }) => fields,
|
panic!("#[derive(*Packet)] can only be used on structs")
|
||||||
_ => panic!("#[derive(*Packet)] can only be used on structs"),
|
|
||||||
};
|
};
|
||||||
let FieldsNamed { named: _, .. } = match fields {
|
let syn::Fields::Named(_) = fields else {
|
||||||
syn::Fields::Named(f) => f,
|
panic!("#[derive(*Packet)] can only be used on structs with named fields")
|
||||||
_ => panic!("#[derive(*Packet)] can only be used on structs with named fields"),
|
|
||||||
};
|
};
|
||||||
let variant_name = variant_name_from(&ident);
|
let variant_name = variant_name_from(&ident);
|
||||||
|
|
||||||
|
|
|
@ -128,7 +128,7 @@ pub fn registry(input: TokenStream) -> TokenStream {
|
||||||
|
|
||||||
// Display that uses registry ids
|
// Display that uses registry ids
|
||||||
let mut display_items = quote! {};
|
let mut display_items = quote! {};
|
||||||
for item in input.items.iter() {
|
for item in &input.items {
|
||||||
let name = &item.name;
|
let name = &item.name;
|
||||||
let id = &item.id;
|
let id = &item.id;
|
||||||
display_items.extend(quote! {
|
display_items.extend(quote! {
|
||||||
|
|
|
@ -263,7 +263,7 @@ impl Chunk {
|
||||||
// TODO: make sure the section exists
|
// TODO: make sure the section exists
|
||||||
let section = &mut self.sections[section_index as usize];
|
let section = &mut self.sections[section_index as usize];
|
||||||
let chunk_section_pos = ChunkSectionBlockPos::from(pos);
|
let chunk_section_pos = ChunkSectionBlockPos::from(pos);
|
||||||
section.set(chunk_section_pos, state)
|
section.set(chunk_section_pos, state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,7 @@ impl AttributeInstance {
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
if let AttributeModifierOperation::MultiplyTotal = modifier.operation {
|
if let AttributeModifierOperation::MultiplyTotal = modifier.operation {
|
||||||
total *= 1.0 + modifier.amount
|
total *= 1.0 + modifier.amount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
total
|
total
|
||||||
|
|
|
@ -30,7 +30,7 @@ use uuid::Uuid;
|
||||||
pub struct MinecraftEntityId(pub u32);
|
pub struct MinecraftEntityId(pub u32);
|
||||||
impl std::hash::Hash for MinecraftEntityId {
|
impl std::hash::Hash for MinecraftEntityId {
|
||||||
fn hash<H: std::hash::Hasher>(&self, hasher: &mut H) {
|
fn hash<H: std::hash::Hasher>(&self, hasher: &mut H) {
|
||||||
hasher.write_u32(self.0)
|
hasher.write_u32(self.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl nohash_hasher::IsEnabled for MinecraftEntityId {}
|
impl nohash_hasher::IsEnabled for MinecraftEntityId {}
|
||||||
|
|
|
@ -87,7 +87,7 @@ impl PalettedContainer {
|
||||||
/// want `.set` instead.
|
/// want `.set` instead.
|
||||||
pub fn set_at_index(&mut self, index: usize, value: u32) {
|
pub fn set_at_index(&mut self, index: usize, value: u32) {
|
||||||
let paletted_value = self.id_for(value);
|
let paletted_value = self.id_for(value);
|
||||||
self.storage.set(index, paletted_value as u64)
|
self.storage.set(index, paletted_value as u64);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the id at the given coordinates and return the previous id
|
/// Sets the id at the given coordinates and return the previous id
|
||||||
|
|
|
@ -95,7 +95,7 @@ pub fn deduplicate_entities(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
error!("Entity was inserted into a world that doesn't exist.")
|
error!("Entity was inserted into a world that doesn't exist.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,10 +2,11 @@ use azalea_core::Vec3;
|
||||||
use azalea_ecs::{
|
use azalea_ecs::{
|
||||||
app::{App, Plugin},
|
app::{App, Plugin},
|
||||||
component::Component,
|
component::Component,
|
||||||
|
entity::Entity,
|
||||||
event::EventReader,
|
event::EventReader,
|
||||||
schedule::IntoSystemDescriptor,
|
schedule::IntoSystemDescriptor,
|
||||||
schedule::SystemSet,
|
schedule::SystemSet,
|
||||||
system::Query, entity::Entity,
|
system::Query,
|
||||||
};
|
};
|
||||||
use azalea_world::entity::{set_rotation, Jumping, Physics, Position};
|
use azalea_world::entity::{set_rotation, Jumping, Physics, Position};
|
||||||
use iyes_loopless::prelude::*;
|
use iyes_loopless::prelude::*;
|
||||||
|
@ -95,8 +96,8 @@ fn look_at_listener(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the (y_rot, x_rot) that would make a client at `current` be looking
|
/// Return the (`y_rot`, `x_rot`) that would make a client at `current` be
|
||||||
/// at `target`.
|
/// looking at `target`.
|
||||||
fn direction_looking_at(current: &Vec3, target: &Vec3) -> (f32, f32) {
|
fn direction_looking_at(current: &Vec3, target: &Vec3) -> (f32, f32) {
|
||||||
// borrowed from mineflayer's Bot.lookAt because i didn't want to do math
|
// borrowed from mineflayer's Bot.lookAt because i didn't want to do math
|
||||||
let delta = target - current;
|
let delta = target - current;
|
||||||
|
|
|
@ -47,6 +47,7 @@ where
|
||||||
Fut: Future<Output = Result<(), anyhow::Error>> + Send + 'static,
|
Fut: Future<Output = Result<(), anyhow::Error>> + Send + 'static,
|
||||||
{
|
{
|
||||||
/// Start building a client that can join the world.
|
/// Start building a client that can join the world.
|
||||||
|
#[must_use]
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
// we create the app here so plugins can add onto it.
|
// we create the app here so plugins can add onto it.
|
||||||
|
@ -63,11 +64,13 @@ where
|
||||||
/// You can only have one client handler, calling this again will replace
|
/// You can only have one client handler, calling this again will replace
|
||||||
/// the old client handler function (you can have a client handler and swarm
|
/// the old client handler function (you can have a client handler and swarm
|
||||||
/// handler separately though).
|
/// handler separately though).
|
||||||
|
#[must_use]
|
||||||
pub fn set_handler(mut self, handler: HandleFn<Fut, S>) -> Self {
|
pub fn set_handler(mut self, handler: HandleFn<Fut, S>) -> Self {
|
||||||
self.handler = Some(handler);
|
self.handler = Some(handler);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
/// Add a plugin to the client's ECS.
|
/// Add a plugin to the client's ECS.
|
||||||
|
#[must_use]
|
||||||
pub fn add_plugin<T: Plugin>(mut self, plugin: T) -> Self {
|
pub fn add_plugin<T: Plugin>(mut self, plugin: T) -> Self {
|
||||||
self.app.add_plugin(plugin);
|
self.app.add_plugin(plugin);
|
||||||
self
|
self
|
||||||
|
@ -85,9 +88,8 @@ where
|
||||||
account: Account,
|
account: Account,
|
||||||
address: impl TryInto<ServerAddress>,
|
address: impl TryInto<ServerAddress>,
|
||||||
) -> Result<(), StartError> {
|
) -> Result<(), StartError> {
|
||||||
let address = match address.try_into() {
|
let Ok(address) = address.try_into() else {
|
||||||
Ok(address) => address,
|
return Err(StartError::InvalidAddress)
|
||||||
Err(_) => return Err(StartError::InvalidAddress),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let (bot, mut rx) = Client::join(&account, address).await?;
|
let (bot, mut rx) = Client::join(&account, address).await?;
|
||||||
|
|
|
@ -49,7 +49,7 @@ impl PathfinderClientExt for azalea_client::Client {
|
||||||
self.ecs.lock().send_event(GotoEvent {
|
self.ecs.lock().send_event(GotoEvent {
|
||||||
entity: self.entity,
|
entity: self.entity,
|
||||||
goal: Box::new(goal),
|
goal: Box::new(goal),
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub struct GotoEvent {
|
pub struct GotoEvent {
|
||||||
|
@ -101,7 +101,7 @@ fn goto_listener(
|
||||||
.get(world_name)
|
.get(world_name)
|
||||||
.expect("Entity tried to pathfind but the entity isn't in a valid world");
|
.expect("Entity tried to pathfind but the entity isn't in a valid world");
|
||||||
let world = world_lock.read();
|
let world = world_lock.read();
|
||||||
for possible_move in possible_moves.iter() {
|
for possible_move in &possible_moves {
|
||||||
edges.push(Edge {
|
edges.push(Edge {
|
||||||
target: possible_move.next_node(node),
|
target: possible_move.next_node(node),
|
||||||
cost: possible_move.cost(&world, node),
|
cost: possible_move.cost(&world, node),
|
||||||
|
@ -143,9 +143,7 @@ fn tick_execute_path(
|
||||||
) {
|
) {
|
||||||
for (entity, mut pathfinder, position, physics) in &mut query {
|
for (entity, mut pathfinder, position, physics) in &mut query {
|
||||||
loop {
|
loop {
|
||||||
let target = if let Some(target) = pathfinder.path.front() {
|
let Some(target) = pathfinder.path.front() else {
|
||||||
target
|
|
||||||
} else {
|
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let center = target.pos.center();
|
let center = target.pos.center();
|
||||||
|
@ -207,6 +205,7 @@ pub trait Goal {
|
||||||
impl Node {
|
impl Node {
|
||||||
/// Returns whether the entity is at the node and should start going to the
|
/// Returns whether the entity is at the node and should start going to the
|
||||||
/// next node.
|
/// next node.
|
||||||
|
#[must_use]
|
||||||
pub fn is_reached(&self, position: &Position, physics: &Physics) -> bool {
|
pub fn is_reached(&self, position: &Position, physics: &Physics) -> bool {
|
||||||
// println!(
|
// println!(
|
||||||
// "entity.delta.y: {} {:?}=={:?}, self.vertical_vel={:?}",
|
// "entity.delta.y: {} {:?}=={:?}, self.vertical_vel={:?}",
|
||||||
|
|
|
@ -3,9 +3,9 @@
|
||||||
//!
|
//!
|
||||||
//! Future optimization attempt ideas:
|
//! Future optimization attempt ideas:
|
||||||
//! - Use a different priority queue (e.g. fibonacci heap)
|
//! - Use a different priority queue (e.g. fibonacci heap)
|
||||||
//! - Use FxHash instead of the default hasher
|
//! - Use `FxHash` instead of the default hasher
|
||||||
//! - Have `par` be a raw pointer
|
//! - Have `par` be a raw pointer
|
||||||
//! - Try borrowing vs copying the Node in several places (like state_mut)
|
//! - Try borrowing vs copying the Node in several places (like `state_mut`)
|
||||||
//! - Store edge costs in their own map
|
//! - Store edge costs in their own map
|
||||||
|
|
||||||
use priority_queue::DoublePriorityQueue;
|
use priority_queue::DoublePriorityQueue;
|
||||||
|
@ -260,9 +260,7 @@ impl<
|
||||||
// identify a path from sstart to sgoal using the parent pointers
|
// identify a path from sstart to sgoal using the parent pointers
|
||||||
let mut target = self.state(&self.goal).par;
|
let mut target = self.state(&self.goal).par;
|
||||||
while !(Some(self.start) == target) {
|
while !(Some(self.start) == target) {
|
||||||
let this_target = if let Some(this_target) = target {
|
let Some(this_target) = target else {
|
||||||
this_target
|
|
||||||
} else {
|
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
// hunter follows path from start to goal;
|
// hunter follows path from start to goal;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
//! Implements SwarmEvent::Chat
|
//! Implements `SwarmEvent::Chat`.
|
||||||
|
|
||||||
// How the chat event works (to avoid firing the event multiple times):
|
// How the chat event works (to avoid firing the event multiple times):
|
||||||
// ---
|
// ---
|
||||||
|
@ -14,7 +14,7 @@
|
||||||
// messages from the queue that are before that index.
|
// messages from the queue that are before that index.
|
||||||
|
|
||||||
use azalea_client::{packet_handling::ChatReceivedEvent, ChatPacket, LocalPlayer};
|
use azalea_client::{packet_handling::ChatReceivedEvent, ChatPacket, LocalPlayer};
|
||||||
use azalea_ecs::app::{Plugin, App};
|
use azalea_ecs::app::{App, Plugin};
|
||||||
use azalea_ecs::{
|
use azalea_ecs::{
|
||||||
component::Component,
|
component::Component,
|
||||||
entity::Entity,
|
entity::Entity,
|
||||||
|
|
|
@ -87,6 +87,7 @@ where
|
||||||
SS: Default + Send + Sync + Clone + Component + 'static,
|
SS: Default + Send + Sync + Clone + Component + 'static,
|
||||||
{
|
{
|
||||||
/// Start creating the swarm.
|
/// Start creating the swarm.
|
||||||
|
#[must_use]
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
// we create the app here so plugins can add onto it.
|
// we create the app here so plugins can add onto it.
|
||||||
|
@ -108,6 +109,7 @@ where
|
||||||
/// Use [`Self::add_account`] to only add one account. If you want the
|
/// Use [`Self::add_account`] to only add one account. If you want the
|
||||||
/// clients to have different default states, add them one at a time with
|
/// clients to have different default states, add them one at a time with
|
||||||
/// [`Self::add_account_with_state`].
|
/// [`Self::add_account_with_state`].
|
||||||
|
#[must_use]
|
||||||
pub fn add_accounts(mut self, accounts: Vec<Account>) -> Self {
|
pub fn add_accounts(mut self, accounts: Vec<Account>) -> Self {
|
||||||
for account in accounts {
|
for account in accounts {
|
||||||
self = self.add_account(account);
|
self = self.add_account(account);
|
||||||
|
@ -119,11 +121,13 @@ where
|
||||||
///
|
///
|
||||||
/// This will make the state for this client be the default, use
|
/// This will make the state for this client be the default, use
|
||||||
/// [`Self::add_account_with_state`] to avoid that.
|
/// [`Self::add_account_with_state`] to avoid that.
|
||||||
|
#[must_use]
|
||||||
pub fn add_account(self, account: Account) -> Self {
|
pub fn add_account(self, account: Account) -> Self {
|
||||||
self.add_account_with_state(account, S::default())
|
self.add_account_with_state(account, S::default())
|
||||||
}
|
}
|
||||||
/// Add an account with a custom initial state. Use just
|
/// Add an account with a custom initial state. Use just
|
||||||
/// [`Self::add_account`] to use the Default implementation for the state.
|
/// [`Self::add_account`] to use the Default implementation for the state.
|
||||||
|
#[must_use]
|
||||||
pub fn add_account_with_state(mut self, account: Account, state: S) -> Self {
|
pub fn add_account_with_state(mut self, account: Account, state: S) -> Self {
|
||||||
self.accounts.push(account);
|
self.accounts.push(account);
|
||||||
self.states.push(state);
|
self.states.push(state);
|
||||||
|
@ -136,6 +140,7 @@ where
|
||||||
/// You can only have one client handler, calling this again will replace
|
/// You can only have one client handler, calling this again will replace
|
||||||
/// the old client handler function (you can have a client handler and swarm
|
/// the old client handler function (you can have a client handler and swarm
|
||||||
/// handler separately though).
|
/// handler separately though).
|
||||||
|
#[must_use]
|
||||||
pub fn set_handler(mut self, handler: HandleFn<Fut, S>) -> Self {
|
pub fn set_handler(mut self, handler: HandleFn<Fut, S>) -> Self {
|
||||||
self.handler = Some(handler);
|
self.handler = Some(handler);
|
||||||
self
|
self
|
||||||
|
@ -146,12 +151,14 @@ where
|
||||||
/// You can only have one swarm handler, calling this again will replace
|
/// You can only have one swarm handler, calling this again will replace
|
||||||
/// the old swarm handler function (you can have a client handler and swarm
|
/// the old swarm handler function (you can have a client handler and swarm
|
||||||
/// handler separately though).
|
/// handler separately though).
|
||||||
|
#[must_use]
|
||||||
pub fn set_swarm_handler(mut self, handler: SwarmHandleFn<SwarmFut, SS>) -> Self {
|
pub fn set_swarm_handler(mut self, handler: SwarmHandleFn<SwarmFut, SS>) -> Self {
|
||||||
self.swarm_handler = Some(handler);
|
self.swarm_handler = Some(handler);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add a plugin to the swarm.
|
/// Add a plugin to the swarm.
|
||||||
|
#[must_use]
|
||||||
pub fn add_plugin<T: Plugin>(mut self, plugin: T) -> Self {
|
pub fn add_plugin<T: Plugin>(mut self, plugin: T) -> Self {
|
||||||
self.app.add_plugin(plugin);
|
self.app.add_plugin(plugin);
|
||||||
self
|
self
|
||||||
|
@ -162,11 +169,13 @@ where
|
||||||
/// By default, every bot will connect at the same time. If you set this
|
/// By default, every bot will connect at the same time. If you set this
|
||||||
/// field, however, the bots will wait for the previous one to have
|
/// field, however, the bots will wait for the previous one to have
|
||||||
/// connected and *then* they'll wait the given duration.
|
/// connected and *then* they'll wait the given duration.
|
||||||
|
#[must_use]
|
||||||
pub fn join_delay(mut self, delay: std::time::Duration) -> Self {
|
pub fn join_delay(mut self, delay: std::time::Duration) -> Self {
|
||||||
self.join_delay = Some(delay);
|
self.join_delay = Some(delay);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
fn add_default_swarm_plugins(self) -> Self {
|
fn add_default_swarm_plugins(self) -> Self {
|
||||||
self.add_plugin(chat::SwarmChatPlugin)
|
self.add_plugin(chat::SwarmChatPlugin)
|
||||||
.add_plugin(events::SwarmPlugin)
|
.add_plugin(events::SwarmPlugin)
|
||||||
|
@ -413,6 +422,10 @@ pub enum SwarmStartError {
|
||||||
impl Swarm {
|
impl Swarm {
|
||||||
/// Add a new account to the swarm. You can remove it later by calling
|
/// Add a new account to the swarm. You can remove it later by calling
|
||||||
/// [`Client::disconnect`].
|
/// [`Client::disconnect`].
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
///
|
||||||
|
/// Returns an `Err` if the bot could not do a handshake successfully.
|
||||||
pub async fn add<S: Component + Clone>(
|
pub async fn add<S: Component + Clone>(
|
||||||
&mut self,
|
&mut self,
|
||||||
account: &Account,
|
account: &Account,
|
||||||
|
@ -444,8 +457,6 @@ impl Swarm {
|
||||||
let cloned_bot = bot.clone();
|
let cloned_bot = bot.clone();
|
||||||
let owned_account = account.clone();
|
let owned_account = account.clone();
|
||||||
let swarm_tx = self.swarm_tx.clone();
|
let swarm_tx = self.swarm_tx.clone();
|
||||||
// send the init event immediately so it's the first thing we get
|
|
||||||
swarm_tx.send(SwarmEvent::Init).unwrap();
|
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
while let Some(event) = rx.recv().await {
|
while let Some(event) = rx.recv().await {
|
||||||
// we can't handle events here (since we can't copy the handler),
|
// we can't handle events here (since we can't copy the handler),
|
||||||
|
|
Loading…
Add table
Reference in a new issue