aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/me/xmrvizzy/skyblocker
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/me/xmrvizzy/skyblocker')
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/SkyblockerMod.java2
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/config/SkyblockerConfig.java9
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/mixin/YggdrasilServicesKeyInfoMixin.java49
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/skyblock/special/SpecialEffects.java96
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/utils/render/RenderHelper.java2
5 files changed, 157 insertions, 1 deletions
diff --git a/src/main/java/me/xmrvizzy/skyblocker/SkyblockerMod.java b/src/main/java/me/xmrvizzy/skyblocker/SkyblockerMod.java
index 5c7f2a99..cdf78d73 100644
--- a/src/main/java/me/xmrvizzy/skyblocker/SkyblockerMod.java
+++ b/src/main/java/me/xmrvizzy/skyblocker/SkyblockerMod.java
@@ -15,6 +15,7 @@ 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.shortcut.Shortcuts;
+import me.xmrvizzy.skyblocker.skyblock.special.SpecialEffects;
import me.xmrvizzy.skyblocker.skyblock.tabhud.TabHud;
import me.xmrvizzy.skyblocker.skyblock.tabhud.screenbuilder.ScreenMaster;
import me.xmrvizzy.skyblocker.skyblock.tabhud.util.PlayerListMgr;
@@ -101,6 +102,7 @@ public class SkyblockerMod implements ClientModInitializer {
CustomArmorTrims.init();
TicTacToe.init();
QuiverWarning.init();
+ SpecialEffects.init();
containerSolverManager.init();
statusBarTracker.init();
scheduler.scheduleCyclic(Utils::update, 20);
diff --git a/src/main/java/me/xmrvizzy/skyblocker/config/SkyblockerConfig.java b/src/main/java/me/xmrvizzy/skyblocker/config/SkyblockerConfig.java
index 12978cdb..5e729f19 100644
--- a/src/main/java/me/xmrvizzy/skyblocker/config/SkyblockerConfig.java
+++ b/src/main/java/me/xmrvizzy/skyblocker/config/SkyblockerConfig.java
@@ -189,6 +189,10 @@ public class SkyblockerConfig implements ConfigData {
@ConfigEntry.Category("itemInfoDisplay")
@ConfigEntry.Gui.CollapsibleObject
public ItemInfoDisplay itemInfoDisplay = new ItemInfoDisplay();
+
+ @ConfigEntry.Category("specialEffects")
+ @ConfigEntry.Gui.CollapsibleObject
+ public SpecialEffects specialEffects = new SpecialEffects();
@ConfigEntry.Category("hitbox")
@ConfigEntry.Gui.CollapsibleObject()
@@ -406,6 +410,11 @@ public class SkyblockerConfig implements ConfigData {
@ConfigEntry.Gui.Tooltip
public boolean attributeShardInfo = true;
}
+
+ public static class SpecialEffects {
+ @ConfigEntry.Gui.Tooltip
+ public boolean rareDungeonDropEffects = true;
+ }
public static class Locations {
@ConfigEntry.Category("barn")
diff --git a/src/main/java/me/xmrvizzy/skyblocker/mixin/YggdrasilServicesKeyInfoMixin.java b/src/main/java/me/xmrvizzy/skyblocker/mixin/YggdrasilServicesKeyInfoMixin.java
new file mode 100644
index 00000000..3416e282
--- /dev/null
+++ b/src/main/java/me/xmrvizzy/skyblocker/mixin/YggdrasilServicesKeyInfoMixin.java
@@ -0,0 +1,49 @@
+package me.xmrvizzy.skyblocker.mixin;
+
+import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
+import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
+import com.mojang.authlib.yggdrasil.YggdrasilServicesKeyInfo;
+import me.xmrvizzy.skyblocker.utils.Utils;
+import org.slf4j.Logger;
+import org.spongepowered.asm.mixin.Final;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.Shadow;
+import org.spongepowered.asm.mixin.Unique;
+import org.spongepowered.asm.mixin.injection.At;
+
+import java.util.ArrayList;
+import java.util.Base64;
+import java.util.List;
+import java.util.Map;
+
+@Mixin(value = YggdrasilServicesKeyInfo.class, remap = false)
+public class YggdrasilServicesKeyInfoMixin {
+ @Shadow
+ @Final
+ private static Logger LOGGER;
+ @Unique
+ private static final Map<String, String> REPLACEMENT_HASHMAP = Map.of();
+ @Unique
+ private static final List<Integer> ERROR_HASH_ARRAYLIST = new ArrayList<>();
+
+ @WrapOperation(method = "validateProperty", at = @At(value = "INVOKE", target = "Ljava/util/Base64$Decoder;decode(Ljava/lang/String;)[B", remap = false), remap = false)
+ private byte[] skyblocker$replaceKnownWrongBase64(Base64.Decoder decoder, String signature, Operation<byte[]> decode) {
+ try {
+ return decode.call(decoder, signature.replaceAll("[^A-Za-z0-9+/=]", ""));
+ } catch (IllegalArgumentException e) {
+ if (Utils.isOnSkyblock()) {
+ if (REPLACEMENT_HASHMAP.containsKey(signature)) {
+ return decode.call(decoder, REPLACEMENT_HASHMAP.get(signature));
+ }
+ int signatureHashCode = signature.hashCode();
+ if (!ERROR_HASH_ARRAYLIST.contains(signatureHashCode)) {
+ ERROR_HASH_ARRAYLIST.add(signatureHashCode);
+ LOGGER.warn("[Skyblocker Base64 Fixer] Failed to decode base64 string No.{}: {}", ERROR_HASH_ARRAYLIST.size() - 1, signature);
+ } else {
+ LOGGER.warn("[Skyblocker Base64 Fixer] Failed to decode the base64 string No.{} again", ERROR_HASH_ARRAYLIST.indexOf(signatureHashCode));
+ }
+ }
+ throw e;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/special/SpecialEffects.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/special/SpecialEffects.java
new file mode 100644
index 00000000..a3d7e5c5
--- /dev/null
+++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/special/SpecialEffects.java
@@ -0,0 +1,96 @@
+package me.xmrvizzy.skyblocker.skyblock.special;
+
+import com.mojang.blaze3d.systems.RenderSystem;
+import me.xmrvizzy.skyblocker.config.SkyblockerConfig;
+import me.xmrvizzy.skyblocker.utils.Utils;
+import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents;
+import net.minecraft.client.MinecraftClient;
+import net.minecraft.enchantment.Enchantments;
+import net.minecraft.item.ItemStack;
+import net.minecraft.item.Items;
+import net.minecraft.nbt.StringNbtReader;
+import net.minecraft.particle.ParticleTypes;
+import net.minecraft.text.Text;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class SpecialEffects {
+ private static final Logger LOGGER = LoggerFactory.getLogger(SpecialEffects.class);
+ private static final Pattern DROP_PATTERN = Pattern.compile("(?:\\[[A-Z+]+] )?(?<player>[A-Za-z0-9_]+) unlocked (?<item>.+)!");
+ private static final ItemStack NECRON_HANDLE = new ItemStack(Items.STICK);
+ private static final ItemStack SCROLL = new ItemStack(Items.WRITABLE_BOOK);
+ private static ItemStack TIER_5_SKULL;
+ private static ItemStack FIFTH_STAR;
+
+ static {
+ NECRON_HANDLE.addEnchantment(Enchantments.PROTECTION, 1);
+ SCROLL.addEnchantment(Enchantments.PROTECTION, 1);
+ try {
+ TIER_5_SKULL = ItemStack.fromNbt(StringNbtReader.parse("{id:\"minecraft:player_head\",Count:1,tag:{SkullOwner:{Id:[I;-1613868903,-527154034,-1445577520,748807544],Properties:{textures:[{Value:\"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOTEwZjlmMTA4NWQ0MDcxNDFlYjc3NjE3YTRhYmRhYWEwOGQ4YWYzM2I5NjAyMDBmZThjMTI2YzFkMTQ0NTY4MiJ9fX0=\"}]}}}}"));
+ FIFTH_STAR = ItemStack.fromNbt(StringNbtReader.parse("{id:\"minecraft:player_head\",Count:1,tag:{SkullOwner:{Id:[I;1904417095,756174249,-1302927470,1407004198],Properties:{textures:[{Value:\"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNzFjODA0MjUyN2Y4MWM4ZTI5M2UyODEwMTEzNDg5ZjQzOTRjYzZlZmUxNWQxYWZhYzQzMTU3MWM3M2I2MmRjNCJ9fX0=\"}]}}}}"));
+ } catch (Exception e) {
+ TIER_5_SKULL = ItemStack.EMPTY;
+ FIFTH_STAR = ItemStack.EMPTY;
+ LOGGER.error("[Skyblocker Special Effects] Failed to parse NBT for a player head!", e);
+ }
+ }
+
+ public static void init() {
+ ClientReceiveMessageEvents.GAME.register(SpecialEffects::displayRareDropEffect);
+ }
+
+ private static void displayRareDropEffect(Text message, boolean overlay) {
+ //We don't check if we're in dungeons because that check doesn't work in m7 which defeats the point of this
+ //It might also allow it to work with Croesus
+ if (Utils.isOnSkyblock() && SkyblockerConfig.get().general.specialEffects.rareDungeonDropEffects) {
+ try {
+ String stringForm = message.getString();
+ Matcher matcher = DROP_PATTERN.matcher(stringForm);
+
+ if (matcher.matches()) {
+ MinecraftClient client = MinecraftClient.getInstance();
+ String player = matcher.group("player");
+
+ if (player.equals(client.getSession().getUsername())) {
+ ItemStack stack = getStackFromName(matcher.group("item"));
+
+ if (!stack.isEmpty()) {
+ if (RenderSystem.isOnRenderThread()) {
+ client.particleManager.addEmitter(client.player, ParticleTypes.PORTAL, 30);
+ client.gameRenderer.showFloatingItem(stack);
+ } else {
+ RenderSystem.recordRenderCall(() -> {
+ client.particleManager.addEmitter(client.player, ParticleTypes.PORTAL, 30);
+ client.gameRenderer.showFloatingItem(stack);
+ });
+ }
+ }
+ }
+ }
+ } catch (Exception e) { //In case there's a regex failure or something else bad happens
+ LOGGER.error("[Skyblocker Special Effects] An unexpected exception was encountered: ", e);
+ }
+ }
+ }
+
+ private static ItemStack getStackFromName(String itemName) {
+ return switch (itemName) {
+ //M7
+ case "Necron Dye" -> new ItemStack(Items.ORANGE_DYE);
+ case "Dark Claymore" -> new ItemStack(Items.STONE_SWORD);
+ case "Necron's Handle", "Shiny Necron's Handle" -> NECRON_HANDLE;
+ case "Enchanted Book (Thunderlord VII)" -> new ItemStack(Items.ENCHANTED_BOOK);
+ case "Master Skull - Tier 5" -> TIER_5_SKULL;
+ case "Shadow Warp", "Wither Shield", "Implosion" -> SCROLL;
+ case "Fifth Master Star" -> FIFTH_STAR;
+
+ //M6
+ case "Giant's Sword" -> new ItemStack(Items.IRON_SWORD);
+
+ default -> ItemStack.EMPTY;
+ };
+ }
+}
diff --git a/src/main/java/me/xmrvizzy/skyblocker/utils/render/RenderHelper.java b/src/main/java/me/xmrvizzy/skyblocker/utils/render/RenderHelper.java
index aaf92d68..907896e2 100644
--- a/src/main/java/me/xmrvizzy/skyblocker/utils/render/RenderHelper.java
+++ b/src/main/java/me/xmrvizzy/skyblocker/utils/render/RenderHelper.java
@@ -95,7 +95,7 @@ public class RenderHelper {
matrices.translate(-camera.getX(), -camera.getY(), -camera.getZ());
buffer.begin(DrawMode.LINES, VertexFormats.LINES);
- WorldRenderer.drawBox(matrices, buffer, box, colorComponents[0] * 255f, colorComponents[1] * 255f, colorComponents[2] * 255f, 1f);
+ WorldRenderer.drawBox(matrices, buffer, box, colorComponents[0], colorComponents[1], colorComponents[2], 1f);
tessellator.draw();
matrices.pop();