From 92f5d26d20e9005cb4b5779c5d697e9a17dc9e5f Mon Sep 17 00:00:00 2001 From: tildejustin Date: Sun, 3 Aug 2025 21:17:19 -0400 Subject: [PATCH 1/6] default autosave interval to ticks for glitched verification --- .../java/com/redlimerl/speedrunigt/option/SpeedRunOptions.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/redlimerl/speedrunigt/option/SpeedRunOptions.java b/src/main/java/com/redlimerl/speedrunigt/option/SpeedRunOptions.java index 0cb2464fa..834e3e018 100644 --- a/src/main/java/com/redlimerl/speedrunigt/option/SpeedRunOptions.java +++ b/src/main/java/com/redlimerl/speedrunigt/option/SpeedRunOptions.java @@ -187,7 +187,7 @@ public String valueToString(Boolean value) { }; public enum TimerSaveInterval { NONE, PAUSE, TICKS } - public static final OptionArgument TIMER_DATA_AUTO_SAVE = new OptionArgument(new Identifier(SpeedRunIGT.MOD_ID, "auto_save_interval"), TimerSaveInterval.PAUSE) { + public static final OptionArgument TIMER_DATA_AUTO_SAVE = new OptionArgument(new Identifier(SpeedRunIGT.MOD_ID, "auto_save_interval"), TimerSaveInterval.TICKS) { @Override public TimerSaveInterval valueFromString(String string) { return TimerSaveInterval.valueOf(string); From 1c40d8f4e865051861d0311d2c58fb61c0c09e09 Mon Sep 17 00:00:00 2001 From: tildejustin Date: Sun, 3 Aug 2025 22:22:58 -0400 Subject: [PATCH 2/6] refactor MaC logic, work with nether not caves b/c hasCeiling does not account for that --- .../speedrunigt/mixins/ClientWorldMixin.java | 118 ++++++++++-------- 1 file changed, 68 insertions(+), 50 deletions(-) diff --git a/src/main/java/com/redlimerl/speedrunigt/mixins/ClientWorldMixin.java b/src/main/java/com/redlimerl/speedrunigt/mixins/ClientWorldMixin.java index 4113b96f2..72974cf83 100644 --- a/src/main/java/com/redlimerl/speedrunigt/mixins/ClientWorldMixin.java +++ b/src/main/java/com/redlimerl/speedrunigt/mixins/ClientWorldMixin.java @@ -12,7 +12,7 @@ import net.minecraft.world.MutableWorldProperties; import net.minecraft.world.World; import net.minecraft.world.chunk.Chunk; -import net.minecraft.world.chunk.EmptyChunk; +import net.minecraft.world.chunk.ChunkStatus; import net.minecraft.world.dimension.DimensionType; import net.minecraft.world.gen.chunk.FlatChunkGenerator; import org.spongepowered.asm.mixin.Final; @@ -23,13 +23,11 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import java.util.Arrays; import java.util.function.Supplier; @Mixin(ClientWorld.class) public abstract class ClientWorldMixin extends World { - @Shadow - public abstract ClientWorld.Properties getLevelProperties(); - @Shadow @Final private MinecraftClient client; @@ -43,67 +41,87 @@ public void onTick(CallbackInfo ci) { InGameTimer.getInstance().tick(); } + @Unique + private final int[][] heightmapAccumulator = new int[16 * 3][16 * 3]; + @Inject(method = "updateListeners", at = @At("TAIL")) public void onBlockUpdate(BlockPos pos, BlockState oldState, BlockState newState, int flags, CallbackInfo ci) { - // TODO: doesn't support nether or overworld caves - if (this.getDimension().hasCeiling()) { + InGameTimer timer = InGameTimer.getInstance(); + if (timer.getCategory() != RunCategories.MINE_A_CHUNK) { return; } - InGameTimer timer = InGameTimer.getInstance(); - if (timer.getCategory() == RunCategories.MINE_A_CHUNK) { - int chunkX = pos.getX() >> 4; - int chunkZ = pos.getZ() >> 4; - - for (int i = -1; i < 2; ++i) { - for (int j = -1; j < 2; ++j) { - // if all the chunks aren't loaded (and chunks are given as EmptyChunks), it will break because the heightmap is reported as all 0's - if (getChunk(chunkX + i, chunkZ + j) instanceof EmptyChunk) { - return; - } + if (this.getDimensionRegistryKey() == DimensionType.THE_END_REGISTRY_KEY) { + return; + } + + int chunkX = pos.getX() >> 4; + int chunkZ = pos.getZ() >> 4; + + for (int i = -1; i < 2; ++i) { + for (int j = -1; j < 2; ++j) { + // if all the chunks aren't loaded, it will break because the heightmap is reported as all 0's + if (getChunk(chunkX + i, chunkZ + j, ChunkStatus.FULL, false) == null) { + return; } } + } - // checks for 16 x 16 squares that have blocks only at or below bedrock in the square from the chunks -1, -1 to 1, 1 relative to the chunk the block update was in - // algorithm from https://stackoverflow.com/a/17790267 - int[][] heightmapAccumulator = new int[16 * 3][16 * 3]; - - for (int x = 0; x < 16 * 3; ++x) { - for (int z = 0; z < 16 * 3; ++z) { - // convert the 0 to 47 x and z counters in to -1 to 1 chunk offsets - Chunk chunk = this.getChunk(chunkX + (x >> 4) - 1, chunkZ + (z >> 4) - 1); - int height = chunk.getHeightmap(Heightmap.Type.WORLD_SURFACE).get(mod(x, 16), mod(z, 16)); - if (height <= getBedrockMaxHeight()) { - if (x == 0 || z == 0) { - // special case for first row and column, no previous work to check - heightmapAccumulator[x][z] = 1; - continue; - } - // calculate the max value the next square is allowed to be using the bounds of the previous adjacent ones - int currentSquareLevel = Math.min(Math.min(heightmapAccumulator[x - 1][z], heightmapAccumulator[x][z - 1]), heightmapAccumulator[x - 1][z - 1]) + 1; - // if we hit 16 on the square level, we've found a large enough area - if (currentSquareLevel == 16) { - InGameTimer.complete(); - return; + // checks for 16 x 16 squares that have blocks only at or below bedrock in the square from the chunks -1, -1 to 1, 1 relative to the chunk the block update was in + // algorithm from https://stackoverflow.com/a/17790267 + for (int[] arr : heightmapAccumulator) { + Arrays.fill(arr, 0); + } + + boolean hasCeiling = this.getDimension().hasCeiling(); + int firstNonBedrockLayer = this.getFirstNonBedrockLayer(); + int lastNonBedrockLayer = this.getDimensionHeight() - 6; + + BlockPos.Mutable mutable = new BlockPos.Mutable(); + for (int x = 0; x < 16 * 3; ++x) { + for (int z = 0; z < 16 * 3; ++z) { + boolean columnClear = true; + Chunk chunk = this.getChunk(chunkX + (x >> 4) - 1, chunkZ + (z >> 4) - 1, ChunkStatus.FULL, false); + assert chunk != null; // already checked at the start + if (hasCeiling) { + // check the column manually, use mutable for less churn + // calculate world coordinates + mutable.set((chunkX << 4) - 16 + x, 0, (chunkZ << 4) - 16 + z); + for (int y = firstNonBedrockLayer; y <= lastNonBedrockLayer; y++) { + mutable.setY(y); + if (!chunk.getBlockState(mutable).isAir()) { + columnClear = false; + break; } - // otherwise, just assign the value to it's place in the matrix - heightmapAccumulator[x][z] = currentSquareLevel; - } else { - heightmapAccumulator[x][z] = 0; } + } else { + // calculate chunk coordinates + columnClear = chunk.getHeightmap(Heightmap.Type.WORLD_SURFACE).get(x & 15, z & 15) <= firstNonBedrockLayer; + } + if (columnClear) { + if (x == 0 || z == 0) { + // special case for first row and column, no previous work to check + heightmapAccumulator[x][z] = 1; + continue; + } + // calculate the max value the next square is allowed to be using the bounds of the previous adjacent ones + int currentSquareLevel = Math.min(Math.min(heightmapAccumulator[x - 1][z], heightmapAccumulator[x][z - 1]), heightmapAccumulator[x - 1][z - 1]) + 1; + // if we hit 16 on the square level, we've found a large enough area + if (currentSquareLevel == 16) { + InGameTimer.complete(); + return; + } + // otherwise, just assign the value to it's place in the matrix + heightmapAccumulator[x][z] = currentSquareLevel; + } else { + heightmapAccumulator[x][z] = 0; } } } } - // handles negative numbers correctly, like python - @Unique - private static int mod(int divisor, int dividend) { - return ((divisor % dividend) + dividend) % dividend; - } - @Unique - private int getBedrockMaxHeight() { + private int getFirstNonBedrockLayer() { if (this.client.isIntegratedServerRunning() && this.client.getServer().getWorld((this.getRegistryKey())).getChunkManager().getChunkGenerator() instanceof FlatChunkGenerator) { return 1; } @@ -127,7 +145,7 @@ private void printHeightmap(int chunkX, int chunkZ) { for (int x = 0; x < 16 * 3; ++x) { for (int z = 0; z < 16 * 3; ++z) { Chunk chunk = this.getChunk(chunkX + (x >> 4) - 1, chunkZ + (z >> 4) - 1); - int height = chunk.getHeightmap(Heightmap.Type.WORLD_SURFACE).get(mod(x, 16), mod(z, 16)); + int height = chunk.getHeightmap(Heightmap.Type.WORLD_SURFACE).get(x & 15, z & 15); System.out.printf("%02d ", height); } System.out.println(); From a8eda8d5a9148c4edcb463a95e6d087f1781819f Mon Sep 17 00:00:00 2001 From: tildejustin Date: Mon, 4 Aug 2025 03:17:20 -0400 Subject: [PATCH 3/6] fix timer not starting on /time set 0 if on first input --- .../speedrunigt/timer/packet/packets/TimerStartPacket.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/redlimerl/speedrunigt/timer/packet/packets/TimerStartPacket.java b/src/main/java/com/redlimerl/speedrunigt/timer/packet/packets/TimerStartPacket.java index 093475cdc..9cc1d6ab2 100644 --- a/src/main/java/com/redlimerl/speedrunigt/timer/packet/packets/TimerStartPacket.java +++ b/src/main/java/com/redlimerl/speedrunigt/timer/packet/packets/TimerStartPacket.java @@ -101,6 +101,7 @@ public void timerInit(TimerPacketBuf buf, boolean isIntegrated) { InGameTimer.getInstance().setStartTime(startTime); InGameTimer.getInstance().setCategory(category, false); } + InGameTimer.getInstance().setPause(false, "coop start"); InGameTimer.getInstance().setCoop(true); InGameTimer.getInstance().setServerIntegrated(isIntegrated); From 802b446216766023e0bfccdd613367633eaf00b6 Mon Sep 17 00:00:00 2001 From: tildejustin Date: Tue, 5 Aug 2025 22:53:23 -0400 Subject: [PATCH 4/6] sort of fix commands in coop /speedrunigt start false does not pause except for the host, and thus only the host can unpause and restart for everyone. there would need to be a packet for pausing to get it to work correctly, idk if you want to add that for this niche use case. --- .../speedrunigt/instance/TimerCommand.java | 2 ++ .../mixins/command/ArgumentTypesMixin.java | 24 +++++++++++++++++++ src/main/resources/speedrunigt.mixins.json | 1 + 3 files changed, 27 insertions(+) create mode 100644 src/main/java/com/redlimerl/speedrunigt/mixins/command/ArgumentTypesMixin.java diff --git a/src/main/java/com/redlimerl/speedrunigt/instance/TimerCommand.java b/src/main/java/com/redlimerl/speedrunigt/instance/TimerCommand.java index 0648826cd..aa94eef2f 100644 --- a/src/main/java/com/redlimerl/speedrunigt/instance/TimerCommand.java +++ b/src/main/java/com/redlimerl/speedrunigt/instance/TimerCommand.java @@ -107,7 +107,9 @@ private static int setVisible(ServerCommandSource source, boolean visible) { } private static int startTimer(ServerCommandSource source, RunCategory runCategory, boolean instantStart) { + boolean coop = InGameTimer.getInstance().isCoop(); InGameTimer.start(InGameTimer.getInstance().getWorldName(), RunType.OLD_WORLD); + InGameTimer.getInstance().setCoop(coop); InGameTimer.getInstance().setCategory(runCategory, true); if (instantStart) InGameTimer.getInstance().setPause(false, "instant start"); source.sendFeedback(new LiteralText("Timer is started" + (instantStart ? " instantly" : "") + " with " + runCategory.getText().getString() + " category"), true); diff --git a/src/main/java/com/redlimerl/speedrunigt/mixins/command/ArgumentTypesMixin.java b/src/main/java/com/redlimerl/speedrunigt/mixins/command/ArgumentTypesMixin.java new file mode 100644 index 000000000..cbdfdee13 --- /dev/null +++ b/src/main/java/com/redlimerl/speedrunigt/mixins/command/ArgumentTypesMixin.java @@ -0,0 +1,24 @@ +package com.redlimerl.speedrunigt.mixins.command; + +import com.mojang.brigadier.arguments.ArgumentType; +import com.redlimerl.speedrunigt.timer.category.RunCategoryArgumentType; +import net.minecraft.command.arguments.ArgumentTypes; +import net.minecraft.command.arguments.serialize.ArgumentSerializer; +import net.minecraft.command.arguments.serialize.ConstantArgumentSerializer; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(ArgumentTypes.class) +public abstract class ArgumentTypesMixin { + @Shadow + public static > void register(String id, Class class_, ArgumentSerializer argumentSerializer) { + } + + @Inject(method = "register()V", at = @At("TAIL")) + private static void registerRunCategoryArgumentType(CallbackInfo ci) { + register("speedrunigt:run_category", RunCategoryArgumentType.class, new ConstantArgumentSerializer<>(RunCategoryArgumentType::new)); + } +} diff --git a/src/main/resources/speedrunigt.mixins.json b/src/main/resources/speedrunigt.mixins.json index f5f97120b..0e17d6475 100644 --- a/src/main/resources/speedrunigt.mixins.json +++ b/src/main/resources/speedrunigt.mixins.json @@ -9,6 +9,7 @@ "ServerStatHandlerMixin", "ServerWorldMixin", "access.ServerStatHandlerAccessor", + "command.ArgumentTypesMixin", "command.CommandManagerMixin", "coop.PlayerManagerMixin", "coop.TimeCommandMixin", From 9a2d68461c5a842fccd630f16eabbb0071486565 Mon Sep 17 00:00:00 2001 From: tildejustin Date: Sun, 7 Sep 2025 14:16:20 -0400 Subject: [PATCH 5/6] mine a chunk superflat option autodetecting was not possible to do completely correctly (ow caves, etc) --- .../impl/CategoryRegistryImpl.java | 2 +- .../speedrunigt/mixins/ClientWorldMixin.java | 74 ++++++++----------- .../timer/category/RunCategories.java | 1 + .../assets/speedrunigt/lang/en_us.json | 1 + 4 files changed, 33 insertions(+), 45 deletions(-) diff --git a/src/main/java/com/redlimerl/speedrunigt/impl/CategoryRegistryImpl.java b/src/main/java/com/redlimerl/speedrunigt/impl/CategoryRegistryImpl.java index a65bc69ea..b5ceaf6d1 100644 --- a/src/main/java/com/redlimerl/speedrunigt/impl/CategoryRegistryImpl.java +++ b/src/main/java/com/redlimerl/speedrunigt/impl/CategoryRegistryImpl.java @@ -18,7 +18,7 @@ public Collection registerCategories() { list.add(KILL_ALL_BOSSES);list.add(KILL_WITHER);list.add(KILL_ELDER_GUARDIAN); list.add(HOW_DID_WE_GET_HERE);list.add(HERO_OF_VILLAGE);list.add(ARBALISTIC);list.add(COVER_ME_IN_DEBRIS); list.add(ENTER_NETHER);list.add(ENTER_END); - list.add(MINE_A_CHUNK); + list.add(MINE_A_CHUNK);list.add(MINE_A_CHUNK_SF); list.add(HIGH); list.add(ALL_SWORDS);list.add(ALL_MINERALS);list.add(FULL_IA_15_LVL);list.add(ALL_WORKSTATIONS);list.add(FULL_INV);list.add(STACK_OF_LIME_WOOL); return list; diff --git a/src/main/java/com/redlimerl/speedrunigt/mixins/ClientWorldMixin.java b/src/main/java/com/redlimerl/speedrunigt/mixins/ClientWorldMixin.java index 72974cf83..db3d926e4 100644 --- a/src/main/java/com/redlimerl/speedrunigt/mixins/ClientWorldMixin.java +++ b/src/main/java/com/redlimerl/speedrunigt/mixins/ClientWorldMixin.java @@ -2,8 +2,8 @@ import com.redlimerl.speedrunigt.timer.InGameTimer; import com.redlimerl.speedrunigt.timer.category.RunCategories; +import com.redlimerl.speedrunigt.timer.category.RunCategory; import net.minecraft.block.BlockState; -import net.minecraft.client.MinecraftClient; import net.minecraft.client.world.ClientWorld; import net.minecraft.util.math.BlockPos; import net.minecraft.util.profiler.Profiler; @@ -14,10 +14,7 @@ import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.ChunkStatus; import net.minecraft.world.dimension.DimensionType; -import net.minecraft.world.gen.chunk.FlatChunkGenerator; -import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -28,10 +25,6 @@ @Mixin(ClientWorld.class) public abstract class ClientWorldMixin extends World { - @Shadow - @Final - private MinecraftClient client; - protected ClientWorldMixin(MutableWorldProperties mutableWorldProperties, RegistryKey registryKey, RegistryKey registryKey2, DimensionType dimensionType, Supplier profiler, boolean bl, boolean bl2, long l) { super(mutableWorldProperties, registryKey, registryKey2, dimensionType, profiler, bl, bl2, l); } @@ -44,14 +37,13 @@ public void onTick(CallbackInfo ci) { @Unique private final int[][] heightmapAccumulator = new int[16 * 3][16 * 3]; + @Unique + private final BlockPos.Mutable mutable = new BlockPos.Mutable(); + @Inject(method = "updateListeners", at = @At("TAIL")) public void onBlockUpdate(BlockPos pos, BlockState oldState, BlockState newState, int flags, CallbackInfo ci) { - InGameTimer timer = InGameTimer.getInstance(); - if (timer.getCategory() != RunCategories.MINE_A_CHUNK) { - return; - } - - if (this.getDimensionRegistryKey() == DimensionType.THE_END_REGISTRY_KEY) { + RunCategory category = InGameTimer.getInstance().getCategory(); + if (category != RunCategories.MINE_A_CHUNK && category != RunCategories.MINE_A_CHUNK_SF) { return; } @@ -74,16 +66,19 @@ public void onBlockUpdate(BlockPos pos, BlockState oldState, BlockState newState } boolean hasCeiling = this.getDimension().hasCeiling(); - int firstNonBedrockLayer = this.getFirstNonBedrockLayer(); + int firstNonBedrockLayer = category == RunCategories.MINE_A_CHUNK ? 5 : (category == RunCategories.MINE_A_CHUNK_SF ? 1 : -1); + assert firstNonBedrockLayer != -1; int lastNonBedrockLayer = this.getDimensionHeight() - 6; - BlockPos.Mutable mutable = new BlockPos.Mutable(); for (int x = 0; x < 16 * 3; ++x) { for (int z = 0; z < 16 * 3; ++z) { boolean columnClear = true; Chunk chunk = this.getChunk(chunkX + (x >> 4) - 1, chunkZ + (z >> 4) - 1, ChunkStatus.FULL, false); assert chunk != null; // already checked at the start - if (hasCeiling) { + if (!hasCeiling) { + // calculate chunk coordinates + columnClear = chunk.getHeightmap(Heightmap.Type.WORLD_SURFACE).get(x & 15, z & 15) <= firstNonBedrockLayer; + } else { // check the column manually, use mutable for less churn // calculate world coordinates mutable.set((chunkX << 4) - 16 + x, 0, (chunkZ << 4) - 16 + z); @@ -94,42 +89,32 @@ public void onBlockUpdate(BlockPos pos, BlockState oldState, BlockState newState break; } } - } else { - // calculate chunk coordinates - columnClear = chunk.getHeightmap(Heightmap.Type.WORLD_SURFACE).get(x & 15, z & 15) <= firstNonBedrockLayer; } - if (columnClear) { - if (x == 0 || z == 0) { - // special case for first row and column, no previous work to check - heightmapAccumulator[x][z] = 1; - continue; - } - // calculate the max value the next square is allowed to be using the bounds of the previous adjacent ones - int currentSquareLevel = Math.min(Math.min(heightmapAccumulator[x - 1][z], heightmapAccumulator[x][z - 1]), heightmapAccumulator[x - 1][z - 1]) + 1; - // if we hit 16 on the square level, we've found a large enough area - if (currentSquareLevel == 16) { - InGameTimer.complete(); - return; - } - // otherwise, just assign the value to it's place in the matrix - heightmapAccumulator[x][z] = currentSquareLevel; - } else { + if (!columnClear) { heightmapAccumulator[x][z] = 0; + continue; + } + if (x == 0 || z == 0) { + // special case for first row and column, no previous work to check + heightmapAccumulator[x][z] = 1; + continue; } + // calculate the max value the next square is allowed to be using the bounds of the previous adjacent ones + int currentSquareLevel = Math.min(Math.min(heightmapAccumulator[x - 1][z], heightmapAccumulator[x][z - 1]), heightmapAccumulator[x - 1][z - 1]) + 1; + // if we hit 16 on the square level, we've found a large enough area + if (currentSquareLevel == 16) { + InGameTimer.complete(); + return; + } + // otherwise, just assign the value to it's place in the matrix + heightmapAccumulator[x][z] = currentSquareLevel; } } } - @Unique - private int getFirstNonBedrockLayer() { - if (this.client.isIntegratedServerRunning() && this.client.getServer().getWorld((this.getRegistryKey())).getChunkManager().getChunkGenerator() instanceof FlatChunkGenerator) { - return 1; - } - return 5; - } - // for debugging purposes @Unique + @SuppressWarnings("unused") private void printHeightmapAccumulator(int[][] heightmap) { for (int[] row : heightmap) { for (int height : row) { @@ -141,6 +126,7 @@ private void printHeightmapAccumulator(int[][] heightmap) { } @Unique + @SuppressWarnings("unused") private void printHeightmap(int chunkX, int chunkZ) { for (int x = 0; x < 16 * 3; ++x) { for (int z = 0; z < 16 * 3; ++z) { diff --git a/src/main/java/com/redlimerl/speedrunigt/timer/category/RunCategories.java b/src/main/java/com/redlimerl/speedrunigt/timer/category/RunCategories.java index e002c1471..62314d038 100644 --- a/src/main/java/com/redlimerl/speedrunigt/timer/category/RunCategories.java +++ b/src/main/java/com/redlimerl/speedrunigt/timer/category/RunCategories.java @@ -40,6 +40,7 @@ public class RunCategories { .setCanSegment(true).build(); public static AllBlocksRunCategory ALL_BLOCKS = new AllBlocksRunCategory(); public static RunCategory MINE_A_CHUNK = new RunCategory("MINE_A_CHUNK","mcce#Mine_a_Chunk"); + public static RunCategory MINE_A_CHUNK_SF = new RunCategory("MINE_A_CHUNK_SF","mc_juice#Mine_a_Chunk_Superflat"); public static void checkAllBossesCompleted() { InGameTimer timer = InGameTimer.getInstance(); diff --git a/src/main/resources/assets/speedrunigt/lang/en_us.json b/src/main/resources/assets/speedrunigt/lang/en_us.json index a4614ba36..f3df5b805 100644 --- a/src/main/resources/assets/speedrunigt/lang/en_us.json +++ b/src/main/resources/assets/speedrunigt/lang/en_us.json @@ -69,6 +69,7 @@ "speedrunigt.option.timer_category.pogloot_quater": "Quater", "speedrunigt.option.timer_category.all_portals": "All Portals", "speedrunigt.option.timer_category.mine_a_chunk": "Mine a Chunk", + "speedrunigt.option.timer_category.mine_a_chunk_sf": "Mine a Chunk Superflat", "speedrunigt.option.hide_timer_in_options": "Hide Timer in Options", "speedrunigt.option.hide_timer_in_debugs": "Hide Timer in F3", "speedrunigt.option.debug_mode": "Debug Mode", From 6e0983a4ad354298ac0a91be32c95d5d10375d09 Mon Sep 17 00:00:00 2001 From: tildejustin Date: Sun, 7 Sep 2025 14:24:23 -0400 Subject: [PATCH 6/6] temporarily remove broken portal time fix this code is supposed to enforce portal animations to contribute exactly 4.0s to igt, as a frame retime would unfortunately, it not only doesn't fulfill its intended purpose (which is sort of a blessing in disguise, because it would remove the additional delay from setting up boat eye, 3 * ticks in boat), but it applies after going through a portal, and now that people do preemptive in the portal (partially due to extra options :/) it causes a lot of verifier time to be spent fixing the timer reversion. the correct way this should be implemented is adjusting the client length of ticks in the portal to be equal to the server length of ticks in the portal, and that will be done at some point during the tick timing reform. --- .../redlimerl/speedrunigt/mixins/ClientPlayerEntityMixin.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/redlimerl/speedrunigt/mixins/ClientPlayerEntityMixin.java b/src/main/java/com/redlimerl/speedrunigt/mixins/ClientPlayerEntityMixin.java index ca21b9a54..7bb2fa4fa 100644 --- a/src/main/java/com/redlimerl/speedrunigt/mixins/ClientPlayerEntityMixin.java +++ b/src/main/java/com/redlimerl/speedrunigt/mixins/ClientPlayerEntityMixin.java @@ -191,7 +191,7 @@ private void onMove(MovementType movementType, Vec3d vec3d, CallbackInfo ci) { } } - + /* private Long latestPortalEnter = null; private int portalTick = 0; @Inject(at = @At("HEAD"), method = "tick") @@ -212,6 +212,7 @@ public void updateNausea(CallbackInfo ci) { this.portalTick = 0; } } + */ @Override public void changeLookDirection(double cursorDeltaX, double cursorDeltaY) {