aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/de
diff options
context:
space:
mode:
authorAaron <51387595+AzureAaron@users.noreply.github.com>2025-06-10 23:29:26 -0400
committerAaron <51387595+AzureAaron@users.noreply.github.com>2025-06-10 23:29:26 -0400
commit2684925f290ec3742764b3953cfcbc24cbdb90d4 (patch)
treec5cc4b73ffacee02ebb3a2f7af8edd41146d1578 /src/main/java/de
parent17e401a50114646d8009a7dab6ba69f6478a5622 (diff)
downloadSkyblocker-2684925f290ec3742764b3953cfcbc24cbdb90d4.tar.gz
Skyblocker-2684925f290ec3742764b3953cfcbc24cbdb90d4.tar.bz2
Skyblocker-2684925f290ec3742764b3953cfcbc24cbdb90d4.zip
Terracotta Puzzle Solver
Diffstat (limited to 'src/main/java/de')
-rw-r--r--src/main/java/de/hysky/skyblocker/config/categories/ForagingCategory.java9
-rw-r--r--src/main/java/de/hysky/skyblocker/config/configs/ForagingConfig.java3
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/galatea/TerracottaPuzzle.java131
-rw-r--r--src/main/java/de/hysky/skyblocker/utils/Area.java1
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;