diff options
Diffstat (limited to 'src/main/java')
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 |