save up to play / status

This commit is contained in:
ElementG9 2020-05-25 14:05:39 -06:00
parent ac3c3b0339
commit ef86b059c5
7 changed files with 1074 additions and 1 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
target/

394
Cargo.lock generated Normal file
View File

@ -0,0 +1,394 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "Composition"
version = "0.1.0"
dependencies = [
"ozelot",
"serde",
"serde_json",
]
[[package]]
name = "addr2line"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a49806b9dadc843c61e7c97e72490ad7f7220ae249012fbda9ad0609457c0543"
dependencies = [
"gimli",
]
[[package]]
name = "adler32"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d2e7343e7fc9de883d1b0341e0b13970f764c14101234857d2ddafa1cb1cac2"
[[package]]
name = "autocfg"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d"
[[package]]
name = "backtrace"
version = "0.3.48"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0df2f85c8a2abbe3b7d7e748052fdd9b76a0458fdeb16ad4223f5eca78c7c130"
dependencies = [
"addr2line",
"cfg-if",
"libc",
"object",
"rustc-demangle",
]
[[package]]
name = "bitflags"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
[[package]]
name = "byteorder"
version = "1.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
[[package]]
name = "cc"
version = "1.0.54"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7bbb73db36c1246e9034e307d0fba23f9a2e251faa47ade70c1bd252220c8311"
[[package]]
name = "cfg-if"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
[[package]]
name = "crc32fast"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1"
dependencies = [
"cfg-if",
]
[[package]]
name = "curl"
version = "0.4.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "762e34611d2d5233a506a79072be944fddd057db2f18e04c0d6fa79e3fd466fd"
dependencies = [
"curl-sys",
"libc",
"openssl-probe",
"openssl-sys",
"schannel",
"socket2",
"winapi",
]
[[package]]
name = "curl-sys"
version = "0.4.31+curl-7.70.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcd62757cc4f5ab9404bc6ca9f0ae447e729a1403948ce5106bd588ceac6a3b0"
dependencies = [
"cc",
"libc",
"libz-sys",
"openssl-sys",
"pkg-config",
"vcpkg",
"winapi",
]
[[package]]
name = "error-chain"
version = "0.12.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d371106cc88ffdfb1eabd7111e432da544f16f3e2d7bf1dfe8bf575f1df045cd"
dependencies = [
"backtrace",
"version_check",
]
[[package]]
name = "flate2"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2cfff41391129e0a856d6d822600b8d71179d46879e310417eb9c762eb178b42"
dependencies = [
"cfg-if",
"crc32fast",
"libc",
"miniz_oxide",
]
[[package]]
name = "foreign-types"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
dependencies = [
"foreign-types-shared",
]
[[package]]
name = "foreign-types-shared"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
[[package]]
name = "gimli"
version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bcc8e0c9bce37868955864dbecd2b1ab2bdf967e6f28066d65aaac620444b65c"
[[package]]
name = "itoa"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e"
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.70"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3baa92041a6fec78c687fa0cc2b3fae8884f743d672cf551bed1d6dac6988d0f"
[[package]]
name = "libz-sys"
version = "1.0.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2eb5e43362e38e2bca2fd5f5134c4d4564a23a5c28e9b95411652021a8675ebe"
dependencies = [
"cc",
"libc",
"pkg-config",
"vcpkg",
]
[[package]]
name = "miniz_oxide"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa679ff6578b1cddee93d7e82e263b94a575e0bfced07284eb0c037c1d2416a5"
dependencies = [
"adler32",
]
[[package]]
name = "netbuf"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f41e95a536af3c11c6dcf16f30b8319aad291049e67c8aa4701f69f11761a9db"
[[package]]
name = "object"
version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9cbca9424c482ee628fa549d9c812e2cd22f1180b9222c9200fdfa6eb31aecb2"
[[package]]
name = "openssl"
version = "0.10.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cee6d85f4cb4c4f59a6a85d5b68a233d280c82e29e822913b9c8b129fbf20bdd"
dependencies = [
"bitflags",
"cfg-if",
"foreign-types",
"lazy_static",
"libc",
"openssl-sys",
]
[[package]]
name = "openssl-probe"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de"
[[package]]
name = "openssl-sys"
version = "0.9.57"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7410fef80af8ac071d4f63755c0ab89ac3df0fd1ea91f1d1f37cf5cec4395990"
dependencies = [
"autocfg",
"cc",
"libc",
"pkg-config",
"vcpkg",
]
[[package]]
name = "ozelot"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea00748638603838e4c5907d8d10449ee9a7e548667af7c20c684888006f6657"
dependencies = [
"byteorder",
"curl",
"error-chain",
"flate2",
"netbuf",
"openssl",
"serde",
"serde_derive",
"serde_json",
]
[[package]]
name = "pkg-config"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677"
[[package]]
name = "proc-macro2"
version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1502d12e458c49a4c9cbff560d0fe0060c252bc29799ed94ca2ed4bb665a0101"
dependencies = [
"unicode-xid",
]
[[package]]
name = "quote"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "54a21852a652ad6f610c9510194f398ff6f8692e334fd1145fed931f7fbe44ea"
dependencies = [
"proc-macro2",
]
[[package]]
name = "redox_syscall"
version = "0.1.56"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84"
[[package]]
name = "rustc-demangle"
version = "0.1.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783"
[[package]]
name = "ryu"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed3d612bc64430efeb3f7ee6ef26d590dce0c43249217bddc62112540c7941e1"
[[package]]
name = "schannel"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75"
dependencies = [
"lazy_static",
"winapi",
]
[[package]]
name = "serde"
version = "1.0.110"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99e7b308464d16b56eba9964e4972a3eee817760ab60d88c3f86e1fecb08204c"
[[package]]
name = "serde_derive"
version = "1.0.110"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "818fbf6bfa9a42d3bfcaca148547aa00c7b915bec71d1757aa2d44ca68771984"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.53"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "993948e75b189211a9b31a7528f950c6adc21f9720b6438ff80a7fa2f864cea2"
dependencies = [
"itoa",
"ryu",
"serde",
]
[[package]]
name = "socket2"
version = "0.3.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03088793f677dce356f3ccc2edb1b314ad191ab702a5de3faf49304f7e104918"
dependencies = [
"cfg-if",
"libc",
"redox_syscall",
"winapi",
]
[[package]]
name = "syn"
version = "1.0.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f14a640819f79b72a710c0be059dce779f9339ae046c8bef12c361d56702146f"
dependencies = [
"proc-macro2",
"quote",
"unicode-xid",
]
[[package]]
name = "unicode-xid"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
[[package]]
name = "vcpkg"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fc439f2794e98976c88a2a2dafce96b930fe8010b0a256b3c2199a773933168"
[[package]]
name = "version_check"
version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed"
[[package]]
name = "winapi"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"

12
Cargo.toml Normal file
View File

@ -0,0 +1,12 @@
[package]
name = "Composition"
version = "0.1.0"
authors = ["ElementG9 <garentyler@gmail.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
serde = "1.0.110"
serde_json = "1.0.53"
ozelot = "0.9.0"

View File

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2020 ElementG9
Copyright (c) 2020 Garen Tyler
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

17
src/main.rs Normal file
View File

@ -0,0 +1,17 @@
#![allow(non_snake_case)]
pub static DEBUG_LOGGING: bool = true;
pub static SERVER_VERSION: &str = "1.15.2";
pub static SERVER_PROTOCOL_VERSION: usize = 578;
pub static SERVER_MOTD: &str = "ligma balls";
// mod net;
// mod mctypes;
fn main() -> std::io::Result<()> {
// Listener loops forever.
// net::start_listener().expect("could not start listener");
// println!("Stopping server");
use std::{io::prelude::*, net::TcpStream};
let mut stream = TcpStream::connect("206.189.67.44:25565")?;
}

432
src/mctypes.rs Normal file
View File

@ -0,0 +1,432 @@
use std::io::prelude::*;
use std::net::TcpStream;
pub fn read_byte(t: &mut TcpStream) -> std::io::Result<u8> {
let mut buffer = [0u8; 1];
t.read_exact(&mut buffer)?;
Ok(buffer[0])
}
pub fn get_bytes(v: Vec<u8>, l: usize) -> Box<[u8]> {
use std::collections::VecDeque;
let mut v = VecDeque::from(v);
while v.len() > l {
v.pop_front();
}
while v.len() < l {
v.push_front(0u8);
}
let mut a = Vec::new();
for b in v {
a.push(b);
}
a.into_boxed_slice()
}
pub fn io_error(s: &str) -> std::io::Error {
use std::io::{Error, ErrorKind};
Error::new(ErrorKind::Other, s)
}
#[allow(dead_code)]
#[derive(Debug, Copy, Clone)]
pub enum MCBoolean {
True,
False,
}
impl From<bool> for MCBoolean {
fn from(v: bool) -> MCBoolean {
if v {
MCBoolean::True
} else {
MCBoolean::False
}
}
}
#[allow(dead_code)]
impl MCBoolean {
pub fn from_stream(t: &mut TcpStream) -> std::io::Result<MCBoolean> {
let b = read_byte(t)?;
Ok(MCBoolean::from_bytes(vec![b]))
}
pub fn from_bytes(v: Vec<u8>) -> MCBoolean {
if get_bytes(v, 1)[0] == 0x01 {
MCBoolean::True
} else {
MCBoolean::False
}
}
pub fn to_bytes(&self) -> Vec<u8> {
match self {
MCBoolean::True => vec![0x01],
MCBoolean::False => vec![0x00],
}
}
}
#[allow(dead_code)]
#[derive(Debug, Copy, Clone)]
pub struct MCByte {
pub value: i8 // -128 to 127
}
impl From<i8> for MCByte {
fn from(v: i8) -> MCByte {
MCByte {
value: v
}
}
}
#[allow(dead_code)]
impl MCByte {
pub fn from_stream(t: &mut TcpStream) -> std::io::Result<MCByte> {
Ok(MCByte::from_bytes(vec![read_byte(t)?]))
}
pub fn from_bytes(v: Vec<u8>) -> MCByte {
MCByte {
value: get_bytes(v, 1)[0] as i8
}
}
pub fn to_bytes(&self) -> Vec<u8> {
self.value.to_be_bytes().to_vec()
}
}
#[allow(dead_code)]
#[derive(Debug, Copy, Clone)]
pub struct MCUnsignedByte {
pub value: u8 // 0 to 255
}
impl From<u8> for MCUnsignedByte {
fn from(v: u8) -> MCUnsignedByte {
MCUnsignedByte {
value: v
}
}
}
#[allow(dead_code)]
impl MCUnsignedByte {
pub fn from_stream(t: &mut TcpStream) -> std::io::Result<MCUnsignedByte> {
Ok(MCUnsignedByte::from_bytes(vec![read_byte(t)?]))
}
pub fn from_bytes(v: Vec<u8>) -> MCUnsignedByte {
MCUnsignedByte {
value: get_bytes(v, 1)[0]
}
}
pub fn to_bytes(&self) -> Vec<u8> {
self.value.to_be_bytes().to_vec()
}
}
#[allow(dead_code)]
#[derive(Debug, Copy, Clone)]
pub struct MCShort {
pub value: i16 // -32768 to 32767
}
impl From<i16> for MCShort {
fn from(v: i16) -> MCShort {
MCShort {
value: v
}
}
}
#[allow(dead_code)]
impl MCShort {
pub fn from_stream(t: &mut TcpStream) -> std::io::Result<MCShort> {
let mut bytes = Vec::new();
bytes.push(read_byte(t)?); // MSD
bytes.push(read_byte(t)?); // LSD
Ok(MCShort::from_bytes(bytes))
}
pub fn from_bytes(v: Vec<u8>) -> MCShort {
let mut a = [0u8; 2];
a.copy_from_slice(&get_bytes(v, 2));
MCShort {
value: i16::from_be_bytes(a)
}
}
pub fn to_bytes(&self) -> Vec<u8> {
self.value.to_be_bytes().to_vec()
}
}
#[allow(dead_code)]
#[derive(Debug, Copy, Clone)]
pub struct MCUnsignedShort {
pub value: u16 // 0 to 65535
}
impl From<u16> for MCUnsignedShort {
fn from(v: u16) -> MCUnsignedShort {
MCUnsignedShort {
value: v
}
}
}
#[allow(dead_code)]
impl MCUnsignedShort {
pub fn from_stream(t: &mut TcpStream) -> std::io::Result<MCUnsignedShort> {
let mut bytes = Vec::new();
bytes.push(read_byte(t)?); // MSD
bytes.push(read_byte(t)?); // LSD
Ok(MCUnsignedShort::from_bytes(bytes))
}
pub fn from_bytes(v: Vec<u8>) -> MCUnsignedShort {
let mut a = [0u8; 2];
a.copy_from_slice(&get_bytes(v, 2));
MCUnsignedShort {
value: u16::from_be_bytes(a)
}
}
pub fn to_bytes(&self) -> Vec<u8> {
self.value.to_be_bytes().to_vec()
}
}
#[allow(dead_code)]
#[derive(Debug, Copy, Clone)]
pub struct MCInt {
pub value: i32 // -2147483648 to 2147483647
}
impl From<i32> for MCInt {
fn from(v: i32) -> MCInt {
MCInt {
value: v
}
}
}
#[allow(dead_code)]
impl MCInt {
pub fn from_stream(t: &mut TcpStream) -> std::io::Result<MCInt> {
let mut bytes = Vec::new();
for _ in 0..4 {
bytes.push(read_byte(t)?);
}
Ok(MCInt::from_bytes(bytes))
}
pub fn from_bytes(v: Vec<u8>) -> MCInt {
let mut a = [0u8; 4];
a.copy_from_slice(&get_bytes(v, 4));
MCInt {
value: i32::from_be_bytes(a)
}
}
pub fn to_bytes(&self) -> Vec<u8> {
self.value.to_be_bytes().to_vec()
}
}
#[allow(dead_code)]
#[derive(Debug, Copy, Clone)]
pub struct MCLong {
pub value: i64 // -9223372036854775808 to 9223372036854775807
}
impl From<i64> for MCLong {
fn from(v: i64) -> MCLong {
MCLong {
value: v
}
}
}
#[allow(dead_code)]
impl MCLong {
pub fn from_stream(t: &mut TcpStream) -> std::io::Result<MCLong> {
let mut bytes = Vec::new();
for _ in 0..8 {
bytes.push(read_byte(t)?);
}
Ok(MCLong::from_bytes(bytes))
}
pub fn from_bytes(v: Vec<u8>) -> MCLong {
let mut a = [0u8; 8];
a.copy_from_slice(&get_bytes(v, 8));
MCLong {
value: i64::from_be_bytes(a)
}
}
pub fn to_bytes(&self) -> Vec<u8> {
self.value.to_be_bytes().to_vec()
}
}
#[allow(dead_code)]
#[derive(Debug, Copy, Clone)]
pub struct MCFloat {
pub value: f32 // 32-bit floating point number
}
impl From<f32> for MCFloat {
fn from(v: f32) -> MCFloat {
MCFloat {
value: v
}
}
}
#[allow(dead_code)]
impl MCFloat {
pub fn from_stream(t: &mut TcpStream) -> std::io::Result<MCFloat> {
let mut bytes = Vec::new();
for _ in 0..4 {
bytes.push(read_byte(t)?);
}
Ok(MCFloat::from_bytes(bytes))
}
pub fn from_bytes(v: Vec<u8>) -> MCFloat {
let mut a = [0u8; 4];
a.copy_from_slice(&get_bytes(v, 4));
MCFloat {
value: f32::from_be_bytes(a)
}
}
pub fn to_bytes(&self) -> Vec<u8> {
self.value.to_be_bytes().to_vec()
}
}
#[allow(dead_code)]
#[derive(Debug, Copy, Clone)]
pub struct MCDouble {
pub value: f64 // 64-bit floating point number
}
impl From<f64> for MCDouble {
fn from(v: f64) -> MCDouble {
MCDouble {
value: v
}
}
}
#[allow(dead_code)]
impl MCDouble {
pub fn from_stream(t: &mut TcpStream) -> std::io::Result<MCDouble> {
let mut bytes = Vec::new();
for _ in 0..8 {
bytes.push(read_byte(t)?);
}
Ok(MCDouble::from_bytes(bytes))
}
pub fn from_bytes(v: Vec<u8>) -> MCDouble {
let mut a = [0u8; 8];
a.copy_from_slice(&get_bytes(v, 8));
MCDouble {
value: f64::from_be_bytes(a)
}
}
pub fn to_bytes(&self) -> Vec<u8> {
self.value.to_be_bytes().to_vec()
}
}
#[allow(dead_code)]
#[derive(Debug, Copy, Clone)]
pub struct MCVarInt {
pub value: i32 // Variable length 32-bit integer
}
impl From<i32> for MCVarInt {
fn from(v: i32) -> MCVarInt {
MCVarInt {
value: v
}
}
}
#[allow(dead_code)]
impl MCVarInt {
pub fn new(i: i32) -> MCVarInt {
MCVarInt {
value: i
}
}
pub fn from_stream(t: &mut TcpStream) -> std::io::Result<MCVarInt> {
let mut numRead = 0;
let mut result = 0i32;
let mut read = 0u8;
let mut run_once = false;
while (read & 0b10000000) != 0 || !run_once {
run_once = true;
read = read_byte(t)?;
let value = (read & 0b01111111) as i32;
result |= value << (7 * numRead);
numRead += 1;
if numRead > 5 {
return Err(io_error("MCVarInt is too big"));
}
}
Ok(MCVarInt {
value: result
})
}
pub fn from_bytes(_: Vec<u8>) -> MCVarInt {
panic!("Cannot construct MCVarInt from raw bytes");
}
pub fn to_bytes(&self) -> Vec<u8> {
let mut value = self.value.clone();
let mut run_once = false;
let mut out: Vec<u8> = Vec::new();
while value != 0 || !run_once {
run_once = true;
let mut temp: u8 = (value & 0b01111111) as u8;
value >>= 7;
if value != 0 {
temp |= 0b10000000;
}
out.push(temp);
}
return out;
}
}
impl std::fmt::Display for MCVarInt {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.value)
}
}
#[allow(dead_code)]
#[derive(Debug)]
pub struct MCString {
pub value: String
}
#[allow(dead_code)]
impl MCString {
pub fn from_stream(t: &mut TcpStream) -> std::io::Result<MCString> {
let length = MCVarInt::from_stream(t)?.value as u32;
let mut bytes = Vec::new();
for _ in 0..length {
bytes.push(read_byte(t)?);
}
let value = String::from_utf8(bytes);
if value.is_ok() {
Ok(MCString {
value: value.unwrap()
})
} else {
return Err(io_error("MCString contains invalid utf-8"));
}
}
pub fn from_bytes(_: Vec<u8>) -> MCString {
panic!("Cannot construct MCVarInt from raw bytes");
}
pub fn to_bytes(&self) -> Vec<u8> {
let mut out = Vec::new();
let length = MCVarInt {
value: self.value.len() as i32
};
for b in length.to_bytes() {
out.push(b);
}
for b in self.value.clone().into_bytes() {
out.push(b);
}
out
}
}
impl From<&str> for MCString {
fn from(s: &str) -> MCString {
MCString {
value: s.to_owned()
}
}
}
impl From<String> for MCString {
fn from(s: String) -> MCString {
MCString {
value: s.clone()
}
}
}
impl Clone for MCString {
fn clone(&self) -> Self {
MCString {
value: self.value.clone()
}
}
}
impl std::fmt::Display for MCString {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "\"{}\" ({} chars)", self.value, self.value.len())
}
}

217
src/net.rs Normal file
View File

@ -0,0 +1,217 @@
pub static SERVER_LISTENER_ADDRESS: &str = "127.0.0.1:25565";
pub static SOCKET_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(5);
extern crate serde;
extern crate serde_json;
use serde::Serialize;
use serde_json::json;
use std::io::prelude::*;
use std::net::{TcpStream, TcpListener};
use std::thread;
use crate::mctypes::*;
pub struct MCPacket {
pub id: MCVarInt,
pub data: Vec<u8>
}
#[allow(dead_code)]
impl MCPacket {
pub fn read_header(t: &mut TcpStream) -> std::io::Result<(MCVarInt, MCVarInt)> {
let length = MCVarInt::from_stream(t)?;
let id = MCVarInt::from_stream(t)?;
Ok((length, id))
}
pub fn new(id: u8) -> MCPacket {
MCPacket {
id: MCVarInt::new(id as i32),
data: Vec::new(),
}
}
pub fn write(&mut self, v: Vec<u8>) {
for b in v {
self.data.push(b);
}
}
pub fn to_bytes(&self) -> Vec<u8> {
let mut bytes = Vec::new();
for b in MCVarInt::new((
self.id.to_bytes().len() +
self.data.len()
) as i32).to_bytes() {
bytes.push(b);
}
for b in self.id.to_bytes() {
bytes.push(b);
}
for b in &self.data {
bytes.push(*b);
}
bytes
}
}
#[allow(dead_code)]
#[derive(PartialEq, Debug)]
pub enum GameState {
Handshake,
Status,
Login,
Play,
Closed
}
#[allow(dead_code)]
pub struct GameConnection {
pub stream: TcpStream,
pub state: GameState,
}
pub fn start_listener() -> std::io::Result<()> {
if crate::DEBUG_LOGGING {
println!("Started listener at {}", SERVER_LISTENER_ADDRESS);
}
let listener = TcpListener::bind(SERVER_LISTENER_ADDRESS)?;
// Spawn a new thread for each connection.
for stream in listener.incoming() {
let stream = stream?;
thread::Builder::new().name(format!("GameConnection {}", stream.peer_addr().unwrap())).spawn(move || -> std::io::Result<()> {
if crate::DEBUG_LOGGING {
println!("Client connected at {}", stream.peer_addr().unwrap());
}
stream
.set_read_timeout(Some(SOCKET_TIMEOUT))
.expect("set_read_timeout call failed");
stream
.set_write_timeout(Some(SOCKET_TIMEOUT))
.expect("set_write_timeout call failed");
handle_client(GameConnection {
stream: stream,
state: GameState::Handshake,
})?;
Ok(())
})?;
}
Ok(())
}
pub fn handle_client(mut gc: GameConnection) -> std::io::Result<()> {
loop {
let (packet_length, packet_id) = MCPacket::read_header(&mut gc.stream)?;
if crate::DEBUG_LOGGING {
println!("Packet Length: {}, Packet ID: {}", packet_length.value, packet_id.value);
}
match gc.state {
GameState::Handshake => {
match packet_id.value {
0x00 => {
handshake(&mut gc)?;
},
_ => {
if crate::DEBUG_LOGGING {
println!("Unknown packet id {} in Handshake", packet_id);
}
}
}
},
GameState::Login => {
match packet_id.value {
0x00 => {
login(&mut gc)?;
},
_ => {
if crate::DEBUG_LOGGING {
println!("Unknown packet id {} in Login", packet_id);
}
}
}
},
GameState::Status => {
match packet_id.value {
0x00 => {
// Send a response packet.
let mut packet = MCPacket::new(0x00);
let json_response = json!({
"version": {
"name": crate::SERVER_VERSION,
"protocol": crate::SERVER_PROTOCOL_VERSION
},
"players": {
"max": 100,
"online": 5,
"sample": [
{
"name": "thinkofdeath",
"id": "4566e69f-c907-48ee-8d71-d7ba5aa00d20"
}
]
},
"description": {
"text": crate::SERVER_MOTD
}
// No favicon for now.
// "favicon": "data:image/png;base64,<data>"
}).to_string();
packet.write(MCVarInt::new(json_response.len() as i32).to_bytes());
packet.write(MCString::from(json_response.clone()).to_bytes());
gc.stream.write(&packet.to_bytes())?;
println!("=== SENT SERVER RESPONSE ===\n{}", json_response);
},
_ => {
if crate::DEBUG_LOGGING {
println!("Unknown packet id {} in Status", packet_id);
}
}
}
}
_ => {
if crate::DEBUG_LOGGING {
println!("Unknown gamestate {:?}", gc.state);
}
}
}
}
}
pub fn handshake(gc: &mut GameConnection) -> std::io::Result<()> {
// C->S Handshake
let protocol_version = MCVarInt::from_stream(&mut gc.stream)?;
let server_address = MCString::from_stream(&mut gc.stream)?;
let server_port = MCUnsignedShort::from_stream(&mut gc.stream)?;
let next_state = match MCVarInt::from_stream(&mut gc.stream)?.value {
1 => GameState::Status,
2 => GameState::Login,
_ => {
if crate::DEBUG_LOGGING {
println!("Unknown next_state in handshake");
}
GameState::Handshake
}
};
if crate::DEBUG_LOGGING {
println!("Handshake: Protocol Version: {}, Server Address: {}:{}, Next State: {:?}",
protocol_version.value,
server_address.value,
server_port.value,
next_state
);
}
gc.state = next_state;
Ok(())
}
pub fn login(gc: &mut GameConnection) -> std::io::Result<()> {
// C->S Login Start
let player_username = MCString::from_stream(&mut gc.stream)?;
if crate::DEBUG_LOGGING {
println!("Login: Player Username: {}", player_username);
}
// S->C Encryption Request
// C->S Encryption Response
// S->C Set Compression
// S->C Login Success
let mut login_success = MCPacket::new(0x02);
login_success.write(MCString::from("00000000-0000-0000-0000-000000000000").to_bytes()); // UUID
login_success.write(player_username.to_bytes());
gc.stream.write(&login_success.to_bytes())?;
// Move to Play state
gc.state = GameState::Play;
play(gc)?;
Ok(())
}
pub fn play(gc: &mut GameConnection) -> std::io::Result<()> {
Ok(())
}