Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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,10 @@

import org.jetbrains.annotations.NotNull;

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

/**
* MUST be implemented on any multiblock which uses
Expand All @@ -19,45 +21,80 @@ 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);
Set<IOpticalComputationProvider> seen = new HashSet<>();
Map<IOpticalComputationProvider, Object> simulationState = new HashMap<>();
return requestCWUt(cwut, simulate, seen, simulationState);
}

/**
* Simulates a request of some amount of CWU/t (Compute Work Units per tick) from this Machine.
* Simulation state allows sharing the simulation across multiple requests.
*
* @param cwut Maximum amount of CWU/t requested.
* @param simulationState simulation state to allow sharing simulation across multiple requests
* @return The amount of CWU/t that could be supplied.
*/
default int requestCWUtSimulated(int cwut, Map<IOpticalComputationProvider, Object> simulationState) {
Set<IOpticalComputationProvider> seen = new HashSet<>();
return requestCWUt(cwut, true, seen, simulationState);
}

/**
* 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 seen The Optical Computation Providers already checked
* @param simulationState state of simulation for each provider
*
* @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 Set<IOpticalComputationProvider> seen,
@NotNull Map<IOpticalComputationProvider, Object> simulationState);

/**
* 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);
Set<IOpticalComputationProvider> seen = new HashSet<>();
Map<IOpticalComputationProvider, Object> simulationState = new HashMap<>();
return getMaxCWUt(seen, simulationState);
}

/**
* The maximum of CWU/t that this computation provider can provide.
*/
default int getMaxCWUtInSimulation(Map<IOpticalComputationProvider, Object> simulationState) {
Set<IOpticalComputationProvider> seen = new HashSet<>();
return getMaxCWUt(seen, simulationState);
}

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

/**
* 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);
Set<IOpticalComputationProvider> seen = new HashSet<>();
Map<IOpticalComputationProvider, Object> simulationState = new HashMap<>();
return canBridge(seen, simulationState);
}

/**
* Whether this Computation Provider can "Bridge" with other Computation Providers.
* Checked by machines like the Network Switch.
*/
default boolean canBridgeInSimulation(Map<IOpticalComputationProvider, Object> simulationState) {
Set<IOpticalComputationProvider> seen = new HashSet<>();
return canBridge(seen, simulationState);
}

/**
Expand All @@ -66,5 +103,6 @@ default boolean canBridge() {
*
* @param seen The Optical Computation Providers already checked
*/
boolean canBridge(@NotNull Collection<IOpticalComputationProvider> seen);
boolean canBridge(@NotNull Set<IOpticalComputationProvider> seen,
@NotNull Map<IOpticalComputationProvider, Object> simulationState);
}
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 @@ -20,9 +21,7 @@
import lombok.Getter;
import org.jetbrains.annotations.Nullable;

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

public class NotifiableComputationContainer extends NotifiableRecipeHandlerTrait<Integer>
implements IOpticalComputationHatch, IOpticalComputationReceiver {
Expand All @@ -32,24 +31,47 @@ 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, Set<IOpticalComputationProvider> seen,
Map<IOpticalComputationProvider, Object> simulationState) {
ComputationTransferContext localTransferContext = (ComputationTransferContext) simulationState
.getOrDefault(this, this.transferContext);
localTransferContext = localTransferContext.conditionalTimedUpdate(getMachine());
if (!simulate) {
this.transferContext = localTransferContext;
} else {
simulationState.put(this, localTransferContext);
}

seen.add(this);
Expand All @@ -58,18 +80,18 @@ public int requestCWUt(int cwut, boolean simulate, Collection<IOpticalComputatio
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, seen, simulationState);
} 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, seen, simulationState);
}
for (MachineTrait trait : controller.getAllTraits()) {
if (trait instanceof IOpticalComputationProvider provider) {
return provider.requestCWUt(cwut, simulate, seen);
return provider.requestCWUt(cwut, simulate, seen, simulationState);
}
}
}
Expand All @@ -84,23 +106,30 @@ 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, seen, simulationState);
}
} else {
lastOutputCwu = lastOutputCwu - cwut;
return Math.min(lastOutputCwu, cwut);
localTransferContext = localTransferContext.subtractLastOutput(cwut);
localTransferContext = localTransferContext.conditionalTimedUpdate(getMachine());
if (!simulate) {
this.transferContext = localTransferContext;
} else {
simulationState.put(this, localTransferContext);
}
return Math.min(localTransferContext.lastOutputCwu(), cwut);
}
}

@Override
public int getMaxCWUt(Collection<IOpticalComputationProvider> seen) {
public int getMaxCWUt(Set<IOpticalComputationProvider> seen,
Map<IOpticalComputationProvider, Object> simulationState) {
seen.add(this);
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(seen, simulationState);
} else if (machine instanceof MultiblockPartMachine part) {
if (!part.isFormed()) {
return 0;
Expand All @@ -110,11 +139,11 @@ public int getMaxCWUt(Collection<IOpticalComputationProvider> seen) {
continue;
}
if (controller instanceof IOpticalComputationProvider provider) {
return provider.getMaxCWUt(seen);
return provider.getMaxCWUt(seen, simulationState);
}
for (MachineTrait trait : controller.getAllTraits()) {
if (trait instanceof IOpticalComputationProvider provider) {
return provider.getMaxCWUt(seen);
return provider.getMaxCWUt(seen, simulationState);
}
}
}
Expand All @@ -129,22 +158,25 @@ 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(seen, simulationState);
}
} else {
return lastOutputCwu;
ComputationTransferContext localTransferContext = (ComputationTransferContext) simulationState
.getOrDefault(this, this.transferContext);
return localTransferContext.lastOutputCwu();
}
}

@Override
public boolean canBridge(Collection<IOpticalComputationProvider> seen) {
public boolean canBridge(Set<IOpticalComputationProvider> seen,
Map<IOpticalComputationProvider, Object> simulationState) {
seen.add(this);
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(seen, simulationState);
} else if (machine instanceof MultiblockPartMachine part) {
if (!part.isFormed()) {
return false;
Expand All @@ -154,11 +186,11 @@ public boolean canBridge(Collection<IOpticalComputationProvider> seen) {
continue;
}
if (controller instanceof IOpticalComputationProvider provider) {
return provider.canBridge(seen);
return provider.canBridge(seen, simulationState);
}
for (MachineTrait trait : controller.getAllTraits()) {
if (trait instanceof IOpticalComputationProvider provider) {
return provider.canBridge(seen);
return provider.canBridge(seen, simulationState);
}
}
}
Expand All @@ -173,7 +205,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(seen, simulationState);
}
} else {
return false;
Expand Down Expand Up @@ -211,9 +243,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 +255,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,8 @@
import java.lang.ref.WeakReference;
import java.util.Collection;
import java.util.EnumMap;
import java.util.Map;
import java.util.Set;

public class OpticalPipeBlockEntity extends PipeBlockEntity<OpticalPipeType, OpticalPipeProperties> {

Expand Down Expand Up @@ -178,17 +180,21 @@ 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 Set<IOpticalComputationProvider> seen,
@NotNull Map<IOpticalComputationProvider, Object> simulationState) {
return 0;
}

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

@Override
public boolean canBridge(@NotNull Collection<IOpticalComputationProvider> seen) {
public boolean canBridge(@NotNull Set<IOpticalComputationProvider> seen,
@NotNull Map<IOpticalComputationProvider, Object> simulationState) {
return false;
}
}
Expand Down
Loading
Loading