diff options
author | nea <nea@nea.moe> | 2023-01-29 20:38:21 +0100 |
---|---|---|
committer | nea <nea@nea.moe> | 2023-01-29 20:38:21 +0100 |
commit | b9e1d23e2000cca681370cb9d215efa8c74ef52b (patch) | |
tree | 3fc15554b060ef51d26e0e50ed4f2076e416f93d /src | |
download | mgasi-b9e1d23e2000cca681370cb9d215efa8c74ef52b.tar.gz mgasi-b9e1d23e2000cca681370cb9d215efa8c74ef52b.tar.bz2 mgasi-b9e1d23e2000cca681370cb9d215efa8c74ef52b.zip |
initial
Diffstat (limited to 'src')
-rw-r--r-- | src/main.rs | 98 |
1 files changed, 98 insertions, 0 deletions
diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..8f925e3 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,98 @@ +use std::net::{IpAddr, Ipv4Addr, SocketAddr, TcpListener, TcpStream}; + +use anyhow::Result; +use craftio_rs::{CraftIo, CraftSyncReader, CraftSyncWriter, CraftTcpConnection}; +use mcproto_rs::protocol::State; +use mcproto_rs::status::{StatusFaviconSpec, StatusPlayersSpec, StatusSpec, StatusVersionSpec}; +use mcproto_rs::types::{Chat, TextComponent}; +use mcproto_rs::types::Chat::Text; +use mcproto_rs::v1_19::{HandshakeNextState, Packet759, RawPacket759, StatusPingSpec, StatusPongSpec, StatusResponseSpec}; +use mcproto_rs::v1_19::Packet759Kind::{Handshake, PlayServerPlayerAbilities}; +use tokio; + +pub struct MinecraftClient { + connection: CraftTcpConnection, +} + +impl MinecraftClient { + pub fn new(connection: CraftTcpConnection) -> Self { + Self { connection } + } + + pub fn from_stream(stream: TcpStream) -> anyhow::Result<Self> { + Ok(Self { + connection: CraftTcpConnection::from_std(stream, mcproto_rs::protocol::PacketDirection::ServerBound)?, + }) + } + pub async fn read_next_packet(&mut self) -> Result<Option<Packet759>> { + if let Some(raw) = self.connection.read_packet::<RawPacket759>()? { + println!("Client -> Server: {:?}", raw); + Ok(Some(raw)) + } else { + Ok(None) + } + } + pub async fn send_packet(&mut self, packet: Packet759) -> Result<()> { + self.connection.write_packet(packet)?; + Ok(()) + } +} + +macro_rules! assert_packet { + ($packet_type:ident, $obj:expr) => {if let Packet759::$packet_type(packet_data) = $obj { packet_data } else {panic!("Expected packet of type {}", stringify!($packet_type))}}; +} + +#[tokio::main] +async fn main() -> Result<()> { + println!("Starting server"); + let bind = TcpListener::bind(SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), 25565))?; + loop { + if let Ok((socket, address)) = bind.accept() { + println!("Connection accepted from {}", address); + let mut client = MinecraftClient::from_stream(socket)?; + if let Err(x) = handle_conn(client).await { + println!("Error: {:?}", x); + } + } + } +} + +async fn handle_conn(mut client: MinecraftClient) -> Result<()> { + let hs = assert_packet!(Handshake, client.read_next_packet().await?.ok_or(anyhow::anyhow!("Missing packet"))?); + println!("Hs: {:?}", hs); + if hs.next_state == HandshakeNextState::Login { + client.connection.set_state(State::Login); + let loginstart = assert_packet!(LoginStart, client.read_next_packet().await?.ok_or(anyhow::anyhow!("Missing packet"))?); + println!("Login: {:?}", loginstart) + } else { + client.connection.set_state(State::Status); + loop { + println!("Polling status packet"); + match client.read_next_packet().await?.ok_or(anyhow::anyhow!("Missing packet"))? { + Packet759::StatusRequest(_) => { + client.send_packet(Packet759::StatusResponse(StatusResponseSpec { + response: StatusSpec { + version: Some(StatusVersionSpec { name: "1.19 mgasi".to_string(), protocol: 759 }), + players: StatusPlayersSpec { + max: 100, + online: 0, + sample: vec![], + }, + description: Chat::from_text("hehehe"), + favicon: None, + }, + })).await?; + } + Packet759::StatusPing(StatusPingSpec { payload }) => { + client.send_packet(Packet759::StatusPong(StatusPongSpec { + payload, + })).await?; + return Ok(()) + } + _ => anyhow::bail!("") + } + } + } + Ok(()) +} + |