1
2
Fork 0
mirror of https://github.com/mat-1/azalea.git synced 2025-08-02 14:26:04 +00:00

Merge branch 'main' into swarm

This commit is contained in:
mat 2022-11-20 15:47:08 -06:00
commit 336d155049
40 changed files with 3423 additions and 3265 deletions

3
.github/FUNDING.yml vendored Normal file
View file

@ -0,0 +1,3 @@
# These are supported funding model platforms
ko_fi: matdoesdev

2704
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -4,13 +4,13 @@ edition = "2021"
license = "MIT"
name = "azalea-auth"
repository = "https://github.com/mat-1/azalea/tree/main/azalea-auth"
version = "0.3.0"
version = "0.4.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
azalea-buf = {path = "../azalea-buf", version = "^0.3.0"}
azalea-crypto = {path = "../azalea-crypto", version = "^0.3.0"}
azalea-buf = {path = "../azalea-buf", version = "^0.4.0" }
azalea-crypto = {path = "../azalea-crypto", version = "^0.4.0" }
chrono = {version = "0.4.22", default-features = false}
log = "0.4.17"
num-bigint = "0.4.3"

View file

@ -4,12 +4,12 @@ edition = "2021"
license = "MIT"
name = "azalea-block"
repository = "https://github.com/mat-1/azalea/tree/main/azalea-block"
version = "0.3.0"
version = "0.4.0"
[lib]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
azalea-block-macros = {path = "./azalea-block-macros", version = "^0.3.0" }
azalea-buf = {path = "../azalea-buf", version = "^0.3.0" }
azalea-block-macros = {path = "./azalea-block-macros", version = "^0.4.0" }
azalea-buf = {path = "../azalea-buf", version = "^0.4.0" }

View file

@ -4,7 +4,7 @@ edition = "2021"
license = "MIT"
name = "azalea-block-macros"
repository = "https://github.com/mat-1/azalea/tree/main/azalea-block/azalea-block-macros"
version = "0.3.0"
version = "0.4.0"
[lib]
proc-macro = true

View file

@ -4,7 +4,7 @@ edition = "2021"
license = "MIT"
name = "azalea-brigadier"
repository = "https://github.com/mat-1/azalea/tree/main/azalea-brigadier"
version = "0.3.0"
version = "0.4.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

View file

@ -4,12 +4,12 @@ edition = "2021"
license = "MIT"
name = "azalea-buf"
repository = "https://github.com/mat-1/azalea/tree/main/azalea-buf"
version = "0.3.0"
version = "0.4.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
azalea-buf-macros = {path = "./azalea-buf-macros", version = "^0.3.0" }
azalea-buf-macros = {path = "./azalea-buf-macros", version = "^0.4.0" }
byteorder = "^1.4.3"
serde_json = {version = "^1.0", optional = true}
thiserror = "^1.0.34"

View file

@ -4,7 +4,7 @@ edition = "2021"
license = "MIT"
name = "azalea-buf-macros"
repository = "https://github.com/mat-1/azalea/tree/main/azalea-buf"
version = "0.3.0"
version = "0.4.0"
[lib]
proc-macro = true

View file

@ -3,14 +3,14 @@ description = "Parse Minecraft chat messages."
edition = "2021"
license = "MIT"
name = "azalea-chat"
version = "0.3.0"
version = "0.4.0"
repository = "https://github.com/mat-1/azalea/tree/main/azalea-chat"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
azalea-buf = {path = "../azalea-buf", features = ["serde_json"], version = "^0.3.0" }
azalea-language = {path = "../azalea-language", version = "^0.3.0" }
lazy_static = "^1.4.0"
azalea-buf = {path = "../azalea-buf", features = ["serde_json"], version = "^0.4.0" }
azalea-language = {path = "../azalea-language", version = "^0.4.0" }
once_cell = "1.16.0"
serde = "^1.0.130"
serde_json = "^1.0.72"

View file

@ -1,17 +1,16 @@
use std::{
fmt::Display,
io::{Cursor, Write},
};
use azalea_buf::{BufReadError, McBufReadable, McBufWritable};
use serde::{de, Deserialize, Deserializer};
use crate::{
base_component::BaseComponent,
style::{ChatFormatting, Style},
text_component::TextComponent,
translatable_component::{StringOrComponent, TranslatableComponent},
};
use azalea_buf::{BufReadError, McBufReadable, McBufWritable};
use once_cell::sync::Lazy;
use serde::{de, Deserialize, Deserializer};
use std::{
fmt::Display,
io::{Cursor, Write},
};
/// A chat component, basically anything you can see in chat.
#[derive(Clone, Debug)]
@ -20,12 +19,10 @@ pub enum Component {
Translatable(TranslatableComponent),
}
lazy_static! {
pub static ref DEFAULT_STYLE: Style = Style {
color: Some(ChatFormatting::White.try_into().unwrap()),
..Style::default()
};
}
pub static DEFAULT_STYLE: Lazy<Style> = Lazy::new(|| Style {
color: Some(ChatFormatting::White.try_into().unwrap()),
..Style::default()
});
/// A chat component
impl Component {

View file

@ -1,9 +1,6 @@
//! Things for working with Minecraft chat messages.
//! This was inspired by Minecraft and prismarine-chat.
#[macro_use]
extern crate lazy_static;
pub mod base_component;
mod component;
pub mod style;

View file

@ -1,6 +1,7 @@
use std::{collections::HashMap, fmt};
use azalea_buf::McBuf;
use once_cell::sync::Lazy;
use serde_json::Value;
#[derive(Clone, PartialEq, Eq, Debug)]
@ -28,8 +29,8 @@ impl TextColor {
}
}
lazy_static! {
static ref LEGACY_FORMAT_TO_COLOR: HashMap<&'static ChatFormatting, TextColor> = {
static LEGACY_FORMAT_TO_COLOR: Lazy<HashMap<&'static ChatFormatting, TextColor>> =
Lazy::new(|| {
let mut legacy_format_to_color = HashMap::new();
for formatter in &ChatFormatting::FORMATTERS {
if !formatter.is_format() && *formatter != ChatFormatting::Reset {
@ -43,15 +44,14 @@ lazy_static! {
}
}
legacy_format_to_color
};
static ref NAMED_COLORS: HashMap<String, TextColor> = {
let mut named_colors = HashMap::new();
for color in LEGACY_FORMAT_TO_COLOR.values() {
named_colors.insert(color.name.clone().unwrap(), color.clone());
}
named_colors
};
}
});
static NAMED_COLORS: Lazy<HashMap<String, TextColor>> = Lazy::new(|| {
let mut named_colors = HashMap::new();
for color in LEGACY_FORMAT_TO_COLOR.values() {
named_colors.insert(color.name.clone().unwrap(), color.clone());
}
named_colors
});
pub struct Ansi {}
impl Ansi {

View file

@ -4,24 +4,26 @@ edition = "2021"
license = "MIT"
name = "azalea-client"
repository = "https://github.com/mat-1/azalea/tree/main/azalea-client"
version = "0.3.0"
version = "0.4.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
anyhow = "1.0.59"
async-trait = "0.1.58"
azalea-auth = {path = "../azalea-auth", version = "0.3.0"}
azalea-block = {path = "../azalea-block", version = "0.3.0"}
azalea-chat = {path = "../azalea-chat", version = "0.3.0"}
azalea-core = {path = "../azalea-core", version = "0.3.0"}
azalea-crypto = {path = "../azalea-crypto", version = "0.3.0"}
azalea-physics = {path = "../azalea-physics", version = "0.3.0"}
azalea-protocol = {path = "../azalea-protocol", version = "0.3.0"}
azalea-world = {path = "../azalea-world", version = "0.3.0"}
azalea-auth = {path = "../azalea-auth", version = "0.4.0"}
azalea-block = {path = "../azalea-block", version = "0.4.0"}
azalea-chat = {path = "../azalea-chat", version = "0.4.0"}
azalea-core = {path = "../azalea-core", version = "0.4.0"}
azalea-crypto = {path = "../azalea-crypto", version = "0.4.0"}
azalea-physics = {path = "../azalea-physics", version = "0.4.0"}
azalea-protocol = {path = "../azalea-protocol", version = "0.4.0"}
azalea-world = {path = "../azalea-world", version = "0.4.0"}
log = "0.4.17"
nohash-hasher = "0.2.0"
parking_lot = {version = "0.12.1", features = ["deadlock_detection"]}
once_cell = "1.16.0"
parking_lot = {version = "^0.12.1", features = ["deadlock_detection"]}
regex = "1.7.0"
thiserror = "^1.0.34"
tokio = {version = "^1.21.2", features = ["sync"]}
typemap_rev = "0.2.0"

View file

@ -18,6 +18,13 @@ pub enum ChatPacket {
Player(Box<ClientboundPlayerChatPacket>),
}
macro_rules! regex {
($re:literal $(,)?) => {{
static RE: once_cell::sync::OnceCell<regex::Regex> = once_cell::sync::OnceCell::new();
RE.get_or_init(|| regex::Regex::new($re).unwrap())
}};
}
impl ChatPacket {
/// Get the message shown in chat for this packet.
pub fn message(&self) -> Component {
@ -26,6 +33,49 @@ impl ChatPacket {
ChatPacket::Player(p) => p.message(false),
}
}
/// Determine the username of the sender and content of the message. This
/// does not preserve formatting codes. If it's not a player-sent chat
/// message or the sender couldn't be determined, the username part will be
/// None.
pub fn split_sender_and_content(&self) -> (Option<String>, String) {
match self {
ChatPacket::Player(p) => (
// If it's a player chat packet, then the sender and content
// are already split for us.
Some(p.chat_type.name.to_string()),
p.message.content(false).to_string(),
),
ChatPacket::System(p) => {
let message = p.content.to_string();
// Overlay messages aren't in chat
if p.overlay {
return (None, message);
}
// It's a system message, so we'll have to match the content
// with regex
if let Some(m) = regex!("^<([a-zA-Z_0-9]{1,16})> (.+)$").captures(&message) {
return (Some(m[1].to_string()), m[2].to_string());
}
(None, message)
}
}
}
/// Get the username of the sender of the message. If it's not a
/// player-sent chat message or the sender couldn't be determined, this
/// will be None.
pub fn username(&self) -> Option<String> {
self.split_sender_and_content().0
}
/// Get the content part of the message as a string. This does not preserve
/// formatting codes. If it's not a player-sent chat message or the sender
/// couldn't be determined, this will contain the entire message.
pub fn content(&self) -> String {
self.split_sender_and_content().1
}
}
impl Client {

View file

@ -1,7 +1,8 @@
pub use crate::chat::ChatPacket;
use crate::{movement::WalkDirection, plugins::Plugins, Account, Player};
use crate::{movement::WalkDirection, plugins::Plugins, Account, PlayerInfo};
use azalea_auth::game_profile::GameProfile;
use azalea_core::{ChunkPos, ResourceLocation, Vec3};
use azalea_chat::Component;
use azalea_core::{ChunkPos, GameType, ResourceLocation, Vec3};
use azalea_protocol::{
connect::{Connection, ConnectionError, ReadConnection, WriteConnection},
packets::{
@ -35,6 +36,7 @@ use azalea_world::{
use log::{debug, error, info, warn};
use parking_lot::{Mutex, RwLock, RwLockReadGuard, RwLockWriteGuard};
use std::{
collections::HashMap,
fmt::Debug,
io::{self, Cursor},
sync::Arc,
@ -45,6 +47,7 @@ use tokio::{
task::JoinHandle,
time::{self},
};
use uuid::Uuid;
pub type ClientInformation = ServerboundClientInformationPacket;
@ -62,15 +65,43 @@ pub enum Event {
/// Happens 20 times per second, but only when the world is loaded.
Tick,
Packet(Box<ClientboundGamePacket>),
/// Happens when a player is added, removed, or updated in the tab list.
UpdatePlayers(UpdatePlayersEvent),
}
/// Happens when a player is added, removed, or updated in the tab list.
#[derive(Debug, Clone)]
pub enum UpdatePlayersEvent {
/// A player with the given info was added to the tab list (usually means
/// they joined the server).
Add(PlayerInfo),
/// A player with the given UUID was removed from the tab list (usually
/// means they left the server)
Remove { uuid: Uuid },
/// The latency of the player with the given UUID was updated in the tab
/// list. Note that this can be spoofed by the player and may not represent
/// their actual latency.
Latency {
uuid: Uuid,
/// The time it took in milliseconds for this player to reply to the ping packet.
latency: i32,
},
/// The played switched to a different gamemode (i.e. survival, creative, spectator)
GameMode { uuid: Uuid, game_mode: GameType },
/// The name of the player with the given UUID in the tab list was changed or reset.
DisplayName {
uuid: Uuid,
display_name: Option<Component>,
},
}
/// A player that you control that is currently in a Minecraft server.
#[derive(Clone)]
pub struct Client {
game_profile: GameProfile,
pub profile: GameProfile,
pub read_conn: Arc<tokio::sync::Mutex<ReadConnection<ClientboundGamePacket>>>,
pub write_conn: Arc<tokio::sync::Mutex<WriteConnection<ServerboundGamePacket>>>,
pub player: Arc<RwLock<Player>>,
pub entity_id: Arc<RwLock<u32>>,
/// The world that this client has access to. This supports shared worlds.
pub world: Arc<RwLock<World>>,
/// A container of world names to worlds. If we're not using a shared world
@ -84,6 +115,8 @@ pub struct Client {
/// client and keep state. If you're not making a plugin and you're using
/// the `azalea` crate. you can ignore this field.
pub plugins: Arc<Plugins>,
/// A map of player uuids to their information in the tab list
pub players: Arc<RwLock<HashMap<Uuid, PlayerInfo>>>,
tasks: Arc<Mutex<Vec<JoinHandle<()>>>>,
}
@ -135,7 +168,7 @@ impl Client {
/// You should only use this if you want to change these fields from the
/// defaults, otherwise use [`Client::join`].
pub fn new(
game_profile: GameProfile,
profile: GameProfile,
conn: Connection<ClientboundGamePacket, ServerboundGamePacket>,
world_container: Option<Arc<RwLock<WeakWorldContainer>>>,
) -> Self {
@ -146,20 +179,21 @@ impl Client {
);
Self {
game_profile,
profile,
read_conn,
write_conn,
player: Arc::new(RwLock::new(Player::default())),
// the world will be set later
// default our id to 0, it'll be set later
entity_id: Arc::new(RwLock::new(0)),
world: Arc::new(RwLock::new(World::default())),
world_container: world_container
.unwrap_or_else(|| Arc::new(RwLock::new(WeakWorldContainer::new()))),
world_name: Arc::new(RwLock::new(None)),
physics_state: Arc::new(Mutex::new(PhysicsState::default())),
client_information: Arc::new(
RwLock::new(ServerboundClientInformationPacket::default()),
),
client_information: Arc::new(RwLock::new(ClientInformation::default())),
// The plugins can be modified by the user by replacing the plugins
// field right after this. No Mutex so the user doesn't need to .lock().
plugins: Arc::new(Plugins::new()),
players: Arc::new(RwLock::new(HashMap::new())),
tasks: Arc::new(Mutex::new(Vec::new())),
}
}
@ -243,7 +277,7 @@ impl Client {
)
.await?;
let (conn, game_profile) = loop {
let (conn, profile) = loop {
let packet = conn.read().await?;
match packet {
ClientboundLoginPacket::Hello(p) => {
@ -453,15 +487,13 @@ impl Client {
);
let entity = EntityData::new(
client.game_profile.uuid,
client.profile.uuid,
Vec3::default(),
EntityMetadata::Player(metadata::Player::default()),
);
world_lock.add_entity(p.player_id, entity);
let mut player_lock = client.player.write();
player_lock.set_entity_id(p.player_id);
*client.entity_id.write() = p.player_id;
}
// send the client information that we have set
@ -525,10 +557,7 @@ impl Client {
debug!("Got player position packet {:?}", p);
let (new_pos, y_rot, x_rot) = {
let player_entity_id = {
let player_lock = client.player.write();
player_lock.entity_id
};
let player_entity_id = *client.entity_id.read();
let mut world_lock = client.world.write();
@ -612,7 +641,97 @@ impl Client {
.await?;
}
ClientboundGamePacket::PlayerInfo(p) => {
use azalea_protocol::packets::game::clientbound_player_info_packet::Action;
debug!("Got player info packet {:?}", p);
let mut players_lock = client.players.write();
match &p.action {
Action::AddPlayer(players) => {
for player in players {
let player_info = PlayerInfo {
profile: GameProfile {
uuid: player.uuid,
name: player.name.clone(),
properties: player.properties.clone(),
},
uuid: player.uuid,
gamemode: player.gamemode,
latency: player.latency,
display_name: player.display_name.clone(),
};
players_lock.insert(player.uuid, player_info.clone());
tx.send(Event::UpdatePlayers(UpdatePlayersEvent::Add(player_info)))
.unwrap();
}
}
Action::UpdateGameMode(players) => {
for player in players {
if let Some(p) = players_lock.get_mut(&player.uuid) {
p.gamemode = player.gamemode;
tx.send(Event::UpdatePlayers(UpdatePlayersEvent::GameMode {
uuid: player.uuid,
game_mode: player.gamemode,
}))
.unwrap();
} else {
warn!(
"Ignoring PlayerInfo (UpdateGameMode) for unknown player {}",
player.uuid
);
}
}
}
Action::UpdateLatency(players) => {
for player in players {
if let Some(p) = players_lock.get_mut(&player.uuid) {
p.latency = player.latency;
tx.send(Event::UpdatePlayers(UpdatePlayersEvent::Latency {
uuid: player.uuid,
latency: player.latency,
}))
.unwrap();
} else {
warn!(
"Ignoring PlayerInfo (UpdateLatency) for unknown player {}",
player.uuid
);
}
}
}
Action::UpdateDisplayName(players) => {
for player in players {
if let Some(p) = players_lock.get_mut(&player.uuid) {
p.display_name = player.display_name.clone();
tx.send(Event::UpdatePlayers(UpdatePlayersEvent::DisplayName {
uuid: player.uuid,
display_name: player.display_name.clone(),
}))
.unwrap();
} else {
warn!(
"Ignoring PlayerInfo (UpdateDisplayName) for unknown player {}",
player.uuid
);
}
}
}
Action::RemovePlayer(players) => {
for player in players {
if players_lock.remove(&player.uuid).is_some() {
tx.send(Event::UpdatePlayers(UpdatePlayersEvent::Remove {
uuid: player.uuid,
}))
.unwrap();
} else {
warn!(
"Ignoring PlayerInfo (RemovePlayer) for unknown player {}",
player.uuid
);
}
}
}
}
// TODO
}
ClientboundGamePacket::SetChunkCacheCenter(p) => {
debug!("Got chunk cache center packet {:?}", p);
@ -853,8 +972,8 @@ impl Client {
// return if there's no chunk at the player's position
{
let world_lock = client.world.write();
let player_lock = client.player.write();
let player_entity = player_lock.entity(&world_lock);
let player_entity_id = *client.entity_id.read();
let player_entity = world_lock.entity(player_entity_id);
let player_entity = if let Some(player_entity) = player_entity {
player_entity
} else {
@ -899,10 +1018,7 @@ impl Client {
/// Returns the entity associated to the player.
pub fn entity_mut(&self) -> Entity<RwLockWriteGuard<World>> {
let entity_id = {
let player_lock = self.player.write();
player_lock.entity_id
};
let entity_id = *self.entity_id.read();
let mut world = self.world.write();
@ -915,10 +1031,7 @@ impl Client {
}
/// Returns the entity associated to the player.
pub fn entity(&self) -> Entity<RwLockReadGuard<World>> {
let entity_id = {
let player_lock = self.player.read();
player_lock.entity_id
};
let entity_id = *self.entity_id.read();
let world = self.world.read();

View file

@ -20,7 +20,7 @@ mod plugins;
pub use account::Account;
pub use client::{ChatPacket, Client, ClientInformation, Event, JoinError, PhysicsState};
pub use movement::{SprintDirection, WalkDirection};
pub use player::Player;
pub use player::PlayerInfo;
pub use plugins::{Plugin, Plugins};
#[cfg(test)]

View file

@ -153,20 +153,20 @@ impl Client {
// Set our current position to the provided Vec3, potentially clipping through blocks.
pub async fn set_pos(&mut self, new_pos: Vec3) -> Result<(), MovePlayerError> {
let player_lock = self.player.write();
let player_entity_id = *self.entity_id.read();
let mut world_lock = self.world.write();
world_lock.set_entity_pos(player_lock.entity_id, new_pos)?;
world_lock.set_entity_pos(player_entity_id, new_pos)?;
Ok(())
}
pub async fn move_entity(&mut self, movement: &Vec3) -> Result<(), MovePlayerError> {
let mut world_lock = self.world.write();
let player = self.player.write();
let player_entity_id = *self.entity_id.read();
let mut entity = player
.entity_mut(&mut world_lock)
let mut entity = world_lock
.entity_mut(player_entity_id)
.ok_or(MovePlayerError::PlayerNotInWorld)?;
log::trace!(
"move entity bounding box: {} {:?}",

View file

@ -1,37 +1,39 @@
use azalea_world::entity::Entity;
use azalea_auth::game_profile::GameProfile;
use azalea_chat::Component;
use azalea_core::GameType;
use azalea_world::entity::EntityData;
use azalea_world::World;
use uuid::Uuid;
/// Something that has a world associated to it. Usually, this is a `Client`.
/// Something that has a world associated to it. this is usually a `Client`.
pub trait WorldHaver {
fn world(&self) -> &World;
}
/// A player in the world or tab list.
#[derive(Default, Debug)]
pub struct Player {
/// The player's uuid.
/// A player in the tab list.
#[derive(Debug, Clone)]
pub struct PlayerInfo {
pub profile: GameProfile,
/// The player's UUID.
pub uuid: Uuid,
/// The player's entity id.
pub entity_id: u32,
pub gamemode: GameType,
pub latency: i32,
/// The player's display name in the tab list.
pub display_name: Option<Component>,
}
impl Player {
impl PlayerInfo {
/// Get a reference to the entity of the player in the world.
pub fn entity<'d>(&'d self, world: &'d World) -> Option<Entity<&World>> {
world.entity(self.entity_id)
pub fn entity<'d>(&'d self, world: &'d World) -> Option<&EntityData> {
world.entity_by_uuid(&self.uuid)
}
/// Get a mutable reference to the entity of the player in the world.
pub fn entity_mut<'d>(&'d self, world: &'d mut World) -> Option<Entity> {
world.entity_mut(self.entity_id)
pub fn entity_mut<'d>(&'d mut self, world: &'d mut World) -> Option<&'d mut EntityData> {
world.entity_mut_by_uuid(&self.uuid)
}
pub fn set_uuid(&mut self, uuid: Uuid) {
self.uuid = uuid;
}
pub fn set_entity_id(&mut self, entity_id: u32) {
self.entity_id = entity_id;
}
}

View file

@ -3,13 +3,13 @@ description = "Miscellaneous things in Azalea."
edition = "2021"
license = "MIT"
name = "azalea-core"
version = "0.3.0"
version = "0.4.0"
repository = "https://github.com/mat-1/azalea/tree/main/azalea-core"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
azalea-buf = {path = "../azalea-buf", version = "^0.3.0" }
azalea-chat = {path = "../azalea-chat", version = "^0.3.0" }
azalea-nbt = {path = "../azalea-nbt", version = "^0.3.0" }
azalea-buf = {path = "../azalea-buf", version = "^0.4.0" }
azalea-chat = {path = "../azalea-chat", version = "^0.4.0" }
azalea-nbt = {path = "../azalea-nbt", version = "^0.4.0" }
uuid = "^1.1.2"

View file

@ -3,19 +3,19 @@ use std::io::{Cursor, Write};
#[derive(Hash, Copy, Clone, Debug)]
pub enum GameType {
SURVIVAL,
CREATIVE,
ADVENTURE,
SPECTATOR,
Survival,
Creative,
Adventure,
Spectator,
}
impl GameType {
pub fn to_id(&self) -> u8 {
match self {
GameType::SURVIVAL => 0,
GameType::CREATIVE => 1,
GameType::ADVENTURE => 2,
GameType::SPECTATOR => 3,
GameType::Survival => 0,
GameType::Creative => 1,
GameType::Adventure => 2,
GameType::Spectator => 3,
}
}
@ -29,10 +29,10 @@ impl GameType {
pub fn from_id(id: u8) -> Option<GameType> {
Some(match id {
0 => GameType::SURVIVAL,
1 => GameType::CREATIVE,
2 => GameType::ADVENTURE,
3 => GameType::SPECTATOR,
0 => GameType::Survival,
1 => GameType::Creative,
2 => GameType::Adventure,
3 => GameType::Spectator,
_ => return None,
})
}
@ -50,29 +50,29 @@ impl GameType {
pub fn short_name(&self) -> &'static str {
// TODO: these should be translated TranslatableComponent("selectWorld.gameMode." + string2)
match self {
GameType::SURVIVAL => "Survival",
GameType::CREATIVE => "Creative",
GameType::ADVENTURE => "Adventure",
GameType::SPECTATOR => "Spectator",
GameType::Survival => "Survival",
GameType::Creative => "Creative",
GameType::Adventure => "Adventure",
GameType::Spectator => "Spectator",
}
}
pub fn long_name(&self) -> &'static str {
// TODO: These should be translated TranslatableComponent("gameMode." + string2);
match self {
GameType::SURVIVAL => "Survival Mode",
GameType::CREATIVE => "Creative Mode",
GameType::ADVENTURE => "Adventure Mode",
GameType::SPECTATOR => "Spectator Mode",
GameType::Survival => "Survival Mode",
GameType::Creative => "Creative Mode",
GameType::Adventure => "Adventure Mode",
GameType::Spectator => "Spectator Mode",
}
}
pub fn from_name(name: &str) -> GameType {
match name {
"survival" => GameType::SURVIVAL,
"creative" => GameType::CREATIVE,
"adventure" => GameType::ADVENTURE,
"spectator" => GameType::SPECTATOR,
"survival" => GameType::Survival,
"creative" => GameType::Creative,
"adventure" => GameType::Adventure,
"spectator" => GameType::Spectator,
_ => panic!("Unknown game type name: {name}"),
}
}

View file

@ -3,14 +3,14 @@ description = "Cryptography features used in Minecraft."
edition = "2021"
license = "MIT"
name = "azalea-crypto"
version = "0.3.0"
version = "0.4.0"
repository = "https://github.com/mat-1/azalea/tree/main/azalea-crypto"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
aes = "0.8.1"
azalea-buf = {path = "../azalea-buf", version = "^0.3.0" }
azalea-buf = {path = "../azalea-buf", version = "^0.4.0" }
cfb8 = "0.8.1"
num-bigint = "^0.4.3"
rand = {version = "^0.8.4", features = ["getrandom"]}

View file

@ -4,12 +4,12 @@ edition = "2021"
license = "MIT"
name = "azalea-language"
repository = "https://github.com/mat-1/azalea/tree/main/azalea-language"
version = "0.3.0"
version = "0.4.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
lazy_static = "1.4.0"
once_cell = "1.16.0"
serde = "1.0.137"
serde_json = "1.0.81"
# tokio = {version = "^1.21.2", features = ["fs"]}

View file

@ -1,4 +1,4 @@
# Azalea Assets
# Azalea Language
Translate Minecraft strings from their id.

View file

@ -1,6 +1,6 @@
//! Translate Minecraft strings from their id.
use lazy_static::lazy_static;
use once_cell::sync::Lazy;
use std::io::Read;
use std::path::Path;
use std::{collections::HashMap, fs::File};
@ -31,16 +31,16 @@ use std::{collections::HashMap, fs::File};
// Language object that we passed around everywhere which is not convenient
// The code above is kept in case I come up with a better solution
lazy_static! {
pub static ref STORAGE: HashMap<String, String> = serde_json::from_str(&{
pub static STORAGE: Lazy<HashMap<String, String>> = Lazy::new(|| {
serde_json::from_str(&{
let src_dir = Path::new(concat!(env!("CARGO_MANIFEST_DIR"), "/src/en_us.json"));
let mut file = File::open(src_dir).unwrap();
let mut contents = String::new();
file.read_to_string(&mut contents).unwrap();
contents
})
.unwrap();
}
.unwrap()
});
pub fn get(key: &str) -> Option<&str> {
STORAGE.get(key).map(|s| s.as_str())

View file

@ -3,14 +3,14 @@ description = "A fast NBT serializer and deserializer."
edition = "2021"
license = "MIT"
name = "azalea-nbt"
version = "0.3.0"
version = "0.4.0"
repository = "https://github.com/mat-1/azalea/tree/main/azalea-nbt"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
ahash = "^0.8.0"
azalea-buf = {path = "../azalea-buf", version = "^0.3.0" }
azalea-buf = {path = "../azalea-buf", version = "^0.4.0" }
byteorder = "^1.4.3"
flate2 = "^1.0.23"
log = "0.4.17"

View file

@ -4,15 +4,15 @@ edition = "2021"
license = "MIT"
name = "azalea-physics"
repository = "https://github.com/mat-1/azalea/tree/main/azalea-physics"
version = "0.3.0"
version = "0.4.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
azalea-block = {path = "../azalea-block", version = "^0.3.0"}
azalea-core = {path = "../azalea-core", version = "^0.3.0"}
azalea-world = {path = "../azalea-world", version = "^0.3.0"}
lazy_static = "1.4.0"
azalea-block = {path = "../azalea-block", version = "^0.4.0" }
azalea-core = {path = "../azalea-core", version = "^0.4.0" }
azalea-world = {path = "../azalea-world", version = "^0.4.0" }
once_cell = "1.16.0"
parking_lot = "^0.12.1"
[dev-dependencies]

File diff suppressed because it is too large Load diff

View file

@ -4,24 +4,24 @@ edition = "2021"
license = "MIT"
name = "azalea-protocol"
repository = "https://github.com/mat-1/azalea/tree/main/azalea-protocol"
version = "0.3.0"
version = "0.4.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
async-compression = {version = "^0.3.8", features = ["tokio", "zlib"], optional = true}
async-recursion = "1.0.0"
azalea-auth = {path = "../azalea-auth", version = "^0.3.0"}
azalea-block = {path = "../azalea-block", default-features = false, version = "^0.3.0"}
azalea-brigadier = {path = "../azalea-brigadier", version = "^0.3.0"}
azalea-buf = {path = "../azalea-buf", version = "^0.3.0"}
azalea-chat = {path = "../azalea-chat", version = "^0.3.0"}
azalea-core = {path = "../azalea-core", optional = true, version = "^0.3.0"}
azalea-crypto = {path = "../azalea-crypto", version = "^0.3.0"}
azalea-nbt = {path = "../azalea-nbt", version = "^0.3.0"}
azalea-protocol-macros = {path = "./azalea-protocol-macros", version = "^0.3.0"}
azalea-registry = {path = "../azalea-registry", version = "^0.3.0"}
azalea-world = {path = "../azalea-world", version = "^0.3.0"}
azalea-auth = {path = "../azalea-auth", version = "^0.4.0" }
azalea-block = {path = "../azalea-block", default-features = false, version = "^0.4.0" }
azalea-brigadier = {path = "../azalea-brigadier", version = "^0.4.0" }
azalea-buf = {path = "../azalea-buf", version = "^0.4.0" }
azalea-chat = {path = "../azalea-chat", version = "^0.4.0" }
azalea-core = {path = "../azalea-core", optional = true, version = "^0.4.0" }
azalea-crypto = {path = "../azalea-crypto", version = "^0.4.0" }
azalea-nbt = {path = "../azalea-nbt", version = "^0.4.0" }
azalea-protocol-macros = {path = "./azalea-protocol-macros", version = "^0.4.0" }
azalea-registry = {path = "../azalea-registry", version = "^0.4.0" }
azalea-world = {path = "../azalea-world", version = "^0.4.0" }
byteorder = "^1.4.3"
bytes = "^1.1.0"
flate2 = "1.0.23"

View file

@ -3,7 +3,7 @@ description = "Macros internally used in azalea-protocol."
edition = "2021"
license = "MIT"
name = "azalea-protocol-macros"
version = "0.3.0"
version = "0.4.0"
repository = "https://github.com/mat-1/azalea/tree/main/azalea-protocol/azalea-protocol-macros"
[lib]

View file

@ -1,8 +1,11 @@
use crate::packets::login::serverbound_hello_packet::ProfilePublicKeyData;
use azalea_auth::game_profile::ProfilePropertyValue;
use azalea_buf::{BufReadError, McBuf};
use azalea_buf::{McBufReadable, McBufWritable};
use azalea_chat::Component;
use azalea_core::GameType;
use azalea_protocol_macros::ClientboundGamePacket;
use std::collections::HashMap;
use std::io::{Cursor, Write};
use uuid::Uuid;
@ -20,22 +23,14 @@ pub enum Action {
RemovePlayer(Vec<RemovePlayer>),
}
#[derive(Clone, Debug, McBuf)]
pub struct PlayerProperty {
pub name: String,
pub value: String,
pub signature: Option<String>,
}
#[derive(Clone, Debug, McBuf)]
pub struct AddPlayer {
pub uuid: Uuid,
pub name: String,
pub properties: Vec<PlayerProperty>,
pub properties: HashMap<String, ProfilePropertyValue>,
pub gamemode: GameType,
#[var]
pub gamemode: u32,
#[var]
pub ping: i32,
pub latency: i32,
pub display_name: Option<Component>,
pub profile_public_key: Option<ProfilePublicKeyData>,
}
@ -43,15 +38,14 @@ pub struct AddPlayer {
#[derive(Clone, Debug, McBuf)]
pub struct UpdateGameMode {
pub uuid: Uuid,
#[var]
pub gamemode: u32,
pub gamemode: GameType,
}
#[derive(Clone, Debug, McBuf)]
pub struct UpdateLatency {
pub uuid: Uuid,
#[var]
pub ping: i32,
pub latency: i32,
}
#[derive(Clone, Debug, McBuf)]

View file

@ -3,11 +3,11 @@ description = "Use Minecraft's registries."
edition = "2021"
license = "MIT"
name = "azalea-registry"
version = "0.3.0"
version = "0.4.0"
repository = "https://github.com/mat-1/azalea/tree/main/azalea-registry"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
azalea-buf = {path = "../azalea-buf", version = "^0.3.0" }
azalea-registry-macros = {path = "./azalea-registry-macros", version = "^0.3.0" }
azalea-buf = {path = "../azalea-buf", version = "^0.4.0" }
azalea-registry-macros = {path = "./azalea-registry-macros", version = "^0.4.0" }

View file

@ -4,7 +4,7 @@ edition = "2021"
license = "MIT"
name = "azalea-registry-macros"
repository = "https://github.com/mat-1/azalea/tree/main/azalea-registry/azalea-registry-macros"
version = "0.3.0"
version = "0.4.0"
[lib]
proc-macro = true

View file

@ -4,17 +4,17 @@ edition = "2021"
license = "MIT"
name = "azalea-world"
repository = "https://github.com/mat-1/azalea/tree/main/azalea-world"
version = "0.3.0"
version = "0.4.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
azalea-block = {path = "../azalea-block", default-features = false, version = "^0.3.0"}
azalea-buf = {path = "../azalea-buf", version = "^0.3.0"}
azalea-chat = {path = "../azalea-chat", version = "^0.3.0"}
azalea-core = {path = "../azalea-core", version = "^0.3.0"}
azalea-nbt = {path = "../azalea-nbt", version = "^0.3.0"}
azalea-registry = {path = "../azalea-registry", version = "^0.3.0"}
azalea-block = {path = "../azalea-block", default-features = false, version = "^0.4.0" }
azalea-buf = {path = "../azalea-buf", version = "^0.4.0" }
azalea-chat = {path = "../azalea-chat", version = "^0.4.0" }
azalea-core = {path = "../azalea-core", version = "^0.4.0" }
azalea-nbt = {path = "../azalea-nbt", version = "^0.4.0" }
azalea-registry = {path = "../azalea-registry", version = "^0.4.0" }
enum-as-inner = "0.5.1"
log = "0.4.17"
nohash-hasher = "0.2.0"

0
azalea-world/src/lib.rs Executable file → Normal file
View file

View file

@ -4,7 +4,7 @@ edition = "2021"
license = "MIT"
name = "azalea"
repository = "https://github.com/mat-1/azalea/tree/main/azalea"
version = "0.3.0"
version = "0.4.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

View file

@ -27,17 +27,17 @@ async fn main() {
async fn handle(bot: Client, event: Event, state: State) -> anyhow::Result<()> {
match event {
Event::Chat(m) => {
if m.username == bot.player.username {
if m.username() == Some(bot.game_profile.name) {
return Ok(());
};
if m.content == "go" {
// make sure we only start once
let ctx_lock = ctx.lock().unwrap();
if ctx_lock.started {
return;
};
ctx_lock.started = true;
drop(ctx_lock);
if m.content() == "go" {
{
// make sure we only start once
if *state.started.lock() {
return Ok(());
};
*state.started.lock() = true;
}
bot.goto(pathfinder::Goals::NearXZ(5, azalea::BlockXZ(0, 0)))
.await;

View file

@ -24,10 +24,12 @@ pub struct State {}
async fn handle(bot: Client, event: Event, state: State) -> anyhow::Result<()> {
match event {
Event::Chat(m) => {
if m.username == bot.username {
return Ok(()); // ignore our own messages
if let (Some(sender), content) = m.split_sender_and_content() {
if sender == bot.game_profile.name {
return Ok(()); // ignore our own messages
}
bot.chat(&content).await?;
};
bot.chat(m.content).await;
}
_ => {}
}

View file

@ -6,6 +6,7 @@ use crate::{Client, Event};
use async_trait::async_trait;
use azalea_core::{BlockPos, CardinalDirection};
use azalea_world::entity::EntityData;
use log::debug;
use mtdstarlite::Edge;
pub use mtdstarlite::MTDStarLite;
use parking_lot::Mutex;
@ -47,7 +48,7 @@ impl Trait for azalea_client::Client {
vertical_vel: VerticalVel::None,
};
let end = goal.goal_node();
println!("start: {:?}, end: {:?}", start, end);
debug!("start: {start:?}, end: {end:?}");
let possible_moves: Vec<&dyn moves::Move> = vec![
&moves::ForwardMove(CardinalDirection::North),
@ -96,8 +97,8 @@ impl Trait for azalea_client::Client {
let start = std::time::Instant::now();
let p = pf.find_path();
let end = std::time::Instant::now();
println!("path: {:?}", p);
println!("time: {:?}", end - start);
debug!("path: {p:?}");
debug!("time: {:?}", end - start);
let state = self
.plugins

View file

@ -33,7 +33,7 @@ async fn main() -> anyhow::Result<()> {
println!("{} deadlocks detected", deadlocks.len());
for (i, threads) in deadlocks.iter().enumerate() {
println!("Deadlock #{}", i);
println!("Deadlock #{i}");
for t in threads {
println!("Thread Id {:#?}", t.thread_id());
println!("{:#?}", t.backtrace());
@ -67,7 +67,7 @@ async fn main() -> anyhow::Result<()> {
join_delay: Some(std::time::Duration::from_secs(5)),
})
.await;
println!("{:?}", e);
println!("{e:?}");
}
}

View file

@ -49,14 +49,8 @@ def generate_block_shapes_code(blocks: dict, shapes: dict, block_states_report,
# look at downloads/generator-mod-*/blockCollisionShapes.json for format of blocks and shapes
generated_shape_code = ''
# we make several lazy_static! blocks so it doesn't complain about
# recursion and hopefully the compiler can paralleize it?
generated_shape_code += 'lazy_static! {'
for i, (shape_id, shape) in enumerate(sorted(shapes.items(), key=lambda shape: int(shape[0]))):
if i > 0 and i % 10 == 0:
generated_shape_code += '}\nlazy_static! {'
for (shape_id, shape) in sorted(shapes.items(), key=lambda shape: int(shape[0])):
generated_shape_code += generate_code_for_shape(shape_id, shape)
generated_shape_code += '}'
# BlockState::PurpurStairs_NorthTopStraightTrue => &SHAPE24,
generated_match_inner_code = ''
@ -93,11 +87,12 @@ def generate_block_shapes_code(blocks: dict, shapes: dict, block_states_report,
// modify it, change that file.
#![allow(clippy::explicit_auto_deref)]
#![allow(clippy::redundant_closure)]
use super::VoxelShape;
use crate::collision::{{self, Shapes}};
use azalea_block::*;
use lazy_static::lazy_static;
use once_cell::sync::Lazy;
pub trait BlockWithShape {{
fn shape(&self) -> &'static VoxelShape;
@ -119,7 +114,7 @@ def generate_code_for_shape(shape_id: str, parts: list[list[float]]):
def make_arguments(part: list[float]):
return ', '.join(map(lambda n: str(n).rstrip('0'), part))
code = ''
code += f'static ref SHAPE{shape_id}: VoxelShape = '
code += f'static SHAPE{shape_id}: Lazy<VoxelShape> = Lazy::new(|| {{'
steps = []
if parts == []:
steps.append('collision::empty_shape()')
@ -136,5 +131,6 @@ def generate_code_for_shape(shape_id: str, parts: list[list[float]]):
for step in steps[:-1]:
code += f' let s = {step};\n'
code += f' {steps[-1]}\n'
code += '};\n'
code += '}\n'
code += '});\n'
return code