mirror of
https://github.com/Creators-of-Create/Create.git
synced 2025-01-01 01:47:02 +01:00
Belt funnel & World funnel implementation
- Funnels on belts can now extract and insert items according to their setting and filter - Funnels can now push/pull items to/from a depot - Fixed creative crates not marking their inventory as removed when destroyed - Funnels can now pick up items colliding with their front face - When holding a funnel the game will now always prefer placement over block interaction - Fixed items not able to be held in place by tunnels
This commit is contained in:
parent
f7ad748a09
commit
ce1c5d8697
13 changed files with 314 additions and 29 deletions
|
@ -69,6 +69,10 @@ public class AllShapes {
|
||||||
.add(1, 6, 1, 15, 10, 15)
|
.add(1, 6, 1, 15, 10, 15)
|
||||||
.add(0, 10, 0, 16, 16, 16)
|
.add(0, 10, 0, 16, 16, 16)
|
||||||
.forDirectional(UP),
|
.forDirectional(UP),
|
||||||
|
REALITY_FUNNEL_COLLISION = shape(3, -2, 3, 13, 2, 13).add(2, 2, 2, 14, 6, 14)
|
||||||
|
.add(1, 6, 1, 15, 10, 15)
|
||||||
|
.add(0, 10, 0, 16, 13, 16)
|
||||||
|
.forDirectional(UP),
|
||||||
CHUTE_FUNNEL = shape(3, -2, 3, 13, 2, 13).add(2, 2, 2, 14, 6, 14)
|
CHUTE_FUNNEL = shape(3, -2, 3, 13, 2, 13).add(2, 2, 2, 14, 6, 14)
|
||||||
.add(1, 5, 1, 15, 16, 15)
|
.add(1, 5, 1, 15, 16, 15)
|
||||||
.add(0, 8, 0, 16, 14, 16)
|
.add(0, 8, 0, 16, 14, 16)
|
||||||
|
|
|
@ -338,11 +338,12 @@ public class BeltTileEntity extends KineticTileEntity {
|
||||||
return inventory;
|
return inventory;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void applyToAllItems(Function<TransportedItemStack, List<TransportedItemStack>> processFunction) {
|
private void applyToAllItems(float maxDistanceFromCenter,
|
||||||
|
Function<TransportedItemStack, List<TransportedItemStack>> processFunction) {
|
||||||
BeltTileEntity controller = getControllerTE();
|
BeltTileEntity controller = getControllerTE();
|
||||||
if (controller != null)
|
if (controller != null)
|
||||||
controller.getInventory()
|
controller.getInventory()
|
||||||
.applyToEachWithin(index + .5f, .51f, processFunction);
|
.applyToEachWithin(index + .5f, maxDistanceFromCenter, processFunction);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Vec3d getWorldPositionOf(TransportedItemStack transported) {
|
private Vec3d getWorldPositionOf(TransportedItemStack transported) {
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
package com.simibubi.create.content.contraptions.relays.belt.transport;
|
||||||
|
|
||||||
|
import com.simibubi.create.AllBlocks;
|
||||||
|
import com.simibubi.create.content.contraptions.relays.belt.BeltHelper;
|
||||||
|
import com.simibubi.create.content.logistics.block.realityFunnel.BeltFunnelBlock;
|
||||||
|
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
|
||||||
|
import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour;
|
||||||
|
import com.simibubi.create.foundation.tileEntity.behaviour.inventory.InsertingBehaviour;
|
||||||
|
|
||||||
|
import net.minecraft.block.BlockState;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.util.math.MathHelper;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
|
public class BeltFunnelInteractionHandler {
|
||||||
|
|
||||||
|
public static boolean checkForFunnels(BeltInventory beltInventory, TransportedItemStack currentItem,
|
||||||
|
float nextOffset) {
|
||||||
|
boolean beltMovementPositive = beltInventory.beltMovementPositive;
|
||||||
|
int firstUpcomingSegment = (int) (currentItem.beltPosition + (beltMovementPositive ? .5f : -.5f));
|
||||||
|
int step = beltMovementPositive ? 1 : -1;
|
||||||
|
firstUpcomingSegment = MathHelper.clamp(firstUpcomingSegment, 0, beltInventory.belt.beltLength - 1);
|
||||||
|
|
||||||
|
for (int segment = firstUpcomingSegment; beltMovementPositive ? segment + .5f <= nextOffset
|
||||||
|
: segment + .5f >= nextOffset; segment += step) {
|
||||||
|
BlockPos funnelPos = BeltHelper.getPositionForOffset(beltInventory.belt, segment)
|
||||||
|
.up();
|
||||||
|
World world = beltInventory.belt.getWorld();
|
||||||
|
BlockState funnelState = world.getBlockState(funnelPos);
|
||||||
|
if (!AllBlocks.BELT_FUNNEL.has(funnelState))
|
||||||
|
continue;
|
||||||
|
if (funnelState.get(BeltFunnelBlock.HORIZONTAL_FACING) != beltInventory.belt.getMovementFacing()
|
||||||
|
.getOpposite())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
currentItem.beltPosition = segment + .5f;
|
||||||
|
|
||||||
|
if (funnelState.get(BeltFunnelBlock.PUSHING))
|
||||||
|
return true;
|
||||||
|
if (funnelState.get(BeltFunnelBlock.POWERED))
|
||||||
|
return true;
|
||||||
|
InsertingBehaviour behaviour = TileEntityBehaviour.get(world, funnelPos, InsertingBehaviour.TYPE);
|
||||||
|
FilteringBehaviour filtering = TileEntityBehaviour.get(world, funnelPos, FilteringBehaviour.TYPE);
|
||||||
|
if (behaviour == null || world.isRemote)
|
||||||
|
return true;
|
||||||
|
if (filtering != null && !filtering.test(currentItem.stack))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
ItemStack before = currentItem.stack.copy();
|
||||||
|
ItemStack remainder = behaviour.insert(before, false);
|
||||||
|
if (before.equals(remainder, false))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
currentItem.stack = remainder;
|
||||||
|
beltInventory.belt.sendData();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -138,7 +138,12 @@ public class BeltInventory {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Belt Tunnels
|
// Belt Tunnels
|
||||||
BeltTunnelInteractionHandler.flapTunnelsAndCheckIfStuck(this, currentItem, nextOffset);
|
if (BeltTunnelInteractionHandler.flapTunnelsAndCheckIfStuck(this, currentItem, nextOffset))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Belt Funnels
|
||||||
|
if (BeltFunnelInteractionHandler.checkForFunnels(this, currentItem, nextOffset))
|
||||||
|
continue;
|
||||||
|
|
||||||
// Apply Movement
|
// Apply Movement
|
||||||
currentItem.beltPosition += limitedMovement;
|
currentItem.beltPosition += limitedMovement;
|
||||||
|
@ -154,10 +159,8 @@ public class BeltInventory {
|
||||||
int lastOffset = beltMovementPositive ? belt.beltLength - 1 : 0;
|
int lastOffset = beltMovementPositive ? belt.beltLength - 1 : 0;
|
||||||
BlockPos nextPosition = BeltHelper.getPositionForOffset(belt, beltMovementPositive ? belt.beltLength : -1);
|
BlockPos nextPosition = BeltHelper.getPositionForOffset(belt, beltMovementPositive ? belt.beltLength : -1);
|
||||||
|
|
||||||
if (ending == Ending.FUNNEL) {
|
if (ending == Ending.FUNNEL)
|
||||||
// TODO
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
if (ending == Ending.INSERT) {
|
if (ending == Ending.INSERT) {
|
||||||
DirectBeltInputBehaviour inputBehaviour =
|
DirectBeltInputBehaviour inputBehaviour =
|
||||||
|
@ -267,7 +270,7 @@ public class BeltInventory {
|
||||||
}
|
}
|
||||||
|
|
||||||
private enum Ending {
|
private enum Ending {
|
||||||
UNRESOLVED(0), EJECT(0), INSERT(.25f), FUNNEL(.35f), BLOCKED(.45f);
|
UNRESOLVED(0), EJECT(0), INSERT(.25f), FUNNEL(.5f), BLOCKED(.45f);
|
||||||
|
|
||||||
private float margin;
|
private float margin;
|
||||||
|
|
||||||
|
|
|
@ -28,8 +28,10 @@ public class BeltTunnelInteractionHandler {
|
||||||
if (!beltInventory.beltMovementPositive && nextOffset == 0)
|
if (!beltInventory.beltMovementPositive && nextOffset == 0)
|
||||||
upcomingSegment = -1;
|
upcomingSegment = -1;
|
||||||
if (currentSegment != upcomingSegment) {
|
if (currentSegment != upcomingSegment) {
|
||||||
if (stuckAtTunnel(beltInventory, upcomingSegment, current.stack, movementFacing))
|
if (stuckAtTunnel(beltInventory, upcomingSegment, current.stack, movementFacing)) {
|
||||||
|
current.beltPosition = currentSegment + (beltInventory.beltMovementPositive ? .99f : -.01f);
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
if (!beltInventory.belt.getWorld().isRemote) {
|
if (!beltInventory.belt.getWorld().isRemote) {
|
||||||
flapTunnel(beltInventory, currentSegment, movementFacing, false);
|
flapTunnel(beltInventory, currentSegment, movementFacing, false);
|
||||||
flapTunnel(beltInventory, upcomingSegment, movementFacing.getOpposite(), true);
|
flapTunnel(beltInventory, upcomingSegment, movementFacing.getOpposite(), true);
|
||||||
|
|
|
@ -148,9 +148,12 @@ public class DepotTileEntity extends SmartTileEntity {
|
||||||
return empty;
|
return empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void applyToAllItems(Function<TransportedItemStack, List<TransportedItemStack>> processFunction) {
|
private void applyToAllItems(float maxDistanceFromCentre,
|
||||||
|
Function<TransportedItemStack, List<TransportedItemStack>> processFunction) {
|
||||||
if (heldItem == null)
|
if (heldItem == null)
|
||||||
return;
|
return;
|
||||||
|
if (.5f - heldItem.beltPosition > maxDistanceFromCentre)
|
||||||
|
return;
|
||||||
|
|
||||||
boolean dirty = false;
|
boolean dirty = false;
|
||||||
List<TransportedItemStack> toBeAdded = new ArrayList<>();
|
List<TransportedItemStack> toBeAdded = new ArrayList<>();
|
||||||
|
@ -190,7 +193,8 @@ public class DepotTileEntity extends SmartTileEntity {
|
||||||
|
|
||||||
public boolean isOutputEmpty() {
|
public boolean isOutputEmpty() {
|
||||||
for (int i = 0; i < processingOutputBuffer.getSlots(); i++)
|
for (int i = 0; i < processingOutputBuffer.getSlots(); i++)
|
||||||
if (!processingOutputBuffer.getStackInSlot(i).isEmpty())
|
if (!processingOutputBuffer.getStackInSlot(i)
|
||||||
|
.isEmpty())
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,6 +57,12 @@ public class CreativeCrateTileEntity extends CrateTileEntity {
|
||||||
otherCrate.filter.setFilter(filter);
|
otherCrate.filter.setFilter(filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remove() {
|
||||||
|
if (itemHandler != null)
|
||||||
|
itemHandler.invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
private CreativeCrateTileEntity getOtherCrate() {
|
private CreativeCrateTileEntity getOtherCrate() {
|
||||||
if (!AllBlocks.CREATIVE_CRATE.has(getBlockState()))
|
if (!AllBlocks.CREATIVE_CRATE.has(getBlockState()))
|
||||||
return null;
|
return null;
|
||||||
|
@ -73,7 +79,8 @@ public class CreativeCrateTileEntity extends CrateTileEntity {
|
||||||
if (otherCrate == null)
|
if (otherCrate == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
filter.withCallback($ -> {});
|
filter.withCallback($ -> {
|
||||||
|
});
|
||||||
filter.setFilter(otherCrate.filter.getFilter());
|
filter.setFilter(otherCrate.filter.getFilter());
|
||||||
filter.withCallback(this::filterChanged);
|
filter.withCallback(this::filterChanged);
|
||||||
}
|
}
|
||||||
|
@ -90,7 +97,8 @@ public class CreativeCrateTileEntity extends CrateTileEntity {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void rotate(BlockState state, MatrixStack ms) {
|
protected void rotate(BlockState state, MatrixStack ms) {
|
||||||
MatrixStacker.of(ms).rotateX(90);
|
MatrixStacker.of(ms)
|
||||||
|
.rotateX(90);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
package com.simibubi.create.content.logistics.block.realityFunnel;
|
package com.simibubi.create.content.logistics.block.realityFunnel;
|
||||||
|
|
||||||
|
import com.simibubi.create.AllBlocks;
|
||||||
import com.simibubi.create.AllShapes;
|
import com.simibubi.create.AllShapes;
|
||||||
import com.simibubi.create.content.contraptions.relays.belt.BeltBlock;
|
import com.simibubi.create.content.contraptions.relays.belt.BeltBlock;
|
||||||
import com.simibubi.create.content.contraptions.relays.belt.BeltBlock.Slope;
|
import com.simibubi.create.content.contraptions.relays.belt.BeltBlock.Slope;
|
||||||
|
import com.simibubi.create.content.contraptions.relays.belt.BeltTileEntity;
|
||||||
import com.simibubi.create.content.logistics.block.belts.tunnel.BeltTunnelBlock;
|
import com.simibubi.create.content.logistics.block.belts.tunnel.BeltTunnelBlock;
|
||||||
import com.simibubi.create.content.logistics.block.depot.DepotBlock;
|
import com.simibubi.create.content.logistics.block.depot.DepotBlock;
|
||||||
import com.simibubi.create.foundation.utility.Lang;
|
import com.simibubi.create.foundation.utility.Lang;
|
||||||
|
@ -10,9 +12,11 @@ import com.simibubi.create.foundation.utility.VoxelShaper;
|
||||||
|
|
||||||
import net.minecraft.block.Block;
|
import net.minecraft.block.Block;
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
|
import net.minecraft.item.BlockItemUseContext;
|
||||||
import net.minecraft.state.EnumProperty;
|
import net.minecraft.state.EnumProperty;
|
||||||
import net.minecraft.state.IProperty;
|
import net.minecraft.state.IProperty;
|
||||||
import net.minecraft.state.StateContainer.Builder;
|
import net.minecraft.state.StateContainer.Builder;
|
||||||
|
import net.minecraft.tileentity.TileEntity;
|
||||||
import net.minecraft.util.Direction;
|
import net.minecraft.util.Direction;
|
||||||
import net.minecraft.util.IStringSerializable;
|
import net.minecraft.util.IStringSerializable;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
@ -22,6 +26,7 @@ import net.minecraft.world.IBlockReader;
|
||||||
import net.minecraft.world.ILightReader;
|
import net.minecraft.world.ILightReader;
|
||||||
import net.minecraft.world.IWorld;
|
import net.minecraft.world.IWorld;
|
||||||
import net.minecraft.world.IWorldReader;
|
import net.minecraft.world.IWorldReader;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
public class BeltFunnelBlock extends HorizontalInteractionFunnelBlock {
|
public class BeltFunnelBlock extends HorizontalInteractionFunnelBlock {
|
||||||
|
|
||||||
|
@ -47,6 +52,26 @@ public class BeltFunnelBlock extends HorizontalInteractionFunnelBlock {
|
||||||
setDefaultState(getDefaultState().with(SHAPE, Shape.RETRACTED));
|
setDefaultState(getDefaultState().with(SHAPE, Shape.RETRACTED));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockState getStateForPlacement(BlockItemUseContext ctx) {
|
||||||
|
BlockState state = super.getStateForPlacement(ctx);
|
||||||
|
World world = ctx.getWorld();
|
||||||
|
BlockPos posBelow = ctx.getPos()
|
||||||
|
.down();
|
||||||
|
BlockState stateBelow = world.getBlockState(posBelow);
|
||||||
|
if (!AllBlocks.BELT.has(stateBelow))
|
||||||
|
return state;
|
||||||
|
TileEntity teBelow = world.getTileEntity(posBelow);
|
||||||
|
if (teBelow == null || !(teBelow instanceof BeltTileEntity))
|
||||||
|
return state;
|
||||||
|
BeltTileEntity beltTileEntity = (BeltTileEntity) teBelow;
|
||||||
|
if (beltTileEntity.getSpeed() == 0)
|
||||||
|
return state;
|
||||||
|
Direction movementFacing = beltTileEntity.getMovementFacing();
|
||||||
|
Direction funnelFacing = ctx.getFace();
|
||||||
|
return state.with(PUSHING, movementFacing == funnelFacing);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void fillStateContainer(Builder<Block, BlockState> p_206840_1_) {
|
protected void fillStateContainer(Builder<Block, BlockState> p_206840_1_) {
|
||||||
super.fillStateContainer(p_206840_1_.add(SHAPE));
|
super.fillStateContainer(p_206840_1_.add(SHAPE));
|
||||||
|
|
|
@ -10,13 +10,25 @@ import net.minecraft.util.Direction;
|
||||||
import net.minecraft.util.Rotation;
|
import net.minecraft.util.Rotation;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
import net.minecraftforge.event.entity.player.PlayerInteractEvent;
|
||||||
|
import net.minecraftforge.eventbus.api.Event.Result;
|
||||||
|
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||||
|
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
|
||||||
|
|
||||||
|
@EventBusSubscriber
|
||||||
public class FunnelItem extends BlockItem {
|
public class FunnelItem extends BlockItem {
|
||||||
|
|
||||||
public FunnelItem(Block p_i48527_1_, Properties p_i48527_2_) {
|
public FunnelItem(Block p_i48527_1_, Properties p_i48527_2_) {
|
||||||
super(p_i48527_1_, p_i48527_2_);
|
super(p_i48527_1_, p_i48527_2_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public static void funnelItemAlwaysPlacesWhenUsed(PlayerInteractEvent.RightClickBlock event) {
|
||||||
|
if (event.getItemStack()
|
||||||
|
.getItem() instanceof FunnelItem)
|
||||||
|
event.setUseBlock(Result.DENY);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected BlockState getStateForPlacement(BlockItemUseContext ctx) {
|
protected BlockState getStateForPlacement(BlockItemUseContext ctx) {
|
||||||
BlockState state = super.getStateForPlacement(ctx);
|
BlockState state = super.getStateForPlacement(ctx);
|
||||||
|
|
|
@ -6,17 +6,27 @@ import com.simibubi.create.AllBlocks;
|
||||||
import com.simibubi.create.AllShapes;
|
import com.simibubi.create.AllShapes;
|
||||||
import com.simibubi.create.AllTileEntities;
|
import com.simibubi.create.AllTileEntities;
|
||||||
import com.simibubi.create.content.logistics.block.chute.ChuteBlock;
|
import com.simibubi.create.content.logistics.block.chute.ChuteBlock;
|
||||||
|
import com.simibubi.create.foundation.block.ITE;
|
||||||
import com.simibubi.create.foundation.block.ProperDirectionalBlock;
|
import com.simibubi.create.foundation.block.ProperDirectionalBlock;
|
||||||
|
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
|
||||||
|
import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour;
|
||||||
|
import com.simibubi.create.foundation.tileEntity.behaviour.inventory.InsertingBehaviour;
|
||||||
|
import com.simibubi.create.foundation.utility.VecHelper;
|
||||||
|
|
||||||
import net.minecraft.block.Block;
|
import net.minecraft.block.Block;
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.entity.item.ItemEntity;
|
||||||
import net.minecraft.item.BlockItemUseContext;
|
import net.minecraft.item.BlockItemUseContext;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.state.BooleanProperty;
|
import net.minecraft.state.BooleanProperty;
|
||||||
import net.minecraft.state.StateContainer.Builder;
|
import net.minecraft.state.StateContainer.Builder;
|
||||||
import net.minecraft.state.properties.BlockStateProperties;
|
import net.minecraft.state.properties.BlockStateProperties;
|
||||||
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.AxisDirection;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.util.math.Vec3d;
|
||||||
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;
|
||||||
|
@ -24,7 +34,7 @@ import net.minecraft.world.IWorld;
|
||||||
import net.minecraft.world.IWorldReader;
|
import net.minecraft.world.IWorldReader;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
public class RealityFunnelBlock extends ProperDirectionalBlock {
|
public class RealityFunnelBlock extends ProperDirectionalBlock implements ITE<RealityFunnelTileEntity> {
|
||||||
|
|
||||||
public static final BooleanProperty POWERED = BlockStateProperties.POWERED;
|
public static final BooleanProperty POWERED = BlockStateProperties.POWERED;
|
||||||
|
|
||||||
|
@ -48,6 +58,39 @@ public class RealityFunnelBlock extends ProperDirectionalBlock {
|
||||||
.isBlockPowered(context.getPos()));
|
.isBlockPowered(context.getPos()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onEntityCollision(BlockState state, World worldIn, BlockPos pos, Entity entityIn) {
|
||||||
|
if (worldIn.isRemote)
|
||||||
|
return;
|
||||||
|
if (!(entityIn instanceof ItemEntity))
|
||||||
|
return;
|
||||||
|
if (state.get(POWERED))
|
||||||
|
return;
|
||||||
|
ItemEntity itemEntity = (ItemEntity) entityIn;
|
||||||
|
|
||||||
|
Direction direction = state.get(FACING);
|
||||||
|
Vec3d diff = entityIn.getPositionVec()
|
||||||
|
.subtract(VecHelper.getCenterOf(pos));
|
||||||
|
double projectedDiff = direction.getAxis()
|
||||||
|
.getCoordinate(diff.x, diff.y, diff.z);
|
||||||
|
if (projectedDiff < 0 == (direction.getAxisDirection() == AxisDirection.POSITIVE))
|
||||||
|
return;
|
||||||
|
|
||||||
|
FilteringBehaviour filter = TileEntityBehaviour.get(worldIn, pos, FilteringBehaviour.TYPE);
|
||||||
|
InsertingBehaviour inserter = TileEntityBehaviour.get(worldIn, pos, InsertingBehaviour.TYPE);
|
||||||
|
if (inserter == null)
|
||||||
|
return;
|
||||||
|
ItemStack toInsert = itemEntity.getItem();
|
||||||
|
if (filter != null && !filter.test(toInsert))
|
||||||
|
return;
|
||||||
|
|
||||||
|
ItemStack remainder = inserter.insert(toInsert, false);
|
||||||
|
if (remainder.isEmpty())
|
||||||
|
itemEntity.remove();
|
||||||
|
if (remainder.getCount() < toInsert.getCount())
|
||||||
|
itemEntity.setItem(remainder);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasTileEntity(BlockState state) {
|
public boolean hasTileEntity(BlockState state) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -64,11 +107,17 @@ public class RealityFunnelBlock extends ProperDirectionalBlock {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public VoxelShape getShape(BlockState state, IBlockReader p_220053_2_, BlockPos p_220053_3_,
|
public VoxelShape getShape(BlockState state, IBlockReader world, BlockPos pos, ISelectionContext context) {
|
||||||
ISelectionContext p_220053_4_) {
|
|
||||||
return AllShapes.REALITY_FUNNEL.get(state.get(FACING));
|
return AllShapes.REALITY_FUNNEL.get(state.get(FACING));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public VoxelShape getCollisionShape(BlockState state, IBlockReader world, BlockPos pos, ISelectionContext context) {
|
||||||
|
if (context.getEntity() instanceof ItemEntity)
|
||||||
|
return AllShapes.REALITY_FUNNEL_COLLISION.get(state.get(FACING));
|
||||||
|
return getShape(state, world, pos, context);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BlockState updatePostPlacement(BlockState state, Direction direction, BlockState p_196271_3_, IWorld world,
|
public BlockState updatePostPlacement(BlockState state, Direction direction, BlockState p_196271_3_, IWorld world,
|
||||||
BlockPos pos, BlockPos p_196271_6_) {
|
BlockPos pos, BlockPos p_196271_6_) {
|
||||||
|
@ -131,8 +180,7 @@ public class RealityFunnelBlock extends ProperDirectionalBlock {
|
||||||
@Override
|
@Override
|
||||||
public void onReplaced(BlockState p_196243_1_, World p_196243_2_, BlockPos p_196243_3_, BlockState p_196243_4_,
|
public void onReplaced(BlockState p_196243_1_, World p_196243_2_, BlockPos p_196243_3_, BlockState p_196243_4_,
|
||||||
boolean p_196243_5_) {
|
boolean p_196243_5_) {
|
||||||
if (p_196243_1_.hasTileEntity()
|
if (p_196243_1_.hasTileEntity() && (p_196243_1_.getBlock() != p_196243_4_.getBlock() && !isFunnel(p_196243_4_)
|
||||||
&& (p_196243_1_.getBlock() != p_196243_4_.getBlock() && !isFunnel(p_196243_4_)
|
|
||||||
|| !p_196243_4_.hasTileEntity())) {
|
|| !p_196243_4_.hasTileEntity())) {
|
||||||
p_196243_2_.removeTileEntity(p_196243_3_);
|
p_196243_2_.removeTileEntity(p_196243_3_);
|
||||||
}
|
}
|
||||||
|
@ -144,4 +192,9 @@ public class RealityFunnelBlock extends ProperDirectionalBlock {
|
||||||
|| state.getBlock() instanceof HorizontalInteractionFunnelBlock;
|
|| state.getBlock() instanceof HorizontalInteractionFunnelBlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<RealityFunnelTileEntity> getTileEntityClass() {
|
||||||
|
return RealityFunnelTileEntity.class;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,31 +1,130 @@
|
||||||
package com.simibubi.create.content.logistics.block.realityFunnel;
|
package com.simibubi.create.content.logistics.block.realityFunnel;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
|
|
||||||
|
import com.simibubi.create.AllBlocks;
|
||||||
|
import com.simibubi.create.content.contraptions.relays.belt.transport.TransportedItemStack;
|
||||||
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.belt.DirectBeltInputBehaviour;
|
||||||
|
import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour;
|
||||||
import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour;
|
import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour;
|
||||||
|
import com.simibubi.create.foundation.tileEntity.behaviour.inventory.ExtractingBehaviour;
|
||||||
import com.simibubi.create.foundation.tileEntity.behaviour.inventory.InsertingBehaviour;
|
import com.simibubi.create.foundation.tileEntity.behaviour.inventory.InsertingBehaviour;
|
||||||
import com.simibubi.create.foundation.tileEntity.behaviour.inventory.InventoryManagementBehaviour.Attachments;
|
import com.simibubi.create.foundation.tileEntity.behaviour.inventory.InventoryManagementBehaviour.Attachments;
|
||||||
|
|
||||||
|
import net.minecraft.block.BlockState;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.state.properties.BlockStateProperties;
|
||||||
import net.minecraft.tileentity.TileEntityType;
|
import net.minecraft.tileentity.TileEntityType;
|
||||||
|
import net.minecraft.util.Direction;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
|
||||||
public class RealityFunnelTileEntity extends SmartTileEntity {
|
public class RealityFunnelTileEntity extends SmartTileEntity {
|
||||||
|
|
||||||
private FilteringBehaviour filtering;
|
private FilteringBehaviour filtering;
|
||||||
private InsertingBehaviour inserting;
|
private InsertingBehaviour inserting;
|
||||||
|
private ExtractingBehaviour extracting;
|
||||||
|
|
||||||
|
static enum Mode {
|
||||||
|
INVALID, PAUSED, COLLECT, BELT, CHUTE_SIDE, CHUTE_END
|
||||||
|
}
|
||||||
|
|
||||||
public RealityFunnelTileEntity(TileEntityType<?> tileEntityTypeIn) {
|
public RealityFunnelTileEntity(TileEntityType<?> tileEntityTypeIn) {
|
||||||
super(tileEntityTypeIn);
|
super(tileEntityTypeIn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Mode determineCurrentMode() {
|
||||||
|
BlockState state = getBlockState();
|
||||||
|
if (!RealityFunnelBlock.isFunnel(state))
|
||||||
|
return Mode.INVALID;
|
||||||
|
if (state.get(BlockStateProperties.POWERED))
|
||||||
|
return Mode.PAUSED;
|
||||||
|
if (AllBlocks.BELT_FUNNEL.has(state))
|
||||||
|
return Mode.BELT;
|
||||||
|
if (AllBlocks.CHUTE_FUNNEL.has(state))
|
||||||
|
return Mode.CHUTE_SIDE;
|
||||||
|
|
||||||
|
Direction facing = RealityFunnelBlock.getFunnelFacing(state);
|
||||||
|
BlockState input = world.getBlockState(pos.offset(facing));
|
||||||
|
|
||||||
|
if (AllBlocks.CHUTE.has(input))
|
||||||
|
return Mode.CHUTE_END;
|
||||||
|
return Mode.COLLECT;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tick() {
|
||||||
|
super.tick();
|
||||||
|
Mode mode = determineCurrentMode();
|
||||||
|
if (mode == Mode.BELT)
|
||||||
|
tickAsBeltFunnel();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void tickAsBeltFunnel() {
|
||||||
|
BlockState blockState = getBlockState();
|
||||||
|
Direction facing = blockState.get(BeltFunnelBlock.HORIZONTAL_FACING);
|
||||||
|
if (world.isRemote)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!blockState.get(BeltFunnelBlock.PUSHING)) {
|
||||||
|
// Belts handle insertion from their side
|
||||||
|
if (AllBlocks.BELT.has(world.getBlockState(pos.down())))
|
||||||
|
return;
|
||||||
|
TransportedItemStackHandlerBehaviour handler =
|
||||||
|
TileEntityBehaviour.get(world, pos.down(), TransportedItemStackHandlerBehaviour.TYPE);
|
||||||
|
if (handler == null)
|
||||||
|
return;
|
||||||
|
handler.handleCenteredProcessingOnAllItems(1 / 32f, this::collectFromHandler);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DirectBeltInputBehaviour inputBehaviour =
|
||||||
|
TileEntityBehaviour.get(world, pos.down(), DirectBeltInputBehaviour.TYPE);
|
||||||
|
if (inputBehaviour == null)
|
||||||
|
return;
|
||||||
|
if (!inputBehaviour.canInsertFromSide(facing))
|
||||||
|
return;
|
||||||
|
|
||||||
|
extracting.setCallback(stack -> inputBehaviour.handleInsertion(stack, facing, false));
|
||||||
|
extracting.withAdditionalFilter(stack -> inputBehaviour.handleInsertion(stack, facing, true)
|
||||||
|
.isEmpty());
|
||||||
|
extracting.extract();
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<TransportedItemStack> collectFromHandler(TransportedItemStack stack) {
|
||||||
|
ItemStack toInsert = stack.stack.copy();
|
||||||
|
if (!filtering.test(toInsert))
|
||||||
|
return null;
|
||||||
|
ItemStack remainder = inserting.insert(toInsert, false);
|
||||||
|
if (remainder.equals(stack.stack, false))
|
||||||
|
return null;
|
||||||
|
List<TransportedItemStack> list = new ArrayList<>();
|
||||||
|
if (remainder.isEmpty())
|
||||||
|
return list;
|
||||||
|
TransportedItemStack changed = stack.copy();
|
||||||
|
changed.stack = remainder;
|
||||||
|
list.add(changed);
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addBehaviours(List<TileEntityBehaviour> behaviours) {
|
public void addBehaviours(List<TileEntityBehaviour> behaviours) {
|
||||||
|
Supplier<List<Pair<BlockPos, Direction>>> direction =
|
||||||
|
Attachments.toward(() -> RealityFunnelBlock.getFunnelFacing(getBlockState())
|
||||||
|
.getOpposite());
|
||||||
|
|
||||||
|
inserting = new InsertingBehaviour(this, direction);
|
||||||
|
extracting = new ExtractingBehaviour(this, direction);
|
||||||
filtering = new FilteringBehaviour(this, new FunnelFilterSlotPositioning());
|
filtering = new FilteringBehaviour(this, new FunnelFilterSlotPositioning());
|
||||||
|
|
||||||
behaviours.add(filtering);
|
behaviours.add(filtering);
|
||||||
inserting =
|
|
||||||
new InsertingBehaviour(this, Attachments.toward(() -> RealityFunnelBlock.getFunnelFacing(getBlockState())));
|
|
||||||
behaviours.add(inserting);
|
behaviours.add(inserting);
|
||||||
|
behaviours.add(extracting);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -29,7 +29,12 @@ public class TransportedItemStackHandlerBehaviour extends TileEntityBehaviour {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handleProcessingOnAllItems(Function<TransportedItemStack, List<TransportedItemStack>> processFunction) {
|
public void handleProcessingOnAllItems(Function<TransportedItemStack, List<TransportedItemStack>> processFunction) {
|
||||||
this.processingCallback.applyToAllItems(processFunction);
|
handleCenteredProcessingOnAllItems(.51f, processFunction);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleCenteredProcessingOnAllItems(float maxDistanceFromCenter,
|
||||||
|
Function<TransportedItemStack, List<TransportedItemStack>> processFunction) {
|
||||||
|
this.processingCallback.applyToAllItems(maxDistanceFromCenter, processFunction);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Vec3d getWorldPositionOf(TransportedItemStack transported) {
|
public Vec3d getWorldPositionOf(TransportedItemStack transported) {
|
||||||
|
@ -43,7 +48,8 @@ public class TransportedItemStackHandlerBehaviour extends TileEntityBehaviour {
|
||||||
|
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
public interface ProcessingCallback {
|
public interface ProcessingCallback {
|
||||||
public void applyToAllItems(Function<TransportedItemStack, List<TransportedItemStack>> processFunction);
|
public void applyToAllItems(float maxDistanceFromCenter,
|
||||||
|
Function<TransportedItemStack, List<TransportedItemStack>> processFunction);
|
||||||
}
|
}
|
||||||
|
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
|
|
|
@ -27,6 +27,11 @@ public class ExtractingBehaviour extends InventoryManagementBehaviour {
|
||||||
private Predicate<ItemStack> customFilter;
|
private Predicate<ItemStack> customFilter;
|
||||||
private Consumer<ItemStack> callback;
|
private Consumer<ItemStack> callback;
|
||||||
|
|
||||||
|
public ExtractingBehaviour(SmartTileEntity te, Supplier<List<Pair<BlockPos, Direction>>> attachments) {
|
||||||
|
this(te, attachments, item -> {
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public ExtractingBehaviour(SmartTileEntity te, Supplier<List<Pair<BlockPos, Direction>>> attachments,
|
public ExtractingBehaviour(SmartTileEntity te, Supplier<List<Pair<BlockPos, Direction>>> attachments,
|
||||||
Consumer<ItemStack> onExtract) {
|
Consumer<ItemStack> onExtract) {
|
||||||
super(te, attachments);
|
super(te, attachments);
|
||||||
|
|
Loading…
Reference in a new issue