Skip to content
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

Common interface for chunk producers/consumers. #506

Open
rj00a opened this issue Aug 30, 2023 · 0 comments
Open

Common interface for chunk producers/consumers. #506

rj00a opened this issue Aug 30, 2023 · 0 comments
Labels
enhancement New feature or request

Comments

@rj00a
Copy link
Member

rj00a commented Aug 30, 2023

Describe the problem related to your feature request.

For some applications written in Valence, it is desirable to load and unload chunks from memory automatically as players explore the environment. This could include:

  • Chunks from a terrain generation algorithm.
  • Chunks from/to a file format like Anvil.

However, Valence doesn't make this easy. Loading and unloading must be done manually by the programmer in a tedious and error-prone way.

valence_anvil does the required work of loading and unloading for us, but this functionality is locked behind valence_anvil and must be recreated for any "chunk producer" or "chunk consumer" we might want to make. This hinders interoperability.

What solution would you like?

  • Create a new crate called valence_chunk_manager (name TBD) which has...
    • ChunkManagerPlugin
    • ChunkProducer component for chunk layers containing a boxed trait object named ProduceChunk.
    • ChunkConsumer component for chunk layers containing a boxed trait object named ConsumeChunk.
    • EmptyChunkProducer, CompositeChunkProducer, maybe more.
    • Systems and other public functions needed to make this work.

The ProduceChunk trait looks something like this:

pub trait ProduceChunk {
    // `height` and `min_y` are from the dimension type. Used as hints. (maybe pass in the whole dimension info?)
    fn produce_chunk(&mut self, pos: ChunkPos, height: u32, min_y: i32) -> ProduceChunkResult;
    // Called once per tick.
    fn poll_pending(&mut self, pending: &mut Vec<(ChunkPos, Option<UnloadedChunk>)>);
}

pub enum ProduceChunkResult {
    /// The chunk is available now. Contains the chunk or `None` if there is no chunk at this position.
    Now(Option<UnloadedChunk>),
    /// The chunk isn't available this tick, but will be produced later by [`ProduceChunk::poll_pending`].
    Pending,
}

ConsumeChunk looks like

/// Called by the chunk manager when a chunk is removed from the layer, usually because the chunk is out of range of players.
pub trait ConsumeChunk {
    fn consume_chunk(&mut self, pos: ChunkPos, chunk: UnloadedChunk);
}

For convenience, the library should provide trivial implementations of these traits. This is useful for simple "void worlds" and the examples.

pub struct EmptyChunkProducer;

impl ProduceChunk for EmptyChunkProducer {
    fn produce_chunk(_pos: ChunkPos, _height: u32, _min_y: i32) -> ProduceChunkResult {
        ProduceChunkResult::Now(Some(UnloadedChunk::default()))
    }
}

Next, we need some way to compose chunk providers together. This enables us to, for example, separate terrain generation from file formats.

We can do this without introducing any new primitives:

/// An implementation of [`ChunkProducer`] which combines the producers `A` and `B` together.
/// If `A` fails to produce a chunk at some position, then `B` is used to fill the gap.
pub struct CompositeChunkProducer<A, B> {
    pub a: A,
    pub b: B,
    ...
}

impl<A, B> ChunkProducer for CompositeChunkProducer<A, B> where A: ChunkProducer, B: ChunkProducer { ... }

Finally, we can use this new approach in the examples.

What alternative(s) have you considered?

  • Better name for "chunk manager"?
  • How does this integrate with entities and EntityLayer?
  • Is there a more "ECS friendly" way to design this API?

Additional context

Possibly relevant for #504

@rj00a rj00a added the enhancement New feature or request label Aug 30, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

1 participant