minecraft-source/src/net/minecraft/server/level/WorldGenRegion.java

375 lines
13 KiB
Java

package net.minecraft.server.level;
import org.apache.logging.log4j.LogManager;
import java.util.Collections;
import net.minecraft.world.phys.AABB;
import net.minecraft.core.particles.ParticleOptions;
import net.minecraft.sounds.SoundSource;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.world.level.levelgen.Heightmap;
import net.minecraft.world.level.chunk.ChunkSource;
import net.minecraft.world.DifficultyInstance;
import net.minecraft.world.level.border.WorldBorder;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.block.EntityBlock;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.Level;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.lighting.LevelLightEngine;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.entity.Entity;
import java.util.function.Predicate;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.core.BlockPos;
import javax.annotation.Nullable;
import net.minecraft.world.level.chunk.ChunkStatus;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.Util;
import net.minecraft.util.Mth;
import net.minecraft.world.level.biome.BiomeManager;
import net.minecraft.world.level.material.Fluid;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.TickList;
import net.minecraft.world.level.levelgen.ChunkGeneratorSettings;
import net.minecraft.world.level.dimension.Dimension;
import java.util.Random;
import net.minecraft.world.level.storage.LevelData;
import net.minecraft.world.level.chunk.ChunkAccess;
import java.util.List;
import org.apache.logging.log4j.Logger;
import net.minecraft.world.level.LevelAccessor;
public class WorldGenRegion implements LevelAccessor {
private static final Logger LOGGER;
private final List<ChunkAccess> cache;
private final int x;
private final int z;
private final int size;
private final ServerLevel level;
private final long seed;
private final int seaLevel;
private final LevelData levelData;
private final Random random;
private final Dimension dimension;
private final ChunkGeneratorSettings settings;
private final TickList<Block> blockTicks;
private final TickList<Fluid> liquidTicks;
private final BiomeManager biomeManager;
public WorldGenRegion(final ServerLevel xd, final List<ChunkAccess> list) {
this.blockTicks = new WorldGenTickList<Block>(fk -> this.getChunk(fk).getBlockTicks());
this.liquidTicks = new WorldGenTickList<Fluid>(fk -> this.getChunk(fk).getLiquidTicks());
final int integer4 = Mth.floor(Math.sqrt(list.size()));
if (integer4 * integer4 != list.size()) {
throw Util.<IllegalStateException>pauseInIde(new IllegalStateException("Cache size is not a square."));
}
final ChunkPos bje5 = list.get(list.size() / 2).getPos();
this.cache = list;
this.x = bje5.x;
this.z = bje5.z;
this.size = integer4;
this.level = xd;
this.seed = xd.getSeed();
this.settings = (ChunkGeneratorSettings)xd.getChunkSource().getGenerator().getSettings();
this.seaLevel = xd.getSeaLevel();
this.levelData = xd.getLevelData();
this.random = xd.getRandom();
this.dimension = xd.getDimension();
this.biomeManager = new BiomeManager(this, LevelData.obfuscateSeed(this.seed), this.dimension.getType().getBiomeZoomer());
}
public int getCenterX() {
return this.x;
}
public int getCenterZ() {
return this.z;
}
@Override
public ChunkAccess getChunk(final int integer1, final int integer2) {
return this.getChunk(integer1, integer2, ChunkStatus.EMPTY);
}
@Nullable
@Override
public ChunkAccess getChunk(final int integer1, final int integer2, final ChunkStatus cab, final boolean boolean4) {
ChunkAccess bzv6;
if (this.hasChunk(integer1, integer2)) {
final ChunkPos bje7 = this.cache.get(0).getPos();
final int integer3 = integer1 - bje7.x;
final int integer4 = integer2 - bje7.z;
bzv6 = this.cache.get(integer3 + integer4 * this.size);
if (bzv6.getStatus().isOrAfter(cab)) {
return bzv6;
}
}
else {
bzv6 = null;
}
if (!boolean4) {
return null;
}
final ChunkAccess bzv7 = this.cache.get(0);
final ChunkAccess bzv8 = this.cache.get(this.cache.size() - 1);
WorldGenRegion.LOGGER.error("Requested chunk : {} {}", integer1, integer2);
WorldGenRegion.LOGGER.error("Region bounds : {} {} | {} {}", bzv7.getPos().x, bzv7.getPos().z, bzv8.getPos().x, bzv8.getPos().z);
if (bzv6 != null) {
throw Util.<RuntimeException>pauseInIde(new RuntimeException(String.format("Chunk is not of correct status. Expecting %s, got %s | %s %s", cab, bzv6.getStatus(), integer1, integer2)));
}
throw Util.<RuntimeException>pauseInIde(new RuntimeException(String.format("We are asking a region for a chunk out of bound | %s %s", integer1, integer2)));
}
@Override
public boolean hasChunk(final int integer1, final int integer2) {
final ChunkAccess bzv4 = this.cache.get(0);
final ChunkAccess bzv5 = this.cache.get(this.cache.size() - 1);
return integer1 >= bzv4.getPos().x && integer1 <= bzv5.getPos().x && integer2 >= bzv4.getPos().z && integer2 <= bzv5.getPos().z;
}
@Override
public BlockState getBlockState(final BlockPos fk) {
return this.getChunk(fk.getX() >> 4, fk.getZ() >> 4).getBlockState(fk);
}
@Override
public FluidState getFluidState(final BlockPos fk) {
return this.getChunk(fk).getFluidState(fk);
}
@Nullable
@Override
public Player getNearestPlayer(final double double1, final double double2, final double double3, final double double4, final Predicate<Entity> predicate) {
return null;
}
@Override
public int getSkyDarken() {
return 0;
}
@Override
public BiomeManager getBiomeManager() {
return this.biomeManager;
}
@Override
public Biome getUncachedNoiseBiome(final int integer1, final int integer2, final int integer3) {
return this.level.getUncachedNoiseBiome(integer1, integer2, integer3);
}
@Override
public LevelLightEngine getLightEngine() {
return this.level.getLightEngine();
}
@Override
public boolean destroyBlock(final BlockPos fk, final boolean boolean2, @Nullable final Entity akn) {
final BlockState byg5 = this.getBlockState(fk);
if (byg5.isAir()) {
return false;
}
if (boolean2) {
final BlockEntity bwi6 = byg5.getBlock().isEntityBlock() ? this.getBlockEntity(fk) : null;
Block.dropResources(byg5, this.level, fk, bwi6, akn, ItemStack.EMPTY);
}
return this.setBlock(fk, Blocks.AIR.defaultBlockState(), 3);
}
@Nullable
@Override
public BlockEntity getBlockEntity(final BlockPos fk) {
final ChunkAccess bzv3 = this.getChunk(fk);
BlockEntity bwi4 = bzv3.getBlockEntity(fk);
if (bwi4 != null) {
return bwi4;
}
final CompoundTag jt5 = bzv3.getBlockEntityNbt(fk);
if (jt5 != null) {
if ("DUMMY".equals(jt5.getString("id"))) {
final Block bpe6 = this.getBlockState(fk).getBlock();
if (!(bpe6 instanceof EntityBlock)) {
return null;
}
bwi4 = ((EntityBlock)bpe6).newBlockEntity(this.level);
}
else {
bwi4 = BlockEntity.loadStatic(jt5);
}
if (bwi4 != null) {
bzv3.setBlockEntity(fk, bwi4);
return bwi4;
}
}
if (bzv3.getBlockState(fk).getBlock() instanceof EntityBlock) {
WorldGenRegion.LOGGER.warn("Tried to access a block entity before it was created. {}", fk);
}
return null;
}
@Override
public boolean setBlock(final BlockPos fk, final BlockState byg, final int integer) {
final ChunkAccess bzv5 = this.getChunk(fk);
final BlockState byg2 = bzv5.setBlockState(fk, byg, false);
if (byg2 != null) {
this.level.onBlockStateChange(fk, byg2, byg);
}
final Block bpe7 = byg.getBlock();
if (bpe7.isEntityBlock()) {
if (bzv5.getStatus().getChunkType() == ChunkStatus.ChunkType.LEVELCHUNK) {
bzv5.setBlockEntity(fk, ((EntityBlock)bpe7).newBlockEntity(this));
}
else {
final CompoundTag jt8 = new CompoundTag();
jt8.putInt("x", fk.getX());
jt8.putInt("y", fk.getY());
jt8.putInt("z", fk.getZ());
jt8.putString("id", "DUMMY");
bzv5.setBlockEntityNbt(jt8);
}
}
else if (byg2 != null && byg2.getBlock().isEntityBlock()) {
bzv5.removeBlockEntity(fk);
}
if (byg.hasPostProcess(this, fk)) {
this.markPosForPostprocessing(fk);
}
return true;
}
private void markPosForPostprocessing(final BlockPos fk) {
this.getChunk(fk).markPosForPostprocessing(fk);
}
@Override
public boolean addFreshEntity(final Entity akn) {
final int integer3 = Mth.floor(akn.getX() / 16.0);
final int integer4 = Mth.floor(akn.getZ() / 16.0);
this.getChunk(integer3, integer4).addEntity(akn);
return true;
}
@Override
public boolean removeBlock(final BlockPos fk, final boolean boolean2) {
return this.setBlock(fk, Blocks.AIR.defaultBlockState(), 3);
}
@Override
public WorldBorder getWorldBorder() {
return this.level.getWorldBorder();
}
@Override
public boolean isClientSide() {
return false;
}
@Deprecated
@Override
public ServerLevel getLevel() {
return this.level;
}
@Override
public LevelData getLevelData() {
return this.levelData;
}
@Override
public DifficultyInstance getCurrentDifficultyAt(final BlockPos fk) {
if (!this.hasChunk(fk.getX() >> 4, fk.getZ() >> 4)) {
throw new RuntimeException("We are asking a region for a chunk out of bound");
}
return new DifficultyInstance(this.level.getDifficulty(), this.level.getDayTime(), 0L, this.level.getMoonBrightness());
}
@Override
public ChunkSource getChunkSource() {
return this.level.getChunkSource();
}
@Override
public long getSeed() {
return this.seed;
}
@Override
public TickList<Block> getBlockTicks() {
return this.blockTicks;
}
@Override
public TickList<Fluid> getLiquidTicks() {
return this.liquidTicks;
}
@Override
public int getSeaLevel() {
return this.seaLevel;
}
@Override
public Random getRandom() {
return this.random;
}
@Override
public void blockUpdated(final BlockPos fk, final Block bpe) {
}
@Override
public int getHeight(final Heightmap.Types a, final int integer2, final int integer3) {
return this.getChunk(integer2 >> 4, integer3 >> 4).getHeight(a, integer2 & 0xF, integer3 & 0xF) + 1;
}
@Override
public void playSound(@Nullable final Player ayg, final BlockPos fk, final SoundEvent aah, final SoundSource aaj, final float float5, final float float6) {
}
@Override
public void addParticle(final ParticleOptions gt, final double double2, final double double3, final double double4, final double double5, final double double6, final double double7) {
}
@Override
public void levelEvent(@Nullable final Player ayg, final int integer2, final BlockPos fk, final int integer4) {
}
@Override
public BlockPos getSharedSpawnPos() {
return this.level.getSharedSpawnPos();
}
@Override
public Dimension getDimension() {
return this.dimension;
}
@Override
public boolean isStateAtPosition(final BlockPos fk, final Predicate<BlockState> predicate) {
return predicate.test(this.getBlockState(fk));
}
@Override
public <T extends Entity> List<T> getEntitiesOfClass(final Class<? extends T> class1, final AABB cvc, @Nullable final Predicate<? super T> predicate) {
return Collections.<T>emptyList();
}
@Override
public List<Entity> getEntities(@Nullable final Entity akn, final AABB cvc, @Nullable final Predicate<? super Entity> predicate) {
return Collections.<Entity>emptyList();
}
@Override
public List<Player> players() {
return Collections.<Player>emptyList();
}
static {
LOGGER = LogManager.getLogger();
}
}