Thinking about how to get trees working without the second pass chunk generation stage makes me think it is time to address improvements to the world generation model. Some musings and thoughts:
- Firstly, it still seems sensible to have multiple classes doing passes over the chunk, each concerned with a separate feature - basic terrain followed by flowers followed by trees followed by whatever else. This allows some mixing and matching, and separates concerns. However...
- Using the chunk itself to convey information from pass to pass won't cut it. A tree needs to be able to grow into a chunk from "off-chunk", this means it needs to be deterministic where it will grow from and how it will grow. This means the tree growth algorithm cannot require scanning a chunk for the surface or a block type - the information must be available from elsewhere.
- This supports the need for a separate, conceptual model of the world, which is rasterised by the chunk generation passes. This model needs will need to be interrogated by systems outside the world generator as well - it provides information useful for map generation, spawn location determination and other needs. (Thought: an alternate way of handling the world would be to remove per-block modifications entirely, and do modifications to the conceptual model. This would be a different sort of game though).
One way of doing the conceptual model would be a network of information providers. Each provides will provide certain information, and require certain information. Providers can "stack" - a provider may provide information that overrides the information that it requires. A vague example may be something like:
* Heightmap - provides surface and basic air/solid information
* CaveSystem - requires basic air/solid information, provides basic air/solid information modified to add caves.
* Climate - provides humidity and temperature info
* BiomeSystem - requires surface, humidity, temperature and air/solid information, provides biome information.
* TreeSystem - uses surface, air/solid and biome information, provides tree locations and sizes.
* Cities - uses much of the above, provides city locations, may alter surface and air/solid info (to flatten landscape), remove trees.
Then each chunk pass would require various types of information.
Important - the conceptual model would not refer to specific block types. That should be determined by chunk passes. Ultimately chunk passes should determine appropriate blocks through the components of the blocks (after block improvement work).
A model for this would be to model each information element as an interface:
Code:
public interface SurfaceProvider extends MapDataProvider {
int getSurfaceFor(int x, int y);
}
public interface TreeProvider extends MapDataProvider {
TreeInfo getTreesInArea(Region3i);
}
Implementations would implement the interfaces for the data they provide, and have setters for the data they require
Code:
public class FairyCircleProvider implements TreeProvider, StandingStoneProvider {
@Requires
public void setSurfaceProvider(SurfaceProvider provider) {
// ...
}
// ...
}
Some care would need to be taken around the population of the required providers - generally the last provider registered for each interface would be used, with that provider chaining back to earlier providers of that type.
Likewise chunk passes would have setters for the data they require.
Some potential benefits:
* Allows chunk passes to be replaced without changing conceptual data - could use the same provider to produce trees, and then either a non-growing or growing chunk pass to add them.
* Adds some scope for mods adding providers or chunk passes to modify the world. So a mod could simply add fairy circles or giant cairns on top of an existing world generator.
Outstanding questions:
* A common use case would be a world feature that overrides other features in its area - like a city removing the trees, standing stones, and any other features in its area. Can this be addressed in a simple way without requiring a city to know about all features that may be placed before it, or those feature providers knowing about cities? What of features a city might build around but not remove? Is it even worth trying to deal with this?