Skip to content

Commit a289a73

Browse files
committed
Fix player data loading
1 parent f5f395a commit a289a73

File tree

14 files changed

+223
-42
lines changed

14 files changed

+223
-42
lines changed

Cargo.lock

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

core/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ pub use save::{entity, level, player_data, region};
4343
pub use world::{BlockPosition, ChunkPosition, Position};
4444

4545
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, Hash)]
46+
#[serde(rename_all = "lowercase")]
4647
pub enum Gamemode {
4748
Survival,
4849
Creative,

core/src/save/player_data.rs

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,13 @@
1-
use std::fs::File;
2-
31
use crate::entity::BaseEntityData;
42
use crate::inventory::{
53
SlotIndex, HOTBAR_SIZE, INVENTORY_SIZE, SLOT_ARMOR_MAX, SLOT_ARMOR_MIN, SLOT_HOTBAR_OFFSET,
64
SLOT_INVENTORY_OFFSET, SLOT_OFFHAND,
75
};
86
use crate::ItemStack;
97
use feather_items::Item;
10-
use std::fs;
11-
use std::io::Write;
128
use std::path::{Path, PathBuf};
13-
use tokio::prelude::AsyncRead;
9+
use tokio::io::AsyncWriteExt;
10+
use tokio::prelude::{AsyncRead, AsyncWrite};
1411
use uuid::Uuid;
1512

1613
/// Represents the contents of a player data file.
@@ -106,15 +103,25 @@ pub async fn load_player_data(world_dir: &Path, uuid: Uuid) -> Result<PlayerData
106103
Ok(data)
107104
}
108105

109-
fn save_to_file<W: Write>(mut writer: W, data: PlayerData) -> Result<(), nbt::Error> {
110-
nbt::to_gzip_writer(&mut writer, &data, None)
106+
async fn save_to_file<W: AsyncWrite + Unpin>(
107+
mut writer: W,
108+
data: &PlayerData,
109+
) -> Result<(), anyhow::Error> {
110+
let mut buf = vec![];
111+
nbt::to_gzip_writer(&mut buf, data, None)?;
112+
writer.write_all(&buf).await?;
113+
Ok(())
111114
}
112115

113-
pub fn save_player_data(world_dir: &Path, uuid: Uuid, data: PlayerData) -> Result<(), nbt::Error> {
114-
fs::create_dir_all(world_dir.join("playerdata"))?;
116+
pub async fn save_player_data(
117+
world_dir: &Path,
118+
uuid: Uuid,
119+
data: &PlayerData,
120+
) -> Result<(), anyhow::Error> {
121+
tokio::fs::create_dir_all(world_dir.join("playerdata")).await?;
115122
let file_path = file_path(world_dir, uuid);
116-
let file = File::create(file_path)?;
117-
save_to_file(file, data)
123+
let file = tokio::fs::File::create(file_path).await?;
124+
save_to_file(file, data).await
118125
}
119126

120127
fn file_path(world_dir: &Path, uuid: Uuid) -> PathBuf {

data/build.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,24 @@ use std::process::Command;
99

1010
fn main() -> Result<(), Box<dyn Error>> {
1111
let path = Path::new(concat!(env!("CARGO_MANIFEST_DIR"), "/minecraft"));
12+
dbg!(path);
1213
let path_server = path.join("server.jar");
14+
println!("cargo:rerun-if-changed={}", &path.display());
1315

1416
let _ = fs::remove_dir_all(&path);
1517
fs::create_dir_all(&path)?;
1618

1719
donwload(&path_server)?;
1820
generate(&path)?;
1921
extract(&path)?;
20-
21-
println!("cargo:rerun-if-changed={}", &path.display());
2222
Ok(())
2323
}
2424

2525
fn donwload<P: AsRef<Path>>(server: P) -> Result<(), Box<dyn Error>> {
26+
if File::open(&server).is_ok() {
27+
return Ok(());
28+
}
29+
2630
let mut response = reqwest::blocking::get("https://launcher.mojang.com/v1/objects/3737db93722a9e39eeada7c27e7aca28b144ffa7/server.jar")?;
2731
let mut dest = File::create(server)?;
2832
copy(&mut response, &mut dest)?;

server/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ multimap = "0.8"
6262
smallvec = "1.2"
6363
arrayvec = "0.5"
6464
indexmap = "1.3"
65-
dashmap = "3.7"
65+
dashmap = "3.10"
6666

6767
# Logging
6868
log = "0.4"

server/src/config.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use feather_core::Gamemode;
12
use std::fs::read_to_string;
23
use std::time::Duration;
34
use thiserror::Error;
@@ -47,7 +48,7 @@ pub struct Server {
4748
pub view_distance: u8,
4849
pub address: String,
4950
pub port: u16,
50-
pub default_gamemode: String,
51+
pub default_gamemode: Gamemode,
5152
}
5253

5354
#[derive(Serialize, Deserialize, Debug, Clone)]

server/src/game.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,11 @@ use crate::p_inventory::InventoryUpdateEvent;
3232
use crate::physics::EntityPhysicsLandEvent;
3333
use crate::player;
3434
use crate::player::Player;
35-
use crate::save::{on_chunk_load_queue_for_saving, on_chunk_unload_save_chunk, SaveQueue};
35+
use crate::save::{
36+
on_chunk_load_queue_for_saving, on_chunk_unload_save_chunk, on_player_leave_save_data,
37+
SaveQueue,
38+
};
39+
use crate::task::RunningTasks;
3640
use crate::time::{on_player_join_send_time, Time};
3741
use crate::view::{
3842
on_chunk_cross_update_chunks, on_chunk_cross_update_entities, on_chunk_load_send_to_clients,
@@ -92,6 +96,7 @@ pub struct Game {
9296
pub time: Time,
9397
pub save_queue: SaveQueue,
9498
pub lighting_worker_handle: LightingWorkerHandle,
99+
pub running_tasks: RunningTasks,
95100
}
96101

97102
impl Game {
@@ -127,9 +132,7 @@ impl Game {
127132

128133
/// Spawns a player with the given `PlayerInfo`.
129134
pub fn spawn_player(&mut self, info: NewClientInfo, world: &mut World) {
130-
let entity = player::create(world, info);
131-
self.on_entity_spawn(world, entity);
132-
self.on_player_join(world, entity);
135+
player::create(self, world, info);
133136
}
134137

135138
/// Returns a bump allocator.
@@ -301,8 +304,9 @@ impl Game {
301304
///
302305
/// As with `on_entity_despawn`, this function is called __before__
303306
/// `player` is removed from the world.
304-
pub fn on_player_leave(&mut self, _world: &mut World, _player: Entity) {
307+
pub fn on_player_leave(&mut self, world: &mut World, player: Entity) {
305308
self.player_count.fetch_sub(1, Ordering::Relaxed);
309+
on_player_leave_save_data(self, world, player);
306310
}
307311

308312
/// Called when a chunk loads successfully.

server/src/io/worker.rs

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,11 @@ use crate::io::{
1313
WorkerToServerMessage,
1414
};
1515
use crate::packet_buffer::PacketBuffers;
16+
use feather_core::entity::BaseEntityData;
1617
use feather_core::network::codec::MinecraftCodec;
1718
use feather_core::network::packet::PacketDirection;
1819
use feather_core::player_data::PlayerData;
19-
use feather_core::Packet;
20+
use feather_core::{Packet, Position, Vec3d};
2021
use fecs::Entity;
2122
use futures::channel::mpsc;
2223
use futures::future::Either;
@@ -33,6 +34,7 @@ use uuid::Uuid;
3334

3435
struct Worker {
3536
framed: Framed<TcpStream, MinecraftCodec>,
37+
config: Arc<Config>,
3638
ip: SocketAddr,
3739
/// The listener's sender to send the initial `NewClient` message
3840
/// to the server. Also used to request an entity for the player.
@@ -93,6 +95,7 @@ pub async fn run_worker(
9395
tx,
9496
initial_handler,
9597
entity,
98+
config,
9699
};
97100

98101
let msg = match run_worker_impl(&mut worker).await {
@@ -188,13 +191,15 @@ async fn handle_ih_actions(worker: &mut Worker) -> anyhow::Result<()> {
188191
Action::Disconnect => anyhow::bail!("initial handler requested disconnect"),
189192
Action::SetStage(stage) => worker.framed.codec_mut().set_stage(stage),
190193
Action::JoinGame(info) => {
194+
let data = load_player_data(&worker.config, info.uuid).await?;
195+
let position = data.entity.read_position()?;
191196
let info = NewClientInfo {
192197
ip: worker.ip,
193198
username: info.username.unwrap_or_else(|| String::from("undefined")),
194199
profile: info.props,
195200
uuid: info.uuid,
196-
data: Default::default(), // TODO
197-
position: position!(0.0, 70.0, 0.0), // TODO
201+
data,
202+
position,
198203
sender: worker.server_tx.clone(),
199204
receiver: worker.server_rx.clone(),
200205
entity: worker.entity,
@@ -213,7 +218,29 @@ async fn handle_ih_actions(worker: &mut Worker) -> anyhow::Result<()> {
213218
Ok(())
214219
}
215220

216-
#[allow(dead_code)] // TODO
217-
async fn load_player_data(config: &Config, uuid: Uuid) -> Result<PlayerData, nbt::Error> {
218-
feather_core::player_data::load_player_data(Path::new(&config.world.name), uuid).await
221+
const DEFAULT_POSITION: Position = position!(0.0, 70.0, 0.0); // TODO: better calculation
222+
223+
async fn load_player_data(config: &Config, uuid: Uuid) -> Result<PlayerData, anyhow::Error> {
224+
log::debug!("Loading player data for UUID {}", uuid);
225+
match feather_core::player_data::load_player_data(Path::new(&config.world.name), uuid).await {
226+
Ok(data) => Ok(data),
227+
Err(e) => {
228+
log::debug!(
229+
"Failed to load player data for {} ({}); creating default data",
230+
uuid,
231+
e,
232+
);
233+
234+
let data = PlayerData {
235+
entity: BaseEntityData::new(DEFAULT_POSITION, Vec3d::broadcast(0.0)),
236+
gamemode: config.server.default_gamemode.id() as i32,
237+
inventory: vec![],
238+
};
239+
240+
feather_core::player_data::save_player_data(Path::new(&config.world.name), uuid, &data)
241+
.await?;
242+
243+
Ok(data)
244+
}
245+
}
219246
}

server/src/lib.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@ pub mod player;
160160
mod save;
161161
pub mod shutdown;
162162
mod systems;
163+
mod task;
163164
mod time;
164165
pub mod util;
165166
mod view;
@@ -173,7 +174,7 @@ pub const PROTOCOL_VERSION: u32 = 404;
173174
pub const SERVER_VERSION: &str = "Feather 1.13.2";
174175
pub const TICK_TIME: u64 = 1000 / TPS;
175176

176-
pub fn main() {
177+
pub async fn main() {
177178
let config = Arc::new(load_config());
178179
init_log(&config);
179180

@@ -237,6 +238,7 @@ pub fn main() {
237238
time,
238239
save_queue: Default::default(),
239240
lighting_worker_handle: lighting::start_worker(),
241+
running_tasks: Default::default(),
240242
};
241243

242244
let (executor, resources) = init_executor(game, packet_buffers);
@@ -269,7 +271,9 @@ pub fn main() {
269271
info!("Saving level.dat");
270272
shutdown::save_level(&mut *resources.get_mut::<Game>());
271273
info!("Saving player data");
272-
shutdown::save_player_data(&world);
274+
shutdown::save_player_data(&*resources.get::<Game>(), &world);
275+
info!("Waiting for tasks to finish");
276+
shutdown::wait_for_task_completion(&*resources.get::<Game>()).await;
273277

274278
info!("Goodbye");
275279
exit(0);

server/src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
#[tokio::main]
22
async fn main() {
3-
feather_server::main();
3+
feather_server::main().await;
44
}

0 commit comments

Comments
 (0)