mirror of https://github.com/zyllian/classics.git synced 2025-05-10 14:47:06 -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 = [
"cfg-if",
"crunchy",
"serde",
]
[[package]]

View file

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

View file

@ -1,12 +1,14 @@
use std::{
collections::BTreeSet,
collections::{BTreeMap, BTreeSet},
io::{Read, Write},
path::Path,
};
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;
@ -39,6 +41,9 @@ pub struct Level {
pub updates: Vec<BlockUpdate>,
#[serde(skip)]
pub save_now: bool,
#[serde(default)]
pub player_data: BTreeMap<String, SavablePlayerData>,
}
impl Level {
@ -53,6 +58,7 @@ impl Level {
awaiting_update: Default::default(),
updates: Default::default(),
save_now: false,
player_data: Default::default(),
}
}
@ -107,6 +113,13 @@ impl Level {
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
pub async fn save<P>(&self, path: P) -> Result<(), GeneralError>
where

View file

@ -1,4 +1,7 @@
use std::net::SocketAddr;
use std::{
net::SocketAddr,
ops::{Deref, DerefMut},
};
use half::f16;
use serde::{Deserialize, Serialize};
@ -12,16 +15,8 @@ pub struct Player {
pub id: i8,
/// the player's username
pub username: String,
/// 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,
/// the player's savable data
pub savable_data: SavablePlayerData,
/// the player's permission state
pub permissions: PlayerType,
@ -37,6 +32,35 @@ pub struct Player {
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
#[derive(
Debug,

View file

@ -137,7 +137,13 @@ impl Server {
// TODO: cancel pending tasks/send out "Server is stopping" messages *here* instead of elsewhere
// 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
.save(PathBuf::from(LEVELS_PATH).join(&data.config.level_name))
.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(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()));
}
let zero = f16::from_f32(0.0);
let mut data = data.write().await;
match &data.config.protection_mode {
@ -208,15 +209,15 @@ async fn handle_stream_inner(
.copied()
.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 {
_addr: addr,
id: *own_id, // TODO: actually assign user ids
username,
x: zero,
y: zero,
z: zero,
yaw: 0,
pitch: 0,
savable_data,
permissions: player_type,
extensions: ExtBitmask::none(),
custom_blocks_support_level: 0,
@ -252,35 +253,39 @@ async fn handle_stream_inner(
let username = player.username.clone();
let (spawn_x, spawn_y, spawn_z, spawn_yaw, spawn_pitch) =
if let Some(spawn) = &data.config.spawn {
(spawn.x, spawn.y, spawn.z, spawn.yaw, spawn.pitch)
} else {
(16.5, (data.level.y_size / 2 + 2) as f32, 16.5, 0, 0)
};
if needs_spawn_coords {
let (spawn_x, spawn_y, spawn_z, spawn_yaw, spawn_pitch) =
if let Some(spawn) = &data.config.spawn {
(spawn.x, spawn.y, spawn.z, spawn.yaw, spawn.pitch)
} else {
(16.5, (data.level.y_size / 2 + 2) as f32, 16.5, 0, 0)
};
let (spawn_x, spawn_y, spawn_z) = (
f16::from_f32(spawn_x),
f16::from_f32(spawn_y),
f16::from_f32(spawn_z),
);
let (spawn_x, spawn_y, spawn_z) = (
f16::from_f32(spawn_x),
f16::from_f32(spawn_y),
f16::from_f32(spawn_z),
);
player.x = spawn_x;
player.y = spawn_y;
player.z = spawn_z;
player.yaw = spawn_yaw;
player.pitch = spawn_pitch;
data.players.push(player);
player.x = spawn_x;
player.y = spawn_y;
player.z = spawn_z;
player.yaw = spawn_yaw;
player.pitch = spawn_pitch;
}
let spawn_packet = ServerPacket::SpawnPlayer {
player_id: *own_id,
player_name: username.clone(),
x: spawn_x,
y: spawn_y,
z: spawn_z,
yaw: spawn_yaw,
pitch: spawn_pitch,
x: player.x,
y: player.y,
z: player.z,
yaw: player.yaw,
pitch: player.pitch,
};
data.players.push(player);
let message_packet = ServerPacket::Message {
player_id: *own_id,
message: format!("&e{} has joined the server.", username),