mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2024-11-11 04:54:12 +01:00
Depot Implementation and Interaction
- Depots can now hold on to items similarly to belts - Item processing such as the press and bulk smelting now targets a Processing TE behaviour, rather than the belt only - The press and similar processing can no longer commence whenever there is a block with a collision shape between item and machine - Implemented item processing for Depots - Items can seamlessly traverse from belts to depots
This commit is contained in:
parent
9fe1d85199
commit
f7ad748a09
@ -72,6 +72,8 @@ import com.simibubi.create.content.logistics.block.belts.observer.BeltObserverRe
|
||||
import com.simibubi.create.content.logistics.block.belts.observer.BeltObserverTileEntity;
|
||||
import com.simibubi.create.content.logistics.block.belts.tunnel.BeltTunnelRenderer;
|
||||
import com.simibubi.create.content.logistics.block.belts.tunnel.BeltTunnelTileEntity;
|
||||
import com.simibubi.create.content.logistics.block.depot.DepotRenderer;
|
||||
import com.simibubi.create.content.logistics.block.depot.DepotTileEntity;
|
||||
import com.simibubi.create.content.logistics.block.diodes.AdjustablePulseRepeaterTileEntity;
|
||||
import com.simibubi.create.content.logistics.block.diodes.AdjustableRepeaterRenderer;
|
||||
import com.simibubi.create.content.logistics.block.diodes.AdjustableRepeaterTileEntity;
|
||||
@ -219,6 +221,8 @@ public class AllTileEntities {
|
||||
public static final TileEntityEntry<CreativeCrateTileEntity> CREATIVE_CRATE =
|
||||
register("creative_crate", CreativeCrateTileEntity::new, AllBlocks.CREATIVE_CRATE);
|
||||
|
||||
public static final TileEntityEntry<DepotTileEntity> DEPOT =
|
||||
register("depot", DepotTileEntity::new, AllBlocks.DEPOT);
|
||||
public static final TileEntityEntry<RealityFunnelTileEntity> REALITY_FUNNEL = register("reality_funnel",
|
||||
RealityFunnelTileEntity::new, AllBlocks.REALITY_FUNNEL, AllBlocks.BELT_FUNNEL, AllBlocks.CHUTE_FUNNEL);
|
||||
public static final TileEntityEntry<PackagerTileEntity> PACKAGER =
|
||||
@ -295,6 +299,7 @@ public class AllTileEntities {
|
||||
bind(FURNACE_ENGINE, EngineRenderer::new);
|
||||
bind(ROTATION_SPEED_CONTROLLER, SpeedControllerRenderer::new);
|
||||
bind(PACKAGER, PackagerRenderer::new);
|
||||
bind(DEPOT, DepotRenderer::new);
|
||||
|
||||
bind(CREATIVE_CRATE, SmartTileEntityRenderer::new);
|
||||
bind(REDSTONE_LINK, SmartTileEntityRenderer::new);
|
||||
|
@ -7,11 +7,12 @@ import java.util.List;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import com.simibubi.create.content.contraptions.particle.AirFlowParticleData;
|
||||
import com.simibubi.create.content.contraptions.relays.belt.BeltHelper;
|
||||
import com.simibubi.create.content.contraptions.relays.belt.BeltTileEntity;
|
||||
import com.simibubi.create.content.logistics.InWorldProcessing;
|
||||
import com.simibubi.create.content.logistics.InWorldProcessing.Type;
|
||||
import com.simibubi.create.foundation.config.AllConfigs;
|
||||
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
|
||||
import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour;
|
||||
import com.simibubi.create.foundation.utility.Iterate;
|
||||
import com.simibubi.create.foundation.utility.VecHelper;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
@ -21,9 +22,7 @@ import net.minecraft.entity.EntityType;
|
||||
import net.minecraft.entity.item.ItemEntity;
|
||||
import net.minecraft.entity.monster.EndermanEntity;
|
||||
import net.minecraft.entity.player.ServerPlayerEntity;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.state.properties.BlockStateProperties;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.DamageSource;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.SoundCategory;
|
||||
@ -42,10 +41,10 @@ import net.minecraftforge.common.Tags;
|
||||
|
||||
public class AirCurrent {
|
||||
|
||||
private static DamageSource damageSourceFire =
|
||||
new DamageSource("create.fan_fire").setDifficultyScaled().setFireDamage();
|
||||
private static DamageSource damageSourceLava =
|
||||
new DamageSource("create.fan_lava").setDifficultyScaled().setFireDamage();
|
||||
private static DamageSource damageSourceFire = new DamageSource("create.fan_fire").setDifficultyScaled()
|
||||
.setFireDamage();
|
||||
private static DamageSource damageSourceLava = new DamageSource("create.fan_lava").setDifficultyScaled()
|
||||
.setFireDamage();
|
||||
|
||||
public final EncasedFanTileEntity source;
|
||||
public AxisAlignedBB bounds = new AxisAlignedBB(0, 0, 0, 0, 0, 0);
|
||||
@ -54,7 +53,8 @@ public class AirCurrent {
|
||||
public boolean pushing;
|
||||
public float maxDistance;
|
||||
|
||||
protected List<Pair<BeltTileEntity, InWorldProcessing.Type>> affectedBelts = new ArrayList<>();
|
||||
protected List<Pair<TransportedItemStackHandlerBehaviour, InWorldProcessing.Type>> affectedItemHandlers =
|
||||
new ArrayList<>();
|
||||
protected List<Entity> caughtEntities = new ArrayList<>();
|
||||
|
||||
public AirCurrent(EncasedFanTileEntity source) {
|
||||
@ -66,14 +66,16 @@ public class AirCurrent {
|
||||
Direction facing = direction;
|
||||
if (world.isRemote) {
|
||||
float offset = pushing ? 0.5f : maxDistance + .5f;
|
||||
Vec3d pos = VecHelper.getCenterOf(source.getPos()).add(new Vec3d(facing.getDirectionVec()).scale(offset));
|
||||
Vec3d pos = VecHelper.getCenterOf(source.getPos())
|
||||
.add(new Vec3d(facing.getDirectionVec()).scale(offset));
|
||||
if (world.rand.nextFloat() < AllConfigs.CLIENT.fanParticleDensity.get())
|
||||
world.addParticle(new AirFlowParticleData(source.getPos()), pos.x, pos.y, pos.z, 0, 0, 0);
|
||||
}
|
||||
|
||||
for (Iterator<Entity> iterator = caughtEntities.iterator(); iterator.hasNext();) {
|
||||
Entity entity = iterator.next();
|
||||
if (!entity.getBoundingBox().intersects(bounds)) {
|
||||
if (!entity.getBoundingBox()
|
||||
.intersects(bounds)) {
|
||||
iterator.remove();
|
||||
continue;
|
||||
}
|
||||
@ -83,7 +85,8 @@ public class AirCurrent {
|
||||
|
||||
float sneakModifier = entity.isSneaking() ? 4096f : 512f;
|
||||
float speed = Math.abs(source.getSpeed());
|
||||
double entityDistance = entity.getPositionVec().distanceTo(center);
|
||||
double entityDistance = entity.getPositionVec()
|
||||
.distanceTo(center);
|
||||
float acceleration = (float) (speed / sneakModifier / (entityDistance / maxDistance));
|
||||
Vec3d previousMotion = entity.getMotion();
|
||||
float maxAcceleration = 5;
|
||||
@ -127,15 +130,16 @@ public class AirCurrent {
|
||||
}
|
||||
break;
|
||||
case SPLASHING:
|
||||
if (entity instanceof EndermanEntity || entity.getType() == EntityType.SNOW_GOLEM || entity.getType() == EntityType.BLAZE) {
|
||||
if (entity instanceof EndermanEntity || entity.getType() == EntityType.SNOW_GOLEM
|
||||
|| entity.getType() == EntityType.BLAZE) {
|
||||
entity.attackEntityFrom(DamageSource.DROWN, 2);
|
||||
}
|
||||
if (!entity.isBurning())
|
||||
break;
|
||||
entity.extinguish();
|
||||
world.playSound(null, entity.getPosition(), SoundEvents.ENTITY_GENERIC_EXTINGUISH_FIRE,
|
||||
SoundCategory.NEUTRAL, 0.7F,
|
||||
1.6F + (world.rand.nextFloat() - world.rand.nextFloat()) * 0.4F);
|
||||
SoundCategory.NEUTRAL, 0.7F,
|
||||
1.6F + (world.rand.nextFloat() - world.rand.nextFloat()) * 0.4F);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -145,7 +149,7 @@ public class AirCurrent {
|
||||
|
||||
}
|
||||
|
||||
tickBelts();
|
||||
tickAffectedHandlers();
|
||||
}
|
||||
|
||||
public void rebuild() {
|
||||
@ -158,7 +162,8 @@ public class AirCurrent {
|
||||
|
||||
World world = source.getWorld();
|
||||
BlockPos start = source.getPos();
|
||||
direction = source.getBlockState().get(BlockStateProperties.FACING);
|
||||
direction = source.getBlockState()
|
||||
.get(BlockStateProperties.FACING);
|
||||
pushing = source.getAirFlowDirection() == direction;
|
||||
Vec3d directionVec = new Vec3d(direction.getDirectionVec());
|
||||
Vec3d planeVec = VecHelper.planeByNormal(directionVec);
|
||||
@ -166,9 +171,9 @@ public class AirCurrent {
|
||||
// 4 Rays test for holes in the shapes blocking the flow
|
||||
float offsetDistance = .25f;
|
||||
Vec3d[] offsets = new Vec3d[] { planeVec.mul(offsetDistance, offsetDistance, offsetDistance),
|
||||
planeVec.mul(-offsetDistance, -offsetDistance, offsetDistance),
|
||||
planeVec.mul(offsetDistance, -offsetDistance, -offsetDistance),
|
||||
planeVec.mul(-offsetDistance, offsetDistance, -offsetDistance), };
|
||||
planeVec.mul(-offsetDistance, -offsetDistance, offsetDistance),
|
||||
planeVec.mul(offsetDistance, -offsetDistance, -offsetDistance),
|
||||
planeVec.mul(-offsetDistance, offsetDistance, -offsetDistance), };
|
||||
|
||||
maxDistance = source.getMaxDistance();
|
||||
float limitedDistance = 0;
|
||||
@ -190,15 +195,17 @@ public class AirCurrent {
|
||||
}
|
||||
|
||||
for (Vec3d offset : offsets) {
|
||||
Vec3d rayStart =
|
||||
VecHelper.getCenterOf(currentPos).subtract(directionVec.scale(.5f + 1 / 32f)).add(offset);
|
||||
Vec3d rayStart = VecHelper.getCenterOf(currentPos)
|
||||
.subtract(directionVec.scale(.5f + 1 / 32f))
|
||||
.add(offset);
|
||||
Vec3d rayEnd = rayStart.add(directionVec.scale(1 + 1 / 32f));
|
||||
BlockRayTraceResult blockraytraceresult =
|
||||
world.rayTraceBlocks(rayStart, rayEnd, currentPos, voxelshape, state);
|
||||
if (blockraytraceresult == null)
|
||||
continue Outer;
|
||||
|
||||
double distance = i - 1 + blockraytraceresult.getHitVec().distanceTo(rayStart);
|
||||
double distance = i - 1 + blockraytraceresult.getHitVec()
|
||||
.distanceTo(rayStart);
|
||||
if (limitedDistance < distance)
|
||||
limitedDistance = (float) distance;
|
||||
}
|
||||
@ -244,68 +251,58 @@ public class AirCurrent {
|
||||
if (factor > 0)
|
||||
bounds = new AxisAlignedBB(start.offset(direction)).expand(scale);
|
||||
else {
|
||||
bounds = new AxisAlignedBB(start.offset(direction)).contract(scale.x, scale.y, scale.z).offset(scale);
|
||||
bounds = new AxisAlignedBB(start.offset(direction)).contract(scale.x, scale.y, scale.z)
|
||||
.offset(scale);
|
||||
}
|
||||
}
|
||||
findAffectedBelts();
|
||||
findAffectedHandlers();
|
||||
}
|
||||
|
||||
public void findEntities() {
|
||||
caughtEntities.clear();
|
||||
caughtEntities = source.getWorld().getEntitiesWithinAABBExcludingEntity(null, bounds);
|
||||
caughtEntities = source.getWorld()
|
||||
.getEntitiesWithinAABBExcludingEntity(null, bounds);
|
||||
}
|
||||
|
||||
public void findAffectedBelts() {
|
||||
public void findAffectedHandlers() {
|
||||
World world = source.getWorld();
|
||||
BlockPos start = source.getPos();
|
||||
affectedBelts.clear();
|
||||
affectedItemHandlers.clear();
|
||||
for (int i = 0; i < maxDistance + 1; i++) {
|
||||
Type type = getSegmentAt(i);
|
||||
if (type == null)
|
||||
continue;
|
||||
BlockPos pos = start.offset(direction, i);
|
||||
TileEntity te = world.getTileEntity(pos);
|
||||
if (te != null && (te instanceof BeltTileEntity))
|
||||
affectedBelts.add(Pair.of((BeltTileEntity) te, type));
|
||||
if (direction.getAxis().isVertical())
|
||||
continue;
|
||||
|
||||
pos = pos.down();
|
||||
te = world.getTileEntity(pos);
|
||||
if (te == null || !(te instanceof BeltTileEntity))
|
||||
continue;
|
||||
affectedBelts.add(Pair.of((BeltTileEntity) te, type));
|
||||
for (int offset : Iterate.zeroAndOne) {
|
||||
BlockPos pos = start.offset(direction, i)
|
||||
.down(offset);
|
||||
TransportedItemStackHandlerBehaviour behaviour =
|
||||
TileEntityBehaviour.get(world, pos, TransportedItemStackHandlerBehaviour.TYPE);
|
||||
if (behaviour != null)
|
||||
affectedItemHandlers.add(Pair.of(behaviour, type));
|
||||
if (direction.getAxis()
|
||||
.isVertical())
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void tickBelts() {
|
||||
for (Pair<BeltTileEntity, Type> pair : affectedBelts) {
|
||||
BeltTileEntity belt = pair.getKey();
|
||||
World world = belt.getWorld();
|
||||
public void tickAffectedHandlers() {
|
||||
for (Pair<TransportedItemStackHandlerBehaviour, Type> pair : affectedItemHandlers) {
|
||||
TransportedItemStackHandlerBehaviour handler = pair.getKey();
|
||||
World world = handler.getWorld();
|
||||
InWorldProcessing.Type processingType = pair.getRight();
|
||||
|
||||
BeltTileEntity controller = belt.getControllerTE();
|
||||
if (controller == null)
|
||||
continue;
|
||||
|
||||
controller.getInventory().forEachWithin(belt.index + .5f, .51f, (transported) -> {
|
||||
InWorldProcessing.spawnParticlesForProcessing(world,
|
||||
BeltHelper.getVectorForOffset(controller, transported.beltPosition), processingType);
|
||||
handler.handleProcessingOnAllItems((transported) -> {
|
||||
InWorldProcessing.spawnParticlesForProcessing(world, handler.getWorldPositionOf(transported),
|
||||
processingType);
|
||||
if (world.isRemote)
|
||||
return null;
|
||||
return InWorldProcessing.applyProcessing(transported, belt, processingType);
|
||||
return InWorldProcessing.applyProcessing(transported, world, processingType);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void writeToNBT(CompoundNBT nbt) {
|
||||
|
||||
}
|
||||
|
||||
public void readFromNBT(CompoundNBT nbt) {
|
||||
|
||||
}
|
||||
|
||||
private static boolean shouldAlwaysPass(BlockState state) {
|
||||
if (state.isIn(Tags.Blocks.FENCES))
|
||||
return true;
|
||||
|
@ -7,17 +7,17 @@ import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import com.simibubi.create.content.contraptions.components.press.MechanicalPressTileEntity.Mode;
|
||||
import com.simibubi.create.content.contraptions.relays.belt.transport.BeltInventory;
|
||||
import com.simibubi.create.content.contraptions.relays.belt.transport.TransportedItemStack;
|
||||
import com.simibubi.create.foundation.item.ItemHelper;
|
||||
import com.simibubi.create.foundation.tileEntity.behaviour.belt.BeltProcessingBehaviour.ProcessingResult;
|
||||
import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
public class BeltPressingCallbacks {
|
||||
|
||||
static ProcessingResult onItemReceived(TransportedItemStack transported, BeltInventory beltInventory,
|
||||
MechanicalPressTileEntity press) {
|
||||
static ProcessingResult onItemReceived(TransportedItemStack transported,
|
||||
TransportedItemStackHandlerBehaviour handler, MechanicalPressTileEntity press) {
|
||||
if (press.getSpeed() == 0 || press.running)
|
||||
return PASS;
|
||||
if (!press.getRecipe(transported.stack)
|
||||
@ -28,9 +28,9 @@ public class BeltPressingCallbacks {
|
||||
return HOLD;
|
||||
}
|
||||
|
||||
static ProcessingResult whenItemHeld(TransportedItemStack transportedStack, BeltInventory beltInventory,
|
||||
static ProcessingResult whenItemHeld(TransportedItemStack transported, TransportedItemStackHandlerBehaviour handler,
|
||||
MechanicalPressTileEntity pressTe) {
|
||||
|
||||
|
||||
if (pressTe.getSpeed() == 0)
|
||||
return PASS;
|
||||
if (!pressTe.running)
|
||||
@ -38,9 +38,9 @@ public class BeltPressingCallbacks {
|
||||
if (pressTe.runningTicks != 30)
|
||||
return HOLD;
|
||||
|
||||
Optional<PressingRecipe> recipe = pressTe.getRecipe(transportedStack.stack);
|
||||
Optional<PressingRecipe> recipe = pressTe.getRecipe(transported.stack);
|
||||
pressTe.pressedItems.clear();
|
||||
pressTe.pressedItems.add(transportedStack.stack);
|
||||
pressTe.pressedItems.add(transported.stack);
|
||||
|
||||
if (!recipe.isPresent())
|
||||
return PASS;
|
||||
@ -48,10 +48,10 @@ public class BeltPressingCallbacks {
|
||||
ItemStack out = recipe.get()
|
||||
.getRecipeOutput()
|
||||
.copy();
|
||||
List<ItemStack> multipliedOutput = ItemHelper.multipliedOutput(transportedStack.stack, out);
|
||||
List<ItemStack> multipliedOutput = ItemHelper.multipliedOutput(transported.stack, out);
|
||||
if (multipliedOutput.isEmpty())
|
||||
transportedStack.stack = ItemStack.EMPTY;
|
||||
transportedStack.stack = multipliedOutput.get(0);
|
||||
transported.stack = ItemStack.EMPTY;
|
||||
transported.stack = multipliedOutput.get(0);
|
||||
pressTe.sendData();
|
||||
return HOLD;
|
||||
}
|
||||
|
@ -250,7 +250,7 @@ public class BeltBlock extends HorizontalKineticBlock implements ITE<BeltTileEnt
|
||||
if (worldIn.isRemote)
|
||||
return ActionResultType.SUCCESS;
|
||||
controllerBelt.getInventory()
|
||||
.forEachWithin(belt.index + .5f, .55f, (transportedItemStack) -> {
|
||||
.applyToEachWithin(belt.index + .5f, .55f, (transportedItemStack) -> {
|
||||
player.inventory.placeItemBackInInventory(worldIn, transportedItemStack.stack);
|
||||
return Collections.emptyList();
|
||||
});
|
||||
|
@ -12,6 +12,7 @@ import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
|
||||
@ -24,6 +25,7 @@ import com.simibubi.create.content.contraptions.relays.belt.transport.ItemHandle
|
||||
import com.simibubi.create.content.contraptions.relays.belt.transport.TransportedItemStack;
|
||||
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.utility.ColorHelper;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
@ -39,6 +41,7 @@ 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.Vec3d;
|
||||
import net.minecraft.util.math.Vec3i;
|
||||
import net.minecraftforge.common.capabilities.Capability;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
@ -72,6 +75,8 @@ public class BeltTileEntity extends KineticTileEntity {
|
||||
behaviours.add(new DirectBeltInputBehaviour(this)
|
||||
.onlyInsertWhen(d -> getSpeed() != 0 && getMovementFacing() != d.getOpposite())
|
||||
.setInsertionHandler(this::tryInsertingFromSide));
|
||||
behaviours.add(new TransportedItemStackHandlerBehaviour(this, this::applyToAllItems)
|
||||
.withStackPlacement(this::getWorldPositionOf));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -333,6 +338,20 @@ public class BeltTileEntity extends KineticTileEntity {
|
||||
return inventory;
|
||||
}
|
||||
|
||||
private void applyToAllItems(Function<TransportedItemStack, List<TransportedItemStack>> processFunction) {
|
||||
BeltTileEntity controller = getControllerTE();
|
||||
if (controller != null)
|
||||
controller.getInventory()
|
||||
.applyToEachWithin(index + .5f, .51f, processFunction);
|
||||
}
|
||||
|
||||
private Vec3d getWorldPositionOf(TransportedItemStack transported) {
|
||||
BeltTileEntity controllerTE = getControllerTE();
|
||||
if (controllerTE == null)
|
||||
return Vec3d.ZERO;
|
||||
return BeltHelper.getVectorForOffset(controllerTE, transported.beltPosition);
|
||||
}
|
||||
|
||||
/**
|
||||
* always target a DirectBeltInsertionBehaviour
|
||||
*/
|
||||
|
@ -18,6 +18,7 @@ import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
|
||||
import com.simibubi.create.foundation.tileEntity.behaviour.belt.BeltProcessingBehaviour;
|
||||
import com.simibubi.create.foundation.tileEntity.behaviour.belt.BeltProcessingBehaviour.ProcessingResult;
|
||||
import com.simibubi.create.foundation.tileEntity.behaviour.belt.DirectBeltInputBehaviour;
|
||||
import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour;
|
||||
import com.simibubi.create.foundation.utility.ServerSpeedProvider;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
@ -165,7 +166,7 @@ public class BeltInventory {
|
||||
continue;
|
||||
if (!inputBehaviour.canInsertFromSide(movementFacing))
|
||||
continue;
|
||||
|
||||
|
||||
ItemStack remainder = inputBehaviour.handleInsertion(currentItem, movementFacing, false);
|
||||
if (remainder.equals(currentItem.stack, false))
|
||||
continue;
|
||||
@ -198,14 +199,18 @@ public class BeltInventory {
|
||||
// Continue processing if held
|
||||
if (currentItem.locked) {
|
||||
BeltProcessingBehaviour processingBehaviour = getBeltProcessingAtSegment(currentSegment);
|
||||
TransportedItemStackHandlerBehaviour stackHandlerBehaviour =
|
||||
getTransportedItemStackHandlerAtSegment(currentSegment);
|
||||
|
||||
if (stackHandlerBehaviour == null)
|
||||
return false;
|
||||
if (processingBehaviour == null) {
|
||||
currentItem.locked = false;
|
||||
belt.sendData();
|
||||
return false;
|
||||
}
|
||||
|
||||
ProcessingResult result = processingBehaviour.handleHeldItem(currentItem, this);
|
||||
ProcessingResult result = processingBehaviour.handleHeldItem(currentItem, stackHandlerBehaviour);
|
||||
if (result == ProcessingResult.REMOVE)
|
||||
return true;
|
||||
if (result == ProcessingResult.HOLD)
|
||||
@ -225,10 +230,17 @@ public class BeltInventory {
|
||||
: segment + .5f >= nextOffset; segment += step) {
|
||||
|
||||
BeltProcessingBehaviour processingBehaviour = getBeltProcessingAtSegment(segment);
|
||||
TransportedItemStackHandlerBehaviour stackHandlerBehaviour =
|
||||
getTransportedItemStackHandlerAtSegment(segment);
|
||||
|
||||
if (processingBehaviour == null)
|
||||
continue;
|
||||
if (stackHandlerBehaviour == null)
|
||||
continue;
|
||||
if (BeltProcessingBehaviour.isBlocked(belt.getWorld(), BeltHelper.getPositionForOffset(belt, segment)))
|
||||
continue;
|
||||
|
||||
ProcessingResult result = processingBehaviour.handleReceivedItem(currentItem, this);
|
||||
ProcessingResult result = processingBehaviour.handleReceivedItem(currentItem, stackHandlerBehaviour);
|
||||
if (result == ProcessingResult.REMOVE)
|
||||
return true;
|
||||
|
||||
@ -249,6 +261,11 @@ public class BeltInventory {
|
||||
.up(2), BeltProcessingBehaviour.TYPE);
|
||||
}
|
||||
|
||||
protected TransportedItemStackHandlerBehaviour getTransportedItemStackHandlerAtSegment(int segment) {
|
||||
return TileEntityBehaviour.get(belt.getWorld(), BeltHelper.getPositionForOffset(belt, segment),
|
||||
TransportedItemStackHandlerBehaviour.TYPE);
|
||||
}
|
||||
|
||||
private enum Ending {
|
||||
UNRESOLVED(0), EJECT(0), INSERT(.25f), FUNNEL(.35f), BLOCKED(.45f);
|
||||
|
||||
@ -373,22 +390,25 @@ public class BeltInventory {
|
||||
belt.getWorld()
|
||||
.addEntity(entity);
|
||||
}
|
||||
|
||||
|
||||
public void ejectAll() {
|
||||
items.forEach(this::eject);
|
||||
items.clear();
|
||||
}
|
||||
|
||||
public void forEachWithin(float position, float distance,
|
||||
Function<TransportedItemStack, List<TransportedItemStack>> callback) {
|
||||
public void applyToEachWithin(float position, float maxDistanceToPosition,
|
||||
Function<TransportedItemStack, List<TransportedItemStack>> processFunction) {
|
||||
List<TransportedItemStack> toBeAdded = new ArrayList<>();
|
||||
boolean dirty = false;
|
||||
for (Iterator<TransportedItemStack> iterator = items.iterator(); iterator.hasNext();) {
|
||||
TransportedItemStack transportedItemStack = iterator.next();
|
||||
if (Math.abs(position - transportedItemStack.beltPosition) < distance) {
|
||||
List<TransportedItemStack> apply = callback.apply(transportedItemStack);
|
||||
ItemStack stackBefore = transportedItemStack.stack.copy();
|
||||
if (Math.abs(position - transportedItemStack.beltPosition) < maxDistanceToPosition) {
|
||||
List<TransportedItemStack> apply = processFunction.apply(transportedItemStack);
|
||||
if (apply == null)
|
||||
continue;
|
||||
if (apply.size() == 1 && apply.get(0).stack.equals(stackBefore, false))
|
||||
continue;
|
||||
dirty = true;
|
||||
toBeAdded.addAll(apply);
|
||||
iterator.remove();
|
||||
|
@ -54,6 +54,7 @@ public class TransportedItemStack implements Comparable<TransportedItemStack> {
|
||||
public TransportedItemStack copy() {
|
||||
TransportedItemStack copy = getSimilar();
|
||||
copy.angle = angle;
|
||||
copy.sideOffset = sideOffset;
|
||||
return copy;
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,6 @@ import java.util.Optional;
|
||||
import com.simibubi.create.AllRecipeTypes;
|
||||
import com.simibubi.create.content.contraptions.components.fan.SplashingRecipe;
|
||||
import com.simibubi.create.content.contraptions.processing.ProcessingRecipe;
|
||||
import com.simibubi.create.content.contraptions.relays.belt.BeltTileEntity;
|
||||
import com.simibubi.create.content.contraptions.relays.belt.transport.TransportedItemStack;
|
||||
import com.simibubi.create.foundation.config.AllConfigs;
|
||||
import com.simibubi.create.foundation.item.ItemHelper;
|
||||
@ -61,7 +60,7 @@ public class InWorldProcessing {
|
||||
if (fluidState.getFluid() == Fluids.WATER || fluidState.getFluid() == Fluids.FLOWING_WATER)
|
||||
return Type.SPLASHING;
|
||||
if (blockState.getBlock() == Blocks.FIRE
|
||||
|| (blockState.getBlock() == Blocks.CAMPFIRE && blockState.get(CampfireBlock.LIT)))
|
||||
|| (blockState.getBlock() == Blocks.CAMPFIRE && blockState.get(CampfireBlock.LIT)))
|
||||
return Type.SMOKING;
|
||||
if (blockState.getBlock() == Blocks.LAVA)
|
||||
return Type.BLASTING;
|
||||
@ -70,8 +69,10 @@ public class InWorldProcessing {
|
||||
}
|
||||
|
||||
public static boolean canProcess(ItemEntity entity, Type type) {
|
||||
if (entity.getPersistentData().contains("CreateData")) {
|
||||
CompoundNBT compound = entity.getPersistentData().getCompound("CreateData");
|
||||
if (entity.getPersistentData()
|
||||
.contains("CreateData")) {
|
||||
CompoundNBT compound = entity.getPersistentData()
|
||||
.getCompound("CreateData");
|
||||
if (compound.contains("Processing")) {
|
||||
CompoundNBT processing = compound.getCompound("Processing");
|
||||
|
||||
@ -100,7 +101,8 @@ public class InWorldProcessing {
|
||||
SmokerTileEntity smoker = new SmokerTileEntity();
|
||||
smoker.setLocation(world, BlockPos.ZERO);
|
||||
smoker.setInventorySlotContents(0, stack);
|
||||
Optional<SmokingRecipe> recipe = world.getRecipeManager().getRecipe(IRecipeType.SMOKING, smoker, world);
|
||||
Optional<SmokingRecipe> recipe = world.getRecipeManager()
|
||||
.getRecipe(IRecipeType.SMOKING, smoker, world);
|
||||
return recipe.isPresent();
|
||||
}
|
||||
|
||||
@ -112,8 +114,8 @@ public class InWorldProcessing {
|
||||
|
||||
public static boolean isWashable(ItemStack stack, World world) {
|
||||
splashingInv.setInventorySlotContents(0, stack);
|
||||
Optional<SplashingRecipe> recipe =
|
||||
world.getRecipeManager().getRecipe(AllRecipeTypes.SPLASHING.getType(), splashingInv, world);
|
||||
Optional<SplashingRecipe> recipe = world.getRecipeManager()
|
||||
.getRecipe(AllRecipeTypes.SPLASHING.getType(), splashingInv, world);
|
||||
return recipe.isPresent();
|
||||
}
|
||||
|
||||
@ -135,15 +137,15 @@ public class InWorldProcessing {
|
||||
}
|
||||
}
|
||||
|
||||
public static List<TransportedItemStack> applyProcessing(TransportedItemStack transported, BeltTileEntity belt,
|
||||
Type type) {
|
||||
public static List<TransportedItemStack> applyProcessing(TransportedItemStack transported,
|
||||
World world, Type type) {
|
||||
if (transported.processedBy != type) {
|
||||
transported.processedBy = type;
|
||||
int timeModifierForStackSize = ((transported.stack.getCount() - 1) / 16) + 1;
|
||||
int processingTime =
|
||||
(int) (AllConfigs.SERVER.kinetics.inWorldProcessingTime.get() * timeModifierForStackSize) + 1;
|
||||
transported.processingTime = processingTime;
|
||||
if (!canProcess(transported.stack, type, belt.getWorld()))
|
||||
if (!canProcess(transported.stack, type, world))
|
||||
transported.processingTime = -1;
|
||||
return null;
|
||||
}
|
||||
@ -152,15 +154,13 @@ public class InWorldProcessing {
|
||||
if (transported.processingTime-- > 0)
|
||||
return null;
|
||||
|
||||
List<ItemStack> stacks = process(transported.stack, type, belt.getWorld());
|
||||
List<ItemStack> stacks = process(transported.stack, type, world);
|
||||
if (stacks == null)
|
||||
return null;
|
||||
|
||||
|
||||
List<TransportedItemStack> transportedStacks = new ArrayList<>();
|
||||
for (ItemStack additional : stacks) {
|
||||
TransportedItemStack newTransported = transported.getSimilar();
|
||||
newTransported.beltPosition -= Math.signum(belt.getDirectionAwareBeltMovementSpeed()) * 1/32f;
|
||||
newTransported.prevBeltPosition = newTransported.beltPosition;
|
||||
newTransported.stack = additional.copy();
|
||||
transportedStacks.add(newTransported);
|
||||
}
|
||||
@ -170,8 +170,8 @@ public class InWorldProcessing {
|
||||
private static List<ItemStack> process(ItemStack stack, Type type, World world) {
|
||||
if (type == Type.SPLASHING) {
|
||||
splashingInv.setInventorySlotContents(0, stack);
|
||||
Optional<SplashingRecipe> recipe =
|
||||
world.getRecipeManager().getRecipe(AllRecipeTypes.SPLASHING.getType(), splashingInv, world);
|
||||
Optional<SplashingRecipe> recipe = world.getRecipeManager()
|
||||
.getRecipe(AllRecipeTypes.SPLASHING.getType(), splashingInv, world);
|
||||
if (recipe.isPresent())
|
||||
return applyRecipeOn(stack, recipe.get());
|
||||
return null;
|
||||
@ -181,15 +181,16 @@ public class InWorldProcessing {
|
||||
SmokerTileEntity smoker = new SmokerTileEntity();
|
||||
smoker.setLocation(world, BlockPos.ZERO);
|
||||
smoker.setInventorySlotContents(0, stack);
|
||||
Optional<SmokingRecipe> smokingRecipe = world.getRecipeManager().getRecipe(IRecipeType.SMOKING, smoker, world);
|
||||
Optional<SmokingRecipe> smokingRecipe = world.getRecipeManager()
|
||||
.getRecipe(IRecipeType.SMOKING, smoker, world);
|
||||
|
||||
if (type == Type.BLASTING) {
|
||||
// FIXME this does not need to be a TE
|
||||
FurnaceTileEntity furnace = new FurnaceTileEntity();
|
||||
furnace.setLocation(world, BlockPos.ZERO);
|
||||
furnace.setInventorySlotContents(0, stack);
|
||||
Optional<FurnaceRecipe> smeltingRecipe =
|
||||
world.getRecipeManager().getRecipe(IRecipeType.SMELTING, furnace, world);
|
||||
Optional<FurnaceRecipe> smeltingRecipe = world.getRecipeManager()
|
||||
.getRecipe(IRecipeType.SMELTING, furnace, world);
|
||||
|
||||
if (!smokingRecipe.isPresent()) {
|
||||
if (smeltingRecipe.isPresent())
|
||||
@ -199,8 +200,8 @@ public class InWorldProcessing {
|
||||
BlastFurnaceTileEntity blastFurnace = new BlastFurnaceTileEntity();
|
||||
blastFurnace.setLocation(world, BlockPos.ZERO);
|
||||
blastFurnace.setInventorySlotContents(0, stack);
|
||||
Optional<BlastingRecipe> blastingRecipe =
|
||||
world.getRecipeManager().getRecipe(IRecipeType.BLASTING, blastFurnace, world);
|
||||
Optional<BlastingRecipe> blastingRecipe = world.getRecipeManager()
|
||||
.getRecipe(IRecipeType.BLASTING, blastFurnace, world);
|
||||
|
||||
if (blastingRecipe.isPresent())
|
||||
return applyRecipeOn(stack, blastingRecipe.get());
|
||||
@ -228,7 +229,8 @@ public class InWorldProcessing {
|
||||
|
||||
if (!processing.contains("Type") || Type.valueOf(processing.getString("Type")) != type) {
|
||||
processing.putString("Type", type.name());
|
||||
int timeModifierForStackSize = ((entity.getItem().getCount() - 1) / 16) + 1;
|
||||
int timeModifierForStackSize = ((entity.getItem()
|
||||
.getCount() - 1) / 16) + 1;
|
||||
int processingTime =
|
||||
(int) (AllConfigs.SERVER.kinetics.inWorldProcessingTime.get() * timeModifierForStackSize) + 1;
|
||||
processing.putInt("Time", processingTime);
|
||||
@ -269,7 +271,7 @@ public class InWorldProcessing {
|
||||
if (!ItemHandlerHelper.canItemStacksStack(stack, previouslyRolled))
|
||||
continue;
|
||||
int amount = Math.min(previouslyRolled.getMaxStackSize() - previouslyRolled.getCount(),
|
||||
stack.getCount());
|
||||
stack.getCount());
|
||||
previouslyRolled.grow(amount);
|
||||
stack.shrink(amount);
|
||||
}
|
||||
@ -281,7 +283,8 @@ public class InWorldProcessing {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ItemStack out = recipe.getRecipeOutput().copy();
|
||||
ItemStack out = recipe.getRecipeOutput()
|
||||
.copy();
|
||||
stacks = ItemHelper.multipliedOutput(stackIn, out);
|
||||
}
|
||||
|
||||
@ -304,10 +307,10 @@ public class InWorldProcessing {
|
||||
case SPLASHING:
|
||||
Vec3d color = ColorHelper.getRGB(0x0055FF);
|
||||
world.addParticle(new RedstoneParticleData((float) color.x, (float) color.y, (float) color.z, 1),
|
||||
vec.x + (world.rand.nextFloat() - .5f) * .5f, vec.y + .5f,
|
||||
vec.z + (world.rand.nextFloat() - .5f) * .5f, 0, 1 / 8f, 0);
|
||||
vec.x + (world.rand.nextFloat() - .5f) * .5f, vec.y + .5f, vec.z + (world.rand.nextFloat() - .5f) * .5f,
|
||||
0, 1 / 8f, 0);
|
||||
world.addParticle(ParticleTypes.SPIT, vec.x + (world.rand.nextFloat() - .5f) * .5f, vec.y + .5f,
|
||||
vec.z + (world.rand.nextFloat() - .5f) * .5f, 0, 1 / 8f, 0);
|
||||
vec.z + (world.rand.nextFloat() - .5f) * .5f, 0, 1 / 8f, 0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -53,7 +53,7 @@ public class BeltObserverTileEntity extends SmartTileEntity {
|
||||
if (controllerTE == null)
|
||||
return;
|
||||
|
||||
controllerTE.getInventory().forEachWithin(beltTE.index + .5f, .45f, stack -> {
|
||||
controllerTE.getInventory().applyToEachWithin(beltTE.index + .5f, .45f, stack -> {
|
||||
if (filtering.test(stack.stack) && turnOffTicks != 6) {
|
||||
world.setBlockState(pos, getBlockState().with(BeltObserverBlock.POWERED, true));
|
||||
world.notifyNeighborsOfStateChange(pos, getBlockState().getBlock());
|
||||
|
@ -1,24 +1,132 @@
|
||||
package com.simibubi.create.content.logistics.block.depot;
|
||||
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.AllShapes;
|
||||
import com.simibubi.create.AllTileEntities;
|
||||
import com.simibubi.create.content.contraptions.relays.belt.transport.TransportedItemStack;
|
||||
import com.simibubi.create.foundation.block.ITE;
|
||||
import com.simibubi.create.foundation.item.ItemHelper;
|
||||
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
|
||||
import com.simibubi.create.foundation.tileEntity.behaviour.belt.DirectBeltInputBehaviour;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.item.ItemEntity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.inventory.InventoryHelper;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.ActionResultType;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.BlockRayTraceResult;
|
||||
import net.minecraft.util.math.shapes.ISelectionContext;
|
||||
import net.minecraft.util.math.shapes.VoxelShape;
|
||||
import net.minecraft.world.IBlockReader;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.items.ItemStackHandler;
|
||||
|
||||
public class DepotBlock extends Block {
|
||||
public class DepotBlock extends Block implements ITE<DepotTileEntity> {
|
||||
|
||||
public DepotBlock(Properties p_i48440_1_) {
|
||||
super(p_i48440_1_);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public VoxelShape getShape(BlockState p_220053_1_, IBlockReader p_220053_2_, BlockPos p_220053_3_,
|
||||
ISelectionContext p_220053_4_) {
|
||||
return AllShapes.DEPOT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasTileEntity(BlockState state) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TileEntity createTileEntity(BlockState state, IBlockReader world) {
|
||||
return AllTileEntities.DEPOT.create();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<DepotTileEntity> getTileEntityClass() {
|
||||
return DepotTileEntity.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionResultType onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand,
|
||||
BlockRayTraceResult ray) {
|
||||
if (ray.getFace() != Direction.UP)
|
||||
return ActionResultType.PASS;
|
||||
if (world.isRemote)
|
||||
return ActionResultType.SUCCESS;
|
||||
|
||||
withTileEntityDo(world, pos, te -> {
|
||||
boolean wasEmptyHanded = player.getHeldItem(hand)
|
||||
.isEmpty();
|
||||
|
||||
ItemStack mainItemStack = te.getHeldItemStack();
|
||||
if (!mainItemStack.isEmpty()) {
|
||||
player.inventory.placeItemBackInInventory(world, mainItemStack);
|
||||
te.setHeldItem(null);
|
||||
}
|
||||
ItemStackHandler outputs = te.processingOutputBuffer;
|
||||
for (int i = 0; i < outputs.getSlots(); i++)
|
||||
player.inventory.placeItemBackInInventory(world, outputs.extractItem(i, 64, false));
|
||||
|
||||
if (!wasEmptyHanded) {
|
||||
TransportedItemStack heldItem = new TransportedItemStack(player.getHeldItem(hand));
|
||||
heldItem.insertedFrom = player.getHorizontalFacing();
|
||||
heldItem.prevBeltPosition = .25f;
|
||||
heldItem.beltPosition = .25f;
|
||||
te.setHeldItem(heldItem);
|
||||
player.setHeldItem(hand, ItemStack.EMPTY);
|
||||
}
|
||||
|
||||
te.markDirty();
|
||||
te.sendData();
|
||||
});
|
||||
|
||||
return ActionResultType.SUCCESS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReplaced(BlockState state, World worldIn, BlockPos pos, BlockState newState, boolean isMoving) {
|
||||
if (!state.hasTileEntity() || state.getBlock() == newState.getBlock()) {
|
||||
return;
|
||||
}
|
||||
|
||||
withTileEntityDo(worldIn, pos, te -> {
|
||||
ItemHelper.dropContents(worldIn, pos, te.processingOutputBuffer);
|
||||
if (!te.getHeldItemStack()
|
||||
.isEmpty())
|
||||
InventoryHelper.spawnItemStack(worldIn, pos.getX(), pos.getY(), pos.getZ(), te.getHeldItemStack());
|
||||
});
|
||||
worldIn.removeTileEntity(pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLanded(IBlockReader worldIn, Entity entityIn) {
|
||||
super.onLanded(worldIn, entityIn);
|
||||
if (!AllBlocks.DEPOT.has(worldIn.getBlockState(entityIn.getPosition())))
|
||||
return;
|
||||
if (!(entityIn instanceof ItemEntity))
|
||||
return;
|
||||
if (!entityIn.isAlive())
|
||||
return;
|
||||
if (entityIn.world.isRemote)
|
||||
return;
|
||||
ItemEntity itemEntity = (ItemEntity) entityIn;
|
||||
DirectBeltInputBehaviour inputBehaviour =
|
||||
TileEntityBehaviour.get(worldIn, entityIn.getPosition(), DirectBeltInputBehaviour.TYPE);
|
||||
if (inputBehaviour == null)
|
||||
return;
|
||||
ItemStack remainder = inputBehaviour.handleInsertion(itemEntity.getItem(), Direction.DOWN, false);
|
||||
itemEntity.setItem(remainder);
|
||||
if (remainder.isEmpty())
|
||||
itemEntity.remove();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,74 @@
|
||||
package com.simibubi.create.content.logistics.block.depot;
|
||||
|
||||
import com.simibubi.create.content.contraptions.relays.belt.transport.TransportedItemStack;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraftforge.items.IItemHandler;
|
||||
|
||||
public class DepotItemHandler implements IItemHandler {
|
||||
|
||||
private static final int MAIN_SLOT = 0;
|
||||
private DepotTileEntity te;
|
||||
|
||||
public DepotItemHandler(DepotTileEntity te) {
|
||||
this.te = te;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSlots() {
|
||||
return 9;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getStackInSlot(int slot) {
|
||||
return slot == MAIN_SLOT ? te.getHeldItemStack() : te.processingOutputBuffer.getStackInSlot(slot - 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack insertItem(int slot, ItemStack stack, boolean simulate) {
|
||||
if (slot != MAIN_SLOT)
|
||||
return stack;
|
||||
if (!te.getHeldItemStack()
|
||||
.isEmpty())
|
||||
return stack;
|
||||
if (!te.isOutputEmpty())
|
||||
return stack;
|
||||
if (!simulate) {
|
||||
te.setHeldItem(new TransportedItemStack(stack));
|
||||
te.markDirty();
|
||||
te.sendData();
|
||||
}
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack extractItem(int slot, int amount, boolean simulate) {
|
||||
if (slot != MAIN_SLOT)
|
||||
return te.processingOutputBuffer.extractItem(slot - 1, amount, simulate);
|
||||
|
||||
TransportedItemStack held = te.heldItem;
|
||||
if (held == null)
|
||||
return ItemStack.EMPTY;
|
||||
ItemStack stack = held.stack.copy();
|
||||
ItemStack extracted = stack.split(amount);
|
||||
if (!simulate) {
|
||||
te.heldItem.stack = stack;
|
||||
if (stack.isEmpty())
|
||||
te.heldItem = null;
|
||||
te.markDirty();
|
||||
te.sendData();
|
||||
}
|
||||
return extracted;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSlotLimit(int slot) {
|
||||
return 64;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isItemValid(int slot, ItemStack stack) {
|
||||
return slot == MAIN_SLOT;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,107 @@
|
||||
package com.simibubi.create.content.logistics.block.depot;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||
import com.simibubi.create.content.contraptions.relays.belt.transport.TransportedItemStack;
|
||||
import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer;
|
||||
import com.simibubi.create.foundation.utility.MatrixStacker;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.IRenderTypeBuffer;
|
||||
import net.minecraft.client.renderer.ItemRenderer;
|
||||
import net.minecraft.client.renderer.model.ItemCameraTransforms.TransformType;
|
||||
import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.Direction.Axis;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
|
||||
public class DepotRenderer extends SafeTileEntityRenderer<DepotTileEntity> {
|
||||
|
||||
public DepotRenderer(TileEntityRendererDispatcher dispatcher) {
|
||||
super(dispatcher);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderSafe(DepotTileEntity te, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer,
|
||||
int light, int overlay) {
|
||||
|
||||
TransportedItemStack transported = te.heldItem;
|
||||
MatrixStacker msr = MatrixStacker.of(ms);
|
||||
|
||||
ms.push();
|
||||
ms.translate(.5f, 15 / 16f, .5f);
|
||||
|
||||
// Render main item
|
||||
if (transported != null) {
|
||||
ms.push();
|
||||
msr.nudge(0);
|
||||
float offset = MathHelper.lerp(partialTicks, transported.prevBeltPosition, transported.beltPosition);
|
||||
float sideOffset = MathHelper.lerp(partialTicks, transported.prevSideOffset, transported.sideOffset);
|
||||
Vec3d offsetVec = new Vec3d(transported.insertedFrom.getOpposite()
|
||||
.getDirectionVec()).scale(.5f - offset);
|
||||
ms.translate(offsetVec.x, offsetVec.y, offsetVec.z);
|
||||
|
||||
if (transported.insertedFrom.getAxis()
|
||||
.isHorizontal()) {
|
||||
boolean alongX = transported.insertedFrom.rotateY()
|
||||
.getAxis() == Axis.X;
|
||||
if (!alongX)
|
||||
sideOffset *= -1;
|
||||
ms.translate(alongX ? sideOffset : 0, 0, alongX ? 0 : sideOffset);
|
||||
}
|
||||
|
||||
ItemStack itemStack = transported.stack;
|
||||
int angle = transported.angle;
|
||||
Random r = new Random(0);
|
||||
renderItem(ms, buffer, light, overlay, itemStack, angle, r);
|
||||
ms.pop();
|
||||
}
|
||||
|
||||
// Render output items
|
||||
for (int i = 0; i < te.processingOutputBuffer.getSlots(); i++) {
|
||||
ItemStack stack = te.processingOutputBuffer.getStackInSlot(i);
|
||||
if (stack.isEmpty())
|
||||
continue;
|
||||
ms.push();
|
||||
msr.nudge(i);
|
||||
msr.rotateY(360 / 8f * i);
|
||||
ms.translate(.35f, 0, 0);
|
||||
Random r = new Random(i + 1);
|
||||
int angle = (int) (360 * r.nextFloat());
|
||||
renderItem(ms, buffer, light, overlay, stack, angle, r);
|
||||
ms.pop();
|
||||
}
|
||||
|
||||
ms.pop();
|
||||
}
|
||||
|
||||
protected void renderItem(MatrixStack ms, IRenderTypeBuffer buffer, int light, int overlay, ItemStack itemStack,
|
||||
int angle, Random r) {
|
||||
ItemRenderer itemRenderer = Minecraft.getInstance()
|
||||
.getItemRenderer();
|
||||
MatrixStacker msr = MatrixStacker.of(ms);
|
||||
int count = (int) (MathHelper.log2((int) (itemStack.getCount()))) / 2;
|
||||
boolean blockItem = itemRenderer.getItemModelWithOverrides(itemStack, null, null)
|
||||
.isGui3d();
|
||||
for (int i = 0; i <= count; i++) {
|
||||
ms.push();
|
||||
msr.rotateY(angle);
|
||||
if (!blockItem) {
|
||||
ms.translate(0, -.09375, 0);
|
||||
msr.rotateX(90);
|
||||
}
|
||||
if (blockItem)
|
||||
ms.translate(r.nextFloat() * .0625f * i, 0, r.nextFloat() * .0625f * i);
|
||||
ms.scale(.5f, .5f, .5f);
|
||||
itemRenderer.renderItem(itemStack, TransformType.FIXED, light, overlay, ms, buffer);
|
||||
ms.pop();
|
||||
|
||||
if (!blockItem)
|
||||
msr.rotateY(10);
|
||||
ms.translate(0, blockItem ? 1 / 64d : 1 / 16d, 0);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,203 @@
|
||||
package com.simibubi.create.content.logistics.block.depot;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
|
||||
import com.simibubi.create.content.contraptions.relays.belt.transport.TransportedItemStack;
|
||||
import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
|
||||
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
|
||||
import com.simibubi.create.foundation.tileEntity.behaviour.belt.BeltProcessingBehaviour;
|
||||
import com.simibubi.create.foundation.tileEntity.behaviour.belt.BeltProcessingBehaviour.ProcessingResult;
|
||||
import com.simibubi.create.foundation.tileEntity.behaviour.belt.DirectBeltInputBehaviour;
|
||||
import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.tileentity.TileEntityType;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraftforge.common.capabilities.Capability;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
import net.minecraftforge.items.CapabilityItemHandler;
|
||||
import net.minecraftforge.items.ItemStackHandler;
|
||||
|
||||
public class DepotTileEntity extends SmartTileEntity {
|
||||
|
||||
TransportedItemStack heldItem;
|
||||
ItemStackHandler processingOutputBuffer;
|
||||
|
||||
DepotItemHandler itemHandler;
|
||||
LazyOptional<DepotItemHandler> lazyItemHandler;
|
||||
|
||||
public DepotTileEntity(TileEntityType<?> tileEntityTypeIn) {
|
||||
super(tileEntityTypeIn);
|
||||
itemHandler = new DepotItemHandler(this);
|
||||
lazyItemHandler = LazyOptional.of(() -> itemHandler);
|
||||
processingOutputBuffer = new ItemStackHandler(8) {
|
||||
protected void onContentsChanged(int slot) {
|
||||
markDirty();
|
||||
sendData();
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
super.tick();
|
||||
if (heldItem == null)
|
||||
return;
|
||||
|
||||
heldItem.prevBeltPosition = heldItem.beltPosition;
|
||||
heldItem.prevSideOffset = heldItem.sideOffset;
|
||||
float diff = .5f - heldItem.beltPosition;
|
||||
if (diff > 1 / 512f) {
|
||||
if (diff > 1 / 32f)
|
||||
heldItem.angle += 1;
|
||||
heldItem.beltPosition += diff / 4f;
|
||||
}
|
||||
|
||||
if (diff > 1 / 16f)
|
||||
return;
|
||||
if (world.isRemote)
|
||||
return;
|
||||
|
||||
BeltProcessingBehaviour processingBehaviour =
|
||||
TileEntityBehaviour.get(world, pos.up(2), BeltProcessingBehaviour.TYPE);
|
||||
if (processingBehaviour == null)
|
||||
return;
|
||||
if (!heldItem.locked && BeltProcessingBehaviour.isBlocked(world, pos))
|
||||
return;
|
||||
|
||||
boolean wasLocked = heldItem.locked;
|
||||
ItemStack previousItem = heldItem.stack;
|
||||
TransportedItemStackHandlerBehaviour handler = getBehaviour(TransportedItemStackHandlerBehaviour.TYPE);
|
||||
ProcessingResult result = wasLocked ? processingBehaviour.handleHeldItem(heldItem, handler)
|
||||
: processingBehaviour.handleReceivedItem(heldItem, handler);
|
||||
if (result == ProcessingResult.REMOVE) {
|
||||
heldItem = null;
|
||||
sendData();
|
||||
return;
|
||||
}
|
||||
|
||||
heldItem.locked = result == ProcessingResult.HOLD;
|
||||
if (heldItem.locked != wasLocked || !previousItem.equals(heldItem.stack, false))
|
||||
sendData();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundNBT write(CompoundNBT compound) {
|
||||
if (heldItem != null)
|
||||
compound.put("HeldItem", heldItem.serializeNBT());
|
||||
compound.put("OutputBuffer", processingOutputBuffer.serializeNBT());
|
||||
return super.write(compound);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(CompoundNBT compound) {
|
||||
heldItem = null;
|
||||
if (compound.contains("HeldItem"))
|
||||
heldItem = TransportedItemStack.read(compound.getCompound("HeldItem"));
|
||||
processingOutputBuffer.deserializeNBT(compound.getCompound("OutputBuffer"));
|
||||
super.read(compound);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBehaviours(List<TileEntityBehaviour> behaviours) {
|
||||
behaviours.add(new DirectBeltInputBehaviour(this).setInsertionHandler(this::tryInsertingFromSide));
|
||||
behaviours.add(new TransportedItemStackHandlerBehaviour(this, this::applyToAllItems)
|
||||
.withStackPlacement(this::getWorldPositionOf));
|
||||
}
|
||||
|
||||
public ItemStack getHeldItemStack() {
|
||||
return heldItem == null ? ItemStack.EMPTY : heldItem.stack;
|
||||
}
|
||||
|
||||
public void setHeldItem(TransportedItemStack heldItem) {
|
||||
this.heldItem = heldItem;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> LazyOptional<T> getCapability(Capability<T> cap, Direction side) {
|
||||
if (cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY)
|
||||
return lazyItemHandler.cast();
|
||||
return super.getCapability(cap, side);
|
||||
}
|
||||
|
||||
private ItemStack tryInsertingFromSide(TransportedItemStack transportedStack, Direction side, boolean simulate) {
|
||||
ItemStack inserted = transportedStack.stack;
|
||||
ItemStack empty = ItemStack.EMPTY;
|
||||
|
||||
if (!getHeldItemStack().isEmpty())
|
||||
return inserted;
|
||||
if (!isOutputEmpty())
|
||||
return inserted;
|
||||
if (simulate)
|
||||
return empty;
|
||||
|
||||
transportedStack = transportedStack.copy();
|
||||
transportedStack.beltPosition = side.getAxis()
|
||||
.isVertical() ? .5f : 0;
|
||||
transportedStack.insertedFrom = side;
|
||||
transportedStack.prevSideOffset = transportedStack.sideOffset;
|
||||
transportedStack.prevBeltPosition = transportedStack.beltPosition;
|
||||
setHeldItem(transportedStack);
|
||||
markDirty();
|
||||
sendData();
|
||||
|
||||
return empty;
|
||||
}
|
||||
|
||||
private void applyToAllItems(Function<TransportedItemStack, List<TransportedItemStack>> processFunction) {
|
||||
if (heldItem == null)
|
||||
return;
|
||||
|
||||
boolean dirty = false;
|
||||
List<TransportedItemStack> toBeAdded = new ArrayList<>();
|
||||
TransportedItemStack transportedItemStack = heldItem;
|
||||
ItemStack stackBefore = transportedItemStack.stack.copy();
|
||||
List<TransportedItemStack> apply = processFunction.apply(transportedItemStack);
|
||||
|
||||
if (apply == null)
|
||||
return;
|
||||
if (apply.size() == 1 && apply.get(0).stack.equals(stackBefore, false))
|
||||
return;
|
||||
|
||||
dirty = true;
|
||||
heldItem = null;
|
||||
toBeAdded.addAll(apply);
|
||||
for (TransportedItemStack added : toBeAdded) {
|
||||
if (heldItem == null) {
|
||||
heldItem = added;
|
||||
heldItem.beltPosition = 0.5f;
|
||||
heldItem.prevBeltPosition = 0.5f;
|
||||
continue;
|
||||
}
|
||||
for (int i = 0; i < processingOutputBuffer.getSlots(); i++) {
|
||||
ItemStack stackInSlot = processingOutputBuffer.getStackInSlot(i);
|
||||
if (!stackInSlot.isEmpty())
|
||||
continue;
|
||||
processingOutputBuffer.setStackInSlot(i, added.stack);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (dirty) {
|
||||
markDirty();
|
||||
sendData();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isOutputEmpty() {
|
||||
for (int i = 0; i < processingOutputBuffer.getSlots(); i++)
|
||||
if (!processingOutputBuffer.getStackInSlot(i).isEmpty())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
private Vec3d getWorldPositionOf(TransportedItemStack transported) {
|
||||
Vec3d offsetVec = new Vec3d(.5f, 14 / 16f, .5f);
|
||||
return offsetVec.add(new Vec3d(pos));
|
||||
}
|
||||
|
||||
}
|
@ -138,7 +138,7 @@ public class FunnelBlock extends AttachedLogisticalBlock
|
||||
if (controllerBelt == null)
|
||||
return;
|
||||
|
||||
controllerBelt.getInventory().forEachWithin(belt.index + .5f, .55f, (transportedItemStack) -> {
|
||||
controllerBelt.getInventory().applyToEachWithin(belt.index + .5f, .55f, (transportedItemStack) -> {
|
||||
controllerBelt.getInventory().eject(transportedItemStack);
|
||||
return Collections.emptyList();
|
||||
});
|
||||
|
@ -7,7 +7,7 @@ import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.ILightReader;
|
||||
import net.minecraft.world.IBlockReader;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public abstract class TileEntityBehaviour {
|
||||
@ -90,12 +90,12 @@ public abstract class TileEntityBehaviour {
|
||||
return tileEntity.getWorld();
|
||||
}
|
||||
|
||||
public static <T extends TileEntityBehaviour> T get(ILightReader reader, BlockPos pos,
|
||||
public static <T extends TileEntityBehaviour> T get(IBlockReader reader, BlockPos pos,
|
||||
BehaviourType<T> type) {
|
||||
return get(reader.getTileEntity(pos), type);
|
||||
}
|
||||
|
||||
public static <T extends TileEntityBehaviour> void destroy(ILightReader reader, BlockPos pos,
|
||||
public static <T extends TileEntityBehaviour> void destroy(IBlockReader reader, BlockPos pos,
|
||||
BehaviourType<T> type) {
|
||||
T behaviour = get(reader.getTileEntity(pos), type);
|
||||
if (behaviour != null)
|
||||
|
@ -1,15 +1,17 @@
|
||||
package com.simibubi.create.foundation.tileEntity.behaviour.belt;
|
||||
|
||||
import com.simibubi.create.content.contraptions.relays.belt.transport.BeltInventory;
|
||||
import com.simibubi.create.content.contraptions.relays.belt.transport.TransportedItemStack;
|
||||
import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
|
||||
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
|
||||
import com.simibubi.create.foundation.tileEntity.behaviour.BehaviourType;
|
||||
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.IBlockReader;
|
||||
|
||||
/**
|
||||
* Behaviour for TileEntities which can process items on belts or depots beneath them.
|
||||
* Currently only supports placement location 2 spaces above the belt block.
|
||||
* Example use: Mechanical Press
|
||||
* Behaviour for TileEntities which can process items on belts or depots beneath
|
||||
* them. Currently only supports placement location 2 spaces above the belt
|
||||
* block. Example use: Mechanical Press
|
||||
*/
|
||||
public class BeltProcessingBehaviour extends TileEntityBehaviour {
|
||||
|
||||
@ -18,7 +20,7 @@ public class BeltProcessingBehaviour extends TileEntityBehaviour {
|
||||
public static enum ProcessingResult {
|
||||
PASS, HOLD, REMOVE;
|
||||
}
|
||||
|
||||
|
||||
private ProcessingCallback onItemEnter;
|
||||
private ProcessingCallback continueProcessing;
|
||||
|
||||
@ -27,33 +29,40 @@ public class BeltProcessingBehaviour extends TileEntityBehaviour {
|
||||
onItemEnter = (s, i) -> ProcessingResult.PASS;
|
||||
continueProcessing = (s, i) -> ProcessingResult.PASS;
|
||||
}
|
||||
|
||||
|
||||
public BeltProcessingBehaviour whenItemEnters(ProcessingCallback callback) {
|
||||
onItemEnter = callback;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public BeltProcessingBehaviour whileItemHeld(ProcessingCallback callback) {
|
||||
continueProcessing = callback;
|
||||
return this;
|
||||
}
|
||||
|
||||
public static boolean isBlocked(IBlockReader world, BlockPos processingSpace) {
|
||||
return !world.getBlockState(processingSpace.up())
|
||||
.getCollisionShape(world, processingSpace.up())
|
||||
.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BehaviourType<?> getType() {
|
||||
return TYPE;
|
||||
}
|
||||
|
||||
public ProcessingResult handleReceivedItem(TransportedItemStack stack, BeltInventory inventory) {
|
||||
public ProcessingResult handleReceivedItem(TransportedItemStack stack,
|
||||
TransportedItemStackHandlerBehaviour inventory) {
|
||||
return onItemEnter.apply(stack, inventory);
|
||||
}
|
||||
|
||||
public ProcessingResult handleHeldItem(TransportedItemStack stack, BeltInventory inventory) {
|
||||
public ProcessingResult handleHeldItem(TransportedItemStack stack, TransportedItemStackHandlerBehaviour inventory) {
|
||||
return continueProcessing.apply(stack, inventory);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface ProcessingCallback {
|
||||
public ProcessingResult apply(TransportedItemStack stack, BeltInventory inventory);
|
||||
public ProcessingResult apply(TransportedItemStack stack, TransportedItemStackHandlerBehaviour inventory);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,54 @@
|
||||
package com.simibubi.create.foundation.tileEntity.behaviour.belt;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
|
||||
import com.simibubi.create.content.contraptions.relays.belt.transport.TransportedItemStack;
|
||||
import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
|
||||
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
|
||||
import com.simibubi.create.foundation.tileEntity.behaviour.BehaviourType;
|
||||
import com.simibubi.create.foundation.utility.VecHelper;
|
||||
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
|
||||
public class TransportedItemStackHandlerBehaviour extends TileEntityBehaviour {
|
||||
|
||||
public static BehaviourType<TransportedItemStackHandlerBehaviour> TYPE = new BehaviourType<>();
|
||||
private ProcessingCallback processingCallback;
|
||||
private PositionGetter positionGetter;
|
||||
|
||||
public TransportedItemStackHandlerBehaviour(SmartTileEntity te, ProcessingCallback processingCallback) {
|
||||
super(te);
|
||||
this.processingCallback = processingCallback;
|
||||
positionGetter = t -> VecHelper.getCenterOf(te.getPos());
|
||||
}
|
||||
|
||||
public TransportedItemStackHandlerBehaviour withStackPlacement(PositionGetter function) {
|
||||
this.positionGetter = function;
|
||||
return this;
|
||||
}
|
||||
|
||||
public void handleProcessingOnAllItems(Function<TransportedItemStack, List<TransportedItemStack>> processFunction) {
|
||||
this.processingCallback.applyToAllItems(processFunction);
|
||||
}
|
||||
|
||||
public Vec3d getWorldPositionOf(TransportedItemStack transported) {
|
||||
return positionGetter.getWorldPositionVector(transported);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BehaviourType<?> getType() {
|
||||
return TYPE;
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface ProcessingCallback {
|
||||
public void applyToAllItems(Function<TransportedItemStack, List<TransportedItemStack>> processFunction);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface PositionGetter {
|
||||
public Vec3d getWorldPositionVector(TransportedItemStack transported);
|
||||
}
|
||||
|
||||
}
|
@ -10,7 +10,7 @@ import net.minecraft.util.math.BlockPos;
|
||||
public class Iterate {
|
||||
|
||||
public static final boolean[] trueAndFalse = { true, false };
|
||||
public static final int[] zeroAndOne = { 1, -1 };
|
||||
public static final int[] zeroAndOne = { 0, 1 };
|
||||
public static final int[] positiveAndNegative = { 1, -1 };
|
||||
public static final Direction[] directions = Direction.values();
|
||||
public static final Direction[] horizontalDirections = getHorizontals();
|
||||
|
Loading…
Reference in New Issue
Block a user