mirror of
https://github.com/griffi-gh/kubi.git
synced 2024-11-21 22:38:41 -06:00
this sucks
This commit is contained in:
parent
570382520c
commit
61b99409ce
|
@ -116,6 +116,9 @@ impl WorldSaveFile {
|
||||||
header_modified = true;
|
header_modified = true;
|
||||||
self.allocate_sector()
|
self.allocate_sector()
|
||||||
});
|
});
|
||||||
|
if header_modified {
|
||||||
|
self.header.chunk_map.insert(position, sector);
|
||||||
|
}
|
||||||
|
|
||||||
let offset = sector as u64 * SECTOR_SIZE as u64;
|
let offset = sector as u64 * SECTOR_SIZE as u64;
|
||||||
|
|
||||||
|
|
|
@ -2,9 +2,12 @@ use glam::IVec3;
|
||||||
use flume::{Receiver, Sender, TryIter};
|
use flume::{Receiver, Sender, TryIter};
|
||||||
use shipyard::Unique;
|
use shipyard::Unique;
|
||||||
use crate::chunk::BlockData;
|
use crate::chunk::BlockData;
|
||||||
|
|
||||||
use super::WorldSaveFile;
|
use super::WorldSaveFile;
|
||||||
|
|
||||||
|
// Maximum amount of chunks to save in a single batch before checking if there are any pending read requests
|
||||||
|
// may be broken, so currently disabled
|
||||||
|
const MAX_SAVE_BATCH_SIZE: usize = usize::MAX;
|
||||||
|
|
||||||
pub enum IOCommand {
|
pub enum IOCommand {
|
||||||
SaveChunk {
|
SaveChunk {
|
||||||
position: IVec3,
|
position: IVec3,
|
||||||
|
@ -39,6 +42,7 @@ struct IOThreadContext {
|
||||||
tx: Sender<IOResponse>,
|
tx: Sender<IOResponse>,
|
||||||
rx: Receiver<IOCommand>,
|
rx: Receiver<IOCommand>,
|
||||||
save: WorldSaveFile,
|
save: WorldSaveFile,
|
||||||
|
save_queue: Vec<(IVec3, BlockData)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: Implement proper error handling (I/O errors are rlly common)
|
//TODO: Implement proper error handling (I/O errors are rlly common)
|
||||||
|
@ -54,32 +58,80 @@ impl IOThreadContext {
|
||||||
save: WorldSaveFile,
|
save: WorldSaveFile,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
// save.load_data().unwrap();
|
// save.load_data().unwrap();
|
||||||
Self { tx, rx, save }
|
let save_queue = Vec::new();
|
||||||
|
Self { tx, rx, save, save_queue }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run(mut self) {
|
pub fn run(mut self) {
|
||||||
loop {
|
loop {
|
||||||
match self.rx.recv().unwrap() {
|
// because were waiting for the next command, we can't process the save_queue
|
||||||
|
// which breaks batching, so we need to check if there are any pending save requests
|
||||||
|
// and if there are, use non-blocking recv to give them a chance to be processed
|
||||||
|
'rx: while let Some(command) = {
|
||||||
|
if self.save_queue.len() > 0 {
|
||||||
|
self.rx.try_recv().ok()
|
||||||
|
} else {
|
||||||
|
self.rx.recv().ok()
|
||||||
|
}
|
||||||
|
} {
|
||||||
|
match command {
|
||||||
IOCommand::SaveChunk { position, data } => {
|
IOCommand::SaveChunk { position, data } => {
|
||||||
self.save.save_chunk(position, &data).unwrap();
|
// if chunk already has a save request, overwrite it
|
||||||
|
for (pos, old_data) in self.save_queue.iter_mut() {
|
||||||
|
if *pos == position {
|
||||||
|
*old_data = data;
|
||||||
|
continue 'rx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// if not, save to the queue
|
||||||
|
self.save_queue.push((position, data));
|
||||||
|
//log::trace!("amt of unsaved chunks: {}", self.save_queue.len());
|
||||||
}
|
}
|
||||||
IOCommand::LoadChunk { position } => {
|
IOCommand::LoadChunk { position } => {
|
||||||
|
// HOLD ON
|
||||||
|
// first check if the chunk is already in the save queue
|
||||||
|
// if it is, send it and continue
|
||||||
|
// (NOT doing this WILL result in data loss if the user returns to the chunk too quickly)
|
||||||
|
for (pos, data) in self.save_queue.iter() {
|
||||||
|
if *pos == position {
|
||||||
|
self.tx.send(IOResponse::ChunkLoaded { position, data: Some(data.clone()) }).unwrap();
|
||||||
|
continue 'rx;
|
||||||
|
}
|
||||||
|
}
|
||||||
let data = self.save.load_chunk(position).unwrap();
|
let data = self.save.load_chunk(position).unwrap();
|
||||||
self.tx.send(IOResponse::ChunkLoaded { position, data }).unwrap();
|
self.tx.send(IOResponse::ChunkLoaded { position, data }).unwrap();
|
||||||
}
|
}
|
||||||
IOCommand::Kys => {
|
IOCommand::Kys => {
|
||||||
// Process all pending write commands
|
// Process all pending write commands
|
||||||
|
log::info!("info: queue has {} chunks", self.save_queue.len());
|
||||||
|
let mut saved_amount = 0;
|
||||||
|
for (pos, data) in self.save_queue.drain(..) {
|
||||||
|
self.save.save_chunk(pos, &data).unwrap();
|
||||||
|
saved_amount += 1;
|
||||||
|
}
|
||||||
|
log::debug!("now, moving on to the rx queue...");
|
||||||
for cmd in self.rx.try_iter() {
|
for cmd in self.rx.try_iter() {
|
||||||
let IOCommand::SaveChunk { position, data } = cmd else {
|
let IOCommand::SaveChunk { position, data } = cmd else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
self.save.save_chunk(position, &data).unwrap();
|
self.save.save_chunk(position, &data).unwrap();
|
||||||
|
saved_amount += 1;
|
||||||
}
|
}
|
||||||
|
log::info!("saved {} chunks on exit", saved_amount);
|
||||||
self.tx.send(IOResponse::Terminated).unwrap();
|
self.tx.send(IOResponse::Terminated).unwrap();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// between every betch of requests, check if there are any pending save requests
|
||||||
|
if self.save_queue.len() > 0 {
|
||||||
|
let will_drain = MAX_SAVE_BATCH_SIZE.min(self.save_queue.len());
|
||||||
|
log::info!("saving {}/{} chunks with batch size {}...", will_drain, self.save_queue.len(), MAX_SAVE_BATCH_SIZE);
|
||||||
|
for (pos, data) in self.save_queue.drain(..will_drain) {
|
||||||
|
self.save.save_chunk(pos, &data).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -62,10 +62,10 @@ impl ChunkStorage {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Unique)]
|
// #[derive(Unique)]
|
||||||
pub struct WorldInfo {
|
// pub struct WorldInfo {
|
||||||
pub seed: u32,
|
// pub seed: u32,
|
||||||
}
|
// }
|
||||||
|
|
||||||
#[derive(Default, Unique)]
|
#[derive(Default, Unique)]
|
||||||
pub struct ChunkMeshStorage {
|
pub struct ChunkMeshStorage {
|
||||||
|
|
|
@ -57,6 +57,7 @@ pub struct Chunk {
|
||||||
pub desired_state: DesiredChunkState,
|
pub desired_state: DesiredChunkState,
|
||||||
pub abortion: Option<Arc<Atomic<AbortState>>>,
|
pub abortion: Option<Arc<Atomic<AbortState>>>,
|
||||||
pub mesh_dirty: bool,
|
pub mesh_dirty: bool,
|
||||||
|
pub data_modified: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Chunk {
|
impl Chunk {
|
||||||
|
@ -69,6 +70,7 @@ impl Chunk {
|
||||||
desired_state: Default::default(),
|
desired_state: Default::default(),
|
||||||
abortion: None,
|
abortion: None,
|
||||||
mesh_dirty: false,
|
mesh_dirty: false,
|
||||||
|
data_modified: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -282,6 +282,9 @@ fn process_state_changes(
|
||||||
//TODO IMPORTANT: WAIT FOR CHUNK TO FINISH SAVING FIRST BEFORE TRANSITIONING TO UNLOADED
|
//TODO IMPORTANT: WAIT FOR CHUNK TO FINISH SAVING FIRST BEFORE TRANSITIONING TO UNLOADED
|
||||||
// OTHERWISE WE WILL LOSE THE SAVE DATA IF THE USER COMES BACK TO THE CHUNK TOO QUICKLY
|
// OTHERWISE WE WILL LOSE THE SAVE DATA IF THE USER COMES BACK TO THE CHUNK TOO QUICKLY
|
||||||
// ==========================================================
|
// ==========================================================
|
||||||
|
//XXX: CHECK IF WE REALLY NEED THIS OR IF WE CAN JUST KILL THE CHUNK RIGHT AWAY
|
||||||
|
//CHANGES TO CHUNK SAVING LOGIC SHOULD HAVE MADE THE ABOVE COMMENT OBSOLETE
|
||||||
|
|
||||||
if let Some(io) = &io {
|
if let Some(io) = &io {
|
||||||
if let Some(block_data) = &chunk.block_data {
|
if let Some(block_data) = &chunk.block_data {
|
||||||
// log::debug!("issue save command");
|
// log::debug!("issue save command");
|
||||||
|
|
|
@ -27,6 +27,7 @@ pub fn apply_queued_blocks(
|
||||||
let (chunk_pos, block_pos) = ChunkStorage::to_chunk_coords(event.position);
|
let (chunk_pos, block_pos) = ChunkStorage::to_chunk_coords(event.position);
|
||||||
let chunk = world.chunks.get_mut(&chunk_pos).expect("This error should never happen, if it does then something is super fucked up and the whole project needs to be burnt down.");
|
let chunk = world.chunks.get_mut(&chunk_pos).expect("This error should never happen, if it does then something is super fucked up and the whole project needs to be burnt down.");
|
||||||
chunk.mesh_dirty = true;
|
chunk.mesh_dirty = true;
|
||||||
|
chunk.data_modified = true;
|
||||||
//If block pos is close to the border, some neighbors may be dirty!
|
//If block pos is close to the border, some neighbors may be dirty!
|
||||||
const DIRECTIONS: [IVec3; 6] = [
|
const DIRECTIONS: [IVec3; 6] = [
|
||||||
ivec3(1, 0, 0),
|
ivec3(1, 0, 0),
|
||||||
|
|
Loading…
Reference in a new issue