Skip to content

Conversation

@cb341
Copy link
Owner

@cb341 cb341 commented Jan 18, 2026

Persistent World

When starting the server, the admin may select a world file that should be loaded instead of generating a new world every time. Files are non-human readable but small-ish.

CleanShot 2026-01-18 at 02 17 53@2x

A masterpiece of a structure that shouldn't be forgotten in history

Added clap for CLI args with two commands generate-world and load-world:

$ cargo rs
Usage: server <COMMAND>

Commands:
  generate-world  Generate a new world with the given name
  load-world      Load an existing world from disk
  help            Print this message or the help of the given subcommand(s)

Options:
  -h, --help     Print help
  -V, --version  Print version

Added periodic world backups:

Backing up world..
Saved world backup to: 'backups/my_world_20260123213639250.rsmcw.bak'

Added world save files

Updated world file: 'worlds/my_world.rsmcw'

rsmcw -> rsmc world

Some cool sources:

Things I learned:

  • How to handle and propagate Result
  • How to join different kinds of Err
  • How to parse CLI arguments with clap
  • How to run systems on app exit
  • How to read and write files with std::io
  • How to concatinate paths
  • Applied Polymorphism with Enums

Made with ❤️

@cb341 cb341 self-assigned this Jan 18, 2026
"Received block update from client {} {} {:?}",
client_id, position, block
);
chunk_manager.update_block(position, block);
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💀

"Received block update from client {} {} {:?}",
client_id, position, block
);
chunk_manager.update_block(position, block);
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Didn't spot this one as the clients always receive world updates.
The world serializer doesn't take the diff into consideration but rather the physical chunks from the ChunkManager.

pub struct TerrainPlugin;
mod persistence;

pub enum TerrainStrategy {
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know if I like this name

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's okay. Or TerrainGenerationStrategy, but that's quite long.


pub enum TerrainStrategy {
SeededRandom(u32),
LoadFromSave(Box<WorldSave>),
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Borrow checker complained about WorldSave being too many bytes for an enum, fair enough..

event.chunk_position
);
let chunk_option = chunk_manager.get_chunk(event.chunk_position);
let chunk_option = chunk_manager.get_chunk(&event.chunk_position);
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unrelated refactoring.

serde-big-array = "0.5.1"
chrono = "0.4.38"
rayon = "1.10.0"
clap = { version = "4.5.54", features = ["derive"] }
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CLI arg parsing

let mut file = File::create(path)?;
let serialized = bincode::serialize(&world_save)?;
file.write_all(&serialized)?;
file.flush()?;
Copy link
Owner Author

@cb341 cb341 Jan 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

file should be auto flushed once dropped.
somehow was causing UnexpectedEOF without manual flush.

Copy link

@hunchr hunchr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error handling could be better. I'd expect the server to exit here instead of creating a new world:

$ cargo rs -- -w my_world.rsmcw
Loading world save from file 'my_world.rsmcw'
Error: Save File not found 'my_world.rsmcw'
Generating new world with seed [0]

The world persistence is a nice feature!

pub struct TerrainPlugin;
mod persistence;

pub enum TerrainStrategy {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's okay. Or TerrainGenerationStrategy, but that's quite long.

@cb341 cb341 marked this pull request as draft January 22, 2026 18:02
@cb341 cb341 marked this pull request as ready for review January 23, 2026 10:59
@cb341 cb341 marked this pull request as draft January 23, 2026 10:59
@cb341
Copy link
Owner Author

cb341 commented Jan 23, 2026

The error handling could be better. I'd expect the server to exit here instead of creating a new world:

$ cargo rs -- -w my_world.rsmcw
Loading world save from file 'my_world.rsmcw'
Error: Save File not found 'my_world.rsmcw'
Generating new world with seed [0]

The world persistence is a nice feature!

I also noticed this issue.
Fixed it.

@cb341 cb341 marked this pull request as ready for review January 23, 2026 21:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants