Arm interaction point utilities for addons

This commit is contained in:
kotakotik22 2021-07-09 18:45:50 +02:00
parent 6eb54267f3
commit e5eca1ed36

View file

@ -1,16 +1,17 @@
package com.simibubi.create.content.logistics.block.mechanicalArm; package com.simibubi.create.content.logistics.block.mechanicalArm;
import java.util.HashMap;
import java.util.function.Supplier; import java.util.function.Supplier;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import org.apache.commons.lang3.mutable.MutableBoolean; import org.apache.commons.lang3.mutable.MutableBoolean;
import com.google.common.collect.ImmutableMap;
import com.jozufozu.flywheel.core.PartialModel; import com.jozufozu.flywheel.core.PartialModel;
import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.AllBlockPartials; import com.simibubi.create.AllBlockPartials;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.Create;
import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.base.KineticTileEntity;
import com.simibubi.create.content.contraptions.components.crafter.MechanicalCrafterBlock; import com.simibubi.create.content.contraptions.components.crafter.MechanicalCrafterBlock;
import com.simibubi.create.content.contraptions.components.crafter.MechanicalCrafterTileEntity; import com.simibubi.create.content.contraptions.components.crafter.MechanicalCrafterTileEntity;
@ -65,74 +66,80 @@ import net.minecraftforge.items.ItemHandlerHelper;
import net.minecraftforge.items.wrapper.InvWrapper; import net.minecraftforge.items.wrapper.InvWrapper;
public abstract class ArmInteractionPoint { public abstract class ArmInteractionPoint {
public enum Mode {
enum Mode {
DEPOSIT, TAKE DEPOSIT, TAKE
} }
BlockPos pos; protected BlockPos pos;
BlockState state; protected BlockState state;
Mode mode; protected Mode mode;
private LazyOptional<IItemHandler> cachedHandler; protected LazyOptional<IItemHandler> cachedHandler;
private ArmAngleTarget cachedAngles; protected ArmAngleTarget cachedAngles;
private static ImmutableMap<ArmInteractionPoint, Supplier<ArmInteractionPoint>> POINTS = protected static final HashMap<ArmInteractionPoint, Supplier<ArmInteractionPoint>> POINTS = new HashMap<>();
ImmutableMap.<ArmInteractionPoint, Supplier<ArmInteractionPoint>>builder()
.put(new Saw(), Saw::new) static {
.put(new Belt(), Belt::new) addPoint(new Saw(), Saw::new);
.put(new Depot(), Depot::new) addPoint(new Belt(), Belt::new);
.put(new Chute(), Chute::new) addPoint(new Depot(), Depot::new);
.put(new Basin(), Basin::new) addPoint(new Chute(), Chute::new);
.put(new Funnel(), Funnel::new) addPoint(new Basin(), Basin::new);
.put(new Jukebox(), Jukebox::new) addPoint(new Funnel(), Funnel::new);
.put(new Crafter(), Crafter::new) addPoint(new Jukebox(), Jukebox::new);
.put(new Deployer(), Deployer::new) addPoint(new Crafter(), Crafter::new);
.put(new Composter(), Composter::new) addPoint(new Deployer(), Deployer::new);
.put(new Millstone(), Millstone::new) addPoint(new Composter(), Composter::new);
.put(new BlazeBurner(), BlazeBurner::new) addPoint(new Millstone(), Millstone::new);
.put(new CrushingWheels(), CrushingWheels::new) addPoint(new BlazeBurner(), BlazeBurner::new);
.build(); addPoint(new CrushingWheels(), CrushingWheels::new);
}
public static void addPoint(ArmInteractionPoint instance, Supplier<ArmInteractionPoint> factory) {
if (POINTS.containsKey(instance))
Create.LOGGER.warn("Point for " + instance.getClass().getSimpleName() + " was overridden");
POINTS.put(instance, factory);
}
public ArmInteractionPoint() { public ArmInteractionPoint() {
cachedHandler = LazyOptional.empty(); cachedHandler = LazyOptional.empty();
} }
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
void transformFlag(MatrixStack stack) {} protected void transformFlag(MatrixStack stack) {}
PartialModel getFlagType() { protected PartialModel getFlagType() {
return mode == Mode.TAKE ? AllBlockPartials.FLAG_LONG_OUT : AllBlockPartials.FLAG_LONG_IN; return mode == Mode.TAKE ? AllBlockPartials.FLAG_LONG_OUT : AllBlockPartials.FLAG_LONG_IN;
} }
void cycleMode() { protected void cycleMode() {
mode = mode == Mode.DEPOSIT ? Mode.TAKE : Mode.DEPOSIT; mode = mode == Mode.DEPOSIT ? Mode.TAKE : Mode.DEPOSIT;
} }
Vector3d getInteractionPositionVector() { protected Vector3d getInteractionPositionVector() {
return VecHelper.getCenterOf(pos); return VecHelper.getCenterOf(pos);
} }
Direction getInteractionDirection() { protected Direction getInteractionDirection() {
return Direction.DOWN; return Direction.DOWN;
} }
boolean isStillValid(IBlockReader reader) { protected boolean isStillValid(IBlockReader reader) {
return isValid(reader, pos, reader.getBlockState(pos)); return isValid(reader, pos, reader.getBlockState(pos));
} }
void keepAlive(IWorld world) {} protected void keepAlive(IWorld world) {}
abstract boolean isValid(IBlockReader reader, BlockPos pos, BlockState state); protected abstract boolean isValid(IBlockReader reader, BlockPos pos, BlockState state);
static boolean isInteractable(IBlockReader reader, BlockPos pos, BlockState state) { protected static boolean isInteractable(IBlockReader reader, BlockPos pos, BlockState state) {
for (ArmInteractionPoint armInteractionPoint : POINTS.keySet()) for (ArmInteractionPoint armInteractionPoint : POINTS.keySet())
if (armInteractionPoint.isValid(reader, pos, state)) if (armInteractionPoint.isValid(reader, pos, state))
return true; return true;
return false; return false;
} }
ArmAngleTarget getTargetAngles(BlockPos armPos, boolean ceiling) { protected ArmAngleTarget getTargetAngles(BlockPos armPos, boolean ceiling) {
if (cachedAngles == null) if (cachedAngles == null)
cachedAngles = cachedAngles =
new ArmAngleTarget(armPos, getInteractionPositionVector(), getInteractionDirection(), ceiling); new ArmAngleTarget(armPos, getInteractionPositionVector(), getInteractionDirection(), ceiling);
@ -141,7 +148,7 @@ public abstract class ArmInteractionPoint {
} }
@Nullable @Nullable
IItemHandler getHandler(World world) { protected IItemHandler getHandler(World world) {
if (!cachedHandler.isPresent()) { if (!cachedHandler.isPresent()) {
TileEntity te = world.getTileEntity(pos); TileEntity te = world.getTileEntity(pos);
if (te == null) if (te == null)
@ -151,25 +158,25 @@ public abstract class ArmInteractionPoint {
return cachedHandler.orElse(null); return cachedHandler.orElse(null);
} }
ItemStack insert(World world, ItemStack stack, boolean simulate) { protected ItemStack insert(World world, ItemStack stack, boolean simulate) {
IItemHandler handler = getHandler(world); IItemHandler handler = getHandler(world);
if (handler == null) if (handler == null)
return stack; return stack;
return ItemHandlerHelper.insertItem(handler, stack, simulate); return ItemHandlerHelper.insertItem(handler, stack, simulate);
} }
ItemStack extract(World world, int slot, int amount, boolean simulate) { protected ItemStack extract(World world, int slot, int amount, boolean simulate) {
IItemHandler handler = getHandler(world); IItemHandler handler = getHandler(world);
if (handler == null) if (handler == null)
return ItemStack.EMPTY; return ItemStack.EMPTY;
return handler.extractItem(slot, amount, simulate); return handler.extractItem(slot, amount, simulate);
} }
ItemStack extract(World world, int slot, boolean simulate) { protected ItemStack extract(World world, int slot, boolean simulate) {
return extract(world, slot, 64, simulate); return extract(world, slot, 64, simulate);
} }
int getSlotCount(World world) { protected int getSlotCount(World world) {
IItemHandler handler = getHandler(world); IItemHandler handler = getHandler(world);
if (handler == null) if (handler == null)
return 0; return 0;
@ -177,7 +184,7 @@ public abstract class ArmInteractionPoint {
} }
@Nullable @Nullable
static ArmInteractionPoint createAt(IBlockReader world, BlockPos pos) { protected static ArmInteractionPoint createAt(IBlockReader world, BlockPos pos) {
BlockState state = world.getBlockState(pos); BlockState state = world.getBlockState(pos);
ArmInteractionPoint point = null; ArmInteractionPoint point = null;
@ -195,14 +202,14 @@ public abstract class ArmInteractionPoint {
return point; return point;
} }
CompoundNBT serialize(BlockPos anchor) { protected CompoundNBT serialize(BlockPos anchor) {
CompoundNBT nbt = new CompoundNBT(); CompoundNBT nbt = new CompoundNBT();
nbt.put("Pos", NBTUtil.writeBlockPos(pos.subtract(anchor))); nbt.put("Pos", NBTUtil.writeBlockPos(pos.subtract(anchor)));
NBTHelper.writeEnum(nbt, "Mode", mode); NBTHelper.writeEnum(nbt, "Mode", mode);
return nbt; return nbt;
} }
static ArmInteractionPoint deserialize(IBlockReader world, BlockPos anchor, CompoundNBT nbt) { protected static ArmInteractionPoint deserialize(IBlockReader world, BlockPos anchor, CompoundNBT nbt) {
BlockPos pos = NBTUtil.readBlockPos(nbt.getCompound("Pos")); BlockPos pos = NBTUtil.readBlockPos(nbt.getCompound("Pos"));
ArmInteractionPoint interactionPoint = createAt(world, pos.add(anchor)); ArmInteractionPoint interactionPoint = createAt(world, pos.add(anchor));
if (interactionPoint == null) if (interactionPoint == null)
@ -211,112 +218,112 @@ public abstract class ArmInteractionPoint {
return interactionPoint; return interactionPoint;
} }
static abstract class TopFaceArmInteractionPoint extends ArmInteractionPoint { public static abstract class TopFaceArmInteractionPoint extends ArmInteractionPoint {
@Override @Override
Vector3d getInteractionPositionVector() { protected Vector3d getInteractionPositionVector() {
return Vector3d.of(pos).add(.5f, 1, .5f); return Vector3d.of(pos).add(.5f, 1, .5f);
} }
} }
static class Depot extends ArmInteractionPoint { public static class Depot extends ArmInteractionPoint {
@Override @Override
Vector3d getInteractionPositionVector() { protected Vector3d getInteractionPositionVector() {
return Vector3d.of(pos).add(.5f, 14 / 16f, .5f); return Vector3d.of(pos).add(.5f, 14 / 16f, .5f);
} }
@Override @Override
boolean isValid(IBlockReader reader, BlockPos pos, BlockState state) { protected boolean isValid(IBlockReader reader, BlockPos pos, BlockState state) {
return AllBlocks.DEPOT.has(state) || AllBlocks.WEIGHTED_EJECTOR.has(state); return AllBlocks.DEPOT.has(state) || AllBlocks.WEIGHTED_EJECTOR.has(state);
} }
} }
static class Saw extends Depot { public static class Saw extends Depot {
@Override @Override
boolean isValid(IBlockReader reader, BlockPos pos, BlockState state) { protected boolean isValid(IBlockReader reader, BlockPos pos, BlockState state) {
return AllBlocks.MECHANICAL_SAW.has(state) && state.get(SawBlock.FACING) == Direction.UP return AllBlocks.MECHANICAL_SAW.has(state) && state.get(SawBlock.FACING) == Direction.UP
&& ((KineticTileEntity) reader.getTileEntity(pos)).getSpeed() != 0; && ((KineticTileEntity) reader.getTileEntity(pos)).getSpeed() != 0;
} }
} }
static class Millstone extends ArmInteractionPoint { public static class Millstone extends ArmInteractionPoint {
@Override @Override
boolean isValid(IBlockReader reader, BlockPos pos, BlockState state) { protected boolean isValid(IBlockReader reader, BlockPos pos, BlockState state) {
return AllBlocks.MILLSTONE.has(state); return AllBlocks.MILLSTONE.has(state);
} }
} }
static class CrushingWheels extends TopFaceArmInteractionPoint { public static class CrushingWheels extends TopFaceArmInteractionPoint {
@Override @Override
boolean isValid(IBlockReader reader, BlockPos pos, BlockState state) { protected boolean isValid(IBlockReader reader, BlockPos pos, BlockState state) {
return AllBlocks.CRUSHING_WHEEL_CONTROLLER.has(state); return AllBlocks.CRUSHING_WHEEL_CONTROLLER.has(state);
} }
} }
static class Composter extends TopFaceArmInteractionPoint { public static class Composter extends TopFaceArmInteractionPoint {
@Override @Override
Vector3d getInteractionPositionVector() { protected Vector3d getInteractionPositionVector() {
return Vector3d.of(pos).add(.5f, 13 / 16f, .5f); return Vector3d.of(pos).add(.5f, 13 / 16f, .5f);
} }
@Override @Override
boolean isValid(IBlockReader reader, BlockPos pos, BlockState state) { protected boolean isValid(IBlockReader reader, BlockPos pos, BlockState state) {
return Blocks.COMPOSTER.equals(state.getBlock()); return Blocks.COMPOSTER.equals(state.getBlock());
} }
@Nullable @Nullable
@Override @Override
IItemHandler getHandler(World world) { protected IItemHandler getHandler(World world) {
return new InvWrapper( return new InvWrapper(
((ComposterBlock) Blocks.COMPOSTER).createInventory(world.getBlockState(pos), world, pos)); ((ComposterBlock) Blocks.COMPOSTER).createInventory(world.getBlockState(pos), world, pos));
} }
} }
static class Deployer extends ArmInteractionPoint { public static class Deployer extends ArmInteractionPoint {
@Override @Override
boolean isValid(IBlockReader reader, BlockPos pos, BlockState state) { protected boolean isValid(IBlockReader reader, BlockPos pos, BlockState state) {
return AllBlocks.DEPLOYER.has(state); return AllBlocks.DEPLOYER.has(state);
} }
@Override @Override
Direction getInteractionDirection() { protected Direction getInteractionDirection() {
return state.get(DeployerBlock.FACING) return state.get(DeployerBlock.FACING)
.getOpposite(); .getOpposite();
} }
@Override @Override
Vector3d getInteractionPositionVector() { protected Vector3d getInteractionPositionVector() {
return super.getInteractionPositionVector() return super.getInteractionPositionVector()
.add(Vector3d.of(getInteractionDirection().getDirectionVec()).scale(.65f)); .add(Vector3d.of(getInteractionDirection().getDirectionVec()).scale(.65f));
} }
} }
static class BlazeBurner extends ArmInteractionPoint { public static class BlazeBurner extends ArmInteractionPoint {
@Override @Override
boolean isValid(IBlockReader reader, BlockPos pos, BlockState state) { protected boolean isValid(IBlockReader reader, BlockPos pos, BlockState state) {
return AllBlocks.BLAZE_BURNER.has(state); return AllBlocks.BLAZE_BURNER.has(state);
} }
@Override @Override
ItemStack extract(World world, int slot, int amount, boolean simulate) { protected ItemStack extract(World world, int slot, int amount, boolean simulate) {
return ItemStack.EMPTY; return ItemStack.EMPTY;
} }
@Override @Override
ItemStack insert(World world, ItemStack stack, boolean simulate) { protected ItemStack insert(World world, ItemStack stack, boolean simulate) {
ItemStack input = stack.copy(); ItemStack input = stack.copy();
if (!BlazeBurnerBlock.tryInsert(state, world, pos, input, false, true) if (!BlazeBurnerBlock.tryInsert(state, world, pos, input, false, true)
.getResult() .getResult()
@ -330,25 +337,25 @@ public abstract class ArmInteractionPoint {
} }
@Override @Override
void cycleMode() {} protected void cycleMode() {}
} }
static class Crafter extends ArmInteractionPoint { public static class Crafter extends ArmInteractionPoint {
@Override @Override
boolean isValid(IBlockReader reader, BlockPos pos, BlockState state) { protected boolean isValid(IBlockReader reader, BlockPos pos, BlockState state) {
return AllBlocks.MECHANICAL_CRAFTER.has(state); return AllBlocks.MECHANICAL_CRAFTER.has(state);
} }
@Override @Override
Direction getInteractionDirection() { protected Direction getInteractionDirection() {
return state.get(MechanicalCrafterBlock.HORIZONTAL_FACING) return state.get(MechanicalCrafterBlock.HORIZONTAL_FACING)
.getOpposite(); .getOpposite();
} }
@Override @Override
ItemStack extract(World world, int slot, int amount, boolean simulate) { protected ItemStack extract(World world, int slot, int amount, boolean simulate) {
TileEntity te = world.getTileEntity(pos); TileEntity te = world.getTileEntity(pos);
if (!(te instanceof MechanicalCrafterTileEntity)) if (!(te instanceof MechanicalCrafterTileEntity))
return ItemStack.EMPTY; return ItemStack.EMPTY;
@ -361,36 +368,36 @@ public abstract class ArmInteractionPoint {
} }
@Override @Override
Vector3d getInteractionPositionVector() { protected Vector3d getInteractionPositionVector() {
return super.getInteractionPositionVector() return super.getInteractionPositionVector()
.add(Vector3d.of(getInteractionDirection().getDirectionVec()).scale(.5f)); .add(Vector3d.of(getInteractionDirection().getDirectionVec()).scale(.5f));
} }
} }
static class Basin extends ArmInteractionPoint { public static class Basin extends ArmInteractionPoint {
@Override @Override
boolean isValid(IBlockReader reader, BlockPos pos, BlockState state) { protected boolean isValid(IBlockReader reader, BlockPos pos, BlockState state) {
return AllBlocks.BASIN.has(state); return AllBlocks.BASIN.has(state);
} }
} }
static class Jukebox extends TopFaceArmInteractionPoint { public static class Jukebox extends TopFaceArmInteractionPoint {
@Override @Override
boolean isValid(IBlockReader reader, BlockPos pos, BlockState state) { protected boolean isValid(IBlockReader reader, BlockPos pos, BlockState state) {
return state.getBlock() instanceof JukeboxBlock; return state.getBlock() instanceof JukeboxBlock;
} }
@Override @Override
int getSlotCount(World world) { protected int getSlotCount(World world) {
return 1; return 1;
} }
@Override @Override
ItemStack insert(World world, ItemStack stack, boolean simulate) { protected ItemStack insert(World world, ItemStack stack, boolean simulate) {
TileEntity tileEntity = world.getTileEntity(pos); TileEntity tileEntity = world.getTileEntity(pos);
if (!(tileEntity instanceof JukeboxTileEntity)) if (!(tileEntity instanceof JukeboxTileEntity))
return stack; return stack;
@ -414,7 +421,7 @@ public abstract class ArmInteractionPoint {
} }
@Override @Override
ItemStack extract(World world, int slot, int amount, boolean simulate) { protected ItemStack extract(World world, int slot, int amount, boolean simulate) {
TileEntity tileEntity = world.getTileEntity(pos); TileEntity tileEntity = world.getTileEntity(pos);
if (!(tileEntity instanceof JukeboxTileEntity)) if (!(tileEntity instanceof JukeboxTileEntity))
return ItemStack.EMPTY; return ItemStack.EMPTY;
@ -434,16 +441,16 @@ public abstract class ArmInteractionPoint {
} }
static class Belt extends Depot { public static class Belt extends Depot {
@Override @Override
boolean isValid(IBlockReader reader, BlockPos pos, BlockState state) { protected boolean isValid(IBlockReader reader, BlockPos pos, BlockState state) {
return AllBlocks.BELT.has(state) && !(reader.getBlockState(pos.up()) return AllBlocks.BELT.has(state) && !(reader.getBlockState(pos.up())
.getBlock() instanceof BeltTunnelBlock); .getBlock() instanceof BeltTunnelBlock);
} }
@Override @Override
void keepAlive(IWorld world) { protected void keepAlive(IWorld world) {
super.keepAlive(world); super.keepAlive(world);
BeltTileEntity beltTE = BeltHelper.getSegmentTE(world, pos); BeltTileEntity beltTE = BeltHelper.getSegmentTE(world, pos);
if (beltTE == null) if (beltTE == null)
@ -464,41 +471,41 @@ public abstract class ArmInteractionPoint {
} }
static class Chute extends TopFaceArmInteractionPoint { public static class Chute extends TopFaceArmInteractionPoint {
@Override @Override
boolean isValid(IBlockReader reader, BlockPos pos, BlockState state) { protected boolean isValid(IBlockReader reader, BlockPos pos, BlockState state) {
return AbstractChuteBlock.isChute(state); return AbstractChuteBlock.isChute(state);
} }
} }
static class Funnel extends ArmInteractionPoint { public static class Funnel extends ArmInteractionPoint {
@Override @Override
Vector3d getInteractionPositionVector() { protected Vector3d getInteractionPositionVector() {
return VecHelper.getCenterOf(pos) return VecHelper.getCenterOf(pos)
.add(Vector3d.of(FunnelBlock.getFunnelFacing(state) .add(Vector3d.of(FunnelBlock.getFunnelFacing(state)
.getDirectionVec()).scale(-.15f)); .getDirectionVec()).scale(-.15f));
} }
@Override @Override
int getSlotCount(World world) { protected int getSlotCount(World world) {
return 0; return 0;
} }
@Override @Override
ItemStack extract(World world, int slot, int amount, boolean simulate) { protected ItemStack extract(World world, int slot, int amount, boolean simulate) {
return ItemStack.EMPTY; return ItemStack.EMPTY;
} }
@Override @Override
Direction getInteractionDirection() { protected Direction getInteractionDirection() {
return FunnelBlock.getFunnelFacing(state) return FunnelBlock.getFunnelFacing(state)
.getOpposite(); .getOpposite();
} }
@Override @Override
ItemStack insert(World world, ItemStack stack, boolean simulate) { protected ItemStack insert(World world, ItemStack stack, boolean simulate) {
FilteringBehaviour filtering = TileEntityBehaviour.get(world, pos, FilteringBehaviour.TYPE); FilteringBehaviour filtering = TileEntityBehaviour.get(world, pos, FilteringBehaviour.TYPE);
InvManipulationBehaviour inserter = TileEntityBehaviour.get(world, pos, InvManipulationBehaviour.TYPE); InvManipulationBehaviour inserter = TileEntityBehaviour.get(world, pos, InvManipulationBehaviour.TYPE);
BlockState state = world.getBlockState(pos); BlockState state = world.getBlockState(pos);
@ -524,15 +531,14 @@ public abstract class ArmInteractionPoint {
} }
@Override @Override
boolean isValid(IBlockReader reader, BlockPos pos, BlockState state) { protected boolean isValid(IBlockReader reader, BlockPos pos, BlockState state) {
return state.getBlock() instanceof AbstractFunnelBlock return state.getBlock() instanceof AbstractFunnelBlock
&& !(state.contains(FunnelBlock.EXTRACTING) && state.get(FunnelBlock.EXTRACTING)) && !(state.contains(FunnelBlock.EXTRACTING) && state.get(FunnelBlock.EXTRACTING))
&& !(state.contains(BeltFunnelBlock.SHAPE) && state.get(BeltFunnelBlock.SHAPE) == Shape.PUSHING); && !(state.contains(BeltFunnelBlock.SHAPE) && state.get(BeltFunnelBlock.SHAPE) == Shape.PUSHING);
} }
@Override @Override
void cycleMode() {} protected void cycleMode() {}
} }
} }