433 lines
		
	
	
	
		
			16 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
			
		
		
	
	
			433 lines
		
	
	
	
		
			16 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
| package net.minecraft.world.level.chunk;
 | |
| 
 | |
| import com.google.common.collect.Lists;
 | |
| import com.google.common.collect.Sets;
 | |
| import com.mojang.logging.LogUtils;
 | |
| import com.mojang.serialization.Codec;
 | |
| import it.unimi.dsi.fastutil.ints.IntArrays;
 | |
| import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
 | |
| import it.unimi.dsi.fastutil.objects.ObjectSet;
 | |
| import java.util.EnumSet;
 | |
| import java.util.IdentityHashMap;
 | |
| import java.util.List;
 | |
| import java.util.Map;
 | |
| import java.util.Set;
 | |
| import net.minecraft.core.BlockPos;
 | |
| import net.minecraft.core.Direction;
 | |
| import net.minecraft.core.Direction8;
 | |
| import net.minecraft.core.SectionPos;
 | |
| import net.minecraft.core.registries.BuiltInRegistries;
 | |
| import net.minecraft.nbt.CompoundTag;
 | |
| import net.minecraft.world.level.ChunkPos;
 | |
| import net.minecraft.world.level.EmptyBlockGetter;
 | |
| import net.minecraft.world.level.Level;
 | |
| import net.minecraft.world.level.LevelAccessor;
 | |
| import net.minecraft.world.level.LevelHeightAccessor;
 | |
| import net.minecraft.world.level.block.Block;
 | |
| import net.minecraft.world.level.block.Blocks;
 | |
| import net.minecraft.world.level.block.ChestBlock;
 | |
| import net.minecraft.world.level.block.HorizontalDirectionalBlock;
 | |
| import net.minecraft.world.level.block.StemBlock;
 | |
| import net.minecraft.world.level.block.entity.BlockEntity;
 | |
| import net.minecraft.world.level.block.entity.ChestBlockEntity;
 | |
| import net.minecraft.world.level.block.state.BlockState;
 | |
| import net.minecraft.world.level.block.state.properties.BlockStateProperties;
 | |
| import net.minecraft.world.level.block.state.properties.ChestType;
 | |
| import net.minecraft.world.level.material.Fluid;
 | |
| import net.minecraft.world.level.material.Fluids;
 | |
| import net.minecraft.world.ticks.SavedTick;
 | |
| import org.slf4j.Logger;
 | |
| 
 | |
| public class UpgradeData {
 | |
| 	private static final Logger LOGGER = LogUtils.getLogger();
 | |
| 	public static final UpgradeData EMPTY = new UpgradeData(EmptyBlockGetter.INSTANCE);
 | |
| 	private static final String TAG_INDICES = "Indices";
 | |
| 	private static final Direction8[] DIRECTIONS = Direction8.values();
 | |
| 	private static final Codec<List<SavedTick<Block>>> BLOCK_TICKS_CODEC = SavedTick.codec(BuiltInRegistries.BLOCK.byNameCodec().orElse(Blocks.AIR)).listOf();
 | |
| 	private static final Codec<List<SavedTick<Fluid>>> FLUID_TICKS_CODEC = SavedTick.codec(BuiltInRegistries.FLUID.byNameCodec().orElse(Fluids.EMPTY)).listOf();
 | |
| 	private final EnumSet<Direction8> sides = EnumSet.noneOf(Direction8.class);
 | |
| 	private final List<SavedTick<Block>> neighborBlockTicks = Lists.<SavedTick<Block>>newArrayList();
 | |
| 	private final List<SavedTick<Fluid>> neighborFluidTicks = Lists.<SavedTick<Fluid>>newArrayList();
 | |
| 	private final int[][] index;
 | |
| 	static final Map<Block, UpgradeData.BlockFixer> MAP = new IdentityHashMap();
 | |
| 	static final Set<UpgradeData.BlockFixer> CHUNKY_FIXERS = Sets.<UpgradeData.BlockFixer>newHashSet();
 | |
| 
 | |
| 	private UpgradeData(LevelHeightAccessor level) {
 | |
| 		this.index = new int[level.getSectionsCount()][];
 | |
| 	}
 | |
| 
 | |
| 	public UpgradeData(CompoundTag tag, LevelHeightAccessor level) {
 | |
| 		this(level);
 | |
| 		tag.getCompound("Indices").ifPresent(compoundTag -> {
 | |
| 			for (int ix = 0; ix < this.index.length; ix++) {
 | |
| 				this.index[ix] = (int[])compoundTag.getIntArray(String.valueOf(ix)).orElse(null);
 | |
| 			}
 | |
| 		});
 | |
| 		int i = tag.getIntOr("Sides", 0);
 | |
| 
 | |
| 		for (Direction8 direction8 : Direction8.values()) {
 | |
| 			if ((i & 1 << direction8.ordinal()) != 0) {
 | |
| 				this.sides.add(direction8);
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		tag.read("neighbor_block_ticks", BLOCK_TICKS_CODEC).ifPresent(this.neighborBlockTicks::addAll);
 | |
| 		tag.read("neighbor_fluid_ticks", FLUID_TICKS_CODEC).ifPresent(this.neighborFluidTicks::addAll);
 | |
| 	}
 | |
| 
 | |
| 	private UpgradeData(UpgradeData other) {
 | |
| 		this.sides.addAll(other.sides);
 | |
| 		this.neighborBlockTicks.addAll(other.neighborBlockTicks);
 | |
| 		this.neighborFluidTicks.addAll(other.neighborFluidTicks);
 | |
| 		this.index = new int[other.index.length][];
 | |
| 
 | |
| 		for (int i = 0; i < other.index.length; i++) {
 | |
| 			int[] is = other.index[i];
 | |
| 			this.index[i] = is != null ? IntArrays.copy(is) : null;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	public void upgrade(LevelChunk chunk) {
 | |
| 		this.upgradeInside(chunk);
 | |
| 
 | |
| 		for (Direction8 direction8 : DIRECTIONS) {
 | |
| 			upgradeSides(chunk, direction8);
 | |
| 		}
 | |
| 
 | |
| 		Level level = chunk.getLevel();
 | |
| 		this.neighborBlockTicks.forEach(savedTick -> {
 | |
| 			Block block = savedTick.type() == Blocks.AIR ? level.getBlockState(savedTick.pos()).getBlock() : (Block)savedTick.type();
 | |
| 			level.scheduleTick(savedTick.pos(), block, savedTick.delay(), savedTick.priority());
 | |
| 		});
 | |
| 		this.neighborFluidTicks.forEach(savedTick -> {
 | |
| 			Fluid fluid = savedTick.type() == Fluids.EMPTY ? level.getFluidState(savedTick.pos()).getType() : (Fluid)savedTick.type();
 | |
| 			level.scheduleTick(savedTick.pos(), fluid, savedTick.delay(), savedTick.priority());
 | |
| 		});
 | |
| 		CHUNKY_FIXERS.forEach(blockFixer -> blockFixer.processChunk(level));
 | |
| 	}
 | |
| 
 | |
| 	private static void upgradeSides(LevelChunk chunk, Direction8 side) {
 | |
| 		Level level = chunk.getLevel();
 | |
| 		if (chunk.getUpgradeData().sides.remove(side)) {
 | |
| 			Set<Direction> set = side.getDirections();
 | |
| 			int i = 0;
 | |
| 			int j = 15;
 | |
| 			boolean bl = set.contains(Direction.EAST);
 | |
| 			boolean bl2 = set.contains(Direction.WEST);
 | |
| 			boolean bl3 = set.contains(Direction.SOUTH);
 | |
| 			boolean bl4 = set.contains(Direction.NORTH);
 | |
| 			boolean bl5 = set.size() == 1;
 | |
| 			ChunkPos chunkPos = chunk.getPos();
 | |
| 			int k = chunkPos.getMinBlockX() + (!bl5 || !bl4 && !bl3 ? (bl2 ? 0 : 15) : 1);
 | |
| 			int l = chunkPos.getMinBlockX() + (!bl5 || !bl4 && !bl3 ? (bl2 ? 0 : 15) : 14);
 | |
| 			int m = chunkPos.getMinBlockZ() + (!bl5 || !bl && !bl2 ? (bl4 ? 0 : 15) : 1);
 | |
| 			int n = chunkPos.getMinBlockZ() + (!bl5 || !bl && !bl2 ? (bl4 ? 0 : 15) : 14);
 | |
| 			Direction[] directions = Direction.values();
 | |
| 			BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos();
 | |
| 
 | |
| 			for (BlockPos blockPos : BlockPos.betweenClosed(k, level.getMinY(), m, l, level.getMaxY(), n)) {
 | |
| 				BlockState blockState = level.getBlockState(blockPos);
 | |
| 				BlockState blockState2 = blockState;
 | |
| 
 | |
| 				for (Direction direction : directions) {
 | |
| 					mutableBlockPos.setWithOffset(blockPos, direction);
 | |
| 					blockState2 = updateState(blockState2, direction, level, blockPos, mutableBlockPos);
 | |
| 				}
 | |
| 
 | |
| 				Block.updateOrDestroy(blockState, blockState2, level, blockPos, 18);
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	private static BlockState updateState(BlockState state, Direction direction, LevelAccessor level, BlockPos pos, BlockPos offsetPos) {
 | |
| 		return ((UpgradeData.BlockFixer)MAP.getOrDefault(state.getBlock(), UpgradeData.BlockFixers.DEFAULT))
 | |
| 			.updateShape(state, direction, level.getBlockState(offsetPos), level, pos, offsetPos);
 | |
| 	}
 | |
| 
 | |
| 	private void upgradeInside(LevelChunk chunk) {
 | |
| 		BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos();
 | |
| 		BlockPos.MutableBlockPos mutableBlockPos2 = new BlockPos.MutableBlockPos();
 | |
| 		ChunkPos chunkPos = chunk.getPos();
 | |
| 		LevelAccessor levelAccessor = chunk.getLevel();
 | |
| 
 | |
| 		for (int i = 0; i < this.index.length; i++) {
 | |
| 			LevelChunkSection levelChunkSection = chunk.getSection(i);
 | |
| 			int[] is = this.index[i];
 | |
| 			this.index[i] = null;
 | |
| 			if (is != null && is.length > 0) {
 | |
| 				Direction[] directions = Direction.values();
 | |
| 				PalettedContainer<BlockState> palettedContainer = levelChunkSection.getStates();
 | |
| 				int j = chunk.getSectionYFromSectionIndex(i);
 | |
| 				int k = SectionPos.sectionToBlockCoord(j);
 | |
| 
 | |
| 				for (int l : is) {
 | |
| 					int m = l & 15;
 | |
| 					int n = l >> 8 & 15;
 | |
| 					int o = l >> 4 & 15;
 | |
| 					mutableBlockPos.set(chunkPos.getMinBlockX() + m, k + n, chunkPos.getMinBlockZ() + o);
 | |
| 					BlockState blockState = palettedContainer.get(l);
 | |
| 					BlockState blockState2 = blockState;
 | |
| 
 | |
| 					for (Direction direction : directions) {
 | |
| 						mutableBlockPos2.setWithOffset(mutableBlockPos, direction);
 | |
| 						if (SectionPos.blockToSectionCoord(mutableBlockPos.getX()) == chunkPos.x && SectionPos.blockToSectionCoord(mutableBlockPos.getZ()) == chunkPos.z) {
 | |
| 							blockState2 = updateState(blockState2, direction, levelAccessor, mutableBlockPos, mutableBlockPos2);
 | |
| 						}
 | |
| 					}
 | |
| 
 | |
| 					Block.updateOrDestroy(blockState, blockState2, levelAccessor, mutableBlockPos, 18);
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		for (int ix = 0; ix < this.index.length; ix++) {
 | |
| 			if (this.index[ix] != null) {
 | |
| 				LOGGER.warn("Discarding update data for section {} for chunk ({} {})", levelAccessor.getSectionYFromSectionIndex(ix), chunkPos.x, chunkPos.z);
 | |
| 			}
 | |
| 
 | |
| 			this.index[ix] = null;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	public boolean isEmpty() {
 | |
| 		for (int[] is : this.index) {
 | |
| 			if (is != null) {
 | |
| 				return false;
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		return this.sides.isEmpty();
 | |
| 	}
 | |
| 
 | |
| 	public CompoundTag write() {
 | |
| 		CompoundTag compoundTag = new CompoundTag();
 | |
| 		CompoundTag compoundTag2 = new CompoundTag();
 | |
| 
 | |
| 		for (int i = 0; i < this.index.length; i++) {
 | |
| 			String string = String.valueOf(i);
 | |
| 			if (this.index[i] != null && this.index[i].length != 0) {
 | |
| 				compoundTag2.putIntArray(string, this.index[i]);
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		if (!compoundTag2.isEmpty()) {
 | |
| 			compoundTag.put("Indices", compoundTag2);
 | |
| 		}
 | |
| 
 | |
| 		int ix = 0;
 | |
| 
 | |
| 		for (Direction8 direction8 : this.sides) {
 | |
| 			ix |= 1 << direction8.ordinal();
 | |
| 		}
 | |
| 
 | |
| 		compoundTag.putByte("Sides", (byte)ix);
 | |
| 		if (!this.neighborBlockTicks.isEmpty()) {
 | |
| 			compoundTag.store("neighbor_block_ticks", BLOCK_TICKS_CODEC, this.neighborBlockTicks);
 | |
| 		}
 | |
| 
 | |
| 		if (!this.neighborFluidTicks.isEmpty()) {
 | |
| 			compoundTag.store("neighbor_fluid_ticks", FLUID_TICKS_CODEC, this.neighborFluidTicks);
 | |
| 		}
 | |
| 
 | |
| 		return compoundTag;
 | |
| 	}
 | |
| 
 | |
| 	public UpgradeData copy() {
 | |
| 		return this == EMPTY ? EMPTY : new UpgradeData(this);
 | |
| 	}
 | |
| 
 | |
| 	public interface BlockFixer {
 | |
| 		BlockState updateShape(BlockState state, Direction direction, BlockState offsetState, LevelAccessor level, BlockPos pos, BlockPos offsetPos);
 | |
| 
 | |
| 		default void processChunk(LevelAccessor level) {
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	static enum BlockFixers implements UpgradeData.BlockFixer {
 | |
| 		BLACKLIST(
 | |
| 			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.CHERRY_SIGN,
 | |
| 			Blocks.JUNGLE_SIGN,
 | |
| 			Blocks.DARK_OAK_SIGN,
 | |
| 			Blocks.PALE_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,
 | |
| 			Blocks.PALE_OAK_WALL_SIGN,
 | |
| 			Blocks.OAK_HANGING_SIGN,
 | |
| 			Blocks.SPRUCE_HANGING_SIGN,
 | |
| 			Blocks.BIRCH_HANGING_SIGN,
 | |
| 			Blocks.ACACIA_HANGING_SIGN,
 | |
| 			Blocks.JUNGLE_HANGING_SIGN,
 | |
| 			Blocks.DARK_OAK_HANGING_SIGN,
 | |
| 			Blocks.PALE_OAK_HANGING_SIGN,
 | |
| 			Blocks.OAK_WALL_HANGING_SIGN,
 | |
| 			Blocks.SPRUCE_WALL_HANGING_SIGN,
 | |
| 			Blocks.BIRCH_WALL_HANGING_SIGN,
 | |
| 			Blocks.ACACIA_WALL_HANGING_SIGN,
 | |
| 			Blocks.JUNGLE_WALL_HANGING_SIGN,
 | |
| 			Blocks.DARK_OAK_WALL_HANGING_SIGN,
 | |
| 			Blocks.PALE_OAK_WALL_HANGING_SIGN
 | |
| 		) {
 | |
| 			@Override
 | |
| 			public BlockState updateShape(BlockState state, Direction direction, BlockState offsetState, LevelAccessor level, BlockPos pos, BlockPos offsetPos) {
 | |
| 				return state;
 | |
| 			}
 | |
| 		},
 | |
| 		DEFAULT {
 | |
| 			@Override
 | |
| 			public BlockState updateShape(BlockState state, Direction direction, BlockState offsetState, LevelAccessor level, BlockPos pos, BlockPos offsetPos) {
 | |
| 				return state.updateShape(level, level, pos, direction, offsetPos, level.getBlockState(offsetPos), level.getRandom());
 | |
| 			}
 | |
| 		},
 | |
| 		CHEST(Blocks.CHEST, Blocks.TRAPPED_CHEST) {
 | |
| 			@Override
 | |
| 			public BlockState updateShape(BlockState state, Direction direction, BlockState offsetState, LevelAccessor level, BlockPos pos, BlockPos offsetPos) {
 | |
| 				if (offsetState.is(state.getBlock())
 | |
| 					&& direction.getAxis().isHorizontal()
 | |
| 					&& state.getValue(ChestBlock.TYPE) == ChestType.SINGLE
 | |
| 					&& offsetState.getValue(ChestBlock.TYPE) == ChestType.SINGLE) {
 | |
| 					Direction direction2 = state.getValue(ChestBlock.FACING);
 | |
| 					if (direction.getAxis() != direction2.getAxis() && direction2 == offsetState.getValue(ChestBlock.FACING)) {
 | |
| 						ChestType chestType = direction == direction2.getClockWise() ? ChestType.LEFT : ChestType.RIGHT;
 | |
| 						level.setBlock(offsetPos, offsetState.setValue(ChestBlock.TYPE, chestType.getOpposite()), 18);
 | |
| 						if (direction2 == Direction.NORTH || direction2 == Direction.EAST) {
 | |
| 							BlockEntity blockEntity = level.getBlockEntity(pos);
 | |
| 							BlockEntity blockEntity2 = level.getBlockEntity(offsetPos);
 | |
| 							if (blockEntity instanceof ChestBlockEntity && blockEntity2 instanceof ChestBlockEntity) {
 | |
| 								ChestBlockEntity.swapContents((ChestBlockEntity)blockEntity, (ChestBlockEntity)blockEntity2);
 | |
| 							}
 | |
| 						}
 | |
| 
 | |
| 						return state.setValue(ChestBlock.TYPE, chestType);
 | |
| 					}
 | |
| 				}
 | |
| 
 | |
| 				return state;
 | |
| 			}
 | |
| 		},
 | |
| 		LEAVES(
 | |
| 			true,
 | |
| 			Blocks.ACACIA_LEAVES,
 | |
| 			Blocks.CHERRY_LEAVES,
 | |
| 			Blocks.BIRCH_LEAVES,
 | |
| 			Blocks.PALE_OAK_LEAVES,
 | |
| 			Blocks.DARK_OAK_LEAVES,
 | |
| 			Blocks.JUNGLE_LEAVES,
 | |
| 			Blocks.OAK_LEAVES,
 | |
| 			Blocks.SPRUCE_LEAVES
 | |
| 		) {
 | |
| 			private final ThreadLocal<List<ObjectSet<BlockPos>>> queue = ThreadLocal.withInitial(() -> Lists.newArrayListWithCapacity(7));
 | |
| 
 | |
| 			@Override
 | |
| 			public BlockState updateShape(BlockState state, Direction direction, BlockState offsetState, LevelAccessor level, BlockPos pos, BlockPos offsetPos) {
 | |
| 				BlockState blockState = state.updateShape(level, level, pos, direction, offsetPos, level.getBlockState(offsetPos), level.getRandom());
 | |
| 				if (state != blockState) {
 | |
| 					int i = (Integer)blockState.getValue(BlockStateProperties.DISTANCE);
 | |
| 					List<ObjectSet<BlockPos>> list = (List<ObjectSet<BlockPos>>)this.queue.get();
 | |
| 					if (list.isEmpty()) {
 | |
| 						for (int j = 0; j < 7; j++) {
 | |
| 							list.add(new ObjectOpenHashSet());
 | |
| 						}
 | |
| 					}
 | |
| 
 | |
| 					((ObjectSet)list.get(i)).add(pos.immutable());
 | |
| 				}
 | |
| 
 | |
| 				return state;
 | |
| 			}
 | |
| 
 | |
| 			@Override
 | |
| 			public void processChunk(LevelAccessor level) {
 | |
| 				BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos();
 | |
| 				List<ObjectSet<BlockPos>> list = (List<ObjectSet<BlockPos>>)this.queue.get();
 | |
| 
 | |
| 				for (int i = 2; i < list.size(); i++) {
 | |
| 					int j = i - 1;
 | |
| 					ObjectSet<BlockPos> objectSet = (ObjectSet<BlockPos>)list.get(j);
 | |
| 					ObjectSet<BlockPos> objectSet2 = (ObjectSet<BlockPos>)list.get(i);
 | |
| 
 | |
| 					for (BlockPos blockPos : objectSet) {
 | |
| 						BlockState blockState = level.getBlockState(blockPos);
 | |
| 						if ((Integer)blockState.getValue(BlockStateProperties.DISTANCE) >= j) {
 | |
| 							level.setBlock(blockPos, blockState.setValue(BlockStateProperties.DISTANCE, j), 18);
 | |
| 							if (i != 7) {
 | |
| 								for (Direction direction : DIRECTIONS) {
 | |
| 									mutableBlockPos.setWithOffset(blockPos, direction);
 | |
| 									BlockState blockState2 = level.getBlockState(mutableBlockPos);
 | |
| 									if (blockState2.hasProperty(BlockStateProperties.DISTANCE) && (Integer)blockState.getValue(BlockStateProperties.DISTANCE) > i) {
 | |
| 										objectSet2.add(mutableBlockPos.immutable());
 | |
| 									}
 | |
| 								}
 | |
| 							}
 | |
| 						}
 | |
| 					}
 | |
| 				}
 | |
| 
 | |
| 				list.clear();
 | |
| 			}
 | |
| 		},
 | |
| 		STEM_BLOCK(Blocks.MELON_STEM, Blocks.PUMPKIN_STEM) {
 | |
| 			@Override
 | |
| 			public BlockState updateShape(BlockState state, Direction direction, BlockState offsetState, LevelAccessor level, BlockPos pos, BlockPos offsetPos) {
 | |
| 				if ((Integer)state.getValue(StemBlock.AGE) == 7) {
 | |
| 					Block block = state.is(Blocks.PUMPKIN_STEM) ? Blocks.PUMPKIN : Blocks.MELON;
 | |
| 					if (offsetState.is(block)) {
 | |
| 						return (state.is(Blocks.PUMPKIN_STEM) ? Blocks.ATTACHED_PUMPKIN_STEM : Blocks.ATTACHED_MELON_STEM)
 | |
| 							.defaultBlockState()
 | |
| 							.setValue(HorizontalDirectionalBlock.FACING, direction);
 | |
| 					}
 | |
| 				}
 | |
| 
 | |
| 				return state;
 | |
| 			}
 | |
| 		};
 | |
| 
 | |
| 		public static final Direction[] DIRECTIONS = Direction.values();
 | |
| 
 | |
| 		BlockFixers(final Block... blocks) {
 | |
| 			this(false, blocks);
 | |
| 		}
 | |
| 
 | |
| 		BlockFixers(final boolean chunkyFixer, final Block... blocks) {
 | |
| 			for (Block block : blocks) {
 | |
| 				UpgradeData.MAP.put(block, this);
 | |
| 			}
 | |
| 
 | |
| 			if (chunkyFixer) {
 | |
| 				UpgradeData.CHUNKY_FIXERS.add(this);
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| }
 |