1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
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(())
}
|