package net.minecraft.world.level.chunk; import it.unimi.dsi.fastutil.longs.LongSet; import java.util.Map; import java.util.function.BiConsumer; import java.util.function.Predicate; import net.minecraft.Util; import net.minecraft.core.BlockPos; import net.minecraft.core.Holder; import net.minecraft.core.HolderLookup; import net.minecraft.core.registries.Registries; import net.minecraft.nbt.CompoundTag; import net.minecraft.world.entity.Entity; import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.biome.BiomeResolver; import net.minecraft.world.level.biome.Climate.Sampler; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.chunk.status.ChunkStatus; import net.minecraft.world.level.levelgen.Heightmap; import net.minecraft.world.level.levelgen.blending.BlendingData; import net.minecraft.world.level.levelgen.structure.Structure; import net.minecraft.world.level.levelgen.structure.StructureStart; import net.minecraft.world.level.lighting.ChunkSkyLightSources; import net.minecraft.world.level.material.Fluid; import net.minecraft.world.level.material.FluidState; import net.minecraft.world.ticks.BlackholeTickAccess; import net.minecraft.world.ticks.TickContainerAccess; import org.jetbrains.annotations.Nullable; /** * During world generation, adjacent chunks may be fully generated (and thus be level chunks), but are often needed in proto chunk form. This wraps a completely generated chunk as a proto chunk. */ public class ImposterProtoChunk extends ProtoChunk { private final LevelChunk wrapped; private final boolean allowWrites; public ImposterProtoChunk(LevelChunk wrapped, boolean allowWrites) { super( wrapped.getPos(), UpgradeData.EMPTY, wrapped.levelHeightAccessor, wrapped.getLevel().registryAccess().lookupOrThrow(Registries.BIOME), wrapped.getBlendingData() ); this.wrapped = wrapped; this.allowWrites = allowWrites; } @Nullable @Override public BlockEntity getBlockEntity(BlockPos pos) { return this.wrapped.getBlockEntity(pos); } @Override public BlockState getBlockState(BlockPos pos) { return this.wrapped.getBlockState(pos); } @Override public FluidState getFluidState(BlockPos pos) { return this.wrapped.getFluidState(pos); } @Override public LevelChunkSection getSection(int index) { return this.allowWrites ? this.wrapped.getSection(index) : super.getSection(index); } @Nullable @Override public BlockState setBlockState(BlockPos pos, BlockState state, int flags) { return this.allowWrites ? this.wrapped.setBlockState(pos, state, flags) : null; } @Override public void setBlockEntity(BlockEntity blockEntity) { if (this.allowWrites) { this.wrapped.setBlockEntity(blockEntity); } } @Override public void addEntity(Entity entity) { if (this.allowWrites) { this.wrapped.addEntity(entity); } } @Override public void setPersistedStatus(ChunkStatus status) { if (this.allowWrites) { super.setPersistedStatus(status); } } @Override public LevelChunkSection[] getSections() { return this.wrapped.getSections(); } @Override public void setHeightmap(Heightmap.Types type, long[] data) { } private Heightmap.Types fixType(Heightmap.Types type) { if (type == Heightmap.Types.WORLD_SURFACE_WG) { return Heightmap.Types.WORLD_SURFACE; } else { return type == Heightmap.Types.OCEAN_FLOOR_WG ? Heightmap.Types.OCEAN_FLOOR : type; } } @Override public Heightmap getOrCreateHeightmapUnprimed(Heightmap.Types type) { return this.wrapped.getOrCreateHeightmapUnprimed(type); } @Override public int getHeight(Heightmap.Types type, int x, int z) { return this.wrapped.getHeight(this.fixType(type), x, z); } @Override public Holder getNoiseBiome(int i, int j, int k) { return this.wrapped.getNoiseBiome(i, j, k); } @Override public ChunkPos getPos() { return this.wrapped.getPos(); } @Nullable @Override public StructureStart getStartForStructure(Structure structure) { return this.wrapped.getStartForStructure(structure); } @Override public void setStartForStructure(Structure structure, StructureStart structureStart) { } @Override public Map getAllStarts() { return this.wrapped.getAllStarts(); } @Override public void setAllStarts(Map structureStarts) { } @Override public LongSet getReferencesForStructure(Structure structure) { return this.wrapped.getReferencesForStructure(structure); } @Override public void addReferenceForStructure(Structure structure, long reference) { } @Override public Map getAllReferences() { return this.wrapped.getAllReferences(); } @Override public void setAllReferences(Map structureReferencesMap) { } @Override public void markUnsaved() { this.wrapped.markUnsaved(); } @Override public boolean canBeSerialized() { return false; } @Override public boolean tryMarkSaved() { return false; } @Override public boolean isUnsaved() { return false; } @Override public ChunkStatus getPersistedStatus() { return this.wrapped.getPersistedStatus(); } @Override public void removeBlockEntity(BlockPos pos) { } @Override public void markPosForPostprocessing(BlockPos pos) { } @Override public void setBlockEntityNbt(CompoundTag tag) { } @Nullable @Override public CompoundTag getBlockEntityNbt(BlockPos pos) { return this.wrapped.getBlockEntityNbt(pos); } @Nullable @Override public CompoundTag getBlockEntityNbtForSaving(BlockPos pos, HolderLookup.Provider registries) { return this.wrapped.getBlockEntityNbtForSaving(pos, registries); } @Override public void findBlocks(Predicate predicate, BiConsumer output) { this.wrapped.findBlocks(predicate, output); } @Override public TickContainerAccess getBlockTicks() { return this.allowWrites ? this.wrapped.getBlockTicks() : BlackholeTickAccess.emptyContainer(); } @Override public TickContainerAccess getFluidTicks() { return this.allowWrites ? this.wrapped.getFluidTicks() : BlackholeTickAccess.emptyContainer(); } @Override public ChunkAccess.PackedTicks getTicksForSerialization(long gametime) { return this.wrapped.getTicksForSerialization(gametime); } @Nullable @Override public BlendingData getBlendingData() { return this.wrapped.getBlendingData(); } @Override public CarvingMask getCarvingMask() { if (this.allowWrites) { return super.getCarvingMask(); } else { throw (UnsupportedOperationException)Util.pauseInIde(new UnsupportedOperationException("Meaningless in this context")); } } @Override public CarvingMask getOrCreateCarvingMask() { if (this.allowWrites) { return super.getOrCreateCarvingMask(); } else { throw (UnsupportedOperationException)Util.pauseInIde(new UnsupportedOperationException("Meaningless in this context")); } } public LevelChunk getWrapped() { return this.wrapped; } @Override public boolean isLightCorrect() { return this.wrapped.isLightCorrect(); } @Override public void setLightCorrect(boolean lightCorrect) { this.wrapped.setLightCorrect(lightCorrect); } @Override public void fillBiomesFromNoise(BiomeResolver resolver, Sampler sampler) { if (this.allowWrites) { this.wrapped.fillBiomesFromNoise(resolver, sampler); } } @Override public void initializeLightSources() { this.wrapped.initializeLightSources(); } @Override public ChunkSkyLightSources getSkyLightSources() { return this.wrapped.getSkyLightSources(); } }