Forge 1.20.1 World Generation Architecture Review — Dynamic Rising Sea Level System Hello. I am developing a Forge 1.20.1 mod called World FloodEnd. The core mechanic of the mod is a gradually rising global ocean level. Every 5 in-game days the global water level increases by 1 block. Example: Day 0: Sea level Y=63
Day 5: Sea level Y=64
Day 10: Sea level Y=65
...
The main challenge is performance. I do not want to use the common approach: Increase water level
|
v
Scan the entire world
|
v
Place millions of water blocks
because this will eventually destroy TPS on large worlds. The goal is to make the rising ocean behave like a world generation parameter, not like a giant block update operation. Intended architecture The world should have a global value: FloodLevel = current ocean height
This value is stored by the mod and increases every 5 Minecraft days. The system is divided into three cases: FloodWorldData
|
|
Current FloodLevel
|
┌────────────────┼────────────────┐
| | |
v v v
New unexplored Loaded chunks Unloaded chunks
chunks around players stored on disk
World generation FloodManager No processing
uses current handles gradual while inactive
FloodLevel flooding
1. New unexplored chunks When a player travels into unexplored territory, the chunk should already generate with the current ocean level. Example: Day 100
FloodLevel = Y=100
Player travels far away
New chunks should generate already matching Y=100
The goal is: Chunk generation
|
v
Current FloodLevel applied
|
v
Chunk appears already flooded
Not: Generate chunk
|
v
Place thousands of water blocks afterwards
because that causes huge performance spikes. Currently I am investigating the world generation stage. I created a Mixin into: NoiseBasedChunkGenerator.fillFromNoise()
Example: @Inject(method = "fillFromNoise", at = @At("HEAD"))
private void worldFloodEnd$fillFromNoise(
Executor executor,
Blender blender,
RandomState randomState,
StructureManager structureManager,
ChunkAccess chunk,
CallbackInfoReturnable<CompletableFuture<ChunkAccess>> cir
)
{
int waterLevel = FloodWorldData.getWaterLevel();
WorldFloodEnd.LOGGER.info(
"[WorldFloodEnd] New chunk {} {} | Water Level {}",
chunk.getPos().x,
chunk.getPos().z,
waterLevel
);
}
However, this is currently only for testing. The idea is not to manually place water inside this method. The intended solution is to make the generator itself use the current FloodLevel. Possible approaches I am considering: dynamically replacing NoiseGeneratorSettings.seaLevel; overriding ChunkGenerator#getSeaLevel() through Mixin; another Forge-supported world generation hook. 2. Already generated and currently loaded chunks These chunks are handled differently. A separate FloodManager should only work with chunks that are currently loaded around players. Example: Player base area loaded
|
v
FloodManager gradually updates these chunks
|
v
Water level increases smoothly
The FloodManager should: process only active chunks; use a limited queue; avoid large TPS spikes; never scan the whole world. The goal is that the player sees the ocean slowly advancing, while the server remains stable. 3. Previously generated but unloaded chunks This is an important part. I do not want unloaded chunks to be constantly processed. Example: Day 100
FloodLevel = Y=100
Chunk was generated years ago
Player leaves
Chunk unloads
↓
No background flooding process
Later: Player returns
↓
Chunk loads again
↓
Chunk should know the current FloodLevel
↓
It updates to the correct state
The world should not require a full scan after every ocean level increase. Desired final behavior The complete system should work like this: Every 5 days:
FloodLevel +1
|
|
New chunks:
generated with new water height
Loaded chunks:
FloodManager gradually updates them
Unloaded chunks:
wait until loaded again, then synchronize
Questions for experienced Forge developers I would appreciate feedback on the architecture before continuing development. Is using dynamic NoiseGeneratorSettings.seaLevel the correct approach for making new chunks generate with a higher ocean level? Is NoiseBasedChunkGenerator.fillFromNoise() a good place to hook into, or is there a better generation stage? Would overriding ChunkGenerator#getSeaLevel() with Mixin be safe, or could it create compatibility issues with other world generation mods? What is the recommended Forge approach for unloaded chunks: storing a FloodLevel value in chunk NBT? using capabilities? another chunk lifecycle event? Could this approach interfere with: structures; villages; custom terrain generators; biome generation mods; aquifers? Is the architecture: Generation modification for new chunks
+
FloodManager for active chunks
+
state synchronization for unloaded chunks
a reasonable way to implement a dynamic rising ocean without destroying server performance? Environment: Minecraft Forge 1.20.1 Java 17 I am not asking for a complete implementation. I mainly want an architecture review from people familiar with Minecraft world generation and Forge internals. Thank you.
By
_LugerT_ · 7 hours ago 7 hr