aboutsummaryrefslogtreecommitdiff
path: root/src/main/java
diff options
context:
space:
mode:
authorLorenz <ESs95s3P5z8Pheb>2022-07-11 23:30:46 +0200
committerLorenz <ESs95s3P5z8Pheb>2022-07-11 23:30:46 +0200
commitddf652388cce1d14dc1a9dc7c44c5b6ccbb9c367 (patch)
treea1df487f4393f3ef8c4356ea1047f19757706e53 /src/main/java
parentcbd64656802075dd31964853723ad8dac8555062 (diff)
downloadskyhanni-ddf652388cce1d14dc1a9dc7c44c5b6ccbb9c367.tar.gz
skyhanni-ddf652388cce1d14dc1a9dc7c44c5b6ccbb9c367.tar.bz2
skyhanni-ddf652388cce1d14dc1a9dc7c44c5b6ccbb9c367.zip
add action bar event, add item ability cooldown feature
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/at/lorenz/mod/HideNotClickableItems.kt2
-rw-r--r--src/main/java/at/lorenz/mod/ItemDisplayOverlayFeatures.kt14
-rw-r--r--src/main/java/at/lorenz/mod/LorenzMod.java2
-rw-r--r--src/main/java/at/lorenz/mod/chat/ChatManager.kt5
-rw-r--r--src/main/java/at/lorenz/mod/config/Features.java32
-rw-r--r--src/main/java/at/lorenz/mod/events/LorenzActionBarEvent.kt3
-rw-r--r--src/main/java/at/lorenz/mod/items/ItemAbilityCooldown.kt288
-rw-r--r--src/main/java/at/lorenz/mod/items/WitherImpactDetection.kt65
-rw-r--r--src/main/java/at/lorenz/mod/utils/ItemUtil.kt2
-rw-r--r--src/main/java/at/lorenz/mod/utils/ItemUtils.kt23
-rw-r--r--src/main/java/at/lorenz/mod/utils/LorenzUtils.kt13
11 files changed, 430 insertions, 19 deletions
diff --git a/src/main/java/at/lorenz/mod/HideNotClickableItems.kt b/src/main/java/at/lorenz/mod/HideNotClickableItems.kt
index 52706a6f4..325eb32af 100644
--- a/src/main/java/at/lorenz/mod/HideNotClickableItems.kt
+++ b/src/main/java/at/lorenz/mod/HideNotClickableItems.kt
@@ -136,7 +136,7 @@ class HideNotClickableItems {
private fun isDisabled(): Boolean {
if (bypassUntil > System.currentTimeMillis()) return true
- return !LorenzMod.feature.item.hideNotClickableItems
+ return !LorenzMod.feature.items.hideNotClickableItems
}
private fun hide(chestName: String, stack: ItemStack): Boolean {
diff --git a/src/main/java/at/lorenz/mod/ItemDisplayOverlayFeatures.kt b/src/main/java/at/lorenz/mod/ItemDisplayOverlayFeatures.kt
index e051e9438..3efd35dd5 100644
--- a/src/main/java/at/lorenz/mod/ItemDisplayOverlayFeatures.kt
+++ b/src/main/java/at/lorenz/mod/ItemDisplayOverlayFeatures.kt
@@ -42,7 +42,7 @@ class ItemDisplayOverlayFeatures {
private fun getStackTip(item: ItemStack): String {
val name = item.cleanName()
- if (LorenzMod.feature.item.displayMasterStarNumber) {
+ if (LorenzMod.feature.items.displayMasterStarNumber) {
when (name) {
"First Master Star" -> return "1"
"Second Master Star" -> return "2"
@@ -52,13 +52,13 @@ class ItemDisplayOverlayFeatures {
}
}
- if (LorenzMod.feature.item.displayMasterSkullNumber) {
+ if (LorenzMod.feature.items.displayMasterSkullNumber) {
if (name.matchRegex("(.*)Master Skull - Tier .")) {
return name.substring(name.length - 1)
}
}
- if (LorenzMod.feature.item.displayDungeonHeadFloor) {
+ if (LorenzMod.feature.items.displayDungeonHeadFloor) {
if (name.contains("Golden ") || name.contains("Diamond ")) {
when {
name.contains("Bonzo") -> return "1"
@@ -72,7 +72,7 @@ class ItemDisplayOverlayFeatures {
}
}
- if (LorenzMod.feature.item.displayNewYearCakeNumber) {
+ if (LorenzMod.feature.items.displayNewYearCakeNumber) {
if (name.startsWith("New Year Cake (")) {
try {
return "§b" + name.between("(Year ", ")")
@@ -84,7 +84,7 @@ class ItemDisplayOverlayFeatures {
}
}
- if (LorenzMod.feature.item.displayPetLevel) {
+ if (LorenzMod.feature.items.displayPetLevel) {
if (ItemUtils.isPet(name)) {
try {
val level = name.between("Lvl ", "] ").toInt()
@@ -99,7 +99,7 @@ class ItemDisplayOverlayFeatures {
}
}
- if (LorenzMod.feature.item.displaySackName) {
+ if (LorenzMod.feature.items.displaySackName) {
if (ItemUtils.isSack(name)) {
val split = name.split(" ")
val sackName = split[split.size - 2]
@@ -107,7 +107,7 @@ class ItemDisplayOverlayFeatures {
}
}
- if (LorenzMod.feature.item.displayMinionTier) {
+ if (LorenzMod.feature.items.displayMinionTier) {
if (name.contains(" Minion ")) {
val array = name.split(" ")
val last = array[array.size - 1]
diff --git a/src/main/java/at/lorenz/mod/LorenzMod.java b/src/main/java/at/lorenz/mod/LorenzMod.java
index 634841201..d4c871dfa 100644
--- a/src/main/java/at/lorenz/mod/LorenzMod.java
+++ b/src/main/java/at/lorenz/mod/LorenzMod.java
@@ -10,6 +10,7 @@ import at.lorenz.mod.dungeon.DungeonChatFilter;
import at.lorenz.mod.dungeon.DungeonData;
import at.lorenz.mod.dungeon.DungeonHighlightClickedBlocks;
import at.lorenz.mod.dungeon.damageindicator.DungeonBossDamageIndicator;
+import at.lorenz.mod.items.ItemAbilityCooldown;
import at.lorenz.mod.misc.*;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
@@ -61,6 +62,7 @@ public class LorenzMod {
MinecraftForge.EVENT_BUS.register(new CurrentPetDisplay());
MinecraftForge.EVENT_BUS.register(new ExpBottleOnGroundHider());
MinecraftForge.EVENT_BUS.register(new DungeonBossDamageIndicator());
+ MinecraftForge.EVENT_BUS.register(new ItemAbilityCooldown());
Commands.init();
diff --git a/src/main/java/at/lorenz/mod/chat/ChatManager.kt b/src/main/java/at/lorenz/mod/chat/ChatManager.kt
index 878c4e8c0..c4ad5ee8d 100644
--- a/src/main/java/at/lorenz/mod/chat/ChatManager.kt
+++ b/src/main/java/at/lorenz/mod/chat/ChatManager.kt
@@ -1,5 +1,6 @@
package at.lorenz.mod.chat
+import at.lorenz.mod.events.LorenzActionBarEvent
import at.lorenz.mod.utils.LorenzLogger
import at.lorenz.mod.events.LorenzChatEvent
import at.lorenz.mod.events.PacketEvent
@@ -23,8 +24,8 @@ class ChatManager {
val message = LorenzUtils.stripVanillaMessage(messageComponent.formattedText)
if (packet.type.toInt() == 2) {
-// val actionBarEvent = LorenzActionBarEvent(message)
-// actionBarEvent.postAndCatch()
+ val actionBarEvent = LorenzActionBarEvent(message)
+ actionBarEvent.postAndCatch()
} else {
val chatEvent = LorenzChatEvent(message, messageComponent)
diff --git a/src/main/java/at/lorenz/mod/config/Features.java b/src/main/java/at/lorenz/mod/config/Features.java
index d4c1e6014..25c36d310 100644
--- a/src/main/java/at/lorenz/mod/config/Features.java
+++ b/src/main/java/at/lorenz/mod/config/Features.java
@@ -13,7 +13,9 @@ import net.minecraft.client.Minecraft;
public class Features {
private void editOverlay(String activeConfig, int width, int height, Position position) {
- Minecraft.getMinecraft().displayGuiScreen(new GuiPositionEditor(position, width, height, () -> {}, () -> {}, () -> LorenzMod.screenToOpen = new GuiScreenElementWrapper(new SBHConfigEditor(LorenzMod.feature, activeConfig))));
+ Minecraft.getMinecraft().displayGuiScreen(new GuiPositionEditor(position, width, height, () -> {
+ }, () -> {
+ }, () -> LorenzMod.screenToOpen = new GuiScreenElementWrapper(new SBHConfigEditor(LorenzMod.feature, activeConfig))));
}
public void executeRunnable(String runnableId) {
@@ -32,7 +34,7 @@ public class Features {
}
if (runnableId.equals("testPos")) {
- editOverlay(activeConfigCategory, 200, 16, test.testPos);
+ editOverlay(activeConfigCategory, 200, 16, debug.testPos);
return;
}
}
@@ -46,20 +48,24 @@ public class Features {
public Dungeon dungeon = new Dungeon();
@Expose
- @Category(name = "Item", desc = "Changing the behavior around items and the inventory.")
- public Inventory item = new Inventory();
+ @Category(name = "Items", desc = "Changing the behavior around items and the inventory.")
+ public Items items = new Items();
@Expose
@Category(name = "Bazaar", desc = "Bazaar settings.")
public Bazaar bazaar = new Bazaar();
@Expose
- @Category(name = "Misc", desc = "Settings without a big category")
+ @Category(name = "Misc", desc = "Settings without a category.")
public Misc misc = new Misc();
@Expose
- @Category(name = "Test", desc = "Test stuff")
- public Test test = new Test();
+ @Category(name = "Debug", desc = "Debug and test stuff.")
+ public Debug debug = new Debug();
+
+ @Expose
+ @Category(name = "Abilities", desc = "Stuff about abilities.")
+ public Abilities abilities = new Abilities();
public static class Chat {
@@ -123,7 +129,7 @@ public class Features {
public boolean bossDamageIndicator = false;
}
- public static class Inventory {
+ public static class Items {
@Expose
@ConfigOption(name = "Not Clickable Items", desc = "Hide items that are not clickable in " + "the current inventory: ah, bz, accessory bag, etc")
@@ -197,7 +203,7 @@ public class Features {
public boolean configButtonOnPause = true;
}
- public static class Test {
+ public static class Debug {
@Expose
@ConfigOption(name = "Enable Test", desc = "Enable Test logic")
@@ -209,4 +215,12 @@ public class Features {
@ConfigEditorButton(runnableId = "testPos", buttonText = "Edit")
public Position testPos = new Position(10, 10, false, true);
}
+
+ public static class Abilities {
+
+ @Expose
+ @ConfigOption(name = "Item Cooldown", desc = "Shows the cooldown of item abilities.")
+ @ConfigEditorBoolean
+ public boolean itemAbilityCooldown = false;
+ }
}
diff --git a/src/main/java/at/lorenz/mod/events/LorenzActionBarEvent.kt b/src/main/java/at/lorenz/mod/events/LorenzActionBarEvent.kt
new file mode 100644
index 000000000..ef7a8bc7b
--- /dev/null
+++ b/src/main/java/at/lorenz/mod/events/LorenzActionBarEvent.kt
@@ -0,0 +1,3 @@
+package at.lorenz.mod.events
+
+class LorenzActionBarEvent(val message: String) : LorenzEvent() \ No newline at end of file
diff --git a/src/main/java/at/lorenz/mod/items/ItemAbilityCooldown.kt b/src/main/java/at/lorenz/mod/items/ItemAbilityCooldown.kt
new file mode 100644
index 000000000..84ab089dc
--- /dev/null
+++ b/src/main/java/at/lorenz/mod/items/ItemAbilityCooldown.kt
@@ -0,0 +1,288 @@
+package at.lorenz.mod.items
+
+import at.lorenz.mod.LorenzMod
+import at.lorenz.mod.events.GuiRenderItemEvent
+import at.lorenz.mod.events.LorenzActionBarEvent
+import at.lorenz.mod.utils.ItemUtils
+import at.lorenz.mod.utils.ItemUtils.cleanName
+import at.lorenz.mod.utils.LorenzColor
+import at.lorenz.mod.utils.LorenzUtils
+import at.lorenz.mod.utils.LorenzUtils.between
+import net.minecraft.client.Minecraft
+import net.minecraft.client.renderer.GlStateManager
+import net.minecraft.item.ItemStack
+import net.minecraftforge.common.MinecraftForge
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+import net.minecraftforge.fml.common.gameevent.TickEvent
+
+class ItemAbilityCooldown {
+
+ var lastAbility = ""
+ var tick = 0
+ val items = mutableMapOf<ItemStack, ItemText>()
+ val witherImpactDetection = WitherImpactDetection(this)
+
+ init {
+ MinecraftForge.EVENT_BUS.register(witherImpactDetection)
+ }
+
+ fun clickWitherImpact() {
+ Ability.WITHER_IMPACT.click()
+ }
+
+ @SubscribeEvent
+ fun onActionBar(event: LorenzActionBarEvent) {
+ if (!isEnabled()) return
+
+ val message: String = event.message
+ if (message.contains(" (§6")) {
+ if (message.contains("§b) ")) {
+ val name: String = message.between(" (§6", "§b) ")
+ if (name == lastAbility) return
+ lastAbility = name
+ for (ability in Ability.values()) {
+ if (ability.abilityName == name) {
+ click(ability)
+ return
+ }
+ }
+ return
+ }
+ }
+ lastAbility = ""
+ }
+
+ private fun isEnabled(): Boolean {
+ return LorenzUtils.inSkyblock && LorenzMod.feature.abilities.itemAbilityCooldown
+ }
+
+ private fun click(ability: Ability) {
+// if (ability.isActive()) return
+ if (!ability.actionBarDetection) return
+ ability.click()
+ }
+
+ @SubscribeEvent
+ fun onTick(event: TickEvent.ClientTickEvent) {
+ if (!isEnabled()) return
+
+ tick++
+ if (tick % 2 == 0) {
+ checkHotbar()
+ }
+ }
+
+ private fun checkHotbar() {
+ items.clear()
+ for ((stack, slot) in ItemUtils.getItemsInInventoryWithSlots(true)) {
+// val inHotbar = slot in 36..43
+
+ val itemName: String = stack.cleanName()
+ val ability = hasAbility(itemName)
+ if (ability != null) {
+
+ if (ability.isOnCooldown()) {
+ val duration: Long = ability.lastClick + ability.getCooldown() - System.currentTimeMillis()
+ val color = if (duration < 600) LorenzColor.RED else LorenzColor.YELLOW
+ items[stack] = ItemText(color, ability.getDurationText(), true)
+ } else {
+ items[stack] = ItemText(LorenzColor.GREEN, "R", false)
+ }
+ }
+ }
+
+ }
+
+ @SubscribeEvent
+ fun onRenderItemOverlayPost(event: GuiRenderItemEvent.RenderOverlayEvent.Post) {
+ if (!isEnabled()) return
+
+ val item = event.stack ?: return
+// if (item.stackSize != 1 || item.tagCompound?.hasKey("SkytilsNoItemOverlay") == true) return
+ if (item.stackSize != 1) return
+
+ var stackTip = ""
+
+ val guiOpen = Minecraft.getMinecraft().currentScreen != null
+ val itemText = items.filter { it.key == item }
+ .firstNotNullOfOrNull { it.value } ?: return
+ if (guiOpen && !itemText.onCooldown) return
+
+ stackTip = itemText.color.getChatColor() + itemText.text
+
+ if (stackTip.isNotEmpty()) {
+ GlStateManager.disableLighting()
+ GlStateManager.disableDepth()
+ GlStateManager.disableBlend()
+ event.fr.drawStringWithShadow(
+ stackTip,
+ (event.x + 17 - event.fr.getStringWidth(stackTip)).toFloat(),
+ (event.y + 9).toFloat(),
+ 16777215
+ )
+ GlStateManager.enableLighting()
+ GlStateManager.enableDepth()
+ }
+ }
+
+// @SubscribeEvent
+// fun onRenderItemOverlayPost(event: GuiRenderItemEvent.RenderOverlayEvent.Pre) {
+// if (!isEnabled()) return
+//
+// val item = event.stack ?: return
+//// if (item.stackSize != 1 || item.tagCompound?.hasKey("SkytilsNoItemOverlay") == true) return
+// if (item.stackSize != 1) return
+//
+// var stackTip = ""
+//
+// val isActive = Minecraft.getMinecraft().currentScreen == null
+// val itemText = items.filter { it.key == item && it.value.active }
+// .firstNotNullOfOrNull { it.value }
+//
+// if (itemText != null) return
+//// if (!isActive && !itemText.active) return
+//
+// stackTip = "T"
+//
+//// items.filter { it.key == item }
+//// .forEach { stackTip = it.value.color.getChatColor() + it.value.text }
+//
+// if (stackTip.isNotEmpty()) {
+// GlStateManager.disableLighting()
+// GlStateManager.disableDepth()
+// GlStateManager.disableBlend()
+// event.fr.drawStringWithShadow(
+// stackTip,
+// (event.x + 17 - event.fr.getStringWidth(stackTip)).toFloat(),
+// (event.y + 9).toFloat(),
+// 16777215
+// )
+// GlStateManager.enableLighting()
+// GlStateManager.enableDepth()
+// }
+// }
+
+// @SubscribeEvent
+// fun onGuiDrawEvent(event: GuiContainerEvent.BackgroundDrawnEvent) {
+// if (!isEnabled())
+//
+// val guiContainer: GuiContainer? = event.gui
+// if (guiContainer != null && guiContainer !is GuiInventory) return
+// val chest = guiContainer.inventorySlots
+//
+//// val chestName = chest.lowerChestInventory.displayName.unformattedText.trim()
+//// if (chestName != "Spirit Leap") return
+//
+// for (slot in chest.inventorySlots) {
+// if (slot == null) continue
+//// if (slot.slotNumber == slot.slotIndex) continue
+// if (slot.stack == null) continue
+//
+// val stack = slot.stack
+//
+//// for ((item, text) in map) {
+//// if (item == stack) {
+//// slot highlight text.color
+//// }
+//// }
+// map.filter { it.key == stack }.forEach { slot highlight it.value.color }
+//
+//// slot highlight LorenzColor.WHITE
+//
+//// val displayName = stack.displayName
+//// if (displayName == " ") continue
+//
+//// val itemLore = stack.getLore()
+//// if (itemLore.size == 1 && itemLore[0] == "§eClick to teleport!") {
+////
+//// if (displayName.contains(witherDoorName)) {
+//// if (lastWitherDoorOpened + 10_000 > System.currentTimeMillis()) {
+//// slot highlight LorenzColor.YELLOW
+//// return
+//// }
+//// }
+//// if (displayName.contains(teleportName)) {
+//// if (lastTeleport + 10_000 > System.currentTimeMillis()) {
+//// slot highlight LorenzColor.AQUA
+//// return
+//// }
+//// }
+//// } else {
+//// //TODO hide the item totally?
+//// slot highlight LorenzColor.RED
+//// }
+//
+// }
+// }
+
+ private fun hasAbility(itemName: String): Ability? {
+ for (ability in Ability.values()) {
+ for (name in ability.itemNames) {
+ if (itemName.contains(name)) {
+ return ability
+ }
+ }
+ }
+ return null
+ }
+
+ enum class Ability(
+ val abilityName: String,
+ val cooldownInSeconds: Long,
+ vararg val itemNames: String,
+ var lastClick: Long = 0L,
+ val actionBarDetection: Boolean = true
+ ) {
+ ATOMSPLIT("Soulcry", 4, "Atomsplit Katana", "Vorpal Katana", "Voidedge Katana"),
+ WITHER_IMPACT("Wither Impact", 5, "Hyperion", "Scylla", "Valkyrie", "Astrea", actionBarDetection = false),
+
+ HEAL_1("Small Heal", 7, "Wand of Healing"),
+ HEAL_2("Medium Heal", 7, "Wand of Mending"),
+ HEAL_3("Big Heal", 7, "Wand of Restoration"),
+ HEAL_4("Huge Heal", 7, "Wand of Atonement"),
+
+ ICE_SPRAY("Ice Spray", 5, "Ice Spray Wand"),
+ GYRO("Gravity Storm", 30, "Gyrokinetic Wand"),
+ GIANTS_SWORD("Giant's Slam", 30, "Giant's Sword"),
+
+ STAR_FALL("Starfall", 2, "Starlight Wand"),
+ VODOO_DOLL("Acupuncture", 5, "Voodoo Doll"),
+ INK_WAND("Ink Bomb", 30, "Ink Wand"),
+ GOLEM_SWORD("Iron Punch", 3, "Golem Sword"),
+ EMBER_ROD("Fire Blast", 30, "Ember Rod"),
+ ENDER_BOW("Ender Warp", 30, "Ender Bow"),
+
+ LIVID_DAGGER("Throw", 5, "Livid Dagger"),
+ WEIRD_TUBA("Howl", 20, "Weird Tuba"),
+
+ ENDSTONE_SWORD("Extreme Focus", 5, "End Stone Sword"),
+ PIGMAN_SWORD("Burning Souls", 5, "Pigman Sword"),
+
+ SOULWARD("Soulward", 20, "Soul Esoward");
+
+ fun click() {
+ lastClick = System.currentTimeMillis()
+ }
+
+ fun isOnCooldown(): Boolean = lastClick + getCooldown() > System.currentTimeMillis()
+
+ fun getCooldown(): Long = cooldownInSeconds * 1000
+
+ fun getDurationText(): String {
+ var duration: Long = lastClick + getCooldown() - System.currentTimeMillis()
+ return if (duration < 1600) {
+ duration /= 100
+ var d = duration.toDouble()
+ d /= 10.0
+ LorenzUtils.formatDouble(d)
+ } else {
+ duration /= 1000
+ duration++
+ LorenzUtils.formatInteger(duration.toInt())
+ }
+ }
+
+ }
+
+ class ItemText(val color: LorenzColor, val text: String, val onCooldown: Boolean)
+} \ No newline at end of file
diff --git a/src/main/java/at/lorenz/mod/items/WitherImpactDetection.kt b/src/main/java/at/lorenz/mod/items/WitherImpactDetection.kt
new file mode 100644
index 000000000..5312e28a3
--- /dev/null
+++ b/src/main/java/at/lorenz/mod/items/WitherImpactDetection.kt
@@ -0,0 +1,65 @@
+package at.lorenz.mod.items
+
+import at.lorenz.mod.events.PacketEvent
+import at.lorenz.mod.utils.ItemUtil.asStringSet
+import at.lorenz.mod.utils.ItemUtil.getExtraAttributes
+import at.lorenz.mod.utils.LorenzUtils
+import net.minecraft.client.Minecraft
+import net.minecraft.init.Items
+import net.minecraft.network.play.client.C08PacketPlayerBlockPlacement
+import net.minecraft.network.play.server.S1CPacketEntityMetadata
+import net.minecraft.network.play.server.S2APacketParticles
+import net.minecraft.util.EnumParticleTypes
+import net.minecraftforge.common.util.Constants
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+import net.minecraftforge.fml.common.gameevent.TickEvent
+
+/**
+ * Taken from Skytils under AGPL 3.0
+ * Modified
+ * https://github.com/Skytils/SkytilsMod/blob/1.x/LICENSE.md
+ * @author Skytils
+ */
+class WitherImpactDetection(private val itemAbilityCooldown: ItemAbilityCooldown) {
+
+ val S2APacketParticles.type: EnumParticleTypes
+ get() = this.particleType
+ var lastShieldUse = -1L
+ var lastShieldClick = 0L
+
+ @SubscribeEvent
+ fun onReceivePacket(event: PacketEvent.ReceiveEvent) {
+ val mc = Minecraft.getMinecraft()
+ if (!LorenzUtils.inSkyblock || mc.theWorld == null) return
+
+ event.packet.apply {
+
+ if (this is S1CPacketEntityMetadata && lastShieldClick != -1L && entityId == mc.thePlayer?.entityId && System.currentTimeMillis() - lastShieldClick <= 500 && func_149376_c()?.any { it.dataValueId == 17 } == true) {
+ lastShieldUse = System.currentTimeMillis()
+ lastShieldClick = -1
+ itemAbilityCooldown.clickWitherImpact()
+ }
+ }
+ }
+
+ @SubscribeEvent
+ fun onSendPacket(event: PacketEvent.SendEvent) {
+ val mc = Minecraft.getMinecraft()
+ if (!LorenzUtils.inSkyblock || lastShieldUse != -1L || mc.thePlayer?.heldItem == null) return
+ if (event.packet is C08PacketPlayerBlockPlacement && mc.thePlayer.heldItem.item == Items.iron_sword && getExtraAttributes(
+ mc.thePlayer.heldItem
+ )?.getTagList("ability_scroll", Constants.NBT.TAG_STRING)?.asStringSet()
+ ?.contains("WITHER_SHIELD_SCROLL") == true
+ ) {
+ lastShieldClick = System.currentTimeMillis()
+ }
+ }
+
+ @SubscribeEvent
+ fun onTick(event: TickEvent.ClientTickEvent) {
+ if (lastShieldUse != -1L) {
+ val diff = ((lastShieldUse + 5000 - System.currentTimeMillis()) / 1000f)
+ if (diff < 0) lastShieldUse = -1
+ }
+ }
+} \ No newline at end of file
diff --git a/src/main/java/at/lorenz/mod/utils/ItemUtil.kt b/src/main/java/at/lorenz/mod/utils/ItemUtil.kt
index fc0409e31..341b94ca8 100644
--- a/src/main/java/at/lorenz/mod/utils/ItemUtil.kt
+++ b/src/main/java/at/lorenz/mod/utils/ItemUtil.kt
@@ -208,4 +208,6 @@ object ItemUtil {
})
return this
}
+
+ fun NBTTagList.asStringSet() = (0..tagCount()).mapTo(hashSetOf()) { getStringTagAt(it) }
} \ No newline at end of file
diff --git a/src/main/java/at/lorenz/mod/utils/ItemUtils.kt b/src/main/java/at/lorenz/mod/utils/ItemUtils.kt
index 168b41ddf..6d5bf57da 100644
--- a/src/main/java/at/lorenz/mod/utils/ItemUtils.kt
+++ b/src/main/java/at/lorenz/mod/utils/ItemUtils.kt
@@ -46,4 +46,27 @@ object ItemUtils {
fun maxPetLevel(name: String) = if (name.contains("Golden Dragon")) 200 else 100
+ fun getItemsInInventoryWithSlots(withCursorItem: Boolean = false): Map<ItemStack, Int> {
+ val map: LinkedHashMap<ItemStack, Int> = LinkedHashMap()
+ val player = Minecraft.getMinecraft().thePlayer
+ if (player == null) {
+ LorenzUtils.warning("getItemsInInventoryWithSlots: player is null!")
+ return map
+ }
+ for (slot in player.openContainer.inventorySlots) {
+ if (slot.hasStack) {
+ map[slot.stack] = slot.slotNumber
+ }
+ }
+
+ if (withCursorItem) {
+ if (player.inventory != null) {
+ if (player.inventory.itemStack != null) {
+ map[player.inventory.itemStack] = -1
+ }
+ }
+ }
+
+ return map
+ }
} \ No newline at end of file
diff --git a/src/main/java/at/lorenz/mod/utils/LorenzUtils.kt b/src/main/java/at/lorenz/mod/utils/LorenzUtils.kt
index b36fbb94e..875b41af5 100644
--- a/src/main/java/at/lorenz/mod/utils/LorenzUtils.kt
+++ b/src/main/java/at/lorenz/mod/utils/LorenzUtils.kt
@@ -6,6 +6,7 @@ import net.minecraft.entity.EntityLivingBase
import net.minecraft.entity.SharedMonsterAttributes
import net.minecraft.util.ChatComponentText
import org.intellij.lang.annotations.Language
+import java.text.DecimalFormat
import java.text.SimpleDateFormat
object LorenzUtils {
@@ -114,4 +115,16 @@ object LorenzUtils {
val EntityLivingBase.baseMaxHealth: Double
get() = this.getEntityAttribute(SharedMonsterAttributes.maxHealth).baseValue
+
+ fun formatPercentage(percentage: Double): String = formatPercentage(percentage, "0.00")
+
+ fun formatPercentage(percentage: Double, format: String?): String =
+ DecimalFormat(format).format(percentage * 100).replace(',', '.') + "%"
+
+ fun formatInteger(i: Int): String = DecimalFormat("#,##0").format(i.toLong()).replace(',', '.')
+
+ fun formatDouble(d: Double, format: String?): String =
+ DecimalFormat(format).format(d).replace(',', 'x').replace('.', ',').replace('x', '.')
+
+ fun formatDouble(d: Double): String = formatDouble(d, "#,##0.0")
} \ No newline at end of file