Skip to content

Commit 6db6f40

Browse files
committed
Fix #28: compute pipe transfer limit over multiple ticks to account for cauldrons
1 parent 2432214 commit 6db6f40

File tree

3 files changed

+83
-62
lines changed

3 files changed

+83
-62
lines changed

src/main/java/dev/technici4n/moderndynamics/network/energy/EnergyHost.java

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
import dev.technici4n.moderndynamics.network.NetworkManager;
2323
import dev.technici4n.moderndynamics.network.NetworkNode;
2424
import dev.technici4n.moderndynamics.network.NodeHost;
25-
import dev.technici4n.moderndynamics.network.TickHelper;
2625
import dev.technici4n.moderndynamics.network.shared.TransferLimits;
2726
import dev.technici4n.moderndynamics.pipe.PipeBlockEntity;
2827
import java.util.List;
@@ -41,9 +40,10 @@ public class EnergyHost extends NodeHost {
4140
private final EnergyPipeTier tier;
4241
private long energy;
4342
// Rate limiting
44-
private long lastRateUpdate = 0;
45-
private final TransferLimits insertLimit = new TransferLimits(); // inserted INTO the neighbor inventories
46-
private final TransferLimits extractLimit = new TransferLimits(); // extracted FROM the neighbor inventories
43+
// inserted INTO the neighbor inventories
44+
private final TransferLimits<Void> insertLimit = new TransferLimits<>(this::getTransferLimit);
45+
// extracted FROM the neighbor inventories
46+
private final TransferLimits<Void> extractLimit = new TransferLimits<>(this::getTransferLimit);
4747
// Caps
4848
private final EnergyStorage[] caps = new EnergyStorage[6];
4949

@@ -157,14 +157,8 @@ public void readNbt(CompoundTag tag) {
157157
energy = Math.max(0, Math.min(tag.getLong("energy"), getMaxEnergy()));
158158
}
159159

160-
private void updateRateLimits() {
161-
long currentTick = TickHelper.getTickCounter();
162-
163-
if (currentTick > lastRateUpdate) {
164-
lastRateUpdate = currentTick;
165-
extractLimit.reset();
166-
insertLimit.reset();
167-
}
160+
private long getTransferLimit(Direction side, Void context) {
161+
return tier.getMaxConnectionTransfer();
168162
}
169163

170164
private class ExternalEnergyStorage extends DelegatingEnergyStorage {
@@ -177,8 +171,7 @@ private ExternalEnergyStorage(EnergyStorage delegate, int directionId) {
177171

178172
@Override
179173
public long insert(long maxAmount, TransactionContext transaction) {
180-
updateRateLimits();
181-
maxAmount = Math.min(maxAmount, tier.getMaxConnectionTransfer() - insertLimit.used[directionId]);
174+
maxAmount = insertLimit.limit(directionId, maxAmount, null);
182175
if (maxAmount <= 0)
183176
return 0;
184177

@@ -189,8 +182,7 @@ public long insert(long maxAmount, TransactionContext transaction) {
189182

190183
@Override
191184
public long extract(long maxAmount, TransactionContext transaction) {
192-
updateRateLimits();
193-
maxAmount = Math.min(maxAmount, tier.getMaxConnectionTransfer() - extractLimit.used[directionId]);
185+
maxAmount = extractLimit.limit(directionId, maxAmount, null);
194186
if (maxAmount <= 0)
195187
return 0;
196188

@@ -213,10 +205,9 @@ public long insert(long maxAmount, TransactionContext transaction) {
213205
NetworkNode<EnergyHost, EnergyCache> node = findNode();
214206

215207
if (node != null && node.getHost() == EnergyHost.this) {
216-
updateRateLimits();
217208
// extractLimit because the network is receiving from an adjacent inventory,
218209
// as if it was extracting from it
219-
maxAmount = Math.min(maxAmount, tier.getMaxConnectionTransfer() - extractLimit.used[directionId]);
210+
maxAmount = extractLimit.limit(directionId, maxAmount, null);
220211
if (maxAmount <= 0)
221212
return 0;
222213

@@ -235,10 +226,9 @@ public long extract(long maxAmount, TransactionContext transaction) {
235226
NetworkNode<EnergyHost, EnergyCache> node = findNode();
236227

237228
if (node != null && node.getHost() == EnergyHost.this) {
238-
updateRateLimits();
239229
// insertLimit because the network is being extracted from an adjacent inventory,
240230
// as if it was inserting into it
241-
maxAmount = Math.min(maxAmount, tier.getMaxConnectionTransfer() - insertLimit.used[directionId]);
231+
maxAmount = insertLimit.limit(directionId, maxAmount, null);
242232
if (maxAmount <= 0)
243233
return 0;
244234

src/main/java/dev/technici4n/moderndynamics/network/fluid/FluidHost.java

Lines changed: 13 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
import dev.technici4n.moderndynamics.network.NetworkManager;
2929
import dev.technici4n.moderndynamics.network.NetworkNode;
3030
import dev.technici4n.moderndynamics.network.NodeHost;
31-
import dev.technici4n.moderndynamics.network.TickHelper;
3231
import dev.technici4n.moderndynamics.network.shared.TransferLimits;
3332
import dev.technici4n.moderndynamics.pipe.PipeBlockEntity;
3433
import dev.technici4n.moderndynamics.util.TransferUtil;
@@ -55,9 +54,10 @@ public class FluidHost extends NodeHost {
5554
private FluidVariant variant = FluidVariant.blank();
5655
private long amount = 0;
5756
// Rate limiting
58-
private long lastRateUpdate = 0;
59-
private final TransferLimits insertLimit = new TransferLimits(); // inserted INTO the neighbor inventories
60-
private final TransferLimits extractLimit = new TransferLimits(); // extracted FROM the neighbor inventories
57+
// inserted INTO the neighbor inventories
58+
private final TransferLimits<FluidVariant> insertLimit = new TransferLimits<>(this::getNetworkToOutsideLimit);
59+
// extracted FROM the neighbor inventories
60+
private final TransferLimits<FluidVariant> extractLimit = new TransferLimits<>(this::getOutsideToNetworkLimit);
6161
// Caps
6262
private final Storage<FluidVariant>[] caps = new Storage[6];
6363

@@ -234,19 +234,9 @@ public void readClientNbt(CompoundTag tag) {
234234
amount = tag.getLong("amount");
235235
}
236236

237-
private void updateRateLimits() {
238-
long currentTick = TickHelper.getTickCounter();
239-
240-
if (currentTick > lastRateUpdate) {
241-
lastRateUpdate = currentTick;
242-
extractLimit.reset();
243-
insertLimit.reset();
244-
}
245-
}
246-
247-
private long getNetworkToOutsideLimit(Direction side, FluidVariant variant) {
237+
private long getNetworkToOutsideLimit(Direction side, @Nullable FluidVariant variant) {
248238
if (getAttachment(side) instanceof FluidAttachedIo io) {
249-
if (!io.matchesFilter(variant) || !io.isEnabledViaRedstone(pipe)) {
239+
if ((variant != null && !io.matchesFilter(variant)) || !io.isEnabledViaRedstone(pipe)) {
250240
return 0;
251241
}
252242
if (io.getType() == IoAttachmentType.EXTRACTOR)
@@ -258,9 +248,9 @@ private long getNetworkToOutsideLimit(Direction side, FluidVariant variant) {
258248
return Constants.Fluids.BASE_IO;
259249
}
260250

261-
private long getOutsideToNetworkLimit(Direction side, FluidVariant variant) {
251+
private long getOutsideToNetworkLimit(Direction side, @Nullable FluidVariant variant) {
262252
if (getAttachment(side) instanceof FluidAttachedIo io) {
263-
if (!io.matchesFilter(variant) || !io.isEnabledViaRedstone(pipe)) {
253+
if ((variant != null && !io.matchesFilter(variant)) || !io.isEnabledViaRedstone(pipe)) {
264254
return 0;
265255
}
266256
if (io.getType() == IoAttachmentType.ATTRACTOR)
@@ -293,9 +283,7 @@ private class ExternalFluidStorage implements Storage<FluidVariant> {
293283

294284
@Override
295285
public long insert(FluidVariant resource, long maxAmount, TransactionContext transaction) {
296-
updateRateLimits();
297-
maxAmount = Math.min(maxAmount,
298-
getNetworkToOutsideLimit(Direction.from3DDataValue(directionId), resource) - insertLimit.used[directionId]);
286+
maxAmount = insertLimit.limit(directionId, maxAmount, resource);
299287
if (maxAmount <= 0)
300288
return 0;
301289

@@ -306,9 +294,7 @@ public long insert(FluidVariant resource, long maxAmount, TransactionContext tra
306294

307295
@Override
308296
public long extract(FluidVariant resource, long maxAmount, TransactionContext transaction) {
309-
updateRateLimits();
310-
maxAmount = Math.min(maxAmount,
311-
getOutsideToNetworkLimit(Direction.from3DDataValue(directionId), resource) - extractLimit.used[directionId]);
297+
maxAmount = extractLimit.limit(directionId, maxAmount, resource);
312298
if (maxAmount <= 0)
313299
return 0;
314300

@@ -331,9 +317,7 @@ private View(StorageView<FluidVariant> view) {
331317

332318
@Override
333319
public long extract(FluidVariant resource, long maxAmount, TransactionContext transaction) {
334-
updateRateLimits();
335-
maxAmount = Math.min(maxAmount,
336-
getOutsideToNetworkLimit(Direction.from3DDataValue(directionId), resource) - extractLimit.used[directionId]);
320+
maxAmount = extractLimit.limit(directionId, maxAmount, resource);
337321
if (maxAmount <= 0)
338322
return 0;
339323

@@ -380,11 +364,9 @@ private NetworkFluidStorage(int directionId) {
380364
public long insert(FluidVariant resource, long maxAmount, TransactionContext transaction) {
381365
StoragePreconditions.notBlankNotNegative(resource, maxAmount);
382366

383-
updateRateLimits();
384367
// extractLimit because the network is receiving from an adjacent inventory,
385368
// as if it was extracting from it
386-
maxAmount = Math.min(maxAmount,
387-
getOutsideToNetworkLimit(Direction.from3DDataValue(directionId), resource) - extractLimit.used[directionId]);
369+
maxAmount = extractLimit.limit(directionId, maxAmount, resource);
388370
if (maxAmount <= 0)
389371
return 0;
390372

@@ -398,11 +380,9 @@ public long insert(FluidVariant resource, long maxAmount, TransactionContext tra
398380
public long extract(FluidVariant resource, long maxAmount, TransactionContext transaction) {
399381
StoragePreconditions.notBlankNotNegative(resource, maxAmount);
400382

401-
updateRateLimits();
402383
// insertLimit because the network is being extracted from an adjacent inventory,
403384
// as if it was inserting into it
404-
maxAmount = Math.min(maxAmount,
405-
getNetworkToOutsideLimit(Direction.from3DDataValue(directionId), resource) - insertLimit.used[directionId]);
385+
maxAmount = insertLimit.limit(directionId, maxAmount, resource);
406386
if (maxAmount <= 0)
407387
return 0;
408388

src/main/java/dev/technici4n/moderndynamics/network/shared/TransferLimits.java

Lines changed: 60 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,31 +18,82 @@
1818
*/
1919
package dev.technici4n.moderndynamics.network.shared;
2020

21+
import dev.technici4n.moderndynamics.network.TickHelper;
2122
import java.util.Arrays;
23+
import net.fabricmc.fabric.api.transfer.v1.storage.StoragePreconditions;
2224
import net.fabricmc.fabric.api.transfer.v1.transaction.TransactionContext;
2325
import net.fabricmc.fabric.api.transfer.v1.transaction.base.SnapshotParticipant;
26+
import net.minecraft.core.Direction;
27+
import org.jetbrains.annotations.Nullable;
2428

25-
public class TransferLimits extends SnapshotParticipant<long[]> {
26-
public final long[] used = new long[6];
29+
public class TransferLimits<T> extends SnapshotParticipant<long[]> {
30+
// These numbers are somewhat arbitrary, we can always change them later...
31+
private static final long MAX_TICK_DIFF = 20;
32+
private static final long MAX_BUFFER_FACTOR = 50;
2733

28-
public void reset() {
29-
for (int i = 0; i < 6; ++i) {
30-
used[i] = 0;
34+
private long lastUpdateTick = 0;
35+
private final long[] available = new long[6];
36+
private final LimitSupplier<T> limitSupplier;
37+
38+
public TransferLimits(LimitSupplier<T> limitSupplier) {
39+
this.limitSupplier = limitSupplier;
40+
}
41+
42+
private void checkForNewTick() {
43+
long currentTick = TickHelper.getTickCounter();
44+
45+
if (currentTick != lastUpdateTick) {
46+
long tickDiff = lastUpdateTick != 0 ? currentTick - lastUpdateTick : 1;
47+
// Add transfer for used ticks.
48+
tickDiff = Math.min(tickDiff, MAX_TICK_DIFF); // 20 at most
49+
50+
if (tickDiff > 0) {
51+
for (var dir : Direction.values()) {
52+
int i = dir.get3DDataValue();
53+
long cap = limitSupplier.getLimit(dir, null);
54+
available[i] = Math.min(available[i] + tickDiff * cap, MAX_BUFFER_FACTOR * cap);
55+
}
56+
}
57+
58+
lastUpdateTick = currentTick;
3159
}
3260
}
3361

34-
public void use(int i, long amount, TransactionContext tx) {
62+
/**
63+
* Limit the passed amount.
64+
*/
65+
public long limit(int side, long amount, T context) {
66+
StoragePreconditions.notNegative(amount);
67+
checkForNewTick();
68+
69+
// Always check if transfer is still valid.
70+
if (limitSupplier.getLimit(Direction.from3DDataValue(side), context) == 0) {
71+
return 0;
72+
}
73+
// If ok, check what's available.
74+
return Math.min(available[side], amount);
75+
}
76+
77+
public void use(int side, long amount, TransactionContext tx) {
3578
updateSnapshots(tx);
36-
used[i] += amount;
79+
available[side] -= amount;
3780
}
3881

3982
@Override
4083
protected long[] createSnapshot() {
41-
return Arrays.copyOf(used, used.length);
84+
return Arrays.copyOf(available, available.length);
4285
}
4386

4487
@Override
4588
protected void readSnapshot(long[] snapshot) {
46-
System.arraycopy(snapshot, 0, used, 0, snapshot.length);
89+
System.arraycopy(snapshot, 0, available, 0, snapshot.length);
90+
}
91+
92+
@FunctionalInterface
93+
public interface LimitSupplier<T> {
94+
/**
95+
* @return Transfer limit for direction and context, or "default" limit if context is null.
96+
*/
97+
long getLimit(Direction direction, @Nullable T context);
4798
}
4899
}

0 commit comments

Comments
 (0)