mirror of
https://github.com/Creators-of-Create/Create.git
synced 2024-12-27 23:47:38 +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.AllTileEntities;
|
||||
import com.simibubi.create.foundation.block.ITE;
|
||||
import com.simibubi.create.foundation.block.ProperDirectionalBlock;
|
||||
|
||||
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.VoxelShape;
|
||||
import net.minecraft.world.IBlockReader;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
@ParametersAreNonnullByDefault
|
||||
@MethodsReturnNonnullByDefault
|
||||
public class PortableStorageInterfaceBlock extends ProperDirectionalBlock {
|
||||
public class PortableStorageInterfaceBlock extends ProperDirectionalBlock
|
||||
implements ITE<PortableStorageInterfaceTileEntity> {
|
||||
|
||||
public PortableStorageInterfaceBlock(Properties p_i48415_1_) {
|
||||
super(p_i48415_1_);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean hasTileEntity(BlockState state) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public TileEntity createTileEntity(BlockState state, IBlockReader world) {
|
||||
return AllTileEntities.PORTABLE_STORAGE_INTERFACE.create();
|
||||
|
@ -44,4 +47,23 @@ public class PortableStorageInterfaceBlock extends ProperDirectionalBlock {
|
|||
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;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
import java.util.Optional;
|
||||
|
||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour;
|
||||
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 net.minecraft.block.BlockState;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.client.renderer.IRenderTypeBuffer;
|
||||
import net.minecraft.nbt.NBTUtil;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.Direction.Axis;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.items.IItemHandlerModifiable;
|
||||
import net.minecraftforge.items.ItemHandlerHelper;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
|
||||
public class PortableStorageInterfaceMovement extends MovementBehaviour {
|
||||
|
||||
private static final String _exporting_ = "Exporting";
|
||||
private static final String _delay_ = "Delay";
|
||||
private static final String _workingPos_ = "WorkingPos";
|
||||
static final String _workingPos_ = "WorkingPos";
|
||||
static final String _clientPrevPos_ = "ClientPrevPos";
|
||||
|
||||
@Override
|
||||
public Vec3d getActiveAreaOffset(MovementContext context) {
|
||||
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
|
||||
public void visitNewPosition(MovementContext context, BlockPos pos) {
|
||||
Direction currentFacing = getCurrentFacing(context);
|
||||
PortableStorageInterfaceTileEntity psi =
|
||||
getValidStationaryInterface(context.world, pos, currentFacing.getAxis());
|
||||
context.data.remove(_workingPos_);
|
||||
if (findInterface(context, pos))
|
||||
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)
|
||||
return;
|
||||
if (psi.isTransferring())
|
||||
return;
|
||||
context.data.put(_workingPos_, NBTUtil.writeBlockPos(pos));
|
||||
context.stall = true;
|
||||
return false;
|
||||
|
||||
if (psi.isTransferring() && !context.world.isRemote)
|
||||
return false;
|
||||
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
|
||||
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;
|
||||
if (context.world.isRemote)
|
||||
}
|
||||
|
||||
if (!context.data.contains(_workingPos_))
|
||||
return;
|
||||
|
||||
BlockPos pos = NBTUtil.readBlockPos(context.data.getCompound(_workingPos_));
|
||||
Optional<Direction> currentFacingIfValid = getCurrentFacingIfValid(context);
|
||||
if (!currentFacingIfValid.isPresent())
|
||||
return;
|
||||
|
||||
PortableStorageInterfaceTileEntity stationaryInterface =
|
||||
getValidStationaryInterface(context.world, pos, getCurrentFacing(context).getAxis());
|
||||
if (stationaryInterface == null) {
|
||||
getStationaryInterfaceAt(context.world, pos, currentFacingIfValid.get());
|
||||
if (stationaryInterface == null || !stationaryInterface.isTransferring()) {
|
||||
reset(context);
|
||||
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
|
||||
|
@ -136,32 +107,42 @@ public class PortableStorageInterfaceMovement extends MovementBehaviour {
|
|||
}
|
||||
|
||||
public void reset(MovementContext context) {
|
||||
context.data.remove(_clientPrevPos_);
|
||||
context.data.remove(_workingPos_);
|
||||
context.data.remove(_delay_);
|
||||
context.data.remove(_exporting_);
|
||||
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);
|
||||
if (!(te instanceof PortableStorageInterfaceTileEntity))
|
||||
return null;
|
||||
BlockState blockState = world.getBlockState(pos);
|
||||
if (!AllBlocks.PORTABLE_STORAGE_INTERFACE.has(blockState))
|
||||
return null;
|
||||
if (blockState.get(PortableStorageInterfaceBlock.FACING)
|
||||
.getAxis() != validAxis)
|
||||
return null;
|
||||
if (world.isBlockPowered(pos))
|
||||
if (blockState.get(PortableStorageInterfaceBlock.FACING) != facing.getOpposite())
|
||||
return null;
|
||||
return (PortableStorageInterfaceTileEntity) te;
|
||||
}
|
||||
|
||||
private Direction getCurrentFacing(MovementContext context) {
|
||||
private Optional<Direction> getCurrentFacingIfValid(MovementContext context) {
|
||||
Vec3d directionVec = new Vec3d(context.state.get(PortableStorageInterfaceBlock.FACING)
|
||||
.getDirectionVec());
|
||||
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;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||
import com.mojang.blaze3d.vertex.IVertexBuilder;
|
||||
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.utility.AngleHelper;
|
||||
import com.simibubi.create.foundation.utility.AnimationTickHolder;
|
||||
import com.simibubi.create.foundation.utility.MatrixStacker;
|
||||
import com.simibubi.create.foundation.utility.SuperByteBuffer;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.IRenderTypeBuffer;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
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.math.MathHelper;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
public class PortableStorageInterfaceRenderer extends SafeTileEntityRenderer<PortableStorageInterfaceTileEntity> {
|
||||
|
||||
|
@ -25,40 +30,83 @@ public class PortableStorageInterfaceRenderer extends SafeTileEntityRenderer<Por
|
|||
@Override
|
||||
protected void renderSafe(PortableStorageInterfaceTileEntity te, float partialTicks, MatrixStack ms,
|
||||
IRenderTypeBuffer buffer, int light, int overlay) {
|
||||
|
||||
BlockState blockState = te.getBlockState();
|
||||
SuperByteBuffer middle = AllBlockPartials.PORTABLE_STORAGE_INTERFACE_MIDDLE.renderOn(blockState);
|
||||
SuperByteBuffer top = AllBlockPartials.PORTABLE_STORAGE_INTERFACE_TOP.renderOn(blockState);
|
||||
float progress = te.getExtensionDistance(partialTicks);
|
||||
IVertexBuilder vb = buffer.getBuffer(RenderType.getSolid());
|
||||
render(blockState, progress, te.isConnected(), sbb -> sbb.renderInto(ms, vb), ms);
|
||||
}
|
||||
|
||||
ms.push();
|
||||
|
||||
Direction facing = blockState.get(PortableStorageInterfaceBlock.FACING);
|
||||
MatrixStacker.of(ms)
|
||||
.centre()
|
||||
.rotateY(AngleHelper.horizontalAngle(facing))
|
||||
.rotateX(facing == Direction.UP ? 0 : facing == Direction.DOWN ? 180 : 90)
|
||||
.unCentre();
|
||||
|
||||
float progress = (float) ((AnimationTickHolder.getRenderTick() * .25f) % (Math.PI * 2));
|
||||
float bounce = (MathHelper.sin(progress) + 1) / 4f;
|
||||
public static void renderInContraption(MovementContext context, MatrixStack ms, MatrixStack msLocal,
|
||||
IRenderTypeBuffer buffer) {
|
||||
BlockState blockState = context.state;
|
||||
PortableStorageInterfaceTileEntity te = getTargetPSI(context);
|
||||
IVertexBuilder vb = buffer.getBuffer(RenderType.getSolid());
|
||||
float renderPartialTicks = Minecraft.getInstance()
|
||||
.getRenderPartialTicks();
|
||||
|
||||
if (bounce > 7/16f) {
|
||||
middle = AllBlockPartials.PORTABLE_STORAGE_INTERFACE_MIDDLE_POWERED.renderOn(blockState);
|
||||
float progress = 0;
|
||||
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);
|
||||
|
||||
ms.push();
|
||||
ms.translate(0, 6/16f, 0);
|
||||
middle.renderInto(ms, vb);
|
||||
ms.pop();
|
||||
|
||||
ms.translate(0, bounce, 0);
|
||||
top.renderInto(ms, vb);
|
||||
protected static PortableStorageInterfaceTileEntity getTargetPSI(MovementContext context) {
|
||||
String _workingPos_ = PortableStorageInterfaceMovement._workingPos_;
|
||||
if (!context.contraption.stalled || !context.data.contains(_workingPos_))
|
||||
return null;
|
||||
|
||||
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 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.SyncedTileEntity;
|
||||
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.util.Direction;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraftforge.common.capabilities.Capability;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
import net.minecraftforge.items.IItemHandlerModifiable;
|
||||
import net.minecraftforge.items.wrapper.CombinedInvWrapper;
|
||||
|
||||
public class PortableStorageInterfaceTileEntity extends SmartTileEntity {
|
||||
|
||||
protected int transferTimeout;
|
||||
protected int transferTimer;
|
||||
protected float distance;
|
||||
protected LazyOptional<IItemHandlerModifiable> capability;
|
||||
protected LerpedFloat connectionAnimation;
|
||||
|
||||
public PortableStorageInterfaceTileEntity(TileEntityType<?> tileEntityTypeIn) {
|
||||
super(tileEntityTypeIn);
|
||||
transferTimeout = 0;
|
||||
transferTimer = 0;
|
||||
capability = LazyOptional.empty();
|
||||
connectionAnimation = LerpedFloat.linear().startWithValue(0);
|
||||
}
|
||||
|
||||
public void startTransferringTo(Contraption contraption) {
|
||||
CombinedInvWrapper inventory = contraption.inventory;
|
||||
public void startTransferringTo(Contraption contraption, float distance) {
|
||||
capability.invalidate();
|
||||
capability = LazyOptional.of(() -> inventory);
|
||||
|
||||
capability = LazyOptional.of(() -> new InterfaceItemHandler(contraption.inventory));
|
||||
this.distance = distance;
|
||||
startConnecting();
|
||||
notifyUpdate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void 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() {
|
||||
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
|
||||
public <T> LazyOptional<T> getCapability(Capability<T> cap, Direction side) {
|
||||
if (isItemHandlerCap(cap))
|
||||
return capability.cast();
|
||||
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
|
||||
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.tileentity.ITickableTileEntity;
|
||||
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 {
|
||||
|
||||
|
@ -145,5 +148,13 @@ public abstract class SmartTileEntity extends SyncedTileEntity implements ITicka
|
|||
return (T) behaviours.get(type);
|
||||
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.SmartFluidTank;
|
||||
import com.simibubi.create.foundation.item.SmartInventory;
|
||||
import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
|
||||
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
|
||||
import com.simibubi.create.foundation.tileEntity.behaviour.BehaviourType;
|
||||
|
|
|
@ -36,6 +36,7 @@ public class InvManipulationBehaviour extends TileEntityBehaviour {
|
|||
protected LazyOptional<IItemHandler> targetCapability;
|
||||
protected boolean simulateNext;
|
||||
protected boolean bypassSided;
|
||||
private boolean findNewNextTick;
|
||||
|
||||
private BehaviourType<InvManipulationBehaviour> behaviourType;
|
||||
|
||||
|
@ -55,7 +56,7 @@ public class InvManipulationBehaviour extends TileEntityBehaviour {
|
|||
InterfaceProvider target) {
|
||||
super(te);
|
||||
behaviourType = type;
|
||||
setLazyTickRate(40);
|
||||
setLazyTickRate(5);
|
||||
this.target = target;
|
||||
this.targetCapability = LazyOptional.empty();
|
||||
simulateNext = false;
|
||||
|
@ -137,11 +138,12 @@ public class InvManipulationBehaviour extends TileEntityBehaviour {
|
|||
@Override
|
||||
public void initialize() {
|
||||
super.initialize();
|
||||
findNewCapability();
|
||||
findNewNextTick = true;
|
||||
}
|
||||
|
||||
protected void onHandlerInvalidated(LazyOptional<IItemHandler> handler) {
|
||||
findNewCapability();
|
||||
findNewNextTick = true;
|
||||
targetCapability = LazyOptional.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -150,6 +152,15 @@ public class InvManipulationBehaviour extends TileEntityBehaviour {
|
|||
if (!targetCapability.isPresent())
|
||||
findNewCapability();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
super.tick();
|
||||
if (findNewNextTick) {
|
||||
findNewNextTick = false;
|
||||
findNewCapability();
|
||||
}
|
||||
}
|
||||
|
||||
public int getAmountFromFilter() {
|
||||
int amount = -1;
|
||||
|
|
Loading…
Reference in a new issue