Smelty on the Belty returns

- Encased fans now work on the "fake items" moving on the belt
- Chunk no longer redraws when TEs send data. (May break stuff)
- Regular fan particles are less noisy
- Items no longer spazz out when the belt is stopped
- Fixed extractors waiting indefinitely if belt is occupied
This commit is contained in:
simibubi 2019-11-20 22:50:19 +01:00
parent e742149c8d
commit 55818d33fa
19 changed files with 418 additions and 219 deletions

View file

@ -28,7 +28,7 @@ public abstract class SyncedTileEntity extends TileEntity {
} }
public void sendData() { public void sendData() {
world.notifyBlockUpdate(getPos(), getBlockState(), getBlockState(), 2 | 16); world.notifyBlockUpdate(getPos(), getBlockState(), getBlockState(), 2 | 4 | 16);
} }
public void causeBlockUpdate() { public void causeBlockUpdate() {

View file

@ -0,0 +1,71 @@
package com.simibubi.create.modules.contraptions.receivers;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity;
import com.simibubi.create.modules.logistics.InWorldProcessing;
import com.simibubi.create.modules.logistics.InWorldProcessing.Type;
import net.minecraft.particles.ParticleTypes;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
public class EncasedFanBeltHandler {
// Fans need to be aware of belt TEs within their range
// all belts are handled equally
// requires ref to controller and index
static List<BeltTileEntity> findBelts(EncasedFanTileEntity fan) {
if (fan.getSpeed() == 0)
return Collections.emptyList();
List<BeltTileEntity> belts = new ArrayList<>();
AxisAlignedBB searchBB = fan.frontBB.shrink(.25).contract(0, 0, 0).expand(0, -.25f, 0);
BlockPos.getAllInBox((int) searchBB.minX, (int) searchBB.minY, (int) searchBB.minZ, (int) searchBB.maxX - 1,
(int) searchBB.maxY - 1, (int) searchBB.maxZ - 1)
.filter(p -> AllBlocks.BELT.typeOf(fan.getWorld().getBlockState(p))).forEach(p -> {
TileEntity te = fan.getWorld().getTileEntity(p);
if (te == null || !(te instanceof BeltTileEntity))
return;
belts.add((BeltTileEntity) te);
});
return belts;
}
static void tickBelts(EncasedFanTileEntity fan, List<BeltTileEntity> belts) {
Type processingType = fan.getProcessingType();
if (processingType == null)
return;
for (BeltTileEntity belt : belts) {
BeltTileEntity controller = belt.getControllerTE();
if (controller == null)
continue;
World world = belt.getWorld();
controller.getInventory().forEachWithin(belt.index + .5f, .5f, (transported) -> {
if (world.rand.nextInt(4) == 0 && world.isRemote) {
Vec3d vec = controller.getInventory().getVectorForOffset(transported.beltPosition);
if (processingType == Type.BLASTING)
world.addParticle(ParticleTypes.LARGE_SMOKE, vec.x, vec.y + .25f, vec.z, 0, 1 / 16f, 0);
if (processingType == Type.SMOKING)
world.addParticle(ParticleTypes.CLOUD, vec.x, vec.y + .25f, vec.z, 0, 1 / 16f, 0);
if (processingType == Type.SPLASHING)
world.addParticle(ParticleTypes.BUBBLE_POP, vec.x + (world.rand.nextFloat() - .5f) * .5f,
vec.y + .25f, vec.z + (world.rand.nextFloat() - .5f) * .5f, 0, 1 / 16f, 0);
}
if (world.isRemote)
return null;
return InWorldProcessing.applyProcessing(transported, belt, processingType);
});
}
}
}

View file

@ -26,7 +26,7 @@ public class EncasedFanParticleHandler {
private void initEffects() { private void initEffects() {
List<FanEffect> standardFX = new ArrayList<>(2); List<FanEffect> standardFX = new ArrayList<>(2);
standardFX.add(new FanEffect(ParticleTypes.BUBBLE_POP, 1 / 4f, 1 / 4f, 1 / 3f, 1)); standardFX.add(new FanEffect(ParticleTypes.BUBBLE_POP, 1 / 4f, 1 / 4f, 1 / 8f, 1));
standardFX.add(new FanEffect(new RedstoneParticleData(1, 1, 1, 1), 1 / 2f, 1 / 32f, 1/16f, 512f)); standardFX.add(new FanEffect(new RedstoneParticleData(1, 1, 1, 1), 1 / 2f, 1 / 32f, 1/16f, 512f));
effects.put(Blocks.AIR, standardFX); effects.put(Blocks.AIR, standardFX);

View file

@ -5,6 +5,7 @@ import static net.minecraft.state.properties.BlockStateProperties.AXIS;
import static net.minecraft.util.Direction.AxisDirection.NEGATIVE; import static net.minecraft.util.Direction.AxisDirection.NEGATIVE;
import static net.minecraft.util.Direction.AxisDirection.POSITIVE; import static net.minecraft.util.Direction.AxisDirection.POSITIVE;
import java.util.Collections;
import java.util.List; import java.util.List;
import com.simibubi.create.AllBlockTags; import com.simibubi.create.AllBlockTags;
@ -14,6 +15,7 @@ import com.simibubi.create.CreateClient;
import com.simibubi.create.CreateConfig; import com.simibubi.create.CreateConfig;
import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.modules.contraptions.base.GeneratingKineticTileEntity; import com.simibubi.create.modules.contraptions.base.GeneratingKineticTileEntity;
import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity;
import com.simibubi.create.modules.logistics.InWorldProcessing; import com.simibubi.create.modules.logistics.InWorldProcessing;
import com.simibubi.create.modules.logistics.InWorldProcessing.Type; import com.simibubi.create.modules.logistics.InWorldProcessing.Type;
@ -51,6 +53,7 @@ public class EncasedFanTileEntity extends GeneratingKineticTileEntity {
protected boolean findFrontBlock; protected boolean findFrontBlock;
protected BlockState frontBlock; protected BlockState frontBlock;
protected boolean isGenerator; protected boolean isGenerator;
protected List<BeltTileEntity> affectedBelts = Collections.emptyList();
public EncasedFanTileEntity() { public EncasedFanTileEntity() {
super(AllTileEntities.ENCASED_FAN.type); super(AllTileEntities.ENCASED_FAN.type);
@ -67,6 +70,7 @@ public class EncasedFanTileEntity extends GeneratingKineticTileEntity {
super.readClientUpdate(tag); super.readClientUpdate(tag);
updateFrontBlock(); updateFrontBlock();
updateBBs(); updateBBs();
affectedBelts = EncasedFanBeltHandler.findBelts(this);
} }
@Override @Override
@ -140,6 +144,7 @@ public class EncasedFanTileEntity extends GeneratingKineticTileEntity {
backBB = new AxisAlignedBB(0, 0, 0, 0, 0, 0); backBB = new AxisAlignedBB(0, 0, 0, 0, 0, 0);
} }
affectedBelts = EncasedFanBeltHandler.findBelts(this);
sendData(); sendData();
} }
@ -190,6 +195,8 @@ public class EncasedFanTileEntity extends GeneratingKineticTileEntity {
if (getSpeed() == 0 || isGenerator) if (getSpeed() == 0 || isGenerator)
return; return;
EncasedFanBeltHandler.tickBelts(this, affectedBelts);
List<Entity> frontEntities = world.getEntitiesWithinAABBExcludingEntity(null, frontBB); List<Entity> frontEntities = world.getEntitiesWithinAABBExcludingEntity(null, frontBB);
for (Entity entity : frontEntities) { for (Entity entity : frontEntities) {
moveEntity(entity, true); moveEntity(entity, true);
@ -238,7 +245,7 @@ public class EncasedFanTileEntity extends GeneratingKineticTileEntity {
return; return;
if (canProcess((ItemEntity) entity)) if (canProcess((ItemEntity) entity))
InWorldProcessing.process((ItemEntity) entity, getProcessingType()); InWorldProcessing.applyProcessing((ItemEntity) entity, getProcessingType());
} else { } else {
if (getProcessingType() == Type.SMOKING) { if (getProcessingType() == Type.SMOKING) {

View file

@ -13,9 +13,9 @@ import com.simibubi.create.modules.contraptions.base.HorizontalKineticBlock;
import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.BeltAttachmentState; import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.BeltAttachmentState;
import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.IBeltAttachment; import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.IBeltAttachment;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock; import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock;
import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope; import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope;
import com.simibubi.create.modules.contraptions.relays.belt.BeltInventory.TransportedItemStack; import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity;
import com.simibubi.create.modules.contraptions.relays.belt.TransportedItemStack;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;

View file

@ -6,8 +6,8 @@ import com.simibubi.create.AllRecipes;
import com.simibubi.create.AllTileEntities; import com.simibubi.create.AllTileEntities;
import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.modules.contraptions.base.KineticTileEntity; import com.simibubi.create.modules.contraptions.base.KineticTileEntity;
import com.simibubi.create.modules.contraptions.relays.belt.BeltInventory.TransportedItemStack;
import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity; import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity;
import com.simibubi.create.modules.contraptions.relays.belt.TransportedItemStack;
import com.simibubi.create.modules.logistics.InWorldProcessing; import com.simibubi.create.modules.logistics.InWorldProcessing;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;

View file

@ -6,7 +6,6 @@ import java.util.function.Consumer;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.Create; import com.simibubi.create.Create;
import com.simibubi.create.modules.contraptions.relays.belt.BeltInventory.TransportedItemStack;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;

View file

@ -1,6 +1,6 @@
package com.simibubi.create.modules.contraptions.relays.belt; package com.simibubi.create.modules.contraptions.relays.belt;
import java.util.Iterator; import java.util.Collections;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
@ -10,7 +10,6 @@ import com.simibubi.create.foundation.block.IWithTileEntity;
import com.simibubi.create.foundation.block.IWithoutBlockItem; import com.simibubi.create.foundation.block.IWithoutBlockItem;
import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.modules.contraptions.base.HorizontalKineticBlock; import com.simibubi.create.modules.contraptions.base.HorizontalKineticBlock;
import com.simibubi.create.modules.contraptions.relays.belt.BeltInventory.TransportedItemStack;
import com.simibubi.create.modules.contraptions.relays.belt.BeltMovementHandler.TransportedEntityInfo; import com.simibubi.create.modules.contraptions.relays.belt.BeltMovementHandler.TransportedEntityInfo;
import net.minecraft.block.Block; import net.minecraft.block.Block;
@ -187,22 +186,15 @@ public class BeltBlock extends HorizontalKineticBlock implements IWithoutBlockIt
BeltTileEntity belt = (BeltTileEntity) te; BeltTileEntity belt = (BeltTileEntity) te;
if (isHand) { if (isHand) {
TileEntity controllerTe = worldIn.getTileEntity(belt.getController()); BeltTileEntity controllerBelt = belt.getControllerTE();
if (controllerTe == null || !(controllerTe instanceof BeltTileEntity)) if (controllerBelt == null)
return false; return false;
if (worldIn.isRemote) if (worldIn.isRemote)
return true; return true;
BeltTileEntity controllerBelt = (BeltTileEntity) controllerTe; controllerBelt.getInventory().forEachWithin(belt.index, .75f, (transportedItemStack) -> {
for (Iterator<TransportedItemStack> iterator = controllerBelt.getInventory().items.iterator(); iterator
.hasNext();) {
TransportedItemStack transportedItemStack = iterator.next();
if (Math.abs(belt.index + .5 - transportedItemStack.beltPosition) < .75f) {
player.inventory.placeItemBackInInventory(worldIn, transportedItemStack.stack); player.inventory.placeItemBackInInventory(worldIn, transportedItemStack.stack);
iterator.remove(); return Collections.emptyList();
controllerBelt.markDirty(); });
controllerBelt.sendData();
}
}
} }
if (isShaft) { if (isShaft) {

View file

@ -1,10 +1,11 @@
package com.simibubi.create.modules.contraptions.relays.belt; package com.simibubi.create.modules.contraptions.relays.belt;
import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Random; import java.util.function.Function;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.utility.VecHelper;
@ -122,13 +123,14 @@ public class BeltInventory {
int upcomingSegment = (int) (current.beltPosition + (beltMovementPositive ? .5f : -.5f)); int upcomingSegment = (int) (current.beltPosition + (beltMovementPositive ? .5f : -.5f));
for (int segment = upcomingSegment; beltMovementPositive for (int segment = upcomingSegment; beltMovementPositive
? segment + .5f <= current.beltPosition + limitedMovement ? segment + .5f <= current.beltPosition + limitedMovement
: segment + .5f >= current.beltPosition + limitedMovement; segment += beltMovementPositive ? 1 : -1) { : segment + .5f >= current.beltPosition + limitedMovement; segment += beltMovementPositive ? 1
: -1) {
BeltTileEntity beltSegment = getBeltSegment(segmentBefore); BeltTileEntity beltSegment = getBeltSegment(segmentBefore);
if (beltSegment == null) if (beltSegment == null)
break; break;
for (BeltAttachmentState attachmentState : beltSegment.attachmentTracker.attachments) { for (BeltAttachmentState attachmentState : beltSegment.attachmentTracker.attachments) {
if (attachmentState.attachment.startProcessingItem(beltSegment, current, attachmentState)) { if (attachmentState.attachment.startProcessingItem(beltSegment, current, attachmentState)) {
current.beltPosition += (segment + .5f) - current.beltPosition; current.beltPosition = segment + .5f + (beltMovementPositive ? 1 / 64f : -1 / 64f);
current.locked = true; current.locked = true;
belt.sendData(); belt.sendData();
continue Items; continue Items;
@ -230,63 +232,6 @@ public class BeltInventory {
} }
public static class TransportedItemStack implements Comparable<TransportedItemStack> {
public ItemStack stack;
public float beltPosition;
public float sideOffset;
public int angle;
public int insertedAt;
public Direction insertedFrom;
public boolean locked;
public float prevBeltPosition;
public float prevSideOffset;
public TransportedItemStack(ItemStack stack) {
this.stack = stack;
angle = new Random().nextInt(360);
sideOffset = prevSideOffset = getTargetSideOffset();
insertedFrom = Direction.UP;
}
public float getTargetSideOffset() {
return (angle - 180) / (360 * 3f);
}
@Override
public int compareTo(TransportedItemStack o) {
return beltPosition < o.beltPosition ? 1 : beltPosition > o.beltPosition ? -1 : 0;
}
public CompoundNBT serializeNBT() {
CompoundNBT nbt = new CompoundNBT();
nbt.put("Item", stack.serializeNBT());
nbt.putFloat("Pos", beltPosition);
nbt.putFloat("PrevPos", prevBeltPosition);
nbt.putFloat("Offset", sideOffset);
nbt.putFloat("PrevOffset", prevSideOffset);
nbt.putInt("InSegment", insertedAt);
nbt.putInt("Angle", angle);
nbt.putInt("InDirection", insertedFrom.getIndex());
nbt.putBoolean("Locked", locked);
return nbt;
}
public static TransportedItemStack read(CompoundNBT nbt) {
TransportedItemStack stack = new TransportedItemStack(ItemStack.read(nbt.getCompound("Item")));
stack.beltPosition = nbt.getFloat("Pos");
stack.prevBeltPosition = nbt.getFloat("PrevPos");
stack.sideOffset = nbt.getFloat("Offset");
stack.prevSideOffset = nbt.getFloat("PrevOffset");
stack.insertedAt = nbt.getInt("InSegment");
stack.angle = nbt.getInt("Angle");
stack.insertedFrom = Direction.byIndex(nbt.getInt("InDirection"));
stack.locked = nbt.getBoolean("Locked");
return stack;
}
}
public boolean canInsertAt(int segment) { public boolean canInsertAt(int segment) {
return canInsertFrom(segment, Direction.UP); return canInsertFrom(segment, Direction.UP);
} }
@ -328,9 +273,6 @@ public class BeltInventory {
} }
items.add(index, newStack); items.add(index, newStack);
} }
belt.markDirty();
belt.sendData();
} }
public TransportedItemStack getStackAtOffset(int offset) { public TransportedItemStack getStackAtOffset(int offset) {
@ -373,7 +315,7 @@ public class BeltInventory {
belt.getWorld().addEntity(entity); belt.getWorld().addEntity(entity);
} }
private Vec3d getVectorForOffset(float offset) { public Vec3d getVectorForOffset(float offset) {
Slope slope = belt.getBlockState().get(BeltBlock.SLOPE); Slope slope = belt.getBlockState().get(BeltBlock.SLOPE);
int verticality = slope == Slope.DOWNWARD ? -1 : slope == Slope.UPWARD ? 1 : 0; int verticality = slope == Slope.DOWNWARD ? -1 : slope == Slope.UPWARD ? 1 : 0;
float verticalMovement = verticality; float verticalMovement = verticality;
@ -409,70 +351,30 @@ public class BeltInventory {
return belt.getDirectionAwareBeltMovementSpeed() > 0; return belt.getDirectionAwareBeltMovementSpeed() > 0;
} }
public class ItemHandlerSegment implements IItemHandler { public IItemHandler createHandlerForSegment(int segment) {
int offset; return new ItemHandlerBeltSegment(this, segment);
public ItemHandlerSegment(int offset) {
this.offset = offset;
} }
@Override public void forEachWithin(float position, float distance,
public int getSlots() { Function<TransportedItemStack, List<TransportedItemStack>> callback) {
return 1; 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);
if (apply == null)
continue;
dirty = true;
toBeAdded.addAll(apply);
iterator.remove();
} }
@Override
public ItemStack getStackInSlot(int slot) {
TransportedItemStack stackAtOffset = getStackAtOffset(offset);
if (stackAtOffset == null)
return ItemStack.EMPTY;
return stackAtOffset.stack;
} }
toBeAdded.forEach(this::insert);
@Override if (dirty) {
public ItemStack insertItem(int slot, ItemStack stack, boolean simulate) {
if (canInsertAt(offset)) {
if (!simulate) {
TransportedItemStack newStack = new TransportedItemStack(stack);
newStack.insertedAt = offset;
newStack.beltPosition = offset + .5f;
newStack.prevBeltPosition = newStack.beltPosition;
insert(newStack);
}
return ItemStack.EMPTY;
}
return stack;
}
@Override
public ItemStack extractItem(int slot, int amount, boolean simulate) {
TransportedItemStack transported = getStackAtOffset(offset);
if (transported == null)
return ItemStack.EMPTY;
amount = Math.min(amount, transported.stack.getCount());
ItemStack extracted = simulate ? transported.stack.copy().split(amount) : transported.stack.split(amount);
if (!simulate) {
belt.markDirty(); belt.markDirty();
belt.sendData(); belt.sendData();
} }
return extracted;
}
@Override
public int getSlotLimit(int slot) {
return Math.min(getStackInSlot(slot).getMaxStackSize(), 64);
}
@Override
public boolean isItemValid(int slot, ItemStack stack) {
return true;
}
}
public IItemHandler createHandlerForSegment(int segment) {
return new ItemHandlerSegment(segment);
} }
} }

View file

@ -20,7 +20,6 @@ import com.simibubi.create.modules.contraptions.base.KineticTileEntity;
import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.Tracker; import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.Tracker;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Part; import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Part;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope; import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope;
import com.simibubi.create.modules.contraptions.relays.belt.BeltInventory.TransportedItemStack;
import com.simibubi.create.modules.contraptions.relays.belt.BeltMovementHandler.TransportedEntityInfo; import com.simibubi.create.modules.contraptions.relays.belt.BeltMovementHandler.TransportedEntityInfo;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
@ -183,6 +182,15 @@ public class BeltTileEntity extends KineticTileEntity {
} }
} }
public BeltTileEntity getControllerTE() {
if (!world.isBlockPresent(controller))
return null;
TileEntity te = world.getTileEntity(controller);
if (te == null || !(te instanceof BeltTileEntity))
return null;
return (BeltTileEntity) te;
}
public void setController(BlockPos controller) { public void setController(BlockPos controller) {
this.controller = controller; this.controller = controller;
} }
@ -283,13 +291,9 @@ public class BeltTileEntity extends KineticTileEntity {
} }
public boolean tryInsertingFromSide(Direction side, TransportedItemStack transportedStack, boolean simulate) { public boolean tryInsertingFromSide(Direction side, TransportedItemStack transportedStack, boolean simulate) {
BlockPos controller = getController(); BeltTileEntity nextBeltController = getControllerTE();
if (!world.isBlockPresent(controller)) if (nextBeltController == null)
return false; return false;
TileEntity te = world.getTileEntity(controller);
if (te == null || !(te instanceof BeltTileEntity))
return false;
BeltTileEntity nextBeltController = (BeltTileEntity) te;
BeltInventory nextInventory = nextBeltController.getInventory(); BeltInventory nextInventory = nextBeltController.getInventory();
if (!nextInventory.canInsertFrom(index, side)) if (!nextInventory.canInsertFrom(index, side))
@ -314,6 +318,7 @@ public class BeltTileEntity extends KineticTileEntity {
transportedStack.insertedFrom = side; transportedStack.insertedFrom = side;
transportedStack.prevBeltPosition = transportedStack.beltPosition; transportedStack.prevBeltPosition = transportedStack.beltPosition;
nextInventory.insert(transportedStack); nextInventory.insert(transportedStack);
nextBeltController.markDirty();
nextBeltController.sendData(); nextBeltController.sendData();
return true; return true;
} }

View file

@ -11,7 +11,6 @@ import com.simibubi.create.modules.contraptions.base.KineticTileEntity;
import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer; import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer;
import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer.BlockModelSpinner; import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer.BlockModelSpinner;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope; import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope;
import com.simibubi.create.modules.contraptions.relays.belt.BeltInventory.TransportedItemStack;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
@ -57,6 +56,11 @@ public class BeltTileEntityRenderer extends TileEntityRenderer<BeltTileEntity> {
float sideOffset = MathHelper.lerp(partialTicks, transported.prevSideOffset, transported.sideOffset); float sideOffset = MathHelper.lerp(partialTicks, transported.prevSideOffset, transported.sideOffset);
float verticalMovement = verticality; float verticalMovement = verticality;
if (te.getSpeed() == 0) {
offset = transported.beltPosition;
sideOffset = transported.sideOffset;
}
if (offset < .5) if (offset < .5)
verticalMovement = 0; verticalMovement = 0;
verticalMovement = verticalMovement * (Math.min(offset, te.beltLength - .5f) - .5f); verticalMovement = verticalMovement * (Math.min(offset, te.beltLength - .5f) - .5f);

View file

@ -0,0 +1,69 @@
package com.simibubi.create.modules.contraptions.relays.belt;
import net.minecraft.item.ItemStack;
import net.minecraftforge.items.IItemHandler;
public class ItemHandlerBeltSegment implements IItemHandler {
private final BeltInventory beltInventory;
int offset;
public ItemHandlerBeltSegment(BeltInventory beltInventory, int offset) {
this.beltInventory = beltInventory;
this.offset = offset;
}
@Override
public int getSlots() {
return 1;
}
@Override
public ItemStack getStackInSlot(int slot) {
TransportedItemStack stackAtOffset = this.beltInventory.getStackAtOffset(offset);
if (stackAtOffset == null)
return ItemStack.EMPTY;
return stackAtOffset.stack;
}
@Override
public ItemStack insertItem(int slot, ItemStack stack, boolean simulate) {
if (this.beltInventory.canInsertAt(offset)) {
if (!simulate) {
TransportedItemStack newStack = new TransportedItemStack(stack);
newStack.insertedAt = offset;
newStack.beltPosition = offset + .5f;
newStack.prevBeltPosition = newStack.beltPosition;
this.beltInventory.insert(newStack);
}
return ItemStack.EMPTY;
}
return stack;
}
@Override
public ItemStack extractItem(int slot, int amount, boolean simulate) {
TransportedItemStack transported = this.beltInventory.getStackAtOffset(offset);
if (transported == null)
return ItemStack.EMPTY;
amount = Math.min(amount, transported.stack.getCount());
ItemStack extracted = simulate ? transported.stack.copy().split(amount) : transported.stack.split(amount);
if (!simulate) {
this.beltInventory.belt.markDirty();
this.beltInventory.belt.sendData();
}
return extracted;
}
@Override
public int getSlotLimit(int slot) {
return Math.min(getStackInSlot(slot).getMaxStackSize(), 64);
}
@Override
public boolean isItemValid(int slot, ItemStack stack) {
return true;
}
}

View file

@ -0,0 +1,87 @@
package com.simibubi.create.modules.contraptions.relays.belt;
import java.util.Random;
import com.simibubi.create.modules.logistics.InWorldProcessing;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.util.Direction;
public class TransportedItemStack implements Comparable<TransportedItemStack> {
public ItemStack stack;
public float beltPosition;
public float sideOffset;
public int angle;
public int insertedAt;
public Direction insertedFrom;
public boolean locked;
public float prevBeltPosition;
public float prevSideOffset;
public InWorldProcessing.Type processedBy;
public int processingTime;
public TransportedItemStack(ItemStack stack) {
this.stack = stack;
angle = new Random().nextInt(360);
sideOffset = prevSideOffset = getTargetSideOffset();
insertedFrom = Direction.UP;
}
public float getTargetSideOffset() {
return (angle - 180) / (360 * 3f);
}
@Override
public int compareTo(TransportedItemStack o) {
return beltPosition < o.beltPosition ? 1 : beltPosition > o.beltPosition ? -1 : 0;
}
public TransportedItemStack getSimilar() {
TransportedItemStack copy = new TransportedItemStack(stack.copy());
copy.beltPosition = beltPosition;
copy.insertedAt = insertedAt;
copy.insertedFrom = insertedFrom;
copy.prevBeltPosition = prevBeltPosition;
copy.prevSideOffset = prevSideOffset;
copy.processedBy = processedBy;
copy.processingTime = processingTime;
return copy;
}
public TransportedItemStack copy() {
TransportedItemStack copy = getSimilar();
copy.angle = angle;
return copy;
}
public CompoundNBT serializeNBT() {
CompoundNBT nbt = new CompoundNBT();
nbt.put("Item", stack.serializeNBT());
nbt.putFloat("Pos", beltPosition);
nbt.putFloat("PrevPos", prevBeltPosition);
nbt.putFloat("Offset", sideOffset);
nbt.putFloat("PrevOffset", prevSideOffset);
nbt.putInt("InSegment", insertedAt);
nbt.putInt("Angle", angle);
nbt.putInt("InDirection", insertedFrom.getIndex());
nbt.putBoolean("Locked", locked);
return nbt;
}
public static TransportedItemStack read(CompoundNBT nbt) {
TransportedItemStack stack = new TransportedItemStack(ItemStack.read(nbt.getCompound("Item")));
stack.beltPosition = nbt.getFloat("Pos");
stack.prevBeltPosition = nbt.getFloat("PrevPos");
stack.sideOffset = nbt.getFloat("Offset");
stack.prevSideOffset = nbt.getFloat("PrevOffset");
stack.insertedAt = nbt.getInt("InSegment");
stack.angle = nbt.getInt("Angle");
stack.insertedFrom = Direction.byIndex(nbt.getInt("InDirection"));
stack.locked = nbt.getBoolean("Locked");
return stack;
}
}

View file

@ -64,7 +64,7 @@ public class WindowInABlockTileEntity extends SyncedTileEntity {
windowBlock = getWindowBlock().updatePostPlacement(side, world.getBlockState(offsetPos), world, pos, windowBlock = getWindowBlock().updatePostPlacement(side, world.getBlockState(offsetPos), world, pos,
offsetPos); offsetPos);
} }
sendData(); world.notifyBlockUpdate(getPos(), getBlockState(), getBlockState(), 2 | 16);
markDirty(); markDirty();
} }

View file

@ -1,13 +1,17 @@
package com.simibubi.create.modules.logistics; package com.simibubi.create.modules.logistics;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import com.simibubi.create.AllRecipes; import com.simibubi.create.AllRecipes;
import com.simibubi.create.CreateConfig; import com.simibubi.create.CreateConfig;
import com.simibubi.create.foundation.utility.ItemHelper; import com.simibubi.create.foundation.utility.ItemHelper;
import com.simibubi.create.modules.contraptions.base.ProcessingRecipe;
import com.simibubi.create.modules.contraptions.receivers.SplashingRecipe; import com.simibubi.create.modules.contraptions.receivers.SplashingRecipe;
import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity;
import com.simibubi.create.modules.contraptions.relays.belt.TransportedItemStack;
import net.minecraft.entity.item.ItemEntity; import net.minecraft.entity.item.ItemEntity;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
@ -40,12 +44,27 @@ public class InWorldProcessing {
} }
public static boolean canProcess(ItemEntity entity, Type type) { public static boolean canProcess(ItemEntity entity, Type type) {
World world = entity.world; if (entity.getPersistentData().contains("CreateData")) {
CompoundNBT compound = entity.getPersistentData().getCompound("CreateData");
if (compound.contains("Processing")) {
CompoundNBT processing = compound.getCompound("Processing");
if (entity.getPersistentData().contains("CreateData") if (Type.valueOf(processing.getString("Type")) != type) {
&& entity.getPersistentData().getCompound("CreateData").contains("Processing")) boolean canProcess = canProcess(entity.getItem(), type, entity.world);
processing.putString("Type", type.name());
if (!canProcess)
processing.putInt("Time", -1);
return canProcess;
} else if (processing.getInt("Time") >= 0)
return true; return true;
else if (processing.getInt("Time") == -1)
return false;
}
}
return canProcess(entity.getItem(), type, entity.world);
}
private static boolean canProcess(ItemStack stack, Type type, World world) {
if (type == Type.BLASTING) { if (type == Type.BLASTING) {
return true; return true;
} }
@ -53,13 +72,13 @@ public class InWorldProcessing {
if (type == Type.SMOKING) { if (type == Type.SMOKING) {
SmokerTileEntity smoker = new SmokerTileEntity(); SmokerTileEntity smoker = new SmokerTileEntity();
smoker.setWorld(world); smoker.setWorld(world);
smoker.setInventorySlotContents(0, entity.getItem()); 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(); return recipe.isPresent();
} }
if (type == Type.SPLASHING) { if (type == Type.SPLASHING) {
splashingInv.setInventorySlotContents(0, entity.getItem()); splashingInv.setInventorySlotContents(0, stack);
Optional<SplashingRecipe> recipe = world.getRecipeManager().getRecipe(AllRecipes.Types.SPLASHING, Optional<SplashingRecipe> recipe = world.getRecipeManager().getRecipe(AllRecipes.Types.SPLASHING,
splashingInv, world); splashingInv, world);
return recipe.isPresent(); return recipe.isPresent();
@ -68,59 +87,90 @@ public class InWorldProcessing {
return false; return false;
} }
public static void process(ItemEntity entity, Type type) { public static void applyProcessing(ItemEntity entity, Type type) {
World world = entity.world;
if (decrementProcessingTime(entity, type) != 0) if (decrementProcessingTime(entity, type) != 0)
return; return;
List<ItemStack> stacks = process(entity.getItem(), type, entity.world);
if (stacks == null)
return;
if (stacks.isEmpty()) {
entity.remove();
return;
}
entity.setItem(stacks.remove(0));
for (ItemStack additional : stacks) {
ItemEntity entityIn = new ItemEntity(entity.world, entity.posX, entity.posY, entity.posZ, additional);
entityIn.setMotion(entity.getMotion());
entity.world.addEntity(entityIn);
}
}
public static List<TransportedItemStack> applyProcessing(TransportedItemStack transported, BeltTileEntity belt, Type type) {
if (transported.processedBy != type) {
transported.processedBy = type;
transported.processingTime = CreateConfig.parameters.inWorldProcessingTime.get() + 1;
if (!canProcess(transported.stack, type, belt.getWorld()))
transported.processingTime = -1;
return null;
}
if (transported.processingTime == -1)
return null;
if (transported.processingTime-- > 0)
return null;
List<ItemStack> stacks = process(transported.stack, type, belt.getWorld());
List<TransportedItemStack> transportedStacks = new ArrayList<>();
for (ItemStack additional : stacks) {
TransportedItemStack newTransported = transported.getSimilar();
newTransported.stack = additional.copy();
transportedStacks.add(newTransported);
}
return transportedStacks;
}
private static List<ItemStack> process(ItemStack stack, Type type, World world) {
if (type == Type.SPLASHING) { if (type == Type.SPLASHING) {
splashingInv.setInventorySlotContents(0, entity.getItem()); splashingInv.setInventorySlotContents(0, stack);
Optional<SplashingRecipe> recipe = world.getRecipeManager().getRecipe(AllRecipes.Types.SPLASHING, Optional<SplashingRecipe> recipe = world.getRecipeManager().getRecipe(AllRecipes.Types.SPLASHING,
splashingInv, world); splashingInv, world);
if (recipe.isPresent()) if (recipe.isPresent())
applyRecipeOn(entity, recipe.get()); return applyRecipeOn(stack, recipe.get());
return; return null;
} }
SmokerTileEntity smoker = new SmokerTileEntity(); SmokerTileEntity smoker = new SmokerTileEntity();
smoker.setWorld(world); smoker.setWorld(world);
smoker.setInventorySlotContents(0, entity.getItem()); 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) { if (type == Type.BLASTING) {
FurnaceTileEntity furnace = new FurnaceTileEntity(); FurnaceTileEntity furnace = new FurnaceTileEntity();
furnace.setWorld(world); furnace.setWorld(world);
furnace.setInventorySlotContents(0, entity.getItem()); furnace.setInventorySlotContents(0, stack);
Optional<FurnaceRecipe> smeltingRecipe = world.getRecipeManager().getRecipe(IRecipeType.SMELTING, furnace, Optional<FurnaceRecipe> smeltingRecipe = world.getRecipeManager().getRecipe(IRecipeType.SMELTING, furnace,
world); world);
if (!smokingRecipe.isPresent()) { if (!smokingRecipe.isPresent()) {
if (smeltingRecipe.isPresent()) { if (smeltingRecipe.isPresent())
applyRecipeOn(entity, smeltingRecipe.get()); return applyRecipeOn(stack, smeltingRecipe.get());
return;
}
BlastFurnaceTileEntity blastFurnace = new BlastFurnaceTileEntity(); BlastFurnaceTileEntity blastFurnace = new BlastFurnaceTileEntity();
blastFurnace.setWorld(world); blastFurnace.setWorld(world);
blastFurnace.setInventorySlotContents(0, entity.getItem()); blastFurnace.setInventorySlotContents(0, stack);
Optional<BlastingRecipe> blastingRecipe = world.getRecipeManager().getRecipe(IRecipeType.BLASTING, Optional<BlastingRecipe> blastingRecipe = world.getRecipeManager().getRecipe(IRecipeType.BLASTING,
blastFurnace, world); blastFurnace, world);
if (blastingRecipe.isPresent()) { if (blastingRecipe.isPresent())
applyRecipeOn(entity, blastingRecipe.get()); return applyRecipeOn(stack, blastingRecipe.get());
return;
}
} }
entity.remove(); return Collections.emptyList();
return;
} }
if (type == Type.SMOKING && smokingRecipe.isPresent()) { if (type == Type.SMOKING && smokingRecipe.isPresent())
applyRecipeOn(entity, smokingRecipe.get()); return applyRecipeOn(stack, smokingRecipe.get());
return;
}
return null;
} }
private static int decrementProcessingTime(ItemEntity entity, Type type) { private static int decrementProcessingTime(ItemEntity entity, Type type) {
@ -145,12 +195,29 @@ public class InWorldProcessing {
} }
public static void applyRecipeOn(ItemEntity entity, IRecipe<?> recipe) { public static void applyRecipeOn(ItemEntity entity, IRecipe<?> recipe) {
List<ItemStack> stacks = applyRecipeOn(entity.getItem(), recipe);
if (stacks == null)
return;
if (stacks.isEmpty()) {
entity.remove();
return;
}
entity.setItem(stacks.remove(0));
for (ItemStack additional : stacks) {
ItemEntity entityIn = new ItemEntity(entity.world, entity.posX, entity.posY, entity.posZ, additional);
entityIn.setMotion(entity.getMotion());
entity.world.addEntity(entityIn);
}
}
private static List<ItemStack> applyRecipeOn(ItemStack stackIn, IRecipe<?> recipe) {
List<ItemStack> stacks; List<ItemStack> stacks;
if (recipe instanceof SplashingRecipe) { if (recipe instanceof ProcessingRecipe) {
stacks = new ArrayList<>(); stacks = new ArrayList<>();
for (int i = 0; i < entity.getItem().getCount(); i++) { for (int i = 0; i < stackIn.getCount(); i++) {
for (ItemStack stack : ((SplashingRecipe) recipe).rollResults()) { List<ItemStack> rollResults = ((ProcessingRecipe<?>) recipe).rollResults();
for (ItemStack stack : rollResults) {
for (ItemStack previouslyRolled : stacks) { for (ItemStack previouslyRolled : stacks) {
if (stack.isEmpty()) if (stack.isEmpty())
continue; continue;
@ -170,19 +237,10 @@ public class InWorldProcessing {
} }
} else { } else {
ItemStack out = recipe.getRecipeOutput().copy(); ItemStack out = recipe.getRecipeOutput().copy();
stacks = ItemHelper.multipliedOutput(entity.getItem(), out); stacks = ItemHelper.multipliedOutput(stackIn, out);
} }
if (stacks.isEmpty()) { return stacks;
entity.remove();
return;
}
entity.setItem(stacks.remove(0));
for (ItemStack additional : stacks) {
ItemEntity entityIn = new ItemEntity(entity.world, entity.posX, entity.posY, entity.posZ, additional);
entityIn.setMotion(entity.getMotion());
entity.world.addEntity(entityIn);
}
} }
public static boolean isFrozen() { public static boolean isFrozen() {

View file

@ -123,7 +123,22 @@ public interface IExtractor extends ITickableTileEntity, IInventoryManipulator {
} }
default boolean hasSpaceForExtracting() { default boolean hasSpaceForExtracting() {
return getWorld().getEntitiesWithinAABBExcludingEntity(null, new AxisAlignedBB(getPos())).isEmpty(); BlockPos pos = getPos();
World world = getWorld();
if (AllBlocks.BELT.typeOf(world.getBlockState(pos.down()))) {
TileEntity te = world.getTileEntity(pos.down());
if (te != null && te instanceof BeltTileEntity) {
BeltTileEntity belt = (BeltTileEntity) te;
BeltTileEntity controller = belt.getControllerTE();
if (controller != null) {
if (!controller.getInventory().canInsertFrom(belt.index, Direction.UP))
return false;
}
}
}
return world.getEntitiesWithinAABBExcludingEntity(null, new AxisAlignedBB(getPos())).isEmpty();
} }
default ItemStack extract(boolean simulate) { default ItemStack extract(boolean simulate) {
@ -131,7 +146,6 @@ public interface IExtractor extends ITickableTileEntity, IInventoryManipulator {
ItemStack extracting = ItemStack.EMPTY; ItemStack extracting = ItemStack.EMPTY;
ItemStack filterItem = (this instanceof IHaveFilter) ? ((IHaveFilter) this).getFilter() : ItemStack.EMPTY; ItemStack filterItem = (this instanceof IHaveFilter) ? ((IHaveFilter) this).getFilter() : ItemStack.EMPTY;
World world = getWorld(); World world = getWorld();
BlockPos pos = getPos();
int extractionCount = filterItem.isEmpty() ? CreateConfig.parameters.extractorAmount.get() int extractionCount = filterItem.isEmpty() ? CreateConfig.parameters.extractorAmount.get()
: filterItem.getCount(); : filterItem.getCount();
boolean checkHasEnoughItems = !filterItem.isEmpty(); boolean checkHasEnoughItems = !filterItem.isEmpty();
@ -177,15 +191,6 @@ public interface IExtractor extends ITickableTileEntity, IInventoryManipulator {
break Extraction; break Extraction;
} while (true); } while (true);
if (AllBlocks.BELT.typeOf(world.getBlockState(pos.down()))) {
TileEntity te = world.getTileEntity(pos.down());
if (te != null && te instanceof BeltTileEntity && !extracting.isEmpty()) {
if (((BeltTileEntity) te).tryInsertingFromSide(Direction.UP, extracting.copy(), simulate))
return extracting;
return ItemStack.EMPTY;
}
}
if (!simulate && hasEnoughItems) { if (!simulate && hasEnoughItems) {
Vec3d entityPos = VecHelper.getCenterOf(getPos()).add(0, -0.5f, 0); Vec3d entityPos = VecHelper.getCenterOf(getPos()).add(0, -0.5f, 0);
Entity entityIn = null; Entity entityIn = null;

View file

@ -10,8 +10,8 @@ import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.BeltAttachmentState; import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.BeltAttachmentState;
import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.IBeltAttachment; import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.IBeltAttachment;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock; import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock;
import com.simibubi.create.modules.contraptions.relays.belt.BeltInventory.TransportedItemStack;
import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity; import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity;
import com.simibubi.create.modules.contraptions.relays.belt.TransportedItemStack;
import com.simibubi.create.modules.logistics.block.IBlockWithFilter; import com.simibubi.create.modules.logistics.block.IBlockWithFilter;
import com.simibubi.create.modules.logistics.block.IInventoryManipulator; import com.simibubi.create.modules.logistics.block.IInventoryManipulator;
@ -25,8 +25,8 @@ import net.minecraft.item.ItemStack;
import net.minecraft.state.StateContainer.Builder; import net.minecraft.state.StateContainer.Builder;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.Hand;
import net.minecraft.util.Direction.Axis; import net.minecraft.util.Direction.Axis;
import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult; import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;

View file

@ -3,7 +3,7 @@ package com.simibubi.create.modules.logistics.block.belts;
import com.simibubi.create.AllTileEntities; import com.simibubi.create.AllTileEntities;
import com.simibubi.create.foundation.block.SyncedTileEntity; import com.simibubi.create.foundation.block.SyncedTileEntity;
import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.modules.contraptions.relays.belt.BeltInventory.ItemHandlerSegment; import com.simibubi.create.modules.contraptions.relays.belt.ItemHandlerBeltSegment;
import com.simibubi.create.modules.logistics.block.IHaveFilter; import com.simibubi.create.modules.logistics.block.IHaveFilter;
import com.simibubi.create.modules.logistics.block.IInventoryManipulator; import com.simibubi.create.modules.logistics.block.IInventoryManipulator;
@ -113,7 +113,7 @@ public class BeltFunnelTileEntity extends SyncedTileEntity
public ItemStack tryToInsert(ItemStack stack) { public ItemStack tryToInsert(ItemStack stack) {
if (!inventory.isPresent()) if (!inventory.isPresent())
return stack; return stack;
if (waitingForInventorySpace && !(inventory.orElse(null) instanceof ItemHandlerSegment)) if (waitingForInventorySpace && !(inventory.orElse(null) instanceof ItemHandlerBeltSegment))
return stack; return stack;
if (!filter.isEmpty() && !ItemStack.areItemsEqual(filter, stack)) if (!filter.isEmpty() && !ItemStack.areItemsEqual(filter, stack))
return stack; return stack;

View file

@ -13,8 +13,8 @@ import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.I
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock; import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Part; import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Part;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope; import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope;
import com.simibubi.create.modules.contraptions.relays.belt.BeltInventory.TransportedItemStack;
import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity; import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity;
import com.simibubi.create.modules.contraptions.relays.belt.TransportedItemStack;
import com.simibubi.create.modules.logistics.block.IBlockWithFilter; import com.simibubi.create.modules.logistics.block.IBlockWithFilter;
import net.minecraft.block.Block; import net.minecraft.block.Block;