25f259e0bc
- merge mc1.18/dev - reuse transform interfaces from Flywheel and include them in catnip - extend SBB interface slightly - copy .editorconfig to catnip and ponder
292 lines
10 KiB
Java
292 lines
10 KiB
Java
package com.simibubi.create.content.contraptions.components.crafter;
|
|
|
|
import com.simibubi.create.AllBlocks;
|
|
import com.simibubi.create.AllItems;
|
|
import com.simibubi.create.AllTileEntities;
|
|
import com.simibubi.create.content.contraptions.base.HorizontalKineticBlock;
|
|
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
|
|
import com.simibubi.create.content.contraptions.components.crafter.ConnectedInputHandler.ConnectedInput;
|
|
import com.simibubi.create.content.contraptions.components.crafter.MechanicalCrafterTileEntity.Phase;
|
|
import com.simibubi.create.content.contraptions.relays.elementary.ICogWheel;
|
|
import com.simibubi.create.foundation.block.ITE;
|
|
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
|
|
import com.simibubi.create.foundation.tileEntity.behaviour.inventory.InvManipulationBehaviour;
|
|
|
|
import net.createmod.catnip.utility.Iterate;
|
|
import net.createmod.catnip.utility.Pointing;
|
|
import net.createmod.catnip.utility.VecHelper;
|
|
import net.createmod.catnip.utility.math.AngleHelper;
|
|
import net.minecraft.core.BlockPos;
|
|
import net.minecraft.core.Direction;
|
|
import net.minecraft.core.Direction.Axis;
|
|
import net.minecraft.core.Direction.AxisDirection;
|
|
import net.minecraft.world.InteractionHand;
|
|
import net.minecraft.world.InteractionResult;
|
|
import net.minecraft.world.entity.player.Player;
|
|
import net.minecraft.world.item.ItemStack;
|
|
import net.minecraft.world.item.context.BlockPlaceContext;
|
|
import net.minecraft.world.item.context.UseOnContext;
|
|
import net.minecraft.world.level.Level;
|
|
import net.minecraft.world.level.block.Block;
|
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
|
import net.minecraft.world.level.block.entity.BlockEntityType;
|
|
import net.minecraft.world.level.block.state.BlockState;
|
|
import net.minecraft.world.level.block.state.StateDefinition.Builder;
|
|
import net.minecraft.world.level.block.state.properties.EnumProperty;
|
|
import net.minecraft.world.phys.BlockHitResult;
|
|
import net.minecraft.world.phys.Vec3;
|
|
import net.minecraftforge.common.util.LazyOptional;
|
|
import net.minecraftforge.items.CapabilityItemHandler;
|
|
import net.minecraftforge.items.IItemHandler;
|
|
import net.minecraftforge.items.ItemHandlerHelper;
|
|
import net.minecraftforge.items.ItemStackHandler;
|
|
|
|
public class MechanicalCrafterBlock extends HorizontalKineticBlock
|
|
implements ITE<MechanicalCrafterTileEntity>, ICogWheel {
|
|
|
|
public static final EnumProperty<Pointing> POINTING = EnumProperty.create("pointing", Pointing.class);
|
|
|
|
public MechanicalCrafterBlock(Properties properties) {
|
|
super(properties);
|
|
registerDefaultState(defaultBlockState().setValue(POINTING, Pointing.UP));
|
|
}
|
|
|
|
@Override
|
|
protected void createBlockStateDefinition(Builder<Block, BlockState> builder) {
|
|
super.createBlockStateDefinition(builder.add(POINTING));
|
|
}
|
|
|
|
@Override
|
|
public Axis getRotationAxis(BlockState state) {
|
|
return state.getValue(HORIZONTAL_FACING)
|
|
.getAxis();
|
|
}
|
|
|
|
@Override
|
|
public BlockState getStateForPlacement(BlockPlaceContext context) {
|
|
Direction face = context.getClickedFace();
|
|
BlockPos placedOnPos = context.getClickedPos()
|
|
.relative(face.getOpposite());
|
|
BlockState blockState = context.getLevel()
|
|
.getBlockState(placedOnPos);
|
|
|
|
if ((blockState.getBlock() != this) || (context.getPlayer() != null && context.getPlayer()
|
|
.isShiftKeyDown())) {
|
|
BlockState stateForPlacement = super.getStateForPlacement(context);
|
|
Direction direction = stateForPlacement.getValue(HORIZONTAL_FACING);
|
|
if (direction != face)
|
|
stateForPlacement = stateForPlacement.setValue(POINTING, pointingFromFacing(face, direction));
|
|
return stateForPlacement;
|
|
}
|
|
|
|
Direction otherFacing = blockState.getValue(HORIZONTAL_FACING);
|
|
Pointing pointing = pointingFromFacing(face, otherFacing);
|
|
return defaultBlockState().setValue(HORIZONTAL_FACING, otherFacing)
|
|
.setValue(POINTING, pointing);
|
|
}
|
|
|
|
@Override
|
|
public void onRemove(BlockState state, Level worldIn, BlockPos pos, BlockState newState, boolean isMoving) {
|
|
if (state.getBlock() == newState.getBlock()) {
|
|
if (getTargetDirection(state) != getTargetDirection(newState)) {
|
|
MechanicalCrafterTileEntity crafter = CrafterHelper.getCrafter(worldIn, pos);
|
|
if (crafter != null)
|
|
crafter.blockChanged();
|
|
}
|
|
}
|
|
|
|
if (state.hasBlockEntity() && state.getBlock() != newState.getBlock()) {
|
|
MechanicalCrafterTileEntity crafter = CrafterHelper.getCrafter(worldIn, pos);
|
|
if (crafter != null) {
|
|
if (crafter.covered)
|
|
Block.popResource(worldIn, pos, AllItems.CRAFTER_SLOT_COVER.asStack());
|
|
if (!isMoving)
|
|
crafter.ejectWholeGrid();
|
|
}
|
|
|
|
for (Direction direction : Iterate.directions) {
|
|
if (direction.getAxis() == state.getValue(HORIZONTAL_FACING)
|
|
.getAxis())
|
|
continue;
|
|
|
|
BlockPos otherPos = pos.relative(direction);
|
|
ConnectedInput thisInput = CrafterHelper.getInput(worldIn, pos);
|
|
ConnectedInput otherInput = CrafterHelper.getInput(worldIn, otherPos);
|
|
|
|
if (thisInput == null || otherInput == null)
|
|
continue;
|
|
if (!pos.offset(thisInput.data.get(0))
|
|
.equals(otherPos.offset(otherInput.data.get(0))))
|
|
continue;
|
|
|
|
ConnectedInputHandler.toggleConnection(worldIn, pos, otherPos);
|
|
}
|
|
|
|
worldIn.removeBlockEntity(pos);
|
|
}
|
|
}
|
|
|
|
public static Pointing pointingFromFacing(Direction pointingFace, Direction blockFacing) {
|
|
boolean positive = blockFacing.getAxisDirection() == AxisDirection.POSITIVE;
|
|
|
|
Pointing pointing = pointingFace == Direction.DOWN ? Pointing.UP : Pointing.DOWN;
|
|
if (pointingFace == Direction.EAST)
|
|
pointing = positive ? Pointing.LEFT : Pointing.RIGHT;
|
|
if (pointingFace == Direction.WEST)
|
|
pointing = positive ? Pointing.RIGHT : Pointing.LEFT;
|
|
if (pointingFace == Direction.NORTH)
|
|
pointing = positive ? Pointing.LEFT : Pointing.RIGHT;
|
|
if (pointingFace == Direction.SOUTH)
|
|
pointing = positive ? Pointing.RIGHT : Pointing.LEFT;
|
|
return pointing;
|
|
}
|
|
|
|
@Override
|
|
public InteractionResult onWrenched(BlockState state, UseOnContext context) {
|
|
if (context.getClickedFace() == state.getValue(HORIZONTAL_FACING)) {
|
|
if (!context.getLevel().isClientSide)
|
|
KineticTileEntity.switchToBlockState(context.getLevel(), context.getClickedPos(),
|
|
state.cycle(POINTING));
|
|
return InteractionResult.SUCCESS;
|
|
}
|
|
|
|
return InteractionResult.PASS;
|
|
}
|
|
|
|
@Override
|
|
public InteractionResult use(BlockState state, Level worldIn, BlockPos pos, Player player, InteractionHand handIn,
|
|
BlockHitResult hit) {
|
|
BlockEntity te = worldIn.getBlockEntity(pos);
|
|
if (!(te instanceof MechanicalCrafterTileEntity crafter))
|
|
return InteractionResult.PASS;
|
|
|
|
ItemStack heldItem = player.getItemInHand(handIn);
|
|
|
|
if (AllBlocks.MECHANICAL_ARM.isIn(heldItem))
|
|
return InteractionResult.PASS;
|
|
|
|
boolean isHand = heldItem.isEmpty() && handIn == InteractionHand.MAIN_HAND;
|
|
boolean wrenched = AllItems.WRENCH.isIn(heldItem);
|
|
|
|
if (hit.getDirection() == state.getValue(HORIZONTAL_FACING)) {
|
|
|
|
if (crafter.phase != Phase.IDLE && !wrenched) {
|
|
crafter.ejectWholeGrid();
|
|
return InteractionResult.SUCCESS;
|
|
}
|
|
|
|
if (crafter.phase == Phase.IDLE && !isHand && !wrenched) {
|
|
if (worldIn.isClientSide)
|
|
return InteractionResult.SUCCESS;
|
|
|
|
if (AllItems.CRAFTER_SLOT_COVER.isIn(heldItem)) {
|
|
if (crafter.covered)
|
|
return InteractionResult.PASS;
|
|
if (!crafter.inventory.isEmpty())
|
|
return InteractionResult.PASS;
|
|
crafter.covered = true;
|
|
crafter.setChanged();
|
|
crafter.sendData();
|
|
if (!player.isCreative())
|
|
heldItem.shrink(1);
|
|
return InteractionResult.SUCCESS;
|
|
}
|
|
|
|
LazyOptional<IItemHandler> capability =
|
|
crafter.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY);
|
|
if (!capability.isPresent())
|
|
return InteractionResult.PASS;
|
|
ItemStack remainder =
|
|
ItemHandlerHelper.insertItem(capability.orElse(new ItemStackHandler()), heldItem.copy(), false);
|
|
if (remainder.getCount() != heldItem.getCount())
|
|
player.setItemInHand(handIn, remainder);
|
|
return InteractionResult.SUCCESS;
|
|
}
|
|
|
|
ItemStack inSlot = crafter.getInventory()
|
|
.getItem(0);
|
|
if (inSlot.isEmpty()) {
|
|
if (crafter.covered && !wrenched) {
|
|
if (worldIn.isClientSide)
|
|
return InteractionResult.SUCCESS;
|
|
crafter.covered = false;
|
|
crafter.setChanged();
|
|
crafter.sendData();
|
|
if (!player.isCreative())
|
|
player.getInventory()
|
|
.placeItemBackInInventory(AllItems.CRAFTER_SLOT_COVER.asStack());
|
|
return InteractionResult.SUCCESS;
|
|
}
|
|
return InteractionResult.PASS;
|
|
}
|
|
if (!isHand && !ItemHandlerHelper.canItemStacksStack(heldItem, inSlot))
|
|
return InteractionResult.PASS;
|
|
if (worldIn.isClientSide)
|
|
return InteractionResult.SUCCESS;
|
|
player.getInventory()
|
|
.placeItemBackInInventory(inSlot);
|
|
crafter.getInventory()
|
|
.setStackInSlot(0, ItemStack.EMPTY);
|
|
return InteractionResult.SUCCESS;
|
|
}
|
|
|
|
return InteractionResult.PASS;
|
|
}
|
|
|
|
@Override
|
|
public void neighborChanged(BlockState state, Level worldIn, BlockPos pos, Block blockIn, BlockPos fromPos,
|
|
boolean isMoving) {
|
|
InvManipulationBehaviour behaviour = TileEntityBehaviour.get(worldIn, pos, InvManipulationBehaviour.TYPE);
|
|
if (behaviour != null)
|
|
behaviour.onNeighborChanged(fromPos);
|
|
}
|
|
|
|
@Override
|
|
public float getParticleTargetRadius() {
|
|
return .85f;
|
|
}
|
|
|
|
@Override
|
|
public float getParticleInitialRadius() {
|
|
return .75f;
|
|
}
|
|
|
|
public static Direction getTargetDirection(BlockState state) {
|
|
if (!AllBlocks.MECHANICAL_CRAFTER.has(state))
|
|
return Direction.UP;
|
|
Direction facing = state.getValue(HORIZONTAL_FACING);
|
|
Pointing point = state.getValue(POINTING);
|
|
Vec3 targetVec = new Vec3(0, 1, 0);
|
|
targetVec = VecHelper.rotate(targetVec, -point.getXRotation(), Axis.Z);
|
|
targetVec = VecHelper.rotate(targetVec, AngleHelper.horizontalAngle(facing), Axis.Y);
|
|
return Direction.getNearest(targetVec.x, targetVec.y, targetVec.z);
|
|
}
|
|
|
|
public static boolean isValidTarget(Level world, BlockPos targetPos, BlockState crafterState) {
|
|
BlockState targetState = world.getBlockState(targetPos);
|
|
if (!world.isLoaded(targetPos))
|
|
return false;
|
|
if (!AllBlocks.MECHANICAL_CRAFTER.has(targetState))
|
|
return false;
|
|
if (crafterState.getValue(HORIZONTAL_FACING) != targetState.getValue(HORIZONTAL_FACING))
|
|
return false;
|
|
if (Math.abs(crafterState.getValue(POINTING)
|
|
.getXRotation()
|
|
- targetState.getValue(POINTING)
|
|
.getXRotation()) == 180)
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public Class<MechanicalCrafterTileEntity> getTileEntityClass() {
|
|
return MechanicalCrafterTileEntity.class;
|
|
}
|
|
|
|
@Override
|
|
public BlockEntityType<? extends MechanicalCrafterTileEntity> getTileEntityType() {
|
|
return AllTileEntities.MECHANICAL_CRAFTER.get();
|
|
}
|
|
|
|
}
|