diff options
| -rw-r--r-- | addon.gradle | 6 | ||||
| -rw-r--r-- | dependencies.gradle | 2 | ||||
| -rw-r--r-- | src/main/java/net/glease/ggfab/mte/MTE_AdvAssLine.java | 78 | ||||
| -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.java | 71 | ||||
| -rw-r--r-- | src/main/resources/assets/ggfab/lang/en_US.lang | 4 | ||||
| -rw-r--r-- | src/test/java/net/glease/ggfab/util/OverclockHelperTest.java | 36 | 
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 | 
