Skip to content

Commit

Permalink
Make world send rate changable via command
Browse files Browse the repository at this point in the history
  • Loading branch information
Paul1365972 committed Jan 9, 2024
1 parent 7c49162 commit ac316a4
Show file tree
Hide file tree
Showing 9 changed files with 96 additions and 15 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

27 changes: 26 additions & 1 deletion crates/core/src/plot/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use mchprs_network::packets::clientbound::{
};
use mchprs_network::packets::PacketEncoder;
use mchprs_network::PlayerPacketSender;
use mchprs_save_data::plot_data::Tps;
use mchprs_save_data::plot_data::{Tps, WorldSendRate};
use once_cell::sync::Lazy;
use std::ops::Add;
use std::str::FromStr;
Expand Down Expand Up @@ -491,6 +491,31 @@ impl Plot {
let slot = 36 + self.players[player].selected_slot;
self.players[player].set_inventory_slot(slot, Some(item));
}
"/worldsendrate" | "/wsr" => {
if args.len() != 1 {
self.players[player].send_error_message("Usage: /worldsendrate <hertz>");
return false;
}

let Ok(hertz) = args[0].parse::<u32>() else {
self.players[player].send_error_message("Unable to parse send rate!");
return false;
};
if hertz == 0 {
self.players[player].send_error_message("The world send rate cannot be 0!");
return false;
}
if hertz > 1000 {
self.players[player]
.send_error_message("The world send rate cannot go higher than 1000!");
return false;
}

self.world_send_rate = WorldSendRate(hertz);
self.reset_timings();
self.players[player]
.send_system_message("The world send rate was successfully set.");
}
_ => self.players[player].send_error_message("Command not found!"),
}
false
Expand Down
3 changes: 2 additions & 1 deletion crates/core/src/plot/data.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use super::{Plot, PlotWorld, PLOT_SECTIONS, PLOT_WIDTH};
use anyhow::{Context, Result};
use mchprs_save_data::plot_data::{ChunkData, PlotData, Tps};
use mchprs_save_data::plot_data::{ChunkData, PlotData, Tps, WorldSendRate};
use once_cell::sync::Lazy;
use std::path::Path;
use std::time::Duration;
Expand Down Expand Up @@ -55,6 +55,7 @@ static EMPTY_PLOT: Lazy<PlotData<PLOT_SECTIONS>> = Lazy::new(|| {
world.chunks.iter_mut().map(|c| c.save()).collect();
PlotData {
tps: Tps::Limited(10),
world_send_rate: WorldSendRate::default(),
chunk_data,
pending_ticks: Vec::new(),
}
Expand Down
15 changes: 10 additions & 5 deletions crates/core/src/plot/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use mchprs_blocks::{BlockFace, BlockPos};
use mchprs_network::packets::clientbound::*;
use mchprs_network::packets::SlotData;
use mchprs_network::PlayerPacketSender;
use mchprs_save_data::plot_data::{ChunkData, PlotData, Tps};
use mchprs_save_data::plot_data::{ChunkData, PlotData, Tps, WorldSendRate};
use mchprs_world::{TickEntry, TickPriority};
use monitor::TimingsMonitor;
use scoreboard::RedpilerState;
Expand Down Expand Up @@ -54,8 +54,6 @@ pub const PLOT_SECTIONS: usize = 16;
/// The plot height in blocks
pub const PLOT_BLOCK_HEIGHT: i32 = PLOT_SECTIONS as i32 * 16;

pub const WORLD_SEND_RATE: Duration = Duration::from_millis(15);

pub struct Plot {
pub world: PlotWorld,
pub players: Vec<Player>,
Expand All @@ -70,6 +68,7 @@ pub struct Plot {

// Timings
tps: Tps,
world_send_rate: WorldSendRate,
last_update_time: Instant,
lag_time: Duration,
last_nspt: Option<Duration>,
Expand Down Expand Up @@ -815,10 +814,13 @@ impl Plot {
let now = Instant::now();
self.last_player_time = now;

let world_send_rate =
Duration::from_nanos(1_000_000_000 / self.world_send_rate.0 as u64);

let max_batch_size = match self.last_nspt {
Some(Duration::ZERO) | None => 1,
Some(last_nspt) => {
let ticks_fit = (WORLD_SEND_RATE.as_nanos() / last_nspt.as_nanos()) as u64;
let ticks_fit = (world_send_rate.as_nanos() / last_nspt.as_nanos()) as u64;
// A tick previously took longer than the world send rate.
// Run at least one just so we're not stuck doing nothing
ticks_fit.max(1)
Expand Down Expand Up @@ -869,7 +871,7 @@ impl Plot {

let now = Instant::now();
let time_since_last_world_send = now - self.last_world_send_time;
if time_since_last_world_send > WORLD_SEND_RATE {
if time_since_last_world_send > world_send_rate {
self.last_world_send_time = now;
self.world.flush_block_changes();
}
Expand Down Expand Up @@ -955,6 +957,7 @@ impl Plot {
packet_senders: Vec::new(),
};
let tps = plot_data.tps;
let world_send_rate = plot_data.world_send_rate;
Plot {
last_player_time: Instant::now(),
last_update_time: Instant::now(),
Expand All @@ -970,6 +973,7 @@ impl Plot {
running: true,
auto_redpiler: CONFIG.auto_redpiler,
tps,
world_send_rate,
always_running,
redpiler: Default::default(),
timings: TimingsMonitor::new(tps),
Expand Down Expand Up @@ -1005,6 +1009,7 @@ impl Plot {
world.chunks.iter_mut().map(|c| c.save()).collect();
let data = PlotData {
tps: self.tps,
world_send_rate: self.world_send_rate,
chunk_data,
pending_ticks: world.to_be_ticked.clone(),
};
Expand Down
1 change: 1 addition & 0 deletions crates/save_data/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ rustc-hash = "1.1"
mchprs_world = { path = "../world" }
mchprs_blocks = { path = "../blocks" }
serde-big-array = "0.5"
tracing = "0.1"
22 changes: 18 additions & 4 deletions crates/save_data/src/plot_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use std::path::Path;
use std::{fmt, io};
use thiserror::Error;

const VERSION: u32 = 0;
pub const VERSION: u32 = 1;

#[derive(Error, Debug)]
pub enum PlotLoadError {
Expand All @@ -32,6 +32,9 @@ pub enum PlotLoadError {

#[error(transparent)]
Io(#[from] io::Error),

#[error("plot data version {0} too new to be loaded")]
ConversionUnavailable(u32),
}

impl From<PlotSaveError> for PlotLoadError {
Expand Down Expand Up @@ -76,6 +79,15 @@ pub enum Tps {
Unlimited,
}

#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq)]
pub struct WorldSendRate(pub u32);

impl Default for WorldSendRate {
fn default() -> Self {
Self(60)
}
}

impl fmt::Display for Tps {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Expand All @@ -88,6 +100,7 @@ impl fmt::Display for Tps {
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct PlotData<const NUM_CHUNK_SECTIONS: usize> {
pub tps: Tps,
pub world_send_rate: WorldSendRate,
pub chunk_data: Vec<ChunkData<NUM_CHUNK_SECTIONS>>,
pub pending_ticks: Vec<TickEntry>,
}
Expand All @@ -106,9 +119,10 @@ impl<const NUM_CHUNK_SECTIONS: usize> PlotData<NUM_CHUNK_SECTIONS> {
}

let version = file.read_u32::<LittleEndian>()?;
// if version < VERSION {
// return fixer::try_fix(path, FixInfo::OldVersion(version))?.ok_or(PlotLoadError::ConversionFailed(version));
// }
if version < VERSION {
return fixer::try_fix(path, FixInfo::OldVersion { version })?
.ok_or(PlotLoadError::ConversionFailed(version));
}
if version > VERSION {
return Err(PlotLoadError::TooNew(version));
}
Expand Down
15 changes: 12 additions & 3 deletions crates/save_data/src/plot_data/fixer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,18 @@
//! module may become quite big.
use super::{PlotData, PlotLoadError};
use crate::plot_data::VERSION;
use std::fs;
use std::path::Path;
use tracing::debug;

mod pre_header;
mod pre_worldsendrate;

#[derive(Debug)]
pub enum FixInfo {
InvalidHeader,
// OldVersion(u32),
OldVersion { version: u32 },
}

fn make_backup(path: impl AsRef<Path>) -> Result<(), PlotLoadError> {
Expand All @@ -38,19 +42,24 @@ pub fn try_fix<const NUM_SECTIONS: usize>(
path: impl AsRef<Path>,
info: FixInfo,
) -> Result<Option<PlotData<NUM_SECTIONS>>, PlotLoadError> {
debug!("Trying to fix plot with {:?}", info);
let result = match info {
FixInfo::InvalidHeader => {
let data = fs::read(&path)?;
pre_header::try_fix(&data)
}
// We don't have old versions yet
// FixInfo::OldVersion(_) => None,
FixInfo::OldVersion { version: 0 } => {
let data = fs::read(&path)?;
pre_worldsendrate::try_fix(&data)
}
_ => None,
};

Ok(match result {
Some(data) => {
make_backup(&path)?;
data.save_to_file(&path)?;
debug!("Successfully converted plot to version {}", VERSION);
Some(data)
}
None => None,
Expand Down
3 changes: 2 additions & 1 deletion crates/save_data/src/plot_data/fixer/pre_header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//! plot save file. For mchprs versions targetting 1.17.1 and below, we did
//! not have a file header.
use crate::plot_data::{ChunkData, ChunkSectionData, PlotData, Tps};
use crate::plot_data::{ChunkData, ChunkSectionData, PlotData, Tps, WorldSendRate};
use mchprs_blocks::block_entities::BlockEntity;
use mchprs_blocks::BlockPos;
use mchprs_world::TickEntry;
Expand Down Expand Up @@ -32,6 +32,7 @@ pub fn try_fix<const NUM_SECTIONS: usize>(data: &[u8]) -> Option<PlotData<NUM_SE
u32::MAX => Tps::Unlimited,
limit => Tps::Limited(limit),
},
world_send_rate: WorldSendRate::default(),
chunk_data: old_data
.chunk_data
.into_iter()
Expand Down
24 changes: 24 additions & 0 deletions crates/save_data/src/plot_data/fixer/pre_worldsendrate.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
use crate::plot_data::{ChunkData, PlotData, Tps, WorldSendRate};
use mchprs_world::TickEntry;
use serde::Deserialize;

#[derive(Deserialize)]
pub struct PreSendratePlotData<const NUM_CHUNK_SECTIONS: usize> {
pub tps: Tps,
pub chunk_data: Vec<ChunkData<NUM_CHUNK_SECTIONS>>,
pub pending_ticks: Vec<TickEntry>,
}

pub fn try_fix<const NUM_SECTIONS: usize>(data: &[u8]) -> Option<PlotData<NUM_SECTIONS>> {
// Skip magic and version header
let data = &data[12..data.len()];
let old_data: PreSendratePlotData<NUM_SECTIONS> = bincode::deserialize(data).ok()?;

let data = PlotData {
tps: old_data.tps,
world_send_rate: WorldSendRate::default(),
chunk_data: old_data.chunk_data,
pending_ticks: old_data.pending_ticks,
};
Some(data)
}

0 comments on commit ac316a4

Please sign in to comment.