Disclaimer
I am nobody important, this document is not official in any way. It contains my ideas for the World Generator API for the Sponge project. Please yell at me if anything is incorrect. Also I would love to hear your suggestions and input too!
If I’m stepping on anyone’s toes, let me know and I’ll take this down ASAP!
NB: It’s important we keep this simple, otherwise it’ll be impossible to maintain.
YouTrack Issue
http://issues.spongepowered.org/youtrack/issue/SPONGE-2
Fork
I’ve stated poking at this in a fork, nowhere near perfect yet, but it’s taking shape I think.
https://github.com/hoqhuuep/SpongeAPI
https://github.com/hoqhuuep/SpongeAPI/compare/SpongePowered:master...master
Goals
- Complete customization of block placement during world generation
- Complete customization of biome distribution during world generation
- Ability to get/set blocks in the world after generation
- Ability to get/set biomes in the world after generation
- Ability to add/remove structures from the world after generation (w.r.t. the regions which are defined, not the actual blocks)
- Ability to list available generators
- Ability to get/set generators for each world
- Avoid unnecessary coupling while maintaining acceptable performance
- Focus on server-side only modifications
- But keep in mind custom blocks and custom biomes, which client-side mods can add
Possibilities
- Mix-and-match generation parts between plugins/mods and vanilla
- Additional API for retroactive world generation (maybe?)
- Add or remove village buildings (maybe?)
Out of Scope
- Anything which cannot be controlled from server side (e.g. atmosphere color)
- Multi-threaded chunk generation, or other major refactorings
- Modifying the vanilla generator at a finer level. For example, more configuration of cave size and frequency. This should be done by plugins which can emulate the behavior of the vanilla FeatureGenerators but with more configuration.
- Multi-layered biome generators. This could be handled by plugins.
- Support for schematics. This could be handled by plugins.
Interfaces - Implemented by Sponge
(only showing methods relevant to world generation)
World
public interface World {
Dimension getDimension();
String getName();
long getSeed();
// NOTE: no setter for WorldGenerator, every world has exactly one
// It only exists to remove clutter from the World interface
WorldGenerator getGenerator();
Block getBlock(int x, int y, int z)
Block getBlock(Vector3i location);
void setBlock(int x, int y, int z, Block block);
void setBlock(Vector3i location, Block block);
Biome getBiome(int x, int z);
Biome getBiome(Vector2i location);
void setBiome(int x, int z, Biome biome);
void setBiome(Vector2i location, Biome biome);
Set<Structure> getStructures();
void addStructure(Structure structure);
void removeStructure(Structure structure);
}
WorldGenerator
public interface WorldGenerator {
BiomeGenerator getBiomeGenerator();
void setBiomeGenerator(BiomeGenerator biomeGenerator);
TerrainGenerator getTerrainGenerator();
void setTerrainGenerator(TerrainGenerator terrainGenerator);
List<FeatureGenerator> getFeatureGenerators();
void addFeatureGenerator(FeatureGenerator featureGenerator);
void removeFeatureGenerator(FeatureGenerator featureGenerator);
List<StructureGenerator> getStructureGenerators();
void addStructureGenerator(StructureGenerator structureGenerator);
void removeStructureGenerator(StructureGenerator structureGenerator);
}
Biome
See discussion on Custom Biomes below.
public interface Biome {
int getId();
String getName();
float getTemperature();
float getRainfall();
boolean canRain();
boolean canSnow();
float getMinHeight();
float getMaxHeight();
Set<CreatureType> getSpawnableCreatures();
}
Structure
Types: Mineshaft, Village, Fortress, Stronghold, Temple
public interface Structure {
Vector3i getMinBounds();
Vector3i getMaxBounds();
Set<CreatureType> getSpawnableCreatures();
}
Dimension
Needs to be one of these provided by Sponge for each dimension.
public interface Dimension {
BiomeGenerator getVanillaBiomeGenerator();
TerrainGenerator getVanillaTerrainGenerator();
FeatureGenerator getVanillaFeatureGenerator();
StructureGenerator getVanillaStructureGenerator();
}
All the returned objects should allow for these settings: Custom – Minecraft Wiki. So there is no need for indiviual vanilla feature and structure generators, they can be aggregated.
Interfaces - Implemented by Plugins
The following interfaces should be provided by the API. It should be possible for plugins to implement any or all of these interfaces to influence the world generation.
It should be possible to use a BiomeGenerator from one plugin, a TerrainGenerator from another and a collection of Feature and Structure generators from various plugins all for the same world.
It should also be possible to mix with vanilla generators, though the granularity of this is still to be determined.
This configuration of generators (for each world) should be able to be configured programmatically from plugins or by server owners using a config file.
##BiomeGenerator
Used for distributing the biomes in the world. Implemented in vanilla by (MCP::net.minecraft.world.biome.WorldChunkManager) and subclass, or possibly down to the level of (MCP::net.minecraft.world.gen.layer.GenLayer).
public interface BiomeGenerator {
// Either this
Biome generateBiome(World world, int x, int z);
// Or if we need more efficiency it could be this
Biome[] generateBiomes(World world, ChunkPosition chunkPosition);
}
During terrain generation, the vanilla TerrainGenerator requests a Biome[10*10] for an 4x unzoomed view of a 40x40 block area of the world. It may be worth the extra efficiency to allow plugins to implement this also. Though I feel that’s over coupled to the implementation.
TerrainGenerator
Used for placing the bulk of the blocks in each chunk. Implemented in vanilla by (MCP::net.minecraft.world.gen.ChunkProviderGenerate) and subclasses .
public interface TerrainGenerator {
Block[] generateTerrain(World world, ChunkPosition chunkPosition);
}
Can access the biome data from world if required.
FeatureGenerator
Used to create trees, lakes, ore veins, etc. in each chunk. Called after a chunk has been generated by the TerrainGenerator if the 3 adjacent chunks on the negative (?) x and z sides are already generated. Implemented in vanilla by subclasses of (MCP::net.minecraft.world.gen.feature.WorldGenerator).
public interface FeatureGenerator {
void generateFeature(World world, Random random, int x, int y, int z);
}
Calls mutating methods on the world to place blocks. Can access the biome and block data from world if required.
StructureGenerator
Used to create Strongholds, Villages, Nether Fortresses, Desert Temples, Jungle Temples, Ocean Monuments, Witch Huts, etc. These structures are stored in the world file. They can control mob spawns for example. Implemented in vanilla by subclasses of (MCP::net.minecraft.world.gen.structure.MapGenStructure).
public interface StructureGenerator {
void generateStructure(World world, Random random, ChunkPosition chunkPosition)
}
Calls mutating methods on the world to place blocks and add structures. Can access the biome and block data from world if required.
Things to Think About
There are many trade-offs between performance and not exposing implementation details. For terrain generation performance is quite an important concern. Though less so when/if this happens:
http://www.reddit.com/r/Minecraft/comments/2euigb/for_anyone_who_cares_possibly_multithreaded_chunk/
FeatureGenerator and StructureGenerator could be combined as they have close to the same interface. The critical difference is that Structures are stored in the world files, but this does not effect the interface. In vanilla, structure generators are not passed a y-coordinate, but this is easy to work around.
The custom terrain in the nether and end is determined by the “dimension” of the world. I think this should be handled by having both a BiomeGenerator for that world which returns a constant biome for all locations, and a TerrainGenerator which describes the shape of the terrain for each vanilla dimension.
I have been asked about ore generation (and feature generation in general) after world generation. For example if a server owner adds a plugin which doubles diamond ore frequency, and they want it to apply to existing chunks in an existing world. This is a tricky topic, and I would love to hear ideas. Basically it would involve the feature generator running on chunks which that feature generator has not been run on as they’re loaded. Usually feature generators are not added after world creation and so it’s sufficient to store a single boolean per chunk to remember if it has been populated. However if this was extended to be a boolean per feature generator per chunk, it would be possible to run feature generators which were not present during world generation, during later chunk loading. This behavior may not always be desired though, and it’s difficult to foresee issues that could occur.
Custom Bimes
Biomes in vanilla are currently identified by integer IDs, this may change as most magic-numbers in the game are being replaced with Strings.
BiomeGenerators should be capable of handling custom biomes. These require client-side modifications to work (e.g. Biomes O’ Plenty or Enhanced Biomes). Biome should not be an Enum as it should be extendable. Something akin to Forge’s BiomeDictionary should be used. This way, biome generators can look up the available biomes, if there are no client-side mods, only vanilla biomes will be available.
Possible implementation idea for custom biomes:
public interface Biome {
VanillaBiome getVanillaFallback();
...
}
public enum VanillaBiome implements Biome {
...
@Override
public VanillaBiome getVanillaFallback() {
return this;
}
...
}
So when they’re sent to the client, it would use the “vanilla fallback”, but when used internally the custom biome can be used. Biomes are stored on disk as a byte id, so if we want to allow for more than 256 biomes, we would need extra storage.
Links
Chunk data packet format: Chunk Format - wiki.vg
Shows that only 256 bytes are sent per chunk for biomes. Atmospheric color is not sent.
Generated structures data file format: Generated structures data file format – Minecraft Wiki
Enhanced Biomes: Enhanced Biomes 2.5 - Nearly 100 new biomes (20/10/14) - Minecraft Mods - Mapping and Modding: Java Edition - Minecraft Forum - Minecraft Forum
Forge’s BiomeDictionary: How to use the Forge BiomeDictionary - Mapping and Modding Tutorials - Mapping and Modding: Java Edition - Minecraft Forum - Minecraft Forum
Change History
12 September, 2014
- Removed ability to change biome atmosphere color. Unfortunately this is controlled client-side.
- Added some links
- Re-orgainised some points
- Moved some things to “Out of Scope”
- Added vanilla class names for the curious