aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--addon.gradle6
-rw-r--r--dependencies.gradle2
-rw-r--r--src/main/java/net/glease/ggfab/mte/MTE_AdvAssLine.java78
-rw-r--r--src/main/java/net/glease/ggfab/util/GGUtils.java (renamed from src/main/java/net/glease/ggfab/GGUtils.java)2
-rw-r--r--src/main/java/net/glease/ggfab/util/OverclockHelper.java71
-rw-r--r--src/main/resources/assets/ggfab/lang/en_US.lang4
-rw-r--r--src/test/java/net/glease/ggfab/util/OverclockHelperTest.java36
7 files changed, 155 insertions, 44 deletions
diff --git a/addon.gradle b/addon.gradle
index e879a8b814..94f0829400 100644
--- a/addon.gradle
+++ b/addon.gradle
@@ -5,3 +5,9 @@ idea {
testOutputDir = compileTestJava.destinationDir
}
}
+test {
+ useJUnitPlatform()
+ testLogging {
+ events "passed", "skipped", "failed"
+ }
+} \ No newline at end of file
diff --git a/dependencies.gradle b/dependencies.gradle
index 2c6f782eb7..f523b40a7b 100644
--- a/dependencies.gradle
+++ b/dependencies.gradle
@@ -1,6 +1,8 @@
// Add your dependencies here
dependencies {
+ testImplementation(platform('org.junit:junit-bom:5.8.2'))
+ testImplementation('org.junit.jupiter:junit-jupiter')
compile("net.industrial-craft:industrialcraft-2:2.2.828-experimental:dev")
compile("com.github.GTNewHorizons:GT5-Unofficial:5.09.41.172:dev")
}
diff --git a/src/main/java/net/glease/ggfab/mte/MTE_AdvAssLine.java b/src/main/java/net/glease/ggfab/mte/MTE_AdvAssLine.java
index bd533b29c8..58aacf178c 100644
--- a/src/main/java/net/glease/ggfab/mte/MTE_AdvAssLine.java
+++ b/src/main/java/net/glease/ggfab/mte/MTE_AdvAssLine.java
@@ -1,6 +1,5 @@
package net.glease.ggfab.mte;
-import com.google.common.collect.Collections2;
import com.gtnewhorizon.structurelib.alignment.constructable.ISurvivalConstructable;
import com.gtnewhorizon.structurelib.structure.IStructureDefinition;
import com.gtnewhorizon.structurelib.structure.ISurvivalBuildEnvironment;
@@ -18,6 +17,7 @@ import gregtech.api.util.*;
import mcp.mobius.waila.api.IWailaConfigHandler;
import mcp.mobius.waila.api.IWailaDataAccessor;
import net.glease.ggfab.GGConstants;
+import net.glease.ggfab.util.OverclockHelper;
import net.minecraft.client.resources.I18n;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.item.ItemStack;
@@ -49,7 +49,7 @@ Dev note:
1. This multi will be an assline but with greater throughput. it will take one input every
2.
*/
-public class MTE_AdvAssLine extends GT_MetaTileEntity_EnhancedMultiBlockBase<MTE_AdvAssLine> implements ISurvivalConstructable {
+public class MTE_AdvAssLine extends GT_MetaTileEntity_ExtendedPowerMultiBlockBase<MTE_AdvAssLine> implements ISurvivalConstructable {
private static final String STRUCTURE_PIECE_FIRST = "first";
private static final String STRUCTURE_PIECE_LATER = "later";
private static final String STRUCTURE_PIECE_LAST = "last";
@@ -123,12 +123,12 @@ public class MTE_AdvAssLine extends GT_MetaTileEntity_EnhancedMultiBlockBase<MTE
private final Slice[] slices = IntStream.range(0, 16).mapToObj(Slice::new).toArray(Slice[]::new);
private boolean processing;
private long inputVoltage;
+ // surely no one is using more EUt than this, no?
+ private long inputEUt;
private long baseEUt;
private boolean stuck;
private final ArrayList<GT_MetaTileEntity_Hatch_DataAccess> mDataAccessHatches = new ArrayList<>();
- private final Collection<GT_MetaTileEntity_Hatch> allEnergyHatchesView = Collections2.filter(new ConcatList<>(mExoticEnergyHatches, mEnergyHatches), GT_MetaTileEntity_MultiBlockBase::isValidMetaTileEntity);
-
public MTE_AdvAssLine(int aID, String aName, String aNameRegional) {
super(aID, aName, aNameRegional);
}
@@ -200,7 +200,7 @@ public class MTE_AdvAssLine extends GT_MetaTileEntity_EnhancedMultiBlockBase<MTE
@SuppressWarnings("unchecked") List<EntityPlayerMP> l = MinecraftServer.getServer().getConfigurationManager().playerEntityList;
for (EntityPlayerMP p : l) {
if (p.getUniqueID().equals(ownerUuid)) {
- for (int i = 0; i < 7; i++) {
+ for (int i = 0; i < 9; i++) {
p.addChatMessage(new ChatComponentTranslation("ggfab.info.advassline." + i));
}
}
@@ -365,12 +365,9 @@ public class MTE_AdvAssLine extends GT_MetaTileEntity_EnhancedMultiBlockBase<MTE
public boolean checkMachine(IGregTechTileEntity aBaseMetaTileEntity, ItemStack aStack) {
if (checkMachine()) {
inputVoltage = Integer.MAX_VALUE;
- for (GT_MetaTileEntity_Hatch tHatch : mEnergyHatches) {
- inputVoltage = Math.min(inputVoltage, tHatch.maxEUInput());
- }
- for (GT_MetaTileEntity_Hatch tHatch : mExoticEnergyHatches) {
- inputVoltage = Math.min(inputVoltage, tHatch.maxEUInput());
- }
+ inputEUt = 0;
+ mEnergyHatches.forEach(this::recordEnergySupplier);
+ mExoticEnergyHatches.forEach(this::recordEnergySupplier);
return true;
} else {
inputVoltage = V[0];
@@ -378,9 +375,14 @@ public class MTE_AdvAssLine extends GT_MetaTileEntity_EnhancedMultiBlockBase<MTE
}
}
- @Override
- public boolean drainEnergyInput(long aEU) {
- return GT_ExoticEnergyInputHelper.drainEnergy(aEU, allEnergyHatchesView);
+ private void recordEnergySupplier(GT_MetaTileEntity_Hatch hatch) {
+ if (!isValidMetaTileEntity(hatch))
+ return;
+ inputEUt += hatch.maxEUInput() * hatch.maxAmperesIn();
+ inputVoltage = Math.min(inputVoltage, hatch.maxEUInput());
+ if (inputEUt < 0)
+ // I'd prefer bullying colen than use bigint
+ inputEUt = Long.MAX_VALUE;
}
@Override
@@ -578,9 +580,20 @@ public class MTE_AdvAssLine extends GT_MetaTileEntity_EnhancedMultiBlockBase<MTE
recipe = findRecipe(stack);
if (recipe != null) {
setCurrentRecipe(stack, recipe);
+ // first overclock normally
calculateOverclockedNessMulti(currentRecipe.mEUt, Math.max(recipe.mDuration / recipe.mInputs.length, 1), 1, inputVoltage);
- // correct the recipe duration
- mMaxProgresstime *= recipe.mInputs.length;
+ // then laser overclock if needed
+ if (!mExoticEnergyHatches.isEmpty()) {
+ OverclockHelper.OverclockOutput laserOverclock = OverclockHelper.laserOverclock(mEUt, mMaxProgresstime, inputEUt / recipe.mInputs.length, 0.3f);
+ if (laserOverclock == null) {
+ if (GT_Values.D1) {
+ GT_FML_LOGGER.info("Recipe too OP");
+ }
+ continue;
+ }
+ lEUt = laserOverclock.getEUt();
+ mMaxProgresstime = laserOverclock.getDuration();
+ }
// In case recipe is too OP for that machine
if (mMaxProgresstime == Integer.MAX_VALUE - 1 && mEUt == Integer.MAX_VALUE - 1) {
if (GT_Values.D1) {
@@ -588,6 +601,8 @@ public class MTE_AdvAssLine extends GT_MetaTileEntity_EnhancedMultiBlockBase<MTE
}
continue;
}
+ // correct the recipe duration
+ mMaxProgresstime *= recipe.mInputs.length;
break;
}
}
@@ -690,6 +705,11 @@ public class MTE_AdvAssLine extends GT_MetaTileEntity_EnhancedMultiBlockBase<MTE
tag.setInteger("mDuration", mMaxProgresstime / currentRecipe.mInputs.length);
}
+ @Override
+ public String[] getInfoData() {
+ return super.getInfoData();
+ }
+
private void drainAllFluids(GT_Recipe.GT_Recipe_AssemblyLine recipe) {
for (int i = 0; i < recipe.mFluidInputs.length; i++) {
depleteInput(recipe.mFluidInputs[i]);
@@ -800,30 +820,4 @@ public class MTE_AdvAssLine extends GT_MetaTileEntity_EnhancedMultiBlockBase<MTE
return t.mDataAccessHatches.size();
}
}
-
- private static class ConcatList<T> extends AbstractList<T> {
- private final List<? extends T> la, lb;
-
- public ConcatList(List<? extends T> la, List<? extends T> lb) {
- this.la = la;
- this.lb = lb;
- }
-
- @Override
- public T get(int index) {
- int lasize = la.size();
- return index < lasize ? la.get(index) : lb.get(index - lasize);
- }
-
- @Override
- public int size() {
- return la.size() + lb.size();
- }
-
- @Override
- public T remove(int index) {
- int lasize = la.size();
- return index < lasize ? la.remove(index) : lb.remove(index - lasize);
- }
- }
}
diff --git a/src/main/java/net/glease/ggfab/GGUtils.java b/src/main/java/net/glease/ggfab/util/GGUtils.java
index ea34952971..1f47c82885 100644
--- a/src/main/java/net/glease/ggfab/GGUtils.java
+++ b/src/main/java/net/glease/ggfab/util/GGUtils.java
@@ -1,4 +1,4 @@
-package net.glease.ggfab;
+package net.glease.ggfab.util;
import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
diff --git a/src/main/java/net/glease/ggfab/util/OverclockHelper.java b/src/main/java/net/glease/ggfab/util/OverclockHelper.java
new file mode 100644
index 0000000000..7d0699a298
--- /dev/null
+++ b/src/main/java/net/glease/ggfab/util/OverclockHelper.java
@@ -0,0 +1,71 @@
+package net.glease.ggfab.util;
+
+import gregtech.api.util.GT_Utility;
+
+public class OverclockHelper {
+ public static OverclockOutput normalOverclock(long recipeEUt, int duration, long inputVoltage, boolean perfectOC) {
+ if (recipeEUt > inputVoltage) return null;
+ int recipeTier = Math.max(1, GT_Utility.getTier(recipeEUt)); // ULV no overclock
+ int machineTier = GT_Utility.getTier(inputVoltage);
+ int shift = perfectOC ? 2 : 1;
+ while (recipeTier < machineTier && duration > 1) {
+ duration >>= shift;
+ recipeEUt <<= 2;
+ recipeTier++;
+ }
+ return new OverclockOutput(recipeEUt, duration);
+ }
+
+ public static OverclockOutput laserOverclock(long recipeEUt, int duration, long inputEUt, float penaltyIncreaseFactor) {
+ if (recipeEUt > inputEUt) return null;
+ float currentPenalty = 4 + penaltyIncreaseFactor;
+ // 2/(n+k) overclock until energy hatch is crying
+ while (recipeEUt * currentPenalty < inputEUt && duration > 1) {
+ duration >>= 1;
+ recipeEUt *= currentPenalty;
+ currentPenalty += penaltyIncreaseFactor;
+ }
+ return new OverclockOutput(recipeEUt, duration);
+ }
+
+ public static final class OverclockOutput {
+ private final long mEUt;
+ private final int mDuration;
+
+ public OverclockOutput(long aEUt, int aDuration) {
+ this.mEUt = aEUt;
+ this.mDuration = aDuration;
+ }
+
+ public long getEUt() {
+ return mEUt;
+ }
+
+ public int getDuration() {
+ return mDuration;
+ }
+
+ @Override
+ public String toString() {
+ return mEUt + "@" + mDuration + "ticks";
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof OverclockOutput)) return false;
+
+ OverclockOutput that = (OverclockOutput) o;
+
+ if (mEUt != that.mEUt) return false;
+ return mDuration == that.mDuration;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = (int) (mEUt ^ (mEUt >>> 32));
+ result = 31 * result + mDuration;
+ return result;
+ }
+ }
+}
diff --git a/src/main/resources/assets/ggfab/lang/en_US.lang b/src/main/resources/assets/ggfab/lang/en_US.lang
index e726ec787e..9384c42b05 100644
--- a/src/main/resources/assets/ggfab/lang/en_US.lang
+++ b/src/main/resources/assets/ggfab/lang/en_US.lang
@@ -4,7 +4,9 @@ ggfab.info.advassline.2=It supports item pipelining. That is, it will mimic a re
ggfab.info.advassline.3=You can think of an advanced assembly line as a collection of assembly slices. Each assembly slice is capably of processing each step independent of other slices.
ggfab.info.advassline.4=It will start processing once the input bus contents align with any stored data stick. The first slice will consume the input in Bus #1. After (recipe time/number of inputs) time, the first slice's work is concluded and will start the second slice. At the same time, first slice will look for input in input bus #1. If there are still enough input there slice #1 will start working again.
ggfab.info.advassline.5=The terminal slice (the n-th slice, where n is number of item input in recipe) will put the recipe output in output bus when it has concluded his work. Whenever a non-terminal slice finished its work, it will try to pass the work onto next slice. If the next slice cannot find the materials in its input bus, the just-finished slice will remain in §4STUCK§r state and hang the assembly line. To help locate these §4STUCK§r assembly lines, the controller's front face will have its status light turned orange.
-ggfab.info.advassline.6=The EU/t cost of this machine is number of slices active multiplied by the original recipe EU/t. §4STUCK§r slices do not consume power.
+ggfab.info.advassline.6=The EU/t cost of this machine is number of slices active multiplied by the original recipe EU/t. §4STUCK§r slices do not consume power. It will use the worst energy supplying hatch's input voltage for recipe tier calculation and normal imperfect overclock.
+ggfab.info.advassline.7=With exotic energy hatches, it can overclock beyond usual voltage tier, but will consume even more power than usual imperfect overclock. Every §2laser overclock§r will add 0.5 to power exponent.
+ggfab.info.advassline.8=1 §2laser overclock§r will have 50% recipe time and use 430% power. 2 §2laser overclock§r will have 25% recipe time and use 1978% (4.3*4.6) power. Will not overclock beyond 1 tick. Machine first tries to parallelize, then normal imperfect overclock, then §2laser overclock§r.
ggfab.waila.advassline.slice=Slice #%s: %s s/%s s
ggfab.waila.advassline.slice.small=Slice #%s: %s ticks remaining
ggfab.waila.advassline.slice.idle=Slice #%s: Idle
diff --git a/src/test/java/net/glease/ggfab/util/OverclockHelperTest.java b/src/test/java/net/glease/ggfab/util/OverclockHelperTest.java
new file mode 100644
index 0000000000..41707d97ac
--- /dev/null
+++ b/src/test/java/net/glease/ggfab/util/OverclockHelperTest.java
@@ -0,0 +1,36 @@
+package net.glease.ggfab.util;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+class OverclockHelperTest {
+
+ @Test
+ void normalOverclockImperfect() {
+ // fails recipe
+ assertNull(OverclockHelper.normalOverclock(10000, 10000, 1, false));
+ // no overclock
+ assertEquals(new OverclockHelper.OverclockOutput(30, 64), OverclockHelper.normalOverclock(30, 64, 32, false));
+ // imperfect overclock
+ assertEquals(new OverclockHelper.OverclockOutput(120, 32), OverclockHelper.normalOverclock(30, 64, 128, false));
+ // lots of overclock
+ assertEquals(new OverclockHelper.OverclockOutput(30720, 2), OverclockHelper.normalOverclock(30, 64, 32768, false));
+ // do not overclock beyond useful
+ assertEquals(new OverclockHelper.OverclockOutput(122880, 1), OverclockHelper.normalOverclock(30, 64, 524288, false));
+ }
+
+ @Test
+ void laserOverclock() {
+ // fails recipe
+ assertNull(OverclockHelper.laserOverclock(10000, 10000, 1, 5));
+ // no overclock
+ assertEquals(new OverclockHelper.OverclockOutput(30, 64), OverclockHelper.laserOverclock(30, 64, 32, 0.5f));
+ // laser overclock
+ assertEquals(new OverclockHelper.OverclockOutput(135, 32), OverclockHelper.laserOverclock(30, 64, 32 * 16, 0.5f));
+ // lots of overclock
+ assertEquals(new OverclockHelper.OverclockOutput(22272, 4), OverclockHelper.laserOverclock(30, 64, 32 * 1024, 0.5f));
+ // do not overclock beyond useful
+ assertEquals(new OverclockHelper.OverclockOutput(135, 1), OverclockHelper.laserOverclock(30, 2, 32 * 16, 0.5f));
+ }
+} \ No newline at end of file