aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/me/xmrvizzy/skyblocker/skyblock
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/me/xmrvizzy/skyblocker/skyblock')
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/CroesusHelper.java2
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/DungeonBlaze.java153
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/StarredMobGlow.java51
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/TicTacToe.java138
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/skyblock/item/CustomArmorTrims.java7
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/skyblock/quicknav/QuickNav.java4
6 files changed, 296 insertions, 59 deletions
diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/CroesusHelper.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/CroesusHelper.java
index 44c8803f..def1eb76 100644
--- a/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/CroesusHelper.java
+++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/CroesusHelper.java
@@ -25,7 +25,7 @@ public class CroesusHelper extends ContainerSolver {
List<ColorHighlight> highlights = new ArrayList<>();
for (Map.Entry<Integer, ItemStack> entry : slots.entrySet()) {
ItemStack stack = entry.getValue();
- if (stack != null && stack.getNbt() != null && stack.getNbt().toString().contains("No more Chests to open!")) {
+ if (stack != null && stack.getNbt() != null && stack.getNbt().toString().contains("Opened Chest:")) {
highlights.add(ColorHighlight.gray(entry.getKey()));
}
}
diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/DungeonBlaze.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/DungeonBlaze.java
index d0dcf1e1..c3e12c3d 100644
--- a/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/DungeonBlaze.java
+++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/DungeonBlaze.java
@@ -9,8 +9,10 @@ import me.xmrvizzy.skyblocker.utils.color.QuadColor;
import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderContext;
import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents;
import net.minecraft.client.MinecraftClient;
+import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.client.world.ClientWorld;
-import net.minecraft.entity.Entity;
+import net.minecraft.entity.decoration.ArmorStandEntity;
+import net.minecraft.predicate.entity.EntityPredicates;
import net.minecraft.util.math.Box;
import net.minecraft.util.math.Vec3d;
import org.slf4j.Logger;
@@ -20,92 +22,133 @@ import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
+/**
+ * This class provides functionality to render outlines around Blaze entities
+ */
public class DungeonBlaze {
private static final Logger LOGGER = LoggerFactory.getLogger(DungeonBlaze.class.getName());
- private static final float[] WHITE_COLOR_COMPONENTS = { 1.0f, 1.0f, 1.0f };
- static Entity highestBlaze = null;
- static Entity lowestBlaze = null;
- static Entity nextHighestBlaze = null;
- static Entity nextLowestBlaze = null;
- static boolean renderHooked = false;
-
+ private static final float[] WHITE_COLOR_COMPONENTS = {1.0f, 1.0f, 1.0f};
+ private static final QuadColor outlineColorGreen = QuadColor.single(0.0F, 1.0f, 0.0f, 1f);
+ private static final QuadColor outlineColorWhite = QuadColor.single(1.0f, 1.0f, 1.0f, 1.0f);
+
+ private static ArmorStandEntity highestBlaze = null;
+ private static ArmorStandEntity lowestBlaze = null;
+ private static ArmorStandEntity nextHighestBlaze = null;
+ private static ArmorStandEntity nextLowestBlaze = null;
+ private static boolean renderHooked = false;
+
+ /**
+ * Updates the state of Blaze entities and triggers the rendering process if necessary.
+ */
public static void update() {
ClientWorld world = MinecraftClient.getInstance().world;
- if (world == null || !Utils.isInDungeons()) return;
- if (!renderHooked){
-
+ ClientPlayerEntity player = MinecraftClient.getInstance().player;
+ if (world == null || player == null || !Utils.isInDungeons()) return;
+ if (!renderHooked) {
WorldRenderEvents.BEFORE_DEBUG_RENDER.register(DungeonBlaze::blazeRenderer);
renderHooked = true;
}
- Iterable<Entity> entities = world.getEntities();
- List<ObjectIntPair<Entity>> blazes = new ArrayList<>();
+ List<ObjectIntPair<ArmorStandEntity>> blazes = getBlazesInWorld(world, player);
+ sortBlazes(blazes);
+ updateBlazeEntities(blazes);
+ }
- for (Entity entity : entities) {
- String blazeName = entity.getName().getString();
-
+ /**
+ * Retrieves Blaze entities in the world and parses their health information.
+ *
+ * @param world The client world to search for Blaze entities.
+ * @return A list of Blaze entities and their associated health.
+ */
+ private static List<ObjectIntPair<ArmorStandEntity>> getBlazesInWorld(ClientWorld world, ClientPlayerEntity player) {
+ List<ObjectIntPair<ArmorStandEntity>> blazes = new ArrayList<>();
+ for (ArmorStandEntity blaze : world.getEntitiesByClass(ArmorStandEntity.class, player.getBoundingBox().expand(500D), EntityPredicates.NOT_MOUNTED)) {
+ String blazeName = blaze.getName().getString();
if (blazeName.contains("Blaze") && blazeName.contains("/")) {
try {
int health = Integer.parseInt(blazeName.substring(blazeName.indexOf("/") + 1, blazeName.length() - 1));
-
- blazes.add(ObjectIntPair.of(entity, health));
- } catch (NumberFormatException ex) {
- ex.printStackTrace();
+ blazes.add(ObjectIntPair.of(blaze, health));
+ } catch (NumberFormatException e) {
+ handleException(e);
}
}
}
+ return blazes;
+ }
- // Order the blazes in the list from the lowest health to the highest health
+ /**
+ * Sorts the Blaze entities based on their health values.
+ *
+ * @param blazes The list of Blaze entities to be sorted.
+ */
+ private static void sortBlazes(List<ObjectIntPair<ArmorStandEntity>> blazes) {
blazes.sort(Comparator.comparingInt(ObjectIntPair::rightInt));
+ }
- // Ensure that there are blazes in the list
+ /**
+ * Updates information about Blaze entities based on sorted list.
+ *
+ * @param blazes The sorted list of Blaze entities with associated health values.
+ */
+ private static void updateBlazeEntities(List<ObjectIntPair<ArmorStandEntity>> blazes) {
if (!blazes.isEmpty()) {
lowestBlaze = blazes.get(0).left();
-
int highestIndex = blazes.size() - 1;
highestBlaze = blazes.get(highestIndex).left();
-
- // If there's more than 1 blaze
if (blazes.size() > 1) {
- nextLowestBlaze = blazes.get(1).left();
- nextHighestBlaze = blazes.get(highestIndex - 1).left();
+ nextLowestBlaze = blazes.get(1).left();
+ nextHighestBlaze = blazes.get(highestIndex - 1).left();
}
}
-
}
+
+ /**
+ * Renders outlines for Blaze entities based on health and position.
+ *
+ * @param wrc The WorldRenderContext used for rendering.
+ */
public static void blazeRenderer(WorldRenderContext wrc) {
- QuadColor outlineColorRed = QuadColor.single( 0.0F, 1.0F, 0.0F, 1f);
- QuadColor outlineColorGreen = QuadColor.single(1.0F, 0.0F, 0.0F, 1f);
- QuadColor outlineColorWhite = QuadColor.single(1.0f, 1.0f, 1.0f, 1.0f);
-
try {
- if (highestBlaze != null && lowestBlaze != null && highestBlaze.isAlive() && lowestBlaze.isAlive() && SkyblockerConfig.get().locations.dungeons.blazesolver){
- /* Outline */
+ if (highestBlaze != null && lowestBlaze != null && highestBlaze.isAlive() && lowestBlaze.isAlive() && SkyblockerConfig.get().locations.dungeons.blazesolver) {
if (highestBlaze.getY() < 69) {
- Box blaze = highestBlaze.getBoundingBox().expand(0.3, 0.9, 0.3).offset(0, -1.1, 0);
- RenderUtils.drawBoxOutline(blaze, outlineColorRed, 5f);
-
- if (nextHighestBlaze != null && nextHighestBlaze.isAlive() && nextHighestBlaze != highestBlaze) {
- Box nextBlaze = nextHighestBlaze.getBoundingBox().expand(0.3, 0.9, 0.3).offset(0, -1.1, 0);
- RenderUtils.drawBoxOutline(nextBlaze, outlineColorWhite, 5f);
- RenderHelper.renderLinesFromPoints(wrc, new Vec3d[] { blaze.getCenter(), nextBlaze.getCenter() }, WHITE_COLOR_COMPONENTS, 1f, 5f);
- }
+ renderBlazeOutline(highestBlaze, nextHighestBlaze, wrc);
}
-
- /* Outline */
if (lowestBlaze.getY() > 69) {
- Box blaze = lowestBlaze.getBoundingBox().expand(0.3, 0.9, 0.3).offset(0, -1.1, 0);
- RenderUtils.drawBoxOutline(blaze, outlineColorRed, 5f);
-
- if (nextLowestBlaze != null && nextLowestBlaze.isAlive() && nextLowestBlaze != lowestBlaze) {
- Box nextBlaze = nextLowestBlaze.getBoundingBox().expand(0.3, 0.9, 0.3).offset(0, -1.1, 0);
- RenderUtils.drawBoxOutline(nextBlaze, outlineColorWhite, 5f);
- RenderHelper.renderLinesFromPoints(wrc, new Vec3d[] { blaze.getCenter(), nextBlaze.getCenter() }, WHITE_COLOR_COMPONENTS, 1f, 5f);
- }
+ renderBlazeOutline(lowestBlaze, nextLowestBlaze, wrc);
}
}
} catch (Exception e) {
- LOGGER.warn("[Skyblocker BlazeRenderer] " + e);
- e.printStackTrace();
+ handleException(e);
}
}
-} \ No newline at end of file
+
+ /**
+ * Renders outlines for Blaze entities and connections between them.
+ *
+ * @param blaze The Blaze entity for which to render an outline.
+ * @param nextBlaze The next Blaze entity for connection rendering.
+ * @param wrc The WorldRenderContext used for rendering.
+ */
+ private static void renderBlazeOutline(ArmorStandEntity blaze, ArmorStandEntity nextBlaze, WorldRenderContext wrc) {
+ Box blazeBox = blaze.getBoundingBox().expand(0.3, 0.9, 0.3).offset(0, -1.1, 0);
+ RenderUtils.drawBoxOutline(blazeBox, DungeonBlaze.outlineColorGreen, 5f);
+
+ if (nextBlaze != null && nextBlaze.isAlive() && nextBlaze != blaze) {
+ Box nextBlazeBox = nextBlaze.getBoundingBox().expand(0.3, 0.9, 0.3).offset(0, -1.1, 0);
+ RenderUtils.drawBoxOutline(nextBlazeBox, DungeonBlaze.outlineColorWhite, 5f);
+
+ Vec3d blazeCenter = blazeBox.getCenter();
+ Vec3d nextBlazeCenter = nextBlazeBox.getCenter();
+
+ RenderHelper.renderLinesFromPoints(wrc, new Vec3d[]{blazeCenter, nextBlazeCenter}, WHITE_COLOR_COMPONENTS, 1f, 5f);
+ }
+ }
+
+ /**
+ * Handles exceptions by logging and printing stack traces.
+ *
+ * @param e The exception to handle.
+ */
+ private static void handleException(Exception e) {
+ LOGGER.warn("[Skyblocker BlazeRenderer] Encountered an unknown exception", e);
+ }
+}
diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/StarredMobGlow.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/StarredMobGlow.java
new file mode 100644
index 00000000..b45242f9
--- /dev/null
+++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/StarredMobGlow.java
@@ -0,0 +1,51 @@
+package me.xmrvizzy.skyblocker.skyblock.dungeon;
+
+import java.util.List;
+
+import me.xmrvizzy.skyblocker.utils.Utils;
+import me.xmrvizzy.skyblocker.utils.culling.OcclusionCulling;
+import net.minecraft.entity.Entity;
+import net.minecraft.entity.decoration.ArmorStandEntity;
+import net.minecraft.entity.player.PlayerEntity;
+import net.minecraft.predicate.entity.EntityPredicates;
+import net.minecraft.util.math.Box;
+
+public class StarredMobGlow {
+
+ public static boolean shouldMobGlow(Entity entity) {
+ Box box = entity.getBoundingBox();
+
+ if (Utils.isInDungeons() && !entity.isInvisible() && OcclusionCulling.isVisible(box.minX, box.minY, box.minZ, box.maxX, box.maxY, box.maxZ)) {
+ //Minibosses
+ if (entity instanceof PlayerEntity) {
+ switch (entity.getName().getString()) {
+ case "Lost Adventurer": return true;
+ case "Shadow Assassin": return true;
+ case "Diamond Guy": return true;
+ }
+ }
+
+ //Regular Mobs
+ if (!(entity instanceof ArmorStandEntity)) {
+ Box searchBox = box.expand(0, 2, 0);
+ List<ArmorStandEntity> armorStands = entity.getWorld().getEntitiesByClass(ArmorStandEntity.class, searchBox, EntityPredicates.NOT_MOUNTED);
+
+ if (!armorStands.isEmpty() && armorStands.get(0).getName().getString().contains("✯")) return true;
+ }
+ }
+
+ return false;
+ }
+
+ public static int getGlowColor(Entity entity) {
+ if (entity instanceof PlayerEntity) {
+ switch (entity.getName().getString()) {
+ case "Lost Adventurer": return 0xfee15c;
+ case "Shadow Assassin": return 0x5b2cb2;
+ case "Diamond Guy": return 0x57c2f7;
+ }
+ }
+
+ return 0xf57738;
+ }
+}
diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/TicTacToe.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/TicTacToe.java
new file mode 100644
index 00000000..f5d55d2c
--- /dev/null
+++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/TicTacToe.java
@@ -0,0 +1,138 @@
+package me.xmrvizzy.skyblocker.skyblock.dungeon;
+
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import me.xmrvizzy.skyblocker.config.SkyblockerConfig;
+import me.xmrvizzy.skyblocker.utils.RenderUtils;
+import me.xmrvizzy.skyblocker.utils.Utils;
+import me.xmrvizzy.skyblocker.utils.color.QuadColor;
+import me.xmrvizzy.skyblocker.utils.tictactoe.TicTacToeUtils;
+import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderContext;
+import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents;
+import net.minecraft.block.Block;
+import net.minecraft.block.Blocks;
+import net.minecraft.client.MinecraftClient;
+import net.minecraft.client.network.ClientPlayerEntity;
+import net.minecraft.client.world.ClientWorld;
+import net.minecraft.entity.decoration.ItemFrameEntity;
+import net.minecraft.item.FilledMapItem;
+import net.minecraft.item.map.MapState;
+import net.minecraft.util.math.BlockPos;
+import net.minecraft.util.math.Box;
+import net.minecraft.util.math.Direction;
+
+/**
+ * Thanks to Danker for a reference implementation!
+ */
+public class TicTacToe {
+ private static final Logger LOGGER = LoggerFactory.getLogger(TicTacToe.class);
+ private static final QuadColor RED = QuadColor.single(1.0f, 0.0f, 0.0f, 1f);
+ private static Box nextBestMoveToMake = null;
+
+ public static void init() {
+ WorldRenderEvents.BEFORE_DEBUG_RENDER.register(TicTacToe::solutionRenderer);
+ }
+
+ public static void tick() {
+ MinecraftClient client = MinecraftClient.getInstance();
+ ClientWorld world = client.world;
+ ClientPlayerEntity player = client.player;
+
+ nextBestMoveToMake = null;
+
+ if (world == null || player == null || !Utils.isInDungeons()) return;
+
+ //Search within 21 blocks for item frames that contain maps
+ Box searchBox = new Box(player.getX() - 21, player.getY() - 21, player.getZ() - 21, player.getX() + 21, player.getY() + 21, player.getZ() + 21);
+ List<ItemFrameEntity> itemFramesThatHoldMaps = world.getEntitiesByClass(ItemFrameEntity.class, searchBox, ItemFrameEntity::containsMap);
+
+ try {
+ //Only attempt to solve if its the player's turn
+ if (itemFramesThatHoldMaps.size() != 9 && itemFramesThatHoldMaps.size() % 2 == 1) {
+ char[][] board = new char[3][3];
+ BlockPos leftmostRow = null;
+ int sign = 1;
+ char facing = 'X';
+
+ for (ItemFrameEntity itemFrame : itemFramesThatHoldMaps) {
+ MapState mapState = world.getMapState(FilledMapItem.getMapName(itemFrame.getMapId().getAsInt()));
+
+ if (mapState == null) continue;
+
+ int column = 0, row;
+ sign = 1;
+
+ //Find position of the item frame relative to where it is on the tic tac toe board
+ if (itemFrame.getHorizontalFacing() == Direction.SOUTH || itemFrame.getHorizontalFacing() == Direction.WEST) sign = -1;
+ BlockPos itemFramePos = BlockPos.ofFloored(itemFrame.getX(), itemFrame.getY(), itemFrame.getZ());
+
+ for (int i = 2; i >= 0; i--) {
+ int realI = i * sign;
+ BlockPos blockPos = itemFramePos;
+
+ if (itemFrame.getX() % 0.5 == 0) {
+ blockPos = itemFramePos.add(realI, 0, 0);
+ } else if (itemFrame.getZ() % 0.5 == 0) {
+ blockPos = itemFramePos.add(0, 0, realI);
+ facing = 'Z';
+ }
+
+ Block block = world.getBlockState(blockPos).getBlock();
+ if (block == Blocks.AIR || block == Blocks.STONE_BUTTON) {
+ leftmostRow = blockPos;
+ column = i;
+
+ break;
+ }
+ }
+
+ //Determine the row of the item frame
+ if (itemFrame.getY() == 72.5) {
+ row = 0;
+ } else if (itemFrame.getY() == 71.5) {
+ row = 1;
+ } else if (itemFrame.getY() == 70.5) {
+ row = 2;
+ } else {
+ continue;
+ }
+
+
+ //Get the color of the middle pixel of the map which determines whether its X or O
+ int middleColor = mapState.colors[8256] & 255;
+
+ if (middleColor == 114) {
+ board[row][column] = 'X';
+ } else if (middleColor == 33) {
+ board[row][column] = 'O';
+ }
+
+ int bestMove = TicTacToeUtils.getBestMove(board) - 1;
+
+ if (leftmostRow != null) {
+ double drawX = facing == 'X' ? leftmostRow.getX() - sign * (bestMove % 3) : leftmostRow.getX();
+ double drawY = 72 - (double) (bestMove / 3);
+ double drawZ = facing == 'Z' ? leftmostRow.getZ() - sign * (bestMove % 3) : leftmostRow.getZ();
+
+ nextBestMoveToMake = new Box(drawX, drawY, drawZ, drawX + 1, drawY + 1, drawZ + 1);
+ }
+ }
+ }
+ } catch (Exception e) {
+ LOGGER.error("[Skyblocker Tic Tac Toe] Encountered an exception while determining a tic tac toe solution!", e);
+ }
+ }
+
+ private static void solutionRenderer(WorldRenderContext context) {
+ try {
+ if (SkyblockerConfig.get().locations.dungeons.solveTicTacToe && nextBestMoveToMake != null) {
+ RenderUtils.drawBoxOutline(nextBestMoveToMake, RED, 5);
+ }
+ } catch (Exception e) {
+ LOGGER.error("[Skyblocker Tic Tac Toe] Encountered an exception while rendering the tic tac toe solution!", e);
+ }
+ }
+}
diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/item/CustomArmorTrims.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/item/CustomArmorTrims.java
index ffc3f67d..6c648da9 100644
--- a/src/main/java/me/xmrvizzy/skyblocker/skyblock/item/CustomArmorTrims.java
+++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/item/CustomArmorTrims.java
@@ -42,7 +42,10 @@ public class CustomArmorTrims {
private static void initializeTrimCache() {
ClientPlayerEntity player = MinecraftClient.getInstance().player;
- if (!trimsInitialized && player != null) {
+ if (trimsInitialized || player == null) {
+ return;
+ }
+ try {
TRIMS_CACHE.clear();
DynamicRegistryManager registryManager = player.networkHandler.getRegistryManager();
for (Identifier material : registryManager.get(RegistryKeys.TRIM_MATERIAL).getIds()) {
@@ -62,6 +65,8 @@ public class CustomArmorTrims {
LOGGER.info("[Skyblocker] Successfully cached all armor trims!");
trimsInitialized = true;
+ } catch (Exception e) {
+ LOGGER.error("[Skyblocker] Encountered an exception while caching armor trims", e);
}
}
diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/quicknav/QuickNav.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/quicknav/QuickNav.java
index 1d58435e..351cef48 100644
--- a/src/main/java/me/xmrvizzy/skyblocker/skyblock/quicknav/QuickNav.java
+++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/quicknav/QuickNav.java
@@ -18,8 +18,8 @@ public class QuickNav {
private static final String dungeonHubIconNbt = "{id:\"minecraft:player_head\",Count:1,tag:{SkullOwner:{Id:[I;1605800870,415127827,-1236127084,15358548],Properties:{textures:[{Value:\"e3RleHR1cmVzOntTS0lOOnt1cmw6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNzg5MWQ1YjI3M2ZmMGJjNTBjOTYwYjJjZDg2ZWVmMWM0MGExYjk0MDMyYWU3MWU3NTQ3NWE1NjhhODI1NzQyMSJ9fX0=\"}]}}}}";
public static void init() {
- ScreenEvents.AFTER_INIT.register((client, screen, scaledWidth, scaledHeight) -> {
- if (Utils.isOnSkyblock() && SkyblockerConfig.get().quickNav.enableQuickNav && screen instanceof HandledScreen<?>) {
+ ScreenEvents.AFTER_INIT.register((client, screen, scaledWidth, scaledHeight) -> {
+ if (Utils.isOnSkyblock() && SkyblockerConfig.get().quickNav.enableQuickNav && screen instanceof HandledScreen<?> && client.player != null && !client.player.isCreative()) {
String screenTitle = screen.getTitle().getString().trim();
List<QuickNavButton> buttons = QuickNav.init(screenTitle);
for (QuickNavButton button : buttons) Screens.getButtons(screen).add(button);