Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,15 @@ public static ConfigCategory create(SkyblockerConfig defaults, SkyblockerConfig
.name(Component.translatable("skyblocker.config.mining"))

//Uncategorized Options
.option(Option.<Boolean>createBuilder()
.name(Component.translatable("skyblocker.config.mining.enablePickaxeAbility"))
.description(Component.translatable("skyblocker.config.mining.enablePickaxeAbility.@Tooltip"))
.binding(defaults.mining.enablePickaxeAbility,
() -> config.mining.enablePickaxeAbility,
newValue -> config.mining.enablePickaxeAbility = newValue)
.controller(ConfigUtils.createBooleanController())
.build())

.option(Option.<Boolean>createBuilder()
.name(Component.translatable("skyblocker.config.mining.enableDrillFuel"))
.description(Component.translatable("skyblocker.config.mining.enableDrillFuel.@Tooltip"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
import net.minecraft.client.resources.language.I18n;

public class MiningConfig {
public boolean enablePickaxeAbility = false;

public boolean enableDrillFuel = true;

public boolean commissionHighlight = true;
Expand Down
14 changes: 9 additions & 5 deletions src/main/java/de/hysky/skyblocker/mixins/ItemStackMixin.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
import de.hysky.skyblocker.utils.ItemUtils;
import de.hysky.skyblocker.utils.OkLabColor;
import de.hysky.skyblocker.utils.Utils;
import it.unimi.dsi.fastutil.ints.IntIntPair;
import org.jspecify.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
Expand All @@ -23,6 +22,7 @@
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

import java.util.List;
import java.util.OptionalDouble;
import java.util.function.Consumer;
import net.minecraft.ChatFormatting;
import net.minecraft.client.Minecraft;
Expand All @@ -40,6 +40,9 @@ public abstract class ItemStackMixin implements DataComponentHolder, SkyblockerS
@Unique
private float durabilityBarFill = -1;

@Unique
private boolean shouldTryToProcessDurabilityFill = false;

@Unique
private @Nullable String skyblockId;

Expand Down Expand Up @@ -102,6 +105,7 @@ public abstract class ItemStackMixin implements DataComponentHolder, SkyblockerS

@ModifyReturnValue(method = "isBarVisible", at = @At("RETURN"))
private boolean modifyItemBarVisible(boolean original) {
shouldTryToProcessDurabilityFill = true;
return original || durabilityBarFill >= 0f;
}

Expand Down Expand Up @@ -138,7 +142,7 @@ private void onInit(CallbackInfo ci) {

@Unique
private boolean skyblocker$shouldProcess() { // Durability bar renders atop of tooltips in ProfileViewer so disable on this screen
return !(Minecraft.getInstance() != null && Minecraft.getInstance().screen instanceof ProfileViewerScreen) && Utils.isOnSkyblock() && SkyblockerConfigManager.get().mining.enableDrillFuel && ItemUtils.hasCustomDurability((ItemStack) (Object) this);
return shouldTryToProcessDurabilityFill && !(Minecraft.getInstance().screen instanceof ProfileViewerScreen) && Utils.isOnSkyblock() && ItemUtils.hasCustomDurability((ItemStack) (Object) this);
}

@Unique
Expand All @@ -148,14 +152,14 @@ private void onInit(CallbackInfo ci) {
return;
}
// Calculate the durability
IntIntPair durability = ItemUtils.getDurability((ItemStack) (Object) this);
OptionalDouble durability = ItemUtils.getDurability((ItemStack) (Object) this);
// Return if calculating the durability failed
if (durability == null) {
if (durability.isEmpty()) {
durabilityBarFill = -1;
return;
}
// Saves the calculated durability
durabilityBarFill = (float) durability.firstInt() / durability.secondInt();
durabilityBarFill = (float) durability.getAsDouble();
}

@SuppressWarnings("deprecation")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package de.hysky.skyblocker.skyblock.dwarven;

import de.hysky.skyblocker.annotations.Init;
import de.hysky.skyblocker.utils.ItemAbility;
import de.hysky.skyblocker.utils.ItemUtils;
import it.unimi.dsi.fastutil.objects.ObjectSet;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents;
import net.minecraft.client.Minecraft;
import net.minecraft.world.item.ItemStack;
import org.apache.commons.lang3.math.NumberUtils;
import org.jspecify.annotations.Nullable;

import java.util.Objects;
import java.util.OptionalDouble;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public final class PickaxeAbility {
private static final Pattern COOLDOWN = Pattern.compile("Your Pickaxe ability is on cooldown for (\\d+)s");
private static final Set<String> PICKAXE_ABILITIES = ObjectSet.of(
"Mining Speed Boost",
"Pickobulus",
"Tunnel Vision",
"Maniac Miner",
"Gemstone Infusion",
"Sheer Force"
);
private static @Nullable String cachedAbility;
private static int cooldown = -1;
private static int cooldownTime = -1;

@Init
public static void init() {
ClientTickEvents.END_WORLD_TICK.register(level -> {
findPickaxeAbility(Objects.requireNonNull(Minecraft.getInstance().player).getMainHandItem());
if (cachedAbility == null || cooldownTime >= cooldown || cooldownTime < 0) return;
cooldownTime++;
});
ClientReceiveMessageEvents.ALLOW_GAME.register((component, overlay) -> {
if (!overlay) onChatMessage(component.getString().trim());
return true;
});
}

private static void onChatMessage(String string) {
if (cachedAbility == null) return;
if (string.equals("You used your " + cachedAbility + " Pickaxe Ability!")) {
cooldownTime = 0;
return;
} else if (string.equals(cachedAbility + " is now available!")) {
cooldownTime = cooldown + 1;
}
Matcher matcher = COOLDOWN.matcher(string);
if (matcher.find()) {
int i = NumberUtils.toInt(matcher.group(1), 0);
cooldownTime = cooldown - i;
}
}

public static boolean canHavePickaxeAbility(ItemStack stack) {
return ItemUtils.getLoreLineIf(stack, s -> s.startsWith("Breaking Power")) != null;
}

/**
* @return empty if we know for sure the cooldown is over from the "is now available!" message.
*/
public static OptionalDouble getCooldownPercentage() {
if (cachedAbility == null || cooldownTime < 0 || cooldownTime > cooldown) return OptionalDouble.empty();
return OptionalDouble.of((double) cooldownTime / cooldown);
}

private static void findPickaxeAbility(ItemStack stack) {
if (!canHavePickaxeAbility(stack)) return;
for (ItemAbility ability : stack.skyblocker$getAbilities()) {
if (PICKAXE_ABILITIES.contains(ability.name()) && ability.cooldown().isPresent()) {
cachedAbility = ability.name();
cooldown = ability.cooldown().getAsInt();
return;
}
}
cachedAbility = null;
cooldownTime = -1;
cooldown = -1;
}
}
44 changes: 27 additions & 17 deletions src/main/java/de/hysky/skyblocker/utils/ItemUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@
import com.mojang.serialization.JsonOps;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import de.hysky.skyblocker.SkyblockerMod;
import de.hysky.skyblocker.config.SkyblockerConfigManager;
import de.hysky.skyblocker.debug.Debug;
import de.hysky.skyblocker.skyblock.ChestValue;
import de.hysky.skyblocker.skyblock.dwarven.PickaxeAbility;
import de.hysky.skyblocker.skyblock.hunting.Attribute;
import de.hysky.skyblocker.skyblock.hunting.Attributes;
import de.hysky.skyblocker.skyblock.item.PetInfo;
Expand All @@ -23,7 +25,6 @@
import de.hysky.skyblocker.utils.networth.NetworthCalculator;
import io.github.moulberry.repo.data.NEUItem;
import it.unimi.dsi.fastutil.doubles.DoubleBooleanPair;
import it.unimi.dsi.fastutil.ints.IntIntPair;
import it.unimi.dsi.fastutil.longs.LongBooleanPair;
import it.unimi.dsi.fastutil.objects.Object2DoubleMap;
import it.unimi.dsi.fastutil.objects.Object2ObjectMap;
Expand Down Expand Up @@ -408,30 +409,39 @@ public static String getTimestamp(ItemStack stack) {
}

public static boolean hasCustomDurability(ItemStack stack) {
CompoundTag customData = getCustomData(stack);
return !customData.isEmpty() && (customData.contains("drill_fuel") || customData.getStringOr(ID, "").equals("PICKONIMBUS"));
if (SkyblockerConfigManager.get().mining.enableDrillFuel) {
CompoundTag customData = getCustomData(stack);
return !customData.isEmpty() && (customData.contains("drill_fuel") || stack.getSkyblockId().equals("PICKONIMBUS"));
} else if (SkyblockerConfigManager.get().mining.enablePickaxeAbility) {
return PickaxeAbility.canHavePickaxeAbility(stack);
}
return false;
}

public static @Nullable IntIntPair getDurability(ItemStack stack) {
CompoundTag customData = getCustomData(stack);
if (customData.isEmpty()) return null;
public static OptionalDouble getDurability(ItemStack stack) {
if (SkyblockerConfigManager.get().mining.enableDrillFuel) {
CompoundTag customData = getCustomData(stack);
if (customData.isEmpty()) return OptionalDouble.empty();

// TODO Calculate drill durability based on the drill_fuel flag, fuel_tank flag, and hotm level
// TODO Cache the max durability and only update the current durability on inventory tick
// TODO Calculate drill durability based on the drill_fuel flag, fuel_tank flag, and hotm level
// TODO Cache the max durability and only update the current durability on inventory tick

if (stack.getSkyblockId().equals("PICKONIMBUS")) {
int pickonimbusDurability = customData.getIntOr("pickonimbus_durability", 0);
if (stack.getSkyblockId().equals("PICKONIMBUS")) {
int pickonimbusDurability = customData.getIntOr("pickonimbus_durability", 0);

return IntIntPair.of(customData.contains("pickonimbus_durability") ? pickonimbusDurability : 2000, 2000);
}
return OptionalDouble.of((customData.contains("pickonimbus_durability") ? pickonimbusDurability : 2000) / 2000d);
}

String drillFuel = ChatFormatting.stripFormatting(getLoreLineIf(stack, FUEL_PREDICATE));
if (drillFuel != null) {
String[] drillFuelStrings = NOT_DURABILITY.matcher(drillFuel).replaceAll("").trim().split("/");
return IntIntPair.of(Integer.parseInt(drillFuelStrings[0]), Integer.parseInt(drillFuelStrings[1]) * 1000);
String drillFuel = ChatFormatting.stripFormatting(getLoreLineIf(stack, FUEL_PREDICATE));
if (drillFuel != null) {
String[] drillFuelStrings = NOT_DURABILITY.matcher(drillFuel).replaceAll("").trim().split("/");
return OptionalDouble.of(Integer.parseInt(drillFuelStrings[0]) / (Integer.parseInt(drillFuelStrings[1]) * 1000d));
}
} else if (SkyblockerConfigManager.get().mining.enablePickaxeAbility) {
return PickaxeAbility.getCooldownPercentage();
}

return null;
return OptionalDouble.empty();
}

/**
Expand Down
5 changes: 4 additions & 1 deletion src/main/resources/assets/skyblocker/lang/en_us.json
Original file line number Diff line number Diff line change
Expand Up @@ -874,7 +874,10 @@
"skyblocker.config.mining.dwarvenMines.solvePuzzler": "Solve Puzzler Puzzle",

"skyblocker.config.mining.enableDrillFuel": "Enable Drill Fuel",
"skyblocker.config.mining.enableDrillFuel.@Tooltip": "Shows remaining fuel with the durability bar.\nShows the remaining blocks for Pickonimbus.",
"skyblocker.config.mining.enableDrillFuel.@Tooltip": "Shows remaining fuel with the durability bar.\nShows the remaining blocks for Pickonimbus.\nTakes priority over Enable Pickaxe Ability",

"skyblocker.config.mining.enablePickaxeAbility": "Enable Pickaxe Ability",
"skyblocker.config.mining.enablePickaxeAbility.@Tooltip": "Shows pickaxe ability cooldowns with the durability bar.",

"skyblocker.config.mining.glacite": "Glacite Tunnels",
"skyblocker.config.mining.glacite.autoShareCorpses": "Automatically Share Found Corpses In Chat",
Expand Down
10 changes: 5 additions & 5 deletions src/test/java/de/hysky/skyblocker/utils/ItemUtilsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,19 @@
import com.mojang.serialization.Dynamic;
import com.mojang.serialization.JsonOps;
import de.hysky.skyblocker.skyblock.item.tooltip.adders.ObtainedDateTooltip;
import it.unimi.dsi.fastutil.ints.IntIntPair;
import net.minecraft.SharedConstants;
import net.minecraft.data.registries.VanillaRegistries;
import net.minecraft.resources.RegistryOps;
import net.minecraft.server.Bootstrap;
import net.minecraft.util.Mth;
import net.minecraft.util.datafix.DataFixers;
import net.minecraft.util.datafix.fixes.References;
import net.minecraft.world.item.ItemStack;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;

import java.util.OptionalDouble;
import java.util.TimeZone;

public class ItemUtilsTest {
Expand Down Expand Up @@ -123,9 +124,8 @@ void testGetTimestamp() {

@Test
void testGetDurability() {
IntIntPair durability = ItemUtils.getDurability(TITANIUM_DRILL_DR_X655);
Assertions.assertNotNull(durability);
Assertions.assertEquals(5395, durability.leftInt());
Assertions.assertEquals(10_000, durability.rightInt());
OptionalDouble durability = ItemUtils.getDurability(TITANIUM_DRILL_DR_X655);
Assertions.assertTrue(durability.isPresent());
Assertions.assertTrue(Mth.equal(durability.getAsDouble(), 0.5395));
}
}