321 lines
16 KiB
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();
|
|
}
|
|
}
|
|
}
|