@@ -279,8 +279,15 @@ protected static boolean areItemStacksEqual(ItemStack stackA, ItemStack stackB)
279279 ItemStack .areItemStackTagsEqual (stackA , stackB ));
280280 }
281281
282+ /**
283+ * Attempts to start the specified recipe. A recipe will fail to start if there is insufficient energy,
284+ * the output inventories are full, or the required ingredients are not present.
285+ *
286+ * @param recipe the recipe to start
287+ * @return {@code true} if the recipe was started and inputs consumed, {@code false} otherwise.
288+ */
282289 protected boolean setupAndConsumeRecipeInputs (Recipe recipe ) {
283- int [] resultOverclock = calculateOverclock (recipe . getEUt (), recipe . getDuration () );
290+ int [] resultOverclock = calculateOverclock (recipe );
284291 int totalEUt = resultOverclock [0 ] * resultOverclock [1 ];
285292 IItemHandlerModifiable importInventory = getInputInventory ();
286293 IItemHandlerModifiable exportInventory = getOutputInventory ();
@@ -306,11 +313,32 @@ protected boolean setupAndConsumeRecipeInputs(Recipe recipe) {
306313 return recipe .matches (true , importInventory , importFluids );
307314 }
308315
309- protected int [] calculateOverclock (int EUt , int duration ) {
310- return calculateOverclock (EUt , this .overclockPolicy .getAsLong (), duration );
316+ /**
317+ * Performs overclocking with voltage using {@link #overclockPolicy} for the voltage.
318+ * @see #calculateOverclock(Recipe, long)
319+ */
320+ protected int [] calculateOverclock (@ NotNull Recipe recipe ) {
321+ return calculateOverclock (recipe , this .overclockPolicy .getAsLong ());
311322 }
312323
313- protected int [] calculateOverclock (int EUt , long voltage , int duration ) {
324+ /**
325+ * Attempts to overclock a given recipe.
326+ * <ul>
327+ * <li>Recipes at or below 16 EU/t overclock by halving duration and quadrupling energy consumption, until the duration
328+ * reaches a single game tick or the EU/t can no longer be increased.</li>
329+ * <li>Recipes above 16 EU/t overclock by dividing duration by 2.8 and quadrupling energy consumption, until the duration
330+ * reaches fewer than 3 game ticks or the EU/t can no longer be increased.</li>
331+ * </ul>
332+ * @param recipe the Recipe to overclock
333+ * @param voltage the maximum EU/t to use for overclocking. This value must be positive.
334+ * @return an {@code int[]} of length 2, where [0] is the computed EU/t and [1] the duration.
335+ */
336+ protected int [] calculateOverclock (@ NotNull final Recipe recipe , final long voltage ) {
337+ assert (voltage >= 0 );
338+
339+ int EUt = recipe .getEUt ();
340+ int duration = recipe .getDuration ();
341+
314342 if (!allowOverclocking ) {
315343 return new int [] {EUt , duration };
316344 }
@@ -322,19 +350,22 @@ protected int[] calculateOverclock(int EUt, long voltage, int duration) {
322350 EUt = -EUt ;
323351 if (EUt <= 16 ) {
324352 int multiplier = EUt <= 8 ? tier : tier - 1 ;
325- int resultEUt = EUt * (1 << multiplier ) * (1 << multiplier );
326- int resultDuration = duration / (1 << multiplier );
327- return new int []{negativeEU ? -resultEUt : resultEUt , resultDuration };
353+ // Restrict the maximum number of overclocks to how many times the duration can be halved
354+ int speedCap = (31 - Integer .numberOfLeadingZeros (duration ));
355+ if (multiplier > speedCap ) multiplier = speedCap ;
356+ EUt *= (1 << 2 * multiplier );
357+ duration /= (1 << multiplier );
328358 } else {
329- int resultEUt = EUt ;
330- double resultDuration = duration ;
331- //do not overclock further if duration is already too small
332- while (resultDuration >= 3 && resultEUt <= GTValues .V [tier - 1 ]) {
333- resultEUt *= 4 ;
334- resultDuration /= 2.8 ;
359+ // Restrict the maximum number of overclocks to how many times the duration is divisible by 2.8
360+ int speedCap = (int ) (Math .log (duration ) / Math .log (2.8 ));
361+ int dt = tier - recipe .getBaseTier ();
362+ if (dt > speedCap ) dt = speedCap ;
363+ if (dt > 0 ) {
364+ EUt *= Math .pow (4 , dt );
365+ duration /= Math .pow (2.8 , dt );
335366 }
336- return new int []{negativeEU ? -resultEUt : resultEUt , (int ) Math .ceil (resultDuration )};
337367 }
368+ return new int []{negativeEU ? -EUt : EUt , duration };
338369 }
339370
340371 protected int getOverclockingTier (long voltage ) {
@@ -356,7 +387,7 @@ public String[] getAvailableOverclockingTiers() {
356387 }
357388
358389 protected void setupRecipe (Recipe recipe ) {
359- int [] resultOverclock = calculateOverclock (recipe . getEUt (), recipe . getDuration () );
390+ int [] resultOverclock = calculateOverclock (recipe );
360391 this .progressTime = 1 ;
361392 setMaxProgress (resultOverclock [1 ]);
362393 this .recipeEUt = resultOverclock [0 ];
@@ -399,8 +430,13 @@ public List<Pair<ItemStack, Integer>> getChancedItemOutputs() {
399430 return chancedItemOutputs ;
400431 }
401432
433+ /**
434+ * <b>This is NOT for energy calculations. Use {@link #getOverclockingTier(long)} for energy.</b><br />
435+ * Used to override the machine's tier for the purposes of determining chanced outputs.
436+ * The default implementation simply returns the overclocking tier of the maximum voltage of the machine.
437+ */
402438 protected int getMachineTierForRecipe (Recipe recipe ) {
403- return GTUtility . getTierByVoltage (getMaxVoltage ());
439+ return getOverclockingTier (getMaxVoltage ());
404440 }
405441
406442 protected void completeRecipe () {
0 commit comments