Restructure packet module

This commit is contained in:
Ryan 2022-07-29 05:34:29 -07:00
parent 959e2b2deb
commit e21fd70160
14 changed files with 1548 additions and 1541 deletions

View file

@ -253,7 +253,11 @@ impl Config for Game {
let mut vel = (victim.position() - e.state.attacker_pos).normalized(); let mut vel = (victim.position() - e.state.attacker_pos).normalized();
let knockback_xz = if e.state.extra_knockback { 18.0 } else { 8.0 }; let knockback_xz = if e.state.extra_knockback { 18.0 } else { 8.0 };
let knockback_y = if e.state.extra_knockback { 8.432 } else { 6.432 }; let knockback_y = if e.state.extra_knockback {
8.432
} else {
6.432
};
vel.x *= knockback_xz; vel.x *= knockback_xz;
vel.y = knockback_y; vel.y = knockback_y;

View file

@ -175,8 +175,8 @@ impl Config for Game {
&& (0..SIZE_Z as i32).contains(&position.z) && (0..SIZE_Z as i32).contains(&position.z)
&& position.y == BOARD_Y && position.y == BOARD_Y
{ {
server.state.board[position.x as usize + position.z as usize * SIZE_X] = server.state.board
true; [position.x as usize + position.z as usize * SIZE_X] = true;
} }
} }
Event::ArmSwing(hand) => match hand { Event::ArmSwing(hand) => match hand {

View file

@ -16,8 +16,8 @@ use valence::protocol::codec::Decoder;
use valence::protocol::packets::handshake::{Handshake, HandshakeNextState}; use valence::protocol::packets::handshake::{Handshake, HandshakeNextState};
use valence::protocol::packets::login::c2s::{EncryptionResponse, LoginStart}; use valence::protocol::packets::login::c2s::{EncryptionResponse, LoginStart};
use valence::protocol::packets::login::s2c::{LoginSuccess, S2cLoginPacket}; use valence::protocol::packets::login::s2c::{LoginSuccess, S2cLoginPacket};
use valence::protocol::packets::play::c2s::C2sPlayPacket; use valence::protocol::packets::c2s::play::C2sPlayPacket;
use valence::protocol::packets::play::s2c::S2cPlayPacket; use valence::protocol::packets::s2c::play::S2cPlayPacket;
use valence::protocol::packets::status::c2s::{QueryPing, QueryRequest}; use valence::protocol::packets::status::c2s::{QueryPing, QueryRequest};
use valence::protocol::packets::status::s2c::{QueryPong, QueryResponse}; use valence::protocol::packets::status::s2c::{QueryPong, QueryResponse};
use valence::protocol::packets::{DecodePacket, EncodePacket}; use valence::protocol::packets::{DecodePacket, EncodePacket};

View file

@ -2,7 +2,7 @@
use crate::ident; use crate::ident;
use crate::ident::Ident; use crate::ident::Ident;
use crate::protocol_inner::packets::play::s2c::Biome as BiomeRegistryBiome; use crate::protocol_inner::packets::s2c::play::Biome as BiomeRegistryBiome;
/// Identifies a particular [`Biome`] on the server. /// Identifies a particular [`Biome`] on the server.
/// ///
@ -48,7 +48,7 @@ pub struct Biome {
impl Biome { impl Biome {
pub(crate) fn to_biome_registry_item(&self, id: i32) -> BiomeRegistryBiome { pub(crate) fn to_biome_registry_item(&self, id: i32) -> BiomeRegistryBiome {
use crate::protocol_inner::packets::play::s2c::{ use crate::protocol_inner::packets::s2c::play::{
BiomeAdditionsSound, BiomeEffects, BiomeMoodSound, BiomeMusic, BiomeParticle, BiomeAdditionsSound, BiomeEffects, BiomeMoodSound, BiomeMusic, BiomeParticle,
BiomeParticleOptions, BiomeProperty, BiomeParticleOptions, BiomeProperty,
}; };

View file

@ -17,8 +17,8 @@ use crate::block_pos::BlockPos;
pub use crate::chunk_pos::ChunkPos; pub use crate::chunk_pos::ChunkPos;
use crate::config::Config; use crate::config::Config;
use crate::dimension::DimensionId; use crate::dimension::DimensionId;
use crate::protocol_inner::packets::play::s2c::{ use crate::protocol_inner::packets::s2c::play::{
BlockUpdate, ChunkDataHeightmaps, ChunkData, S2cPlayPacket, ChunkSectionUpdate, BlockUpdate, ChunkData, ChunkDataHeightmaps, ChunkSectionUpdate, S2cPlayPacket,
}; };
use crate::protocol_inner::{Encode, Nbt, VarInt, VarLong}; use crate::protocol_inner::{Encode, Nbt, VarInt, VarLong};
use crate::server::SharedServer; use crate::server::SharedServer;

View file

@ -22,19 +22,19 @@ use crate::entity::{
StatusOrAnimation, StatusOrAnimation,
}; };
use crate::player_textures::SignedPlayerTextures; use crate::player_textures::SignedPlayerTextures;
use crate::protocol_inner::packets::play::c2s::{ use crate::protocol_inner::packets::c2s::play::{
C2sPlayPacket, DiggingStatus, InteractKind, PlayerCommandId, C2sPlayPacket, DiggingStatus, InteractKind, PlayerCommandId,
}; };
pub use crate::protocol_inner::packets::play::s2c::TitleAnimationTimes as TitleAnimationTimes; pub use crate::protocol_inner::packets::s2c::play::TitleAnimationTimes;
use crate::protocol_inner::packets::play::s2c::{ use crate::protocol_inner::packets::s2c::play::{
EntityAnimation, BiomeRegistry, PlayerActionResponse, ChatType, ChatTypeChat, ChatTypeNarration, BiomeRegistry, ChatType, ChatTypeChat, ChatTypeNarration, ChatTypeRegistry,
ChatTypeRegistry, ChatTypeRegistryEntry, ClearTitles, DimensionTypeRegistry, ChatTypeRegistryEntry, ChunkLoadDistance, ChunkRenderDistanceCenter, ClearTitles,
DimensionTypeRegistryEntry, Disconnect, EntityStatus, UnloadChunk, GameStateChange, DimensionTypeRegistry, DimensionTypeRegistryEntry, Disconnect, EntitiesDestroy,
GameStateChangeReason, KeepAlive, GameJoin, MoveRelative, RotateAndMoveRelative, EntityAnimation, EntityAttributes, EntityAttributesProperty, EntityPosition, EntitySetHeadYaw,
Rotate, PlayerPositionLook, PlayerPositionLookFlags, RegistryCodec, EntitiesDestroy, EntityStatus, EntityTrackerUpdate, EntityVelocityUpdate, GameJoin, GameMessage,
PlayerRespawn, EntitySetHeadYaw, S2cPlayPacket, ChunkRenderDistanceCenter, ChunkLoadDistance, GameStateChange, GameStateChangeReason, KeepAlive, MoveRelative, PlayerActionResponse,
EntityTrackerUpdate, EntityVelocityUpdate, UpdateSubtitle, UpdateTitle, PlayerSpawnPosition, GameMessage, PlayerPositionLook, PlayerPositionLookFlags, PlayerRespawn, PlayerSpawnPosition, RegistryCodec,
EntityPosition, EntityAttributes, EntityAttributesProperty, Rotate, RotateAndMoveRelative, S2cPlayPacket, UnloadChunk, UpdateSubtitle, UpdateTitle,
}; };
use crate::protocol_inner::{BoundedInt, ByteAngle, Nbt, RawBytes, VarInt}; use crate::protocol_inner::{BoundedInt, ByteAngle, Nbt, RawBytes, VarInt};
use crate::server::{C2sPacketChannels, NewClientData, SharedServer}; use crate::server::{C2sPacketChannels, NewClientData, SharedServer};

View file

@ -4,9 +4,9 @@ use vek::Vec3;
use crate::block_pos::BlockPos; use crate::block_pos::BlockPos;
use crate::entity::EntityId; use crate::entity::EntityId;
use crate::protocol_inner::packets::play::c2s::BlockFace; use crate::protocol_inner::packets::c2s::play::BlockFace;
pub use crate::protocol_inner::packets::play::c2s::{ChatMode, DisplayedSkinParts, Hand, MainHand}; pub use crate::protocol_inner::packets::c2s::play::{ChatMode, DisplayedSkinParts, Hand, MainHand};
pub use crate::protocol_inner::packets::play::s2c::GameMode; pub use crate::protocol_inner::packets::s2c::play::GameMode;
/// Represents an action performed by a client. /// Represents an action performed by a client.
/// ///

View file

@ -1,7 +1,7 @@
//! Dimension configuration and identification. //! Dimension configuration and identification.
use crate::ident; use crate::ident;
use crate::protocol_inner::packets::play::s2c::DimensionType; use crate::protocol_inner::packets::s2c::play::DimensionType;
/// Identifies a particular [`Dimension`] on the server. /// Identifies a particular [`Dimension`] on the server.
/// ///

View file

@ -12,8 +12,8 @@ use uuid::Uuid;
use vek::{Aabb, Vec3}; use vek::{Aabb, Vec3};
use crate::config::Config; use crate::config::Config;
use crate::protocol_inner::packets::play::s2c::{ use crate::protocol_inner::packets::s2c::play::{
EntitySpawn, ExperienceOrbSpawn, PlayerSpawn, S2cPlayPacket, EntityTrackerUpdate, EntitySpawn, EntityTrackerUpdate, ExperienceOrbSpawn, PlayerSpawn, S2cPlayPacket,
}; };
use crate::protocol_inner::{ByteAngle, RawBytes, VarInt}; use crate::protocol_inner::{ByteAngle, RawBytes, VarInt};
use crate::slotmap::{Key, SlotMap}; use crate::slotmap::{Key, SlotMap};

View file

@ -8,7 +8,7 @@ use uuid::Uuid;
use crate::client::GameMode; use crate::client::GameMode;
use crate::player_textures::SignedPlayerTextures; use crate::player_textures::SignedPlayerTextures;
use crate::protocol_inner::packets::play::s2c::{ use crate::protocol_inner::packets::s2c::play::{
PlayerListAddPlayer, PlayerListHeaderFooter, S2cPlayPacket, UpdatePlayerList, PlayerListAddPlayer, PlayerListHeaderFooter, S2cPlayPacket, UpdatePlayerList,
}; };
use crate::protocol_inner::packets::Property; use crate::protocol_inner::packets::Property;

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,707 @@
//! Client to server packets.
use super::*;
pub mod handshake {
use super::*;
def_struct! {
Handshake 0x00 {
protocol_version: VarInt,
server_adddress: BoundedString<0, 255>,
server_port: u16,
next_state: HandshakeNextState,
}
}
def_enum! {
HandshakeNextState: VarInt {
Status = 1,
Login = 2,
}
}
}
pub mod status {
use super::*;
def_struct! {
QueryRequest 0x00 {}
}
def_struct! {
QueryPing 0x01 {
payload: u64
}
}
}
pub mod login {
use super::*;
def_struct! {
LoginStart 0x00 {
username: BoundedString<3, 16>,
sig_data: Option<SignatureData>,
}
}
def_struct! {
EncryptionResponse 0x01 {
shared_secret: BoundedArray<u8, 16, 128>,
token_or_sig: VerifyTokenOrMsgSig,
}
}
def_enum! {
VerifyTokenOrMsgSig: u8 {
VerifyToken: BoundedArray<u8, 16, 128> = 1,
MsgSig: MessageSignature = 0,
}
}
def_struct! {
MessageSignature {
salt: u64,
sig: Vec<u8>, // TODO: bounds?
}
}
def_struct! {
LoginPluginResponse 0x02 {
message_id: VarInt,
data: Option<RawBytes>,
}
}
def_packet_group! {
C2sLoginPacket {
LoginStart,
EncryptionResponse,
LoginPluginResponse,
}
}
}
pub mod play {
use super::super::*;
def_struct! {
TeleportConfirm 0x00 {
teleport_id: VarInt
}
}
def_struct! {
QueryBlockNbt 0x01 {
transaction_id: VarInt,
location: BlockPos,
}
}
def_enum! {
UpdateDifficulty 0x02: i8 {
Peaceful = 0,
Easy = 1,
Normal = 2,
Hard = 3,
}
}
def_struct! {
CommandExecution 0x03 {
command: String, // TODO: bounded?
// TODO: timestamp, arg signatures
signed_preview: bool,
}
}
def_struct! {
ChatMessage 0x04 {
message: BoundedString<0, 256>,
timestamp: u64,
salt: u64,
signature: Vec<u8>,
signed_preview: bool,
}
}
def_struct! {
RequestChatPreview 0x05 {
query: i32, // TODO: is this an i32 or a varint?
message: BoundedString<0, 256>,
}
}
def_enum! {
ClientStatus 0x06: VarInt {
/// Sent when ready to complete login and ready to respawn after death.
PerformRespawn = 0,
/// Sent when the statistics menu is opened.
RequestStatus = 1,
}
}
def_struct! {
ClientSettings 0x07 {
/// e.g. en_US
locale: BoundedString<0, 16>,
/// Client-side render distance in chunks.
view_distance: BoundedInt<u8, 2, 32>,
chat_mode: ChatMode,
chat_colors: bool,
displayed_skin_parts: DisplayedSkinParts,
main_hand: MainHand,
/// Currently always false
enable_text_filtering: bool,
/// False if the client should not show up in the hover preview.
allow_server_listings: bool,
}
}
def_enum! {
#[derive(Copy, PartialEq, Eq)]
ChatMode: VarInt {
Enabled = 0,
CommandsOnly = 1,
Hidden = 2,
}
}
def_bitfield! {
DisplayedSkinParts: u8 {
cape = 0,
jacket = 1,
left_sleeve = 2,
right_sleeve = 3,
left_pants_leg = 4,
right_pants_leg = 5,
hat = 6,
}
}
def_enum! {
#[derive(Copy, PartialEq, Eq)]
MainHand: VarInt {
Left = 0,
Right = 1,
}
}
def_struct! {
RequestCommandCompletion 0x08 {
transaction_id: VarInt,
/// Text behind the cursor without the '/'.
text: BoundedString<0, 32500>
}
}
def_struct! {
ButtonClick 0x09 {
window_id: i8,
button_id: i8,
}
}
def_struct! {
ClickSlot 0x0a {
// TODO
}
}
def_struct! {
CloseHandledScreen 0x0b {
window_id: u8,
}
}
def_struct! {
CustomPayload 0x0c {
channel: Ident,
data: RawBytes,
}
}
def_struct! {
BookUpdate 0x0d {
slot: VarInt,
entries: Vec<String>,
title: Option<String>,
}
}
def_struct! {
QueryEntityNbt 0x0e {
transaction_id: VarInt,
entity_id: VarInt,
}
}
def_struct! {
PlayerInteractEntity 0x0f {
entity_id: VarInt,
kind: InteractKind,
sneaking: bool,
}
}
def_enum! {
InteractKind: VarInt {
Interact: Hand = 0,
Attack = 1,
InteractAt: (Vec3<f32>, Hand) = 2
}
}
def_enum! {
#[derive(Copy, PartialEq, Eq)]
Hand: VarInt {
Main = 0,
Off = 1,
}
}
def_struct! {
JigsawGenerate 0x10 {
location: BlockPos,
levels: VarInt,
keep_jigsaws: bool,
}
}
def_struct! {
KeepAlive 0x11 {
id: i64,
}
}
def_struct! {
UpdateDifficultyLock 0x12 {
locked: bool
}
}
def_struct! {
MovePlayerPosition 0x13 {
position: Vec3<f64>,
on_ground: bool,
}
}
def_struct! {
MovePlayerPositionAndRotation 0x14 {
// Absolute position
position: Vec3<f64>,
/// Absolute rotation on X axis in degrees.
yaw: f32,
/// Absolute rotation on Y axis in degrees.
pitch: f32,
on_ground: bool,
}
}
def_struct! {
MovePlayerRotation 0x15 {
/// Absolute rotation on X axis in degrees.
yaw: f32,
/// Absolute rotation on Y axis in degrees.
pitch: f32,
on_ground: bool,
}
}
def_struct! {
MovePlayerOnGround 0x16 {
on_ground: bool
}
}
def_struct! {
MoveVehicle 0x17 {
/// Absolute position
position: Vec3<f64>,
/// Degrees
yaw: f32,
/// Degrees
pitch: f32,
}
}
def_struct! {
BoatPaddleState 0x18 {
left_paddle_turning: bool,
right_paddle_turning: bool,
}
}
def_struct! {
PickFromInventory 0x19 {
slot_to_use: VarInt,
}
}
def_struct! {
CraftRequest 0x1a {
window_id: i8,
recipe: Ident,
make_all: bool,
}
}
def_enum! {
UpdatePlayerAbilities 0x1b: i8 {
NotFlying = 0,
Flying = 0b10,
}
}
def_struct! {
PlayerAction 0x1c {
status: DiggingStatus,
location: BlockPos,
face: BlockFace,
sequence: VarInt,
}
}
def_enum! {
DiggingStatus: VarInt {
StartedDigging = 0,
CancelledDigging = 1,
FinishedDigging = 2,
DropItemStack = 3,
DropItem = 4,
ShootArrowOrFinishEating = 5,
SwapItemInHand = 6,
}
}
def_enum! {
#[derive(Copy, PartialEq, Eq)]
BlockFace: i8 {
/// -Y
Bottom = 0,
/// +Y
Top = 1,
/// -Z
North = 2,
/// +Z
South = 3,
/// -X
West = 4,
/// +X
East = 5,
}
}
def_struct! {
PlayerCommand 0x1d {
entity_id: VarInt,
action_id: PlayerCommandId,
jump_boost: BoundedInt<VarInt, 0, 100>,
}
}
def_enum! {
PlayerCommandId: VarInt {
StartSneaking = 0,
StopSneaking = 1,
LeaveBed = 2,
StartSprinting = 3,
StopSprinting = 4,
StartJumpWithHorse = 5,
StopJumpWithHorse = 6,
OpenHorseInventory = 7,
StartFlyingWithElytra = 8,
}
}
def_struct! {
PlayerInput 0x1e {
sideways: f32,
forward: f32,
flags: PlayerInputFlags,
}
}
def_bitfield! {
PlayerInputFlags: u8 {
jump = 0,
unmount = 1,
}
}
def_struct! {
PlayPong 0x1f {
id: i32,
}
}
def_struct! {
RecipeBookChangeSettings 0x20 {
book_id: RecipeBookId,
book_open: bool,
filter_active: bool,
}
}
def_enum! {
RecipeBookId: VarInt {
Crafting = 0,
Furnace = 1,
BlastFurnace = 2,
Smoker = 3,
}
}
def_struct! {
RecipeBookSeenRecipe 0x21 {
recipe_id: Ident,
}
}
def_struct! {
RenameItem 0x22 {
item_name: BoundedString<0, 50>,
}
}
def_enum! {
ResourcePackStatus 0x23: VarInt {
SuccessfullyLoaded = 0,
Declined = 1,
FailedDownload = 2,
Accepted = 3,
}
}
def_enum! {
AdvancementTab 0x24: VarInt {
OpenedTab: Ident = 0,
ClosedScreen = 1,
}
}
def_struct! {
SelectMerchantTrade 0x25 {
selected_slot: VarInt,
}
}
def_struct! {
UpdateBeacon 0x26 {
// TODO: potion ids
primary_effect: Option<VarInt>,
secondary_effect: Option<VarInt>,
}
}
def_struct! {
UpdateSelectedSlot 0x27 {
slot: BoundedInt<i16, 0, 8>,
}
}
def_struct! {
UpdateCommandBlock 0x28 {
location: BlockPos,
command: String,
mode: CommandBlockMode,
flags: CommandBlockFlags,
}
}
def_enum! {
CommandBlockMode: VarInt {
Sequence = 0,
Auto = 1,
Redstone = 2,
}
}
def_bitfield! {
CommandBlockFlags: i8 {
track_output = 0,
is_conditional = 1,
automatic = 2,
}
}
def_struct! {
UpdateCommandBlockMinecart 0x29 {
entity_id: VarInt,
command: String,
track_output: bool,
}
}
def_struct! {
UpdateCreativeModeSlot 0x2a {
slot: i16,
// TODO: clicked_item: Slot,
}
}
def_struct! {
UpdateJigsaw 0x2b {
location: BlockPos,
name: Ident,
target: Ident,
pool: Ident,
final_state: String,
joint_type: String,
}
}
def_struct! {
UpdateStructureBlock 0x2c {
location: BlockPos,
action: StructureBlockAction,
mode: StructureBlockMode,
name: String,
offset_xyz: [BoundedInt<i8, -32, 32>; 3],
size_xyz: [BoundedInt<i8, 0, 32>; 3],
mirror: StructureBlockMirror,
rotation: StructureBlockRotation,
metadata: String,
integrity: f32, // TODO: bounded float between 0 and 1.
seed: VarLong,
flags: StructureBlockFlags,
}
}
def_enum! {
StructureBlockAction: VarInt {
UpdateData = 0,
SaveStructure = 1,
LoadStructure = 2,
DetectSize = 3,
}
}
def_enum! {
StructureBlockMode: VarInt {
Save = 0,
Load = 1,
Corner = 2,
Data = 3,
}
}
def_enum! {
StructureBlockMirror: VarInt {
None = 0,
LeftRight = 1,
FrontBack = 2,
}
}
def_enum! {
StructureBlockRotation: VarInt {
None = 0,
Clockwise90 = 1,
Clockwise180 = 2,
Counterclockwise90 = 3,
}
}
def_bitfield! {
StructureBlockFlags: i8 {
ignore_entities = 0,
show_air = 1,
show_bounding_box = 2,
}
}
def_struct! {
UpdateSign 0x2d {
location: BlockPos,
lines: [BoundedString<0, 384>; 4],
}
}
def_struct! {
HandSwing 0x2e {
hand: Hand,
}
}
def_struct! {
SpectatorTeleport 0x2f {
target: Uuid,
}
}
def_struct! {
PlayerInteractBlock 0x30 {
hand: Hand,
location: BlockPos,
face: BlockFace,
cursor_pos: Vec3<f32>,
head_inside_block: bool,
sequence: VarInt,
}
}
def_struct! {
PlayerInteractItem 0x31 {
hand: Hand,
sequence: VarInt,
}
}
def_packet_group! {
C2sPlayPacket {
TeleportConfirm,
QueryBlockNbt,
UpdateDifficulty,
CommandExecution,
ChatMessage,
RequestChatPreview,
ClientStatus,
ClientSettings,
RequestCommandCompletion,
ButtonClick,
ClickSlot,
CloseHandledScreen,
CustomPayload,
BookUpdate,
QueryEntityNbt,
PlayerInteractEntity,
JigsawGenerate,
KeepAlive,
UpdateDifficultyLock,
MovePlayerPosition,
MovePlayerPositionAndRotation,
MovePlayerRotation,
MovePlayerOnGround,
MoveVehicle,
BoatPaddleState,
PickFromInventory,
CraftRequest,
UpdatePlayerAbilities,
PlayerAction,
PlayerCommand,
PlayerInput,
PlayPong,
RecipeBookChangeSettings,
RecipeBookSeenRecipe,
RenameItem,
ResourcePackStatus,
AdvancementTab,
SelectMerchantTrade,
UpdateBeacon,
UpdateSelectedSlot,
UpdateCommandBlock,
UpdateCommandBlockMinecart,
UpdateCreativeModeSlot,
UpdateJigsaw,
UpdateStructureBlock,
UpdateSign,
HandSwing,
SpectatorTeleport,
PlayerInteractBlock,
PlayerInteractItem,
}
}
}

View file

@ -0,0 +1,794 @@
//! Server to client packets.
use super::*;
pub mod status {
use super::*;
def_struct! {
QueryResponse 0x00 {
json_response: String
}
}
def_struct! {
QueryPong 0x01 {
/// Should be the same as the payload from ping.
payload: u64
}
}
}
pub mod login {
use super::*;
def_struct! {
LoginDisconnect 0x00 {
reason: Text,
}
}
def_struct! {
EncryptionRequest 0x01 {
/// Currently unused
server_id: BoundedString<0, 20>,
/// The RSA public key
public_key: Vec<u8>,
verify_token: BoundedArray<u8, 16, 16>,
}
}
def_struct! {
LoginSuccess 0x02 {
uuid: Uuid,
username: BoundedString<3, 16>,
properties: Vec<Property>,
}
}
def_struct! {
LoginCompression 0x03 {
threshold: VarInt
}
}
def_struct! {
LoginPluginRequest 0x04 {
message_id: VarInt,
channel: Ident,
data: RawBytes,
}
}
def_packet_group! {
S2cLoginPacket {
LoginDisconnect,
EncryptionRequest,
LoginSuccess,
LoginCompression,
LoginPluginRequest,
}
}
}
pub mod play {
use super::*;
def_struct! {
EntitySpawn 0x00 {
entity_id: VarInt,
object_uuid: Uuid,
kind: VarInt,
position: Vec3<f64>,
pitch: ByteAngle,
yaw: ByteAngle,
head_yaw: ByteAngle,
data: VarInt,
velocity: Vec3<i16>,
}
}
def_struct! {
ExperienceOrbSpawn 0x01 {
entity_id: VarInt,
position: Vec3<f64>,
count: i16,
}
}
def_struct! {
PlayerSpawn 0x02 {
entity_id: VarInt,
player_uuid: Uuid,
position: Vec3<f64>,
yaw: ByteAngle,
pitch: ByteAngle,
}
}
def_struct! {
EntityAnimation 0x03 {
entity_id: VarInt,
animation: u8,
}
}
def_struct! {
PlayerActionResponse 0x05 {
sequence: VarInt,
}
}
def_struct! {
BlockBreakingProgress 0x06 {
entity_id: VarInt,
location: BlockPos,
destroy_stage: BoundedInt<u8, 0, 10>,
}
}
def_struct! {
BlockEntityUpdate 0x07 {
location: BlockPos,
kind: VarInt, // TODO: use enum here
data: nbt::Blob,
}
}
def_struct! {
BlockEvent 0x08 {
location: BlockPos,
action_id: u8,
action_param: u8,
block_type: VarInt, // TODO: use BlockType type.
}
}
def_struct! {
BlockUpdate 0x09 {
location: BlockPos,
block_id: VarInt,
}
}
def_struct! {
BossBar 0x0a {
uuid: Uuid,
action: BossBarAction,
}
}
def_enum! {
BossBarAction: VarInt {
Add: BossBarActionAdd = 0,
// TODO
}
}
def_struct! {
BossBarActionAdd {
title: Text,
health: f32,
color: BossBarColor,
division: BossBarDivision,
/// TODO: bitmask
flags: u8,
}
}
def_enum! {
BossBarColor: VarInt {
Pink = 0,
Blue = 1,
Red = 2,
Green = 3,
Yellow = 4,
Purple = 5,
White = 6,
}
}
def_enum! {
BossBarDivision: VarInt {
NoDivision = 0,
SixNotches = 1,
TenNotches = 2,
TwelveNotches = 3,
TwentyNotches = 4,
}
}
def_struct! {
SetDifficulty 0x0b {
difficulty: Difficulty,
locked: bool,
}
}
def_enum! {
Difficulty: u8 {
Peaceful = 0,
Easy = 1,
Normal = 2,
Hard = 3,
}
}
def_struct! {
ClearTitles 0x0d {
reset: bool,
}
}
def_struct! {
Disconnect 0x17 {
reason: Text,
}
}
def_struct! {
EntityStatus 0x18 {
entity_id: i32,
entity_status: u8,
}
}
def_struct! {
UnloadChunk 0x1a {
chunk_x: i32,
chunk_z: i32
}
}
def_struct! {
GameStateChange 0x1b {
reason: GameStateChangeReason,
value: f32,
}
}
def_enum! {
GameStateChangeReason: u8 {
NoRespawnBlockAvailable = 0,
EndRaining = 1,
BeginRaining = 2,
ChangeGameMode = 3,
WinGame = 4,
DemoEvent = 5,
ArrowHitPlayer = 6,
RainLevelChange = 7,
ThunderLevelChange = 8,
PlayPufferfishStingSound = 9,
PlayElderGuardianMobAppearance = 10,
EnableRespawnScreen = 11,
}
}
def_struct! {
WorldBorderInitialize 0x1d {
x: f64,
z: f64,
old_diameter: f64,
new_diameter: f64,
speed: VarLong,
portal_teleport_boundary: VarInt,
warning_blocks: VarInt,
warning_time: VarInt,
}
}
def_struct! {
KeepAlive 0x1e {
id: i64,
}
}
def_struct! {
ChunkData 0x1f {
chunk_x: i32,
chunk_z: i32,
heightmaps: Nbt<ChunkDataHeightmaps>,
blocks_and_biomes: Vec<u8>,
block_entities: Vec<ChunkDataBlockEntity>,
trust_edges: bool,
sky_light_mask: BitVec<u64>,
block_light_mask: BitVec<u64>,
empty_sky_light_mask: BitVec<u64>,
empty_block_light_mask: BitVec<u64>,
sky_light_arrays: Vec<[u8; 2048]>,
block_light_arrays: Vec<[u8; 2048]>,
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ChunkDataHeightmaps {
#[serde(rename = "MOTION_BLOCKING", serialize_with = "nbt::i64_array")]
pub motion_blocking: Vec<i64>,
}
def_struct! {
ChunkDataBlockEntity {
packed_xz: i8,
y: i16,
kind: VarInt,
data: nbt::Blob,
}
}
def_struct! {
GameJoin 0x23 {
/// Entity ID of the joining player
entity_id: i32,
is_hardcore: bool,
gamemode: GameMode,
previous_gamemode: GameMode,
dimension_names: Vec<Ident>,
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,
/// No longer used by the client.
max_players: VarInt,
view_distance: BoundedInt<VarInt, 2, 32>,
simulation_distance: VarInt,
/// If reduced debug info should be shown on the F3 screen.
reduced_debug_info: bool,
/// If player respawns should be instant or not.
enable_respawn_screen: bool,
is_debug: bool,
/// 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 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)]
pub struct DimensionTypeRegistry {
#[serde(rename = "type")]
pub kind: Ident,
pub value: Vec<DimensionTypeRegistryEntry>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct DimensionTypeRegistryEntry {
pub name: Ident,
pub id: i32,
pub element: DimensionType,
}
#[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>,
pub infiniburn: String, // TODO: tag type?
pub respawn_anchor_works: bool,
pub has_skylight: bool,
pub bed_works: bool,
pub effects: Ident,
pub min_y: i32,
pub height: i32,
pub logical_height: i32,
pub coordinate_scale: f64,
pub ultrawarm: bool,
pub has_ceiling: bool,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct BiomeRegistry {
#[serde(rename = "type")]
pub kind: Ident,
pub value: Vec<Biome>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Biome {
pub name: Ident,
pub id: i32,
pub element: BiomeProperty,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct BiomeProperty {
pub precipitation: String,
pub depth: f32,
pub temperature: f32,
pub scale: f32,
pub downfall: f32,
pub category: String,
pub temperature_modifier: Option<String>,
pub effects: BiomeEffects,
pub particle: Option<BiomeParticle>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct BiomeEffects {
pub sky_color: i32,
pub water_fog_color: i32,
pub fog_color: i32,
pub water_color: i32,
pub foliage_color: Option<i32>,
pub grass_color: Option<i32>,
pub grass_color_modifier: Option<String>,
pub music: Option<BiomeMusic>,
pub ambient_sound: Option<Ident>,
pub additions_sound: Option<BiomeAdditionsSound>,
pub mood_sound: Option<BiomeMoodSound>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct BiomeMusic {
pub replace_current_music: bool,
pub sound: Ident,
pub max_delay: i32,
pub min_delay: i32,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct BiomeAdditionsSound {
pub sound: Ident,
pub tick_chance: f64,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct BiomeMoodSound {
pub sound: Ident,
pub tick_delay: i32,
pub offset: f64,
pub block_search_extent: i32,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct BiomeParticle {
pub probability: f32,
pub options: BiomeParticleOptions,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct BiomeParticleOptions {
#[serde(rename = "type")]
pub kind: Ident,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ChatTypeRegistry {
#[serde(rename = "type")]
pub kind: Ident,
pub value: Vec<ChatTypeRegistryEntry>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ChatTypeRegistryEntry {
pub name: Ident,
pub id: i32,
pub element: ChatType,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ChatType {
pub chat: ChatTypeChat,
pub narration: ChatTypeNarration,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ChatTypeChat {}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ChatTypeNarration {
pub priority: String,
}
def_enum! {
#[derive(Copy, PartialEq, Eq, PartialOrd, Ord, Default, Hash)]
GameMode: u8 {
#[default]
Survival = 0,
Creative = 1,
Adventure = 2,
Spectator = 3,
}
}
def_struct! {
MoveRelative 0x26 {
entity_id: VarInt,
delta: Vec3<i16>,
on_ground: bool,
}
}
def_struct! {
RotateAndMoveRelative 0x27 {
entity_id: VarInt,
delta: Vec3<i16>,
yaw: ByteAngle,
pitch: ByteAngle,
on_ground: bool,
}
}
def_struct! {
Rotate 0x28 {
entity_id: VarInt,
yaw: ByteAngle,
pitch: ByteAngle,
on_ground: bool,
}
}
def_struct! {
ChatMessage 0x30 {
message: Text,
/// Index into the chat type registry
kind: VarInt,
sender: Uuid,
// TODO more fields
}
}
def_enum! {
UpdatePlayerList 0x34: VarInt {
AddPlayer: Vec<PlayerListAddPlayer> = 0,
UpdateGameMode: Vec<(Uuid, GameMode)> = 1,
UpdateLatency: Vec<(Uuid, VarInt)> = 2,
UpdateDisplayName: Vec<(Uuid, Option<Text>)> = 3,
RemovePlayer: Vec<Uuid> = 4,
}
}
def_struct! {
PlayerListAddPlayer {
uuid: Uuid,
username: BoundedString<3, 16>,
properties: Vec<Property>,
game_mode: GameMode,
ping: VarInt,
display_name: Option<Text>,
sig_data: Option<SignatureData>,
}
}
def_struct! {
PlayerPositionLook 0x36 {
position: Vec3<f64>,
yaw: f32,
pitch: f32,
flags: PlayerPositionLookFlags,
teleport_id: VarInt,
dismount_vehicle: bool,
}
}
def_bitfield! {
PlayerPositionLookFlags: u8 {
x = 0,
y = 1,
z = 2,
y_rot = 3,
x_rot = 4,
}
}
def_struct! {
EntitiesDestroy 0x38 {
entities: Vec<VarInt>,
}
}
def_struct! {
PlayerRespawn 0x3b {
dimension_type_name: Ident,
dimension_name: Ident,
hashed_seed: u64,
game_mode: GameMode,
previous_game_mode: GameMode,
is_debug: bool,
is_flat: bool,
copy_metadata: bool,
last_death_location: Option<(Ident, BlockPos)>,
}
}
def_struct! {
EntitySetHeadYaw 0x3c {
entity_id: VarInt,
head_yaw: ByteAngle,
}
}
def_struct! {
ChunkSectionUpdate 0x3d {
chunk_section_position: i64,
invert_trust_edges: bool,
blocks: Vec<VarLong>,
}
}
def_struct! {
UpdateSelectedSlot 0x47 {
slot: BoundedInt<u8, 0, 9>,
}
}
def_struct! {
ChunkRenderDistanceCenter 0x48 {
chunk_x: VarInt,
chunk_z: VarInt,
}
}
def_struct! {
ChunkLoadDistance 0x49 {
view_distance: BoundedInt<VarInt, 2, 32>,
}
}
def_struct! {
PlayerSpawnPosition 0x4a {
location: BlockPos,
angle: f32,
}
}
def_struct! {
EntityTrackerUpdate 0x4d {
entity_id: VarInt,
metadata: RawBytes,
}
}
def_struct! {
EntityVelocityUpdate 0x4f {
entity_id: VarInt,
velocity: Vec3<i16>,
}
}
def_struct! {
UpdateSubtitle 0x58 {
subtitle_text: Text,
}
}
def_struct! {
WorldTimeUpdate 0x59 {
/// The age of the world in 1/20ths of a second.
world_age: i64,
/// The current time of day in 1/20ths of a second.
/// The value should be in the range \[0, 24000].
/// 6000 is noon, 12000 is sunset, and 18000 is midnight.
time_of_day: i64,
}
}
def_struct! {
UpdateTitle 0x5a {
text: Text,
}
}
def_struct! {
#[derive(Copy, PartialEq, Eq)]
TitleAnimationTimes 0x5b {
/// Ticks to spend fading in.
fade_in: u32,
/// Ticks to keep the title displayed.
stay: u32,
/// Ticks to spend fading out.
fade_out: u32,
}
}
def_struct! {
GameMessage 0x5f {
chat: Text,
/// Index into the chat type registry.
kind: VarInt,
}
}
def_struct! {
PlayerListHeaderFooter 0x60 {
header: Text,
footer: Text,
}
}
def_struct! {
EntityPosition 0x63 {
entity_id: VarInt,
position: Vec3<f64>,
yaw: ByteAngle,
pitch: ByteAngle,
on_ground: bool,
}
}
def_struct! {
EntityAttributes 0x65 {
entity_id: VarInt,
properties: Vec<EntityAttributesProperty>,
}
}
def_struct! {
EntityAttributesProperty {
key: Ident,
value: f64,
modifiers: Vec<EntityAttributesModifiers>
}
}
def_struct! {
EntityAttributesModifiers {
uuid: Uuid,
amount: f64,
operation: u8,
}
}
def_packet_group! {
S2cPlayPacket {
EntitySpawn,
ExperienceOrbSpawn,
PlayerSpawn,
EntityAnimation,
PlayerActionResponse,
BlockBreakingProgress,
BlockEntityUpdate,
BlockEvent,
BlockUpdate,
BossBar,
ClearTitles,
Disconnect,
EntityStatus,
UnloadChunk,
GameStateChange,
KeepAlive,
ChunkData,
GameJoin,
MoveRelative,
RotateAndMoveRelative,
Rotate,
ChatMessage,
UpdatePlayerList,
PlayerPositionLook,
EntitiesDestroy,
PlayerRespawn,
EntitySetHeadYaw,
ChunkSectionUpdate,
UpdateSelectedSlot,
ChunkRenderDistanceCenter,
ChunkLoadDistance,
PlayerSpawnPosition,
EntityTrackerUpdate,
EntityVelocityUpdate,
UpdateSubtitle,
WorldTimeUpdate,
UpdateTitle,
TitleAnimationTimes,
GameMessage,
PlayerListHeaderFooter,
EntityPosition,
EntityAttributes,
}
}
}

View file

@ -34,16 +34,16 @@ use crate::dimension::{Dimension, DimensionId};
use crate::entity::Entities; use crate::entity::Entities;
use crate::player_textures::SignedPlayerTextures; use crate::player_textures::SignedPlayerTextures;
use crate::protocol_inner::codec::{Decoder, Encoder}; use crate::protocol_inner::codec::{Decoder, Encoder};
use crate::protocol_inner::packets::handshake::{Handshake, HandshakeNextState}; use crate::protocol_inner::packets::c2s::handshake::{Handshake, HandshakeNextState};
use crate::protocol_inner::packets::login::c2s::{ use crate::protocol_inner::packets::c2s::login::{
EncryptionResponse, LoginStart, VerifyTokenOrMsgSig, EncryptionResponse, LoginStart, VerifyTokenOrMsgSig,
}; };
use crate::protocol_inner::packets::login::s2c::{EncryptionRequest, LoginSuccess, LoginCompression}; use crate::protocol_inner::packets::c2s::play::C2sPlayPacket;
use crate::protocol_inner::packets::play::c2s::C2sPlayPacket; use crate::protocol_inner::packets::c2s::status::{QueryPing, QueryRequest};
use crate::protocol_inner::packets::play::s2c::S2cPlayPacket; use crate::protocol_inner::packets::s2c::login::{EncryptionRequest, LoginCompression, LoginDisconnect, LoginSuccess};
use crate::protocol_inner::packets::status::c2s::{QueryPing, QueryRequest}; use crate::protocol_inner::packets::s2c::play::S2cPlayPacket;
use crate::protocol_inner::packets::status::s2c::{QueryPong, QueryResponse}; use crate::protocol_inner::packets::s2c::status::{QueryPong, QueryResponse};
use crate::protocol_inner::packets::{login, Property}; use crate::protocol_inner::packets::Property;
use crate::protocol_inner::{BoundedArray, BoundedString, VarInt}; use crate::protocol_inner::{BoundedArray, BoundedString, VarInt};
use crate::util::valid_username; use crate::util::valid_username;
use crate::world::Worlds; use crate::world::Worlds;
@ -723,7 +723,7 @@ async fn handle_login<C: Config>(
if let Err(reason) = server.0.cfg.login(server, &npd).await { if let Err(reason) = server.0.cfg.login(server, &npd).await {
log::info!("Disconnect at login: \"{reason}\""); log::info!("Disconnect at login: \"{reason}\"");
c.enc c.enc
.write_packet(&login::s2c::LoginDisconnect { reason }) .write_packet(&LoginDisconnect { reason })
.await?; .await?;
return Ok(None); return Ok(None);
} }