10000 Add Serde Feature by PieKing1215 · Pull Request #2 · oli-obk/layer-proc-gen · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

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

Closed
wants to merge 2 commits into from
Closed

Add Serde Feature #2

wants to merge 2 commits into from

Conversation

PieKing1215
Copy link
Contributor

Adds an optional serde feature that derives Serialize/Deserialize on various types
(working on a project where I need to Serialize/Deserialize my Layers)

@oli-obk
Copy link
Owner
oli-obk commented Mar 30, 2025

Hmm. What are you using this for?

On disk caches so you don't have to recompute them again?

@PieKing1215
Copy link
Contributor Author
PieKing1215 commented Mar 30, 2025

I was thinking more for saving/loading the game state
Kind of theoretical but say you generate an area then save the game
If I then update something that causes the layers' rng to change, and you load the save
I would like for it to remember the chunks it already generated at every layer
But if the layers' storages aren't part of the save then it would change the context of areas that were already generated

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...
Curious if you have any thoughts?

(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)

@oli-obk
Copy link
Owner
oli-obk commented Mar 30, 2025

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

@PieKing1215
Copy link
Contributor Author
PieKing1215 commented Mar 31, 2025

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 Fn and not FnMut or something is kind of restrictive
If you eg wanted to save/load to a HashMap you'd need to RwLock it or do some shenanigans with channels or something?
And also the save function probably goes off more than needed because of RollingGrid::get retuning a clone instead of reference I think?

I'm sure you can probably think of something more clever :)

@oli-obk
Copy link
Owner
oli-obk commented Mar 31, 2025

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

@PieKing1215
Copy link
Contributor Author

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
Though could maybe still be useful just for snapshotting the state of the generator?
But I'm not really particularly blocked by this, no rush

@oli-obk
Copy link
Owner
oli-obk commented Apr 9, 2025

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.

@oli-obk
Copy link
Owner
oli-obk commented Apr 25, 2025

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 Drop. I'll try handling the drop/on_drop logic in Layer instead, maybe that works

@oli-obk
Copy link
Owner
oli-obk 7B44 commented Apr 25, 2025

I'll try handling the drop/on_drop logic in Layer instead, maybe that works

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

@oli-obk oli-obk closed this Apr 25, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants
0