Skip to content

Commit efa8513

Browse files
authored
Overclock logic tests (#3661)
1 parent 168482b commit efa8513

File tree

1 file changed

+291
-0
lines changed

1 file changed

+291
-0
lines changed
Lines changed: 291 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,291 @@
1+
package com.gregtechceu.gtceu.api.recipe;
2+
3+
import com.gregtechceu.gtceu.GTCEu;
4+
import com.gregtechceu.gtceu.api.GTValues;
5+
import com.gregtechceu.gtceu.api.blockentity.MetaMachineBlockEntity;
6+
import com.gregtechceu.gtceu.api.machine.MetaMachine;
7+
import com.gregtechceu.gtceu.api.machine.multiblock.MultiblockControllerMachine;
8+
import com.gregtechceu.gtceu.common.machine.multiblock.part.FluidHatchPartMachine;
9+
import com.gregtechceu.gtceu.common.machine.multiblock.part.ItemBusPartMachine;
10+
import com.gregtechceu.gtceu.gametest.util.TestUtils;
11+
12+
import net.minecraft.core.BlockPos;
13+
import net.minecraft.gametest.framework.BeforeBatch;
14+
import net.minecraft.gametest.framework.GameTest;
15+
import net.minecraft.gametest.framework.GameTestHelper;
16+
import net.minecraft.server.level.ServerLevel;
17+
import net.minecraft.world.item.ItemStack;
18+
import net.minecraft.world.item.Items;
19+
import net.minecraft.world.level.block.Blocks;
20+
import net.minecraft.world.level.block.entity.BlockEntity;
21+
import net.minecraftforge.gametest.GameTestHolder;
22+
import net.minecraftforge.gametest.PrefixGameTestTemplate;
23+
24+
import static com.gregtechceu.gtceu.api.recipe.OverclockingLogic.*;
25+
import static com.gregtechceu.gtceu.common.data.GTRecipeModifiers.*;
26+
import static com.gregtechceu.gtceu.common.data.GTRecipeTypes.LARGE_CHEMICAL_RECIPES;
27+
28+
@PrefixGameTestTemplate(false)
29+
@GameTestHolder(GTCEu.MOD_ID)
30+
public class OverclockLogicTest {
31+
32+
@BeforeBatch(batch = "OverclockLogic")
33+
public static void prepare(ServerLevel level) {
34+
LARGE_CHEMICAL_RECIPES.getLookup().addRecipe(LARGE_CHEMICAL_RECIPES
35+
.recipeBuilder(GTCEu.id("test-overlock-logic"))
36+
.id(GTCEu.id("test-overlock-logic"))
37+
.inputItems(new ItemStack(Items.RED_BED))
38+
.outputItems(new ItemStack(Blocks.STONE))
39+
.EUt(GTValues.VA[GTValues.HV])
40+
.duration(20)
41+
// NBT has a schematic in it with an HV energy input hatch
42+
.buildRawRecipe());
43+
LARGE_CHEMICAL_RECIPES.getLookup().addRecipe(LARGE_CHEMICAL_RECIPES
44+
.recipeBuilder(GTCEu.id("test-overlock-logic-2"))
45+
.id(GTCEu.id("test-overlock-logic-2"))
46+
.inputItems(new ItemStack(Items.STICK))
47+
.outputItems(new ItemStack(Blocks.STONE))
48+
.EUt(GTValues.VA[GTValues.LV])
49+
.duration(1)
50+
// NBT has a schematic in it with an HV energy input hatch
51+
.buildRawRecipe());
52+
LARGE_CHEMICAL_RECIPES.getLookup().addRecipe(LARGE_CHEMICAL_RECIPES
53+
.recipeBuilder(GTCEu.id("test-overlock-logic-3"))
54+
.id(GTCEu.id("test-overlock-logic-3"))
55+
.inputItems(new ItemStack(Items.BROWN_BED))
56+
.outputItems(new ItemStack(Blocks.STONE))
57+
.EUt(GTValues.VA[GTValues.EV])
58+
.duration(1)
59+
// NBT has a schematic in it with an HV energy input hatch
60+
.buildRawRecipe());
61+
}
62+
63+
private static MetaMachine getMetaMachine(BlockEntity entity) {
64+
return ((MetaMachineBlockEntity) entity).getMetaMachine();
65+
}
66+
67+
private record BusHolder(ItemBusPartMachine inputBus1, ItemBusPartMachine inputBus2, ItemBusPartMachine outputBus1,
68+
FluidHatchPartMachine outputHatch1, MultiblockControllerMachine controller) {}
69+
70+
/**
71+
* Retrieves the busses for this specific template and force a multiblock structure check
72+
*
73+
* @param helper the GameTestHelper
74+
* @return the busses, in the BusHolder record.
75+
*/
76+
private static BusHolder getBussesAndForm(GameTestHelper helper) {
77+
MultiblockControllerMachine controller = (MultiblockControllerMachine) getMetaMachine(
78+
helper.getBlockEntity(new BlockPos(1, 2, 0)));
79+
TestUtils.formMultiblock(controller);
80+
ItemBusPartMachine inputBus1 = (ItemBusPartMachine) getMetaMachine(
81+
helper.getBlockEntity(new BlockPos(2, 1, 0)));
82+
ItemBusPartMachine inputBus2 = (ItemBusPartMachine) getMetaMachine(
83+
helper.getBlockEntity(new BlockPos(2, 2, 0)));
84+
ItemBusPartMachine outputBus1 = (ItemBusPartMachine) getMetaMachine(
85+
helper.getBlockEntity(new BlockPos(0, 1, 0)));
86+
FluidHatchPartMachine outputHatch1 = (FluidHatchPartMachine) getMetaMachine(
87+
helper.getBlockEntity(new BlockPos(0, 2, 0)));
88+
return new BusHolder(inputBus1, inputBus2, outputBus1, outputHatch1, controller);
89+
}
90+
91+
// Test for running HV recipe at HV
92+
@GameTest(template = "lcr_input_separation", batch = "OverclockLogic", setupTicks = 40, timeoutTicks = 200)
93+
public static void overclockLogicOnTierNothingChanges(GameTestHelper helper) {
94+
BusHolder busHolder = getBussesAndForm(helper);
95+
busHolder.inputBus1.getInventory().setStackInSlot(0, new ItemStack(Items.RED_BED));
96+
// One tick to start, 20 for the recipe to run
97+
helper.succeedOnTickWhen(21, () -> {
98+
helper.assertTrue(
99+
TestUtils.isItemStackEqual(busHolder.outputBus1.getInventory().getStackInSlot(0),
100+
new ItemStack(Blocks.STONE)),
101+
"Item didn't craft at the right tick with an on-tier recipe" +
102+
busHolder.outputBus1.getInventory().getStackInSlot(0).getDisplayName());
103+
});
104+
}
105+
106+
// Test for running LV 1t recipe at HV
107+
@GameTest(template = "lcr_input_separation", batch = "OverclockLogic", setupTicks = 40, timeoutTicks = 200)
108+
public static void overclockLogicTwoTiersAbove16Parallels(GameTestHelper helper) {
109+
BusHolder busHolder = getBussesAndForm(helper);
110+
busHolder.inputBus1.getInventory().setStackInSlot(0, new ItemStack(Items.STICK, 64));
111+
// One tick to start, 4 for the recipe to run (16/t from ULV recipe to HV)
112+
helper.succeedOnTickWhen(5, () -> {
113+
helper.assertTrue(
114+
TestUtils.isItemStackEqual(busHolder.outputBus1.getInventory().getStackInSlot(0),
115+
new ItemStack(Blocks.STONE, 64)),
116+
"Item didn't craft at the right tick with an on-tier recipe" +
117+
busHolder.outputBus1.getInventory().getStackInSlot(0).getDisplayName());
118+
});
119+
}
120+
121+
// Test for running EV recipe at HV
122+
@GameTest(template = "lcr_input_separation", batch = "OverclockLogic", setupTicks = 40, timeoutTicks = 200)
123+
public static void overclockLogicOverTierNothingHappens(GameTestHelper helper) {
124+
BusHolder busHolder = getBussesAndForm(helper);
125+
busHolder.inputBus1.getInventory().setStackInSlot(0, new ItemStack(Items.BROWN_BED));
126+
helper.failIfEver(() -> {
127+
helper.assertFalse(
128+
busHolder.outputBus1.getInventory().getStackInSlot(0).getItem().equals(Blocks.STONE.asItem()),
129+
"Item crafted at one tier over when it shouldn't have");
130+
});
131+
helper.succeed();
132+
}
133+
134+
// Test for code wise calculating perfect OC
135+
@GameTest(template = "lcr_input_separation", batch = "OverclockLogic")
136+
public static void overclockLogicApplyPerfectOverclockTest(GameTestHelper helper) {
137+
BusHolder busHolder = getBussesAndForm(helper);
138+
// An HV LCR can overclock an MV recipe once
139+
// We pass the controller because it is used to fetch .getMaxVoltageTier() and check input ingredients for
140+
// parallel
141+
GTRecipe recipeBeforeModifiers = LARGE_CHEMICAL_RECIPES
142+
.recipeBuilder(GTCEu.id("test-multiblock-input-separation"))
143+
.id(GTCEu.id("test-multiblock-input-separation"))
144+
.inputItems(new ItemStack(Blocks.COBBLESTONE), new ItemStack(Blocks.ACACIA_WOOD))
145+
.outputItems(new ItemStack(Blocks.STONE))
146+
.EUt(GTValues.VA[GTValues.MV]).duration(100)
147+
.buildRawRecipe();
148+
149+
GTRecipe newRecipe = OC_PERFECT.applyModifier(busHolder.controller, recipeBeforeModifiers);
150+
helper.assertTrue(newRecipe != null, "Could not apply overclock to recipe");
151+
helper.assertTrue(newRecipe.duration == (recipeBeforeModifiers.duration / PERFECT_DURATION_FACTOR_INV),
152+
"Perfect perfect overclock didn't cut recipe time by 4");
153+
helper.assertTrue(
154+
newRecipe.getInputEUt().getTotalEU() ==
155+
(recipeBeforeModifiers.getInputEUt().getTotalEU() * STD_VOLTAGE_FACTOR),
156+
"Non perfect overclock didn't multiply EU by 4");
157+
helper.succeed();
158+
}
159+
160+
// Test for code wise calculating non-perfect OC
161+
@GameTest(template = "lcr_input_separation", batch = "OverclockLogic")
162+
public static void overclockLogicApplyNonPerfectOverclockTest(GameTestHelper helper) {
163+
BusHolder busHolder = getBussesAndForm(helper);
164+
// An HV LCR can overclock an MV recipe once
165+
// We pass the controller because it is used to fetch .getMaxVoltageTier() and check input ingredients for
166+
// parallel
167+
GTRecipe recipeBeforeModifiers = LARGE_CHEMICAL_RECIPES
168+
.recipeBuilder(GTCEu.id("test-multiblock-overclock-test-npo"))
169+
.id(GTCEu.id("test-multiblock-overclock-test-npo"))
170+
.inputItems(new ItemStack(Blocks.COBBLESTONE), new ItemStack(Blocks.ACACIA_WOOD))
171+
.outputItems(new ItemStack(Blocks.STONE))
172+
.EUt(GTValues.VA[GTValues.MV]).duration(100)
173+
.buildRawRecipe();
174+
175+
GTRecipe newRecipe = OC_NON_PERFECT.applyModifier(busHolder.controller, recipeBeforeModifiers);
176+
helper.assertTrue(newRecipe != null, "Could not apply overclock to recipe");
177+
helper.assertTrue(newRecipe.duration == (recipeBeforeModifiers.duration / STD_DURATION_FACTOR_INV),
178+
"Non perfect overclock didn't cut recipe time by 2");
179+
helper.assertTrue(
180+
newRecipe.getInputEUt().getTotalEU() ==
181+
(recipeBeforeModifiers.getInputEUt().getTotalEU() * STD_VOLTAGE_FACTOR),
182+
"Non perfect overclock didn't multiply EU by 4");
183+
helper.succeed();
184+
}
185+
186+
// Test for code wise calculating subtick perfect OC
187+
@GameTest(template = "lcr_input_separation", batch = "OverclockLogic")
188+
public static void overclockLogicApplyPerfectParallelOverclockTest(GameTestHelper helper) {
189+
BusHolder busHolder = getBussesAndForm(helper);
190+
// An HV LCR can overclock an MV recipe once
191+
// We pass the controller because it is used to fetch .getMaxVoltageTier() and check input ingredients for
192+
// parallel
193+
GTRecipe recipeBeforeModifiers = LARGE_CHEMICAL_RECIPES
194+
.recipeBuilder(GTCEu.id("test-multiblock-overclock-test-psto"))
195+
.id(GTCEu.id("test-multiblock-overclock-test-psto"))
196+
.inputItems(new ItemStack(Blocks.COBBLESTONE))
197+
.outputItems(new ItemStack(Blocks.STONE))
198+
.EUt(GTValues.VA[GTValues.MV]).duration(1)
199+
.buildRawRecipe();
200+
busHolder.inputBus1.getInventory().setStackInSlot(0, new ItemStack(Blocks.COBBLESTONE, 64));
201+
202+
GTRecipe newRecipe = OC_PERFECT_SUBTICK.applyModifier(busHolder.controller, recipeBeforeModifiers);
203+
204+
helper.assertTrue(newRecipe != null, "Could not apply overclock to recipe");
205+
helper.assertTrue(newRecipe.parallels == PERFECT_DURATION_FACTOR_INV,
206+
"Perfect subtick overclock didn't multiply parallels by 4");
207+
helper.assertTrue(
208+
newRecipe.getInputEUt().getTotalEU() ==
209+
(recipeBeforeModifiers.getInputEUt().getTotalEU() * STD_VOLTAGE_FACTOR),
210+
"Perfect subtick overclock didn't multiply EU by 4");
211+
helper.succeed();
212+
}
213+
214+
// Test for code wise calculating subtick non-perfect OC
215+
@GameTest(template = "lcr_input_separation", batch = "OverclockLogic")
216+
public static void overclockLogicApplyNonPerfectParallelOverclockTest(GameTestHelper helper) {
217+
BusHolder busHolder = getBussesAndForm(helper);
218+
// An HV LCR can overclock an MV recipe once
219+
// We pass the controller because it is used to fetch .getMaxVoltageTier() and check input ingredients for
220+
// parallel
221+
GTRecipe recipeBeforeModifiers = LARGE_CHEMICAL_RECIPES
222+
.recipeBuilder(GTCEu.id("test-multiblock-overclock-test-npsto"))
223+
.id(GTCEu.id("test-multiblock-overclock-test-npsto"))
224+
.inputItems(new ItemStack(Blocks.COBBLESTONE))
225+
.outputItems(new ItemStack(Blocks.STONE))
226+
.EUt(GTValues.VA[GTValues.MV]).duration(1)
227+
.buildRawRecipe();
228+
busHolder.inputBus1.getInventory().setStackInSlot(0, new ItemStack(Blocks.COBBLESTONE, 64));
229+
230+
GTRecipe newRecipe = OC_NON_PERFECT_SUBTICK.applyModifier(busHolder.controller, recipeBeforeModifiers);
231+
232+
helper.assertTrue(newRecipe != null, "Could not apply overclock to recipe");
233+
helper.assertTrue(newRecipe.parallels == STD_DURATION_FACTOR_INV,
234+
"Non-Perfect subtick overclock didn't multiply parallels by 2");
235+
helper.assertTrue(
236+
newRecipe.getInputEUt().getTotalEU() ==
237+
(recipeBeforeModifiers.getInputEUt().getTotalEU() * STD_VOLTAGE_FACTOR),
238+
"Non-Perfect subtick overclock didn't multiply EU by 4");
239+
helper.succeed();
240+
}
241+
242+
// Test for code wise calculating non-subtick non-perfect OC on a 1t recipe
243+
@GameTest(template = "lcr_input_separation", batch = "OverclockLogic")
244+
public static void overclockLogicApplyNonPerfectNonParallel1tOverclockTest(GameTestHelper helper) {
245+
BusHolder busHolder = getBussesAndForm(helper);
246+
// An HV LCR can overclock an MV recipe once
247+
// We pass the controller because it is used to fetch .getMaxVoltageTier() and check input ingredients for
248+
// parallel
249+
GTRecipe recipeBeforeModifiers = LARGE_CHEMICAL_RECIPES
250+
.recipeBuilder(GTCEu.id("test-multiblock-overclock-test-npsto"))
251+
.id(GTCEu.id("test-multiblock-overclock-test-npsto"))
252+
.inputItems(new ItemStack(Blocks.COBBLESTONE))
253+
.outputItems(new ItemStack(Blocks.STONE))
254+
.EUt(GTValues.VA[GTValues.MV]).duration(1)
255+
.buildRawRecipe();
256+
busHolder.inputBus1.getInventory().setStackInSlot(0, new ItemStack(Blocks.COBBLESTONE, 64));
257+
258+
GTRecipe newRecipe = OC_NON_PERFECT.applyModifier(busHolder.controller, recipeBeforeModifiers);
259+
260+
helper.assertTrue(newRecipe != null, "Could not apply overclock to recipe");
261+
helper.assertTrue(newRecipe.parallels == 1,
262+
"Non-Perfect Non-subtick overclock overclocked when it shouldn't have");
263+
helper.assertTrue(
264+
newRecipe.getInputEUt().getTotalEU() == recipeBeforeModifiers.getInputEUt().getTotalEU(),
265+
"Non-Perfect Non-subtick overclock at 1t changed EU");
266+
helper.succeed();
267+
}
268+
269+
// Test for code wise calculating an overclock on a recipe that can't be run
270+
@GameTest(template = "lcr_input_separation", batch = "OverclockLogic")
271+
public static void overclockLogicEVRecipeHVMachineTest(GameTestHelper helper) {
272+
BusHolder busHolder = getBussesAndForm(helper);
273+
// An HV LCR can overclock an MV recipe once
274+
// We pass the controller because it is used to fetch .getMaxVoltageTier() and check input ingredients for
275+
// parallel
276+
GTRecipe recipeBeforeModifiers = LARGE_CHEMICAL_RECIPES
277+
.recipeBuilder(GTCEu.id("test-multiblock-overclock-test-ev-hv"))
278+
.id(GTCEu.id("test-multiblock-overclock-test-ev-hv"))
279+
.inputItems(new ItemStack(Blocks.COBBLESTONE))
280+
.outputItems(new ItemStack(Blocks.STONE))
281+
.EUt(GTValues.VA[GTValues.EV]).duration(1)
282+
.buildRawRecipe();
283+
busHolder.inputBus1.getInventory().setStackInSlot(0, new ItemStack(Blocks.COBBLESTONE, 64));
284+
285+
GTRecipe newRecipe = OC_NON_PERFECT.applyModifier(busHolder.controller, recipeBeforeModifiers);
286+
287+
helper.assertTrue(newRecipe == null, "Applied EV overclock to HV recipe when it shouldn't have");
288+
289+
helper.succeed();
290+
}
291+
}

0 commit comments

Comments
 (0)