diff options
| author | Aaron <51387595+AzureAaron@users.noreply.github.com> | 2025-06-10 23:29:26 -0400 |
|---|---|---|
| committer | Aaron <51387595+AzureAaron@users.noreply.github.com> | 2025-06-10 23:29:26 -0400 |
| commit | 2684925f290ec3742764b3953cfcbc24cbdb90d4 (patch) | |
| tree | c5cc4b73ffacee02ebb3a2f7af8edd41146d1578 /src/main/java/de | |
| parent | 17e401a50114646d8009a7dab6ba69f6478a5622 (diff) | |
| download | Skyblocker-2684925f290ec3742764b3953cfcbc24cbdb90d4.tar.gz Skyblocker-2684925f290ec3742764b3953cfcbc24cbdb90d4.tar.bz2 Skyblocker-2684925f290ec3742764b3953cfcbc24cbdb90d4.zip | |
Terracotta Puzzle Solver
Diffstat (limited to 'src/main/java/de')
4 files changed, 144 insertions, 0 deletions
diff --git a/src/main/java/de/hysky/skyblocker/config/categories/ForagingCategory.java b/src/main/java/de/hysky/skyblocker/config/categories/ForagingCategory.java index 81e64ea4..1441256e 100644 --- a/src/main/java/de/hysky/skyblocker/config/categories/ForagingCategory.java +++ b/src/main/java/de/hysky/skyblocker/config/categories/ForagingCategory.java @@ -4,6 +4,7 @@ import de.hysky.skyblocker.config.ConfigUtils; import de.hysky.skyblocker.config.SkyblockerConfig; import dev.isxander.yacl3.api.ConfigCategory; import dev.isxander.yacl3.api.Option; +import dev.isxander.yacl3.api.OptionDescription; import dev.isxander.yacl3.api.OptionGroup; import net.minecraft.text.Text; @@ -25,6 +26,14 @@ public class ForagingCategory { newValue -> config.foraging.galatea.enableForestNodeHelper = newValue) .controller(ConfigUtils::createBooleanController) .build()) + .option(Option.<Boolean>createBuilder() + .name(Text.translatable("skyblocker.config.foraging.galatea.solveForestTemplePuzzle")) + .description(OptionDescription.of(Text.translatable("skyblocker.config.foraging.galatea.solveForestTemplePuzzle.@Tooltip"))) + .binding(defaults.foraging.galatea.solveForestTemplePuzzle, + () -> config.foraging.galatea.solveForestTemplePuzzle, + newValue -> config.foraging.galatea.solveForestTemplePuzzle = newValue) + .controller(ConfigUtils::createBooleanController) + .build()) .build()) //Hunting - YACL doesn't like empty option groups diff --git a/src/main/java/de/hysky/skyblocker/config/configs/ForagingConfig.java b/src/main/java/de/hysky/skyblocker/config/configs/ForagingConfig.java index aa4dcc6d..1f81b795 100644 --- a/src/main/java/de/hysky/skyblocker/config/configs/ForagingConfig.java +++ b/src/main/java/de/hysky/skyblocker/config/configs/ForagingConfig.java @@ -13,6 +13,9 @@ public class ForagingConfig { public static class Galatea { @SerialEntry public boolean enableForestNodeHelper = true; + + @SerialEntry + public boolean solveForestTemplePuzzle = true; } public static class Hunting { diff --git a/src/main/java/de/hysky/skyblocker/skyblock/galatea/TerracottaPuzzle.java b/src/main/java/de/hysky/skyblocker/skyblock/galatea/TerracottaPuzzle.java new file mode 100644 index 00000000..ef84f452 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/skyblock/galatea/TerracottaPuzzle.java @@ -0,0 +1,131 @@ +package de.hysky.skyblocker.skyblock.galatea; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import de.hysky.skyblocker.annotations.Init; +import de.hysky.skyblocker.config.SkyblockerConfigManager; +import de.hysky.skyblocker.utils.Area; +import de.hysky.skyblocker.utils.Utils; +import de.hysky.skyblocker.utils.render.RenderHelper; +import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderContext; +import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.client.MinecraftClient; +import net.minecraft.state.property.Properties; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; +import net.minecraft.util.math.Vec3d; + +public class TerracottaPuzzle { + private static final MinecraftClient CLIENT = MinecraftClient.getInstance(); + private static final BlockPos WALL_TOP_LEFT = new BlockPos(-633, 66, 85); + private static final BlockPos WALL_BOTTOM_RIGHT = new BlockPos(-640, 65, 85); + private static final BlockPos FLOOR_TOP_LEFT = new BlockPos(-633, 59, 76); + private static final BlockPos FLOOR_BOTTOM_LEFT = new BlockPos(-633, 59, 75); + /** + * Mappings of the direction of the terracotta blocks on the wall to the ones on the floor. + */ + private static final Map<Direction, Direction> DIRECTION_MAPPINGS = Map.ofEntries( + Map.entry(Direction.NORTH, Direction.WEST), + Map.entry(Direction.EAST, Direction.SOUTH), + Map.entry(Direction.SOUTH, Direction.EAST), + Map.entry(Direction.WEST, Direction.NORTH) + ); + + @Init + public static void init() { + WorldRenderEvents.AFTER_TRANSLUCENT.register(TerracottaPuzzle::render); + } + + /** + * Calculates the direction of each terracotta block on the wall. + */ + private static List<Direction> solve() { + if (CLIENT.world == null) return List.of(); + //Two row layout where the top indices are even and the bottom indices are odd + //For example, index 0 is the top left block, 1 is the bottom left, and so on... + List<Direction> solutions = new ArrayList<>(); + + for (int x = WALL_TOP_LEFT.getX(); x >= WALL_BOTTOM_RIGHT.getX(); x--) { + for (int y = WALL_TOP_LEFT.getY(); y >= WALL_BOTTOM_RIGHT.getY(); y--) { + //The Z is same for top & bottom + BlockPos pos = new BlockPos(x, y, WALL_TOP_LEFT.getZ()); + BlockState state = CLIENT.world.getBlockState(pos); + + //This should be the case but we'll be extra safe + if (!state.isOf(Blocks.ORANGE_GLAZED_TERRACOTTA) || !state.contains(Properties.HORIZONTAL_FACING)) continue; + + Direction facing = state.get(Properties.HORIZONTAL_FACING); + + solutions.add(DIRECTION_MAPPINGS.get(facing)); + } + } + + return solutions; + } + + private static void render(WorldRenderContext context) { + if (!SkyblockerConfigManager.get().foraging.galatea.solveForestTemplePuzzle || !Utils.isInGalatea() || Utils.getArea() != Area.FOREST_TEMPLE || CLIENT.world == null) return; + + List<Direction> solutions = solve(); + + for (int i = 0; i < solutions.size(); i++) { + Direction correctDirection = solutions.get(i); + BlockPos pos = getFloorBlock(i); + BlockState state = CLIENT.world.getBlockState(pos); + + //This should be the case but we'll be extra safe + if (!state.isOf(Blocks.ORANGE_GLAZED_TERRACOTTA) || !state.contains(Properties.HORIZONTAL_FACING)) continue; + + Direction floorDirection = state.get(Properties.HORIZONTAL_FACING); + + //Simulate rotating either way to find the most efficient path + int clockwiseRotations = 0; + Direction lastClockwiseRotation = floorDirection; + int counterclockwiseRotations = 0; + Direction lastCounterclockwiseRotation = floorDirection; + + //How many rotations are needed to solve this block + int rotationsNeeded = 0; + + for (int j = 0; j < 4; j++) { + if (floorDirection == correctDirection) break; + + clockwiseRotations++; + lastClockwiseRotation = lastClockwiseRotation.rotateYClockwise(); + + if (lastClockwiseRotation == correctDirection) { + rotationsNeeded = clockwiseRotations; + break; + } + + counterclockwiseRotations++; + lastCounterclockwiseRotation = lastCounterclockwiseRotation.rotateYCounterclockwise(); + + if (lastCounterclockwiseRotation == correctDirection) { + //Invert counterclockwise rotations since you perform them by left clicking (I imagine most will rotate the blocks with right click) + rotationsNeeded = -counterclockwiseRotations; + break; + } + } + + //If the block needs to be rotated + if (clockwiseRotations != 0) { + RenderHelper.renderText(context, Text.literal(String.valueOf(rotationsNeeded)).formatted(Formatting.DARK_BLUE), Vec3d.ofCenter(pos).add(0, 1, 0), false); + } + } + } + + private static BlockPos getFloorBlock(int index) { + //Find how much the index is offset from the start of the row + int rowIndex = index / 2; + + //If the index is even we're on the top row, odd if bottom row + return index % 2 == 0 ? FLOOR_TOP_LEFT.add(-rowIndex, 0, 0) : FLOOR_BOTTOM_LEFT.add(-rowIndex, 0, 0); + } +} diff --git a/src/main/java/de/hysky/skyblocker/utils/Area.java b/src/main/java/de/hysky/skyblocker/utils/Area.java index c5a62e1d..0ed0b490 100644 --- a/src/main/java/de/hysky/skyblocker/utils/Area.java +++ b/src/main/java/de/hysky/skyblocker/utils/Area.java @@ -8,6 +8,7 @@ import java.util.Arrays; public enum Area { CARNIVAL("Carnival"), CHATEAU("Stillgore Château"), + FOREST_TEMPLE("Forest Temple"), UNKNOWN("Unknown"); private final String name; |
