1
2
Fork 0
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:
Ubuntu 2023-01-30 20:56:40 +00:00
parent f924a06e4b
commit 4a6d518473
31 changed files with 103 additions and 106 deletions

View file

@ -71,7 +71,7 @@ impl Parse for PropertyWithNameAndDefault {
is_enum = true;
property_type = first_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" {
property_type = Ident::new("bool", first_ident.span());
} else {
@ -386,7 +386,7 @@ pub fn make_block_states(input: TokenStream) -> TokenStream {
// Ident::new(&property.to_string(), proc_macro2::Span::call_site());
block_struct_fields.extend(quote! {
pub #name: #struct_name,
})
});
}
let block_name_pascal_case = Ident::new(
@ -418,8 +418,7 @@ pub fn make_block_states(input: TokenStream) -> TokenStream {
combination
.iter()
.map(|v| v[0..1].to_uppercase() + &v[1..])
.collect::<Vec<String>>()
.join("")
.collect::<String>()
),
proc_macro2::Span::call_site(),
);
@ -507,20 +506,20 @@ pub fn make_block_states(input: TokenStream) -> TokenStream {
..
} 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_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! {
match b {
#from_block_to_state_match_inner
}
}
} else {
quote! { BlockState::#block_name_pascal_case }
};
let block_struct = quote! {

View file

@ -136,7 +136,7 @@ impl<S> CommandDispatcher<S> {
return Ordering::Greater;
};
Ordering::Equal
})
});
}
let best_potential = potentials.into_iter().next().unwrap();
return Ok(best_potential);
@ -195,7 +195,7 @@ impl<S> CommandDispatcher<S> {
let mut node = self.root.clone();
for name in path {
if let Some(child) = node.clone().borrow().child(name) {
node = child
node = child;
} else {
return None;
}
@ -228,7 +228,7 @@ impl<S> CommandDispatcher<S> {
let mut next: Vec<CommandContext<S>> = vec![];
while !contexts.is_empty() {
for context in contexts.iter() {
for context in &contexts {
let child = &context.child;
if let Some(child) = child {
forked |= child.forks;

View file

@ -31,7 +31,7 @@ impl<M: Clone> Suggestion<M> {
}
result.push_str(&self.text);
if self.range.end() < input.len() {
result.push_str(&input[self.range.end()..])
result.push_str(&input[self.range.end()..]);
}
result

View file

@ -65,7 +65,9 @@ impl<S> CommandNode<S> {
pub fn get_relevant_nodes(&self, input: &mut StringReader) -> Vec<Rc<RefCell<CommandNode<S>>>> {
let literals = &self.literals;
if !literals.is_empty() {
if literals.is_empty() {
self.arguments.values().cloned().collect()
} else {
let cursor = input.cursor();
while input.can_read() && input.peek() != ' ' {
input.skip();
@ -83,8 +85,6 @@ impl<S> CommandNode<S> {
} else {
self.arguments.values().cloned().collect()
}
} else {
self.arguments.values().cloned().collect()
}
}

View file

@ -39,9 +39,8 @@ fn read_named_fields(
pub fn create_impl_mcbufreadable(ident: &Ident, data: &Data) -> proc_macro2::TokenStream {
match data {
syn::Data::Struct(syn::DataStruct { fields, .. }) => {
let FieldsNamed { named, .. } = match fields {
syn::Fields::Named(f) => f,
_ => panic!("#[derive(McBuf)] can only be used on structs with named fields"),
let syn::Fields::Named(FieldsNamed { named, .. }) = fields else {
panic!("#[derive(McBuf)] can only be used on structs with named fields")
};
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")) {
reader_code.extend(quote! {
Self::#variant_name(azalea_buf::McBufVarReadable::var_read_from(buf)?),
})
});
} else {
reader_code.extend(quote! {
Self::#variant_name(azalea_buf::McBufReadable::read_from(buf)?),
})
});
}
}
quote! { Ok(#reader_code) }

View file

@ -40,9 +40,8 @@ fn write_named_fields(
pub fn create_impl_mcbufwritable(ident: &Ident, data: &Data) -> proc_macro2::TokenStream {
match data {
syn::Data::Struct(syn::DataStruct { fields, .. }) => {
let FieldsNamed { named, .. } = match fields {
syn::Fields::Named(f) => f,
_ => panic!("#[derive(McBuf)] can only be used on structs with named fields"),
let syn::Fields::Named(FieldsNamed { named, .. }) = fields else {
panic!("#[derive(McBuf)] can only be used on structs with named 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")) {
writers_code.extend(quote! {
azalea_buf::McBufVarWritable::var_write_into(#param_ident, buf)?;
})
});
} else {
writers_code.extend(quote! {
azalea_buf::McBufWritable::write_into(#param_ident, buf)?;
})
});
}
}
match_arms.extend(quote! {

View file

@ -216,9 +216,7 @@ impl<'de> Deserialize<'de> for FormattedText {
"keybind text components aren't yet supported",
));
} else {
let _nbt = if let Some(nbt) = json.get("nbt") {
nbt
} else {
let Some(_nbt) = json.get("nbt") else {
return Err(de::Error::custom(
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") {
let extra = match extra.as_array() {
Some(r) => r,
None => return Err(de::Error::custom("Extra isn't an array")),
let Some(extra) = extra.as_array() else {
return Err(de::Error::custom("Extra isn't an array"));
};
if extra.is_empty() {
return Err(de::Error::custom("Unexpected empty array of components"));

View file

@ -41,12 +41,9 @@ pub fn legacy_color_code_to_text_component(legacy_color_code: &str) -> TextCompo
while i < legacy_color_code.chars().count() {
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 = match formatting_code {
Some(formatting_code) => formatting_code,
None => {
i += 1;
continue;
}
let Some(formatting_code) = formatting_code else {
i += 1;
continue;
};
if let Some(formatter) = ChatFormatting::from_code(formatting_code) {
if components.is_empty() || !components.last().unwrap().text.is_empty() {

View file

@ -57,12 +57,9 @@ impl TranslatableComponent {
while i < template.len() {
if template.chars().nth(i).unwrap() == '%' {
let char_after = match template.chars().nth(i + 1) {
Some(c) => c,
None => {
built_text.push(template.chars().nth(i).unwrap());
break;
}
let Some(char_after) = template.chars().nth(i + 1) else {
built_text.push(template.chars().nth(i).unwrap());
break;
};
i += 1;
match char_after {
@ -111,7 +108,7 @@ impl TranslatableComponent {
built_text.push(template.chars().nth(i).unwrap());
}
i += 1
i += 1;
}
if components.is_empty() {

View file

@ -338,7 +338,7 @@ impl Client {
/// Write a packet directly to the server.
pub fn write_packet(&self, packet: ServerboundGamePacket) {
self.local_player_mut(&mut self.ecs.lock())
.write_packet(packet)
.write_packet(packet);
}
/// Disconnect this client from the server by ending all tasks.

View file

@ -111,7 +111,7 @@ impl LocalPlayer {
/// The OwnedReadHalf for the TCP connection is in one of the tasks, so it
/// automatically closes the connection when that's dropped.
pub fn disconnect(&self) {
for task in self.tasks.iter() {
for task in &self.tasks {
task.abort();
}
}

View file

@ -2,12 +2,14 @@ use std::{collections::HashSet, io::Cursor, sync::Arc};
use azalea_core::{ChunkPos, ResourceLocation, Vec3};
use azalea_ecs::{
app::{App, Plugin},
component::Component,
ecs::Ecs,
entity::Entity,
event::EventWriter,
query::Changed,
schedule::{IntoSystemDescriptor, SystemSet},
system::{Commands, Query, ResMut, SystemState},
app::{App, Plugin}, event::EventWriter, entity::Entity,
};
use azalea_protocol::{
connect::{ReadConnection, WriteConnection},
@ -114,7 +116,7 @@ fn handle_packets(ecs: &mut Ecs) {
}
for (player_entity, packets) in events_owned {
for packet in packets.iter() {
for packet in &packets {
match packet {
ClientboundGamePacket::Login(p) => {
debug!("Got login packet");
@ -631,7 +633,7 @@ fn handle_packets(ecs: &mut Ecs) {
partial_world: local_player.partial_world.clone(),
update: Box::new(move |entity| {
let mut position = entity.get_mut::<Position>().unwrap();
**position = new_position
**position = new_position;
}),
});
} else {
@ -661,7 +663,7 @@ fn handle_packets(ecs: &mut Ecs) {
partial_world: local_player.partial_world.clone(),
update: Box::new(move |entity| {
let mut position = entity.get_mut::<Position>().unwrap();
**position = position.with_delta(&delta)
**position = position.with_delta(&delta);
}),
});
} else {
@ -690,7 +692,7 @@ fn handle_packets(ecs: &mut Ecs) {
partial_world: local_player.partial_world.clone(),
update: Box::new(move |entity| {
let mut position = entity.get_mut::<Position>().unwrap();
**position = position.with_delta(&delta)
**position = position.with_delta(&delta);
}),
});
} else {

View file

@ -26,9 +26,7 @@ pub fn get_lit_str(attr_name: Symbol, lit: &syn::Lit) -> syn::Result<&syn::LitSt
} else {
Err(syn::Error::new_spanned(
lit,
format!(
"expected {attr_name} attribute to be a string: `{attr_name} = \"...\"`"
),
format!("expected {attr_name} attribute to be a string: `{attr_name} = \"...\"`"),
))
}
}

View file

@ -1,8 +1,9 @@
use proc_macro::Span;
use syn::{Data, DataStruct, Error, Fields, FieldsNamed};
/// Get the fields of a data structure if that structure is a struct with named fields;
/// otherwise, return a compile error that points to the site of the macro invocation.
/// Get the fields of a data structure if that structure is a struct with named
/// 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> {
match data {
Data::Struct(DataStruct {

View file

@ -28,62 +28,62 @@ fn write_compound(
Tag::Byte(value) => {
writer.write_u8(1)?;
write_string(writer, key)?;
writer.write_i8(*value)?
writer.write_i8(*value)?;
}
Tag::Short(value) => {
writer.write_u8(2)?;
write_string(writer, key)?;
writer.write_i16::<BE>(*value)?
writer.write_i16::<BE>(*value)?;
}
Tag::Int(value) => {
writer.write_u8(3)?;
write_string(writer, key)?;
writer.write_i32::<BE>(*value)?
writer.write_i32::<BE>(*value)?;
}
Tag::Long(value) => {
writer.write_u8(4)?;
write_string(writer, key)?;
writer.write_i64::<BE>(*value)?
writer.write_i64::<BE>(*value)?;
}
Tag::Float(value) => {
writer.write_u8(5)?;
write_string(writer, key)?;
writer.write_f32::<BE>(*value)?
writer.write_f32::<BE>(*value)?;
}
Tag::Double(value) => {
writer.write_u8(6)?;
write_string(writer, key)?;
writer.write_f64::<BE>(*value)?
writer.write_f64::<BE>(*value)?;
}
Tag::ByteArray(value) => {
writer.write_u8(7)?;
write_string(writer, key)?;
write_bytearray(writer, value)?
write_bytearray(writer, value)?;
}
Tag::String(value) => {
writer.write_u8(8)?;
write_string(writer, key)?;
write_string(writer, value)?
write_string(writer, value)?;
}
Tag::List(value) => {
writer.write_u8(9)?;
write_string(writer, key)?;
write_list(writer, value)?
write_list(writer, value)?;
}
Tag::Compound(value) => {
writer.write_u8(10)?;
write_string(writer, key)?;
write_compound(writer, value, true)?
write_compound(writer, value, true)?;
}
Tag::IntArray(value) => {
writer.write_u8(11)?;
write_string(writer, key)?;
write_intarray(writer, value)?
write_intarray(writer, value)?;
}
Tag::LongArray(value) => {
writer.write_u8(12)?;
write_string(writer, key)?;
write_longarray(writer, value)?
write_longarray(writer, value)?;
}
}
}

View file

@ -64,7 +64,7 @@ impl DiscreteVoxelShape {
}
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);
}
}

View file

@ -539,7 +539,7 @@ impl VoxelShape {
x_coords[var7 as usize],
y_coords[var8 as usize],
z_coords[var9 as usize],
)
);
},
true,
);

View file

@ -71,9 +71,8 @@ impl<'a> Iterator for BlockCollisions<'a> {
}
let chunk = self.get_chunk(item.pos.x, item.pos.z);
let chunk = match chunk {
Some(chunk) => chunk,
None => continue,
let Some(chunk) = chunk else {
continue
};
let pos = item.pos;

View file

@ -3,19 +3,17 @@ use quote::quote;
use syn::{
self, braced,
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 {
let DeriveInput { ident, data, .. } = parse_macro_input!(input);
let fields = match &data {
syn::Data::Struct(syn::DataStruct { fields, .. }) => fields,
_ => panic!("#[derive(*Packet)] can only be used on structs"),
let syn::Data::Struct(syn::DataStruct { fields, .. }) = &data else {
panic!("#[derive(*Packet)] can only be used on structs")
};
let FieldsNamed { named: _, .. } = match fields {
syn::Fields::Named(f) => f,
_ => panic!("#[derive(*Packet)] can only be used on structs with named fields"),
let syn::Fields::Named(_) = fields else {
panic!("#[derive(*Packet)] can only be used on structs with named fields")
};
let variant_name = variant_name_from(&ident);

View file

@ -128,7 +128,7 @@ pub fn registry(input: TokenStream) -> TokenStream {
// Display that uses registry ids
let mut display_items = quote! {};
for item in input.items.iter() {
for item in &input.items {
let name = &item.name;
let id = &item.id;
display_items.extend(quote! {

View file

@ -263,7 +263,7 @@ impl Chunk {
// TODO: make sure the section exists
let section = &mut self.sections[section_index as usize];
let chunk_section_pos = ChunkSectionBlockPos::from(pos);
section.set(chunk_section_pos, state)
section.set(chunk_section_pos, state);
}
}

View file

@ -42,7 +42,7 @@ impl AttributeInstance {
_ => {}
}
if let AttributeModifierOperation::MultiplyTotal = modifier.operation {
total *= 1.0 + modifier.amount
total *= 1.0 + modifier.amount;
}
}
total

View file

@ -30,7 +30,7 @@ use uuid::Uuid;
pub struct MinecraftEntityId(pub u32);
impl std::hash::Hash for MinecraftEntityId {
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 {}

View file

@ -87,7 +87,7 @@ impl PalettedContainer {
/// 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)
self.storage.set(index, paletted_value as u64);
}
/// Sets the id at the given coordinates and return the previous id

View file

@ -95,7 +95,7 @@ pub fn deduplicate_entities(
}
}
} else {
error!("Entity was inserted into a world that doesn't exist.")
error!("Entity was inserted into a world that doesn't exist.");
}
}
}

View file

@ -2,10 +2,11 @@ use azalea_core::Vec3;
use azalea_ecs::{
app::{App, Plugin},
component::Component,
entity::Entity,
event::EventReader,
schedule::IntoSystemDescriptor,
schedule::SystemSet,
system::Query, entity::Entity,
system::Query,
};
use azalea_world::entity::{set_rotation, Jumping, Physics, Position};
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
/// at `target`.
/// Return the (`y_rot`, `x_rot`) that would make a client at `current` be
/// looking at `target`.
fn direction_looking_at(current: &Vec3, target: &Vec3) -> (f32, f32) {
// borrowed from mineflayer's Bot.lookAt because i didn't want to do math
let delta = target - current;

View file

@ -47,6 +47,7 @@ where
Fut: Future<Output = Result<(), anyhow::Error>> + Send + 'static,
{
/// Start building a client that can join the world.
#[must_use]
pub fn new() -> Self {
Self {
// 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
/// the old client handler function (you can have a client handler and swarm
/// handler separately though).
#[must_use]
pub fn set_handler(mut self, handler: HandleFn<Fut, S>) -> Self {
self.handler = Some(handler);
self
}
/// Add a plugin to the client's ECS.
#[must_use]
pub fn add_plugin<T: Plugin>(mut self, plugin: T) -> Self {
self.app.add_plugin(plugin);
self
@ -85,9 +88,8 @@ where
account: Account,
address: impl TryInto<ServerAddress>,
) -> Result<(), StartError> {
let address = match address.try_into() {
Ok(address) => address,
Err(_) => return Err(StartError::InvalidAddress),
let Ok(address) = address.try_into() else {
return Err(StartError::InvalidAddress)
};
let (bot, mut rx) = Client::join(&account, address).await?;

View file

@ -49,7 +49,7 @@ impl PathfinderClientExt for azalea_client::Client {
self.ecs.lock().send_event(GotoEvent {
entity: self.entity,
goal: Box::new(goal),
})
});
}
}
pub struct GotoEvent {
@ -101,7 +101,7 @@ fn goto_listener(
.get(world_name)
.expect("Entity tried to pathfind but the entity isn't in a valid world");
let world = world_lock.read();
for possible_move in possible_moves.iter() {
for possible_move in &possible_moves {
edges.push(Edge {
target: possible_move.next_node(node),
cost: possible_move.cost(&world, node),
@ -143,9 +143,7 @@ fn tick_execute_path(
) {
for (entity, mut pathfinder, position, physics) in &mut query {
loop {
let target = if let Some(target) = pathfinder.path.front() {
target
} else {
let Some(target) = pathfinder.path.front() else {
return;
};
let center = target.pos.center();
@ -207,6 +205,7 @@ pub trait Goal {
impl Node {
/// Returns whether the entity is at the node and should start going to the
/// next node.
#[must_use]
pub fn is_reached(&self, position: &Position, physics: &Physics) -> bool {
// println!(
// "entity.delta.y: {} {:?}=={:?}, self.vertical_vel={:?}",

View file

@ -3,9 +3,9 @@
//!
//! Future optimization attempt ideas:
//! - 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
//! - 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
use priority_queue::DoublePriorityQueue;
@ -260,9 +260,7 @@ impl<
// identify a path from sstart to sgoal using the parent pointers
let mut target = self.state(&self.goal).par;
while !(Some(self.start) == target) {
let this_target = if let Some(this_target) = target {
this_target
} else {
let Some(this_target) = target else {
break;
};
// hunter follows path from start to goal;

View file

@ -1,4 +1,4 @@
//! Implements SwarmEvent::Chat
//! Implements `SwarmEvent::Chat`.
// 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.
use azalea_client::{packet_handling::ChatReceivedEvent, ChatPacket, LocalPlayer};
use azalea_ecs::app::{Plugin, App};
use azalea_ecs::app::{App, Plugin};
use azalea_ecs::{
component::Component,
entity::Entity,

View file

@ -87,6 +87,7 @@ where
SS: Default + Send + Sync + Clone + Component + 'static,
{
/// Start creating the swarm.
#[must_use]
pub fn new() -> Self {
Self {
// 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
/// clients to have different default states, add them one at a time with
/// [`Self::add_account_with_state`].
#[must_use]
pub fn add_accounts(mut self, accounts: Vec<Account>) -> Self {
for account in accounts {
self = self.add_account(account);
@ -119,11 +121,13 @@ where
///
/// This will make the state for this client be the default, use
/// [`Self::add_account_with_state`] to avoid that.
#[must_use]
pub fn add_account(self, account: Account) -> Self {
self.add_account_with_state(account, S::default())
}
/// Add an account with a custom initial state. Use just
/// [`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 {
self.accounts.push(account);
self.states.push(state);
@ -136,6 +140,7 @@ where
/// 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
/// handler separately though).
#[must_use]
pub fn set_handler(mut self, handler: HandleFn<Fut, S>) -> Self {
self.handler = Some(handler);
self
@ -146,12 +151,14 @@ where
/// 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
/// handler separately though).
#[must_use]
pub fn set_swarm_handler(mut self, handler: SwarmHandleFn<SwarmFut, SS>) -> Self {
self.swarm_handler = Some(handler);
self
}
/// Add a plugin to the swarm.
#[must_use]
pub fn add_plugin<T: Plugin>(mut self, plugin: T) -> Self {
self.app.add_plugin(plugin);
self
@ -162,11 +169,13 @@ where
/// 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
/// connected and *then* they'll wait the given duration.
#[must_use]
pub fn join_delay(mut self, delay: std::time::Duration) -> Self {
self.join_delay = Some(delay);
self
}
#[must_use]
fn add_default_swarm_plugins(self) -> Self {
self.add_plugin(chat::SwarmChatPlugin)
.add_plugin(events::SwarmPlugin)
@ -413,6 +422,10 @@ pub enum SwarmStartError {
impl Swarm {
/// Add a new account to the swarm. You can remove it later by calling
/// [`Client::disconnect`].
///
/// # Errors
///
/// Returns an `Err` if the bot could not do a handshake successfully.
pub async fn add<S: Component + Clone>(
&mut self,
account: &Account,
@ -444,8 +457,6 @@ impl Swarm {
let cloned_bot = bot.clone();
let owned_account = account.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 {
while let Some(event) = rx.recv().await {
// we can't handle events here (since we can't copy the handler),