Buffing the Buffers

- Fixed large amounts of output in crushing wheels getting voided due to its buffer capacity
- Fixed basin processing running constant recipe lookups while backed up #1911
- Fixed mixer retracting after every operation when auto-output is active
This commit is contained in:
simibubi 2021-07-09 19:27:50 +02:00
parent 7ed7b957dd
commit 352f213429
14 changed files with 113 additions and 63 deletions

View file

@ -426,17 +426,17 @@ a3a11524cd3515fc01d905767b4b7ea782adaf03 assets/create/blockstates/yellow_seat.j
7f39521b211441f5c3e06d60c5978cebe16cacfb assets/create/blockstates/zinc_block.json
b7181bcd8182b2f17088e5aa881f374c9c65470c assets/create/blockstates/zinc_ore.json
e1d3c02695cbd2ee7bbede97f72941835634a3a5 assets/create/lang/en_ud.json
c75657997c7adf06fd12020aacc9465605563183 assets/create/lang/en_us.json
94f26bdaf8d1a39c25c4da551530696d4ff8b24c assets/create/lang/unfinished/de_de.json
7628f0328198a4100dc938de4c4ea8f792473a85 assets/create/lang/en_us.json
54c93de1ca876299fc34dc593580aeed5748aa15 assets/create/lang/unfinished/de_de.json
51ed1df10b8afcf27f9dcdae3bca80d05740d450 assets/create/lang/unfinished/es_es.json
47bf5a31dfd8530a0db9813a56b762cf3129ddc6 assets/create/lang/unfinished/es_mx.json
8bc26af581f714ea54f6e1a89ee2cbac917bf7df assets/create/lang/unfinished/fr_fr.json
e1c11002170d4c0acb9ef442c41ea04b99d20440 assets/create/lang/unfinished/it_it.json
72e1a89ef45c530eaab6f27b4d2dd447775b5d0a assets/create/lang/unfinished/es_mx.json
0da959961c4bde45bcef869bc9bd58eac1d3bd40 assets/create/lang/unfinished/fr_fr.json
ba963b9db50f0ea57dee1a93664aacf2dc44eec5 assets/create/lang/unfinished/it_it.json
caa45f4ae4e4e9b338999b7975767dc33e569881 assets/create/lang/unfinished/ja_jp.json
aaa8ecc84b853cc8a93f8d5812f22beefaf48266 assets/create/lang/unfinished/ko_kr.json
9e32f7de0acff6ee4ee6bfa5beb5a4c103cdcb0a assets/create/lang/unfinished/nl_nl.json
2046b5e7c9904f6ac07d7f9b94fd80a52a1f5721 assets/create/lang/unfinished/nl_nl.json
70f552fe3bd0365d9f1f339032bc598bc0ff9026 assets/create/lang/unfinished/pl_pl.json
83422c331b7c670d1dc8450e0b02a6443fc8ca1b assets/create/lang/unfinished/pt_br.json
427a0252a5f3d5282ab572c6b06638117ed68760 assets/create/lang/unfinished/pt_br.json
f12de6d61ff3f634e5af7485230032202ce0f9de assets/create/lang/unfinished/ru_ru.json
75c32bf33d907d0575d05ad575566d50bc78c1c9 assets/create/lang/unfinished/zh_cn.json
32a411bf248dae1eeb8a3e7d9450e5c1b9cd0b59 assets/create/lang/unfinished/zh_tw.json
@ -1699,7 +1699,7 @@ d080b1b25e5bc8baf5aee68691b08c7f12ece3b0 assets/create/models/item/windmill_bear
a80fb25a0b655e76be986b5b49fcb0f03461a1ab assets/create/models/item/zinc_nugget.json
b1689617190c05ef34bd18456b0c7ae09bb3210f assets/create/models/item/zinc_ore.json
58880e397902f8ca5b3b59ed4423e626109ddc4c assets/create/sounds.json
5d0cc4c0255dc241e61c173b31ddca70c88d08e4 data/create/advancements/aesthetics.json
0f1b4b980afba9bf2caf583b88e261bba8b10313 data/create/advancements/aesthetics.json
187921fa131b06721bfaf63f2623a28c141aae9a data/create/advancements/andesite_alloy.json
0ea2db7173b5be28b289ea7c9a6a0cf5805c60c7 data/create/advancements/andesite_casing.json
83c046bd200623933545c9e4326f782fb02c87fa data/create/advancements/arm_blaze_burner.json

View file

@ -1765,7 +1765,7 @@
"create.ponder.empty_blaze_burner.text_3": "You now have an ideal heat source for various machines",
"create.ponder.empty_blaze_burner.text_4": "For Aesthetic purposes, Empty Blaze Burners can also be lit using Flint and Steel",
"create.ponder.empty_blaze_burner.text_5": "The flame can be transformed using a soul-infused item",
"create.ponder.empty_blaze_burner.text_6": "However, these are not suitable for industrial heating",
"create.ponder.empty_blaze_burner.text_6": "However, without a blaze they are not suitable for industrial heating",
"create.ponder.encased_fluid_pipe.header": "Encasing Fluid Pipes",
"create.ponder.encased_fluid_pipe.text_1": "Copper Casing can be used to decorate Fluid Pipes",

View file

@ -1766,7 +1766,7 @@
"create.ponder.empty_blaze_burner.text_3": "UNLOCALIZED: You now have an ideal heat source for various machines",
"create.ponder.empty_blaze_burner.text_4": "UNLOCALIZED: For Aesthetic purposes, Empty Blaze Burners can also be lit using Flint and Steel",
"create.ponder.empty_blaze_burner.text_5": "UNLOCALIZED: The flame can be transformed using a soul-infused item",
"create.ponder.empty_blaze_burner.text_6": "UNLOCALIZED: However, these are not suitable for industrial heating",
"create.ponder.empty_blaze_burner.text_6": "UNLOCALIZED: However, without a blaze they are not suitable for industrial heating",
"create.ponder.encased_fluid_pipe.header": "UNLOCALIZED: Encasing Fluid Pipes",
"create.ponder.encased_fluid_pipe.text_1": "UNLOCALIZED: Copper Casing can be used to decorate Fluid Pipes",

View file

@ -1766,7 +1766,7 @@
"create.ponder.empty_blaze_burner.text_3": "UNLOCALIZED: You now have an ideal heat source for various machines",
"create.ponder.empty_blaze_burner.text_4": "UNLOCALIZED: For Aesthetic purposes, Empty Blaze Burners can also be lit using Flint and Steel",
"create.ponder.empty_blaze_burner.text_5": "UNLOCALIZED: The flame can be transformed using a soul-infused item",
"create.ponder.empty_blaze_burner.text_6": "UNLOCALIZED: However, these are not suitable for industrial heating",
"create.ponder.empty_blaze_burner.text_6": "UNLOCALIZED: However, without a blaze they are not suitable for industrial heating",
"create.ponder.encased_fluid_pipe.header": "UNLOCALIZED: Encasing Fluid Pipes",
"create.ponder.encased_fluid_pipe.text_1": "UNLOCALIZED: Copper Casing can be used to decorate Fluid Pipes",

View file

@ -1766,7 +1766,7 @@
"create.ponder.empty_blaze_burner.text_3": "UNLOCALIZED: You now have an ideal heat source for various machines",
"create.ponder.empty_blaze_burner.text_4": "UNLOCALIZED: For Aesthetic purposes, Empty Blaze Burners can also be lit using Flint and Steel",
"create.ponder.empty_blaze_burner.text_5": "UNLOCALIZED: The flame can be transformed using a soul-infused item",
"create.ponder.empty_blaze_burner.text_6": "UNLOCALIZED: However, these are not suitable for industrial heating",
"create.ponder.empty_blaze_burner.text_6": "UNLOCALIZED: However, without a blaze they are not suitable for industrial heating",
"create.ponder.encased_fluid_pipe.header": "UNLOCALIZED: Encasing Fluid Pipes",
"create.ponder.encased_fluid_pipe.text_1": "UNLOCALIZED: Copper Casing can be used to decorate Fluid Pipes",

View file

@ -1766,7 +1766,7 @@
"create.ponder.empty_blaze_burner.text_3": "UNLOCALIZED: You now have an ideal heat source for various machines",
"create.ponder.empty_blaze_burner.text_4": "UNLOCALIZED: For Aesthetic purposes, Empty Blaze Burners can also be lit using Flint and Steel",
"create.ponder.empty_blaze_burner.text_5": "UNLOCALIZED: The flame can be transformed using a soul-infused item",
"create.ponder.empty_blaze_burner.text_6": "UNLOCALIZED: However, these are not suitable for industrial heating",
"create.ponder.empty_blaze_burner.text_6": "UNLOCALIZED: However, without a blaze they are not suitable for industrial heating",
"create.ponder.encased_fluid_pipe.header": "UNLOCALIZED: Encasing Fluid Pipes",
"create.ponder.encased_fluid_pipe.text_1": "UNLOCALIZED: Copper Casing can be used to decorate Fluid Pipes",

View file

@ -1766,7 +1766,7 @@
"create.ponder.empty_blaze_burner.text_3": "UNLOCALIZED: You now have an ideal heat source for various machines",
"create.ponder.empty_blaze_burner.text_4": "UNLOCALIZED: For Aesthetic purposes, Empty Blaze Burners can also be lit using Flint and Steel",
"create.ponder.empty_blaze_burner.text_5": "UNLOCALIZED: The flame can be transformed using a soul-infused item",
"create.ponder.empty_blaze_burner.text_6": "UNLOCALIZED: However, these are not suitable for industrial heating",
"create.ponder.empty_blaze_burner.text_6": "UNLOCALIZED: However, without a blaze they are not suitable for industrial heating",
"create.ponder.encased_fluid_pipe.header": "UNLOCALIZED: Encasing Fluid Pipes",
"create.ponder.encased_fluid_pipe.text_1": "UNLOCALIZED: Copper Casing can be used to decorate Fluid Pipes",

View file

@ -1766,7 +1766,7 @@
"create.ponder.empty_blaze_burner.text_3": "UNLOCALIZED: You now have an ideal heat source for various machines",
"create.ponder.empty_blaze_burner.text_4": "UNLOCALIZED: For Aesthetic purposes, Empty Blaze Burners can also be lit using Flint and Steel",
"create.ponder.empty_blaze_burner.text_5": "UNLOCALIZED: The flame can be transformed using a soul-infused item",
"create.ponder.empty_blaze_burner.text_6": "UNLOCALIZED: However, these are not suitable for industrial heating",
"create.ponder.empty_blaze_burner.text_6": "UNLOCALIZED: However, without a blaze they are not suitable for industrial heating",
"create.ponder.encased_fluid_pipe.header": "UNLOCALIZED: Encasing Fluid Pipes",
"create.ponder.encased_fluid_pipe.text_1": "UNLOCALIZED: Copper Casing can be used to decorate Fluid Pipes",

View file

@ -28,8 +28,8 @@
"trigger": "create:bracket_apply",
"conditions": {
"accepted_entries": [
"create:large_cogwheel",
"create:cogwheel"
"create:cogwheel",
"create:large_cogwheel"
]
}
},

View file

@ -197,7 +197,9 @@ public class MechanicalPressTileEntity extends BasinOperatingTileEntity {
finished = true;
running = false;
if (onBasin() && matchBasinRecipe(currentRecipe))
if (onBasin() && matchBasinRecipe(currentRecipe)
&& getBasin().filter(BasinTileEntity::canContinueProcessing)
.isPresent())
startProcessingBasin();
pressedItems.clear();

View file

@ -60,9 +60,12 @@ public abstract class BasinOperatingTileEntity extends KineticTileEntity {
if (getSpeed() == 0)
return true;
if (isRunning())
return false;
return true;
if (world == null || world.isRemote)
return true;
if (!getBasin().filter(BasinTileEntity::canContinueProcessing)
.isPresent())
return true;
List<IRecipe<?>> recipes = getMatchingRecipes();
if (recipes.isEmpty())
@ -98,6 +101,7 @@ public abstract class BasinOperatingTileEntity extends KineticTileEntity {
if (!optionalBasin.isPresent())
return;
BasinTileEntity basin = optionalBasin.get();
boolean wasEmpty = basin.canContinueProcessing();
if (!BasinRecipe.apply(basin, currentRecipe))
return;
Optional<ITriggerable> processedRecipeTrigger = getProcessedRecipeTrigger();
@ -106,7 +110,7 @@ public abstract class BasinOperatingTileEntity extends KineticTileEntity {
basin.inputTank.sendDataImmediately();
// Continue mixing
if (matchBasinRecipe(currentRecipe)) {
if (wasEmpty && matchBasinRecipe(currentRecipe)) {
continueWithPreviousRecipe();
sendData();
}

View file

@ -88,6 +88,7 @@ public class BasinTileEntity extends SmartTileEntity implements IHaveGoggleInfor
List<Direction> disabledSpoutputs;
Direction preferredSpoutput;
protected List<ItemStack> spoutputBuffer;
protected List<FluidStack> spoutputFluidBuffer;
public static final int OUTPUT_ANIMATION_TIME = 10;
List<IntAttached<ItemStack>> visualizedOutputItems;
@ -114,6 +115,7 @@ public class BasinTileEntity extends SmartTileEntity implements IHaveGoggleInfor
disabledSpoutputs = new ArrayList<>();
preferredSpoutput = null;
spoutputBuffer = new ArrayList<>();
spoutputFluidBuffer = new ArrayList<>();
}
@Override
@ -152,6 +154,8 @@ public class BasinTileEntity extends SmartTileEntity implements IHaveGoggleInfor
ListNBT disabledList = compound.getList("DisabledSpoutput", NBT.TAG_STRING);
disabledList.forEach(d -> disabledSpoutputs.add(Direction.valueOf(((StringNBT) d).getString())));
spoutputBuffer = NBTHelper.readItemList(compound.getList("Overflow", NBT.TAG_COMPOUND));
spoutputFluidBuffer = NBTHelper.readCompoundList(compound.getList("FluidOverflow", NBT.TAG_COMPOUND),
FluidStack::loadFluidStackFromNBT);
if (!clientPacket)
return;
@ -175,6 +179,8 @@ public class BasinTileEntity extends SmartTileEntity implements IHaveGoggleInfor
disabledSpoutputs.forEach(d -> disabledList.add(StringNBT.of(d.name())));
compound.put("DisabledSpoutput", disabledList);
compound.put("Overflow", NBTHelper.writeItemList(spoutputBuffer));
compound.put("FluidOverflow",
NBTHelper.writeCompoundList(spoutputFluidBuffer, fs -> fs.writeToNBT(new CompoundNBT())));
if (!clientPacket)
return;
@ -280,11 +286,11 @@ public class BasinTileEntity extends SmartTileEntity implements IHaveGoggleInfor
ingredientRotation.setValue(ingredientRotation.getValue() + ingredientRotationSpeed.getValue());
}
if (!spoutputBuffer.isEmpty() && !world.isRemote)
if ((!spoutputBuffer.isEmpty() || !spoutputFluidBuffer.isEmpty()) && !world.isRemote)
tryClearingSpoutputOverflow();
if (!contentsChanged)
return;
contentsChanged = false;
getOperator().ifPresent(te -> te.basinChecker.scheduleUpdate());
@ -308,15 +314,22 @@ public class BasinTileEntity extends SmartTileEntity implements IHaveGoggleInfor
Direction direction = blockState.get(BasinBlock.FACING);
TileEntity te = world.getTileEntity(pos.down()
.offset(direction));
FilteringBehaviour filter = null;
InvManipulationBehaviour inserter = null;
if (te != null) {
filter = TileEntityBehaviour.get(world, te.getPos(), FilteringBehaviour.TYPE);
inserter = TileEntityBehaviour.get(world, te.getPos(), InvManipulationBehaviour.TYPE);
}
IItemHandler targetInv = te == null ? null
: te.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, direction.getOpposite())
.orElse(inserter == null ? null : inserter.getInventory());
IFluidHandler targetTank = te == null ? null
: te.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, direction.getOpposite())
.orElse(null);
boolean update = false;
for (Iterator<ItemStack> iterator = spoutputBuffer.iterator(); iterator.hasNext();) {
@ -329,9 +342,8 @@ public class BasinTileEntity extends SmartTileEntity implements IHaveGoggleInfor
continue;
}
if (targetInv == null) {
return;
}
if (targetInv == null)
break;
if (!ItemHandlerHelper.insertItemStacked(targetInv, itemStack, true)
.isEmpty())
continue;
@ -344,6 +356,34 @@ public class BasinTileEntity extends SmartTileEntity implements IHaveGoggleInfor
visualizedOutputItems.add(IntAttached.withZero(itemStack));
}
for (Iterator<FluidStack> iterator = spoutputFluidBuffer.iterator(); iterator.hasNext();) {
FluidStack fluidStack = iterator.next();
if (direction == Direction.DOWN) {
iterator.remove();
update = true;
continue;
}
if (targetTank == null)
break;
for (boolean simulate : Iterate.trueAndFalse) {
FluidAction action = simulate ? FluidAction.SIMULATE : FluidAction.EXECUTE;
int fill = targetTank instanceof SmartFluidTankBehaviour.InternalFluidHandler
? ((SmartFluidTankBehaviour.InternalFluidHandler) targetTank).forceFill(fluidStack.copy(), action)
: targetTank.fill(fluidStack.copy(), action);
if (fill != fluidStack.getAmount())
break;
if (simulate)
continue;
update = true;
iterator.remove();
visualizedOutputFluids.add(IntAttached.withZero(fluidStack));
}
}
if (update) {
notifyChangeOfContents();
sendData();
@ -407,6 +447,10 @@ public class BasinTileEntity extends SmartTileEntity implements IHaveGoggleInfor
return 256;
}
public boolean canContinueProcessing() {
return spoutputBuffer.isEmpty() && spoutputFluidBuffer.isEmpty();
}
public boolean acceptOutputs(List<ItemStack> outputItems, List<FluidStack> outputFluids, boolean simulate) {
outputInventory.allowInsertion();
outputTank.allowInsertion();
@ -420,52 +464,54 @@ public class BasinTileEntity extends SmartTileEntity implements IHaveGoggleInfor
BlockState blockState = getBlockState();
if (!(blockState.getBlock() instanceof BasinBlock))
return false;
Direction direction = blockState.get(BasinBlock.FACING);
IItemHandler targetInv = null;
IFluidHandler targetTank = null;
TileEntity te = null;
InvManipulationBehaviour inserter = null;
if (direction == Direction.DOWN) {
// No output basin, gather locally
targetInv = outputInventory;
targetTank = outputTank.getCapability()
.orElse(null);
} else {
// Output basin, try moving items to it
if (!spoutputBuffer.isEmpty())
return false;
te = world.getTileEntity(pos.down()
if (direction != Direction.DOWN) {
TileEntity te = world.getTileEntity(pos.down()
.offset(direction));
if (te == null)
return false;
inserter = TileEntityBehaviour.get(world, te.getPos(), InvManipulationBehaviour.TYPE);
targetInv = te.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, direction.getOpposite())
InvManipulationBehaviour inserter =
te == null ? null : TileEntityBehaviour.get(world, te.getPos(), InvManipulationBehaviour.TYPE);
IItemHandler targetInv = te == null ? null
: te.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, direction.getOpposite())
.orElse(inserter == null ? null : inserter.getInventory());
targetTank = te.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, direction.getOpposite())
IFluidHandler targetTank = te == null ? null
: te.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, direction.getOpposite())
.orElse(null);
if (!outputItems.isEmpty() && targetInv == null)
return false;
if (!outputFluids.isEmpty() && targetTank == null)
return false;
if (simulate)
return true;
for (ItemStack itemStack : outputItems) {
if (itemStack.hasContainerItem() && itemStack.getContainerItem()
.isItemEqual(itemStack))
continue;
spoutputBuffer.add(itemStack.copy());
}
for (FluidStack fluidStack : outputFluids)
spoutputFluidBuffer.add(fluidStack.copy());
return true;
}
IItemHandler targetInv = outputInventory;
IFluidHandler targetTank = outputTank.getCapability()
.orElse(null);
if (targetInv == null && !outputItems.isEmpty())
return false;
FilteringBehaviour filter = world == null || te == null ? null : TileEntityBehaviour.get(world, te.getPos(), FilteringBehaviour.TYPE);
for (ItemStack itemStack : outputItems) {
// Catalyst items are never consumed
if (itemStack.hasContainerItem() && itemStack.getContainerItem()
.isItemEqual(itemStack))
continue;
if (simulate || direction == Direction.DOWN) {
if (!ItemHandlerHelper.insertItemStacked(targetInv, itemStack.copy(), simulate)
.isEmpty() || (filter != null && !filter.test(itemStack)))
return false;
} else {
spoutputBuffer.add(itemStack.copy());
}
if (!ItemHandlerHelper.insertItemStacked(targetInv, itemStack.copy(), simulate)
.isEmpty())
return false;
}
if (outputFluids.isEmpty())
@ -480,8 +526,6 @@ public class BasinTileEntity extends SmartTileEntity implements IHaveGoggleInfor
: targetTank.fill(fluidStack.copy(), action);
if (fill != fluidStack.getAmount())
return false;
else if (!simulate)
visualizedOutputFluids.add(IntAttached.withZero(fluidStack));
}
return true;

View file

@ -14,7 +14,7 @@ public class ProcessingInventory extends ItemStackHandler {
private boolean limit;
public ProcessingInventory(Consumer<ItemStack> callback) {
super(10);
super(16);
this.callback = callback;
}

View file

@ -638,10 +638,10 @@ public class ProcessingScenes {
.pointAt(util.vector.blockSurface(center.east()
.up(), Direction.UP))
.placeNearTarget();
scene.idle(70);
scene.overlay.showText(60)
scene.idle(80);
scene.overlay.showText(90)
.colored(PonderPalette.RED)
.text("However, these are not suitable for industrial heating")
.text("However, without a blaze they are not suitable for industrial heating")
.pointAt(util.vector.blockSurface(center.east()
.up(), Direction.UP))
.placeNearTarget();