mirror of
https://github.com/griffi-gh/kubi.git
synced 2024-11-25 08:18:43 -06:00
Implement saving on the server-side
This commit is contained in:
parent
63e26e3a5b
commit
1b89756648
|
@ -50,7 +50,7 @@ pub fn sync_client_positions(
|
||||||
};
|
};
|
||||||
|
|
||||||
//log movement (annoying duh)
|
//log movement (annoying duh)
|
||||||
log::debug!("dbg: player moved id: {} coords: {} quat: {}", message.client_id, position, direction);
|
// log::debug!("dbg: player moved id: {} coords: {} quat: {}", message.client_id, position, direction);
|
||||||
|
|
||||||
//Apply position to server-side client
|
//Apply position to server-side client
|
||||||
let mut trans = (&mut transforms).get(message.entity_id).unwrap();
|
let mut trans = (&mut transforms).get(message.entity_id).unwrap();
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use shipyard::{IntoWorkload, Workload, WorkloadModificator, World};
|
use shipyard::{IntoWorkload, SystemModificator, Workload, WorkloadModificator, World};
|
||||||
use std::{thread, time::Duration};
|
use std::{thread, time::Duration};
|
||||||
use kubi_shared::fixed_timestamp::init_fixed_timestamp_storage;
|
use kubi_shared::fixed_timestamp::{FixedTimestamp, init_fixed_timestamp_storage};
|
||||||
|
|
||||||
mod util;
|
mod util;
|
||||||
mod config;
|
mod config;
|
||||||
|
@ -13,7 +13,7 @@ use config::read_config;
|
||||||
use server::{bind_server, update_server, log_server_errors};
|
use server::{bind_server, update_server, log_server_errors};
|
||||||
use client::{init_client_maps, on_client_disconnect, sync_client_positions};
|
use client::{init_client_maps, on_client_disconnect, sync_client_positions};
|
||||||
use auth::authenticate_players;
|
use auth::authenticate_players;
|
||||||
use world::{update_world, init_world};
|
use world::{init_world, save::save_modified, update_world};
|
||||||
|
|
||||||
fn initialize() -> Workload {
|
fn initialize() -> Workload {
|
||||||
(
|
(
|
||||||
|
@ -34,7 +34,10 @@ fn update() -> Workload {
|
||||||
update_world,
|
update_world,
|
||||||
sync_client_positions,
|
sync_client_positions,
|
||||||
on_client_disconnect,
|
on_client_disconnect,
|
||||||
).into_workload()
|
).into_workload(),
|
||||||
|
save_modified
|
||||||
|
.into_workload()
|
||||||
|
.make_fixed(10000, 0),
|
||||||
).into_sequential_workload()
|
).into_sequential_workload()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -250,7 +250,11 @@ fn process_block_queue(
|
||||||
let Some(blocks) = &mut chunk.blocks else {
|
let Some(blocks) = &mut chunk.blocks else {
|
||||||
return true
|
return true
|
||||||
};
|
};
|
||||||
blocks[block_position.x as usize][block_position.y as usize][block_position.z as usize] = item.block_type;
|
let block = &mut blocks[block_position.x as usize][block_position.y as usize][block_position.z as usize];
|
||||||
|
if item.block_type != *block {
|
||||||
|
*block = item.block_type;
|
||||||
|
chunk.data_modified = true;
|
||||||
|
}
|
||||||
false
|
false
|
||||||
});
|
});
|
||||||
if initial_len != queue.queue.len() {
|
if initial_len != queue.queue.len() {
|
||||||
|
|
|
@ -16,13 +16,16 @@ pub struct Chunk {
|
||||||
pub state: ChunkState,
|
pub state: ChunkState,
|
||||||
pub blocks: Option<BlockData>,
|
pub blocks: Option<BlockData>,
|
||||||
pub subscriptions: HashSet<ClientId, BuildNoHashHasher<ClientId>>,
|
pub subscriptions: HashSet<ClientId, BuildNoHashHasher<ClientId>>,
|
||||||
|
pub data_modified: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Chunk {
|
impl Chunk {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
state: ChunkState::Nothing,
|
state: ChunkState::Nothing,
|
||||||
blocks: None,
|
blocks: None,
|
||||||
subscriptions: HashSet::with_capacity_and_hasher(4, BuildNoHashHasher::default()),
|
subscriptions: HashSet::with_capacity_and_hasher(4, BuildNoHashHasher::default()),
|
||||||
|
data_modified: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
use kubi_shared::data::{io_thread::IOThreadManager, open_local_save_file};
|
use kubi_shared::data::{io_thread::IOThreadManager, open_local_save_file};
|
||||||
use shipyard::{AllStoragesView, UniqueView};
|
use shipyard::{AllStoragesView, UniqueView, UniqueViewMut};
|
||||||
|
|
||||||
use crate::config::ConfigTable;
|
use crate::config::ConfigTable;
|
||||||
|
use super::{
|
||||||
|
tasks::{ChunkTask, ChunkTaskManager},
|
||||||
|
ChunkManager,
|
||||||
|
};
|
||||||
|
|
||||||
pub fn init_save_file(storages: &AllStoragesView) -> Option<IOThreadManager> {
|
pub fn init_save_file(storages: &AllStoragesView) -> Option<IOThreadManager> {
|
||||||
let config = storages.borrow::<UniqueView<ConfigTable>>().unwrap();
|
let config = storages.borrow::<UniqueView<ConfigTable>>().unwrap();
|
||||||
|
@ -14,3 +17,27 @@ pub fn init_save_file(storages: &AllStoragesView) -> Option<IOThreadManager> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn save_modified(
|
||||||
|
mut chunks: UniqueViewMut<ChunkManager>,
|
||||||
|
ctm: UniqueView<ChunkTaskManager>,
|
||||||
|
) {
|
||||||
|
log::info!("Saving...");
|
||||||
|
let mut amount_saved = 0;
|
||||||
|
for (position, chunk) in chunks.chunks.iter_mut() {
|
||||||
|
if chunk.data_modified {
|
||||||
|
let Some(data) = chunk.blocks.clone() else {
|
||||||
|
continue
|
||||||
|
};
|
||||||
|
ctm.run(ChunkTask::SaveChunk {
|
||||||
|
position: *position,
|
||||||
|
data: data,
|
||||||
|
});
|
||||||
|
chunk.data_modified = false;
|
||||||
|
amount_saved += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if amount_saved > 0 {
|
||||||
|
log::info!("Queued {} chunks for saving", amount_saved);
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,7 +12,11 @@ pub enum ChunkTask {
|
||||||
LoadChunk {
|
LoadChunk {
|
||||||
position: IVec3,
|
position: IVec3,
|
||||||
seed: u64,
|
seed: u64,
|
||||||
}
|
},
|
||||||
|
SaveChunk {
|
||||||
|
position: IVec3,
|
||||||
|
data: BlockData,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum ChunkTaskResponse {
|
pub enum ChunkTaskResponse {
|
||||||
|
@ -40,12 +44,14 @@ impl ChunkTaskManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run(&self, task: ChunkTask) {
|
pub fn run(&self, task: ChunkTask) {
|
||||||
|
match task {
|
||||||
|
ChunkTask::LoadChunk { position: chunk_position, seed } => {
|
||||||
// 1. Check if the chunk exists in the save file
|
// 1. Check if the chunk exists in the save file
|
||||||
#[allow(irrefutable_let_patterns)]
|
|
||||||
if let ChunkTask::LoadChunk { position, .. } = &task {
|
if let ChunkTask::LoadChunk { position, .. } = &task {
|
||||||
if let Some(iota) = &self.iota {
|
if let Some(iota) = &self.iota {
|
||||||
if iota.chunk_exists(*position) {
|
if iota.chunk_exists(*position) {
|
||||||
iota.send(IOCommand::LoadChunk { position: *position });
|
iota.send(IOCommand::LoadChunk { position: *position });
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -53,14 +59,20 @@ impl ChunkTaskManager {
|
||||||
// 2. Generate the chunk if it doesn't exist
|
// 2. Generate the chunk if it doesn't exist
|
||||||
let sender = self.channel.0.clone();
|
let sender = self.channel.0.clone();
|
||||||
self.pool.spawn(move || {
|
self.pool.spawn(move || {
|
||||||
sender.send(match task {
|
sender.send({
|
||||||
ChunkTask::LoadChunk { position: chunk_position, seed } => {
|
|
||||||
//unwrap is fine because abort is not possible
|
//unwrap is fine because abort is not possible
|
||||||
let (blocks, queue) = generate_world(chunk_position, seed, None).unwrap();
|
let (blocks, queue) = generate_world(chunk_position, seed, None).unwrap();
|
||||||
ChunkTaskResponse::ChunkLoaded { chunk_position, blocks, queue }
|
ChunkTaskResponse::ChunkLoaded { chunk_position, blocks, queue }
|
||||||
}
|
|
||||||
}).unwrap()
|
}).unwrap()
|
||||||
})
|
});
|
||||||
|
},
|
||||||
|
ChunkTask::SaveChunk { position, data } => {
|
||||||
|
// Save the chunk to the save file
|
||||||
|
if let Some(iota) = &self.iota {
|
||||||
|
iota.send(IOCommand::SaveChunk { position, data });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn receive(&self) -> Option<ChunkTaskResponse> {
|
pub fn receive(&self) -> Option<ChunkTaskResponse> {
|
||||||
|
|
|
@ -22,6 +22,9 @@ pub fn apply_queued_blocks(
|
||||||
if event.soft && *block != Block::Air {
|
if event.soft && *block != Block::Air {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if event.block_type == *block {
|
||||||
|
return false
|
||||||
|
}
|
||||||
*block = event.block_type;
|
*block = event.block_type;
|
||||||
//mark chunk as dirty
|
//mark chunk as dirty
|
||||||
let (chunk_pos, block_pos) = ChunkStorage::to_chunk_coords(event.position);
|
let (chunk_pos, block_pos) = ChunkStorage::to_chunk_coords(event.position);
|
||||||
|
|
Loading…
Reference in a new issue