Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ jobs:
target: x86_64-unknown-linux-musl
- os: ubuntu-24.04-arm
target: aarch64-unknown-linux-musl
- os: ubuntu-22.04 # cuz glibc forward incompatible
target: x86_64-unknown-linux-gnu
- os: ubuntu-22.04-arm
target: aarch64-unknown-linux-gnu
- os: windows-latest
target: x86_64-pc-windows-msvc
- os: macos-14
Expand All @@ -60,13 +64,15 @@ jobs:
with:
shared-key: "ferrumc"
- name: Install musl-tools
if: runner.os == 'Linux'
if: contains(matrix.target, 'musl')
run: sudo apt-get update && sudo apt-get install -y musl-tools

- name: Build
run: cargo build --profile production --target ${{ matrix.target }} -p ferrumc --features release
env:
CC: ${{ runner.os == 'Linux' && 'musl-gcc' || '' }}
CXX: ${{ runner.os == 'Linux' && 'g++' || '' }}
CC: ${{ contains(matrix.target, 'musl') && 'musl-gcc' || '' }}
CXX: ${{ contains(matrix.target, 'musl') && 'g++' || '' }}

- name: Package (Linux/macOS)
if: runner.os != 'Windows'
run: tar -czf ferrumc-${{ github.ref_name }}-${{ matrix.target }}.tar.gz -C target/${{ matrix.target }}/production ferrumc
Expand Down
7 changes: 7 additions & 0 deletions assets/data/configs/main-config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,13 @@ chunks_per_tick = 0
# set to a static number or unlimited. Setting this to 0 disables the minimum.
chunks_per_tick_min = 16

[fluids]
# Which fluid-spreading algorithm to use.
# "vanilla" - Minecraft-faithful: fluid steers toward the nearest hole (bounded slope search).
# Matches vanilla behaviour at a higher CPU cost.
# "simplified" - Cheaper approximation: uniform spread with no hole steering.
algorithm = "vanilla"

[dashboard]
# The port the dashboard will run on.
port = 9000
Expand Down
1 change: 1 addition & 0 deletions src/bin/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ crossbeam-channel = { workspace = true }
uuid = { workspace = true }
dhat = { workspace = true, optional = true }
bitcode = { workspace = true }
ctor = { workspace = true }

[features]
dhat = ["dep:dhat"]
Expand Down
10 changes: 10 additions & 0 deletions src/bin/src/commands/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
//! Binary-local commands (those that need ECS resources defined in the binary crate, such as the
//! fluid scheduler/control, which the shared `ferrumc-default-commands` crate cannot name).
//!
//! Commands register themselves at startup via the `#[command]` macro's `#[ctor]`. [`init`] only
//! exists to guarantee this module is linked into the final binary so those constructors run.

pub mod tick;

/// Ensures the binary-local command modules are linked so their `#[ctor]` registrations fire.
pub fn init() {}
66 changes: 66 additions & 0 deletions src/bin/src/commands/tick.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
//! `/tick` debug commands for the fluid simulation clock.
//!
//! These let a developer pause and single-step fluid spreading so the large cascade produced by a
//! single bucket placement can be inspected one game tick at a time, instead of being buried in
//! logs. Only the fluid simulation is affected; the rest of the server keeps ticking, so you can
//! still move around and place/break blocks while fluids are frozen.
//!
//! * `/tick freeze` — stop advancing fluid ticks.
//! * `/tick run` — resume normal fluid ticking.
//! * `/tick step [n]` — while frozen, advance fluid simulation by `n` ticks (default 1).

use crate::systems::fluids::FluidTickControl;
use bevy_ecs::prelude::ResMut;
use ferrumc_commands::arg::primitive::int::Integer;
use ferrumc_commands::Sender;
use ferrumc_macros::command;
use ferrumc_text::{NamedColor, TextComponentBuilder};

#[command("tick freeze")]
fn tick_freeze(#[sender] sender: Sender, mut control: ResMut<FluidTickControl>) {
control.frozen = true;
control.steps = 0;
sender.send_message(
TextComponentBuilder::new("Fluid simulation frozen. Use /tick step [n] or /tick run.")
.color(NamedColor::Yellow)
.build(),
false,
);
}

#[command("tick run")]
fn tick_run(#[sender] sender: Sender, mut control: ResMut<FluidTickControl>) {
control.frozen = false;
control.steps = 0;
sender.send_message(
TextComponentBuilder::new("Fluid simulation resumed.")
.color(NamedColor::Green)
.build(),
false,
);
}

/// Step count is bounded so a typo cannot queue a runaway number of steps.
type StepCount = Integer<1, 10_000>;

#[command("tick step")]
fn tick_step(
#[sender] sender: Sender,
#[arg] count: StepCount,
mut control: ResMut<FluidTickControl>,
) {
// Stepping implies frozen: if the user steps without freezing first, freeze now so the steps
// are meaningful rather than racing the normal clock.
control.frozen = true;
let n = (*count).max(0) as u32;
control.steps = control.steps.saturating_add(n);
sender.send_message(
TextComponentBuilder::new(format!(
"Queued {n} fluid step(s); {} pending.",
control.steps
))
.color(NamedColor::Aqua)
.build(),
false,
);
}
2 changes: 2 additions & 0 deletions src/bin/src/game_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ pub fn start_game_loop(global_state: GlobalState) -> Result<(), BinaryError> {

// Initialize default server commands (e.g., /stop, /help, etc.)
ferrumc_default_commands::init();
// Initialize binary-local commands (e.g., /tick freeze|step|run for fluid debugging).
crate::commands::init();

// Wrap global state for ECS resource access
let global_state_res = GlobalStateResource(global_state.clone());
Expand Down
1 change: 1 addition & 0 deletions src/bin/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use std::time::Instant;
use tracing::{error, info};

mod cli;
pub(crate) mod commands;
pub(crate) mod errors;
mod game_loop;
mod launch;
Expand Down
3 changes: 2 additions & 1 deletion src/bin/src/register_resources.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::systems::fluids::{ActiveDimension, FluidScheduler};
use crate::systems::fluids::{ActiveDimension, FluidScheduler, FluidTickControl};
use crate::systems::new_connections::NewConnectionRecv;
use bevy_ecs::prelude::World;
use crossbeam_channel::Receiver;
Expand All @@ -25,6 +25,7 @@ pub fn register_resources(
world.insert_resource(TickCounter::new());
world.insert_resource(FluidScheduler::default());
world.insert_resource(ActiveDimension::default());
world.insert_resource(FluidTickControl::default());
world.insert_resource(ServerPerformance::new(get_global_config().tps));
world.insert_resource(PhysicalRegistry::new());
}
Loading