Omnidirectional Crushing

-Fix directionality of horizontally placed crushing wheels.
-Allow crushing wheels to work omnidirectionally
-Allow downwards crushers to deposit directly into belts/chutes/depots and such below.
-Allow horizontal crushers to take input from belts going below them.
-Allow horizontal crushers to deposit directly into belts/chutes/depots and such placed below, offset by one in the output direction.
-Crushers stall when they have a valid output block but cannot actually output.
-Crushers outputting in any direction except down will shoot out the item entities with some speed.
-Crushers can take entity input from their corresponding input directions rather than just up. However, outputting the entity drops in the right location does currently not work consistently.
This commit is contained in:
_0Steven 2021-01-24 16:46:07 +01:00
parent 667f27d9b7
commit cb25c5ab21
6 changed files with 281 additions and 74 deletions

View File

@ -111,7 +111,10 @@ public class AllShapes {
.forHorizontal(Direction.SOUTH), .forHorizontal(Direction.SOUTH),
PUMP = shape(2, 0, 2, 14, 5, 14).add(4, 0, 4, 12, 16, 12) PUMP = shape(2, 0, 2, 14, 5, 14).add(4, 0, 4, 12, 16, 12)
.add(3, 12, 3, 13, 16, 13) .add(3, 12, 3, 13, 16, 13)
.forDirectional(Direction.UP) .forDirectional(Direction.UP),
CRUSHING_WHEEL_CONTROLLER_COLLISION = shape(0, 0, 0, 16, 13, 16)
.forDirectional(Direction.DOWN)
; ;
@ -147,7 +150,8 @@ public class AllShapes {
HEATER_BLOCK_SHAPE = shape(2, 0, 2, 14, 14, 14).add(0, 0, 0, 16, 4, 16) HEATER_BLOCK_SHAPE = shape(2, 0, 2, 14, 14, 14).add(0, 0, 0, 16, 4, 16)
.build(), .build(),
HEATER_BLOCK_SPECIAL_COLLISION_SHAPE = shape(0, 0, 0, 16, 4, 16).build(), HEATER_BLOCK_SPECIAL_COLLISION_SHAPE = shape(0, 0, 0, 16, 4, 16).build(),
CRUSHING_WHEEL_COLLISION_SHAPE = cuboid(0, 0, 0, 16, 22, 16), SEAT = cuboid(0, 0, 0, 16, 8, 16), CRUSHING_WHEEL_COLLISION_SHAPE = cuboid(0, 0, 0, 16, 16, 16),
SEAT = cuboid(0, 0, 0, 16, 8, 16),
SEAT_COLLISION = cuboid(0, 0, 0, 16, 6, 16), SEAT_COLLISION = cuboid(0, 0, 0, 16, 6, 16),
MECHANICAL_PROCESSOR_SHAPE = shape(VoxelShapes.fullCube()).erase(4, 0, 4, 12, 16, 12) MECHANICAL_PROCESSOR_SHAPE = shape(VoxelShapes.fullCube()).erase(4, 0, 4, 12, 16, 12)
.build(), .build(),

View File

@ -1,6 +1,7 @@
package com.simibubi.create.content.contraptions.components.crusher; package com.simibubi.create.content.contraptions.components.crusher;
import static com.simibubi.create.content.contraptions.components.crusher.CrushingWheelControllerBlock.VALID; import static com.simibubi.create.content.contraptions.components.crusher.CrushingWheelControllerBlock.VALID;
import static com.simibubi.create.content.contraptions.components.crusher.CrushingWheelControllerBlock.FACING;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllShapes; import com.simibubi.create.AllShapes;
@ -17,6 +18,7 @@ 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.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.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;
@ -53,7 +55,7 @@ public class CrushingWheelBlock extends RotatedPillarKineticBlock implements ITE
@Override @Override
public void onReplaced(BlockState state, World worldIn, BlockPos pos, BlockState newState, boolean isMoving) { public void onReplaced(BlockState state, World worldIn, BlockPos pos, BlockState newState, boolean isMoving) {
for (Direction d : Iterate.horizontalDirections) { for (Direction d : Iterate.directions) {
if (d.getAxis() == state.get(AXIS)) if (d.getAxis() == state.get(AXIS))
continue; continue;
if (AllBlocks.CRUSHING_WHEEL_CONTROLLER.has(worldIn.getBlockState(pos.offset(d)))) if (AllBlocks.CRUSHING_WHEEL_CONTROLLER.has(worldIn.getBlockState(pos.offset(d))))
@ -65,21 +67,26 @@ public class CrushingWheelBlock extends RotatedPillarKineticBlock implements ITE
} }
} }
public void updateControllers(BlockState state, World world, BlockPos pos, Direction facing) { public void updateControllers(BlockState state, World world, BlockPos pos, Direction side) {
if (facing.getAxis() == state.get(AXIS) || facing.getAxis() if (side.getAxis() == state.get(AXIS))
.isVertical())
return; return;
if (world == null) if (world == null)
return; return;
BlockPos controllerPos = pos.offset(facing); BlockPos controllerPos = pos.offset(side);
BlockPos otherWheelPos = pos.offset(facing, 2); BlockPos otherWheelPos = pos.offset(side, 2);
boolean controllerExists = AllBlocks.CRUSHING_WHEEL_CONTROLLER.has(world.getBlockState(controllerPos)); boolean controllerExists = AllBlocks.CRUSHING_WHEEL_CONTROLLER.has(world.getBlockState(controllerPos));
boolean controllerIsValid = controllerExists && world.getBlockState(controllerPos) boolean controllerIsValid = controllerExists && world.getBlockState(controllerPos)
.get(VALID); .get(VALID);
Direction controllerOldDirection = controllerExists
? world.getBlockState(controllerPos)
.get(FACING)
: null;
boolean controllerShouldExist = false; boolean controllerShouldExist = false;
boolean controllerShouldBeValid = false; boolean controllerShouldBeValid = false;
Direction controllerNewDirection = Direction.DOWN;
BlockState otherState = world.getBlockState(otherWheelPos); BlockState otherState = world.getBlockState(otherWheelPos);
if (AllBlocks.CRUSHING_WHEEL.has(otherState)) { if (AllBlocks.CRUSHING_WHEEL.has(otherState)) {
@ -90,10 +97,22 @@ public class CrushingWheelBlock extends RotatedPillarKineticBlock implements ITE
CrushingWheelTileEntity otherTe = getTileEntity(world, otherWheelPos); CrushingWheelTileEntity otherTe = getTileEntity(world, otherWheelPos);
if (te != null && otherTe != null && (te.getSpeed() > 0) != (otherTe.getSpeed() > 0) if (te != null && otherTe != null && (te.getSpeed() > 0) != (otherTe.getSpeed() > 0)
&& te.getSpeed() != 0) { && te.getSpeed() != 0) {
float signum = Math.signum(te.getSpeed()) * (state.get(AXIS) == Axis.X ? -1 : 1); Axis wheelAxis = state.get(AXIS);
controllerShouldBeValid = facing.getAxisDirection() Axis sideAxis = side.getAxis();
.getOffset() != signum; int controllerADO = Math.round(Math.signum(te.getSpeed())) * side.getAxisDirection().getOffset();
Vec3d controllerDirVec = new Vec3d(wheelAxis == Axis.X ? 1 : 0
, wheelAxis == Axis.Y ? 1 : 0
, wheelAxis == Axis.Z ? 1 : 0)
.crossProduct(new Vec3d(sideAxis == Axis.X ? 1 : 0
, sideAxis == Axis.Y ? 1 : 0
, sideAxis == Axis.Z ? 1 : 0));
controllerNewDirection = Direction.getFacingFromVector(controllerDirVec.x * controllerADO
, controllerDirVec.y * controllerADO
, controllerDirVec.z * controllerADO);
controllerShouldBeValid = true;
} }
if (otherState.get(AXIS) != state.get(AXIS)) if (otherState.get(AXIS) != state.get(AXIS))
controllerShouldExist = false; controllerShouldExist = false;
@ -111,18 +130,20 @@ public class CrushingWheelBlock extends RotatedPillarKineticBlock implements ITE
if (!controllerExists) { if (!controllerExists) {
if (!world.getBlockState(controllerPos) if (!world.getBlockState(controllerPos)
.getMaterial() .getMaterial()
.isReplaceable()) .isReplaceable())
return; return;
world.setBlockState(controllerPos, AllBlocks.CRUSHING_WHEEL_CONTROLLER.getDefaultState() world.setBlockState(controllerPos, AllBlocks.CRUSHING_WHEEL_CONTROLLER.getDefaultState()
.with(VALID, controllerShouldBeValid)); .with(VALID, controllerShouldBeValid)
} else if (controllerIsValid != controllerShouldBeValid) { .with(FACING, controllerNewDirection));
} else if (controllerIsValid != controllerShouldBeValid || controllerOldDirection != controllerNewDirection) {
world.setBlockState(controllerPos, world.getBlockState(controllerPos) world.setBlockState(controllerPos, world.getBlockState(controllerPos)
.with(VALID, controllerShouldBeValid)); .with(VALID, controllerShouldBeValid)
.with(FACING, controllerNewDirection));
} }
((CrushingWheelControllerBlock) AllBlocks.CRUSHING_WHEEL_CONTROLLER.get()) ((CrushingWheelControllerBlock) AllBlocks.CRUSHING_WHEEL_CONTROLLER.get())
.updateSpeed(world.getBlockState(controllerPos), world, controllerPos); .updateSpeed(world.getBlockState(controllerPos), world, controllerPos);
} }

View File

@ -3,6 +3,7 @@ package com.simibubi.create.content.contraptions.components.crusher;
import java.util.Random; import java.util.Random;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllShapes;
import com.simibubi.create.AllTileEntities; import com.simibubi.create.AllTileEntities;
import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.base.KineticTileEntity;
import com.simibubi.create.foundation.block.ITE; import com.simibubi.create.foundation.block.ITE;
@ -11,6 +12,7 @@ import com.simibubi.create.foundation.utility.Iterate;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.DirectionalBlock;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.item.ItemEntity; import net.minecraft.entity.item.ItemEntity;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
@ -23,7 +25,7 @@ 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.math.AxisAlignedBB; 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.util.math.shapes.ISelectionContext; import net.minecraft.util.math.shapes.ISelectionContext;
@ -34,7 +36,7 @@ import net.minecraft.world.IBlockReader;
import net.minecraft.world.IWorld; import net.minecraft.world.IWorld;
import net.minecraft.world.World; import net.minecraft.world.World;
public class CrushingWheelControllerBlock extends Block public class CrushingWheelControllerBlock extends DirectionalBlock
implements ITE<CrushingWheelControllerTileEntity> { implements ITE<CrushingWheelControllerTileEntity> {
public CrushingWheelControllerBlock(Properties p_i48440_1_) { public CrushingWheelControllerBlock(Properties p_i48440_1_) {
@ -66,27 +68,40 @@ public class CrushingWheelControllerBlock extends Block
@Override @Override
protected void fillStateContainer(Builder<Block, BlockState> builder) { protected void fillStateContainer(Builder<Block, BlockState> builder) {
builder.add(VALID); builder.add(VALID);
builder.add(FACING);
super.fillStateContainer(builder); super.fillStateContainer(builder);
} }
public void onEntityCollision(BlockState state, World worldIn, BlockPos pos, Entity entityIn) { public void onEntityCollision(BlockState state, World worldIn, BlockPos pos, Entity entityIn) {
if (!state.get(VALID)) if (!state.get(VALID))
return; return;
Direction facing = state.get(FACING);
Axis axis = facing.getAxis();
checkEntityForProcessing(worldIn, pos, entityIn);
withTileEntityDo(worldIn, pos, te -> { withTileEntityDo(worldIn, pos, te -> {
if (te.processingEntity == entityIn) if (te.processingEntity == entityIn)
entityIn.setMotionMultiplier(state, new Vec3d(0.25D, (double) 0.05F, 0.25D));
entityIn.setMotionMultiplier(state, new Vec3d(axis == Axis.X ? (double) 0.05F : 0.25D
, axis == Axis.Y ? (double) 0.05F : 0.25D
, axis == Axis.Z ? (double) 0.05F : 0.25D));
}); });
} }
@Override public void checkEntityForProcessing(World worldIn, BlockPos pos, Entity entityIn){
public void onLanded(IBlockReader worldIn, Entity entityIn) {
super.onLanded(worldIn, entityIn);
try { try {
CrushingWheelControllerTileEntity te = getTileEntity(worldIn, entityIn.getPosition().down()); CrushingWheelControllerTileEntity te = getTileEntity(worldIn, pos);
if (te.crushingspeed == 0) if (te.crushingspeed == 0)
return; return;
if (entityIn instanceof ItemEntity) if (entityIn instanceof ItemEntity)
((ItemEntity) entityIn).setPickupDelay(10); ((ItemEntity) entityIn).setPickupDelay(10);
CompoundNBT data = entityIn.getPersistentData();
if (data.contains("BypassCrushingWheel")) {
if (pos.equals(NBTUtil.readBlockPos(data.getCompound("BypassCrushingWheel"))))
return;
}
if (te.isOccupied()) if (te.isOccupied())
return; return;
boolean isPlayer = entityIn instanceof PlayerEntity; boolean isPlayer = entityIn instanceof PlayerEntity;
@ -99,6 +114,12 @@ public class CrushingWheelControllerBlock extends Block
} catch (TileEntityException e) {} } catch (TileEntityException e) {}
} }
@Override
public void onLanded(IBlockReader worldIn, Entity entityIn) {
super.onLanded(worldIn, entityIn);
//Moved to onEntityCollision to allow for omnidirectional input
}
@Override @Override
public void animateTick(BlockState stateIn, World worldIn, BlockPos pos, Random rand) { public void animateTick(BlockState stateIn, World worldIn, BlockPos pos, Random rand) {
if (!stateIn.get(VALID)) if (!stateIn.get(VALID))
@ -128,7 +149,7 @@ public class CrushingWheelControllerBlock extends Block
return; return;
} }
for (Direction d : Iterate.horizontalDirections) { for (Direction d : Iterate.directions) {
BlockState neighbour = world.getBlockState(pos.offset(d)); BlockState neighbour = world.getBlockState(pos.offset(d));
if (!AllBlocks.CRUSHING_WHEEL.has(neighbour)) if (!AllBlocks.CRUSHING_WHEEL.has(neighbour))
continue; continue;
@ -144,22 +165,19 @@ public class CrushingWheelControllerBlock extends Block
@Override @Override
public VoxelShape getCollisionShape(BlockState state, IBlockReader worldIn, BlockPos pos, public VoxelShape getCollisionShape(BlockState state, IBlockReader worldIn, BlockPos pos,
ISelectionContext context) { ISelectionContext context) {
if (!state.get(VALID)) if (!state.get(VALID))
return VoxelShapes.fullCube(); return AllShapes.CRUSHING_WHEEL_CONTROLLER_COLLISION.get(state.get(FACING));
Entity entity = context.getEntity(); Entity entity = context.getEntity();
if (entity != null) { if (entity != null) {
if (entity != null) {
CompoundNBT data = entity.getPersistentData();
if (data.contains("BypassCrushingWheel")) {
if (pos.equals(NBTUtil.readBlockPos(data.getCompound("BypassCrushingWheel"))))
return VoxelShapes.empty();
}
}
if (new AxisAlignedBB(pos).contains(entity.getPositionVec())) CompoundNBT data = entity.getPersistentData();
return VoxelShapes.empty(); if (data.contains("BypassCrushingWheel")) {
if (pos.equals(NBTUtil.readBlockPos(data.getCompound("BypassCrushingWheel"))))
if (state.get(FACING) != Direction.UP) //Allow output items to land on top of the block rather than falling back through.
return VoxelShapes.empty();
}
try { try {
CrushingWheelControllerTileEntity te = getTileEntity(worldIn, pos); CrushingWheelControllerTileEntity te = getTileEntity(worldIn, pos);
@ -167,7 +185,7 @@ public class CrushingWheelControllerBlock extends Block
return VoxelShapes.empty(); return VoxelShapes.empty();
} catch (TileEntityException e) {} } catch (TileEntityException e) {}
} }
return VoxelShapes.fullCube(); return AllShapes.CRUSHING_WHEEL_CONTROLLER_COLLISION.get(state.get(FACING));
} }
@Override @Override

View File

@ -6,6 +6,8 @@ import java.util.Optional;
import java.util.Random; import java.util.Random;
import java.util.UUID; import java.util.UUID;
import static com.simibubi.create.content.contraptions.components.crusher.CrushingWheelControllerBlock.FACING;
import com.simibubi.create.AllRecipeTypes; import com.simibubi.create.AllRecipeTypes;
import com.simibubi.create.content.contraptions.processing.ProcessingInventory; import com.simibubi.create.content.contraptions.processing.ProcessingInventory;
import com.simibubi.create.content.contraptions.processing.ProcessingRecipe; import com.simibubi.create.content.contraptions.processing.ProcessingRecipe;
@ -16,6 +18,7 @@ import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
import com.simibubi.create.foundation.tileEntity.behaviour.belt.DirectBeltInputBehaviour; import com.simibubi.create.foundation.tileEntity.behaviour.belt.DirectBeltInputBehaviour;
import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.block.BlockState;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.item.ItemEntity; import net.minecraft.entity.item.ItemEntity;
import net.minecraft.item.BlockItem; import net.minecraft.item.BlockItem;
@ -28,7 +31,9 @@ import net.minecraft.particles.ItemParticleData;
import net.minecraft.particles.ParticleTypes; import net.minecraft.particles.ParticleTypes;
import net.minecraft.tileentity.TileEntityType; import net.minecraft.tileentity.TileEntityType;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.Capability;
@ -63,7 +68,15 @@ public class CrushingWheelControllerTileEntity extends SmartTileEntity {
@Override @Override
public void addBehaviours(List<TileEntityBehaviour> behaviours) { public void addBehaviours(List<TileEntityBehaviour> behaviours) {
behaviours.add(new DirectBeltInputBehaviour(this)); behaviours.add(new DirectBeltInputBehaviour(this).onlyInsertWhen(this::supportsDirectBeltInput));
}
private boolean supportsDirectBeltInput(Direction side) {
BlockState blockState = getBlockState();
if (blockState == null)
return false;
Direction direction = blockState.get(CrushingWheelControllerBlock.FACING);
return direction == Direction.DOWN || direction == side;
} }
@Override @Override
@ -72,26 +85,37 @@ public class CrushingWheelControllerTileEntity extends SmartTileEntity {
if (searchForEntity) { if (searchForEntity) {
searchForEntity = false; searchForEntity = false;
List<Entity> search = world.getEntitiesInAABBexcluding(null, new AxisAlignedBB(getPos()), List<Entity> search = world.getEntitiesInAABBexcluding(null, new AxisAlignedBB(getPos()),
e -> entityUUID.equals(e.getUniqueID())); e -> entityUUID.equals(e.getUniqueID()));
if (search.isEmpty()) if (search.isEmpty())
clear(); clear();
else else
processingEntity = search.get(0); processingEntity = search.get(0);
} }
if (!isOccupied()) if (!isOccupied())
return; return;
if (crushingspeed == 0) if (crushingspeed == 0)
return; return;
float speed = crushingspeed * 4; float speed = crushingspeed * 4;
Vec3d outPos = VecHelper.getCenterOf(pos);
Vec3d centerPos = VecHelper.getCenterOf(pos);
Direction facing = getBlockState().get(FACING);
int offset = facing.getAxisDirection().getOffset();
Vec3d outSpeed = new Vec3d((facing.getAxis() == Axis.X ? 0.25D : 0.0D) * offset
, offset == 1 ? (facing.getAxis() == Axis.Y ? 0.5D : 0.0D) : 0.0D //Increased upwards speed so upwards crushing wheels shoot out the item properly.
, (facing.getAxis() == Axis.Z ? 0.25D : 0.0D) * offset); //No downwards speed, so downwards crushing wheels drop the items as before.
Vec3d outPos = centerPos.add((facing.getAxis() == Axis.X ? .55f * offset : 0f)
, (facing.getAxis() == Axis.Y ? .55f * offset : 0f)
, (facing.getAxis() == Axis.Z ? .55f * offset : 0f));
if (!hasEntity()) { if (!hasEntity()) {
float processingSpeed = float processingSpeed =
MathHelper.clamp((speed) / (!inventory.appliedRecipe ? MathHelper.log2(inventory.getStackInSlot(0) MathHelper.clamp((speed) / (!inventory.appliedRecipe ? MathHelper.log2(inventory.getStackInSlot(0)
.getCount()) : 1), .25f, 20); .getCount()) : 1), .25f, 20);
inventory.remainingTime -= processingSpeed; inventory.remainingTime -= processingSpeed;
spawnParticles(inventory.getStackInSlot(0)); spawnParticles(inventory.getStackInSlot(0));
@ -105,61 +129,111 @@ public class CrushingWheelControllerTileEntity extends SmartTileEntity {
return; return;
} }
if (inventory.remainingTime <= 0) { if (inventory.remainingTime > 0) {
for (int slot = 0; slot < inventory.getSlots(); slot++) {
ItemStack stack = inventory.getStackInSlot(slot);
if (stack.isEmpty())
continue;
ItemEntity entityIn = new ItemEntity(world, outPos.x, outPos.y, outPos.z, stack);
entityIn.setMotion(Vec3d.ZERO);
entityIn.getPersistentData()
.put("BypassCrushingWheel", NBTUtil.writeBlockPos(pos));
world.addEntity(entityIn);
}
inventory.clear();
world.notifyBlockUpdate(pos, getBlockState(), getBlockState(), 2 | 16);
return; return;
} }
inventory.remainingTime = 0;
//Output Items
if (facing.getAxis().isHorizontal() || facing == Direction.DOWN) {
BlockPos nextPos = pos.add(facing.getAxis() == Axis.X ? 1f * offset : 0f
, (facing == Direction.DOWN || facing.getAxis().isHorizontal()) ? -1f : 0f
, facing.getAxis() == Axis.Z ? 1f * offset : 0f);
DirectBeltInputBehaviour behaviour = TileEntityBehaviour.get(world, nextPos, DirectBeltInputBehaviour.TYPE);
if (behaviour != null) {
boolean changed = false;
if (!behaviour.canInsertFromSide(facing))
return;
for (int slot = 0; slot < inventory.getSlots(); slot++) {
ItemStack stack = inventory.getStackInSlot(slot);
if (stack.isEmpty())
continue;
ItemStack remainder = behaviour.handleInsertion(stack, facing, false);
if (remainder.equals(stack, false))
continue;
inventory.setStackInSlot(slot, remainder);
changed = true;
}
if (changed) {
markDirty();
sendData();
}
return;
}
}
//Eject Items
for (int slot = 0; slot < inventory.getSlots(); slot++) {
ItemStack stack = inventory.getStackInSlot(slot);
if (stack.isEmpty())
continue;
ItemEntity entityIn = new ItemEntity(world, outPos.x, outPos.y, outPos.z, stack);
entityIn.setMotion(outSpeed);
entityIn.getPersistentData()
.put("BypassCrushingWheel", NBTUtil.writeBlockPos(pos));
world.addEntity(entityIn);
}
inventory.clear();
world.notifyBlockUpdate(pos, getBlockState(), getBlockState(), 2 | 16);
return; return;
} }
if (!processingEntity.isAlive() || !processingEntity.getBoundingBox() if (!processingEntity.isAlive() || !processingEntity.getBoundingBox()
.intersects(new AxisAlignedBB(pos).grow(.5f))) { .intersects(new AxisAlignedBB(pos).grow(.5f))) {
clear(); clear();
return; return;
} }
double xMotion = ((pos.getX() + .5f) - processingEntity.getX()) / 2f; double xMotion = ((pos.getX() + .5f) - processingEntity.getX()) / 2f;
double yMotion = ((pos.getY() + .5f) - processingEntity.getY()) / 2f;
double zMotion = ((pos.getZ() + .5f) - processingEntity.getZ()) / 2f; double zMotion = ((pos.getZ() + .5f) - processingEntity.getZ()) / 2f;
if (processingEntity.isSneaking()) if (processingEntity.isSneaking())
xMotion = zMotion = 0; xMotion = zMotion = 0;
double movement = Math.max(-speed / 4f, -.5f) * -offset;
processingEntity.setMotion(new Vec3d(xMotion, Math.max(-speed / 4f, -.5f), zMotion)); processingEntity.setMotion(new Vec3d(facing.getAxis() == Axis.X ? movement : xMotion
, facing.getAxis() == Axis.Y ? movement : 0f //Do not move entities upwards or downwards for horizontal crushers,
, facing.getAxis() == Axis.Z ? movement : zMotion)); //Or they'll only get their feet crushed.
if (world.isRemote) if (world.isRemote)
return; return;
if (!(processingEntity instanceof ItemEntity)) { if (!(processingEntity instanceof ItemEntity)) {
processingEntity.attackEntityFrom(CrushingWheelTileEntity.damageSource, processingEntity.attackEntityFrom(CrushingWheelTileEntity.damageSource,
AllConfigs.SERVER.kinetics.crushingDamage.get()); AllConfigs.SERVER.kinetics.crushingDamage.get());
if (!processingEntity.isAlive()) { if (!processingEntity.isAlive()) {
processingEntity.setPosition(outPos.x, outPos.y - .75f, outPos.z); processingEntity.setPosition(outPos.x + (facing.getAxis() == Axis.X ? .75f * offset : 0f) //This is supposed to move the mobs to the output location
, outPos.y + (facing.getAxis() == Axis.Y ? .75f * offset : 0f) //So the item drops end up on the other end
, outPos.z + (facing.getAxis() == Axis.Z ? .75f * offset : 0f)); //This, however, does not currently work consistently for non-downwards crushers.
} }
return; return;
} }
ItemEntity itemEntity = (ItemEntity) processingEntity; ItemEntity itemEntity = (ItemEntity) processingEntity;
itemEntity.setPickupDelay(20); itemEntity.setPickupDelay(20);
if (processingEntity.getY() < pos.getY() + .25f) { if (facing.getAxis() == Axis.Y) {
inventory.clear(); if (processingEntity.getY() * -offset < (centerPos.y - .25f) * -offset) {
inventory.setStackInSlot(0, itemEntity.getItem() intakeItem(itemEntity);
.copy()); }
itemInserted(inventory.getStackInSlot(0)); } else if (facing.getAxis() == Axis.Z) {
itemEntity.remove(); if (processingEntity.getZ() * -offset < (centerPos.z - .25f) * -offset) {
world.notifyBlockUpdate(pos, getBlockState(), getBlockState(), 2 | 16); intakeItem(itemEntity);
}
} else {
if (processingEntity.getX() * -offset < (centerPos.x - .25f) * -offset) {
intakeItem(itemEntity);
}
} }
}
private void intakeItem(ItemEntity itemEntity) {
inventory.clear();
inventory.setStackInSlot(0, itemEntity.getItem()
.copy());
itemInserted(inventory.getStackInSlot(0));
itemEntity.remove();
world.notifyBlockUpdate(pos, getBlockState(), getBlockState(), 2 | 16);
} }
protected void spawnParticles(ItemStack stack) { protected void spawnParticles(ItemStack stack) {
@ -169,14 +243,14 @@ public class CrushingWheelControllerTileEntity extends SmartTileEntity {
IParticleData particleData = null; IParticleData particleData = null;
if (stack.getItem() instanceof BlockItem) if (stack.getItem() instanceof BlockItem)
particleData = new BlockParticleData(ParticleTypes.BLOCK, ((BlockItem) stack.getItem()).getBlock() particleData = new BlockParticleData(ParticleTypes.BLOCK, ((BlockItem) stack.getItem()).getBlock()
.getDefaultState()); .getDefaultState());
else else
particleData = new ItemParticleData(ParticleTypes.ITEM, stack); particleData = new ItemParticleData(ParticleTypes.ITEM, stack);
Random r = world.rand; Random r = world.rand;
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
world.addParticle(particleData, pos.getX() + r.nextFloat(), pos.getY() + r.nextFloat(), world.addParticle(particleData, pos.getX() + r.nextFloat(), pos.getY() + r.nextFloat(),
pos.getZ() + r.nextFloat(), 0, 0, 0); pos.getZ() + r.nextFloat(), 0, 0, 0);
} }
private void applyRecipe() { private void applyRecipe() {
@ -185,11 +259,11 @@ public class CrushingWheelControllerTileEntity extends SmartTileEntity {
List<ItemStack> list = new ArrayList<>(); List<ItemStack> list = new ArrayList<>();
if (recipe.isPresent()) { if (recipe.isPresent()) {
int rolls = inventory.getStackInSlot(0) int rolls = inventory.getStackInSlot(0)
.getCount(); .getCount();
inventory.clear(); inventory.clear();
for (int roll = 0; roll < rolls; roll++) { for (int roll = 0; roll < rolls; roll++) {
List<ItemStack> rolledResults = recipe.get() List<ItemStack> rolledResults = recipe.get()
.rollResults(); .rollResults();
for (int i = 0; i < rolledResults.size(); i++) { for (int i = 0; i < rolledResults.size(); i++) {
ItemStack stack = rolledResults.get(i); ItemStack stack = rolledResults.get(i);
ItemHelper.addToList(stack, list); ItemHelper.addToList(stack, list);
@ -238,7 +312,7 @@ public class CrushingWheelControllerTileEntity extends SmartTileEntity {
private void itemInserted(ItemStack stack) { private void itemInserted(ItemStack stack) {
Optional<ProcessingRecipe<RecipeWrapper>> recipe = findRecipe(); Optional<ProcessingRecipe<RecipeWrapper>> recipe = findRecipe();
inventory.remainingTime = recipe.isPresent() ? recipe.get() inventory.remainingTime = recipe.isPresent() ? recipe.get()
.getProcessingDuration() : 100; .getProcessingDuration() : 100;
inventory.appliedRecipe = false; inventory.appliedRecipe = false;
} }

View File

@ -0,0 +1,86 @@
package com.simibubi.create.content.contraptions.relays.belt.transport;
import com.simibubi.create.content.contraptions.components.crusher.CrushingWheelControllerBlock;
import com.simibubi.create.content.contraptions.components.crusher.CrushingWheelControllerTileEntity;
import com.simibubi.create.content.contraptions.relays.belt.BeltHelper;
import net.minecraft.block.BlockState;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.World;
import net.minecraftforge.items.ItemHandlerHelper;
public class BeltCrusherInteractionHandler {
public static boolean checkForCrushers(BeltInventory beltInventory, TransportedItemStack currentItem,
float nextOffset) {
boolean beltMovementPositive = beltInventory.beltMovementPositive;
int firstUpcomingSegment = (int) Math.floor(currentItem.beltPosition);
int step = beltMovementPositive ? 1 : -1;
firstUpcomingSegment = MathHelper.clamp(firstUpcomingSegment, 0, beltInventory.belt.beltLength - 1);
for (int segment = firstUpcomingSegment; beltMovementPositive ? segment <= nextOffset
: segment + 1 >= nextOffset; segment += step) {
BlockPos crusherPos = BeltHelper.getPositionForOffset(beltInventory.belt, segment)
.up();
World world = beltInventory.belt.getWorld();
BlockState crusherState = world.getBlockState(crusherPos);
if (!(crusherState.getBlock() instanceof CrushingWheelControllerBlock))
continue;
Direction crusherFacing = crusherState.get(CrushingWheelControllerBlock.FACING);
Direction movementFacing = beltInventory.belt.getMovementFacing();
boolean blocking = crusherFacing == movementFacing;
if (crusherFacing != movementFacing)
continue;
float crusherEntry = segment + .5f;
crusherEntry += .399f * (beltMovementPositive ? -1 : 1);
boolean hasCrossed = nextOffset > crusherEntry && beltMovementPositive
|| nextOffset < crusherEntry && !beltMovementPositive;
if (!hasCrossed)
return false;
if (blocking)
currentItem.beltPosition = crusherEntry;
TileEntity te = world.getTileEntity(crusherPos);
if (!(te instanceof CrushingWheelControllerTileEntity))
return true;
CrushingWheelControllerTileEntity crusherTE = (CrushingWheelControllerTileEntity) te;
int amountToExtract = -1;
ItemStack toInsert = currentItem.stack.copy();
if (amountToExtract > toInsert.getCount())
if (blocking)
return true;
else
continue;
ItemStack remainder = ItemHandlerHelper.insertItemStacked(crusherTE.inventory, toInsert, false);
if (toInsert.equals(remainder, false))
if (blocking)
return true;
else
continue;
int notFilled = currentItem.stack.getCount() - toInsert.getCount();
if (!remainder.isEmpty()) {
remainder.grow(notFilled);
} else if (notFilled > 0)
remainder = ItemHandlerHelper.copyStackWithSize(currentItem.stack, notFilled);
currentItem.stack = remainder;
beltInventory.belt.sendData();
if (blocking)
return true;
}
return false;
}
}

View File

@ -151,6 +151,10 @@ public class BeltInventory {
if (BeltFunnelInteractionHandler.checkForFunnels(this, currentItem, nextOffset)) if (BeltFunnelInteractionHandler.checkForFunnels(this, currentItem, nextOffset))
continue; continue;
// Horizontal Crushing Wheels
if (BeltCrusherInteractionHandler.checkForCrushers(this, currentItem, nextOffset))
continue;
// Apply Movement // Apply Movement
currentItem.beltPosition += limitedMovement; currentItem.beltPosition += limitedMovement;
currentItem.sideOffset += currentItem.sideOffset +=