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

321 lines
16 KiB
Java

package net.minecraft.world.level.chunk;
import net.minecraft.world.level.block.state.AbstractStateHolder;
import net.minecraft.world.level.block.StemGrownBlock;
import net.minecraft.world.level.block.HorizontalDirectionalBlock;
import net.minecraft.world.level.block.StemBlock;
import it.unimi.dsi.fastutil.objects.ObjectIterator;
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import com.google.common.collect.Lists;
import it.unimi.dsi.fastutil.objects.ObjectSet;
import java.util.List;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.ChestBlockEntity;
import net.minecraft.world.level.block.state.properties.Property;
import net.minecraft.world.level.block.state.properties.ChestType;
import net.minecraft.world.level.block.ChestBlock;
import net.minecraft.world.level.block.Blocks;
import com.google.common.collect.Sets;
import java.util.IdentityHashMap;
import org.apache.logging.log4j.LogManager;
import net.minecraft.nbt.Tag;
import net.minecraft.world.level.block.state.BlockState;
import java.util.Iterator;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.core.Vec3i;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.nbt.CompoundTag;
import java.util.Set;
import net.minecraft.world.level.block.Block;
import java.util.Map;
import java.util.EnumSet;
import net.minecraft.core.Direction8;
import org.apache.logging.log4j.Logger;
public class UpgradeData {
private static final Logger LOGGER;
public static final UpgradeData EMPTY;
private static final Direction8[] DIRECTIONS;
private final EnumSet<Direction8> sides;
private final int[][] index;
private static final Map<Block, BlockFixer> MAP;
private static final Set<BlockFixer> CHUNKY_FIXERS;
private UpgradeData() {
this.sides = EnumSet.<Direction8>noneOf(Direction8.class);
this.index = new int[16][];
}
public UpgradeData(final CompoundTag jt) {
this();
if (jt.contains("Indices", 10)) {
final CompoundTag jt2 = jt.getCompound("Indices");
for (int integer4 = 0; integer4 < this.index.length; ++integer4) {
final String string5 = String.valueOf(integer4);
if (jt2.contains(string5, 11)) {
this.index[integer4] = jt2.getIntArray(string5);
}
}
}
final int integer5 = jt.getInt("Sides");
for (final Direction8 fq7 : Direction8.values()) {
if ((integer5 & 1 << fq7.ordinal()) != 0x0) {
this.sides.add(fq7);
}
}
}
public void upgrade(final LevelChunk cai) {
this.upgradeInside(cai);
for (final Direction8 fq6 : UpgradeData.DIRECTIONS) {
upgradeSides(cai, fq6);
}
final Level bjt3 = cai.getLevel();
UpgradeData.CHUNKY_FIXERS.forEach(a -> a.processChunk(bjt3));
}
private static void upgradeSides(final LevelChunk cai, final Direction8 fq) {
final Level bjt3 = cai.getLevel();
if (!cai.getUpgradeData().sides.remove(fq)) {
return;
}
final Set<Direction> set4 = fq.getDirections();
final int integer5 = 0;
final int integer6 = 15;
final boolean boolean7 = set4.contains(Direction.EAST);
final boolean boolean8 = set4.contains(Direction.WEST);
final boolean boolean9 = set4.contains(Direction.SOUTH);
final boolean boolean10 = set4.contains(Direction.NORTH);
final boolean boolean11 = set4.size() == 1;
final ChunkPos bje12 = cai.getPos();
final int integer7 = bje12.getMinBlockX() + ((boolean11 && (boolean10 || boolean9)) ? 1 : (boolean8 ? 0 : 15));
final int integer8 = bje12.getMinBlockX() + ((boolean11 && (boolean10 || boolean9)) ? 14 : (boolean8 ? 0 : 15));
final int integer9 = bje12.getMinBlockZ() + ((boolean11 && (boolean7 || boolean8)) ? 1 : (boolean10 ? 0 : 15));
final int integer10 = bje12.getMinBlockZ() + ((boolean11 && (boolean7 || boolean8)) ? 14 : (boolean10 ? 0 : 15));
final Direction[] arr17 = Direction.values();
final BlockPos.MutableBlockPos a18 = new BlockPos.MutableBlockPos();
for (final BlockPos fk20 : BlockPos.betweenClosed(integer7, 0, integer9, integer8, bjt3.getMaxBuildHeight() - 1, integer10)) {
BlockState byg22;
final BlockState byg21 = byg22 = bjt3.getBlockState(fk20);
for (final Direction fp26 : arr17) {
a18.set(fk20).move(fp26);
byg22 = updateState(byg22, fp26, bjt3, fk20, a18);
}
Block.updateOrDestroy(byg21, byg22, bjt3, fk20, 18);
}
}
private static BlockState updateState(final BlockState byg, final Direction fp, final LevelAccessor bju, final BlockPos fk4, final BlockPos fk5) {
return UpgradeData.MAP.getOrDefault(byg.getBlock(), BlockFixers.DEFAULT).updateShape(byg, fp, bju.getBlockState(fk5), bju, fk4, fk5);
}
private void upgradeInside(final LevelChunk cai) {
try (final BlockPos.PooledMutableBlockPos b3 = BlockPos.PooledMutableBlockPos.acquire();
final BlockPos.PooledMutableBlockPos b4 = BlockPos.PooledMutableBlockPos.acquire()) {
final ChunkPos bje7 = cai.getPos();
final LevelAccessor bju8 = cai.getLevel();
for (int integer9 = 0; integer9 < 16; ++integer9) {
final LevelChunkSection caj10 = cai.getSections()[integer9];
final int[] arr11 = this.index[integer9];
this.index[integer9] = null;
if (caj10 != null && arr11 != null) {
if (arr11.length > 0) {
final Direction[] arr12 = Direction.values();
final PalettedContainer<BlockState> cap13 = caj10.getStates();
for (final int integer10 : arr11) {
final int integer11 = integer10 & 0xF;
final int integer12 = integer10 >> 8 & 0xF;
final int integer13 = integer10 >> 4 & 0xF;
b3.set(bje7.getMinBlockX() + integer11, (integer9 << 4) + integer12, bje7.getMinBlockZ() + integer13);
BlockState byg22;
final BlockState byg21 = byg22 = cap13.get(integer10);
for (final Direction fp26 : arr12) {
b4.set((Vec3i)b3).move(fp26);
if (b3.getX() >> 4 == bje7.x) {
if (b3.getZ() >> 4 == bje7.z) {
byg22 = updateState(byg22, fp26, bju8, b3, b4);
}
}
}
Block.updateOrDestroy(byg21, byg22, bju8, b3, 18);
}
}
}
}
for (int integer9 = 0; integer9 < this.index.length; ++integer9) {
if (this.index[integer9] != null) {
UpgradeData.LOGGER.warn("Discarding update data for section {} for chunk ({} {})", integer9, bje7.x, bje7.z);
}
this.index[integer9] = null;
}
}
}
public boolean isEmpty() {
for (final int[] arr5 : this.index) {
if (arr5 != null) {
return false;
}
}
return this.sides.isEmpty();
}
public CompoundTag write() {
final CompoundTag jt2 = new CompoundTag();
final CompoundTag jt3 = new CompoundTag();
for (int integer4 = 0; integer4 < this.index.length; ++integer4) {
final String string5 = String.valueOf(integer4);
if (this.index[integer4] != null && this.index[integer4].length != 0) {
jt3.putIntArray(string5, this.index[integer4]);
}
}
if (!jt3.isEmpty()) {
jt2.put("Indices", jt3);
}
int integer4 = 0;
for (final Direction8 fq6 : this.sides) {
integer4 |= 1 << fq6.ordinal();
}
jt2.putByte("Sides", (byte)integer4);
return jt2;
}
static {
LOGGER = LogManager.getLogger();
EMPTY = new UpgradeData();
DIRECTIONS = Direction8.values();
MAP = new IdentityHashMap<Block, BlockFixer>();
CHUNKY_FIXERS = Sets.newHashSet();
}
public interface BlockFixer {
BlockState updateShape(final BlockState byg1, final Direction fp, final BlockState byg3, final LevelAccessor bju, final BlockPos fk5, final BlockPos fk6);
default void processChunk(final LevelAccessor bju) {
}
}
enum BlockFixers implements BlockFixer {
BLACKLIST(new Block[] { Blocks.OBSERVER, Blocks.NETHER_PORTAL, Blocks.WHITE_CONCRETE_POWDER, Blocks.ORANGE_CONCRETE_POWDER, Blocks.MAGENTA_CONCRETE_POWDER, Blocks.LIGHT_BLUE_CONCRETE_POWDER, Blocks.YELLOW_CONCRETE_POWDER, Blocks.LIME_CONCRETE_POWDER, Blocks.PINK_CONCRETE_POWDER, Blocks.GRAY_CONCRETE_POWDER, Blocks.LIGHT_GRAY_CONCRETE_POWDER, Blocks.CYAN_CONCRETE_POWDER, Blocks.PURPLE_CONCRETE_POWDER, Blocks.BLUE_CONCRETE_POWDER, Blocks.BROWN_CONCRETE_POWDER, Blocks.GREEN_CONCRETE_POWDER, Blocks.RED_CONCRETE_POWDER, Blocks.BLACK_CONCRETE_POWDER, Blocks.ANVIL, Blocks.CHIPPED_ANVIL, Blocks.DAMAGED_ANVIL, Blocks.DRAGON_EGG, Blocks.GRAVEL, Blocks.SAND, Blocks.RED_SAND, Blocks.OAK_SIGN, Blocks.SPRUCE_SIGN, Blocks.BIRCH_SIGN, Blocks.ACACIA_SIGN, Blocks.JUNGLE_SIGN, Blocks.DARK_OAK_SIGN, Blocks.OAK_WALL_SIGN, Blocks.SPRUCE_WALL_SIGN, Blocks.BIRCH_WALL_SIGN, Blocks.ACACIA_WALL_SIGN, Blocks.JUNGLE_WALL_SIGN, Blocks.DARK_OAK_WALL_SIGN }) {
@Override
public BlockState updateShape(final BlockState byg1, final Direction fp, final BlockState byg3, final LevelAccessor bju, final BlockPos fk5, final BlockPos fk6) {
return byg1;
}
},
DEFAULT(new Block[0]) {
@Override
public BlockState updateShape(final BlockState byg1, final Direction fp, final BlockState byg3, final LevelAccessor bju, final BlockPos fk5, final BlockPos fk6) {
return byg1.updateShape(fp, bju.getBlockState(fk6), bju, fk5, fk6);
}
},
CHEST(new Block[] { Blocks.CHEST, Blocks.TRAPPED_CHEST }) {
@Override
public BlockState updateShape(final BlockState byg1, final Direction fp, final BlockState byg3, final LevelAccessor bju, final BlockPos fk5, final BlockPos fk6) {
if (byg3.getBlock() == byg1.getBlock() && fp.getAxis().isHorizontal() && byg1.<ChestType>getValue(ChestBlock.TYPE) == ChestType.SINGLE && byg3.<ChestType>getValue(ChestBlock.TYPE) == ChestType.SINGLE) {
final Direction fp2 = byg1.<Direction>getValue((Property<Direction>)ChestBlock.FACING);
if (fp.getAxis() != fp2.getAxis() && fp2 == byg3.<Direction>getValue((Property<Direction>)ChestBlock.FACING)) {
final ChestType byz9 = (fp == fp2.getClockWise()) ? ChestType.LEFT : ChestType.RIGHT;
bju.setBlock(fk6, ((AbstractStateHolder<O, BlockState>)byg3).<ChestType, ChestType>setValue(ChestBlock.TYPE, byz9.getOpposite()), 18);
if (fp2 == Direction.NORTH || fp2 == Direction.EAST) {
final BlockEntity bwi10 = bju.getBlockEntity(fk5);
final BlockEntity bwi11 = bju.getBlockEntity(fk6);
if (bwi10 instanceof ChestBlockEntity && bwi11 instanceof ChestBlockEntity) {
ChestBlockEntity.swapContents((ChestBlockEntity)bwi10, (ChestBlockEntity)bwi11);
}
}
return ((AbstractStateHolder<O, BlockState>)byg1).<ChestType, ChestType>setValue(ChestBlock.TYPE, byz9);
}
}
return byg1;
}
},
LEAVES(true, new Block[] { Blocks.ACACIA_LEAVES, Blocks.BIRCH_LEAVES, Blocks.DARK_OAK_LEAVES, Blocks.JUNGLE_LEAVES, Blocks.OAK_LEAVES, Blocks.SPRUCE_LEAVES }) {
private final ThreadLocal<List<ObjectSet<BlockPos>>> queue;
{
this.queue = ThreadLocal.<List<ObjectSet<BlockPos>>>withInitial(() -> Lists.newArrayListWithCapacity(7));
}
@Override
public BlockState updateShape(final BlockState byg1, final Direction fp, final BlockState byg3, final LevelAccessor bju, final BlockPos fk5, final BlockPos fk6) {
final BlockState byg4 = byg1.updateShape(fp, bju.getBlockState(fk6), bju, fk5, fk6);
if (byg1 != byg4) {
final int integer9 = byg4.<Integer>getValue((Property<Integer>)BlockStateProperties.DISTANCE);
final List<ObjectSet<BlockPos>> list10 = this.queue.get();
if (list10.isEmpty()) {
for (int integer10 = 0; integer10 < 7; ++integer10) {
list10.add((ObjectSet<BlockPos>)new ObjectOpenHashSet());
}
}
list10.get(integer9).add(fk5.immutable());
}
return byg1;
}
@Override
public void processChunk(final LevelAccessor bju) {
final BlockPos.MutableBlockPos a3 = new BlockPos.MutableBlockPos();
final List<ObjectSet<BlockPos>> list4 = this.queue.get();
for (int integer5 = 2; integer5 < list4.size(); ++integer5) {
final int integer6 = integer5 - 1;
final ObjectSet<BlockPos> objectSet7 = list4.get(integer6);
final ObjectSet<BlockPos> objectSet8 = list4.get(integer5);
for (final BlockPos fk10 : objectSet7) {
final BlockState byg11 = bju.getBlockState(fk10);
if (byg11.<Integer>getValue((Property<Integer>)BlockStateProperties.DISTANCE) < integer6) {
continue;
}
bju.setBlock(fk10, ((AbstractStateHolder<O, BlockState>)byg11).<Comparable, Integer>setValue((Property<Comparable>)BlockStateProperties.DISTANCE, integer6), 18);
if (integer5 == 7) {
continue;
}
for (final Direction fp15 : UpgradeData$BlockFixers$4.DIRECTIONS) {
a3.set(fk10).move(fp15);
final BlockState byg12 = bju.getBlockState(a3);
if (byg12.<Comparable>hasProperty((Property<Comparable>)BlockStateProperties.DISTANCE) && byg11.<Integer>getValue((Property<Integer>)BlockStateProperties.DISTANCE) > integer5) {
objectSet8.add(a3.immutable());
}
}
}
}
list4.clear();
}
},
STEM_BLOCK(new Block[] { Blocks.MELON_STEM, Blocks.PUMPKIN_STEM }) {
@Override
public BlockState updateShape(final BlockState byg1, final Direction fp, final BlockState byg3, final LevelAccessor bju, final BlockPos fk5, final BlockPos fk6) {
if (byg1.<Integer>getValue((Property<Integer>)StemBlock.AGE) == 7) {
final StemGrownBlock bus8 = ((StemBlock)byg1.getBlock()).getFruit();
if (byg3.getBlock() == bus8) {
return ((AbstractStateHolder<O, BlockState>)bus8.getAttachedStem().defaultBlockState()).<Comparable, Direction>setValue((Property<Comparable>)HorizontalDirectionalBlock.FACING, fp);
}
}
return byg1;
}
};
public static final Direction[] DIRECTIONS;
private BlockFixers(final Block[] arr) {
this(false, arr);
}
private BlockFixers(final boolean boolean3, final Block[] arr) {
for (final Block bpe9 : arr) {
UpgradeData.MAP.put(bpe9, this);
}
if (boolean3) {
UpgradeData.CHUNKY_FIXERS.add(this);
}
}
static {
DIRECTIONS = Direction.values();
}
}
}