mirror of
https://github.com/mat-1/azalea.git
synced 2025-08-02 06:16:04 +00:00
implement new packet implementation
This commit is contained in:
parent
544c8a3394
commit
0b484df40c
6 changed files with 66 additions and 95 deletions
|
@ -3,7 +3,7 @@ use minecraft_protocol::ServerAddress;
|
|||
use tokio::runtime::Runtime;
|
||||
|
||||
async fn bot() {
|
||||
let address = ServerAddress::parse(&"play.wynncraft.com".to_string()).unwrap();
|
||||
let address = ServerAddress::parse(&"mc.hypixel.net".to_string()).unwrap();
|
||||
minecraft_protocol::server_status_pinger::ping_server(&address)
|
||||
.await
|
||||
.unwrap();
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
use crate::ServerIpAddress;
|
||||
use crate::{friendly_byte_buf::FriendlyByteBuf, packets::Packet, ServerIpAddress};
|
||||
use bytes::BytesMut;
|
||||
use tokio::{io::BufWriter, net::TcpStream};
|
||||
use tokio::{
|
||||
io::{AsyncWriteExt, BufWriter},
|
||||
net::TcpStream,
|
||||
};
|
||||
|
||||
pub enum PacketFlow {
|
||||
ClientToServer,
|
||||
|
@ -35,4 +38,30 @@ impl Connection {
|
|||
buffer: BytesMut::with_capacity(4 * 1024 * 1024),
|
||||
})
|
||||
}
|
||||
|
||||
/// Write a packet to the server
|
||||
pub async fn send_packet(&mut self, packet: &dyn Packet) {
|
||||
// packet structure:
|
||||
// length + id + data
|
||||
|
||||
// Is this efficient? I have no idea, probably not.
|
||||
// getting rid of the FriendlyByteBuffer struct might help
|
||||
|
||||
// write the packet id
|
||||
let mut id_and_data_buf = vec![packet.get_id()];
|
||||
|
||||
// write the packet data
|
||||
let mut id_and_data_friendly_buf = FriendlyByteBuf::new(&mut id_and_data_buf);
|
||||
packet.write(&mut id_and_data_friendly_buf);
|
||||
|
||||
// add the packet length to the beginning
|
||||
let mut complete_buf: Vec<u8> = Vec::new();
|
||||
let mut complete_friendly_buf = FriendlyByteBuf::new(&mut complete_buf);
|
||||
complete_friendly_buf.write_varint(id_and_data_buf.len() as u32);
|
||||
complete_buf.append(&mut id_and_data_buf);
|
||||
|
||||
// finally, write and flush to the stream
|
||||
self.stream.write_all(&complete_buf).await.unwrap();
|
||||
self.stream.flush().await.unwrap();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,22 +1,24 @@
|
|||
//! Minecraft calls it a "friendly byte buffer".
|
||||
|
||||
use byteorder::{BigEndian, WriteBytesExt};
|
||||
// use std::io::Write;
|
||||
|
||||
const MAX_VARINT_SIZE: u32 = 5;
|
||||
const MAX_VARLONG_SIZE: u32 = 10;
|
||||
const DEFAULT_NBT_QUOTA: u32 = 2097152;
|
||||
// const MAX_VARINT_SIZE: u32 = 5;
|
||||
// const MAX_VARLONG_SIZE: u32 = 10;
|
||||
// const DEFAULT_NBT_QUOTA: u32 = 2097152;
|
||||
const MAX_STRING_LENGTH: u16 = 32767;
|
||||
const MAX_COMPONENT_STRING_LENGTH: u32 = 262144;
|
||||
// const MAX_COMPONENT_STRING_LENGTH: u32 = 262144;
|
||||
|
||||
pub struct FriendlyByteBuf<'a> {
|
||||
source: &'a mut Vec<u8>,
|
||||
}
|
||||
|
||||
impl FriendlyByteBuf<'_> {
|
||||
impl<'a> FriendlyByteBuf<'a> {
|
||||
pub fn new(source: &'a mut Vec<u8>) -> FriendlyByteBuf<'a> {
|
||||
FriendlyByteBuf { source }
|
||||
}
|
||||
|
||||
pub fn write_byte(&mut self, n: u8) {
|
||||
self.source.write_u8(n).unwrap();
|
||||
println!("write_byte: {}", n);
|
||||
}
|
||||
|
||||
pub fn write_bytes(&mut self, bytes: &[u8]) {
|
||||
|
|
|
@ -5,17 +5,19 @@ use crate::friendly_byte_buf::FriendlyByteBuf;
|
|||
use super::{ConnectionProtocol, Packet};
|
||||
|
||||
#[derive(Hash)]
|
||||
pub struct ClientIntentionPacket {
|
||||
protocol_version: u32,
|
||||
hostname: String,
|
||||
port: u16,
|
||||
pub struct ClientIntentionPacket<'a> {
|
||||
pub protocol_version: u32,
|
||||
pub hostname: &'a String,
|
||||
pub port: u16,
|
||||
/// 1 for status, 2 for login
|
||||
intention: ConnectionProtocol,
|
||||
pub intention: ConnectionProtocol,
|
||||
}
|
||||
|
||||
// implement "Packet" for "ClientIntentionPacket"
|
||||
impl Packet for ClientIntentionPacket {
|
||||
const ID: u8 = 0x00;
|
||||
impl<'a> Packet for ClientIntentionPacket<'a> {
|
||||
fn get_id(&self) -> u8 {
|
||||
0x00
|
||||
}
|
||||
|
||||
// implement "from_reader" for "ClientIntentionPacket"
|
||||
fn write(&self, buf: &mut FriendlyByteBuf) {
|
||||
|
@ -25,4 +27,3 @@ impl Packet for ClientIntentionPacket {
|
|||
buf.write_varint(self.intention.clone() as u32);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
pub mod client_intention_packet;
|
||||
|
||||
use std::collections::HashMap;
|
||||
mod client_intention_packet;
|
||||
pub use client_intention_packet::ClientIntentionPacket;
|
||||
mod serverbound_status_request_packet;
|
||||
pub use serverbound_status_request_packet::ServerboundStatusRequestPacket;
|
||||
|
||||
use crate::friendly_byte_buf::FriendlyByteBuf;
|
||||
|
||||
|
@ -13,9 +14,8 @@ pub enum ConnectionProtocol {
|
|||
}
|
||||
|
||||
pub trait Packet {
|
||||
/// The id of the packet, this is always a byte in vanilla.
|
||||
/// This might be bigger than a u8 if using modpacks with lots of custom packets?
|
||||
const ID: u8;
|
||||
|
||||
/// Get the id of the packet, this is always a byte.
|
||||
fn get_id(&self) -> u8;
|
||||
|
||||
fn write(&self, friendly_byte_buf: &mut FriendlyByteBuf) -> ();
|
||||
}
|
||||
|
|
|
@ -1,81 +1,22 @@
|
|||
use crate::{connection::Connection, resolver, ServerAddress};
|
||||
use tokio::{
|
||||
io::{AsyncReadExt, AsyncWriteExt, BufWriter},
|
||||
net::TcpStream,
|
||||
};
|
||||
|
||||
struct ServerStatus {}
|
||||
|
||||
async fn write_byte(buf: &mut Vec<u8>, n: u8) {
|
||||
buf.write_u8(n).await.unwrap();
|
||||
println!("write_byte: {}", n);
|
||||
}
|
||||
|
||||
async fn write_bytes(buf: &mut Vec<u8>, bytes: &[u8]) {
|
||||
buf.write_all(bytes).await.unwrap();
|
||||
println!("write_bytes: {:?}", buf);
|
||||
}
|
||||
|
||||
async fn write_varint(buf: &mut Vec<u8>, mut n: u32) {
|
||||
loop {
|
||||
if (n & 0xFFFFFF80) == 0 {
|
||||
write_byte(buf, n as u8).await;
|
||||
return ();
|
||||
}
|
||||
write_byte(buf, (n & 0x7F | 0x80) as u8).await;
|
||||
n >>= 7;
|
||||
}
|
||||
}
|
||||
|
||||
async fn write_utf(buf: &mut Vec<u8>, string: &[u8], len: usize) {
|
||||
if string.len() > len {
|
||||
panic!(
|
||||
"String too big (was {} bytes encoded, max {})",
|
||||
string.len(),
|
||||
len
|
||||
);
|
||||
}
|
||||
write_varint(buf, string.len() as u32).await;
|
||||
write_bytes(buf, string).await;
|
||||
}
|
||||
|
||||
async fn write_short(buf: &mut Vec<u8>, n: u16) {
|
||||
buf.write_u16(n).await.unwrap();
|
||||
println!("write_short: {}", n);
|
||||
}
|
||||
use crate::{connection::Connection, resolver, ServerAddress, packets::{ClientIntentionPacket, ServerboundStatusRequestPacket, ConnectionProtocol}};
|
||||
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||
|
||||
pub async fn ping_server(address: &ServerAddress) -> Result<(), String> {
|
||||
let resolved_address = resolver::resolve_address(&address).await?;
|
||||
|
||||
let mut conn = Connection::new(&resolved_address).await?;
|
||||
|
||||
// protocol version is 757
|
||||
|
||||
// client intention packet
|
||||
// friendlyByteBuf.writeVarInt(this.protocolVersion);
|
||||
// friendlyByteBuf.writeUtf(this.hostName);
|
||||
// friendlyByteBuf.writeShort(this.port);
|
||||
// friendlyByteBuf.writeVarInt(this.intention.getId());
|
||||
|
||||
println!("resolved_address {}", &resolved_address.ip);
|
||||
println!("writing intention packet {}", address.host);
|
||||
|
||||
let mut buf: Vec<u8> = vec![0x00]; // 0 is the packet id for handshake
|
||||
write_varint(&mut buf, 757).await;
|
||||
write_utf(&mut buf, address.host.as_bytes(), 32767).await;
|
||||
write_short(&mut buf, address.port).await;
|
||||
write_varint(&mut buf, 1).await;
|
||||
conn.send_packet(&ClientIntentionPacket {
|
||||
protocol_version: 757,
|
||||
hostname: &address.host,
|
||||
port: address.port,
|
||||
intention: ConnectionProtocol::Status,
|
||||
}).await;
|
||||
conn.send_packet(&ServerboundStatusRequestPacket {}).await;
|
||||
|
||||
let mut full_buffer = vec![];
|
||||
write_varint(&mut full_buffer, buf.len() as u32).await; // length of 1st packet id + data as VarInt
|
||||
full_buffer.append(&mut buf);
|
||||
full_buffer.extend_from_slice(&[
|
||||
1, // length of 2nd packet id + data as VarInt
|
||||
0x00, // 2nd packet id: 0 for request as VarInt
|
||||
]);
|
||||
|
||||
conn.stream.write_all(&full_buffer).await.unwrap();
|
||||
conn.stream.flush().await.unwrap();
|
||||
|
||||
// log what the server sends back
|
||||
loop {
|
||||
|
@ -95,6 +36,4 @@ pub async fn ping_server(address: &ServerAddress) -> Result<(), String> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue