Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(player-data): Support saving and loading player NBT Data #600

Open
wants to merge 5 commits into
base: master
Choose a base branch
from

Conversation

HookWoods
Copy link
Contributor

Description

This PR adds the must-have feature to save and load player NBT Data !

This code actually does:

  • Add a util class to pumpkin-nbt to compress and decompress NBT to GZip which is useful in multiple places in Minecraft code.
  • Load or create player data on join
  • Cache player data to avoid having to read the player file again
  • Save player data on leave
  • Save every player's data on server shutdown
  • Save player data in a scheduler to avoid massive data loss in case of a crash
  • Add a config to control if player data saving should be enabled
  • Add some working content to player NBT

This code also contains a rework of the experience packet and health packet with tick_experience and tick_health; this is needed with how NBT data are handled before player spawning in the world. Like that, we send experience, health, ... directly on the first player tick and send them when there is an update like before.

I also added some data to NBT, like gamemode, or food, and impl them in the code to use them now instead of default data. Now the future part needed for this code is the implementation of other NBT values accessible from https://minecraft.wiki/w/Player.dat_format

Testing

I have tested to move on the map, give experience, change gamemode, ... stopping the server and joining again and all is working good. May need more test from others !

Please follow our Coding Guidelines

@Snowiiii
Copy link
Collaborator

Snowiiii commented Mar 1, 2025

Why not move the nbt data into the hunger manager

Copy link
Contributor

@kralverde kralverde left a comment

Choose a reason for hiding this comment

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

Why do we now save player data periodically? Isn't saving when players leave enough?

compound.put_int("test_value", 12345);

// Create a temporary file path
let path = Path::new("test_nbt_file.dat");
Copy link
Contributor

Choose a reason for hiding this comment

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

You should use the temp file crate for this

@@ -137,6 +141,10 @@ impl Server {
server_listing: Mutex::new(CachedStatus::new()),
server_branding: CachedBranding::new(),
bossbars: Mutex::new(CustomBossbars::new()),
player_data_storage: ServerPlayerData::new(
format!("./{world_name}/playerdata"),
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not comfortable with this being a solo relative path. I know that our world is relative to where we execute the server, but having "magic string" like this, even if is correct now can cause issues in the future if there are refactors.

Could you make a get_world_path or something on the config instance, then pass that here and to our world loading?

@DataM0del
Copy link
Contributor

Why do we now save player data periodically? Isn't saving when players leave enough?

What if the program panics / crashes, and we can't handle leaving or the server shutting down?
What if the power is unexpectedly unplugged while the server is running?
Etc.

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.

4 participants