aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornea <nea@nea.moe>2023-09-09 19:33:28 +0200
committernea <nea@nea.moe>2023-09-09 19:33:28 +0200
commit5b8361e41aaa5171f10059e15ffc4326de9780ea (patch)
tree2ded97e3f21133877425517474baafa770a3bcde
parent13a2f67df489e6a77fb3e61d790ef9c9c5e3576e (diff)
parentce52a805da551f4cef1b14beab58821887e349b9 (diff)
downloadNotEnoughUpdates-5b8361e41aaa5171f10059e15ffc4326de9780ea.tar.gz
NotEnoughUpdates-5b8361e41aaa5171f10059e15ffc4326de9780ea.tar.bz2
NotEnoughUpdates-5b8361e41aaa5171f10059e15ffc4326de9780ea.zip
Merge branch 'master' of github.com:NotEnoughUpdates/NotEnoughUpdates into moulconfig
-rw-r--r--config/detekt/detekt.yml4
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/core/util/render/RenderUtils.java14
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/listener/NEUEventListener.java6
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/PetInfoOverlay.java127
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/world/CrystalHollowChestHighlighter.java131
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/world/GenericBlockHighlighter.java6
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscgui/CalendarOverlay.java134
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscgui/StorageOverlay.java1
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/loaders/MinionHelperApiLoader.java2
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/render/MinionHelperOverlay.java2
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinNetHandlerPlayClient.java8
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/WorldConfig.java25
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/profileviewer/BasicPage.java3
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/profileviewer/SkyblockProfiles.java87
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/profileviewer/bestiary/BestiaryData.java1094
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/profileviewer/bestiary/BestiaryData.kt213
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/profileviewer/bestiary/BestiaryPage.java270
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/profileviewer/bestiary/BestiaryPage.kt302
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/profileviewer/level/task/MiscTaskLevel.java38
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/profileviewer/rift/RiftPage.java2
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/util/ApiUtil.java1
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/util/Constants.java2
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/util/ItemUtils.java13
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/util/ProfileApiSyncer.java39
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/util/StarCultCalculator.java48
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/util/Utils.java15
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/util/XPInformation.java47
-rw-r--r--src/main/kotlin/io/github/moulberry/notenoughupdates/util/TabSkillInfoParser.kt114
28 files changed, 1086 insertions, 1662 deletions
diff --git a/config/detekt/detekt.yml b/config/detekt/detekt.yml
index 80ff2814..dfea9a5e 100644
--- a/config/detekt/detekt.yml
+++ b/config/detekt/detekt.yml
@@ -9,3 +9,7 @@ forge:
active: true
InvalidSubscribeEvent:
active: true
+
+style:
+ MagicNumber:
+ active: false
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/util/render/RenderUtils.java b/src/main/java/io/github/moulberry/notenoughupdates/core/util/render/RenderUtils.java
index b3a84c52..5f501115 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/core/util/render/RenderUtils.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/core/util/render/RenderUtils.java
@@ -311,27 +311,29 @@ public class RenderUtils {
public static void renderBoundingBox(
BlockPos worldPos,
int rgb,
- float partialTicks
+ float partialTicks,
+ boolean disableDepth
) {
Vector3f interpolatedPlayerPosition = getInterpolatedPlayerPosition(partialTicks);
renderBoundingBoxInViewSpace(
worldPos.getX() - interpolatedPlayerPosition.x,
worldPos.getY() - interpolatedPlayerPosition.y,
worldPos.getZ() - interpolatedPlayerPosition.z,
- rgb
+ rgb,
+ disableDepth
);
}
- private static void renderBoundingBoxInViewSpace(double x, double y, double z, int rgb) {
+ private static void renderBoundingBoxInViewSpace(double x, double y, double z, int rgb, boolean disableDepth) {
AxisAlignedBB bb = new AxisAlignedBB(x, y, z, x + 1, y + 1, z + 1);
- GlStateManager.disableDepth();
+ if (disableDepth) GlStateManager.disableDepth();
GlStateManager.disableCull();
GlStateManager.disableTexture2D();
CustomItemEffects.drawFilledBoundingBox(bb, 1f, SpecialColour.special(0, (rgb >> 24) & 0xFF, rgb));
GlStateManager.enableTexture2D();
GlStateManager.enableCull();
- GlStateManager.enableDepth();
+ if (disableDepth) GlStateManager.enableDepth();
}
public static void renderBeaconBeam(BlockPos block, int rgb, float alphaMult, float partialTicks) {
@@ -395,7 +397,7 @@ public class RenderUtils {
if (distSq > 10 * 10) {
RenderUtils.renderBeaconBeam(x, y, z, rgb, 1.0f, partialTicks, true);
} else {
- RenderUtils.renderBoundingBoxInViewSpace(x, y, z, rgb);
+ RenderUtils.renderBoundingBoxInViewSpace(x, y, z, rgb, true);
}
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/listener/NEUEventListener.java b/src/main/java/io/github/moulberry/notenoughupdates/listener/NEUEventListener.java
index 4a5df63f..0b4e3934 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/listener/NEUEventListener.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/listener/NEUEventListener.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2022 NotEnoughUpdates contributors
+ * Copyright (C) 2022-2023 NotEnoughUpdates contributors
*
* This file is part of NotEnoughUpdates.
*
@@ -45,6 +45,7 @@ import io.github.moulberry.notenoughupdates.util.Constants;
import io.github.moulberry.notenoughupdates.util.NotificationHandler;
import io.github.moulberry.notenoughupdates.util.ProfileApiSyncer;
import io.github.moulberry.notenoughupdates.util.SBInfo;
+import io.github.moulberry.notenoughupdates.util.TabSkillInfoParser;
import io.github.moulberry.notenoughupdates.util.Utils;
import io.github.moulberry.notenoughupdates.util.XPInformation;
import net.minecraft.client.Minecraft;
@@ -171,8 +172,7 @@ public class NEUEventListener {
CrystalOverlay.tick();
FairySouls.getInstance().tick();
- XPInformation.getInstance().tick();
- ProfileApiSyncer.getInstance().tick();
+ TabSkillInfoParser.parseSkillInfo();
ItemCustomizeManager.tick();
BackgroundBlur.markDirty();
NPCRetexturing.getInstance().tick();
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/PetInfoOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/PetInfoOverlay.java
index 016c17f0..726856cb 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/PetInfoOverlay.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/PetInfoOverlay.java
@@ -22,8 +22,6 @@ package io.github.moulberry.notenoughupdates.miscfeatures;
import com.google.common.collect.Lists;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
-import com.google.gson.JsonArray;
-import com.google.gson.JsonElement;
import com.google.gson.JsonNull;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
@@ -36,11 +34,8 @@ import io.github.moulberry.notenoughupdates.listener.RenderListener;
import io.github.moulberry.notenoughupdates.options.NEUConfig;
import io.github.moulberry.notenoughupdates.overlays.TextOverlay;
import io.github.moulberry.notenoughupdates.overlays.TextOverlayStyle;
-import io.github.moulberry.notenoughupdates.profileviewer.ProfileViewer;
-import io.github.moulberry.notenoughupdates.profileviewer.SkyblockProfiles;
import io.github.moulberry.notenoughupdates.util.Constants;
import io.github.moulberry.notenoughupdates.util.PetLeveling;
-import io.github.moulberry.notenoughupdates.util.ProfileApiSyncer;
import io.github.moulberry.notenoughupdates.util.Utils;
import io.github.moulberry.notenoughupdates.util.XPInformation;
import net.minecraft.client.Minecraft;
@@ -54,7 +49,6 @@ import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.ChatComponentText;
import net.minecraft.util.EnumChatFormatting;
import net.minecraftforge.client.event.ClientChatReceivedEvent;
-import net.minecraftforge.event.world.WorldEvent;
import net.minecraftforge.fml.common.eventhandler.EventPriority;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.gameevent.TickEvent;
@@ -156,6 +150,10 @@ public class PetInfoOverlay extends TextOverlay {
private static long lastPetSelect = -1;
private static PetConfig config = new PetConfig();
+ public static PetConfig getConfig() {
+ return config;
+ }
+
private static long lastUpdate = 0;
private static float levelXpLast = 0;
@@ -281,110 +279,6 @@ public class PetInfoOverlay extends TextOverlay {
}
}
- private static void getAndSetPet(SkyblockProfiles profile) {
- Map<String, ProfileViewer.Level> skyblockInfo = profile.getLatestProfile().getLevelingInfo();
- Map<String, JsonArray> invInfo = profile.getLatestProfile().getInventoryInfo();
- JsonObject profileInfo = profile.getLatestProfile().getProfileJson();
- if (invInfo != null && profileInfo != null) {
- JsonObject stats = profileInfo.get("stats").getAsJsonObject();
- boolean hasBeastmasterCrest = false;
- Rarity currentBeastRarity = Rarity.COMMON;
- for (JsonElement talisman : invInfo.get("talisman_bag")) {
- if (talisman.isJsonNull()) continue;
- String internalName = talisman.getAsJsonObject().get("internalname").getAsString();
- if (internalName.startsWith("BEASTMASTER_CREST")) {
- hasBeastmasterCrest = true;
- try {
- Rarity talismanRarity = Rarity.valueOf(internalName.replace("BEASTMASTER_CREST_", ""));
- if (talismanRarity.beastcreatMultiplyer > currentBeastRarity.beastcreatMultiplyer)
- currentBeastRarity = talismanRarity;
- } catch (Exception ignored) {
- }
- }
- }
- if (hasBeastmasterCrest) {
- if (stats.has("mythos_kills")) {
- int mk = stats.get("mythos_kills").getAsInt();
- float petXpBoost = mk > 10000 ? 1f : mk > 7500 ? 0.9f : mk > 5000 ? 0.8f : mk > 2500 ? 0.7f :
- mk > 1000
- ? 0.6f
- : mk > 500
- ? 0.5f
- : mk > 250
- ? 0.4f
- : mk > 100
- ? 0.3f
- : mk > 25 ? 0.2f : 0.1f;
- config.beastMultiplier = petXpBoost * currentBeastRarity.beastcreatMultiplyer;
- } else {
- config.beastMultiplier = 0.1f * currentBeastRarity.beastcreatMultiplyer;
- }
- }
- }
- if (skyblockInfo != null && profile.getLatestProfile().skillsApiEnabled()) {
- config.tamingLevel = (int) skyblockInfo.get("taming").level;
- }
-
- //JsonObject petObject = profile.getPetsInfo(profile.getLatestProfile());
- /*JsonObject petsJson = Constants.PETS;
- if(petsJson != null) {
- if(petObject != null) {
- boolean forceUpdateLevels = System.currentTimeMillis() - lastXpGain > 30000;
- Set<String> foundPets = new HashSet<>();
- Set<Pet> addedPets = new HashSet<>();
- for(int i = 0; i < petObject.getAsJsonArray("pets").size(); i++) {
- JsonElement petElement = petObject.getAsJsonArray("pets").get(i);
- JsonObject petObj = petElement.getAsJsonObject();
- Pet pet = new Pet();
- pet.petType = petObj.get("type").getAsString();
- Rarity rarity;
- try {
- rarity = Rarity.valueOf(petObj.get("tier").getAsString());
- } catch(Exception ignored) {
- rarity = Rarity.COMMON;
- }
- pet.rarity = rarity;
- pet.petLevel = GuiProfileViewer.getPetLevel(petsJson.get("pet_levels").getAsJsonArray(), rarity.petOffset, petObj.get("exp").getAsFloat());
- JsonElement heldItem = petObj.get("heldItem");
- pet.petItem = heldItem.isJsonNull() ? null : heldItem.getAsString();
- if(rarity != Rarity.MYTHIC && pet.petItem != null && pet.petItem.equals("PET_ITEM_TIER_BOOST")) {
- rarity = Rarity.values()[rarity.ordinal()+1];
- }
- JsonObject petTypes = petsJson.get("pet_types").getAsJsonObject();
- pet.petXpType = petTypes.has(pet.petType) ? petTypes.get(pet.petType.toUpperCase()).getAsString().toLowerCase() : "unknown";
-
- Pet closest = null;
- if(petList.containsKey(pet.petType + ";" + pet.rarity.petId)) {
- closest = getClosestPet(pet);
- if(addedPets.contains(closest)) {
- closest = null;
- }
-
- if(closest != null) {
- if(!forceUpdateLevels || Math.floor(pet.petLevel.level) < Math.floor(closest.petLevel.level)) {
- pet.petLevel = closest.petLevel;
- }
- petList.get(pet.petType + ";" + pet.rarity.petId).remove(closest);
- }
- }
- foundPets.add(pet.petType + ";" + pet.rarity.petId);
- petList.computeIfAbsent(pet.petType + ";" + pet.rarity.petId, k->new HashSet<>()).add(pet);
- addedPets.add(pet);
-
- if(petObj.get("active").getAsBoolean()) {
- if(currentPet == null && !setActivePet) {
- currentPet = pet;
- } else if(closest == currentPet) {
- currentPet = pet;
- }
- }
- }
- petList.keySet().retainAll(foundPets);
- setActivePet = true;
- }
- }*/
- }
-
private float interp(float now, float last) {
float interp = now;
if (last >= 0 && last != now) {
@@ -659,12 +553,6 @@ public class PetInfoOverlay extends TextOverlay {
return;
}
- int updateTime = 60000;
-
- if (NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard()) {
- ProfileApiSyncer.getInstance().requestResync("petinfo", updateTime, () -> {}, PetInfoOverlay::getAndSetPet);
- }
-
Pet currentPet = getCurrentPet();
if (currentPet == null) {
overlayStrings = null;
@@ -1097,13 +985,6 @@ public class PetInfoOverlay extends TextOverlay {
}
}
- @SubscribeEvent
- public void switchWorld(WorldEvent.Load event) {
- if (NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard()) {
- ProfileApiSyncer.getInstance().requestResync("petinfo_quick", 10000, () -> {}, PetInfoOverlay::getAndSetPet);
- }
- }
-
private int lastLevelHovered = 0;
private static final Pattern AUTOPET_EQUIP = Pattern.compile(
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/world/CrystalHollowChestHighlighter.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/world/CrystalHollowChestHighlighter.java
new file mode 100644
index 00000000..61c96aad
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/world/CrystalHollowChestHighlighter.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2023 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.miscfeatures.world;
+
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe;
+import io.github.moulberry.notenoughupdates.core.util.render.RenderUtils;
+import io.github.moulberry.notenoughupdates.util.SBInfo;
+import io.github.moulberry.notenoughupdates.util.SpecialColour;
+import net.minecraft.block.Block;
+import net.minecraft.block.state.IBlockState;
+import net.minecraft.client.Minecraft;
+import net.minecraft.init.Blocks;
+import net.minecraft.network.play.server.S22PacketMultiBlockChange;
+import net.minecraft.network.play.server.S23PacketBlockChange;
+import net.minecraft.util.BlockPos;
+import net.minecraft.util.Vec3;
+import net.minecraft.world.World;
+import net.minecraftforge.client.event.RenderWorldLastEvent;
+import net.minecraftforge.event.entity.player.PlayerInteractEvent;
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
+import net.minecraftforge.fml.common.gameevent.TickEvent;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+@NEUAutoSubscribe
+public class CrystalHollowChestHighlighter extends GenericBlockHighlighter {
+
+ // Because ConcurrentModificationException is the bane of me
+ public static CopyOnWriteArrayList<BlockPos> markedBlocks = new CopyOnWriteArrayList<>();
+
+ public static void processBlockChangePacket(S23PacketBlockChange packetIn) {
+ BlockPos pos = packetIn.getBlockPosition();
+ if (packetIn.blockState == null) return;
+ checkForChest(pos, packetIn.blockState);
+ }
+
+ public static void processMultiBlockChangePacket(S22PacketMultiBlockChange packetIn) {
+ for (S22PacketMultiBlockChange.BlockUpdateData blockChanged : packetIn.getChangedBlocks()) {
+ BlockPos pos = blockChanged.getPos();
+ checkForChest(pos, blockChanged.getBlockState());
+ }
+ }
+
+ public static void checkForChest(BlockPos pos, IBlockState blockState) {
+ IBlockState oldState = Minecraft.getMinecraft().theWorld.getBlockState(pos);
+
+ if ((oldState.getBlock() == Blocks.air || oldState.getBlock() == Blocks.stone) &&
+ blockState.getBlock() == Blocks.chest) {
+
+ // Only add if in a 10x10x10 area. Minimises other players' chests being caught
+ if (Minecraft.getMinecraft().thePlayer.getEntityBoundingBox().expand(10, 10, 10).isVecInside(new Vec3(pos))) {
+ markedBlocks.add(pos);
+ }
+ }
+ }
+
+ @SubscribeEvent
+ public void onTick(TickEvent.ClientTickEvent event) {
+ if (!isEnabled()) return;
+
+ markedBlocks.forEach(this::tryRegisterInterest);
+
+ // Here to catch chests that get highlighted by other people after they open them, and
+ // any highlighted blocks in which the chest despawned in
+ List<BlockPos> blockToRemove = new ArrayList<>();
+ highlightedBlocks.forEach(it -> {
+ if (Minecraft.getMinecraft().theWorld.getBlockState(it).getBlock() != Blocks.chest) {
+ blockToRemove.add(it);
+ }
+ });
+
+ blockToRemove.forEach(highlightedBlocks::remove);
+ }
+
+ @SubscribeEvent
+ public void onBlockInteraction(PlayerInteractEvent event) {
+ if (event.action == PlayerInteractEvent.Action.RIGHT_CLICK_BLOCK) {
+ markedBlocks.remove(event.pos);
+ highlightedBlocks.remove(event.pos);
+ }
+ }
+
+ @Override
+ public void onWorldRenderLast(RenderWorldLastEvent event) {
+ if (!isEnabled()) return;
+ World w = Minecraft.getMinecraft().theWorld;
+ if (w == null) return;
+ for (BlockPos blockPos : highlightedBlocks) {
+ RenderUtils.renderBoundingBox(blockPos, getColor(blockPos), event.partialTicks, false);
+ }
+ }
+
+ @Override
+ protected boolean isEnabled() {
+ return "crystal_hollows".equals(SBInfo.getInstance().getLocation()) &&
+ NotEnoughUpdates.INSTANCE.config.world.highlightCrystalHollowChests;
+ }
+
+ @Override
+ protected boolean isValidHighlightSpot(BlockPos key) {
+ World w = Minecraft.getMinecraft().theWorld;
+ if (w == null) return false;
+ Block b = w.getBlockState(key).getBlock();
+ return b == Blocks.chest;
+ }
+
+ @Override
+ protected int getColor(BlockPos blockPos) {
+ return SpecialColour.specialToChromaRGB(NotEnoughUpdates.INSTANCE.config.world.crystalHollowChestColor);
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/world/GenericBlockHighlighter.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/world/GenericBlockHighlighter.java
index 67d6f46e..5cacff2b 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/world/GenericBlockHighlighter.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/world/GenericBlockHighlighter.java
@@ -49,7 +49,7 @@ public abstract class GenericBlockHighlighter {
World w = Minecraft.getMinecraft().theWorld;
if (w == null) return;
for (BlockPos blockPos : highlightedBlocks) {
- RenderUtils.renderBoundingBox(blockPos, getColor(blockPos), event.partialTicks);
+ RenderUtils.renderBoundingBox(blockPos, getColor(blockPos), event.partialTicks, true);
}
}
@@ -110,6 +110,10 @@ public abstract class GenericBlockHighlighter {
highlightedBlocks.clear();
}
+ public boolean tryRegisterInterest(BlockPos pos) {
+ return tryRegisterInterest(pos.getX(), pos.getY(), pos.getZ());
+ }
+
public boolean tryRegisterInterest(double x, double y, double z) {
BlockPos blockPos = new BlockPos(x, y, z);
boolean contains = highlightedBlocks.contains(blockPos);
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/CalendarOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/CalendarOverlay.java
index 61c5915d..c83b310c 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/CalendarOverlay.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/CalendarOverlay.java
@@ -26,7 +26,9 @@ import com.google.gson.JsonPrimitive;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe;
import io.github.moulberry.notenoughupdates.core.BackgroundBlur;
+import io.github.moulberry.notenoughupdates.events.RepositoryReloadEvent;
import io.github.moulberry.notenoughupdates.util.ItemUtils;
+import io.github.moulberry.notenoughupdates.util.JsonUtils;
import io.github.moulberry.notenoughupdates.util.SkyBlockTime;
import io.github.moulberry.notenoughupdates.util.Utils;
import kotlin.Pair;
@@ -53,6 +55,7 @@ import net.minecraftforge.client.event.RenderGameOverlayEvent;
import net.minecraftforge.fml.common.eventhandler.EventPriority;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.gameevent.TickEvent;
+import org.jetbrains.annotations.NotNull;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.GL11;
@@ -63,13 +66,12 @@ import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.TreeMap;
-import java.util.concurrent.TimeUnit;
+import java.util.TreeSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
@@ -87,6 +89,11 @@ public class CalendarOverlay {
private static boolean enabled = false;
public static boolean ableToClickCalendar = true;
+ long thunderStormEpoch = 1692826500000L;
+ long rainInterval = 3600000L;
+ long thunderFrequency = 3;
+ long rainDuration = 1200 * 1000L;
+ List<Pair<Long, SBEvent>> externalEvents = new ArrayList<>();
public static void setEnabled(boolean enabled) {
CalendarOverlay.enabled = enabled;
@@ -127,6 +134,11 @@ public class CalendarOverlay {
private static final ItemStack DA_STACK; // Dark Auction
private static final ItemStack JF_STACK; // Jacob's Farming Contest
+ private static final ItemStack STAR_CULT_STACK = Utils.createItemStack(
+ Items.nether_star,
+ "Cult of the Fallen Star",
+ "NEU Calendar Item"
+ ); // Star Cult Stack
static {
NBTTagCompound tag = new NBTTagCompound();
@@ -209,7 +221,7 @@ public class CalendarOverlay {
}
public Set<SBEvent> getEventsAt(long timestamp) {
- return eventMap.computeIfAbsent(timestamp, k -> new HashSet<>());
+ return eventMap.computeIfAbsent(timestamp, k -> new TreeSet<>());
}
JsonObject getFarmingEventTypes() {
@@ -256,30 +268,70 @@ public class CalendarOverlay {
}
public void populateDefaultEvents() {
- if (eventMap.isEmpty() || eventMap.size() <= 20) {
+ if (eventMap.size() <= 20) {
fillRepeatingEvents(25 - eventMap.size());
fillSpecialMayors(4);
fillWeather();
+ fillRepoMandatedEvents();
+ fillStarCult();
+ }
+ }
+
+ public void fillRepoMandatedEvents() {
+ for (Pair<Long, SBEvent> externalEvent : externalEvents) {
+ addEvent(
+ SkyBlockTime.Companion.fromInstant(Instant.ofEpochMilli(externalEvent.component1())),
+ externalEvent.component2()
+ );
+ }
+ }
+
+ public void fillStarCult() {
+ SkyBlockTime now = SkyBlockTime.now();
+
+ long STAR_CULT_DURATION = 60 * 1000L * 6;
+ List<SkyBlockTime> allTimes = new ArrayList<>();
+ allTimes.add(new SkyBlockTime(now.getYear() - 1, 12, 28, 0, 0, 0));
+ for (int i = 1; i <= 12; i++) {
+ for (int d = 7; d < 30; d += 7) {
+ allTimes.add(new SkyBlockTime(now.getYear(), i, d, 0, 0, 0));
+ }
+ }
+ for (SkyBlockTime allTime : allTimes) {
+ addEvent(
+ allTime,
+ new SBEvent(
+ "starcult",
+ "§3Cult of the Fallen Star",
+ false,
+ STAR_CULT_STACK,
+ Arrays.asList(
+ "§3The Cult of the Fallen Star meets then.",
+ "§3Attending may give a reward",
+ "§3You can find them near the Star in the Dwarven Mines"
+ ),
+ STAR_CULT_DURATION,
+ true
+ )
+ );
}
}
private void fillWeather() {
- long rainInterval = 4850 * 1000L;
- long rainingTime = 1000 * 1000L;
- long thunderStormEpoch = 1668551956000L - rainingTime;
+
long currentTime = System.currentTimeMillis();
- long timeSinceLastThunderStart = (currentTime - thunderStormEpoch) % (rainInterval * 4);
+ long timeSinceLastThunderStart = (currentTime - thunderStormEpoch) % (rainInterval * thunderFrequency);
long lastThunderStart = currentTime - timeSinceLastThunderStart;
for (int i = 0; i < 11; i++) {
long eventTimer = lastThunderStart + rainInterval * i;
- if (i % 4 == 0) {
+ if (i % thunderFrequency == 0) {
addEvent(SkyBlockTime.Companion.fromInstant(Instant.ofEpochMilli(eventTimer)), new SBEvent(
"spiders_den_thunder",
"§9Spider's Den Thunder",
true,
new ItemStack(Blocks.slime_block),
Arrays.asList("§aIt will rain in the Spider's Den", "§aand Toxic Rain Slimes will spawn"),
- rainingTime,
+ rainDuration,
true
));
} else {
@@ -291,7 +343,7 @@ public class CalendarOverlay {
false,
new ItemStack(Items.slime_ball),
Arrays.asList("§aIt will rain in the Spider's Den", "§aand Rain Slimes will spawn"),
- rainingTime,
+ rainDuration,
true
)
);
@@ -301,6 +353,49 @@ public class CalendarOverlay {
}
@SubscribeEvent
+ public void tick(RepositoryReloadEvent event) {
+ JsonObject calendarJson = NotEnoughUpdates.INSTANCE.manager.getJsonFromFile(new File(
+ event.getRepositoryRoot(),
+ "constants/calendar.json"
+ ));
+ if (calendarJson == null) return;
+ if (calendarJson.has("thunderEpochStart")) {
+ thunderStormEpoch = calendarJson.get("thunderEpochStart").getAsLong();
+ }
+ if (calendarJson.has("rainInterval")) {
+ rainInterval = calendarJson.get("rainInterval").getAsLong();
+ }
+ if (calendarJson.has("thunderFrequency")) {
+ thunderFrequency = calendarJson.get("thunderFrequency").getAsLong();
+ }
+ if (calendarJson.has("rainDuration")) {
+ rainDuration = calendarJson.get("rainDuration").getAsLong();
+ }
+ if (calendarJson.has("external")) {
+ List<Pair<Long, SBEvent>> externalEvents = new ArrayList<>();
+ for (JsonElement external : calendarJson.getAsJsonArray("external")) {
+ if (!(external instanceof JsonObject)) continue;
+ SBEvent sbEvent = new SBEvent(
+ Utils.getElementAsString(Utils.getElement(external, "id"), "external"),
+ Utils.getElementAsString(Utils.getElement(external, "display"), "§aExternal Event"),
+ Utils.getElementAsBool(Utils.getElement(external, "special"), false),
+ NotEnoughUpdates.INSTANCE.manager.createItem(Utils.getElementAsString(Utils.getElement(
+ external,
+ "itemStack"
+ ), "painting")),
+ JsonUtils.getJsonArrayOrEmpty((JsonObject) external, "description", it -> Utils.getElementAsString(it, "")),
+ Utils.getElementAsInt(Utils.getElement(external, "duration"), -1),
+ true
+ );
+ long start = Utils.getElementAsLong(Utils.getElement(external, "start"), 0);
+ externalEvents.add(new Pair<>(start, sbEvent));
+ }
+ this.externalEvents = externalEvents;
+ }
+ eventMap.clear();
+ }
+
+ @SubscribeEvent
public void tick(TickEvent.ClientTickEvent event) {
if (event.phase != TickEvent.Phase.START) return;
handleJinglePlayer();
@@ -338,7 +433,7 @@ public class CalendarOverlay {
}
public void addEvent(SkyBlockTime time, SBEvent event) {
- if (time.toInstant().isBefore(Instant.now())&&
+ if (time.toInstant().isBefore(Instant.now()) &&
time.toInstant().plus(event.lastsFor, ChronoUnit.MILLIS).isBefore(Instant.now())) return;
getEventsAt(time.toMillis()).add(event);
}
@@ -1316,7 +1411,6 @@ public class CalendarOverlay {
}
}
-
if (nextEvent != null) {
GlStateManager.translate(0, 0, 50);
boolean toastRendered = renderToast(nextEvent, timeUntilNext);
@@ -1449,7 +1543,7 @@ public class CalendarOverlay {
GlStateManager.color(1, 1, 1, 1);
}
- private static class SBEvent {
+ private static class SBEvent implements Comparable<SBEvent> {
String id;
String display;
ItemStack stack;
@@ -1491,6 +1585,18 @@ public class CalendarOverlay {
}
return stack;
}
+
+ @Override
+ public int compareTo(@NotNull CalendarOverlay.SBEvent o) {
+ int i;
+ if ((i = id.compareTo(o.id)) != 0) return i;
+ if ((i = display.compareTo(o.display)) != 0) return i;
+ if ((i = Long.compare(lastsFor, o.lastsFor)) != 0) return i;
+ if ((i = Boolean.compare(isSpecial, o.isSpecial)) != 0) return i;
+ if ((i = Boolean.compare(isArtificial, o.isArtificial)) != 0) return i;
+
+ return 0;
+ }
}
private String prettyTime(long millis, boolean trimmed) {
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/StorageOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/StorageOverlay.java
index 4a478d1f..13cafd98 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/StorageOverlay.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/StorageOverlay.java
@@ -2131,6 +2131,7 @@ public class StorageOverlay extends GuiElement {
for (Slot slot : container.inventorySlots.inventorySlots) {
if (slot != null && ((AccessorGuiContainer) container).doIsMouseOverSlot(slot, mouseX, mouseY)) {
String internalName = manager.createItemResolutionQuery().withItemStack(slot.getStack()).resolveInternalName();
+ if (internalName == null) continue;
JsonObject item = manager.getItemInformation().get(internalName);
if (Keyboard.getEventKey() == manager.keybindViewRecipe.getKeyCode()) manager.showRecipe(item);
if (Keyboard.getEventKey() == manager.keybindViewUsages.getKeyCode()) manager.displayGuiItemUsages(internalName);
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/loaders/MinionHelperApiLoader.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/loaders/MinionHelperApiLoader.java
index ecf02236..ed275c7a 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/loaders/MinionHelperApiLoader.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/loaders/MinionHelperApiLoader.java
@@ -53,7 +53,7 @@ public class MinionHelperApiLoader {
private ApiData apiData = null;
private boolean notifyNoCollectionApi = false;
private long lastLoaded = 0;
- private boolean invalidApiKey = false;
+ private boolean invalidApiKey = true;
public MinionHelperApiLoader(MinionHelperManager manager) {
this.manager = manager;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/render/MinionHelperOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/render/MinionHelperOverlay.java
index 93a39ec0..a6a92a6a 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/render/MinionHelperOverlay.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/render/MinionHelperOverlay.java
@@ -115,7 +115,7 @@ public class MinionHelperOverlay {
if (!NotEnoughUpdates.INSTANCE.config.minionHelper.gui) return;
if (manager.isInvalidApiKey()) {
LinkedHashMap<String, OverviewLine> map = new LinkedHashMap<>();
- map.put("§cInvalid API Key!", new OverviewText(Collections.emptyList(), () -> {}));
+ map.put("§cNo data found, try running /pv", new OverviewText(Collections.emptyList(), () -> {}));
render(map);
return;
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinNetHandlerPlayClient.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinNetHandlerPlayClient.java
index 49f357e6..5245d604 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinNetHandlerPlayClient.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinNetHandlerPlayClient.java
@@ -26,6 +26,7 @@ import io.github.moulberry.notenoughupdates.miscfeatures.EnchantingSolvers;
import io.github.moulberry.notenoughupdates.miscfeatures.ItemCooldowns;
import io.github.moulberry.notenoughupdates.miscfeatures.MiningStuff;
import io.github.moulberry.notenoughupdates.miscfeatures.StorageManager;
+import io.github.moulberry.notenoughupdates.miscfeatures.world.CrystalHollowChestHighlighter;
import io.github.moulberry.notenoughupdates.util.SBInfo;
import net.minecraft.client.multiplayer.WorldClient;
import net.minecraft.client.network.NetHandlerPlayClient;
@@ -33,6 +34,7 @@ import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.network.Packet;
import net.minecraft.network.play.client.C01PacketChatMessage;
import net.minecraft.network.play.client.C0EPacketClickWindow;
+import net.minecraft.network.play.server.S22PacketMultiBlockChange;
import net.minecraft.network.play.server.S23PacketBlockChange;
import net.minecraft.network.play.server.S2DPacketOpenWindow;
import net.minecraft.network.play.server.S2EPacketCloseWindow;
@@ -119,6 +121,12 @@ public class MixinNetHandlerPlayClient {
public void handleBlockChange(S23PacketBlockChange packetIn, CallbackInfo ci) {
MiningStuff.processBlockChangePacket(packetIn);
ItemCooldowns.processBlockChangePacket(packetIn);
+ CrystalHollowChestHighlighter.processBlockChangePacket(packetIn);
+ }
+
+ @Inject(method = "handleMultiBlockChange", at = @At("HEAD"))
+ public void handleMultiBlockChange(S22PacketMultiBlockChange packetIn, CallbackInfo ci) {
+ CrystalHollowChestHighlighter.processMultiBlockChangePacket(packetIn);
}
@Inject(method = "addToSendQueue", at = @At("HEAD"), cancellable = true)
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/WorldConfig.java b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/WorldConfig.java
index 2f8adc0f..4e1118b7 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/WorldConfig.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/WorldConfig.java
@@ -106,4 +106,29 @@ public class WorldConfig {
@ConfigAccordionId(id = 3)
public String frozenTreasuresColor2 = "0:100:0:255:0";
+ @Expose
+ @ConfigOption(
+ name = "Crystal Hollow Chests",
+ desc = ""
+ )
+ @ConfigEditorAccordion(id = 4)
+ public boolean crystalHollowChestsAccordion = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Crystal Hollow Chest Highlighter",
+ desc = "Highlights chests found in the crystal hollows whilst powder mining"
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 4)
+ public boolean highlightCrystalHollowChests = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Chest Highlight Color",
+ desc = "In which color should chests be highlighted"
+ )
+ @ConfigEditorColour
+ @ConfigAccordionId(id = 4)
+ public String crystalHollowChestColor = "0:66:255:0:41";
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/BasicPage.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/BasicPage.java
index a1135205..7db8a21c 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/BasicPage.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/BasicPage.java
@@ -766,6 +766,9 @@ public class BasicPage extends GuiProfileViewerPage {
if (NotEnoughUpdates.INSTANCE.config.profileViewer.displayWeight) {
renderWeight(mouseX, mouseY, selectedProfile);
}
+
+ selectedProfile.updateTamingLevel();
+ selectedProfile.updateBeastMasterMultiplier();
}
private String getIcon(String gameModeType) {
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/SkyblockProfiles.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/SkyblockProfiles.java
index c16d8df0..3bfac529 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/SkyblockProfiles.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/SkyblockProfiles.java
@@ -24,6 +24,8 @@ import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.events.ProfileDataLoadedEvent;
+import io.github.moulberry.notenoughupdates.miscfeatures.PetInfoOverlay;
import io.github.moulberry.notenoughupdates.profileviewer.bestiary.BestiaryData;
import io.github.moulberry.notenoughupdates.profileviewer.weight.senither.SenitherWeight;
import io.github.moulberry.notenoughupdates.profileviewer.weight.weight.Weight;
@@ -32,6 +34,7 @@ import io.github.moulberry.notenoughupdates.util.UrsaClient;
import io.github.moulberry.notenoughupdates.util.Utils;
import io.github.moulberry.notenoughupdates.util.hypixelapi.ProfileCollectionInfo;
import lombok.Getter;
+import net.minecraft.client.Minecraft;
import net.minecraft.init.Items;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompressedStreamTools;
@@ -320,6 +323,12 @@ public class SkyblockProfiles {
profileViewer.getManager().ursaClient
.get(UrsaClient.profiles(Utils.parseDashlessUUID(uuid)))
.handle((profilesJson, throwable) -> {
+ try {
+ if (Utils.parseDashlessUUID(uuid).toString().equals(Minecraft.getMinecraft().thePlayer.getUniqueID().toString())) {
+ new ProfileDataLoadedEvent(uuid, profilesJson).post();
+ }
+ } catch (Exception ignored) {
+ }
if (profilesJson != null && profilesJson.has("success")
&& profilesJson.get("success").getAsBoolean() && profilesJson.has("profiles")) {
Map<String, SkyblockProfile> nameToProfile = new HashMap<>();
@@ -865,7 +874,6 @@ public class SkyblockProfiles {
if (skillName.equals("farming")) {
maxLevel += Utils.getElementAsInt(Utils.getElement(profileJson, "jacob2.perks.farming_level_cap"), 0);
}
-
out.put(skillName, ProfileViewerUtils.getLevel(levelingArray, skillExperience, maxLevel, false));
}
@@ -943,37 +951,7 @@ public class SkyblockProfiles {
}
public int getBestiaryLevel() {
- int beLevel = 0;
- for (ItemStack items : BestiaryData.getBestiaryLocations().keySet()) {
- List<String> mobs = BestiaryData.getBestiaryLocations().get(items);
- if (mobs != null) {
- for (String mob : mobs) {
- if (mob != null) {
- float kills = Utils.getElementAsFloat(Utils.getElement(getProfileJson(), "bestiary.kills_" + mob), 0);
- String type;
- if (BestiaryData.getMobType().get(mob) != null) {
- type = BestiaryData.getMobType().get(mob);
- } else {
- type = "MOB";
- }
- JsonObject leveling = Constants.LEVELING;
- ProfileViewer.Level level = null;
- if (leveling != null && Utils.getElement(leveling, "bestiary." + type) != null) {
- JsonArray levelingArray = Utils.getElement(leveling, "bestiary." + type).getAsJsonArray();
- int levelCap = Utils.getElementAsInt(Utils.getElement(leveling, "bestiary.caps." + type), 0);
- level = ProfileViewerUtils.getLevel(levelingArray, kills, levelCap, false);
- }
-
- float levelNum = 0;
- if (level != null) {
- levelNum = level.level;
- }
- beLevel += (int) Math.floor(levelNum);
- }
- }
- }
- }
- return beLevel;
+ return BestiaryData.calculateTotalBestiaryLevel(BestiaryData.parseBestiaryData(getProfileJson()));
}
public JsonObject getPetsInfo() {
@@ -1171,5 +1149,50 @@ public class SkyblockProfiles {
loadMuseumData();
return new MuseumData(null).asLoading();
}
+
+ public void updateBeastMasterMultiplier() {
+ if (!getUuid().equals(Minecraft.getMinecraft().thePlayer.getUniqueID().toString().replace("-", ""))) return;
+ JsonObject stats = getProfileJson().get("stats").getAsJsonObject();
+ boolean hasBeastmasterCrest = false;
+ PetInfoOverlay.Rarity currentBeastRarity = PetInfoOverlay.Rarity.COMMON;
+ for (JsonElement talisman : getInventoryInfo().get("talisman_bag")) {
+ if (talisman.isJsonNull()) continue;
+ String internalName = talisman.getAsJsonObject().get("internalname").getAsString();
+ if (internalName.startsWith("BEASTMASTER_CREST")) {
+ hasBeastmasterCrest = true;
+ try {
+ PetInfoOverlay.Rarity talismanRarity = PetInfoOverlay.Rarity.valueOf(internalName.replace("BEASTMASTER_CREST_", ""));
+ if (talismanRarity.beastcreatMultiplyer > currentBeastRarity.beastcreatMultiplyer)
+ currentBeastRarity = talismanRarity;
+ } catch (Exception ignored) {
+ }
+ }
+ }
+ if (hasBeastmasterCrest) {
+ if (stats.has("mythos_kills")) {
+ int mk = stats.get("mythos_kills").getAsInt();
+ float petXpBoost = mk > 10000 ? 1f : mk > 7500 ? 0.9f : mk > 5000 ? 0.8f : mk > 2500 ? 0.7f :
+ mk > 1000
+ ? 0.6f
+ : mk > 500
+ ? 0.5f
+ : mk > 250
+ ? 0.4f
+ : mk > 100
+ ? 0.3f
+ : mk > 25 ? 0.2f : 0.1f;
+ PetInfoOverlay.getConfig().beastMultiplier = petXpBoost * currentBeastRarity.beastcreatMultiplyer;
+ } else {
+ PetInfoOverlay.getConfig().beastMultiplier = 0.1f * currentBeastRarity.beastcreatMultiplyer;
+ }
+ }
+ }
+
+ public void updateTamingLevel() {
+ if (!getUuid().equals(Minecraft.getMinecraft().thePlayer.getUniqueID().toString().replace("-", ""))) return;
+ if (!getLatestProfile().skillsApiEnabled()) return;
+
+ PetInfoOverlay.getConfig().tamingLevel = (int) getLevelingInfo().get("taming").level;
+ }
}
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/bestiary/BestiaryData.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/bestiary/BestiaryData.java
deleted file mode 100644
index 36fc07aa..00000000
--- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/bestiary/BestiaryData.java
+++ /dev/null
@@ -1,1094 +0,0 @@
-/*
- * Copyright (C) 2022 NotEnoughUpdates contributors
- *
- * This file is part of NotEnoughUpdates.
- *
- * NotEnoughUpdates is free software: you can redistribute it
- * and/or modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation, either
- * version 3 of the License, or (at your option) any later version.
- *
- * NotEnoughUpdates is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
- */
-
-package io.github.moulberry.notenoughupdates.profileviewer.bestiary;
-
-import io.github.moulberry.notenoughupdates.util.Utils;
-import net.minecraft.init.Blocks;
-import net.minecraft.init.Items;
-import net.minecraft.item.Item;
-import net.minecraft.item.ItemStack;
-import net.minecraft.util.EnumChatFormatting;
-
-import java.util.LinkedHashMap;
-import java.util.List;
-
-public class BestiaryData {
-
- private static final LinkedHashMap<ItemStack, List<String>> bestiaryLocations = new LinkedHashMap<ItemStack, List<String>>() {
- {
- put(
- Utils.createSkull(
- EnumChatFormatting.AQUA + "Private Island",
- "bdee7687-9c85-4e7a-b789-b55e90d21d68",
- "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYzljODg4MWU0MjkxNWE5ZDI5YmI2MWExNmZiMjZkMDU5OTEzMjA0ZDI2NWRmNWI0MzliM2Q3OTJhY2Q1NiJ9fX0="
- ),
- Utils.createList(
- "family_cave_spider",
- "family_enderman_private",
- "family_skeleton",
- "family_slime",
- "family_spider",
- "family_witch",
- "family_zombie"
- )
- );
- put(
- Utils.createSkull(
- EnumChatFormatting.AQUA + "Hub",
- "88208736-41cd-4ed8-8ed7-53179140a7fa",
- "eyJ0aW1lc3RhbXAiOjE1NTkyMTU0MTY5MDksInByb2ZpbGVJZCI6IjQxZDNhYmMyZDc0OTQwMGM5MDkwZDU0MzRkMDM4MzFiIiwicHJvZmlsZU5hbWUiOiJNZWdha2xvb24iLCJzaWduYXR1cmVSZXF1aXJlZCI6dHJ1ZSwidGV4dHVyZXMiOnsiU0tJTiI6eyJ1cmwiOiJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlL2Q3Y2M2Njg3NDIzZDA1NzBkNTU2YWM1M2UwNjc2Y2I1NjNiYmRkOTcxN2NkODI2OWJkZWJlZDZmNmQ0ZTdiZjgifX19"
- ),
- Utils.createList("family_unburried_zombie", "family_old_wolf", "family_ruin_wolf", "family_zombie_villager")
- );
- put(
- Utils.createSkull(
- EnumChatFormatting.AQUA + "Spiders Den",
- "acbeaf98-2081-40c5-b5a3-221a2957d532",
- "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYzc1NDMxOGEzMzc2ZjQ3MGU0ODFkZmNkNmM4M2E1OWFhNjkwYWQ0YjRkZDc1NzdmZGFkMWMyZWYwOGQ4YWVlNiJ9fX0"
- ),
- Utils.createList(
- "family_arachne",
- "family_arachne_brood",
- "family_arachne_keeper",
- "family_brood_mother_spider",
- "family_dasher_spider",
- "family_respawning_skeleton",
- "family_random_slime",
- "family_spider_jockey",
- "family_splitter_spider",
- "family_voracious_spider",
- "family_weaver_spider"
- )
- );
- put(
- Utils.createSkull(
- EnumChatFormatting.AQUA + "The End",
- "e39ea8b1-a267-48a9-907a-1b97b85342bc",
- "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNzg0MGI4N2Q1MjI3MWQyYTc1NWRlZGM4Mjg3N2UwZWQzZGY2N2RjYzQyZWE0NzllYzE0NjE3NmIwMjc3OWE1In19fQ"
- ),
- Utils.createList(
- "family_dragon",
- "family_enderman",
- "family_endermite",
- "family_corrupted_protector",
- "family_obsidian_wither",
- "family_voidling_extremist",
- "family_voidling_fanatic",
- "family_watcher",
- "family_zealot_enderman"
- )
- );
- put(
- Utils.createSkull(
- EnumChatFormatting.AQUA + "Crimson Isles",
- "d8489bfe-dcd7-41f0-bfbd-fb482bf61ecb",
- "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYzM2ODdlMjVjNjMyYmNlOGFhNjFlMGQ2NGMyNGU2OTRjM2VlYTYyOWVhOTQ0ZjRjZjMwZGNmYjRmYmNlMDcxIn19fQ"
- ),
- Utils.createList(
- "family_ashfang",
- "family_barbarian_duke_x",
- "family_bladesoul",
- "family_blaze",
- "family_flaming_spider",
- "family_ghast",
- "family_mage_outlaw",
- "family_magma_cube",
- "family_magma_boss",
- "family_matcho",
- "family_charging_mushroom_cow",
- "family_pigman",
- "family_wither_skeleton",
- "family_wither_spectre"
- )
- );
- put(
- Utils.createSkull(
- EnumChatFormatting.AQUA + "Deep Caverns",
- "896b5137-a2dd-4de2-8c63-d5a5649bfc70",
- "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNTY5YTFmMTE0MTUxYjQ1MjEzNzNmMzRiYzE0YzI5NjNhNTAxMWNkYzI1YTY1NTRjNDhjNzA4Y2Q5NmViZmMifX19"
- ),
- Utils.createList(
- "family_automaton",
- "family_butterfly",
- "family_emerald_slime",
- "family_caverns_ghost",
- "family_goblin",
- "family_team_treasurite",
- "family_ice_walker",
- "family_lapis_zombie",
- "family_diamond_skeleton",
- "family_diamond_zombie",
- "family_redstone_pigman",
- "family_sludge",
- "family_invisible_creeper",
- "family_thyst",
- "family_treasure_hoarder",
- "family_worms",
- "family_yog"
- )
- );
- put(
- Utils.createSkull(
- EnumChatFormatting.AQUA + "The Park",
- "6473b2ff-0575-4aec-811f-5f0dca2131b6",
- "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYTIyMWY4MTNkYWNlZTBmZWY4YzU5Zjc2ODk0ZGJiMjY0MTU0NzhkOWRkZmM0NGMyZTcwOGE2ZDNiNzU0OWIifX19"
- ),
- Utils.createList("family_howling_spirit", "family_pack_spirit", "family_soul_of_the_alpha")
- );
- put(
- Utils.createItemStack(Item.getItemFromBlock(Blocks.lit_pumpkin), EnumChatFormatting.AQUA + "Spooky"),
- Utils.createList(
- "family_batty_witch",
- "family_headless_horseman",
- "family_phantom_spirit",
- "family_scary_jerry",
- "family_trick_or_treater",
- "family_wither_gourd",
- "family_wraith"
- )
- );
- put(
- Utils.createSkull(
- EnumChatFormatting.AQUA + "Catacombs",
- "00b3837d-9275-304c-8bf9-656659087e6b",
- "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOTY0ZTFjM2UzMTVjOGQ4ZmZmYzM3OTg1YjY2ODFjNWJkMTZhNmY5N2ZmZDA3MTk5ZThhMDVlZmJlZjEwMzc5MyJ9fX0"
- ),
- Utils.createList(
- "family_diamond_guy",
- "family_cellar_spider",
- "family_crypt_dreadlord",
- "family_crypt_lurker",
- "family_crypt_souleater",
- "family_king_midas",
- "family_lonely_spider",
- "family_lost_adventurer",
- "family_scared_skeleton",
- "family_shadow_assassin",
- "family_skeleton_grunt",
- "family_skeleton_master",
- "family_skeleton_soldier",
- "family_skeletor",
- "family_sniper_skeleton",
- "family_super_archer",
- "family_super_tank_zombie",
- "family_crypt_tank_zombie",
- "family_watcher_summon_undead",
- "family_dungeon_respawning_skeleton",
- "family_crypt_witherskeleton",
- "family_zombie_commander",
- "family_zombie_grunt",
- "family_zombie_knight",
- "family_zombie_soldier"
- )
- );
- }
- };
- private static final LinkedHashMap<String, ItemStack> bestiaryMobs = new LinkedHashMap<String, ItemStack>() {
- {
- // Private Island
- put(
- "family_cave_spider",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aCave Spider",
- "a8aee72d-0d1d-3db7-8cf8-be1ce6ec2dc4",
- "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNDE2NDVkZmQ3N2QwOTkyMzEwN2IzNDk2ZTk0ZWViNWMzMDMyOWY5N2VmYzk2ZWQ3NmUyMjZlOTgyMjQifX19"
- )
- );
- put(
- "family_enderman_private",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aEnderman",
- "2005daad-730b-363c-abae-e6f3830816fb",
- "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOTZjMGIzNmQ1M2ZmZjY5YTQ5YzdkNmYzOTMyZjJiMGZlOTQ4ZTAzMjIyNmQ1ZTgwNDVlYzU4NDA4YTM2ZTk1MSJ9fX0="
- )
- );
- put(
- "family_skeleton",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aSkeleton",
- "53924f1a-87e6-4709-8e53-f1c7d13dc239",
- "ewogICJ0aW1lc3RhbXAiIDogMTY1NTYzMTgzNjcwNCwKICAicHJvZmlsZUlkIiA6ICI1MzkyNGYxYTg3ZTY0NzA5OGU1M2YxYzdkMTNkYzIzOSIsCiAgInByb2ZpbGVOYW1lIiA6ICJUaHJvd3BvIiwKICAic2lnbmF0dXJlUmVxdWlyZWQiIDogdHJ1ZSwKICAidGV4dHVyZXMiIDogewogICAgIlNLSU4iIDogewogICAgICAidXJsIiA6ICJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzg4ZWI2OGE0ZDM4ZTlmNDQ2YjhlOTkyNzVmMTYwMzAyZjM2NmVmMTAyMTZhYmY5NDg0ODdlNTgyNTEyYmQwZjMiCiAgICB9CiAgfQp9="
- )
- );
- put(
- "family_slime",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aSlime",
- "3b70a2f3-319c-38d5-b7d1-5b2425770184",
- "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvODk1YWVlYzZiODQyYWRhODY2OWY4NDZkNjViYzQ5NzYyNTk3ODI0YWI5NDRmMjJmNDViZjNiYmI5NDFhYmU2YyJ9fX0="
- )
- );
- put(
- "family_spider",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aSpider",
- "7c63f3cf-a963-311a-aeca-3a075b417806",
- "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvY2Q1NDE1NDFkYWFmZjUwODk2Y2QyNThiZGJkZDRjZjgwYzNiYTgxNjczNTcyNjA3OGJmZTM5MzkyN2U1N2YxIn19fQ=="
- )
- );
- put(
- "family_witch",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aWitch",
- "cf4f97d7-2e1f-3678-9ca3-4a7b9666cc28",
- "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZmNlNjYwNDE1N2ZjNGFiNTU5MWU0YmNmNTA3YTc0OTkxOGVlOWM0MWUzNTdkNDczNzZlMGVlNzM0MjA3NGM5MCJ9fX0="
- )
- );
- put(
- "family_zombie",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aZombie",
- "9673d491-d589-44cb-b63e-5f8b3148b3df",
- "ewogICJ0aW1lc3RhbXAiIDogMTY0Njc1NjU2MzM1MiwKICAicHJvZmlsZUlkIiA6ICJkYmQ4MDQ2M2EwMzY0Y2FjYjI3OGNhODBhMDBkZGIxMyIsCiAgInByb2ZpbGVOYW1lIiA6ICJ4bG9nMjEiLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYjM2NjZkMWJkZjQ1NThiMGQxNjk5MGIyNDFlODE4NWNiZjU4YzNlMDNjMjRkOTA0NTQ0ZThjYzY1YjFjMzhkMSIKICAgIH0KICB9Cn0=\", \"n8vct7fj3NdiODy/h6PJhjxSR2U7d8gQxHjdVq553HqG60SSczt1Tl9XhvQbZP14ZrJGWxCziauuYb/HjZza0ugNAhfwh9z8hqR1PjBJGdvp+wpxoWpP2wd5RT9i5/GYEqpiAIAt9vHY1YeyejFqKZhXaGgp7gZZNjOQWQqB0SZzTUTAPzRW9FiY8x2re7H7Y1POThRXOvvkeQ6qWdPV6Hk5hTumV0rfEGm971jQRIbfdzBZDJRcro+8y+dlje/NpF5qf0JLy78Xr4hc2cwbT9+wqOeoUTcM/r9mwL15OKgFLjB44jszauKRHNfoqb6B3+1fNQEJrJK/7hIyvswpde7C5uOxkE7oMFib6X68VVEhb6PGC1+HWNaMaGjI0wWEkCahp48ihN9+sBEBFXOxIAhXG/pvJcbEi742/cBS1CTtOI8qui6JSL9MKX5jmyhtjjibOYRZbacosqayCnwsJAdMmwS7zIxc8jGhpfKECiSni/baS4zRla0bns4hfEM0l7ASv0Dh99WQD0We2ZMqltmix8lMEaAILXJVBln3CFrjYvncfku2hrSaqu1lNAtfMYYSITEUCBJ7McVAVmUHOrER0XGoVs9L237H0BQNSLqlGGEQ7OM8HV6G0YfXGlbNgNBx6O9k8ZijuK60JeEoJapcmbNj/LVHEU+dsgcFAbo="
- )
- );
-
- // Hub
- put("family_unburried_zombie", Utils.createItemStack(Items.golden_sword, EnumChatFormatting.AQUA + "§aCrypt Ghoul"));
- put(
- "family_old_wolf",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aOld Wolf",
- "26e6f2d9-8a27-3a77-965c-5bd2b5d2dc93",
- "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZDM1OTUzN2MxNTUzNGY2MWMxY2Q4ODZiYzExODc3NGVkMjIyODBlN2NkYWI2NjEzODcwMTYwYWFkNGNhMzkifX19"
- )
- );
- put(
- "family_ruin_wolf",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aWolf",
- "7e9af289-f295-3f8c-bd54-58b7667d5759",
- "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNjlkMWQzMTEzZWM0M2FjMjk2MWRkNTlmMjgxNzVmYjQ3MTg4NzNjNmM0NDhkZmNhODcyMjMxN2Q2NyJ9fX0="
- )
- );
- put(
- "family_zombie_villager",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aZombie Villager",
- "3acb9940-fc42-328e-91e8-c9a9a57e8698",
- "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZTVlMDhhODc3NmMxNzY0YzNmZTZhNmRkZDQxMmRmY2I4N2Y0MTMzMWRhZDQ3OWFjOTZjMjFkZjRiZjNhYzg5YyJ9fX0="
- )
- );
-
- // Spiders Den
- put(
- "family_arachne",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aArachne",
- "7c63f3cf-a963-311a-aeca-3a075b417806",
- "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvY2Q1NDE1NDFkYWFmZjUwODk2Y2QyNThiZGJkZDRjZjgwYzNiYTgxNjczNTcyNjA3OGJmZTM5MzkyN2U1N2YxIn19fQ=="
- )
- );
- put(
- "family_arachne_brood",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aArachne's Brood",
- "7c63f3cf-a963-311a-aeca-3a075b417806",
- "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvY2Q1NDE1NDFkYWFmZjUwODk2Y2QyNThiZGJkZDRjZjgwYzNiYTgxNjczNTcyNjA3OGJmZTM5MzkyN2U1N2YxIn19fQ=="
- )
- );
- put(
- "family_arachne_keeper",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aArachne's Keeper",
- "7c63f3cf-a963-311a-aeca-3a075b417806",
- "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvY2Q1NDE1NDFkYWFmZjUwODk2Y2QyNThiZGJkZDRjZjgwYzNiYTgxNjczNTcyNjA3OGJmZTM5MzkyN2U1N2YxIn19fQ=="
- )
- );
- put(
- "family_brood_mother_spider",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aBrood Mother",
- "d7390e70-1e99-3c24-9b1c-bb098e0bbef1",
- "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvY2YwNjIyYjM5OThkNDJiMzRkNWJjNzYwYmIyYzgzZmRiYzZlNjhmYWIwNWI3ZWExN2IzNTA5N2VkODExOTBkNiJ9fX0="
- )
- );
- put(
- "family_dasher_spider",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aDasher Spider",
- "7c63f3cf-a963-311a-aeca-3a075b417806",
- "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvY2Q1NDE1NDFkYWFmZjUwODk2Y2QyNThiZGJkZDRjZjgwYzNiYTgxNjczNTcyNjA3OGJmZTM5MzkyN2U1N2YxIn19fQ=="
- )
- );
- put(
- "family_respawning_skeleton",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aGravel Skeleton",
- "53924f1a-87e6-4709-8e53-f1c7d13dc239",
- "ewogICJ0aW1lc3RhbXAiIDogMTY1NTYzMTgzNjcwNCwKICAicHJvZmlsZUlkIiA6ICI1MzkyNGYxYTg3ZTY0NzA5OGU1M2YxYzdkMTNkYzIzOSIsCiAgInByb2ZpbGVOYW1lIiA6ICJUaHJvd3BvIiwKICAic2lnbmF0dXJlUmVxdWlyZWQiIDogdHJ1ZSwKICAidGV4dHVyZXMiIDogewogICAgIlNLSU4iIDogewogICAgICAidXJsIiA6ICJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzg4ZWI2OGE0ZDM4ZTlmNDQ2YjhlOTkyNzVmMTYwMzAyZjM2NmVmMTAyMTZhYmY5NDg0ODdlNTgyNTEyYmQwZjMiCiAgICB9CiAgfQp9="
- )
- );
- put(
- "family_random_slime",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aRain Slime",
- "3b70a2f3-319c-38d5-b7d1-5b2425770184",
- "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvODk1YWVlYzZiODQyYWRhODY2OWY4NDZkNjViYzQ5NzYyNTk3ODI0YWI5NDRmMjJmNDViZjNiYmI5NDFhYmU2YyJ9fX0="
- )
- );
- put(
- "family_spider_jockey",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aSpider Jockey",
- "4eb8745c-80d2-356b-b4fa-f3ffa74082e7",
- "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNzA5MzkzNzNjYWZlNGIxZjUzOTdhYWZkMDlmM2JiMTY2M2U3YjYyOWE0MWE3NWZiZGMxODYwYjZiZjhiNDc1ZiJ9fX0="
- )
- );
- put(
- "family_splitter_spider",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aSplitter Spider",
- "50010472-fa22-3519-b941-2d6d22f47bf1",
- "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMmFjZjY5ZmM3YWY1NDk3YTE3NDE4OTFkMWU1YmYzMmI5NmFlMGQ2YzBiYmQzYzE0NzU4ZWE0NGEwM2M1NzI4MyJ9fX0="
- )
- );
- put(
- "family_voracious_spider",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aVoracious Spider",
- "3e5474d4-4365-3ea7-b4bc-b4edc54da341",
- "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvODMwMDk4NmVkMGEwNGVhNzk5MDRmNmFlNTNmNDllZDNhMGZmNWIxZGY2MmJiYTYyMmVjYmQzNzc3ZjE1NmRmOCJ9fX0="
- )
- );
- put(
- "family_weaver_spider",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aWeaver Spider",
- "97414c0c-623b-3df3-b1f6-bbcaddafc7fc",
- "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOTIxNDM4ZjY0NmRjMDQ1MTU5NjdlODE5NWNjYzNkMzFlMjNiMDJmOWFhMGFjOTE0ZWRjMjgyMmY5ODM5NGI4NiJ9fX0="
- )
- );
-
- // The End
- put("family_dragon", Utils.createItemStack(Item.getItemFromBlock(Blocks.dragon_egg), EnumChatFormatting.AQUA + "§aDragon"));
- put(
- "family_enderman",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aEnderman",
- "2005daad-730b-363c-abae-e6f3830816fb",
- "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOTZjMGIzNmQ1M2ZmZjY5YTQ5YzdkNmYzOTMyZjJiMGZlOTQ4ZTAzMjIyNmQ1ZTgwNDVlYzU4NDA4YTM2ZTk1MSJ9fX0="
- )
- );
- put(
- "family_endermite",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aEndermite",
- "b3224e56-73d2-32f9-9081-a23b7512035b",
- "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNWJjN2I5ZDM2ZmI5MmI2YmYyOTJiZTczZDMyYzZjNWIwZWNjMjViNDQzMjNhNTQxZmFlMWYxZTY3ZTM5M2EzZSJ9fX0="
- )
- );
- put(
- "family_corrupted_protector",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aEndstone Protector",
- "a46a9adf-60a3-38f2-a3dd-335d85f1cc10",
- "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMjJiY2FjZWViNDE2MmY0MDBkNDQ3NDMzMTU5MzJhYzgyMGQzMTE5YWM4OTg2YTAxNjFhNzI2MTYxY2NjOTNmYyJ9fX0="
- )
- );
- put(
- "family_obsidian_wither",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aObsidian Defender",
- "d0e05de7-6067-454d-beae-c6d19d886191",
- "ewogICJ0aW1lc3RhbXAiIDogMTY1NTYzMjg1MTE1NCwKICAicHJvZmlsZUlkIiA6ICJkMGUwNWRlNzYwNjc0NTRkYmVhZWM2ZDE5ZDg4NjE5MSIsCiAgInByb2ZpbGVOYW1lIiA6ICJNb3VsYmVycnkiLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYmNlMTU1MjI0ZWE0YmM0OWE4ZTkxOTA3MzdjYjA0MTdkOGE3YzM4YTAzN2Q4ZDAzODJkZGU0ODI5YzEwMzU5MCIsCiAgICAgICJtZXRhZGF0YSIgOiB7CiAgICAgICAgIm1vZGVsIiA6ICJzbGltIgogICAgICB9CiAgICB9CiAgfQp9"
- )
- );
- put(
- "family_voidling_extremist",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§a§dVoidling Extremist",
- "159dcb01-74e3-382c-87d6-3afa022fb379",
- "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZWIwNzU5NGUyZGYyNzM5MjFhNzdjMTAxZDBiZmRmYTExMTVhYmVkNWI5YjIwMjllYjQ5NmNlYmE5YmRiYjRiMyJ9fX0="
- )
- );
- put(
- "family_voidling_fanatic",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aVoidling Fanatic",
- "e86aab24-6245-3967-bf3d-07e31999b602",
- "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZTUzYjdiY2Q1NmYwYjk1Zjg3ZGQ3OWVkMTc2MzZiZWI5ZDgzNDY3NDQwMTQyMjhlYTJmNmIxMTBiMTQ4YzEifX19"
- )
- );
- put(
- "family_watcher",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aWatcher",
- "00a702b9-7bad-3205-a04b-52478d8c0e7f",
- "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZGFhOGZjOGRlNjQxN2I0OGQ0OGM4MGI0NDNjZjUzMjZlM2Q5ZGE0ZGJlOWIyNWZjZDQ5NTQ5ZDk2MTY4ZmMwIn19fQ=="
- )
- );
- put(
- "family_zealot_enderman",
- Utils.createItemStack(Item.getItemFromBlock(Blocks.ender_chest), EnumChatFormatting.AQUA + "§aZealot")
- );
-
- // Crimson Isle
- put(
- "family_ashfang",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aAshfang",
- "1bc8810e-2b57-3a89-8e00-a47a057d6ecc",
- "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvM2QyYTViNGIxMDliZDc4OGVkYmEwMTcxZDBhYWI4YTU1MzA1YWMyZjU2MTg0ZGY3MGEzMTljZDQ4OGEzNmMzZSJ9fX0="
- )
- );
- put(
- "family_barbarian_duke_x",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aBarbarian Duke X",
- "6ddece1d-8227-35f3-b9ca-476a9f6cd8c5",
- "ewogICJ0aW1lc3RhbXAiIDogMTY0MTI0OTYyNTU3NSwKICAicHJvZmlsZUlkIiA6ICIyNzZlMDQ2YjI0MDM0M2VkOTk2NmU0OTRlN2U2Y2IzNCIsCiAgInByb2ZpbGVOYW1lIiA6ICJBRFJBTlM3MTAiLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZmVlOWZjN2MxODFlMmY2MzBmNmIxYWY4NWQ0OTUxMzU5Y2FmY2ZhODJmZjVlYTNiYzI4M2UwZTYwODhjNmU1NCIKICAgIH0KICB9Cn0"
- )
- );
- put(
- "family_bladesoul",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aBladesoul",
- "9a1699a4-9b61-37a5-be7a-ca23a1f092a1",
- "ewogICJ0aW1lc3RhbXAiIDogMTY0NDA4Mjg1NzcxMCwKICAicHJvZmlsZUlkIiA6ICIwNTVhOTk2NTk2M2E0YjRmOGMwMjRmMTJmNDFkMmNmMiIsCiAgInByb2ZpbGVOYW1lIiA6ICJUaGVWb3hlbGxlIiwKICAic2lnbmF0dXJlUmVxdWlyZWQiIDogdHJ1ZSwKICAidGV4dHVyZXMiIDogewogICAgIlNLSU4iIDogewogICAgICAidXJsIiA6ICJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzdmNWYzMzg0Mzg0ZDdmMDNiZjk3YTczMDk5YjBiYWZiNzJjNTM4ZmMwNDE1YWM4NjEzYjY2NGY4NzU3OWEzNzkiCiAgICB9CiAgfQp9"
- )
- );
- put(
- "family_blaze",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aBlaze",
- "118fe834-28aa-3b0d-afe6-f0c52d01afe8",
- "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYjc4ZWYyZTRjZjJjNDFhMmQxNGJmZGU5Y2FmZjEwMjE5ZjViMWJmNWIzNWE0OWViNTFjNjQ2Nzg4MmNiNWYwIn19fQ=="
- )
- );
- put(
- "family_flaming_spider",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aFlaming Spider",
- "d27e14a2-f35e-3c7b-8062-089fa201a533",
- "ewogICJ0aW1lc3RhbXAiIDogMTY0NDQ5OTUzOTQ2NywKICAicHJvZmlsZUlkIiA6ICJhYTZhNzUwNWVkYmU0NjNiYjk1NWYyMWY0MjNiYTM1NCIsCiAgInByb2ZpbGVOYW1lIiA6ICJub3RhbmR5d2FyaG9sIiwKICAic2lnbmF0dXJlUmVxdWlyZWQiIDogdHJ1ZSwKICAidGV4dHVyZXMiIDogewogICAgIlNLSU4iIDogewogICAgICAidXJsIiA6ICJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzVhNjVlZjIzZWEzNTA0NzE1MGQzMzg4MDQ3M2E0N2ZlNjM1ZjBjMGUzYzgyM2JkNzZkYzg0OWNiMDI0NDE2NTUiLAogICAgICAibWV0YWRhdGEiIDogewogICAgICAgICJtb2RlbCIgOiAic2xpbSIKICAgICAgfQogICAgfQogIH0KfQ=="
- )
- );
- put(
- "family_ghast",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aGhast",
- "69725d7d-1933-3dea-87bd-a3052482ab2c",
- "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZGU4YTM4ZTlhZmJkM2RhMTBkMTliNTc3YzU1YzdiZmQ2YjRmMmU0MDdlNDRkNDAxN2IyM2JlOTE2N2FiZmYwMiJ9fX0="
- )
- );
- put(
- "family_mage_outlaw",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aMage Outlaw",
- "1d16c26c-d937-336f-821a-371968d050c2",
- "ewogICJ0aW1lc3RhbXAiIDogMTY0NDA4Mjg3Mzk2NywKICAicHJvZmlsZUlkIiA6ICJiNzQ3OWJhZTI5YzQ0YjIzYmE1NjI4MzM3OGYwZTNjNiIsCiAgInByb2ZpbGVOYW1lIiA6ICJTeWxlZXgiLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZWJlYzk5YjNhMDUwZmQyNzc1Mjg0MDc2NzYzNjZlMjBiOTIwMDZhZDg4ZDE0NzI3YTRkOTllYjhjYjI3M2I2MiIKICAgIH0KICB9Cn0"
- )
- );
- put(
- "family_magma_cube",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aMagma Cube",
- "35f02923-7bec-3869-9ef5-b42a4794cac8",
- "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzg5NTdkNTAyM2M5MzdjNGM0MWFhMjQxMmQ0MzQxMGJkYTIzY2Y3OWE5ZjZhYjM2Yjc2ZmVmMmQ3YzQyOSJ9fX0="
- )
- );
- put(
- "family_magma_boss",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§a§4§lMagma Boss",
- "35f02923-7bec-3869-9ef5-b42a4794cac8",
- "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzg5NTdkNTAyM2M5MzdjNGM0MWFhMjQxMmQ0MzQxMGJkYTIzY2Y3OWE5ZjZhYjM2Yjc2ZmVmMmQ3YzQyOSJ9fX0="
- )
- );
- put(
- "family_matcho",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aMatcho",
- "61db73be-677f-554a-9450-e306a7ff0449",
- "e3RleHR1cmVzOntTS0lOOnt1cmw6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZWYyZGFhYmI3OGExZjdhYTEyZDE0NWQ4OGMwY2E0NmI5ZTg1NmY1NTM0ZTkyODZlNTU1ZmFmMGMyOTFmNGZkNSJ9fX0="
- )
- );
- put(
- "family_charging_mushroom_cow",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aMushroom Bull",
- "2b9eb675-2097-4b51-8fec-c1a51562f19c",
- "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYTE2M2JjNDE2YjhlNjA1OGY5MmIyMzFlOWE1MjRiN2ZlMTE4ZWI2ZTdlZWFiNGFkMTZkMWI1MmEzZWMwNGZjZCJ9fX0="
- )
- );
- put(
- "family_pigman",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aPigman",
- "3fc29372-e78e-3ad6-b0b0-05ca0a84babd",
- "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNzRlOWM2ZTk4NTgyZmZkOGZmOGZlYjMzMjJjZDE4NDljNDNmYjE2YjE1OGFiYjExY2E3YjQyZWRhNzc0M2ViIn19fQ=="
- )
- );
- put(
- "family_wither_skeleton",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aWither Skeleton",
- "2141b934-c877-3db1-bc6c-7c9a347ffa95",
- "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNzk1M2I2YzY4NDQ4ZTdlNmI2YmY4ZmIyNzNkNzIwM2FjZDhlMWJlMTllODE0ODFlYWQ1MWY0NWRlNTlhOCJ9fX0="
- )
- );
- put(
- "family_wither_spectre",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aWither Spectre",
- "9a1699a4-9b61-37a5-be7a-ca23a1f092a1",
- "ewogICJ0aW1lc3RhbXAiIDogMTY0NDA4Mjg1NzcxMCwKICAicHJvZmlsZUlkIiA6ICIwNTVhOTk2NTk2M2E0YjRmOGMwMjRmMTJmNDFkMmNmMiIsCiAgInByb2ZpbGVOYW1lIiA6ICJUaGVWb3hlbGxlIiwKICAic2lnbmF0dXJlUmVxdWlyZWQiIDogdHJ1ZSwKICAidGV4dHVyZXMiIDogewogICAgIlNLSU4iIDogewogICAgICAidXJsIiA6ICJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzdmNWYzMzg0Mzg0ZDdmMDNiZjk3YTczMDk5YjBiYWZiNzJjNTM4ZmMwNDE1YWM4NjEzYjY2NGY4NzU3OWEzNzkiCiAgICB9CiAgfQp9"
- )
- );
-
- // Deep Caverns
- put(
- "family_automaton",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aAutomaton",
- "a46a9adf-60a3-38f2-a3dd-335d85f1cc10",
- "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMjJiY2FjZWViNDE2MmY0MDBkNDQ3NDMzMTU5MzJhYzgyMGQzMTE5YWM4OTg2YTAxNjFhNzI2MTYxY2NjOTNmYyJ9fX0="
- )
- );
- put(
- "family_butterfly",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§a§eButterfly",
- "9dd11ec6-cfea-34df-9336-416c946567bc",
- "ewogICJ0aW1lc3RhbXAiIDogMTYyNTUxMjE4ODY3NCwKICAicHJvZmlsZUlkIiA6ICI3MzgyZGRmYmU0ODU0NTVjODI1ZjkwMGY4OGZkMzJmOCIsCiAgInByb2ZpbGVOYW1lIiA6ICJJb3lhbCIsCiAgInNpZ25hdHVyZVJlcXVpcmVkIiA6IHRydWUsCiAgInRleHR1cmVzIiA6IHsKICAgICJTS0lOIiA6IHsKICAgICAgInVybCIgOiAiaHR0cDovL3RleHR1cmVzLm1pbmVjcmFmdC5uZXQvdGV4dHVyZS85ZmQ4MDZkZWZkZmRmNTliMWYyNjA5YzhlZTM2NDY2NmRlNjYxMjdhNjIzNDE1YjU0MzBjOTM1OGM2MDFlZjdjIgogICAgfQogIH0KfQ=="
- )
- );
- put(
- "family_emerald_slime",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aEmerald Slime",
- "cb762e0d-a1e6-3888-8c05-eddabbbe49a2",
- "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNTc3NGU4NmFhNGNmZjc5MjM5NWI3N2FkZDU3YjAwYmIxYTEwMmY4ZjBmMDk4MGY0ZDU1YjNkN2FmZjFlNmRhOSJ9fX0="
- )
- );
- put(
- "family_caverns_ghost",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aGhost",
- "c5752211-7503-3e77-9890-d1cf6ba1d0e7",
- "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOTgxOTc3OTE4YTExODBlMGRlYzg3OWU2YmNkMWFhMzk0OTQ5NzdiYjkxM2JlMmFiMDFhZmYxZGIxZmE0In19fQ=="
- )
- );
- put(
- "family_goblin",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aGoblin",
- "7c7d07db-4911-31f1-9a19-1589899cfe25",
- "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYjZiOTcyZTMyZDc2MWIxOTI2MjZlNWQ2ZDAxZWRjMDk0OTQwOTEwMTAzY2VhNWUyZTJkMWYyMzFhZGI3NTVkNSJ9fX0="
- )
- );
- put(
- "family_team_treasurite",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aGrunt",
- "a64ccd19-2a64-39a4-b2f5-cb6799c12a99",
- "ewogICJ0aW1lc3RhbXAiIDogMTYxODE5NTA2MDUwMCwKICAicHJvZmlsZUlkIiA6ICI0ZTMwZjUwZTdiYWU0M2YzYWZkMmE3NDUyY2ViZTI5YyIsCiAgInByb2ZpbGVOYW1lIiA6ICJfdG9tYXRvel8iLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZWY1ZTAzYjhkZTExOWY4NTg5YTgwODIyNGNiZWE3MzdmNWRjZjI0MjM1Nzk5YjczNzhhYzViZjA2YWJmNmRkNCIKICAgIH0KICB9Cn0="
- )
- );
- put(
- "family_ice_walker",
- Utils.createItemStack(Item.getItemFromBlock(Blocks.packed_ice), EnumChatFormatting.AQUA + "§aIce Walker")
- );
- put("family_lapis_zombie", Utils.createItemStack(Items.dye, EnumChatFormatting.AQUA + "§aLapis Zombie", 4));
- put(
- "family_diamond_skeleton",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aMiner Skeleton",
- "39c843e6-237b-36b2-8a7b-c5ff5d3ebf99",
- "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvODM2YmJjNDIxNWNlYTFiNmE0ODRlODkzYjExNmU3MzQ1OWVmMzZiZmZjNjIyNzQxZTU3N2U5NDkzYTQxZTZlIn19fQ=="
- )
- );
- put(
- "family_diamond_zombie",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aMiner Zombie",
- "468210c9-f4bd-34c7-aa8d-2c3d0d5e05c1",
- "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZDI4ZDlmZjU0MTg4YTFhZmVlNjViOTRmM2JmY2NlMzIxYzY0M2EzNDU5MGMxNGIxOTJiMmUzZWMyZjUyNWQzIn19fQ=="
- )
- );
- put("family_redstone_pigman", Utils.createItemStack(Items.redstone, EnumChatFormatting.AQUA + "§aRedstone Pigman"));
- put(
- "family_sludge",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aSludge",
- "3b70a2f3-319c-38d5-b7d1-5b2425770184",
- "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvODk1YWVlYzZiODQyYWRhODY2OWY4NDZkNjViYzQ5NzYyNTk3ODI0YWI5NDRmMjJmNDViZjNiYmI5NDFhYmU2YyJ9fX0="
- )
- );
- put(
- "family_invisible_creeper",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aSneaky Creeper",
- "81fb1385-b2fc-4d4f-b5bb-0fe9b1d37d60",
- "ewogICJ0aW1lc3RhbXAiIDogMTYxOTE5MjI5MzI5OCwKICAicHJvZmlsZUlkIiA6ICI0ZjU2ZTg2ODk2OGU0ZWEwYmNjM2M2NzRlNzQ3ODdjOCIsCiAgInByb2ZpbGVOYW1lIiA6ICJDVUNGTDE1IiwKICAic2lnbmF0dXJlUmVxdWlyZWQiIDogdHJ1ZSwKICAidGV4dHVyZXMiIDogewogICAgIlNLSU4iIDogewogICAgICAidXJsIiA6ICJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlL2E2ODIyNGNmOGVkNGMwM2I0NTdiZjQ5YmViNmY1NDQxOTM2NzkyNjhiODQyMWIwMWZmY2U2ZDI3YjI1YWMzMmQiCiAgICB9CiAgfQp9"
- )
- );
- put(
- "family_thyst",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aThyst",
- "b3224e56-73d2-32f9-9081-a23b7512035b",
- "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNWJjN2I5ZDM2ZmI5MmI2YmYyOTJiZTczZDMyYzZjNWIwZWNjMjViNDQzMjNhNTQxZmFlMWYxZTY3ZTM5M2EzZSJ9fX0="
- )
- );
- put(
- "family_treasure_hoarder",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aTreasure Hoarder",
- "b0f13fc2-07a5-3964-8303-784f802e5f0f",
- "ewogICJ0aW1lc3RhbXAiIDogMTU5MDE1NjYzNDYzOCwKICAicHJvZmlsZUlkIiA6ICI5MWZlMTk2ODdjOTA0NjU2YWExZmMwNTk4NmRkM2ZlNyIsCiAgInByb2ZpbGVOYW1lIiA6ICJoaGphYnJpcyIsCiAgInNpZ25hdHVyZVJlcXVpcmVkIiA6IHRydWUsCiAgInRleHR1cmVzIiA6IHsKICAgICJTS0lOIiA6IHsKICAgICAgInVybCIgOiAiaHR0cDovL3RleHR1cmVzLm1pbmVjcmFmdC5uZXQvdGV4dHVyZS9iMmIxMmE4MTRjZWQ4YWYwMmNkZGYyOWEzN2U3ZjMwMTFlNDMwZThhMThiMzhiNzA2ZjI3YzZiZDMxNjUwYjY1IgogICAgfQogIH0KfQ=="
- )
- );
- put(
- "family_worms",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aWorm",
- "29f95759-1a6f-3e85-9941-91a7a2275274",
- "ewogICJ0aW1lc3RhbXAiIDogMTYyMDQ0NTc2NDQ1MSwKICAicHJvZmlsZUlkIiA6ICJmNDY0NTcxNDNkMTU0ZmEwOTkxNjBlNGJmNzI3ZGNiOSIsCiAgInByb2ZpbGVOYW1lIiA6ICJSZWxhcGFnbzA1IiwKICAic2lnbmF0dXJlUmVxdWlyZWQiIDogdHJ1ZSwKICAidGV4dHVyZXMiIDogewogICAgIlNLSU4iIDogewogICAgICAidXJsIiA6ICJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlL2RmMDNhZDk2MDkyZjNmNzg5OTAyNDM2NzA5Y2RmNjlkZTZiNzI3YzEyMWIzYzJkYWVmOWZmYTFjY2FlZDE4NmMiLAogICAgICAibWV0YWRhdGEiIDogewogICAgICAgICJtb2RlbCIgOiAic2xpbSIKICAgICAgfQogICAgfQogIH0KfQ=="
- )
- );
- put(
- "family_yog",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aYog",
- "35f02923-7bec-3869-9ef5-b42a4794cac8",
- "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzg5NTdkNTAyM2M5MzdjNGM0MWFhMjQxMmQ0MzQxMGJkYTIzY2Y3OWE5ZjZhYjM2Yjc2ZmVmMmQ3YzQyOSJ9fX0="
- )
- );
-
- // The Park
- put(
- "family_howling_spirit",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§a§bHowling Spirit",
- "802a167c-cbcd-3a1f-becd-5b1a25a4cf15",
- "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYjdjOGJlZjZiZWI3N2UyOWFmODYyN2VjZGMzOGQ4NmFhMmZlYTdjY2QxNjNkYzczYzAwZjlmMjU4ZjlhMTQ1NyJ9fX0="
- )
- );
- put(
- "family_pack_spirit",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§a§bPack Spirit",
- "802a167c-cbcd-3a1f-becd-5b1a25a4cf15",
- "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYjdjOGJlZjZiZWI3N2UyOWFmODYyN2VjZGMzOGQ4NmFhMmZlYTdjY2QxNjNkYzczYzAwZjlmMjU4ZjlhMTQ1NyJ9fX0="
- )
- );
- put(
- "family_soul_of_the_alpha",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§a§3Soul of the Alpha",
- "802a167c-cbcd-3a1f-becd-5b1a25a4cf15",
- "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYjdjOGJlZjZiZWI3N2UyOWFmODYyN2VjZGMzOGQ4NmFhMmZlYTdjY2QxNjNkYzczYzAwZjlmMjU4ZjlhMTQ1NyJ9fX0="
- )
- );
-
- // Spooky
- put(
- "family_batty_witch",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§a§8Crazy Witch",
- "cf4f97d7-2e1f-3678-9ca3-4a7b9666cc28",
- "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZmNlNjYwNDE1N2ZjNGFiNTU5MWU0YmNmNTA3YTc0OTkxOGVlOWM0MWUzNTdkNDczNzZlMGVlNzM0MjA3NGM5MCJ9fX0="
- )
- );
- put(
- "family_headless_horseman",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§a§6Headless Horseman",
- "2594a979-1302-3d6e-a1da-c9dbf0959539",
- "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNGM2NTcwZjEyNDI5OTJmNmViYTIzZWU1ODI1OThjMzllM2U3NDUzODMyNzNkZWVmOGIzOTc3NTgzZmUzY2Y1In19fQ=="
- )
- );
- put(
- "family_phantom_spirit",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§a§cPhantom Spirit",
- "805d7035-5f25-37ea-8530-7c0d09156c8e",
- "ewogICJ0aW1lc3RhbXAiIDogMTYwMzcyMjc5NzYzNywKICAicHJvZmlsZUlkIiA6ICJhMmY4MzQ1OTVjODk0YTI3YWRkMzA0OTcxNmNhOTEwYyIsCiAgInByb2ZpbGVOYW1lIiA6ICJiUHVuY2giLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNjUzYjJmN2M1ZTE3N2JkNjdjZWFkMzBkMGVlNTM0MjVjNzY4NGM5NzVjOGMyYTUyNzNhMDljYTQ5YTFmNmNkZCIKICAgIH0KICB9Cn0="
- )
- );
- put(
- "family_scary_jerry",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§a§6Scary Jerry",
- "127e3dec-4ab7-3798-9410-5fce3f227632",
- "ewogICJ0aW1lc3RhbXAiIDogMTYwMzczMzU4OTcxOSwKICAicHJvZmlsZUlkIiA6ICJhMmY4MzQ1OTVjODk0YTI3YWRkMzA0OTcxNmNhOTEwYyIsCiAgInByb2ZpbGVOYW1lIiA6ICJiUHVuY2giLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZGYyMDJkYzI0ZDE1ZjdjZTM2ZTAyZmI0YjNlODE1M2IxNDZhYjljMTcyNGFhYTVkNDg0Yzc0MWRhMGVlYjZmZCIKICAgIH0KICB9Cn0="
- )
- );
- put(
- "family_trick_or_treater",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§a§eTrick or Treater",
- "79dd9434-1fde-3aac-87a7-bb09d91eba77",
- "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZDdjYmUwNjFiNDQ1Yjg4Y2IyZGY1OWFjY2M4ZDJjMWMxMjExOGZlMGIyMTI3ZTZlNzU4MTM1NTBhZGFjNjdjZiJ9fX0="
- )
- );
- put(
- "family_wither_gourd",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§a§6Wither Gourd",
- "3263c14e-c555-365e-a244-0ee97a8b2056",
- "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNjhmMmZmYzZmYjRlOTk1OWI5YTdhMzE3ZjUxYTY3NzVhMTU5ZGRjMjI0MWRiZDZjNzc0ZDNhYzA4YjYifX19"
- )
- );
- put(
- "family_wraith",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§a§8Wraith",
- "bca22b11-8e4c-386a-8824-7b2bd6364cde",
- "ewogICJ0aW1lc3RhbXAiIDogMTYwMzczMzcxNjI0MiwKICAicHJvZmlsZUlkIiA6ICJhMmY4MzQ1OTVjODk0YTI3YWRkMzA0OTcxNmNhOTEwYyIsCiAgInByb2ZpbGVOYW1lIiA6ICJiUHVuY2giLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYWVhYmMzMDc1Y2Y0MWYzOGU2ZGYxMjM2Yjk1Y2FhZmNiYTFiZWUyMmM0OWQ4MDRiOTQyNzQ4OGMyZjZlMGVmYyIKICAgIH0KICB9Cn0="
- )
- );
-
- // Dungeons
- put(
- "family_diamond_guy",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§a§d§lAngry Archeologist",
- "db784d7a-fae1-3d60-9a5a-42a1814037f8",
- "eyJ0aW1lc3RhbXAiOjE1NzU0NzAzOTQwMzEsInByb2ZpbGVJZCI6IjdkYTJhYjNhOTNjYTQ4ZWU4MzA0OGFmYzNiODBlNjhlIiwicHJvZmlsZU5hbWUiOiJHb2xkYXBmZWwiLCJzaWduYXR1cmVSZXF1aXJlZCI6dHJ1ZSwidGV4dHVyZXMiOnsiU0tJTiI6eyJ1cmwiOiJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlL2M0OGM3ODM0NThlNGNmODUxOGU4YWI1ODYzZmJjNGNiOTQ4ZjkwNTY4ZWViOWE2MGQxNmM0ZmRlMmI5NmMwMzMifX19"
- )
- );
- put(
- "family_cellar_spider",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aCellar Spider",
- "a8aee72d-0d1d-3db7-8cf8-be1ce6ec2dc4",
- "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNDE2NDVkZmQ3N2QwOTkyMzEwN2IzNDk2ZTk0ZWViNWMzMDMyOWY5N2VmYzk2ZWQ3NmUyMjZlOTgyMjQifX19"
- )
- );
- put(
- "family_crypt_dreadlord",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aCrypt Dreadlord",
- "68b4c885-7447-3382-b86b-b661b464d76e",
- "eyJ0aW1lc3RhbXAiOjE1NjI0Mjc0MTA5MTQsInByb2ZpbGVJZCI6ImIwZDczMmZlMDBmNzQwN2U5ZTdmNzQ2MzAxY2Q5OGNhIiwicHJvZmlsZU5hbWUiOiJPUHBscyIsInNpZ25hdHVyZVJlcXVpcmVkIjp0cnVlLCJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNjZmMzQ5MjcwYTNiODUxODk2Y2RhZDg0MmY1ZWVjNmUxNDBiZDkxMTliNzVjMDc0OTU1YzNiZTc4NjVlMjdjNyJ9fX0="
- )
- );
- put(
- "family_crypt_lurker",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aCrypt Lurker",
- "9673d491-d589-44cb-b63e-5f8b3148b3df",
- "ewogICJ0aW1lc3RhbXAiIDogMTY0Njc1NjU2MzM1MiwKICAicHJvZmlsZUlkIiA6ICJkYmQ4MDQ2M2EwMzY0Y2FjYjI3OGNhODBhMDBkZGIxMyIsCiAgInByb2ZpbGVOYW1lIiA6ICJ4bG9nMjEiLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYjM2NjZkMWJkZjQ1NThiMGQxNjk5MGIyNDFlODE4NWNiZjU4YzNlMDNjMjRkOTA0NTQ0ZThjYzY1YjFjMzhkMSIKICAgIH0KICB9Cn0=\", \"n8vct7fj3NdiODy/h6PJhjxSR2U7d8gQxHjdVq553HqG60SSczt1Tl9XhvQbZP14ZrJGWxCziauuYb/HjZza0ugNAhfwh9z8hqR1PjBJGdvp+wpxoWpP2wd5RT9i5/GYEqpiAIAt9vHY1YeyejFqKZhXaGgp7gZZNjOQWQqB0SZzTUTAPzRW9FiY8x2re7H7Y1POThRXOvvkeQ6qWdPV6Hk5hTumV0rfEGm971jQRIbfdzBZDJRcro+8y+dlje/NpF5qf0JLy78Xr4hc2cwbT9+wqOeoUTcM/r9mwL15OKgFLjB44jszauKRHNfoqb6B3+1fNQEJrJK/7hIyvswpde7C5uOxkE7oMFib6X68VVEhb6PGC1+HWNaMaGjI0wWEkCahp48ihN9+sBEBFXOxIAhXG/pvJcbEi742/cBS1CTtOI8qui6JSL9MKX5jmyhtjjibOYRZbacosqayCnwsJAdMmwS7zIxc8jGhpfKECiSni/baS4zRla0bns4hfEM0l7ASv0Dh99WQD0We2ZMqltmix8lMEaAILXJVBln3CFrjYvncfku2hrSaqu1lNAtfMYYSITEUCBJ7McVAVmUHOrER0XGoVs9L237H0BQNSLqlGGEQ7OM8HV6G0YfXGlbNgNBx6O9k8ZijuK60JeEoJapcmbNj/LVHEU+dsgcFAbo="
- )
- );
- put(
- "family_crypt_souleater",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aCrypt Souleater",
- "68b4c885-7447-3382-b86b-b661b464d76e",
- "eyJ0aW1lc3RhbXAiOjE1NjI0Mjc0MTA5MTQsInByb2ZpbGVJZCI6ImIwZDczMmZlMDBmNzQwN2U5ZTdmNzQ2MzAxY2Q5OGNhIiwicHJvZmlsZU5hbWUiOiJPUHBscyIsInNpZ25hdHVyZVJlcXVpcmVkIjp0cnVlLCJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNjZmMzQ5MjcwYTNiODUxODk2Y2RhZDg0MmY1ZWVjNmUxNDBiZDkxMTliNzVjMDc0OTU1YzNiZTc4NjVlMjdjNyJ9fX0="
- )
- );
- put(
- "family_king_midas",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§a§d§lKing Midas",
- "1a85d923-f8dd-35b8-899a-8f13b9469b0c",
- "ewogICJ0aW1lc3RhbXAiIDogMTU5MTU3NjA3MDMwMCwKICAicHJvZmlsZUlkIiA6ICJkYTQ5OGFjNGU5Mzc0ZTVjYjYxMjdiMzgwODU1Nzk4MyIsCiAgInByb2ZpbGVOYW1lIiA6ICJOaXRyb2hvbGljXzIiLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNjJiY2EwODU3NTAwNDM1MDNmNWRmOWY3ZGVmODI0YTJlM2FjZmMyNzg0MmJjZDA5ZDJiNjY5NTg4MWU4MzJmNSIKICAgIH0KICB9Cn0="
- )
- );
- put(
- "family_lonely_spider",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aLonely Spider",
- "7c63f3cf-a963-311a-aeca-3a075b417806",
- "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvY2Q1NDE1NDFkYWFmZjUwODk2Y2QyNThiZGJkZDRjZjgwYzNiYTgxNjczNTcyNjA3OGJmZTM5MzkyN2U1N2YxIn19fQ=="
- )
- );
- put(
- "family_lost_adventurer",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§a§d§lLost Adventurer",
- "f69ba621-a8b6-31a7-8de1-dc7ade140e1d",
- "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHBzOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzFlMDMyOWY0MjE5MmVlN2MxYTBjNzA0ZjgyZGJiYmU3YzAwZmJmYTNmMDIwYzEwNjdhMjA4NjMwYjk5MWI5ODgifX19"
- )
- );
- put(
- "family_scared_skeleton",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aScared Skeleton",
- "53924f1a-87e6-4709-8e53-f1c7d13dc239",
- "ewogICJ0aW1lc3RhbXAiIDogMTY1NTYzMTgzNjcwNCwKICAicHJvZmlsZUlkIiA6ICI1MzkyNGYxYTg3ZTY0NzA5OGU1M2YxYzdkMTNkYzIzOSIsCiAgInByb2ZpbGVOYW1lIiA6ICJUaHJvd3BvIiwKICAic2lnbmF0dXJlUmVxdWlyZWQiIDogdHJ1ZSwKICAidGV4dHVyZXMiIDogewogICAgIlNLSU4iIDogewogICAgICAidXJsIiA6ICJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzg4ZWI2OGE0ZDM4ZTlmNDQ2YjhlOTkyNzVmMTYwMzAyZjM2NmVmMTAyMTZhYmY5NDg0ODdlNTgyNTEyYmQwZjMiCiAgICB9CiAgfQp9="
- )
- );
- put(
- "family_shadow_assassin",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§a§d§lShadow Assassin",
- "ef18719c-db6a-3ffb-97ca-4ed764ce9464",
- "ewogICJ0aW1lc3RhbXAiIDogMTU5MjI2ODE3MDkxMSwKICAicHJvZmlsZUlkIiA6ICJkYTQ5OGFjNGU5Mzc0ZTVjYjYxMjdiMzgwODU1Nzk4MyIsCiAgInByb2ZpbGVOYW1lIiA6ICJOaXRyb2hvbGljXzIiLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzM5OWUwMGY0MDQ0MTFlNDY1ZDc0Mzg4ZGYxMzJkNTFmZTg2OGVjZjg2ZjFjMDczZmFmZmExZDkxNzJlYzBmMyIKICAgIH0KICB9Cn0="
- )
- );
- put(
- "family_skeleton_grunt",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aSkeleton Grunt",
- "dfed3415-919e-3358-b563-0abd0513f74c",
- "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNzA0NzE2NzdiMzdhZTg0MmMyYmQyMzJlMTZlZWI4NGQ1YTQ5MzIzMWVlY2VjMDcyZGEzOGJlMzEyN2RkNWM4In19fQ=="
- )
- );
- put(
- "family_skeleton_master",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aSkeleton Master",
- "ce22e0d7-c78e-3c8d-907a-2368c927808c",
- "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNzRlOTVlMWI3ZGM4MmJhNzg0NWE2OGZjNmEzMTJmNGNkOTBlZTJmNmNjZTI2YTY4Yzg4YjA0YjEwNzJkODc5In19fQ=="
- )
- );
- put(
- "family_skeleton_soldier",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aSkeleton Soldier",
- "cab75065-c896-338e-a399-c4a6da16d678",
- "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMjE5Njg4ZTBjMmYwNWFlYjk3OWQ2YTFiOGM5MTE5NTdiN2QzNjU3ZTE0YjU3YWY5M2M1ZWY2ZjZhNTk1NjlkZCJ9fX0="
- )
- );
- put(
- "family_skeletor",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aSkeletor",
- "49fcfb3e-da7e-3fda-b4f9-37df5ac8fbd3",
- "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvODlkMDc0YWQ5Yjk5NzE4NzllYjMyNWJkZGZmMzY3NWY3MjI0ODU2YmQ2ZDU2OWZjOGQ0ODNjMTMzZDczMDA1ZCJ9fX0K"
- )
- );
- put(
- "family_sniper_skeleton",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aSniper",
- "848130dc-9c46-3818-a099-b429cb2f1d75",
- "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYjE4YzA3MWYwODBkYmE1MGE2MmE2MjYzZmY3MjRlZGMxNTdjZTRmYjQ4ODNjY2VmZjI0OTFkNWJiZGU4MzBjMSJ9fX0K"
- )
- );
- put(
- "family_super_archer",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aSuper Archer",
- "8ebf155b-7b8f-386f-91f1-2e425db4230f",
- "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZGNhZTZkYjBiNTlhNjQzMDUwNzZkOTY2ZDhlN2I5YTk3YmU0NmRhZTNhODA3NzE0ZmE4NmQzNzg0OGY2In19fQ=="
- )
- );
- put(
- "family_super_tank_zombie",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aSuper Tank Zombie",
- "9673d491-d589-44cb-b63e-5f8b3148b3df",
- "ewogICJ0aW1lc3RhbXAiIDogMTY0Njc1NjU2MzM1MiwKICAicHJvZmlsZUlkIiA6ICJkYmQ4MDQ2M2EwMzY0Y2FjYjI3OGNhODBhMDBkZGIxMyIsCiAgInByb2ZpbGVOYW1lIiA6ICJ4bG9nMjEiLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYjM2NjZkMWJkZjQ1NThiMGQxNjk5MGIyNDFlODE4NWNiZjU4YzNlMDNjMjRkOTA0NTQ0ZThjYzY1YjFjMzhkMSIKICAgIH0KICB9Cn0=\", \"n8vct7fj3NdiODy/h6PJhjxSR2U7d8gQxHjdVq553HqG60SSczt1Tl9XhvQbZP14ZrJGWxCziauuYb/HjZza0ugNAhfwh9z8hqR1PjBJGdvp+wpxoWpP2wd5RT9i5/GYEqpiAIAt9vHY1YeyejFqKZhXaGgp7gZZNjOQWQqB0SZzTUTAPzRW9FiY8x2re7H7Y1POThRXOvvkeQ6qWdPV6Hk5hTumV0rfEGm971jQRIbfdzBZDJRcro+8y+dlje/NpF5qf0JLy78Xr4hc2cwbT9+wqOeoUTcM/r9mwL15OKgFLjB44jszauKRHNfoqb6B3+1fNQEJrJK/7hIyvswpde7C5uOxkE7oMFib6X68VVEhb6PGC1+HWNaMaGjI0wWEkCahp48ihN9+sBEBFXOxIAhXG/pvJcbEi742/cBS1CTtOI8qui6JSL9MKX5jmyhtjjibOYRZbacosqayCnwsJAdMmwS7zIxc8jGhpfKECiSni/baS4zRla0bns4hfEM0l7ASv0Dh99WQD0We2ZMqltmix8lMEaAILXJVBln3CFrjYvncfku2hrSaqu1lNAtfMYYSITEUCBJ7McVAVmUHOrER0XGoVs9L237H0BQNSLqlGGEQ7OM8HV6G0YfXGlbNgNBx6O9k8ZijuK60JeEoJapcmbNj/LVHEU+dsgcFAbo="
- )
- );
- put(
- "family_crypt_tank_zombie",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aTank Zombie",
- "9673d491-d589-44cb-b63e-5f8b3148b3df",
- "ewogICJ0aW1lc3RhbXAiIDogMTY0Njc1NjU2MzM1MiwKICAicHJvZmlsZUlkIiA6ICJkYmQ4MDQ2M2EwMzY0Y2FjYjI3OGNhODBhMDBkZGIxMyIsCiAgInByb2ZpbGVOYW1lIiA6ICJ4bG9nMjEiLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYjM2NjZkMWJkZjQ1NThiMGQxNjk5MGIyNDFlODE4NWNiZjU4YzNlMDNjMjRkOTA0NTQ0ZThjYzY1YjFjMzhkMSIKICAgIH0KICB9Cn0=\", \"n8vct7fj3NdiODy/h6PJhjxSR2U7d8gQxHjdVq553HqG60SSczt1Tl9XhvQbZP14ZrJGWxCziauuYb/HjZza0ugNAhfwh9z8hqR1PjBJGdvp+wpxoWpP2wd5RT9i5/GYEqpiAIAt9vHY1YeyejFqKZhXaGgp7gZZNjOQWQqB0SZzTUTAPzRW9FiY8x2re7H7Y1POThRXOvvkeQ6qWdPV6Hk5hTumV0rfEGm971jQRIbfdzBZDJRcro+8y+dlje/NpF5qf0JLy78Xr4hc2cwbT9+wqOeoUTcM/r9mwL15OKgFLjB44jszauKRHNfoqb6B3+1fNQEJrJK/7hIyvswpde7C5uOxkE7oMFib6X68VVEhb6PGC1+HWNaMaGjI0wWEkCahp48ihN9+sBEBFXOxIAhXG/pvJcbEi742/cBS1CTtOI8qui6JSL9MKX5jmyhtjjibOYRZbacosqayCnwsJAdMmwS7zIxc8jGhpfKECiSni/baS4zRla0bns4hfEM0l7ASv0Dh99WQD0We2ZMqltmix8lMEaAILXJVBln3CFrjYvncfku2hrSaqu1lNAtfMYYSITEUCBJ7McVAVmUHOrER0XGoVs9L237H0BQNSLqlGGEQ7OM8HV6G0YfXGlbNgNBx6O9k8ZijuK60JeEoJapcmbNj/LVHEU+dsgcFAbo="
- )
- );
- put(
- "family_watcher_summon_undead",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§a§4§lUndead",
- "0ac53e90-4e60-388c-a754-092dd4578592",
- "eyJ0aW1lc3RhbXAiOjE1ODYwNDAyMDM1NzMsInByb2ZpbGVJZCI6ImRhNDk4YWM0ZTkzNzRlNWNiNjEyN2IzODA4NTU3OTgzIiwicHJvZmlsZU5hbWUiOiJOaXRyb2hvbGljXzIiLCJzaWduYXR1cmVSZXF1aXJlZCI6dHJ1ZSwidGV4dHVyZXMiOnsiU0tJTiI6eyJ1cmwiOiJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlL2Y0NjI0YTlhOGM2OWNhMjA0NTA0YWJiMDQzZDQ3NDU2Y2Q5YjA5NzQ5YTM2MzU3NDYyMzAzZjI3NmEyMjlkNCJ9fX0="
- )
- );
- put(
- "family_dungeon_respawning_skeleton",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aUndead Skeleton",
- "53924f1a-87e6-4709-8e53-f1c7d13dc239",
- "ewogICJ0aW1lc3RhbXAiIDogMTY1NTYzMTgzNjcwNCwKICAicHJvZmlsZUlkIiA6ICI1MzkyNGYxYTg3ZTY0NzA5OGU1M2YxYzdkMTNkYzIzOSIsCiAgInByb2ZpbGVOYW1lIiA6ICJUaHJvd3BvIiwKICAic2lnbmF0dXJlUmVxdWlyZWQiIDogdHJ1ZSwKICAidGV4dHVyZXMiIDogewogICAgIlNLSU4iIDogewogICAgICAidXJsIiA6ICJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzg4ZWI2OGE0ZDM4ZTlmNDQ2YjhlOTkyNzVmMTYwMzAyZjM2NmVmMTAyMTZhYmY5NDg0ODdlNTgyNTEyYmQwZjMiCiAgICB9CiAgfQp9="
- )
- );
- put(
- "family_crypt_witherskeleton",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aWithermancer",
- "d0e05de7-6067-454d-beae-c6d19d886191",
- "ewogICJ0aW1lc3RhbXAiIDogMTY1NTYzMjg1MTE1NCwKICAicHJvZmlsZUlkIiA6ICJkMGUwNWRlNzYwNjc0NTRkYmVhZWM2ZDE5ZDg4NjE5MSIsCiAgInByb2ZpbGVOYW1lIiA6ICJNb3VsYmVycnkiLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYmNlMTU1MjI0ZWE0YmM0OWE4ZTkxOTA3MzdjYjA0MTdkOGE3YzM4YTAzN2Q4ZDAzODJkZGU0ODI5YzEwMzU5MCIsCiAgICAgICJtZXRhZGF0YSIgOiB7CiAgICAgICAgIm1vZGVsIiA6ICJzbGltIgogICAgICB9CiAgICB9CiAgfQp9"
- )
- );
- put(
- "family_zombie_commander",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aZombie Commander",
- "9673d491-d589-44cb-b63e-5f8b3148b3df",
- "ewogICJ0aW1lc3RhbXAiIDogMTY0Njc1NjU2MzM1MiwKICAicHJvZmlsZUlkIiA6ICJkYmQ4MDQ2M2EwMzY0Y2FjYjI3OGNhODBhMDBkZGIxMyIsCiAgInByb2ZpbGVOYW1lIiA6ICJ4bG9nMjEiLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYjM2NjZkMWJkZjQ1NThiMGQxNjk5MGIyNDFlODE4NWNiZjU4YzNlMDNjMjRkOTA0NTQ0ZThjYzY1YjFjMzhkMSIKICAgIH0KICB9Cn0=\", \"n8vct7fj3NdiODy/h6PJhjxSR2U7d8gQxHjdVq553HqG60SSczt1Tl9XhvQbZP14ZrJGWxCziauuYb/HjZza0ugNAhfwh9z8hqR1PjBJGdvp+wpxoWpP2wd5RT9i5/GYEqpiAIAt9vHY1YeyejFqKZhXaGgp7gZZNjOQWQqB0SZzTUTAPzRW9FiY8x2re7H7Y1POThRXOvvkeQ6qWdPV6Hk5hTumV0rfEGm971jQRIbfdzBZDJRcro+8y+dlje/NpF5qf0JLy78Xr4hc2cwbT9+wqOeoUTcM/r9mwL15OKgFLjB44jszauKRHNfoqb6B3+1fNQEJrJK/7hIyvswpde7C5uOxkE7oMFib6X68VVEhb6PGC1+HWNaMaGjI0wWEkCahp48ihN9+sBEBFXOxIAhXG/pvJcbEi742/cBS1CTtOI8qui6JSL9MKX5jmyhtjjibOYRZbacosqayCnwsJAdMmwS7zIxc8jGhpfKECiSni/baS4zRla0bns4hfEM0l7ASv0Dh99WQD0We2ZMqltmix8lMEaAILXJVBln3CFrjYvncfku2hrSaqu1lNAtfMYYSITEUCBJ7McVAVmUHOrER0XGoVs9L237H0BQNSLqlGGEQ7OM8HV6G0YfXGlbNgNBx6O9k8ZijuK60JeEoJapcmbNj/LVHEU+dsgcFAbo="
- )
- );
- put(
- "family_zombie_grunt",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aZombie Grunt",
- "9673d491-d589-44cb-b63e-5f8b3148b3df",
- "ewogICJ0aW1lc3RhbXAiIDogMTY0Njc1NjU2MzM1MiwKICAicHJvZmlsZUlkIiA6ICJkYmQ4MDQ2M2EwMzY0Y2FjYjI3OGNhODBhMDBkZGIxMyIsCiAgInByb2ZpbGVOYW1lIiA6ICJ4bG9nMjEiLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYjM2NjZkMWJkZjQ1NThiMGQxNjk5MGIyNDFlODE4NWNiZjU4YzNlMDNjMjRkOTA0NTQ0ZThjYzY1YjFjMzhkMSIKICAgIH0KICB9Cn0=\", \"n8vct7fj3NdiODy/h6PJhjxSR2U7d8gQxHjdVq553HqG60SSczt1Tl9XhvQbZP14ZrJGWxCziauuYb/HjZza0ugNAhfwh9z8hqR1PjBJGdvp+wpxoWpP2wd5RT9i5/GYEqpiAIAt9vHY1YeyejFqKZhXaGgp7gZZNjOQWQqB0SZzTUTAPzRW9FiY8x2re7H7Y1POThRXOvvkeQ6qWdPV6Hk5hTumV0rfEGm971jQRIbfdzBZDJRcro+8y+dlje/NpF5qf0JLy78Xr4hc2cwbT9+wqOeoUTcM/r9mwL15OKgFLjB44jszauKRHNfoqb6B3+1fNQEJrJK/7hIyvswpde7C5uOxkE7oMFib6X68VVEhb6PGC1+HWNaMaGjI0wWEkCahp48ihN9+sBEBFXOxIAhXG/pvJcbEi742/cBS1CTtOI8qui6JSL9MKX5jmyhtjjibOYRZbacosqayCnwsJAdMmwS7zIxc8jGhpfKECiSni/baS4zRla0bns4hfEM0l7ASv0Dh99WQD0We2ZMqltmix8lMEaAILXJVBln3CFrjYvncfku2hrSaqu1lNAtfMYYSITEUCBJ7McVAVmUHOrER0XGoVs9L237H0BQNSLqlGGEQ7OM8HV6G0YfXGlbNgNBx6O9k8ZijuK60JeEoJapcmbNj/LVHEU+dsgcFAbo="
- )
- );
- put(
- "family_zombie_knight",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aZombie Knight",
- "34af9e21-dff4-3b94-9fb5-07816e41af75",
- "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMjVkMmYzMWJhMTYyZmU2MjcyZTgzMWFlZDE3ZjUzMjEzZGI2ZmExYzRjYmU0ZmM4MjdmMzk2M2NjOThiOSJ9fX0="
- )
- );
- put(
- "family_zombie_soldier",
- Utils.createSkull(
- EnumChatFormatting.AQUA + "§aZombie Soldier",
- "9673d491-d589-44cb-b63e-5f8b3148b3df",
- "ewogICJ0aW1lc3RhbXAiIDogMTY0Njc1NjU2MzM1MiwKICAicHJvZmlsZUlkIiA6ICJkYmQ4MDQ2M2EwMzY0Y2FjYjI3OGNhODBhMDBkZGIxMyIsCiAgInByb2ZpbGVOYW1lIiA6ICJ4bG9nMjEiLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYjM2NjZkMWJkZjQ1NThiMGQxNjk5MGIyNDFlODE4NWNiZjU4YzNlMDNjMjRkOTA0NTQ0ZThjYzY1YjFjMzhkMSIKICAgIH0KICB9Cn0=\", \"n8vct7fj3NdiODy/h6PJhjxSR2U7d8gQxHjdVq553HqG60SSczt1Tl9XhvQbZP14ZrJGWxCziauuYb/HjZza0ugNAhfwh9z8hqR1PjBJGdvp+wpxoWpP2wd5RT9i5/GYEqpiAIAt9vHY1YeyejFqKZhXaGgp7gZZNjOQWQqB0SZzTUTAPzRW9FiY8x2re7H7Y1POThRXOvvkeQ6qWdPV6Hk5hTumV0rfEGm971jQRIbfdzBZDJRcro+8y+dlje/NpF5qf0JLy78Xr4hc2cwbT9+wqOeoUTcM/r9mwL15OKgFLjB44jszauKRHNfoqb6B3+1fNQEJrJK/7hIyvswpde7C5uOxkE7oMFib6X68VVEhb6PGC1+HWNaMaGjI0wWEkCahp48ihN9+sBEBFXOxIAhXG/pvJcbEi742/cBS1CTtOI8qui6JSL9MKX5jmyhtjjibOYRZbacosqayCnwsJAdMmwS7zIxc8jGhpfKECiSni/baS4zRla0bns4hfEM0l7ASv0Dh99WQD0We2ZMqltmix8lMEaAILXJVBln3CFrjYvncfku2hrSaqu1lNAtfMYYSITEUCBJ7McVAVmUHOrER0XGoVs9L237H0BQNSLqlGGEQ7OM8HV6G0YfXGlbNgNBx6O9k8ZijuK60JeEoJapcmbNj/LVHEU+dsgcFAbo="
- )
- );
- }
- };
- private static final LinkedHashMap<String, String> mobTypeMap = new LinkedHashMap<String, String>() {
- {
- // Island
- put("family_cave_spider", "ISLAND");
- put("family_enderman_private", "ISLAND");
- put("family_skeleton", "ISLAND");
- put("family_slime", "ISLAND");
- put("family_spider", "ISLAND");
- put("family_witch", "ISLAND");
- put("family_zombie", "ISLAND");
-
- // Hub
- put("family_unburried_zombie", "MOB");
- put("family_old_wolf", "MOB");
- put("family_ruin_wolf", "MOB");
- put("family_zombie_villager", "MOB");
-
- // Spiders Den
- put("family_arachne", "BOSS");
- put("family_arachne_brood", "MOB");
- put("family_arachne_keeper", "MOB");
- put("family_brood_mother_spider", "BOSS");
- put("family_dasher_spider", "MOB");
- put("family_respawning_skeleton", "MOB");
- put("family_random_slime", "MOB");
- put("family_spider_jockey", "MOB");
- put("family_splitter_spider", "MOB");
- put("family_voracious_spider", "MOB");
- put("family_weaver_spider", "MOB");
-
- // The End
- put("family_dragon", "BOSS");
- put("family_enderman", "MOB");
- put("family_endermite", "MOB");
- put("family_corrupted_protector", "BOSS");
- put("family_obsidian_wither", "MOB");
- put("family_voidling_extremist", "MOB");
- put("family_voidling_fanatic", "MOB");
- put("family_watcher", "MOB");
- put("family_zealot_enderman", "MOB");
-
- // Crimson Isles
- put("family_ashfang", "BOSS");
- put("family_barbarian_duke_x", "BOSS");
- put("family_bladesoul", "BOSS");
- put("family_blaze", "MOB");
- put("family_flaming_spider", "MOB");
- put("family_ghast", "MOB");
- put("family_mage_outlaw", "BOSS");
- put("family_magma_cube", "MOB");
- put("family_magma_boss", "BOSS");
- put("family_matcho", "MOB");
- put("family_charging_mushroom_cow", "MOB");
- put("family_pigman", "MOB");
- put("family_wither_skeleton", "MOB");
- put("family_wither_spectre", "MOB");
-
- // Deep Caverns
- put("family_automaton", "MOB");
- put("family_butterfly", "MOB");
- put("family_emerald_slime", "MOB");
- put("family_caverns_ghost", "MOB");
- put("family_goblin", "MOB");
- put("family_team_treasurite", "MOB");
- put("family_ice_walker", "MOB");
- put("family_lapis_zombie", "MOB");
- put("family_diamond_skeleton", "MOB");
- put("family_diamond_zombie", "MOB");
- put("family_redstone_pigman", "MOB");
- put("family_sludge", "MOB");
- put("family_invisible_creeper", "MOB");
- put("family_thyst", "MOB");
- put("family_treasure_hoarder", "MOB");
- put("family_worms", "MOB");
- put("family_yog", "MOB");
-
- // The Park
- put("family_howling_spirit", "MOB");
- put("family_pack_spirit", "MOB");
- put("family_soul_of_the_alpha", "MOB");
-
- // Spooky
- put("family_batty_witch", "MOB");
- put("family_headless_horseman", "BOSS");
- put("family_phantom_spirit", "MOB");
- put("family_scary_jerry", "MOB");
- put("family_trick_or_treater", "MOB");
- put("family_wither_gourd", "MOB");
- put("family_wraith", "MOB");
-
- // Catacombs
- put("family_diamond_guy", "MOB");
- put("family_cellar_spider", "MOB");
- put("family_crypt_dreadlord", "MOB");
- put("family_crypt_lurker", "MOB");
- put("family_crypt_souleater", "MOB");
- put("family_king_midas", "MOB");
- put("family_lonely_spider", "MOB");
- put("family_lost_adventurer", "MOB");
- put("family_scared_skeleton", "MOB");
- put("family_shadow_assassin", "MOB");
- put("family_skeleton_grunt", "MOB");
- put("family_skeleton_master", "MOB");
- put("family_skeleton_soldier", "MOB");
- put("family_skeletor", "MOB");
- put("family_sniper_skeleton", "MOB");
- put("family_super_archer", "MOB");
- put("family_super_tank_zombie", "MOB");
- put("family_crypt_tank_zombie", "MOB");
- put("family_watcher_summon_undead", "MOB");
- put("family_dungeon_respawning_skeleton", "MOB");
- put("family_crypt_witherskeleton", "MOB");
- put("family_zombie_commander", "MOB");
- put("family_zombie_grunt", "MOB");
- put("family_zombie_knight", "MOB");
- put("family_zombie_soldier", "MOB");
- }
- };
-
- public static LinkedHashMap<ItemStack, List<String>> getBestiaryLocations() {
- return bestiaryLocations;
- }
-
- public static LinkedHashMap<String, ItemStack> getBestiaryMobs() {
- return bestiaryMobs;
- }
-
- public static LinkedHashMap<String, String> getMobType() {
- return mobTypeMap;
- }
-}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/bestiary/BestiaryData.kt b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/bestiary/BestiaryData.kt
new file mode 100644
index 00000000..ff2d2288
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/bestiary/BestiaryData.kt
@@ -0,0 +1,213 @@
+/*
+ * Copyright (C) 2023 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.profileviewer.bestiary
+
+import com.google.gson.JsonObject
+import io.github.moulberry.notenoughupdates.util.Constants
+import io.github.moulberry.notenoughupdates.util.ItemUtils
+import io.github.moulberry.notenoughupdates.util.Utils
+
+object BestiaryData {
+ private val categoriesToParse = listOf(
+ "dynamic",
+ "hub",
+ "farming_1",
+ "combat_1",
+ "combat_3",
+ "crimson_isle",
+ "mining_2",
+ "mining_3",
+ "crystal_hollows",
+ "foraging_1",
+ "spooky_festival",
+ "mythological_creatures",
+ "jerry",
+ "kuudra",
+ "catacombs",
+ "fishing"
+ )
+
+ /**
+ * Calculates the sum of all individual tiers for this profile
+ *
+ * @param computedCategories List of parsed categories
+ * @see BestiaryPage.parseBestiaryData
+ */
+ @JvmStatic
+ fun calculateTotalBestiaryLevel(computedCategories: List<Category>): Int {
+ var level = 0.0
+ computedCategories.forEach {
+ level += countTotalLevels(it)
+ }
+ return level.toInt() - 1
+ }
+
+ private fun countTotalLevels(category: Category): Int {
+ var levels = 0
+ for (mob in category.mobs) {
+ levels += mob.mobLevelData.level
+ }
+ category.subCategories.forEach { levels += countTotalLevels(it) }
+ return levels
+ }
+
+ /**
+ * Checks if a user profile has migrated.
+ *
+ * @param profileInfo skyblock profile information
+ */
+ fun hasMigrated(profileInfo: JsonObject): Boolean {
+ val bestiaryObject = profileInfo.getAsJsonObject("bestiary") ?: return false
+
+ return (bestiaryObject.get("migration") ?: return false).asBoolean
+ }
+
+ /**
+ * Parse the bestiary data for the profile. Categories are taken from the `constants/bestiary.json` repo file
+ *
+ * @param profileInfo the JsonObject containing the bestiary data
+ */
+ @JvmStatic
+ fun parseBestiaryData(profileInfo: JsonObject): MutableList<Category> {
+ if (!hasMigrated(profileInfo) || Constants.BESTIARY == null) {
+ return mutableListOf()
+ }
+
+ val parsedCategories = mutableListOf<Category>()
+
+ val apiKills = profileInfo.getAsJsonObject("bestiary")!!.getAsJsonObject("kills") ?: return mutableListOf()
+ val apiDeaths = profileInfo.getAsJsonObject("bestiary").getAsJsonObject("deaths")
+ val killsMap: HashMap<String, Int> = HashMap()
+ for (entry in apiKills.entrySet()) {
+ killsMap[entry.key] = entry.value.asInt
+ }
+ val deathsMap: HashMap<String, Int> = HashMap()
+ for (entry in apiDeaths.entrySet()) {
+ deathsMap[entry.key] = entry.value.asInt
+ }
+
+ for (categoryId in categoriesToParse) {
+ val categoryData = Constants.BESTIARY.getAsJsonObject(categoryId)!!
+ parsedCategories.add(parseCategory(categoryData, categoryId, killsMap, deathsMap))
+ }
+
+ return parsedCategories
+ }
+
+ /**
+ * Parse one individual category, including potential subcategories
+ */
+ private fun parseCategory(
+ categoryData: JsonObject,
+ categoryId: String,
+ killsMap: HashMap<String, Int>,
+ deathsMap: HashMap<String, Int>
+ ): Category {
+ val categoryName = categoryData["name"].asString
+ val computedMobs: MutableList<Mob> = mutableListOf()
+ val categoryIconData = categoryData["icon"].asJsonObject
+
+ val categoryIcon = if (categoryIconData.has("skullOwner")) {
+ Utils.createSkull(
+ categoryName, categoryIconData["skullOwner"].asString, categoryIconData["texture"].asString
+ )
+ } else {
+ ItemUtils.createItemStackFromId(categoryIconData["item"].asString, categoryName)
+ }
+ if (categoryData.has("hasSubcategories")) { // It must have some subcategories
+ val subCategories: MutableList<Category> = mutableListOf()
+
+ val reserved = listOf("name", "icon", "hasSubcategories")
+ for (entry in categoryData.entrySet()) {
+ if (!reserved.contains(entry.key)) {
+ subCategories.add(
+ parseCategory(
+ entry.value.asJsonObject,
+ "${categoryId}_${entry.key}",
+ killsMap,
+ deathsMap
+ )
+ )
+ }
+ }
+ return Category(categoryId, categoryName, categoryIcon, emptyList(), subCategories)
+ } else {
+ val categoryMobs = categoryData["mobs"].asJsonArray.map { it.asJsonObject }
+
+ for (mobData in categoryMobs) {
+ val mobName = mobData["name"].asString
+ val mobIcon = if (mobData.has("skullOwner")) {
+ Utils.createSkull(
+ mobName, mobData["skullOwner"].asString, mobData["texture"].asString
+ )
+ } else {
+ ItemUtils.createItemStackFromId(mobData["item"].asString, mobName)
+ }
+
+ val cap = mobData["cap"].asDouble
+ val bracket = mobData["bracket"].asInt
+
+ var kills = 0.0
+ var deaths = 0.0
+
+ // The mobs array contains the individual names returned by the API
+ val mobsArray = mobData["mobs"].asJsonArray.map { it.asString }
+ for (s in mobsArray) {
+ kills += killsMap.getOrDefault(s, 0)
+ deaths += deathsMap.getOrDefault(s, 0)
+ }
+
+ val levelData = calculateLevel(bracket, kills, cap)
+ computedMobs.add(Mob(mobName, mobIcon, kills, deaths, levelData))
+ }
+ return Category(categoryId, categoryName, categoryIcon, computedMobs, emptyList())
+ }
+ }
+
+ /**
+ * Calculates the level for a given mob
+ *
+ * @param bracket applicable bracket number
+ * @param kills number of kills the player has on that mob type
+ * @param cap maximum kill limit for the mob
+ */
+ private fun calculateLevel(bracket: Int, kills: Double, cap: Double): MobLevelData {
+ val bracketData =
+ Constants.BESTIARY["brackets"].asJsonObject[bracket.toString()].asJsonArray.map { it.asDouble }
+ var maxLevel = false
+
+ val effectiveKills = if (kills >= cap) {
+ maxLevel = true
+ cap
+ } else {
+ kills
+ }
+
+ var level = 0
+ for (requiredKills in bracketData) {
+ if (effectiveKills >= requiredKills) {
+ level++
+ } else {
+ break
+ }
+ }
+ return MobLevelData(level, maxLevel)
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/bestiary/BestiaryPage.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/bestiary/BestiaryPage.java
deleted file mode 100644
index 17cd6787..00000000
--- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/bestiary/BestiaryPage.java
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
- * Copyright (C) 2022 NotEnoughUpdates contributors
- *
- * This file is part of NotEnoughUpdates.
- *
- * NotEnoughUpdates is free software: you can redistribute it
- * and/or modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation, either
- * version 3 of the License, or (at your option) any later version.
- *
- * NotEnoughUpdates is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
- */
-
-package io.github.moulberry.notenoughupdates.profileviewer.bestiary;
-
-import com.google.gson.JsonArray;
-import com.google.gson.JsonObject;
-import io.github.moulberry.notenoughupdates.core.util.StringUtils;
-import io.github.moulberry.notenoughupdates.profileviewer.GuiProfileViewer;
-import io.github.moulberry.notenoughupdates.profileviewer.GuiProfileViewerPage;
-import io.github.moulberry.notenoughupdates.profileviewer.ProfileViewer;
-import io.github.moulberry.notenoughupdates.profileviewer.ProfileViewerUtils;
-import io.github.moulberry.notenoughupdates.profileviewer.SkyblockProfiles;
-import io.github.moulberry.notenoughupdates.util.Constants;
-import io.github.moulberry.notenoughupdates.util.Utils;
-import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.ScaledResolution;
-import net.minecraft.client.renderer.GlStateManager;
-import net.minecraft.client.renderer.RenderHelper;
-import net.minecraft.item.ItemStack;
-import net.minecraft.util.EnumChatFormatting;
-import net.minecraft.util.ResourceLocation;
-import org.lwjgl.opengl.GL11;
-
-import java.awt.*;
-import java.util.ArrayList;
-import java.util.List;
-
-import static io.github.moulberry.notenoughupdates.profileviewer.GuiProfileViewer.pv_elements;
-
-public class BestiaryPage extends GuiProfileViewerPage {
-
- private static final ResourceLocation BESTIARY_TEXTURE = new ResourceLocation("notenoughupdates:pv_bestiary_tab.png");
- private static final int XCOUNT = 7;
- private static final int YCOUNT = 5;
- private static final float XPADDING = (190 - XCOUNT * 20) / (float) (XCOUNT + 1);
- private static final float YPADDING = (202 - YCOUNT * 20) / (float) (YCOUNT + 1);
- private ItemStack selectedBestiaryLocation = null;
- private List<String> tooltipToDisplay = null;
-
- public BestiaryPage(GuiProfileViewer instance) {
- super(instance);
- }
-
- @Override
- public void drawPage(int mouseX, int mouseY, float partialTicks) {
- int guiLeft = GuiProfileViewer.getGuiLeft();
- int guiTop = GuiProfileViewer.getGuiTop();
-
- SkyblockProfiles.SkyblockProfile selectedProfile = getSelectedProfile();
- if (selectedProfile == null) {
- return;
- }
-
- JsonObject profileInfo = selectedProfile.getProfileJson();
-
- int bestiarySize = BestiaryData.getBestiaryLocations().size();
- int bestiaryXSize = (int) (350f / (bestiarySize - 1 + 0.0000001f));
-
- {
- int yIndex = 0;
- for (ItemStack stack : BestiaryData.getBestiaryLocations().keySet()) {
- Minecraft.getMinecraft().getTextureManager().bindTexture(pv_elements);
- if (mouseX > guiLeft + 30 + bestiaryXSize * yIndex && mouseX < guiLeft + 30 + bestiaryXSize * yIndex + 20) {
- if (mouseY > guiTop + 10 && mouseY < guiTop + 10 + 20) {
- tooltipToDisplay = stack.getTooltip(Minecraft.getMinecraft().thePlayer, false);
- }
- }
- if (stack == selectedBestiaryLocation) {
- Utils.drawTexturedRect(
- guiLeft + 30 + bestiaryXSize * yIndex,
- guiTop + 10,
- 20,
- 20,
- 20 / 256f,
- 0,
- 20 / 256f,
- 0,
- GL11.GL_NEAREST
- );
- Utils.drawItemStack(stack, guiLeft + 32 + bestiaryXSize * yIndex, guiTop + 12);
- } else {
- Utils.drawTexturedRect(
- guiLeft + 30 + bestiaryXSize * yIndex,
- guiTop + 10,
- 20,
- 20,
- 0,
- 20 / 256f,
- 0,
- 20 / 256f,
- GL11.GL_NEAREST
- );
- Utils.drawItemStack(stack, guiLeft + 32 + bestiaryXSize * yIndex, guiTop + 12);
- }
- yIndex++;
- }
- }
- ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft());
- int width = scaledResolution.getScaledWidth();
- int height = scaledResolution.getScaledHeight();
-
- Minecraft.getMinecraft().getTextureManager().bindTexture(BESTIARY_TEXTURE);
- Utils.drawTexturedRect(guiLeft, guiTop, 431, 202, GL11.GL_NEAREST);
-
- GlStateManager.color(1, 1, 1, 1);
- Color color = new Color(128, 128, 128, 255);
- Utils.renderAlignedString(
- EnumChatFormatting.RED + "Bestiary Level: ",
- EnumChatFormatting.GRAY + "" + (float) getSelectedProfile().getBestiaryLevel() / 10,
- guiLeft + 220,
- guiTop + 50,
- 110
- );
-
- GlStateManager.disableLighting();
- RenderHelper.enableGUIStandardItemLighting();
- List<String> mobs = BestiaryData.getBestiaryLocations().get(selectedBestiaryLocation);
- if (mobs != null) {
- for (int i = 0; i < mobs.size(); i++) {
- String mob = mobs.get(i);
- if (mob != null) {
- ItemStack mobItem = BestiaryData.getBestiaryMobs().get(mob);
- if (mobItem != null) {
- int xIndex = i % XCOUNT;
- int yIndex = i / XCOUNT;
-
- float x = 23 + XPADDING + (XPADDING + 20) * xIndex;
- float y = 30 + YPADDING + (YPADDING + 20) * yIndex;
-
- float completedness = 0;
-
- GlStateManager.color(1, 1, 1, 1);
- Minecraft.getMinecraft().getTextureManager().bindTexture(pv_elements);
- Utils.drawTexturedRect(
- guiLeft + x,
- guiTop + y,
- 20,
- 20 * (1 - completedness),
- 0,
- 20 / 256f,
- 0,
- 20 * (1 - completedness) / 256f,
- GL11.GL_NEAREST
- );
- //GlStateManager.color(1, 185 / 255f, 0, 1);
- Minecraft.getMinecraft().getTextureManager().bindTexture(pv_elements);
- Utils.drawTexturedRect(
- guiLeft + x,
- guiTop + y + 20 * (1 - completedness),
- 20,
- 20 * (completedness),
- 0,
- 20 / 256f,
- 20 * (1 - completedness) / 256f,
- 20 / 256f,
- GL11.GL_NEAREST
- );
- Utils.drawItemStack(mobItem, guiLeft + (int) x + 2, guiTop + (int) y + 2);
- float kills = Utils.getElementAsFloat(Utils.getElement(profileInfo, "bestiary.kills_" + mob), 0);
- float deaths = Utils.getElementAsFloat(Utils.getElement(profileInfo, "bestiary.deaths_" + mob), 0);
-
- String type;
- if (BestiaryData.getMobType().get(mob) != null) {
- type = BestiaryData.getMobType().get(mob);
- } else {
- type = "MOB";
- }
- JsonObject leveling = Constants.LEVELING;
- ProfileViewer.Level level = null;
- if (leveling != null && Utils.getElement(leveling, "bestiary." + type) != null) {
- JsonArray levelingArray = Utils.getElement(leveling, "bestiary." + type).getAsJsonArray();
- int levelCap = Utils.getElementAsInt(Utils.getElement(leveling, "bestiary.caps." + type), 0);
- level = ProfileViewerUtils.getLevel(levelingArray, kills, levelCap, false);
- } else {
- Utils.showOutdatedRepoNotification();
- }
-
- float levelNum = -1;
- if (level != null) {
- levelNum = level.level;
- }
- if (mouseX > guiLeft + (int) x + 2 && mouseX < guiLeft + (int) x + 18) {
- if (mouseY > guiTop + (int) y + 2 && mouseY < guiTop + (int) y + 18) {
- tooltipToDisplay = new ArrayList<>();
- tooltipToDisplay.add(
- mobItem.getDisplayName() + " " + ((levelNum == -1) ? "?" : (int) Math.floor(levelNum))
- );
- tooltipToDisplay.add(
- EnumChatFormatting.GRAY + "Kills: " + EnumChatFormatting.GREEN + StringUtils.formatNumber(kills)
- );
- tooltipToDisplay.add(
- EnumChatFormatting.GRAY + "Deaths: " + EnumChatFormatting.GREEN + StringUtils.formatNumber(deaths)
- );
- if (level != null) {
- String progressStr;
- if (level.maxed) {
- progressStr = EnumChatFormatting.GOLD + "MAXED!";
- } else {
- progressStr = EnumChatFormatting.AQUA +
- StringUtils.shortNumberFormat(Math.round((levelNum % 1) * level.maxXpForLevel)) +
- "/" +
- StringUtils.shortNumberFormat(level.maxXpForLevel);
- }
- tooltipToDisplay.add(EnumChatFormatting.GRAY + "Progress: " + progressStr);
- }
- }
- }
-
- GlStateManager.color(1, 1, 1, 1);
- // if (tier >= 0) {
- // Utils.drawStringCentered(tierString,
- // guiLeft + x + 10, guiTop + y - 4, true,
- // tierStringColour
- // );
- // }
- Utils.drawStringCentered(
- (int) Math.floor(levelNum) + "",
- guiLeft + x + 10, guiTop + y + 26, true, color.getRGB()
- );
- }
- }
- }
- }
- if (tooltipToDisplay != null) {
- List<String> grayTooltip = new ArrayList<>(tooltipToDisplay.size());
- for (String line : tooltipToDisplay) {
- grayTooltip.add(EnumChatFormatting.GRAY + line);
- }
- Utils.drawHoveringText(grayTooltip, mouseX, mouseY, width, height, -1);
- tooltipToDisplay = null;
- }
- }
-
- @Override
- public void mouseReleased(int mouseX, int mouseY, int mouseButton) {
- int guiLeft = GuiProfileViewer.getGuiLeft();
- int guiTop = GuiProfileViewer.getGuiTop();
-
- int bestiarySize = BestiaryData.getBestiaryLocations().size();
- int bestiaryYSize = (int) (350f / (bestiarySize - 1 + 0.0000001f));
- int yIndex = 0;
- for (ItemStack stack : BestiaryData.getBestiaryLocations().keySet()) {
- if (mouseX > guiLeft + 30 + bestiaryYSize * yIndex && mouseX < guiLeft + 30 + bestiaryYSize * yIndex + 20) {
- if (mouseY > guiTop + 10 && mouseY < guiTop + 10 + 20) {
- selectedBestiaryLocation = stack;
- Utils.playPressSound();
- return;
- }
- }
- yIndex++;
- }
- }
-}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/bestiary/BestiaryPage.kt b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/bestiary/BestiaryPage.kt
new file mode 100644
index 00000000..ea5a576b
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/bestiary/BestiaryPage.kt
@@ -0,0 +1,302 @@
+/*
+ * Copyright (C) 2022-2023 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+package io.github.moulberry.notenoughupdates.profileviewer.bestiary
+
+import io.github.moulberry.notenoughupdates.core.util.StringUtils
+import io.github.moulberry.notenoughupdates.profileviewer.GuiProfileViewer
+import io.github.moulberry.notenoughupdates.profileviewer.GuiProfileViewerPage
+import io.github.moulberry.notenoughupdates.profileviewer.bestiary.BestiaryData.calculateTotalBestiaryLevel
+import io.github.moulberry.notenoughupdates.profileviewer.bestiary.BestiaryData.hasMigrated
+import io.github.moulberry.notenoughupdates.profileviewer.bestiary.BestiaryData.parseBestiaryData
+import io.github.moulberry.notenoughupdates.util.Constants
+import io.github.moulberry.notenoughupdates.util.Utils
+import net.minecraft.client.Minecraft
+import net.minecraft.client.gui.ScaledResolution
+import net.minecraft.client.renderer.GlStateManager
+import net.minecraft.client.renderer.RenderHelper
+import net.minecraft.item.ItemStack
+import net.minecraft.util.EnumChatFormatting
+import net.minecraft.util.ResourceLocation
+import org.lwjgl.input.Mouse
+import org.lwjgl.opengl.GL11
+import java.awt.Color
+
+/**
+ * Individual mob entry in the Bestiary
+ */
+data class Mob(
+ val name: String, val icon: ItemStack, val kills: Double, val deaths: Double, val mobLevelData: MobLevelData
+)
+
+/**
+ * A Bestiary category as defined in `constants/bestiary.json`
+ */
+data class Category(
+ val id: String, val name: String, val icon: ItemStack, val mobs: List<Mob>, val subCategories: List<Category>
+)
+
+/**
+ * Level data for one specific mob
+ */
+data class MobLevelData(val level: Int, val maxLevel: Boolean)
+
+class BestiaryPage(instance: GuiProfileViewer?) : GuiProfileViewerPage(instance) {
+ private var selectedCategory = "dynamic"
+ private var lastSelectedCategory = ""
+ private var selectedSubCategory = ""
+ private var tooltipToDisplay: MutableList<String> = mutableListOf()
+ private var bestiaryLevel = 0
+ private var computedCategories: MutableList<Category> = mutableListOf()
+
+ private val bestiaryTexture = ResourceLocation("notenoughupdates:pv_bestiary_tab.png")
+ private val mobListXCount = 9
+ private val mobListYCount = 5
+ private val mobListXPadding = (240 - mobListXCount * 20) / (mobListXCount + 1).toFloat()
+ private val mobListYPadding = (202 - mobListYCount * 20) / (mobListYCount + 1).toFloat()
+
+ override fun drawPage(mouseX: Int, mouseY: Int, partialTicks: Float) {
+ val guiLeft = GuiProfileViewer.getGuiLeft()
+ val guiTop = GuiProfileViewer.getGuiTop()
+
+ val selectedProfile = selectedProfile ?: return
+ val profileInfo = selectedProfile.profileJson
+
+ if (!hasMigrated(profileInfo) || Constants.BESTIARY == null) {
+ Utils.drawStringCentered(
+ "${EnumChatFormatting.RED}No valid bestiary data!",
+ guiLeft + 431 / 2f,
+ (guiTop + 101).toFloat(),
+ true,
+ 0
+ )
+ return
+ }
+ // Do the initial parsing only once
+ if (computedCategories.isEmpty()) {
+ computedCategories = parseBestiaryData(profileInfo)
+ bestiaryLevel = calculateTotalBestiaryLevel(computedCategories)
+ }
+ val bestiarySize = computedCategories.size
+ val bestiaryXSize = (350f / (bestiarySize - 1 + 0.0000001f)).toInt()
+
+
+ // Render the category list
+ for ((categoryXIndex, category) in computedCategories.withIndex()) {
+ Minecraft.getMinecraft().textureManager.bindTexture(GuiProfileViewer.pv_elements)
+
+ if (mouseX > guiLeft + 30 + bestiaryXSize * categoryXIndex &&
+ mouseX < guiLeft + 30 + bestiaryXSize * categoryXIndex + 20
+ && mouseY > guiTop + 10 && mouseY < guiTop + 10 + 20
+ ) {
+ tooltipToDisplay = category.icon.getTooltip(Minecraft.getMinecraft().thePlayer, false)
+ if (Mouse.getEventButtonState() && selectedCategory != category.id) {
+ selectedCategory = category.id
+ Utils.playPressSound()
+ }
+ }
+
+
+ if (category.id == selectedCategory) {
+ Utils.drawTexturedRect(
+ (guiLeft + 30 + bestiaryXSize * categoryXIndex).toFloat(),
+ (guiTop + 10).toFloat(),
+ 20f,
+ 20f,
+ 20 / 256f,
+ 0f,
+ 20 / 256f,
+ 0f,
+ GL11.GL_NEAREST
+ )
+ } else {
+ Utils.drawTexturedRect(
+ (guiLeft + 30 + bestiaryXSize * categoryXIndex).toFloat(),
+ (guiTop + 10).toFloat(),
+ 20f,
+ 20f,
+ 0f,
+ 20 / 256f,
+ 0f,
+ 20 / 256f,
+ GL11.GL_NEAREST
+ )
+ }
+ Utils.drawItemStack(category.icon, guiLeft + 32 + bestiaryXSize * categoryXIndex, guiTop + 12)
+ }
+
+ val scaledResolution = ScaledResolution(Minecraft.getMinecraft())
+ val width = scaledResolution.scaledWidth
+ val height = scaledResolution.scaledHeight
+
+ Minecraft.getMinecraft().textureManager.bindTexture(bestiaryTexture)
+ Utils.drawTexturedRect(guiLeft.toFloat(), guiTop.toFloat(), 431f, 202f, GL11.GL_NEAREST)
+ GlStateManager.color(1f, 1f, 1f, 1f)
+ val color = Color(128, 128, 128, 255)
+ Utils.renderAlignedString(
+ EnumChatFormatting.RED.toString() + "Milestone: ",
+ "${EnumChatFormatting.GRAY}${(bestiaryLevel / 10) - 1}",
+ (guiLeft + 280).toFloat(),
+ (guiTop + 50).toFloat(),
+ 110
+ )
+
+ // Render the subcategories in the bottom right corner, if applicable
+ val selectedCategory = computedCategories.first { it.id == selectedCategory }
+ if (selectedCategory.subCategories.isNotEmpty()) {
+ if (selectedSubCategory == "") {
+ selectedSubCategory = selectedCategory.subCategories.first().id
+ }
+
+ Utils.renderShadowedString(
+ "${EnumChatFormatting.RED}Subcategories", (guiLeft + 317).toFloat(), (guiTop + 165).toFloat(), 1000
+ )
+ GlStateManager.color(1f, 1f, 1f, 1f)
+
+ val xStart = (guiLeft + 280).toFloat()
+ val y = (guiTop + 175).toFloat()
+ for ((i, subCategory) in selectedCategory.subCategories.withIndex()) {
+ Minecraft.getMinecraft().textureManager.bindTexture(GuiProfileViewer.pv_elements)
+
+ if (subCategory.id == selectedSubCategory) {
+ Utils.drawTexturedRect(
+ (xStart + 24 * i.toFloat()),
+ y,
+ 20f,
+ 20f,
+ 20 / 256f,
+ 0f,
+ 20 / 256f,
+ 0f,
+ GL11.GL_NEAREST
+ )
+ } else {
+ Utils.drawTexturedRect(
+ (xStart + 24 * i.toFloat()),
+ y,
+ 20f,
+ 20f,
+ 0f,
+ 20 / 256f,
+ 0f,
+ 20 / 256f,
+ GL11.GL_NEAREST
+ )
+ }
+ Utils.drawItemStack(subCategory.icon, (xStart + 24 * i + 2).toInt(), y.toInt() + 2)
+ if (mouseX > xStart + 24 * i
+ && mouseX < xStart + 24 * (i + 1)
+ && mouseY > y
+ && mouseY < y + 16
+ ) {
+ tooltipToDisplay.add(subCategory.name)
+ if (Mouse.getEventButtonState() && selectedSubCategory != subCategory.id) {
+ selectedSubCategory = subCategory.id
+ Utils.playPressSound()
+ }
+ }
+ }
+ } else {
+ selectedSubCategory = ""
+ }
+
+ // Determine which mobs should be displayed
+ val mobs = if (selectedSubCategory != "") {
+ selectedCategory.subCategories.first { it.id == selectedSubCategory }.mobs
+ } else {
+ selectedCategory.mobs
+ }
+
+ // Render the mob list
+ for ((i, mob) in mobs.withIndex()) {
+ val stack = mob.icon
+ val xIndex = i % mobListXCount
+ val yIndex = i / mobListXCount
+ val x = 23 + mobListXPadding + (mobListXPadding + 20) * xIndex
+ val y = 30 + mobListYPadding + (mobListYPadding + 20) * yIndex
+ val completedness = 0f
+
+ GlStateManager.disableLighting()
+ RenderHelper.enableGUIStandardItemLighting()
+ GlStateManager.color(1f, 1f, 1f, 1f)
+ Minecraft.getMinecraft().textureManager.bindTexture(GuiProfileViewer.pv_elements)
+ Utils.drawTexturedRect(
+ guiLeft + x,
+ guiTop + y,
+ 20f,
+ 20 * (1 - completedness),
+ 0f,
+ 20 / 256f,
+ 0f,
+ 20 * (1 - completedness) / 256f,
+ GL11.GL_NEAREST
+ )
+ //GlStateManager.color(1, 185 / 255f, 0, 1);
+ Minecraft.getMinecraft().textureManager.bindTexture(GuiProfileViewer.pv_elements)
+ Utils.drawTexturedRect(
+ guiLeft + x,
+ guiTop + y + 20 * (1 - completedness),
+ 20f,
+ 20 * completedness,
+ 0f,
+ 20 / 256f,
+ 20 * (1 - completedness) / 256f,
+ 20 / 256f,
+ GL11.GL_NEAREST
+ )
+ Utils.drawItemStack(stack, guiLeft + x.toInt() + 2, guiTop + y.toInt() + 2)
+ val kills = mob.kills
+ val deaths = mob.deaths
+
+ if (mouseX > guiLeft + x.toInt() + 2 && mouseX < guiLeft + x.toInt() + 18) {
+ if (mouseY > guiTop + y.toInt() + 2 && mouseY < guiTop + y.toInt() + 18) {
+ tooltipToDisplay = ArrayList()
+ tooltipToDisplay.add(
+ "${mob.name} ${mob.mobLevelData.level}"
+ )
+ tooltipToDisplay.add(
+ EnumChatFormatting.GRAY.toString() + "Kills: " + EnumChatFormatting.GREEN +
+ StringUtils.formatNumber(kills)
+ )
+ tooltipToDisplay.add(
+ EnumChatFormatting.GRAY.toString() + "Deaths: " + EnumChatFormatting.GREEN +
+ StringUtils.formatNumber(deaths)
+ )
+ }
+ }
+ GlStateManager.color(1f, 1f, 1f, 1f)
+ Utils.drawStringCentered(
+ if (mob.mobLevelData.maxLevel) {
+ "${EnumChatFormatting.GOLD}${mob.mobLevelData.level}"
+ } else {
+ mob.mobLevelData.level.toString()
+ }, guiLeft + x + 10, guiTop + y + 26, true, color.rgb
+ )
+ }
+
+ // Render the accumulated tooltip, if applicable
+ if (tooltipToDisplay.isNotEmpty()) {
+ val grayTooltip: MutableList<String> = ArrayList(tooltipToDisplay.size)
+ for (line in tooltipToDisplay) {
+ grayTooltip.add(EnumChatFormatting.GRAY.toString() + line)
+ }
+ Utils.drawHoveringText(grayTooltip, mouseX, mouseY, width, height, -1)
+ tooltipToDisplay.clear()
+ }
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/level/task/MiscTaskLevel.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/level/task/MiscTaskLevel.java
index 992b2609..291bf4cf 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/level/task/MiscTaskLevel.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/level/task/MiscTaskLevel.java
@@ -166,12 +166,28 @@ public class MiscTaskLevel extends GuiTaskLevel {
}
int sbXpTimeCharm = 0;
- if (object.has("rift") &&
- object.getAsJsonObject("rift").has("gallery") &&
- object.getAsJsonObject("rift").getAsJsonObject("gallery").has("secured_trophies")) {
- JsonArray timeCharms = object.getAsJsonObject("rift").getAsJsonObject("gallery").getAsJsonArray(
- "secured_trophies");
- sbXpTimeCharm += timeCharms.size() * miscellaneousTask.get("timecharm_xp").getAsInt();
+ int sbXpBurger = 0;
+ if (object.has("rift")) {
+ JsonObject rift = object.getAsJsonObject("rift");
+ if (rift.has("gallery") &&
+ rift.getAsJsonObject("gallery").has("secured_trophies")) {
+ JsonArray timeCharms = rift.getAsJsonObject("gallery").getAsJsonArray(
+ "secured_trophies");
+ sbXpTimeCharm += timeCharms.size() * miscellaneousTask.get("timecharm_xp").getAsInt();
+ }
+
+
+ if (rift.has("castle") && rift.getAsJsonObject("castle").has("grubber_stacks") && miscellaneousTask.has("mcgrubber_burger_xp")) {
+ sbXpBurger = miscellaneousTask.get("mcgrubber_burger_xp").getAsInt()
+ * rift.getAsJsonObject("castle").get("grubber_stacks").getAsInt();
+ }
+ }
+
+ int sbXpSerum = 0;
+ if (object.has("experimentation") &&
+ object.getAsJsonObject("experimentation").has("serums_drank")
+ && miscellaneousTask.has("metaphysical_serum_xp")) {
+ sbXpSerum = miscellaneousTask.get("metaphysical_serum_xp").getAsInt() * object.getAsJsonObject("experimentation").get("serums_drank").getAsInt();
}
List<String> lore = new ArrayList<>();
@@ -179,8 +195,9 @@ public class MiscTaskLevel extends GuiTaskLevel {
lore.add(levelPage.buildLore("Accessory Bag Upgrades",
sbXpAccessoryUpgrade, 0, true
));
- lore.add(levelPage.buildLore("Reaper Peppers",
- sbXpReaperPeppers, miscellaneousTask.get("reaper_peppers").getAsInt(), false
+ int xpConsumableItems = sbXpReaperPeppers + sbXpBurger + sbXpSerum;
+ lore.add(levelPage.buildLore("Consumable Items",
+ xpConsumableItems, miscellaneousTask.get("consumable_items").getAsInt(), false
));
lore.add(levelPage.buildLore("Timecharms",
sbXpTimeCharm, miscellaneousTask.get("timecharm").getAsInt(), false
@@ -208,8 +225,9 @@ public class MiscTaskLevel extends GuiTaskLevel {
sbXpRelays, miscellaneousTask.get("unlocking_relays").getAsInt(), false
));
- int totalXp = sbXpReaperPeppers + sbXpDojo + sbXpGainedHarp + sbXpAbiphone +
- sbXpCommunityUpgrade + sbXpPersonalBank + sbXpTimeCharm + sbXpRelays;
+
+ int totalXp =sbXpDojo + sbXpGainedHarp + sbXpAbiphone +
+ sbXpCommunityUpgrade + sbXpPersonalBank + sbXpTimeCharm + sbXpRelays + xpConsumableItems;
levelPage.renderLevelBar(
"Misc. Task",
new ItemStack(Items.map),
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/rift/RiftPage.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/rift/RiftPage.java
index bff6834c..9dc1ea8d 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/rift/RiftPage.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/rift/RiftPage.java
@@ -121,7 +121,7 @@ public class RiftPage extends GuiProfileViewerPage {
Utils.drawTexturedRect(guiLeft + 35, guiTop + 156, 20, 20, 0, 20 / 256f, 0, 20 / 256f, GL11.GL_NEAREST);
JsonObject deadCats = riftData.getAsJsonObject("dead_cats");
- if (!deadCats.entrySet().isEmpty() && deadCats.has("found_cata")) {
+ if (!deadCats.entrySet().isEmpty() && deadCats.has("found_cats")) {
JsonArray foundCats = deadCats.getAsJsonArray("found_cats");
int size = foundCats.size();
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/ApiUtil.java b/src/main/java/io/github/moulberry/notenoughupdates/util/ApiUtil.java
index e96043fa..9611f197 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/util/ApiUtil.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/util/ApiUtil.java
@@ -109,6 +109,7 @@ public class ApiUtil {
}
public void updateProfileData(String playerUuid) {
+ if (true) return;
if (!updateTasks.getOrDefault(playerUuid, CompletableFuture.completedFuture(null)).isDone()) return;
String uuid = Minecraft.getMinecraft().thePlayer.getUniqueID().toString().replace("-", "");
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/Constants.java b/src/main/java/io/github/moulberry/notenoughupdates/util/Constants.java
index 5f1cc247..c30f869e 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/util/Constants.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/util/Constants.java
@@ -83,6 +83,7 @@ public class Constants {
public static JsonObject ESSENCESHOPS;
public static JsonObject SBLEVELS;
public static JsonObject MUSEUM;
+ public static JsonObject BESTIARY;
private static final ReentrantLock lock = new ReentrantLock();
@@ -109,6 +110,7 @@ public class Constants {
ESSENCESHOPS = Utils.getConstant("essenceshops", gson);
SBLEVELS = Utils.getConstant("sblevels", gson);
MUSEUM = Utils.getConstant("museum", gson);
+ BESTIARY = Utils.getConstant("bestiary", gson);
parseEssenceCosts();
} catch (Exception ex) {
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/ItemUtils.java b/src/main/java/io/github/moulberry/notenoughupdates/util/ItemUtils.java
index d10ae721..bdea26d5 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/util/ItemUtils.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/util/ItemUtils.java
@@ -29,6 +29,7 @@ import io.github.moulberry.notenoughupdates.core.util.StringUtils;
import io.github.moulberry.notenoughupdates.listener.ItemTooltipListener;
import io.github.moulberry.notenoughupdates.miscfeatures.PetInfoOverlay;
import io.github.moulberry.notenoughupdates.profileviewer.GuiProfileViewer;
+import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.JsonToNBT;
import net.minecraft.nbt.NBTException;
@@ -40,7 +41,6 @@ import net.minecraft.util.MathHelper;
import java.nio.charset.StandardCharsets;
import java.text.DecimalFormat;
-import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Base64;
@@ -469,4 +469,15 @@ public class ItemUtils {
return id;
}
+ public static ItemStack createItemStackFromId(String id, String displayname) {
+ Item item = Item.getByNameOrId(id);
+ if (item == null) {
+ return null;
+ }
+
+ ItemStack itemStack = new ItemStack(item);
+ itemStack.setStackDisplayName(displayname);
+ return itemStack;
+ }
+
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/ProfileApiSyncer.java b/src/main/java/io/github/moulberry/notenoughupdates/util/ProfileApiSyncer.java
index ed88a6a5..5a4e1c9e 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/util/ProfileApiSyncer.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/util/ProfileApiSyncer.java
@@ -19,10 +19,7 @@
package io.github.moulberry.notenoughupdates.util;
-import com.google.gson.JsonObject;
-import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
import io.github.moulberry.notenoughupdates.profileviewer.SkyblockProfiles;
-import net.minecraft.client.Minecraft;
import java.util.HashMap;
import java.util.function.Consumer;
@@ -65,40 +62,4 @@ public class ProfileApiSyncer {
}
return time;
}
-
- public void tick() {
- if (Minecraft.getMinecraft().thePlayer == null) return;
-
- long resyncTime = getCurrentResyncTime();
-
- if (resyncTime < 0) return;
-
- long currentTime = System.currentTimeMillis();
-
- if (currentTime - lastResync > resyncTime) {
- lastResync = currentTime;
- resyncTimes.clear();
-
- for (Runnable r : syncingCallbacks.values()) r.run();
- syncingCallbacks.clear();
-
- forceResync();
- }
- }
-
- private void forceResync() {
- if (Minecraft.getMinecraft().thePlayer == null) return;
-
- String uuid = Minecraft.getMinecraft().thePlayer.getUniqueID().toString().replace("-", "");
- NotEnoughUpdates.INSTANCE.manager.apiUtils
- .newHypixelApiRequest("/skyblock/profiles")
- .queryArgument("uuid", uuid)
- .requestJson()
- .thenAcceptAsync((profile) -> {
- SkyblockProfiles skyblockProfiles = new SkyblockProfiles(NotEnoughUpdates.profileViewer, uuid);
- for (Consumer<SkyblockProfiles> c : finishSyncCallbacks.values())
- c.accept((skyblockProfiles));
- finishSyncCallbacks.clear();
- }, MinecraftExecutor.OnThread);
- }
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/StarCultCalculator.java b/src/main/java/io/github/moulberry/notenoughupdates/util/StarCultCalculator.java
index 4c4fe02d..fadfef40 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/util/StarCultCalculator.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/util/StarCultCalculator.java
@@ -55,8 +55,32 @@ public class StarCultCalculator {
private static long activeTill = 0;
public static String getNextStarCult() {
- Instant instantNow = Instant.now();
- long nowEpoch = instantNow.toEpochMilli();
+ Instant cultStart = getNextStarCultTime();
+
+ long l = System.currentTimeMillis();
+ if (cultStart.toEpochMilli() - l <= 1000) {
+ active = true;
+ activeTill = l + 300000;
+ }
+
+ if (l > activeTill) {
+ active = false;
+ activeTill = 0;
+ }
+
+ if (active && activeTill != 0) {
+ return "Active! (" + Utils.prettyTime(activeTill - System.currentTimeMillis()) + ")";
+ }
+
+ return Utils.prettyTime(cultStart.toEpochMilli() - l);
+ }
+
+ public static Instant getNextStarCultTime() {
+ return getNextStarCultTime(Instant.now());
+ }
+
+ public static Instant getNextStarCultTime(Instant after) {
+ long nowEpoch = after.toEpochMilli();
long currentOffset = (nowEpoch - YEAR_0) % YEAR_MS;
int currentMonth = (int) Math.floorDiv(currentOffset, MONTH_MS);
@@ -72,7 +96,7 @@ public class StarCultCalculator {
}
Instant cultStart = Instant.ofEpochMilli(
YEAR_0 + (getSkyblockYear() - 1) * YEAR_MS + currentMonth * MONTH_MS + (out - 1) * DAY_MS);
- if (cultStart.isBefore(instantNow)) {
+ if (cultStart.isBefore(after)) {
int curYearCult = getSkyblockYear() - 1;
if (out == 28) {
out = 7;
@@ -88,23 +112,7 @@ public class StarCultCalculator {
out--;
cultStart = Instant.ofEpochMilli(YEAR_0 + (curYearCult) * YEAR_MS + currentMonth * MONTH_MS + out * DAY_MS);
}
-
- long l = System.currentTimeMillis();
- if (cultStart.toEpochMilli() - l <= 1000) {
- active = true;
- activeTill = l + 300000;
- }
-
- if (l > activeTill) {
- active = false;
- activeTill = 0;
- }
-
- if (active && activeTill != 0) {
- return "Active! (" + Utils.prettyTime(activeTill - System.currentTimeMillis()) + ")";
- }
-
- return Utils.prettyTime(cultStart.toEpochMilli() - l);
+ return cultStart;
}
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/Utils.java b/src/main/java/io/github/moulberry/notenoughupdates/util/Utils.java
index 052ea33f..847b9430 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/util/Utils.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/util/Utils.java
@@ -1571,6 +1571,13 @@ public class Utils {
if (!prim.isNumber()) return def;
return prim.getAsInt();
}
+ public static long getElementAsLong(JsonElement element, long def) {
+ if (element == null) return def;
+ if (!element.isJsonPrimitive()) return def;
+ JsonPrimitive prim = element.getAsJsonPrimitive();
+ if (!prim.isNumber()) return def;
+ return prim.getAsLong();
+ }
public static String getElementAsString(JsonElement element, String def) {
if (element == null) return def;
@@ -1580,6 +1587,14 @@ public class Utils {
return prim.getAsString();
}
+ public static boolean getElementAsBool(JsonElement element, boolean def) {
+ if (element == null) return def;
+ if (!element.isJsonPrimitive()) return def;
+ JsonPrimitive prim = element.getAsJsonPrimitive();
+ if (!prim.isBoolean()) return def;
+ return prim.getAsBoolean();
+ }
+
public static JsonElement getElement(JsonElement element, String path) {
List<String> path_split = PATH_SPLITTER.splitToList(path);
if (element instanceof JsonObject) {
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/XPInformation.java b/src/main/java/io/github/moulberry/notenoughupdates/util/XPInformation.java
index 0a501415..117545c9 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/util/XPInformation.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/util/XPInformation.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2022 NotEnoughUpdates contributors
+ * Copyright (C) 2022-2023 NotEnoughUpdates contributors
*
* This file is part of NotEnoughUpdates.
*
@@ -24,15 +24,12 @@ import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe;
import io.github.moulberry.notenoughupdates.core.util.StringUtils;
-import io.github.moulberry.notenoughupdates.profileviewer.ProfileViewer;
-import io.github.moulberry.notenoughupdates.profileviewer.SkyblockProfiles;
import net.minecraftforge.client.event.ClientChatReceivedEvent;
import net.minecraftforge.fml.common.eventhandler.EventPriority;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import java.util.HashMap;
import java.util.List;
-import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -210,46 +207,4 @@ public class XPInformation {
}
updateWithPercentage.clear();
}
-
- public void tick() {
- ProfileApiSyncer.getInstance().requestResync("xpinformation", 5 * 60 * 1000,
- () -> {
- }, this::onApiUpdated
- );
- }
-
- private static final String[] skills = {
- "taming",
- "mining",
- "foraging",
- "enchanting",
- "carpentry",
- "farming",
- "combat",
- "fishing",
- "alchemy",
- "runecrafting"
- };
-
- private void onApiUpdated(SkyblockProfiles profile) {
- Map<String, ProfileViewer.Level> skyblockInfo = profile.getLatestProfile().getLevelingInfo();
- if (skyblockInfo == null) {
- return;
- }
-
- for (String skill : skills) {
- SkillInfo info = new SkillInfo();
-
- ProfileViewer.Level levelInfo = skyblockInfo.get(skill);
- float level = levelInfo.level;
-
- info.totalXp = levelInfo.totalXp;
- info.currentXpMax = levelInfo.maxXpForLevel;
- info.level = (int) level;
- info.currentXp = (level % 1) * info.currentXpMax;
- info.fromApi = true;
-
- skillInfoMap.put(skill.toLowerCase(), info);
- }
- }
}
diff --git a/src/main/kotlin/io/github/moulberry/notenoughupdates/util/TabSkillInfoParser.kt b/src/main/kotlin/io/github/moulberry/notenoughupdates/util/TabSkillInfoParser.kt
new file mode 100644
index 00000000..b4bfdf28
--- /dev/null
+++ b/src/main/kotlin/io/github/moulberry/notenoughupdates/util/TabSkillInfoParser.kt
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2023 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.util
+
+import com.google.gson.JsonArray
+import net.minecraft.util.EnumChatFormatting
+import java.util.regex.Pattern
+import kotlin.math.abs
+
+object TabSkillInfoParser {
+ private val skillTabPattern: Pattern =
+ Pattern.compile("^§r§e§lSkills: §r§a(?<type>\\w+) (?<level>\\d+): §r§3(?<progress>.+)%§r\$")
+ private val maxSkillTabPattern: Pattern =
+ Pattern.compile("^§r§e§lSkills: §r§a(?<type>\\w+) (?<level>\\d+): §r§c§lMAX§r\$")
+ private var sentErrorOnce = false
+
+ private fun calculateLevelXp(levelingArray: JsonArray, level: Int): Double {
+ var totalXp = 0.0
+ for (i in 0 until level + 1) {
+ val xp = levelingArray[i].asDouble
+ totalXp += xp
+ }
+ return totalXp
+ }
+
+ private fun isWithinPercentageRange(xp: Double, existingXp: Double, percentage: Double): Boolean {
+ val diff = (abs(xp - existingXp) / existingXp) * 100
+ return diff <= percentage
+ }
+
+ private fun sendError(message: String) {
+ if (!sentErrorOnce) {
+ Utils.addChatMessage(message)
+ sentErrorOnce = true
+ }
+ }
+
+ private fun levelArray(skillType: String) =
+ if (skillType == "runecrafting") Utils.getElement(Constants.LEVELING, "runecrafting_xp").asJsonArray
+ else Utils.getElement(Constants.LEVELING, "leveling_xp").asJsonArray
+
+ @JvmStatic
+ fun parseSkillInfo() {
+ if (Constants.LEVELING == null) {
+ sendError("${EnumChatFormatting.RED}[NEU] There is an error with your repo, please report this in the discord at ${EnumChatFormatting.AQUA}discord.gg/moulberry")
+ return
+ }
+
+ for (s in TabListUtils.getTabList()) {
+ val matcher = skillTabPattern.matcher(s)
+ val maxLevelMatcher = maxSkillTabPattern.matcher(s)
+ if (matcher.matches()) {
+ // All the groups are guaranteed to match
+ val name = matcher.group("type")!!.lowercase()
+ val level = matcher.group("level")!!.toInt()
+ val progress = matcher.group("progress")!!.toFloatOrNull()
+ if (progress == null) {
+ sendError("${EnumChatFormatting.RED}[NEU] Error while parsing skill level from tab list")
+ return
+ }
+ val levelingArray = levelArray(name)
+ val levelXp = calculateLevelXp(levelingArray, level - 1)
+ // This *should* not cause problems, since skills that are max Level won't be picked up
+ val nextLevelDiff = levelingArray[level].asDouble
+ val nextLevelProgress = nextLevelDiff * progress / 100
+
+ val totalXp = levelXp + nextLevelProgress
+ val existingLevel = XPInformation.getInstance().getSkillInfo(name) ?: XPInformation.SkillInfo()
+
+ // Only update if the numbers are substantially different
+ if (!isWithinPercentageRange(totalXp, existingLevel.totalXp.toDouble(), 1.0)) {
+ existingLevel.level = level
+ existingLevel.totalXp = totalXp.toFloat()
+ existingLevel.currentXp = nextLevelProgress.toFloat()
+ existingLevel.currentXpMax = nextLevelDiff.toFloat()
+ XPInformation.getInstance().skillInfoMap[name] = existingLevel
+ }
+
+ // There is only one skill at a time in the tab list
+ break
+ } else if (maxLevelMatcher.matches()) {
+ val name = maxLevelMatcher.group("type")!!.lowercase()
+ val level = maxLevelMatcher.group("level")!!.toInt()
+
+ val existingLevel = XPInformation.getInstance().getSkillInfo(name) ?: XPInformation.SkillInfo()
+ if (existingLevel.level != level) {
+ existingLevel.level = level
+ val levelingArray = levelArray(name)
+
+ val totalXp = calculateLevelXp(levelingArray, level - 1)
+ existingLevel.totalXp = totalXp.toFloat()
+ XPInformation.getInstance().skillInfoMap[name] = existingLevel
+ }
+ }
+ }
+ }
+}