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:
parent
6b72840495
commit
b146afa72e
6 changed files with 94 additions and 45 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -181,6 +181,7 @@ checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888"
|
|||
dependencies = [
|
||||
"cfg-if",
|
||||
"crunchy",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
|
@ -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"]}
|
||||
|
|
17
src/level.rs
17
src/level.rs
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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?;
|
||||
|
|
|
@ -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),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue