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:
simibubi 2020-06-27 15:20:22 +02:00
parent 9fe1d85199
commit f7ad748a09
18 changed files with 723 additions and 123 deletions

View file

@ -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);

View file

@ -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;

View file

@ -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;
}

View file

@ -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();
});

View file

@ -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
*/

View file

@ -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();

View file

@ -54,6 +54,7 @@ public class TransportedItemStack implements Comparable<TransportedItemStack> {
public TransportedItemStack copy() {
TransportedItemStack copy = getSimilar();
copy.angle = angle;
copy.sideOffset = sideOffset;
return copy;
}

View file

@ -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;

View file

@ -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());

View file

@ -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();
}
}

View file

@ -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;
}
}

View file

@ -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);
}
}
}

View file

@ -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));
}
}

View file

@ -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();
});

View file

@ -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)

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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();