diff --git a/src/main/java/com/simibubi/create/foundation/block/SyncedTileEntity.java b/src/main/java/com/simibubi/create/foundation/block/SyncedTileEntity.java index 2fe20f40d..9f9eb3b8e 100644 --- a/src/main/java/com/simibubi/create/foundation/block/SyncedTileEntity.java +++ b/src/main/java/com/simibubi/create/foundation/block/SyncedTileEntity.java @@ -28,9 +28,9 @@ public abstract class SyncedTileEntity extends TileEntity { } public void sendData() { - world.notifyBlockUpdate(getPos(), getBlockState(), getBlockState(), 2 | 16); + world.notifyBlockUpdate(getPos(), getBlockState(), getBlockState(), 2 | 4 | 16); } - + public void causeBlockUpdate() { world.notifyBlockUpdate(getPos(), getBlockState(), getBlockState(), 1); } diff --git a/src/main/java/com/simibubi/create/modules/contraptions/receivers/EncasedFanBeltHandler.java b/src/main/java/com/simibubi/create/modules/contraptions/receivers/EncasedFanBeltHandler.java new file mode 100644 index 000000000..ab4e01f04 --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/contraptions/receivers/EncasedFanBeltHandler.java @@ -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 findBelts(EncasedFanTileEntity fan) { + if (fan.getSpeed() == 0) + return Collections.emptyList(); + List 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 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); + }); + } + + } +} diff --git a/src/main/java/com/simibubi/create/modules/contraptions/receivers/EncasedFanParticleHandler.java b/src/main/java/com/simibubi/create/modules/contraptions/receivers/EncasedFanParticleHandler.java index cf04c912d..f40e14b24 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/receivers/EncasedFanParticleHandler.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/receivers/EncasedFanParticleHandler.java @@ -26,7 +26,7 @@ public class EncasedFanParticleHandler { private void initEffects() { List 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)); effects.put(Blocks.AIR, standardFX); diff --git a/src/main/java/com/simibubi/create/modules/contraptions/receivers/EncasedFanTileEntity.java b/src/main/java/com/simibubi/create/modules/contraptions/receivers/EncasedFanTileEntity.java index 806902bce..cb684146e 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/receivers/EncasedFanTileEntity.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/receivers/EncasedFanTileEntity.java @@ -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.POSITIVE; +import java.util.Collections; import java.util.List; import com.simibubi.create.AllBlockTags; @@ -14,6 +15,7 @@ import com.simibubi.create.CreateClient; import com.simibubi.create.CreateConfig; import com.simibubi.create.foundation.utility.VecHelper; 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.Type; @@ -51,6 +53,7 @@ public class EncasedFanTileEntity extends GeneratingKineticTileEntity { protected boolean findFrontBlock; protected BlockState frontBlock; protected boolean isGenerator; + protected List affectedBelts = Collections.emptyList(); public EncasedFanTileEntity() { super(AllTileEntities.ENCASED_FAN.type); @@ -67,6 +70,7 @@ public class EncasedFanTileEntity extends GeneratingKineticTileEntity { super.readClientUpdate(tag); updateFrontBlock(); updateBBs(); + affectedBelts = EncasedFanBeltHandler.findBelts(this); } @Override @@ -140,6 +144,7 @@ public class EncasedFanTileEntity extends GeneratingKineticTileEntity { backBB = new AxisAlignedBB(0, 0, 0, 0, 0, 0); } + affectedBelts = EncasedFanBeltHandler.findBelts(this); sendData(); } @@ -190,6 +195,8 @@ public class EncasedFanTileEntity extends GeneratingKineticTileEntity { if (getSpeed() == 0 || isGenerator) return; + EncasedFanBeltHandler.tickBelts(this, affectedBelts); + List frontEntities = world.getEntitiesWithinAABBExcludingEntity(null, frontBB); for (Entity entity : frontEntities) { moveEntity(entity, true); @@ -238,7 +245,7 @@ public class EncasedFanTileEntity extends GeneratingKineticTileEntity { return; if (canProcess((ItemEntity) entity)) - InWorldProcessing.process((ItemEntity) entity, getProcessingType()); + InWorldProcessing.applyProcessing((ItemEntity) entity, getProcessingType()); } else { if (getProcessingType() == Type.SMOKING) { diff --git a/src/main/java/com/simibubi/create/modules/contraptions/receivers/MechanicalPressBlock.java b/src/main/java/com/simibubi/create/modules/contraptions/receivers/MechanicalPressBlock.java index c88e2ea80..9f9dcebcb 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/receivers/MechanicalPressBlock.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/receivers/MechanicalPressBlock.java @@ -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.IBeltAttachment; 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.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.BlockState; diff --git a/src/main/java/com/simibubi/create/modules/contraptions/receivers/MechanicalPressTileEntity.java b/src/main/java/com/simibubi/create/modules/contraptions/receivers/MechanicalPressTileEntity.java index bc00afb61..348878c48 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/receivers/MechanicalPressTileEntity.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/receivers/MechanicalPressTileEntity.java @@ -6,8 +6,8 @@ import com.simibubi.create.AllRecipes; import com.simibubi.create.AllTileEntities; import com.simibubi.create.foundation.utility.VecHelper; 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.TransportedItemStack; import com.simibubi.create.modules.logistics.InWorldProcessing; import net.minecraft.entity.Entity; diff --git a/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/AllBeltAttachments.java b/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/AllBeltAttachments.java index 4252dfe56..2373205ff 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/AllBeltAttachments.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/AllBeltAttachments.java @@ -6,7 +6,6 @@ import java.util.function.Consumer; import com.simibubi.create.AllBlocks; import com.simibubi.create.Create; -import com.simibubi.create.modules.contraptions.relays.belt.BeltInventory.TransportedItemStack; import net.minecraft.block.BlockState; import net.minecraft.entity.Entity; diff --git a/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltBlock.java b/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltBlock.java index 2d59c8d71..f08081956 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltBlock.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltBlock.java @@ -1,6 +1,6 @@ package com.simibubi.create.modules.contraptions.relays.belt; -import java.util.Iterator; +import java.util.Collections; import java.util.LinkedList; 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.utility.Lang; 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 net.minecraft.block.Block; @@ -91,7 +90,7 @@ public class BeltBlock extends HorizontalKineticBlock implements IWithoutBlockIt public boolean isFlammable(BlockState state, IBlockReader world, BlockPos pos, Direction face) { return false; } - + @Override public void onLanded(IBlockReader worldIn, Entity entityIn) { super.onLanded(worldIn, entityIn); @@ -187,22 +186,15 @@ public class BeltBlock extends HorizontalKineticBlock implements IWithoutBlockIt BeltTileEntity belt = (BeltTileEntity) te; if (isHand) { - TileEntity controllerTe = worldIn.getTileEntity(belt.getController()); - if (controllerTe == null || !(controllerTe instanceof BeltTileEntity)) + BeltTileEntity controllerBelt = belt.getControllerTE(); + if (controllerBelt == null) return false; if (worldIn.isRemote) return true; - BeltTileEntity controllerBelt = (BeltTileEntity) controllerTe; - for (Iterator 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); - iterator.remove(); - controllerBelt.markDirty(); - controllerBelt.sendData(); - } - } + controllerBelt.getInventory().forEachWithin(belt.index, .75f, (transportedItemStack) -> { + player.inventory.placeItemBackInInventory(worldIn, transportedItemStack.stack); + return Collections.emptyList(); + }); } if (isShaft) { diff --git a/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltInventory.java b/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltInventory.java index afa335b11..c0c09313e 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltInventory.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltInventory.java @@ -1,10 +1,11 @@ package com.simibubi.create.modules.contraptions.relays.belt; +import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.LinkedList; import java.util.List; -import java.util.Random; +import java.util.function.Function; import com.simibubi.create.AllBlocks; import com.simibubi.create.foundation.utility.VecHelper; @@ -122,13 +123,14 @@ public class BeltInventory { int upcomingSegment = (int) (current.beltPosition + (beltMovementPositive ? .5f : -.5f)); for (int segment = upcomingSegment; beltMovementPositive ? 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); if (beltSegment == null) break; for (BeltAttachmentState attachmentState : beltSegment.attachmentTracker.attachments) { 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; belt.sendData(); continue Items; @@ -230,63 +232,6 @@ public class BeltInventory { } - public static class TransportedItemStack implements Comparable { - 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) { return canInsertFrom(segment, Direction.UP); } @@ -328,9 +273,6 @@ public class BeltInventory { } items.add(index, newStack); } - - belt.markDirty(); - belt.sendData(); } public TransportedItemStack getStackAtOffset(int offset) { @@ -373,7 +315,7 @@ public class BeltInventory { belt.getWorld().addEntity(entity); } - private Vec3d getVectorForOffset(float offset) { + public Vec3d getVectorForOffset(float offset) { Slope slope = belt.getBlockState().get(BeltBlock.SLOPE); int verticality = slope == Slope.DOWNWARD ? -1 : slope == Slope.UPWARD ? 1 : 0; float verticalMovement = verticality; @@ -409,70 +351,30 @@ public class BeltInventory { return belt.getDirectionAwareBeltMovementSpeed() > 0; } - public class ItemHandlerSegment implements IItemHandler { - int offset; - - public ItemHandlerSegment(int offset) { - this.offset = offset; - } - - @Override - public int getSlots() { - return 1; - } - - @Override - public ItemStack getStackInSlot(int slot) { - TransportedItemStack stackAtOffset = getStackAtOffset(offset); - if (stackAtOffset == null) - return ItemStack.EMPTY; - return stackAtOffset.stack; - } - - @Override - 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.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 ItemHandlerBeltSegment(this, segment); } - public IItemHandler createHandlerForSegment(int segment) { - return new ItemHandlerSegment(segment); + public void forEachWithin(float position, float distance, + Function> callback) { + List toBeAdded = new ArrayList<>(); + boolean dirty = false; + for (Iterator iterator = items.iterator(); iterator.hasNext();) { + TransportedItemStack transportedItemStack = iterator.next(); + if (Math.abs(position - transportedItemStack.beltPosition) < distance) { + List apply = callback.apply(transportedItemStack); + if (apply == null) + continue; + dirty = true; + toBeAdded.addAll(apply); + iterator.remove(); + } + } + toBeAdded.forEach(this::insert); + if (dirty) { + belt.markDirty(); + belt.sendData(); + } } } diff --git a/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltTileEntity.java b/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltTileEntity.java index e55311eec..ee8052b49 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltTileEntity.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltTileEntity.java @@ -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.BeltBlock.Part; 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 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) { this.controller = controller; } @@ -283,13 +291,9 @@ public class BeltTileEntity extends KineticTileEntity { } public boolean tryInsertingFromSide(Direction side, TransportedItemStack transportedStack, boolean simulate) { - BlockPos controller = getController(); - if (!world.isBlockPresent(controller)) + BeltTileEntity nextBeltController = getControllerTE(); + if (nextBeltController == null) return false; - TileEntity te = world.getTileEntity(controller); - if (te == null || !(te instanceof BeltTileEntity)) - return false; - BeltTileEntity nextBeltController = (BeltTileEntity) te; BeltInventory nextInventory = nextBeltController.getInventory(); if (!nextInventory.canInsertFrom(index, side)) @@ -314,6 +318,7 @@ public class BeltTileEntity extends KineticTileEntity { transportedStack.insertedFrom = side; transportedStack.prevBeltPosition = transportedStack.beltPosition; nextInventory.insert(transportedStack); + nextBeltController.markDirty(); nextBeltController.sendData(); return true; } diff --git a/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltTileEntityRenderer.java b/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltTileEntityRenderer.java index f55c973e7..1b92bebc3 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltTileEntityRenderer.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltTileEntityRenderer.java @@ -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.BlockModelSpinner; 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.client.Minecraft; @@ -56,6 +55,11 @@ public class BeltTileEntityRenderer extends TileEntityRenderer { float offset = MathHelper.lerp(partialTicks, transported.prevBeltPosition, transported.beltPosition); float sideOffset = MathHelper.lerp(partialTicks, transported.prevSideOffset, transported.sideOffset); float verticalMovement = verticality; + + if (te.getSpeed() == 0) { + offset = transported.beltPosition; + sideOffset = transported.sideOffset; + } if (offset < .5) verticalMovement = 0; diff --git a/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/ItemHandlerBeltSegment.java b/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/ItemHandlerBeltSegment.java new file mode 100644 index 000000000..a4f1e2f62 --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/ItemHandlerBeltSegment.java @@ -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; + } + +} \ No newline at end of file diff --git a/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/TransportedItemStack.java b/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/TransportedItemStack.java new file mode 100644 index 000000000..491c859ad --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/TransportedItemStack.java @@ -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 { + 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; + } + +} \ No newline at end of file diff --git a/src/main/java/com/simibubi/create/modules/curiosities/partialWindows/WindowInABlockTileEntity.java b/src/main/java/com/simibubi/create/modules/curiosities/partialWindows/WindowInABlockTileEntity.java index 8369c85e7..57a9e61de 100644 --- a/src/main/java/com/simibubi/create/modules/curiosities/partialWindows/WindowInABlockTileEntity.java +++ b/src/main/java/com/simibubi/create/modules/curiosities/partialWindows/WindowInABlockTileEntity.java @@ -20,7 +20,7 @@ public class WindowInABlockTileEntity extends SyncedTileEntity { private BlockState partialBlock = Blocks.AIR.getDefaultState(); private BlockState windowBlock = Blocks.AIR.getDefaultState(); - + @OnlyIn(value = Dist.CLIENT) private IModelData modelData; @@ -64,7 +64,7 @@ public class WindowInABlockTileEntity extends SyncedTileEntity { windowBlock = getWindowBlock().updatePostPlacement(side, world.getBlockState(offsetPos), world, pos, offsetPos); } - sendData(); + world.notifyBlockUpdate(getPos(), getBlockState(), getBlockState(), 2 | 16); markDirty(); } diff --git a/src/main/java/com/simibubi/create/modules/logistics/InWorldProcessing.java b/src/main/java/com/simibubi/create/modules/logistics/InWorldProcessing.java index 47d1400c6..c35402825 100644 --- a/src/main/java/com/simibubi/create/modules/logistics/InWorldProcessing.java +++ b/src/main/java/com/simibubi/create/modules/logistics/InWorldProcessing.java @@ -1,13 +1,17 @@ package com.simibubi.create.modules.logistics; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Optional; import com.simibubi.create.AllRecipes; import com.simibubi.create.CreateConfig; 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.relays.belt.BeltTileEntity; +import com.simibubi.create.modules.contraptions.relays.belt.TransportedItemStack; import net.minecraft.entity.item.ItemEntity; import net.minecraft.item.ItemStack; @@ -40,12 +44,27 @@ public class InWorldProcessing { } 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") - && entity.getPersistentData().getCompound("CreateData").contains("Processing")) - return true; + if (Type.valueOf(processing.getString("Type")) != type) { + 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; + 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) { return true; } @@ -53,13 +72,13 @@ public class InWorldProcessing { if (type == Type.SMOKING) { SmokerTileEntity smoker = new SmokerTileEntity(); smoker.setWorld(world); - smoker.setInventorySlotContents(0, entity.getItem()); + smoker.setInventorySlotContents(0, stack); Optional recipe = world.getRecipeManager().getRecipe(IRecipeType.SMOKING, smoker, world); return recipe.isPresent(); } if (type == Type.SPLASHING) { - splashingInv.setInventorySlotContents(0, entity.getItem()); + splashingInv.setInventorySlotContents(0, stack); Optional recipe = world.getRecipeManager().getRecipe(AllRecipes.Types.SPLASHING, splashingInv, world); return recipe.isPresent(); @@ -68,59 +87,90 @@ public class InWorldProcessing { return false; } - public static void process(ItemEntity entity, Type type) { - World world = entity.world; + public static void applyProcessing(ItemEntity entity, Type type) { if (decrementProcessingTime(entity, type) != 0) return; + List 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 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 stacks = process(transported.stack, type, belt.getWorld()); + List transportedStacks = new ArrayList<>(); + for (ItemStack additional : stacks) { + TransportedItemStack newTransported = transported.getSimilar(); + newTransported.stack = additional.copy(); + transportedStacks.add(newTransported); + } + return transportedStacks; + } + + private static List process(ItemStack stack, Type type, World world) { if (type == Type.SPLASHING) { - splashingInv.setInventorySlotContents(0, entity.getItem()); + splashingInv.setInventorySlotContents(0, stack); Optional recipe = world.getRecipeManager().getRecipe(AllRecipes.Types.SPLASHING, splashingInv, world); if (recipe.isPresent()) - applyRecipeOn(entity, recipe.get()); - return; + return applyRecipeOn(stack, recipe.get()); + return null; } SmokerTileEntity smoker = new SmokerTileEntity(); smoker.setWorld(world); - smoker.setInventorySlotContents(0, entity.getItem()); + smoker.setInventorySlotContents(0, stack); Optional smokingRecipe = world.getRecipeManager().getRecipe(IRecipeType.SMOKING, smoker, world); if (type == Type.BLASTING) { FurnaceTileEntity furnace = new FurnaceTileEntity(); furnace.setWorld(world); - furnace.setInventorySlotContents(0, entity.getItem()); + furnace.setInventorySlotContents(0, stack); Optional smeltingRecipe = world.getRecipeManager().getRecipe(IRecipeType.SMELTING, furnace, world); if (!smokingRecipe.isPresent()) { - if (smeltingRecipe.isPresent()) { - applyRecipeOn(entity, smeltingRecipe.get()); - return; - } + if (smeltingRecipe.isPresent()) + return applyRecipeOn(stack, smeltingRecipe.get()); BlastFurnaceTileEntity blastFurnace = new BlastFurnaceTileEntity(); blastFurnace.setWorld(world); - blastFurnace.setInventorySlotContents(0, entity.getItem()); + blastFurnace.setInventorySlotContents(0, stack); Optional blastingRecipe = world.getRecipeManager().getRecipe(IRecipeType.BLASTING, blastFurnace, world); - if (blastingRecipe.isPresent()) { - applyRecipeOn(entity, blastingRecipe.get()); - return; - } + if (blastingRecipe.isPresent()) + return applyRecipeOn(stack, blastingRecipe.get()); } - entity.remove(); - return; + return Collections.emptyList(); } - if (type == Type.SMOKING && smokingRecipe.isPresent()) { - applyRecipeOn(entity, smokingRecipe.get()); - return; - } + if (type == Type.SMOKING && smokingRecipe.isPresent()) + return applyRecipeOn(stack, smokingRecipe.get()); + return null; } private static int decrementProcessingTime(ItemEntity entity, Type type) { @@ -143,14 +193,31 @@ public class InWorldProcessing { processing.putInt("Time", value); return value; } - + public static void applyRecipeOn(ItemEntity entity, IRecipe recipe) { + List 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 applyRecipeOn(ItemStack stackIn, IRecipe recipe) { List stacks; - if (recipe instanceof SplashingRecipe) { + if (recipe instanceof ProcessingRecipe) { stacks = new ArrayList<>(); - for (int i = 0; i < entity.getItem().getCount(); i++) { - for (ItemStack stack : ((SplashingRecipe) recipe).rollResults()) { + for (int i = 0; i < stackIn.getCount(); i++) { + List rollResults = ((ProcessingRecipe) recipe).rollResults(); + for (ItemStack stack : rollResults) { for (ItemStack previouslyRolled : stacks) { if (stack.isEmpty()) continue; @@ -170,19 +237,10 @@ public class InWorldProcessing { } } else { ItemStack out = recipe.getRecipeOutput().copy(); - stacks = ItemHelper.multipliedOutput(entity.getItem(), out); + stacks = ItemHelper.multipliedOutput(stackIn, out); } - 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); - } + return stacks; } public static boolean isFrozen() { diff --git a/src/main/java/com/simibubi/create/modules/logistics/block/IExtractor.java b/src/main/java/com/simibubi/create/modules/logistics/block/IExtractor.java index fa8a01087..29b5d40a2 100644 --- a/src/main/java/com/simibubi/create/modules/logistics/block/IExtractor.java +++ b/src/main/java/com/simibubi/create/modules/logistics/block/IExtractor.java @@ -123,7 +123,22 @@ public interface IExtractor extends ITickableTileEntity, IInventoryManipulator { } 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) { @@ -131,7 +146,6 @@ public interface IExtractor extends ITickableTileEntity, IInventoryManipulator { ItemStack extracting = ItemStack.EMPTY; ItemStack filterItem = (this instanceof IHaveFilter) ? ((IHaveFilter) this).getFilter() : ItemStack.EMPTY; World world = getWorld(); - BlockPos pos = getPos(); int extractionCount = filterItem.isEmpty() ? CreateConfig.parameters.extractorAmount.get() : filterItem.getCount(); boolean checkHasEnoughItems = !filterItem.isEmpty(); @@ -177,15 +191,6 @@ public interface IExtractor extends ITickableTileEntity, IInventoryManipulator { break Extraction; } 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) { Vec3d entityPos = VecHelper.getCenterOf(getPos()).add(0, -0.5f, 0); Entity entityIn = null; diff --git a/src/main/java/com/simibubi/create/modules/logistics/block/belts/BeltFunnelBlock.java b/src/main/java/com/simibubi/create/modules/logistics/block/belts/BeltFunnelBlock.java index 8b156f226..4919c99f6 100644 --- a/src/main/java/com/simibubi/create/modules/logistics/block/belts/BeltFunnelBlock.java +++ b/src/main/java/com/simibubi/create/modules/logistics/block/belts/BeltFunnelBlock.java @@ -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.IBeltAttachment; 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.TransportedItemStack; import com.simibubi.create.modules.logistics.block.IBlockWithFilter; 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.tileentity.TileEntity; import net.minecraft.util.Direction; -import net.minecraft.util.Hand; import net.minecraft.util.Direction.Axis; +import net.minecraft.util.Hand; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockRayTraceResult; import net.minecraft.util.math.Vec3d; diff --git a/src/main/java/com/simibubi/create/modules/logistics/block/belts/BeltFunnelTileEntity.java b/src/main/java/com/simibubi/create/modules/logistics/block/belts/BeltFunnelTileEntity.java index 9987bc0c3..53a5f4b9b 100644 --- a/src/main/java/com/simibubi/create/modules/logistics/block/belts/BeltFunnelTileEntity.java +++ b/src/main/java/com/simibubi/create/modules/logistics/block/belts/BeltFunnelTileEntity.java @@ -3,7 +3,7 @@ package com.simibubi.create.modules.logistics.block.belts; import com.simibubi.create.AllTileEntities; import com.simibubi.create.foundation.block.SyncedTileEntity; 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.IInventoryManipulator; @@ -113,7 +113,7 @@ public class BeltFunnelTileEntity extends SyncedTileEntity public ItemStack tryToInsert(ItemStack stack) { if (!inventory.isPresent()) return stack; - if (waitingForInventorySpace && !(inventory.orElse(null) instanceof ItemHandlerSegment)) + if (waitingForInventorySpace && !(inventory.orElse(null) instanceof ItemHandlerBeltSegment)) return stack; if (!filter.isEmpty() && !ItemStack.areItemsEqual(filter, stack)) return stack; diff --git a/src/main/java/com/simibubi/create/modules/logistics/block/belts/EntityDetectorBlock.java b/src/main/java/com/simibubi/create/modules/logistics/block/belts/EntityDetectorBlock.java index 94884f53c..c34911991 100644 --- a/src/main/java/com/simibubi/create/modules/logistics/block/belts/EntityDetectorBlock.java +++ b/src/main/java/com/simibubi/create/modules/logistics/block/belts/EntityDetectorBlock.java @@ -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.Part; 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 com.simibubi.create.modules.logistics.block.IBlockWithFilter; import net.minecraft.block.Block;