From 8f90b29cfed79fcf0c2dc103a88c0c32961ba98a Mon Sep 17 00:00:00 2001 From: Snowiiii Date: Sun, 3 Nov 2024 11:25:15 +0100 Subject: [PATCH] Extractor: Parse and use screens.json --- assets/screens.json | 102 ++++++++++++++++++ .../kotlin/de/snowii/extractor/Extractor.kt | 1 + .../snowii/extractor/extractors/Particles.kt | 1 - .../de/snowii/extractor/extractors/Screen.kt | 26 +++++ pumpkin-inventory/Cargo.toml | 1 + pumpkin-inventory/src/lib.rs | 52 ++++----- pumpkin-macros/src/lib.rs | 5 + pumpkin-macros/src/screen.rs | 27 +++++ pumpkin/src/client/combat.rs | 14 +-- pumpkin/src/client/container.rs | 16 +-- pumpkin/src/client/mod.rs | 2 +- pumpkin/src/client/player_packet.rs | 95 ++-------------- pumpkin/src/command/commands/cmd_echest.rs | 4 +- pumpkin/src/entity/player.rs | 82 +++++++++++++- pumpkin/src/rcon/mod.rs | 11 -- pumpkin/src/server/mod.rs | 2 +- 16 files changed, 288 insertions(+), 153 deletions(-) create mode 100644 assets/screens.json create mode 100644 extractor/src/main/kotlin/de/snowii/extractor/extractors/Screen.kt create mode 100644 pumpkin-macros/src/screen.rs diff --git a/assets/screens.json b/assets/screens.json new file mode 100644 index 000000000..b72b74a78 --- /dev/null +++ b/assets/screens.json @@ -0,0 +1,102 @@ +[ + { + "id": 0, + "name": "minecraft:generic_9x1" + }, + { + "id": 1, + "name": "minecraft:generic_9x2" + }, + { + "id": 2, + "name": "minecraft:generic_9x3" + }, + { + "id": 3, + "name": "minecraft:generic_9x4" + }, + { + "id": 4, + "name": "minecraft:generic_9x5" + }, + { + "id": 5, + "name": "minecraft:generic_9x6" + }, + { + "id": 6, + "name": "minecraft:generic_3x3" + }, + { + "id": 7, + "name": "minecraft:crafter_3x3" + }, + { + "id": 8, + "name": "minecraft:anvil" + }, + { + "id": 9, + "name": "minecraft:beacon" + }, + { + "id": 10, + "name": "minecraft:blast_furnace" + }, + { + "id": 11, + "name": "minecraft:brewing_stand" + }, + { + "id": 12, + "name": "minecraft:crafting" + }, + { + "id": 13, + "name": "minecraft:enchantment" + }, + { + "id": 14, + "name": "minecraft:furnace" + }, + { + "id": 15, + "name": "minecraft:grindstone" + }, + { + "id": 16, + "name": "minecraft:hopper" + }, + { + "id": 17, + "name": "minecraft:lectern" + }, + { + "id": 18, + "name": "minecraft:loom" + }, + { + "id": 19, + "name": "minecraft:merchant" + }, + { + "id": 20, + "name": "minecraft:shulker_box" + }, + { + "id": 21, + "name": "minecraft:smithing" + }, + { + "id": 22, + "name": "minecraft:smoker" + }, + { + "id": 23, + "name": "minecraft:cartography_table" + }, + { + "id": 24, + "name": "minecraft:stonecutter" + } +] \ No newline at end of file diff --git a/extractor/src/main/kotlin/de/snowii/extractor/Extractor.kt b/extractor/src/main/kotlin/de/snowii/extractor/Extractor.kt index 5a053c250..dfedee0c3 100644 --- a/extractor/src/main/kotlin/de/snowii/extractor/Extractor.kt +++ b/extractor/src/main/kotlin/de/snowii/extractor/Extractor.kt @@ -28,6 +28,7 @@ class Extractor : ModInitializer { Particles(), SyncedRegistries(), Packet(), + Screen(), Items(), Blocks(), ) diff --git a/extractor/src/main/kotlin/de/snowii/extractor/extractors/Particles.kt b/extractor/src/main/kotlin/de/snowii/extractor/extractors/Particles.kt index d07fb1e9d..f6aa1f34c 100644 --- a/extractor/src/main/kotlin/de/snowii/extractor/extractors/Particles.kt +++ b/extractor/src/main/kotlin/de/snowii/extractor/extractors/Particles.kt @@ -4,7 +4,6 @@ import com.google.gson.JsonArray import com.google.gson.JsonElement import com.google.gson.JsonObject import de.snowii.extractor.Extractor -import net.minecraft.network.packet.s2c.play.InventoryS2CPacket import net.minecraft.registry.Registries import net.minecraft.server.MinecraftServer diff --git a/extractor/src/main/kotlin/de/snowii/extractor/extractors/Screen.kt b/extractor/src/main/kotlin/de/snowii/extractor/extractors/Screen.kt new file mode 100644 index 000000000..54ad23418 --- /dev/null +++ b/extractor/src/main/kotlin/de/snowii/extractor/extractors/Screen.kt @@ -0,0 +1,26 @@ +package de.snowii.extractor.extractors + +import com.google.gson.JsonArray +import com.google.gson.JsonElement +import com.google.gson.JsonObject +import de.snowii.extractor.Extractor +import net.minecraft.registry.Registries +import net.minecraft.server.MinecraftServer + +class Screen : Extractor.Extractor { + override fun fileName(): String { + return "screens.json" + } + + override fun extract(server: MinecraftServer): JsonElement { + val screensJson = JsonArray() + for (screen in Registries.SCREEN_HANDLER) { + val screenJson = JsonObject() + screenJson.addProperty("id", Registries.SCREEN_HANDLER.getRawId(screen)) + screenJson.addProperty("name", Registries.SCREEN_HANDLER.getId(screen)!!.toString()) + screensJson.add(screenJson) + } + + return screensJson + } +} diff --git a/pumpkin-inventory/Cargo.toml b/pumpkin-inventory/Cargo.toml index b5c60b2f7..de5eb7d71 100644 --- a/pumpkin-inventory/Cargo.toml +++ b/pumpkin-inventory/Cargo.toml @@ -6,6 +6,7 @@ edition.workspace = true [dependencies] # For items pumpkin-world = { path = "../pumpkin-world" } +pumpkin-macros = { path = "../pumpkin-macros" } log.workspace = true itertools.workspace = true diff --git a/pumpkin-inventory/src/lib.rs b/pumpkin-inventory/src/lib.rs index e1e554fae..db9147aa9 100644 --- a/pumpkin-inventory/src/lib.rs +++ b/pumpkin-inventory/src/lib.rs @@ -1,6 +1,7 @@ use crate::container_click::MouseClick; use crate::player::PlayerInventory; use num_derive::{FromPrimitive, ToPrimitive}; +use pumpkin_macros::screen; use pumpkin_world::item::ItemStack; pub mod container_click; @@ -15,42 +16,43 @@ pub use open_container::OpenContainer; /// https://wiki.vg/Inventory #[derive(Debug, ToPrimitive, FromPrimitive, Clone, Copy, Eq, PartialEq)] +#[repr(u16)] pub enum WindowType { // not used - Generic9x1, + Generic9x1 = screen!("minecraft:generic_9x1"), // not used - Generic9x2, + Generic9x2 = screen!("minecraft:generic_9x2"), // General-purpose 3-row inventory. Used by Chest, minecart with chest, ender chest, and barrel - Generic9x3, + Generic9x3 = screen!("minecraft:generic_9x3"), // not used - Generic9x4, + Generic9x4 = screen!("minecraft:generic_9x4"), // not used - Generic9x5, + Generic9x5 = screen!("minecraft:generic_9x5"), // Used by large chests - Generic9x6, + Generic9x6 = screen!("minecraft:generic_9x6"), // General-purpose 3-by-3 square inventory, used by Dispenser and Dropper - Generic3x3, + Generic3x3 = screen!("minecraft:generic_3x3"), // General-purpose 3-by-3 square inventory, used by the Crafter - Craft3x3, - Anvil, - Beacon, - BlastFurnace, - BrewingStand, - CraftingTable, - EnchantmentTable, - Furnace, - Grindstone, + Craft3x3 = screen!("minecraft:crafter_3x3"), + Anvil = screen!("minecraft:anvil"), + Beacon = screen!("minecraft:beacon"), + BlastFurnace = screen!("minecraft:blast_furnace"), + BrewingStand = screen!("minecraft:brewing_stand"), + CraftingTable = screen!("minecraft:crafting"), + EnchantmentTable = screen!("minecraft:enchantment"), + Furnace = screen!("minecraft:furnace"), + Grindstone = screen!("minecraft:grindstone"), // Hopper or minecart with hopper - Hopper, - Lectern, - Loom, + Hopper = screen!("minecraft:hopper"), + Lectern = screen!("minecraft:lectern"), + Loom = screen!("minecraft:loom"), // Villager, Wandering Trader - Merchant, - ShulkerBox, - SmithingTable, - Smoker, - CartographyTable, - Stonecutter, + Merchant = screen!("minecraft:merchant"), + ShulkerBox = screen!("minecraft:shulker_box"), + SmithingTable = screen!("minecraft:smithing"), + Smoker = screen!("minecraft:smoker"), + CartographyTable = screen!("minecraft:cartography_table"), + Stonecutter = screen!("minecraft:stonecutter"), } pub struct ContainerStruct([Option; SLOTS]); diff --git a/pumpkin-macros/src/lib.rs b/pumpkin-macros/src/lib.rs index cc6e5e017..989641c9c 100644 --- a/pumpkin-macros/src/lib.rs +++ b/pumpkin-macros/src/lib.rs @@ -25,6 +25,11 @@ pub fn client_packet(input: TokenStream, item: TokenStream) -> TokenStream { gen.into() } +mod screen; +#[proc_macro] +pub fn screen(item: TokenStream) -> TokenStream { + screen::screen_impl(item) +} mod sound; #[proc_macro] pub fn sound(item: TokenStream) -> TokenStream { diff --git a/pumpkin-macros/src/screen.rs b/pumpkin-macros/src/screen.rs new file mode 100644 index 000000000..2c8da2886 --- /dev/null +++ b/pumpkin-macros/src/screen.rs @@ -0,0 +1,27 @@ +use std::{collections::HashMap, sync::LazyLock}; + +use proc_macro::TokenStream; +use quote::quote; +use serde::Deserialize; + +#[derive(Deserialize)] +pub struct Screen { + name: String, + id: u16, +} + +static SCREENS: LazyLock> = LazyLock::new(|| { + serde_json::from_str::>(include_str!("../../assets/screens.json")) + .expect("Could not parse screens.json registry.") + .into_iter() + .map(|val| (val.name, val.id)) + .collect() +}); + +pub(crate) fn screen_impl(item: TokenStream) -> TokenStream { + let input_string = item.to_string(); + let screen_name = input_string.trim_matches('"'); + + let id = SCREENS.get(screen_name).expect("Invalid screen"); + quote! { #id }.into() +} diff --git a/pumpkin/src/client/combat.rs b/pumpkin/src/client/combat.rs index ab025cd71..d7ac8ef25 100644 --- a/pumpkin/src/client/combat.rs +++ b/pumpkin/src/client/combat.rs @@ -60,7 +60,7 @@ impl AttackType { } } -pub(super) async fn handle_knockback( +pub async fn handle_knockback( attacker_entity: &Entity, victim: &Player, victim_entity: &Entity, @@ -93,11 +93,7 @@ pub(super) async fn handle_knockback( victim.client.send_packet(packet).await; } -pub(super) async fn spawn_sweep_particle( - attacker_entity: &Entity, - world: &World, - pos: &Vector3, -) { +pub async fn spawn_sweep_particle(attacker_entity: &Entity, world: &World, pos: &Vector3) { let yaw = attacker_entity.yaw.load(); let d = -f64::from((yaw * (PI / 180.0)).sin()); let e = f64::from((yaw * (PI / 180.0)).cos()); @@ -123,11 +119,7 @@ pub(super) async fn spawn_sweep_particle( .await; } -pub(super) async fn player_attack_sound( - pos: &Vector3, - world: &World, - attack_type: AttackType, -) { +pub async fn player_attack_sound(pos: &Vector3, world: &World, attack_type: AttackType) { match attack_type { AttackType::Knockback => { world diff --git a/pumpkin/src/client/container.rs b/pumpkin/src/client/container.rs index 504abe944..31a528ec1 100644 --- a/pumpkin/src/client/container.rs +++ b/pumpkin/src/client/container.rs @@ -8,8 +8,8 @@ use pumpkin_inventory::container_click::{ }; use pumpkin_inventory::drag_handler::DragHandler; use pumpkin_inventory::window_property::{WindowProperty, WindowPropertyTrait}; -use pumpkin_inventory::Container; use pumpkin_inventory::{container_click, InventoryError, OptionallyCombinedContainer}; +use pumpkin_inventory::{Container, WindowType}; use pumpkin_protocol::client::play::{ CCloseContainer, COpenScreen, CSetContainerContent, CSetContainerProperty, CSetContainerSlot, }; @@ -22,7 +22,7 @@ use std::sync::Arc; #[expect(unused)] impl Player { - pub async fn open_container(&self, server: &Server, minecraft_menu_id: &str) { + pub async fn open_container(&self, server: &Server, window_type: WindowType) { let inventory = self.inventory.lock().await; inventory .state_id @@ -30,17 +30,7 @@ impl Player { let total_opened_containers = inventory.total_opened_containers; let container = self.get_open_container(server); let container = container.as_ref().map(|container| container.lock()); - // let menu_protocol_id = (*pumpkin_world::global_registry::REGISTRY - // .get("minecraft:menu") - // .unwrap() - // .entries - // .get(minecraft_menu_id) - // .expect("Should be a valid menu id") - // .get("protocol_id") - // .unwrap()) - // .into(); // TODO - let menu_protocol_id = VarInt(0); let window_title = match container { Some(container) => container.await.window_name(), None => inventory.window_name(), @@ -50,7 +40,7 @@ impl Player { self.client .send_packet(&COpenScreen::new( total_opened_containers.into(), - menu_protocol_id, + VarInt(window_type as i32), title, )) .await; diff --git a/pumpkin/src/client/mod.rs b/pumpkin/src/client/mod.rs index 503a6ea16..8e4065c5b 100644 --- a/pumpkin/src/client/mod.rs +++ b/pumpkin/src/client/mod.rs @@ -43,7 +43,7 @@ use thiserror::Error; pub mod authentication; mod client_packet; -mod combat; +pub mod combat; mod container; pub mod player_packet; diff --git a/pumpkin/src/client/player_packet.rs b/pumpkin/src/client/player_packet.rs index ea85d3b6a..404ae7a52 100644 --- a/pumpkin/src/client/player_packet.rs +++ b/pumpkin/src/client/player_packet.rs @@ -7,7 +7,7 @@ use crate::{ world::player_chunker, }; use num_traits::FromPrimitive; -use pumpkin_config::{PVPConfig, ADVANCED_CONFIG}; +use pumpkin_config::ADVANCED_CONFIG; use pumpkin_core::math::position::WorldPosition; use pumpkin_core::{ math::{vector3::Vector3, wrap_degrees}, @@ -15,12 +15,11 @@ use pumpkin_core::{ GameMode, }; use pumpkin_inventory::{InventoryError, WindowType}; -use pumpkin_macros::sound; +use pumpkin_protocol::server::play::{SCloseContainer, SKeepAlive, SSetPlayerGround, SUseItem}; use pumpkin_protocol::{ client::play::{ - Animation, CAcknowledgeBlockChange, CEntityAnimation, CHeadRot, CHurtAnimation, - CPingResponse, CPlayerChatMessage, CUpdateEntityPos, CUpdateEntityPosRot, CUpdateEntityRot, - FilterType, + Animation, CAcknowledgeBlockChange, CEntityAnimation, CHeadRot, CPingResponse, + CPlayerChatMessage, CUpdateEntityPos, CUpdateEntityPosRot, CUpdateEntityRot, FilterType, }, server::play::{ Action, ActionType, SChatCommand, SChatMessage, SClientInformationPlay, SConfirmTeleport, @@ -28,18 +27,10 @@ use pumpkin_protocol::{ SPlayerPosition, SPlayerPositionRotation, SPlayerRotation, SSetCreativeSlot, SSetHeldItem, SSwingArm, SUseItemOn, Status, }, - SoundCategory, -}; -use pumpkin_protocol::{ - server::play::{SCloseContainer, SKeepAlive, SSetPlayerGround, SUseItem}, - VarInt, }; use pumpkin_world::block::{block_registry::get_block_by_item, BlockFace}; -use super::{ - combat::{self, player_attack_sound, AttackType}, - PlayerConfig, -}; +use super::PlayerConfig; fn modulus(a: f32, b: f32) -> f32 { ((a % b) + b) % b @@ -435,7 +426,7 @@ impl Player { return; }; - self.attack(&victim, config).await; + self.attack(&victim).await; } ActionType::Interact | ActionType::InteractAt => { log::debug!("todo"); @@ -443,72 +434,6 @@ impl Player { } } - pub async fn attack(&self, victim: &Arc, config: &PVPConfig) { - let world = &self.living_entity.entity.world; - let victim_entity = &victim.living_entity.entity; - let attacker_entity = &self.living_entity.entity; - - let pos = victim_entity.pos.load(); - - let attack_cooldown_progress = self.get_attack_cooldown_progress(0.5); - self.last_attacked_ticks - .store(0, std::sync::atomic::Ordering::Relaxed); - - // TODO: attack damage attribute and deal damage - let damage = 2.0; - if !victim.living_entity.damage(damage) - || (config.protect_creative && victim.gamemode.load() == GameMode::Creative) - { - world - .play_sound( - sound!("minecraft:entity.player.attack.nodamage"), - SoundCategory::Players, - &pos, - ) - .await; - return; - } - - world - .play_sound( - sound!("minecraft:entity.player.hurt"), - SoundCategory::Players, - &pos, - ) - .await; - - let attack_type = AttackType::new(self, attack_cooldown_progress).await; - - player_attack_sound(&pos, world, attack_type).await; - - // if is_crit { - // damage *= 1.5; - // } - - let mut knockback_strength = 1.0; - match attack_type { - AttackType::Knockback => knockback_strength += 1.0, - AttackType::Sweeping => { - combat::spawn_sweep_particle(attacker_entity, world, &pos).await; - } - _ => {} - }; - - if config.knockback { - combat::handle_knockback(attacker_entity, victim, victim_entity, knockback_strength) - .await; - } - - if config.hurt_animation { - let entity_id = VarInt(victim_entity.entity_id); - world - .broadcast_packet_all(&CHurtAnimation::new(&entity_id, attacker_entity.yaw.load())) - .await; - } - - if config.swing {} - } - pub async fn handle_player_action(&self, player_action: SPlayerAction) { match Status::from_i32(player_action.status.0) { Some(status) => match status { @@ -674,6 +599,10 @@ impl Player { // This function will in the future be used to keep track of if the client is in a valid state. // But this is not possible yet pub async fn handle_close_container(&self, server: &Server, packet: SCloseContainer) { + let Some(_window_type) = WindowType::from_i32(packet.window_id.0) else { + self.kick(TextComponent::text("Invalid window ID")).await; + return; + }; // window_id 0 represents both 9x1 Generic AND inventory here self.inventory .lock() @@ -688,9 +617,5 @@ impl Player { } self.open_container.store(None); } - let Some(_window_type) = WindowType::from_i32(packet.window_id.0) else { - self.kick(TextComponent::text("Invalid window ID")).await; - return; - }; } } diff --git a/pumpkin/src/command/commands/cmd_echest.rs b/pumpkin/src/command/commands/cmd_echest.rs index 625f0610d..04ac05acb 100644 --- a/pumpkin/src/command/commands/cmd_echest.rs +++ b/pumpkin/src/command/commands/cmd_echest.rs @@ -32,7 +32,9 @@ impl CommandExecutor for EchestExecutor { open_containers.insert(0, open_container); } } - player.open_container(server, "minecraft:generic_9x3").await; + player + .open_container(server, pumpkin_inventory::WindowType::Generic9x3) + .await; } Ok(()) diff --git a/pumpkin/src/entity/player.rs b/pumpkin/src/entity/player.rs index dc4db4f7d..097b64bf9 100644 --- a/pumpkin/src/entity/player.rs +++ b/pumpkin/src/entity/player.rs @@ -11,6 +11,7 @@ use crossbeam::atomic::AtomicCell; use itertools::Itertools; use num_derive::FromPrimitive; use num_traits::{FromPrimitive, ToPrimitive}; +use pumpkin_config::ADVANCED_CONFIG; use pumpkin_core::{ math::{boundingbox::BoundingBox, position::WorldPosition, vector2::Vector2, vector3::Vector3}, text::TextComponent, @@ -18,11 +19,13 @@ use pumpkin_core::{ }; use pumpkin_entity::{entity_type::EntityType, EntityId}; use pumpkin_inventory::player::PlayerInventory; +use pumpkin_macros::sound; use pumpkin_protocol::{ bytebuf::DeserializerError, client::play::{ - CGameEvent, CKeepAlive, CPlayDisconnect, CPlayerAbilities, CPlayerInfoUpdate, CSetHealth, - CSyncPlayerPosition, CSystemChatMessage, GameEvent, PlayerAction, + CGameEvent, CHurtAnimation, CKeepAlive, CPlayDisconnect, CPlayerAbilities, + CPlayerInfoUpdate, CSetHealth, CSyncPlayerPosition, CSystemChatMessage, GameEvent, + PlayerAction, }, server::play::{ SChatCommand, SChatMessage, SClientInformationPlay, SConfirmTeleport, SInteract, @@ -30,7 +33,7 @@ use pumpkin_protocol::{ SPlayerRotation, SSetCreativeSlot, SSetHeldItem, SSetPlayerGround, SSwingArm, SUseItem, SUseItemOn, ServerboundPlayPackets, }, - RawPacket, ServerPacket, VarInt, + RawPacket, ServerPacket, SoundCategory, VarInt, }; use tokio::sync::{Mutex, Notify}; use tokio::task::JoinHandle; @@ -40,7 +43,11 @@ use pumpkin_world::{cylindrical_chunk_iterator::Cylindrical, item::ItemStack}; use super::Entity; use crate::{ - client::{authentication::GameProfile, Client, PlayerConfig}, + client::{ + authentication::GameProfile, + combat::{self, player_attack_sound, AttackType}, + Client, PlayerConfig, + }, server::Server, world::World, }; @@ -331,6 +338,73 @@ impl Player { //self.living_entity.entity.world.level.list_cached(); } + pub async fn attack(&self, victim: &Arc) { + let world = &self.living_entity.entity.world; + let victim_entity = &victim.living_entity.entity; + let attacker_entity = &self.living_entity.entity; + let config = &ADVANCED_CONFIG.pvp; + + let pos = victim_entity.pos.load(); + + let attack_cooldown_progress = self.get_attack_cooldown_progress(0.5); + self.last_attacked_ticks + .store(0, std::sync::atomic::Ordering::Relaxed); + + // TODO: attack damage attribute and deal damage + let damage = 2.0; + if !victim.living_entity.damage(damage) + || (config.protect_creative && victim.gamemode.load() == GameMode::Creative) + { + world + .play_sound( + sound!("minecraft:entity.player.attack.nodamage"), + SoundCategory::Players, + &pos, + ) + .await; + return; + } + + world + .play_sound( + sound!("minecraft:entity.player.hurt"), + SoundCategory::Players, + &pos, + ) + .await; + + let attack_type = AttackType::new(self, attack_cooldown_progress).await; + + player_attack_sound(&pos, world, attack_type).await; + + // if is_crit { + // damage *= 1.5; + // } + + let mut knockback_strength = 1.0; + match attack_type { + AttackType::Knockback => knockback_strength += 1.0, + AttackType::Sweeping => { + combat::spawn_sweep_particle(attacker_entity, world, &pos).await; + } + _ => {} + }; + + if config.knockback { + combat::handle_knockback(attacker_entity, victim, victim_entity, knockback_strength) + .await; + } + + if config.hurt_animation { + let entity_id = VarInt(victim_entity.entity_id); + world + .broadcast_packet_all(&CHurtAnimation::new(&entity_id, attacker_entity.yaw.load())) + .await; + } + + if config.swing {} + } + pub async fn await_cancel(&self) { self.cancel_tasks.notified().await; } diff --git a/pumpkin/src/rcon/mod.rs b/pumpkin/src/rcon/mod.rs index 2f20c7257..fa87d4348 100644 --- a/pumpkin/src/rcon/mod.rs +++ b/pumpkin/src/rcon/mod.rs @@ -3,23 +3,12 @@ use std::net::SocketAddr; use packet::{ClientboundPacket, Packet, PacketError, ServerboundPacket}; use pumpkin_config::{RCONConfig, ADVANCED_CONFIG}; use std::sync::Arc; -use thiserror::Error; use tokio::io::{AsyncReadExt, AsyncWriteExt}; use crate::server::Server; mod packet; -#[derive(Debug, Error)] -pub enum RCONError { - #[error("authentication failed")] - Auth, - #[error("command exceeds the maximum length")] - CommandTooLong, - #[error("{}", _0)] - Io(std::io::Error), -} - pub struct RCONServer; impl RCONServer { diff --git a/pumpkin/src/server/mod.rs b/pumpkin/src/server/mod.rs index 745502831..eb6ff064b 100644 --- a/pumpkin/src/server/mod.rs +++ b/pumpkin/src/server/mod.rs @@ -147,7 +147,7 @@ impl Server { } pub async fn remove_player(&self) { - // TODO: Config if we want increase online + // TODO: Config if we want decrease online self.server_listing.lock().await.remove_player(); }