mirror of
https://github.com/mat-1/azalea.git
synced 2025-08-02 14:26:04 +00:00
merge main
This commit is contained in:
commit
2ae0fe044f
66 changed files with 7075 additions and 21152 deletions
60
Cargo.lock
generated
60
Cargo.lock
generated
|
@ -162,7 +162,7 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "azalea"
|
name = "azalea"
|
||||||
version = "0.5.0"
|
version = "0.6.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
|
@ -180,7 +180,6 @@ dependencies = [
|
||||||
"env_logger 0.10.0",
|
"env_logger 0.10.0",
|
||||||
"futures",
|
"futures",
|
||||||
"futures-lite",
|
"futures-lite",
|
||||||
"iyes_loopless",
|
|
||||||
"log",
|
"log",
|
||||||
"nohash-hasher",
|
"nohash-hasher",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
|
@ -193,7 +192,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "azalea-auth"
|
name = "azalea-auth"
|
||||||
version = "0.5.0"
|
version = "0.6.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"azalea-buf",
|
"azalea-buf",
|
||||||
"azalea-crypto",
|
"azalea-crypto",
|
||||||
|
@ -211,15 +210,16 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "azalea-block"
|
name = "azalea-block"
|
||||||
version = "0.5.0"
|
version = "0.6.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"azalea-block-macros",
|
"azalea-block-macros",
|
||||||
"azalea-buf",
|
"azalea-buf",
|
||||||
|
"azalea-registry",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "azalea-block-macros"
|
name = "azalea-block-macros"
|
||||||
version = "0.5.0"
|
version = "0.6.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -228,7 +228,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "azalea-brigadier"
|
name = "azalea-brigadier"
|
||||||
version = "0.5.0"
|
version = "0.6.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"azalea-buf",
|
"azalea-buf",
|
||||||
"azalea-chat",
|
"azalea-chat",
|
||||||
|
@ -236,7 +236,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "azalea-buf"
|
name = "azalea-buf"
|
||||||
version = "0.5.0"
|
version = "0.6.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"azalea-buf-macros",
|
"azalea-buf-macros",
|
||||||
"byteorder",
|
"byteorder",
|
||||||
|
@ -249,7 +249,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "azalea-buf-macros"
|
name = "azalea-buf-macros"
|
||||||
version = "0.5.0"
|
version = "0.6.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -258,7 +258,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "azalea-chat"
|
name = "azalea-chat"
|
||||||
version = "0.5.0"
|
version = "0.6.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"azalea-buf",
|
"azalea-buf",
|
||||||
"azalea-language",
|
"azalea-language",
|
||||||
|
@ -270,7 +270,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "azalea-client"
|
name = "azalea-client"
|
||||||
version = "0.5.0"
|
version = "0.6.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
|
@ -290,7 +290,6 @@ dependencies = [
|
||||||
"derive_more",
|
"derive_more",
|
||||||
"env_logger 0.9.3",
|
"env_logger 0.9.3",
|
||||||
"futures",
|
"futures",
|
||||||
"iyes_loopless",
|
|
||||||
"log",
|
"log",
|
||||||
"nohash-hasher",
|
"nohash-hasher",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
|
@ -304,7 +303,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "azalea-core"
|
name = "azalea-core"
|
||||||
version = "0.5.0"
|
version = "0.6.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"azalea-buf",
|
"azalea-buf",
|
||||||
"azalea-chat",
|
"azalea-chat",
|
||||||
|
@ -316,7 +315,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "azalea-crypto"
|
name = "azalea-crypto"
|
||||||
version = "0.5.0"
|
version = "0.6.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aes",
|
"aes",
|
||||||
"azalea-buf",
|
"azalea-buf",
|
||||||
|
@ -331,18 +330,17 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "azalea-ecs"
|
name = "azalea-ecs"
|
||||||
version = "0.5.0"
|
version = "0.6.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"azalea-ecs-macros",
|
"azalea-ecs-macros",
|
||||||
"bevy_app",
|
"bevy_app",
|
||||||
"bevy_ecs",
|
"bevy_ecs",
|
||||||
"iyes_loopless",
|
|
||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "azalea-ecs-macros"
|
name = "azalea-ecs-macros"
|
||||||
version = "0.5.0"
|
version = "0.6.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -369,7 +367,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "azalea-language"
|
name = "azalea-language"
|
||||||
version = "0.5.0"
|
version = "0.6.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"serde",
|
"serde",
|
||||||
|
@ -378,7 +376,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "azalea-nbt"
|
name = "azalea-nbt"
|
||||||
version = "0.5.0"
|
version = "0.6.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ahash 0.8.3",
|
"ahash 0.8.3",
|
||||||
"azalea-buf",
|
"azalea-buf",
|
||||||
|
@ -393,14 +391,13 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "azalea-physics"
|
name = "azalea-physics"
|
||||||
version = "0.5.0"
|
version = "0.6.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"azalea-block",
|
"azalea-block",
|
||||||
"azalea-core",
|
"azalea-core",
|
||||||
"azalea-ecs",
|
"azalea-ecs",
|
||||||
"azalea-registry",
|
"azalea-registry",
|
||||||
"azalea-world",
|
"azalea-world",
|
||||||
"iyes_loopless",
|
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
"uuid",
|
"uuid",
|
||||||
|
@ -408,7 +405,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "azalea-protocol"
|
name = "azalea-protocol"
|
||||||
version = "0.5.0"
|
version = "0.6.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-compression",
|
"async-compression",
|
||||||
|
@ -445,7 +442,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "azalea-protocol-macros"
|
name = "azalea-protocol-macros"
|
||||||
version = "0.5.0"
|
version = "0.6.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -454,7 +451,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "azalea-registry"
|
name = "azalea-registry"
|
||||||
version = "0.5.0"
|
version = "0.6.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"azalea-buf",
|
"azalea-buf",
|
||||||
"azalea-registry-macros",
|
"azalea-registry-macros",
|
||||||
|
@ -463,7 +460,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "azalea-registry-macros"
|
name = "azalea-registry-macros"
|
||||||
version = "0.5.0"
|
version = "0.6.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -472,7 +469,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "azalea-world"
|
name = "azalea-world"
|
||||||
version = "0.5.0"
|
version = "0.6.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"azalea-block",
|
"azalea-block",
|
||||||
"azalea-buf",
|
"azalea-buf",
|
||||||
|
@ -483,7 +480,6 @@ dependencies = [
|
||||||
"azalea-registry",
|
"azalea-registry",
|
||||||
"derive_more",
|
"derive_more",
|
||||||
"enum-as-inner",
|
"enum-as-inner",
|
||||||
"iyes_loopless",
|
|
||||||
"log",
|
"log",
|
||||||
"nohash-hasher",
|
"nohash-hasher",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
|
@ -1547,18 +1543,6 @@ version = "1.0.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440"
|
checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "iyes_loopless"
|
|
||||||
version = "0.9.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "c47fd2cbdb1d7f295c25e6bfccfd78a84b6eef3055bc9f01b34ae861721b01ee"
|
|
||||||
dependencies = [
|
|
||||||
"bevy_app",
|
|
||||||
"bevy_ecs",
|
|
||||||
"bevy_time",
|
|
||||||
"bevy_utils",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "js-sys"
|
name = "js-sys"
|
||||||
version = "0.3.61"
|
version = "0.3.61"
|
||||||
|
|
|
@ -4,13 +4,13 @@ edition = "2021"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
name = "azalea-auth"
|
name = "azalea-auth"
|
||||||
repository = "https://github.com/mat-1/azalea/tree/main/azalea-auth"
|
repository = "https://github.com/mat-1/azalea/tree/main/azalea-auth"
|
||||||
version = "0.5.0"
|
version = "0.6.0"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
azalea-buf = {path = "../azalea-buf", version = "^0.5.0"}
|
azalea-buf = {path = "../azalea-buf", version = "^0.6.0" }
|
||||||
azalea-crypto = {path = "../azalea-crypto", version = "^0.5.0"}
|
azalea-crypto = {path = "../azalea-crypto", version = "^0.6.0" }
|
||||||
chrono = {version = "0.4.22", default-features = false}
|
chrono = {version = "0.4.22", default-features = false}
|
||||||
log = "0.4.17"
|
log = "0.4.17"
|
||||||
num-bigint = "0.4.3"
|
num-bigint = "0.4.3"
|
||||||
|
|
7
azalea-block/Cargo.toml
Executable file → Normal file
7
azalea-block/Cargo.toml
Executable file → Normal file
|
@ -4,12 +4,13 @@ edition = "2021"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
name = "azalea-block"
|
name = "azalea-block"
|
||||||
repository = "https://github.com/mat-1/azalea/tree/main/azalea-block"
|
repository = "https://github.com/mat-1/azalea/tree/main/azalea-block"
|
||||||
version = "0.5.0"
|
version = "0.6.0"
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
azalea-block-macros = {path = "./azalea-block-macros", version = "^0.5.0" }
|
azalea-block-macros = { path = "./azalea-block-macros", version = "^0.6.0" }
|
||||||
azalea-buf = {path = "../azalea-buf", version = "^0.5.0" }
|
azalea-buf = { path = "../azalea-buf", version = "^0.6.0" }
|
||||||
|
azalea-registry = { version = "0.6.0", path = "../azalea-registry" }
|
||||||
|
|
|
@ -1,10 +1,48 @@
|
||||||
# Azalea Block
|
|
||||||
|
|
||||||
Representation of Minecraft block states.
|
Representation of Minecraft block states.
|
||||||
|
|
||||||
There's two main things here, the `BlockState` enum and the `Block` trait.
|
There's three block types, used for different things. You can (mostly) convert between them with `.into()`.
|
||||||
`BlockState` is a simple enum with every possible block state as variant, and `Block` is a heavier trait which lets you access information about a block more easily.
|
|
||||||
|
|
||||||
Every block is a struct that implements `Block`. You can freely convert between `BlockState` and `Block` with .into().
|
## BlockState struct
|
||||||
|
|
||||||
|
[`BlockState`] is a struct containing the numerical protocol ID of a block state. This is how blocks are stored in the world.
|
||||||
|
|
||||||
|
```
|
||||||
|
# use azalea_block::BlockState;
|
||||||
|
let block_state: BlockState = azalea_block::CobblestoneWallBlock {
|
||||||
|
east: azalea_block::EastWall::Low,
|
||||||
|
north: azalea_block::NorthWall::Low,
|
||||||
|
south: azalea_block::SouthWall::Low,
|
||||||
|
west: azalea_block::WestWall::Low,
|
||||||
|
up: false,
|
||||||
|
waterlogged: false,
|
||||||
|
}
|
||||||
|
.into();
|
||||||
|
```
|
||||||
|
```
|
||||||
|
# use azalea_block::BlockState;
|
||||||
|
let block_state: BlockState = azalea_registry::Block::Jukebox.into();
|
||||||
|
```
|
||||||
|
|
||||||
|
## Block trait
|
||||||
|
|
||||||
|
The [`Block`] trait represents a type of a block. With the the [`Block`] trait, you can get some extra things like the string block ID and some information about the block's behavior. Also, the structs that implement the trait contain the block attributes as fields so it's more convenient to get them. Note that this is often used as `Box<dyn Block>`.
|
||||||
|
If for some reason you don't want the `Block` trait, set default-features to false.
|
||||||
|
|
||||||
|
```
|
||||||
|
# use azalea_block::{Block, BlockState};
|
||||||
|
# let block_state = BlockState::from(azalea_registry::Block::Jukebox);
|
||||||
|
let block = Box::<dyn Block>::from(block_state);
|
||||||
|
```
|
||||||
|
```
|
||||||
|
# use azalea_block::{Block, BlockState};
|
||||||
|
# let block_state: BlockState = azalea_registry::Block::Jukebox.into();
|
||||||
|
if let Some(jukebox) = Box::<dyn Block>::from(block_state).downcast_ref::<azalea_block::JukeboxBlock>() {
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## azalea_registry::Block enum
|
||||||
|
|
||||||
|
This one technically isn't from the `azalea-block` crate, but it's still very relevant. It's an enum that contains every block type as a variant *without* containing any state data (unlike `BlockState` and the `Block` trait). Converting this into any other block type will use the default state for that block.
|
||||||
|
|
||||||
If you don't want the `Block` trait, set default-features to false.
|
|
||||||
|
|
2
azalea-block/azalea-block-macros/Cargo.toml
Executable file → Normal file
2
azalea-block/azalea-block-macros/Cargo.toml
Executable file → Normal file
|
@ -4,7 +4,7 @@ edition = "2021"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
name = "azalea-block-macros"
|
name = "azalea-block-macros"
|
||||||
repository = "https://github.com/mat-1/azalea/tree/main/azalea-block/azalea-block-macros"
|
repository = "https://github.com/mat-1/azalea/tree/main/azalea-block/azalea-block-macros"
|
||||||
version = "0.5.0"
|
version = "0.6.0"
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
proc-macro = true
|
proc-macro = true
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
mod utils;
|
mod utils;
|
||||||
|
|
||||||
use proc_macro::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
|
use proc_macro2::TokenTree;
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
|
@ -234,7 +235,7 @@ pub fn make_block_states(input: TokenStream) -> TokenStream {
|
||||||
let mut properties_map = HashMap::new();
|
let mut properties_map = HashMap::new();
|
||||||
let mut property_struct_names_to_names = HashMap::new();
|
let mut property_struct_names_to_names = HashMap::new();
|
||||||
|
|
||||||
let mut state_id: usize = 0;
|
let mut state_id: u32 = 0;
|
||||||
|
|
||||||
for property in &input.property_definitions.properties {
|
for property in &input.property_definitions.properties {
|
||||||
let property_type_name: Ident;
|
let property_type_name: Ident;
|
||||||
|
@ -282,8 +283,8 @@ pub fn make_block_states(input: TokenStream) -> TokenStream {
|
||||||
#property_enum_variants
|
#property_enum_variants
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<usize> for #property_type_name {
|
impl From<u32> for #property_type_name {
|
||||||
fn from(value: usize) -> Self {
|
fn from(value: u32) -> Self {
|
||||||
match value {
|
match value {
|
||||||
#property_from_number_variants
|
#property_from_number_variants
|
||||||
_ => panic!("Invalid property value: {}", value),
|
_ => panic!("Invalid property value: {}", value),
|
||||||
|
@ -305,7 +306,11 @@ pub fn make_block_states(input: TokenStream) -> TokenStream {
|
||||||
|
|
||||||
let mut block_state_enum_variants = quote! {};
|
let mut block_state_enum_variants = quote! {};
|
||||||
let mut block_structs = quote! {};
|
let mut block_structs = quote! {};
|
||||||
|
|
||||||
let mut from_state_to_block_match = quote! {};
|
let mut from_state_to_block_match = quote! {};
|
||||||
|
let mut from_registry_block_to_block_match = quote! {};
|
||||||
|
let mut from_registry_block_to_blockstate_match = quote! {};
|
||||||
|
|
||||||
for block in &input.block_definitions.blocks {
|
for block in &input.block_definitions.blocks {
|
||||||
let block_property_names = &block
|
let block_property_names = &block
|
||||||
.properties_and_defaults
|
.properties_and_defaults
|
||||||
|
@ -403,30 +408,18 @@ pub fn make_block_states(input: TokenStream) -> TokenStream {
|
||||||
let mut from_block_to_state_match_inner = quote! {};
|
let mut from_block_to_state_match_inner = quote! {};
|
||||||
|
|
||||||
let first_state_id = state_id;
|
let first_state_id = state_id;
|
||||||
|
let mut default_state_id = None;
|
||||||
|
|
||||||
// if there's no properties, then the block is just a single state
|
// if there's no properties, then the block is just a single state
|
||||||
if block_properties_vec.is_empty() {
|
if block_properties_vec.is_empty() {
|
||||||
block_state_enum_variants.extend(quote! {
|
block_state_enum_variants.extend(quote! {
|
||||||
#block_name_pascal_case,
|
#block_name_pascal_case,
|
||||||
});
|
});
|
||||||
|
default_state_id = Some(state_id);
|
||||||
state_id += 1;
|
state_id += 1;
|
||||||
}
|
}
|
||||||
for combination in combinations_of(&block_properties_vec) {
|
for combination in combinations_of(&block_properties_vec) {
|
||||||
state_id += 1;
|
let mut is_default = true;
|
||||||
let variant_name = Ident::new(
|
|
||||||
&format!(
|
|
||||||
"{}_{}",
|
|
||||||
block_name_pascal_case,
|
|
||||||
combination
|
|
||||||
.iter()
|
|
||||||
.map(|v| v[0..1].to_uppercase() + &v[1..])
|
|
||||||
.collect::<String>()
|
|
||||||
),
|
|
||||||
proc_macro2::Span::call_site(),
|
|
||||||
);
|
|
||||||
block_state_enum_variants.extend(quote! {
|
|
||||||
#variant_name,
|
|
||||||
});
|
|
||||||
|
|
||||||
// face: properties::Face::Floor,
|
// face: properties::Face::Floor,
|
||||||
// facing: properties::Facing::North,
|
// facing: properties::Facing::North,
|
||||||
|
@ -439,6 +432,18 @@ pub fn make_block_states(input: TokenStream) -> TokenStream {
|
||||||
let variant =
|
let variant =
|
||||||
Ident::new(&combination[i].to_string(), proc_macro2::Span::call_site());
|
Ident::new(&combination[i].to_string(), proc_macro2::Span::call_site());
|
||||||
|
|
||||||
|
// this terrible code just gets the property default as a string
|
||||||
|
let property_default_as_string = if let TokenTree::Ident(i) =
|
||||||
|
property.default.clone().into_iter().last().unwrap()
|
||||||
|
{
|
||||||
|
i.to_string()
|
||||||
|
} else {
|
||||||
|
panic!()
|
||||||
|
};
|
||||||
|
if property_default_as_string != combination[i] {
|
||||||
|
is_default = false;
|
||||||
|
}
|
||||||
|
|
||||||
let property_type = if property.is_enum {
|
let property_type = if property.is_enum {
|
||||||
quote! {#property_struct_name_ident::#variant}
|
quote! {#property_struct_name_ident::#variant}
|
||||||
} else {
|
} else {
|
||||||
|
@ -453,10 +458,21 @@ pub fn make_block_states(input: TokenStream) -> TokenStream {
|
||||||
from_block_to_state_match_inner.extend(quote! {
|
from_block_to_state_match_inner.extend(quote! {
|
||||||
#block_struct_name {
|
#block_struct_name {
|
||||||
#from_block_to_state_combination_match_inner
|
#from_block_to_state_combination_match_inner
|
||||||
} => BlockState::#variant_name,
|
} => BlockState { id: #state_id },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if is_default {
|
||||||
|
default_state_id = Some(state_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
state_id += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let Some(default_state_id) = default_state_id else {
|
||||||
|
let defaults = properties_with_name.iter().map(|p| if let TokenTree::Ident(i) = p.default.clone().into_iter().last().unwrap() { i.to_string() } else { panic!() }).collect::<Vec<_>>();
|
||||||
|
panic!("Couldn't get default state id for {block_name_pascal_case}, combinations={block_properties_vec:?}, defaults={defaults:?}")
|
||||||
|
};
|
||||||
|
|
||||||
// 7035..=7058 => {
|
// 7035..=7058 => {
|
||||||
// let b = b - 7035;
|
// let b = b - 7035;
|
||||||
// &AcaciaButtonBlock {
|
// &AcaciaButtonBlock {
|
||||||
|
@ -466,7 +482,7 @@ pub fn make_block_states(input: TokenStream) -> TokenStream {
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
let mut from_state_to_block_inner = quote! {};
|
let mut from_state_to_block_inner = quote! {};
|
||||||
let mut division = 1usize;
|
let mut division = 1u32;
|
||||||
for i in (0..properties_with_name.len()).rev() {
|
for i in (0..properties_with_name.len()).rev() {
|
||||||
let PropertyWithNameAndDefault {
|
let PropertyWithNameAndDefault {
|
||||||
property_type: property_struct_name_ident,
|
property_type: property_struct_name_ident,
|
||||||
|
@ -475,11 +491,12 @@ pub fn make_block_states(input: TokenStream) -> TokenStream {
|
||||||
} = &properties_with_name[i];
|
} = &properties_with_name[i];
|
||||||
|
|
||||||
let property_variants = &block_properties_vec[i];
|
let property_variants = &block_properties_vec[i];
|
||||||
let property_variants_count = property_variants.len();
|
let property_variants_count = property_variants.len() as u32;
|
||||||
let conversion_code = {
|
let conversion_code = {
|
||||||
if &property_struct_name_ident.to_string() == "bool" {
|
if &property_struct_name_ident.to_string() == "bool" {
|
||||||
assert_eq!(property_variants_count, 2);
|
assert_eq!(property_variants_count, 2);
|
||||||
quote! {(b / #division) % #property_variants_count != 0}
|
// this is not a mistake, it starts with true for some reason
|
||||||
|
quote! {(b / #division) % #property_variants_count == 0}
|
||||||
} else {
|
} else {
|
||||||
quote! {#property_struct_name_ident::from((b / #division) % #property_variants_count)}
|
quote! {#property_struct_name_ident::from((b / #division) % #property_variants_count)}
|
||||||
}
|
}
|
||||||
|
@ -500,6 +517,12 @@ pub fn make_block_states(input: TokenStream) -> TokenStream {
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
from_registry_block_to_block_match.extend(quote! {
|
||||||
|
azalea_registry::Block::#block_name_pascal_case => Box::new(#block_struct_name::default()),
|
||||||
|
});
|
||||||
|
from_registry_block_to_blockstate_match.extend(quote! {
|
||||||
|
azalea_registry::Block::#block_name_pascal_case => BlockState { id: #default_state_id },
|
||||||
|
});
|
||||||
|
|
||||||
let mut block_default_fields = quote! {};
|
let mut block_default_fields = quote! {};
|
||||||
for PropertyWithNameAndDefault {
|
for PropertyWithNameAndDefault {
|
||||||
|
@ -515,10 +538,10 @@ pub fn make_block_states(input: TokenStream) -> TokenStream {
|
||||||
let block_id = block.name.to_string();
|
let block_id = block.name.to_string();
|
||||||
|
|
||||||
let from_block_to_state_match = if block.properties_and_defaults.is_empty() {
|
let from_block_to_state_match = if block.properties_and_defaults.is_empty() {
|
||||||
quote! { BlockState::#block_name_pascal_case }
|
quote! { BlockState { id: #first_state_id } }
|
||||||
} else {
|
} else {
|
||||||
quote! {
|
quote! {
|
||||||
match b {
|
match self {
|
||||||
#from_block_to_state_match_inner
|
#from_block_to_state_match_inner
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -537,11 +560,14 @@ pub fn make_block_states(input: TokenStream) -> TokenStream {
|
||||||
fn id(&self) -> &'static str {
|
fn id(&self) -> &'static str {
|
||||||
#block_id
|
#block_id
|
||||||
}
|
}
|
||||||
|
fn as_blockstate(&self) -> BlockState {
|
||||||
|
#from_block_to_state_match
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<#block_struct_name> for BlockState {
|
impl From<#block_struct_name> for BlockState {
|
||||||
fn from(b: #block_struct_name) -> Self {
|
fn from(b: #block_struct_name) -> Self {
|
||||||
#from_block_to_state_match
|
b.as_blockstate()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -557,18 +583,24 @@ pub fn make_block_states(input: TokenStream) -> TokenStream {
|
||||||
block_structs.extend(block_struct);
|
block_structs.extend(block_struct);
|
||||||
}
|
}
|
||||||
|
|
||||||
let last_state_id = (state_id - 1) as u32;
|
let last_state_id = state_id - 1;
|
||||||
let mut generated = quote! {
|
let mut generated = quote! {
|
||||||
#property_enums
|
#property_enums
|
||||||
|
|
||||||
#[repr(u32)]
|
/// A representation of a state a block can be in. (for example, a stone
|
||||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
/// block only has one state but each possible stair rotation is a
|
||||||
pub enum BlockState {
|
/// different state).
|
||||||
#block_state_enum_variants
|
#[derive(Copy, Clone, PartialEq, Eq, Default)]
|
||||||
|
pub struct BlockState {
|
||||||
|
/// The protocol ID for the block state. IDs may change every
|
||||||
|
/// version, so you shouldn't hard-code them or store them in databases.
|
||||||
|
pub id: u32
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BlockState {
|
impl BlockState {
|
||||||
/// Returns the highest possible state
|
pub const AIR: BlockState = BlockState { id: 0 };
|
||||||
|
|
||||||
|
/// Returns the highest possible state ID.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn max_state() -> u32 {
|
pub fn max_state() -> u32 {
|
||||||
#last_state_id
|
#last_state_id
|
||||||
|
@ -577,8 +609,7 @@ pub fn make_block_states(input: TokenStream) -> TokenStream {
|
||||||
|
|
||||||
impl std::fmt::Debug for BlockState {
|
impl std::fmt::Debug for BlockState {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
// having a big match statement here would take up 700kb
|
write!(f, "BlockState(id: {}, {:?})", self.id, Box::<dyn Block>::from(*self))
|
||||||
f.write_str("BlockState")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -587,14 +618,30 @@ pub fn make_block_states(input: TokenStream) -> TokenStream {
|
||||||
#block_structs
|
#block_structs
|
||||||
|
|
||||||
impl From<BlockState> for Box<dyn Block> {
|
impl From<BlockState> for Box<dyn Block> {
|
||||||
fn from(b: BlockState) -> Self {
|
fn from(block_state: BlockState) -> Self {
|
||||||
let b = b as usize;
|
let b = block_state.id;
|
||||||
match b {
|
match b {
|
||||||
#from_state_to_block_match
|
#from_state_to_block_match
|
||||||
_ => panic!("Invalid block state: {}", b),
|
_ => panic!("Invalid block state: {}", b),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl From<azalea_registry::Block> for Box<dyn Block> {
|
||||||
|
fn from(block: azalea_registry::Block) -> Self {
|
||||||
|
match block {
|
||||||
|
#from_registry_block_to_block_match
|
||||||
|
_ => unreachable!("There should always be a block struct for every azalea_registry::Block variant")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl From<azalea_registry::Block> for BlockState {
|
||||||
|
fn from(block: azalea_registry::Block) -> Self {
|
||||||
|
match block {
|
||||||
|
#from_registry_block_to_blockstate_match
|
||||||
|
_ => unreachable!("There should always be a block state for every azalea_registry::Block variant")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
generated.into()
|
generated.into()
|
||||||
|
|
|
@ -1,9 +1,18 @@
|
||||||
|
use std::any::Any;
|
||||||
|
|
||||||
use crate::BlockBehavior;
|
use crate::BlockBehavior;
|
||||||
use azalea_block_macros::make_block_states;
|
use azalea_block_macros::make_block_states;
|
||||||
|
use std::fmt::Debug;
|
||||||
|
|
||||||
pub trait Block {
|
pub trait Block: Debug + Any {
|
||||||
fn behavior(&self) -> BlockBehavior;
|
fn behavior(&self) -> BlockBehavior;
|
||||||
fn id(&self) -> &'static str;
|
fn id(&self) -> &'static str;
|
||||||
|
fn as_blockstate(&self) -> BlockState;
|
||||||
|
}
|
||||||
|
impl dyn Block {
|
||||||
|
pub fn downcast_ref<T: Block>(&self) -> Option<&T> {
|
||||||
|
(self as &dyn Any).downcast_ref::<T>()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
make_block_states! {
|
make_block_states! {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#![doc = include_str!("../README.md")]
|
#![doc = include_str!("../README.md")]
|
||||||
|
#![feature(trait_upcasting)]
|
||||||
|
|
||||||
mod behavior;
|
mod behavior;
|
||||||
mod blocks;
|
mod blocks;
|
||||||
|
@ -6,10 +7,7 @@ mod blocks;
|
||||||
use azalea_buf::{BufReadError, McBufReadable, McBufVarReadable, McBufVarWritable, McBufWritable};
|
use azalea_buf::{BufReadError, McBufReadable, McBufVarReadable, McBufVarWritable, McBufWritable};
|
||||||
pub use behavior::BlockBehavior;
|
pub use behavior::BlockBehavior;
|
||||||
pub use blocks::*;
|
pub use blocks::*;
|
||||||
use std::{
|
use std::io::{Cursor, Write};
|
||||||
io::{Cursor, Write},
|
|
||||||
mem,
|
|
||||||
};
|
|
||||||
|
|
||||||
impl BlockState {
|
impl BlockState {
|
||||||
/// Transmutes a u32 to a block state.
|
/// Transmutes a u32 to a block state.
|
||||||
|
@ -17,8 +15,8 @@ impl BlockState {
|
||||||
/// # Safety
|
/// # Safety
|
||||||
/// The `state_id` should be a valid block state.
|
/// The `state_id` should be a valid block state.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn from_u32_unsafe(state_id: u32) -> Self {
|
pub unsafe fn from_u32_unchecked(state_id: u32) -> Self {
|
||||||
mem::transmute::<u32, BlockState>(state_id)
|
BlockState { id: state_id }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -33,7 +31,7 @@ impl TryFrom<u32> for BlockState {
|
||||||
/// Safely converts a state id to a block state.
|
/// Safely converts a state id to a block state.
|
||||||
fn try_from(state_id: u32) -> Result<Self, Self::Error> {
|
fn try_from(state_id: u32) -> Result<Self, Self::Error> {
|
||||||
if Self::is_valid_state(state_id) {
|
if Self::is_valid_state(state_id) {
|
||||||
Ok(unsafe { Self::from_u32_unsafe(state_id) })
|
Ok(unsafe { Self::from_u32_unchecked(state_id) })
|
||||||
} else {
|
} else {
|
||||||
Err(())
|
Err(())
|
||||||
}
|
}
|
||||||
|
@ -50,7 +48,7 @@ impl McBufReadable for BlockState {
|
||||||
}
|
}
|
||||||
impl McBufWritable for BlockState {
|
impl McBufWritable for BlockState {
|
||||||
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||||
u32::var_write_into(&(*self as u32), buf)
|
u32::var_write_into(&self.id, buf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,7 +58,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_from_u32() {
|
fn test_from_u32() {
|
||||||
assert_eq!(BlockState::try_from(0).unwrap(), BlockState::Air);
|
assert_eq!(BlockState::try_from(0).unwrap(), BlockState::AIR);
|
||||||
|
|
||||||
assert!(BlockState::try_from(BlockState::max_state()).is_ok());
|
assert!(BlockState::try_from(BlockState::max_state()).is_ok());
|
||||||
assert!(BlockState::try_from(BlockState::max_state() + 1).is_err());
|
assert!(BlockState::try_from(BlockState::max_state() + 1).is_err());
|
||||||
|
@ -68,10 +66,34 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_from_blockstate() {
|
fn test_from_blockstate() {
|
||||||
let block: Box<dyn Block> = Box::<dyn Block>::from(BlockState::Air);
|
let block: Box<dyn Block> = Box::<dyn Block>::from(BlockState::AIR);
|
||||||
assert_eq!(block.id(), "air");
|
assert_eq!(block.id(), "air");
|
||||||
|
|
||||||
let block: Box<dyn Block> = Box::<dyn Block>::from(BlockState::FloweringAzalea);
|
let block: Box<dyn Block> =
|
||||||
|
Box::<dyn Block>::from(BlockState::from(azalea_registry::Block::FloweringAzalea));
|
||||||
assert_eq!(block.id(), "flowering_azalea");
|
assert_eq!(block.id(), "flowering_azalea");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_debug_blockstate() {
|
||||||
|
let formatted = format!(
|
||||||
|
"{:?}",
|
||||||
|
BlockState::from(azalea_registry::Block::FloweringAzalea)
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
formatted.ends_with(", FloweringAzaleaBlock)"),
|
||||||
|
"{}",
|
||||||
|
formatted
|
||||||
|
);
|
||||||
|
|
||||||
|
let formatted = format!(
|
||||||
|
"{:?}",
|
||||||
|
BlockState::from(azalea_registry::Block::BigDripleafStem)
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
formatted.ends_with(", BigDripleafStemBlock { facing: North, waterlogged: false })"),
|
||||||
|
"{}",
|
||||||
|
formatted
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
6
azalea-brigadier/Cargo.toml
Executable file → Normal file
6
azalea-brigadier/Cargo.toml
Executable file → Normal file
|
@ -4,13 +4,13 @@ edition = "2021"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
name = "azalea-brigadier"
|
name = "azalea-brigadier"
|
||||||
repository = "https://github.com/mat-1/azalea/tree/main/azalea-brigadier"
|
repository = "https://github.com/mat-1/azalea/tree/main/azalea-brigadier"
|
||||||
version = "0.5.0"
|
version = "0.6.0"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
azalea-buf = {path = "../azalea-buf", version = "^0.5.0", optional = true}
|
azalea-buf = {path = "../azalea-buf", version = "^0.6.0", optional = true}
|
||||||
azalea-chat = {path = "../azalea-chat", version = "^0.5.0", optional = true}
|
azalea-chat = {path = "../azalea-chat", version = "^0.6.0", optional = true}
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
azalea-buf = ["dep:azalea-buf", "dep:azalea-chat"]
|
azalea-buf = ["dep:azalea-buf", "dep:azalea-chat"]
|
||||||
|
|
|
@ -4,12 +4,12 @@ edition = "2021"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
name = "azalea-buf"
|
name = "azalea-buf"
|
||||||
repository = "https://github.com/mat-1/azalea/tree/main/azalea-buf"
|
repository = "https://github.com/mat-1/azalea/tree/main/azalea-buf"
|
||||||
version = "0.5.0"
|
version = "0.6.0"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
azalea-buf-macros = {path = "./azalea-buf-macros", version = "^0.5.0" }
|
azalea-buf-macros = {path = "./azalea-buf-macros", version = "^0.6.0" }
|
||||||
byteorder = "^1.4.3"
|
byteorder = "^1.4.3"
|
||||||
log = "0.4.17"
|
log = "0.4.17"
|
||||||
serde_json = {version = "^1.0", optional = true}
|
serde_json = {version = "^1.0", optional = true}
|
||||||
|
|
2
azalea-buf/azalea-buf-macros/Cargo.toml
Executable file → Normal file
2
azalea-buf/azalea-buf-macros/Cargo.toml
Executable file → Normal file
|
@ -4,7 +4,7 @@ edition = "2021"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
name = "azalea-buf-macros"
|
name = "azalea-buf-macros"
|
||||||
repository = "https://github.com/mat-1/azalea/tree/main/azalea-buf"
|
repository = "https://github.com/mat-1/azalea/tree/main/azalea-buf"
|
||||||
version = "0.5.0"
|
version = "0.6.0"
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
proc-macro = true
|
proc-macro = true
|
||||||
|
|
6
azalea-chat/Cargo.toml
Executable file → Normal file
6
azalea-chat/Cargo.toml
Executable file → Normal file
|
@ -4,7 +4,7 @@ edition = "2021"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
name = "azalea-chat"
|
name = "azalea-chat"
|
||||||
repository = "https://github.com/mat-1/azalea/tree/main/azalea-chat"
|
repository = "https://github.com/mat-1/azalea/tree/main/azalea-chat"
|
||||||
version = "0.5.0"
|
version = "0.6.0"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
@ -14,8 +14,8 @@ default = ["azalea-buf"]
|
||||||
[dependencies]
|
[dependencies]
|
||||||
azalea-buf = { path = "../azalea-buf", features = [
|
azalea-buf = { path = "../azalea-buf", features = [
|
||||||
"serde_json",
|
"serde_json",
|
||||||
], version = "^0.5.0", optional = true }
|
], version = "^0.6.0", optional = true }
|
||||||
azalea-language = { path = "../azalea-language", version = "^0.5.0" }
|
azalea-language = { path = "../azalea-language", version = "^0.6.0" }
|
||||||
log = "0.4.17"
|
log = "0.4.17"
|
||||||
once_cell = "1.16.0"
|
once_cell = "1.16.0"
|
||||||
serde = { version = "^1.0.148", features = ["derive"] }
|
serde = { version = "^1.0.148", features = ["derive"] }
|
||||||
|
|
|
@ -4,38 +4,37 @@ edition = "2021"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
name = "azalea-client"
|
name = "azalea-client"
|
||||||
repository = "https://github.com/mat-1/azalea/tree/main/azalea-client"
|
repository = "https://github.com/mat-1/azalea/tree/main/azalea-client"
|
||||||
version = "0.5.0"
|
version = "0.6.0"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.59"
|
anyhow = "1.0.59"
|
||||||
async-trait = "0.1.58"
|
async-trait = "0.1.58"
|
||||||
azalea-auth = {path = "../azalea-auth", version = "0.5.0"}
|
azalea-auth = { path = "../azalea-auth", version = "0.6.0" }
|
||||||
azalea-block = {path = "../azalea-block", version = "0.5.0"}
|
azalea-block = { path = "../azalea-block", version = "0.6.0" }
|
||||||
azalea-chat = {path = "../azalea-chat", version = "0.5.0"}
|
azalea-chat = { path = "../azalea-chat", version = "0.6.0" }
|
||||||
azalea-core = {path = "../azalea-core", version = "0.5.0"}
|
azalea-core = { path = "../azalea-core", version = "0.6.0" }
|
||||||
azalea-crypto = {path = "../azalea-crypto", version = "0.5.0"}
|
azalea-crypto = { path = "../azalea-crypto", version = "0.6.0" }
|
||||||
azalea-ecs = {path = "../azalea-ecs", version = "0.5.0"}
|
azalea-ecs = { path = "../azalea-ecs", version = "0.6.0" }
|
||||||
azalea-inventory = {path = "../azalea-inventory", version = "0.1.0"}
|
azalea-physics = { path = "../azalea-physics", version = "0.6.0" }
|
||||||
azalea-physics = {path = "../azalea-physics", version = "0.5.0"}
|
azalea-protocol = { path = "../azalea-protocol", version = "0.6.0" }
|
||||||
azalea-protocol = {path = "../azalea-protocol", version = "0.5.0"}
|
azalea-registry = { path = "../azalea-registry", version = "0.6.0" }
|
||||||
azalea-registry = {path = "../azalea-registry", version = "0.5.0"}
|
azalea-world = { path = "../azalea-world", version = "0.6.0" }
|
||||||
azalea-world = {path = "../azalea-world", version = "0.5.0"}
|
azalea-inventory = { path = "../azalea-inventory", version = "0.1.0" }
|
||||||
bevy_tasks = "0.9.1"
|
|
||||||
bevy_time = "0.9.1"
|
bevy_time = "0.9.1"
|
||||||
derive_more = {version = "0.99.17", features = ["deref", "deref_mut"]}
|
derive_more = { version = "0.99.17", features = ["deref", "deref_mut"] }
|
||||||
futures = "0.3.25"
|
futures = "0.3.25"
|
||||||
iyes_loopless = "0.9.1"
|
|
||||||
log = "0.4.17"
|
log = "0.4.17"
|
||||||
nohash-hasher = "0.2.0"
|
nohash-hasher = "0.2.0"
|
||||||
once_cell = "1.16.0"
|
once_cell = "1.16.0"
|
||||||
parking_lot = {version = "^0.12.1", features = ["deadlock_detection"]}
|
parking_lot = { version = "^0.12.1", features = ["deadlock_detection"] }
|
||||||
regex = "1.7.0"
|
regex = "1.7.0"
|
||||||
thiserror = "^1.0.34"
|
thiserror = "^1.0.34"
|
||||||
tokio = {version = "^1.24.2", features = ["sync"]}
|
tokio = { version = "^1.24.2", features = ["sync"] }
|
||||||
typemap_rev = "0.3.0"
|
typemap_rev = "0.3.0"
|
||||||
uuid = "^1.1.2"
|
uuid = "^1.1.2"
|
||||||
|
bevy_tasks = "0.9.1"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
env_logger = "0.9.1"
|
env_logger = "0.9.1"
|
||||||
|
|
|
@ -43,7 +43,10 @@ use azalea_protocol::{
|
||||||
},
|
},
|
||||||
resolver, ServerAddress,
|
resolver, ServerAddress,
|
||||||
};
|
};
|
||||||
use azalea_world::{entity::WorldName, EntityPlugin, Local, PartialWorld, World, WorldContainer};
|
use azalea_world::{
|
||||||
|
entity::{EntityPlugin, Local, WorldName},
|
||||||
|
PartialWorld, World, WorldContainer,
|
||||||
|
};
|
||||||
use log::{debug, error};
|
use log::{debug, error};
|
||||||
use parking_lot::{Mutex, RwLock};
|
use parking_lot::{Mutex, RwLock};
|
||||||
use std::{collections::HashMap, fmt::Debug, io, net::SocketAddr, sync::Arc};
|
use std::{collections::HashMap, fmt::Debug, io, net::SocketAddr, sync::Arc};
|
||||||
|
@ -377,7 +380,8 @@ impl Client {
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # fn example(client: &azalea::Client) {
|
/// # use azalea_world::entity::WorldName;
|
||||||
|
/// # fn example(client: &azalea_client::Client) {
|
||||||
/// let world_name = client.component::<WorldName>();
|
/// let world_name = client.component::<WorldName>();
|
||||||
/// # }
|
/// # }
|
||||||
pub fn component<T: Component + Clone>(&self) -> T {
|
pub fn component<T: Component + Clone>(&self) -> T {
|
||||||
|
|
|
@ -15,6 +15,7 @@ impl Client {
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
/// ```
|
/// ```
|
||||||
|
/// # use azalea_world::entity::WorldName;
|
||||||
/// # fn example(mut client: azalea_client::Client) {
|
/// # fn example(mut client: azalea_client::Client) {
|
||||||
/// let is_logged_in = client
|
/// let is_logged_in = client
|
||||||
/// .query::<Option<&WorldName>>(&mut client.ecs.lock())
|
/// .query::<Option<&WorldName>>(&mut client.ecs.lock())
|
||||||
|
|
|
@ -20,8 +20,8 @@ use tokio::sync::mpsc;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
packet_handling::{
|
packet_handling::{
|
||||||
AddPlayerEvent, ChatReceivedEvent, DeathEvent, PacketReceiver, RemovePlayerEvent,
|
AddPlayerEvent, ChatReceivedEvent, DeathEvent, KeepAliveEvent, PacketReceiver,
|
||||||
UpdatePlayerEvent,
|
RemovePlayerEvent, UpdatePlayerEvent,
|
||||||
},
|
},
|
||||||
ChatPacket, PlayerInfo,
|
ChatPacket, PlayerInfo,
|
||||||
};
|
};
|
||||||
|
@ -73,6 +73,8 @@ pub enum Event {
|
||||||
UpdatePlayer(PlayerInfo),
|
UpdatePlayer(PlayerInfo),
|
||||||
/// The client player died in-game.
|
/// The client player died in-game.
|
||||||
Death(Option<Arc<ClientboundPlayerCombatKillPacket>>),
|
Death(Option<Arc<ClientboundPlayerCombatKillPacket>>),
|
||||||
|
/// A `KeepAlive` packet was sent by the server.
|
||||||
|
KeepAlive(u64),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A component that contains an event sender for events that are only
|
/// A component that contains an event sender for events that are only
|
||||||
|
@ -94,6 +96,7 @@ impl Plugin for EventPlugin {
|
||||||
.add_system(update_player_listener)
|
.add_system(update_player_listener)
|
||||||
.add_system(remove_player_listener)
|
.add_system(remove_player_listener)
|
||||||
.add_system(death_listener)
|
.add_system(death_listener)
|
||||||
|
.add_system(keepalive_listener)
|
||||||
.add_tick_system(tick_listener);
|
.add_tick_system(tick_listener);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -157,7 +160,7 @@ fn update_player_listener(
|
||||||
for event in events.iter() {
|
for event in events.iter() {
|
||||||
let local_player_events = query
|
let local_player_events = query
|
||||||
.get(event.entity)
|
.get(event.entity)
|
||||||
.expect("Non-localplayer entities shouldn't be able to receive add player events");
|
.expect("Non-localplayer entities shouldn't be able to receive update player events");
|
||||||
local_player_events
|
local_player_events
|
||||||
.send(Event::UpdatePlayer(event.info.clone()))
|
.send(Event::UpdatePlayer(event.info.clone()))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
@ -171,7 +174,7 @@ fn remove_player_listener(
|
||||||
for event in events.iter() {
|
for event in events.iter() {
|
||||||
let local_player_events = query
|
let local_player_events = query
|
||||||
.get(event.entity)
|
.get(event.entity)
|
||||||
.expect("Non-localplayer entities shouldn't be able to receive add player events");
|
.expect("Non-localplayer entities shouldn't be able to receive remove player events");
|
||||||
local_player_events
|
local_player_events
|
||||||
.send(Event::RemovePlayer(event.info.clone()))
|
.send(Event::RemovePlayer(event.info.clone()))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
@ -187,3 +190,14 @@ fn death_listener(query: Query<&LocalPlayerEvents>, mut events: EventReader<Deat
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn keepalive_listener(query: Query<&LocalPlayerEvents>, mut events: EventReader<KeepAliveEvent>) {
|
||||||
|
for event in events.iter() {
|
||||||
|
let local_player_events = query
|
||||||
|
.get(event.entity)
|
||||||
|
.expect("Non-localplayer entities shouldn't be able to receive keepalive events");
|
||||||
|
local_player_events
|
||||||
|
.send(Event::KeepAlive(event.id))
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ use crate::{
|
||||||
/// You can also use the [`Local`] marker component for queries if you're only
|
/// You can also use the [`Local`] marker component for queries if you're only
|
||||||
/// checking for a local player and don't need the contents of this component.
|
/// checking for a local player and don't need the contents of this component.
|
||||||
///
|
///
|
||||||
/// [`Local`]: azalea_world::Local
|
/// [`Local`]: azalea_world::entity::Local
|
||||||
/// [`Client`]: crate::Client
|
/// [`Client`]: crate::Client
|
||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
pub struct LocalPlayer {
|
pub struct LocalPlayer {
|
||||||
|
|
|
@ -21,6 +21,7 @@ use azalea_protocol::{
|
||||||
serverbound_move_player_pos_rot_packet::ServerboundMovePlayerPosRotPacket,
|
serverbound_move_player_pos_rot_packet::ServerboundMovePlayerPosRotPacket,
|
||||||
ClientboundGamePacket, ServerboundGamePacket,
|
ClientboundGamePacket, ServerboundGamePacket,
|
||||||
},
|
},
|
||||||
|
read::ReadPacketError,
|
||||||
};
|
};
|
||||||
use azalea_world::{
|
use azalea_world::{
|
||||||
entity::{
|
entity::{
|
||||||
|
@ -28,7 +29,8 @@ use azalea_world::{
|
||||||
set_rotation, Dead, EntityBundle, EntityKind, LastSentPosition, MinecraftEntityId, Physics,
|
set_rotation, Dead, EntityBundle, EntityKind, LastSentPosition, MinecraftEntityId, Physics,
|
||||||
PlayerBundle, Position, WorldName,
|
PlayerBundle, Position, WorldName,
|
||||||
},
|
},
|
||||||
LoadedBy, PartialWorld, RelativeEntityUpdate, WorldContainer,
|
entity::{LoadedBy, RelativeEntityUpdate},
|
||||||
|
PartialWorld, WorldContainer,
|
||||||
};
|
};
|
||||||
use log::{debug, error, trace, warn};
|
use log::{debug, error, trace, warn};
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
|
@ -51,13 +53,14 @@ impl Plugin for PacketHandlerPlugin {
|
||||||
.add_event::<RemovePlayerEvent>()
|
.add_event::<RemovePlayerEvent>()
|
||||||
.add_event::<UpdatePlayerEvent>()
|
.add_event::<UpdatePlayerEvent>()
|
||||||
.add_event::<ChatReceivedEvent>()
|
.add_event::<ChatReceivedEvent>()
|
||||||
.add_event::<DeathEvent>();
|
.add_event::<DeathEvent>()
|
||||||
|
.add_event::<KeepAliveEvent>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A player joined the game (or more specifically, was added to the tab
|
/// A player joined the game (or more specifically, was added to the tab
|
||||||
/// list of a local player).
|
/// list of a local player).
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct AddPlayerEvent {
|
pub struct AddPlayerEvent {
|
||||||
/// The local player entity that received this event.
|
/// The local player entity that received this event.
|
||||||
pub entity: Entity,
|
pub entity: Entity,
|
||||||
|
@ -65,7 +68,7 @@ pub struct AddPlayerEvent {
|
||||||
}
|
}
|
||||||
/// A player left the game (or maybe is still in the game and was just
|
/// A player left the game (or maybe is still in the game and was just
|
||||||
/// removed from the tab list of a local player).
|
/// removed from the tab list of a local player).
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct RemovePlayerEvent {
|
pub struct RemovePlayerEvent {
|
||||||
/// The local player entity that received this event.
|
/// The local player entity that received this event.
|
||||||
pub entity: Entity,
|
pub entity: Entity,
|
||||||
|
@ -73,7 +76,7 @@ pub struct RemovePlayerEvent {
|
||||||
}
|
}
|
||||||
/// A player was updated in the tab list of a local player (gamemode, display
|
/// A player was updated in the tab list of a local player (gamemode, display
|
||||||
/// name, or latency changed).
|
/// name, or latency changed).
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct UpdatePlayerEvent {
|
pub struct UpdatePlayerEvent {
|
||||||
/// The local player entity that received this event.
|
/// The local player entity that received this event.
|
||||||
pub entity: Entity,
|
pub entity: Entity,
|
||||||
|
@ -81,7 +84,7 @@ pub struct UpdatePlayerEvent {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A client received a chat message packet.
|
/// A client received a chat message packet.
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct ChatReceivedEvent {
|
pub struct ChatReceivedEvent {
|
||||||
pub entity: Entity,
|
pub entity: Entity,
|
||||||
pub packet: ChatPacket,
|
pub packet: ChatPacket,
|
||||||
|
@ -90,11 +93,22 @@ pub struct ChatReceivedEvent {
|
||||||
/// Event for when an entity dies. dies. If it's a local player and there's a
|
/// Event for when an entity dies. dies. If it's a local player and there's a
|
||||||
/// reason in the death screen, the [`ClientboundPlayerCombatKillPacket`] will
|
/// reason in the death screen, the [`ClientboundPlayerCombatKillPacket`] will
|
||||||
/// be included.
|
/// be included.
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
pub struct DeathEvent {
|
pub struct DeathEvent {
|
||||||
pub entity: Entity,
|
pub entity: Entity,
|
||||||
pub packet: Option<ClientboundPlayerCombatKillPacket>,
|
pub packet: Option<ClientboundPlayerCombatKillPacket>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A KeepAlive packet is sent from the server to verify that the client is
|
||||||
|
/// still connected.
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct KeepAliveEvent {
|
||||||
|
pub entity: Entity,
|
||||||
|
/// The ID of the keepalive. This is an arbitrary number, but vanilla
|
||||||
|
/// servers use the time to generate this.
|
||||||
|
pub id: u64,
|
||||||
|
}
|
||||||
|
|
||||||
/// Something that receives packets from the server.
|
/// Something that receives packets from the server.
|
||||||
#[derive(Component, Clone)]
|
#[derive(Component, Clone)]
|
||||||
pub struct PacketReceiver {
|
pub struct PacketReceiver {
|
||||||
|
@ -826,11 +840,18 @@ fn handle_packets(ecs: &mut Ecs) {
|
||||||
ClientboundGamePacket::KeepAlive(p) => {
|
ClientboundGamePacket::KeepAlive(p) => {
|
||||||
debug!("Got keep alive packet {p:?} for {player_entity:?}");
|
debug!("Got keep alive packet {p:?} for {player_entity:?}");
|
||||||
|
|
||||||
let mut system_state: SystemState<Query<&mut LocalPlayer>> =
|
let mut system_state: SystemState<(
|
||||||
SystemState::new(ecs);
|
Query<&mut LocalPlayer>,
|
||||||
let mut query = system_state.get_mut(ecs);
|
EventWriter<KeepAliveEvent>,
|
||||||
let mut local_player = query.get_mut(player_entity).unwrap();
|
)> = SystemState::new(ecs);
|
||||||
|
let (mut query, mut keepalive_events) = system_state.get_mut(ecs);
|
||||||
|
|
||||||
|
keepalive_events.send(KeepAliveEvent {
|
||||||
|
entity: player_entity,
|
||||||
|
id: p.id,
|
||||||
|
});
|
||||||
|
|
||||||
|
let mut local_player = query.get_mut(player_entity).unwrap();
|
||||||
local_player.write_packet(ServerboundKeepAlivePacket { id: p.id }.get());
|
local_player.write_packet(ServerboundKeepAlivePacket { id: p.id }.get());
|
||||||
debug!("Sent keep alive packet {p:?} for {player_entity:?}");
|
debug!("Sent keep alive packet {p:?} for {player_entity:?}");
|
||||||
}
|
}
|
||||||
|
@ -1005,10 +1026,20 @@ impl PacketReceiver {
|
||||||
/// Loop that reads from the connection and adds the packets to the queue +
|
/// Loop that reads from the connection and adds the packets to the queue +
|
||||||
/// runs the schedule.
|
/// runs the schedule.
|
||||||
pub async fn read_task(self, mut read_conn: ReadConnection<ClientboundGamePacket>) {
|
pub async fn read_task(self, mut read_conn: ReadConnection<ClientboundGamePacket>) {
|
||||||
while let Ok(packet) = read_conn.read().await {
|
loop {
|
||||||
self.packets.lock().push(packet);
|
match read_conn.read().await {
|
||||||
// tell the client to run all the systems
|
Ok(packet) => {
|
||||||
self.run_schedule_sender.send(()).await.unwrap();
|
self.packets.lock().push(packet);
|
||||||
|
// tell the client to run all the systems
|
||||||
|
self.run_schedule_sender.send(()).await.unwrap();
|
||||||
|
}
|
||||||
|
Err(error) => {
|
||||||
|
if !matches!(*error, ReadPacketError::ConnectionClosed) {
|
||||||
|
error!("Error reading packet from Client: {error:?}");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ use azalea_ecs::{
|
||||||
event::EventReader,
|
event::EventReader,
|
||||||
system::{Commands, Res},
|
system::{Commands, Res},
|
||||||
};
|
};
|
||||||
use azalea_world::EntityInfos;
|
use azalea_world::entity::EntityInfos;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use crate::{packet_handling::AddPlayerEvent, GameProfileComponent};
|
use crate::{packet_handling::AddPlayerEvent, GameProfileComponent};
|
||||||
|
|
|
@ -4,16 +4,16 @@ edition = "2021"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
name = "azalea-core"
|
name = "azalea-core"
|
||||||
repository = "https://github.com/mat-1/azalea/tree/main/azalea-core"
|
repository = "https://github.com/mat-1/azalea/tree/main/azalea-core"
|
||||||
version = "0.5.0"
|
version = "0.6.0"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
azalea-buf = {path = "../azalea-buf", version = "^0.5.0"}
|
azalea-buf = { path = "../azalea-buf", version = "^0.6.0" }
|
||||||
azalea-chat = {path = "../azalea-chat", version = "^0.5.0"}
|
azalea-chat = { path = "../azalea-chat", version = "^0.6.0" }
|
||||||
azalea-nbt = {path = "../azalea-nbt", version = "^0.5.0"}
|
azalea-nbt = { path = "../azalea-nbt", version = "^0.6.0" }
|
||||||
azalea-registry = {path = "../azalea-registry", version = "^0.5.0"}
|
azalea-registry = { path = "../azalea-registry", version = "^0.6.0" }
|
||||||
bevy_ecs = {version = "0.9.1", default-features = false, optional = true}
|
bevy_ecs = { version = "0.9.1", default-features = false, optional = true }
|
||||||
uuid = "^1.1.2"
|
uuid = "^1.1.2"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
|
|
4
azalea-crypto/Cargo.toml
Executable file → Normal file
4
azalea-crypto/Cargo.toml
Executable file → Normal file
|
@ -3,14 +3,14 @@ description = "Cryptography features used in Minecraft."
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
name = "azalea-crypto"
|
name = "azalea-crypto"
|
||||||
version = "0.5.0"
|
version = "0.6.0"
|
||||||
repository = "https://github.com/mat-1/azalea/tree/main/azalea-crypto"
|
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
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
aes = "0.8.1"
|
aes = "0.8.1"
|
||||||
azalea-buf = {path = "../azalea-buf", version = "^0.5.0" }
|
azalea-buf = {path = "../azalea-buf", version = "^0.6.0" }
|
||||||
cfb8 = "0.8.1"
|
cfb8 = "0.8.1"
|
||||||
num-bigint = "^0.4.3"
|
num-bigint = "^0.4.3"
|
||||||
rand = {version = "^0.8.4", features = ["getrandom"]}
|
rand = {version = "^0.8.4", features = ["getrandom"]}
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
[package]
|
[package]
|
||||||
|
description = "ECS stuff used in Azalea"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
license = "MIT"
|
||||||
name = "azalea-ecs"
|
name = "azalea-ecs"
|
||||||
version = "0.5.0"
|
version = "0.6.0"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
azalea-ecs-macros = {path = "./azalea-ecs-macros", version = "^0.5.0"}
|
azalea-ecs-macros = {path = "./azalea-ecs-macros", version = "^0.6.0"}
|
||||||
bevy_app = "0.9.1"
|
bevy_app = "0.9.1"
|
||||||
bevy_ecs = {version = "0.9.1", default-features = false}
|
bevy_ecs = {version = "0.9.1", default-features = false}
|
||||||
iyes_loopless = "0.9.1"
|
|
||||||
tokio = {version = "1.25.0", features = ["time"]}
|
tokio = {version = "1.25.0", features = ["time"]}
|
||||||
|
|
|
@ -3,7 +3,7 @@ description = "Azalea ECS Macros"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
name = "azalea-ecs-macros"
|
name = "azalea-ecs-macros"
|
||||||
version = "0.5.0"
|
version = "0.6.0"
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
proc-macro = true
|
proc-macro = true
|
||||||
|
|
|
@ -6,5 +6,5 @@ version = "0.1.0"
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
azalea-core = { version = "0.5.0", path = "../azalea-core" }
|
azalea-core = { version = "0.6.0", path = "../azalea-core" }
|
||||||
azalea-inventory-macros = { version = "0.1.0", path = "./azalea-inventory-macros" }
|
azalea-inventory-macros = { version = "0.1.0", path = "./azalea-inventory-macros" }
|
||||||
|
|
2
azalea-language/Cargo.toml
Executable file → Normal file
2
azalea-language/Cargo.toml
Executable file → Normal file
|
@ -4,7 +4,7 @@ edition = "2021"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
name = "azalea-language"
|
name = "azalea-language"
|
||||||
repository = "https://github.com/mat-1/azalea/tree/main/azalea-language"
|
repository = "https://github.com/mat-1/azalea/tree/main/azalea-language"
|
||||||
version = "0.5.0"
|
version = "0.6.0"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
|
4
azalea-nbt/Cargo.toml
Executable file → Normal file
4
azalea-nbt/Cargo.toml
Executable file → Normal file
|
@ -3,14 +3,14 @@ description = "A fast NBT serializer and deserializer."
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
name = "azalea-nbt"
|
name = "azalea-nbt"
|
||||||
version = "0.5.0"
|
version = "0.6.0"
|
||||||
repository = "https://github.com/mat-1/azalea/tree/main/azalea-nbt"
|
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
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
ahash = { version = "^0.8.0", features = ["serde"]}
|
ahash = { version = "^0.8.0", features = ["serde"]}
|
||||||
azalea-buf = {path = "../azalea-buf", version = "^0.5.0" }
|
azalea-buf = {path = "../azalea-buf", version = "^0.6.0" }
|
||||||
byteorder = "^1.4.3"
|
byteorder = "^1.4.3"
|
||||||
flate2 = "^1.0.23"
|
flate2 = "^1.0.23"
|
||||||
log = "0.4.17"
|
log = "0.4.17"
|
||||||
|
|
|
@ -4,19 +4,18 @@ edition = "2021"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
name = "azalea-physics"
|
name = "azalea-physics"
|
||||||
repository = "https://github.com/mat-1/azalea/tree/main/azalea-physics"
|
repository = "https://github.com/mat-1/azalea/tree/main/azalea-physics"
|
||||||
version = "0.5.0"
|
version = "0.6.0"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
azalea-block = { path = "../azalea-block", version = "^0.5.0" }
|
azalea-block = {path = "../azalea-block", version = "^0.6.0"}
|
||||||
azalea-core = { path = "../azalea-core", version = "^0.5.0" }
|
azalea-core = {path = "../azalea-core", version = "^0.6.0"}
|
||||||
azalea-world = { path = "../azalea-world", version = "^0.5.0" }
|
azalea-ecs = {version = "0.6.0", path = "../azalea-ecs"}
|
||||||
azalea-registry = { path = "../azalea-registry", version = "^0.5.0" }
|
azalea-registry = {path = "../azalea-registry", version = "^0.6.0"}
|
||||||
iyes_loopless = "0.9.1"
|
azalea-world = {path = "../azalea-world", version = "^0.6.0"}
|
||||||
once_cell = "1.16.0"
|
once_cell = "1.16.0"
|
||||||
parking_lot = "^0.12.1"
|
parking_lot = "^0.12.1"
|
||||||
azalea-ecs = { version = "0.5.0", path = "../azalea-ecs" }
|
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
uuid = "^1.1.2"
|
uuid = "^1.1.2"
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -79,7 +79,7 @@ impl<'a> Iterator for BlockCollisions<'a> {
|
||||||
let block_state: BlockState = chunk
|
let block_state: BlockState = chunk
|
||||||
.read()
|
.read()
|
||||||
.get(&(&pos).into(), self.world.chunks.min_y)
|
.get(&(&pos).into(), self.world.chunks.min_y)
|
||||||
.unwrap_or(BlockState::Air);
|
.unwrap_or(BlockState::AIR);
|
||||||
|
|
||||||
// TODO: continue if self.only_suffocating_blocks and the block is not
|
// TODO: continue if self.only_suffocating_blocks and the block is not
|
||||||
// suffocating
|
// suffocating
|
||||||
|
|
|
@ -16,9 +16,10 @@ use azalea_ecs::{
|
||||||
};
|
};
|
||||||
use azalea_world::{
|
use azalea_world::{
|
||||||
entity::{
|
entity::{
|
||||||
metadata::Sprinting, move_relative, Attributes, Jumping, Physics, Position, WorldName,
|
metadata::Sprinting, move_relative, Attributes, Jumping, Local, Physics, Position,
|
||||||
|
WorldName,
|
||||||
},
|
},
|
||||||
Local, World, WorldContainer,
|
World, WorldContainer,
|
||||||
};
|
};
|
||||||
use collision::{move_colliding, MoverType};
|
use collision::{move_colliding, MoverType};
|
||||||
|
|
||||||
|
@ -74,7 +75,7 @@ fn travel(
|
||||||
let block_state_below = world
|
let block_state_below = world
|
||||||
.chunks
|
.chunks
|
||||||
.get_block_state(&block_pos_below)
|
.get_block_state(&block_pos_below)
|
||||||
.unwrap_or(BlockState::Air);
|
.unwrap_or(BlockState::AIR);
|
||||||
let block_below: Box<dyn Block> = block_state_below.into();
|
let block_below: Box<dyn Block> = block_state_below.into();
|
||||||
let block_friction = block_below.behavior().friction;
|
let block_friction = block_below.behavior().friction;
|
||||||
|
|
||||||
|
@ -310,8 +311,8 @@ mod tests {
|
||||||
use azalea_core::{ChunkPos, ResourceLocation};
|
use azalea_core::{ChunkPos, ResourceLocation};
|
||||||
use azalea_ecs::{app::App, TickPlugin};
|
use azalea_ecs::{app::App, TickPlugin};
|
||||||
use azalea_world::{
|
use azalea_world::{
|
||||||
entity::{EntityBundle, MinecraftEntityId},
|
entity::{EntityBundle, EntityPlugin, MinecraftEntityId},
|
||||||
Chunk, EntityPlugin, PartialWorld,
|
Chunk, PartialWorld,
|
||||||
};
|
};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
@ -411,7 +412,7 @@ mod tests {
|
||||||
.id();
|
.id();
|
||||||
let block_state = partial_world.chunks.set_block_state(
|
let block_state = partial_world.chunks.set_block_state(
|
||||||
&BlockPos { x: 0, y: 69, z: 0 },
|
&BlockPos { x: 0, y: 69, z: 0 },
|
||||||
BlockState::Stone,
|
azalea_registry::Block::Stone.into(),
|
||||||
&mut world_lock.write().chunks,
|
&mut world_lock.write().chunks,
|
||||||
);
|
);
|
||||||
assert!(
|
assert!(
|
||||||
|
@ -468,7 +469,11 @@ mod tests {
|
||||||
.id();
|
.id();
|
||||||
let block_state = partial_world.chunks.set_block_state(
|
let block_state = partial_world.chunks.set_block_state(
|
||||||
&BlockPos { x: 0, y: 69, z: 0 },
|
&BlockPos { x: 0, y: 69, z: 0 },
|
||||||
BlockState::StoneSlab_BottomFalse,
|
azalea_block::StoneSlabBlock {
|
||||||
|
kind: azalea_block::Type::Bottom,
|
||||||
|
waterlogged: false,
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
&mut world_lock.write().chunks,
|
&mut world_lock.write().chunks,
|
||||||
);
|
);
|
||||||
assert!(
|
assert!(
|
||||||
|
@ -517,7 +522,11 @@ mod tests {
|
||||||
.id();
|
.id();
|
||||||
let block_state = world_lock.write().chunks.set_block_state(
|
let block_state = world_lock.write().chunks.set_block_state(
|
||||||
&BlockPos { x: 0, y: 69, z: 0 },
|
&BlockPos { x: 0, y: 69, z: 0 },
|
||||||
BlockState::StoneSlab_TopFalse,
|
azalea_block::StoneSlabBlock {
|
||||||
|
kind: azalea_block::Type::Top,
|
||||||
|
waterlogged: false,
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
);
|
);
|
||||||
assert!(
|
assert!(
|
||||||
block_state.is_some(),
|
block_state.is_some(),
|
||||||
|
@ -565,7 +574,15 @@ mod tests {
|
||||||
.id();
|
.id();
|
||||||
let block_state = world_lock.write().chunks.set_block_state(
|
let block_state = world_lock.write().chunks.set_block_state(
|
||||||
&BlockPos { x: 0, y: 69, z: 0 },
|
&BlockPos { x: 0, y: 69, z: 0 },
|
||||||
BlockState::CobblestoneWall_LowLowLowFalseFalseLow,
|
azalea_block::CobblestoneWallBlock {
|
||||||
|
east: azalea_block::EastWall::Low,
|
||||||
|
north: azalea_block::NorthWall::Low,
|
||||||
|
south: azalea_block::SouthWall::Low,
|
||||||
|
west: azalea_block::WestWall::Low,
|
||||||
|
up: false,
|
||||||
|
waterlogged: false,
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
);
|
);
|
||||||
assert!(
|
assert!(
|
||||||
block_state.is_some(),
|
block_state.is_some(),
|
||||||
|
|
|
@ -4,24 +4,24 @@ edition = "2021"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
name = "azalea-protocol"
|
name = "azalea-protocol"
|
||||||
repository = "https://github.com/mat-1/azalea/tree/main/azalea-protocol"
|
repository = "https://github.com/mat-1/azalea/tree/main/azalea-protocol"
|
||||||
version = "0.5.0"
|
version = "0.6.0"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
async-compression = {version = "^0.3.8", features = ["tokio", "zlib"], optional = true}
|
async-compression = {version = "^0.3.8", features = ["tokio", "zlib"], optional = true}
|
||||||
async-recursion = "1.0.0"
|
async-recursion = "1.0.0"
|
||||||
azalea-auth = {path = "../azalea-auth", version = "^0.5.0" }
|
azalea-auth = {path = "../azalea-auth", version = "^0.6.0" }
|
||||||
azalea-block = {path = "../azalea-block", default-features = false, version = "^0.5.0" }
|
azalea-block = {path = "../azalea-block", default-features = false, version = "^0.6.0" }
|
||||||
azalea-brigadier = {path = "../azalea-brigadier", version = "^0.5.0", features = ["azalea-buf"]}
|
azalea-brigadier = {path = "../azalea-brigadier", version = "^0.6.0", features = ["azalea-buf"]}
|
||||||
azalea-buf = {path = "../azalea-buf", version = "^0.5.0" }
|
azalea-buf = {path = "../azalea-buf", version = "^0.6.0" }
|
||||||
azalea-chat = {path = "../azalea-chat", version = "^0.5.0" }
|
azalea-chat = {path = "../azalea-chat", version = "^0.6.0" }
|
||||||
azalea-core = {path = "../azalea-core", optional = true, version = "^0.5.0" }
|
azalea-core = {path = "../azalea-core", optional = true, version = "^0.6.0" }
|
||||||
azalea-crypto = {path = "../azalea-crypto", version = "^0.5.0" }
|
azalea-crypto = {path = "../azalea-crypto", version = "^0.6.0" }
|
||||||
azalea-nbt = {path = "../azalea-nbt", version = "^0.5.0" }
|
azalea-nbt = {path = "../azalea-nbt", version = "^0.6.0" }
|
||||||
azalea-protocol-macros = {path = "./azalea-protocol-macros", version = "^0.5.0" }
|
azalea-protocol-macros = {path = "./azalea-protocol-macros", version = "^0.6.0" }
|
||||||
azalea-registry = {path = "../azalea-registry", version = "^0.5.0" }
|
azalea-registry = {path = "../azalea-registry", version = "^0.6.0" }
|
||||||
azalea-world = {path = "../azalea-world", version = "^0.5.0" }
|
azalea-world = {path = "../azalea-world", version = "^0.6.0" }
|
||||||
bevy_ecs = { version = "0.9.1", default-features = false }
|
bevy_ecs = { version = "0.9.1", default-features = false }
|
||||||
byteorder = "^1.4.3"
|
byteorder = "^1.4.3"
|
||||||
bytes = "^1.1.0"
|
bytes = "^1.1.0"
|
||||||
|
@ -46,4 +46,4 @@ packets = ["connecting", "dep:async-compression", "dep:azalea-core"]
|
||||||
anyhow = "^1.0.65"
|
anyhow = "^1.0.65"
|
||||||
tracing = "^0.1.36"
|
tracing = "^0.1.36"
|
||||||
tracing-subscriber = "^0.3.15"
|
tracing-subscriber = "^0.3.15"
|
||||||
once_cell = "1.17.0"
|
once_cell = "1.17.0"
|
||||||
|
|
2
azalea-protocol/azalea-protocol-macros/Cargo.toml
Executable file → Normal file
2
azalea-protocol/azalea-protocol-macros/Cargo.toml
Executable file → Normal file
|
@ -3,7 +3,7 @@ description = "Macros internally used in azalea-protocol."
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
name = "azalea-protocol-macros"
|
name = "azalea-protocol-macros"
|
||||||
version = "0.5.0"
|
version = "0.6.0"
|
||||||
repository = "https://github.com/mat-1/azalea/tree/main/azalea-protocol/azalea-protocol-macros"
|
repository = "https://github.com/mat-1/azalea/tree/main/azalea-protocol/azalea-protocol-macros"
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
|
|
|
@ -37,7 +37,7 @@ impl McBufReadable for BlockStateWithPosition {
|
||||||
|
|
||||||
impl McBufWritable for BlockStateWithPosition {
|
impl McBufWritable for BlockStateWithPosition {
|
||||||
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||||
let data = (self.state as u64) << 12
|
let data = (self.state.id as u64) << 12
|
||||||
| (u64::from(self.pos.x) << 8 | u64::from(self.pos.z) << 4 | u64::from(self.pos.y));
|
| (u64::from(self.pos.x) << 8 | u64::from(self.pos.z) << 4 | u64::from(self.pos.y));
|
||||||
u64::var_write_into(&data, buf)?;
|
u64::var_write_into(&data, buf)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
6
azalea-registry/Cargo.toml
Executable file → Normal file
6
azalea-registry/Cargo.toml
Executable file → Normal file
|
@ -4,11 +4,11 @@ edition = "2021"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
name = "azalea-registry"
|
name = "azalea-registry"
|
||||||
repository = "https://github.com/mat-1/azalea/tree/main/azalea-registry"
|
repository = "https://github.com/mat-1/azalea/tree/main/azalea-registry"
|
||||||
version = "0.5.0"
|
version = "0.6.0"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
azalea-buf = {path = "../azalea-buf", version = "^0.5.0"}
|
azalea-buf = {path = "../azalea-buf", version = "^0.6.0" }
|
||||||
azalea-registry-macros = {path = "./azalea-registry-macros", version = "^0.5.0"}
|
azalea-registry-macros = {path = "./azalea-registry-macros", version = "^0.6.0" }
|
||||||
enum-as-inner = "0.5.1"
|
enum-as-inner = "0.5.1"
|
||||||
|
|
2
azalea-registry/azalea-registry-macros/Cargo.toml
Executable file → Normal file
2
azalea-registry/azalea-registry-macros/Cargo.toml
Executable file → Normal file
|
@ -4,7 +4,7 @@ edition = "2021"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
name = "azalea-registry-macros"
|
name = "azalea-registry-macros"
|
||||||
repository = "https://github.com/mat-1/azalea/tree/main/azalea-registry/azalea-registry-macros"
|
repository = "https://github.com/mat-1/azalea/tree/main/azalea-registry/azalea-registry-macros"
|
||||||
version = "0.5.0"
|
version = "0.6.0"
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
proc-macro = true
|
proc-macro = true
|
||||||
|
|
|
@ -5,7 +5,7 @@ use syn::{
|
||||||
parse::{Parse, ParseStream, Result},
|
parse::{Parse, ParseStream, Result},
|
||||||
parse_macro_input,
|
parse_macro_input,
|
||||||
punctuated::Punctuated,
|
punctuated::Punctuated,
|
||||||
Ident, LitStr, Token,
|
Attribute, Ident, LitStr, Token,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RegistryItem {
|
struct RegistryItem {
|
||||||
|
@ -16,6 +16,7 @@ struct RegistryItem {
|
||||||
struct Registry {
|
struct Registry {
|
||||||
name: Ident,
|
name: Ident,
|
||||||
items: Vec<RegistryItem>,
|
items: Vec<RegistryItem>,
|
||||||
|
attributes: Vec<Attribute>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for RegistryItem {
|
impl Parse for RegistryItem {
|
||||||
|
@ -30,12 +31,16 @@ impl Parse for RegistryItem {
|
||||||
|
|
||||||
impl Parse for Registry {
|
impl Parse for Registry {
|
||||||
fn parse(input: ParseStream) -> Result<Self> {
|
fn parse(input: ParseStream) -> Result<Self> {
|
||||||
// Block, {
|
// enum Block {
|
||||||
// Air => "minecraft:air",
|
// Air => "minecraft:air",
|
||||||
// Stone => "minecraft:stone"
|
// Stone => "minecraft:stone"
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
// this also includes docs
|
||||||
|
let attributes = input.call(Attribute::parse_outer).unwrap_or_default();
|
||||||
|
|
||||||
|
input.parse::<Token![enum]>()?;
|
||||||
let name = input.parse()?;
|
let name = input.parse()?;
|
||||||
let _ = input.parse::<Token![,]>()?;
|
|
||||||
let content;
|
let content;
|
||||||
braced!(content in input);
|
braced!(content in input);
|
||||||
let items: Punctuated<RegistryItem, Token![,]> =
|
let items: Punctuated<RegistryItem, Token![,]> =
|
||||||
|
@ -44,6 +49,7 @@ impl Parse for Registry {
|
||||||
Ok(Registry {
|
Ok(Registry {
|
||||||
name,
|
name,
|
||||||
items: items.into_iter().collect(),
|
items: items.into_iter().collect(),
|
||||||
|
attributes,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -66,7 +72,9 @@ pub fn registry(input: TokenStream) -> TokenStream {
|
||||||
#name = #protocol_id,
|
#name = #protocol_id,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
let attributes = input.attributes;
|
||||||
generated.extend(quote! {
|
generated.extend(quote! {
|
||||||
|
#(#attributes)*
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, azalea_buf::McBuf)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, azalea_buf::McBuf)]
|
||||||
#[repr(u32)]
|
#[repr(u32)]
|
||||||
pub enum #name {
|
pub enum #name {
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
#![doc = include_str!("../README.md")]
|
#![doc = include_str!("../README.md")]
|
||||||
|
|
||||||
// This file is automatically generated in codegen/lib/code/registry.py
|
// The contents of the macros below are generated in
|
||||||
|
// codegen/lib/code/registry.py, though the rest of the file isn't
|
||||||
|
// auto-generated (so you can add doc comments to the registry enums if you
|
||||||
|
// want)
|
||||||
|
|
||||||
use azalea_buf::{BufReadError, McBufReadable, McBufVarReadable, McBufVarWritable, McBufWritable};
|
use azalea_buf::{BufReadError, McBufReadable, McBufVarReadable, McBufVarWritable, McBufWritable};
|
||||||
use azalea_registry_macros::registry;
|
use azalea_registry_macros::registry;
|
||||||
|
@ -39,7 +42,9 @@ impl<T: Registry> McBufWritable for OptionalRegistry<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
registry!(Activity, {
|
registry! {
|
||||||
|
/// The AI code that's currently being executed for the entity.
|
||||||
|
enum Activity {
|
||||||
Core => "minecraft:core",
|
Core => "minecraft:core",
|
||||||
Idle => "minecraft:idle",
|
Idle => "minecraft:idle",
|
||||||
Work => "minecraft:work",
|
Work => "minecraft:work",
|
||||||
|
@ -66,9 +71,11 @@ registry!(Activity, {
|
||||||
Roar => "minecraft:roar",
|
Roar => "minecraft:roar",
|
||||||
Emerge => "minecraft:emerge",
|
Emerge => "minecraft:emerge",
|
||||||
Dig => "minecraft:dig",
|
Dig => "minecraft:dig",
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
|
||||||
registry!(Attribute, {
|
registry! {
|
||||||
|
enum Attribute {
|
||||||
GenericMaxHealth => "minecraft:generic.max_health",
|
GenericMaxHealth => "minecraft:generic.max_health",
|
||||||
GenericFollowRange => "minecraft:generic.follow_range",
|
GenericFollowRange => "minecraft:generic.follow_range",
|
||||||
GenericKnockbackResistance => "minecraft:generic.knockback_resistance",
|
GenericKnockbackResistance => "minecraft:generic.knockback_resistance",
|
||||||
|
@ -82,9 +89,11 @@ registry!(Attribute, {
|
||||||
GenericLuck => "minecraft:generic.luck",
|
GenericLuck => "minecraft:generic.luck",
|
||||||
ZombieSpawnReinforcements => "minecraft:zombie.spawn_reinforcements",
|
ZombieSpawnReinforcements => "minecraft:zombie.spawn_reinforcements",
|
||||||
HorseJumpStrength => "minecraft:horse.jump_strength",
|
HorseJumpStrength => "minecraft:horse.jump_strength",
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
|
||||||
registry!(BannerPattern, {
|
registry! {
|
||||||
|
enum BannerPattern {
|
||||||
Base => "minecraft:base",
|
Base => "minecraft:base",
|
||||||
SquareBottomLeft => "minecraft:square_bottom_left",
|
SquareBottomLeft => "minecraft:square_bottom_left",
|
||||||
SquareBottomRight => "minecraft:square_bottom_right",
|
SquareBottomRight => "minecraft:square_bottom_right",
|
||||||
|
@ -126,9 +135,16 @@ registry!(BannerPattern, {
|
||||||
Flower => "minecraft:flower",
|
Flower => "minecraft:flower",
|
||||||
Mojang => "minecraft:mojang",
|
Mojang => "minecraft:mojang",
|
||||||
Piglin => "minecraft:piglin",
|
Piglin => "minecraft:piglin",
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
|
||||||
registry!(Block, {
|
registry! {
|
||||||
|
/// An enum of every type of block in the game. To represent a block *state*,
|
||||||
|
/// use [`azalea_block::BlockState`] or the [`azalea_block::Block`] trait.
|
||||||
|
///
|
||||||
|
/// [`azalea_block::BlockState`]: https://docs.rs/azalea-block/latest/azalea_block/struct.BlockState.html
|
||||||
|
/// [`azalea_block::Block`]: https://docs.rs/azalea-block/latest/azalea_block/trait.Block.html
|
||||||
|
enum Block {
|
||||||
Air => "minecraft:air",
|
Air => "minecraft:air",
|
||||||
Stone => "minecraft:stone",
|
Stone => "minecraft:stone",
|
||||||
Granite => "minecraft:granite",
|
Granite => "minecraft:granite",
|
||||||
|
@ -1101,9 +1117,14 @@ registry!(Block, {
|
||||||
PearlescentFroglight => "minecraft:pearlescent_froglight",
|
PearlescentFroglight => "minecraft:pearlescent_froglight",
|
||||||
Frogspawn => "minecraft:frogspawn",
|
Frogspawn => "minecraft:frogspawn",
|
||||||
ReinforcedDeepslate => "minecraft:reinforced_deepslate",
|
ReinforcedDeepslate => "minecraft:reinforced_deepslate",
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
|
||||||
registry!(BlockEntityKind, {
|
registry! {
|
||||||
|
/// An enum that contains every type of block entity. A block entity is a block
|
||||||
|
/// that contains data that can't be represented as just a block state, like
|
||||||
|
/// how chests store items.
|
||||||
|
enum BlockEntityKind {
|
||||||
Furnace => "minecraft:furnace",
|
Furnace => "minecraft:furnace",
|
||||||
Chest => "minecraft:chest",
|
Chest => "minecraft:chest",
|
||||||
TrappedChest => "minecraft:trapped_chest",
|
TrappedChest => "minecraft:trapped_chest",
|
||||||
|
@ -1142,9 +1163,11 @@ registry!(BlockEntityKind, {
|
||||||
SculkCatalyst => "minecraft:sculk_catalyst",
|
SculkCatalyst => "minecraft:sculk_catalyst",
|
||||||
SculkShrieker => "minecraft:sculk_shrieker",
|
SculkShrieker => "minecraft:sculk_shrieker",
|
||||||
ChiseledBookshelf => "minecraft:chiseled_bookshelf",
|
ChiseledBookshelf => "minecraft:chiseled_bookshelf",
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
|
||||||
registry!(BlockPredicateKind, {
|
registry! {
|
||||||
|
enum BlockPredicateKind {
|
||||||
MatchingBlocks => "minecraft:matching_blocks",
|
MatchingBlocks => "minecraft:matching_blocks",
|
||||||
MatchingBlockTag => "minecraft:matching_block_tag",
|
MatchingBlockTag => "minecraft:matching_block_tag",
|
||||||
MatchingFluids => "minecraft:matching_fluids",
|
MatchingFluids => "minecraft:matching_fluids",
|
||||||
|
@ -1157,9 +1180,11 @@ registry!(BlockPredicateKind, {
|
||||||
AllOf => "minecraft:all_of",
|
AllOf => "minecraft:all_of",
|
||||||
Not => "minecraft:not",
|
Not => "minecraft:not",
|
||||||
True => "minecraft:true",
|
True => "minecraft:true",
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
|
||||||
registry!(CatVariant, {
|
registry! {
|
||||||
|
enum CatVariant {
|
||||||
Tabby => "minecraft:tabby",
|
Tabby => "minecraft:tabby",
|
||||||
Black => "minecraft:black",
|
Black => "minecraft:black",
|
||||||
Red => "minecraft:red",
|
Red => "minecraft:red",
|
||||||
|
@ -1171,9 +1196,11 @@ registry!(CatVariant, {
|
||||||
White => "minecraft:white",
|
White => "minecraft:white",
|
||||||
Jellie => "minecraft:jellie",
|
Jellie => "minecraft:jellie",
|
||||||
AllBlack => "minecraft:all_black",
|
AllBlack => "minecraft:all_black",
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
|
||||||
registry!(ChunkStatus, {
|
registry! {
|
||||||
|
enum ChunkStatus {
|
||||||
Empty => "minecraft:empty",
|
Empty => "minecraft:empty",
|
||||||
StructureStarts => "minecraft:structure_starts",
|
StructureStarts => "minecraft:structure_starts",
|
||||||
StructureReferences => "minecraft:structure_references",
|
StructureReferences => "minecraft:structure_references",
|
||||||
|
@ -1187,9 +1214,11 @@ registry!(ChunkStatus, {
|
||||||
Spawn => "minecraft:spawn",
|
Spawn => "minecraft:spawn",
|
||||||
Heightmaps => "minecraft:heightmaps",
|
Heightmaps => "minecraft:heightmaps",
|
||||||
Full => "minecraft:full",
|
Full => "minecraft:full",
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
|
||||||
registry!(CommandArgumentKind, {
|
registry! {
|
||||||
|
enum CommandArgumentKind {
|
||||||
Bool => "brigadier:bool",
|
Bool => "brigadier:bool",
|
||||||
Float => "brigadier:float",
|
Float => "brigadier:float",
|
||||||
Double => "brigadier:double",
|
Double => "brigadier:double",
|
||||||
|
@ -1238,9 +1267,11 @@ registry!(CommandArgumentKind, {
|
||||||
TemplateMirror => "minecraft:template_mirror",
|
TemplateMirror => "minecraft:template_mirror",
|
||||||
TemplateRotation => "minecraft:template_rotation",
|
TemplateRotation => "minecraft:template_rotation",
|
||||||
Uuid => "minecraft:uuid",
|
Uuid => "minecraft:uuid",
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
|
||||||
registry!(CustomStat, {
|
registry! {
|
||||||
|
enum CustomStat {
|
||||||
LeaveGame => "minecraft:leave_game",
|
LeaveGame => "minecraft:leave_game",
|
||||||
PlayTime => "minecraft:play_time",
|
PlayTime => "minecraft:play_time",
|
||||||
TotalWorldTime => "minecraft:total_world_time",
|
TotalWorldTime => "minecraft:total_world_time",
|
||||||
|
@ -1316,9 +1347,11 @@ registry!(CustomStat, {
|
||||||
InteractWithGrindstone => "minecraft:interact_with_grindstone",
|
InteractWithGrindstone => "minecraft:interact_with_grindstone",
|
||||||
TargetHit => "minecraft:target_hit",
|
TargetHit => "minecraft:target_hit",
|
||||||
InteractWithSmithingTable => "minecraft:interact_with_smithing_table",
|
InteractWithSmithingTable => "minecraft:interact_with_smithing_table",
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
|
||||||
registry!(Enchantment, {
|
registry! {
|
||||||
|
enum Enchantment {
|
||||||
Protection => "minecraft:protection",
|
Protection => "minecraft:protection",
|
||||||
FireProtection => "minecraft:fire_protection",
|
FireProtection => "minecraft:fire_protection",
|
||||||
FeatherFalling => "minecraft:feather_falling",
|
FeatherFalling => "minecraft:feather_falling",
|
||||||
|
@ -1358,9 +1391,12 @@ registry!(Enchantment, {
|
||||||
Piercing => "minecraft:piercing",
|
Piercing => "minecraft:piercing",
|
||||||
Mending => "minecraft:mending",
|
Mending => "minecraft:mending",
|
||||||
VanishingCurse => "minecraft:vanishing_curse",
|
VanishingCurse => "minecraft:vanishing_curse",
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
|
||||||
registry!(EntityKind, {
|
registry! {
|
||||||
|
/// An enum that contains every type of entity.
|
||||||
|
enum EntityKind {
|
||||||
Allay => "minecraft:allay",
|
Allay => "minecraft:allay",
|
||||||
AreaEffectCloud => "minecraft:area_effect_cloud",
|
AreaEffectCloud => "minecraft:area_effect_cloud",
|
||||||
ArmorStand => "minecraft:armor_stand",
|
ArmorStand => "minecraft:armor_stand",
|
||||||
|
@ -1480,30 +1516,38 @@ registry!(EntityKind, {
|
||||||
ZombifiedPiglin => "minecraft:zombified_piglin",
|
ZombifiedPiglin => "minecraft:zombified_piglin",
|
||||||
Player => "minecraft:player",
|
Player => "minecraft:player",
|
||||||
FishingBobber => "minecraft:fishing_bobber",
|
FishingBobber => "minecraft:fishing_bobber",
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
|
||||||
registry!(FloatProviderKind, {
|
registry! {
|
||||||
|
enum FloatProviderKind {
|
||||||
Constant => "minecraft:constant",
|
Constant => "minecraft:constant",
|
||||||
Uniform => "minecraft:uniform",
|
Uniform => "minecraft:uniform",
|
||||||
ClampedNormal => "minecraft:clamped_normal",
|
ClampedNormal => "minecraft:clamped_normal",
|
||||||
Trapezoid => "minecraft:trapezoid",
|
Trapezoid => "minecraft:trapezoid",
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
|
||||||
registry!(Fluid, {
|
registry! {
|
||||||
|
enum Fluid {
|
||||||
Empty => "minecraft:empty",
|
Empty => "minecraft:empty",
|
||||||
FlowingWater => "minecraft:flowing_water",
|
FlowingWater => "minecraft:flowing_water",
|
||||||
Water => "minecraft:water",
|
Water => "minecraft:water",
|
||||||
FlowingLava => "minecraft:flowing_lava",
|
FlowingLava => "minecraft:flowing_lava",
|
||||||
Lava => "minecraft:lava",
|
Lava => "minecraft:lava",
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
|
||||||
registry!(FrogVariant, {
|
registry! {
|
||||||
|
enum FrogVariant {
|
||||||
Temperate => "minecraft:temperate",
|
Temperate => "minecraft:temperate",
|
||||||
Warm => "minecraft:warm",
|
Warm => "minecraft:warm",
|
||||||
Cold => "minecraft:cold",
|
Cold => "minecraft:cold",
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
|
||||||
registry!(GameEvent, {
|
registry! {
|
||||||
|
enum GameEvent {
|
||||||
BlockActivate => "minecraft:block_activate",
|
BlockActivate => "minecraft:block_activate",
|
||||||
BlockAttach => "minecraft:block_attach",
|
BlockAttach => "minecraft:block_attach",
|
||||||
BlockChange => "minecraft:block_change",
|
BlockChange => "minecraft:block_change",
|
||||||
|
@ -1550,18 +1594,22 @@ registry!(GameEvent, {
|
||||||
Step => "minecraft:step",
|
Step => "minecraft:step",
|
||||||
Swim => "minecraft:swim",
|
Swim => "minecraft:swim",
|
||||||
Teleport => "minecraft:teleport",
|
Teleport => "minecraft:teleport",
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
|
||||||
registry!(HeightProviderKind, {
|
registry! {
|
||||||
|
enum HeightProviderKind {
|
||||||
Constant => "minecraft:constant",
|
Constant => "minecraft:constant",
|
||||||
Uniform => "minecraft:uniform",
|
Uniform => "minecraft:uniform",
|
||||||
BiasedToBottom => "minecraft:biased_to_bottom",
|
BiasedToBottom => "minecraft:biased_to_bottom",
|
||||||
VeryBiasedToBottom => "minecraft:very_biased_to_bottom",
|
VeryBiasedToBottom => "minecraft:very_biased_to_bottom",
|
||||||
Trapezoid => "minecraft:trapezoid",
|
Trapezoid => "minecraft:trapezoid",
|
||||||
WeightedList => "minecraft:weighted_list",
|
WeightedList => "minecraft:weighted_list",
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
|
||||||
registry!(Instrument, {
|
registry! {
|
||||||
|
enum Instrument {
|
||||||
PonderGoatHorn => "minecraft:ponder_goat_horn",
|
PonderGoatHorn => "minecraft:ponder_goat_horn",
|
||||||
SingGoatHorn => "minecraft:sing_goat_horn",
|
SingGoatHorn => "minecraft:sing_goat_horn",
|
||||||
SeekGoatHorn => "minecraft:seek_goat_horn",
|
SeekGoatHorn => "minecraft:seek_goat_horn",
|
||||||
|
@ -1570,18 +1618,22 @@ registry!(Instrument, {
|
||||||
CallGoatHorn => "minecraft:call_goat_horn",
|
CallGoatHorn => "minecraft:call_goat_horn",
|
||||||
YearnGoatHorn => "minecraft:yearn_goat_horn",
|
YearnGoatHorn => "minecraft:yearn_goat_horn",
|
||||||
DreamGoatHorn => "minecraft:dream_goat_horn",
|
DreamGoatHorn => "minecraft:dream_goat_horn",
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
|
||||||
registry!(IntProviderKind, {
|
registry! {
|
||||||
|
enum IntProviderKind {
|
||||||
Constant => "minecraft:constant",
|
Constant => "minecraft:constant",
|
||||||
Uniform => "minecraft:uniform",
|
Uniform => "minecraft:uniform",
|
||||||
BiasedToBottom => "minecraft:biased_to_bottom",
|
BiasedToBottom => "minecraft:biased_to_bottom",
|
||||||
Clamped => "minecraft:clamped",
|
Clamped => "minecraft:clamped",
|
||||||
WeightedList => "minecraft:weighted_list",
|
WeightedList => "minecraft:weighted_list",
|
||||||
ClampedNormal => "minecraft:clamped_normal",
|
ClampedNormal => "minecraft:clamped_normal",
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
|
||||||
registry!(Item, {
|
registry! {
|
||||||
|
enum Item {
|
||||||
Air => "minecraft:air",
|
Air => "minecraft:air",
|
||||||
Stone => "minecraft:stone",
|
Stone => "minecraft:stone",
|
||||||
Granite => "minecraft:granite",
|
Granite => "minecraft:granite",
|
||||||
|
@ -2768,9 +2820,11 @@ registry!(Item, {
|
||||||
PearlescentFroglight => "minecraft:pearlescent_froglight",
|
PearlescentFroglight => "minecraft:pearlescent_froglight",
|
||||||
Frogspawn => "minecraft:frogspawn",
|
Frogspawn => "minecraft:frogspawn",
|
||||||
EchoShard => "minecraft:echo_shard",
|
EchoShard => "minecraft:echo_shard",
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
|
||||||
registry!(LootConditionKind, {
|
registry! {
|
||||||
|
enum LootConditionKind {
|
||||||
Inverted => "minecraft:inverted",
|
Inverted => "minecraft:inverted",
|
||||||
Alternative => "minecraft:alternative",
|
Alternative => "minecraft:alternative",
|
||||||
RandomChance => "minecraft:random_chance",
|
RandomChance => "minecraft:random_chance",
|
||||||
|
@ -2788,9 +2842,11 @@ registry!(LootConditionKind, {
|
||||||
Reference => "minecraft:reference",
|
Reference => "minecraft:reference",
|
||||||
TimeCheck => "minecraft:time_check",
|
TimeCheck => "minecraft:time_check",
|
||||||
ValueCheck => "minecraft:value_check",
|
ValueCheck => "minecraft:value_check",
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
|
||||||
registry!(LootFunctionKind, {
|
registry! {
|
||||||
|
enum LootFunctionKind {
|
||||||
SetCount => "minecraft:set_count",
|
SetCount => "minecraft:set_count",
|
||||||
EnchantWithLevels => "minecraft:enchant_with_levels",
|
EnchantWithLevels => "minecraft:enchant_with_levels",
|
||||||
EnchantRandomly => "minecraft:enchant_randomly",
|
EnchantRandomly => "minecraft:enchant_randomly",
|
||||||
|
@ -2816,21 +2872,27 @@ registry!(LootFunctionKind, {
|
||||||
SetBannerPattern => "minecraft:set_banner_pattern",
|
SetBannerPattern => "minecraft:set_banner_pattern",
|
||||||
SetPotion => "minecraft:set_potion",
|
SetPotion => "minecraft:set_potion",
|
||||||
SetInstrument => "minecraft:set_instrument",
|
SetInstrument => "minecraft:set_instrument",
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
|
||||||
registry!(LootNbtProviderKind, {
|
registry! {
|
||||||
|
enum LootNbtProviderKind {
|
||||||
Storage => "minecraft:storage",
|
Storage => "minecraft:storage",
|
||||||
Context => "minecraft:context",
|
Context => "minecraft:context",
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
|
||||||
registry!(LootNumberProviderKind, {
|
registry! {
|
||||||
|
enum LootNumberProviderKind {
|
||||||
Constant => "minecraft:constant",
|
Constant => "minecraft:constant",
|
||||||
Uniform => "minecraft:uniform",
|
Uniform => "minecraft:uniform",
|
||||||
Binomial => "minecraft:binomial",
|
Binomial => "minecraft:binomial",
|
||||||
Score => "minecraft:score",
|
Score => "minecraft:score",
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
|
||||||
registry!(LootPoolEntryKind, {
|
registry! {
|
||||||
|
enum LootPoolEntryKind {
|
||||||
Empty => "minecraft:empty",
|
Empty => "minecraft:empty",
|
||||||
Item => "minecraft:item",
|
Item => "minecraft:item",
|
||||||
LootTable => "minecraft:loot_table",
|
LootTable => "minecraft:loot_table",
|
||||||
|
@ -2839,14 +2901,18 @@ registry!(LootPoolEntryKind, {
|
||||||
Alternatives => "minecraft:alternatives",
|
Alternatives => "minecraft:alternatives",
|
||||||
Sequence => "minecraft:sequence",
|
Sequence => "minecraft:sequence",
|
||||||
Group => "minecraft:group",
|
Group => "minecraft:group",
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
|
||||||
registry!(LootScoreProviderKind, {
|
registry! {
|
||||||
|
enum LootScoreProviderKind {
|
||||||
Fixed => "minecraft:fixed",
|
Fixed => "minecraft:fixed",
|
||||||
Context => "minecraft:context",
|
Context => "minecraft:context",
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
|
||||||
registry!(MemoryModuleKind, {
|
registry! {
|
||||||
|
enum MemoryModuleKind {
|
||||||
Dummy => "minecraft:dummy",
|
Dummy => "minecraft:dummy",
|
||||||
Home => "minecraft:home",
|
Home => "minecraft:home",
|
||||||
JobSite => "minecraft:job_site",
|
JobSite => "minecraft:job_site",
|
||||||
|
@ -2940,9 +3006,11 @@ registry!(MemoryModuleKind, {
|
||||||
LikedNoteblock => "minecraft:liked_noteblock",
|
LikedNoteblock => "minecraft:liked_noteblock",
|
||||||
LikedNoteblockCooldownTicks => "minecraft:liked_noteblock_cooldown_ticks",
|
LikedNoteblockCooldownTicks => "minecraft:liked_noteblock_cooldown_ticks",
|
||||||
ItemPickupCooldownTicks => "minecraft:item_pickup_cooldown_ticks",
|
ItemPickupCooldownTicks => "minecraft:item_pickup_cooldown_ticks",
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
|
||||||
registry!(Menu, {
|
registry! {
|
||||||
|
enum Menu {
|
||||||
Generic9x1 => "minecraft:generic_9x1",
|
Generic9x1 => "minecraft:generic_9x1",
|
||||||
Generic9x2 => "minecraft:generic_9x2",
|
Generic9x2 => "minecraft:generic_9x2",
|
||||||
Generic9x3 => "minecraft:generic_9x3",
|
Generic9x3 => "minecraft:generic_9x3",
|
||||||
|
@ -2967,9 +3035,11 @@ registry!(Menu, {
|
||||||
Smoker => "minecraft:smoker",
|
Smoker => "minecraft:smoker",
|
||||||
CartographyTable => "minecraft:cartography_table",
|
CartographyTable => "minecraft:cartography_table",
|
||||||
Stonecutter => "minecraft:stonecutter",
|
Stonecutter => "minecraft:stonecutter",
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
|
||||||
registry!(MobEffect, {
|
registry! {
|
||||||
|
enum MobEffect {
|
||||||
Speed => "minecraft:speed",
|
Speed => "minecraft:speed",
|
||||||
Slowness => "minecraft:slowness",
|
Slowness => "minecraft:slowness",
|
||||||
Haste => "minecraft:haste",
|
Haste => "minecraft:haste",
|
||||||
|
@ -3003,9 +3073,11 @@ registry!(MobEffect, {
|
||||||
BadOmen => "minecraft:bad_omen",
|
BadOmen => "minecraft:bad_omen",
|
||||||
HeroOfTheVillage => "minecraft:hero_of_the_village",
|
HeroOfTheVillage => "minecraft:hero_of_the_village",
|
||||||
Darkness => "minecraft:darkness",
|
Darkness => "minecraft:darkness",
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
|
||||||
registry!(PaintingVariant, {
|
registry! {
|
||||||
|
enum PaintingVariant {
|
||||||
Kebab => "minecraft:kebab",
|
Kebab => "minecraft:kebab",
|
||||||
Aztec => "minecraft:aztec",
|
Aztec => "minecraft:aztec",
|
||||||
Alban => "minecraft:alban",
|
Alban => "minecraft:alban",
|
||||||
|
@ -3036,9 +3108,11 @@ registry!(PaintingVariant, {
|
||||||
Water => "minecraft:water",
|
Water => "minecraft:water",
|
||||||
Fire => "minecraft:fire",
|
Fire => "minecraft:fire",
|
||||||
DonkeyKong => "minecraft:donkey_kong",
|
DonkeyKong => "minecraft:donkey_kong",
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
|
||||||
registry!(ParticleKind, {
|
registry! {
|
||||||
|
enum ParticleKind {
|
||||||
AmbientEntityEffect => "minecraft:ambient_entity_effect",
|
AmbientEntityEffect => "minecraft:ambient_entity_effect",
|
||||||
AngryVillager => "minecraft:angry_villager",
|
AngryVillager => "minecraft:angry_villager",
|
||||||
Block => "minecraft:block",
|
Block => "minecraft:block",
|
||||||
|
@ -3132,9 +3206,11 @@ registry!(ParticleKind, {
|
||||||
ElectricSpark => "minecraft:electric_spark",
|
ElectricSpark => "minecraft:electric_spark",
|
||||||
Scrape => "minecraft:scrape",
|
Scrape => "minecraft:scrape",
|
||||||
Shriek => "minecraft:shriek",
|
Shriek => "minecraft:shriek",
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
|
||||||
registry!(PointOfInterestKind, {
|
registry! {
|
||||||
|
enum PointOfInterestKind {
|
||||||
Armorer => "minecraft:armorer",
|
Armorer => "minecraft:armorer",
|
||||||
Butcher => "minecraft:butcher",
|
Butcher => "minecraft:butcher",
|
||||||
Cartographer => "minecraft:cartographer",
|
Cartographer => "minecraft:cartographer",
|
||||||
|
@ -3155,20 +3231,26 @@ registry!(PointOfInterestKind, {
|
||||||
NetherPortal => "minecraft:nether_portal",
|
NetherPortal => "minecraft:nether_portal",
|
||||||
Lodestone => "minecraft:lodestone",
|
Lodestone => "minecraft:lodestone",
|
||||||
LightningRod => "minecraft:lightning_rod",
|
LightningRod => "minecraft:lightning_rod",
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
|
||||||
registry!(PosRuleTest, {
|
registry! {
|
||||||
|
enum PosRuleTest {
|
||||||
AlwaysTrue => "minecraft:always_true",
|
AlwaysTrue => "minecraft:always_true",
|
||||||
LinearPos => "minecraft:linear_pos",
|
LinearPos => "minecraft:linear_pos",
|
||||||
AxisAlignedLinearPos => "minecraft:axis_aligned_linear_pos",
|
AxisAlignedLinearPos => "minecraft:axis_aligned_linear_pos",
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
|
||||||
registry!(PositionSourceKind, {
|
registry! {
|
||||||
|
enum PositionSourceKind {
|
||||||
Block => "minecraft:block",
|
Block => "minecraft:block",
|
||||||
Entity => "minecraft:entity",
|
Entity => "minecraft:entity",
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
|
||||||
registry!(Potion, {
|
registry! {
|
||||||
|
enum Potion {
|
||||||
Empty => "minecraft:empty",
|
Empty => "minecraft:empty",
|
||||||
Water => "minecraft:water",
|
Water => "minecraft:water",
|
||||||
Mundane => "minecraft:mundane",
|
Mundane => "minecraft:mundane",
|
||||||
|
@ -3212,9 +3294,11 @@ registry!(Potion, {
|
||||||
Luck => "minecraft:luck",
|
Luck => "minecraft:luck",
|
||||||
SlowFalling => "minecraft:slow_falling",
|
SlowFalling => "minecraft:slow_falling",
|
||||||
LongSlowFalling => "minecraft:long_slow_falling",
|
LongSlowFalling => "minecraft:long_slow_falling",
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
|
||||||
registry!(RecipeSerializer, {
|
registry! {
|
||||||
|
enum RecipeSerializer {
|
||||||
CraftingShaped => "minecraft:crafting_shaped",
|
CraftingShaped => "minecraft:crafting_shaped",
|
||||||
CraftingShapeless => "minecraft:crafting_shapeless",
|
CraftingShapeless => "minecraft:crafting_shapeless",
|
||||||
CraftingSpecialArmordye => "minecraft:crafting_special_armordye",
|
CraftingSpecialArmordye => "minecraft:crafting_special_armordye",
|
||||||
|
@ -3236,9 +3320,11 @@ registry!(RecipeSerializer, {
|
||||||
CampfireCooking => "minecraft:campfire_cooking",
|
CampfireCooking => "minecraft:campfire_cooking",
|
||||||
Stonecutting => "minecraft:stonecutting",
|
Stonecutting => "minecraft:stonecutting",
|
||||||
Smithing => "minecraft:smithing",
|
Smithing => "minecraft:smithing",
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
|
||||||
registry!(RecipeKind, {
|
registry! {
|
||||||
|
enum RecipeKind {
|
||||||
Crafting => "minecraft:crafting",
|
Crafting => "minecraft:crafting",
|
||||||
Smelting => "minecraft:smelting",
|
Smelting => "minecraft:smelting",
|
||||||
Blasting => "minecraft:blasting",
|
Blasting => "minecraft:blasting",
|
||||||
|
@ -3246,25 +3332,31 @@ registry!(RecipeKind, {
|
||||||
CampfireCooking => "minecraft:campfire_cooking",
|
CampfireCooking => "minecraft:campfire_cooking",
|
||||||
Stonecutting => "minecraft:stonecutting",
|
Stonecutting => "minecraft:stonecutting",
|
||||||
Smithing => "minecraft:smithing",
|
Smithing => "minecraft:smithing",
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
|
||||||
registry!(RuleTest, {
|
registry! {
|
||||||
|
enum RuleTest {
|
||||||
AlwaysTrue => "minecraft:always_true",
|
AlwaysTrue => "minecraft:always_true",
|
||||||
BlockMatch => "minecraft:block_match",
|
BlockMatch => "minecraft:block_match",
|
||||||
BlockstateMatch => "minecraft:blockstate_match",
|
BlockstateMatch => "minecraft:blockstate_match",
|
||||||
TagMatch => "minecraft:tag_match",
|
TagMatch => "minecraft:tag_match",
|
||||||
RandomBlockMatch => "minecraft:random_block_match",
|
RandomBlockMatch => "minecraft:random_block_match",
|
||||||
RandomBlockstateMatch => "minecraft:random_blockstate_match",
|
RandomBlockstateMatch => "minecraft:random_blockstate_match",
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
|
||||||
registry!(Schedule, {
|
registry! {
|
||||||
|
enum Schedule {
|
||||||
Empty => "minecraft:empty",
|
Empty => "minecraft:empty",
|
||||||
Simple => "minecraft:simple",
|
Simple => "minecraft:simple",
|
||||||
VillagerBaby => "minecraft:villager_baby",
|
VillagerBaby => "minecraft:villager_baby",
|
||||||
VillagerDefault => "minecraft:villager_default",
|
VillagerDefault => "minecraft:villager_default",
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
|
||||||
registry!(SensorKind, {
|
registry! {
|
||||||
|
enum SensorKind {
|
||||||
Dummy => "minecraft:dummy",
|
Dummy => "minecraft:dummy",
|
||||||
NearestItems => "minecraft:nearest_items",
|
NearestItems => "minecraft:nearest_items",
|
||||||
NearestLivingEntities => "minecraft:nearest_living_entities",
|
NearestLivingEntities => "minecraft:nearest_living_entities",
|
||||||
|
@ -3287,9 +3379,11 @@ registry!(SensorKind, {
|
||||||
FrogAttackables => "minecraft:frog_attackables",
|
FrogAttackables => "minecraft:frog_attackables",
|
||||||
IsInWater => "minecraft:is_in_water",
|
IsInWater => "minecraft:is_in_water",
|
||||||
WardenEntitySensor => "minecraft:warden_entity_sensor",
|
WardenEntitySensor => "minecraft:warden_entity_sensor",
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
|
||||||
registry!(SoundEvent, {
|
registry! {
|
||||||
|
enum SoundEvent {
|
||||||
EntityAllayAmbientWithItem => "minecraft:entity.allay.ambient_with_item",
|
EntityAllayAmbientWithItem => "minecraft:entity.allay.ambient_with_item",
|
||||||
EntityAllayAmbientWithoutItem => "minecraft:entity.allay.ambient_without_item",
|
EntityAllayAmbientWithoutItem => "minecraft:entity.allay.ambient_without_item",
|
||||||
EntityAllayDeath => "minecraft:entity.allay.death",
|
EntityAllayDeath => "minecraft:entity.allay.death",
|
||||||
|
@ -4682,9 +4776,11 @@ registry!(SoundEvent, {
|
||||||
EntityZombieVillagerDeath => "minecraft:entity.zombie_villager.death",
|
EntityZombieVillagerDeath => "minecraft:entity.zombie_villager.death",
|
||||||
EntityZombieVillagerHurt => "minecraft:entity.zombie_villager.hurt",
|
EntityZombieVillagerHurt => "minecraft:entity.zombie_villager.hurt",
|
||||||
EntityZombieVillagerStep => "minecraft:entity.zombie_villager.step",
|
EntityZombieVillagerStep => "minecraft:entity.zombie_villager.step",
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
|
||||||
registry!(StatKind, {
|
registry! {
|
||||||
|
enum StatKind {
|
||||||
Mined => "minecraft:mined",
|
Mined => "minecraft:mined",
|
||||||
Crafted => "minecraft:crafted",
|
Crafted => "minecraft:crafted",
|
||||||
Used => "minecraft:used",
|
Used => "minecraft:used",
|
||||||
|
@ -4694,9 +4790,11 @@ registry!(StatKind, {
|
||||||
Killed => "minecraft:killed",
|
Killed => "minecraft:killed",
|
||||||
KilledBy => "minecraft:killed_by",
|
KilledBy => "minecraft:killed_by",
|
||||||
Custom => "minecraft:custom",
|
Custom => "minecraft:custom",
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
|
||||||
registry!(VillagerProfession, {
|
registry! {
|
||||||
|
enum VillagerProfession {
|
||||||
None => "minecraft:none",
|
None => "minecraft:none",
|
||||||
Armorer => "minecraft:armorer",
|
Armorer => "minecraft:armorer",
|
||||||
Butcher => "minecraft:butcher",
|
Butcher => "minecraft:butcher",
|
||||||
|
@ -4712,9 +4810,11 @@ registry!(VillagerProfession, {
|
||||||
Shepherd => "minecraft:shepherd",
|
Shepherd => "minecraft:shepherd",
|
||||||
Toolsmith => "minecraft:toolsmith",
|
Toolsmith => "minecraft:toolsmith",
|
||||||
Weaponsmith => "minecraft:weaponsmith",
|
Weaponsmith => "minecraft:weaponsmith",
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
|
||||||
registry!(VillagerKind, {
|
registry! {
|
||||||
|
enum VillagerKind {
|
||||||
Desert => "minecraft:desert",
|
Desert => "minecraft:desert",
|
||||||
Jungle => "minecraft:jungle",
|
Jungle => "minecraft:jungle",
|
||||||
Plains => "minecraft:plains",
|
Plains => "minecraft:plains",
|
||||||
|
@ -4722,16 +4822,20 @@ registry!(VillagerKind, {
|
||||||
Snow => "minecraft:snow",
|
Snow => "minecraft:snow",
|
||||||
Swamp => "minecraft:swamp",
|
Swamp => "minecraft:swamp",
|
||||||
Taiga => "minecraft:taiga",
|
Taiga => "minecraft:taiga",
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
|
||||||
registry!(WorldgenBiomeSource, {
|
registry! {
|
||||||
|
enum WorldgenBiomeSource {
|
||||||
Fixed => "minecraft:fixed",
|
Fixed => "minecraft:fixed",
|
||||||
MultiNoise => "minecraft:multi_noise",
|
MultiNoise => "minecraft:multi_noise",
|
||||||
Checkerboard => "minecraft:checkerboard",
|
Checkerboard => "minecraft:checkerboard",
|
||||||
TheEnd => "minecraft:the_end",
|
TheEnd => "minecraft:the_end",
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
|
||||||
registry!(WorldgenBlockStateProviderKind, {
|
registry! {
|
||||||
|
enum WorldgenBlockStateProviderKind {
|
||||||
SimpleStateProvider => "minecraft:simple_state_provider",
|
SimpleStateProvider => "minecraft:simple_state_provider",
|
||||||
WeightedStateProvider => "minecraft:weighted_state_provider",
|
WeightedStateProvider => "minecraft:weighted_state_provider",
|
||||||
NoiseThresholdProvider => "minecraft:noise_threshold_provider",
|
NoiseThresholdProvider => "minecraft:noise_threshold_provider",
|
||||||
|
@ -4739,21 +4843,27 @@ registry!(WorldgenBlockStateProviderKind, {
|
||||||
DualNoiseProvider => "minecraft:dual_noise_provider",
|
DualNoiseProvider => "minecraft:dual_noise_provider",
|
||||||
RotatedBlockProvider => "minecraft:rotated_block_provider",
|
RotatedBlockProvider => "minecraft:rotated_block_provider",
|
||||||
RandomizedIntStateProvider => "minecraft:randomized_int_state_provider",
|
RandomizedIntStateProvider => "minecraft:randomized_int_state_provider",
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
|
||||||
registry!(WorldgenCarver, {
|
registry! {
|
||||||
|
enum WorldgenCarver {
|
||||||
Cave => "minecraft:cave",
|
Cave => "minecraft:cave",
|
||||||
NetherCave => "minecraft:nether_cave",
|
NetherCave => "minecraft:nether_cave",
|
||||||
Canyon => "minecraft:canyon",
|
Canyon => "minecraft:canyon",
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
|
||||||
registry!(WorldgenChunkGenerator, {
|
registry! {
|
||||||
|
enum WorldgenChunkGenerator {
|
||||||
Noise => "minecraft:noise",
|
Noise => "minecraft:noise",
|
||||||
Flat => "minecraft:flat",
|
Flat => "minecraft:flat",
|
||||||
Debug => "minecraft:debug",
|
Debug => "minecraft:debug",
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
|
||||||
registry!(WorldgenDensityFunctionKind, {
|
registry! {
|
||||||
|
enum WorldgenDensityFunctionKind {
|
||||||
BlendAlpha => "minecraft:blend_alpha",
|
BlendAlpha => "minecraft:blend_alpha",
|
||||||
BlendOffset => "minecraft:blend_offset",
|
BlendOffset => "minecraft:blend_offset",
|
||||||
Beardifier => "minecraft:beardifier",
|
Beardifier => "minecraft:beardifier",
|
||||||
|
@ -4786,9 +4896,11 @@ registry!(WorldgenDensityFunctionKind, {
|
||||||
Spline => "minecraft:spline",
|
Spline => "minecraft:spline",
|
||||||
Constant => "minecraft:constant",
|
Constant => "minecraft:constant",
|
||||||
YClampedGradient => "minecraft:y_clamped_gradient",
|
YClampedGradient => "minecraft:y_clamped_gradient",
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
|
||||||
registry!(WorldgenFeature, {
|
registry! {
|
||||||
|
enum WorldgenFeature {
|
||||||
NoOp => "minecraft:no_op",
|
NoOp => "minecraft:no_op",
|
||||||
Tree => "minecraft:tree",
|
Tree => "minecraft:tree",
|
||||||
Flower => "minecraft:flower",
|
Flower => "minecraft:flower",
|
||||||
|
@ -4850,14 +4962,18 @@ registry!(WorldgenFeature, {
|
||||||
LargeDripstone => "minecraft:large_dripstone",
|
LargeDripstone => "minecraft:large_dripstone",
|
||||||
PointedDripstone => "minecraft:pointed_dripstone",
|
PointedDripstone => "minecraft:pointed_dripstone",
|
||||||
SculkPatch => "minecraft:sculk_patch",
|
SculkPatch => "minecraft:sculk_patch",
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
|
||||||
registry!(WorldgenFeatureSizeKind, {
|
registry! {
|
||||||
|
enum WorldgenFeatureSizeKind {
|
||||||
TwoLayersFeatureSize => "minecraft:two_layers_feature_size",
|
TwoLayersFeatureSize => "minecraft:two_layers_feature_size",
|
||||||
ThreeLayersFeatureSize => "minecraft:three_layers_feature_size",
|
ThreeLayersFeatureSize => "minecraft:three_layers_feature_size",
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
|
||||||
registry!(WorldgenFoliagePlacerKind, {
|
registry! {
|
||||||
|
enum WorldgenFoliagePlacerKind {
|
||||||
BlobFoliagePlacer => "minecraft:blob_foliage_placer",
|
BlobFoliagePlacer => "minecraft:blob_foliage_placer",
|
||||||
SpruceFoliagePlacer => "minecraft:spruce_foliage_placer",
|
SpruceFoliagePlacer => "minecraft:spruce_foliage_placer",
|
||||||
PineFoliagePlacer => "minecraft:pine_foliage_placer",
|
PineFoliagePlacer => "minecraft:pine_foliage_placer",
|
||||||
|
@ -4868,9 +4984,11 @@ registry!(WorldgenFoliagePlacerKind, {
|
||||||
MegaPineFoliagePlacer => "minecraft:mega_pine_foliage_placer",
|
MegaPineFoliagePlacer => "minecraft:mega_pine_foliage_placer",
|
||||||
DarkOakFoliagePlacer => "minecraft:dark_oak_foliage_placer",
|
DarkOakFoliagePlacer => "minecraft:dark_oak_foliage_placer",
|
||||||
RandomSpreadFoliagePlacer => "minecraft:random_spread_foliage_placer",
|
RandomSpreadFoliagePlacer => "minecraft:random_spread_foliage_placer",
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
|
||||||
registry!(WorldgenMaterialCondition, {
|
registry! {
|
||||||
|
enum WorldgenMaterialCondition {
|
||||||
Biome => "minecraft:biome",
|
Biome => "minecraft:biome",
|
||||||
NoiseThreshold => "minecraft:noise_threshold",
|
NoiseThreshold => "minecraft:noise_threshold",
|
||||||
VerticalGradient => "minecraft:vertical_gradient",
|
VerticalGradient => "minecraft:vertical_gradient",
|
||||||
|
@ -4882,16 +5000,20 @@ registry!(WorldgenMaterialCondition, {
|
||||||
Hole => "minecraft:hole",
|
Hole => "minecraft:hole",
|
||||||
AbovePreliminarySurface => "minecraft:above_preliminary_surface",
|
AbovePreliminarySurface => "minecraft:above_preliminary_surface",
|
||||||
StoneDepth => "minecraft:stone_depth",
|
StoneDepth => "minecraft:stone_depth",
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
|
||||||
registry!(WorldgenMaterialRule, {
|
registry! {
|
||||||
|
enum WorldgenMaterialRule {
|
||||||
Bandlands => "minecraft:bandlands",
|
Bandlands => "minecraft:bandlands",
|
||||||
Block => "minecraft:block",
|
Block => "minecraft:block",
|
||||||
Sequence => "minecraft:sequence",
|
Sequence => "minecraft:sequence",
|
||||||
Condition => "minecraft:condition",
|
Condition => "minecraft:condition",
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
|
||||||
registry!(WorldgenPlacementModifierKind, {
|
registry! {
|
||||||
|
enum WorldgenPlacementModifierKind {
|
||||||
BlockPredicateFilter => "minecraft:block_predicate_filter",
|
BlockPredicateFilter => "minecraft:block_predicate_filter",
|
||||||
RarityFilter => "minecraft:rarity_filter",
|
RarityFilter => "minecraft:rarity_filter",
|
||||||
SurfaceRelativeThresholdFilter => "minecraft:surface_relative_threshold_filter",
|
SurfaceRelativeThresholdFilter => "minecraft:surface_relative_threshold_filter",
|
||||||
|
@ -4907,13 +5029,17 @@ registry!(WorldgenPlacementModifierKind, {
|
||||||
InSquare => "minecraft:in_square",
|
InSquare => "minecraft:in_square",
|
||||||
RandomOffset => "minecraft:random_offset",
|
RandomOffset => "minecraft:random_offset",
|
||||||
CarvingMask => "minecraft:carving_mask",
|
CarvingMask => "minecraft:carving_mask",
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
|
||||||
registry!(WorldgenRootPlacerKind, {
|
registry! {
|
||||||
|
enum WorldgenRootPlacerKind {
|
||||||
MangroveRootPlacer => "minecraft:mangrove_root_placer",
|
MangroveRootPlacer => "minecraft:mangrove_root_placer",
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
|
||||||
registry!(WorldgenStructurePiece, {
|
registry! {
|
||||||
|
enum WorldgenStructurePiece {
|
||||||
Mscorridor => "minecraft:mscorridor",
|
Mscorridor => "minecraft:mscorridor",
|
||||||
Mscrossing => "minecraft:mscrossing",
|
Mscrossing => "minecraft:mscrossing",
|
||||||
Msroom => "minecraft:msroom",
|
Msroom => "minecraft:msroom",
|
||||||
|
@ -4970,22 +5096,28 @@ registry!(WorldgenStructurePiece, {
|
||||||
Shipwreck => "minecraft:shipwreck",
|
Shipwreck => "minecraft:shipwreck",
|
||||||
Nefos => "minecraft:nefos",
|
Nefos => "minecraft:nefos",
|
||||||
Jigsaw => "minecraft:jigsaw",
|
Jigsaw => "minecraft:jigsaw",
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
|
||||||
registry!(WorldgenStructurePlacement, {
|
registry! {
|
||||||
|
enum WorldgenStructurePlacement {
|
||||||
RandomSpread => "minecraft:random_spread",
|
RandomSpread => "minecraft:random_spread",
|
||||||
ConcentricRings => "minecraft:concentric_rings",
|
ConcentricRings => "minecraft:concentric_rings",
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
|
||||||
registry!(WorldgenStructurePoolElement, {
|
registry! {
|
||||||
|
enum WorldgenStructurePoolElement {
|
||||||
SinglePoolElement => "minecraft:single_pool_element",
|
SinglePoolElement => "minecraft:single_pool_element",
|
||||||
ListPoolElement => "minecraft:list_pool_element",
|
ListPoolElement => "minecraft:list_pool_element",
|
||||||
FeaturePoolElement => "minecraft:feature_pool_element",
|
FeaturePoolElement => "minecraft:feature_pool_element",
|
||||||
EmptyPoolElement => "minecraft:empty_pool_element",
|
EmptyPoolElement => "minecraft:empty_pool_element",
|
||||||
LegacySinglePoolElement => "minecraft:legacy_single_pool_element",
|
LegacySinglePoolElement => "minecraft:legacy_single_pool_element",
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
|
||||||
registry!(WorldgenStructureProcessor, {
|
registry! {
|
||||||
|
enum WorldgenStructureProcessor {
|
||||||
BlockIgnore => "minecraft:block_ignore",
|
BlockIgnore => "minecraft:block_ignore",
|
||||||
BlockRot => "minecraft:block_rot",
|
BlockRot => "minecraft:block_rot",
|
||||||
Gravity => "minecraft:gravity",
|
Gravity => "minecraft:gravity",
|
||||||
|
@ -4996,9 +5128,11 @@ registry!(WorldgenStructureProcessor, {
|
||||||
BlackstoneReplace => "minecraft:blackstone_replace",
|
BlackstoneReplace => "minecraft:blackstone_replace",
|
||||||
LavaSubmergedBlock => "minecraft:lava_submerged_block",
|
LavaSubmergedBlock => "minecraft:lava_submerged_block",
|
||||||
ProtectedBlocks => "minecraft:protected_blocks",
|
ProtectedBlocks => "minecraft:protected_blocks",
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
|
||||||
registry!(WorldgenStructureKind, {
|
registry! {
|
||||||
|
enum WorldgenStructureKind {
|
||||||
BuriedTreasure => "minecraft:buried_treasure",
|
BuriedTreasure => "minecraft:buried_treasure",
|
||||||
DesertPyramid => "minecraft:desert_pyramid",
|
DesertPyramid => "minecraft:desert_pyramid",
|
||||||
EndCity => "minecraft:end_city",
|
EndCity => "minecraft:end_city",
|
||||||
|
@ -5015,18 +5149,22 @@ registry!(WorldgenStructureKind, {
|
||||||
Stronghold => "minecraft:stronghold",
|
Stronghold => "minecraft:stronghold",
|
||||||
SwampHut => "minecraft:swamp_hut",
|
SwampHut => "minecraft:swamp_hut",
|
||||||
WoodlandMansion => "minecraft:woodland_mansion",
|
WoodlandMansion => "minecraft:woodland_mansion",
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
|
||||||
registry!(WorldgenTreeDecoratorKind, {
|
registry! {
|
||||||
|
enum WorldgenTreeDecoratorKind {
|
||||||
TrunkVine => "minecraft:trunk_vine",
|
TrunkVine => "minecraft:trunk_vine",
|
||||||
LeaveVine => "minecraft:leave_vine",
|
LeaveVine => "minecraft:leave_vine",
|
||||||
Cocoa => "minecraft:cocoa",
|
Cocoa => "minecraft:cocoa",
|
||||||
Beehive => "minecraft:beehive",
|
Beehive => "minecraft:beehive",
|
||||||
AlterGround => "minecraft:alter_ground",
|
AlterGround => "minecraft:alter_ground",
|
||||||
AttachedToLeaves => "minecraft:attached_to_leaves",
|
AttachedToLeaves => "minecraft:attached_to_leaves",
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
|
||||||
registry!(WorldgenTrunkPlacerKind, {
|
registry! {
|
||||||
|
enum WorldgenTrunkPlacerKind {
|
||||||
StraightTrunkPlacer => "minecraft:straight_trunk_placer",
|
StraightTrunkPlacer => "minecraft:straight_trunk_placer",
|
||||||
ForkingTrunkPlacer => "minecraft:forking_trunk_placer",
|
ForkingTrunkPlacer => "minecraft:forking_trunk_placer",
|
||||||
GiantTrunkPlacer => "minecraft:giant_trunk_placer",
|
GiantTrunkPlacer => "minecraft:giant_trunk_placer",
|
||||||
|
@ -5035,4 +5173,5 @@ registry!(WorldgenTrunkPlacerKind, {
|
||||||
FancyTrunkPlacer => "minecraft:fancy_trunk_placer",
|
FancyTrunkPlacer => "minecraft:fancy_trunk_placer",
|
||||||
BendingTrunkPlacer => "minecraft:bending_trunk_placer",
|
BendingTrunkPlacer => "minecraft:bending_trunk_placer",
|
||||||
UpwardsBranchingTrunkPlacer => "minecraft:upwards_branching_trunk_placer",
|
UpwardsBranchingTrunkPlacer => "minecraft:upwards_branching_trunk_placer",
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -4,21 +4,20 @@ edition = "2021"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
name = "azalea-world"
|
name = "azalea-world"
|
||||||
repository = "https://github.com/mat-1/azalea/tree/main/azalea-world"
|
repository = "https://github.com/mat-1/azalea/tree/main/azalea-world"
|
||||||
version = "0.5.0"
|
version = "0.6.0"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
azalea-block = {path = "../azalea-block", default-features = false, version = "^0.5.0"}
|
azalea-block = {path = "../azalea-block", default-features = false, version = "^0.6.0"}
|
||||||
azalea-buf = {path = "../azalea-buf", version = "^0.5.0"}
|
azalea-buf = {path = "../azalea-buf", version = "^0.6.0"}
|
||||||
azalea-chat = {path = "../azalea-chat", version = "^0.5.0"}
|
azalea-chat = {path = "../azalea-chat", version = "^0.6.0"}
|
||||||
azalea-core = {path = "../azalea-core", version = "^0.5.0", features = ["bevy_ecs"]}
|
azalea-core = {path = "../azalea-core", version = "^0.6.0", features = ["bevy_ecs"]}
|
||||||
azalea-ecs = { version = "0.5.0", path = "../azalea-ecs" }
|
azalea-ecs = {version = "0.6.0", path = "../azalea-ecs"}
|
||||||
azalea-nbt = {path = "../azalea-nbt", version = "^0.5.0"}
|
azalea-nbt = {path = "../azalea-nbt", version = "^0.6.0"}
|
||||||
azalea-registry = {path = "../azalea-registry", version = "^0.5.0"}
|
azalea-registry = {path = "../azalea-registry", version = "^0.6.0"}
|
||||||
derive_more = {version = "0.99.17", features = ["deref", "deref_mut"]}
|
derive_more = {version = "0.99.17", features = ["deref", "deref_mut"]}
|
||||||
enum-as-inner = "0.5.1"
|
enum-as-inner = "0.5.1"
|
||||||
iyes_loopless = "0.9.1"
|
|
||||||
log = "0.4.17"
|
log = "0.4.17"
|
||||||
nohash-hasher = "0.2.0"
|
nohash-hasher = "0.2.0"
|
||||||
once_cell = "1.16.0"
|
once_cell = "1.16.0"
|
||||||
|
|
|
@ -343,20 +343,20 @@ impl Section {
|
||||||
.states
|
.states
|
||||||
.get(pos.x as usize, pos.y as usize, pos.z as usize);
|
.get(pos.x as usize, pos.y as usize, pos.z as usize);
|
||||||
// if there's an unknown block assume it's air
|
// if there's an unknown block assume it's air
|
||||||
BlockState::try_from(state).unwrap_or(BlockState::Air)
|
BlockState::try_from(state).unwrap_or(BlockState::AIR)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_and_set(&mut self, pos: ChunkSectionBlockPos, state: BlockState) -> BlockState {
|
fn get_and_set(&mut self, pos: ChunkSectionBlockPos, state: BlockState) -> BlockState {
|
||||||
let previous_state =
|
let previous_state =
|
||||||
self.states
|
self.states
|
||||||
.get_and_set(pos.x as usize, pos.y as usize, pos.z as usize, state as u32);
|
.get_and_set(pos.x as usize, pos.y as usize, pos.z as usize, state.id);
|
||||||
// if there's an unknown block assume it's air
|
// if there's an unknown block assume it's air
|
||||||
BlockState::try_from(previous_state).unwrap_or(BlockState::Air)
|
BlockState::try_from(previous_state).unwrap_or(BlockState::AIR)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set(&mut self, pos: ChunkSectionBlockPos, state: BlockState) {
|
fn set(&mut self, pos: ChunkSectionBlockPos, state: BlockState) {
|
||||||
self.states
|
self.states
|
||||||
.set(pos.x as usize, pos.y as usize, pos.z as usize, state as u32);
|
.set(pos.x as usize, pos.y as usize, pos.z as usize, state.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
//! Implement things relating to entity datas, like an index of uuids to
|
||||||
|
//! entities.
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
deduplicate_entities, deduplicate_local_entities,
|
deduplicate_entities, deduplicate_local_entities,
|
||||||
entity::{
|
entity::{
|
||||||
|
@ -27,6 +30,8 @@ use std::{
|
||||||
};
|
};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
use super::Local;
|
||||||
|
|
||||||
/// Plugin handling some basic entity functionality.
|
/// Plugin handling some basic entity functionality.
|
||||||
pub struct EntityPlugin;
|
pub struct EntityPlugin;
|
||||||
impl Plugin for EntityPlugin {
|
impl Plugin for EntityPlugin {
|
||||||
|
@ -263,11 +268,6 @@ pub fn add_updates_received(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A marker component that signifies that this entity is "local" and shouldn't
|
|
||||||
/// be updated by other clients.
|
|
||||||
#[derive(Component)]
|
|
||||||
pub struct Local;
|
|
||||||
|
|
||||||
/// The [`UpdatesReceived`] component should never be on [`Local`] entities.
|
/// The [`UpdatesReceived`] component should never be on [`Local`] entities.
|
||||||
/// This warns if an entity has both components.
|
/// This warns if an entity has both components.
|
||||||
fn debug_detect_updates_received_on_local_entities(
|
fn debug_detect_updates_received_on_local_entities(
|
|
@ -2368,7 +2368,7 @@ impl Default for EndermanMetadataBundle {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
carry_state: CarryState(BlockState::Air),
|
carry_state: CarryState(BlockState::AIR),
|
||||||
creepy: Creepy(false),
|
creepy: Creepy(false),
|
||||||
stared_at: StaredAt(false),
|
stared_at: StaredAt(false),
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
pub mod attributes;
|
pub mod attributes;
|
||||||
mod data;
|
mod data;
|
||||||
mod dimensions;
|
mod dimensions;
|
||||||
|
mod info;
|
||||||
pub mod metadata;
|
pub mod metadata;
|
||||||
|
|
||||||
use crate::ChunkStorage;
|
use crate::ChunkStorage;
|
||||||
|
@ -21,6 +22,7 @@ use azalea_ecs::{
|
||||||
pub use data::*;
|
pub use data::*;
|
||||||
use derive_more::{Deref, DerefMut};
|
use derive_more::{Deref, DerefMut};
|
||||||
pub use dimensions::{update_bounding_box, EntityDimensions};
|
pub use dimensions::{update_bounding_box, EntityDimensions};
|
||||||
|
pub use info::{EntityInfos, EntityPlugin, LoadedBy, PartialEntityInfos, RelativeEntityUpdate};
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
@ -92,7 +94,7 @@ pub fn on_pos(offset: f32, chunk_storage: &ChunkStorage, pos: &Position) -> Bloc
|
||||||
// TODO: check if block below is a fence, wall, or fence gate
|
// TODO: check if block below is a fence, wall, or fence gate
|
||||||
let block_pos = pos.down(1);
|
let block_pos = pos.down(1);
|
||||||
let block_state = chunk_storage.get_block_state(&block_pos);
|
let block_state = chunk_storage.get_block_state(&block_pos);
|
||||||
if block_state == Some(BlockState::Air) {
|
if block_state == Some(BlockState::AIR) {
|
||||||
let block_pos_below = block_pos.down(1);
|
let block_pos_below = block_pos.down(1);
|
||||||
let block_state_below = chunk_storage.get_block_state(&block_pos_below);
|
let block_state_below = chunk_storage.get_block_state(&block_pos_below);
|
||||||
if let Some(_block_state_below) = block_state_below {
|
if let Some(_block_state_below) = block_state_below {
|
||||||
|
@ -314,6 +316,11 @@ pub struct PlayerBundle {
|
||||||
pub metadata: metadata::PlayerMetadataBundle,
|
pub metadata: metadata::PlayerMetadataBundle,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A marker component that signifies that this entity is "local" and shouldn't
|
||||||
|
/// be updated by other clients.
|
||||||
|
#[derive(Component)]
|
||||||
|
pub struct Local;
|
||||||
|
|
||||||
// #[cfg(test)]
|
// #[cfg(test)]
|
||||||
// mod tests {
|
// mod tests {
|
||||||
// use super::*;
|
// use super::*;
|
||||||
|
|
|
@ -7,7 +7,6 @@ mod bit_storage;
|
||||||
mod chunk_storage;
|
mod chunk_storage;
|
||||||
mod container;
|
mod container;
|
||||||
pub mod entity;
|
pub mod entity;
|
||||||
mod entity_info;
|
|
||||||
mod palette;
|
mod palette;
|
||||||
mod world;
|
mod world;
|
||||||
|
|
||||||
|
@ -16,9 +15,6 @@ use std::backtrace::Backtrace;
|
||||||
pub use bit_storage::BitStorage;
|
pub use bit_storage::BitStorage;
|
||||||
pub use chunk_storage::{Chunk, ChunkStorage, PartialChunkStorage};
|
pub use chunk_storage::{Chunk, ChunkStorage, PartialChunkStorage};
|
||||||
pub use container::*;
|
pub use container::*;
|
||||||
pub use entity_info::{
|
|
||||||
EntityInfos, EntityPlugin, LoadedBy, Local, PartialEntityInfos, RelativeEntityUpdate,
|
|
||||||
};
|
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
pub use world::*;
|
pub use world::*;
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
entity::{EntityUuid, MinecraftEntityId, WorldName},
|
entity::{
|
||||||
entity_info::LoadedBy,
|
EntityInfos, EntityUuid, LoadedBy, Local, MinecraftEntityId, PartialEntityInfos, WorldName,
|
||||||
ChunkStorage, EntityInfos, Local, PartialChunkStorage, PartialEntityInfos, WorldContainer,
|
},
|
||||||
|
ChunkStorage, PartialChunkStorage, WorldContainer,
|
||||||
};
|
};
|
||||||
use azalea_core::ChunkPos;
|
use azalea_core::ChunkPos;
|
||||||
use azalea_ecs::{
|
use azalea_ecs::{
|
||||||
|
|
|
@ -4,30 +4,29 @@ edition = "2021"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
name = "azalea"
|
name = "azalea"
|
||||||
repository = "https://github.com/mat-1/azalea/tree/main/azalea"
|
repository = "https://github.com/mat-1/azalea/tree/main/azalea"
|
||||||
version = "0.5.0"
|
version = "0.6.0"
|
||||||
|
|
||||||
[package.metadata.release]
|
[package.metadata.release]
|
||||||
pre-release-replacements = [
|
pre-release-replacements = [
|
||||||
{file = "src/lib.rs", search = "//! `azalea = \"[a-z0-9\\.-]+\"`", replace = "//! `azalea = \"{{version}}\"`"},
|
{file = "README.md", search = "`azalea = \"[a-z0-9\\.-]+\"`", replace = "`azalea = \"{{version}}\"`"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "^1.0.65"
|
anyhow = "^1.0.65"
|
||||||
async-trait = "0.1.58"
|
async-trait = "0.1.58"
|
||||||
azalea-block = {version = "0.5.0", path = "../azalea-block"}
|
azalea-block = {version = "0.6.0", path = "../azalea-block"}
|
||||||
azalea-chat = {version = "0.5.0", path = "../azalea-chat"}
|
azalea-chat = {version = "0.6.0", path = "../azalea-chat"}
|
||||||
azalea-client = {version = "0.5.0", path = "../azalea-client"}
|
azalea-client = {version = "0.6.0", path = "../azalea-client"}
|
||||||
azalea-core = {version = "0.5.0", path = "../azalea-core"}
|
azalea-core = {version = "0.6.0", path = "../azalea-core"}
|
||||||
azalea-ecs = { version = "0.5.0", path = "../azalea-ecs" }
|
azalea-ecs = {version = "0.6.0", path = "../azalea-ecs"}
|
||||||
azalea-physics = {version = "0.5.0", path = "../azalea-physics"}
|
azalea-physics = {version = "0.6.0", path = "../azalea-physics"}
|
||||||
azalea-protocol = {version = "0.5.0", path = "../azalea-protocol"}
|
azalea-protocol = {version = "0.6.0", path = "../azalea-protocol"}
|
||||||
azalea-registry = {version = "0.5.0", path = "../azalea-registry"}
|
azalea-registry = {version = "0.6.0", path = "../azalea-registry"}
|
||||||
azalea-world = {version = "0.5.0", path = "../azalea-world"}
|
azalea-world = {version = "0.6.0", path = "../azalea-world"}
|
||||||
bevy_tasks = "0.9.1"
|
bevy_tasks = "0.9.1"
|
||||||
derive_more = {version = "0.99.17", features = ["deref", "deref_mut"]}
|
derive_more = {version = "0.99.17", features = ["deref", "deref_mut"]}
|
||||||
futures = "0.3.25"
|
futures = "0.3.25"
|
||||||
futures-lite = "1.12.0"
|
futures-lite = "1.12.0"
|
||||||
iyes_loopless = "0.9.1"
|
|
||||||
log = "0.4.17"
|
log = "0.4.17"
|
||||||
nohash-hasher = "0.2.0"
|
nohash-hasher = "0.2.0"
|
||||||
num-traits = "0.2.15"
|
num-traits = "0.2.15"
|
||||||
|
|
|
@ -15,7 +15,7 @@ Then, add one of the following lines to your Cargo.toml:
|
||||||
Latest bleeding-edge version:
|
Latest bleeding-edge version:
|
||||||
`azalea = { git="https://github.com/mat-1/azalea" }`\
|
`azalea = { git="https://github.com/mat-1/azalea" }`\
|
||||||
Latest "stable" release:
|
Latest "stable" release:
|
||||||
`azalea = "0.5.0"`
|
`azalea = "0.6.0"`
|
||||||
|
|
||||||
## Optimization
|
## Optimization
|
||||||
|
|
||||||
|
@ -33,7 +33,6 @@ opt-level = 1
|
||||||
opt-level = 3
|
opt-level = 3
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
# Examples
|
# Examples
|
||||||
|
|
||||||
```rust,no_run
|
```rust,no_run
|
||||||
|
@ -49,9 +48,9 @@ async fn main() {
|
||||||
// or Account::microsoft("example@example.com").await.unwrap();
|
// or Account::microsoft("example@example.com").await.unwrap();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let e = azalea::ClientBuilder::new()
|
let e = ClientBuilder::new()
|
||||||
.set_handler(handle)
|
.set_handler(handle)
|
||||||
.start(account, "localhost")
|
.start(account.clone(), "localhost")
|
||||||
.await;
|
.await;
|
||||||
eprintln!("{:?}", e);
|
eprintln!("{:?}", e);
|
||||||
}
|
}
|
||||||
|
@ -72,6 +71,10 @@ async fn handle(bot: Client, event: Event, state: State) -> anyhow::Result<()> {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
# Swarms
|
||||||
|
|
||||||
|
Azalea lets you create "swarms", which are a group of bots in the same world that can perform actions together. See [testbot](https://github.com/mat-1/azalea/blob/main/azalea/examples/testbot.rs) for an example. Also, if you're using swarms, you should also have both `azalea::prelude::*` and `azalea::swarm::prelude::*`.
|
||||||
|
|
||||||
# Plugins
|
# Plugins
|
||||||
|
|
||||||
Azalea uses [Bevy ECS](https://docs.rs/bevy_ecs) internally to store information about the world and clients. Bevy plugins are more powerful than async handler functions, but more difficult to use. See [pathfinder](azalea/src/pathfinder/mod.rs) as an example of how to make a plugin. You can then enable a plugin by adding `.add_plugin(ExamplePlugin)` in your client/swarm builder.
|
Azalea uses [Bevy ECS](https://docs.rs/bevy_ecs) internally to store information about the world and clients. Bevy plugins are more powerful than async handler functions, but more difficult to use. See [pathfinder](azalea/src/pathfinder/mod.rs) as an example of how to make a plugin. You can then enable a plugin by adding `.add_plugin(ExamplePlugin)` in your client/swarm builder.
|
||||||
|
@ -80,4 +83,4 @@ Also note that just because something is an entity in the ECS doesn't mean that
|
||||||
|
|
||||||
See the [Bevy Cheatbook](https://bevy-cheatbook.github.io/programming/ecs-intro.html) to learn more about Bevy ECS (and the ECS paradigm in general).
|
See the [Bevy Cheatbook](https://bevy-cheatbook.github.io/programming/ecs-intro.html) to learn more about Bevy ECS (and the ECS paradigm in general).
|
||||||
|
|
||||||
[`azalea_client`]: https://docs.rs/azalea-client
|
[`azalea_client`]: https://docs.rs/azalea-client
|
||||||
|
|
|
@ -3,7 +3,7 @@ use azalea::prelude::*;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
#[derive(Default, Clone)]
|
#[derive(Default, Clone, Component)]
|
||||||
struct State {
|
struct State {
|
||||||
pub started: Arc<Mutex<bool>>,
|
pub started: Arc<Mutex<bool>>,
|
||||||
}
|
}
|
||||||
|
@ -13,15 +13,11 @@ async fn main() {
|
||||||
let account = Account::offline("bot");
|
let account = Account::offline("bot");
|
||||||
// or let bot = Account::microsoft("email").await;
|
// or let bot = Account::microsoft("email").await;
|
||||||
|
|
||||||
azalea::start(azalea::Options {
|
azalea::ClientBuilder::new()
|
||||||
account,
|
.set_handler(handle)
|
||||||
address: "localhost",
|
.start(account, "localhost")
|
||||||
state: State::default(),
|
.await
|
||||||
plugins: plugins![],
|
.unwrap();
|
||||||
handle,
|
|
||||||
})
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn handle(bot: Client, event: Event, state: State) -> anyhow::Result<()> {
|
async fn handle(bot: Client, event: Event, state: State) -> anyhow::Result<()> {
|
||||||
|
|
|
@ -7,15 +7,11 @@ async fn main() {
|
||||||
let account = Account::offline("bot");
|
let account = Account::offline("bot");
|
||||||
// or let account = Account::microsoft("email").await;
|
// or let account = Account::microsoft("email").await;
|
||||||
|
|
||||||
azalea::start(azalea::Options {
|
ClientBuilder::new()
|
||||||
account,
|
.set_handler(handle)
|
||||||
address: "localhost",
|
.start(account, "localhost")
|
||||||
state: State::default(),
|
.await
|
||||||
plugins: plugins![],
|
.unwrap();
|
||||||
handle,
|
|
||||||
})
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Clone, Component)]
|
#[derive(Default, Clone, Component)]
|
||||||
|
@ -28,7 +24,7 @@ async fn handle(bot: Client, event: Event, _state: State) -> anyhow::Result<()>
|
||||||
if sender == bot.profile.name {
|
if sender == bot.profile.name {
|
||||||
return Ok(()); // ignore our own messages
|
return Ok(()); // ignore our own messages
|
||||||
}
|
}
|
||||||
bot.chat(&content).await?;
|
bot.chat(&content);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
use azalea::{prelude::*, SwarmEvent};
|
use azalea::{prelude::*, swarm::prelude::*};
|
||||||
use azalea::{Account, Client, Event, Swarm};
|
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
|
@ -7,44 +6,29 @@ async fn main() {
|
||||||
let mut states = Vec::new();
|
let mut states = Vec::new();
|
||||||
|
|
||||||
for i in 0..10 {
|
for i in 0..10 {
|
||||||
accounts.push(Account::offline(&format!("bot{o}")));
|
accounts.push(Account::offline(&format!("bot{i}")));
|
||||||
states.push(State::default());
|
states.push(State::default());
|
||||||
}
|
}
|
||||||
|
|
||||||
azalea::start_swarm(azalea::SwarmOptions {
|
let e = SwarmBuilder::new()
|
||||||
accounts,
|
.add_accounts(accounts.clone())
|
||||||
address: "localhost",
|
.set_handler(handle)
|
||||||
|
.set_swarm_handler(swarm_handle)
|
||||||
swarm_state: SwarmState::default(),
|
.start("localhost")
|
||||||
states,
|
.await;
|
||||||
|
|
||||||
swarm_plugins: plugins![],
|
|
||||||
plugins: plugins![],
|
|
||||||
|
|
||||||
handle,
|
|
||||||
swarm_handle,
|
|
||||||
|
|
||||||
join_delay: None,
|
|
||||||
})
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Clone)]
|
#[derive(Default, Clone, Component)]
|
||||||
struct State {}
|
struct State {}
|
||||||
|
|
||||||
#[derive(Default, Clone)]
|
#[derive(Default, Clone, Resource)]
|
||||||
struct SwarmState {}
|
struct SwarmState {}
|
||||||
|
|
||||||
async fn handle(bot: Client, event: Event, state: State) -> anyhow::Result<()> {
|
async fn handle(bot: Client, event: Event, state: State) -> anyhow::Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn swarm_handle(
|
async fn swarm_handle(swarm: Swarm, event: SwarmEvent, state: SwarmState) -> anyhow::Result<()> {
|
||||||
swarm: Swarm<State>,
|
|
||||||
event: SwarmEvent,
|
|
||||||
state: SwarmState,
|
|
||||||
) -> anyhow::Result<()> {
|
|
||||||
match &event {
|
match &event {
|
||||||
SwarmEvent::Login => {
|
SwarmEvent::Login => {
|
||||||
swarm.goto(azalea::BlockPos::new(0, 70, 0)).await;
|
swarm.goto(azalea::BlockPos::new(0, 70, 0)).await;
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
A relatively complex bot for farming potatoes.
|
|
||||||
|
|
||||||
Note: At the moment, all of the code here is only hypothetical. I decided to write this to help me decide how I want some the APIs to look.
|
|
||||||
|
|
||||||
## Attempted
|
|
||||||
- Sync: a sync function is called with the state and bot every time we get an event, and the function can queue events to execute at the end of the tick
|
|
||||||
|
|
||||||
Pros: No .lock().unwrap() necessary, and theoretically pausable by saving the state.
|
|
||||||
|
|
||||||
Cons: Async functions like opening containers and pathfinding are annoying because you have to keep state for them, and the code generally ends up being more confusing.
|
|
||||||
|
|
||||||
- Async non-blocking: an async function is called in a new task with the state mutex and bot every time we get an event
|
|
||||||
|
|
||||||
Pros: Easier to do async stuff like interacting with containers, code is somewhat easier to understand
|
|
||||||
|
|
||||||
Cons: Lock spam everywhere is annoying, and you have to make sure stuff doesn't accidentally run in parallel.
|
|
||||||
|
|
||||||
## Considered:
|
|
||||||
(I didn't actually try this because the problems were apparent)
|
|
||||||
- Async blocking: an async function is called with the state and bot every time we get an event, and only handles the next event when this one finishes running
|
|
||||||
|
|
||||||
Pros: No lock spam
|
|
||||||
|
|
||||||
Cons: Sometimes you want to handle multiple events at once like eating if you get hungry while pathfinding, this makes it harder without increasing complexity
|
|
|
@ -1,31 +0,0 @@
|
||||||
//! Automatically eat when we get hungry.
|
|
||||||
|
|
||||||
use async_trait::async_trait;
|
|
||||||
use azalea::prelude::*;
|
|
||||||
use azalea::{Client, Event};
|
|
||||||
use parking_lot::Mutex;
|
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
#[derive(Default, Clone)]
|
|
||||||
pub struct Plugin {
|
|
||||||
pub state: State,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default, Clone, Component)]
|
|
||||||
pub struct State {}
|
|
||||||
|
|
||||||
#[async_trait]
|
|
||||||
impl azalea::PluginState for Plugin {
|
|
||||||
async fn handle(self: Box<Self>, event: Event, bot: Client) {
|
|
||||||
match event {
|
|
||||||
Event::UpdateHunger => {
|
|
||||||
if !bot.using_held_item() && bot.food_level() <= 17 {
|
|
||||||
if bot.hold(azalea::ItemGroup::Food).await {
|
|
||||||
bot.use_held_item().await;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,69 +0,0 @@
|
||||||
mod autoeat;
|
|
||||||
use azalea::prelude::*;
|
|
||||||
use azalea::{pathfinder, BlockPos, ItemKind, Vec3};
|
|
||||||
|
|
||||||
#[derive(Default, Clone)]
|
|
||||||
struct State {}
|
|
||||||
|
|
||||||
#[tokio::main]
|
|
||||||
async fn main() {
|
|
||||||
env_logger::init();
|
|
||||||
|
|
||||||
let account = Account::offline("bot");
|
|
||||||
|
|
||||||
azalea::start(azalea::Options {
|
|
||||||
account,
|
|
||||||
address: "localhost",
|
|
||||||
state: State::default(),
|
|
||||||
plugins: plugins![autoeat::Plugin, pathfinder::Plugin],
|
|
||||||
handle,
|
|
||||||
})
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn handle(bot: Client, event: Event, state: State) -> anyhow::Result<()> {
|
|
||||||
match event {
|
|
||||||
Event::Login => {
|
|
||||||
goto_farm(bot, state).await?;
|
|
||||||
// after we get to the farm, start farming
|
|
||||||
farm(bot, state).await?;
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
// go to the place where we start farming
|
|
||||||
async fn goto_farm(bot: Client, state: State) -> anyhow::Result<()> {
|
|
||||||
bot.goto(pathfinder::Goals::Near(5, BlockPos::new(0, 70, 0)))
|
|
||||||
.await?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
// go to the chest and deposit everything in our inventory.
|
|
||||||
async fn deposit(bot: &mut Client, state: State) -> anyhow::Result<()> {
|
|
||||||
// first throw away any garbage we might have
|
|
||||||
bot.toss(|item| item.kind != ItemKind::Potato && item.kind != ItemKind::DiamondHoe);
|
|
||||||
|
|
||||||
bot.goto(Vec3::new(0, 70, 0)).await?;
|
|
||||||
let chest = bot
|
|
||||||
.open_container(&bot.world.block_at(BlockPos::new(0, 70, 0)))
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let inventory_potato_count: usize = bot
|
|
||||||
.inventory()
|
|
||||||
.count_total(|item| item.kind == ItemKind::Potato);
|
|
||||||
if inventory_potato_count > 64 {
|
|
||||||
chest
|
|
||||||
.deposit_total_count(
|
|
||||||
|item| item.kind == azalea::ItemKind::Potato,
|
|
||||||
inventory_potato_count - 64,
|
|
||||||
)
|
|
||||||
.await;
|
|
||||||
}
|
|
||||||
chest.close().await;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
|
@ -1,5 +1,9 @@
|
||||||
use azalea::{pathfinder, Account, Client, Event, SwarmEvent};
|
use std::time::Duration;
|
||||||
use azalea::{prelude::*, Swarm};
|
|
||||||
|
use azalea::entity::metadata::Player;
|
||||||
|
use azalea::{pathfinder, Account, Client, Event, GameProfileComponent};
|
||||||
|
use azalea::{prelude::*, swarm::prelude::*};
|
||||||
|
use azalea_ecs::query::With;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
|
@ -11,43 +15,32 @@ async fn main() {
|
||||||
states.push(State::default());
|
states.push(State::default());
|
||||||
}
|
}
|
||||||
|
|
||||||
azalea::start_swarm(azalea::SwarmOptions {
|
SwarmBuilder::new()
|
||||||
accounts,
|
.add_accounts(accounts.clone())
|
||||||
address: "localhost",
|
.set_handler(handle)
|
||||||
|
.set_swarm_handler(swarm_handle)
|
||||||
swarm_state: SwarmState::default(),
|
.join_delay(Duration::from_millis(1000))
|
||||||
states,
|
.start("localhost")
|
||||||
|
.await
|
||||||
swarm_plugins: swarm_plugins![pathfinder::Plugin],
|
.unwrap();
|
||||||
plugins: plugins![],
|
|
||||||
|
|
||||||
handle,
|
|
||||||
swarm_handle,
|
|
||||||
|
|
||||||
join_delay: None,
|
|
||||||
})
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Clone)]
|
#[derive(Component, Default, Clone)]
|
||||||
struct State {}
|
struct State {}
|
||||||
|
|
||||||
#[derive(Default, Clone)]
|
#[derive(Resource, Default, Clone)]
|
||||||
struct SwarmState {}
|
struct SwarmState {}
|
||||||
|
|
||||||
async fn handle(bot: Client, event: Event, state: State) -> anyhow::Result<()> {
|
async fn handle(bot: Client, event: Event, state: State) -> anyhow::Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
async fn swarm_handle(
|
async fn swarm_handle(swarm: Swarm, event: SwarmEvent, state: SwarmState) -> anyhow::Result<()> {
|
||||||
swarm: Swarm<State>,
|
|
||||||
event: SwarmEvent,
|
|
||||||
state: SwarmState,
|
|
||||||
) -> anyhow::Result<()> {
|
|
||||||
match event {
|
match event {
|
||||||
SwarmEvent::Tick => {
|
SwarmEvent::Tick => {
|
||||||
if let Some(target_entity) =
|
if let Some(target_entity) =
|
||||||
swarm.entity_by::<Player>(|name: &Name| name == "Herobrine")
|
swarm.entity_by::<With<Player>>(|profile: &&GameProfileComponent| {
|
||||||
|
profile.name == "Herobrine"
|
||||||
|
})
|
||||||
{
|
{
|
||||||
let target_bounding_box =
|
let target_bounding_box =
|
||||||
swarm.map_entity(target_entity, |bb: &BoundingBox| bb.clone());
|
swarm.map_entity(target_entity, |bb: &BoundingBox| bb.clone());
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
//! mat's bot for testing new azalea features
|
//! a bot for testing new azalea features
|
||||||
|
|
||||||
#![feature(type_alias_impl_trait)]
|
#![feature(type_alias_impl_trait)]
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ use azalea::entity::metadata::Player;
|
||||||
use azalea::entity::Position;
|
use azalea::entity::Position;
|
||||||
use azalea::inventory::InventoryComponent;
|
use azalea::inventory::InventoryComponent;
|
||||||
use azalea::pathfinder::BlockPosGoal;
|
use azalea::pathfinder::BlockPosGoal;
|
||||||
use azalea::{prelude::*, BlockPos, GameProfileComponent, Swarm, SwarmEvent, WalkDirection};
|
use azalea::{prelude::*, swarm::prelude::*, BlockPos, GameProfileComponent, WalkDirection};
|
||||||
use azalea::{Account, Client, Event};
|
use azalea::{Account, Client, Event};
|
||||||
use azalea_protocol::packets::game::serverbound_client_command_packet::ServerboundClientCommandPacket;
|
use azalea_protocol::packets::game::serverbound_client_command_packet::ServerboundClientCommandPacket;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
@ -15,7 +15,7 @@ use std::time::Duration;
|
||||||
#[derive(Default, Clone, Component)]
|
#[derive(Default, Clone, Component)]
|
||||||
struct State {}
|
struct State {}
|
||||||
|
|
||||||
#[derive(Default, Clone, Component)]
|
#[derive(Default, Clone, Resource)]
|
||||||
struct SwarmState {}
|
struct SwarmState {}
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
|
@ -55,7 +55,7 @@ async fn main() -> anyhow::Result<()> {
|
||||||
}
|
}
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let e = azalea::SwarmBuilder::new()
|
let e = SwarmBuilder::new()
|
||||||
.add_accounts(accounts.clone())
|
.add_accounts(accounts.clone())
|
||||||
.set_handler(handle)
|
.set_handler(handle)
|
||||||
.set_swarm_handler(swarm_handle)
|
.set_swarm_handler(swarm_handle)
|
|
@ -9,10 +9,7 @@ use azalea_ecs::{
|
||||||
system::{Commands, Query},
|
system::{Commands, Query},
|
||||||
AppTickExt,
|
AppTickExt,
|
||||||
};
|
};
|
||||||
use azalea_world::{
|
use azalea_world::entity::{metadata::Player, set_rotation, Jumping, Local, Physics, Position};
|
||||||
entity::{metadata::Player, set_rotation, Jumping, Physics, Position},
|
|
||||||
Local,
|
|
||||||
};
|
|
||||||
use std::f64::consts::PI;
|
use std::f64::consts::PI;
|
||||||
|
|
||||||
use crate::pathfinder::PathfinderPlugin;
|
use crate::pathfinder::PathfinderPlugin;
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
mod bot;
|
mod bot;
|
||||||
pub mod pathfinder;
|
pub mod pathfinder;
|
||||||
pub mod prelude;
|
pub mod prelude;
|
||||||
mod swarm;
|
pub mod swarm;
|
||||||
|
|
||||||
pub use azalea_block as blocks;
|
pub use azalea_block as blocks;
|
||||||
pub use azalea_client::*;
|
pub use azalea_client::*;
|
||||||
|
@ -23,7 +23,6 @@ use protocol::{
|
||||||
resolver::{self, ResolverError},
|
resolver::{self, ResolverError},
|
||||||
ServerAddress,
|
ServerAddress,
|
||||||
};
|
};
|
||||||
pub use swarm::*;
|
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use tokio::sync::mpsc;
|
use tokio::sync::mpsc;
|
||||||
|
|
||||||
|
@ -43,10 +42,19 @@ pub enum StartError {
|
||||||
/// making Azalea bots.
|
/// making Azalea bots.
|
||||||
///
|
///
|
||||||
/// ```no_run
|
/// ```no_run
|
||||||
/// azalea::ClientBuilder::new()
|
/// # use azalea::prelude::*;
|
||||||
|
/// # #[tokio::main]
|
||||||
|
/// # async fn main() {
|
||||||
|
/// ClientBuilder::new()
|
||||||
/// .set_handler(handle)
|
/// .set_handler(handle)
|
||||||
/// .start(Account::offline("bot"), "localhost")
|
/// .start(Account::offline("bot"), "localhost")
|
||||||
/// .await;
|
/// .await;
|
||||||
|
/// # }
|
||||||
|
/// # #[derive(Component, Clone, Default)]
|
||||||
|
/// # pub struct State;
|
||||||
|
/// # async fn handle(mut bot: Client, event: Event, state: State) -> anyhow::Result<()> {
|
||||||
|
/// # Ok(())
|
||||||
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
pub struct ClientBuilder<S, Fut>
|
pub struct ClientBuilder<S, Fut>
|
||||||
where
|
where
|
||||||
|
@ -79,9 +87,20 @@ where
|
||||||
/// Set the function that's called every time a bot receives an [`Event`].
|
/// Set the function that's called every time a bot receives an [`Event`].
|
||||||
/// This is the way to handle normal per-bot events.
|
/// This is the way to handle normal per-bot events.
|
||||||
///
|
///
|
||||||
/// You can only have one client handler, calling this again will replace
|
/// You must have exactly one client handler, calling this again will
|
||||||
/// the old client handler function (you can have a client handler and swarm
|
/// replace the old client handler function.
|
||||||
/// handler separately though).
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use azalea::prelude::*;
|
||||||
|
/// # let client_builder = azalea::ClientBuilder::new();
|
||||||
|
/// client_builder.set_handler(handle);
|
||||||
|
///
|
||||||
|
/// # #[derive(Component, Clone, Default)]
|
||||||
|
/// # pub struct State;
|
||||||
|
/// async fn handle(mut bot: Client, event: Event, state: State) -> anyhow::Result<()> {
|
||||||
|
/// Ok(())
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn set_handler(mut self, handler: HandleFn<Fut, S>) -> Self {
|
pub fn set_handler(mut self, handler: HandleFn<Fut, S>) -> Self {
|
||||||
self.handler = Some(handler);
|
self.handler = Some(handler);
|
||||||
|
|
|
@ -17,7 +17,7 @@ use azalea_ecs::{
|
||||||
AppTickExt,
|
AppTickExt,
|
||||||
};
|
};
|
||||||
use azalea_world::entity::metadata::Player;
|
use azalea_world::entity::metadata::Player;
|
||||||
use azalea_world::Local;
|
use azalea_world::entity::Local;
|
||||||
use azalea_world::{
|
use azalea_world::{
|
||||||
entity::{Physics, Position, WorldName},
|
entity::{Physics, Position, WorldName},
|
||||||
WorldContainer,
|
WorldContainer,
|
||||||
|
|
|
@ -165,12 +165,12 @@ mod tests {
|
||||||
);
|
);
|
||||||
partial_world.chunks.set_block_state(
|
partial_world.chunks.set_block_state(
|
||||||
&BlockPos::new(0, 0, 0),
|
&BlockPos::new(0, 0, 0),
|
||||||
BlockState::Stone,
|
azalea_registry::Block::Stone.into(),
|
||||||
&mut chunk_storage,
|
&mut chunk_storage,
|
||||||
);
|
);
|
||||||
partial_world.chunks.set_block_state(
|
partial_world.chunks.set_block_state(
|
||||||
&BlockPos::new(0, 1, 0),
|
&BlockPos::new(0, 1, 0),
|
||||||
BlockState::Air,
|
BlockState::AIR,
|
||||||
&mut chunk_storage,
|
&mut chunk_storage,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -190,12 +190,12 @@ mod tests {
|
||||||
);
|
);
|
||||||
partial_world.chunks.set_block_state(
|
partial_world.chunks.set_block_state(
|
||||||
&BlockPos::new(0, 0, 0),
|
&BlockPos::new(0, 0, 0),
|
||||||
BlockState::Stone,
|
azalea_registry::Block::Stone.into(),
|
||||||
&mut chunk_storage,
|
&mut chunk_storage,
|
||||||
);
|
);
|
||||||
partial_world.chunks.set_block_state(
|
partial_world.chunks.set_block_state(
|
||||||
&BlockPos::new(0, 1, 0),
|
&BlockPos::new(0, 1, 0),
|
||||||
BlockState::Air,
|
BlockState::AIR,
|
||||||
&mut chunk_storage,
|
&mut chunk_storage,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -215,22 +215,22 @@ mod tests {
|
||||||
);
|
);
|
||||||
partial_world.chunks.set_block_state(
|
partial_world.chunks.set_block_state(
|
||||||
&BlockPos::new(0, 0, 0),
|
&BlockPos::new(0, 0, 0),
|
||||||
BlockState::Stone,
|
azalea_registry::Block::Stone.into(),
|
||||||
&mut chunk_storage,
|
&mut chunk_storage,
|
||||||
);
|
);
|
||||||
partial_world.chunks.set_block_state(
|
partial_world.chunks.set_block_state(
|
||||||
&BlockPos::new(0, 1, 0),
|
&BlockPos::new(0, 1, 0),
|
||||||
BlockState::Air,
|
BlockState::AIR,
|
||||||
&mut chunk_storage,
|
&mut chunk_storage,
|
||||||
);
|
);
|
||||||
partial_world.chunks.set_block_state(
|
partial_world.chunks.set_block_state(
|
||||||
&BlockPos::new(0, 2, 0),
|
&BlockPos::new(0, 2, 0),
|
||||||
BlockState::Air,
|
BlockState::AIR,
|
||||||
&mut chunk_storage,
|
&mut chunk_storage,
|
||||||
);
|
);
|
||||||
partial_world.chunks.set_block_state(
|
partial_world.chunks.set_block_state(
|
||||||
&BlockPos::new(0, 3, 0),
|
&BlockPos::new(0, 3, 0),
|
||||||
BlockState::Air,
|
BlockState::AIR,
|
||||||
&mut chunk_storage,
|
&mut chunk_storage,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
//! The Azalea prelude. Things that are necessary for a bare-bones bot are
|
//! The Azalea prelude. Things that are necessary for a bare-bones bot are
|
||||||
//! re-exported here.
|
//! re-exported here.
|
||||||
|
|
||||||
pub use crate::bot::BotClientExt;
|
pub use crate::{bot::BotClientExt, pathfinder::PathfinderClientExt, ClientBuilder};
|
||||||
pub use crate::pathfinder::PathfinderClientExt;
|
|
||||||
pub use azalea_client::{Account, Client, Event};
|
pub use azalea_client::{Account, Client, Event};
|
||||||
pub use azalea_ecs::component::Component;
|
pub use azalea_ecs::{component::Component, system::Resource};
|
||||||
|
|
|
@ -23,7 +23,7 @@ use azalea_ecs::{
|
||||||
};
|
};
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
|
|
||||||
use crate::{Swarm, SwarmEvent};
|
use super::{Swarm, SwarmEvent};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SwarmChatPlugin;
|
pub struct SwarmChatPlugin;
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
mod chat;
|
mod chat;
|
||||||
mod events;
|
mod events;
|
||||||
|
pub mod prelude;
|
||||||
|
|
||||||
use crate::{bot::DefaultBotPlugins, HandleFn};
|
use crate::{bot::DefaultBotPlugins, HandleFn};
|
||||||
use azalea_client::{init_ecs_app, start_ecs, Account, ChatPacket, Client, Event, JoinError};
|
use azalea_client::{init_ecs_app, start_ecs, Account, ChatPacket, Client, Event, JoinError};
|
||||||
|
@ -28,12 +29,10 @@ use tokio::sync::mpsc;
|
||||||
/// A swarm is a way to conveniently control many bots at once, while also
|
/// A swarm is a way to conveniently control many bots at once, while also
|
||||||
/// being able to control bots at an individual level when desired.
|
/// being able to control bots at an individual level when desired.
|
||||||
///
|
///
|
||||||
/// Swarms are created from the [`azalea::start_swarm`] function.
|
/// Swarms are created from [`azalea::swarm::SwarmBuilder`].
|
||||||
///
|
///
|
||||||
/// The `S` type parameter is the type of the state for individual bots.
|
/// The `S` type parameter is the type of the state for individual bots.
|
||||||
/// It's used to make the [`Swarm::add`] function work.
|
/// It's used to make the [`Swarm::add`] function work.
|
||||||
///
|
|
||||||
/// [`azalea::start_swarm`]: fn.start_swarm.html
|
|
||||||
#[derive(Clone, Resource)]
|
#[derive(Clone, Resource)]
|
||||||
pub struct Swarm {
|
pub struct Swarm {
|
||||||
pub ecs_lock: Arc<Mutex<Ecs>>,
|
pub ecs_lock: Arc<Mutex<Ecs>>,
|
||||||
|
@ -84,7 +83,7 @@ where
|
||||||
Fut: Future<Output = Result<(), anyhow::Error>> + Send + 'static,
|
Fut: Future<Output = Result<(), anyhow::Error>> + Send + 'static,
|
||||||
SwarmFut: Future<Output = Result<(), anyhow::Error>> + Send + 'static,
|
SwarmFut: Future<Output = Result<(), anyhow::Error>> + Send + 'static,
|
||||||
S: Default + Send + Sync + Clone + Component + 'static,
|
S: Default + Send + Sync + Clone + Component + 'static,
|
||||||
SS: Default + Send + Sync + Clone + Component + 'static,
|
SS: Default + Send + Sync + Clone + Resource + 'static,
|
||||||
{
|
{
|
||||||
/// Start creating the swarm.
|
/// Start creating the swarm.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
|
@ -138,9 +137,30 @@ where
|
||||||
/// Set the function that's called every time a bot receives an [`Event`].
|
/// Set the function that's called every time a bot receives an [`Event`].
|
||||||
/// This is the way to handle normal per-bot events.
|
/// This is the way to handle normal per-bot events.
|
||||||
///
|
///
|
||||||
/// You can only have one client handler, calling this again will replace
|
/// You must have exactly one client handler and one swarm handler, calling
|
||||||
/// the old client handler function (you can have a client handler and swarm
|
/// this again will replace the old client handler function.
|
||||||
/// handler separately though).
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use azalea::{prelude::*, swarm::prelude::*};
|
||||||
|
/// # let swarm_builder = SwarmBuilder::new().set_swarm_handler(swarm_handle);
|
||||||
|
/// swarm_builder.set_handler(handle);
|
||||||
|
///
|
||||||
|
/// #[derive(Component, Default, Clone)]
|
||||||
|
/// struct State {}
|
||||||
|
/// async fn handle(mut bot: Client, event: Event, state: State) -> anyhow::Result<()> {
|
||||||
|
/// Ok(())
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// # #[derive(Resource, Default, Clone)]
|
||||||
|
/// # struct SwarmState {}
|
||||||
|
/// # async fn swarm_handle(
|
||||||
|
/// # mut swarm: Swarm,
|
||||||
|
/// # event: SwarmEvent,
|
||||||
|
/// # state: SwarmState,
|
||||||
|
/// # ) -> anyhow::Result<()> {
|
||||||
|
/// # Ok(())
|
||||||
|
/// # }
|
||||||
|
/// ```
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn set_handler(mut self, handler: HandleFn<Fut, S>) -> Self {
|
pub fn set_handler(mut self, handler: HandleFn<Fut, S>) -> Self {
|
||||||
self.handler = Some(handler);
|
self.handler = Some(handler);
|
||||||
|
@ -149,9 +169,31 @@ where
|
||||||
/// Set the function that's called every time the swarm receives a
|
/// Set the function that's called every time the swarm receives a
|
||||||
/// [`SwarmEvent`]. This is the way to handle global swarm events.
|
/// [`SwarmEvent`]. This is the way to handle global swarm events.
|
||||||
///
|
///
|
||||||
/// You can only have one swarm handler, calling this again will replace
|
/// You must have exactly one client handler and one swarm handler, calling
|
||||||
/// the old swarm handler function (you can have a client handler and swarm
|
/// this again will replace the old swarm handler function.
|
||||||
/// handler separately though).
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use azalea::{prelude::*, swarm::prelude::*};
|
||||||
|
/// # let swarm_builder = SwarmBuilder::new().set_handler(handle);
|
||||||
|
/// swarm_builder.set_swarm_handler(swarm_handle);
|
||||||
|
///
|
||||||
|
/// # #[derive(Component, Default, Clone)]
|
||||||
|
/// # struct State {}
|
||||||
|
///
|
||||||
|
/// # async fn handle(mut bot: Client, event: Event, state: State) -> anyhow::Result<()> {
|
||||||
|
/// # Ok(())
|
||||||
|
/// # }
|
||||||
|
///
|
||||||
|
/// #[derive(Resource, Default, Clone)]
|
||||||
|
/// struct SwarmState {}
|
||||||
|
/// async fn swarm_handle(
|
||||||
|
/// mut swarm: Swarm,
|
||||||
|
/// event: SwarmEvent,
|
||||||
|
/// state: SwarmState,
|
||||||
|
/// ) -> anyhow::Result<()> {
|
||||||
|
/// Ok(())
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn set_swarm_handler(mut self, handler: SwarmHandleFn<SwarmFut, SS>) -> Self {
|
pub fn set_swarm_handler(mut self, handler: SwarmHandleFn<SwarmFut, SS>) -> Self {
|
||||||
self.swarm_handler = Some(handler);
|
self.swarm_handler = Some(handler);
|
||||||
|
@ -297,7 +339,7 @@ where
|
||||||
Fut: Future<Output = Result<(), anyhow::Error>> + Send + 'static,
|
Fut: Future<Output = Result<(), anyhow::Error>> + Send + 'static,
|
||||||
SwarmFut: Future<Output = Result<(), anyhow::Error>> + Send + 'static,
|
SwarmFut: Future<Output = Result<(), anyhow::Error>> + Send + 'static,
|
||||||
S: Default + Send + Sync + Clone + Component + 'static,
|
S: Default + Send + Sync + Clone + Component + 'static,
|
||||||
SS: Default + Send + Sync + Clone + Component + 'static,
|
SS: Default + Send + Sync + Clone + Resource + 'static,
|
||||||
{
|
{
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self::new()
|
Self::new()
|
||||||
|
@ -339,14 +381,13 @@ pub enum SwarmStartError {
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
/// ```rust,no_run
|
/// ```rust,no_run
|
||||||
/// use azalea::{prelude::*, Swarm, SwarmEvent};
|
/// use azalea::{prelude::*, swarm::prelude::*};
|
||||||
/// use azalea::{Account, Client, Event};
|
|
||||||
/// use std::time::Duration;
|
/// use std::time::Duration;
|
||||||
///
|
///
|
||||||
/// #[derive(Default, Clone)]
|
/// #[derive(Default, Clone, Component)]
|
||||||
/// struct State {}
|
/// struct State {}
|
||||||
///
|
///
|
||||||
/// #[derive(Default, Clone)]
|
/// #[derive(Default, Clone, Resource)]
|
||||||
/// struct SwarmState {}
|
/// struct SwarmState {}
|
||||||
///
|
///
|
||||||
/// #[tokio::main]
|
/// #[tokio::main]
|
||||||
|
@ -360,22 +401,13 @@ pub enum SwarmStartError {
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// loop {
|
/// loop {
|
||||||
/// let e = azalea::start_swarm(azalea::SwarmOptions {
|
/// let e = SwarmBuilder::new()
|
||||||
/// accounts: accounts.clone(),
|
/// .add_accounts(accounts.clone())
|
||||||
/// address: "localhost",
|
/// .set_handler(handle)
|
||||||
///
|
/// .set_swarm_handler(swarm_handle)
|
||||||
/// states: states.clone(),
|
/// .join_delay(Duration::from_millis(1000))
|
||||||
/// swarm_state: SwarmState::default(),
|
/// .start("localhost")
|
||||||
///
|
/// .await;
|
||||||
/// plugins: plugins![],
|
|
||||||
/// swarm_plugins: swarm_plugins![],
|
|
||||||
///
|
|
||||||
/// handle,
|
|
||||||
/// swarm_handle,
|
|
||||||
///
|
|
||||||
/// join_delay: Some(Duration::from_millis(1000)),
|
|
||||||
/// })
|
|
||||||
/// .await;
|
|
||||||
/// println!("{e:?}");
|
/// println!("{e:?}");
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
|
@ -388,7 +420,7 @@ pub enum SwarmStartError {
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// async fn swarm_handle(
|
/// async fn swarm_handle(
|
||||||
/// mut swarm: Swarm<State>,
|
/// mut swarm: Swarm,
|
||||||
/// event: SwarmEvent,
|
/// event: SwarmEvent,
|
||||||
/// _state: SwarmState,
|
/// _state: SwarmState,
|
||||||
/// ) -> anyhow::Result<()> {
|
/// ) -> anyhow::Result<()> {
|
||||||
|
@ -405,16 +437,6 @@ pub enum SwarmStartError {
|
||||||
/// }
|
/// }
|
||||||
/// Ok(())
|
/// Ok(())
|
||||||
/// }
|
/// }
|
||||||
// pub async fn start_swarm<
|
|
||||||
// S: Send + Sync + Clone + 'static,
|
|
||||||
// SS: Send + Sync + Clone + 'static,
|
|
||||||
// A: Send + TryInto<ServerAddress>,
|
|
||||||
// Fut: Future<Output = Result<(), anyhow::Error>> + Send + 'static,
|
|
||||||
// SwarmFut: Future<Output = Result<(), anyhow::Error>> + Send + 'static,
|
|
||||||
// >(
|
|
||||||
// options: SwarmOptions<S, SS, A, Fut, SwarmFut>,
|
|
||||||
// ) -> Result<(), SwarmStartError> {
|
|
||||||
// }
|
|
||||||
|
|
||||||
impl Swarm {
|
impl Swarm {
|
||||||
/// Add a new account to the swarm. You can remove it later by calling
|
/// Add a new account to the swarm. You can remove it later by calling
|
||||||
|
@ -457,7 +479,7 @@ impl Swarm {
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
while let Some(event) = rx.recv().await {
|
while let Some(event) = rx.recv().await {
|
||||||
// we can't handle events here (since we can't copy the handler),
|
// we can't handle events here (since we can't copy the handler),
|
||||||
// they're handled above in start_swarm
|
// they're handled above in SwarmBuilder::start
|
||||||
if let Err(e) = cloned_bots_tx.send((Some(event), cloned_bot.clone())) {
|
if let Err(e) = cloned_bots_tx.send((Some(event), cloned_bot.clone())) {
|
||||||
error!("Error sending event to swarm: {e}");
|
error!("Error sending event to swarm: {e}");
|
||||||
}
|
}
|
||||||
|
@ -505,10 +527,15 @@ impl IntoIterator for Swarm {
|
||||||
/// Iterate over the bots in this swarm.
|
/// Iterate over the bots in this swarm.
|
||||||
///
|
///
|
||||||
/// ```rust,no_run
|
/// ```rust,no_run
|
||||||
|
/// # use azalea::{prelude::*, swarm::prelude::*};
|
||||||
|
/// #[derive(Component, Clone)]
|
||||||
|
/// # pub struct State;
|
||||||
|
/// # fn example(swarm: Swarm) {
|
||||||
/// for bot in swarm {
|
/// for bot in swarm {
|
||||||
/// let state = bot.component::<State>();
|
/// let state = bot.component::<State>();
|
||||||
/// // ...
|
/// // ...
|
||||||
/// }
|
/// }
|
||||||
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
fn into_iter(self) -> Self::IntoIter {
|
fn into_iter(self) -> Self::IntoIter {
|
||||||
self.bots
|
self.bots
|
||||||
|
|
3
azalea/src/swarm/prelude.rs
Normal file
3
azalea/src/swarm/prelude.rs
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
//! A prelude that re-exports common swarm types in Azalea.
|
||||||
|
|
||||||
|
pub use crate::swarm::{Swarm, SwarmBuilder, SwarmEvent};
|
|
@ -367,7 +367,7 @@ impl From<EntityDataValue> for UpdateMetadataError {
|
||||||
elif type_name == 'ItemStack':
|
elif type_name == 'ItemStack':
|
||||||
default = f'Slot::Present({default})' if default != 'Empty' else 'Slot::Empty'
|
default = f'Slot::Present({default})' if default != 'Empty' else 'Slot::Empty'
|
||||||
elif type_name == 'BlockState':
|
elif type_name == 'BlockState':
|
||||||
default = f'{default}' if default != 'Empty' else 'BlockState::Air'
|
default = f'{default}' if default != 'Empty' else 'BlockState::AIR'
|
||||||
elif type_name == 'OptionalFormattedText':
|
elif type_name == 'OptionalFormattedText':
|
||||||
default = f'Some({default})' if default != 'Empty' else 'None'
|
default = f'Some({default})' if default != 'Empty' else 'None'
|
||||||
elif type_name == 'CompoundTag':
|
elif type_name == 'CompoundTag':
|
||||||
|
|
|
@ -7,49 +7,8 @@ REGISTRIES_DIR = get_dir_location('../azalea-registry/src/lib.rs')
|
||||||
|
|
||||||
|
|
||||||
def generate_registries(registries: dict):
|
def generate_registries(registries: dict):
|
||||||
code = []
|
with open(REGISTRIES_DIR, 'r') as f:
|
||||||
|
code = f.read().split('\n')
|
||||||
code.append('''#![doc = include_str!("../README.md")]
|
|
||||||
|
|
||||||
// This file is automatically generated in codegen/lib/code/registry.py
|
|
||||||
|
|
||||||
use azalea_buf::{BufReadError, McBufReadable, McBufVarReadable, McBufVarWritable, McBufWritable};
|
|
||||||
use azalea_registry_macros::registry;
|
|
||||||
use std::io::{Cursor, Write};
|
|
||||||
|
|
||||||
pub trait Registry
|
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
fn from_u32(value: u32) -> Option<Self>;
|
|
||||||
fn to_u32(&self) -> u32;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A registry that might not be present. This is transmitted as a single
|
|
||||||
/// varint in the protocol.
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
|
||||||
pub struct OptionalRegistry<T: Registry>(Option<T>);
|
|
||||||
|
|
||||||
impl<T: Registry> McBufReadable for OptionalRegistry<T> {
|
|
||||||
fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
|
||||||
Ok(OptionalRegistry(match u32::var_read_from(buf)? {
|
|
||||||
0 => None,
|
|
||||||
value => Some(
|
|
||||||
T::from_u32(value - 1)
|
|
||||||
.ok_or(BufReadError::UnexpectedEnumVariant { id: value as i32 })?,
|
|
||||||
),
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl<T: Registry> McBufWritable for OptionalRegistry<T> {
|
|
||||||
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
|
||||||
match &self.0 {
|
|
||||||
None => 0u32.var_write_into(buf),
|
|
||||||
Some(value) => (value.to_u32() + 1).var_write_into(buf),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
''')
|
|
||||||
|
|
||||||
for registry_name, registry in registries.items():
|
for registry_name, registry in registries.items():
|
||||||
# registry!(Block, {
|
# registry!(Block, {
|
||||||
|
@ -64,15 +23,35 @@ impl<T: Registry> McBufWritable for OptionalRegistry<T> {
|
||||||
|
|
||||||
registry_struct_name = to_camel_case(registry_name.split(':')[1])
|
registry_struct_name = to_camel_case(registry_name.split(':')[1])
|
||||||
|
|
||||||
code.append(f'registry!({registry_struct_name}, {{')
|
registry_code = []
|
||||||
|
registry_code.append(f'enum {registry_struct_name} {{')
|
||||||
registry_entries = sorted(
|
registry_entries = sorted(
|
||||||
registry['entries'].items(), key=lambda x: x[1]['protocol_id'])
|
registry['entries'].items(), key=lambda x: x[1]['protocol_id'])
|
||||||
for variant_name, _variant in registry_entries:
|
for variant_name, _variant in registry_entries:
|
||||||
variant_struct_name = to_camel_case(
|
variant_struct_name = to_camel_case(
|
||||||
variant_name.split(':')[1])
|
variant_name.split(':')[1])
|
||||||
code.append(f'\t{variant_struct_name} => "{variant_name}",')
|
registry_code.append(f'\t{variant_struct_name} => "{variant_name}",')
|
||||||
code.append('});')
|
registry_code.append('}')
|
||||||
code.append('')
|
|
||||||
|
# when we find a "registry! {" line, find the next line that starts
|
||||||
|
# with "enum <name>" and replace that until we find a line that's "}"
|
||||||
|
found = False
|
||||||
|
in_registry_macro = False
|
||||||
|
for i, line in enumerate(list(code)):
|
||||||
|
if not in_registry_macro and line == "registry! {":
|
||||||
|
in_registry_macro = True
|
||||||
|
elif in_registry_macro and line == registry_code[0]:
|
||||||
|
# found it, now delete until we get to "}"
|
||||||
|
while code[i] != '}':
|
||||||
|
code.pop(i)
|
||||||
|
code[i] = '\n'.join(registry_code)
|
||||||
|
found = True
|
||||||
|
break
|
||||||
|
if not found:
|
||||||
|
code.append('registry! {')
|
||||||
|
code.append('\n'.join(registry_code))
|
||||||
|
code.append('}')
|
||||||
|
code.append('')
|
||||||
|
|
||||||
with open(REGISTRIES_DIR, 'w') as f:
|
with open(REGISTRIES_DIR, 'w') as f:
|
||||||
f.write('\n'.join(code))
|
f.write('\n'.join(code))
|
||||||
|
|
|
@ -7,8 +7,8 @@ COLLISION_BLOCKS_RS_DIR = get_dir_location(
|
||||||
'../azalea-physics/src/collision/blocks.rs')
|
'../azalea-physics/src/collision/blocks.rs')
|
||||||
|
|
||||||
|
|
||||||
def generate_block_shapes(blocks: dict, shapes: dict, aabbs: dict, block_states_report, block_datas_burger, mappings: Mappings):
|
def generate_block_shapes(blocks_pixlyzer: dict, shapes: dict, aabbs: dict, block_states_report, block_datas_burger, mappings: Mappings):
|
||||||
blocks, shapes = simplify_shapes(blocks, shapes, aabbs)
|
blocks, shapes = simplify_shapes(blocks_pixlyzer, shapes, aabbs)
|
||||||
|
|
||||||
code = generate_block_shapes_code(
|
code = generate_block_shapes_code(
|
||||||
blocks, shapes, block_states_report, block_datas_burger, mappings)
|
blocks, shapes, block_states_report, block_datas_burger, mappings)
|
||||||
|
@ -28,8 +28,7 @@ def simplify_shapes(blocks: dict, shapes: dict, aabbs: dict):
|
||||||
|
|
||||||
used_shape_ids = set()
|
used_shape_ids = set()
|
||||||
# determine the used shape ids
|
# determine the used shape ids
|
||||||
for block_id, block_data in blocks.items():
|
for _block_id, block_data in blocks.items():
|
||||||
block_id = block_id.split(':')[-1]
|
|
||||||
block_shapes = [state.get('collision_shape')
|
block_shapes = [state.get('collision_shape')
|
||||||
for state in block_data['states'].values()]
|
for state in block_data['states'].values()]
|
||||||
for s in block_shapes:
|
for s in block_shapes:
|
||||||
|
@ -73,9 +72,9 @@ def generate_block_shapes_code(blocks: dict, shapes: dict, block_states_report,
|
||||||
for (shape_id, shape) in sorted(shapes.items(), key=lambda shape: int(shape[0])):
|
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 += generate_code_for_shape(shape_id, shape)
|
||||||
|
|
||||||
# BlockState::PurpurStairs_NorthTopStraightTrue => &SHAPE24,
|
# 1..100 | 200..300 => &SHAPE1,
|
||||||
generated_match_inner_code = ''
|
generated_match_inner_code = ''
|
||||||
shape_ids_to_variants = {}
|
shape_ids_to_block_state_ids = {}
|
||||||
for block_id, shape_ids in blocks.items():
|
for block_id, shape_ids in blocks.items():
|
||||||
if isinstance(shape_ids, int):
|
if isinstance(shape_ids, int):
|
||||||
shape_ids = [shape_ids]
|
shape_ids = [shape_ids]
|
||||||
|
@ -83,23 +82,34 @@ def generate_block_shapes_code(blocks: dict, shapes: dict, block_states_report,
|
||||||
block_data_burger = block_datas_burger[block_id]
|
block_data_burger = block_datas_burger[block_id]
|
||||||
|
|
||||||
for possible_state, shape_id in zip(block_report_data['states'], shape_ids):
|
for possible_state, shape_id in zip(block_report_data['states'], shape_ids):
|
||||||
variant_values = []
|
block_state_id = possible_state['id']
|
||||||
for value in tuple(possible_state.get('properties', {}).values()):
|
|
||||||
variant_values.append(to_camel_case(value))
|
|
||||||
|
|
||||||
if variant_values == []:
|
if shape_id not in shape_ids_to_block_state_ids:
|
||||||
variant_name = to_camel_case(block_id)
|
shape_ids_to_block_state_ids[shape_id] = []
|
||||||
else:
|
shape_ids_to_block_state_ids[shape_id].append(block_state_id)
|
||||||
variant_name = f'{to_camel_case(block_id)}_{"".join(variant_values)}'
|
|
||||||
|
|
||||||
if shape_id not in shape_ids_to_variants:
|
|
||||||
shape_ids_to_variants[shape_id] = []
|
|
||||||
shape_ids_to_variants[shape_id].append(
|
|
||||||
f'BlockState::{variant_name}')
|
|
||||||
# shape 1 is the most common so we have a _ => &SHAPE1 at the end
|
# shape 1 is the most common so we have a _ => &SHAPE1 at the end
|
||||||
del shape_ids_to_variants[1]
|
del shape_ids_to_block_state_ids[1]
|
||||||
for shape_id, variants in shape_ids_to_variants.items():
|
for shape_id, block_state_ids in shape_ids_to_block_state_ids.items():
|
||||||
generated_match_inner_code += f'{"|".join(variants)} => &SHAPE{shape_id},\n'
|
|
||||||
|
# convert them into ranges (so like 1|2|3 is 1..=3 instead)
|
||||||
|
block_state_ids_ranges = []
|
||||||
|
range_start_block_state_id = None
|
||||||
|
last_block_state_id = None
|
||||||
|
for block_state_id in sorted(block_state_ids):
|
||||||
|
if range_start_block_state_id is None:
|
||||||
|
range_start_block_state_id = block_state_id
|
||||||
|
|
||||||
|
if last_block_state_id is not None:
|
||||||
|
# check if the range is done
|
||||||
|
if block_state_id - 1 != last_block_state_id:
|
||||||
|
block_state_ids_ranges.append(f'{range_start_block_state_id}..={last_block_state_id}' if range_start_block_state_id != last_block_state_id else str(range_start_block_state_id))
|
||||||
|
range_start_block_state_id = block_state_id
|
||||||
|
|
||||||
|
last_block_state_id = block_state_id
|
||||||
|
|
||||||
|
block_state_ids_ranges.append(f'{range_start_block_state_id}..={last_block_state_id}' if range_start_block_state_id != last_block_state_id else str(range_start_block_state_id))
|
||||||
|
generated_match_inner_code += f'{"|".join(block_state_ids_ranges)} => &SHAPE{shape_id},\n'
|
||||||
|
generated_match_inner_code += '_ => &SHAPE1'
|
||||||
|
|
||||||
return f'''
|
return f'''
|
||||||
//! Autogenerated block collisions for every block
|
//! Autogenerated block collisions for every block
|
||||||
|
@ -123,8 +133,8 @@ pub trait BlockWithShape {{
|
||||||
|
|
||||||
impl BlockWithShape for BlockState {{
|
impl BlockWithShape for BlockState {{
|
||||||
fn shape(&self) -> &'static VoxelShape {{
|
fn shape(&self) -> &'static VoxelShape {{
|
||||||
match self {{
|
match self.id {{
|
||||||
{generated_match_inner_code}_ => &SHAPE1
|
{generated_match_inner_code}
|
||||||
}}
|
}}
|
||||||
}}
|
}}
|
||||||
}}
|
}}
|
||||||
|
|
|
@ -4,6 +4,7 @@ from lib.download import get_server_jar, get_burger, get_client_jar, get_pixlyze
|
||||||
from lib.utils import get_dir_location
|
from lib.utils import get_dir_location
|
||||||
from zipfile import ZipFile
|
from zipfile import ZipFile
|
||||||
import subprocess
|
import subprocess
|
||||||
|
import requests
|
||||||
import json
|
import json
|
||||||
import sys
|
import sys
|
||||||
import re
|
import re
|
||||||
|
@ -114,7 +115,20 @@ def get_pixlyzer_data(version_id: str, category: str):
|
||||||
|
|
||||||
target_dir = get_dir_location(f'downloads/pixlyzer-{version_id}')
|
target_dir = get_dir_location(f'downloads/pixlyzer-{version_id}')
|
||||||
|
|
||||||
if not os.path.exists(get_dir_location(target_dir)):
|
# TODO: right now this False is hard-coded, it should retry with this
|
||||||
|
# enabled if # initially getting the data fails
|
||||||
|
if False or (os.path.exists(target_dir) and not os.path.exists(f'{target_dir}/{category}.min.json')):
|
||||||
|
print('Downloading', category, 'from pixlyzer-data.')
|
||||||
|
data = requests.get(f'https://gitlab.com/Bixilon/pixlyzer-data/-/raw/master/version/{version_id}/{category}.min.json?inline=false').text
|
||||||
|
try:
|
||||||
|
os.mkdir(target_dir)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
with open(f'{target_dir}/{category}.min.json', 'w') as f:
|
||||||
|
f.write(data)
|
||||||
|
return json.loads(data)
|
||||||
|
|
||||||
|
if not os.path.exists(target_dir):
|
||||||
pixlyzer_dir = get_pixlyzer()
|
pixlyzer_dir = get_pixlyzer()
|
||||||
|
|
||||||
# for some reason pixlyzer doesn't work right unless the mvn clean
|
# for some reason pixlyzer doesn't work right unless the mvn clean
|
||||||
|
@ -231,7 +245,6 @@ def get_pixlyzer_data(version_id: str, category: str):
|
||||||
with open(f'{target_dir}/{category}.min.json', 'r') as f:
|
with open(f'{target_dir}/{category}.min.json', 'r') as f:
|
||||||
return json.load(f)
|
return json.load(f)
|
||||||
|
|
||||||
|
|
||||||
def get_file_from_jar(version_id: str, file_dir: str):
|
def get_file_from_jar(version_id: str, file_dir: str):
|
||||||
get_client_jar(version_id)
|
get_client_jar(version_id)
|
||||||
with ZipFile(get_dir_location(f'downloads/client-{version_id}.jar')) as z:
|
with ZipFile(get_dir_location(f'downloads/client-{version_id}.jar')) as z:
|
||||||
|
|
Loading…
Add table
Reference in a new issue