mirror of
https://github.com/zyllian/classics.git
synced 2025-01-18 11:47:14 -08:00
replace most .expect
s and .unwrap
s with a custom error type, closes #54
This commit is contained in:
parent
b749eb838b
commit
373fc5889d
8 changed files with 82 additions and 57 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -127,6 +127,7 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"strum",
|
"strum",
|
||||||
|
"thiserror",
|
||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -18,4 +18,5 @@ safer-bytes = "0.2"
|
||||||
serde = {version = "1", features = ["derive"]}
|
serde = {version = "1", features = ["derive"]}
|
||||||
serde_json = "1"
|
serde_json = "1"
|
||||||
strum = { version = "0.26", features = ["derive"] }
|
strum = { version = "0.26", features = ["derive"] }
|
||||||
|
thiserror = "1"
|
||||||
tokio = {version = "1", features = ["full"]}
|
tokio = {version = "1", features = ["full"]}
|
||||||
|
|
12
src/error.rs
Normal file
12
src/error.rs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
/// error type for the server
|
||||||
|
#[derive(Debug, thiserror::Error)]
|
||||||
|
pub enum GeneralError {
|
||||||
|
#[error(transparent)]
|
||||||
|
Io(#[from] std::io::Error),
|
||||||
|
#[error(transparent)]
|
||||||
|
Json(#[from] serde_json::Error),
|
||||||
|
#[error("{0}")]
|
||||||
|
Custom(String),
|
||||||
|
#[error("{0}")]
|
||||||
|
CustomPrivate(String),
|
||||||
|
}
|
21
src/level.rs
21
src/level.rs
|
@ -6,7 +6,7 @@ use std::{
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{packet::server::ServerPacket, util::neighbors};
|
use crate::{error::GeneralError, packet::server::ServerPacket, util::neighbors};
|
||||||
|
|
||||||
use self::block::BLOCK_INFO;
|
use self::block::BLOCK_INFO;
|
||||||
|
|
||||||
|
@ -108,7 +108,7 @@ impl Level {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// saves the level
|
/// saves the level
|
||||||
pub async fn save<P>(&self, path: P) -> std::io::Result<()>
|
pub async fn save<P>(&self, path: P) -> Result<(), GeneralError>
|
||||||
where
|
where
|
||||||
P: AsRef<Path>,
|
P: AsRef<Path>,
|
||||||
{
|
{
|
||||||
|
@ -116,29 +116,22 @@ impl Level {
|
||||||
tokio::fs::create_dir_all(path).await?;
|
tokio::fs::create_dir_all(path).await?;
|
||||||
tokio::fs::write(
|
tokio::fs::write(
|
||||||
path.join(LEVEL_INFO_PATH),
|
path.join(LEVEL_INFO_PATH),
|
||||||
serde_json::to_string_pretty(self).unwrap(),
|
serde_json::to_string_pretty(self)?,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
let mut encoder = flate2::write::GzEncoder::new(Vec::new(), flate2::Compression::best());
|
let mut encoder = flate2::write::GzEncoder::new(Vec::new(), flate2::Compression::best());
|
||||||
encoder
|
encoder.write_all(&self.blocks)?;
|
||||||
.write_all(&self.blocks)
|
Ok(tokio::fs::write(path.join(LEVEL_DATA_PATH), encoder.finish()?).await?)
|
||||||
.expect("failed to write blocks");
|
|
||||||
tokio::fs::write(
|
|
||||||
path.join(LEVEL_DATA_PATH),
|
|
||||||
encoder.finish().expect("failed to encode blocks"),
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// loads the level
|
/// loads the level
|
||||||
pub async fn load<P>(path: P) -> std::io::Result<Self>
|
pub async fn load<P>(path: P) -> Result<Self, GeneralError>
|
||||||
where
|
where
|
||||||
P: AsRef<Path>,
|
P: AsRef<Path>,
|
||||||
{
|
{
|
||||||
let path = path.as_ref();
|
let path = path.as_ref();
|
||||||
let mut info: Self =
|
let mut info: Self =
|
||||||
serde_json::from_str(&tokio::fs::read_to_string(path.join(LEVEL_INFO_PATH)).await?)
|
serde_json::from_str(&tokio::fs::read_to_string(path.join(LEVEL_INFO_PATH)).await?)?;
|
||||||
.expect("failed to deserialize level info");
|
|
||||||
let blocks_data = tokio::fs::read(path.join(LEVEL_DATA_PATH)).await?;
|
let blocks_data = tokio::fs::read(path.join(LEVEL_DATA_PATH)).await?;
|
||||||
let mut decoder = flate2::read::GzDecoder::new(blocks_data.as_slice());
|
let mut decoder = flate2::read::GzDecoder::new(blocks_data.as_slice());
|
||||||
decoder.read_to_end(&mut info.blocks)?;
|
decoder.read_to_end(&mut info.blocks)?;
|
||||||
|
|
|
@ -2,12 +2,14 @@
|
||||||
|
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
use error::GeneralError;
|
||||||
use server::{
|
use server::{
|
||||||
config::{OptionalServerConfig, ServerConfig},
|
config::{OptionalServerConfig, ServerConfig},
|
||||||
Server,
|
Server,
|
||||||
};
|
};
|
||||||
|
|
||||||
mod command;
|
mod command;
|
||||||
|
mod error;
|
||||||
mod level;
|
mod level;
|
||||||
mod packet;
|
mod packet;
|
||||||
mod player;
|
mod player;
|
||||||
|
@ -18,11 +20,10 @@ const SERVER_NAME: &str = "classics";
|
||||||
const CONFIG_FILE: &str = "./server-config.json";
|
const CONFIG_FILE: &str = "./server-config.json";
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> std::io::Result<()> {
|
async fn main() -> Result<(), GeneralError> {
|
||||||
let config_path = PathBuf::from(CONFIG_FILE);
|
let config_path = PathBuf::from(CONFIG_FILE);
|
||||||
let config = if config_path.exists() {
|
let config = if config_path.exists() {
|
||||||
serde_json::from_str::<OptionalServerConfig>(&std::fs::read_to_string(&config_path)?)
|
serde_json::from_str::<OptionalServerConfig>(&std::fs::read_to_string(&config_path)?)?
|
||||||
.expect("failed to deserialize config")
|
|
||||||
.build_default()
|
.build_default()
|
||||||
} else {
|
} else {
|
||||||
ServerConfig::default()
|
ServerConfig::default()
|
||||||
|
|
|
@ -6,6 +6,7 @@ use std::{path::PathBuf, sync::Arc};
|
||||||
use tokio::{net::TcpListener, sync::RwLock};
|
use tokio::{net::TcpListener, sync::RwLock};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
error::GeneralError,
|
||||||
level::{
|
level::{
|
||||||
block::{BlockType, BLOCK_INFO},
|
block::{BlockType, BLOCK_INFO},
|
||||||
BlockUpdate, Level,
|
BlockUpdate, Level,
|
||||||
|
@ -58,7 +59,7 @@ impl ServerData {
|
||||||
|
|
||||||
impl Server {
|
impl Server {
|
||||||
/// creates a new server with a generated level
|
/// creates a new server with a generated level
|
||||||
pub async fn new(config: ServerConfig) -> std::io::Result<Self> {
|
pub async fn new(config: ServerConfig) -> Result<Self, GeneralError> {
|
||||||
let levels_path = PathBuf::from(LEVELS_PATH);
|
let levels_path = PathBuf::from(LEVELS_PATH);
|
||||||
if !levels_path.exists() {
|
if !levels_path.exists() {
|
||||||
std::fs::create_dir_all(&levels_path)?;
|
std::fs::create_dir_all(&levels_path)?;
|
||||||
|
@ -84,7 +85,7 @@ impl Server {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// creates a new server with the given level
|
/// creates a new server with the given level
|
||||||
pub async fn new_with_level(config: ServerConfig, level: Level) -> std::io::Result<Self> {
|
pub async fn new_with_level(config: ServerConfig, level: Level) -> Result<Self, GeneralError> {
|
||||||
let listener = TcpListener::bind("0.0.0.0:25565").await?;
|
let listener = TcpListener::bind("0.0.0.0:25565").await?;
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
|
@ -101,11 +102,15 @@ impl Server {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// starts the server
|
/// starts the server
|
||||||
pub async fn run(self) -> std::io::Result<()> {
|
pub async fn run(self) -> Result<(), GeneralError> {
|
||||||
let data = self.data.clone();
|
let data = self.data.clone();
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
loop {
|
loop {
|
||||||
let (stream, addr) = self.listener.accept().await.unwrap();
|
let (stream, addr) = self
|
||||||
|
.listener
|
||||||
|
.accept()
|
||||||
|
.await
|
||||||
|
.expect("failed to accept listener!");
|
||||||
println!("connection from {addr}");
|
println!("connection from {addr}");
|
||||||
let data = data.clone();
|
let data = data.clone();
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
|
@ -113,7 +118,7 @@ impl Server {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
handle_ticks(self.data.clone()).await;
|
handle_ticks(self.data.clone()).await?;
|
||||||
tokio::time::sleep(std::time::Duration::from_millis(1)).await;
|
tokio::time::sleep(std::time::Duration::from_millis(1)).await;
|
||||||
|
|
||||||
// TODO: cancel pending tasks/send out "Server is stopping" messages *here* instead of elsewhere
|
// TODO: cancel pending tasks/send out "Server is stopping" messages *here* instead of elsewhere
|
||||||
|
@ -129,7 +134,7 @@ impl Server {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// function to tick the server
|
/// function to tick the server
|
||||||
async fn handle_ticks(data: Arc<RwLock<ServerData>>) {
|
async fn handle_ticks(data: Arc<RwLock<ServerData>>) -> Result<(), GeneralError> {
|
||||||
let mut current_tick = 0;
|
let mut current_tick = 0;
|
||||||
let mut last_auto_save = std::time::Instant::now();
|
let mut last_auto_save = std::time::Instant::now();
|
||||||
loop {
|
loop {
|
||||||
|
@ -138,12 +143,7 @@ async fn handle_ticks(data: Arc<RwLock<ServerData>>) {
|
||||||
tick(&mut data, current_tick);
|
tick(&mut data, current_tick);
|
||||||
|
|
||||||
if data.config_needs_saving {
|
if data.config_needs_saving {
|
||||||
std::fs::write(
|
tokio::fs::write(CONFIG_FILE, serde_json::to_string_pretty(&data.config)?).await?;
|
||||||
CONFIG_FILE,
|
|
||||||
serde_json::to_string_pretty(&data.config)
|
|
||||||
.expect("failed to serialize default config"),
|
|
||||||
)
|
|
||||||
.expect("failed to save config file");
|
|
||||||
data.config_needs_saving = false;
|
data.config_needs_saving = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,8 +164,7 @@ async fn handle_ticks(data: Arc<RwLock<ServerData>>) {
|
||||||
data.level.save_now = false;
|
data.level.save_now = false;
|
||||||
data.level
|
data.level
|
||||||
.save(PathBuf::from(LEVELS_PATH).join(&data.config.level_name))
|
.save(PathBuf::from(LEVELS_PATH).join(&data.config.level_name))
|
||||||
.await
|
.await?;
|
||||||
.expect("failed to autosave level");
|
|
||||||
last_auto_save = std::time::Instant::now();
|
last_auto_save = std::time::Instant::now();
|
||||||
|
|
||||||
let packet = ServerPacket::Message {
|
let packet = ServerPacket::Message {
|
||||||
|
@ -181,6 +180,8 @@ async fn handle_ticks(data: Arc<RwLock<ServerData>>) {
|
||||||
current_tick = current_tick.wrapping_add(1);
|
current_tick = current_tick.wrapping_add(1);
|
||||||
tokio::time::sleep(TICK_DURATION).await;
|
tokio::time::sleep(TICK_DURATION).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// function which ticks the server once
|
/// function which ticks the server once
|
||||||
|
|
|
@ -13,6 +13,7 @@ use tokio::{
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
command::Command,
|
command::Command,
|
||||||
|
error::GeneralError,
|
||||||
level::{block::BLOCK_INFO, BlockUpdate, Level},
|
level::{block::BLOCK_INFO, BlockUpdate, Level},
|
||||||
packet::{
|
packet::{
|
||||||
client::ClientPacket, server::ServerPacket, ExtBitmask, PacketWriter, ARRAY_LENGTH,
|
client::ClientPacket, server::ServerPacket, ExtBitmask, PacketWriter, ARRAY_LENGTH,
|
||||||
|
@ -24,7 +25,7 @@ use crate::{
|
||||||
|
|
||||||
use super::ServerData;
|
use super::ServerData;
|
||||||
|
|
||||||
async fn next_packet(stream: &mut TcpStream) -> std::io::Result<Option<ClientPacket>> {
|
async fn next_packet(stream: &mut TcpStream) -> Result<Option<ClientPacket>, GeneralError> {
|
||||||
let id = stream.read_u8().await?;
|
let id = stream.read_u8().await?;
|
||||||
|
|
||||||
if let Some(size) = ClientPacket::get_size_from_id(id) {
|
if let Some(size) = ClientPacket::get_size_from_id(id) {
|
||||||
|
@ -37,7 +38,7 @@ async fn next_packet(stream: &mut TcpStream) -> std::io::Result<Option<ClientPac
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn write_packets<I>(stream: &mut TcpStream, packets: I) -> std::io::Result<()>
|
async fn write_packets<I>(stream: &mut TcpStream, packets: I) -> Result<(), GeneralError>
|
||||||
where
|
where
|
||||||
I: Iterator<Item = ServerPacket>,
|
I: Iterator<Item = ServerPacket>,
|
||||||
{
|
{
|
||||||
|
@ -84,9 +85,12 @@ pub(super) async fn handle_stream(
|
||||||
let r = handle_stream_inner(&mut stream, addr, data.clone(), &mut own_id).await;
|
let r = handle_stream_inner(&mut stream, addr, data.clone(), &mut own_id).await;
|
||||||
|
|
||||||
println!("{addr} is no longer connected");
|
println!("{addr} is no longer connected");
|
||||||
match r {
|
if let Err(e) = r {
|
||||||
Ok(disconnect_reason) => {
|
match e {
|
||||||
if let Some(disconnect_reason) = disconnect_reason {
|
// unexpected eof is expected when clients disconnect
|
||||||
|
GeneralError::Io(e) if e.kind() == std::io::ErrorKind::UnexpectedEof => {}
|
||||||
|
GeneralError::Custom(disconnect_reason) => {
|
||||||
|
println!("disconnecting <{addr}> for reason: {disconnect_reason}");
|
||||||
let packet = ServerPacket::DisconnectPlayer { disconnect_reason };
|
let packet = ServerPacket::DisconnectPlayer { disconnect_reason };
|
||||||
let writer = PacketWriter::default().write_u8(packet.get_id());
|
let writer = PacketWriter::default().write_u8(packet.get_id());
|
||||||
let msg = packet.write(writer).into_raw_packet();
|
let msg = packet.write(writer).into_raw_packet();
|
||||||
|
@ -94,11 +98,8 @@ pub(super) async fn handle_stream(
|
||||||
eprintln!("Failed to write disconnect packet for <{addr}>: {e}");
|
eprintln!("Failed to write disconnect packet for <{addr}>: {e}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
_ => {
|
||||||
Err(e) => {
|
eprintln!("Error in stream handler for <{addr}>: {e:?}");
|
||||||
// unexpected eof is expected when clients disconnect
|
|
||||||
if e.kind() != std::io::ErrorKind::UnexpectedEof {
|
|
||||||
eprintln!("Error in stream handler for <{addr}>: {e}")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -129,7 +130,7 @@ async fn handle_stream_inner(
|
||||||
addr: SocketAddr,
|
addr: SocketAddr,
|
||||||
data: Arc<RwLock<ServerData>>,
|
data: Arc<RwLock<ServerData>>,
|
||||||
own_id: &mut i8,
|
own_id: &mut i8,
|
||||||
) -> std::io::Result<Option<String>> {
|
) -> Result<(), GeneralError> {
|
||||||
let mut reply_queue: Vec<ServerPacket> = Vec::new();
|
let mut reply_queue: Vec<ServerPacket> = Vec::new();
|
||||||
|
|
||||||
macro_rules! msg {
|
macro_rules! msg {
|
||||||
|
@ -144,7 +145,7 @@ async fn handle_stream_inner(
|
||||||
loop {
|
loop {
|
||||||
if let Some(player) = data.read().await.players.iter().find(|p| p.id == *own_id) {
|
if let Some(player) = data.read().await.players.iter().find(|p| p.id == *own_id) {
|
||||||
if let Some(msg) = &player.should_be_kicked {
|
if let Some(msg) = &player.should_be_kicked {
|
||||||
return Ok(Some(format!("Kicked: {msg}")));
|
return Err(GeneralError::Custom(msg.clone()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,7 +158,7 @@ async fn handle_stream_inner(
|
||||||
magic_number,
|
magic_number,
|
||||||
} => {
|
} => {
|
||||||
if protocol_version != 0x07 {
|
if protocol_version != 0x07 {
|
||||||
return Ok(Some("Unknown protocol version! Please connect with a classic 0.30-compatible client.".to_string()));
|
return Err(GeneralError::Custom("Unknown protocol version! Please connect with a classic 0.30-compatible client.".to_string()));
|
||||||
}
|
}
|
||||||
|
|
||||||
let zero = f16::from_f32(0.0);
|
let zero = f16::from_f32(0.0);
|
||||||
|
@ -168,7 +169,9 @@ async fn handle_stream_inner(
|
||||||
ServerProtectionMode::None => {}
|
ServerProtectionMode::None => {}
|
||||||
ServerProtectionMode::Password(password) => {
|
ServerProtectionMode::Password(password) => {
|
||||||
if verification_key != *password {
|
if verification_key != *password {
|
||||||
return Ok(Some("Incorrect password!".to_string()));
|
return Err(GeneralError::Custom(
|
||||||
|
"Incorrect password!".to_string(),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ServerProtectionMode::PasswordsByUser(passwords) => {
|
ServerProtectionMode::PasswordsByUser(passwords) => {
|
||||||
|
@ -177,14 +180,18 @@ async fn handle_stream_inner(
|
||||||
.map(|password| verification_key == *password)
|
.map(|password| verification_key == *password)
|
||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
{
|
{
|
||||||
return Ok(Some("Incorrect password!".to_string()));
|
return Err(GeneralError::Custom(
|
||||||
|
"Incorrect password!".to_string(),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for player in &data.players {
|
for player in &data.players {
|
||||||
if player.username == username {
|
if player.username == username {
|
||||||
return Ok(Some("Player with username already connected!".to_string()));
|
return Err(GeneralError::Custom(
|
||||||
|
"Player with username already connected!".to_string(),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -232,7 +239,7 @@ async fn handle_stream_inner(
|
||||||
|
|
||||||
println!("generating level packets");
|
println!("generating level packets");
|
||||||
reply_queue.extend(
|
reply_queue.extend(
|
||||||
build_level_packets(&data.level, extensions, custom_blocks_support_level)
|
build_level_packets(&data.level, extensions, custom_blocks_support_level)?
|
||||||
.into_iter(),
|
.into_iter(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -321,7 +328,9 @@ async fn handle_stream_inner(
|
||||||
|| y.clamp(0, data.level.y_size as i16 - 1) != y
|
|| y.clamp(0, data.level.y_size as i16 - 1) != y
|
||||||
|| z.clamp(0, data.level.z_size as i16 - 1) != z
|
|| z.clamp(0, data.level.z_size as i16 - 1) != z
|
||||||
{
|
{
|
||||||
return Ok(Some("Attempt to place block out of bounds".to_string()));
|
return Err(GeneralError::Custom(
|
||||||
|
"Attempt to place block out of bounds".to_string(),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
let new_block_info = BLOCK_INFO.get(&block_type);
|
let new_block_info = BLOCK_INFO.get(&block_type);
|
||||||
|
@ -429,7 +438,7 @@ async fn handle_stream_inner(
|
||||||
|
|
||||||
ClientPacket::Extended(_packet) => {
|
ClientPacket::Extended(_packet) => {
|
||||||
// extended packets!
|
// extended packets!
|
||||||
return Ok(Some(
|
return Err(GeneralError::Custom(
|
||||||
"Unexpected extension packet in this phase!".to_string(),
|
"Unexpected extension packet in this phase!".to_string(),
|
||||||
));
|
));
|
||||||
// match packet {
|
// match packet {
|
||||||
|
@ -468,7 +477,7 @@ fn build_level_packets(
|
||||||
level: &Level,
|
level: &Level,
|
||||||
extensions: ExtBitmask,
|
extensions: ExtBitmask,
|
||||||
custom_blocks_support_level: u8,
|
custom_blocks_support_level: u8,
|
||||||
) -> Vec<ServerPacket> {
|
) -> Result<Vec<ServerPacket>, GeneralError> {
|
||||||
let mut packets: Vec<ServerPacket> = vec![ServerPacket::LevelInitialize {}];
|
let mut packets: Vec<ServerPacket> = vec![ServerPacket::LevelInitialize {}];
|
||||||
|
|
||||||
let custom_blocks =
|
let custom_blocks =
|
||||||
|
@ -490,8 +499,8 @@ fn build_level_packets(
|
||||||
}));
|
}));
|
||||||
|
|
||||||
let mut e = GzEncoder::new(Vec::new(), Compression::best());
|
let mut e = GzEncoder::new(Vec::new(), Compression::best());
|
||||||
e.write_all(&data).expect("failed to gzip level data");
|
e.write_all(&data)?;
|
||||||
let data = e.finish().expect("failed to gzip level data");
|
let data = e.finish()?;
|
||||||
let data_len = data.len();
|
let data_len = data.len();
|
||||||
let mut total_bytes = 0;
|
let mut total_bytes = 0;
|
||||||
|
|
||||||
|
@ -513,5 +522,5 @@ fn build_level_packets(
|
||||||
z_size: level.z_size as i16,
|
z_size: level.z_size as i16,
|
||||||
});
|
});
|
||||||
|
|
||||||
packets
|
Ok(packets)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use tokio::net::TcpStream;
|
use tokio::net::TcpStream;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
error::GeneralError,
|
||||||
level::block::CUSTOM_BLOCKS_SUPPORT_LEVEL,
|
level::block::CUSTOM_BLOCKS_SUPPORT_LEVEL,
|
||||||
packet::{
|
packet::{
|
||||||
client::ClientPacket, client_extended::ExtendedClientPacket, server::ServerPacket,
|
client::ClientPacket, client_extended::ExtendedClientPacket, server::ServerPacket,
|
||||||
|
@ -10,7 +11,9 @@ use crate::{
|
||||||
|
|
||||||
use super::{next_packet, write_packets};
|
use super::{next_packet, write_packets};
|
||||||
|
|
||||||
pub async fn get_supported_extensions(stream: &mut TcpStream) -> std::io::Result<(ExtBitmask, u8)> {
|
pub async fn get_supported_extensions(
|
||||||
|
stream: &mut TcpStream,
|
||||||
|
) -> Result<(ExtBitmask, u8), GeneralError> {
|
||||||
let extensions = ExtBitmask::all().all_contained_info();
|
let extensions = ExtBitmask::all().all_contained_info();
|
||||||
|
|
||||||
write_packets(
|
write_packets(
|
||||||
|
@ -39,7 +42,9 @@ pub async fn get_supported_extensions(stream: &mut TcpStream) -> std::io::Result
|
||||||
{
|
{
|
||||||
client_extensions.push(ExtInfo::new(ext_name, version, ExtBitmask::none()));
|
client_extensions.push(ExtInfo::new(ext_name, version, ExtBitmask::none()));
|
||||||
} else {
|
} else {
|
||||||
panic!("expected ExtEntry packet!");
|
return Err(GeneralError::Custom(
|
||||||
|
"expected ExtEntry packet!".to_string(),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
client_extensions.retain_mut(|cext| {
|
client_extensions.retain_mut(|cext| {
|
||||||
|
@ -76,7 +81,9 @@ pub async fn get_supported_extensions(stream: &mut TcpStream) -> std::io::Result
|
||||||
{
|
{
|
||||||
support_level.min(CUSTOM_BLOCKS_SUPPORT_LEVEL)
|
support_level.min(CUSTOM_BLOCKS_SUPPORT_LEVEL)
|
||||||
} else {
|
} else {
|
||||||
panic!("expected CustomBlockSupportLevel packet!");
|
return Err(GeneralError::Custom(
|
||||||
|
"expected CustomBlockSupportLevel packet!".to_string(),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
0
|
0
|
||||||
|
|
Loading…
Add table
Reference in a new issue