Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

import org.jetbrains.annotations.NotNull;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

/**
* MUST be implemented on any multiblock which uses
Expand All @@ -19,52 +19,50 @@ public interface IOpticalComputationProvider {
* @return The amount of CWU/t that could be supplied.
*/
default int requestCWUt(int cwut, boolean simulate) {
Collection<IOpticalComputationProvider> list = new ArrayList<>();
list.add(this);
return requestCWUt(cwut, simulate, list);
Map<IOpticalComputationProvider, Object> seenWithContext = new HashMap<>();
return requestCWUt(cwut, simulate, seenWithContext);
}

/**
* Request some amount of CWU/t (Compute Work Units per tick) from this Machine.
* Implementors should expect these requests to occur each tick that computation is required.
*
* @param cwut Maximum amount of CWU/t requested.
* @param seen The Optical Computation Providers already checked
* @param cwut Maximum amount of CWU/t requested.
* @param seenWithContext The Optical Computation Providers already checked, with provider-specific context for
* simulation case
* @return The amount of CWU/t that could be supplied.
*/
int requestCWUt(int cwut, boolean simulate, @NotNull Collection<IOpticalComputationProvider> seen);
int requestCWUt(int cwut, boolean simulate, @NotNull Map<IOpticalComputationProvider, Object> seenWithContext);

/**
* The maximum of CWU/t that this computation provider can provide.
*/
default int getMaxCWUt() {
Collection<IOpticalComputationProvider> list = new ArrayList<>();
list.add(this);
return getMaxCWUt(list);
Map<IOpticalComputationProvider, Object> seenWithContext = new HashMap<>();
return getMaxCWUt(seenWithContext);
}

/**
* The maximum of CWU/t that this computation provider can provide.
*
* @param seen The Optical Computation Providers already checked
* @param seenWithContext The Optical Computation Providers already checked
*/
int getMaxCWUt(@NotNull Collection<IOpticalComputationProvider> seen);
int getMaxCWUt(@NotNull Map<IOpticalComputationProvider, Object> seenWithContext);

/**
* Whether this Computation Provider can "Bridge" with other Computation Providers.
* Checked by machines like the Network Switch.
*/
default boolean canBridge() {
Collection<IOpticalComputationProvider> list = new ArrayList<>();
list.add(this);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe readd this?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should not be necessary since all implementations are supposed to add themselves to the visited set upon receiving the call. Adding them in advance might actually cause problems due to some of them (like network switch) checking if seen set already contains themselves, and bailing out if it does.

return canBridge(list);
Map<IOpticalComputationProvider, Object> seenWithContext = new HashMap<>();
return canBridge(seenWithContext);
}

/**
* Whether this Computation Provider can "Bridge" with other Computation Providers.
* Checked by machines like the Network Switch.
*
* @param seen The Optical Computation Providers already checked
* @param seenWithContext The Optical Computation Providers already checked
*/
boolean canBridge(@NotNull Collection<IOpticalComputationProvider> seen);
boolean canBridge(@NotNull Map<IOpticalComputationProvider, Object> seenWithContext);
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import com.gregtechceu.gtceu.api.capability.IOpticalComputationProvider;
import com.gregtechceu.gtceu.api.capability.IOpticalComputationReceiver;
import com.gregtechceu.gtceu.api.capability.recipe.*;
import com.gregtechceu.gtceu.api.machine.MetaMachine;
import com.gregtechceu.gtceu.api.machine.feature.IRecipeLogicMachine;
import com.gregtechceu.gtceu.api.machine.multiblock.MultiblockControllerMachine;
import com.gregtechceu.gtceu.api.machine.multiblock.part.MultiblockPartMachine;
Expand All @@ -17,12 +18,13 @@
import net.minecraft.core.Direction;
import net.minecraft.world.level.block.entity.BlockEntity;

import com.google.common.base.Preconditions;
import lombok.Getter;
import org.jetbrains.annotations.Nullable;

import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;

public class NotifiableComputationContainer extends NotifiableRecipeHandlerTrait<Integer>
implements IOpticalComputationHatch, IOpticalComputationReceiver {
Expand All @@ -32,44 +34,62 @@ public class NotifiableComputationContainer extends NotifiableRecipeHandlerTrait
@Getter
protected boolean transmitter;

protected long lastTimeStamp;
private int currentOutputCwu = 0, lastOutputCwu = 0;
private ComputationTransferContext transferContext = ComputationTransferContext.create();

private record ComputationTransferContext(long lastTimeStamp, int currentOutputCwu, int lastOutputCwu) {

public static ComputationTransferContext create() {
return new ComputationTransferContext(Long.MIN_VALUE, 0, 0);
}

public ComputationTransferContext conditionalTimedUpdate(MetaMachine machine) {
var latestTimeStamp = machine.getOffsetTimer();
if (lastTimeStamp < latestTimeStamp) {
return new ComputationTransferContext(latestTimeStamp, 0, currentOutputCwu());
}
return this;
}

public ComputationTransferContext subtractLastOutput(int transferred) {
return new ComputationTransferContext(lastTimeStamp(), currentOutputCwu(), lastOutputCwu() - transferred);
}

public ComputationTransferContext setOutput(int newOutputCwu) {
return new ComputationTransferContext(lastTimeStamp(), newOutputCwu, lastOutputCwu());
}
}

public NotifiableComputationContainer(IO handlerIO, boolean transmitter) {
super();
this.handlerIO = handlerIO;
this.transmitter = transmitter;

this.lastTimeStamp = Long.MIN_VALUE;
}

@Override
public int requestCWUt(int cwut, boolean simulate, Collection<IOpticalComputationProvider> seen) {
var latestTimeStamp = getMachine().getOffsetTimer();
if (lastTimeStamp < latestTimeStamp) {
lastOutputCwu = currentOutputCwu;
currentOutputCwu = 0;
lastTimeStamp = latestTimeStamp;
public int requestCWUt(int cwut, boolean simulate, Map<IOpticalComputationProvider, Object> seenWithContext) {
ComputationTransferContext localTransferContext = this.transferContext.conditionalTimedUpdate(getMachine());
if (!simulate) {
this.transferContext = localTransferContext;
}

seen.add(this);
seenWithContext.put(this, localTransferContext);
if (handlerIO == IO.IN) {
if (isTransmitter()) {
var machine = getMachine();
// Ask the Multiblock controller, which *should* be an IOpticalComputationProvider
if (machine instanceof IOpticalComputationProvider provider) {
return provider.requestCWUt(cwut, simulate, seen);
return provider.requestCWUt(cwut, simulate, seenWithContext);
} else if (machine instanceof MultiblockPartMachine part) {
if (!part.isFormed()) {
return 0;
}
for (MultiblockControllerMachine controller : part.getControllers()) {
if (controller instanceof IOpticalComputationProvider provider) {
return provider.requestCWUt(cwut, simulate, seen);
return provider.requestCWUt(cwut, simulate, seenWithContext);
}
for (MachineTrait trait : controller.getAllTraits()) {
if (trait instanceof IOpticalComputationProvider provider) {
return provider.requestCWUt(cwut, simulate, seen);
return provider.requestCWUt(cwut, simulate, seenWithContext);
}
}
}
Expand All @@ -84,23 +104,26 @@ public int requestCWUt(int cwut, boolean simulate, Collection<IOpticalComputatio
// Ask the attached Transmitter hatch, if it exists
IOpticalComputationProvider provider = getOpticalNetProvider();
if (provider == null) return 0;
return provider.requestCWUt(cwut, simulate, seen);
return provider.requestCWUt(cwut, simulate, seenWithContext);
}
} else {
lastOutputCwu = lastOutputCwu - cwut;
return Math.min(lastOutputCwu, cwut);
localTransferContext = localTransferContext.subtractLastOutput(cwut);
if (!simulate) {
this.transferContext = localTransferContext;
}
return Math.min(localTransferContext.lastOutputCwu(), cwut);
}
}

@Override
public int getMaxCWUt(Collection<IOpticalComputationProvider> seen) {
seen.add(this);
public int getMaxCWUt(Map<IOpticalComputationProvider, Object> seenWithContext) {
seenWithContext.put(this, this.transferContext);
if (handlerIO == IO.IN) {
if (isTransmitter()) {
var machine = getMachine();
// Ask the Multiblock controller, which *should* be an IOpticalComputationProvider
if (machine instanceof IOpticalComputationProvider provider) {
return provider.getMaxCWUt(seen);
return provider.getMaxCWUt(seenWithContext);
} else if (machine instanceof MultiblockPartMachine part) {
if (!part.isFormed()) {
return 0;
Expand All @@ -110,11 +133,11 @@ public int getMaxCWUt(Collection<IOpticalComputationProvider> seen) {
continue;
}
if (controller instanceof IOpticalComputationProvider provider) {
return provider.getMaxCWUt(seen);
return provider.getMaxCWUt(seenWithContext);
}
for (MachineTrait trait : controller.getAllTraits()) {
if (trait instanceof IOpticalComputationProvider provider) {
return provider.getMaxCWUt(seen);
return provider.getMaxCWUt(seenWithContext);
}
}
}
Expand All @@ -129,22 +152,22 @@ public int getMaxCWUt(Collection<IOpticalComputationProvider> seen) {
// Ask the attached Transmitter hatch, if it exists
IOpticalComputationProvider provider = getOpticalNetProvider();
if (provider == null) return 0;
return provider.getMaxCWUt(seen);
return provider.getMaxCWUt(seenWithContext);
}
} else {
return lastOutputCwu;
return Preconditions.checkNotNull((ComputationTransferContext) seenWithContext.get(this)).lastOutputCwu();
}
}

@Override
public boolean canBridge(Collection<IOpticalComputationProvider> seen) {
seen.add(this);
public boolean canBridge(Map<IOpticalComputationProvider, Object> seenWithContext) {
seenWithContext.put(this, this.transferContext);
if (handlerIO == IO.IN) {
if (isTransmitter()) {
var machine = getMachine();
// Ask the Multiblock controller, which *should* be an IOpticalComputationProvider
if (machine instanceof IOpticalComputationProvider provider) {
return provider.canBridge(seen);
return provider.canBridge(seenWithContext);
} else if (machine instanceof MultiblockPartMachine part) {
if (!part.isFormed()) {
return false;
Expand All @@ -154,11 +177,11 @@ public boolean canBridge(Collection<IOpticalComputationProvider> seen) {
continue;
}
if (controller instanceof IOpticalComputationProvider provider) {
return provider.canBridge(seen);
return provider.canBridge(seenWithContext);
}
for (MachineTrait trait : controller.getAllTraits()) {
if (trait instanceof IOpticalComputationProvider provider) {
return provider.canBridge(seen);
return provider.canBridge(seenWithContext);
}
}
}
Expand All @@ -173,7 +196,7 @@ public boolean canBridge(Collection<IOpticalComputationProvider> seen) {
// Ask the attached Transmitter hatch, if it exists
IOpticalComputationProvider provider = getOpticalNetProvider();
if (provider == null) return true; // nothing found, so don't report a problem, just pass quietly
return provider.canBridge(seen);
return provider.canBridge(seenWithContext);
}
} else {
return false;
Expand Down Expand Up @@ -211,9 +234,10 @@ public List<Integer> handleRecipeInner(IO io, GTRecipe recipe, List<Integer> lef
}
}
} else if (io == IO.OUT) {
int canInput = this.getMaxCWUt() - this.lastOutputCwu;
int canInput = this.getMaxCWUt() - this.transferContext.lastOutputCwu();
if (!simulate) {
this.currentOutputCwu = Math.min(canInput, sum);
int newOutputCwu = Math.min(canInput, sum);
this.transferContext = this.transferContext.setOutput(newOutputCwu);
}
sum = sum - canInput;
}
Expand All @@ -222,12 +246,12 @@ public List<Integer> handleRecipeInner(IO io, GTRecipe recipe, List<Integer> lef

@Override
public List<Object> getContents() {
return List.of(lastOutputCwu);
return List.of(this.transferContext.lastOutputCwu());
}

@Override
public double getTotalContentAmount() {
return lastOutputCwu;
return this.transferContext.lastOutputCwu();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import java.lang.ref.WeakReference;
import java.util.Collection;
import java.util.EnumMap;
import java.util.Map;

public class OpticalPipeBlockEntity extends PipeBlockEntity<OpticalPipeType, OpticalPipeProperties> {

Expand Down Expand Up @@ -178,17 +179,18 @@ public boolean isCreative() {
private static class DefaultComputationHandler implements IOpticalComputationProvider {

@Override
public int requestCWUt(int cwut, boolean simulate, @NotNull Collection<IOpticalComputationProvider> seen) {
public int requestCWUt(int cwut, boolean simulate,
@NotNull Map<IOpticalComputationProvider, Object> seenWithContext) {
return 0;
}

@Override
public int getMaxCWUt(@NotNull Collection<IOpticalComputationProvider> seen) {
public int getMaxCWUt(@NotNull Map<IOpticalComputationProvider, Object> seenWithContext) {
return 0;
}

@Override
public boolean canBridge(@NotNull Collection<IOpticalComputationProvider> seen) {
public boolean canBridge(@NotNull Map<IOpticalComputationProvider, Object> seenWithContext) {
return false;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,21 +161,23 @@ public void invalidateStructure(String name) {
this.hpcaHandler.onStructureInvalidate();
}

private static final Object PLACEHOLDER_TRANSFER_CONTEXT = new Object();

@Override
public int requestCWUt(int cwut, boolean simulate, Collection<IOpticalComputationProvider> seen) {
seen.add(this);
public int requestCWUt(int cwut, boolean simulate, Map<IOpticalComputationProvider, Object> seenWithContext) {
seenWithContext.put(this, PLACEHOLDER_TRANSFER_CONTEXT);
return isActive() && isWorkingEnabled() && !hasNotEnoughEnergy ? hpcaHandler.allocateCWUt(cwut, simulate) : 0;
}

@Override
public int getMaxCWUt(Collection<IOpticalComputationProvider> seen) {
seen.add(this);
public int getMaxCWUt(Map<IOpticalComputationProvider, Object> seenWithContext) {
seenWithContext.put(this, PLACEHOLDER_TRANSFER_CONTEXT);
return isActive() && isWorkingEnabled() ? hpcaHandler.getMaxCWUt() : 0;
}

@Override
public boolean canBridge(Collection<IOpticalComputationProvider> seen) {
seen.add(this);
public boolean canBridge(Map<IOpticalComputationProvider, Object> seenWithContext) {
seenWithContext.put(this, PLACEHOLDER_TRANSFER_CONTEXT);
// don't show a problem if the structure is not yet formed
return !isFormed() || hpcaHandler.hasHPCABridge();
}
Expand Down
Loading
Loading