mirror of
https://github.com/italicsjenga/valence.git
synced 2024-12-23 14:31:30 +11:00
Update to 1.19
Authentication is currently broken. Looks like the EncryptionResponse packet changed.
This commit is contained in:
parent
8ad9c8587a
commit
c86b8286ce
250
build/entity.rs
250
build/entity.rs
|
@ -41,9 +41,14 @@ enum Type {
|
|||
Nbt,
|
||||
Particle,
|
||||
VillagerData,
|
||||
Pose,
|
||||
// ==== Specialized ==== //
|
||||
/// Also known as OptVarInt
|
||||
OptEntityId,
|
||||
Pose,
|
||||
CatVariant,
|
||||
FrogVariant,
|
||||
OptGlobalPosition,
|
||||
PaintingVariant,
|
||||
// ==== Specialized ==== //
|
||||
BoatVariant,
|
||||
MainHand,
|
||||
}
|
||||
|
@ -83,8 +88,12 @@ impl Type {
|
|||
Type::Nbt => quote! { nbt::Blob::new() },
|
||||
Type::Particle => quote! { () }, // TODO
|
||||
Type::VillagerData => quote! { VillagerData::default() },
|
||||
Type::Pose => quote! { Pose::default() },
|
||||
Type::OptEntityId => quote! { None },
|
||||
Type::Pose => quote! { Pose::default() },
|
||||
Type::CatVariant => quote! { CatVariant::default() },
|
||||
Type::FrogVariant => quote! { FrogVariant::default() },
|
||||
Type::OptGlobalPosition => quote! { () }, // TODO
|
||||
Type::PaintingVariant => quote! { PaintingVariant::default() },
|
||||
Type::BoatVariant => quote! { BoatVariant::default() },
|
||||
Type::MainHand => quote! { MainHand::default() },
|
||||
}
|
||||
|
@ -110,8 +119,12 @@ impl Type {
|
|||
Type::Nbt => 14,
|
||||
Type::Particle => 15,
|
||||
Type::VillagerData => 16,
|
||||
Type::Pose => 18,
|
||||
Type::OptEntityId => 17,
|
||||
Type::Pose => 18,
|
||||
Type::CatVariant => 19,
|
||||
Type::FrogVariant => 20,
|
||||
Type::OptGlobalPosition => 21,
|
||||
Type::PaintingVariant => 22,
|
||||
Type::BoatVariant => 1,
|
||||
Type::MainHand => 0,
|
||||
}
|
||||
|
@ -225,6 +238,56 @@ const ABSTRACT_ARROW: Class = Class {
|
|||
],
|
||||
};
|
||||
|
||||
const ITEM_FRAME: Class = Class {
|
||||
name: "item_frame",
|
||||
inherit: Some(&BASE_ENTITY),
|
||||
fields: &[
|
||||
Field {
|
||||
name: "item",
|
||||
typ: Type::Slot,
|
||||
},
|
||||
Field {
|
||||
name: "rotation",
|
||||
typ: Type::VarInt(0), // TODO: Direction enum?
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const BOAT: Class = Class {
|
||||
name: "boat",
|
||||
inherit: Some(&BASE_ENTITY),
|
||||
fields: &[
|
||||
Field {
|
||||
name: "last_hit_ticks",
|
||||
typ: Type::VarInt(0),
|
||||
},
|
||||
Field {
|
||||
name: "forward_direction",
|
||||
typ: Type::VarInt(1), // TODO: direction enum?
|
||||
},
|
||||
Field {
|
||||
name: "damage_taken",
|
||||
typ: Type::Float(0.0),
|
||||
},
|
||||
Field {
|
||||
name: "typ",
|
||||
typ: Type::BoatVariant,
|
||||
},
|
||||
Field {
|
||||
name: "left_paddle_turning",
|
||||
typ: Type::Bool(false),
|
||||
},
|
||||
Field {
|
||||
name: "right_paddle_turning",
|
||||
typ: Type::Bool(false),
|
||||
},
|
||||
Field {
|
||||
name: "splash_timer",
|
||||
typ: Type::VarInt(0),
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const LIVING_ENTITY: Class = Class {
|
||||
name: "living_entity",
|
||||
inherit: Some(&BASE_ENTITY),
|
||||
|
@ -566,6 +629,11 @@ const ABSTRACT_MINECART_CONTAINER: Class = Class {
|
|||
};
|
||||
|
||||
const ENTITIES: &[Class] = &[
|
||||
Class {
|
||||
name: "allay",
|
||||
inherit: Some(&PATHFINDER_MOB),
|
||||
fields: &[], // TODO: fields?
|
||||
},
|
||||
Class {
|
||||
// TODO: how is this defined?
|
||||
name: "leash_knot",
|
||||
|
@ -583,11 +651,6 @@ const ENTITIES: &[Class] = &[
|
|||
inherit: None,
|
||||
fields: &[],
|
||||
},
|
||||
Class {
|
||||
name: "painting",
|
||||
inherit: None,
|
||||
fields: &[],
|
||||
},
|
||||
Class {
|
||||
name: "marker",
|
||||
inherit: None,
|
||||
|
@ -717,39 +780,21 @@ const ENTITIES: &[Class] = &[
|
|||
},
|
||||
],
|
||||
},
|
||||
BOAT,
|
||||
Class {
|
||||
name: "boat",
|
||||
inherit: Some(&BASE_ENTITY),
|
||||
fields: &[
|
||||
Field {
|
||||
name: "last_hit_ticks",
|
||||
typ: Type::VarInt(0),
|
||||
},
|
||||
Field {
|
||||
name: "forward_direction",
|
||||
typ: Type::VarInt(1), // TODO: direction enum?
|
||||
},
|
||||
Field {
|
||||
name: "damage_taken",
|
||||
typ: Type::Float(0.0),
|
||||
},
|
||||
Field {
|
||||
name: "typ",
|
||||
typ: Type::BoatVariant,
|
||||
},
|
||||
Field {
|
||||
name: "left_paddle_turning",
|
||||
typ: Type::Bool(false),
|
||||
},
|
||||
Field {
|
||||
name: "right_paddle_turning",
|
||||
typ: Type::Bool(false),
|
||||
},
|
||||
Field {
|
||||
name: "splash_timer",
|
||||
typ: Type::VarInt(0),
|
||||
},
|
||||
],
|
||||
name: "chest_boat",
|
||||
inherit: Some(&BOAT),
|
||||
fields: &[],
|
||||
},
|
||||
Class {
|
||||
name: "tadpole",
|
||||
inherit: Some(&ABSTRACT_FISH),
|
||||
fields: &[],
|
||||
},
|
||||
Class {
|
||||
name: "warden",
|
||||
inherit: Some(&MONSTER),
|
||||
fields: &[], // TODO: warden anger
|
||||
},
|
||||
Class {
|
||||
name: "end_crystal",
|
||||
|
@ -812,34 +857,19 @@ const ENTITIES: &[Class] = &[
|
|||
},
|
||||
],
|
||||
},
|
||||
ITEM_FRAME,
|
||||
Class {
|
||||
name: "item_frame",
|
||||
inherit: Some(&BASE_ENTITY),
|
||||
fields: &[
|
||||
Field {
|
||||
name: "item",
|
||||
typ: Type::Slot,
|
||||
},
|
||||
Field {
|
||||
name: "rotation",
|
||||
typ: Type::VarInt(0), // TODO: Direction enum?
|
||||
},
|
||||
],
|
||||
name: "glow_item_frame",
|
||||
inherit: Some(&ITEM_FRAME),
|
||||
fields: &[],
|
||||
},
|
||||
Class {
|
||||
// TODO: How is glow item frame defined? This is a guess.
|
||||
name: "glow_item_frame",
|
||||
name: "painting",
|
||||
inherit: Some(&BASE_ENTITY),
|
||||
fields: &[
|
||||
Field {
|
||||
name: "item",
|
||||
typ: Type::Slot,
|
||||
},
|
||||
Field {
|
||||
name: "rotation",
|
||||
typ: Type::VarInt(0), // TODO: Direction enum?
|
||||
},
|
||||
],
|
||||
fields: &[Field {
|
||||
name: "variant",
|
||||
typ: Type::PaintingVariant,
|
||||
}],
|
||||
},
|
||||
Class {
|
||||
name: "player",
|
||||
|
@ -905,6 +935,10 @@ const ENTITIES: &[Class] = &[
|
|||
name: "right_shoulder_entity_data",
|
||||
typ: Type::Nbt,
|
||||
},
|
||||
Field {
|
||||
name: "global_position",
|
||||
typ: Type::OptGlobalPosition,
|
||||
}
|
||||
],
|
||||
},
|
||||
Class {
|
||||
|
@ -1187,6 +1221,20 @@ const ENTITIES: &[Class] = &[
|
|||
},
|
||||
],
|
||||
},
|
||||
Class {
|
||||
name: "frog",
|
||||
inherit: Some(&ANIMAL),
|
||||
fields: &[
|
||||
Field {
|
||||
name: "variant",
|
||||
typ: Type::FrogVariant,
|
||||
},
|
||||
Field {
|
||||
name: "tongue_target",
|
||||
typ: Type::VarInt(0),
|
||||
}
|
||||
],
|
||||
},
|
||||
Class {
|
||||
name: "ocelot",
|
||||
inherit: Some(&ANIMAL),
|
||||
|
@ -1339,7 +1387,20 @@ const ENTITIES: &[Class] = &[
|
|||
Class {
|
||||
name: "goat",
|
||||
inherit: Some(&ANIMAL),
|
||||
fields: &[], // TODO: What are the goat fields?
|
||||
fields: &[
|
||||
Field {
|
||||
name: "screaming",
|
||||
typ: Type::Bool(false),
|
||||
},
|
||||
Field {
|
||||
name: "left_horn",
|
||||
typ: Type::Bool(true),
|
||||
},
|
||||
Field {
|
||||
name: "right_horn",
|
||||
typ: Type::Bool(true),
|
||||
}
|
||||
],
|
||||
},
|
||||
Class {
|
||||
name: "strider",
|
||||
|
@ -1365,7 +1426,7 @@ const ENTITIES: &[Class] = &[
|
|||
fields: &[
|
||||
Field {
|
||||
name: "variant",
|
||||
typ: Type::VarInt(1), // TODO: cat variant enum.
|
||||
typ: Type::CatVariant,
|
||||
},
|
||||
Field {
|
||||
name: "lying",
|
||||
|
@ -1849,49 +1910,6 @@ pub fn build() -> anyhow::Result<()> {
|
|||
.map(|c| ident(c.name.to_pascal_case()))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
/*
|
||||
let set_type_arms = entities.iter().map(|&entity| {
|
||||
let entity_name = ident(entity.name.to_pascal_case());
|
||||
|
||||
let mut old_fields = Vec::new();
|
||||
collect_class_fields(entity, &mut old_fields);
|
||||
|
||||
let new_type_arms = entities.iter().map(|&new_entity| {
|
||||
let new_entity_name = ident(new_entity.name.to_pascal_case());
|
||||
|
||||
let mut new_fields = Vec::new();
|
||||
collect_class_fields(new_entity, &mut new_fields);
|
||||
|
||||
let assign_fields = new_fields
|
||||
.iter()
|
||||
.cloned()
|
||||
.filter(|&new_field| old_fields.iter().any(|&f| f.name == new_field.name))
|
||||
.map(|new_field| {
|
||||
let name = ident(new_field.name.to_snake_case());
|
||||
quote! {
|
||||
new.#name = old.#name;
|
||||
}
|
||||
});
|
||||
|
||||
quote! {
|
||||
EntityType::#new_entity_name => {
|
||||
let mut new = #new_entity_name::new();
|
||||
|
||||
#(#assign_fields)*
|
||||
|
||||
*self = Self::#new_entity_name(new);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
quote! {
|
||||
Self::#entity_name(old) => match new_type {
|
||||
#(#new_type_arms)*
|
||||
},
|
||||
}
|
||||
});
|
||||
*/
|
||||
|
||||
let entity_structs = entities.iter().map(|&class| {
|
||||
let mut fields = Vec::new();
|
||||
collect_class_fields(class, &mut fields);
|
||||
|
@ -1918,8 +1936,12 @@ pub fn build() -> anyhow::Result<()> {
|
|||
Type::Nbt => quote! { nbt::Blob },
|
||||
Type::Particle => quote! { () }, // TODO
|
||||
Type::VillagerData => quote! { VillagerData },
|
||||
Type::Pose => quote! { Pose },
|
||||
Type::OptEntityId => quote! { Option<EntityId> },
|
||||
Type::Pose => quote! { Pose },
|
||||
Type::CatVariant => quote! { CatVariant },
|
||||
Type::FrogVariant => quote! { FrogVariant },
|
||||
Type::OptGlobalPosition => quote! { () }, // TODO
|
||||
Type::PaintingVariant => quote! { PaintingVariant },
|
||||
Type::BoatVariant => quote! { BoatVariant },
|
||||
Type::MainHand => quote! { MainHand },
|
||||
};
|
||||
|
@ -2071,8 +2093,12 @@ pub fn build() -> anyhow::Result<()> {
|
|||
},
|
||||
Type::Particle => quote! {}, // TODO
|
||||
Type::VillagerData => standard_getter_setter(quote!(VillagerData)),
|
||||
Type::Pose => standard_getter_setter(quote!(Pose)),
|
||||
Type::OptEntityId => standard_getter_setter(quote!(Option<EntityId>)),
|
||||
Type::Pose => standard_getter_setter(quote!(Pose)),
|
||||
Type::CatVariant => standard_getter_setter(quote!(CatVariant)),
|
||||
Type::FrogVariant => standard_getter_setter(quote!(FrogVariant)),
|
||||
Type::OptGlobalPosition => quote! {}, // TODO
|
||||
Type::PaintingVariant => standard_getter_setter(quote!(PaintingVariant)),
|
||||
Type::BoatVariant => standard_getter_setter(quote!(BoatVariant)),
|
||||
Type::MainHand => standard_getter_setter(quote!(MainHand)),
|
||||
}
|
||||
|
|
27248
data/blocks.json
27248
data/blocks.json
File diff suppressed because it is too large
Load diff
1245
data/entities.json
1245
data/entities.json
File diff suppressed because it is too large
Load diff
|
@ -17,11 +17,11 @@ pub use crate::packets::play::s2c::GameMode;
|
|||
use crate::packets::play::s2c::{
|
||||
Biome as BiomeRegistryBiome, BiomeAdditionsSound, BiomeEffects, BiomeMoodSound, BiomeMusic,
|
||||
BiomeParticle, BiomeParticleOptions, BiomeProperty, BiomeRegistry, ChangeGameState,
|
||||
ChangeGameStateReason, DestroyEntities, DimensionCodec, DimensionType, DimensionTypeRegistry,
|
||||
ChangeGameStateReason, ChatTypeRegistry, DestroyEntities, DimensionType, DimensionTypeRegistry,
|
||||
DimensionTypeRegistryEntry, Disconnect, EntityHeadLook, EntityPosition,
|
||||
EntityPositionAndRotation, EntityRotation, EntityTeleport, EntityVelocity, JoinGame,
|
||||
KeepAliveClientbound, PlayerPositionAndLook, PlayerPositionAndLookFlags, S2cPlayPacket,
|
||||
SpawnPosition, UnloadChunk, UpdateViewDistance, UpdateViewPosition,
|
||||
KeepAliveClientbound, PlayerPositionAndLook, PlayerPositionAndLookFlags, RegistryCodec,
|
||||
S2cPlayPacket, SpawnPosition, UnloadChunk, UpdateViewDistance, UpdateViewPosition,
|
||||
};
|
||||
use crate::protocol::{BoundedInt, Nbt};
|
||||
use crate::server::C2sPacketChannels;
|
||||
|
@ -378,17 +378,21 @@ impl<'a> ClientMut<'a> {
|
|||
.dimensions()
|
||||
.map(|(id, _)| ident!("{LIBRARY_NAMESPACE}:dimension_{}", id.0))
|
||||
.collect(),
|
||||
dimension_codec: Nbt(make_dimension_codec(server)),
|
||||
dimension: Nbt(to_dimension_registry_item(dimension)),
|
||||
registry_codec: Nbt(make_dimension_codec(server)),
|
||||
dimension_type_name: ident!(
|
||||
"{LIBRARY_NAMESPACE}:dimension_type_{}",
|
||||
meta.dimension().0
|
||||
),
|
||||
dimension_name: ident!("{LIBRARY_NAMESPACE}:dimension_{}", meta.dimension().0),
|
||||
hashed_seed: 0,
|
||||
max_players: VarInt(0),
|
||||
view_distance: BoundedInt(VarInt(self.new_max_view_distance as i32)),
|
||||
simulation_distance: VarInt(16),
|
||||
reduced_debug_info: false,
|
||||
enable_respawn_screen: false, // TODO
|
||||
is_debug: false,
|
||||
is_flat: false, // TODO
|
||||
reduced_debug_info: false, // TODO
|
||||
enable_respawn_screen: false,
|
||||
is_debug: false, // TODO
|
||||
is_flat: false,
|
||||
last_death_location: None, // TODO
|
||||
});
|
||||
|
||||
self.teleport(self.position(), self.yaw(), self.pitch());
|
||||
|
@ -688,6 +692,7 @@ impl<'a> ClientMut<'a> {
|
|||
C2sPlayPacket::QueryBlockNbt(_) => {}
|
||||
C2sPlayPacket::SetDifficulty(_) => {}
|
||||
C2sPlayPacket::ChatMessageServerbound(_) => {}
|
||||
C2sPlayPacket::ChatPreview(_) => {}
|
||||
C2sPlayPacket::ClientStatus(_) => {}
|
||||
C2sPlayPacket::ClientSettings(p) => {
|
||||
let old = client.settings.replace(Settings {
|
||||
|
@ -704,7 +709,6 @@ impl<'a> ClientMut<'a> {
|
|||
}
|
||||
C2sPlayPacket::TabCompleteServerbound(_) => {}
|
||||
C2sPlayPacket::ClickWindowButton(_) => {}
|
||||
C2sPlayPacket::ClickWindow(_) => {}
|
||||
C2sPlayPacket::CloseWindow(_) => {}
|
||||
C2sPlayPacket::PluginMessageServerbound(_) => {}
|
||||
C2sPlayPacket::EditBook(_) => {}
|
||||
|
@ -828,7 +832,7 @@ fn send_packet(send_opt: &mut Option<Sender<S2cPlayPacket>>, pkt: impl Into<S2cP
|
|||
}
|
||||
}
|
||||
|
||||
fn make_dimension_codec(server: &Server) -> DimensionCodec {
|
||||
fn make_dimension_codec(server: &Server) -> RegistryCodec {
|
||||
let mut dims = Vec::new();
|
||||
for (id, dim) in server.dimensions() {
|
||||
let id = id.0 as i32;
|
||||
|
@ -854,7 +858,7 @@ fn make_dimension_codec(server: &Server) -> DimensionCodec {
|
|||
biomes.push(to_biome_registry_item(&biome, 0));
|
||||
}
|
||||
|
||||
DimensionCodec {
|
||||
RegistryCodec {
|
||||
dimension_type_registry: DimensionTypeRegistry {
|
||||
typ: ident!("dimension_type"),
|
||||
value: dims,
|
||||
|
@ -863,12 +867,19 @@ fn make_dimension_codec(server: &Server) -> DimensionCodec {
|
|||
typ: ident!("worldgen/biome"),
|
||||
value: biomes,
|
||||
},
|
||||
chat_type_registry: ChatTypeRegistry {
|
||||
typ: ident!("chat_type"),
|
||||
value: Vec::new(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn to_dimension_registry_item(dim: &Dimension) -> DimensionType {
|
||||
DimensionType {
|
||||
piglin_safe: true,
|
||||
has_raids: true,
|
||||
monster_spawn_light_level: 0,
|
||||
monster_spawn_block_light_limit: 0,
|
||||
natural: dim.natural,
|
||||
ambient_light: dim.ambient_light,
|
||||
fixed_time: dim.fixed_time.map(|t| t as i64),
|
||||
|
@ -881,7 +892,6 @@ fn to_dimension_registry_item(dim: &Dimension) -> DimensionType {
|
|||
DimensionEffects::TheNether => ident!("the_nether"),
|
||||
DimensionEffects::TheEnd => ident!("the_end"),
|
||||
},
|
||||
has_raids: true,
|
||||
min_y: dim.min_y,
|
||||
height: dim.height,
|
||||
logical_height: dim.height,
|
||||
|
|
|
@ -51,6 +51,8 @@ pub struct Dimension {
|
|||
// TODO: The following fields should be added if they can affect the
|
||||
// appearance of the dimension to clients.
|
||||
// * infiniburn
|
||||
// * monster_spawn_light_level
|
||||
// * monster_spawn_block_light_level
|
||||
// * respawn_anchor_works
|
||||
// * has_skylight
|
||||
// * bed_works
|
||||
|
|
|
@ -14,8 +14,7 @@ use vek::{Aabb, Vec3};
|
|||
|
||||
use crate::byte_angle::ByteAngle;
|
||||
use crate::packets::play::s2c::{
|
||||
EntityMetadata, S2cPlayPacket, SpawnEntity, SpawnExperienceOrb, SpawnLivingEntity,
|
||||
SpawnPainting, SpawnPlayer,
|
||||
EntityMetadata, S2cPlayPacket, SpawnEntity, SpawnExperienceOrb, SpawnPlayer,
|
||||
};
|
||||
use crate::protocol::RawBytes;
|
||||
use crate::slotmap::{Key, SlotMap};
|
||||
|
@ -306,90 +305,43 @@ impl Entity {
|
|||
}
|
||||
|
||||
pub(crate) fn spawn_packet(&self, this_id: EntityId) -> Option<EntitySpawnPacket> {
|
||||
use EntityMeta::*;
|
||||
match &self.meta {
|
||||
Marker(_) => None,
|
||||
ExperienceOrb(_) => Some(EntitySpawnPacket::SpawnExperienceOrb(SpawnExperienceOrb {
|
||||
EntityMeta::Marker(_) => None,
|
||||
EntityMeta::ExperienceOrb(_) => {
|
||||
Some(EntitySpawnPacket::SpawnExperienceOrb(SpawnExperienceOrb {
|
||||
entity_id: VarInt(this_id.to_network_id()),
|
||||
position: self.new_position,
|
||||
count: 0, // TODO
|
||||
}))
|
||||
}
|
||||
EntityMeta::Player(_) => Some(EntitySpawnPacket::SpawnPlayer(SpawnPlayer {
|
||||
entity_id: VarInt(this_id.to_network_id()),
|
||||
player_uuid: self.uuid,
|
||||
position: self.new_position,
|
||||
count: 0, // TODO
|
||||
yaw: ByteAngle::from_degrees(self.yaw),
|
||||
pitch: ByteAngle::from_degrees(self.pitch),
|
||||
})),
|
||||
Painting(_) => todo!(),
|
||||
Player(_) => todo!(),
|
||||
AreaEffectCloud(_)
|
||||
| Arrow(_)
|
||||
| Boat(_)
|
||||
| DragonFireball(_)
|
||||
| EndCrystal(_)
|
||||
| EvokerFangs(_)
|
||||
| EyeOfEnder(_)
|
||||
| FallingBlock(_)
|
||||
| FireworkRocket(_)
|
||||
| GlowItemFrame(_)
|
||||
| Item(_)
|
||||
| ItemFrame(_)
|
||||
| Fireball(_)
|
||||
| LeashKnot(_)
|
||||
| LightningBolt(_)
|
||||
| LlamaSpit(_)
|
||||
| Minecart(_)
|
||||
| ChestMinecart(_)
|
||||
| CommandBlockMinecart(_)
|
||||
| FurnaceMinecart(_)
|
||||
| HopperMinecart(_)
|
||||
| SpawnerMinecart(_)
|
||||
| TntMinecart(_)
|
||||
| Tnt(_)
|
||||
| ShulkerBullet(_)
|
||||
| SmallFireball(_)
|
||||
| Snowball(_)
|
||||
| SpectralArrow(_)
|
||||
| Egg(_)
|
||||
| EnderPearl(_)
|
||||
| ExperienceBottle(_)
|
||||
| Potion(_)
|
||||
| Trident(_)
|
||||
| WitherSkull(_)
|
||||
| FishingBobber(_) => Some(EntitySpawnPacket::SpawnEntity(SpawnEntity {
|
||||
_ => Some(EntitySpawnPacket::SpawnEntity(SpawnEntity {
|
||||
entity_id: VarInt(this_id.to_network_id()),
|
||||
object_uuid: self.uuid,
|
||||
typ: VarInt(self.typ() as i32),
|
||||
position: self.new_position,
|
||||
pitch: ByteAngle::from_degrees(self.pitch),
|
||||
yaw: ByteAngle::from_degrees(self.yaw),
|
||||
data: 1, // TODO
|
||||
head_yaw: ByteAngle::from_degrees(self.head_yaw),
|
||||
data: VarInt(1), // TODO
|
||||
velocity: velocity_to_packet_units(self.velocity),
|
||||
})),
|
||||
|
||||
ArmorStand(_) | Axolotl(_) | Bat(_) | Bee(_) | Blaze(_) | Cat(_) | CaveSpider(_)
|
||||
| Chicken(_) | Cod(_) | Cow(_) | Creeper(_) | Dolphin(_) | Donkey(_) | Drowned(_)
|
||||
| ElderGuardian(_) | EnderDragon(_) | Enderman(_) | Endermite(_) | Evoker(_)
|
||||
| Fox(_) | Ghast(_) | Giant(_) | GlowSquid(_) | Goat(_) | Guardian(_) | Hoglin(_)
|
||||
| Horse(_) | Husk(_) | Illusioner(_) | IronGolem(_) | Llama(_) | MagmaCube(_)
|
||||
| Mule(_) | Mooshroom(_) | Ocelot(_) | Panda(_) | Parrot(_) | Phantom(_) | Pig(_)
|
||||
| Piglin(_) | PiglinBrute(_) | Pillager(_) | PolarBear(_) | Pufferfish(_)
|
||||
| Rabbit(_) | Ravager(_) | Salmon(_) | Sheep(_) | Shulker(_) | Silverfish(_)
|
||||
| Skeleton(_) | SkeletonHorse(_) | Slime(_) | SnowGolem(_) | Spider(_) | Squid(_)
|
||||
| Stray(_) | Strider(_) | TraderLlama(_) | TropicalFish(_) | Turtle(_) | Vex(_)
|
||||
| Villager(_) | Vindicator(_) | WanderingTrader(_) | Witch(_) | Wither(_)
|
||||
| WitherSkeleton(_) | Wolf(_) | Zoglin(_) | Zombie(_) | ZombieHorse(_)
|
||||
| ZombieVillager(_) | ZombifiedPiglin(_) => {
|
||||
Some(EntitySpawnPacket::SpawnLivingEntity(SpawnLivingEntity {
|
||||
entity_id: VarInt(this_id.to_network_id()),
|
||||
entity_uuid: self.uuid,
|
||||
typ: VarInt(self.typ() as i32),
|
||||
position: self.new_position,
|
||||
yaw: ByteAngle::from_degrees(self.yaw),
|
||||
pitch: ByteAngle::from_degrees(self.pitch),
|
||||
head_yaw: ByteAngle::from_degrees(self.head_yaw),
|
||||
velocity: velocity_to_packet_units(self.velocity),
|
||||
}))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn hitbox(&self) -> Aabb<f64> {
|
||||
let dims = match &self.meta {
|
||||
EntityMeta::Allay(_) => [0.6, 0.35, 0.6],
|
||||
EntityMeta::ChestBoat(_) => [1.375, 0.5625, 1.375],
|
||||
EntityMeta::Frog(_) => [0.5, 0.5, 0.5],
|
||||
EntityMeta::Tadpole(_) => [0.4, 0.3, 0.4],
|
||||
EntityMeta::Warden(_) => [0.9, 2.9, 0.9],
|
||||
EntityMeta::AreaEffectCloud(e) => [
|
||||
e.get_radius() as f64 * 2.0,
|
||||
0.5,
|
||||
|
@ -598,8 +550,6 @@ impl<'a> EntityMut<'a> {
|
|||
pub(crate) enum EntitySpawnPacket {
|
||||
SpawnEntity(SpawnEntity),
|
||||
SpawnExperienceOrb(SpawnExperienceOrb),
|
||||
SpawnLivingEntity(SpawnLivingEntity),
|
||||
SpawnPainting(SpawnPainting),
|
||||
SpawnPlayer(SpawnPlayer),
|
||||
}
|
||||
|
||||
|
@ -608,8 +558,6 @@ impl From<EntitySpawnPacket> for S2cPlayPacket {
|
|||
match pkt {
|
||||
EntitySpawnPacket::SpawnEntity(pkt) => pkt.into(),
|
||||
EntitySpawnPacket::SpawnExperienceOrb(pkt) => pkt.into(),
|
||||
EntitySpawnPacket::SpawnLivingEntity(pkt) => pkt.into(),
|
||||
EntitySpawnPacket::SpawnPainting(pkt) => pkt.into(),
|
||||
EntitySpawnPacket::SpawnPlayer(pkt) => pkt.into(),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,13 +2,8 @@
|
|||
|
||||
use std::io::Write;
|
||||
|
||||
use anyhow::Context;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::block_pos::BlockPos;
|
||||
use crate::protocol::Encode;
|
||||
use crate::var_int::VarInt;
|
||||
use crate::Text;
|
||||
|
||||
#[derive(Clone, Copy, Default, PartialEq, PartialOrd, Debug)]
|
||||
pub struct ArmorStandRotations {
|
||||
|
@ -137,6 +132,12 @@ pub enum Pose {
|
|||
Sneaking,
|
||||
LongJumping,
|
||||
Dying,
|
||||
Croaking,
|
||||
UsingTongue,
|
||||
Roaring,
|
||||
Sniffing,
|
||||
Emerging,
|
||||
Digging,
|
||||
}
|
||||
|
||||
impl Default for Pose {
|
||||
|
@ -191,3 +192,66 @@ impl Encode for BoatVariant {
|
|||
VarInt(*self as i32).encode(w)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
|
||||
pub enum CatVariant {
|
||||
Tabby,
|
||||
Black,
|
||||
Red,
|
||||
Siamese,
|
||||
BritishShorthair,
|
||||
Calico,
|
||||
Persian,
|
||||
Ragdoll,
|
||||
White,
|
||||
Jellie,
|
||||
AllBlack,
|
||||
}
|
||||
|
||||
impl Default for CatVariant {
|
||||
fn default() -> Self {
|
||||
CatVariant::Black
|
||||
}
|
||||
}
|
||||
|
||||
impl Encode for CatVariant {
|
||||
fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> {
|
||||
VarInt(*self as i32).encode(w)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
|
||||
pub enum FrogVariant {
|
||||
Temperate,
|
||||
Warm,
|
||||
Cold,
|
||||
}
|
||||
|
||||
impl Default for FrogVariant {
|
||||
fn default() -> Self {
|
||||
FrogVariant::Temperate
|
||||
}
|
||||
}
|
||||
|
||||
impl Encode for FrogVariant {
|
||||
fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> {
|
||||
VarInt(*self as i32).encode(w)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
|
||||
pub enum PaintingVariant {
|
||||
Default, // TODO
|
||||
}
|
||||
|
||||
impl Default for PaintingVariant {
|
||||
fn default() -> Self {
|
||||
PaintingVariant::Default
|
||||
}
|
||||
}
|
||||
|
||||
impl Encode for PaintingVariant {
|
||||
fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> {
|
||||
VarInt(*self as i32).encode(w)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,9 +47,9 @@ pub use world::{WorldId, WorldMeta, WorldMetaMut, WorldMut, WorldRef, Worlds, Wo
|
|||
pub use {nbt, uuid, vek};
|
||||
|
||||
/// The Minecraft protocol version that this library targets.
|
||||
pub const PROTOCOL_VERSION: i32 = 758;
|
||||
pub const PROTOCOL_VERSION: i32 = 759;
|
||||
/// The name of the Minecraft version that this library targets.
|
||||
pub const VERSION_NAME: &str = "1.18.2";
|
||||
pub const VERSION_NAME: &str = "1.19";
|
||||
|
||||
/// The namespace for this library used internally for namespaced identifiers.
|
||||
const LIBRARY_NAMESPACE: &str = "valence";
|
||||
|
|
310
src/packets.rs
310
src/packets.rs
|
@ -2,7 +2,7 @@
|
|||
//!
|
||||
//! See <https://wiki.vg/Protocol> for up to date protocol information.
|
||||
|
||||
#![allow(dead_code)] // TODO: remove this
|
||||
#![allow(dead_code)]
|
||||
|
||||
use std::fmt;
|
||||
use std::io::{Read, Write};
|
||||
|
@ -409,6 +409,7 @@ pub mod login {
|
|||
LoginSuccess 0x02 {
|
||||
uuid: Uuid,
|
||||
username: BoundedString<3, 16>,
|
||||
null_byte: u8, // TODO: Why is this needed?
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -425,6 +426,15 @@ pub mod login {
|
|||
def_struct! {
|
||||
LoginStart 0x00 {
|
||||
username: BoundedString<3, 16>,
|
||||
sig_data: Option<LoginStartSignatureData>,
|
||||
}
|
||||
}
|
||||
|
||||
def_struct! {
|
||||
LoginStartSignatureData {
|
||||
timestamp: i64,
|
||||
public_key: Vec<u8>,
|
||||
signature: Vec<u8>,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -450,7 +460,8 @@ pub mod play {
|
|||
position: Vec3<f64>,
|
||||
pitch: ByteAngle,
|
||||
yaw: ByteAngle,
|
||||
data: i32,
|
||||
head_yaw: ByteAngle,
|
||||
data: VarInt,
|
||||
velocity: Vec3<i16>,
|
||||
}
|
||||
}
|
||||
|
@ -463,29 +474,6 @@ pub mod play {
|
|||
}
|
||||
}
|
||||
|
||||
def_struct! {
|
||||
SpawnLivingEntity 0x02 {
|
||||
entity_id: VarInt,
|
||||
entity_uuid: Uuid,
|
||||
typ: VarInt,
|
||||
position: Vec3<f64>,
|
||||
yaw: ByteAngle,
|
||||
pitch: ByteAngle,
|
||||
head_yaw: ByteAngle,
|
||||
velocity: Vec3<i16>,
|
||||
}
|
||||
}
|
||||
|
||||
def_struct! {
|
||||
SpawnPainting 0x03 {
|
||||
entity_id: VarInt,
|
||||
entity_uuid: Uuid,
|
||||
variant: VarInt, // TODO: painting ID enum
|
||||
location: BlockPos,
|
||||
direction: PaintingDirection,
|
||||
}
|
||||
}
|
||||
|
||||
def_enum! {
|
||||
PaintingDirection: u8 {
|
||||
South = 0,
|
||||
|
@ -496,7 +484,7 @@ pub mod play {
|
|||
}
|
||||
|
||||
def_struct! {
|
||||
SpawnPlayer 0x04 {
|
||||
SpawnPlayer 0x02 {
|
||||
entity_id: VarInt,
|
||||
player_uuid: Uuid,
|
||||
position: Vec3<f64>,
|
||||
|
@ -506,16 +494,7 @@ pub mod play {
|
|||
}
|
||||
|
||||
def_struct! {
|
||||
SculkVibrationSignal 0x05 {
|
||||
source_position: BlockPos,
|
||||
destination_identifier: Ident, // TODO: destination codec type?
|
||||
destination: BlockPos, // TODO: this type varies depending on destination_identifier
|
||||
arrival_ticks: VarInt,
|
||||
}
|
||||
}
|
||||
|
||||
def_struct! {
|
||||
EntityAnimation 0x06 {
|
||||
EntityAnimation 0x03 {
|
||||
entity_id: VarInt,
|
||||
animation: Animation,
|
||||
}
|
||||
|
@ -533,16 +512,13 @@ pub mod play {
|
|||
}
|
||||
|
||||
def_struct! {
|
||||
AcknoledgePlayerDigging 0x08 {
|
||||
location: BlockPos,
|
||||
block: VarInt, // TODO: block state ID type.
|
||||
status: VarInt, // TODO: VarInt enum here.
|
||||
sucessful: bool,
|
||||
AcknoledgeBlockChanges 0x05 {
|
||||
sequence: VarInt,
|
||||
}
|
||||
}
|
||||
|
||||
def_struct! {
|
||||
BlockBreakAnimation 0x09 {
|
||||
BlockBreakAnimation 0x06 {
|
||||
entity_id: VarInt,
|
||||
location: BlockPos,
|
||||
destroy_stage: BoundedInt<u8, 0, 10>,
|
||||
|
@ -550,7 +526,7 @@ pub mod play {
|
|||
}
|
||||
|
||||
def_struct! {
|
||||
BlockEntityData 0x0a {
|
||||
BlockEntityData 0x07 {
|
||||
location: BlockPos,
|
||||
typ: VarInt, // TODO: use enum here
|
||||
data: nbt::Blob,
|
||||
|
@ -558,23 +534,24 @@ pub mod play {
|
|||
}
|
||||
|
||||
def_struct! {
|
||||
BlockAction 0x0b {
|
||||
BlockAction 0x08 {
|
||||
location: BlockPos,
|
||||
action_id: u8,
|
||||
action_param: u8,
|
||||
block_type: VarInt,
|
||||
// TODO: sequence?
|
||||
}
|
||||
}
|
||||
|
||||
def_struct! {
|
||||
BlockChange 0x0c {
|
||||
BlockChange 0x09 {
|
||||
location: BlockPos,
|
||||
block_id: VarInt,
|
||||
}
|
||||
}
|
||||
|
||||
def_struct! {
|
||||
BossBar 0x0d {
|
||||
BossBar 0x0a {
|
||||
uuid: Uuid,
|
||||
action: BossBarAction,
|
||||
}
|
||||
|
@ -583,6 +560,7 @@ pub mod play {
|
|||
def_enum! {
|
||||
BossBarAction: VarInt {
|
||||
Add: BossBarActionAdd = 0,
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -620,7 +598,7 @@ pub mod play {
|
|||
}
|
||||
|
||||
def_struct! {
|
||||
ServerDifficulty 0x0e {
|
||||
ServerDifficulty 0x0b {
|
||||
difficulty: Difficulty,
|
||||
locked: bool,
|
||||
}
|
||||
|
@ -636,29 +614,35 @@ pub mod play {
|
|||
}
|
||||
|
||||
def_struct! {
|
||||
ChatMessageClientbound 0x0f {
|
||||
ChatMessageClientbound 0x30 {
|
||||
message: Text,
|
||||
position: ChatMessagePosition,
|
||||
typ: ChatMessageType,
|
||||
sender: Uuid,
|
||||
// TODO more fields
|
||||
}
|
||||
}
|
||||
|
||||
def_enum! {
|
||||
ChatMessagePosition: u8 {
|
||||
ChatMessageType: VarInt {
|
||||
Chat = 0,
|
||||
SystemMessage = 1,
|
||||
GameInfo = 2,
|
||||
SayCommand = 3,
|
||||
MsgCommand = 4,
|
||||
TeamMsgCommand = 5,
|
||||
EmoteCommand = 6,
|
||||
TellrawCommand = 7,
|
||||
}
|
||||
}
|
||||
|
||||
def_struct! {
|
||||
ClearTitles 0x10 {
|
||||
ClearTitles 0x0d {
|
||||
reset: bool,
|
||||
}
|
||||
}
|
||||
|
||||
def_struct! {
|
||||
TabComplete 0x11 {
|
||||
TabComplete 0x0e {
|
||||
id: VarInt,
|
||||
start: VarInt,
|
||||
length: VarInt,
|
||||
|
@ -681,7 +665,7 @@ pub mod play {
|
|||
}
|
||||
|
||||
def_struct! {
|
||||
WindowProperty 0x15 {
|
||||
WindowProperty 0x12 {
|
||||
// TODO: use enums
|
||||
window_id: u8,
|
||||
property: i16,
|
||||
|
@ -690,20 +674,20 @@ pub mod play {
|
|||
}
|
||||
|
||||
def_struct! {
|
||||
SetCooldown 0x17 {
|
||||
SetCooldown 0x14 {
|
||||
item_id: VarInt,
|
||||
cooldown_ticks: VarInt,
|
||||
}
|
||||
}
|
||||
|
||||
def_struct! {
|
||||
Disconnect 0x1a {
|
||||
Disconnect 0x17 {
|
||||
reason: Text,
|
||||
}
|
||||
}
|
||||
|
||||
def_struct! {
|
||||
EntityStatus 0x1b {
|
||||
EntityStatus 0x18 {
|
||||
entity_id: i32,
|
||||
/// TODO: enum
|
||||
entity_status: u8,
|
||||
|
@ -711,14 +695,14 @@ pub mod play {
|
|||
}
|
||||
|
||||
def_struct! {
|
||||
UnloadChunk 0x1d {
|
||||
UnloadChunk 0x1a {
|
||||
chunk_x: i32,
|
||||
chunk_z: i32
|
||||
}
|
||||
}
|
||||
|
||||
def_struct! {
|
||||
ChangeGameState 0x1e {
|
||||
ChangeGameState 0x1b {
|
||||
reason: ChangeGameStateReason,
|
||||
value: f32,
|
||||
}
|
||||
|
@ -742,7 +726,7 @@ pub mod play {
|
|||
}
|
||||
|
||||
def_struct! {
|
||||
OpenHorseWindow 0x1f {
|
||||
OpenHorseWindow 0x1c {
|
||||
window_id: u8,
|
||||
slot_count: VarInt,
|
||||
entity_id: i32,
|
||||
|
@ -750,7 +734,7 @@ pub mod play {
|
|||
}
|
||||
|
||||
def_struct! {
|
||||
InitializeWorldBorder 0x20 {
|
||||
InitializeWorldBorder 0x1d {
|
||||
x: f64,
|
||||
z: f64,
|
||||
old_diameter: f64,
|
||||
|
@ -763,13 +747,13 @@ pub mod play {
|
|||
}
|
||||
|
||||
def_struct! {
|
||||
KeepAliveClientbound 0x21 {
|
||||
KeepAliveClientbound 0x1e {
|
||||
id: i64,
|
||||
}
|
||||
}
|
||||
|
||||
def_struct! {
|
||||
ChunkDataAndUpdateLight 0x22 {
|
||||
ChunkDataAndUpdateLight 0x1f {
|
||||
chunk_x: i32,
|
||||
chunk_z: i32,
|
||||
heightmaps: Nbt<ChunkDataHeightmaps>,
|
||||
|
@ -801,19 +785,17 @@ pub mod play {
|
|||
}
|
||||
|
||||
def_struct! {
|
||||
JoinGame 0x26 {
|
||||
JoinGame 0x23 {
|
||||
/// Entity ID of the joining player
|
||||
entity_id: i32,
|
||||
is_hardcore: bool,
|
||||
gamemode: GameMode,
|
||||
/// The previous gamemode for the purpose of the F3+F4 gamemode switcher. (TODO: verify)
|
||||
/// Is `-1` if there was no previous gamemode.
|
||||
previous_gamemode: GameMode,
|
||||
dimension_names: Vec<Ident>,
|
||||
dimension_codec: Nbt<DimensionCodec>,
|
||||
/// The specification of the dimension being spawned into.
|
||||
dimension: Nbt<DimensionType>,
|
||||
/// The identifier of the dimension being spawned into.
|
||||
registry_codec: Nbt<RegistryCodec>,
|
||||
/// The name of the dimension type being spawned into.
|
||||
dimension_type_name: Ident,
|
||||
/// The name of the dimension being spawned into.
|
||||
dimension_name: Ident,
|
||||
/// Hash of the world's seed used for client biome noise.
|
||||
hashed_seed: i64,
|
||||
|
@ -829,15 +811,18 @@ pub mod play {
|
|||
/// If this is a superflat world.
|
||||
/// Superflat worlds have different void fog and horizon levels.
|
||||
is_flat: bool,
|
||||
last_death_location: Option<(Ident, BlockPos)>,
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct DimensionCodec {
|
||||
pub struct RegistryCodec {
|
||||
#[serde(rename = "minecraft:dimension_type")]
|
||||
pub dimension_type_registry: DimensionTypeRegistry,
|
||||
#[serde(rename = "minecraft:worldgen/biome")]
|
||||
pub biome_registry: BiomeRegistry,
|
||||
#[serde(rename = "minecraft:chat_type")]
|
||||
pub chat_type_registry: ChatTypeRegistry,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
|
@ -857,6 +842,9 @@ pub mod play {
|
|||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct DimensionType {
|
||||
pub piglin_safe: bool,
|
||||
pub has_raids: bool,
|
||||
pub monster_spawn_light_level: i32,
|
||||
pub monster_spawn_block_light_limit: i32,
|
||||
pub natural: bool,
|
||||
pub ambient_light: f32,
|
||||
pub fixed_time: Option<i64>,
|
||||
|
@ -865,7 +853,6 @@ pub mod play {
|
|||
pub has_skylight: bool,
|
||||
pub bed_works: bool,
|
||||
pub effects: Ident,
|
||||
pub has_raids: bool,
|
||||
pub min_y: i32,
|
||||
pub height: i32,
|
||||
pub logical_height: i32,
|
||||
|
@ -950,6 +937,18 @@ pub mod play {
|
|||
pub typ: Ident,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct ChatTypeRegistry {
|
||||
#[serde(rename = "type")]
|
||||
pub typ: Ident,
|
||||
pub value: Vec<ChatTypeRegistryEntry>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct ChatTypeRegistryEntry {
|
||||
// TODO
|
||||
}
|
||||
|
||||
def_enum! {
|
||||
#[derive(Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
GameMode: u8 {
|
||||
|
@ -967,7 +966,7 @@ pub mod play {
|
|||
}
|
||||
|
||||
def_struct! {
|
||||
EntityPosition 0x29 {
|
||||
EntityPosition 0x26 {
|
||||
entity_id: VarInt,
|
||||
delta: Vec3<i16>,
|
||||
on_ground: bool,
|
||||
|
@ -975,7 +974,7 @@ pub mod play {
|
|||
}
|
||||
|
||||
def_struct! {
|
||||
EntityPositionAndRotation 0x2a {
|
||||
EntityPositionAndRotation 0x27 {
|
||||
entity_id: VarInt,
|
||||
delta: Vec3<i16>,
|
||||
yaw: ByteAngle,
|
||||
|
@ -985,7 +984,7 @@ pub mod play {
|
|||
}
|
||||
|
||||
def_struct! {
|
||||
EntityRotation 0x2b {
|
||||
EntityRotation 0x28 {
|
||||
entity_id: VarInt,
|
||||
yaw: ByteAngle,
|
||||
pitch: ByteAngle,
|
||||
|
@ -994,7 +993,7 @@ pub mod play {
|
|||
}
|
||||
|
||||
def_struct! {
|
||||
PlayerPositionAndLook 0x38 {
|
||||
PlayerPositionAndLook 0x36 {
|
||||
position: Vec3<f64>,
|
||||
yaw: f32,
|
||||
pitch: f32,
|
||||
|
@ -1015,20 +1014,20 @@ pub mod play {
|
|||
}
|
||||
|
||||
def_struct! {
|
||||
DestroyEntities 0x3a {
|
||||
DestroyEntities 0x38 {
|
||||
entities: Vec<VarInt>,
|
||||
}
|
||||
}
|
||||
|
||||
def_struct! {
|
||||
EntityHeadLook 0x3e {
|
||||
EntityHeadLook 0x3c {
|
||||
entity_id: VarInt,
|
||||
head_yaw: ByteAngle,
|
||||
}
|
||||
}
|
||||
|
||||
def_struct! {
|
||||
MultiBlockChange 0x3f {
|
||||
MultiBlockChange 0x3d {
|
||||
chunk_section_position: u64,
|
||||
invert_trust_edges: bool,
|
||||
blocks: Vec<u64>,
|
||||
|
@ -1036,26 +1035,26 @@ pub mod play {
|
|||
}
|
||||
|
||||
def_struct! {
|
||||
HeldItemChangeClientbound 0x48 {
|
||||
HeldItemChangeClientbound 0x47 {
|
||||
slot: BoundedInt<u8, 0, 9>,
|
||||
}
|
||||
}
|
||||
|
||||
def_struct! {
|
||||
UpdateViewPosition 0x49 {
|
||||
UpdateViewPosition 0x48 {
|
||||
chunk_x: VarInt,
|
||||
chunk_z: VarInt,
|
||||
}
|
||||
}
|
||||
|
||||
def_struct! {
|
||||
UpdateViewDistance 0x4a {
|
||||
UpdateViewDistance 0x49 {
|
||||
view_distance: BoundedInt<VarInt, 2, 32>,
|
||||
}
|
||||
}
|
||||
|
||||
def_struct! {
|
||||
SpawnPosition 0x4b {
|
||||
SpawnPosition 0x4a {
|
||||
location: BlockPos,
|
||||
angle: f32,
|
||||
}
|
||||
|
@ -1087,7 +1086,7 @@ pub mod play {
|
|||
}
|
||||
|
||||
def_struct! {
|
||||
EntityTeleport 0x62 {
|
||||
EntityTeleport 0x63 {
|
||||
entity_id: VarInt,
|
||||
position: Vec3<f64>,
|
||||
yaw: ByteAngle,
|
||||
|
@ -1156,12 +1155,9 @@ pub mod play {
|
|||
def_s2c_play_packet_enum! {
|
||||
SpawnEntity,
|
||||
SpawnExperienceOrb,
|
||||
SpawnLivingEntity,
|
||||
SpawnPainting,
|
||||
SpawnPlayer,
|
||||
SculkVibrationSignal,
|
||||
EntityAnimation,
|
||||
AcknoledgePlayerDigging,
|
||||
AcknoledgeBlockChanges,
|
||||
BlockBreakAnimation,
|
||||
BlockEntityData,
|
||||
BlockAction,
|
||||
|
@ -1218,13 +1214,28 @@ pub mod play {
|
|||
}
|
||||
|
||||
def_struct! {
|
||||
ChatMessageServerbound 0x03 {
|
||||
ChatCommand 0x03 {
|
||||
command: String, // TODO: bounded?
|
||||
// TODO: timestamp, arg signatures
|
||||
signed_preview: bool,
|
||||
}
|
||||
}
|
||||
|
||||
def_struct! {
|
||||
ChatMessageServerbound 0x04 {
|
||||
message: BoundedString<0, 256>
|
||||
}
|
||||
}
|
||||
|
||||
def_struct! {
|
||||
ChatPreview 0x05 {
|
||||
query: i32, // TODO: is this an i32 or a varint?
|
||||
message: BoundedString<0, 256>,
|
||||
}
|
||||
}
|
||||
|
||||
def_enum! {
|
||||
ClientStatus 0x04: VarInt {
|
||||
ClientStatus 0x06: VarInt {
|
||||
/// Sent when ready to complete login and ready to respawn after death.
|
||||
PerformRespawn = 0,
|
||||
/// Sent when the statistics menu is opened.
|
||||
|
@ -1233,7 +1244,7 @@ pub mod play {
|
|||
}
|
||||
|
||||
def_struct! {
|
||||
ClientSettings 0x05 {
|
||||
ClientSettings 0x07 {
|
||||
/// e.g. en_US
|
||||
locale: BoundedString<0, 16>,
|
||||
/// Client-side render distance in chunks.
|
||||
|
@ -1279,7 +1290,7 @@ pub mod play {
|
|||
}
|
||||
|
||||
def_struct! {
|
||||
TabCompleteServerbound 0x06 {
|
||||
TabCompleteServerbound 0x08 {
|
||||
transaction_id: VarInt,
|
||||
/// Text behind the cursor without the '/'.
|
||||
text: BoundedString<0, 32500>
|
||||
|
@ -1287,60 +1298,42 @@ pub mod play {
|
|||
}
|
||||
|
||||
def_struct! {
|
||||
ClickWindowButton 0x07 {
|
||||
ClickWindowButton 0x09 {
|
||||
window_id: i8,
|
||||
button_id: i8,
|
||||
}
|
||||
}
|
||||
|
||||
def_struct! {
|
||||
ClickWindow 0x08 {
|
||||
window_id: u8,
|
||||
state_id: VarInt,
|
||||
slot: i16,
|
||||
button: i8,
|
||||
mode: VarInt, // TODO: enum
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
||||
def_struct! {
|
||||
CloseWindow 0x09 {
|
||||
CloseWindow 0x0b {
|
||||
window_id: u8,
|
||||
}
|
||||
}
|
||||
|
||||
def_struct! {
|
||||
PluginMessageServerbound 0x0a {
|
||||
PluginMessageServerbound 0x0c {
|
||||
channel: Ident,
|
||||
data: RawBytes,
|
||||
}
|
||||
}
|
||||
|
||||
def_struct! {
|
||||
EditBook 0x0b {
|
||||
hand: Hand,
|
||||
EditBook 0x0d {
|
||||
slot: VarInt,
|
||||
entries: Vec<String>,
|
||||
title: Option<String>,
|
||||
}
|
||||
}
|
||||
|
||||
def_enum! {
|
||||
Hand: VarInt {
|
||||
Main = 0,
|
||||
Off = 1,
|
||||
}
|
||||
}
|
||||
|
||||
def_struct! {
|
||||
QueryEntityNbt 0x0c {
|
||||
QueryEntityNbt 0x0e {
|
||||
transaction_id: VarInt,
|
||||
entity_id: VarInt,
|
||||
}
|
||||
}
|
||||
|
||||
def_struct! {
|
||||
InteractEntity 0x0d {
|
||||
InteractEntity 0x0f {
|
||||
entity_id: VarInt,
|
||||
typ: InteractType,
|
||||
sneaking: bool,
|
||||
|
@ -1362,8 +1355,15 @@ pub mod play {
|
|||
}
|
||||
}
|
||||
|
||||
def_enum! {
|
||||
Hand: VarInt {
|
||||
Main = 0,
|
||||
Off = 1,
|
||||
}
|
||||
}
|
||||
|
||||
def_struct! {
|
||||
GenerateStructure 0x0e {
|
||||
GenerateStructure 0x10 {
|
||||
location: BlockPos,
|
||||
levels: VarInt,
|
||||
keep_jigsaws: bool,
|
||||
|
@ -1371,26 +1371,26 @@ pub mod play {
|
|||
}
|
||||
|
||||
def_struct! {
|
||||
KeepAliveServerbound 0x0f {
|
||||
KeepAliveServerbound 0x11 {
|
||||
id: i64,
|
||||
}
|
||||
}
|
||||
|
||||
def_struct! {
|
||||
LockDifficulty 0x10 {
|
||||
LockDifficulty 0x12 {
|
||||
locked: bool
|
||||
}
|
||||
}
|
||||
|
||||
def_struct! {
|
||||
PlayerPosition 0x11 {
|
||||
PlayerPosition 0x13 {
|
||||
position: Vec3<f64>,
|
||||
on_ground: bool,
|
||||
}
|
||||
}
|
||||
|
||||
def_struct! {
|
||||
PlayerPositionAndRotation 0x12 {
|
||||
PlayerPositionAndRotation 0x14 {
|
||||
// Absolute position
|
||||
position: Vec3<f64>,
|
||||
/// Absolute rotation on X axis in degrees.
|
||||
|
@ -1402,7 +1402,7 @@ pub mod play {
|
|||
}
|
||||
|
||||
def_struct! {
|
||||
PlayerRotation 0x13 {
|
||||
PlayerRotation 0x15 {
|
||||
/// Absolute rotation on X axis in degrees.
|
||||
yaw: f32,
|
||||
/// Absolute rotation on Y axis in degrees.
|
||||
|
@ -1412,13 +1412,13 @@ pub mod play {
|
|||
}
|
||||
|
||||
def_struct! {
|
||||
PlayerMovement 0x14 {
|
||||
PlayerMovement 0x16 {
|
||||
on_ground: bool
|
||||
}
|
||||
}
|
||||
|
||||
def_struct! {
|
||||
VehicleMoveServerbound 0x15 {
|
||||
VehicleMoveServerbound 0x17 {
|
||||
/// Absolute position
|
||||
position: Vec3<f64>,
|
||||
/// Degrees
|
||||
|
@ -1429,20 +1429,20 @@ pub mod play {
|
|||
}
|
||||
|
||||
def_struct! {
|
||||
SteerBoat 0x16 {
|
||||
SteerBoat 0x18 {
|
||||
left_paddle_turning: bool,
|
||||
right_paddle_turning: bool,
|
||||
}
|
||||
}
|
||||
|
||||
def_struct! {
|
||||
PickItem 0x17 {
|
||||
PickItem 0x19 {
|
||||
slot_to_use: VarInt,
|
||||
}
|
||||
}
|
||||
|
||||
def_struct! {
|
||||
CraftRecipeRequest 0x18 {
|
||||
CraftRecipeRequest 0x1a {
|
||||
window_id: i8,
|
||||
recipe: Ident,
|
||||
make_all: bool,
|
||||
|
@ -1450,14 +1450,14 @@ pub mod play {
|
|||
}
|
||||
|
||||
def_enum! {
|
||||
PlayerAbilitiesServerbound 0x19: i8 {
|
||||
PlayerAbilitiesServerbound 0x1b: i8 {
|
||||
NotFlying = 0,
|
||||
Flying = 0b10,
|
||||
}
|
||||
}
|
||||
|
||||
def_struct! {
|
||||
PlayerDigging 0x1a {
|
||||
PlayerDigging 0x1c {
|
||||
status: DiggingStatus,
|
||||
location: BlockPos,
|
||||
face: BlockFace,
|
||||
|
@ -1494,7 +1494,7 @@ pub mod play {
|
|||
}
|
||||
|
||||
def_struct! {
|
||||
EntityAction 0x1b {
|
||||
EntityAction 0x1d {
|
||||
entity_id: VarInt,
|
||||
action_id: EntityActionId,
|
||||
jump_boost: BoundedInt<VarInt, 0, 100>,
|
||||
|
@ -1516,7 +1516,7 @@ pub mod play {
|
|||
}
|
||||
|
||||
def_struct! {
|
||||
SteerVehicle 0x1c {
|
||||
SteerVehicle 0x1e {
|
||||
sideways: f32,
|
||||
forward: f32,
|
||||
flags: SteerVehicleFlags,
|
||||
|
@ -1531,13 +1531,13 @@ pub mod play {
|
|||
}
|
||||
|
||||
def_struct! {
|
||||
Pong 0x1d {
|
||||
Pong 0x1f {
|
||||
id: i32,
|
||||
}
|
||||
}
|
||||
|
||||
def_struct! {
|
||||
SetRecipeBookState 0x1e {
|
||||
SetRecipeBookState 0x20 {
|
||||
book_id: RecipeBookId,
|
||||
book_open: bool,
|
||||
filter_active: bool,
|
||||
|
@ -1554,19 +1554,19 @@ pub mod play {
|
|||
}
|
||||
|
||||
def_struct! {
|
||||
SetDisplayedRecipe 0x1f {
|
||||
SetDisplayedRecipe 0x21 {
|
||||
recipe_id: Ident,
|
||||
}
|
||||
}
|
||||
|
||||
def_struct! {
|
||||
NameItem 0x20 {
|
||||
NameItem 0x22 {
|
||||
item_name: BoundedString<0, 50>,
|
||||
}
|
||||
}
|
||||
|
||||
def_enum! {
|
||||
ResourcePackStatus 0x21: VarInt {
|
||||
ResourcePackStatus 0x23: VarInt {
|
||||
SuccessfullyLoaded = 0,
|
||||
Declined = 1,
|
||||
FailedDownload = 2,
|
||||
|
@ -1575,34 +1575,34 @@ pub mod play {
|
|||
}
|
||||
|
||||
def_enum! {
|
||||
AdvancementTab 0x22: VarInt {
|
||||
AdvancementTab 0x24: VarInt {
|
||||
OpenedTab: Ident = 0,
|
||||
ClosedScreen = 1,
|
||||
}
|
||||
}
|
||||
|
||||
def_struct! {
|
||||
SelectTrade 0x23 {
|
||||
SelectTrade 0x25 {
|
||||
selected_slot: VarInt,
|
||||
}
|
||||
}
|
||||
|
||||
def_struct! {
|
||||
SetBeaconEffect 0x24 {
|
||||
// TODO: potion ids?
|
||||
primary_effect: VarInt,
|
||||
secondary_effect: VarInt,
|
||||
SetBeaconEffect 0x26 {
|
||||
// TODO: potion ids
|
||||
primary_effect: Option<VarInt>,
|
||||
secondary_effect: Option<VarInt>,
|
||||
}
|
||||
}
|
||||
|
||||
def_struct! {
|
||||
HeldItemChangeServerbound 0x25 {
|
||||
HeldItemChangeServerbound 0x27 {
|
||||
slot: BoundedInt<i16, 0, 8>,
|
||||
}
|
||||
}
|
||||
|
||||
def_struct! {
|
||||
UpdateCommandBlock 0x26 {
|
||||
UpdateCommandBlock 0x28 {
|
||||
location: BlockPos,
|
||||
command: String,
|
||||
mode: CommandBlockMode,
|
||||
|
@ -1627,7 +1627,7 @@ pub mod play {
|
|||
}
|
||||
|
||||
def_struct! {
|
||||
UpdateCommandBlockMinecart 0x27 {
|
||||
UpdateCommandBlockMinecart 0x29 {
|
||||
entity_id: VarInt,
|
||||
command: String,
|
||||
track_output: bool,
|
||||
|
@ -1635,14 +1635,14 @@ pub mod play {
|
|||
}
|
||||
|
||||
def_struct! {
|
||||
CreativeInventoryAction 0x28 {
|
||||
CreativeInventoryAction 0x2a {
|
||||
slot: i16,
|
||||
// TODO: clicked_item: Slot,
|
||||
}
|
||||
}
|
||||
|
||||
def_struct! {
|
||||
UpdateJigsawBlock 0x29 {
|
||||
UpdateJigsawBlock 0x2b {
|
||||
location: BlockPos,
|
||||
name: Ident,
|
||||
target: Ident,
|
||||
|
@ -1653,7 +1653,7 @@ pub mod play {
|
|||
}
|
||||
|
||||
def_struct! {
|
||||
UpdateStructureBlock 0x2a {
|
||||
UpdateStructureBlock 0x2c {
|
||||
location: BlockPos,
|
||||
action: StructureBlockAction,
|
||||
mode: StructureBlockMode,
|
||||
|
@ -1713,37 +1713,39 @@ pub mod play {
|
|||
}
|
||||
|
||||
def_struct! {
|
||||
UpdateSign 0x2b {
|
||||
UpdateSign 0x2d {
|
||||
location: BlockPos,
|
||||
lines: [BoundedString<0, 384>; 4],
|
||||
}
|
||||
}
|
||||
|
||||
def_struct! {
|
||||
PlayerArmSwing 0x2c {
|
||||
PlayerArmSwing 0x2e {
|
||||
hand: Hand,
|
||||
}
|
||||
}
|
||||
|
||||
def_struct! {
|
||||
Spectate 0x2d {
|
||||
Spectate 0x2f {
|
||||
target: Uuid,
|
||||
}
|
||||
}
|
||||
|
||||
def_struct! {
|
||||
PlayerBlockPlacement 0x2e {
|
||||
PlayerBlockPlacement 0x30 {
|
||||
hand: Hand,
|
||||
location: BlockPos,
|
||||
face: BlockFace,
|
||||
cursor_pos: Vec3<f64>,
|
||||
head_inside_block: bool,
|
||||
sequence: VarInt,
|
||||
}
|
||||
}
|
||||
|
||||
def_struct! {
|
||||
UseItem 0x2f {
|
||||
UseItem 0x31 {
|
||||
hand: Hand,
|
||||
sequence: VarInt,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1802,11 +1804,11 @@ pub mod play {
|
|||
QueryBlockNbt,
|
||||
SetDifficulty,
|
||||
ChatMessageServerbound,
|
||||
ChatPreview,
|
||||
ClientStatus,
|
||||
ClientSettings,
|
||||
TabCompleteServerbound,
|
||||
ClickWindowButton,
|
||||
ClickWindow,
|
||||
CloseWindow,
|
||||
PluginMessageServerbound,
|
||||
EditBook,
|
||||
|
|
|
@ -5,7 +5,8 @@ use anyhow::{anyhow, ensure, Context};
|
|||
use arrayvec::ArrayVec;
|
||||
use bitvec::prelude::*;
|
||||
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde::de::DeserializeOwned;
|
||||
use serde::Serialize;
|
||||
use uuid::Uuid;
|
||||
use vek::{Vec2, Vec3, Vec4};
|
||||
|
||||
|
@ -37,6 +38,19 @@ impl Decode for () {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Encode, U: Encode> Encode for (T, U) {
|
||||
fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> {
|
||||
self.0.encode(w)?;
|
||||
self.1.encode(w)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Decode, U: Decode> Decode for (T, U) {
|
||||
fn decode(r: &mut impl Read) -> anyhow::Result<Self> {
|
||||
Ok((T::decode(r)?, U::decode(r)?))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Encode> Encode for &T {
|
||||
fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> {
|
||||
(*self).encode(w)
|
||||
|
@ -477,16 +491,13 @@ pub struct Nbt<T>(pub T);
|
|||
|
||||
impl<T: Serialize> Encode for Nbt<T> {
|
||||
fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> {
|
||||
let mut enc = nbt::ser::Encoder::new(w, None);
|
||||
self.0.serialize(&mut enc)?;
|
||||
Ok(())
|
||||
Ok(nbt::to_writer(w, &self.0, None)?)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: Deserialize<'a>> Decode for Nbt<T> {
|
||||
impl<T: DeserializeOwned> Decode for Nbt<T> {
|
||||
fn decode(r: &mut impl Read) -> anyhow::Result<Self> {
|
||||
let mut dec = nbt::de::Decoder::new(r);
|
||||
Ok(Nbt(Deserialize::deserialize(&mut dec)?))
|
||||
Ok(Self(nbt::from_reader(r)?))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -573,6 +573,7 @@ async fn handle_login(
|
|||
) -> anyhow::Result<Option<NewClientData>> {
|
||||
let LoginStart {
|
||||
username: BoundedString(username),
|
||||
sig_data: _, // TODO
|
||||
} = c.1.read_packet().await?;
|
||||
|
||||
ensure!(valid_username(&username), "invalid username '{username}'");
|
||||
|
@ -596,23 +597,23 @@ async fn handle_login(
|
|||
.0
|
||||
.rsa_key
|
||||
.decrypt(PaddingScheme::PKCS1v15Encrypt, &encrypted_shared_secret)
|
||||
.context("Failed to decrypt shared secret")?;
|
||||
.context("failed to decrypt shared secret")?;
|
||||
|
||||
let new_verify_token = server
|
||||
.0
|
||||
.rsa_key
|
||||
.decrypt(PaddingScheme::PKCS1v15Encrypt, &encrypted_verify_token)
|
||||
.context("Failed to decrypt verify token")?;
|
||||
.context("failed to decrypt verify token")?;
|
||||
|
||||
ensure!(
|
||||
verify_token.as_slice() == new_verify_token,
|
||||
"Verify tokens do not match"
|
||||
"verify tokens do not match"
|
||||
);
|
||||
|
||||
let crypt_key: [u8; 16] = shared_secret
|
||||
.as_slice()
|
||||
.try_into()
|
||||
.context("Shared secret has the wrong length")?;
|
||||
.context("shared secret has the wrong length")?;
|
||||
|
||||
c.0.enable_encryption(&crypt_key);
|
||||
c.1.enable_encryption(&crypt_key);
|
||||
|
@ -689,6 +690,7 @@ async fn handle_login(
|
|||
c.0.write_packet(&LoginSuccess {
|
||||
uuid: npd.uuid,
|
||||
username: npd.username.clone().into(),
|
||||
null_byte: 0,
|
||||
})
|
||||
.await?;
|
||||
|
||||
|
|
Loading…
Reference in a new issue