mirror of https://github.com/zyllian/classics.git synced 2025-05-10 19:46:38 -07:00

save player location on save/leave

This commit is contained in:
zyl 2024-09-09 16:30:31 -07:00
parent 6b72840495
commit b146afa72e
Signed by: zyl
SSH key fingerprint: SHA256:uxxbSXbdroP/OnKBGnEDk5q7EKB2razvstC/KmzdXXs
6 changed files with 94 additions and 45 deletions

1
Cargo.lock generated
View file

@ -181,6 +181,7 @@ checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"crunchy", "crunchy",
"serde",
] ]
[[package]] [[package]]

View file

@ -8,7 +8,7 @@ bincode = "2.0.0-rc.3"
bitmask-enum = "2" bitmask-enum = "2"
bytes = "1" bytes = "1"
flate2 = "1" flate2 = "1"
half = "2" half = {version = "2", features = ["serde"]}
internment = {version = "0.8", features = ["serde"]} internment = {version = "0.8", features = ["serde"]}
nanoid = "0.4" nanoid = "0.4"
optional_struct = "0.4" optional_struct = "0.4"
@ -17,6 +17,6 @@ rand = "0.8"
safer-bytes = "0.2" safer-bytes = "0.2"
serde = {version = "1", features = ["derive"]} serde = {version = "1", features = ["derive"]}
serde_json = "1" serde_json = "1"
strum = { version = "0.26", features = ["derive"] } strum = {version = "0.26", features = ["derive"]}
thiserror = "1" thiserror = "1"
tokio = {version = "1", features = ["full"]} tokio = {version = "1", features = ["full"]}

View file

@ -1,12 +1,14 @@
use std::{ use std::{
collections::BTreeSet, collections::{BTreeMap, BTreeSet},
io::{Read, Write}, io::{Read, Write},
path::Path, path::Path,
}; };
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::{error::GeneralError, packet::server::ServerPacket, util::neighbors}; use crate::{
error::GeneralError, packet::server::ServerPacket, player::SavablePlayerData, util::neighbors,
};
use self::block::BLOCK_INFO; use self::block::BLOCK_INFO;
@ -39,6 +41,9 @@ pub struct Level {
pub updates: Vec<BlockUpdate>, pub updates: Vec<BlockUpdate>,
#[serde(skip)] #[serde(skip)]
pub save_now: bool, pub save_now: bool,
#[serde(default)]
pub player_data: BTreeMap<String, SavablePlayerData>,
} }
impl Level { impl Level {
@ -53,6 +58,7 @@ impl Level {
awaiting_update: Default::default(), awaiting_update: Default::default(),
updates: Default::default(), updates: Default::default(),
save_now: false, save_now: false,
player_data: Default::default(),
} }
} }
@ -107,6 +113,13 @@ impl Level {
packets packets
} }
/// updates player data for the level
pub fn update_player_data(&mut self, player_data: Vec<(String, SavablePlayerData)>) {
for (username, data) in player_data {
self.player_data.insert(username, data);
}
}
/// saves the level /// saves the level
pub async fn save<P>(&self, path: P) -> Result<(), GeneralError> pub async fn save<P>(&self, path: P) -> Result<(), GeneralError>
where where

View file

@ -1,4 +1,7 @@
use std::net::SocketAddr; use std::{
net::SocketAddr,
ops::{Deref, DerefMut},
};
use half::f16; use half::f16;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -12,16 +15,8 @@ pub struct Player {
pub id: i8, pub id: i8,
/// the player's username /// the player's username
pub username: String, pub username: String,
/// the player's X coordinate /// the player's savable data
pub x: f16, pub savable_data: SavablePlayerData,
/// the player's Y coordinate
pub y: f16,
/// the player's Z coordinate
pub z: f16,
/// the player's yaw
pub yaw: u8,
/// the player's pitch
pub pitch: u8,
/// the player's permission state /// the player's permission state
pub permissions: PlayerType, pub permissions: PlayerType,
@ -37,6 +32,35 @@ pub struct Player {
pub should_be_kicked: Option<String>, pub should_be_kicked: Option<String>,
} }
impl Deref for Player {
type Target = SavablePlayerData;
fn deref(&self) -> &Self::Target {
&self.savable_data
}
}
impl DerefMut for Player {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.savable_data
}
}
/// savable data about the player
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
pub struct SavablePlayerData {
/// the player's X coordinate
pub x: f16,
/// the player's Y coordinate
pub y: f16,
/// the player's Z coordinate
pub z: f16,
/// the player's yaw
pub yaw: u8,
/// the player's pitch
pub pitch: u8,
}
/// enum describing types of players /// enum describing types of players
#[derive( #[derive(
Debug, Debug,

View file

@ -137,7 +137,13 @@ impl Server {
// TODO: cancel pending tasks/send out "Server is stopping" messages *here* instead of elsewhere // TODO: cancel pending tasks/send out "Server is stopping" messages *here* instead of elsewhere
// rn the message isn't guaranteed to actually go out........ // rn the message isn't guaranteed to actually go out........
let data = self.data.read().await; let mut data = self.data.write().await;
let player_data = data
.players
.iter()
.map(|p| (p.username.clone(), p.savable_data.clone()))
.collect();
data.level.update_player_data(player_data);
data.level data.level
.save(PathBuf::from(LEVELS_PATH).join(&data.config.level_name)) .save(PathBuf::from(LEVELS_PATH).join(&data.config.level_name))
.await?; .await?;

View file

@ -122,6 +122,9 @@ pub(super) async fn handle_stream(
player.packets_to_send.push(despawn_packet.clone()); player.packets_to_send.push(despawn_packet.clone());
player.packets_to_send.push(message_packet.clone()); player.packets_to_send.push(message_packet.clone());
} }
data.level
.player_data
.insert(player.username, player.savable_data);
} }
} }
@ -162,8 +165,6 @@ async fn handle_stream_inner(
return Err(GeneralError::Custom("Unknown protocol version! Please connect with a classic 0.30-compatible client.".to_string())); return Err(GeneralError::Custom("Unknown protocol version! Please connect with a classic 0.30-compatible client.".to_string()));
} }
let zero = f16::from_f32(0.0);
let mut data = data.write().await; let mut data = data.write().await;
match &data.config.protection_mode { match &data.config.protection_mode {
@ -208,15 +209,15 @@ async fn handle_stream_inner(
.copied() .copied()
.unwrap_or_default(); .unwrap_or_default();
let savable_data = data.level.player_data.get(&username).cloned();
let needs_spawn_coords = savable_data.is_none();
let savable_data = savable_data.unwrap_or_default();
let mut player = Player { let mut player = Player {
_addr: addr, _addr: addr,
id: *own_id, // TODO: actually assign user ids id: *own_id, // TODO: actually assign user ids
username, username,
x: zero, savable_data,
y: zero,
z: zero,
yaw: 0,
pitch: 0,
permissions: player_type, permissions: player_type,
extensions: ExtBitmask::none(), extensions: ExtBitmask::none(),
custom_blocks_support_level: 0, custom_blocks_support_level: 0,
@ -252,6 +253,7 @@ async fn handle_stream_inner(
let username = player.username.clone(); let username = player.username.clone();
if needs_spawn_coords {
let (spawn_x, spawn_y, spawn_z, spawn_yaw, spawn_pitch) = let (spawn_x, spawn_y, spawn_z, spawn_yaw, spawn_pitch) =
if let Some(spawn) = &data.config.spawn { if let Some(spawn) = &data.config.spawn {
(spawn.x, spawn.y, spawn.z, spawn.yaw, spawn.pitch) (spawn.x, spawn.y, spawn.z, spawn.yaw, spawn.pitch)
@ -270,17 +272,20 @@ async fn handle_stream_inner(
player.z = spawn_z; player.z = spawn_z;
player.yaw = spawn_yaw; player.yaw = spawn_yaw;
player.pitch = spawn_pitch; player.pitch = spawn_pitch;
data.players.push(player); }
let spawn_packet = ServerPacket::SpawnPlayer { let spawn_packet = ServerPacket::SpawnPlayer {
player_id: *own_id, player_id: *own_id,
player_name: username.clone(), player_name: username.clone(),
x: spawn_x, x: player.x,
y: spawn_y, y: player.y,
z: spawn_z, z: player.z,
yaw: spawn_yaw, yaw: player.yaw,
pitch: spawn_pitch, pitch: player.pitch,
}; };
data.players.push(player);
let message_packet = ServerPacket::Message { let message_packet = ServerPacket::Message {
player_id: *own_id, player_id: *own_id,
message: format!("&e{} has joined the server.", username), message: format!("&e{} has joined the server.", username),