things
This commit is contained in:
parent
25cb7d75fc
commit
7e36693485
17
.vscode/tasks.json
vendored
Normal file
17
.vscode/tasks.json
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"type": "cargo",
|
||||
"subcommand": "build",
|
||||
"problemMatcher": [
|
||||
"$rustc"
|
||||
],
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
},
|
||||
"label": "Rust: cargo build - Composition"
|
||||
}
|
||||
]
|
||||
}
|
75
Cargo.lock
generated
75
Cargo.lock
generated
@ -4,10 +4,13 @@
|
||||
name = "Composition"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
"base64",
|
||||
"chrono",
|
||||
"colorful",
|
||||
"fern",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"mojang-api",
|
||||
"ozelot",
|
||||
"radix64",
|
||||
@ -17,9 +20,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "addr2line"
|
||||
version = "0.12.2"
|
||||
version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "602d785912f476e480434627e8732e6766b760c045bbf897d9dfaa9f4fbd399c"
|
||||
checksum = "1b6a2d3371669ab3ca9797670853d61402b03d0b4b9ebf33d677dfa720203072"
|
||||
dependencies = [
|
||||
"gimli",
|
||||
]
|
||||
@ -30,18 +33,23 @@ version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ccc9a9dd069569f212bc4330af9f17c4afb5e8ce185e83dbb14f1349dda18b10"
|
||||
|
||||
[[package]]
|
||||
name = "adler32"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "567b077b825e468cc974f0020d4082ee6e03132512f207ef1a02fd5d00d1f32d"
|
||||
|
||||
[[package]]
|
||||
name = "arrayref"
|
||||
version = "0.3.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544"
|
||||
|
||||
[[package]]
|
||||
name = "atty"
|
||||
version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
"winapi 0.3.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.0.0"
|
||||
@ -50,14 +58,14 @@ checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d"
|
||||
|
||||
[[package]]
|
||||
name = "backtrace"
|
||||
version = "0.3.49"
|
||||
version = "0.3.50"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "05100821de9e028f12ae3d189176b41ee198341eb8f369956407fea2f5cc666c"
|
||||
checksum = "46254cf2fdcdf1badb5934448c1bcbe046a56537b3987d96c51a7afc5d03f293"
|
||||
dependencies = [
|
||||
"addr2line",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"miniz_oxide 0.3.7",
|
||||
"miniz_oxide",
|
||||
"object",
|
||||
"rustc-demangle",
|
||||
]
|
||||
@ -118,6 +126,17 @@ dependencies = [
|
||||
"time",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "colored"
|
||||
version = "1.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f4ffc801dacf156c5854b9df4f425a626539c3a6ef7893cc0c5084a23f0b6c59"
|
||||
dependencies = [
|
||||
"atty",
|
||||
"lazy_static",
|
||||
"winapi 0.3.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "colorful"
|
||||
version = "0.2.1"
|
||||
@ -204,6 +223,16 @@ dependencies = [
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fern"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8c9a4820f0ccc8a7afd67c39a0f1a0f4b07ca1725164271a64939d7aeb9af065"
|
||||
dependencies = [
|
||||
"colored",
|
||||
"log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "flate2"
|
||||
version = "1.0.16"
|
||||
@ -213,7 +242,7 @@ dependencies = [
|
||||
"cfg-if",
|
||||
"crc32fast",
|
||||
"libc",
|
||||
"miniz_oxide 0.4.0",
|
||||
"miniz_oxide",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -318,9 +347,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "gimli"
|
||||
version = "0.21.0"
|
||||
version = "0.22.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bcc8e0c9bce37868955864dbecd2b1ab2bdf967e6f28066d65aaac620444b65c"
|
||||
checksum = "aaf91faf136cb47367fa430cd46e37a788775e7fa104f8b4bcb3861dc389b724"
|
||||
|
||||
[[package]]
|
||||
name = "h2"
|
||||
@ -341,6 +370,15 @@ dependencies = [
|
||||
"tokio-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.1.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3deed196b6e7f9e44a2ae8d94225d80302d81208b1bb673fd21fe634645c85a9"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "http"
|
||||
version = "0.2.1"
|
||||
@ -531,15 +569,6 @@ dependencies = [
|
||||
"unicase",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "791daaae1ed6889560f8c4359194f56648355540573244a5448a83ba1ecc7435"
|
||||
dependencies = [
|
||||
"adler32",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.4.0"
|
||||
|
@ -16,3 +16,6 @@ serde = { version = "1.0.114", features = ["serde_derive"]}
|
||||
base64 = "0.12.3"
|
||||
radix64 = "0.3.0"
|
||||
mojang-api = "0.6.1"
|
||||
log = "*"
|
||||
fern = { version = "0.6", features = ["colored"] }
|
||||
backtrace = "0.3.50"
|
||||
|
175
output.log
Normal file
175
output.log
Normal file
@ -0,0 +1,175 @@
|
||||
|
||||
2020-07-27 11:25:17 [ERROR] - panicked at 'Normal panic', src/main.rs:55:5
|
||||
2020-07-27 11:25:18 [ERROR] - panicked at 'Normal panic', src/main.rs:55:5
|
||||
0: backtrace::backtrace::libunwind::trace
|
||||
at /Users/gt/.cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.50/src/backtrace/libunwind.rs:95
|
||||
backtrace::backtrace::trace_unsynchronized
|
||||
at /Users/gt/.cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.50/src/backtrace/mod.rs:66
|
||||
1: backtrace::backtrace::trace
|
||||
at /Users/gt/.cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.50/src/backtrace/mod.rs:53
|
||||
2: backtrace::capture::Backtrace::create
|
||||
at /Users/gt/.cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.50/src/capture.rs:164
|
||||
3: backtrace::capture::Backtrace::new
|
||||
at /Users/gt/.cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.50/src/capture.rs:128
|
||||
4: Composition::main::{{closure}}
|
||||
at src/main.rs:52
|
||||
5: std::panicking::rust_panic_with_hook
|
||||
at /rustc/5e1a799842ba6ed4a57e91f7ab9435947482f7d8/src/libstd/panicking.rs:475
|
||||
6: std::panicking::begin_panic
|
||||
at /rustc/5e1a799842ba6ed4a57e91f7ab9435947482f7d8/src/libstd/panicking.rs:404
|
||||
7: Composition::main
|
||||
at src/main.rs:55
|
||||
8: std::rt::lang_start::{{closure}}
|
||||
at /rustc/5e1a799842ba6ed4a57e91f7ab9435947482f7d8/src/libstd/rt.rs:67
|
||||
9: std::rt::lang_start_internal::{{closure}}
|
||||
at /rustc/5e1a799842ba6ed4a57e91f7ab9435947482f7d8/src/libstd/rt.rs:52
|
||||
std::panicking::try::do_call
|
||||
at /rustc/5e1a799842ba6ed4a57e91f7ab9435947482f7d8/src/libstd/panicking.rs:292
|
||||
10: __rust_maybe_catch_panic
|
||||
at /rustc/5e1a799842ba6ed4a57e91f7ab9435947482f7d8/src/libpanic_unwind/lib.rs:78
|
||||
11: std::panicking::try
|
||||
at /rustc/5e1a799842ba6ed4a57e91f7ab9435947482f7d8/src/libstd/panicking.rs:270
|
||||
std::panic::catch_unwind
|
||||
at /rustc/5e1a799842ba6ed4a57e91f7ab9435947482f7d8/src/libstd/panic.rs:394
|
||||
std::rt::lang_start_internal
|
||||
at /rustc/5e1a799842ba6ed4a57e91f7ab9435947482f7d8/src/libstd/rt.rs:51
|
||||
12: std::rt::lang_start
|
||||
at /rustc/5e1a799842ba6ed4a57e91f7ab9435947482f7d8/src/libstd/rt.rs:67
|
||||
13: _main
|
||||
|
||||
2020-07-27 11:26:38 [ERROR] - panicked at 'Normal panic', src/main.rs:54:5
|
||||
0: backtrace::backtrace::libunwind::trace
|
||||
at /Users/gt/.cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.50/src/backtrace/libunwind.rs:95
|
||||
backtrace::backtrace::trace_unsynchronized
|
||||
at /Users/gt/.cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.50/src/backtrace/mod.rs:66
|
||||
1: backtrace::backtrace::trace
|
||||
at /Users/gt/.cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.50/src/backtrace/mod.rs:53
|
||||
2: backtrace::capture::Backtrace::create
|
||||
at /Users/gt/.cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.50/src/capture.rs:164
|
||||
3: backtrace::capture::Backtrace::new
|
||||
at /Users/gt/.cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.50/src/capture.rs:128
|
||||
4: Composition::main::{{closure}}
|
||||
at src/main.rs:51
|
||||
5: std::panicking::rust_panic_with_hook
|
||||
at /rustc/5e1a799842ba6ed4a57e91f7ab9435947482f7d8/src/libstd/panicking.rs:475
|
||||
6: std::panicking::begin_panic
|
||||
at /rustc/5e1a799842ba6ed4a57e91f7ab9435947482f7d8/src/libstd/panicking.rs:404
|
||||
7: Composition::main
|
||||
at src/main.rs:54
|
||||
8: std::rt::lang_start::{{closure}}
|
||||
at /rustc/5e1a799842ba6ed4a57e91f7ab9435947482f7d8/src/libstd/rt.rs:67
|
||||
9: std::rt::lang_start_internal::{{closure}}
|
||||
at /rustc/5e1a799842ba6ed4a57e91f7ab9435947482f7d8/src/libstd/rt.rs:52
|
||||
std::panicking::try::do_call
|
||||
at /rustc/5e1a799842ba6ed4a57e91f7ab9435947482f7d8/src/libstd/panicking.rs:292
|
||||
10: __rust_maybe_catch_panic
|
||||
at /rustc/5e1a799842ba6ed4a57e91f7ab9435947482f7d8/src/libpanic_unwind/lib.rs:78
|
||||
11: std::panicking::try
|
||||
at /rustc/5e1a799842ba6ed4a57e91f7ab9435947482f7d8/src/libstd/panicking.rs:270
|
||||
std::panic::catch_unwind
|
||||
at /rustc/5e1a799842ba6ed4a57e91f7ab9435947482f7d8/src/libstd/panic.rs:394
|
||||
std::rt::lang_start_internal
|
||||
at /rustc/5e1a799842ba6ed4a57e91f7ab9435947482f7d8/src/libstd/rt.rs:51
|
||||
12: std::rt::lang_start
|
||||
at /rustc/5e1a799842ba6ed4a57e91f7ab9435947482f7d8/src/libstd/rt.rs:67
|
||||
13: _main
|
||||
|
||||
2020-07-27 11:30:23 [INFO] - Starting server...
|
||||
2020-07-27 11:30:46 [INFO] - Starting server...
|
||||
2020-07-27 11:31:01 [INFO] - Starting server
|
||||
2020-07-27 11:40:10 [INFO] - Starting server...
|
||||
2020-07-27 11:40:10 [INFO] - Done! Start took 763.52µs
|
||||
2020-07-27 11:40:51 [INFO] - Starting server...
|
||||
2020-07-27 11:40:51 [INFO] - Done! Start took 820.196µs
|
||||
2020-07-27 11:47:37 [INFO] - Starting server...
|
||||
2020-07-27 11:47:37 [INFO] - Done! Start took 441.888µs
|
||||
2020-07-27 12:51:18 [INFO] - Starting server...
|
||||
2020-07-27 12:51:18 [INFO] - Done! Start took 929.466µs
|
||||
2020-07-27 13:14:52 [INFO] - Starting server...
|
||||
2020-07-27 13:14:52 [INFO] - Starting network server...
|
||||
2020-07-27 13:14:52 [INFO] - Done! Start took 829.689µs
|
||||
2020-07-27 17:14:52 [INFO] - Starting server...
|
||||
2020-07-27 17:14:52 [INFO] - Done! Start took 920.073µs
|
||||
2020-07-27 17:14:52 [INFO] - Starting network...
|
||||
2020-07-27 17:14:52 [INFO] - []
|
||||
2020-07-27 17:14:52 [INFO] - []
|
||||
2020-07-27 17:14:52 [INFO] - []
|
||||
2020-07-27 17:14:52 [INFO] - []
|
||||
2020-07-27 17:14:52 [INFO] - []
|
||||
2020-07-27 17:14:52 [INFO] - []
|
||||
2020-07-27 17:14:53 [INFO] - []
|
||||
2020-07-27 17:14:53 [INFO] - []
|
||||
2020-07-27 17:14:53 [INFO] - []
|
||||
2020-07-27 17:14:53 [INFO] - []
|
||||
2020-07-27 17:14:53 [INFO] - []
|
||||
2020-07-27 17:14:53 [INFO] - []
|
||||
2020-07-27 17:14:53 [INFO] - []
|
||||
2020-07-27 17:14:53 [INFO] - []
|
||||
2020-07-27 17:14:53 [INFO] - []
|
||||
2020-07-27 17:14:53 [INFO] - []
|
||||
2020-07-27 17:14:53 [INFO] - []
|
||||
2020-07-27 17:14:53 [INFO] - []
|
||||
2020-07-27 17:14:53 [INFO] - []
|
||||
2020-07-27 17:14:53 [INFO] - []
|
||||
2020-07-27 17:14:53 [INFO] - []
|
||||
2020-07-27 17:14:53 [INFO] - []
|
||||
2020-07-27 17:14:53 [INFO] - []
|
||||
2020-07-27 17:14:53 [INFO] - []
|
||||
2020-07-27 17:14:53 [INFO] - []
|
||||
2020-07-27 17:14:54 [INFO] - []
|
||||
2020-07-27 17:14:54 [INFO] - []
|
||||
2020-07-27 17:14:54 [INFO] - []
|
||||
2020-07-27 17:14:54 [INFO] - []
|
||||
2020-07-27 17:14:54 [INFO] - []
|
||||
2020-07-27 17:14:54 [INFO] - []
|
||||
2020-07-27 17:14:54 [INFO] - []
|
||||
2020-07-27 17:14:54 [INFO] - []
|
||||
2020-07-27 17:14:54 [INFO] - []
|
||||
2020-07-27 17:14:54 [INFO] - []
|
||||
2020-07-27 17:14:54 [INFO] - []
|
||||
2020-07-27 17:14:54 [INFO] - []
|
||||
2020-07-27 17:14:54 [INFO] - []
|
||||
2020-07-27 17:14:54 [INFO] - []
|
||||
2020-07-27 17:14:54 [INFO] - []
|
||||
2020-07-27 17:14:54 [INFO] - []
|
||||
2020-07-27 17:14:54 [INFO] - []
|
||||
2020-07-27 17:14:54 [INFO] - []
|
||||
2020-07-27 17:14:54 [INFO] - []
|
||||
2020-07-27 17:14:55 [INFO] - []
|
||||
2020-07-27 17:14:55 [INFO] - []
|
||||
2020-07-27 17:14:55 [INFO] - []
|
||||
2020-07-27 17:14:55 [INFO] - []
|
||||
2020-07-27 17:14:55 [INFO] - []
|
||||
2020-07-27 17:14:55 [INFO] - []
|
||||
2020-07-27 17:14:55 [INFO] - []
|
||||
2020-07-27 17:14:55 [INFO] - []
|
||||
2020-07-27 17:14:55 [INFO] - []
|
||||
2020-07-27 17:14:55 [INFO] - []
|
||||
2020-07-27 17:14:55 [INFO] - []
|
||||
2020-07-27 17:14:55 [INFO] - []
|
||||
2020-07-27 17:14:55 [INFO] - []
|
||||
2020-07-27 17:14:55 [INFO] - []
|
||||
2020-07-27 17:14:55 [INFO] - []
|
||||
2020-07-27 17:14:55 [INFO] - []
|
||||
2020-07-27 17:14:55 [INFO] - []
|
||||
2020-07-27 17:14:55 [INFO] - []
|
||||
2020-07-27 17:14:55 [INFO] - []
|
||||
2020-07-27 17:14:55 [INFO] - []
|
||||
2020-07-27 17:14:56 [INFO] - []
|
||||
2020-07-27 17:14:56 [INFO] - []
|
||||
2020-07-27 17:14:56 [INFO] - []
|
||||
2020-07-27 17:28:01 [INFO] - Starting server...
|
||||
2020-07-27 17:28:01 [INFO] - Done! Start took 1.079011ms
|
||||
2020-07-27 17:28:01 [INFO] - Starting network...
|
||||
2020-07-27 17:28:32 [INFO] - Starting server...
|
||||
2020-07-27 17:28:32 [INFO] - Done! Start took 891.237µs
|
||||
2020-07-27 17:30:03 [INFO] - Starting server...
|
||||
2020-07-27 17:30:03 [INFO] - Done! Start took 889.43µs
|
||||
2020-07-27 17:30:39 [INFO] - Starting server...
|
||||
2020-07-27 17:30:39 [INFO] - Done! Start took 668.524µs
|
||||
2020-07-27 17:32:13 [DEBUG] - Network received client: NetworkClient { id: 0, state: Handshake, alive: true, stream: BufReader { reader: TcpStream { addr: V4(127.0.0.1:25565), peer: V4(127.0.0.1:58986), fd: 5 }, buffer: 0/8192 }, username: None, packets: [] }
|
||||
2020-07-27 17:32:13 [DEBUG] - Network received client: NetworkClient { id: 1, state: Handshake, alive: true, stream: BufReader { reader: TcpStream { addr: V4(127.0.0.1:25565), peer: V4(127.0.0.1:58988), fd: 5 }, buffer: 0/8192 }, username: None, packets: [] }
|
||||
2020-07-27 17:37:57 [INFO] - Starting server...
|
||||
2020-07-27 17:37:57 [INFO] - Done! Start took 1.007552ms
|
||||
2020-07-27 18:15:45 [INFO] - Starting server...
|
||||
2020-07-27 18:15:45 [INFO] - Done! Start took 812.588µs
|
@ -1,99 +0,0 @@
|
||||
// logger.rs
|
||||
// author: Garen Tyler
|
||||
// description:
|
||||
// A global logger for Composition.
|
||||
// The Logger struct makes it easy to create useful server logs.
|
||||
|
||||
extern crate chrono; // Used because std::time sucks.
|
||||
extern crate toml; // Colorful console logging is fun.
|
||||
|
||||
use chrono::prelude::*;
|
||||
use colorful::{Color, Colorful};
|
||||
use std::fs::File;
|
||||
use std::fs::OpenOptions;
|
||||
use std::io::prelude::*;
|
||||
|
||||
// Uses chrono::Local to get a timestamp in YYYY-MM-DD HH:MM:SS format, in local time.
|
||||
pub fn get_timestring() -> String {
|
||||
Local::now().format("%Y-%m-%d %H:%M:%S").to_string()
|
||||
}
|
||||
// Just a helper function to avoid repeating myself.
|
||||
pub fn log(logtype: &str, logmessage: &str) -> String {
|
||||
format!("{} [{}] - {}", get_timestring(), logtype, logmessage)
|
||||
}
|
||||
// So I can do logger::new("log.txt") instead of logger::Logger::new("log.txt").
|
||||
pub fn new(logfile: &str) -> Logger {
|
||||
Logger::new(logfile)
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Logger {
|
||||
pub logfile: String,
|
||||
}
|
||||
impl Logger {
|
||||
pub fn new(logfile: &str) -> Logger {
|
||||
Logger {
|
||||
logfile: logfile.to_owned(),
|
||||
}
|
||||
}
|
||||
// For logging something important, like the server port.
|
||||
pub fn important(&self, s: &str) {
|
||||
let l = log("IMPORTANT", s);
|
||||
println!("{}", l.clone().color(Color::Green));
|
||||
self.append(&l);
|
||||
}
|
||||
// For everything that doesn't fit into any of the other categories.
|
||||
pub fn info(&self, s: &str) {
|
||||
let l = log("INFO", s);
|
||||
// Not sure whether I want normal logs to be user controlled color or white.
|
||||
// println!("{}", l.clone().color(Color::White));
|
||||
println!("{}", l.clone());
|
||||
self.append(&l);
|
||||
}
|
||||
// For warnings.
|
||||
pub fn warn(&self, s: &str) {
|
||||
let l = log("WARN", s);
|
||||
println!("{}", l.clone().color(Color::LightYellow));
|
||||
self.append(&l);
|
||||
}
|
||||
// For errors.
|
||||
pub fn error(&self, s: &str) {
|
||||
let l = log("ERROR", s);
|
||||
println!("{}", l.clone().color(Color::LightRed));
|
||||
self.append(&l);
|
||||
}
|
||||
// Append to the logfile.
|
||||
pub fn append(&self, s: &str) {
|
||||
let a = || -> std::io::Result<()> {
|
||||
let mut file = OpenOptions::new()
|
||||
.create(true)
|
||||
.write(true)
|
||||
.append(true)
|
||||
.open(&self.logfile)?;
|
||||
writeln!(file, "{}", s)?;
|
||||
Ok(())
|
||||
};
|
||||
if a().is_err() {
|
||||
self.logger_error(&format!("Could not write to log file {}", self.logfile));
|
||||
}
|
||||
}
|
||||
// Clear the logfile. Adds an important note to the file that it was cleared.
|
||||
pub fn clear(&self) {
|
||||
if std::fs::remove_file(&self.logfile).is_err() {
|
||||
self.logger_error(&format!("Could not write to log file {}", self.logfile));
|
||||
}
|
||||
self.important(&format!("Cleared log file {}", self.logfile));
|
||||
}
|
||||
// Read the logfile into a String.
|
||||
pub fn read(&self) -> std::io::Result<String> {
|
||||
let mut f = File::open(&self.logfile)?;
|
||||
let mut buffer = String::new();
|
||||
f.read_to_string(&mut buffer)?;
|
||||
Ok(buffer)
|
||||
}
|
||||
// For a critical logger error. This doesn't append to the logfile.
|
||||
pub fn logger_error(&self, error_message: &str) {
|
||||
let l = log("ERROR", error_message);
|
||||
println!("{}", l.clone().color(Color::LightRed));
|
||||
}
|
||||
}
|
115
src/main.rs
115
src/main.rs
@ -1,72 +1,73 @@
|
||||
// main.rs
|
||||
// authors: Garen Tyler, Danton Hou
|
||||
// description:
|
||||
// Main Game loop, config handler.
|
||||
// Initializes the server, main server loop.
|
||||
|
||||
#![allow(non_snake_case)]
|
||||
#![allow(non_upper_case_globals)]
|
||||
#![allow(unused_imports)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
extern crate backtrace;
|
||||
extern crate fern;
|
||||
extern crate log;
|
||||
extern crate serde;
|
||||
pub mod logger;
|
||||
pub mod mctypes;
|
||||
pub mod net;
|
||||
pub mod protocol;
|
||||
|
||||
pub mod network;
|
||||
pub mod server;
|
||||
|
||||
use backtrace::Backtrace;
|
||||
use fern::colors::{Color, ColoredLevelConfig};
|
||||
use log::{debug, error, info, warn};
|
||||
use network::NetworkServer;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
lazy_static! {
|
||||
static ref log: logger::Logger = logger::new("log.txt");
|
||||
static ref config: Config = { Config::from_file("composition.toml") };
|
||||
}
|
||||
use server::{Server, ServerConfig};
|
||||
use std::sync::mpsc::{self, Receiver, Sender};
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
fn main() {
|
||||
// Start the network thread.
|
||||
std::thread::spawn(|| {
|
||||
log.info("Network thread started");
|
||||
net::start_listening();
|
||||
});
|
||||
// Loop the main thread for now.
|
||||
loop {}
|
||||
}
|
||||
// Setup logging.
|
||||
fern::Dispatch::new()
|
||||
.format(move |out, message, record| {
|
||||
out.finish(format_args!(
|
||||
"{date} [{level}] - {message}",
|
||||
date = chrono::Local::now().format("%Y-%m-%d %H:%M:%S"),
|
||||
// target = record.target(),
|
||||
level = record.level(),
|
||||
message = message,
|
||||
))
|
||||
})
|
||||
.level(log::LevelFilter::Debug)
|
||||
.chain(std::io::stdout())
|
||||
.chain(fern::log_file("output.log").unwrap())
|
||||
.apply()
|
||||
.unwrap();
|
||||
|
||||
// Not in it's own config module because of name conflicts.
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct Config {
|
||||
pub port: u16,
|
||||
pub protocol_version: u16,
|
||||
pub max_players: u32,
|
||||
pub motd: String,
|
||||
pub favicon: Option<String>,
|
||||
}
|
||||
impl Config {
|
||||
pub fn default() -> Config {
|
||||
Config {
|
||||
port: 25565,
|
||||
protocol_version: 578,
|
||||
max_players: 250,
|
||||
motd: "Hello world!".to_owned(),
|
||||
favicon: None,
|
||||
}
|
||||
}
|
||||
pub fn from_file(filename: &str) -> Config {
|
||||
use std::fs::File;
|
||||
use std::io::prelude::*;
|
||||
let a = || -> std::io::Result<Config> {
|
||||
let mut file = File::open(filename)?;
|
||||
let mut configStr = String::new();
|
||||
file.read_to_string(&mut configStr)?;
|
||||
Ok(toml::from_str(&configStr)?)
|
||||
};
|
||||
if let Ok(c) = a() {
|
||||
c
|
||||
} else {
|
||||
log.warn(&format!(
|
||||
"Could not load config from {}, using default config.",
|
||||
filename
|
||||
));
|
||||
Config::default()
|
||||
}
|
||||
std::panic::set_hook(Box::new(|panic_info| {
|
||||
let backtrace = Backtrace::new();
|
||||
error!("{}\n{:?}", panic_info.to_string(), backtrace);
|
||||
}));
|
||||
|
||||
info!("Starting server...");
|
||||
let start_time = Instant::now();
|
||||
|
||||
let config = ServerConfig::from_file("composition.toml");
|
||||
let port = config.port;
|
||||
|
||||
// Create the message channels.
|
||||
let (tx, rx) = mpsc::channel();
|
||||
|
||||
// Create the server.
|
||||
let mut server = Server {
|
||||
config,
|
||||
receiver: rx,
|
||||
network: NetworkServer::new(port),
|
||||
};
|
||||
|
||||
info!("Done! Start took {:?}", start_time.elapsed());
|
||||
|
||||
// The main server loop.
|
||||
loop {
|
||||
server.update(); // Do the tick.
|
||||
std::thread::sleep(Duration::from_millis(50));
|
||||
}
|
||||
}
|
||||
|
84
src/network/mod.rs
Normal file
84
src/network/mod.rs
Normal file
@ -0,0 +1,84 @@
|
||||
// network/mod.rs
|
||||
// authors: Garen Tyler
|
||||
// description:
|
||||
// This module contains the network logic.
|
||||
|
||||
pub mod packet;
|
||||
|
||||
use crate::server::ServerMessage;
|
||||
use log::{debug, error, info, warn};
|
||||
use packet::Packet;
|
||||
use std::io::BufReader;
|
||||
use std::net::{TcpListener, TcpStream};
|
||||
use std::sync::mpsc::{self, Receiver, Sender};
|
||||
|
||||
pub struct NetworkServer {
|
||||
receiver: Receiver<NetworkClient>,
|
||||
clients: Vec<NetworkClient>,
|
||||
}
|
||||
impl NetworkServer {
|
||||
pub fn new(port: u16) -> NetworkServer {
|
||||
let (tx, rx) = mpsc::channel();
|
||||
std::thread::spawn(move || NetworkServer::listen(port, tx));
|
||||
NetworkServer {
|
||||
receiver: rx,
|
||||
clients: Vec::new(),
|
||||
}
|
||||
}
|
||||
fn listen(port: u16, sender: Sender<NetworkClient>) {
|
||||
let listener = TcpListener::bind(&format!("0.0.0.0:{}", port)).unwrap();
|
||||
|
||||
for (index, stream) in listener.incoming().enumerate() {
|
||||
let stream = stream.unwrap();
|
||||
stream.set_nonblocking(true).unwrap();
|
||||
sender
|
||||
.send(NetworkClient {
|
||||
// The index will increment after each client making it unique. We'll just use this as the id.
|
||||
id: index as u32,
|
||||
stream: BufReader::new(stream),
|
||||
state: NetworkClientState::Handshake,
|
||||
packets: Vec::new(),
|
||||
username: None,
|
||||
alive: true,
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
pub fn update(&mut self) {
|
||||
loop {
|
||||
match self.receiver.try_recv() {
|
||||
Ok(client) => self.clients.push(client),
|
||||
Err(mpsc::TryRecvError::Empty) => break,
|
||||
Err(mpsc::TryRecvError::Disconnected) => {
|
||||
panic!("Client receiver channel disconnected!")
|
||||
}
|
||||
}
|
||||
}
|
||||
// Todo: Update each client
|
||||
for client in self.clients.iter_mut() {
|
||||
client.update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct NetworkClient {
|
||||
id: u32,
|
||||
state: NetworkClientState,
|
||||
alive: bool,
|
||||
stream: BufReader<TcpStream>,
|
||||
username: Option<String>,
|
||||
packets: Vec<Packet>,
|
||||
}
|
||||
|
||||
impl NetworkClient {
|
||||
pub fn update(&mut self) {}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Debug)]
|
||||
pub enum NetworkClientState {
|
||||
Handshake,
|
||||
Status,
|
||||
Login,
|
||||
Play,
|
||||
}
|
13
src/network/packet/mod.rs
Normal file
13
src/network/packet/mod.rs
Normal file
@ -0,0 +1,13 @@
|
||||
// network/packet/mod.rs
|
||||
// authors: Garen Tyler
|
||||
// description:
|
||||
// This module contains the packet structs.
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Packet {
|
||||
kind: PacketType,
|
||||
}
|
||||
#[derive(PartialEq, Debug)]
|
||||
pub enum PacketType {
|
||||
Handshake,
|
||||
}
|
219
src/old_net.rs
219
src/old_net.rs
@ -1,219 +0,0 @@
|
||||
// old_net.rs
|
||||
// author: Garen Tyler
|
||||
// description:
|
||||
// This was the original implementation of net.rs. Only use as a reference.
|
||||
|
||||
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 crate::mctypes::*;
|
||||
use serde::Serialize;
|
||||
use serde_json::json;
|
||||
use std::io::prelude::*;
|
||||
use std::net::{TcpListener, TcpStream};
|
||||
use std::thread;
|
||||
|
||||
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(())
|
||||
}
|
75
src/server.rs
Normal file
75
src/server.rs
Normal file
@ -0,0 +1,75 @@
|
||||
// server.rs
|
||||
// author: Garen Tyler
|
||||
// description:
|
||||
// Contains the server logic.
|
||||
|
||||
use crate::network::NetworkServer;
|
||||
use log::{debug, error, info, warn};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::sync::mpsc::{self, Receiver, Sender, TryRecvError};
|
||||
|
||||
pub struct Server {
|
||||
pub config: ServerConfig,
|
||||
pub receiver: Receiver<ServerMessage>,
|
||||
pub network: NetworkServer,
|
||||
}
|
||||
impl Server {
|
||||
pub fn update(&mut self) {
|
||||
// Do a tick.
|
||||
while let Ok(message) = self.receiver.try_recv() {
|
||||
debug!("Server received message: {:?}", message);
|
||||
self.handle_message(message);
|
||||
}
|
||||
self.network.update();
|
||||
}
|
||||
fn handle_message(&self, message: ServerMessage) {}
|
||||
pub fn shutdown(&self) {
|
||||
unimplemented!();
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
pub struct ServerConfig {
|
||||
pub port: u16,
|
||||
pub protocol_version: u16,
|
||||
pub max_players: u32,
|
||||
pub motd: String,
|
||||
pub favicon: Option<String>,
|
||||
}
|
||||
impl ServerConfig {
|
||||
pub fn default() -> ServerConfig {
|
||||
ServerConfig {
|
||||
port: 25565,
|
||||
protocol_version: 578,
|
||||
max_players: 250,
|
||||
motd: "Hello world!".to_owned(),
|
||||
favicon: None,
|
||||
}
|
||||
}
|
||||
pub fn from_file(filename: &str) -> ServerConfig {
|
||||
use std::fs::File;
|
||||
use std::io::prelude::*;
|
||||
let a = || -> std::io::Result<ServerConfig> {
|
||||
let mut file = File::open(filename)?;
|
||||
let mut configStr = String::new();
|
||||
file.read_to_string(&mut configStr)?;
|
||||
Ok(toml::from_str(&configStr)?)
|
||||
};
|
||||
if let Ok(c) = a() {
|
||||
c
|
||||
} else {
|
||||
warn!(
|
||||
"Could not load config from {}, using default config.",
|
||||
filename
|
||||
);
|
||||
ServerConfig::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum BroadcastMessage {
|
||||
Shutdown,
|
||||
}
|
||||
#[derive(Debug)]
|
||||
pub enum ServerMessage {}
|
Loading…
x
Reference in New Issue
Block a user