minecraft-source/src/net/minecraft/world/level/chunk/ChunkStatus.java

248 lines
14 KiB
Java

package net.minecraft.world.level.chunk;
import net.minecraft.Util;
import com.google.common.collect.ImmutableList;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.levelgen.GenerationStep;
import java.util.Set;
import net.minecraft.world.level.lighting.LevelLightEngine;
import net.minecraft.server.level.WorldGenRegion;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureManager;
import net.minecraft.server.level.ServerLevel;
import java.util.Collections;
import com.google.common.collect.Lists;
import net.minecraft.core.Registry;
import javax.annotation.Nullable;
import java.util.function.Function;
import net.minecraft.server.level.ChunkHolder;
import com.mojang.datafixers.util.Either;
import java.util.concurrent.CompletableFuture;
import net.minecraft.server.level.ThreadedLevelLightEngine;
import it.unimi.dsi.fastutil.ints.IntList;
import java.util.List;
import net.minecraft.world.level.levelgen.Heightmap;
import java.util.EnumSet;
public class ChunkStatus {
private static final EnumSet<Heightmap.Types> PRE_FEATURES;
private static final EnumSet<Heightmap.Types> POST_FEATURES;
private static final LoadingTask PASSTHROUGH_LOAD_TASK;
public static final ChunkStatus EMPTY;
public static final ChunkStatus STRUCTURE_STARTS;
public static final ChunkStatus STRUCTURE_REFERENCES;
public static final ChunkStatus BIOMES;
public static final ChunkStatus NOISE;
public static final ChunkStatus SURFACE;
public static final ChunkStatus CARVERS;
public static final ChunkStatus LIQUID_CARVERS;
public static final ChunkStatus FEATURES;
public static final ChunkStatus LIGHT;
public static final ChunkStatus SPAWN;
public static final ChunkStatus HEIGHTMAPS;
public static final ChunkStatus FULL;
private static final List<ChunkStatus> STATUS_BY_RANGE;
private static final IntList RANGE_BY_STATUS;
private final String name;
private final int index;
private final ChunkStatus parent;
private final GenerationTask generationTask;
private final LoadingTask loadingTask;
private final int range;
private final ChunkType chunkType;
private final EnumSet<Heightmap.Types> heightmapsAfter;
private static CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>> lightChunk(final ChunkStatus cab, final ThreadedLevelLightEngine xg, final ChunkAccess bzv) {
final boolean boolean4 = isLighted(cab, bzv);
if (!bzv.getStatus().isOrAfter(cab)) {
((ProtoChunk)bzv).setStatus(cab);
}
return xg.lightChunk(bzv, boolean4).<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>>thenApply(Either::left);
}
private static ChunkStatus registerSimple(final String string, @Nullable final ChunkStatus cab, final int integer, final EnumSet<Heightmap.Types> enumSet, final ChunkType a, final SimpleGenerationTask d) {
return register(string, cab, integer, enumSet, a, d);
}
private static ChunkStatus register(final String string, @Nullable final ChunkStatus cab, final int integer, final EnumSet<Heightmap.Types> enumSet, final ChunkType a, final GenerationTask b) {
return register(string, cab, integer, enumSet, a, b, ChunkStatus.PASSTHROUGH_LOAD_TASK);
}
private static ChunkStatus register(final String string, @Nullable final ChunkStatus cab, final int integer, final EnumSet<Heightmap.Types> enumSet, final ChunkType a, final GenerationTask b, final LoadingTask c) {
return Registry.<ChunkStatus>register(Registry.CHUNK_STATUS, string, new ChunkStatus(string, cab, integer, enumSet, a, b, c));
}
public static List<ChunkStatus> getStatusList() {
final List<ChunkStatus> list1 = Lists.newArrayList();
ChunkStatus cab2;
for (cab2 = ChunkStatus.FULL; cab2.getParent() != cab2; cab2 = cab2.getParent()) {
list1.add(cab2);
}
list1.add(cab2);
Collections.reverse(list1);
return list1;
}
private static boolean isLighted(final ChunkStatus cab, final ChunkAccess bzv) {
return bzv.getStatus().isOrAfter(cab) && bzv.isLightCorrect();
}
public static ChunkStatus getStatus(final int integer) {
if (integer >= ChunkStatus.STATUS_BY_RANGE.size()) {
return ChunkStatus.EMPTY;
}
if (integer < 0) {
return ChunkStatus.FULL;
}
return ChunkStatus.STATUS_BY_RANGE.get(integer);
}
public static int maxDistance() {
return ChunkStatus.STATUS_BY_RANGE.size();
}
public static int getDistance(final ChunkStatus cab) {
return ChunkStatus.RANGE_BY_STATUS.getInt(cab.getIndex());
}
ChunkStatus(final String string, @Nullable final ChunkStatus cab, final int integer, final EnumSet<Heightmap.Types> enumSet, final ChunkType a, final GenerationTask b, final LoadingTask c) {
this.name = string;
this.parent = ((cab == null) ? this : cab);
this.generationTask = b;
this.loadingTask = c;
this.range = integer;
this.chunkType = a;
this.heightmapsAfter = enumSet;
this.index = ((cab == null) ? 0 : (cab.getIndex() + 1));
}
public int getIndex() {
return this.index;
}
public String getName() {
return this.name;
}
public ChunkStatus getParent() {
return this.parent;
}
public CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>> generate(final ServerLevel xd, final ChunkGenerator<?> bzx, final StructureManager cml, final ThreadedLevelLightEngine xg, final Function<ChunkAccess, CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>>> function, final List<ChunkAccess> list) {
return this.generationTask.doWork(this, xd, bzx, cml, xg, function, list, list.get(list.size() / 2));
}
public CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>> load(final ServerLevel xd, final StructureManager cml, final ThreadedLevelLightEngine xg, final Function<ChunkAccess, CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>>> function, final ChunkAccess bzv) {
return this.loadingTask.doWork(this, xd, cml, xg, function, bzv);
}
public int getRange() {
return this.range;
}
public ChunkType getChunkType() {
return this.chunkType;
}
public static ChunkStatus byName(final String string) {
return Registry.CHUNK_STATUS.get(ResourceLocation.tryParse(string));
}
public EnumSet<Heightmap.Types> heightmapsAfter() {
return this.heightmapsAfter;
}
public boolean isOrAfter(final ChunkStatus cab) {
return this.getIndex() >= cab.getIndex();
}
@Override
public String toString() {
return Registry.CHUNK_STATUS.getKey(this).toString();
}
static {
PRE_FEATURES = EnumSet.<Heightmap.Types>of(Heightmap.Types.OCEAN_FLOOR_WG, Heightmap.Types.WORLD_SURFACE_WG);
POST_FEATURES = EnumSet.<Heightmap.Types>of(Heightmap.Types.OCEAN_FLOOR, Heightmap.Types.WORLD_SURFACE, Heightmap.Types.MOTION_BLOCKING, Heightmap.Types.MOTION_BLOCKING_NO_LEAVES);
PASSTHROUGH_LOAD_TASK = ((cab, xd, cml, xg, function, bzv) -> {
if (bzv instanceof ProtoChunk && !bzv.getStatus().isOrAfter(cab)) {
bzv.setStatus(cab);
}
return CompletableFuture.<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>>completedFuture(Either.left(bzv));
});
EMPTY = registerSimple("empty", null, -1, ChunkStatus.PRE_FEATURES, ChunkType.PROTOCHUNK, (xd, bzx, list, bzv) -> {});
STRUCTURE_STARTS = register("structure_starts", ChunkStatus.EMPTY, 0, ChunkStatus.PRE_FEATURES, ChunkType.PROTOCHUNK, (cab, xd, bzx, cml, xg, function, list, bzv) -> {
if (!bzv.getStatus().isOrAfter(cab)) {
if (xd.getLevelData().isGenerateMapFeatures()) {
bzx.createStructures(xd.getBiomeManager().withDifferentSource(bzx.getBiomeSource()), bzv, bzx, cml);
}
if (bzv instanceof ProtoChunk) {
bzv.setStatus(cab);
}
}
return CompletableFuture.<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>>completedFuture(Either.left(bzv));
});
STRUCTURE_REFERENCES = registerSimple("structure_references", ChunkStatus.STRUCTURE_STARTS, 8, ChunkStatus.PRE_FEATURES, ChunkType.PROTOCHUNK, (xd, bzx, list, bzv) -> bzx.createReferences(new WorldGenRegion(xd, list), bzv));
BIOMES = registerSimple("biomes", ChunkStatus.STRUCTURE_REFERENCES, 0, ChunkStatus.PRE_FEATURES, ChunkType.PROTOCHUNK, (xd, bzx, list, bzv) -> bzx.createBiomes(bzv));
NOISE = registerSimple("noise", ChunkStatus.BIOMES, 8, ChunkStatus.PRE_FEATURES, ChunkType.PROTOCHUNK, (xd, bzx, list, bzv) -> bzx.fillFromNoise(new WorldGenRegion(xd, list), bzv));
SURFACE = registerSimple("surface", ChunkStatus.NOISE, 0, ChunkStatus.PRE_FEATURES, ChunkType.PROTOCHUNK, (xd, bzx, list, bzv) -> bzx.buildSurfaceAndBedrock(new WorldGenRegion(xd, list), bzv));
CARVERS = registerSimple("carvers", ChunkStatus.SURFACE, 0, ChunkStatus.PRE_FEATURES, ChunkType.PROTOCHUNK, (xd, bzx, list, bzv) -> bzx.applyCarvers(xd.getBiomeManager().withDifferentSource(bzx.getBiomeSource()), bzv, GenerationStep.Carving.AIR));
LIQUID_CARVERS = registerSimple("liquid_carvers", ChunkStatus.CARVERS, 0, ChunkStatus.POST_FEATURES, ChunkType.PROTOCHUNK, (xd, bzx, list, bzv) -> bzx.applyCarvers(xd.getBiomeManager().withDifferentSource(bzx.getBiomeSource()), bzv, GenerationStep.Carving.LIQUID));
final ProtoChunk caq9;
FEATURES = register("features", ChunkStatus.LIQUID_CARVERS, 8, ChunkStatus.POST_FEATURES, ChunkType.PROTOCHUNK, (cab, xd, bzx, cml, xg, function, list, bzv) -> {
caq9 = bzv;
caq9.setLightEngine(xg);
if (!bzv.getStatus().isOrAfter(cab)) {
Heightmap.primeHeightmaps(bzv, EnumSet.<Heightmap.Types>of(Heightmap.Types.MOTION_BLOCKING, Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, Heightmap.Types.OCEAN_FLOOR, Heightmap.Types.WORLD_SURFACE));
bzx.applyBiomeDecoration(new WorldGenRegion(xd, list));
caq9.setStatus(cab);
}
return CompletableFuture.<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>>completedFuture(Either.left(bzv));
});
LIGHT = register("light", ChunkStatus.FEATURES, 1, ChunkStatus.POST_FEATURES, ChunkType.PROTOCHUNK, (cab, xd, bzx, cml, xg, function, list, bzv) -> lightChunk(cab, xg, bzv), (cab, xd, cml, xg, function, bzv) -> lightChunk(cab, xg, bzv));
SPAWN = registerSimple("spawn", ChunkStatus.LIGHT, 0, ChunkStatus.POST_FEATURES, ChunkType.PROTOCHUNK, (xd, bzx, list, bzv) -> bzx.spawnOriginalMobs(new WorldGenRegion(xd, list)));
HEIGHTMAPS = registerSimple("heightmaps", ChunkStatus.SPAWN, 0, ChunkStatus.POST_FEATURES, ChunkType.PROTOCHUNK, (xd, bzx, list, bzv) -> {});
FULL = register("full", ChunkStatus.HEIGHTMAPS, 0, ChunkStatus.POST_FEATURES, ChunkType.LEVELCHUNK, (cab, xd, bzx, cml, xg, function, list, bzv) -> function.apply(bzv), (cab, xd, cml, xg, function, bzv) -> function.apply(bzv));
STATUS_BY_RANGE = ImmutableList.<ChunkStatus>of(ChunkStatus.FULL, ChunkStatus.FEATURES, ChunkStatus.LIQUID_CARVERS, ChunkStatus.STRUCTURE_STARTS, ChunkStatus.STRUCTURE_STARTS, ChunkStatus.STRUCTURE_STARTS, ChunkStatus.STRUCTURE_STARTS, ChunkStatus.STRUCTURE_STARTS, ChunkStatus.STRUCTURE_STARTS, ChunkStatus.STRUCTURE_STARTS, ChunkStatus.STRUCTURE_STARTS);
int integer2;
int integer3;
RANGE_BY_STATUS = Util.<IntList>make((IntList)new IntArrayList(getStatusList().size()), intArrayList -> {
integer2 = 0;
for (integer3 = getStatusList().size() - 1; integer3 >= 0; --integer3) {
while (integer2 + 1 < ChunkStatus.STATUS_BY_RANGE.size() && integer3 <= ChunkStatus.STATUS_BY_RANGE.get(integer2 + 1).getIndex()) {
++integer2;
}
intArrayList.add(0, integer2);
}
});
}
interface SimpleGenerationTask extends GenerationTask {
default CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>> doWork(final ChunkStatus cab, final ServerLevel xd, final ChunkGenerator<?> bzx, final StructureManager cml, final ThreadedLevelLightEngine xg, final Function<ChunkAccess, CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>>> function, final List<ChunkAccess> list, final ChunkAccess bzv) {
if (!bzv.getStatus().isOrAfter(cab)) {
this.doWork(xd, bzx, list, bzv);
if (bzv instanceof ProtoChunk) {
((ProtoChunk)bzv).setStatus(cab);
}
}
return CompletableFuture.<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>>completedFuture(Either.left(bzv));
}
void doWork(final ServerLevel xd, final ChunkGenerator<?> bzx, final List<ChunkAccess> list, final ChunkAccess bzv);
}
public enum ChunkType {
PROTOCHUNK,
LEVELCHUNK;
}
interface GenerationTask {
CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>> doWork(final ChunkStatus cab, final ServerLevel xd, final ChunkGenerator<?> bzx, final StructureManager cml, final ThreadedLevelLightEngine xg, final Function<ChunkAccess, CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>>> function, final List<ChunkAccess> list, final ChunkAccess bzv);
}
interface LoadingTask {
CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>> doWork(final ChunkStatus cab, final ServerLevel xd, final StructureManager cml, final ThreadedLevelLightEngine xg, final Function<ChunkAccess, CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>>> function, final ChunkAccess bzv);
}
}