Compare commits
4 Commits
lazymc-v1_
...
lazymc-mul
Author | SHA1 | Date | |
---|---|---|---|
|
edfdf876c0 | ||
|
5b80bc2df3 | ||
|
113f7f0bb2 | ||
|
692a88c16b |
@@ -222,6 +222,7 @@ impl Decoder for Vec<CompoundTag> {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(timvisee): identifier decoder, we might want a custom type
|
||||
impl Decoder for Vec<String> {
|
||||
type Output = Self;
|
||||
|
||||
@@ -238,6 +239,24 @@ impl Decoder for Vec<String> {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(timvisee): forge mod channel decoder, we might want a custom type
|
||||
impl Decoder for Vec<(String, String)> {
|
||||
type Output = Self;
|
||||
|
||||
fn decode<R: Read>(reader: &mut R) -> Result<Self::Output, DecodeError> {
|
||||
let length = reader.read_var_i32()? as usize;
|
||||
let mut vec = Vec::with_capacity(length);
|
||||
|
||||
for _ in 0..length {
|
||||
let a = reader.read_string(32767)?;
|
||||
let b = reader.read_string(32767)?;
|
||||
vec.push((a, b));
|
||||
}
|
||||
|
||||
Ok(vec)
|
||||
}
|
||||
}
|
||||
|
||||
pub mod var_int {
|
||||
use crate::decoder::DecoderReadExt;
|
||||
use crate::error::DecodeError;
|
||||
|
@@ -196,6 +196,20 @@ impl Encoder for Vec<String> {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(timvisee): forge mod channel encoder, we might want a custom type
|
||||
impl Encoder for Vec<(String, String)> {
|
||||
fn encode<W: Write>(&self, writer: &mut W) -> Result<(), EncodeError> {
|
||||
writer.write_var_i32(self.len() as i32)?;
|
||||
|
||||
for (a, b) in self {
|
||||
writer.write_string(&a, 32767)?;
|
||||
writer.write_string(&b, 32767)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub mod var_int {
|
||||
use crate::encoder::EncoderWriteExt;
|
||||
use crate::error::EncodeError;
|
||||
|
62
protocol/src/version/forge_v1_13/login.rs
Normal file
62
protocol/src/version/forge_v1_13/login.rs
Normal file
@@ -0,0 +1,62 @@
|
||||
use crate::{set_packet_id, version::PacketId};
|
||||
use minecraft_protocol_derive::Decoder;
|
||||
use minecraft_protocol_derive::Encoder;
|
||||
|
||||
set_packet_id!(ModList, 1);
|
||||
set_packet_id!(ModListReply, 2);
|
||||
set_packet_id!(ServerRegistry, 3);
|
||||
set_packet_id!(ConfigurationData, 4);
|
||||
set_packet_id!(Acknowledgement, 99);
|
||||
|
||||
#[derive(Encoder, Decoder, Debug)]
|
||||
pub struct LoginWrapper {
|
||||
pub channel: String,
|
||||
pub packet: Vec<u8>,
|
||||
}
|
||||
|
||||
#[derive(Encoder, Decoder, Debug)]
|
||||
pub struct ModList {
|
||||
pub mod_names: Vec<String>,
|
||||
pub channels: Vec<(String, String)>,
|
||||
pub registries: Vec<String>,
|
||||
}
|
||||
|
||||
impl ModList {
|
||||
/// Transform this into a `ModListReply` with empty registry markers.
|
||||
pub fn into_reply(self) -> ModListReply {
|
||||
ModListReply {
|
||||
mod_names: self.mod_names,
|
||||
channels: self.channels,
|
||||
registries: self
|
||||
.registries
|
||||
.into_iter()
|
||||
.map(|r| (r, "".into()))
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Encoder, Decoder, Debug)]
|
||||
pub struct ModListReply {
|
||||
pub mod_names: Vec<String>,
|
||||
pub channels: Vec<(String, String)>,
|
||||
pub registries: Vec<(String, String)>,
|
||||
}
|
||||
|
||||
#[derive(Encoder, Decoder, Debug)]
|
||||
pub struct ServerRegistry {
|
||||
pub registry_name: String,
|
||||
pub snapshot_present: bool,
|
||||
// TODO: implement this snapshot type!
|
||||
// TODO: add dummy data here, 5x 0 ?
|
||||
pub snapshot: Vec<u8>,
|
||||
}
|
||||
|
||||
#[derive(Encoder, Decoder, Debug)]
|
||||
pub struct ConfigurationData {
|
||||
pub file_name: String,
|
||||
pub data: Vec<u8>,
|
||||
}
|
||||
|
||||
#[derive(Encoder, Decoder, Debug)]
|
||||
pub struct Acknowledgement {}
|
1
protocol/src/version/forge_v1_13/mod.rs
Normal file
1
protocol/src/version/forge_v1_13/mod.rs
Normal file
@@ -0,0 +1 @@
|
||||
pub mod login;
|
@@ -1,4 +1,8 @@
|
||||
pub mod forge_v1_13;
|
||||
pub mod v1_14_4;
|
||||
pub mod v1_16_3;
|
||||
pub mod v1_16_4;
|
||||
pub mod v1_17;
|
||||
pub mod v1_17_1;
|
||||
|
||||
/// Trait to obtain packet ID from packet data.
|
||||
@@ -8,11 +12,15 @@ pub trait PacketId {
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! trait_packet_id (
|
||||
macro_rules! set_packet_id (
|
||||
($type: ident, $id: expr) => (
|
||||
impl $type {
|
||||
pub const PACKET_ID: u8 = $id;
|
||||
}
|
||||
|
||||
impl PacketId for $type {
|
||||
fn packet_id(&self) -> u8 {
|
||||
$id
|
||||
Self::PACKET_ID
|
||||
}
|
||||
}
|
||||
)
|
||||
|
@@ -3,13 +3,25 @@ use crate::decoder::Decoder;
|
||||
use crate::decoder::DecoderReadExt;
|
||||
use crate::encoder::EncoderWriteExt;
|
||||
use crate::error::DecodeError;
|
||||
use crate::{trait_packet_id, version::PacketId};
|
||||
use crate::{set_packet_id, version::PacketId};
|
||||
use byteorder::{ReadBytesExt, WriteBytesExt};
|
||||
use minecraft_protocol_derive::{Decoder, Encoder};
|
||||
use nbt::CompoundTag;
|
||||
use std::io::Read;
|
||||
use uuid::Uuid;
|
||||
|
||||
set_packet_id!(ServerBoundChatMessage, 0x03);
|
||||
set_packet_id!(ServerBoundKeepAlive, 0x0F);
|
||||
set_packet_id!(ServerBoundAbilities, 0x19);
|
||||
|
||||
set_packet_id!(ClientBoundChatMessage, 0x0F);
|
||||
set_packet_id!(GameDisconnect, 0x1A);
|
||||
set_packet_id!(ClientBoundKeepAlive, 0x21);
|
||||
set_packet_id!(ChunkData, 0x21);
|
||||
set_packet_id!(JoinGame, 0x25);
|
||||
set_packet_id!(BossBar, 0x0D);
|
||||
set_packet_id!(EntityAction, 0x1B);
|
||||
|
||||
pub enum GameServerBoundPacket {
|
||||
ServerBoundChatMessage(ServerBoundChatMessage),
|
||||
ServerBoundKeepAlive(ServerBoundKeepAlive),
|
||||
@@ -191,7 +203,7 @@ impl ServerBoundKeepAlive {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Encoder, Decoder)]
|
||||
#[derive(Encoder, Decoder, Debug)]
|
||||
pub struct ClientBoundKeepAlive {
|
||||
pub id: u64,
|
||||
}
|
||||
@@ -733,15 +745,3 @@ mod tests {
|
||||
assert!(abilities.creative_mode);
|
||||
}
|
||||
}
|
||||
|
||||
trait_packet_id!(ServerBoundChatMessage, 0x03);
|
||||
trait_packet_id!(ServerBoundKeepAlive, 0x0F);
|
||||
trait_packet_id!(ServerBoundAbilities, 0x19);
|
||||
|
||||
trait_packet_id!(ClientBoundChatMessage, 0x0F);
|
||||
trait_packet_id!(GameDisconnect, 0x1A);
|
||||
trait_packet_id!(ClientBoundKeepAlive, 0x21);
|
||||
trait_packet_id!(ChunkData, 0x21);
|
||||
trait_packet_id!(JoinGame, 0x25);
|
||||
trait_packet_id!(BossBar, 0x0D);
|
||||
trait_packet_id!(EntityAction, 0x1B);
|
||||
|
@@ -1,9 +1,11 @@
|
||||
use crate::decoder::Decoder;
|
||||
use crate::error::DecodeError;
|
||||
use crate::{trait_packet_id, version::PacketId};
|
||||
use crate::{set_packet_id, version::PacketId};
|
||||
use minecraft_protocol_derive::{Decoder, Encoder};
|
||||
use std::io::Read;
|
||||
|
||||
set_packet_id!(Handshake, 0x00);
|
||||
|
||||
pub enum HandshakeServerBoundPacket {
|
||||
Handshake(Handshake),
|
||||
}
|
||||
@@ -54,5 +56,3 @@ impl Handshake {
|
||||
HandshakeServerBoundPacket::Handshake(handshake)
|
||||
}
|
||||
}
|
||||
|
||||
trait_packet_id!(Handshake, 0x00);
|
||||
|
@@ -4,9 +4,19 @@ use uuid::Uuid;
|
||||
use crate::data::chat::Message;
|
||||
use crate::decoder::Decoder;
|
||||
use crate::error::DecodeError;
|
||||
use crate::{trait_packet_id, version::PacketId};
|
||||
use crate::{set_packet_id, version::PacketId};
|
||||
use minecraft_protocol_derive::{Decoder, Encoder};
|
||||
|
||||
set_packet_id!(LoginStart, 0x00);
|
||||
set_packet_id!(EncryptionResponse, 0x01);
|
||||
set_packet_id!(LoginPluginResponse, 0x02);
|
||||
|
||||
set_packet_id!(LoginDisconnect, 0x00);
|
||||
set_packet_id!(EncryptionRequest, 0x01);
|
||||
set_packet_id!(LoginSuccess, 0x02);
|
||||
set_packet_id!(SetCompression, 0x03);
|
||||
set_packet_id!(LoginPluginRequest, 0x04);
|
||||
|
||||
pub enum LoginServerBoundPacket {
|
||||
LoginStart(LoginStart),
|
||||
EncryptionResponse(EncryptionResponse),
|
||||
@@ -481,13 +491,3 @@ mod tests {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
trait_packet_id!(LoginStart, 0x00);
|
||||
trait_packet_id!(EncryptionResponse, 0x01);
|
||||
trait_packet_id!(LoginPluginResponse, 0x02);
|
||||
|
||||
trait_packet_id!(LoginDisconnect, 0x00);
|
||||
trait_packet_id!(EncryptionRequest, 0x01);
|
||||
trait_packet_id!(LoginSuccess, 0x02);
|
||||
trait_packet_id!(SetCompression, 0x03);
|
||||
trait_packet_id!(LoginPluginRequest, 0x04);
|
||||
|
@@ -1,4 +1,9 @@
|
||||
// Spec: https://wiki.vg/index.php?title=Protocol&oldid=15346
|
||||
|
||||
pub mod game;
|
||||
pub mod handshake;
|
||||
pub mod login;
|
||||
pub mod status;
|
||||
|
||||
/// Minecraft protocol version.
|
||||
pub const PROTOCOL: u32 = 498;
|
||||
|
@@ -1,10 +1,16 @@
|
||||
use crate::data::server_status::*;
|
||||
use crate::decoder::Decoder;
|
||||
use crate::error::DecodeError;
|
||||
use crate::{trait_packet_id, version::PacketId};
|
||||
use crate::{set_packet_id, version::PacketId};
|
||||
use minecraft_protocol_derive::{Decoder, Encoder};
|
||||
use std::io::Read;
|
||||
|
||||
set_packet_id!(StatusRequest, 0x00);
|
||||
set_packet_id!(PingRequest, 0x01);
|
||||
|
||||
set_packet_id!(StatusResponse, 0x00);
|
||||
set_packet_id!(PingResponse, 0x01);
|
||||
|
||||
pub enum StatusServerBoundPacket {
|
||||
StatusRequest(StatusRequest),
|
||||
PingRequest(PingRequest),
|
||||
@@ -208,9 +214,3 @@ mod tests {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
trait_packet_id!(StatusRequest, 0x00);
|
||||
trait_packet_id!(PingRequest, 0x01);
|
||||
|
||||
trait_packet_id!(StatusResponse, 0x00);
|
||||
trait_packet_id!(PingResponse, 0x01);
|
||||
|
139
protocol/src/version/v1_16_3/game.rs
Normal file
139
protocol/src/version/v1_16_3/game.rs
Normal file
@@ -0,0 +1,139 @@
|
||||
use crate::data::chat::Message;
|
||||
use crate::error::DecodeError;
|
||||
use crate::{set_packet_id, version::PacketId};
|
||||
use byteorder::{ReadBytesExt, WriteBytesExt};
|
||||
use minecraft_protocol_derive::{Decoder, Encoder};
|
||||
use nbt::CompoundTag;
|
||||
|
||||
set_packet_id!(ServerBoundPluginMessage, 0x0B);
|
||||
set_packet_id!(ServerBoundKeepAlive, 0x10);
|
||||
|
||||
set_packet_id!(ClientBoundPluginMessage, 0x17);
|
||||
set_packet_id!(NamedSoundEffect, 0x18);
|
||||
set_packet_id!(JoinGame, 0x24);
|
||||
set_packet_id!(PlayerPositionAndLook, 0x34);
|
||||
set_packet_id!(Respawn, 0x39);
|
||||
set_packet_id!(TimeUpdate, 0x4E);
|
||||
set_packet_id!(Title, 0x4F);
|
||||
set_packet_id!(ClientBoundKeepAlive, 0x1F);
|
||||
|
||||
#[derive(Encoder, Decoder, Debug)]
|
||||
pub struct ServerBoundPluginMessage {
|
||||
#[data_type(max_length = 32767)]
|
||||
pub channel: String,
|
||||
pub data: Vec<u8>,
|
||||
}
|
||||
|
||||
#[derive(Encoder, Decoder)]
|
||||
pub struct ServerBoundKeepAlive {
|
||||
pub id: u64,
|
||||
}
|
||||
|
||||
#[derive(Encoder, Decoder, Debug)]
|
||||
pub struct ClientBoundPluginMessage {
|
||||
#[data_type(max_length = 32767)]
|
||||
pub channel: String,
|
||||
pub data: Vec<u8>,
|
||||
}
|
||||
|
||||
// TODO(timvisee): remove clone?
|
||||
#[derive(Clone, Encoder, Decoder, Debug)]
|
||||
pub struct NamedSoundEffect {
|
||||
#[data_type(max_length = 32767)]
|
||||
pub sound_name: String,
|
||||
#[data_type(with = "var_int")]
|
||||
pub sound_category: i32,
|
||||
// Mulitplied by 8
|
||||
pub effect_pos_x: i32,
|
||||
// Mulitplied by 8
|
||||
pub effect_pos_y: i32,
|
||||
// Mulitplied by 8
|
||||
pub effect_pos_z: i32,
|
||||
pub volume: f32,
|
||||
pub pitch: f32,
|
||||
}
|
||||
|
||||
// TODO(timvisee): remove clone?
|
||||
#[derive(Clone, Encoder, Decoder, Debug)]
|
||||
pub struct JoinGame {
|
||||
pub entity_id: u32,
|
||||
pub hardcore: bool,
|
||||
pub game_mode: u8,
|
||||
pub previous_game_mode: u8,
|
||||
// TODO: max string length: 32767
|
||||
pub world_names: Vec<String>,
|
||||
pub dimension_codec: CompoundTag,
|
||||
pub dimension: CompoundTag,
|
||||
#[data_type(max_length = 32767)]
|
||||
pub world_name: String,
|
||||
pub hashed_seed: i64,
|
||||
#[data_type(with = "var_int")]
|
||||
pub max_players: i32,
|
||||
#[data_type(with = "var_int")]
|
||||
pub view_distance: i32,
|
||||
pub reduced_debug_info: bool,
|
||||
pub enable_respawn_screen: bool,
|
||||
pub is_debug: bool,
|
||||
pub is_flat: bool,
|
||||
}
|
||||
|
||||
#[derive(Encoder, Decoder, Debug)]
|
||||
pub struct PlayerPositionAndLook {
|
||||
pub x: f64,
|
||||
pub y: f64,
|
||||
pub z: f64,
|
||||
pub yaw: f32,
|
||||
pub pitch: f32,
|
||||
pub flags: u8,
|
||||
#[data_type(with = "var_int")]
|
||||
pub teleport_id: i32,
|
||||
}
|
||||
|
||||
#[derive(Encoder, Decoder, Debug)]
|
||||
pub struct Respawn {
|
||||
pub dimension: CompoundTag,
|
||||
#[data_type(max_length = 32767)]
|
||||
pub world_name: String,
|
||||
pub hashed_seed: i64,
|
||||
pub game_mode: u8,
|
||||
pub previous_game_mode: u8,
|
||||
pub is_debug: bool,
|
||||
pub is_flat: bool,
|
||||
pub copy_metadata: bool,
|
||||
}
|
||||
|
||||
#[derive(Encoder, Decoder, Debug)]
|
||||
pub struct TimeUpdate {
|
||||
pub world_age: i64,
|
||||
pub time_of_day: i64,
|
||||
}
|
||||
|
||||
#[derive(Encoder, Decoder, Debug)]
|
||||
pub struct Title {
|
||||
pub action: TitleAction,
|
||||
}
|
||||
|
||||
#[derive(Encoder, Decoder, Debug)]
|
||||
pub enum TitleAction {
|
||||
SetTitle {
|
||||
text: Message,
|
||||
},
|
||||
SetSubtitle {
|
||||
text: Message,
|
||||
},
|
||||
SetActionBar {
|
||||
text: Message,
|
||||
},
|
||||
SetTimesAndDisplay {
|
||||
fade_in: i32,
|
||||
stay: i32,
|
||||
fade_out: i32,
|
||||
},
|
||||
Hide,
|
||||
Reset,
|
||||
}
|
||||
|
||||
#[derive(Encoder, Decoder, Debug)]
|
||||
pub struct ClientBoundKeepAlive {
|
||||
pub id: u64,
|
||||
}
|
6
protocol/src/version/v1_16_3/mod.rs
Normal file
6
protocol/src/version/v1_16_3/mod.rs
Normal file
@@ -0,0 +1,6 @@
|
||||
// Spec: https://wiki.vg/index.php?title=Protocol&oldid=16091
|
||||
|
||||
pub mod game;
|
||||
|
||||
/// Minecraft protocol version.
|
||||
pub const PROTOCOL: u32 = 753;
|
6
protocol/src/version/v1_16_4/game.rs
Normal file
6
protocol/src/version/v1_16_4/game.rs
Normal file
@@ -0,0 +1,6 @@
|
||||
// Re-export
|
||||
pub use crate::version::v1_16_3::game::{
|
||||
ClientBoundKeepAlive, ClientBoundPluginMessage, JoinGame, NamedSoundEffect,
|
||||
PlayerPositionAndLook, Respawn, ServerBoundKeepAlive, ServerBoundPluginMessage, TimeUpdate,
|
||||
Title,
|
||||
};
|
6
protocol/src/version/v1_16_4/mod.rs
Normal file
6
protocol/src/version/v1_16_4/mod.rs
Normal file
@@ -0,0 +1,6 @@
|
||||
// Spec: https://wiki.vg/index.php?title=Protocol&oldid=16317
|
||||
|
||||
pub mod game;
|
||||
|
||||
/// Minecraft protocol version.
|
||||
pub const PROTOCOL: u32 = 754;
|
132
protocol/src/version/v1_17/game.rs
Normal file
132
protocol/src/version/v1_17/game.rs
Normal file
@@ -0,0 +1,132 @@
|
||||
use crate::data::chat::Message;
|
||||
use crate::{set_packet_id, version::PacketId};
|
||||
use minecraft_protocol_derive::{Decoder, Encoder};
|
||||
use nbt::CompoundTag;
|
||||
|
||||
set_packet_id!(ServerBoundPluginMessage, 0x0A);
|
||||
set_packet_id!(ServerBoundKeepAlive, 0x0F);
|
||||
|
||||
set_packet_id!(ClientBoundPluginMessage, 0x18);
|
||||
set_packet_id!(NamedSoundEffect, 0x19);
|
||||
set_packet_id!(JoinGame, 0x26);
|
||||
set_packet_id!(PlayerPositionAndLook, 0x38);
|
||||
set_packet_id!(Respawn, 0x3D);
|
||||
set_packet_id!(SetTitleSubtitle, 0x57);
|
||||
set_packet_id!(TimeUpdate, 0x58);
|
||||
set_packet_id!(SetTitleText, 0x59);
|
||||
set_packet_id!(SetTitleTimes, 0x5A);
|
||||
set_packet_id!(ClientBoundKeepAlive, 0x21);
|
||||
|
||||
#[derive(Encoder, Decoder, Debug)]
|
||||
pub struct ServerBoundPluginMessage {
|
||||
#[data_type(max_length = 32767)]
|
||||
pub channel: String,
|
||||
pub data: Vec<u8>,
|
||||
}
|
||||
|
||||
#[derive(Encoder, Decoder)]
|
||||
pub struct ServerBoundKeepAlive {
|
||||
pub id: u64,
|
||||
}
|
||||
|
||||
#[derive(Encoder, Decoder, Debug)]
|
||||
pub struct ClientBoundPluginMessage {
|
||||
#[data_type(max_length = 32767)]
|
||||
pub channel: String,
|
||||
pub data: Vec<u8>,
|
||||
}
|
||||
|
||||
// TODO(timvisee): remove clone?
|
||||
#[derive(Clone, Encoder, Decoder, Debug)]
|
||||
pub struct NamedSoundEffect {
|
||||
#[data_type(max_length = 32767)]
|
||||
pub sound_name: String,
|
||||
#[data_type(with = "var_int")]
|
||||
pub sound_category: i32,
|
||||
// Mulitplied by 8
|
||||
pub effect_pos_x: i32,
|
||||
// Mulitplied by 8
|
||||
pub effect_pos_y: i32,
|
||||
// Mulitplied by 8
|
||||
pub effect_pos_z: i32,
|
||||
pub volume: f32,
|
||||
pub pitch: f32,
|
||||
}
|
||||
|
||||
// TODO(timvisee): remove clone?
|
||||
#[derive(Clone, Encoder, Decoder, Debug)]
|
||||
pub struct JoinGame {
|
||||
pub entity_id: u32,
|
||||
pub hardcore: bool,
|
||||
pub game_mode: u8,
|
||||
pub previous_game_mode: u8,
|
||||
// TODO: max string length: 32767
|
||||
pub world_names: Vec<String>,
|
||||
pub dimension_codec: CompoundTag,
|
||||
pub dimension: CompoundTag,
|
||||
#[data_type(max_length = 32767)]
|
||||
pub world_name: String,
|
||||
pub hashed_seed: i64,
|
||||
#[data_type(with = "var_int")]
|
||||
pub max_players: i32,
|
||||
#[data_type(with = "var_int")]
|
||||
pub view_distance: i32,
|
||||
pub reduced_debug_info: bool,
|
||||
pub enable_respawn_screen: bool,
|
||||
pub is_debug: bool,
|
||||
pub is_flat: bool,
|
||||
}
|
||||
|
||||
#[derive(Encoder, Decoder, Debug)]
|
||||
pub struct Respawn {
|
||||
pub dimension: CompoundTag,
|
||||
#[data_type(max_length = 32767)]
|
||||
pub world_name: String,
|
||||
pub hashed_seed: i64,
|
||||
pub game_mode: u8,
|
||||
pub previous_game_mode: u8,
|
||||
pub is_debug: bool,
|
||||
pub is_flat: bool,
|
||||
pub copy_metadata: bool,
|
||||
}
|
||||
|
||||
#[derive(Encoder, Decoder, Debug)]
|
||||
pub struct PlayerPositionAndLook {
|
||||
pub x: f64,
|
||||
pub y: f64,
|
||||
pub z: f64,
|
||||
pub yaw: f32,
|
||||
pub pitch: f32,
|
||||
pub flags: u8,
|
||||
#[data_type(with = "var_int")]
|
||||
pub teleport_id: i32,
|
||||
pub dismount_vehicle: bool,
|
||||
}
|
||||
|
||||
#[derive(Encoder, Decoder, Debug)]
|
||||
pub struct TimeUpdate {
|
||||
pub world_age: i64,
|
||||
pub time_of_day: i64,
|
||||
}
|
||||
|
||||
#[derive(Encoder, Decoder, Debug)]
|
||||
pub struct SetTitleText {
|
||||
pub text: Message,
|
||||
}
|
||||
|
||||
#[derive(Encoder, Decoder, Debug)]
|
||||
pub struct SetTitleSubtitle {
|
||||
pub text: Message,
|
||||
}
|
||||
|
||||
#[derive(Encoder, Decoder, Debug)]
|
||||
pub struct SetTitleTimes {
|
||||
pub fade_in: i32,
|
||||
pub stay: i32,
|
||||
pub fade_out: i32,
|
||||
}
|
||||
|
||||
#[derive(Encoder, Decoder, Debug)]
|
||||
pub struct ClientBoundKeepAlive {
|
||||
pub id: u64,
|
||||
}
|
6
protocol/src/version/v1_17/mod.rs
Normal file
6
protocol/src/version/v1_17/mod.rs
Normal file
@@ -0,0 +1,6 @@
|
||||
// Spec: https://wiki.vg/index.php?title=Protocol&oldid=16866
|
||||
|
||||
pub mod game;
|
||||
|
||||
/// Minecraft protocol version.
|
||||
pub const PROTOCOL: u32 = 755;
|
@@ -1,313 +1,6 @@
|
||||
use crate::data::chat::Message;
|
||||
use crate::decoder::Decoder;
|
||||
use crate::error::DecodeError;
|
||||
use crate::{trait_packet_id, version::PacketId};
|
||||
use minecraft_protocol_derive::Decoder;
|
||||
use minecraft_protocol_derive::Encoder;
|
||||
use nbt::CompoundTag;
|
||||
use std::io::Read;
|
||||
|
||||
// Re-export Minecraft 1.14.4 types
|
||||
pub use super::super::v1_14_4::game::{
|
||||
BossBar, ChunkData, ClientBoundChatMessage, ClientBoundKeepAlive, EntityAction, GameDisconnect,
|
||||
ServerBoundAbilities, ServerBoundChatMessage, ServerBoundKeepAlive,
|
||||
// Re-export
|
||||
pub use crate::version::v1_17::game::{
|
||||
ClientBoundKeepAlive, ClientBoundPluginMessage, JoinGame, NamedSoundEffect,
|
||||
PlayerPositionAndLook, Respawn, ServerBoundKeepAlive, ServerBoundPluginMessage,
|
||||
SetTitleSubtitle, SetTitleText, SetTitleTimes, TimeUpdate,
|
||||
};
|
||||
|
||||
pub enum GameServerBoundPacket {
|
||||
ServerBoundChatMessage(ServerBoundChatMessage),
|
||||
ServerBoundPluginMessage(ServerBoundPluginMessage),
|
||||
ServerBoundKeepAlive(ServerBoundKeepAlive),
|
||||
ServerBoundAbilities(ServerBoundAbilities),
|
||||
}
|
||||
|
||||
pub enum GameClientBoundPacket {
|
||||
ClientBoundChatMessage(ClientBoundChatMessage),
|
||||
JoinGame(JoinGame),
|
||||
ClientBoundKeepAlive(ClientBoundKeepAlive),
|
||||
ChunkData(ChunkData),
|
||||
GameDisconnect(GameDisconnect),
|
||||
BossBar(BossBar),
|
||||
EntityAction(EntityAction),
|
||||
|
||||
ClientBoundPluginMessage(ClientBoundPluginMessage),
|
||||
NamedSoundEffect(NamedSoundEffect),
|
||||
Respawn(Respawn),
|
||||
PlayerPositionAndLook(PlayerPositionAndLook),
|
||||
SpawnPosition(SpawnPosition),
|
||||
SetTitleSubtitle(SetTitleSubtitle),
|
||||
SetTitleText(SetTitleText),
|
||||
TimeUpdate(TimeUpdate),
|
||||
SetTitleTimes(SetTitleTimes),
|
||||
}
|
||||
|
||||
impl GameServerBoundPacket {
|
||||
pub fn get_type_id(&self) -> u8 {
|
||||
match self {
|
||||
GameServerBoundPacket::ServerBoundChatMessage(_) => 0x03,
|
||||
GameServerBoundPacket::ServerBoundPluginMessage(_) => 0x0A,
|
||||
GameServerBoundPacket::ServerBoundKeepAlive(_) => 0x0F,
|
||||
GameServerBoundPacket::ServerBoundAbilities(_) => 0x19,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn decode<R: Read>(type_id: u8, reader: &mut R) -> Result<Self, DecodeError> {
|
||||
match type_id {
|
||||
0x03 => {
|
||||
let chat_message = ServerBoundChatMessage::decode(reader)?;
|
||||
|
||||
Ok(GameServerBoundPacket::ServerBoundChatMessage(chat_message))
|
||||
}
|
||||
0x0A => {
|
||||
let plugin_message = ServerBoundPluginMessage::decode(reader)?;
|
||||
|
||||
Ok(GameServerBoundPacket::ServerBoundPluginMessage(
|
||||
plugin_message,
|
||||
))
|
||||
}
|
||||
0x0F => {
|
||||
let keep_alive = ServerBoundKeepAlive::decode(reader)?;
|
||||
|
||||
Ok(GameServerBoundPacket::ServerBoundKeepAlive(keep_alive))
|
||||
}
|
||||
0x19 => {
|
||||
let abilities = ServerBoundAbilities::decode(reader)?;
|
||||
|
||||
Ok(GameServerBoundPacket::ServerBoundAbilities(abilities))
|
||||
}
|
||||
_ => Err(DecodeError::UnknownPacketType { type_id }),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GameClientBoundPacket {
|
||||
pub fn get_type_id(&self) -> u8 {
|
||||
match self {
|
||||
GameClientBoundPacket::ClientBoundChatMessage(_) => 0x0E,
|
||||
GameClientBoundPacket::ClientBoundPluginMessage(_) => 0x18,
|
||||
GameClientBoundPacket::NamedSoundEffect(_) => 0x19,
|
||||
GameClientBoundPacket::GameDisconnect(_) => 0x1A,
|
||||
GameClientBoundPacket::ClientBoundKeepAlive(_) => 0x20,
|
||||
GameClientBoundPacket::ChunkData(_) => 0x21,
|
||||
GameClientBoundPacket::JoinGame(_) => 0x25,
|
||||
GameClientBoundPacket::BossBar(_) => 0x0D,
|
||||
GameClientBoundPacket::EntityAction(_) => 0x1B,
|
||||
GameClientBoundPacket::PlayerPositionAndLook(_) => 0x38,
|
||||
GameClientBoundPacket::Respawn(_) => 0x3D,
|
||||
GameClientBoundPacket::SpawnPosition(_) => 0x4B,
|
||||
GameClientBoundPacket::SetTitleSubtitle(_) => 0x57,
|
||||
GameClientBoundPacket::TimeUpdate(_) => 0x58,
|
||||
GameClientBoundPacket::SetTitleText(_) => 0x59,
|
||||
GameClientBoundPacket::SetTitleTimes(_) => 0x5A,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn decode<R: Read>(type_id: u8, reader: &mut R) -> Result<Self, DecodeError> {
|
||||
match type_id {
|
||||
0x0E => {
|
||||
let chat_message = ClientBoundChatMessage::decode(reader)?;
|
||||
|
||||
Ok(GameClientBoundPacket::ClientBoundChatMessage(chat_message))
|
||||
}
|
||||
0x18 => {
|
||||
let plugin_message = ClientBoundPluginMessage::decode(reader)?;
|
||||
|
||||
Ok(GameClientBoundPacket::ClientBoundPluginMessage(
|
||||
plugin_message,
|
||||
))
|
||||
}
|
||||
0x19 => {
|
||||
let named_sound_effect = NamedSoundEffect::decode(reader)?;
|
||||
|
||||
Ok(GameClientBoundPacket::NamedSoundEffect(named_sound_effect))
|
||||
}
|
||||
0x1A => {
|
||||
let game_disconnect = GameDisconnect::decode(reader)?;
|
||||
|
||||
Ok(GameClientBoundPacket::GameDisconnect(game_disconnect))
|
||||
}
|
||||
0x20 => {
|
||||
let keep_alive = ClientBoundKeepAlive::decode(reader)?;
|
||||
|
||||
Ok(GameClientBoundPacket::ClientBoundKeepAlive(keep_alive))
|
||||
}
|
||||
0x21 => {
|
||||
let chunk_data = ChunkData::decode(reader)?;
|
||||
|
||||
Ok(GameClientBoundPacket::ChunkData(chunk_data))
|
||||
}
|
||||
0x25 => {
|
||||
let join_game = JoinGame::decode(reader)?;
|
||||
|
||||
Ok(GameClientBoundPacket::JoinGame(join_game))
|
||||
}
|
||||
0x3D => {
|
||||
let respawn = Respawn::decode(reader)?;
|
||||
|
||||
Ok(GameClientBoundPacket::Respawn(respawn))
|
||||
}
|
||||
0x38 => {
|
||||
let player_position = PlayerPositionAndLook::decode(reader)?;
|
||||
|
||||
Ok(GameClientBoundPacket::PlayerPositionAndLook(
|
||||
player_position,
|
||||
))
|
||||
}
|
||||
0x4B => {
|
||||
let spawn_position = SpawnPosition::decode(reader)?;
|
||||
|
||||
Ok(GameClientBoundPacket::SpawnPosition(spawn_position))
|
||||
}
|
||||
0x57 => {
|
||||
let title_subtitle = SetTitleSubtitle::decode(reader)?;
|
||||
|
||||
Ok(GameClientBoundPacket::SetTitleSubtitle(title_subtitle))
|
||||
}
|
||||
0x58 => {
|
||||
let time_update = TimeUpdate::decode(reader)?;
|
||||
|
||||
Ok(GameClientBoundPacket::TimeUpdate(time_update))
|
||||
}
|
||||
0x59 => {
|
||||
let title_text = SetTitleText::decode(reader)?;
|
||||
|
||||
Ok(GameClientBoundPacket::SetTitleText(title_text))
|
||||
}
|
||||
0x5A => {
|
||||
let title_times = SetTitleTimes::decode(reader)?;
|
||||
|
||||
Ok(GameClientBoundPacket::SetTitleTimes(title_times))
|
||||
}
|
||||
_ => Err(DecodeError::UnknownPacketType { type_id }),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(timvisee): implement new()
|
||||
#[derive(Encoder, Decoder, Debug)]
|
||||
pub struct ServerBoundPluginMessage {
|
||||
#[data_type(max_length = 32767)]
|
||||
pub channel: String,
|
||||
pub data: Vec<u8>,
|
||||
}
|
||||
|
||||
// TODO(timvisee): implement new()
|
||||
#[derive(Encoder, Decoder, Debug)]
|
||||
pub struct ClientBoundPluginMessage {
|
||||
#[data_type(max_length = 32767)]
|
||||
pub channel: String,
|
||||
pub data: Vec<u8>,
|
||||
}
|
||||
|
||||
// TODO(timvisee): implement new()
|
||||
// TODO(timvisee): remove clone?
|
||||
#[derive(Clone, Encoder, Decoder, Debug)]
|
||||
pub struct NamedSoundEffect {
|
||||
#[data_type(max_length = 32767)]
|
||||
pub sound_name: String,
|
||||
#[data_type(with = "var_int")]
|
||||
pub sound_category: i32,
|
||||
// Mulitplied by 8
|
||||
pub effect_pos_x: i32,
|
||||
// Mulitplied by 8
|
||||
pub effect_pos_y: i32,
|
||||
// Mulitplied by 8
|
||||
pub effect_pos_z: i32,
|
||||
pub volume: f32,
|
||||
pub pitch: f32,
|
||||
}
|
||||
|
||||
// TODO(timvisee): implement new()
|
||||
// TODO(timvisee): remove clone?
|
||||
#[derive(Clone, Encoder, Decoder, Debug)]
|
||||
pub struct JoinGame {
|
||||
pub entity_id: u32,
|
||||
pub hardcore: bool,
|
||||
pub game_mode: u8,
|
||||
pub previous_game_mode: u8,
|
||||
// TODO: max string length: 32767
|
||||
pub world_names: Vec<String>,
|
||||
pub dimension_codec: CompoundTag,
|
||||
pub dimension: CompoundTag,
|
||||
#[data_type(max_length = 32767)]
|
||||
pub world_name: String,
|
||||
pub hashed_seed: i64,
|
||||
#[data_type(with = "var_int")]
|
||||
pub max_players: i32,
|
||||
#[data_type(with = "var_int")]
|
||||
pub view_distance: i32,
|
||||
pub reduced_debug_info: bool,
|
||||
pub enable_respawn_screen: bool,
|
||||
pub is_debug: bool,
|
||||
pub is_flat: bool,
|
||||
}
|
||||
|
||||
// TODO(timvisee): implement new()
|
||||
#[derive(Encoder, Decoder, Debug)]
|
||||
pub struct Respawn {
|
||||
pub dimension: CompoundTag,
|
||||
#[data_type(max_length = 32767)]
|
||||
pub world_name: String,
|
||||
pub hashed_seed: i64,
|
||||
pub game_mode: u8,
|
||||
pub previous_game_mode: u8,
|
||||
pub is_debug: bool,
|
||||
pub is_flat: bool,
|
||||
pub copy_metadata: bool,
|
||||
}
|
||||
|
||||
// TODO(timvisee): implement new()
|
||||
#[derive(Encoder, Decoder, Debug)]
|
||||
pub struct PlayerPositionAndLook {
|
||||
pub x: f64,
|
||||
pub y: f64,
|
||||
pub z: f64,
|
||||
pub yaw: f32,
|
||||
pub pitch: f32,
|
||||
pub flags: u8,
|
||||
#[data_type(with = "var_int")]
|
||||
pub teleport_id: i32,
|
||||
pub dismount_vehicle: bool,
|
||||
}
|
||||
|
||||
// TODO(timvisee): implement new()
|
||||
#[derive(Encoder, Decoder, Debug)]
|
||||
pub struct TimeUpdate {
|
||||
pub world_age: i64,
|
||||
pub time_of_day: i64,
|
||||
}
|
||||
|
||||
#[derive(Encoder, Decoder, Debug)]
|
||||
pub struct SetTitleText {
|
||||
pub text: Message,
|
||||
}
|
||||
|
||||
#[derive(Encoder, Decoder, Debug)]
|
||||
pub struct SetTitleSubtitle {
|
||||
pub text: Message,
|
||||
}
|
||||
|
||||
#[derive(Encoder, Decoder, Debug)]
|
||||
pub struct SetTitleTimes {
|
||||
pub fade_in: i32,
|
||||
pub stay: i32,
|
||||
pub fade_out: i32,
|
||||
}
|
||||
|
||||
#[derive(Encoder, Decoder, Debug)]
|
||||
pub struct SpawnPosition {
|
||||
pub position: u64,
|
||||
pub angle: f32,
|
||||
}
|
||||
|
||||
trait_packet_id!(ServerBoundPluginMessage, 0x0A);
|
||||
|
||||
trait_packet_id!(ClientBoundPluginMessage, 0x18);
|
||||
trait_packet_id!(NamedSoundEffect, 0x19);
|
||||
trait_packet_id!(JoinGame, 0x26);
|
||||
trait_packet_id!(PlayerPositionAndLook, 0x38);
|
||||
trait_packet_id!(Respawn, 0x3D);
|
||||
trait_packet_id!(SpawnPosition, 0x4B);
|
||||
trait_packet_id!(SetTitleSubtitle, 0x57);
|
||||
trait_packet_id!(TimeUpdate, 0x58);
|
||||
trait_packet_id!(SetTitleText, 0x59);
|
||||
trait_packet_id!(SetTitleTimes, 0x5A);
|
||||
|
@@ -1 +1,6 @@
|
||||
// Spec: https://wiki.vg/index.php?title=Protocol&oldid=16918
|
||||
|
||||
pub mod game;
|
||||
|
||||
/// Minecraft protocol version.
|
||||
pub const PROTOCOL: u32 = 756;
|
||||
|
Reference in New Issue
Block a user