minecraft-src/net/minecraft/world/level/chunk/status/ChunkStatusTasks.java
2025-07-04 03:15:13 +03:00

202 lines
8.7 KiB
Java

package net.minecraft.world.level.chunk.status;
import java.util.EnumSet;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.level.GenerationChunkHolder;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ThreadedLevelLightEngine;
import net.minecraft.server.level.WorldGenRegion;
import net.minecraft.util.StaticCache2D;
import net.minecraft.world.entity.EntitySpawnReason;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.ImposterProtoChunk;
import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.chunk.ProtoChunk;
import net.minecraft.world.level.levelgen.BelowZeroRetrogen;
import net.minecraft.world.level.levelgen.Heightmap;
import net.minecraft.world.level.levelgen.Heightmap.Types;
import net.minecraft.world.level.levelgen.blending.Blender;
public class ChunkStatusTasks {
private static boolean isLighted(ChunkAccess chunk) {
return chunk.getPersistedStatus().isOrAfter(ChunkStatus.LIGHT) && chunk.isLightCorrect();
}
static CompletableFuture<ChunkAccess> passThrough(
WorldGenContext worldGenContext, ChunkStep step, StaticCache2D<GenerationChunkHolder> cache, ChunkAccess chunk
) {
return CompletableFuture.completedFuture(chunk);
}
static CompletableFuture<ChunkAccess> generateStructureStarts(
WorldGenContext worldGenContext, ChunkStep step, StaticCache2D<GenerationChunkHolder> cache, ChunkAccess chunk
) {
ServerLevel serverLevel = worldGenContext.level();
if (serverLevel.getServer().getWorldData().worldGenOptions().generateStructures()) {
worldGenContext.generator()
.createStructures(
serverLevel.registryAccess(),
serverLevel.getChunkSource().getGeneratorState(),
serverLevel.structureManager(),
chunk,
worldGenContext.structureManager(),
serverLevel.dimension()
);
}
serverLevel.onStructureStartsAvailable(chunk);
return CompletableFuture.completedFuture(chunk);
}
static CompletableFuture<ChunkAccess> loadStructureStarts(
WorldGenContext worldGenContext, ChunkStep step, StaticCache2D<GenerationChunkHolder> cache, ChunkAccess chunk
) {
worldGenContext.level().onStructureStartsAvailable(chunk);
return CompletableFuture.completedFuture(chunk);
}
static CompletableFuture<ChunkAccess> generateStructureReferences(
WorldGenContext worldGenContext, ChunkStep step, StaticCache2D<GenerationChunkHolder> cache, ChunkAccess chunk
) {
ServerLevel serverLevel = worldGenContext.level();
WorldGenRegion worldGenRegion = new WorldGenRegion(serverLevel, cache, step, chunk);
worldGenContext.generator().createReferences(worldGenRegion, serverLevel.structureManager().forWorldGenRegion(worldGenRegion), chunk);
return CompletableFuture.completedFuture(chunk);
}
static CompletableFuture<ChunkAccess> generateBiomes(
WorldGenContext worldGenContext, ChunkStep step, StaticCache2D<GenerationChunkHolder> cache, ChunkAccess chunk
) {
ServerLevel serverLevel = worldGenContext.level();
WorldGenRegion worldGenRegion = new WorldGenRegion(serverLevel, cache, step, chunk);
return worldGenContext.generator()
.createBiomes(
serverLevel.getChunkSource().randomState(), Blender.of(worldGenRegion), serverLevel.structureManager().forWorldGenRegion(worldGenRegion), chunk
);
}
static CompletableFuture<ChunkAccess> generateNoise(
WorldGenContext worldGenContext, ChunkStep step, StaticCache2D<GenerationChunkHolder> cache, ChunkAccess chunk
) {
ServerLevel serverLevel = worldGenContext.level();
WorldGenRegion worldGenRegion = new WorldGenRegion(serverLevel, cache, step, chunk);
return worldGenContext.generator()
.fillFromNoise(
Blender.of(worldGenRegion), serverLevel.getChunkSource().randomState(), serverLevel.structureManager().forWorldGenRegion(worldGenRegion), chunk
)
.thenApply(chunkAccess -> {
if (chunkAccess instanceof ProtoChunk protoChunk) {
BelowZeroRetrogen belowZeroRetrogen = protoChunk.getBelowZeroRetrogen();
if (belowZeroRetrogen != null) {
BelowZeroRetrogen.replaceOldBedrock(protoChunk);
if (belowZeroRetrogen.hasBedrockHoles()) {
belowZeroRetrogen.applyBedrockMask(protoChunk);
}
}
}
return chunkAccess;
});
}
static CompletableFuture<ChunkAccess> generateSurface(
WorldGenContext worldGenContext, ChunkStep step, StaticCache2D<GenerationChunkHolder> cache, ChunkAccess chunk
) {
ServerLevel serverLevel = worldGenContext.level();
WorldGenRegion worldGenRegion = new WorldGenRegion(serverLevel, cache, step, chunk);
worldGenContext.generator()
.buildSurface(worldGenRegion, serverLevel.structureManager().forWorldGenRegion(worldGenRegion), serverLevel.getChunkSource().randomState(), chunk);
return CompletableFuture.completedFuture(chunk);
}
static CompletableFuture<ChunkAccess> generateCarvers(
WorldGenContext worldGenContext, ChunkStep step, StaticCache2D<GenerationChunkHolder> cache, ChunkAccess chunk
) {
ServerLevel serverLevel = worldGenContext.level();
WorldGenRegion worldGenRegion = new WorldGenRegion(serverLevel, cache, step, chunk);
if (chunk instanceof ProtoChunk protoChunk) {
Blender.addAroundOldChunksCarvingMaskFilter(worldGenRegion, protoChunk);
}
worldGenContext.generator()
.applyCarvers(
worldGenRegion,
serverLevel.getSeed(),
serverLevel.getChunkSource().randomState(),
serverLevel.getBiomeManager(),
serverLevel.structureManager().forWorldGenRegion(worldGenRegion),
chunk
);
return CompletableFuture.completedFuture(chunk);
}
static CompletableFuture<ChunkAccess> generateFeatures(
WorldGenContext worldGenContext, ChunkStep step, StaticCache2D<GenerationChunkHolder> cache, ChunkAccess chunk
) {
ServerLevel serverLevel = worldGenContext.level();
Heightmap.primeHeightmaps(chunk, EnumSet.of(Types.MOTION_BLOCKING, Types.MOTION_BLOCKING_NO_LEAVES, Types.OCEAN_FLOOR, Types.WORLD_SURFACE));
WorldGenRegion worldGenRegion = new WorldGenRegion(serverLevel, cache, step, chunk);
worldGenContext.generator().applyBiomeDecoration(worldGenRegion, chunk, serverLevel.structureManager().forWorldGenRegion(worldGenRegion));
Blender.generateBorderTicks(worldGenRegion, chunk);
return CompletableFuture.completedFuture(chunk);
}
static CompletableFuture<ChunkAccess> initializeLight(
WorldGenContext worldGenContext, ChunkStep step, StaticCache2D<GenerationChunkHolder> cache, ChunkAccess chunk
) {
ThreadedLevelLightEngine threadedLevelLightEngine = worldGenContext.lightEngine();
chunk.initializeLightSources();
((ProtoChunk)chunk).setLightEngine(threadedLevelLightEngine);
boolean bl = isLighted(chunk);
return threadedLevelLightEngine.initializeLight(chunk, bl);
}
static CompletableFuture<ChunkAccess> light(WorldGenContext worldGenContext, ChunkStep step, StaticCache2D<GenerationChunkHolder> cache, ChunkAccess chunk) {
boolean bl = isLighted(chunk);
return worldGenContext.lightEngine().lightChunk(chunk, bl);
}
static CompletableFuture<ChunkAccess> generateSpawn(
WorldGenContext worldGenContext, ChunkStep step, StaticCache2D<GenerationChunkHolder> cache, ChunkAccess chunk
) {
if (!chunk.isUpgrading()) {
worldGenContext.generator().spawnOriginalMobs(new WorldGenRegion(worldGenContext.level(), cache, step, chunk));
}
return CompletableFuture.completedFuture(chunk);
}
static CompletableFuture<ChunkAccess> full(WorldGenContext worldGenContext, ChunkStep step, StaticCache2D<GenerationChunkHolder> cache, ChunkAccess chunk) {
ChunkPos chunkPos = chunk.getPos();
GenerationChunkHolder generationChunkHolder = cache.get(chunkPos.x, chunkPos.z);
return CompletableFuture.supplyAsync(() -> {
ProtoChunk protoChunk = (ProtoChunk)chunk;
ServerLevel serverLevel = worldGenContext.level();
LevelChunk levelChunk;
if (protoChunk instanceof ImposterProtoChunk imposterProtoChunk) {
levelChunk = imposterProtoChunk.getWrapped();
} else {
levelChunk = new LevelChunk(serverLevel, protoChunk, levelChunkx -> postLoadProtoChunk(serverLevel, protoChunk.getEntities()));
generationChunkHolder.replaceProtoChunk(new ImposterProtoChunk(levelChunk, false));
}
levelChunk.setFullStatus(generationChunkHolder::getFullStatus);
levelChunk.runPostLoad();
levelChunk.setLoaded(true);
levelChunk.registerAllBlockEntitiesAfterLevelLoad();
levelChunk.registerTickContainerInLevel(serverLevel);
levelChunk.setUnsavedListener(worldGenContext.unsavedListener());
return levelChunk;
}, worldGenContext.mainThreadExecutor());
}
private static void postLoadProtoChunk(ServerLevel level, List<CompoundTag> entityTags) {
if (!entityTags.isEmpty()) {
level.addWorldGenChunkEntities(EntityType.loadEntitiesRecursive(entityTags, level, EntitySpawnReason.LOAD));
}
}
}