diff options
Diffstat (limited to 'src/main/java/de')
17 files changed, 211 insertions, 94 deletions
diff --git a/src/main/java/de/hysky/skyblocker/SkyblockerMod.java b/src/main/java/de/hysky/skyblocker/SkyblockerMod.java index 9d5f2b0f..ad7d4350 100644 --- a/src/main/java/de/hysky/skyblocker/SkyblockerMod.java +++ b/src/main/java/de/hysky/skyblocker/SkyblockerMod.java @@ -203,7 +203,6 @@ public class SkyblockerMod implements ClientModInitializer { Scheduler.INSTANCE.scheduleCyclic(Utils::update, 20); Scheduler.INSTANCE.scheduleCyclic(DiscordRPCManager::updateDataAndPresence, 200); - Scheduler.INSTANCE.scheduleCyclic(LividColor::update, 10); Scheduler.INSTANCE.scheduleCyclic(BackpackPreview::tick, 50); Scheduler.INSTANCE.scheduleCyclic(DwarvenHud::update, 40); Scheduler.INSTANCE.scheduleCyclic(CrystalsHud::update, 40); diff --git a/src/main/java/de/hysky/skyblocker/compatibility/emi/SkyblockerEMIPlugin.java b/src/main/java/de/hysky/skyblocker/compatibility/emi/SkyblockerEMIPlugin.java index c02300ec..9d5a2a46 100644 --- a/src/main/java/de/hysky/skyblocker/compatibility/emi/SkyblockerEMIPlugin.java +++ b/src/main/java/de/hysky/skyblocker/compatibility/emi/SkyblockerEMIPlugin.java @@ -24,7 +24,7 @@ public class SkyblockerEMIPlugin implements EmiPlugin { public void register(EmiRegistry registry) { ItemRepository.getItemsStream().map(EmiStack::of).forEach(emiStack -> { registry.addEmiStack(emiStack); - registry.setDefaultComparison(emiStack, Comparison.compareNbt()); + registry.setDefaultComparison(emiStack, Comparison.compareComponents()); }); registry.addCategory(SKYBLOCK); registry.addWorkstation(SKYBLOCK, EmiStack.of(Items.CRAFTING_TABLE)); diff --git a/src/main/java/de/hysky/skyblocker/config/categories/DungeonsCategory.java b/src/main/java/de/hysky/skyblocker/config/categories/DungeonsCategory.java index 017e9186..3365cf4e 100644 --- a/src/main/java/de/hysky/skyblocker/config/categories/DungeonsCategory.java +++ b/src/main/java/de/hysky/skyblocker/config/categories/DungeonsCategory.java @@ -202,6 +202,14 @@ public class DungeonsCategory { .name(Text.translatable("skyblocker.config.dungeons.livid")) .collapsed(true) .option(Option.<Boolean>createBuilder() + .name(Text.translatable("skyblocker.config.dungeons.livid.enableSolidColor")) + .description(OptionDescription.of(Text.translatable("skyblocker.config.dungeons.livid.enableSolidColor.@Tooltip"))) + .binding(defaults.dungeons.livid.enableSolidColor, + () -> config.dungeons.livid.enableSolidColor, + newValue -> config.dungeons.livid.enableSolidColor = newValue) + .controller(ConfigUtils::createBooleanController) + .build()) + .option(Option.<Boolean>createBuilder() .name(Text.translatable("skyblocker.config.dungeons.livid.enableLividColorGlow")) .description(OptionDescription.of(Text.translatable("skyblocker.config.dungeons.livid.enableLividColorGlow.@Tooltip"))) .binding(defaults.dungeons.livid.enableLividColorGlow, @@ -210,6 +218,14 @@ public class DungeonsCategory { .controller(ConfigUtils::createBooleanController) .build()) .option(Option.<Boolean>createBuilder() + .name(Text.translatable("skyblocker.config.dungeons.livid.enableLividColorBoundingBox")) + .description(OptionDescription.of(Text.translatable("skyblocker.config.dungeons.livid.enableLividColorBoundingBox.@Tooltip"))) + .binding(defaults.dungeons.livid.enableLividColorBoundingBox, + () -> config.dungeons.livid.enableLividColorBoundingBox, + newValue -> config.dungeons.livid.enableLividColorBoundingBox = newValue) + .controller(ConfigUtils::createBooleanController) + .build()) + .option(Option.<Boolean>createBuilder() .name(Text.translatable("skyblocker.config.dungeons.livid.enableLividColorText")) .description(OptionDescription.of(Text.translatable("skyblocker.config.dungeons.livid.enableLividColorText.@Tooltip"))) .binding(defaults.dungeons.livid.enableLividColorText, diff --git a/src/main/java/de/hysky/skyblocker/config/configs/DungeonsConfig.java b/src/main/java/de/hysky/skyblocker/config/configs/DungeonsConfig.java index 1a0cad9d..6a622ae6 100644 --- a/src/main/java/de/hysky/skyblocker/config/configs/DungeonsConfig.java +++ b/src/main/java/de/hysky/skyblocker/config/configs/DungeonsConfig.java @@ -112,7 +112,13 @@ public class DungeonsConfig { public static class Livid { @SerialEntry - public boolean enableLividColorGlow = true; + public boolean enableSolidColor = false; + + @SerialEntry + public boolean enableLividColorGlow = false; + + @SerialEntry + public boolean enableLividColorBoundingBox = true; @SerialEntry public boolean enableLividColorText = true; diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/LividColor.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/LividColor.java index 42810b60..b6a035aa 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/LividColor.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/LividColor.java @@ -1,23 +1,24 @@ package de.hysky.skyblocker.skyblock.dungeon; -import de.hysky.skyblocker.config.SkyblockerConfig; import de.hysky.skyblocker.config.SkyblockerConfigManager; import de.hysky.skyblocker.config.configs.DungeonsConfig; import de.hysky.skyblocker.skyblock.dungeon.secrets.DungeonManager; import de.hysky.skyblocker.utils.Constants; import de.hysky.skyblocker.utils.Utils; import de.hysky.skyblocker.utils.scheduler.MessageScheduler; -import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents; +import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents; +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.entity.effect.StatusEffects; import net.minecraft.registry.Registries; import net.minecraft.text.MutableText; import net.minecraft.util.Formatting; import net.minecraft.util.math.BlockPos; import java.util.Map; -import java.util.Set; public class LividColor { private static final Map<Block, Formatting> WOOL_TO_FORMATTING = Map.of( @@ -42,39 +43,55 @@ public class LividColor { "Doctor Livid", Formatting.GRAY, "Vendetta Livid", Formatting.WHITE ); - public static final Set<String> LIVID_NAMES = Set.copyOf(LIVID_TO_FORMATTING.keySet()); public static final DungeonsConfig.Livid CONFIG = SkyblockerConfigManager.get().dungeons.livid; - private static int tenTicks = 0; - private static Formatting color; + private static Formatting color = Formatting.AQUA; + private static Block lastColor = Blocks.AIR; + + private static boolean isInitialized = false; + /** + * The correct livid may change color in M5, so we use the entity id to track the correct original livid. + */ + private static boolean correctLividIdFound = false; + private static int correctLividId = 0; + private static final long OFFSET_DURATION = 2000; + private static long toggleTime = 0; public static void init() { - ClientReceiveMessageEvents.GAME.register((message, overlay) -> { - DungeonsConfig.Livid config = SkyblockerConfigManager.get().dungeons.livid; - if ((config.enableLividColorText || config.enableLividColorTitle || config.enableLividColorGlow) && message.getString().equals("[BOSS] Livid: I respect you for making it to here, but I'll be your undoing.")) { - tenTicks = 8; - } - }); + ClientPlayConnectionEvents.JOIN.register((handler, sender, client) -> LividColor.reset()); + WorldRenderEvents.AFTER_ENTITIES.register(LividColor::update); } - public static void update() { + private static void update(WorldRenderContext context) { + DungeonsConfig.Livid config = SkyblockerConfigManager.get().dungeons.livid; + if (!(config.enableLividColorText || config.enableLividColorTitle || config.enableLividColorGlow || config.enableLividColorBoundingBox)) return; + MinecraftClient client = MinecraftClient.getInstance(); - if (tenTicks != 0) { - DungeonsConfig.Livid config = SkyblockerConfigManager.get().dungeons.livid; - if ((config.enableLividColorText || config.enableLividColorTitle || config.enableLividColorGlow) && Utils.isInDungeons() && client.world != null) { - if (tenTicks == 1) { - onLividColorFound(client, Blocks.RED_WOOL); - return; - } - Block color = client.world.getBlockState(new BlockPos(5, 110, 42)).getBlock(); - if (WOOL_TO_FORMATTING.containsKey(color) && !color.equals(Blocks.RED_WOOL)) { - onLividColorFound(client, color); - return; - } - tenTicks--; - } else { - tenTicks = 0; + + if (!(Utils.isInDungeons() && DungeonManager.isInBoss() && client.player != null && client.world != null)) return; + + Block currentColor = client.world.getBlockState(new BlockPos(5, 110, 42)).getBlock(); + if (!(WOOL_TO_FORMATTING.containsKey(currentColor) && !currentColor.equals(lastColor))) return; + + if (!isInitialized && client.player.hasStatusEffect(StatusEffects.BLINDNESS)) { + toggleTime = System.currentTimeMillis(); + isInitialized = true; + } else if (isInitialized && System.currentTimeMillis() - toggleTime >= OFFSET_DURATION) { + onLividColorFound(client, currentColor); + if (!correctLividIdFound) { + String lividName = LIVID_TO_FORMATTING.entrySet().stream() + .filter(entry -> entry.getValue() == color) + .map(Map.Entry::getKey) + .findFirst() + .orElse("unknown"); + client.world.getPlayers().stream() + .filter(entity -> entity.getName().getString().equals(lividName)) + .findFirst() + .ifPresent(entity -> correctLividId = entity.getId()); + correctLividIdFound = true; } + lastColor = currentColor; } + } private static void onLividColorFound(MinecraftClient client, Block color) { @@ -91,7 +108,6 @@ public class LividColor { client.inGameHud.setDefaultTitleFade(); client.inGameHud.setTitle(message); } - tenTicks = 0; } public static boolean allowGlow() { @@ -102,8 +118,27 @@ public class LividColor { return SkyblockerConfigManager.get().dungeons.livid.enableLividColorGlow && color == LIVID_TO_FORMATTING.get(name); } + public static boolean shouldDrawBoundingBox(String name) { + return SkyblockerConfigManager.get().dungeons.livid.enableLividColorBoundingBox && color == LIVID_TO_FORMATTING.get(name); + } + @SuppressWarnings("DataFlowIssue") public static int getGlowColor(String name) { - return LIVID_TO_FORMATTING.containsKey(name) ? LIVID_TO_FORMATTING.get(name).getColorValue() : Formatting.WHITE.getColorValue(); + if (SkyblockerConfigManager.get().dungeons.livid.enableSolidColor) return Formatting.RED.getColorValue(); + if (LIVID_TO_FORMATTING.containsKey(name)) return LIVID_TO_FORMATTING.get(name).getColorValue(); + return Formatting.WHITE.getColorValue(); + } + + public static int getCorrectLividId() { + return correctLividId; + } + + private static void reset() { + lastColor = Blocks.AIR; + toggleTime = 0; + isInitialized = false; + correctLividIdFound = false; + correctLividId = 0; + color = Formatting.AQUA; } } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/device/SimonSays.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/device/SimonSays.java index 5aa97dd9..eeb6608f 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/device/SimonSays.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/device/SimonSays.java @@ -5,7 +5,6 @@ import java.util.Objects; import de.hysky.skyblocker.config.SkyblockerConfigManager; import de.hysky.skyblocker.skyblock.dungeon.DungeonBoss; import de.hysky.skyblocker.skyblock.dungeon.secrets.DungeonManager; -import de.hysky.skyblocker.utils.Boxes; import de.hysky.skyblocker.utils.ColorUtils; import de.hysky.skyblocker.utils.Utils; import de.hysky.skyblocker.utils.render.RenderHelper; @@ -101,7 +100,7 @@ public class SimonSays { Box outline = RenderHelper.getBlockBoundingBox(world, state, buttonPos); float[] colour = buttonsRendered == 0 ? GREEN : YELLOW; - RenderHelper.renderFilled(context, Boxes.getMinVec(outline), Boxes.getLengthVec(outline), colour, 0.5f, true); + RenderHelper.renderFilled(context, outline, colour, 0.5f, true); RenderHelper.renderOutline(context, outline, colour, 5f, true); if (++buttonsRendered == 2) return; diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/ThreeWeirdos.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/ThreeWeirdos.java index 98d32c68..d703acb6 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/ThreeWeirdos.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/ThreeWeirdos.java @@ -8,6 +8,7 @@ import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents; import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderContext; import net.fabricmc.fabric.api.event.player.UseBlockCallback; import net.minecraft.client.MinecraftClient; +import net.minecraft.client.world.ClientWorld; import net.minecraft.entity.decoration.ArmorStandEntity; import net.minecraft.text.Text; import net.minecraft.util.ActionResult; @@ -15,7 +16,6 @@ import net.minecraft.util.Formatting; import net.minecraft.util.hit.HitResult; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Box; -import net.minecraft.world.World; import java.util.List; import java.util.regex.Matcher; @@ -25,11 +25,12 @@ public class ThreeWeirdos extends DungeonPuzzle { protected static final Pattern PATTERN = Pattern.compile("^\\[NPC] ([A-Z][a-z]+): (?:The reward is(?: not in my chest!|n't in any of our chests\\.)|My chest (?:doesn't have the reward\\. We are all telling the truth\\.|has the reward and I'm telling the truth!)|At least one of them is lying, and the reward is not in [A-Z][a-z]+'s chest!|Both of them are telling the truth\\. Also, [A-Z][a-z]+ has the reward in their chest!)$"); private static final float[] GREEN_COLOR_COMPONENTS = new float[]{0, 1, 0}; private static BlockPos pos; + static Box boundingBox; private ThreeWeirdos() { super("three-weirdos", "three-chests"); ClientReceiveMessageEvents.GAME.register((message, overlay) -> { - World world = MinecraftClient.getInstance().world; + ClientWorld world = MinecraftClient.getInstance().world; if (overlay || !shouldSolve() || !SkyblockerConfigManager.get().dungeons.puzzleSolvers.solveThreeWeirdos || world == null || !DungeonManager.isCurrentRoomMatched()) return; @SuppressWarnings("DataFlowIssue") @@ -54,7 +55,7 @@ public class ThreeWeirdos extends DungeonPuzzle { new ThreeWeirdos(); } - private void checkForNPC(World world, Room room, BlockPos relative, String name) { + private void checkForNPC(ClientWorld world, Room room, BlockPos relative, String name) { BlockPos npcPos = room.relativeToActual(relative); List<ArmorStandEntity> npcs = world.getEntitiesByClass( ArmorStandEntity.class, @@ -63,6 +64,7 @@ public class ThreeWeirdos extends DungeonPuzzle { ); if (!npcs.isEmpty()) { pos = room.relativeToActual(relative.add(1, 0, 0)); + boundingBox = RenderHelper.getBlockBoundingBox(world, pos); npcs.forEach(entity -> entity.setCustomName(Text.literal(name).formatted(Formatting.GREEN))); } } @@ -72,8 +74,8 @@ public class ThreeWeirdos extends DungeonPuzzle { @Override public void render(WorldRenderContext context) { - if (shouldSolve() && pos != null) { - RenderHelper.renderFilled(context, pos, GREEN_COLOR_COMPONENTS, 0.5f, true); + if (shouldSolve() && boundingBox != null) { + RenderHelper.renderFilled(context, boundingBox, GREEN_COLOR_COMPONENTS, 0.5f, false); } } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/TicTacToe.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/TicTacToe.java index 5a497c19..9e9d20f6 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/TicTacToe.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/TicTacToe.java @@ -23,6 +23,7 @@ import java.util.List; public class TicTacToe extends DungeonPuzzle { private static final Logger LOGGER = LoggerFactory.getLogger(TicTacToe.class); private static final float[] RED_COLOR_COMPONENTS = { 1.0F, 0.0F, 0.0F }; + private static final float[] GREEN_COLOR_COMPONENTS = { 0.0F, 1.0F, 0.0F }; @SuppressWarnings("unused") private static final TicTacToe INSTANCE = new TicTacToe(); private static Box nextBestMoveToMake = null; @@ -101,7 +102,7 @@ public class TicTacToe extends DungeonPuzzle { double nextZ = 17 - bestMove.column(); BlockPos nextPos = DungeonManager.getCurrentRoom().relativeToActual(BlockPos.ofFloored(nextX, nextY, nextZ)); - nextBestMoveToMake = new Box(nextPos); + nextBestMoveToMake = RenderHelper.getBlockBoundingBox(client.world, nextPos); } } catch (Exception e) { LOGGER.error("[Skyblocker Tic Tac Toe] Encountered an exception while determining a tic tac toe solution!", e); @@ -112,7 +113,7 @@ public class TicTacToe extends DungeonPuzzle { public void render(WorldRenderContext context) { try { if (SkyblockerConfigManager.get().dungeons.puzzleSolvers.solveTicTacToe && nextBestMoveToMake != null) { - RenderHelper.renderOutline(context, nextBestMoveToMake, RED_COLOR_COMPONENTS, 5, false); + RenderHelper.renderFilled(context, nextBestMoveToMake, GREEN_COLOR_COMPONENTS, 0.5f, false); } } 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/de/hysky/skyblocker/skyblock/dungeon/puzzle/boulder/Boulder.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/boulder/Boulder.java index aef9109f..2b61940b 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/boulder/Boulder.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/boulder/Boulder.java @@ -9,7 +9,6 @@ import de.hysky.skyblocker.utils.render.RenderHelper; import de.hysky.skyblocker.utils.render.title.Title; import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderContext; import net.minecraft.block.Block; -import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; import net.minecraft.client.MinecraftClient; import net.minecraft.client.world.ClientWorld; @@ -18,7 +17,6 @@ import net.minecraft.util.Formatting; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Box; import net.minecraft.util.math.Vec3d; -import net.minecraft.world.BlockView; import java.util.Arrays; import java.util.List; @@ -106,7 +104,7 @@ public class Boulder extends DungeonPuzzle { button = checkForButtonBlocksOnLine(client.world, point1, point2); if (button != null) { // If a button is found, calculate its bounding box - boundingBox = getBlockBoundingBox(client.world, button); + boundingBox = RenderHelper.getBlockBoundingBox(client.world, button); break; } } @@ -179,18 +177,6 @@ public class Boulder extends DungeonPuzzle { return null; } - /** - * Retrieves the bounding box of a block in the world. - * - * @param world The client world. - * @param pos The position of the block. - * @return The bounding box of the block. - */ - public static Box getBlockBoundingBox(BlockView world, BlockPos pos) { - BlockState blockState = world.getBlockState(pos); - return blockState.getOutlineShape(world, pos).getBoundingBox().offset(pos); - } - @Override public void render(WorldRenderContext context) { if (!shouldSolve() || !SkyblockerConfigManager.get().dungeons.puzzleSolvers.solveBoulder || !DungeonManager.isCurrentRoomMatched()) diff --git a/src/main/java/de/hysky/skyblocker/skyblock/entity/MobBoundingBoxes.java b/src/main/java/de/hysky/skyblocker/skyblock/entity/MobBoundingBoxes.java index 095c5d10..f005fc06 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/entity/MobBoundingBoxes.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/entity/MobBoundingBoxes.java @@ -1,6 +1,7 @@ package de.hysky.skyblocker.skyblock.entity; import de.hysky.skyblocker.config.SkyblockerConfigManager; +import de.hysky.skyblocker.skyblock.dungeon.LividColor; import de.hysky.skyblocker.utils.Utils; import de.hysky.skyblocker.utils.render.FrustumUtils; import de.hysky.skyblocker.utils.render.RenderHelper; @@ -31,6 +32,7 @@ public class MobBoundingBoxes { return switch (entity) { case PlayerEntity _p when name.equals("Lost Adventurer") || name.equals("Shadow Assassin") || name.equals("Diamond Guy") -> SkyblockerConfigManager.get().dungeons.starredMobBoundingBoxes; + case PlayerEntity p when entity.getId() == LividColor.getCorrectLividId() -> LividColor.shouldDrawBoundingBox(name); case ArmorStandEntity _armorStand -> false; // Regular Mobs diff --git a/src/main/java/de/hysky/skyblocker/skyblock/entity/MobGlow.java b/src/main/java/de/hysky/skyblocker/skyblock/entity/MobGlow.java index 81e328ca..0438a8ce 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/entity/MobGlow.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/entity/MobGlow.java @@ -1,5 +1,6 @@ package de.hysky.skyblocker.skyblock.entity; +import com.google.common.collect.Streams; import de.hysky.skyblocker.config.SkyblockerConfigManager; import de.hysky.skyblocker.skyblock.crimson.dojo.DojoManager; import de.hysky.skyblocker.skyblock.dungeon.LividColor; @@ -14,7 +15,6 @@ import net.minecraft.entity.mob.EndermanEntity; import net.minecraft.entity.mob.ZombieEntity; import net.minecraft.entity.passive.BatEntity; import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.ItemStack; import net.minecraft.predicate.entity.EntityPredicates; import net.minecraft.util.Formatting; import net.minecraft.util.math.Box; @@ -23,6 +23,10 @@ import net.minecraft.world.World; import java.util.List; public class MobGlow { + /** + * The Nukekubi head texture id is eb07594e2df273921a77c101d0bfdfa1115abed5b9b2029eb496ceba9bdbb4b3. + */ + public static final String NUKEKUBI_HEAD_TEXTURE = "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZWIwNzU5NGUyZGYyNzM5MjFhNzdjMTAxZDBiZmRmYTExMTVhYmVkNWI5YjIwMjllYjQ5NmNlYmE5YmRiYjRiMyJ9fX0="; public static boolean shouldMobGlow(Entity entity) { Box box = entity.getBoundingBox(); @@ -36,7 +40,7 @@ public class MobGlow { return switch (entity) { // Minibosses case PlayerEntity p when name.equals("Lost Adventurer") || name.equals("Shadow Assassin") || name.equals("Diamond Guy") -> SkyblockerConfigManager.get().dungeons.starredMobGlow; - case PlayerEntity p when LividColor.LIVID_NAMES.contains(name) -> LividColor.shouldGlow(name); + case PlayerEntity p when entity.getId() == LividColor.getCorrectLividId() -> LividColor.shouldGlow(name); // Bats case BatEntity b -> SkyblockerConfigManager.get().dungeons.starredMobGlow || SkyblockerConfigManager.get().dungeons.starredMobBoundingBoxes; @@ -49,7 +53,6 @@ public class MobGlow { }; } - return switch (entity) { // Rift case PlayerEntity p when Utils.isInTheRift() && !entity.isInvisible() && name.equals("Blobbercyst ") -> SkyblockerConfigManager.get().otherLocations.rift.blobbercystGlow; @@ -111,26 +114,21 @@ public class MobGlow { case PlayerEntity p when name.equals("Lost Adventurer") -> 0xfee15c; case PlayerEntity p when name.equals("Shadow Assassin") -> 0x5b2cb2; case PlayerEntity p when name.equals("Diamond Guy") -> 0x57c2f7; - case PlayerEntity p when LividColor.LIVID_NAMES.contains(name) -> LividColor.getGlowColor(name); + case PlayerEntity p when entity.getId() == LividColor.getCorrectLividId() -> LividColor.getGlowColor(name); case PlayerEntity p when name.equals("Blobbercyst ") -> Formatting.GREEN.getColorValue(); case EndermanEntity enderman when TheEnd.isSpecialZealot(enderman) -> Formatting.RED.getColorValue(); - case ArmorStandEntity armorStand when isNukekubiHead(armorStand) -> 0x990099; + case ArmorStandEntity armorStand when isNukekubiHead(armorStand) -> Formatting.GREEN.getColorValue(); case ZombieEntity zombie when Utils.isInCrimson() && DojoManager.inArena -> DojoManager.getColor(); default -> 0xf57738; }; } + /** + * Compares the armor items of an armor stand to the Nukekubi head texture to determine if it is a Nukekubi head. + */ private static boolean isNukekubiHead(ArmorStandEntity entity) { - for (ItemStack armorItem : entity.getArmorItems()) { - // eb07594e2df273921a77c101d0bfdfa1115abed5b9b2029eb496ceba9bdbb4b3 is texture id for the nukekubi head, - // compare against it to exclusively find armorstands that are nukekubi heads - // get the texture of the nukekubi head item itself and compare it - String texture = ItemUtils.getHeadTexture(armorItem); - - return texture.contains("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZWIwNzU5NGUyZGYyNzM5MjFhNzdjMTAxZDBiZmRmYTExMTVhYmVkNWI5YjIwMjllYjQ5NmNlYmE5YmRiYjRiMyJ9fX0="); - } - return false; + return Streams.stream(entity.getArmorItems()).map(ItemUtils::getHeadTexture).anyMatch(headTexture -> headTexture.contains(NUKEKUBI_HEAD_TEXTURE)); } } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/item/slottext/adders/CollectionAdder.java b/src/main/java/de/hysky/skyblocker/skyblock/item/slottext/adders/CollectionAdder.java index 66d7f6e1..5b020fd4 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/item/slottext/adders/CollectionAdder.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/item/slottext/adders/CollectionAdder.java @@ -15,7 +15,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; public class CollectionAdder extends SimpleSlotTextAdder { - private static final Pattern COLLECTION = Pattern.compile("^[\\w ]+ (?<level>[IVXLCDM]+)$"); + private static final Pattern COLLECTION = Pattern.compile("^[\\w -]+ (?<level>[IVXLCDM]+)$"); public CollectionAdder() { super("^\\w+ Collections"); diff --git a/src/main/java/de/hysky/skyblocker/skyblock/quicknav/QuickNavButton.java b/src/main/java/de/hysky/skyblocker/skyblock/quicknav/QuickNavButton.java index f7f33d0f..75c25e58 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/quicknav/QuickNavButton.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/quicknav/QuickNavButton.java @@ -18,10 +18,16 @@ import net.minecraft.util.Identifier; @Environment(value = EnvType.CLIENT) public class QuickNavButton extends ClickableWidget { private final int index; - private boolean toggled; + private final boolean toggled; + private boolean temporaryToggled = false; private final String command; private final ItemStack icon; + private static final long TOGGLE_DURATION = 1000; + private long toggleTime; + + private float alpha = 1.0f; + /** * Checks if the current tab is a top tab based on its index. * @@ -32,7 +38,7 @@ public class QuickNavButton extends ClickableWidget { } public boolean toggled() { - return toggled; + return toggled || temporaryToggled; } /** @@ -49,6 +55,7 @@ public class QuickNavButton extends ClickableWidget { this.toggled = toggled; this.command = command; this.icon = icon; + this.toggleTime = 0; } private void updateCoordinates() { @@ -71,10 +78,12 @@ public class QuickNavButton extends ClickableWidget { */ @Override public void onClick(double mouseX, double mouseY) { - if (!this.toggled) { - this.toggled = true; + if (!this.temporaryToggled) { + this.temporaryToggled = true; + this.toggleTime = System.currentTimeMillis(); MessageScheduler.INSTANCE.sendMessageAfterCooldown(command); // TODO : add null check with log error + this.alpha = 0.5f; } } @@ -93,14 +102,34 @@ public class QuickNavButton extends ClickableWidget { this.updateCoordinates(); RenderSystem.disableDepthTest(); + if (this.temporaryToggled && System.currentTimeMillis() - this.toggleTime >= TOGGLE_DURATION) { + this.temporaryToggled = false; // Reset toggled state + } + //"animation" + if (this.alpha < 1.0f) { + this.alpha += 0.05f; + if (this.alpha > 1.0f) { + this.alpha = 1.0f; + } + } + + //"animation" + RenderSystem.enableBlend(); + RenderSystem.defaultBlendFunc(); + RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, this.alpha); + // Construct the texture identifier based on the index and toggled state - Identifier tabTexture = Identifier.ofVanilla("container/creative_inventory/tab_" + (isTopTab() ? "top" : "bottom") + "_" + (toggled ? "selected" : "unselected") + "_" + (index % 7 + 1)); + Identifier tabTexture = Identifier.ofVanilla("container/creative_inventory/tab_" + (isTopTab() ? "top" : "bottom") + "_" + (toggled() ? "selected" : "unselected") + "_" + (index % 7 + 1)); // Render the button texture context.drawGuiTexture(tabTexture, this.getX(), this.getY(), this.width, this.height); // Render the button icon int yOffset = this.index < 7 ? 1 : -1; context.drawItem(this.icon, this.getX() + 5, this.getY() + 8 + yOffset); + //prevent "fading animation" on not quicknav stuff + RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f); + RenderSystem.disableBlend(); + RenderSystem.enableDepthTest(); } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/waypoint/WaypointsListWidget.java b/src/main/java/de/hysky/skyblocker/skyblock/waypoint/WaypointsListWidget.java index f4b54342..99716bc4 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/waypoint/WaypointsListWidget.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/waypoint/WaypointsListWidget.java @@ -85,7 +85,7 @@ public class WaypointsListWidget extends ElementListWidget<WaypointsListWidget.A void updateButtons() { for (Entry<AbstractWaypointEntry> entry : children()) { - if (entry instanceof WaypointCategoryEntry categoryEntry && categoryEntry.enabled.isChecked() != categoryEntry.category.waypoints().stream().allMatch(screen::isEnabled)) { + if (entry instanceof WaypointCategoryEntry categoryEntry && categoryEntry.enabled.isChecked() != categoryEntry.shouldBeChecked()) { ((CheckboxWidgetAccessor) categoryEntry.enabled).setChecked(!categoryEntry.enabled.isChecked()); } else if (entry instanceof WaypointEntry waypointEntry && waypointEntry.enabled.isChecked() != screen.isEnabled(waypointEntry.waypoint)) { waypointEntry.enabled.onPress(); @@ -114,7 +114,7 @@ public class WaypointsListWidget extends ElementListWidget<WaypointsListWidget.A public WaypointCategoryEntry(WaypointCategory category) { this.category = category; - enabled = CheckboxWidget.builder(Text.literal(""), client.textRenderer).checked(!category.waypoints().isEmpty() && category.waypoints().stream().allMatch(screen::isEnabled)).callback((checkbox, checked) -> category.waypoints().forEach(waypoint -> screen.enabledChanged(waypoint, checked))).build(); + enabled = CheckboxWidget.builder(Text.literal(""), client.textRenderer).checked(shouldBeChecked()).callback((checkbox, checked) -> category.waypoints().forEach(waypoint -> screen.enabledChanged(waypoint, checked))).build(); nameField = new TextFieldWidget(client.textRenderer, 70, 20, Text.literal("Name")); nameField.setText(category.name()); nameField.setChangedListener(this::updateName); @@ -153,6 +153,10 @@ public class WaypointsListWidget extends ElementListWidget<WaypointsListWidget.A return children; } + private boolean shouldBeChecked() { + return !category.waypoints().isEmpty() && category.waypoints().stream().allMatch(screen::isEnabled); + } + private void updateName(String name) { int index = waypoints.indexOf(category); category = category.withName(name); diff --git a/src/main/java/de/hysky/skyblocker/utils/Boxes.java b/src/main/java/de/hysky/skyblocker/utils/Boxes.java index cd944a46..c50d9bcf 100644 --- a/src/main/java/de/hysky/skyblocker/utils/Boxes.java +++ b/src/main/java/de/hysky/skyblocker/utils/Boxes.java @@ -5,14 +5,22 @@ import net.minecraft.util.math.Direction.Axis; import net.minecraft.util.math.Vec3d; public class Boxes { - /** Returns the vector of the min pos of this box. **/ + /** + * Returns the vector of the min pos of this box. + * @deprecated Use {@link Box#getMinPos()} instead. + */ + @Deprecated(since = "1.22") public static Vec3d getMinVec(Box box) { - return new Vec3d(box.minX, box.minY, box.minZ); + return box.getMinPos(); } - /** Returns the vector of the max pos of this box. **/ + /** + * Returns the vector of the max pos of this box. + * @deprecated Use {@link Box#getMaxPos()} instead. + */ + @Deprecated(since = "1.22") public static Vec3d getMaxVec(Box box) { - return new Vec3d(box.maxX, box.maxY, box.maxZ); + return box.getMaxPos(); } /** Returns the vector of the side lengths of this box. **/ @@ -22,12 +30,12 @@ public class Boxes { /** Offsets this box so that minX, minY and minZ are all zero. **/ public static Box moveToZero(Box box) { - return box.offset(getMinVec(box).negate()); + return box.offset(box.getMinPos().negate()); } /** Returns the distance between to oppisite corners of the box. **/ public static double getCornerLength(Box box) { - return getMinVec(box).distanceTo(getMaxVec(box)); + return box.getMinPos().distanceTo(box.getMaxPos()); } /** Returns the length of an axis in the box. **/ diff --git a/src/main/java/de/hysky/skyblocker/utils/NEURepoManager.java b/src/main/java/de/hysky/skyblocker/utils/NEURepoManager.java index f8716ca4..0ecfe623 100644 --- a/src/main/java/de/hysky/skyblocker/utils/NEURepoManager.java +++ b/src/main/java/de/hysky/skyblocker/utils/NEURepoManager.java @@ -2,6 +2,7 @@ package de.hysky.skyblocker.utils; import com.mojang.brigadier.Command; import de.hysky.skyblocker.SkyblockerMod; +import de.hysky.skyblocker.events.SkyblockEvents; import de.hysky.skyblocker.skyblock.itemlist.ItemRepository; import de.hysky.skyblocker.utils.scheduler.Scheduler; import io.github.moulberry.repo.NEURepository; @@ -9,6 +10,7 @@ import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager; import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback; import net.minecraft.client.MinecraftClient; import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.network.packet.s2c.play.SynchronizeRecipesS2CPacket; import net.minecraft.text.Text; import org.apache.commons.lang3.function.Consumers; import org.eclipse.jgit.api.Git; @@ -49,6 +51,23 @@ public class NEURepoManager { })) ) ); + SkyblockEvents.JOIN.register(NEURepoManager::handleRecipeSynchronization); + } + + /** + * load the recipe manually because Hypixel doesn't send any vanilla recipes to the client + */ + private static void handleRecipeSynchronization() { + MinecraftClient client = MinecraftClient.getInstance(); + if (client.world != null && client.getNetworkHandler() != null) { + SynchronizeRecipesS2CPacket packet = new SynchronizeRecipesS2CPacket(List.of()); + + try { + client.getNetworkHandler().onSynchronizeRecipes(packet); + } catch (Exception e) { + LOGGER.info("[Skyblocker] recipe sync error" , e); + } + } } public static boolean isLoading() { diff --git a/src/main/java/de/hysky/skyblocker/utils/render/RenderHelper.java b/src/main/java/de/hysky/skyblocker/utils/render/RenderHelper.java index 1b16b138..20d8157a 100644 --- a/src/main/java/de/hysky/skyblocker/utils/render/RenderHelper.java +++ b/src/main/java/de/hysky/skyblocker/utils/render/RenderHelper.java @@ -5,6 +5,7 @@ import com.mojang.logging.LogUtils; import de.hysky.skyblocker.SkyblockerMod; import de.hysky.skyblocker.mixins.accessors.BeaconBlockEntityRendererInvoker; import de.hysky.skyblocker.mixins.accessors.DrawContextInvoker; +import de.hysky.skyblocker.utils.Boxes; import de.hysky.skyblocker.utils.render.culling.OcclusionCulling; import de.hysky.skyblocker.utils.render.title.Title; import de.hysky.skyblocker.utils.render.title.TitleContainer; @@ -30,7 +31,6 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Box; import net.minecraft.util.math.ColorHelper; import net.minecraft.util.math.Vec3d; - import org.joml.Matrix3f; import org.joml.Matrix4f; import org.joml.Vector3f; @@ -61,6 +61,10 @@ public class RenderHelper { renderBeaconBeam(context, pos, colorComponents); } + public static void renderFilled(WorldRenderContext context, Box box, float[] colorComponents, float alpha, boolean throughWalls) { + renderFilled(context, box.getMinPos(), Boxes.getLengthVec(box), colorComponents, alpha, throughWalls); + } + public static void renderFilled(WorldRenderContext context, BlockPos pos, float[] colorComponents, float alpha, boolean throughWalls) { renderFilled(context, Vec3d.of(pos), ONE, colorComponents, alpha, throughWalls); } @@ -72,11 +76,11 @@ public class RenderHelper { public static void renderFilled(WorldRenderContext context, Vec3d pos, Vec3d dimensions, float[] colorComponents, float alpha, boolean throughWalls) { if (throughWalls) { if (FrustumUtils.isVisible(pos.getX(), pos.getY(), pos.getZ(), pos.getX() + dimensions.x, pos.getY() + dimensions.y, pos.getZ() + dimensions.z)) { - renderFilledInternal(context, pos, dimensions, colorComponents, alpha, true); + renderFilledInternal(context, pos, dimensions, colorComponents, alpha, true); } } else { if (OcclusionCulling.getRegularCuller().isVisible(pos.getX(), pos.getY(), pos.getZ(), pos.getX() + dimensions.x, pos.getY() + dimensions.y, pos.getZ() + dimensions.z)) { - renderFilledInternal(context, pos, dimensions, colorComponents, alpha, false); + renderFilledInternal(context, pos, dimensions, colorComponents, alpha, false); } } } @@ -228,7 +232,7 @@ public class RenderHelper { Vector3f normal = new Vector3f((float) offset.x, (float) offset.y, (float) offset.z); buffer - .vertex(positionMatrix, (float) cameraPoint.x , (float) cameraPoint.y, (float) cameraPoint.z) + .vertex(positionMatrix, (float) cameraPoint.x, (float) cameraPoint.y, (float) cameraPoint.z) .color(colorComponents[0], colorComponents[1], colorComponents[2], alpha) .normal(normal.x, normal.y, normal.z); @@ -298,9 +302,9 @@ public class RenderHelper { scale *= 0.025f; positionMatrix - .translate((float) (pos.getX() - cameraPos.getX()), (float) (pos.getY() - cameraPos.getY()), (float) (pos.getZ() - cameraPos.getZ())) - .rotate(camera.getRotation()) - .scale(scale, -scale, scale); + .translate((float) (pos.getX() - cameraPos.getX()), (float) (pos.getY() - cameraPos.getY()), (float) (pos.getZ() - cameraPos.getZ())) + .rotate(camera.getRotation()) + .scale(scale, -scale, scale); float xOffset = -textRenderer.getWidth(text) / 2f; @@ -336,6 +340,13 @@ public class RenderHelper { } } + /** + * Retrieves the bounding box of a block in the world. + * + * @param world The client world. + * @param pos The position of the block. + * @return The bounding box of the block. + */ public static Box getBlockBoundingBox(ClientWorld world, BlockPos pos) { return getBlockBoundingBox(world, world.getBlockState(pos), pos); } @@ -383,8 +394,9 @@ public class RenderHelper { if (width == 0 || height == 0) { return; } - ((DrawContextInvoker) context).invokeDrawTexturedQuad(sprite.getAtlasId(), x, x + width, y, y + height, z, sprite.getFrameU((float)k / (float)i), sprite.getFrameU((float)(k + width) / (float)i), sprite.getFrameV((float)l / (float)j), sprite.getFrameV((float)(l + height) / (float)j), red, green, blue, alpha); + ((DrawContextInvoker) context).invokeDrawTexturedQuad(sprite.getAtlasId(), x, x + width, y, y + height, z, sprite.getFrameU((float) k / (float) i), sprite.getFrameU((float) (k + width) / (float) i), sprite.getFrameV((float) l / (float) j), sprite.getFrameV((float) (l + height) / (float) j), red, green, blue, alpha); } + private static void drawSpriteTiled(DrawContext context, Sprite sprite, int x, int y, int z, int width, int height, int i, int j, int tileWidth, int tileHeight, int k, int l, float red, float green, float blue, float alpha) { if (width <= 0 || height <= 0) { return; @@ -440,9 +452,10 @@ public class RenderHelper { } private static final float[] colorBuffer = new float[4]; + public static void renderNineSliceColored(DrawContext context, Identifier texture, int x, int y, int width, int height, Color color) { color.getComponents(colorBuffer); - renderNineSliceColored(context, texture, x, y, width, height, colorBuffer[0],colorBuffer[1],colorBuffer[2],colorBuffer[3]); + renderNineSliceColored(context, texture, x, y, width, height, colorBuffer[0], colorBuffer[1], colorBuffer[2], colorBuffer[3]); } // TODO Get rid of reflection once the new Sodium is released |