1
2
Fork 0
mirror of https://github.com/mat-1/azalea.git synced 2025-08-02 14:26:04 +00:00

make Connection a single struct with generics

This isn't that good of a solution but I couldn't come up with a better one and this was pretty simple to implement
This commit is contained in:
mat 2022-07-29 16:29:06 -05:00
parent 0f380f1a12
commit 0c2ce00bae
3 changed files with 70 additions and 94 deletions

View file

@ -3,7 +3,7 @@ use azalea_auth::game_profile::GameProfile;
use azalea_core::{ChunkPos, EntityPos, PositionDelta, PositionDeltaTrait, ResourceLocation};
use azalea_entity::Entity;
use azalea_protocol::{
connect::{GameConnection, HandshakeConnection},
connect::Connection,
packets::{
game::{
clientbound_player_chat_packet::ClientboundPlayerChatPacket,
@ -12,7 +12,7 @@ use azalea_protocol::{
serverbound_custom_payload_packet::ServerboundCustomPayloadPacket,
serverbound_keep_alive_packet::ServerboundKeepAlivePacket,
serverbound_move_player_packet_pos_rot::ServerboundMovePlayerPacketPosRot,
ClientboundGamePacket,
ClientboundGamePacket, ServerboundGamePacket,
},
handshake::client_intention_packet::ClientIntentionPacket,
login::{
@ -61,7 +61,7 @@ pub enum ChatPacket {
#[derive(Clone)]
pub struct Client {
game_profile: GameProfile,
pub conn: Arc<tokio::sync::Mutex<GameConnection>>,
pub conn: Arc<tokio::sync::Mutex<Connection<ClientboundGamePacket, ServerboundGamePacket>>>,
pub player: Arc<Mutex<Player>>,
pub dimension: Arc<Mutex<Option<Dimension>>>,
// game_loop
@ -81,7 +81,7 @@ impl Client {
) -> Result<(Self, UnboundedReceiver<Event>), String> {
let resolved_address = resolver::resolve_address(address).await?;
let mut conn = HandshakeConnection::new(&resolved_address).await?;
let mut conn = Connection::new(&resolved_address).await?;
// handshake
conn.write(

View file

@ -1,6 +1,6 @@
///! Ping Minecraft servers.
use azalea_protocol::{
connect::HandshakeConnection,
connect::Connection,
packets::{
handshake::client_intention_packet::ClientIntentionPacket,
status::{
@ -18,7 +18,7 @@ pub async fn ping_server(
) -> Result<ClientboundStatusResponsePacket, String> {
let resolved_address = resolver::resolve_address(address).await?;
let mut conn = HandshakeConnection::new(&resolved_address).await?;
let mut conn = Connection::new(&resolved_address).await?;
// send the client intention packet and switch to the status state
conn.write(

View file

@ -4,40 +4,58 @@ use crate::packets::game::{ClientboundGamePacket, ServerboundGamePacket};
use crate::packets::handshake::{ClientboundHandshakePacket, ServerboundHandshakePacket};
use crate::packets::login::{ClientboundLoginPacket, ServerboundLoginPacket};
use crate::packets::status::{ClientboundStatusPacket, ServerboundStatusPacket};
use crate::packets::ProtocolPacket;
use crate::read::read_packet;
use crate::write::write_packet;
use crate::ServerIpAddress;
use azalea_crypto::{Aes128CfbDec, Aes128CfbEnc};
use std::fmt::Debug;
use std::marker::PhantomData;
use tokio::net::TcpStream;
pub struct HandshakeConnection {
/// The buffered writer
pub stream: TcpStream,
}
pub struct Handshake;
pub struct Game;
pub struct Status;
pub struct Login;
pub struct GameConnection {
pub struct Connection<R: ProtocolPacket, W: ProtocolPacket> {
/// The buffered writer
pub stream: TcpStream,
pub compression_threshold: Option<u32>,
pub enc_cipher: Option<Aes128CfbEnc>,
pub dec_cipher: Option<Aes128CfbDec>,
_reading: PhantomData<R>,
_writing: PhantomData<W>,
}
pub struct StatusConnection {
/// The buffered writer
pub stream: TcpStream,
impl<R, W> Connection<R, W>
where
R: ProtocolPacket + Debug,
W: ProtocolPacket + Debug,
{
pub async fn read(&mut self) -> Result<R, String> {
read_packet::<R, _>(
&mut self.stream,
self.compression_threshold,
&mut self.dec_cipher,
)
.await
}
/// Write a packet to the server
pub async fn write(&mut self, packet: W) {
write_packet(
packet,
&mut self.stream,
self.compression_threshold,
&mut self.enc_cipher,
)
.await;
}
}
pub struct LoginConnection {
/// The buffered writer
pub stream: TcpStream,
pub compression_threshold: Option<u32>,
pub enc_cipher: Option<Aes128CfbEnc>,
pub dec_cipher: Option<Aes128CfbDec>,
}
impl HandshakeConnection {
pub async fn new(address: &ServerIpAddress) -> Result<HandshakeConnection, String> {
impl Connection<ClientboundHandshakePacket, ServerboundHandshakePacket> {
pub async fn new(address: &ServerIpAddress) -> Result<Self, String> {
let ip = address.ip;
let port = address.port;
@ -50,88 +68,44 @@ impl HandshakeConnection {
.set_nodelay(true)
.expect("Error enabling tcp_nodelay");
Ok(HandshakeConnection { stream })
}
pub fn login(self) -> LoginConnection {
LoginConnection {
stream: self.stream,
Ok(Connection {
stream,
compression_threshold: None,
enc_cipher: None,
dec_cipher: None,
}
_reading: PhantomData,
_writing: PhantomData,
})
}
pub fn status(self) -> StatusConnection {
StatusConnection {
pub fn login(self) -> Connection<ClientboundLoginPacket, ServerboundLoginPacket> {
Connection {
stream: self.stream,
compression_threshold: self.compression_threshold,
enc_cipher: self.enc_cipher,
dec_cipher: self.dec_cipher,
_reading: PhantomData,
_writing: PhantomData,
}
}
pub async fn read(&mut self) -> Result<ClientboundHandshakePacket, String> {
read_packet::<ClientboundHandshakePacket, _>(&mut self.stream, None, &mut None).await
}
/// Write a packet to the server
pub async fn write(&mut self, packet: ServerboundHandshakePacket) {
write_packet(packet, &mut self.stream, None, &mut None).await;
pub fn status(self) -> Connection<ClientboundStatusPacket, ServerboundStatusPacket> {
Connection {
stream: self.stream,
compression_threshold: self.compression_threshold,
enc_cipher: self.enc_cipher,
dec_cipher: self.dec_cipher,
_reading: PhantomData,
_writing: PhantomData,
}
}
}
impl GameConnection {
pub async fn read(&mut self) -> Result<ClientboundGamePacket, String> {
read_packet::<ClientboundGamePacket, _>(
&mut self.stream,
self.compression_threshold,
&mut self.dec_cipher,
)
.await
}
impl Connection<ClientboundGamePacket, ServerboundGamePacket> {}
/// Write a packet to the server
pub async fn write(&mut self, packet: ServerboundGamePacket) {
write_packet(
packet,
&mut self.stream,
self.compression_threshold,
&mut self.enc_cipher,
)
.await;
}
}
impl StatusConnection {
pub async fn read(&mut self) -> Result<ClientboundStatusPacket, String> {
read_packet::<ClientboundStatusPacket, _>(&mut self.stream, None, &mut None).await
}
/// Write a packet to the server
pub async fn write(&mut self, packet: ServerboundStatusPacket) {
write_packet(packet, &mut self.stream, None, &mut None).await;
}
}
impl LoginConnection {
pub async fn read(&mut self) -> Result<ClientboundLoginPacket, String> {
read_packet::<ClientboundLoginPacket, _>(
&mut self.stream,
self.compression_threshold,
&mut self.dec_cipher,
)
.await
}
/// Write a packet to the server
pub async fn write(&mut self, packet: ServerboundLoginPacket) {
write_packet(
packet,
&mut self.stream,
self.compression_threshold,
&mut self.enc_cipher,
)
.await;
}
impl Connection<ClientboundStatusPacket, ServerboundStatusPacket> {}
impl Connection<ClientboundLoginPacket, ServerboundLoginPacket> {
pub fn set_compression_threshold(&mut self, threshold: i32) {
// if you pass a threshold of 0 or less, compression is disabled
if threshold > 0 {
@ -148,12 +122,14 @@ impl LoginConnection {
self.dec_cipher = Some(dec_cipher);
}
pub fn game(self) -> GameConnection {
GameConnection {
pub fn game(self) -> Connection<ClientboundGamePacket, ServerboundGamePacket> {
Connection {
stream: self.stream,
compression_threshold: self.compression_threshold,
enc_cipher: self.enc_cipher,
dec_cipher: self.dec_cipher,
_reading: PhantomData,
_writing: PhantomData,
}
}
}