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),
PUMP = shape(2, 0, 2, 14, 5, 14).add(4, 0, 4, 12, 16, 12)
.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)
.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),
MECHANICAL_PROCESSOR_SHAPE = shape(VoxelShapes.fullCube()).erase(4, 0, 4, 12, 16, 12)
.build(),

View File

@ -1,6 +1,7 @@
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.FACING;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllShapes;
@ -17,6 +18,7 @@ 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.util.math.shapes.ISelectionContext;
import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.world.IBlockReader;
@ -53,7 +55,7 @@ public class CrushingWheelBlock extends RotatedPillarKineticBlock implements ITE
@Override
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))
continue;
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) {
if (facing.getAxis() == state.get(AXIS) || facing.getAxis()
.isVertical())
public void updateControllers(BlockState state, World world, BlockPos pos, Direction side) {
if (side.getAxis() == state.get(AXIS))
return;
if (world == null)
return;
BlockPos controllerPos = pos.offset(facing);
BlockPos otherWheelPos = pos.offset(facing, 2);
BlockPos controllerPos = pos.offset(side);
BlockPos otherWheelPos = pos.offset(side, 2);
boolean controllerExists = AllBlocks.CRUSHING_WHEEL_CONTROLLER.has(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 controllerShouldBeValid = false;
Direction controllerNewDirection = Direction.DOWN;
BlockState otherState = world.getBlockState(otherWheelPos);
if (AllBlocks.CRUSHING_WHEEL.has(otherState)) {
@ -90,10 +97,22 @@ public class CrushingWheelBlock extends RotatedPillarKineticBlock implements ITE
CrushingWheelTileEntity otherTe = getTileEntity(world, otherWheelPos);
if (te != null && otherTe != null && (te.getSpeed() > 0) != (otherTe.getSpeed() > 0)
&& te.getSpeed() != 0) {
float signum = Math.signum(te.getSpeed()) * (state.get(AXIS) == Axis.X ? -1 : 1);
controllerShouldBeValid = facing.getAxisDirection()
.getOffset() != signum;
&& te.getSpeed() != 0) {
Axis wheelAxis = state.get(AXIS);
Axis sideAxis = side.getAxis();
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))
controllerShouldExist = false;
@ -111,18 +130,20 @@ public class CrushingWheelBlock extends RotatedPillarKineticBlock implements ITE
if (!controllerExists) {
if (!world.getBlockState(controllerPos)
.getMaterial()
.isReplaceable())
.getMaterial()
.isReplaceable())
return;
world.setBlockState(controllerPos, AllBlocks.CRUSHING_WHEEL_CONTROLLER.getDefaultState()
.with(VALID, controllerShouldBeValid));
} else if (controllerIsValid != controllerShouldBeValid) {
.with(VALID, controllerShouldBeValid)
.with(FACING, controllerNewDirection));
} else if (controllerIsValid != controllerShouldBeValid || controllerOldDirection != controllerNewDirection) {
world.setBlockState(controllerPos, world.getBlockState(controllerPos)
.with(VALID, controllerShouldBeValid));
.with(VALID, controllerShouldBeValid)
.with(FACING, controllerNewDirection));
}
((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 com.simibubi.create.AllBlocks;
import com.simibubi.create.AllShapes;
import com.simibubi.create.AllTileEntities;
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
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.BlockState;
import net.minecraft.block.DirectionalBlock;
import net.minecraft.entity.Entity;
import net.minecraft.entity.item.ItemEntity;
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.tileentity.TileEntity;
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.Vec3d;
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.World;
public class CrushingWheelControllerBlock extends Block
public class CrushingWheelControllerBlock extends DirectionalBlock
implements ITE<CrushingWheelControllerTileEntity> {
public CrushingWheelControllerBlock(Properties p_i48440_1_) {
@ -66,27 +68,40 @@ public class CrushingWheelControllerBlock extends Block
@Override
protected void fillStateContainer(Builder<Block, BlockState> builder) {
builder.add(VALID);
builder.add(FACING);
super.fillStateContainer(builder);
}
public void onEntityCollision(BlockState state, World worldIn, BlockPos pos, Entity entityIn) {
if (!state.get(VALID))
return;
Direction facing = state.get(FACING);
Axis axis = facing.getAxis();
checkEntityForProcessing(worldIn, pos, entityIn);
withTileEntityDo(worldIn, pos, te -> {
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 onLanded(IBlockReader worldIn, Entity entityIn) {
super.onLanded(worldIn, entityIn);
public void checkEntityForProcessing(World worldIn, BlockPos pos, Entity entityIn){
try {
CrushingWheelControllerTileEntity te = getTileEntity(worldIn, entityIn.getPosition().down());
CrushingWheelControllerTileEntity te = getTileEntity(worldIn, pos);
if (te.crushingspeed == 0)
return;
if (entityIn instanceof ItemEntity)
((ItemEntity) entityIn).setPickupDelay(10);
CompoundNBT data = entityIn.getPersistentData();
if (data.contains("BypassCrushingWheel")) {
if (pos.equals(NBTUtil.readBlockPos(data.getCompound("BypassCrushingWheel"))))
return;
}
if (te.isOccupied())
return;
boolean isPlayer = entityIn instanceof PlayerEntity;
@ -99,6 +114,12 @@ public class CrushingWheelControllerBlock extends Block
} catch (TileEntityException e) {}
}
@Override
public void onLanded(IBlockReader worldIn, Entity entityIn) {
super.onLanded(worldIn, entityIn);
//Moved to onEntityCollision to allow for omnidirectional input
}
@Override
public void animateTick(BlockState stateIn, World worldIn, BlockPos pos, Random rand) {
if (!stateIn.get(VALID))
@ -128,7 +149,7 @@ public class CrushingWheelControllerBlock extends Block
return;
}
for (Direction d : Iterate.horizontalDirections) {
for (Direction d : Iterate.directions) {
BlockState neighbour = world.getBlockState(pos.offset(d));
if (!AllBlocks.CRUSHING_WHEEL.has(neighbour))
continue;
@ -144,22 +165,19 @@ public class CrushingWheelControllerBlock extends Block
@Override
public VoxelShape getCollisionShape(BlockState state, IBlockReader worldIn, BlockPos pos,
ISelectionContext context) {
ISelectionContext context) {
if (!state.get(VALID))
return VoxelShapes.fullCube();
return AllShapes.CRUSHING_WHEEL_CONTROLLER_COLLISION.get(state.get(FACING));
Entity entity = context.getEntity();
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()))
return VoxelShapes.empty();
CompoundNBT data = entity.getPersistentData();
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 {
CrushingWheelControllerTileEntity te = getTileEntity(worldIn, pos);
@ -167,7 +185,7 @@ public class CrushingWheelControllerBlock extends Block
return VoxelShapes.empty();
} catch (TileEntityException e) {}
}
return VoxelShapes.fullCube();
return AllShapes.CRUSHING_WHEEL_CONTROLLER_COLLISION.get(state.get(FACING));
}
@Override

View File

@ -6,6 +6,8 @@ import java.util.Optional;
import java.util.Random;
import java.util.UUID;
import static com.simibubi.create.content.contraptions.components.crusher.CrushingWheelControllerBlock.FACING;
import com.simibubi.create.AllRecipeTypes;
import com.simibubi.create.content.contraptions.processing.ProcessingInventory;
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.utility.VecHelper;
import net.minecraft.block.BlockState;
import net.minecraft.entity.Entity;
import net.minecraft.entity.item.ItemEntity;
import net.minecraft.item.BlockItem;
@ -28,7 +31,9 @@ import net.minecraft.particles.ItemParticleData;
import net.minecraft.particles.ParticleTypes;
import net.minecraft.tileentity.TileEntityType;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import net.minecraftforge.common.capabilities.Capability;
@ -63,7 +68,15 @@ public class CrushingWheelControllerTileEntity extends SmartTileEntity {
@Override
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
@ -72,26 +85,37 @@ public class CrushingWheelControllerTileEntity extends SmartTileEntity {
if (searchForEntity) {
searchForEntity = false;
List<Entity> search = world.getEntitiesInAABBexcluding(null, new AxisAlignedBB(getPos()),
e -> entityUUID.equals(e.getUniqueID()));
e -> entityUUID.equals(e.getUniqueID()));
if (search.isEmpty())
clear();
else
processingEntity = search.get(0);
}
if (!isOccupied())
return;
if (crushingspeed == 0)
return;
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()) {
float processingSpeed =
MathHelper.clamp((speed) / (!inventory.appliedRecipe ? MathHelper.log2(inventory.getStackInSlot(0)
.getCount()) : 1), .25f, 20);
MathHelper.clamp((speed) / (!inventory.appliedRecipe ? MathHelper.log2(inventory.getStackInSlot(0)
.getCount()) : 1), .25f, 20);
inventory.remainingTime -= processingSpeed;
spawnParticles(inventory.getStackInSlot(0));
@ -105,61 +129,111 @@ public class CrushingWheelControllerTileEntity extends SmartTileEntity {
return;
}
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);
if (inventory.remainingTime > 0) {
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;
}
if (!processingEntity.isAlive() || !processingEntity.getBoundingBox()
.intersects(new AxisAlignedBB(pos).grow(.5f))) {
.intersects(new AxisAlignedBB(pos).grow(.5f))) {
clear();
return;
}
double xMotion = ((pos.getX() + .5f) - processingEntity.getX()) / 2f;
double yMotion = ((pos.getY() + .5f) - processingEntity.getY()) / 2f;
double zMotion = ((pos.getZ() + .5f) - processingEntity.getZ()) / 2f;
if (processingEntity.isSneaking())
xMotion = zMotion = 0;
processingEntity.setMotion(new Vec3d(xMotion, Math.max(-speed / 4f, -.5f), zMotion));
double movement = Math.max(-speed / 4f, -.5f) * -offset;
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)
return;
if (!(processingEntity instanceof ItemEntity)) {
processingEntity.attackEntityFrom(CrushingWheelTileEntity.damageSource,
AllConfigs.SERVER.kinetics.crushingDamage.get());
AllConfigs.SERVER.kinetics.crushingDamage.get());
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;
}
ItemEntity itemEntity = (ItemEntity) processingEntity;
itemEntity.setPickupDelay(20);
if (processingEntity.getY() < pos.getY() + .25f) {
inventory.clear();
inventory.setStackInSlot(0, itemEntity.getItem()
.copy());
itemInserted(inventory.getStackInSlot(0));
itemEntity.remove();
world.notifyBlockUpdate(pos, getBlockState(), getBlockState(), 2 | 16);
if (facing.getAxis() == Axis.Y) {
if (processingEntity.getY() * -offset < (centerPos.y - .25f) * -offset) {
intakeItem(itemEntity);
}
} else if (facing.getAxis() == Axis.Z) {
if (processingEntity.getZ() * -offset < (centerPos.z - .25f) * -offset) {
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) {
@ -169,14 +243,14 @@ public class CrushingWheelControllerTileEntity extends SmartTileEntity {
IParticleData particleData = null;
if (stack.getItem() instanceof BlockItem)
particleData = new BlockParticleData(ParticleTypes.BLOCK, ((BlockItem) stack.getItem()).getBlock()
.getDefaultState());
.getDefaultState());
else
particleData = new ItemParticleData(ParticleTypes.ITEM, stack);
Random r = world.rand;
for (int i = 0; i < 4; i++)
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() {
@ -185,11 +259,11 @@ public class CrushingWheelControllerTileEntity extends SmartTileEntity {
List<ItemStack> list = new ArrayList<>();
if (recipe.isPresent()) {
int rolls = inventory.getStackInSlot(0)
.getCount();
.getCount();
inventory.clear();
for (int roll = 0; roll < rolls; roll++) {
List<ItemStack> rolledResults = recipe.get()
.rollResults();
.rollResults();
for (int i = 0; i < rolledResults.size(); i++) {
ItemStack stack = rolledResults.get(i);
ItemHelper.addToList(stack, list);
@ -238,7 +312,7 @@ public class CrushingWheelControllerTileEntity extends SmartTileEntity {
private void itemInserted(ItemStack stack) {
Optional<ProcessingRecipe<RecipeWrapper>> recipe = findRecipe();
inventory.remainingTime = recipe.isPresent() ? recipe.get()
.getProcessingDuration() : 100;
.getProcessingDuration() : 100;
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))
continue;
// Horizontal Crushing Wheels
if (BeltCrusherInteractionHandler.checkForCrushers(this, currentItem, nextOffset))
continue;
// Apply Movement
currentItem.beltPosition += limitedMovement;
currentItem.sideOffset +=