mirror of
https://github.com/mat-1/azalea.git
synced 2025-08-02 06:16:04 +00:00
make handle
cleaner
Arc<Event> -> Event, Arc<Mutex<State>> -> State Items in State now need to have interior mutability (i.e. Arc<Mutex<T>>), but it's a worthwhile tradeoff since it allows the user to customize it for each field
This commit is contained in:
parent
a9ff79a105
commit
2eade86cf7
10 changed files with 114 additions and 85 deletions
|
@ -83,7 +83,7 @@ impl Client {
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
pub async fn chat(&self, message: &str) -> Result<(), std::io::Error> {
|
pub async fn chat(&self, message: &str) -> Result<(), std::io::Error> {
|
||||||
if message.chars().next() == Some('/') {
|
if message.starts_with('/') {
|
||||||
self.send_command_packet(&message[1..]).await
|
self.send_command_packet(&message[1..]).await
|
||||||
} else {
|
} else {
|
||||||
self.send_chat_packet(message).await
|
self.send_chat_packet(message).await
|
||||||
|
|
|
@ -3,9 +3,9 @@ use azalea::{Bot, Client, Event};
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default, Clone)]
|
||||||
struct State {
|
struct State {
|
||||||
pub started: bool,
|
pub started: Arc<Mutex<bool>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
|
@ -16,7 +16,7 @@ async fn main() {
|
||||||
azalea::start(azalea::Options {
|
azalea::start(azalea::Options {
|
||||||
account,
|
account,
|
||||||
address: "localhost",
|
address: "localhost",
|
||||||
state: Arc::new(Mutex::new(State::default())),
|
state: State::default(),
|
||||||
plugins: vec![],
|
plugins: vec![],
|
||||||
handle,
|
handle,
|
||||||
})
|
})
|
||||||
|
@ -24,13 +24,13 @@ async fn main() {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn handle(bot: Client, event: Arc<Event>, state: Arc<Mutex<State>>) {
|
async fn handle(bot: Client, event: Event, state: State) -> anyhow::Result<()> {
|
||||||
match event {
|
match event {
|
||||||
Event::Message(m) => {
|
Event::Chat(m) => {
|
||||||
if m.username == bot.player.username {
|
if m.username == bot.player.username {
|
||||||
return;
|
return Ok(());
|
||||||
};
|
};
|
||||||
if m.message = "go" {
|
if m.content == "go" {
|
||||||
// make sure we only start once
|
// make sure we only start once
|
||||||
let ctx_lock = ctx.lock().unwrap();
|
let ctx_lock = ctx.lock().unwrap();
|
||||||
if ctx_lock.started {
|
if ctx_lock.started {
|
||||||
|
@ -74,4 +74,6 @@ async fn handle(bot: Client, event: Arc<Event>, state: Arc<Mutex<State>>) {
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ async fn main() {
|
||||||
azalea::start(azalea::Options {
|
azalea::start(azalea::Options {
|
||||||
account,
|
account,
|
||||||
address: "localhost",
|
address: "localhost",
|
||||||
state: Arc::new(Mutex::new(State::default())),
|
state: State::default(),
|
||||||
plugins: vec![],
|
plugins: vec![],
|
||||||
handle,
|
handle,
|
||||||
})
|
})
|
||||||
|
@ -20,19 +20,16 @@ async fn main() {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Clone)]
|
||||||
pub struct State {}
|
pub struct State {}
|
||||||
|
|
||||||
async fn handle(bot: Client, event: Arc<Event>, state: Arc<Mutex<State>>) -> anyhow::Result<()> {
|
async fn handle(bot: Client, event: Event, state: State) -> anyhow::Result<()> {
|
||||||
match *event {
|
match event {
|
||||||
Event::Chat(m) => {
|
Event::Chat(m) => {
|
||||||
if m.username == bot.username {
|
if m.username == bot.username {
|
||||||
return Ok(()); // ignore our own messages
|
return Ok(()); // ignore our own messages
|
||||||
};
|
};
|
||||||
bot.chat(m.message).await;
|
bot.chat(m.content).await;
|
||||||
}
|
|
||||||
Event::Kick(m) => {
|
|
||||||
println!(m);
|
|
||||||
bot.reconnect().await.unwrap();
|
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use azalea::{pathfinder, Account, Accounts, Client, Event};
|
use azalea::{pathfinder, Account, Accounts, Client, Event, Swarm};
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
@ -7,31 +7,31 @@ async fn main() {
|
||||||
let accounts = Accounts::new();
|
let accounts = Accounts::new();
|
||||||
|
|
||||||
for i in 0..10 {
|
for i in 0..10 {
|
||||||
accounts.add(Account::offline(format!("bot{}", i)));
|
accounts.add(Account::offline(&format!("bot{}", i)));
|
||||||
}
|
}
|
||||||
|
|
||||||
azalea::start_group(azalea::GroupOptions {
|
azalea::start_swarm(azalea::SwarmOptions {
|
||||||
accounts,
|
accounts,
|
||||||
address: "localhost",
|
address: "localhost",
|
||||||
|
|
||||||
group_state: Arc::new(Mutex::new(State::default())),
|
swarm_state: Arc::new(Mutex::new(State::default())),
|
||||||
state: State::default(),
|
state: State::default(),
|
||||||
|
|
||||||
group_plugins: vec![Arc::new(pathfinder::Plugin::default())],
|
swarm_plugins: vec![Arc::new(pathfinder::Plugin::default())],
|
||||||
plugins: vec![],
|
plugins: vec![],
|
||||||
|
|
||||||
handle: Box::new(handle),
|
handle: Box::new(handle),
|
||||||
group_handle: Box::new(handle),
|
swarm_handle: Box::new(swarm_handle),
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default, Clone)]
|
||||||
struct State {}
|
struct State {}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default, Clone)]
|
||||||
struct GroupState {}
|
struct SwarmState {}
|
||||||
|
|
||||||
async fn handle(bot: Client, event: Arc<Event>, state: Arc<Mutex<State>>) -> anyhow::Result<()> {
|
async fn handle(bot: Client, event: Arc<Event>, state: Arc<Mutex<State>>) -> anyhow::Result<()> {
|
||||||
match event {
|
match event {
|
||||||
|
@ -41,19 +41,20 @@ async fn handle(bot: Client, event: Arc<Event>, state: Arc<Mutex<State>>) -> any
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn group_handle(
|
async fn swarm_handle(
|
||||||
bots: Swarm,
|
swarm: Swarm,
|
||||||
event: Arc<Event>,
|
event: Arc<Event>,
|
||||||
state: Arc<Mutex<GroupState>>,
|
state: Arc<Mutex<SwarmState>>,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
match *event {
|
match *event {
|
||||||
Event::Login => {
|
Event::Login => {
|
||||||
bots.goto(azalea::BlockPos::new(0, 70, 0)).await;
|
swarm.goto(azalea::BlockPos::new(0, 70, 0)).await;
|
||||||
// or bots.goto_goal(pathfinder::Goals::Goto(azalea::BlockPos(0, 70, 0))).await;
|
// or bots.goto_goal(pathfinder::Goals::Goto(azalea::BlockPos(0, 70, 0))).await;
|
||||||
|
|
||||||
// destroy the blocks in this area and then leave
|
// destroy the blocks in this area and then leave
|
||||||
|
|
||||||
bots.fill(
|
swarm
|
||||||
|
.fill(
|
||||||
azalea::Selection::Range(
|
azalea::Selection::Range(
|
||||||
azalea::BlockPos::new(0, 0, 0),
|
azalea::BlockPos::new(0, 0, 0),
|
||||||
azalea::BlockPos::new(16, 255, 16),
|
azalea::BlockPos::new(16, 255, 16),
|
||||||
|
|
|
@ -4,17 +4,17 @@ use async_trait::async_trait;
|
||||||
use azalea::{Client, Event};
|
use azalea::{Client, Event};
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default, Clone)]
|
||||||
pub struct Plugin {
|
pub struct Plugin {
|
||||||
pub state: Arc<Mutex<State>>,
|
pub state: State,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default, Clone)]
|
||||||
pub struct State {}
|
pub struct State {}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl azalea::Plugin for Plugin {
|
impl azalea::Plugin for Plugin {
|
||||||
async fn handle(self: Arc<Self>, bot: Client, event: Arc<Event>) {
|
async fn handle(self: Box<Self>, event: Event, bot: Client) {
|
||||||
match event {
|
match event {
|
||||||
Event::UpdateHunger => {
|
Event::UpdateHunger => {
|
||||||
if !bot.using_held_item() && bot.food_level() <= 17 {
|
if !bot.using_held_item() && bot.food_level() <= 17 {
|
||||||
|
|
|
@ -17,10 +17,10 @@ async fn main() {
|
||||||
azalea::start(azalea::Options {
|
azalea::start(azalea::Options {
|
||||||
account,
|
account,
|
||||||
address: "localhost",
|
address: "localhost",
|
||||||
state: Arc::new(Mutex::new(State::default())),
|
state: State::default(),
|
||||||
plugins: vec![
|
plugins: vec![
|
||||||
Arc::new(autoeat::Plugin::default()),
|
Box::new(autoeat::Plugin::default()),
|
||||||
Arc::new(pathfinder::Plugin::default()),
|
Box::new(pathfinder::Plugin::default()),
|
||||||
],
|
],
|
||||||
handle,
|
handle,
|
||||||
})
|
})
|
||||||
|
@ -28,7 +28,7 @@ async fn main() {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn handle(bot: Client, event: Arc<Event>, state: Arc<Mutex<State>>) -> anyhow::Result<()> {
|
async fn handle(bot: Client, event: Event, state: State) -> anyhow::Result<()> {
|
||||||
match event {
|
match event {
|
||||||
Event::Login => {
|
Event::Login => {
|
||||||
goto_farm(bot, state).await?;
|
goto_farm(bot, state).await?;
|
||||||
|
@ -42,14 +42,14 @@ async fn handle(bot: Client, event: Arc<Event>, state: Arc<Mutex<State>>) -> any
|
||||||
}
|
}
|
||||||
|
|
||||||
// go to the place where we start farming
|
// go to the place where we start farming
|
||||||
async fn goto_farm(bot: Client, state: Arc<Mutex<State>>) -> anyhow::Result<()> {
|
async fn goto_farm(bot: Client, state: State) -> anyhow::Result<()> {
|
||||||
bot.goto(pathfinder::Goals::Near(5, BlockPos::new(0, 70, 0)))
|
bot.goto(pathfinder::Goals::Near(5, BlockPos::new(0, 70, 0)))
|
||||||
.await?;
|
.await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
// go to the chest and deposit everything in our inventory.
|
// go to the chest and deposit everything in our inventory.
|
||||||
async fn deposit(bot: &mut Client, state: &mut Arc<Mutex<State>>) -> anyhow::Result<()> {
|
async fn deposit(bot: &mut Client, state: State) -> anyhow::Result<()> {
|
||||||
// first throw away any garbage we might have
|
// first throw away any garbage we might have
|
||||||
bot.toss(|item| item.kind != ItemKind::Potato && item.kind != ItemKind::DiamondHoe);
|
bot.toss(|item| item.kind != ItemKind::Potato && item.kind != ItemKind::DiamondHoe);
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ async fn main() {
|
||||||
let accounts = Accounts::new();
|
let accounts = Accounts::new();
|
||||||
|
|
||||||
for i in 0..10 {
|
for i in 0..10 {
|
||||||
accounts.add(Account::offline(format!("bot{}", i)));
|
accounts.add(Account::offline(&format!("bot{}", i)));
|
||||||
}
|
}
|
||||||
|
|
||||||
azalea::start_swarm(azalea::SwarmOptions {
|
azalea::start_swarm(azalea::SwarmOptions {
|
||||||
|
@ -21,24 +21,28 @@ async fn main() {
|
||||||
plugins: vec![],
|
plugins: vec![],
|
||||||
|
|
||||||
handle: Box::new(handle),
|
handle: Box::new(handle),
|
||||||
swarm_handle: Box::new(handle),
|
swarm_handle: Box::new(swarm_handle),
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Clone)]
|
||||||
struct State {}
|
struct State {}
|
||||||
|
|
||||||
|
#[derive(Default, Clone)]
|
||||||
struct SwarmState {}
|
struct SwarmState {}
|
||||||
|
|
||||||
async fn handle(bots: Client, event: Arc<Event>, state: Arc<Mutex<State>>) {
|
async fn handle(bot: Client, event: Event, state: State) {}
|
||||||
match *event {
|
async fn swarm_handle(swarm: Swarm, event: Event, state: State) {
|
||||||
|
match event {
|
||||||
Event::Tick => {
|
Event::Tick => {
|
||||||
// choose an arbitrary player within render distance to target
|
// choose an arbitrary player within render distance to target
|
||||||
if let Some(target) = bots
|
if let Some(target) = swarm
|
||||||
.dimension()
|
.dimension
|
||||||
.find_one_entity(|e| e.id == "minecraft:player")
|
.find_one_entity(|e| e.id == "minecraft:player")
|
||||||
{
|
{
|
||||||
for bot in bots {
|
for bot in swarm {
|
||||||
bot.tick_goto_goal(pathfinder::Goals::Reach(target.bounding_box));
|
bot.tick_goto_goal(pathfinder::Goals::Reach(target.bounding_box));
|
||||||
// if target.bounding_box.distance(bot.eyes) < bot.reach_distance() {
|
// if target.bounding_box.distance(bot.eyes) < bot.reach_distance() {
|
||||||
if bot.entity.can_reach(target.bounding_box) {
|
if bot.entity.can_reach(target.bounding_box) {
|
||||||
|
|
|
@ -3,14 +3,14 @@ use async_trait::async_trait;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default, Clone)]
|
||||||
pub struct Plugin {
|
pub struct Plugin {
|
||||||
pub state: Arc<Mutex<State>>,
|
pub state: State,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default, Clone)]
|
||||||
pub struct State {
|
pub struct State {
|
||||||
jumping_once: bool,
|
jumping_once: Arc<Mutex<bool>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait BotTrait {
|
pub trait BotTrait {
|
||||||
|
@ -18,7 +18,7 @@ pub trait BotTrait {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BotTrait for azalea_client::Client {
|
impl BotTrait for azalea_client::Client {
|
||||||
/// Try to jump next tick.
|
/// Queue a jump for the next tick.
|
||||||
fn jump(&self) {
|
fn jump(&self) {
|
||||||
let player_lock = self.player.lock();
|
let player_lock = self.player.lock();
|
||||||
let mut dimension_lock = self.dimension.lock();
|
let mut dimension_lock = self.dimension.lock();
|
||||||
|
@ -33,12 +33,11 @@ impl BotTrait for azalea_client::Client {
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl crate::Plugin for Plugin {
|
impl crate::Plugin for Plugin {
|
||||||
async fn handle(self: Arc<Self>, event: Arc<Event>, mut bot: Client) {
|
async fn handle(self: Box<Self>, event: Event, mut bot: Client) {
|
||||||
if let Event::Tick = *event {
|
if let Event::Tick = event {
|
||||||
let mut state = self.state.lock();
|
if *self.state.jumping_once.lock() {
|
||||||
if state.jumping_once {
|
|
||||||
if bot.jumping() {
|
if bot.jumping() {
|
||||||
state.jumping_once = false;
|
*self.state.jumping_once.lock() = false;
|
||||||
} else {
|
} else {
|
||||||
bot.set_jumping(true);
|
bot.set_jumping(true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
//! .unwrap();
|
//! .unwrap();
|
||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
|
//! #[derive(Default, Clone)]
|
||||||
//! pub struct State {}
|
//! pub struct State {}
|
||||||
//!
|
//!
|
||||||
//! async fn handle(bot: Client, event: Arc<Event>, state: Arc<Mutex<State>>) -> anyhow::Result<()> {
|
//! async fn handle(bot: Client, event: Arc<Event>, state: Arc<Mutex<State>>) -> anyhow::Result<()> {
|
||||||
|
@ -52,17 +53,35 @@ pub mod prelude;
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
pub use azalea_client::*;
|
pub use azalea_client::*;
|
||||||
use azalea_protocol::ServerAddress;
|
use azalea_protocol::ServerAddress;
|
||||||
use parking_lot::Mutex;
|
use std::future::Future;
|
||||||
use std::{future::Future, sync::Arc};
|
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
/// Plugins can keep their own personal state, listen to events, and add new functions to Client.
|
/// Plugins can keep their own personal state, listen to events, and add new functions to Client.
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
pub trait Plugin: Send + Sync {
|
pub trait Plugin: Send + Sync + PluginClone + 'static {
|
||||||
async fn handle(self: Arc<Self>, event: Arc<Event>, bot: Client);
|
async fn handle(self: Box<Self>, event: Event, bot: Client);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type HandleFn<Fut, S> = fn(Client, Arc<Event>, Arc<Mutex<S>>) -> Fut;
|
/// An internal trait that allows Plugin to be cloned.
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub trait PluginClone {
|
||||||
|
fn clone_box(&self) -> Box<dyn Plugin>;
|
||||||
|
}
|
||||||
|
impl<T> PluginClone for T
|
||||||
|
where
|
||||||
|
T: 'static + Plugin + Clone,
|
||||||
|
{
|
||||||
|
fn clone_box(&self) -> Box<dyn Plugin> {
|
||||||
|
Box::new(self.clone())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Clone for Box<dyn Plugin> {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
self.clone_box()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type HandleFn<Fut, S> = fn(Client, Event, S) -> Fut;
|
||||||
|
|
||||||
/// The options that are passed to [`azalea::start`].
|
/// The options that are passed to [`azalea::start`].
|
||||||
///
|
///
|
||||||
|
@ -80,10 +99,22 @@ where
|
||||||
pub account: Account,
|
pub account: Account,
|
||||||
/// A list of plugins that are going to be used. Plugins are external
|
/// A list of plugins that are going to be used. Plugins are external
|
||||||
/// crates that add extra functionality to Azalea.
|
/// crates that add extra functionality to Azalea.
|
||||||
pub plugins: Vec<Arc<dyn Plugin>>,
|
pub plugins: Vec<Box<dyn Plugin>>,
|
||||||
/// A struct that contains the data that you want your bot to remember
|
/// A struct that contains the data that you want your bot to remember
|
||||||
/// across events.
|
/// across events.
|
||||||
pub state: Arc<Mutex<S>>,
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// use parking_lot::Mutex;
|
||||||
|
/// use std::sync::Arc;
|
||||||
|
///
|
||||||
|
/// #[derive(Default, Clone)]
|
||||||
|
/// struct State {
|
||||||
|
/// farming: Arc<Mutex<bool>>,
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
pub state: S,
|
||||||
/// The function that's called whenever we get an event.
|
/// The function that's called whenever we get an event.
|
||||||
pub handle: HandleFn<Fut, S>,
|
pub handle: HandleFn<Fut, S>,
|
||||||
}
|
}
|
||||||
|
@ -107,7 +138,7 @@ pub enum Error {
|
||||||
/// }).await.unwrap();
|
/// }).await.unwrap();
|
||||||
/// ```
|
/// ```
|
||||||
pub async fn start<
|
pub async fn start<
|
||||||
S: Send + 'static,
|
S: Send + Sync + Clone + 'static,
|
||||||
A: Send + TryInto<ServerAddress>,
|
A: Send + TryInto<ServerAddress>,
|
||||||
Fut: Future<Output = Result<(), anyhow::Error>> + Send + 'static,
|
Fut: Future<Output = Result<(), anyhow::Error>> + Send + 'static,
|
||||||
>(
|
>(
|
||||||
|
@ -121,19 +152,16 @@ pub async fn start<
|
||||||
let (bot, mut rx) = Client::join(&options.account, address).await.unwrap();
|
let (bot, mut rx) = Client::join(&options.account, address).await.unwrap();
|
||||||
|
|
||||||
let state = options.state;
|
let state = options.state;
|
||||||
let bot_plugin = Arc::new(bot::Plugin::default());
|
let bot_plugin = bot::Plugin::default();
|
||||||
|
|
||||||
while let Some(event) = rx.recv().await {
|
while let Some(event) = rx.recv().await {
|
||||||
// we put it into an Arc so it's cheaper to clone
|
|
||||||
|
|
||||||
let event = Arc::new(event);
|
|
||||||
|
|
||||||
for plugin in &options.plugins {
|
for plugin in &options.plugins {
|
||||||
tokio::spawn(plugin.clone().handle(event.clone(), bot.clone()));
|
let plugin = plugin.clone();
|
||||||
|
tokio::spawn(plugin.handle(event.clone(), bot.clone()));
|
||||||
}
|
}
|
||||||
|
|
||||||
tokio::spawn(bot::Plugin::handle(
|
tokio::spawn(bot::Plugin::handle(
|
||||||
bot_plugin.clone(),
|
Box::new(bot_plugin.clone()),
|
||||||
event.clone(),
|
event.clone(),
|
||||||
bot.clone(),
|
bot.clone(),
|
||||||
));
|
));
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
use azalea::prelude::*;
|
use azalea::prelude::*;
|
||||||
use azalea::{Account, Client, Event};
|
use azalea::{Account, Client, Event};
|
||||||
use parking_lot::Mutex;
|
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default, Clone)]
|
||||||
struct State {}
|
struct State {}
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
|
@ -15,7 +13,7 @@ async fn main() -> anyhow::Result<()> {
|
||||||
azalea::start(azalea::Options {
|
azalea::start(azalea::Options {
|
||||||
account,
|
account,
|
||||||
address: "localhost",
|
address: "localhost",
|
||||||
state: Arc::new(Mutex::new(State::default())),
|
state: State::default(),
|
||||||
plugins: vec![],
|
plugins: vec![],
|
||||||
handle,
|
handle,
|
||||||
})
|
})
|
||||||
|
@ -25,8 +23,8 @@ async fn main() -> anyhow::Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn handle(bot: Client, event: Arc<Event>, _state: Arc<Mutex<State>>) -> anyhow::Result<()> {
|
async fn handle(bot: Client, event: Event, _state: State) -> anyhow::Result<()> {
|
||||||
match *event {
|
match event {
|
||||||
Event::Login => {
|
Event::Login => {
|
||||||
bot.chat("Hello world").await?;
|
bot.chat("Hello world").await?;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue