Skip to content
This repository was archived by the owner on Feb 26, 2025. It is now read-only.

Commit a0c1411

Browse files
authored
Added Support for Multiple Bots, Advanced Anti AFK Plugin and Discord Plugin (#10)
* RELEASE 0.3.0-alpha.6 * Moved to Minecraft Version 1.20.6 * Moved to Better 1.20.6 * Removed Chat feedback * Fix: stone miner movement (#6) * Optimized Imports * Added Support for multiple bots (#8) * Added support for multiple bots * Added `Config` resource * updated todos * Improved distance calculation for `StopPathfinding` * Added version check for `config.json` * Advanced Anti-AFK (#7) * Added Advanced Anti AFK * fixed anti-afk * Integrated Task Manager to support newer Anti AFK Plugin * Added newer anti-afk plugin to `aether-core` * Created `rust-toolchain` for entire workspace * Updated documentation * Added Chat Feedback back * updated .gitignore * Added Discord Plugin * Added Discord Chat Bridge Plugin * fix: Added support for multiple bots * Integrated Discord Plugin with `aether-core`
1 parent a9386db commit a0c1411

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+1152
-402
lines changed

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,8 @@ Cargo.lock
1212

1313
# MSVC Windows builds of rustc generate these, which store debugging information
1414
*.pdb
15+
16+
.idea
17+
.DS_Store
18+
config.json
19+
log.txt

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ members = [
44
"examples/anti-afk",
55
"examples/stone-miner",
66
"plugins/anti-afk",
7-
"plugins/auto-mine",
7+
"plugins/auto-mine", "plugins/discord",
88
"plugins/task-manager"
99
]
1010

README.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,18 @@
11
# Aether
22
Minecraft Bots written in rust mainly developed for 2b2t.
33

4+
This repository currently supports minecraft version `1.20.6` and uses self-maintained version of [azalea better-1.20.6](https://github.com/as1100k-forks/azalea.git)
5+
which has more features and fixes.
6+
7+
There is `mc-1.21` branch which directly uses [azalea](https://github.com/azalea-rs/azalea.git) but is not mainly
8+
worked on. Once, `azalea-viaversion` will work or `2b2t.org` will directly support `1.21` then this repository will
9+
be completely migrated to `1.21`.
10+
411
## TODOs / Future Goals
512
_For Project related TODOs head to the project's `README.md`_
613

714
- [ ] A Java Plugin that can be used to send command to bot via HTTP
8-
- [ ] Make the code more modular by breaking it into features
15+
- [x] Make the code more modular by breaking it into features/plugins
916
- [ ] Map Art Bot which can create map arts
1017
- [ ] Storage Manager Bot which can manage storage
1118
- [ ] Advanced Pathfinding [Example](https://github.com/adepierre/Botcraft/blob/master/Visuals/pathfinding_climb.gif)

aether-core/Cargo.toml

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "aether-core"
3-
version = "0.3.0-alpha.5"
3+
version = "0.3.0-alpha.6"
44
edition = "2021"
55

66
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@@ -13,17 +13,18 @@ opt-level = 3
1313
[profile.release]
1414
strip = "debuginfo"
1515
lto = true
16+
codegen-units = 1
17+
panic = "abort"
1618

1719
[dependencies]
1820
anyhow = "1.0.83"
19-
azalea = { git = "https://github.com/azalea-rs/azalea" }
20-
# This is temp dependecy until, the PR got merge
21-
azalea-viaversion = { git = "https://github.com/EnderKill98/azalea-viaversion", branch = "feature/update-via-proxy" }
21+
azalea = { git = "https://github.com/as1100k-forks/azalea.git", branch = "better-1.20.6" }
2222
azalea-task-manager = { path = "../plugins/task-manager", features = ["anti-afk"] }
2323
azalea-anti-afk = { path = "../plugins/anti-afk" }
24+
azalea-discord = { path = "../plugins/discord", features = ["chat-bridge"] }
25+
serde = { version = "1.0.203", features = ["derive"] }
2426
serde_json = "1.0.117"
2527
tokio = { version = "1.37.0", features = ["macros"] }
26-
serde = { version = "1.0.201", features = ["derive"] }
2728
parking_lot = "0.12.2"
2829
log = { version = "0.4.21" }
2930
rand = "0.8.5"

aether-core/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ This bot is created to server the main purpose of loading the pearl on 2b2t.
55
## TODOs
66

77
- [ ] Better way to send chat messages with delay
8-
- [ ] Integration with Discord
8+
- [x] Integration with Discord
99
- [ ] Split Code into multiple features
10-
- [ ] Support Multiple Bots
10+
- [x] Support Multiple Bots
1111
- [ ] Add More Roles like `Storage Manager`, `AFK at Farms`, etc.
1212
- [ ] Update `config.json` via commands
1313
- [ ] Move from Chat Listener to HTTP Listener for Commands

aether-core/config.example.json

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,31 @@
11
{
2-
"username": "_aether",
3-
"server": "10.9.12.3",
4-
"mode": "Offline",
5-
"email": null,
6-
"role": "Pearl",
7-
"afk_location": [355, 71, 83],
2+
"server": "10.9.12.13",
83
"members": [
94
"AS1100K"
105
],
11-
"pearl_locations": [
6+
"bots": [
127
{
13-
"owner": "AS1100K",
14-
"cords": [376, 71, 83]
8+
"username": "_aether",
9+
"mode": "Offline",
10+
"email": null,
11+
"role": "Pearl",
12+
"render_distance": 5,
13+
"afk_location": [355, 71, 83],
14+
"pearl_locations": [
15+
{
16+
"owner": "AS1100K",
17+
"cords": [376, 71, 83]
18+
}
19+
],
20+
"chat_bridge": "webhook",
21+
"log_bridge": "webhook",
22+
"queue_bridge": "webhook"
23+
},
24+
{
25+
"username": "_aether_2",
26+
"mode": "Offline",
27+
"role": "AFKAdvanced"
1528
}
16-
]
29+
],
30+
"version": 2
1731
}

aether-core/rust-toolchain

Lines changed: 0 additions & 1 deletion
This file was deleted.

aether-core/src/chat.rs

Lines changed: 48 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,76 @@
11
use crate::command::Command;
22
use crate::handle_command::handle_commands;
33
use crate::utils::parse_chat_content;
4-
use crate::{msg, State};
54
use azalea::chat::ChatPacket;
65
use azalea::Client;
7-
use log::info;
6+
use log::{info, warn};
87
use azalea_anti_afk::AntiAFKClientExt;
8+
use azalea_anti_afk::config::AntiAFKConfig;
9+
use azalea_discord::chat_bridge::DiscordChatBridgeExt;
10+
use azalea_discord::{DiscordExt, SendDiscordMessage};
11+
use crate::config::{Bot, Config};
912

10-
pub async fn handle_chat(client: Client, chat: ChatPacket, mut state: State) -> anyhow::Result<()> {
13+
pub async fn handle_chat(client: Client, chat: ChatPacket, mut state: Bot) -> anyhow::Result<()> {
1114
let (username, content, is_whisper) = parse_chat_content(&chat);
1215

1316
if let Some(ref uname) = username {
14-
if uname == &state.config.username || !state.config.members.contains(uname) {
17+
if uname == &state.username || !client.ecs.lock().resource::<Config>().members.contains(uname) {
1518
return Ok(());
1619
}
1720
} else if username.is_none() {
1821
if content.starts_with("Server") {
19-
for member in state.config.members {
20-
msg!(client, member, content);
21-
}
22+
warn!("{}", content);
2223
} else if content == "Connected to the server.".to_string() {
2324
info!("Connected to the Server, updating the state.");
24-
state.game_information.set_connection_state(true);
25-
client.set_anti_afk(true);
25+
state.set_connection_state(true);
26+
27+
if state.chat_bridge.is_some() {
28+
client.set_discord_chat_bridge(true, "2b2t Server", state.chat_bridge)
29+
} else if state.queue_bridge.is_some() {
30+
client.set_discord_chat_bridge(false, "", None)
31+
}
32+
33+
let central_afk_location = if let Some(afk_location) = state.afk_location {
34+
Some(afk_location.to_vec3_floored())
35+
} else {
36+
None
37+
};
38+
39+
let anti_afk_config = AntiAFKConfig {
40+
jump: true,
41+
sneak: true,
42+
walk: true,
43+
flip_lever: true,
44+
central_afk_location
45+
};
46+
47+
client.set_anti_afk(true, Some(anti_afk_config));
2648
} else if content == "You have lost connection to the server" {
2749
{
2850
info!("Lost Connection to the server, back to queue");
29-
state.game_information.set_connection_state(false);
51+
state.set_connection_state(false);
52+
if state.log_bridge.is_some() {
53+
client.send_discord_message(SendDiscordMessage {
54+
webhook: state.log_bridge.unwrap(),
55+
contents: "Lost Connection to the server, back to queue. Aww".to_string(),
56+
username: Some(state.username),
57+
avatar_url: Some(format!("https://crafatar.com/avatars/{}", client.uuid())),
58+
});
59+
}
60+
61+
if state.queue_bridge.is_some() {
62+
client.set_discord_chat_bridge(true, "2b2t Server", state.queue_bridge)
63+
} else if state.chat_bridge.is_some() {
64+
client.set_discord_chat_bridge(false, "", None)
65+
}
3066
}
3167
}
3268

3369
return Ok(());
3470
}
3571

36-
if *state.game_information.is_connected.lock() && is_whisper {
37-
let command: Command = Command::parse(content.as_str()).await;
72+
if *state.is_connected.lock() && is_whisper {
73+
let command: Command = Command::parse(content.as_str(), &state).await;
3874
handle_commands(command, username.unwrap(), client, chat, state).await?;
3975
}
4076

aether-core/src/client.rs

Lines changed: 53 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,38 @@
1-
use crate::config::Role;
2-
use crate::State;
1+
use crate::config::Bot;
32
use azalea::protocol::packets::game::clientbound_player_combat_kill_packet::ClientboundPlayerCombatKillPacket;
43
use azalea::protocol::packets::game::serverbound_client_command_packet::Action::PerformRespawn;
54
use azalea::protocol::packets::game::serverbound_client_command_packet::ServerboundClientCommandPacket;
65
use azalea::{Client, ClientInformation};
76
use log::info;
87
use std::sync::Arc;
98
use azalea_anti_afk::AntiAFKClientExt;
9+
use azalea_anti_afk::config::AntiAFKConfig;
10+
use azalea_discord::{DiscordExt, SendDiscordMessage};
11+
use azalea_discord::chat_bridge::DiscordChatBridgeExt;
1012

11-
pub async fn handle_init(client: Client, state: State) -> anyhow::Result<()> {
12-
info!("Initialized bot");
13-
if state.config.role == Role::Pearl {
13+
pub async fn handle_init(client: Client, state: Bot) -> anyhow::Result<()> {
14+
info!("Initialized bot, {}", state.username);
15+
if state.log_bridge.is_some() {
16+
client.send_discord_message(SendDiscordMessage {
17+
webhook: state.log_bridge.unwrap(),
18+
contents: "Initialized bot".to_string(),
19+
username: Some(state.username),
20+
avatar_url: Some(format!("https://crafatar.com/avatars/{}", client.uuid())),
21+
});
22+
}
23+
24+
if state.queue_bridge.is_some() {
25+
client.set_discord_chat_bridge(true, "2b2t Server", state.queue_bridge)
26+
}
27+
28+
if state.render_distance.is_some_and(|rd| rd <= 32) {
29+
client
30+
.set_client_information(ClientInformation {
31+
view_distance: state.render_distance.unwrap(),
32+
..Default::default()
33+
})
34+
.await?;
35+
} else {
1436
client
1537
.set_client_information(ClientInformation {
1638
view_distance: 5,
@@ -24,16 +46,38 @@ pub async fn handle_init(client: Client, state: State) -> anyhow::Result<()> {
2446

2547
pub async fn handle_death(
2648
client: Client,
27-
_state: State,
28-
_death: Option<Arc<ClientboundPlayerCombatKillPacket>>,
49+
state: Bot,
50+
death: Option<Arc<ClientboundPlayerCombatKillPacket>>,
2951
) -> anyhow::Result<()> {
30-
info!("The bot has died, respawning.");
52+
info!("{} has died, respawning.", state.username);
53+
if state.log_bridge.is_some() {
54+
client.send_discord_message(SendDiscordMessage {
55+
webhook: state.log_bridge.unwrap(),
56+
contents: format!("I died. ```{:?}```", death),
57+
username: Some(state.username),
58+
avatar_url: Some(format!("https://crafatar.com/avatars/{}", client.uuid())),
59+
});
60+
}
3161
let respawn_command_packet = ServerboundClientCommandPacket {
3262
action: PerformRespawn,
3363
};
3464

65+
let central_afk_location = if let Some(afk_location) = state.afk_location {
66+
Some(afk_location.to_vec3_floored())
67+
} else {
68+
None
69+
};
70+
71+
let anti_afk_config = AntiAFKConfig {
72+
jump: true,
73+
sneak: true,
74+
walk: true,
75+
flip_lever: true,
76+
central_afk_location
77+
};
78+
3579
client.write_packet(respawn_command_packet.get())?;
36-
client.set_anti_afk(true);
80+
client.set_anti_afk(true, Some(anti_afk_config));
3781

3882
Ok(())
3983
}

aether-core/src/command.rs

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use crate::config::{Bot, Role};
2+
13
pub enum Command {
24
PearlLoad,
35
PearlSet(i32, i32, i32),
@@ -7,20 +9,31 @@ pub enum Command {
79
}
810

911
impl Command {
10-
pub async fn parse(input: &str) -> Command {
12+
pub async fn parse(input: &str, state: &Bot) -> Command {
1113
let parts: Vec<&str> = input.split_whitespace().collect();
1214

15+
// TODO: Port all the commands to discord and only support necessary ones via minecraft chat
1316
match parts.as_slice() {
14-
["!pearl", "load"] => Command::PearlLoad,
17+
["!pearl", "load"] => {
18+
if state.role == Role::Pearl {
19+
Command::PearlLoad
20+
} else {
21+
Command::Unknown
22+
}
23+
},
1524
["!pearl", "set", x, y, z] => {
16-
let x = x.parse::<i32>();
17-
let y = y.parse::<i32>();
18-
let z = z.parse::<i32>();
25+
if state.role == Role::Pearl {
26+
let x = x.parse::<i32>();
27+
let y = y.parse::<i32>();
28+
let z = z.parse::<i32>();
1929

20-
if x.is_ok() && y.is_ok() && z.is_ok() {
21-
Command::PearlSet(x.unwrap(), y.unwrap(), z.unwrap())
30+
if x.is_ok() && y.is_ok() && z.is_ok() {
31+
Command::PearlSet(x.unwrap(), y.unwrap(), z.unwrap())
32+
} else {
33+
Command::InvalidArguments
34+
}
2235
} else {
23-
Command::InvalidArguments
36+
Command::Unknown
2437
}
2538
}
2639
["!help"] => Command::Help,

0 commit comments

Comments
 (0)