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:
commit
336d155049
40 changed files with 3423 additions and 3265 deletions
3
.github/FUNDING.yml
vendored
Normal file
3
.github/FUNDING.yml
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
# These are supported funding model platforms
|
||||
|
||||
ko_fi: matdoesdev
|
2704
Cargo.lock
generated
2704
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -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"
|
||||
|
|
|
@ -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" }
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -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: {} {:?}",
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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}"),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"]}
|
||||
|
|
|
@ -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"]}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Azalea Assets
|
||||
# Azalea Language
|
||||
|
||||
Translate Minecraft strings from their id.
|
||||
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
@ -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"
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -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" }
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
0
azalea-world/src/lib.rs
Executable file → Normal 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
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:?}");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue