mirror of
https://github.com/Creators-of-Create/Create.git
synced 2024-12-28 16:06:48 +01:00
Portable Storage Interface remaster
- Implemented new PSI models by Kryppers - PSIs are now used in pairs like contacts - PSIs now act as an inventory proxy of the attached contraption - Comparators can detect when two PSIs are interfacing - Contraptions will continue moving after a second of inactivity
This commit is contained in:
parent
2d6d360da4
commit
27b05bc43e
8 changed files with 362 additions and 145 deletions
|
@ -4,6 +4,7 @@ import javax.annotation.ParametersAreNonnullByDefault;
|
||||||
|
|
||||||
import com.simibubi.create.AllShapes;
|
import com.simibubi.create.AllShapes;
|
||||||
import com.simibubi.create.AllTileEntities;
|
import com.simibubi.create.AllTileEntities;
|
||||||
|
import com.simibubi.create.foundation.block.ITE;
|
||||||
import com.simibubi.create.foundation.block.ProperDirectionalBlock;
|
import com.simibubi.create.foundation.block.ProperDirectionalBlock;
|
||||||
|
|
||||||
import mcp.MethodsReturnNonnullByDefault;
|
import mcp.MethodsReturnNonnullByDefault;
|
||||||
|
@ -14,20 +15,22 @@ import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.util.math.shapes.ISelectionContext;
|
import net.minecraft.util.math.shapes.ISelectionContext;
|
||||||
import net.minecraft.util.math.shapes.VoxelShape;
|
import net.minecraft.util.math.shapes.VoxelShape;
|
||||||
import net.minecraft.world.IBlockReader;
|
import net.minecraft.world.IBlockReader;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
@ParametersAreNonnullByDefault
|
@ParametersAreNonnullByDefault
|
||||||
@MethodsReturnNonnullByDefault
|
@MethodsReturnNonnullByDefault
|
||||||
public class PortableStorageInterfaceBlock extends ProperDirectionalBlock {
|
public class PortableStorageInterfaceBlock extends ProperDirectionalBlock
|
||||||
|
implements ITE<PortableStorageInterfaceTileEntity> {
|
||||||
|
|
||||||
public PortableStorageInterfaceBlock(Properties p_i48415_1_) {
|
public PortableStorageInterfaceBlock(Properties p_i48415_1_) {
|
||||||
super(p_i48415_1_);
|
super(p_i48415_1_);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasTileEntity(BlockState state) {
|
public boolean hasTileEntity(BlockState state) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TileEntity createTileEntity(BlockState state, IBlockReader world) {
|
public TileEntity createTileEntity(BlockState state, IBlockReader world) {
|
||||||
return AllTileEntities.PORTABLE_STORAGE_INTERFACE.create();
|
return AllTileEntities.PORTABLE_STORAGE_INTERFACE.create();
|
||||||
|
@ -44,4 +47,23 @@ public class PortableStorageInterfaceBlock extends ProperDirectionalBlock {
|
||||||
return AllShapes.PORTABLE_STORAGE_INTERFACE.get(state.get(FACING));
|
return AllShapes.PORTABLE_STORAGE_INTERFACE.get(state.get(FACING));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasComparatorInputOverride(BlockState state) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getComparatorInputOverride(BlockState blockState, World worldIn, BlockPos pos) {
|
||||||
|
try {
|
||||||
|
return getTileEntity(worldIn, pos).isConnected() ? 15 : 0;
|
||||||
|
} catch (TileEntityException e) {
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<PortableStorageInterfaceTileEntity> getTileEntityClass() {
|
||||||
|
return PortableStorageInterfaceTileEntity.class;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,133 +1,104 @@
|
||||||
package com.simibubi.create.content.contraptions.components.actors;
|
package com.simibubi.create.content.contraptions.components.actors;
|
||||||
|
|
||||||
import java.util.function.Predicate;
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||||
import com.simibubi.create.AllBlocks;
|
import com.simibubi.create.AllBlocks;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour;
|
import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext;
|
import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext;
|
||||||
import com.simibubi.create.foundation.config.AllConfigs;
|
|
||||||
import com.simibubi.create.foundation.item.ItemHelper;
|
|
||||||
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
|
|
||||||
import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour;
|
|
||||||
import com.simibubi.create.foundation.tileEntity.behaviour.inventory.SingleTargetAutoExtractingBehaviour;
|
|
||||||
import com.simibubi.create.foundation.utility.VecHelper;
|
import com.simibubi.create.foundation.utility.VecHelper;
|
||||||
|
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.client.renderer.IRenderTypeBuffer;
|
||||||
import net.minecraft.nbt.NBTUtil;
|
import net.minecraft.nbt.NBTUtil;
|
||||||
import net.minecraft.tileentity.TileEntity;
|
import net.minecraft.tileentity.TileEntity;
|
||||||
import net.minecraft.util.Direction;
|
import net.minecraft.util.Direction;
|
||||||
import net.minecraft.util.Direction.Axis;
|
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.util.math.Vec3d;
|
import net.minecraft.util.math.Vec3d;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
import net.minecraftforge.items.IItemHandlerModifiable;
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
import net.minecraftforge.items.ItemHandlerHelper;
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
|
|
||||||
public class PortableStorageInterfaceMovement extends MovementBehaviour {
|
public class PortableStorageInterfaceMovement extends MovementBehaviour {
|
||||||
|
|
||||||
private static final String _exporting_ = "Exporting";
|
static final String _workingPos_ = "WorkingPos";
|
||||||
private static final String _delay_ = "Delay";
|
static final String _clientPrevPos_ = "ClientPrevPos";
|
||||||
private static final String _workingPos_ = "WorkingPos";
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Vec3d getActiveAreaOffset(MovementContext context) {
|
public Vec3d getActiveAreaOffset(MovementContext context) {
|
||||||
return new Vec3d(context.state.get(PortableStorageInterfaceBlock.FACING)
|
return new Vec3d(context.state.get(PortableStorageInterfaceBlock.FACING)
|
||||||
.getDirectionVec()).scale(.85f);
|
.getDirectionVec()).scale(1.85f);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@OnlyIn(Dist.CLIENT)
|
||||||
|
public void renderInContraption(MovementContext context, MatrixStack ms, MatrixStack msLocal,
|
||||||
|
IRenderTypeBuffer buffer) {
|
||||||
|
PortableStorageInterfaceRenderer.renderInContraption(context, ms, msLocal, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitNewPosition(MovementContext context, BlockPos pos) {
|
public void visitNewPosition(MovementContext context, BlockPos pos) {
|
||||||
Direction currentFacing = getCurrentFacing(context);
|
context.data.remove(_workingPos_);
|
||||||
PortableStorageInterfaceTileEntity psi =
|
if (findInterface(context, pos))
|
||||||
getValidStationaryInterface(context.world, pos, currentFacing.getAxis());
|
context.stall = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean findInterface(MovementContext context, BlockPos pos) {
|
||||||
|
Optional<Direction> currentFacingIfValid = getCurrentFacingIfValid(context);
|
||||||
|
if (!currentFacingIfValid.isPresent())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Direction currentFacing = currentFacingIfValid.get();
|
||||||
|
PortableStorageInterfaceTileEntity psi = findStationaryInterface(context.world, pos, currentFacing);
|
||||||
if (psi == null)
|
if (psi == null)
|
||||||
return;
|
return false;
|
||||||
if (psi.isTransferring())
|
|
||||||
return;
|
if (psi.isTransferring() && !context.world.isRemote)
|
||||||
context.data.put(_workingPos_, NBTUtil.writeBlockPos(pos));
|
return false;
|
||||||
context.stall = true;
|
context.data.put(_workingPos_, NBTUtil.writeBlockPos(psi.getPos()));
|
||||||
|
if (!context.world.isRemote) {
|
||||||
|
Vec3d diff = VecHelper.getCenterOf(psi.getPos())
|
||||||
|
.subtract(context.position);
|
||||||
|
diff = VecHelper.project(diff, new Vec3d(currentFacing.getDirectionVec()));
|
||||||
|
float distance = (float) (diff.length() + 1.85f - 1);
|
||||||
|
psi.startTransferringTo(context.contraption, distance);
|
||||||
|
} else {
|
||||||
|
context.data.put(_clientPrevPos_, NBTUtil.writeBlockPos(pos));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void tick(MovementContext context) {
|
public void tick(MovementContext context) {
|
||||||
if (!context.data.contains(_workingPos_))
|
if (context.world.isRemote) {
|
||||||
|
boolean stalled = context.contraption.stalled;
|
||||||
|
if (stalled && !context.data.contains(_workingPos_)) {
|
||||||
|
BlockPos pos = new BlockPos(context.position);
|
||||||
|
if (!context.data.contains(_clientPrevPos_)
|
||||||
|
|| !NBTUtil.readBlockPos(context.data.getCompound(_clientPrevPos_))
|
||||||
|
.equals(pos))
|
||||||
|
findInterface(context, pos);
|
||||||
|
}
|
||||||
|
if (!stalled)
|
||||||
|
reset(context);
|
||||||
return;
|
return;
|
||||||
if (context.world.isRemote)
|
}
|
||||||
|
|
||||||
|
if (!context.data.contains(_workingPos_))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
BlockPos pos = NBTUtil.readBlockPos(context.data.getCompound(_workingPos_));
|
BlockPos pos = NBTUtil.readBlockPos(context.data.getCompound(_workingPos_));
|
||||||
|
Optional<Direction> currentFacingIfValid = getCurrentFacingIfValid(context);
|
||||||
|
if (!currentFacingIfValid.isPresent())
|
||||||
|
return;
|
||||||
|
|
||||||
PortableStorageInterfaceTileEntity stationaryInterface =
|
PortableStorageInterfaceTileEntity stationaryInterface =
|
||||||
getValidStationaryInterface(context.world, pos, getCurrentFacing(context).getAxis());
|
getStationaryInterfaceAt(context.world, pos, currentFacingIfValid.get());
|
||||||
if (stationaryInterface == null) {
|
if (stationaryInterface == null || !stationaryInterface.isTransferring()) {
|
||||||
reset(context);
|
reset(context);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int nextExtract = context.data.getInt(_delay_);
|
|
||||||
if (nextExtract > 0) {
|
|
||||||
nextExtract--;
|
|
||||||
context.data.putInt(_delay_, nextExtract);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean extract = context.data.getBoolean(_exporting_);
|
|
||||||
boolean success = false;
|
|
||||||
IItemHandlerModifiable inv = context.contraption.inventory;
|
|
||||||
SingleTargetAutoExtractingBehaviour extracting =
|
|
||||||
TileEntityBehaviour.get(stationaryInterface, SingleTargetAutoExtractingBehaviour.TYPE);
|
|
||||||
FilteringBehaviour filtering = TileEntityBehaviour.get(stationaryInterface, FilteringBehaviour.TYPE);
|
|
||||||
|
|
||||||
if (extract) {
|
|
||||||
// Export from Contraption
|
|
||||||
Predicate<ItemStack> test = extracting.getFilterTest();
|
|
||||||
int exactAmount = extracting.getAmountFromFilter();
|
|
||||||
ItemStack itemExtracted = ItemStack.EMPTY;
|
|
||||||
if (exactAmount != -1)
|
|
||||||
itemExtracted = ItemHelper.extract(inv, test, exactAmount, false);
|
|
||||||
else
|
|
||||||
itemExtracted = ItemHelper.extract(inv, test, stationaryInterface::amountToExtract, false);
|
|
||||||
|
|
||||||
if (!itemExtracted.isEmpty()) {
|
|
||||||
stationaryInterface.onExtract(itemExtracted);
|
|
||||||
success = exactAmount == -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// Import to Contraption
|
|
||||||
if (extracting != null) {
|
|
||||||
extracting.setSynchronized(false);
|
|
||||||
extracting.withAdditionalFilter(stack -> {
|
|
||||||
if (filtering.anyAmount())
|
|
||||||
return true;
|
|
||||||
return ItemHandlerHelper.insertItemStacked(inv, stack, true)
|
|
||||||
.isEmpty();
|
|
||||||
});
|
|
||||||
|
|
||||||
extracting.withAmountThreshold(stack -> {
|
|
||||||
ItemStack tester = stack.copy();
|
|
||||||
tester.setCount(tester.getMaxStackSize());
|
|
||||||
return stack.getCount() - ItemHandlerHelper.insertItemStacked(inv, stack, true)
|
|
||||||
.getCount();
|
|
||||||
});
|
|
||||||
|
|
||||||
extracting.setCallback(stack -> {
|
|
||||||
ItemHandlerHelper.insertItemStacked(inv, stack, false);
|
|
||||||
});
|
|
||||||
|
|
||||||
success = extracting.extract() && filtering.anyAmount();
|
|
||||||
extracting.setSynchronized(true);
|
|
||||||
stationaryInterface.applyFilteringCallbacks();
|
|
||||||
extracting.setCallback(stationaryInterface::onExtract);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!success) {
|
|
||||||
reset(context);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
context.data.putInt(_delay_, AllConfigs.SERVER.logistics.defaultExtractionTimer.get());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -136,32 +107,42 @@ public class PortableStorageInterfaceMovement extends MovementBehaviour {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void reset(MovementContext context) {
|
public void reset(MovementContext context) {
|
||||||
|
context.data.remove(_clientPrevPos_);
|
||||||
context.data.remove(_workingPos_);
|
context.data.remove(_workingPos_);
|
||||||
context.data.remove(_delay_);
|
|
||||||
context.data.remove(_exporting_);
|
|
||||||
context.stall = false;
|
context.stall = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private PortableStorageInterfaceTileEntity getValidStationaryInterface(World world, BlockPos pos, Axis validAxis) {
|
private PortableStorageInterfaceTileEntity findStationaryInterface(World world, BlockPos pos, Direction facing) {
|
||||||
|
for (int i = 0; i < 2; i++) {
|
||||||
|
PortableStorageInterfaceTileEntity interfaceAt =
|
||||||
|
getStationaryInterfaceAt(world, pos.offset(facing, i), facing);
|
||||||
|
if (interfaceAt == null)
|
||||||
|
continue;
|
||||||
|
return interfaceAt;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private PortableStorageInterfaceTileEntity getStationaryInterfaceAt(World world, BlockPos pos, Direction facing) {
|
||||||
TileEntity te = world.getTileEntity(pos);
|
TileEntity te = world.getTileEntity(pos);
|
||||||
if (!(te instanceof PortableStorageInterfaceTileEntity))
|
if (!(te instanceof PortableStorageInterfaceTileEntity))
|
||||||
return null;
|
return null;
|
||||||
BlockState blockState = world.getBlockState(pos);
|
BlockState blockState = world.getBlockState(pos);
|
||||||
if (!AllBlocks.PORTABLE_STORAGE_INTERFACE.has(blockState))
|
if (!AllBlocks.PORTABLE_STORAGE_INTERFACE.has(blockState))
|
||||||
return null;
|
return null;
|
||||||
if (blockState.get(PortableStorageInterfaceBlock.FACING)
|
if (blockState.get(PortableStorageInterfaceBlock.FACING) != facing.getOpposite())
|
||||||
.getAxis() != validAxis)
|
|
||||||
return null;
|
|
||||||
if (world.isBlockPowered(pos))
|
|
||||||
return null;
|
return null;
|
||||||
return (PortableStorageInterfaceTileEntity) te;
|
return (PortableStorageInterfaceTileEntity) te;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Direction getCurrentFacing(MovementContext context) {
|
private Optional<Direction> getCurrentFacingIfValid(MovementContext context) {
|
||||||
Vec3d directionVec = new Vec3d(context.state.get(PortableStorageInterfaceBlock.FACING)
|
Vec3d directionVec = new Vec3d(context.state.get(PortableStorageInterfaceBlock.FACING)
|
||||||
.getDirectionVec());
|
.getDirectionVec());
|
||||||
directionVec = VecHelper.rotate(directionVec, context.rotation.x, context.rotation.y, context.rotation.z);
|
directionVec = VecHelper.rotate(directionVec, context.rotation.x, context.rotation.y, context.rotation.z);
|
||||||
return Direction.getFacingFromVector(directionVec.x, directionVec.y, directionVec.z);
|
Direction facingFromVector = Direction.getFacingFromVector(directionVec.x, directionVec.y, directionVec.z);
|
||||||
|
if (directionVec.distanceTo(new Vec3d(facingFromVector.getDirectionVec())) > 1 / 8f)
|
||||||
|
return Optional.empty();
|
||||||
|
return Optional.of(facingFromVector);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +1,25 @@
|
||||||
package com.simibubi.create.content.contraptions.components.actors;
|
package com.simibubi.create.content.contraptions.components.actors;
|
||||||
|
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||||
import com.mojang.blaze3d.vertex.IVertexBuilder;
|
import com.mojang.blaze3d.vertex.IVertexBuilder;
|
||||||
import com.simibubi.create.AllBlockPartials;
|
import com.simibubi.create.AllBlockPartials;
|
||||||
|
import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext;
|
||||||
import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer;
|
import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer;
|
||||||
import com.simibubi.create.foundation.utility.AngleHelper;
|
import com.simibubi.create.foundation.utility.AngleHelper;
|
||||||
import com.simibubi.create.foundation.utility.AnimationTickHolder;
|
|
||||||
import com.simibubi.create.foundation.utility.MatrixStacker;
|
import com.simibubi.create.foundation.utility.MatrixStacker;
|
||||||
import com.simibubi.create.foundation.utility.SuperByteBuffer;
|
import com.simibubi.create.foundation.utility.SuperByteBuffer;
|
||||||
|
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.renderer.IRenderTypeBuffer;
|
import net.minecraft.client.renderer.IRenderTypeBuffer;
|
||||||
import net.minecraft.client.renderer.RenderType;
|
import net.minecraft.client.renderer.RenderType;
|
||||||
import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher;
|
import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher;
|
||||||
|
import net.minecraft.nbt.NBTUtil;
|
||||||
|
import net.minecraft.tileentity.TileEntity;
|
||||||
import net.minecraft.util.Direction;
|
import net.minecraft.util.Direction;
|
||||||
import net.minecraft.util.math.MathHelper;
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
|
||||||
public class PortableStorageInterfaceRenderer extends SafeTileEntityRenderer<PortableStorageInterfaceTileEntity> {
|
public class PortableStorageInterfaceRenderer extends SafeTileEntityRenderer<PortableStorageInterfaceTileEntity> {
|
||||||
|
|
||||||
|
@ -25,40 +30,83 @@ public class PortableStorageInterfaceRenderer extends SafeTileEntityRenderer<Por
|
||||||
@Override
|
@Override
|
||||||
protected void renderSafe(PortableStorageInterfaceTileEntity te, float partialTicks, MatrixStack ms,
|
protected void renderSafe(PortableStorageInterfaceTileEntity te, float partialTicks, MatrixStack ms,
|
||||||
IRenderTypeBuffer buffer, int light, int overlay) {
|
IRenderTypeBuffer buffer, int light, int overlay) {
|
||||||
|
|
||||||
BlockState blockState = te.getBlockState();
|
BlockState blockState = te.getBlockState();
|
||||||
SuperByteBuffer middle = AllBlockPartials.PORTABLE_STORAGE_INTERFACE_MIDDLE.renderOn(blockState);
|
float progress = te.getExtensionDistance(partialTicks);
|
||||||
SuperByteBuffer top = AllBlockPartials.PORTABLE_STORAGE_INTERFACE_TOP.renderOn(blockState);
|
|
||||||
IVertexBuilder vb = buffer.getBuffer(RenderType.getSolid());
|
IVertexBuilder vb = buffer.getBuffer(RenderType.getSolid());
|
||||||
|
render(blockState, progress, te.isConnected(), sbb -> sbb.renderInto(ms, vb), ms);
|
||||||
|
}
|
||||||
|
|
||||||
ms.push();
|
public static void renderInContraption(MovementContext context, MatrixStack ms, MatrixStack msLocal,
|
||||||
|
IRenderTypeBuffer buffer) {
|
||||||
Direction facing = blockState.get(PortableStorageInterfaceBlock.FACING);
|
BlockState blockState = context.state;
|
||||||
MatrixStacker.of(ms)
|
PortableStorageInterfaceTileEntity te = getTargetPSI(context);
|
||||||
.centre()
|
IVertexBuilder vb = buffer.getBuffer(RenderType.getSolid());
|
||||||
.rotateY(AngleHelper.horizontalAngle(facing))
|
float renderPartialTicks = Minecraft.getInstance()
|
||||||
.rotateX(facing == Direction.UP ? 0 : facing == Direction.DOWN ? 180 : 90)
|
.getRenderPartialTicks();
|
||||||
.unCentre();
|
|
||||||
|
|
||||||
float progress = (float) ((AnimationTickHolder.getRenderTick() * .25f) % (Math.PI * 2));
|
|
||||||
float bounce = (MathHelper.sin(progress) + 1) / 4f;
|
|
||||||
|
|
||||||
if (bounce > 7/16f) {
|
float progress = 0;
|
||||||
middle = AllBlockPartials.PORTABLE_STORAGE_INTERFACE_MIDDLE_POWERED.renderOn(blockState);
|
boolean lit = false;
|
||||||
|
if (te != null) {
|
||||||
|
progress = te.getExtensionDistance(renderPartialTicks);
|
||||||
|
lit = te.isConnected();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
render(blockState, progress, lit, sbb -> sbb.light(msLocal.peek()
|
||||||
|
.getModel())
|
||||||
|
.renderInto(ms, vb), ms, msLocal);
|
||||||
|
}
|
||||||
|
|
||||||
ms.translate(0, bounce, 0);
|
protected static PortableStorageInterfaceTileEntity getTargetPSI(MovementContext context) {
|
||||||
|
String _workingPos_ = PortableStorageInterfaceMovement._workingPos_;
|
||||||
ms.push();
|
if (!context.contraption.stalled || !context.data.contains(_workingPos_))
|
||||||
ms.translate(0, 6/16f, 0);
|
return null;
|
||||||
middle.renderInto(ms, vb);
|
|
||||||
ms.pop();
|
|
||||||
|
|
||||||
ms.translate(0, bounce, 0);
|
|
||||||
top.renderInto(ms, vb);
|
|
||||||
|
|
||||||
ms.pop();
|
BlockPos pos = NBTUtil.readBlockPos(context.data.getCompound(_workingPos_));
|
||||||
|
TileEntity tileEntity = context.world.getTileEntity(pos);
|
||||||
|
if (!(tileEntity instanceof PortableStorageInterfaceTileEntity))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
PortableStorageInterfaceTileEntity psi = (PortableStorageInterfaceTileEntity) tileEntity;
|
||||||
|
if (!psi.isTransferring())
|
||||||
|
return null;
|
||||||
|
return psi;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void render(BlockState blockState, float progress, boolean lit,
|
||||||
|
Consumer<SuperByteBuffer> drawCallback, MatrixStack... matrixStacks) {
|
||||||
|
for (MatrixStack ms : matrixStacks)
|
||||||
|
ms.push();
|
||||||
|
|
||||||
|
SuperByteBuffer middle = AllBlockPartials.PORTABLE_STORAGE_INTERFACE_MIDDLE.renderOn(blockState);
|
||||||
|
SuperByteBuffer top = AllBlockPartials.PORTABLE_STORAGE_INTERFACE_TOP.renderOn(blockState);
|
||||||
|
if (lit)
|
||||||
|
middle = AllBlockPartials.PORTABLE_STORAGE_INTERFACE_MIDDLE_POWERED.renderOn(blockState);
|
||||||
|
|
||||||
|
Direction facing = blockState.get(PortableStorageInterfaceBlock.FACING);
|
||||||
|
for (MatrixStack ms : matrixStacks)
|
||||||
|
MatrixStacker.of(ms)
|
||||||
|
.centre()
|
||||||
|
.rotateY(AngleHelper.horizontalAngle(facing))
|
||||||
|
.rotateX(facing == Direction.UP ? 0 : facing == Direction.DOWN ? 180 : 90)
|
||||||
|
.unCentre();
|
||||||
|
|
||||||
|
for (MatrixStack ms : matrixStacks) {
|
||||||
|
ms.translate(0, progress / 2f, 0);
|
||||||
|
ms.push();
|
||||||
|
ms.translate(0, 6 / 16f, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
drawCallback.accept(middle);
|
||||||
|
|
||||||
|
for (MatrixStack ms : matrixStacks) {
|
||||||
|
ms.pop();
|
||||||
|
ms.translate(0, progress / 2f, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
drawCallback.accept(top);
|
||||||
|
|
||||||
|
for (MatrixStack ms : matrixStacks)
|
||||||
|
ms.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,54 +3,150 @@ package com.simibubi.create.content.contraptions.components.actors;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption;
|
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption;
|
||||||
|
import com.simibubi.create.foundation.config.AllConfigs;
|
||||||
|
import com.simibubi.create.foundation.item.ItemHandlerWrapper;
|
||||||
import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
|
import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
|
||||||
import com.simibubi.create.foundation.tileEntity.SyncedTileEntity;
|
|
||||||
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
|
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
|
||||||
|
import com.simibubi.create.foundation.utility.LerpedFloat;
|
||||||
|
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.nbt.CompoundNBT;
|
||||||
import net.minecraft.tileentity.TileEntityType;
|
import net.minecraft.tileentity.TileEntityType;
|
||||||
import net.minecraft.util.Direction;
|
import net.minecraft.util.Direction;
|
||||||
|
import net.minecraft.util.math.MathHelper;
|
||||||
import net.minecraftforge.common.capabilities.Capability;
|
import net.minecraftforge.common.capabilities.Capability;
|
||||||
import net.minecraftforge.common.util.LazyOptional;
|
import net.minecraftforge.common.util.LazyOptional;
|
||||||
import net.minecraftforge.items.IItemHandlerModifiable;
|
import net.minecraftforge.items.IItemHandlerModifiable;
|
||||||
import net.minecraftforge.items.wrapper.CombinedInvWrapper;
|
|
||||||
|
|
||||||
public class PortableStorageInterfaceTileEntity extends SmartTileEntity {
|
public class PortableStorageInterfaceTileEntity extends SmartTileEntity {
|
||||||
|
|
||||||
protected int transferTimeout;
|
protected int transferTimer;
|
||||||
|
protected float distance;
|
||||||
protected LazyOptional<IItemHandlerModifiable> capability;
|
protected LazyOptional<IItemHandlerModifiable> capability;
|
||||||
|
protected LerpedFloat connectionAnimation;
|
||||||
|
|
||||||
public PortableStorageInterfaceTileEntity(TileEntityType<?> tileEntityTypeIn) {
|
public PortableStorageInterfaceTileEntity(TileEntityType<?> tileEntityTypeIn) {
|
||||||
super(tileEntityTypeIn);
|
super(tileEntityTypeIn);
|
||||||
transferTimeout = 0;
|
transferTimer = 0;
|
||||||
capability = LazyOptional.empty();
|
capability = LazyOptional.empty();
|
||||||
|
connectionAnimation = LerpedFloat.linear().startWithValue(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void startTransferringTo(Contraption contraption) {
|
public void startTransferringTo(Contraption contraption, float distance) {
|
||||||
CombinedInvWrapper inventory = contraption.inventory;
|
|
||||||
capability.invalidate();
|
capability.invalidate();
|
||||||
capability = LazyOptional.of(() -> inventory);
|
capability = LazyOptional.of(() -> new InterfaceItemHandler(contraption.inventory));
|
||||||
|
this.distance = distance;
|
||||||
|
startConnecting();
|
||||||
|
notifyUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void tick() {
|
public void tick() {
|
||||||
super.tick();
|
super.tick();
|
||||||
|
boolean wasConnected = isConnected();
|
||||||
|
|
||||||
|
if (transferTimer > 0) {
|
||||||
|
transferTimer--;
|
||||||
|
if (transferTimer == 0)
|
||||||
|
capability.invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isConnected = isConnected();
|
||||||
|
if (wasConnected != isConnected && !world.isRemote)
|
||||||
|
markDirty();
|
||||||
|
|
||||||
|
float progress = 0;
|
||||||
|
int timeUnit = getTransferTimeout() / 2;
|
||||||
|
if (isConnected)
|
||||||
|
progress = 1;
|
||||||
|
else if (transferTimer >= timeUnit * 3)
|
||||||
|
progress = MathHelper.lerp((transferTimer - timeUnit * 3) / (float) timeUnit, 1, 0);
|
||||||
|
else if (transferTimer < timeUnit)
|
||||||
|
progress = MathHelper.lerp(transferTimer / (float) timeUnit, 0, 1);
|
||||||
|
connectionAnimation.setValue(progress);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void read(CompoundNBT compound, boolean clientPacket) {
|
||||||
|
super.read(compound, clientPacket);
|
||||||
|
transferTimer = compound.getInt("Timer");
|
||||||
|
distance = compound.getFloat("Distance");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void write(CompoundNBT compound, boolean clientPacket) {
|
||||||
|
super.write(compound, clientPacket);
|
||||||
|
compound.putInt("Timer", transferTimer);
|
||||||
|
compound.putFloat("Distance", distance);
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isTransferring() {
|
public boolean isTransferring() {
|
||||||
return transferTimeout != 0;
|
return transferTimer != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isConnected() {
|
||||||
|
int timeUnit = getTransferTimeout() / 2;
|
||||||
|
return transferTimer >= timeUnit && transferTimer < timeUnit * 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
float getExtensionDistance(float partialTicks) {
|
||||||
|
return connectionAnimation.getValue(partialTicks) * distance / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
float getConnectionDistance() {
|
||||||
|
return distance;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> LazyOptional<T> getCapability(Capability<T> cap, Direction side) {
|
public <T> LazyOptional<T> getCapability(Capability<T> cap, Direction side) {
|
||||||
|
if (isItemHandlerCap(cap))
|
||||||
|
return capability.cast();
|
||||||
return super.getCapability(cap, side);
|
return super.getCapability(cap, side);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void resetTimer() {
|
public void startConnecting() {
|
||||||
|
transferTimer = getTransferTimeout() * 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onContentTransferred() {
|
||||||
|
int timeUnit = getTransferTimeout() / 2;
|
||||||
|
transferTimer = timeUnit * 3;
|
||||||
|
sendData();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Integer getTransferTimeout() {
|
||||||
|
return AllConfigs.SERVER.logistics.psiTimeout.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addBehaviours(List<TileEntityBehaviour> behaviours) {}
|
public void addBehaviours(List<TileEntityBehaviour> behaviours) {}
|
||||||
|
|
||||||
|
class InterfaceItemHandler extends ItemHandlerWrapper {
|
||||||
|
|
||||||
|
public InterfaceItemHandler(IItemHandlerModifiable wrapped) {
|
||||||
|
super(wrapped);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ItemStack extractItem(int slot, int amount, boolean simulate) {
|
||||||
|
if (!isConnected())
|
||||||
|
return ItemStack.EMPTY;
|
||||||
|
ItemStack extractItem = super.extractItem(slot, amount, simulate);
|
||||||
|
if (!simulate && !extractItem.isEmpty())
|
||||||
|
onContentTransferred();
|
||||||
|
return extractItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ItemStack insertItem(int slot, ItemStack stack, boolean simulate) {
|
||||||
|
if (!isConnected())
|
||||||
|
return stack;
|
||||||
|
ItemStack insertItem = super.insertItem(slot, stack, simulate);
|
||||||
|
if (!simulate && !insertItem.equals(stack, false))
|
||||||
|
onContentTransferred();
|
||||||
|
return insertItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
package com.simibubi.create.foundation.item;
|
||||||
|
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraftforge.items.IItemHandlerModifiable;
|
||||||
|
|
||||||
|
public class ItemHandlerWrapper implements IItemHandlerModifiable {
|
||||||
|
|
||||||
|
private IItemHandlerModifiable wrapped;
|
||||||
|
|
||||||
|
public ItemHandlerWrapper(IItemHandlerModifiable wrapped) {
|
||||||
|
this.wrapped = wrapped;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getSlots() {
|
||||||
|
return wrapped.getSlots();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ItemStack getStackInSlot(int slot) {
|
||||||
|
return wrapped.getStackInSlot(slot);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ItemStack insertItem(int slot, ItemStack stack, boolean simulate) {
|
||||||
|
return wrapped.insertItem(slot, stack, simulate);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ItemStack extractItem(int slot, int amount, boolean simulate) {
|
||||||
|
return wrapped.extractItem(slot, amount, simulate);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getSlotLimit(int slot) {
|
||||||
|
return wrapped.getSlotLimit(slot);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isItemValid(int slot, ItemStack stack) {
|
||||||
|
return wrapped.isItemValid(slot, stack);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setStackInSlot(int slot, ItemStack stack) {
|
||||||
|
wrapped.setStackInSlot(slot, stack);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -11,6 +11,9 @@ import com.simibubi.create.foundation.tileEntity.behaviour.BehaviourType;
|
||||||
import net.minecraft.nbt.CompoundNBT;
|
import net.minecraft.nbt.CompoundNBT;
|
||||||
import net.minecraft.tileentity.ITickableTileEntity;
|
import net.minecraft.tileentity.ITickableTileEntity;
|
||||||
import net.minecraft.tileentity.TileEntityType;
|
import net.minecraft.tileentity.TileEntityType;
|
||||||
|
import net.minecraftforge.common.capabilities.Capability;
|
||||||
|
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
|
||||||
|
import net.minecraftforge.items.CapabilityItemHandler;
|
||||||
|
|
||||||
public abstract class SmartTileEntity extends SyncedTileEntity implements ITickableTileEntity {
|
public abstract class SmartTileEntity extends SyncedTileEntity implements ITickableTileEntity {
|
||||||
|
|
||||||
|
@ -145,5 +148,13 @@ public abstract class SmartTileEntity extends SyncedTileEntity implements ITicka
|
||||||
return (T) behaviours.get(type);
|
return (T) behaviours.get(type);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected boolean isItemHandlerCap(Capability<?> cap) {
|
||||||
|
return cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean isFluidHandlerCap(Capability<?> cap) {
|
||||||
|
return cap == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,6 @@ import org.apache.commons.lang3.mutable.MutableInt;
|
||||||
|
|
||||||
import com.simibubi.create.foundation.fluid.CombinedTankWrapper;
|
import com.simibubi.create.foundation.fluid.CombinedTankWrapper;
|
||||||
import com.simibubi.create.foundation.fluid.SmartFluidTank;
|
import com.simibubi.create.foundation.fluid.SmartFluidTank;
|
||||||
import com.simibubi.create.foundation.item.SmartInventory;
|
|
||||||
import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
|
import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
|
||||||
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
|
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
|
||||||
import com.simibubi.create.foundation.tileEntity.behaviour.BehaviourType;
|
import com.simibubi.create.foundation.tileEntity.behaviour.BehaviourType;
|
||||||
|
|
|
@ -36,6 +36,7 @@ public class InvManipulationBehaviour extends TileEntityBehaviour {
|
||||||
protected LazyOptional<IItemHandler> targetCapability;
|
protected LazyOptional<IItemHandler> targetCapability;
|
||||||
protected boolean simulateNext;
|
protected boolean simulateNext;
|
||||||
protected boolean bypassSided;
|
protected boolean bypassSided;
|
||||||
|
private boolean findNewNextTick;
|
||||||
|
|
||||||
private BehaviourType<InvManipulationBehaviour> behaviourType;
|
private BehaviourType<InvManipulationBehaviour> behaviourType;
|
||||||
|
|
||||||
|
@ -55,7 +56,7 @@ public class InvManipulationBehaviour extends TileEntityBehaviour {
|
||||||
InterfaceProvider target) {
|
InterfaceProvider target) {
|
||||||
super(te);
|
super(te);
|
||||||
behaviourType = type;
|
behaviourType = type;
|
||||||
setLazyTickRate(40);
|
setLazyTickRate(5);
|
||||||
this.target = target;
|
this.target = target;
|
||||||
this.targetCapability = LazyOptional.empty();
|
this.targetCapability = LazyOptional.empty();
|
||||||
simulateNext = false;
|
simulateNext = false;
|
||||||
|
@ -137,11 +138,12 @@ public class InvManipulationBehaviour extends TileEntityBehaviour {
|
||||||
@Override
|
@Override
|
||||||
public void initialize() {
|
public void initialize() {
|
||||||
super.initialize();
|
super.initialize();
|
||||||
findNewCapability();
|
findNewNextTick = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void onHandlerInvalidated(LazyOptional<IItemHandler> handler) {
|
protected void onHandlerInvalidated(LazyOptional<IItemHandler> handler) {
|
||||||
findNewCapability();
|
findNewNextTick = true;
|
||||||
|
targetCapability = LazyOptional.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -150,6 +152,15 @@ public class InvManipulationBehaviour extends TileEntityBehaviour {
|
||||||
if (!targetCapability.isPresent())
|
if (!targetCapability.isPresent())
|
||||||
findNewCapability();
|
findNewCapability();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tick() {
|
||||||
|
super.tick();
|
||||||
|
if (findNewNextTick) {
|
||||||
|
findNewNextTick = false;
|
||||||
|
findNewCapability();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public int getAmountFromFilter() {
|
public int getAmountFromFilter() {
|
||||||
int amount = -1;
|
int amount = -1;
|
||||||
|
|
Loading…
Reference in a new issue