Skip to content

Commit df3a3a4

Browse files
authored
Use player.dat (#458)
* Use player.dat * Simplify PlayerData handling * Fix fmt after a few manual merges on github * fixed a typo * Fix format * Fix fix
1 parent 21e1485 commit df3a3a4

File tree

16 files changed

+577
-69
lines changed

16 files changed

+577
-69
lines changed

Cargo.lock

Lines changed: 34 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

feather/base/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ nom_locate = "2"
2424
num-derive = "0.3"
2525
num-traits = "0.2"
2626
parking_lot = "0.11"
27+
quill-common = { path = "../../quill/common" }
2728
serde = { version = "1", features = [ "derive" ] }
2829
serde_json = "1"
2930
serde_with = "1"

feather/base/src/anvil/player.dat

-19 Bytes
Binary file not shown.

feather/base/src/anvil/player.rs

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,58 @@
1-
use generated::{Item, ItemStack};
2-
use nbt::Value;
3-
use serde::{Deserialize, Serialize};
41
use std::{
52
collections::HashMap,
63
fs,
74
fs::File,
85
path::{Path, PathBuf},
96
};
7+
8+
use nbt::Value;
9+
use serde::{Deserialize, Serialize};
1010
use uuid::Uuid;
1111

12+
use generated::{Item, ItemStack};
13+
use quill_common::components::{
14+
CanBuild, CanCreativeFly, CreativeFlying, CreativeFlyingSpeed, Instabreak, Invulnerable,
15+
WalkSpeed,
16+
};
17+
1218
use crate::inventory::*;
1319

1420
use super::entity::{AnimalData, ItemNbt};
1521

1622
/// Represents the contents of a player data file.
17-
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
23+
#[derive(Debug, Clone, Serialize, Deserialize)]
1824
pub struct PlayerData {
1925
// Inherit base entity data
2026
#[serde(flatten)]
2127
pub animal: AnimalData,
2228

2329
#[serde(rename = "playerGameType")]
2430
pub gamemode: i32,
31+
#[serde(rename = "previousPlayerGameType")]
32+
pub previous_gamemode: i32,
2533
#[serde(rename = "Inventory")]
2634
pub inventory: Vec<InventorySlot>,
2735
#[serde(rename = "SelectedItemSlot")]
2836
pub held_item: i32,
37+
pub abilities: PlayerAbilities,
38+
}
39+
40+
/// Represents player's abilities (flying, invulnerability, speed, etc.)
41+
#[derive(Debug, Clone, Serialize, Deserialize)]
42+
pub struct PlayerAbilities {
43+
#[serde(rename = "walkSpeed")]
44+
pub walk_speed: WalkSpeed,
45+
#[serde(rename = "flySpeed")]
46+
pub fly_speed: CreativeFlyingSpeed,
47+
#[serde(rename = "mayfly")]
48+
pub may_fly: CanCreativeFly,
49+
#[serde(rename = "flying")]
50+
pub is_flying: CreativeFlying,
51+
#[serde(rename = "mayBuild")]
52+
pub may_build: CanBuild,
53+
#[serde(rename = "instabuild")]
54+
pub instabreak: Instabreak,
55+
pub invulnerable: Invulnerable,
2956
}
3057

3158
/// Represents a single inventory slot (including position index).
@@ -159,21 +186,28 @@ fn file_path(world_dir: &Path, uuid: Uuid) -> PathBuf {
159186

160187
#[cfg(test)]
161188
mod tests {
162-
use super::*;
189+
use std::collections::HashMap;
190+
use std::io::Cursor;
191+
192+
use num_traits::ToPrimitive;
193+
163194
use crate::{
164195
inventory::{SLOT_ARMOR_CHEST, SLOT_ARMOR_FEET, SLOT_ARMOR_HEAD, SLOT_ARMOR_LEGS},
165196
Gamemode,
166197
};
167-
use num_traits::ToPrimitive;
168-
use std::collections::HashMap;
169-
use std::io::Cursor;
198+
199+
use super::*;
170200

171201
#[test]
172202
fn test_deserialize_player() {
173203
let mut cursor = Cursor::new(include_bytes!("player.dat").to_vec());
174204

175205
let player: PlayerData = nbt::from_gzip_reader(&mut cursor).unwrap();
176206
assert_eq!(player.gamemode, Gamemode::Creative.to_i32().unwrap());
207+
assert_eq!(
208+
player.previous_gamemode,
209+
Gamemode::Spectator.to_i32().unwrap()
210+
);
177211
assert_eq!(player.inventory[0].item, "minecraft:diamond_shovel");
178212
assert_eq!(player.inventory[0].nbt, Some(ItemNbt { damage: Some(3) }));
179213
}

feather/common/src/entities/player.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,6 @@ impl HotbarSlot {
2525
Self(id)
2626
}
2727

28-
pub fn default() -> Self {
29-
Self(0)
30-
}
31-
3228
pub fn get(&self) -> usize {
3329
self.0
3430
}
@@ -42,3 +38,9 @@ impl HotbarSlot {
4238
Ok(())
4339
}
4440
}
41+
42+
impl Default for HotbarSlot {
43+
fn default() -> Self {
44+
HotbarSlot(0)
45+
}
46+
}

feather/common/src/world.rs

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
1+
use std::{path::PathBuf, sync::Arc};
2+
13
use ahash::{AHashMap, AHashSet};
4+
use parking_lot::{RwLockReadGuard, RwLockWriteGuard};
5+
use uuid::Uuid;
6+
7+
use base::anvil::player::PlayerData;
28
use base::{BlockPosition, Chunk, ChunkHandle, ChunkLock, ChunkPosition, CHUNK_HEIGHT};
39
use blocks::BlockId;
410
use ecs::{Ecs, SysResult};
5-
use parking_lot::{RwLockReadGuard, RwLockWriteGuard};
6-
use std::{path::PathBuf, sync::Arc};
711
use worldgen::{ComposableGenerator, WorldGenerator};
812

913
use crate::{
@@ -24,6 +28,7 @@ pub struct World {
2428
chunk_worker: ChunkWorker,
2529
loading_chunks: AHashSet<ChunkPosition>,
2630
canceled_chunk_loads: AHashSet<ChunkPosition>,
31+
world_dir: PathBuf,
2732
}
2833

2934
impl Default for World {
@@ -37,6 +42,7 @@ impl Default for World {
3742
cache: ChunkCache::new(),
3843
loading_chunks: AHashSet::new(),
3944
canceled_chunk_loads: AHashSet::new(),
45+
world_dir: "world".into(),
4046
}
4147
}
4248
}
@@ -48,9 +54,10 @@ impl World {
4854

4955
pub fn with_gen_and_path(
5056
generator: Arc<dyn WorldGenerator>,
51-
world_dir: impl Into<PathBuf>,
57+
world_dir: impl Into<PathBuf> + Clone,
5258
) -> Self {
5359
Self {
60+
world_dir: world_dir.clone().into(),
5461
chunk_worker: ChunkWorker::new(world_dir, generator),
5562
..Default::default()
5663
}
@@ -149,6 +156,17 @@ impl World {
149156
pub fn chunk_map_mut(&mut self) -> &mut ChunkMap {
150157
&mut self.chunk_map
151158
}
159+
160+
pub fn load_player_data(&self, uuid: Uuid) -> anyhow::Result<PlayerData> {
161+
Ok(base::anvil::player::load_player_data(
162+
&self.world_dir,
163+
uuid,
164+
)?)
165+
}
166+
167+
pub fn save_player_data(&self, uuid: Uuid, data: &PlayerData) -> anyhow::Result<()> {
168+
base::anvil::player::save_player_data(&self.world_dir, uuid, data)
169+
}
152170
}
153171

154172
pub type ChunkMapInner = AHashMap<ChunkPosition, ChunkHandle>;

feather/protocol/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ generated = { path = "../generated", package = "feather-generated" }
1818
hematite-nbt = { git = "https://github.com/PistonDevelopers/hematite_nbt" }
1919
num-traits = "0.2"
2020
parking_lot = "0.11" # Arc<RwLock<Chunk>> compat
21+
quill-common = { path = "../../quill/common" }
2122
serde = "1"
2223
thiserror = "1"
2324
uuid = "0.8"

feather/protocol/src/io.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use base::{
88
};
99
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
1010
use num_traits::{FromPrimitive, ToPrimitive};
11+
use quill_common::components::PreviousGamemode;
1112
use serde::{de::DeserializeOwned, Serialize};
1213
use std::{
1314
borrow::Cow,
@@ -887,3 +888,18 @@ impl Writeable for Gamemode {
887888
Ok(())
888889
}
889890
}
891+
892+
impl Readable for PreviousGamemode {
893+
fn read(buffer: &mut Cursor<&[u8]>, version: ProtocolVersion) -> anyhow::Result<Self>
894+
where
895+
Self: Sized,
896+
{
897+
Ok(Self::from_id(i8::read(buffer, version)?))
898+
}
899+
}
900+
901+
impl Writeable for PreviousGamemode {
902+
fn write(&self, buffer: &mut Vec<u8>, version: ProtocolVersion) -> anyhow::Result<()> {
903+
self.id().write(buffer, version)
904+
}
905+
}

feather/protocol/src/packets/server/play.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
11
use anyhow::bail;
2+
23
use base::{BlockState, EntityMetadata, Gamemode, ParticleKind, ProfileProperty};
4+
pub use chunk_data::{ChunkData, ChunkDataKind};
5+
use quill_common::components::PreviousGamemode;
6+
pub use update_light::UpdateLight;
37

4-
use super::*;
58
use crate::{io::VarLong, Readable, Writeable};
69

7-
mod chunk_data;
8-
pub use chunk_data::{ChunkData, ChunkDataKind};
10+
use super::*;
911

12+
mod chunk_data;
1013
mod update_light;
11-
pub use update_light::UpdateLight;
12-
1314
packets! {
1415
SpawnEntity {
1516
entity_id VarInt;
@@ -374,7 +375,7 @@ packets! {
374375
entity_id i32;
375376
is_hardcore bool;
376377
gamemode Gamemode;
377-
previous_gamemode u8; // can be 255 if "not set," otherwise corresponds to a gamemode ID
378+
previous_gamemode PreviousGamemode; // can be -1 if "not set", otherwise corresponds to a gamemode ID
378379
world_names VarIntPrefixedVec<String>;
379380

380381
dimension_codec Nbt<Blob>;

feather/server/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ hematite-nbt = { git = "https://github.com/PistonDevelopers/hematite_nbt" }
3030
log = "0.4"
3131
md-5 = "0.9"
3232
num-bigint = "0.4"
33+
num-traits = "0.2"
3334
once_cell = "1"
3435
parking_lot = "0.11"
3536
plugin-host = { path = "../plugin-host", package = "feather-plugin-host" }

0 commit comments

Comments
 (0)