aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/SkyblockerMod.java2
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/config/SkyblockerConfig.java41
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/mixin/ClientPlayerEntityMixin.java8
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/mixin/InGameHudMixin.java7
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/mixin/accessor/FrustumInvoker.java15
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/skyblock/FancyStatusBars.java27
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/skyblock/FishingHelper.java8
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/Trivia.java4
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/skyblock/rift/EffigyWaypoints.java79
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/skyblock/rift/HealingMelonIndicator.java21
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/skyblock/rift/MirrorverseWaypoints.java88
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/skyblock/rift/StakeIndicator.java21
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/skyblock/rift/TheRift.java20
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/skyblock/rift/TwinClawsIndicator.java32
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/utils/FrustumUtils.java5
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/utils/RenderHelper.java31
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/utils/SlayerUtils.java66
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/utils/Utils.java5
-rw-r--r--src/main/resources/assets/skyblocker/lang/en_us.json22
-rw-r--r--src/main/resources/assets/skyblocker/mirrorverse_waypoints.json1019
-rw-r--r--src/main/resources/skyblocker.mixins.json3
21 files changed, 1498 insertions, 26 deletions
diff --git a/src/main/java/me/xmrvizzy/skyblocker/SkyblockerMod.java b/src/main/java/me/xmrvizzy/skyblocker/SkyblockerMod.java
index add81791..a629f851 100644
--- a/src/main/java/me/xmrvizzy/skyblocker/SkyblockerMod.java
+++ b/src/main/java/me/xmrvizzy/skyblocker/SkyblockerMod.java
@@ -16,6 +16,7 @@ import me.xmrvizzy.skyblocker.skyblock.item.PriceInfoTooltip;
import me.xmrvizzy.skyblocker.skyblock.item.WikiLookup;
import me.xmrvizzy.skyblocker.skyblock.itemlist.ItemRegistry;
import me.xmrvizzy.skyblocker.skyblock.quicknav.QuickNav;
+import me.xmrvizzy.skyblocker.skyblock.rift.TheRift;
import me.xmrvizzy.skyblocker.skyblock.tabhud.TabHud;
import me.xmrvizzy.skyblocker.skyblock.tabhud.util.PlayerListMgr;
import me.xmrvizzy.skyblocker.utils.*;
@@ -82,6 +83,7 @@ public class SkyblockerMod implements ClientModInitializer {
FairySouls.init();
TabHud.init();
DungeonMap.init();
+ TheRift.init();
containerSolverManager.init();
scheduler.scheduleCyclic(Utils::update, 20);
scheduler.scheduleCyclic(DiscordRPCManager::updateDataAndPresence, 100);
diff --git a/src/main/java/me/xmrvizzy/skyblocker/config/SkyblockerConfig.java b/src/main/java/me/xmrvizzy/skyblocker/config/SkyblockerConfig.java
index 833e4661..3a8a4a1f 100644
--- a/src/main/java/me/xmrvizzy/skyblocker/config/SkyblockerConfig.java
+++ b/src/main/java/me/xmrvizzy/skyblocker/config/SkyblockerConfig.java
@@ -30,6 +30,10 @@ public class SkyblockerConfig implements ConfigData {
@ConfigEntry.Gui.TransitiveObject
public Locations locations = new Locations();
+ @ConfigEntry.Category("slayer")
+ @ConfigEntry.Gui.TransitiveObject
+ public Slayer slayer = new Slayer();
+
@ConfigEntry.Category("quickNav")
@ConfigEntry.Gui.TransitiveObject
public QuickNav quickNav = new QuickNav();
@@ -178,7 +182,7 @@ public class SkyblockerConfig implements ConfigData {
public static class TabHudConf {
public boolean tabHudEnabled = true;
- @ConfigEntry.BoundedDiscrete(min=10, max=200)
+ @ConfigEntry.BoundedDiscrete(min = 10, max = 200)
@ConfigEntry.Gui.Tooltip()
public int tabHudScale = 100;
}
@@ -290,6 +294,10 @@ public class SkyblockerConfig implements ConfigData {
@ConfigEntry.Category("dwarvenmines")
@ConfigEntry.Gui.CollapsibleObject()
public DwarvenMines dwarvenMines = new DwarvenMines();
+
+ @ConfigEntry.Category("rift")
+ @ConfigEntry.Gui.CollapsibleObject()
+ public Rift rift = new Rift();
}
public static class Dungeons {
@@ -345,7 +353,7 @@ public class SkyblockerConfig implements ConfigData {
CLASSIC;
@Override
- public String toString() {
+ public String toString() {
return switch (this) {
case SIMPLE -> "Simple";
case FANCY -> "Fancy";
@@ -359,6 +367,35 @@ public class SkyblockerConfig implements ConfigData {
public boolean solveTreasureHunter = true;
}
+ public static class Rift {
+ public boolean mirrorverseWaypoints = true;
+ }
+
+ public static class Slayer {
+ @ConfigEntry.Category("vampire")
+ @ConfigEntry.Gui.CollapsibleObject()
+ public VampireSlayer vampireSlayer = new VampireSlayer();
+ }
+
+ public static class VampireSlayer {
+ public boolean enableEffigyWaypoints = true;
+ public boolean compactEffigyWaypoints;
+ @ConfigEntry.BoundedDiscrete(min = 1, max = 10)
+ @ConfigEntry.Gui.Tooltip()
+ public int effigyUpdateFrequency = 5;
+ public boolean enableHolyIceIndicator = true;
+ public int holyIceIndicatorTickDelay = 10;
+ @ConfigEntry.BoundedDiscrete(min = 1, max = 10)
+ @ConfigEntry.Gui.Tooltip()
+ public int holyIceUpdateFrequency = 5;
+ public boolean enableHealingMelonIndicator = true;
+ public float healingMelonHealthThreshold = 4F;
+ public boolean enableSteakStakeIndicator = true;
+ @ConfigEntry.BoundedDiscrete(min = 1, max = 10)
+ @ConfigEntry.Gui.Tooltip()
+ public int steakStakeUpdateFrequency = 5;
+ }
+
public static class Messages {
@ConfigEntry.Gui.EnumHandler(option = ConfigEntry.Gui.EnumHandler.EnumDisplayOption.BUTTON)
public ChatFilterResult hideAbility = ChatFilterResult.PASS;
diff --git a/src/main/java/me/xmrvizzy/skyblocker/mixin/ClientPlayerEntityMixin.java b/src/main/java/me/xmrvizzy/skyblocker/mixin/ClientPlayerEntityMixin.java
index 76c4e8ec..e48e725e 100644
--- a/src/main/java/me/xmrvizzy/skyblocker/mixin/ClientPlayerEntityMixin.java
+++ b/src/main/java/me/xmrvizzy/skyblocker/mixin/ClientPlayerEntityMixin.java
@@ -2,13 +2,16 @@ package me.xmrvizzy.skyblocker.mixin;
import com.mojang.authlib.GameProfile;
import me.xmrvizzy.skyblocker.skyblock.HotbarSlotLock;
+import me.xmrvizzy.skyblocker.skyblock.rift.HealingMelonIndicator;
import me.xmrvizzy.skyblocker.utils.Utils;
+import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.AbstractClientPlayerEntity;
import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.client.world.ClientWorld;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(ClientPlayerEntity.class)
@@ -21,4 +24,9 @@ public abstract class ClientPlayerEntityMixin extends AbstractClientPlayerEntity
public void skyblocker$dropSelectedItem(boolean dropEntireStack, CallbackInfoReturnable<Boolean> cir) {
if (Utils.isOnSkyblock()) HotbarSlotLock.handleDropSelectedItem(this.getInventory().selectedSlot, cir);
}
+
+ @Inject(method = "updateHealth", at = @At("HEAD"))
+ public void skyblocker$updateHealth(float health, CallbackInfo info) {
+ HealingMelonIndicator.updateHealth(MinecraftClient.getInstance());
+ }
} \ No newline at end of file
diff --git a/src/main/java/me/xmrvizzy/skyblocker/mixin/InGameHudMixin.java b/src/main/java/me/xmrvizzy/skyblocker/mixin/InGameHudMixin.java
index 335737a1..7d9182b5 100644
--- a/src/main/java/me/xmrvizzy/skyblocker/mixin/InGameHudMixin.java
+++ b/src/main/java/me/xmrvizzy/skyblocker/mixin/InGameHudMixin.java
@@ -11,7 +11,6 @@ import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.hud.InGameHud;
-import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.text.Text;
@@ -53,7 +52,7 @@ public abstract class InGameHudMixin {
@Inject(method = "setOverlayMessage(Lnet/minecraft/text/Text;Z)V", at = @At("HEAD"), cancellable = true)
private void skyblocker$onSetOverlayMessage(Text message, boolean tinted, CallbackInfo ci) {
- if (!Utils.isOnSkyblock() || !SkyblockerConfig.get().general.bars.enableBars)
+ if (!Utils.isOnSkyblock() || !SkyblockerConfig.get().general.bars.enableBars || Utils.isInTheRift())
return;
String msg = message.getString();
String res = statusBarTracker.update(msg, SkyblockerConfig.get().messages.hideMana);
@@ -84,7 +83,7 @@ public abstract class InGameHudMixin {
@Inject(method = "renderExperienceBar", at = @At("HEAD"), cancellable = true)
private void skyblocker$renderExperienceBar(DrawContext context, int x, CallbackInfo ci) {
- if (Utils.isOnSkyblock() && SkyblockerConfig.get().general.bars.enableBars)
+ if (Utils.isOnSkyblock() && SkyblockerConfig.get().general.bars.enableBars && !Utils.isInTheRift())
ci.cancel();
}
@@ -103,7 +102,7 @@ public abstract class InGameHudMixin {
@Inject(method = "renderMountHealth", at = @At("HEAD"), cancellable = true)
private void skyblocker$renderMountHealth(DrawContext context, CallbackInfo ci) {
- if (Utils.isOnSkyblock() && SkyblockerConfig.get().general.bars.enableBars)
+ if (Utils.isOnSkyblock() && SkyblockerConfig.get().general.bars.enableBars && !Utils.isInTheRift())
ci.cancel();
}
} \ No newline at end of file
diff --git a/src/main/java/me/xmrvizzy/skyblocker/mixin/accessor/FrustumInvoker.java b/src/main/java/me/xmrvizzy/skyblocker/mixin/accessor/FrustumInvoker.java
new file mode 100644
index 00000000..108a7344
--- /dev/null
+++ b/src/main/java/me/xmrvizzy/skyblocker/mixin/accessor/FrustumInvoker.java
@@ -0,0 +1,15 @@
+package me.xmrvizzy.skyblocker.mixin.accessor;
+
+import me.xmrvizzy.skyblocker.utils.FrustumUtils;
+import net.minecraft.client.render.Frustum;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.gen.Invoker;
+
+/**
+ * Use {@link FrustumUtils#isVisible(double, double, double, double, double, double) FrustumUtils#isVisible} which is shorter. For the purpose of avoiding object allocations!
+ */
+@Mixin(Frustum.class)
+public interface FrustumInvoker {
+ @Invoker("isVisible")
+ boolean isVisible(double minX, double minY, double minZ, double maxX, double maxY, double maxZ);
+}
diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/FancyStatusBars.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/FancyStatusBars.java
index 6af06e6d..1a460f5b 100644
--- a/src/main/java/me/xmrvizzy/skyblocker/skyblock/FancyStatusBars.java
+++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/FancyStatusBars.java
@@ -2,6 +2,7 @@ package me.xmrvizzy.skyblocker.skyblock;
import me.xmrvizzy.skyblocker.SkyblockerMod;
import me.xmrvizzy.skyblocker.config.SkyblockerConfig;
+import me.xmrvizzy.skyblocker.utils.Utils;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gui.DrawContext;
@@ -39,7 +40,7 @@ public class FancyStatusBars {
public boolean render(DrawContext context, int scaledWidth, int scaledHeight) {
var player = client.player;
- if (!SkyblockerConfig.get().general.bars.enableBars || player == null)
+ if (!SkyblockerConfig.get().general.bars.enableBars || player == null || Utils.isInTheRift())
return false;
anchorsX[0] = scaledWidth / 2 - 91;
anchorsY[0] = scaledHeight - 33;
@@ -70,10 +71,12 @@ public class FancyStatusBars {
moveBar(i, configAnchorNum);
}
- for (var bar : bars)
+ for (var bar : bars) {
bar.draw(context);
- for (var bar : bars)
+ }
+ for (var bar : bars) {
bar.drawText(context);
+ }
return true;
}
@@ -149,19 +152,23 @@ public class FancyStatusBars {
// Draw the background for the bar
context.drawTexture(BARS, anchorsX[anchorNum] + offsetX + 10, anchorsY[anchorNum], 10, v, 2, 9);
- for (int i = 2; i < bar_width - 2; i += 58)
+ for (int i = 2; i < bar_width - 2; i += 58) {
context.drawTexture(BARS, anchorsX[anchorNum] + offsetX + 10 + i, anchorsY[anchorNum], 12, v, Math.min(58, bar_width - 2 - i), 9);
+ }
context.drawTexture(BARS, anchorsX[anchorNum] + offsetX + 10 + bar_width - 2, anchorsY[anchorNum], 70, v, 2, 9);
// Draw the filled part of the bar
for (int i = 0; i < fill.length; i++) {
int fill_width = this.fill[i] * (bar_width - 2) / 100;
- if (fill_width >= 1)
- context.drawTexture(BARS, anchorsX[anchorNum] + offsetX + 11, anchorsY[anchorNum], 72 + i*60, v, 1, 9);
- for (int j = 1; j < fill_width - 1; j += 58)
- context.drawTexture(BARS, anchorsX[anchorNum] + offsetX + 11 + j, anchorsY[anchorNum], 73 + i*60, v, Math.min(58, fill_width - 1 - j), 9);
- if (fill_width == bar_width - 2)
- context.drawTexture(BARS, anchorsX[anchorNum] + offsetX + 11 + fill_width - 1, anchorsY[anchorNum], 131 + i*60, v, 1, 9);
+ if (fill_width >= 1) {
+ context.drawTexture(BARS, anchorsX[anchorNum] + offsetX + 11, anchorsY[anchorNum], 72 + i * 60, v, 1, 9);
+ }
+ for (int j = 1; j < fill_width - 1; j += 58) {
+ context.drawTexture(BARS, anchorsX[anchorNum] + offsetX + 11 + j, anchorsY[anchorNum], 73 + i * 60, v, Math.min(58, fill_width - 1 - j), 9);
+ }
+ if (fill_width == bar_width - 2) {
+ context.drawTexture(BARS, anchorsX[anchorNum] + offsetX + 11 + fill_width - 1, anchorsY[anchorNum], 131 + i * 60, v, 1, 9);
+ }
}
}
diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/FishingHelper.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/FishingHelper.java
index d82464e1..822b89d9 100644
--- a/src/main/java/me/xmrvizzy/skyblocker/skyblock/FishingHelper.java
+++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/FishingHelper.java
@@ -1,6 +1,7 @@
package me.xmrvizzy.skyblocker.skyblock;
import me.xmrvizzy.skyblocker.config.SkyblockerConfig;
+import me.xmrvizzy.skyblocker.utils.RenderHelper;
import net.fabricmc.fabric.api.event.player.UseItemCallback;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.ClientPlayerEntity;
@@ -8,10 +9,7 @@ import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.FishingRodItem;
import net.minecraft.item.ItemStack;
import net.minecraft.network.packet.s2c.play.PlaySoundS2CPacket;
-import net.minecraft.sound.SoundEvent;
-import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
-import net.minecraft.util.Identifier;
import net.minecraft.util.TypedActionResult;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
@@ -51,9 +49,7 @@ public class FishingHelper {
if (player != null && player.fishHook != null) {
Vec3d soundToFishHook = player.fishHook.getPos().subtract(packet.getX(), 0, packet.getZ());
if (Math.abs(normalYawVector.x * soundToFishHook.z - normalYawVector.z * soundToFishHook.x) < 0.2D && Math.abs(normalYawVector.dotProduct(soundToFishHook)) < 4D && player.getPos().squaredDistanceTo(packet.getX(), packet.getY(), packet.getZ()) > 1D) {
- client.inGameHud.setTitleTicks(0, 10, 5);
- client.inGameHud.setTitle(Text.translatable("skyblocker.fishing.reelNow").formatted(Formatting.GREEN));
- player.playSound(SoundEvent.of(new Identifier("minecraft", "entity.experience_orb.pickup")), 100f, 0.1f);
+ RenderHelper.displayTitleAndPlaySound(10, 5, "skyblocker.fishing.reelNow", Formatting.GREEN);
reset();
}
} else {
diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/Trivia.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/Trivia.java
index 10a2e413..f7598af5 100644
--- a/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/Trivia.java
+++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/Trivia.java
@@ -69,7 +69,7 @@ public class Trivia extends ChatPatternListener {
answers.put("What is the status of Storm?", new String[]{"The Wither Lords"});
answers.put("What is the status of Necron?", new String[]{"The Wither Lords"});
answers.put("What is the status of Maxor, Storm, Goldor and Necron?", new String[]{"The Wither Lords"});
- answers.put("How many total Fairy Souls are there?", new String[]{"240 Fairy Souls"});
+ answers.put("How many total Fairy Souls are there?", new String[]{"242 Fairy Souls"});
answers.put("How many Fairy Souls are there in Spider's Den?", new String[]{"19 Fairy Souls"});
answers.put("How many Fairy Souls are there in The End?", new String[]{"12 Fairy Souls"});
answers.put("How many Fairy Souls are there in The Farming Islands?", new String[]{"20 Fairy Souls"});
@@ -87,7 +87,7 @@ public class Trivia extends ChatPatternListener {
answers.put("What is the name of the person that upgrades pets?", new String[]{"Kat"});
answers.put("What is the name of the lady of the Nether?", new String[]{"Elle"});
answers.put("Which villager in the Village gives you a Rogue Sword?", new String[]{"Jamie"});
- answers.put("How many unique minions are there?", new String[]{"58 Minions"});
+ answers.put("How many unique minions are there?", new String[]{"59 Minions"});
answers.put("Which of these enemies does not spawn in the Spider's Den?", new String[]{"Zombie Spider", "Cave Spider", "Wither Skeleton",
"Dashing Spooder", "Broodfather", "Night Spider"});
answers.put("Which of these monsters only spawns at night?", new String[]{"Zombie Villager", "Ghast"});
diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/rift/EffigyWaypoints.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/rift/EffigyWaypoints.java
new file mode 100644
index 00000000..0d44900a
--- /dev/null
+++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/rift/EffigyWaypoints.java
@@ -0,0 +1,79 @@
+package me.xmrvizzy.skyblocker.skyblock.rift;
+
+import me.xmrvizzy.skyblocker.config.SkyblockerConfig;
+import me.xmrvizzy.skyblocker.utils.RenderHelper;
+import me.xmrvizzy.skyblocker.utils.Utils;
+import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderContext;
+import net.minecraft.client.MinecraftClient;
+import net.minecraft.client.network.ClientPlayerEntity;
+import net.minecraft.scoreboard.Scoreboard;
+import net.minecraft.scoreboard.ScoreboardObjective;
+import net.minecraft.scoreboard.ScoreboardPlayerScore;
+import net.minecraft.scoreboard.Team;
+import net.minecraft.text.Text;
+import net.minecraft.text.TextColor;
+import net.minecraft.util.DyeColor;
+import net.minecraft.util.math.BlockPos;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class EffigyWaypoints {
+ private static final Logger LOGGER = LoggerFactory.getLogger(EffigyWaypoints.class);
+ private static final List<BlockPos> effigies = List.of(
+ new BlockPos(150, 79, 95), //Effigy 1
+ new BlockPos(193, 93, 119), //Effigy 2
+ new BlockPos(235, 110, 147), //Effigy 3
+ new BlockPos(293, 96, 134), //Effigy 4
+ new BlockPos(262, 99, 94), //Effigy 5
+ new BlockPos(240, 129, 118) //Effigy 6
+ );
+ private static final List<BlockPos> unBrokenEffigies = new ArrayList<>();
+
+ public static void updateEffigies() {
+ if (!SkyblockerConfig.get().slayer.vampireSlayer.enableEffigyWaypoints || !Utils.isOnSkyblock() || !Utils.isInTheRift() || !Utils.getLocation().contains("Stillgore Château")) return;
+
+ unBrokenEffigies.clear();
+ try {
+ ClientPlayerEntity player = MinecraftClient.getInstance().player;
+ if (player == null) return;
+ Scoreboard scoreboard = player.getScoreboard();
+ ScoreboardObjective objective = scoreboard.getObjectiveForSlot(1);
+ for (ScoreboardPlayerScore score : scoreboard.getAllPlayerScores(objective)) {
+ Team team = scoreboard.getPlayerTeam(score.getPlayerName());
+ if (team != null) {
+ String line = team.getPrefix().getString() + team.getSuffix().getString();
+ if (line.contains("Effigies")) {
+ List<Text> newList = new ArrayList<>(team.getPrefix().getSiblings());
+ newList.addAll(team.getSuffix().getSiblings());
+ for (int i = 1; i < newList.size(); i++) {
+ if (newList.get(i).getStyle().getColor() == TextColor.parse("gray")) {
+ unBrokenEffigies.add(effigies.get(i - 1));
+ }
+ }
+ }
+ }
+ }
+ } catch (NullPointerException e) {
+ LOGGER.error("[Skyblocker] Error while updating effigies.", e);
+ }
+ }
+
+ public static void render(WorldRenderContext context) {
+ if (SkyblockerConfig.get().slayer.vampireSlayer.enableEffigyWaypoints && Utils.getLocation().contains("Stillgore Château")) {
+ for (BlockPos effigy : unBrokenEffigies) {
+ float[] colorComponents = DyeColor.RED.getColorComponents();
+ if (SkyblockerConfig.get().slayer.vampireSlayer.compactEffigyWaypoints) {
+ RenderHelper.renderFilledThroughWallsWithBeaconBeam(context, effigy.down(6), colorComponents, 0.5F);
+ } else {
+ RenderHelper.renderFilledThroughWallsWithBeaconBeam(context, effigy, colorComponents, 0.5F);
+ for (int i = 1; i < 6; i++) {
+ RenderHelper.renderFilledThroughWalls(context, effigy.down(i), colorComponents, 0.5F - (0.075F * i));
+ }
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/rift/HealingMelonIndicator.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/rift/HealingMelonIndicator.java
new file mode 100644
index 00000000..f98c17e7
--- /dev/null
+++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/rift/HealingMelonIndicator.java
@@ -0,0 +1,21 @@
+package me.xmrvizzy.skyblocker.skyblock.rift;
+
+import me.xmrvizzy.skyblocker.config.SkyblockerConfig;
+import me.xmrvizzy.skyblocker.utils.RenderHelper;
+import me.xmrvizzy.skyblocker.utils.Utils;
+import net.minecraft.client.MinecraftClient;
+import net.minecraft.client.network.ClientPlayerEntity;
+import net.minecraft.util.Formatting;
+
+public class HealingMelonIndicator {
+ private static long lastDisplayTime = 0;
+
+ public static void updateHealth(MinecraftClient client) {
+ if (!SkyblockerConfig.get().slayer.vampireSlayer.enableHealingMelonIndicator || !Utils.isOnSkyblock() || !Utils.isInTheRift() || !Utils.getLocation().contains("Stillgore Château")) return;
+ ClientPlayerEntity player = client.player;
+ if (player != null && player.getHealth() <= SkyblockerConfig.get().slayer.vampireSlayer.healingMelonHealthThreshold * 2F && System.currentTimeMillis() - lastDisplayTime > 2500) {
+ lastDisplayTime = System.currentTimeMillis();
+ RenderHelper.displayTitleAndPlaySound(15, 5, "skyblocker.rift.healNow", Formatting.DARK_RED);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/rift/MirrorverseWaypoints.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/rift/MirrorverseWaypoints.java
new file mode 100644
index 00000000..276ec551
--- /dev/null
+++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/rift/MirrorverseWaypoints.java
@@ -0,0 +1,88 @@
+package me.xmrvizzy.skyblocker.skyblock.rift;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import me.xmrvizzy.skyblocker.SkyblockerMod;
+import me.xmrvizzy.skyblocker.config.SkyblockerConfig;
+import me.xmrvizzy.skyblocker.utils.RenderHelper;
+import me.xmrvizzy.skyblocker.utils.Utils;
+import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderContext;
+import net.minecraft.client.MinecraftClient;
+import net.minecraft.util.DyeColor;
+import net.minecraft.util.Identifier;
+import net.minecraft.util.math.BlockPos;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+
+public class MirrorverseWaypoints {
+ private static final Logger LOGGER = LoggerFactory.getLogger("skyblocker");
+ private static final MinecraftClient CLIENT = MinecraftClient.getInstance();
+ private static final Identifier WAYPOINTS_JSON = new Identifier(SkyblockerMod.NAMESPACE, "mirrorverse_waypoints.json");
+ private static final BlockPos[] LAVA_PATH_WAYPOINTS = new BlockPos[107];
+ private static final BlockPos[] UPSIDE_DOWN_WAYPOINTS = new BlockPos[66];
+ private static final BlockPos[] TURBULATOR_WAYPOINTS = new BlockPos[27];
+ private static final float[] COLOR_COMPONENTS = DyeColor.RED.getColorComponents();
+
+ static {
+ loadWaypoints();
+ }
+
+ /**
+ * Loads the waypoint locations into memory
+ */
+ public static void loadWaypoints() {
+ try (BufferedReader reader = CLIENT.getResourceManager().openAsReader(WAYPOINTS_JSON)) {
+ JsonObject file = JsonParser.parseReader(reader).getAsJsonObject();
+ JsonArray sections = file.get("sections").getAsJsonArray();
+
+ /// Lava Path
+ JsonArray lavaPathWaypoints = sections.get(0).getAsJsonObject().get("waypoints").getAsJsonArray();
+
+ for (int i = 0; i < lavaPathWaypoints.size(); i++) {
+ JsonObject point = lavaPathWaypoints.get(i).getAsJsonObject();
+ LAVA_PATH_WAYPOINTS[i] = new BlockPos(point.get("x").getAsInt(), point.get("y").getAsInt(), point.get("z").getAsInt());
+ }
+
+ /// Upside Down Parkour
+ JsonArray upsideDownParkourWaypoints = sections.get(1).getAsJsonObject().get("waypoints").getAsJsonArray();
+
+ for (int i = 0; i < upsideDownParkourWaypoints.size(); i++) {
+ JsonObject point = upsideDownParkourWaypoints.get(i).getAsJsonObject();
+ UPSIDE_DOWN_WAYPOINTS[i] = new BlockPos(point.get("x").getAsInt(), point.get("y").getAsInt(), point.get("z").getAsInt());
+ }
+
+ /// Turbulator Parkour
+ JsonArray turbulatorParkourWaypoints = sections.get(2).getAsJsonObject().get("waypoints").getAsJsonArray();
+
+ for (int i = 0; i < turbulatorParkourWaypoints.size(); i++) {
+ JsonObject point = turbulatorParkourWaypoints.get(i).getAsJsonObject();
+ TURBULATOR_WAYPOINTS[i] = new BlockPos(point.get("x").getAsInt(), point.get("y").getAsInt(), point.get("z").getAsInt());
+ }
+
+ } catch (IOException e) {
+ LOGGER.info("[Skyblocker] Mirrorverse Waypoints failed to load ;(");
+ e.printStackTrace();
+ }
+ }
+
+ public static void render(WorldRenderContext wrc) {
+ //I would also check for the mirrorverse location but the scoreboard stuff is not performant at all...
+ if (Utils.isInTheRift() && SkyblockerConfig.get().locations.rift.mirrorverseWaypoints) {
+ for (BlockPos pos : LAVA_PATH_WAYPOINTS) {
+ RenderHelper.renderFilledIfVisible(wrc, pos, COLOR_COMPONENTS, 0.5f);
+ }
+
+ for (BlockPos pos : UPSIDE_DOWN_WAYPOINTS) {
+ RenderHelper.renderFilledIfVisible(wrc, pos, COLOR_COMPONENTS, 0.5f);
+ }
+
+ for (BlockPos pos : TURBULATOR_WAYPOINTS) {
+ RenderHelper.renderFilledIfVisible(wrc, pos, COLOR_COMPONENTS, 0.5f);
+ }
+ }
+ }
+}
diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/rift/StakeIndicator.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/rift/StakeIndicator.java
new file mode 100644
index 00000000..d1132be8
--- /dev/null
+++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/rift/StakeIndicator.java
@@ -0,0 +1,21 @@
+package me.xmrvizzy.skyblocker.skyblock.rift;
+
+import me.xmrvizzy.skyblocker.config.SkyblockerConfig;
+import me.xmrvizzy.skyblocker.utils.RenderHelper;
+import me.xmrvizzy.skyblocker.utils.SlayerUtils;
+import me.xmrvizzy.skyblocker.utils.Utils;
+import net.minecraft.entity.Entity;
+import net.minecraft.util.Formatting;
+
+public class StakeIndicator {
+ private static long lastDisplayTime = 0;
+
+ public static void updateStake() {
+ if (!SkyblockerConfig.get().slayer.vampireSlayer.enableSteakStakeIndicator || !Utils.isOnSkyblock() || !Utils.isInTheRift() || !Utils.getLocation().contains("Stillgore Château") || !SlayerUtils.isInSlayer()) return;
+ Entity slayerEntity = SlayerUtils.getSlayerEntity();
+ if (slayerEntity != null && slayerEntity.getDisplayName().toString().contains("҉") && System.currentTimeMillis() - lastDisplayTime > 2500) {
+ lastDisplayTime = System.currentTimeMillis();
+ RenderHelper.displayTitleAndPlaySound(25, 5, "skyblocker.rift.stakeNow", Formatting.RED);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/rift/TheRift.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/rift/TheRift.java
new file mode 100644
index 00000000..91b727e2
--- /dev/null
+++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/rift/TheRift.java
@@ -0,0 +1,20 @@
+package me.xmrvizzy.skyblocker.skyblock.rift;
+
+import me.xmrvizzy.skyblocker.SkyblockerMod;
+import me.xmrvizzy.skyblocker.config.SkyblockerConfig;
+import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents;
+
+public class TheRift {
+ /**
+ * @see me.xmrvizzy.skyblocker.utils.Utils#isInTheRift() Utils#isInTheRift().
+ */
+ public static final String LOCATION = "rift";
+
+ public static void init() {
+ WorldRenderEvents.AFTER_TRANSLUCENT.register(MirrorverseWaypoints::render);
+ WorldRenderEvents.AFTER_TRANSLUCENT.register(EffigyWaypoints::render);
+ SkyblockerMod.getInstance().scheduler.scheduleCyclic(EffigyWaypoints::updateEffigies, SkyblockerConfig.get().slayer.vampireSlayer.effigyUpdateFrequency);
+ SkyblockerMod.getInstance().scheduler.scheduleCyclic(TwinClawsIndicator::updateIce, SkyblockerConfig.get().slayer.vampireSlayer.holyIceUpdateFrequency);
+ SkyblockerMod.getInstance().scheduler.scheduleCyclic(StakeIndicator::updateStake, SkyblockerConfig.get().slayer.vampireSlayer.steakStakeUpdateFrequency);
+ }
+}
diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/rift/TwinClawsIndicator.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/rift/TwinClawsIndicator.java
new file mode 100644
index 00000000..7e1d6605
--- /dev/null
+++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/rift/TwinClawsIndicator.java
@@ -0,0 +1,32 @@
+package me.xmrvizzy.skyblocker.skyblock.rift;
+
+import me.xmrvizzy.skyblocker.SkyblockerMod;
+import me.xmrvizzy.skyblocker.config.SkyblockerConfig;
+import me.xmrvizzy.skyblocker.utils.RenderHelper;
+import me.xmrvizzy.skyblocker.utils.SlayerUtils;
+import me.xmrvizzy.skyblocker.utils.Utils;
+import net.minecraft.entity.Entity;
+import net.minecraft.util.Formatting;
+
+public class TwinClawsIndicator {
+ private static long lastDisplayTime = 0;
+
+ public static void updateIce() {
+ if (!SkyblockerConfig.get().slayer.vampireSlayer.enableHolyIceIndicator || !Utils.isOnSkyblock() || !Utils.isInTheRift() || !(Utils.getLocation().contains("Stillgore Château")) || !SlayerUtils.isInSlayer()) return;
+
+ Entity slayerEntity = SlayerUtils.getSlayerEntity();
+ if (slayerEntity == null) return;
+
+ for (Entity entity : SlayerUtils.getEntityArmorStands(slayerEntity)) {
+ if (entity.getDisplayName().toString().contains("TWINCLAWS")) {
+ SkyblockerMod.getInstance().scheduler.schedule(() -> {
+ if (System.currentTimeMillis() - lastDisplayTime > 2500) {
+ lastDisplayTime = System.currentTimeMillis();
+ RenderHelper.displayTitleAndPlaySound(40, 5, "skyblocker.rift.iceNow", Formatting.AQUA);
+ }
+ }, SkyblockerConfig.get().slayer.vampireSlayer.holyIceIndicatorTickDelay);
+ }
+ }
+
+ }
+} \ No newline at end of file
diff --git a/src/main/java/me/xmrvizzy/skyblocker/utils/FrustumUtils.java b/src/main/java/me/xmrvizzy/skyblocker/utils/FrustumUtils.java
index 6973aa1e..9ea90c16 100644
--- a/src/main/java/me/xmrvizzy/skyblocker/utils/FrustumUtils.java
+++ b/src/main/java/me/xmrvizzy/skyblocker/utils/FrustumUtils.java
@@ -1,6 +1,7 @@
package me.xmrvizzy.skyblocker.utils;
import me.xmrvizzy.skyblocker.mixin.AccessorWorldRenderer;
+import me.xmrvizzy.skyblocker.mixin.accessor.FrustumInvoker;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.Frustum;
import net.minecraft.util.math.Box;
@@ -14,4 +15,8 @@ public class FrustumUtils {
public static boolean isBoxVisible(Box box) {
return getFrustum().isVisible(box);
}
+
+ public static boolean isVisible(double minX, double minY, double minZ, double maxX, double maxY, double maxZ) {
+ return ((FrustumInvoker) getFrustum()).isVisible(minX, minY, minZ, maxX, maxY, maxZ);
+ }
} \ No newline at end of file
diff --git a/src/main/java/me/xmrvizzy/skyblocker/utils/RenderHelper.java b/src/main/java/me/xmrvizzy/skyblocker/utils/RenderHelper.java
index 79308dc3..a7e1fc99 100644
--- a/src/main/java/me/xmrvizzy/skyblocker/utils/RenderHelper.java
+++ b/src/main/java/me/xmrvizzy/skyblocker/utils/RenderHelper.java
@@ -3,13 +3,20 @@ package me.xmrvizzy.skyblocker.utils;
import me.x150.renderer.render.Renderer3d;
import me.xmrvizzy.skyblocker.mixin.accessor.BeaconBlockEntityRendererInvoker;
import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderContext;
+import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.block.entity.BeaconBlockEntityRenderer;
+import net.minecraft.sound.SoundEvent;
+import net.minecraft.text.Text;
+import net.minecraft.util.Formatting;
+import net.minecraft.util.Identifier;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import java.awt.*;
public class RenderHelper {
+ private static final Vec3d ONE = new Vec3d(1, 1, 1);
+
public static void renderFilledThroughWallsWithBeaconBeam(WorldRenderContext context, BlockPos pos, float[] colorComponents, float alpha) {
renderFilledThroughWalls(context, pos, colorComponents, alpha);
renderBeaconBeam(context, pos, colorComponents);
@@ -17,14 +24,36 @@ public class RenderHelper {
public static void renderFilledThroughWalls(WorldRenderContext context, BlockPos pos, float[] colorComponents, float alpha) {
Renderer3d.renderThroughWalls();
- Renderer3d.renderFilled(context.matrixStack(), new Color(colorComponents[0], colorComponents[1], colorComponents[2], alpha), Vec3d.of(pos), new Vec3d(1, 1, 1));
+ renderFilled(context, pos, colorComponents, alpha);
Renderer3d.stopRenderThroughWalls();
}
+ public static void renderFilledIfVisible(WorldRenderContext context, BlockPos pos, float[] colorComponents, float alpha) {
+ if (FrustumUtils.isVisible(pos.getX(), pos.getY(), pos.getZ(), pos.getX() + 1, pos.getY() + 1, pos.getZ() + 1)) {
+ renderFilled(context, pos, colorComponents, alpha);
+ }
+ }
+
+ public static void renderFilled(WorldRenderContext context, BlockPos pos, float[] colorComponents, float alpha) {
+ Renderer3d.renderFilled(context.matrixStack(), new Color(colorComponents[0], colorComponents[1], colorComponents[2], alpha), Vec3d.of(pos), ONE);
+ }
+
public static void renderBeaconBeam(WorldRenderContext context, BlockPos pos, float[] colorComponents) {
context.matrixStack().push();
context.matrixStack().translate(pos.getX() - context.camera().getPos().x, pos.getY() - context.camera().getPos().y, pos.getZ() - context.camera().getPos().z);
BeaconBlockEntityRendererInvoker.renderBeam(context.matrixStack(), context.consumers(), context.tickDelta(), context.world().getTime(), 0, BeaconBlockEntityRenderer.MAX_BEAM_HEIGHT, colorComponents);
context.matrixStack().pop();
}
+
+ public static void displayTitleAndPlaySound(int stayTicks, int fadeOutTicks, String titleKey, Formatting formatting) {
+ MinecraftClient.getInstance().inGameHud.setTitleTicks(0, stayTicks, fadeOutTicks);
+ MinecraftClient.getInstance().inGameHud.setTitle(Text.translatable(titleKey).formatted(formatting));
+ playNotificationSound();
+ }
+
+ private static void playNotificationSound() {
+ if (MinecraftClient.getInstance().player != null) {
+ MinecraftClient.getInstance().player.playSound(SoundEvent.of(new Identifier("entity.experience_orb.pickup")), 100f, 0.1f);
+ }
+ }
}
diff --git a/src/main/java/me/xmrvizzy/skyblocker/utils/SlayerUtils.java b/src/main/java/me/xmrvizzy/skyblocker/utils/SlayerUtils.java
new file mode 100644
index 00000000..6bc09456
--- /dev/null
+++ b/src/main/java/me/xmrvizzy/skyblocker/utils/SlayerUtils.java
@@ -0,0 +1,66 @@
+package me.xmrvizzy.skyblocker.utils;
+
+import net.minecraft.client.MinecraftClient;
+import net.minecraft.client.network.ClientPlayerEntity;
+import net.minecraft.entity.Entity;
+import net.minecraft.entity.decoration.ArmorStandEntity;
+import net.minecraft.scoreboard.Scoreboard;
+import net.minecraft.scoreboard.ScoreboardObjective;
+import net.minecraft.scoreboard.ScoreboardPlayerScore;
+import net.minecraft.scoreboard.Team;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.List;
+
+//TODO Slayer Packet system that can provide information about the current slayer boss, abstract so that different bosses can have different info
+public class SlayerUtils {
+ private static final Logger LOGGER = LoggerFactory.getLogger(SlayerUtils.class);
+
+ //TODO: Cache this, probably included in Packet system
+ public static List<Entity> getEntityArmorStands(Entity entity) {
+ return entity.getEntityWorld().getOtherEntities(entity, entity.getBoundingBox().expand(1F, 2.5F, 1F), x -> x instanceof ArmorStandEntity && x.hasCustomName());
+ }
+
+ //Eventually this should be modified so that if you hit a slayer boss all slayer features will work on that boss.
+ public static Entity getSlayerEntity() {
+ if (MinecraftClient.getInstance().world != null) {
+ for (Entity entity : MinecraftClient.getInstance().world.getEntities()) {
+ //Check if entity is Bloodfiend
+ if (entity.hasCustomName() && entity.getCustomName().getString().contains("Bloodfiend")) {
+ //Grab the players username
+ String username = MinecraftClient.getInstance().getSession().getUsername();
+ //Check all armor stands around the boss
+ for (Entity armorStand : getEntityArmorStands(entity)) {
+ //Check if the display name contains the players username
+ if (armorStand.getDisplayName().getString().contains(username)) {
+ return entity;
+ }
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ public static boolean isInSlayer() {
+ try {
+ ClientPlayerEntity client = MinecraftClient.getInstance().player;
+ if (client == null) return false;
+ Scoreboard scoreboard = MinecraftClient.getInstance().player.getScoreboard();
+ ScoreboardObjective objective = scoreboard.getObjectiveForSlot(1);
+ for (ScoreboardPlayerScore score : scoreboard.getAllPlayerScores(objective)) {
+ Team team = scoreboard.getPlayerTeam(score.getPlayerName());
+ if (team != null) {
+ String line = team.getPrefix().getString() + team.getSuffix().getString();
+ if (line.contains("Slay the boss!")) {
+ return true;
+ }
+ }
+ }
+ } catch (NullPointerException e) {
+ LOGGER.error("[Skyblocker] Error while checking if player is in slayer", e);
+ }
+ return false;
+ }
+} \ No newline at end of file
diff --git a/src/main/java/me/xmrvizzy/skyblocker/utils/Utils.java b/src/main/java/me/xmrvizzy/skyblocker/utils/Utils.java
index d961ba7e..35dfd368 100644
--- a/src/main/java/me/xmrvizzy/skyblocker/utils/Utils.java
+++ b/src/main/java/me/xmrvizzy/skyblocker/utils/Utils.java
@@ -4,6 +4,7 @@ import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import me.xmrvizzy.skyblocker.SkyblockerMod;
import me.xmrvizzy.skyblocker.skyblock.item.PriceInfoTooltip;
+import me.xmrvizzy.skyblocker.skyblock.rift.TheRift;
import net.fabricmc.fabric.api.client.item.v1.ItemTooltipCallback;
import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents;
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents;
@@ -52,6 +53,10 @@ public class Utils {
return isInDungeons;
}
+ public static boolean isInTheRift() {
+ return getLocationRaw().equals(TheRift.LOCATION);
+ }
+
public static boolean isInjected() {
return isInjected;
}
diff --git a/src/main/resources/assets/skyblocker/lang/en_us.json b/src/main/resources/assets/skyblocker/lang/en_us.json
index fc632560..df610333 100644
--- a/src/main/resources/assets/skyblocker/lang/en_us.json
+++ b/src/main/resources/assets/skyblocker/lang/en_us.json
@@ -201,6 +201,9 @@
"text.autoconfig.skyblocker.option.locations.dwarvenMines.dwarvenHud.enableBackground": "Enable Background",
"text.autoconfig.skyblocker.option.locations.dwarvenMines.dwarvenHud.x": "X",
"text.autoconfig.skyblocker.option.locations.dwarvenMines.dwarvenHud.y": "Y",
+
+ "text.autoconfig.skyblocker.option.locations.rift": "The Rift",
+ "text.autoconfig.skyblocker.option.locations.rift.mirrorverseWaypoints": "Enable Mirrorverse Waypoints",
"text.autoconfig.skyblocker.category.messages": "Messages",
"text.autoconfig.skyblocker.option.messages.chatFilterResult.PASS": "Disabled",
@@ -218,6 +221,22 @@
"text.autoconfig.skyblocker.option.messages.hideMana": "Hide Mana Consumption Messages from Action Bar",
"text.autoconfig.skyblocker.option.messages.hideMana.@Tooltip": "Gives a better experience with FancyBar",
+ "text.autoconfig.skyblocker.category.slayer": "Slayers",
+ "text.autoconfig.skyblocker.option.slayer.vampireSlayer": "Vampire Slayer",
+ "text.autoconfig.skyblocker.option.slayer.vampireSlayer.enableEffigyWaypoints": "Enable Effigy Waypoints",
+ "text.autoconfig.skyblocker.option.slayer.vampireSlayer.compactEffigyWaypoints": "Compact Effigy Waypoints",
+ "text.autoconfig.skyblocker.option.slayer.vampireSlayer.effigyUpdateFrequency": "Effigy Waypoints Update Frequency (Ticks)",
+ "text.autoconfig.skyblocker.option.slayer.vampireSlayer.effigyUpdateFrequency.@Tooltip": "The lower the value, the more frequent the updates, which may cause lag.",
+ "text.autoconfig.skyblocker.option.slayer.vampireSlayer.enableHolyIceIndicator": "Enable Holy Ice Indicator",
+ "text.autoconfig.skyblocker.option.slayer.vampireSlayer.holyIceIndicatorTickDelay": "Holy Ice Indicator Delay (Ticks)",
+ "text.autoconfig.skyblocker.option.slayer.vampireSlayer.holyIceUpdateFrequency": "Holy Ice Indicator Update Frequency (Ticks)",
+ "text.autoconfig.skyblocker.option.slayer.vampireSlayer.holyIceUpdateFrequency.@Tooltip": "The lower the value, the more frequent the updates, which may cause lag.",
+ "text.autoconfig.skyblocker.option.slayer.vampireSlayer.enableHealingMelonIndicator": "Enable Healing Melon Indicator",
+ "text.autoconfig.skyblocker.option.slayer.vampireSlayer.healingMelonHealthThreshold": "Healing Melon Indicator Threshold (Hearts)",
+ "text.autoconfig.skyblocker.option.slayer.vampireSlayer.enableSteakStakeIndicator": "Enable Steak Stake Indicator",
+ "text.autoconfig.skyblocker.option.slayer.vampireSlayer.steakStakeUpdateFrequency": "Steak Stake Indicator Update Frequency (Ticks)",
+ "text.autoconfig.skyblocker.option.slayer.vampireSlayer.steakStakeUpdateFrequency.@Tooltip": "The lower the value, the more frequent the updates, which may cause lag.",
+
"skyblocker.update.update_message": "§b[§6Skyblocker§b] §2There is a new version available!",
"skyblocker.update.update_link": " §2§nClick here§r",
"skyblocker.update.update_message_end" : " §ato find out about latest features.",
@@ -230,6 +249,9 @@
"skyblocker.api.got_key": "§b[§6Skyblocker§b] §2Automatically set your API key!",
"skyblocker.fishing.reelNow": "Reel in now!",
+ "skyblocker.rift.healNow": "Heal now!",
+ "skyblocker.rift.iceNow": "Ice now!",
+ "skyblocker.rift.stakeNow": "Stake now!",
"skyblocker.fairySouls.markAllFound": "Marked all fairy souls in the current island as found",
"skyblocker.fairySouls.markAllMissing": "Marked all fairy souls in the current island as missing"
}
diff --git a/src/main/resources/assets/skyblocker/mirrorverse_waypoints.json b/src/main/resources/assets/skyblocker/mirrorverse_waypoints.json
new file mode 100644
index 00000000..2bc0296e
--- /dev/null
+++ b/src/main/resources/assets/skyblocker/mirrorverse_waypoints.json
@@ -0,0 +1,1019 @@
+{
+ "sections": [
+ {
+ "name": "Lava Path",
+ "waypoints": [
+ {
+ "x": -101,
+ "y": 52,
+ "z": -116
+ },
+ {
+ "x": -99,
+ "y": 52,
+ "z": -110
+ },
+ {
+ "x": -95,
+ "y": 52,
+ "z": -108
+ },
+ {
+ "x": -88,
+ "y": 52,
+ "z": -107
+ },
+ {
+ "x": -95,
+ "y": 52,
+ "z": -114
+ },
+ {
+ "x": -95,
+ "y": 52,
+ "z": -109
+ },
+ {
+ "x": -84,
+ "y": 52,
+ "z": -112
+ },
+ {
+ "x": -91,
+ "y": 52,
+ "z": -108
+ },
+ {
+ "x": -94,
+ "y": 52,
+ "z": -116
+ },
+ {
+ "x": -88,
+ "y": 52,
+ "z": -112
+ },
+ {
+ "x": -101,
+ "y": 52,
+ "z": -108
+ },
+ {
+ "x": -94,
+ "y": 52,
+ "z": -114
+ },
+ {
+ "x": -85,
+ "y": 52,
+ "z": -112
+ },
+ {
+ "x": -88,
+ "y": 52,
+ "z": -114
+ },
+ {
+ "x": -90,
+ "y": 52,
+ "z": -110
+ },
+ {
+ "x": -84,
+ "y": 52,
+ "z": -113
+ },
+ {
+ "x": -90,
+ "y": 52,
+ "z": -116
+ },
+ {
+ "x": -105,
+ "y": 52,
+ "z": -113
+ },
+ {
+ "x": -82,
+ "y": 52,
+ "z": -112
+ },
+ {
+ "x": -90,
+ "y": 52,
+ "z": -112
+ },
+ {
+ "x": -88,
+ "y": 52,
+ "z": -111
+ },
+ {
+ "x": -82,
+ "y": 52,
+ "z": -111
+ },
+ {
+ "x": -104,
+ "y": 52,
+ "z": -112
+ },
+ {
+ "x": -87,
+ "y": 52,
+ "z": -107
+ },
+ {
+ "x": -100,
+ "y": 52,
+ "z": -108
+ },
+ {
+ "x": -86,
+ "y": 52,
+ "z": -109
+ },
+ {
+ "x": -91,
+ "y": 52,
+ "z": -110
+ },
+ {
+ "x": -96,
+ "y": 52,
+ "z": -108
+ },
+ {
+ "x": -102,
+ "y": 52,
+ "z": -111
+ },
+ {
+ "x": -96,
+ "y": 52,
+ "z": -115
+ },
+ {
+ "x": -97,
+ "y": 52,
+ "z": -116
+ },
+ {
+ "x": -83,
+ "y": 52,
+ "z": -111
+ },
+ {
+ "x": -84,
+ "y": 52,
+ "z": -107
+ },
+ {
+ "x": -90,
+ "y": 52,
+ "z": -115
+ },
+ {
+ "x": -86,
+ "y": 52,
+ "z": -107
+ },
+ {
+ "x": -97,
+ "y": 52,
+ "z": -112
+ },
+ {
+ "x": -86,
+ "y": 52,
+ "z": -113
+ },
+ {
+ "x": -92,
+ "y": 52,
+ "z": -110
+ },
+ {
+ "x": -95,
+ "y": 52,
+ "z": -111
+ },
+ {
+ "x": -90,
+ "y": 52,
+ "z": -114
+ },
+ {
+ "x": -93,
+ "y": 52,
+ "z": -108
+ },
+ {
+ "x": -98,
+ "y": 52,
+ "z": -116
+ },
+ {
+ "x": -98,
+ "y": 52,
+ "z": -115
+ },
+ {
+ "x": -90,
+ "y": 52,
+ "z": -107
+ },
+ {
+ "x": -98,
+ "y": 52,
+ "z": -112
+ },
+ {
+ "x": -98,
+ "y": 52,
+ "z": -109
+ },
+ {
+ "x": -98,
+ "y": 52,
+ "z": -113
+ },
+ {
+ "x": -100,
+ "y": 52,
+ "z": -116
+ },
+ {
+ "x": -96,
+ "y": 52,
+ "z": -114
+ },
+ {
+ "x": -86,
+ "y": 52,
+ "z": -110
+ },
+ {
+ "x": -93,
+ "y": 52,
+ "z": -109
+ },
+ {
+ "x": -88,
+ "y": 52,
+ "z": -110
+ },
+ {
+ "x": -94,
+ "y": 52,
+ "z": -115
+ },
+ {
+ "x": -84,
+ "y": 52,
+ "z": -111
+ },
+ {
+ "x": -84,
+ "y": 52,
+ "z": -108
+ },
+ {
+ "x": -86,
+ "y": 52,
+ "z": -115
+ },
+ {
+ "x": -98,
+ "y": 52,
+ "z": -110
+ },
+ {
+ "x": -102,
+ "y": 52,
+ "z": -108
+ },
+ {
+ "x": -92,
+ "y": 52,
+ "z": -114
+ },
+ {
+ "x": -102,
+ "y": 52,
+ "z": -114
+ },
+ {
+ "x": -85,
+ "y": 52,
+ "z": -109
+ },
+ {
+ "x": -86,
+ "y": 52,
+ "z": -112
+ },
+ {
+ "x": -104,
+ "y": 52,
+ "z": -113
+ },
+ {
+ "x": -105,
+ "y": 52,
+ "z": -112
+ },
+ {
+ "x": -91,
+ "y": 52,
+ "z": -114
+ },
+ {
+ "x": -100,
+ "y": 52,
+ "z": -112
+ },
+ {
+ "x": -93,
+ "y": 52,
+ "z": -110
+ },
+ {
+ "x": -91,
+ "y": 52,
+ "z": -112
+ },
+ {
+ "x": -101,
+ "y": 52,
+ "z": -112
+ },
+ {
+ "x": -92,
+ "y": 52,
+ "z": -108
+ },
+ {
+ "x": -82,
+ "y": 52,
+ "z": -113
+ },
+ {
+ "x": -87,
+ "y": 52,
+ "z": -115
+ },
+ {
+ "x": -84,
+ "y": 52,
+ "z": -109
+ },
+ {
+ "x": -88,
+ "y": 52,
+ "z": -113
+ },
+ {
+ "x": -92,
+ "y": 52,
+ "z": -116
+ },
+ {
+ "x": -96,
+ "y": 52,
+ "z": -111
+ },
+ {
+ "x": -96,
+ "y": 52,
+ "z": -116
+ },
+ {
+ "x": -98,
+ "y": 52,
+ "z": -108
+ },
+ {
+ "x": -98,
+ "y": 52,
+ "z": -114
+ },
+ {
+ "x": -96,
+ "y": 52,
+ "z": -112
+ },
+ {
+ "x": -85,
+ "y": 52,
+ "z": -107
+ },
+ {
+ "x": -102,
+ "y": 52,
+ "z": -115
+ },
+ {
+ "x": -87,
+ "y": 52,
+ "z": -110
+ },
+ {
+ "x": -100,
+ "y": 52,
+ "z": -113
+ },
+ {
+ "x": -103,
+ "y": 52,
+ "z": -114
+ },
+ {
+ "x": -102,
+ "y": 52,
+ "z": -116
+ },
+ {
+ "x": -95,
+ "y": 52,
+ "z": -110
+ },
+ {
+ "x": -89,
+ "y": 52,
+ "z": -107
+ },
+ {
+ "x": -92,
+ "y": 52,
+ "z": -113
+ },
+ {
+ "x": -100,
+ "y": 52,
+ "z": -110
+ },
+ {
+ "x": -100,
+ "y": 52,
+ "z": -115
+ },
+ {
+ "x": -86,
+ "y": 52,
+ "z": -114
+ },
+ {
+ "x": -88,
+ "y": 52,
+ "z": -115
+ },
+ {
+ "x": -92,
+ "y": 52,
+ "z": -112
+ },
+ {
+ "x": -100,
+ "y": 52,
+ "z": -114
+ },
+ {
+ "x": -91,
+ "y": 52,
+ "z": -116
+ },
+ {
+ "x": -102,
+ "y": 52,
+ "z": -110
+ },
+ {
+ "x": -102,
+ "y": 52,
+ "z": -112
+ },
+ {
+ "x": -93,
+ "y": 52,
+ "z": -116
+ },
+ {
+ "x": -90,
+ "y": 52,
+ "z": -111
+ },
+ {
+ "x": -104,
+ "y": 52,
+ "z": -114
+ },
+ {
+ "x": -83,
+ "y": 52,
+ "z": -112
+ },
+ {
+ "x": -83,
+ "y": 52,
+ "z": -113
+ },
+ {
+ "x": -100,
+ "y": 52,
+ "z": -109
+ },
+ {
+ "x": -102,
+ "y": 52,
+ "z": -109
+ },
+ {
+ "x": -90,
+ "y": 52,
+ "z": -108
+ },
+ {
+ "x": -97,
+ "y": 52,
+ "z": -108
+ }
+ ]
+ },
+ {
+ "name": "Upside Down Parkour",
+ "waypoints": [
+ {
+ "x": -137,
+ "y": 39,
+ "z": -104
+ },
+ {
+ "x": -169,
+ "y": 42,
+ "z": -116
+ },
+ {
+ "x": -173,
+ "y": 43,
+ "z": -112
+ },
+ {
+ "x": -197,
+ "y": 39,
+ "z": -92
+ },
+ {
+ "x": -161,
+ "y": 39,
+ "z": -92
+ },
+ {
+ "x": -137,
+ "y": 40,
+ "z": -116
+ },
+ {
+ "x": -213,
+ "y": 41,
+ "z": -116
+ },
+ {
+ "x": -173,
+ "y": 41,
+ "z": -96
+ },
+ {
+ "x": -205,
+ "y": 41,
+ "z": -100
+ },
+ {
+ "x": -205,
+ "y": 43,
+ "z": -108
+ },
+ {
+ "x": -137,
+ "y": 41,
+ "z": -96
+ },
+ {
+ "x": -145,
+ "y": 40,
+ "z": -104
+ },
+ {
+ "x": -149,
+ "y": 43,
+ "z": -112
+ },
+ {
+ "x": -189,
+ "y": 42,
+ "z": -120
+ },
+ {
+ "x": -157,
+ "y": 41,
+ "z": -104
+ },
+ {
+ "x": -189,
+ "y": 43,
+ "z": -116
+ },
+ {
+ "x": -193,
+ "y": 42,
+ "z": -104
+ },
+ {
+ "x": -161,
+ "y": 40,
+ "z": -120
+ },
+ {
+ "x": -221,
+ "y": 43,
+ "z": -104
+ },
+ {
+ "x": -185,
+ "y": 41,
+ "z": -108
+ },
+ {
+ "x": -141,
+ "y": 41,
+ "z": -120
+ },
+ {
+ "x": -157,
+ "y": 39,
+ "z": -116
+ },
+ {
+ "x": -153,
+ "y": 40,
+ "z": -100
+ },
+ {
+ "x": -209,
+ "y": 43,
+ "z": -120
+ },
+ {
+ "x": -129,
+ "y": 39,
+ "z": -108
+ },
+ {
+ "x": -189,
+ "y": 43,
+ "z": -100
+ },
+ {
+ "x": -141,
+ "y": 42,
+ "z": -100
+ },
+ {
+ "x": -133,
+ "y": 40,
+ "z": -108
+ },
+ {
+ "x": -209,
+ "y": 42,
+ "z": -104
+ },
+ {
+ "x": -173,
+ "y": 41,
+ "z": -100
+ },
+ {
+ "x": -189,
+ "y": 43,
+ "z": -112
+ },
+ {
+ "x": -145,
+ "y": 40,
+ "z": -108
+ },
+ {
+ "x": -217,
+ "y": 42,
+ "z": -108
+ },
+ {
+ "x": -169,
+ "y": 41,
+ "z": -120
+ },
+ {
+ "x": -165,
+ "y": 43,
+ "z": -109
+ },
+ {
+ "x": -145,
+ "y": 42,
+ "z": -116
+ },
+ {
+ "x": -165,
+ "y": 42,
+ "z": -104
+ },
+ {
+ "x": -181,
+ "y": 40,
+ "z": -112
+ },
+ {
+ "x": -193,
+ "y": 41,
+ "z": -108
+ },
+ {
+ "x": -201,
+ "y": 40,
+ "z": -96
+ },
+ {
+ "x": -137,
+ "y": 41,
+ "z": -124
+ },
+ {
+ "x": -173,
+ "y": 43,
+ "z": -108
+ },
+ {
+ "x": -133,
+ "y": 40,
+ "z": -100
+ },
+ {
+ "x": -201,
+ "y": 40,
+ "z": -116
+ },
+ {
+ "x": -185,
+ "y": 41,
+ "z": -108
+ },
+ {
+ "x": -125,
+ "y": 39,
+ "z": -108
+ },
+ {
+ "x": -161,
+ "y": 42,
+ "z": -112
+ },
+ {
+ "x": -165,
+ "y": 40,
+ "z": -96
+ },
+ {
+ "x": -141,
+ "y": 39,
+ "z": -112
+ },
+ {
+ "x": -177,
+ "y": 39,
+ "z": -92
+ },
+ {
+ "x": -213,
+ "y": 41,
+ "z": -112
+ },
+ {
+ "x": -153,
+ "y": 42,
+ "z": -108
+ },
+ {
+ "x": -205,
+ "y": 42,
+ "z": -120
+ },
+ {
+ "x": -197,
+ "y": 43,
+ "z": -112
+ },
+ {
+ "x": -181,
+ "y": 42,
+ "z": -104
+ },
+ {
+ "x": -165,
+ "y": 41,
+ "z": -100
+ },
+ {
+ "x": -193,
+ "y": 42,
+ "z": -96
+ },
+ {
+ "x": -133,
+ "y": 40,
+ "z": -120
+ },
+ {
+ "x": -185,
+ "y": 41,
+ "z": -100
+ },
+ {
+ "x": -165,
+ "y": 41,
+ "z": -124
+ },
+ {
+ "x": -177,
+ "y": 40,
+ "z": -104
+ },
+ {
+ "x": -157,
+ "y": 40,
+ "z": -96
+ },
+ {
+ "x": -205,
+ "y": 41,
+ "z": -116
+ },
+ {
+ "x": -181,
+ "y": 40,
+ "z": -96
+ },
+ {
+ "x": -201,
+ "y": 43,
+ "z": -108
+ },
+ {
+ "x": -185,
+ "y": 41,
+ "z": -116
+ }
+ ]
+ },
+ {
+ "name": "Turbulator Parkour",
+ "waypoints": [
+ {
+ "x": -302,
+ "y": 34,
+ "z": -107
+ },
+ {
+ "x": -304,
+ "y": 52,
+ "z": -109
+ },
+ {
+ "x": -306,
+ "y": 16,
+ "z": -107
+ },
+ {
+ "x": -304,
+ "y": 12,
+ "z": -107
+ },
+ {
+ "x": -308,
+ "y": 6,
+ "z": -105
+ },
+ {
+ "x": -302,
+ "y": 44,
+ "z": -107
+ },
+ {
+ "x": -306,
+ "y": 24,
+ "z": -109
+ },
+ {
+ "x": -302,
+ "y": 18,
+ "z": -111
+ },
+ {
+ "x": -300,
+ "y": 36,
+ "z": -109
+ },
+ {
+ "x": -304,
+ "y": 30,
+ "z": -103
+ },
+ {
+ "x": -302,
+ "y": 26,
+ "z": -111
+ },
+ {
+ "x": -308,
+ "y": 14,
+ "z": -103
+ },
+ {
+ "x": -300,
+ "y": 46,
+ "z": -103
+ },
+ {
+ "x": -300,
+ "y": 10,
+ "z": -111
+ },
+ {
+ "x": -300,
+ "y": 20,
+ "z": -107
+ },
+ {
+ "x": -306,
+ "y": 54,
+ "z": -111
+ },
+ {
+ "x": -306,
+ "y": 4,
+ "z": -103
+ },
+ {
+ "x": -300,
+ "y": 28,
+ "z": -107
+ },
+ {
+ "x": -306,
+ "y": 42,
+ "z": -111
+ },
+ {
+ "x": -308,
+ "y": 50,
+ "z": -105
+ },
+ {
+ "x": -304,
+ "y": 48,
+ "z": -107
+ },
+ {
+ "x": -302,
+ "y": 38,
+ "z": -105
+ },
+ {
+ "x": -304,
+ "y": 22,
+ "z": -111
+ },
+ {
+ "x": -304,
+ "y": 2,
+ "z": -107
+ },
+ {
+ "x": -304,
+ "y": 40,
+ "z": -107
+ },
+ {
+ "x": -306,
+ "y": 32,
+ "z": -105
+ },
+ {
+ "x": -304,
+ "y": 8,
+ "z": -109
+ }
+ ]
+ }
+ ]
+} \ No newline at end of file
diff --git a/src/main/resources/skyblocker.mixins.json b/src/main/resources/skyblocker.mixins.json
index 253e42d7..701d54e5 100644
--- a/src/main/resources/skyblocker.mixins.json
+++ b/src/main/resources/skyblocker.mixins.json
@@ -18,7 +18,8 @@
"PlayerListHudAccessor",
"PlayerListHudMixin",
"RecipeBookWidgetAccessor",
- "accessor.BeaconBlockEntityRendererInvoker"
+ "accessor.BeaconBlockEntityRendererInvoker",
+ "accessor.FrustumInvoker"
],
"injectors": {
"defaultRequire": 1