mirror of
https://github.com/horizon-rust/horizon.git
synced 2026-11-09 17:19:15 -10:00
Autosave counts down from max(100, tick rate * 300) ticks
MinecraftServer.computeNextAutosaveInterval asks for Math.max(100, (int)(rate * 300.0F)) ticks, where the rate is the tick rate or, while /tick sprint runs, the measured NANOSECONDS_PER_SECOND / (averageTickTime + 1); tickServer counts ticksUntilAutosave down and saves when it reaches zero, and onTickRateChanged shortens a wait already running. Horizon saved on every six-thousandth tick whatever the rate, so /tick rate and /tick sprint changed how long a world ran between saves and a slow rate kept the same interval. The countdown is a field on Game, the interval is next_autosave_interval, and /tick rate now calls on_tick_rate_changed. Twenty ticks a second is still the six thousand ticks a world autosaved on, so nothing changes at the default. Port map: the two rest-013 rows now name those functions.
This commit is contained in:
1 parent
3476a852df
commit
8bd75ba4dd
3 files changed
+57
-3
No files matched your search
@@ -2610,6 +2610,9 @@ struct Game<'a> {
|
||||
saving_indicator: horizon_client::hud_overlays::SavingIndicator,
|
||||
/// This game's world is autosaving this tick (`MinecraftServer.isSaving`).
|
||||
autosaving: bool,
|
||||
/// `MinecraftServer.ticksUntilAutosave`: the ticks left before the next
|
||||
/// autosave, counted down a tick at a time.
|
||||
ticks_until_autosave: i64,
|
||||
applied_modifiers: Vec<(String, String)>,
|
||||
experience: Experience,
|
||||
orbs: Vec<ExperienceOrb>,
|
||||
@@ -7298,12 +7301,19 @@ impl Game<'_> {
|
||||
self.world.weather.tick_levels();
|
||||
self.tick_weather_effects();
|
||||
}
|
||||
self.autosaving = self.ticks.is_multiple_of(6000);
|
||||
// MinecraftServer.tickServer's countdown, then autoSave: three
|
||||
// hundred seconds of ticks at the rate the server runs at now.
|
||||
self.ticks_until_autosave -= 1;
|
||||
self.autosaving = self.ticks_until_autosave <= 0;
|
||||
if let Some(serving) = &self.serving {
|
||||
serving.set_saving(self.autosaving);
|
||||
}
|
||||
if self.autosaving {
|
||||
self.save_game_with(false)?;
|
||||
self.ticks_until_autosave = self.next_autosave_interval();
|
||||
if let Some(serving) = &self.serving {
|
||||
serving.set_saving(false);
|
||||
}
|
||||
}
|
||||
if running {
|
||||
self.advance_clock();
|
||||
@@ -15326,6 +15336,25 @@ impl Game<'_> {
|
||||
fn save_game(&mut self) -> Result<()> {
|
||||
self.save_game_with(true)
|
||||
}
|
||||
/// `MinecraftServer.computeNextAutosaveInterval`: three hundred seconds
|
||||
/// of ticks at the rate the server runs at now - its measured rate while
|
||||
/// a `/tick sprint` runs - never fewer than a hundred.
|
||||
fn next_autosave_interval(&self) -> i64 {
|
||||
let rate = if self.clock.sprinting() {
|
||||
1.0e9 / (self.clock.average_nanos() + 1) as f32
|
||||
} else {
|
||||
self.clock.rate()
|
||||
};
|
||||
autosave_interval(rate)
|
||||
}
|
||||
/// `MinecraftServer.onTickRateChanged`: a rate that asks for a shorter
|
||||
/// wait than the one already running shortens it.
|
||||
pub(super) fn on_tick_rate_changed(&mut self) {
|
||||
let interval = self.next_autosave_interval();
|
||||
if interval < self.ticks_until_autosave {
|
||||
self.ticks_until_autosave = interval;
|
||||
}
|
||||
}
|
||||
/// The autosave doesn't `wait` for the chunks to be on disk: every
|
||||
/// generated chunk is saved, hundreds at a time, encoded and written on
|
||||
/// the region writer meanwhile.
|
||||
@@ -16984,6 +17013,10 @@ impl Game<'_> {
|
||||
}
|
||||
}
|
||||
}
|
||||
/// `computeNextAutosaveInterval`'s arithmetic: `Math.max(100, (int)(rate * 300.0F))`.
|
||||
fn autosave_interval(rate: f32) -> i64 {
|
||||
i64::from((rate * 300.0) as i32).max(100)
|
||||
}
|
||||
impl ApplicationHandler for Game<'_> {
|
||||
fn resumed(&mut self, event_loop: &ActiveEventLoop) {
|
||||
if self.window.is_some() {
|
||||
@@ -18918,6 +18951,8 @@ impl<'a> Game<'a> {
|
||||
tool_highlight: Default::default(),
|
||||
saving_indicator: Default::default(),
|
||||
autosaving: false,
|
||||
// `computeNextAutosaveInterval` at the clock's 20 ticks a second.
|
||||
ticks_until_autosave: 6000,
|
||||
applied_modifiers: Vec::new(),
|
||||
experience: Experience::default(),
|
||||
orbs: Vec::new(),
|
||||
@@ -21715,6 +21750,22 @@ mod tests {
|
||||
use super::*;
|
||||
use horizon_client::container_screen::{Button, Clicks, Release, Target};
|
||||
|
||||
/// `MinecraftServer.computeNextAutosaveInterval`: three hundred seconds of
|
||||
/// ticks at the rate the server runs at, never fewer than a hundred.
|
||||
#[test]
|
||||
fn the_autosave_waits_for_three_hundred_seconds_of_ticks() {
|
||||
// 20 ticks a second is the six thousand ticks a world autosaved on
|
||||
// before the rate could be changed (`/tick rate`).
|
||||
assert_eq!(autosave_interval(20.0), 6000);
|
||||
assert_eq!(autosave_interval(10.0), 3000);
|
||||
assert_eq!(autosave_interval(40.0), 12000);
|
||||
assert_eq!(autosave_interval(1000.0), 300_000);
|
||||
// `Math.max(100, ...)`: a very low rate still autosaves every hundred
|
||||
// ticks, and a frozen clock (0) does too.
|
||||
assert_eq!(autosave_interval(0.5), 150);
|
||||
assert_eq!(autosave_interval(0.0), 100);
|
||||
}
|
||||
|
||||
/// `NativeScreenView.id` (the `screen_render_post` hook) is a mod's
|
||||
/// contract: every `Screen` has its own id, and it does not change.
|
||||
/// `Screen::id`'s match makes a new variant give itself one; this list
|
||||
|
||||
@@ -81,6 +81,9 @@ impl Game<'_> {
|
||||
_ => 20.0,
|
||||
};
|
||||
self.clock.set_rate(rate);
|
||||
// MinecraftServer.setTickRate: the autosave wait already
|
||||
// running is shortened when the new rate asks for less.
|
||||
self.on_tick_rate_changed();
|
||||
self.feedback(t(
|
||||
"commands.tick.rate.success",
|
||||
&[lit(format_fixed(f64::from(rate), 1))],
|
||||
|
||||
@@ -78,8 +78,8 @@ MinecraftServer.loadStatusIcon inline crates/horizon-client/src/game/dedicated.r
|
||||
MinecraftServer.processPacketsAndTick port crates/horizon-client/src/game/levels.rs::Game::tick_server reads the network, then ticks the levels
|
||||
MinecraftServer.autoSave inline crates/horizon-client/src/game.rs::Game::tick gap: minor: the save runs every 6000 ticks; /save-off is checked in the dedicated loop, where the check does nothing, so it does not stop the save
|
||||
MinecraftServer.logTickMethodTime skip:server tick timing log for the profiler
|
||||
MinecraftServer.computeNextAutosaveInterval missing minor: the save runs every 6000 ticks (game.rs tick), not 300 s scaled by the tick rate
|
||||
MinecraftServer.onTickRateChanged missing minor: the autosave interval does not follow /tick rate
|
||||
MinecraftServer.computeNextAutosaveInterval port crates/horizon-client/src/game.rs::Game::next_autosave_interval Math.max(100, (int)(rate * 300.0F)) ticks counted down a tick at a time, at the tick rate or the measured rate while /tick sprint runs; twenty a second is still the six thousand a world autosaved on
|
||||
MinecraftServer.onTickRateChanged port crates/horizon-client/src/game.rs::Game::on_tick_rate_changed /tick rate recomputes the wait and shortens the one already running when the new rate asks for less
|
||||
MinecraftServer.buildPlayerStatus port crates/horizon-client/src/lan/mod.rs::Shared::status_json up to 12 sampled player names in the status JSON
|
||||
MinecraftServer.updateEffectiveRespawnData inline crates/horizon-client/src/game/initial_spawn.rs::Game::spawn_finder gap: minor: no cached respawn data; the radius is clamped to the border when the spawn is found
|
||||
MinecraftServer.forceGameTimeSynchronization port crates/horizon-client/src/lan/hub.rs::Hub::sync_world game time sent to guests with SetTime
|
||||
|
||||
|
Reference in new issue
Block a user