~williewillus/botania

66680dd33c5cf3f719359e4c188d5b0d28cdb91c — Vincent Lee 3 months ago 8232c30
In Fabric Transfer API corporea node, iterate StorageView inside a transaction

Some mods change their views when a transaction commits, leading to CME's.
Closes #4403
M Fabric/src/main/java/vazkii/botania/fabric/integration/corporea/FabricTransferCorporeaNode.java => Fabric/src/main/java/vazkii/botania/fabric/integration/corporea/FabricTransferCorporeaNode.java +25 -23
@@ 36,33 36,35 @@ public class FabricTransferCorporeaNode extends AbstractCorporeaNode {
	protected List<ItemStack> iterateOverSlots(CorporeaRequest request, boolean doit) {
		ImmutableList.Builder<ItemStack> builder = ImmutableList.builder();

		for (var storageView : inv) {
			if (storageView.isResourceBlank()) {
				continue;
			}
			// TODO hack: truncate to INT_MAX, we probably won't be able to handle higher values anyway
			var count = (int) Math.min(Integer.MAX_VALUE, storageView.getAmount());
			var item = storageView.getResource();
			var stack = item.toStack(count);
			if (request.getMatcher().test(stack)) {
				request.trackFound(count);
		try (Transaction outer = Transaction.openOuter()) {
			for (var storageView : inv) {
				if (storageView.isResourceBlank()) {
					continue;
				}
				// TODO hack: truncate to INT_MAX, we probably won't be able to handle higher values anyway
				var count = (int) Math.min(Integer.MAX_VALUE, storageView.getAmount());
				var item = storageView.getResource();
				var stack = item.toStack(count);
				if (request.getMatcher().test(stack)) {
					request.trackFound(count);

				int rem = Math.min(count, request.getStillNeeded() == -1 ? count : request.getStillNeeded());
				if (rem > 0) {
					request.trackSatisfied(rem);
					int rem = Math.min(count, request.getStillNeeded() == -1 ? count : request.getStillNeeded());
					if (rem > 0) {
						request.trackSatisfied(rem);

					if (doit) {
						try (Transaction trans = Transaction.openOuter()) {
							builder.addAll(breakDownBigStack(item.toStack((int) inv.extract(item, rem, trans))));
							if (!getSpark().isCreative()) {
								// only commit if non-creative
								trans.commit();
						if (doit) {
							try (Transaction trans = Transaction.openNested(outer)) {
								builder.addAll(breakDownBigStack(item.toStack((int) inv.extract(item, rem, trans))));
								if (!getSpark().isCreative()) {
									// only commit if non-creative
									trans.commit();
								}
							}
							getSpark().onItemExtracted(stack);
							request.trackExtracted(rem);
						} else {
							builder.add(item.toStack((int) inv.simulateExtract(item, rem, null)));
						}
						getSpark().onItemExtracted(stack);
						request.trackExtracted(rem);
					} else {
						builder.add(item.toStack((int) inv.simulateExtract(item, rem, null)));
					}
				}
			}