Merge pull request #900 from SuicidalSteve/mc1.15/dev

Omnidirectional Crushing Wheels
This commit is contained in:
simibubi 2021-02-19 15:01:19 +01:00 committed by GitHub
commit 13e8f67d05
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 270 additions and 74 deletions

View file

@ -107,7 +107,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)
; ;
@ -145,7 +148,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
, (-1f)
, 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,75 @@
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();
if (crusherFacing != movementFacing)
continue;
float crusherEntry = segment + .5f;
crusherEntry += .399f * (beltMovementPositive ? -1 : 1);
float postCrusherEntry = crusherEntry + .799f * (!beltMovementPositive ? -1 : 1);
boolean hasCrossed = nextOffset > crusherEntry && nextOffset < postCrusherEntry && beltMovementPositive
|| nextOffset < crusherEntry && nextOffset > postCrusherEntry && !beltMovementPositive;
if (!hasCrossed)
return false;
currentItem.beltPosition = crusherEntry;
TileEntity te = world.getTileEntity(crusherPos);
if (!(te instanceof CrushingWheelControllerTileEntity))
return true;
CrushingWheelControllerTileEntity crusherTE = (CrushingWheelControllerTileEntity) te;
ItemStack toInsert = currentItem.stack.copy();
ItemStack remainder = ItemHandlerHelper.insertItemStacked(crusherTE.inventory, toInsert, false);
if (toInsert.equals(remainder, false))
return true;
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();
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 +=