-
Notifications
You must be signed in to change notification settings - Fork 3
Add Serde Feature #2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Hmm. What are you using this for? On disk caches so you don't have to recompute them again? |
I was thinking more for saving/loading the game state Kind of like say in minecraft, if the game generates a structure then the game updates to change where that structure generates, it still remembers where it originally generated it (like bounding box wise not just block-wise) Idk if that makes sense it's kind of weird to explain Though now I'm thinking about it more and the whole thing of dropping chunks when they go out of range also conflicts with that idea... (this is also not a hard requirement game design wise, it's kind of "run" based so I could just not allow saving mid run) |
Yea it would make sense for when chunks never get deallocated. But, I recently added flushing the cache, mutating a chunk and subsequently recomputing all layers that depended on it. For this I want to implement storing mutated info to disk anyway. So maybe it would suffice to use the same scheme to mark what you want written to disk and write it on drop and generally try to load from disk before generating |
Ah yeah something like that could probably work Just playing around with another idea I came up with this: struct DepWrap<D, C> {
deps: D,
save: Arc<dyn Fn(C, GridPoint<C>)>,
load: Box<dyn Fn(GridPoint<C>) -> Option<C>>,
}
impl<D: Dependencies, C> Dependencies for DepWrap<D, C> {
fn debug(&self) -> Vec<&dyn debug::DynLayer> {
self.deps.debug()
}
}
#[derive(Default, Clone)]
struct ChunkWrap<C> {
chunk: Option<(C, GridPoint<C>)>,
save: Option<Arc<dyn Fn(C, GridPoint<C>)>>,
}
impl<C> Drop for ChunkWrap<C> {
fn drop(&mut self) {
if let (Some((chunk, point)), Some(save)) = (self.chunk.take(), self.save.take()) {
save(chunk, point);
}
}
}
impl<C: Chunk> Chunk for ChunkWrap<C> {
type LayerStore<T> = C::LayerStore<T>;
type Dependencies = DepWrap<C::Dependencies, C>;
const GRID_OVERLAP: u8 = C::GRID_OVERLAP;
const GRID_SIZE: Point2d<u8> = C::GRID_SIZE;
const SIZE: Point2d<u8> = C::SIZE;
fn compute(DepWrap { deps, save, load }: &Self::Dependencies, index: GridPoint<Self>) -> Self {
let index = index.into_same_chunk_size();
let chunk = load(index).unwrap_or_else(|| C::compute(deps, index));
Self {
chunk: Some((chunk, index)),
save: Some(save.clone()),
}
}
fn clear(DepWrap { deps, .. }: &Self::Dependencies, index: GridPoint<Self>) {
C::clear(deps, index.into_same_chunk_size());
}
} where the idea is you can wrap a Layer with a save & load function let layer: Layer<ChunkWrap<ReducedLocations>> = Layer::new(DepWrap{
deps: ReducedLocationsDeps { pois: Default::default() },
save: Arc::new(|c: ReducedLocations, pos: GridPoint<ReducedLocations>| {
// save chunk to file
}) as _,
load: Box::new(|pos: GridPoint<ReducedLocations>| {
// load chunk from file
None
}) as _,
}); But ofc there's some issues, those functions being I'm sure you can probably think of something more clever :) |
Yea I think I'd want to include it in the chunk information natively. Then I can get the fine control for only writing back things that I mutated and you can get it for everything that was generated. I have some ideas. I'll play with them and post here when I have something that works. Until then, if you want I can merge this PR to unblock you |
Eh feel free to merge if you want but I don't think this PR actually helps that much with what I wanted anyway lol |
I've been hacking on this. Turns out it's quite messy in my own game, so I may need to rethink how I wrote my game. But the general system works and correctly stores all modified chunks and loads them before trying to generate them. |
Ok, I have tested #3 in my own project and it works... mostly. The main issue is that I have not found a nice way to pass something like a savegame directory and had to resort to a global static to know the path. I had considered just making the savegame directory part of the dependencies, but... I can't obtain the dep list in |
jup that works! Ok, no more global state needed after all. Just put the path or your save/load object as a dependency of that layer and you're good to go |
Adds an optional
serde
feature that derivesSerialize
/Deserialize
on various types(working on a project where I need to Serialize/Deserialize my Layers)