From 2c2794402c48329d340f9f1096e168c0d5ccc7b2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 19 Apr 2026 17:41:10 +0000 Subject: [PATCH 1/3] Fix flaky day/night game tests by invalidating LazyAspectVariable cache each tick Agent-Logs-Url: https://github.com/CyclopsMC/IntegratedDynamics/sessions/4de51ebd-44f2-4df8-8c53-0d0d2c2c83cd Co-authored-by: rubensworks <440384+rubensworks@users.noreply.github.com> --- .../gametest/GameTestsAspectsReadWorld.java | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/main/java/org/cyclops/integrateddynamics/gametest/GameTestsAspectsReadWorld.java b/src/main/java/org/cyclops/integrateddynamics/gametest/GameTestsAspectsReadWorld.java index 7962ff37486..875ea85d835 100644 --- a/src/main/java/org/cyclops/integrateddynamics/gametest/GameTestsAspectsReadWorld.java +++ b/src/main/java/org/cyclops/integrateddynamics/gametest/GameTestsAspectsReadWorld.java @@ -61,9 +61,9 @@ public void testAspectsReadWorldWeatherThunderFalse(GameTestHelper helper) { public void testAspectsReadWorldIsDayTrue(GameTestHelper helper) { Supplier variableSupplier = GameTestHelpersIntegratedDynamics.testReadAspectSetup(POS, helper, PartTypes.WORLD_READER, Aspects.Read.World.BOOLEAN_ISDAY); helper.succeedWhen(() -> { - helper.getLevel().registryAccess().get(WorldClocks.OVERWORLD).ifPresent(clockHolder -> - ((ServerLevel) helper.getLevel()).clockManager().setTotalTicks(clockHolder, 1000L)); - GameTestHelpersIntegratedDynamics.assertValueEqual(helper, variableSupplier.get(), ValueTypeBoolean.ValueBoolean.of(true)); + IAspectVariable variable = variableSupplier.get(); + variable.invalidate(); + GameTestHelpersIntegratedDynamics.assertValueEqual(helper, variable, ValueTypeBoolean.ValueBoolean.of(true)); }); } @@ -71,9 +71,9 @@ public void testAspectsReadWorldIsDayTrue(GameTestHelper helper) { public void testAspectsReadWorldIsDayFalse(GameTestHelper helper) { Supplier variableSupplier = GameTestHelpersIntegratedDynamics.testReadAspectSetup(POS, helper, PartTypes.WORLD_READER, Aspects.Read.World.BOOLEAN_ISDAY); helper.succeedWhen(() -> { - helper.getLevel().registryAccess().get(WorldClocks.OVERWORLD).ifPresent(clockHolder -> - ((ServerLevel) helper.getLevel()).clockManager().setTotalTicks(clockHolder, 13000L)); - GameTestHelpersIntegratedDynamics.assertValueEqual(helper, variableSupplier.get(), ValueTypeBoolean.ValueBoolean.of(false)); + IAspectVariable variable = variableSupplier.get(); + variable.invalidate(); + GameTestHelpersIntegratedDynamics.assertValueEqual(helper, variable, ValueTypeBoolean.ValueBoolean.of(false)); }); } @@ -81,9 +81,9 @@ public void testAspectsReadWorldIsDayFalse(GameTestHelper helper) { public void testAspectsReadWorldIsNightTrue(GameTestHelper helper) { Supplier variableSupplier = GameTestHelpersIntegratedDynamics.testReadAspectSetup(POS, helper, PartTypes.WORLD_READER, Aspects.Read.World.BOOLEAN_ISNIGHT); helper.succeedWhen(() -> { - helper.getLevel().registryAccess().get(WorldClocks.OVERWORLD).ifPresent(clockHolder -> - ((ServerLevel) helper.getLevel()).clockManager().setTotalTicks(clockHolder, 13000L)); - GameTestHelpersIntegratedDynamics.assertValueEqual(helper, variableSupplier.get(), ValueTypeBoolean.ValueBoolean.of(true)); + IAspectVariable variable = variableSupplier.get(); + variable.invalidate(); + GameTestHelpersIntegratedDynamics.assertValueEqual(helper, variable, ValueTypeBoolean.ValueBoolean.of(true)); }); } @@ -91,9 +91,9 @@ public void testAspectsReadWorldIsNightTrue(GameTestHelper helper) { public void testAspectsReadWorldIsNightFalse(GameTestHelper helper) { Supplier variableSupplier = GameTestHelpersIntegratedDynamics.testReadAspectSetup(POS, helper, PartTypes.WORLD_READER, Aspects.Read.World.BOOLEAN_ISNIGHT); helper.succeedWhen(() -> { - helper.getLevel().registryAccess().get(WorldClocks.OVERWORLD).ifPresent(clockHolder -> - ((ServerLevel) helper.getLevel()).clockManager().setTotalTicks(clockHolder, 1000L)); - GameTestHelpersIntegratedDynamics.assertValueEqual(helper, variableSupplier.get(), ValueTypeBoolean.ValueBoolean.of(false)); + IAspectVariable variable = variableSupplier.get(); + variable.invalidate(); + GameTestHelpersIntegratedDynamics.assertValueEqual(helper, variable, ValueTypeBoolean.ValueBoolean.of(false)); }); } From 9fcff1358bde4ad0cc4126b329c589fcff4c954c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 19 Apr 2026 18:44:09 +0000 Subject: [PATCH 2/3] Merge four day/night tests into one sequential test to eliminate clock race conditions Agent-Logs-Url: https://github.com/CyclopsMC/IntegratedDynamics/sessions/267090b8-63e7-4515-afdc-86f609ed2fdb Co-authored-by: rubensworks <440384+rubensworks@users.noreply.github.com> --- .../gametest/GameTestsAspectsReadWorld.java | 78 ++++++++++--------- 1 file changed, 41 insertions(+), 37 deletions(-) diff --git a/src/main/java/org/cyclops/integrateddynamics/gametest/GameTestsAspectsReadWorld.java b/src/main/java/org/cyclops/integrateddynamics/gametest/GameTestsAspectsReadWorld.java index 875ea85d835..06db2b14fca 100644 --- a/src/main/java/org/cyclops/integrateddynamics/gametest/GameTestsAspectsReadWorld.java +++ b/src/main/java/org/cyclops/integrateddynamics/gametest/GameTestsAspectsReadWorld.java @@ -1,6 +1,7 @@ package org.cyclops.integrateddynamics.gametest; import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; import net.minecraft.gametest.framework.GameTestHelper; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.clock.WorldClocks; @@ -10,8 +11,13 @@ import org.cyclops.cyclopscore.gametest.GameTest; import org.cyclops.cyclopscore.helper.IModHelpers; import org.cyclops.integrateddynamics.Reference; +import org.cyclops.integrateddynamics.api.part.PartPos; +import org.cyclops.integrateddynamics.api.part.PartTarget; +import org.cyclops.integrateddynamics.api.part.read.IPartStateReader; +import org.cyclops.integrateddynamics.api.part.read.IPartTypeReader; import org.cyclops.integrateddynamics.core.evaluate.variable.*; import org.cyclops.integrateddynamics.core.helper.Helpers; +import org.cyclops.integrateddynamics.core.helper.PartHelpers; import org.cyclops.integrateddynamics.core.part.PartTypes; import org.cyclops.integrateddynamics.part.aspect.Aspects; @@ -57,43 +63,41 @@ public void testAspectsReadWorldWeatherThunderFalse(GameTestHelper helper) { testReadAspect(POS, helper, PartTypes.WORLD_READER, Aspects.Read.World.BOOLEAN_WEATHER_THUNDER, ValueTypeBoolean.ValueBoolean.of(false)); } - @GameTest(template = TEMPLATE_EMPTY, environment = Reference.MOD_ID + ":time_day") - public void testAspectsReadWorldIsDayTrue(GameTestHelper helper) { - Supplier variableSupplier = GameTestHelpersIntegratedDynamics.testReadAspectSetup(POS, helper, PartTypes.WORLD_READER, Aspects.Read.World.BOOLEAN_ISDAY); - helper.succeedWhen(() -> { - IAspectVariable variable = variableSupplier.get(); - variable.invalidate(); - GameTestHelpersIntegratedDynamics.assertValueEqual(helper, variable, ValueTypeBoolean.ValueBoolean.of(true)); - }); - } - - @GameTest(template = TEMPLATE_EMPTY, environment = Reference.MOD_ID + ":time_night") - public void testAspectsReadWorldIsDayFalse(GameTestHelper helper) { - Supplier variableSupplier = GameTestHelpersIntegratedDynamics.testReadAspectSetup(POS, helper, PartTypes.WORLD_READER, Aspects.Read.World.BOOLEAN_ISDAY); - helper.succeedWhen(() -> { - IAspectVariable variable = variableSupplier.get(); - variable.invalidate(); - GameTestHelpersIntegratedDynamics.assertValueEqual(helper, variable, ValueTypeBoolean.ValueBoolean.of(false)); - }); - } - - @GameTest(template = TEMPLATE_EMPTY, environment = Reference.MOD_ID + ":time_night") - public void testAspectsReadWorldIsNightTrue(GameTestHelper helper) { - Supplier variableSupplier = GameTestHelpersIntegratedDynamics.testReadAspectSetup(POS, helper, PartTypes.WORLD_READER, Aspects.Read.World.BOOLEAN_ISNIGHT); - helper.succeedWhen(() -> { - IAspectVariable variable = variableSupplier.get(); - variable.invalidate(); - GameTestHelpersIntegratedDynamics.assertValueEqual(helper, variable, ValueTypeBoolean.ValueBoolean.of(true)); - }); - } - - @GameTest(template = TEMPLATE_EMPTY, environment = Reference.MOD_ID + ":time_day") - public void testAspectsReadWorldIsNightFalse(GameTestHelper helper) { - Supplier variableSupplier = GameTestHelpersIntegratedDynamics.testReadAspectSetup(POS, helper, PartTypes.WORLD_READER, Aspects.Read.World.BOOLEAN_ISNIGHT); - helper.succeedWhen(() -> { - IAspectVariable variable = variableSupplier.get(); - variable.invalidate(); - GameTestHelpersIntegratedDynamics.assertValueEqual(helper, variable, ValueTypeBoolean.ValueBoolean.of(false)); + @GameTest(template = TEMPLATE_EMPTY) + public void testAspectsReadWorldIsDayAndIsNight(GameTestHelper helper) { + // Day-phase cable at POS: check BOOLEAN_ISDAY=true and BOOLEAN_ISNIGHT=false at clock=1000 (day) + Supplier isDayTrueSupplier = GameTestHelpersIntegratedDynamics.testReadAspectSetup(POS, helper, PartTypes.WORLD_READER, Aspects.Read.World.BOOLEAN_ISDAY); + PartPos partPosDay = PartPos.of(helper.getLevel(), helper.absolutePos(POS), Direction.WEST); + PartHelpers.PartStateHolder dayStateHolder = PartHelpers.getPart(partPosDay); + IPartTypeReader dayPartReader = (IPartTypeReader) dayStateHolder.getPart(); + IPartStateReader dayPartState = (IPartStateReader) dayStateHolder.getState(); + Supplier isNightFalseSupplier = () -> dayPartReader.getVariable(PartTarget.fromCenter(partPosDay), dayPartState, Aspects.Read.World.BOOLEAN_ISNIGHT); + + // Night-phase cable at POS.offset(2,0,0): check BOOLEAN_ISDAY=false and BOOLEAN_ISNIGHT=true at clock=13000 (night) + // A separate cable is used so that the night-phase variables are computed fresh (no cached values from the day phase) + BlockPos posNight = POS.offset(2, 0, 0); + Supplier isDayFalseSupplier = GameTestHelpersIntegratedDynamics.testReadAspectSetup(posNight, helper, PartTypes.WORLD_READER, Aspects.Read.World.BOOLEAN_ISDAY); + PartPos partPosNight = PartPos.of(helper.getLevel(), helper.absolutePos(posNight), Direction.WEST); + PartHelpers.PartStateHolder nightStateHolder = PartHelpers.getPart(partPosNight); + IPartTypeReader nightPartReader = (IPartTypeReader) nightStateHolder.getPart(); + IPartStateReader nightPartState = (IPartStateReader) nightStateHolder.getState(); + Supplier isNightTrueSupplier = () -> nightPartReader.getVariable(PartTarget.fromCenter(partPosNight), nightPartState, Aspects.Read.World.BOOLEAN_ISNIGHT); + + // Set clock to day; after 1 tick skyDarken reflects the new value + helper.getLevel().registryAccess().get(WorldClocks.OVERWORLD).ifPresent(clockHolder -> + ((ServerLevel) helper.getLevel()).clockManager().setTotalTicks(clockHolder, 1000L)); + helper.runAfterDelay(1, () -> { + GameTestHelpersIntegratedDynamics.assertValueEqual(helper, isDayTrueSupplier.get(), ValueTypeBoolean.ValueBoolean.of(true)); + GameTestHelpersIntegratedDynamics.assertValueEqual(helper, isNightFalseSupplier.get(), ValueTypeBoolean.ValueBoolean.of(false)); + + // Set clock to night; after 1 tick skyDarken reflects the new value + helper.getLevel().registryAccess().get(WorldClocks.OVERWORLD).ifPresent(clockHolder -> + ((ServerLevel) helper.getLevel()).clockManager().setTotalTicks(clockHolder, 13000L)); + helper.runAfterDelay(1, () -> { + GameTestHelpersIntegratedDynamics.assertValueEqual(helper, isDayFalseSupplier.get(), ValueTypeBoolean.ValueBoolean.of(false)); + GameTestHelpersIntegratedDynamics.assertValueEqual(helper, isNightTrueSupplier.get(), ValueTypeBoolean.ValueBoolean.of(true)); + helper.succeed(); + }); }); } From 1ac2519d0ad28dc2254e29b5e2df15df50a4f9de Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 20 Apr 2026 14:46:27 +0000 Subject: [PATCH 3/3] Fix IsDayAndIsNight test: use getOrThrow + invalidateTickCache + updateSkyBrightness synchronously Agent-Logs-Url: https://github.com/CyclopsMC/IntegratedDynamics/sessions/8e2c5597-58bf-48a8-88e4-3c17b8865e97 Co-authored-by: rubensworks <440384+rubensworks@users.noreply.github.com> --- .../gametest/GameTestsAspectsReadWorld.java | 39 +++++++++---------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/src/main/java/org/cyclops/integrateddynamics/gametest/GameTestsAspectsReadWorld.java b/src/main/java/org/cyclops/integrateddynamics/gametest/GameTestsAspectsReadWorld.java index 06db2b14fca..b81d5b53d9c 100644 --- a/src/main/java/org/cyclops/integrateddynamics/gametest/GameTestsAspectsReadWorld.java +++ b/src/main/java/org/cyclops/integrateddynamics/gametest/GameTestsAspectsReadWorld.java @@ -65,40 +65,39 @@ public void testAspectsReadWorldWeatherThunderFalse(GameTestHelper helper) { @GameTest(template = TEMPLATE_EMPTY) public void testAspectsReadWorldIsDayAndIsNight(GameTestHelper helper) { + ServerLevel level = (ServerLevel) helper.getLevel(); + // Day-phase cable at POS: check BOOLEAN_ISDAY=true and BOOLEAN_ISNIGHT=false at clock=1000 (day) Supplier isDayTrueSupplier = GameTestHelpersIntegratedDynamics.testReadAspectSetup(POS, helper, PartTypes.WORLD_READER, Aspects.Read.World.BOOLEAN_ISDAY); - PartPos partPosDay = PartPos.of(helper.getLevel(), helper.absolutePos(POS), Direction.WEST); + PartPos partPosDay = PartPos.of(level, helper.absolutePos(POS), Direction.WEST); PartHelpers.PartStateHolder dayStateHolder = PartHelpers.getPart(partPosDay); IPartTypeReader dayPartReader = (IPartTypeReader) dayStateHolder.getPart(); IPartStateReader dayPartState = (IPartStateReader) dayStateHolder.getState(); Supplier isNightFalseSupplier = () -> dayPartReader.getVariable(PartTarget.fromCenter(partPosDay), dayPartState, Aspects.Read.World.BOOLEAN_ISNIGHT); - // Night-phase cable at POS.offset(2,0,0): check BOOLEAN_ISDAY=false and BOOLEAN_ISNIGHT=true at clock=13000 (night) - // A separate cable is used so that the night-phase variables are computed fresh (no cached values from the day phase) + // Night-phase cable at POS.offset(2,0,0): use a separate cable so LazyAspectVariable instances are fresh BlockPos posNight = POS.offset(2, 0, 0); Supplier isDayFalseSupplier = GameTestHelpersIntegratedDynamics.testReadAspectSetup(posNight, helper, PartTypes.WORLD_READER, Aspects.Read.World.BOOLEAN_ISDAY); - PartPos partPosNight = PartPos.of(helper.getLevel(), helper.absolutePos(posNight), Direction.WEST); + PartPos partPosNight = PartPos.of(level, helper.absolutePos(posNight), Direction.WEST); PartHelpers.PartStateHolder nightStateHolder = PartHelpers.getPart(partPosNight); IPartTypeReader nightPartReader = (IPartTypeReader) nightStateHolder.getPart(); IPartStateReader nightPartState = (IPartStateReader) nightStateHolder.getState(); Supplier isNightTrueSupplier = () -> nightPartReader.getVariable(PartTarget.fromCenter(partPosNight), nightPartState, Aspects.Read.World.BOOLEAN_ISNIGHT); - // Set clock to day; after 1 tick skyDarken reflects the new value - helper.getLevel().registryAccess().get(WorldClocks.OVERWORLD).ifPresent(clockHolder -> - ((ServerLevel) helper.getLevel()).clockManager().setTotalTicks(clockHolder, 1000L)); - helper.runAfterDelay(1, () -> { - GameTestHelpersIntegratedDynamics.assertValueEqual(helper, isDayTrueSupplier.get(), ValueTypeBoolean.ValueBoolean.of(true)); - GameTestHelpersIntegratedDynamics.assertValueEqual(helper, isNightFalseSupplier.get(), ValueTypeBoolean.ValueBoolean.of(false)); - - // Set clock to night; after 1 tick skyDarken reflects the new value - helper.getLevel().registryAccess().get(WorldClocks.OVERWORLD).ifPresent(clockHolder -> - ((ServerLevel) helper.getLevel()).clockManager().setTotalTicks(clockHolder, 13000L)); - helper.runAfterDelay(1, () -> { - GameTestHelpersIntegratedDynamics.assertValueEqual(helper, isDayFalseSupplier.get(), ValueTypeBoolean.ValueBoolean.of(false)); - GameTestHelpersIntegratedDynamics.assertValueEqual(helper, isNightTrueSupplier.get(), ValueTypeBoolean.ValueBoolean.of(true)); - helper.succeed(); - }); - }); + // Set clock to day and immediately sync skyDarken (no runAfterDelay needed, avoids clock race conditions) + level.clockManager().setTotalTicks(level.registryAccess().getOrThrow(WorldClocks.OVERWORLD), 1000L); + level.environmentAttributes().invalidateTickCache(); + level.updateSkyBrightness(); + GameTestHelpersIntegratedDynamics.assertValueEqual(helper, isDayTrueSupplier.get(), ValueTypeBoolean.ValueBoolean.of(true)); + GameTestHelpersIntegratedDynamics.assertValueEqual(helper, isNightFalseSupplier.get(), ValueTypeBoolean.ValueBoolean.of(false)); + + // Set clock to night and immediately sync skyDarken + level.clockManager().setTotalTicks(level.registryAccess().getOrThrow(WorldClocks.OVERWORLD), 13000L); + level.environmentAttributes().invalidateTickCache(); + level.updateSkyBrightness(); + GameTestHelpersIntegratedDynamics.assertValueEqual(helper, isDayFalseSupplier.get(), ValueTypeBoolean.ValueBoolean.of(false)); + GameTestHelpersIntegratedDynamics.assertValueEqual(helper, isNightTrueSupplier.get(), ValueTypeBoolean.ValueBoolean.of(true)); + helper.succeed(); } @GameTest(template = TEMPLATE_EMPTY, environment = Reference.MOD_ID + ":weather_clear2")