Skip to content

Commit 0575ff3

Browse files
authored
Merge branch 'master' into feat/commands
2 parents 231b8fb + cc11874 commit 0575ff3

File tree

12 files changed

+295
-17
lines changed

12 files changed

+295
-17
lines changed

.etc/example-config.toml

+2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ max_players = 100
1010
network_tick_rate = 30
1111
# World name to load
1212
world = "world"
13+
# Whether the server should validate players via the whitelist
14+
whitelist = false
1315
# Network compression threshold (can be negative). This decides how long a packet has to be before it is compressed.
1416
# Very small packets may actually increase in size when compressed, so setting it to 0 won't be perfect in all situations.
1517
# Set to -1 to disable compression.

Cargo.toml

+3
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ parking_lot = "0.12.3"
124124
rayon = "1.10.0"
125125

126126
# Network
127+
reqwest = { version = "0.12.9", features = ["json"] }
127128

128129
# Error handling
129130
thiserror = "2.0.3"
@@ -140,6 +141,7 @@ serde_derive = "1.0.210"
140141
base64 = "0.22.1"
141142
bitcode = "0.6.3"
142143
bitcode_derive = "0.6.3"
144+
toml = "0.8.19"
143145

144146
# Bit manipulation
145147
byteorder = "1.5.0"
@@ -185,6 +187,7 @@ colored = "2.1.0"
185187
deepsize = "0.2.0"
186188
page_size = "0.6.0"
187189
enum-ordinalize = "4.3.0"
190+
regex = "1.11.1"
188191

189192
# I/O
190193
tempfile = "3.12.0"

src/bin/src/main.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ extern crate core;
55
use crate::errors::BinaryError;
66
use clap::Parser;
77
use ferrumc_config::statics::get_global_config;
8+
use ferrumc_config::whitelist::create_whitelist;
89
use ferrumc_ecs::Universe;
910
use ferrumc_general_purpose::paths::get_root_path;
1011
use ferrumc_net::server::create_server_listener;
@@ -59,13 +60,14 @@ async fn main() {
5960
async fn entry() -> Result<()> {
6061
let state = create_state().await?;
6162
let global_state = Arc::new(state);
63+
create_whitelist().await;
6264

6365
// Needed for some reason because ctor doesn't really want to do ctor things otherwise.
6466
ferrumc_default_commands::init();
6567

6668
let all_system_handles = tokio::spawn(definition::start_all_systems(global_state.clone()));
6769

68-
// Start the systems and wait until all of them are done
70+
//Start the systems and wait until all of them are done
6971
all_system_handles.await??;
7072

7173
// Stop all systems

src/bin/src/packet_handlers/login_process.rs

+26-10
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use ferrumc_commands::graph::CommandsPacket;
2+
use ferrumc_config::statics::{get_global_config, get_whitelist};
23
use ferrumc_core::identity::player_identity::PlayerIdentity;
34
use ferrumc_core::transform::grounded::OnGround;
45
use ferrumc_core::transform::position::Position;
@@ -16,6 +17,7 @@ use ferrumc_net::packets::outgoing::client_bound_known_packs::ClientBoundKnownPa
1617
use ferrumc_net::packets::outgoing::finish_configuration::FinishConfigurationPacket;
1718
use ferrumc_net::packets::outgoing::game_event::GameEventPacket;
1819
use ferrumc_net::packets::outgoing::keep_alive::OutgoingKeepAlivePacket;
20+
use ferrumc_net::packets::outgoing::login_disconnect::LoginDisconnectPacket;
1921
use ferrumc_net::packets::outgoing::login_play::LoginPlayPacket;
2022
use ferrumc_net::packets::outgoing::login_success::LoginSuccessPacket;
2123
use ferrumc_net::packets::outgoing::registry_data::get_registry_packets;
@@ -32,23 +34,37 @@ async fn handle_login_start(
3234
login_start_event: LoginStartEvent,
3335
state: GlobalState,
3436
) -> Result<LoginStartEvent, NetError> {
35-
debug!("Handling login start event");
36-
3737
let uuid = login_start_event.login_start_packet.uuid;
3838
let username = login_start_event.login_start_packet.username.as_str();
39-
debug!("Received login start from user with username {}", username);
40-
41-
// Add the player identity component to the ECS for the entity.
42-
state.universe.add_component::<PlayerIdentity>(
43-
login_start_event.conn_id,
44-
PlayerIdentity::new(username.to_string(), uuid),
45-
)?;
39+
let player_identity = PlayerIdentity::new(username.to_string(), uuid);
40+
debug!("Handling login start event for user: {username}, uuid: {uuid}");
4641

47-
//Send a Login Success Response to further the login sequence
4842
let mut writer = state
4943
.universe
5044
.get_mut::<StreamWriter>(login_start_event.conn_id)?;
5145

46+
if get_global_config().whitelist {
47+
let whitelist = get_whitelist();
48+
49+
if whitelist.get(&uuid).is_none() {
50+
writer
51+
.send_packet(
52+
&LoginDisconnectPacket::new(
53+
"{\"translate\":\"multiplayer.disconnect.not_whitelisted\"}",
54+
),
55+
&NetEncodeOpts::WithLength,
56+
)
57+
.await?;
58+
return Ok(login_start_event);
59+
}
60+
}
61+
62+
// Add the player identity component to the ECS for the entity.
63+
state
64+
.universe
65+
.add_component::<PlayerIdentity>(login_start_event.conn_id, player_identity)?;
66+
67+
//Send a Login Success Response to further the login sequence
5268
writer
5369
.send_packet(
5470
&LoginSuccessPacket::new(uuid, username),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
use ferrumc_macros::{packet, NetEncode};
2+
use std::io::Write;
3+
4+
#[derive(NetEncode)]
5+
#[packet(packet_id = 0x00)]
6+
pub struct LoginDisconnectPacket<'a> {
7+
pub reason: &'a str,
8+
}
9+
10+
impl<'a> LoginDisconnectPacket<'a> {
11+
pub fn new(reason: &'a str) -> Self {
12+
Self { reason }
13+
}
14+
}

src/lib/net/src/packets/outgoing/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ pub mod disconnect;
44
pub mod finish_configuration;
55
pub mod game_event;
66
pub mod keep_alive;
7+
pub mod login_disconnect;
78
pub mod login_play;
89
pub mod login_success;
910
pub mod ping_response;

src/lib/utils/config/Cargo.toml

+8-2
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,18 @@ edition = "2021"
55
description = "FerrumC configuration utilities"
66

77
[dependencies]
8-
toml = "0.8.19"
8+
toml = { workspace = true }
99
thiserror = { workspace = true }
1010
serde = { workspace = true }
1111
serde_derive = { workspace = true }
1212
tracing = { workspace = true }
1313
parking_lot = { workspace = true }
1414
base64 = { workspace = true }
1515
ferrumc-general-purpose = { workspace = true }
16-
lazy_static = { workspace = true }
16+
ferrumc-core = { workspace = true }
17+
lazy_static = { workspace = true }
18+
dashmap = { workspace = true }
19+
uuid = { workspace = true }
20+
regex = { workspace = true }
21+
reqwest = { workspace = true }
22+
futures = { workspace = true }

src/lib/utils/config/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ pub mod favicon;
1515
pub mod server_config;
1616
pub mod setup;
1717
pub mod statics;
18+
pub mod whitelist;
1819

1920
// Re-exports
2021
pub use server_config::DatabaseConfig;

src/lib/utils/config/src/server_config.rs

+2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use serde_derive::{Deserialize, Serialize};
1515
/// - `database` - [DatabaseConfig]: The configuration for the database.
1616
/// - `world`: The name of the world that the server will load.
1717
/// - `network_compression_threshold`: The threshold at which the server will compress network packets.
18+
/// - `whitelist`: Whether the server whitelist is enabled or not.
1819
#[derive(Debug, Deserialize, Serialize)]
1920
pub struct ServerConfig {
2021
pub host: String,
@@ -25,6 +26,7 @@ pub struct ServerConfig {
2526
pub database: DatabaseConfig,
2627
pub world: String,
2728
pub network_compression_threshold: i32, // Can be negative
29+
pub whitelist: bool,
2830
}
2931

3032
/// The database configuration section from [ServerConfig].

src/lib/utils/config/src/setup.rs

+4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::statics::DEFAULT_CONFIG;
2+
use crate::whitelist::create_blank_whitelist_file;
23
use ferrumc_general_purpose::paths::get_root_path;
34
use std::fs::File;
45
use std::io::Write;
@@ -26,6 +27,9 @@ impl From<std::io::Error> for SetupError {
2627
}
2728

2829
pub fn setup() -> Result<(), SetupError> {
30+
if !std::fs::exists(get_root_path().join("whitelist.txt"))? {
31+
create_blank_whitelist_file();
32+
}
2933
if std::fs::exists(get_root_path().join("config.toml"))? {
3034
return Ok(());
3135
}

src/lib/utils/config/src/statics.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
1-
//! # Statics module.
2-
//!
3-
//! Contains the static global configuration and its related functions.
4-
51
use crate::server_config::ServerConfig;
2+
use dashmap::DashSet;
63
use ferrumc_general_purpose::paths::get_root_path;
74
use lazy_static::lazy_static;
85
use std::fs::File;
@@ -16,6 +13,8 @@ pub(crate) const DEFAULT_CONFIG: &str = include_str!("../../../../../.etc/exampl
1613
lazy_static! {
1714
/// The server configuration that is stored in memory.
1815
static ref CONFIG: ServerConfig = create_config();
16+
/// The whitelist of player uuids.
17+
pub static ref WHITELIST: DashSet<u128> = DashSet::new();
1918
}
2019
fn create_config() -> ServerConfig {
2120
let config_location = get_root_path().join("config.toml");
@@ -77,3 +76,7 @@ fn create_config() -> ServerConfig {
7776
pub fn get_global_config() -> &'static ServerConfig {
7877
&CONFIG
7978
}
79+
80+
pub fn get_whitelist() -> &'static DashSet<u128> {
81+
&WHITELIST
82+
}

0 commit comments

Comments
 (0)