From 3a3d0bdf021558f9ab5ddd8e8549ade491fd8a57 Mon Sep 17 00:00:00 2001 From: Linnea Gräf Date: Fri, 4 Oct 2024 20:58:00 +0200 Subject: Add tapcubed stuff [no changelog] --- src/main/kotlin/features/chat/AutoGGOnTapCube.kt | 35 ++++++ .../kotlin/features/fixes/CompatibliltyFeatures.kt | 73 ++++++------ .../features/inventory/ItemRarityCosmetics.kt | 129 ++++++++++++--------- .../inventory/storageoverlay/StorageOverlay.kt | 1 + src/main/kotlin/util/SBData.kt | 107 ++++++++--------- .../kotlin/util/data/ProfileSpecificDataHolder.kt | 8 +- .../resources/assets/firmament/lang/en_us.json | 1 + 7 files changed, 206 insertions(+), 148 deletions(-) create mode 100644 src/main/kotlin/features/chat/AutoGGOnTapCube.kt (limited to 'src') diff --git a/src/main/kotlin/features/chat/AutoGGOnTapCube.kt b/src/main/kotlin/features/chat/AutoGGOnTapCube.kt new file mode 100644 index 0000000..356d40a --- /dev/null +++ b/src/main/kotlin/features/chat/AutoGGOnTapCube.kt @@ -0,0 +1,35 @@ +package moe.nea.firmament.features.chat + +import java.util.concurrent.ThreadLocalRandom +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch +import kotlin.time.Duration.Companion.milliseconds +import net.minecraft.text.Text +import moe.nea.firmament.Firmament +import moe.nea.firmament.annotations.Subscribe +import moe.nea.firmament.events.ProcessChatEvent +import moe.nea.firmament.features.fixes.CompatibliltyFeatures +import moe.nea.firmament.util.FirmFormatters +import moe.nea.firmament.util.MC +import moe.nea.firmament.util.SBData +import moe.nea.firmament.util.useMatch + +object AutoGGOnTapCube { + + val regex = " *. STORE PURCHASE .".toPattern() + + @Subscribe + fun onChat(event: ProcessChatEvent) { + if (!SBData.isTabCube) return + if (!CompatibliltyFeatures.TConfig.tapCube) return + regex.useMatch(event.unformattedString) { + val delay = ThreadLocalRandom.current().nextInt(500, 3000).milliseconds + MC.sendChat(Text.literal("Sending gg in ${FirmFormatters.formatTimespan(delay, true)}")) + Firmament.coroutineScope.launch { + delay(delay) + MC.sendServerChat("gg") + MC.sendChat(Text.literal("Mission accomplished. AutoGG out.")) + } + } + } +} diff --git a/src/main/kotlin/features/fixes/CompatibliltyFeatures.kt b/src/main/kotlin/features/fixes/CompatibliltyFeatures.kt index 7c43cf6..0b64b80 100644 --- a/src/main/kotlin/features/fixes/CompatibliltyFeatures.kt +++ b/src/main/kotlin/features/fixes/CompatibliltyFeatures.kt @@ -1,5 +1,3 @@ - - package moe.nea.firmament.features.fixes import net.fabricmc.loader.api.FabricLoader @@ -13,39 +11,40 @@ import moe.nea.firmament.gui.config.ManagedConfig import moe.nea.firmament.util.MC object CompatibliltyFeatures : FirmamentFeature { - override val identifier: String - get() = "compatibility" - - object TConfig : ManagedConfig(identifier) { - val enhancedExplosions by toggle("explosion-enabled") { false } - val explosionSize by integer("explosion-power", 10, 50) { 1 } - } - - override val config: ManagedConfig? - get() = TConfig - - interface ExplosiveApiWrapper { - fun spawnParticle(vec3d: Vec3d, power: Float) - } - - class ExplosiveApiWrapperImpl : ExplosiveApiWrapper { - override fun spawnParticle(vec3d: Vec3d, power: Float) { - ExplosiveApi.spawnParticles(MC.world, vec3d.x, vec3d.y, vec3d.z, TConfig.explosionSize / 10F) - } - } - - val explosiveApiWrapper = if (FabricLoader.getInstance().isModLoaded("explosiveenhancement")) { - ExplosiveApiWrapperImpl() - } else null - - @Subscribe - fun onExplosion(it: ParticleSpawnEvent) { - if (TConfig.enhancedExplosions && - it.particleEffect.type == ParticleTypes.EXPLOSION_EMITTER && - explosiveApiWrapper != null - ) { - it.cancel() - explosiveApiWrapper.spawnParticle(it.position, 2F) - } - } + override val identifier: String + get() = "compatibility" + + object TConfig : ManagedConfig(identifier) { + val enhancedExplosions by toggle("explosion-enabled") { false } + val explosionSize by integer("explosion-power", 10, 50) { 1 } + val tapCube by toggle("tapcube") { true } + } + + override val config: ManagedConfig? + get() = TConfig + + interface ExplosiveApiWrapper { + fun spawnParticle(vec3d: Vec3d, power: Float) + } + + class ExplosiveApiWrapperImpl : ExplosiveApiWrapper { + override fun spawnParticle(vec3d: Vec3d, power: Float) { + ExplosiveApi.spawnParticles(MC.world, vec3d.x, vec3d.y, vec3d.z, TConfig.explosionSize / 10F) + } + } + + val explosiveApiWrapper = if (FabricLoader.getInstance().isModLoaded("explosiveenhancement")) { + ExplosiveApiWrapperImpl() + } else null + + @Subscribe + fun onExplosion(it: ParticleSpawnEvent) { + if (TConfig.enhancedExplosions && + it.particleEffect.type == ParticleTypes.EXPLOSION_EMITTER && + explosiveApiWrapper != null + ) { + it.cancel() + explosiveApiWrapper.spawnParticle(it.position, 2F) + } + } } diff --git a/src/main/kotlin/features/inventory/ItemRarityCosmetics.kt b/src/main/kotlin/features/inventory/ItemRarityCosmetics.kt index 424f13b..cc2c003 100644 --- a/src/main/kotlin/features/inventory/ItemRarityCosmetics.kt +++ b/src/main/kotlin/features/inventory/ItemRarityCosmetics.kt @@ -1,5 +1,3 @@ - - package moe.nea.firmament.features.inventory import java.awt.Color @@ -11,74 +9,95 @@ import moe.nea.firmament.annotations.Subscribe import moe.nea.firmament.events.HotbarItemRenderEvent import moe.nea.firmament.events.SlotRenderEvents import moe.nea.firmament.features.FirmamentFeature +import moe.nea.firmament.features.fixes.CompatibliltyFeatures import moe.nea.firmament.gui.config.ManagedConfig import moe.nea.firmament.util.MC -import moe.nea.firmament.util.mc.loreAccordingToNbt +import moe.nea.firmament.util.SBData import moe.nea.firmament.util.collections.lastNotNullOfOrNull import moe.nea.firmament.util.collections.memoizeIdentity +import moe.nea.firmament.util.mc.loreAccordingToNbt import moe.nea.firmament.util.unformattedString object ItemRarityCosmetics : FirmamentFeature { - override val identifier: String - get() = "item-rarity-cosmetics" + override val identifier: String + get() = "item-rarity-cosmetics" + + object TConfig : ManagedConfig(identifier) { + val showItemRarityBackground by toggle("background") { false } + val showItemRarityInHotbar by toggle("background-hotbar") { false } + } + + override val config: ManagedConfig + get() = TConfig - object TConfig : ManagedConfig(identifier) { - val showItemRarityBackground by toggle("background") { false } - val showItemRarityInHotbar by toggle("background-hotbar") { false } - } + private val rarityToColor = mapOf( + "UNCOMMON" to Formatting.GREEN, + "COMMON" to Formatting.WHITE, + "RARE" to Formatting.DARK_BLUE, + "EPIC" to Formatting.DARK_PURPLE, + "LEGENDARY" to Formatting.GOLD, + "LEGENJERRY" to Formatting.GOLD, + "MYTHIC" to Formatting.LIGHT_PURPLE, + "DIVINE" to Formatting.BLUE, + "SPECIAL" to Formatting.DARK_RED, + "SUPREME" to Formatting.DARK_RED, + ).mapValues { + val c = Color(it.value.colorValue!!) + Triple(c.red / 255F, c.green / 255F, c.blue / 255F) + } - override val config: ManagedConfig - get() = TConfig + private val tabCubeRarityToColor = mapOf( + "COMMON" to Color.WHITE, + "RELIC" to Color(255, 23, 130), + "BOSS DROP" to Color.YELLOW, + "MYTHIC" to Color.ORANGE, + "RARE" to Color.BLUE, + "UNCOMMON" to Color.GREEN, + "LEGENDARY" to Color(250, 240, 130), + "EPIC" to Color(180, 30, 180), + "ULTIMATE" to Color(255, 130, 0), + "ᴠᴏᴜᴄʜᴇʀ" to Color(80, 120, 255) + ).mapValues { + val c = it.value + Triple(c.red / 255F, c.green / 255F, c.blue / 255F) + } - private val rarityToColor = mapOf( - "UNCOMMON" to Formatting.GREEN, - "COMMON" to Formatting.WHITE, - "RARE" to Formatting.DARK_BLUE, - "EPIC" to Formatting.DARK_PURPLE, - "LEGENDARY" to Formatting.GOLD, - "LEGENJERRY" to Formatting.GOLD, - "MYTHIC" to Formatting.LIGHT_PURPLE, - "DIVINE" to Formatting.BLUE, - "SPECIAL" to Formatting.DARK_RED, - "SUPREME" to Formatting.DARK_RED, - ).mapValues { - val c = Color(it.value.colorValue!!) - Triple(c.red / 255F, c.green / 255F, c.blue / 255F) - } + val currentRarities get() = if (CompatibliltyFeatures.TConfig.tapCube && SBData.isTabCube) tabCubeRarityToColor else rarityToColor - private fun getSkyblockRarity0(itemStack: ItemStack): Triple? { - return itemStack.loreAccordingToNbt.lastNotNullOfOrNull { - val entry = it.unformattedString - rarityToColor.entries.find { (k, v) -> k in entry }?.value - } - } + private fun getSkyblockRarity0(itemStack: ItemStack): Triple? { + return itemStack.loreAccordingToNbt.lastNotNullOfOrNull { + val entry = it.unformattedString + currentRarities.entries.find { (k, v) -> k in entry }?.value + } + } - val getSkyblockRarity = ::getSkyblockRarity0.memoizeIdentity(100) + // TODO: replace with weak cache + val getSkyblockRarity = ::getSkyblockRarity0.memoizeIdentity(100) - fun drawItemStackRarity(drawContext: DrawContext, x: Int, y: Int, item: ItemStack) { - val (r, g, b) = getSkyblockRarity(item) ?: return - drawContext.drawSprite( - x, y, - 0, - 16, 16, - MC.guiAtlasManager.getSprite(Identifier.of("firmament:item_rarity_background")), - r, g, b, 1F - ) - } + fun drawItemStackRarity(drawContext: DrawContext, x: Int, y: Int, item: ItemStack) { + val (r, g, b) = getSkyblockRarity(item) ?: return + drawContext.drawSprite( + x, y, + 0, + 16, 16, + MC.guiAtlasManager.getSprite(Identifier.of("firmament:item_rarity_background")), + r, g, b, 1F + ) + } - @Subscribe - fun onRenderSlot(it: SlotRenderEvents.Before) { - if (!TConfig.showItemRarityBackground) return - val stack = it.slot.stack ?: return - drawItemStackRarity(it.context, it.slot.x, it.slot.y, stack) - } + @Subscribe + fun onRenderSlot(it: SlotRenderEvents.Before) { + if (!TConfig.showItemRarityBackground) return + val stack = it.slot.stack ?: return + drawItemStackRarity(it.context, it.slot.x, it.slot.y, stack) + } - @Subscribe - fun onRenderHotbarItem(it: HotbarItemRenderEvent) { - if (!TConfig.showItemRarityInHotbar) return - val stack = it.item - drawItemStackRarity(it.context, it.x, it.y, stack) - } + @Subscribe + fun onRenderHotbarItem(it: HotbarItemRenderEvent) { + if (!TConfig.showItemRarityInHotbar) return + val stack = it.item + drawItemStackRarity(it.context, it.x, it.y, stack) + } } diff --git a/src/main/kotlin/features/inventory/storageoverlay/StorageOverlay.kt b/src/main/kotlin/features/inventory/storageoverlay/StorageOverlay.kt index b615c73..9ad5636 100644 --- a/src/main/kotlin/features/inventory/storageoverlay/StorageOverlay.kt +++ b/src/main/kotlin/features/inventory/storageoverlay/StorageOverlay.kt @@ -139,6 +139,7 @@ object StorageOverlay : FirmamentFeature { data: SortedMap ) { // TODO: FIXME: FIXME NOW: Definitely don't copy all of this every tick into persistence + // This should be easily doable now that inventory update event exists. val newStacks = VirtualInventory(handler.handler.stacks.take(handler.handler.rows * 9).drop(9).map { it.copy() }) data.compute(handler.storagePageSlot) { slot, existingInventory -> diff --git a/src/main/kotlin/util/SBData.kt b/src/main/kotlin/util/SBData.kt index 353bb06..8b3ad96 100644 --- a/src/main/kotlin/util/SBData.kt +++ b/src/main/kotlin/util/SBData.kt @@ -9,59 +9,62 @@ import moe.nea.firmament.events.AllowChatEvent import moe.nea.firmament.events.ProcessChatEvent import moe.nea.firmament.events.ServerConnectedEvent import moe.nea.firmament.events.SkyblockServerUpdateEvent -import moe.nea.firmament.events.WorldReadyEvent object SBData { - private val profileRegex = "Profile ID: ([a-z0-9\\-]+)".toRegex() - val profileSuggestTexts = listOf( - "CLICK THIS TO SUGGEST IT IN CHAT [DASHES]", - "CLICK THIS TO SUGGEST IT IN CHAT [NO DASHES]", - ) - var profileId: UUID? = null + private val profileRegex = "Profile ID: ([a-z0-9\\-]+)".toRegex() + val profileSuggestTexts = listOf( + "CLICK THIS TO SUGGEST IT IN CHAT [DASHES]", + "CLICK THIS TO SUGGEST IT IN CHAT [NO DASHES]", + ) + var profileId: UUID? = null + val genericProfileId: String? get() = if (isTabCube) "tabcube-${MC.instance.session.uuidOrNull}" else profileId?.toString() - private var hasReceivedProfile = false - var locraw: Locraw? = null - val skyblockLocation: SkyBlockIsland? get() = locraw?.skyblockLocation - val hasValidLocraw get() = locraw?.server !in listOf("limbo", null) - val isOnSkyblock get() = locraw?.gametype == "SKYBLOCK" - var profileIdCommandDebounce = TimeMark.farPast() - fun init() { - ServerConnectedEvent.subscribe("SBData:onServerConnected") { - HypixelModAPI.getInstance().subscribeToEventPacket(ClientboundLocationPacket::class.java) - } - HypixelModAPI.getInstance().createHandler(ClientboundLocationPacket::class.java) { - MC.onMainThread { - val lastLocraw = locraw - locraw = Locraw(it.serverName, - it.serverType.getOrNull()?.name?.uppercase(), - it.mode.getOrNull(), - it.map.getOrNull()) - SkyblockServerUpdateEvent.publish(SkyblockServerUpdateEvent(lastLocraw, null)) - profileIdCommandDebounce = TimeMark.now() - } - } - SkyblockServerUpdateEvent.subscribe("SBData:sendProfileId") { - if (!hasReceivedProfile && isOnSkyblock && profileIdCommandDebounce.passedTime() > 10.seconds) { - profileIdCommandDebounce = TimeMark.now() - MC.sendServerCommand("profileid") - } - } - AllowChatEvent.subscribe("SBData:hideProfileSuggest") { event -> - if (event.unformattedString in profileSuggestTexts && profileIdCommandDebounce.passedTime() < 5.seconds) { - event.cancel() - } - } - ProcessChatEvent.subscribe(receivesCancelled = true, "SBData:loadProfile") { event -> - val profileMatch = profileRegex.matchEntire(event.unformattedString) - if (profileMatch != null) { - try { - profileId = UUID.fromString(profileMatch.groupValues[1]) - hasReceivedProfile = true - } catch (e: IllegalArgumentException) { - profileId = null - e.printStackTrace() - } - } - } - } + private var hasReceivedProfile = false + var locraw: Locraw? = null + val skyblockLocation: SkyBlockIsland? get() = locraw?.skyblockLocation + val hasValidLocraw get() = locraw?.server !in listOf("limbo", null) + val isOnSkyblock get() = locraw?.gametype == "SKYBLOCK" + var profileIdCommandDebounce = TimeMark.farPast() + val connectionAddress: String? get() = MC.networkHandler?.serverInfo?.address + val isTabCube get() = connectionAddress == "tapcube.minehut.gg" + + fun init() { + ServerConnectedEvent.subscribe("SBData:onServerConnected") { + HypixelModAPI.getInstance().subscribeToEventPacket(ClientboundLocationPacket::class.java) + } + HypixelModAPI.getInstance().createHandler(ClientboundLocationPacket::class.java) { + MC.onMainThread { + val lastLocraw = locraw + locraw = Locraw(it.serverName, + it.serverType.getOrNull()?.name?.uppercase(), + it.mode.getOrNull(), + it.map.getOrNull()) + SkyblockServerUpdateEvent.publish(SkyblockServerUpdateEvent(lastLocraw, null)) + profileIdCommandDebounce = TimeMark.now() + } + } + SkyblockServerUpdateEvent.subscribe("SBData:sendProfileId") { + if (!hasReceivedProfile && isOnSkyblock && profileIdCommandDebounce.passedTime() > 10.seconds) { + profileIdCommandDebounce = TimeMark.now() + MC.sendServerCommand("profileid") + } + } + AllowChatEvent.subscribe("SBData:hideProfileSuggest") { event -> + if (event.unformattedString in profileSuggestTexts && profileIdCommandDebounce.passedTime() < 5.seconds) { + event.cancel() + } + } + ProcessChatEvent.subscribe(receivesCancelled = true, "SBData:loadProfile") { event -> + val profileMatch = profileRegex.matchEntire(event.unformattedString) + if (profileMatch != null) { + try { + profileId = UUID.fromString(profileMatch.groupValues[1]) + hasReceivedProfile = true + } catch (e: IllegalArgumentException) { + profileId = null + e.printStackTrace() + } + } + } + } } diff --git a/src/main/kotlin/util/data/ProfileSpecificDataHolder.kt b/src/main/kotlin/util/data/ProfileSpecificDataHolder.kt index 1cd4f22..2566e4c 100644 --- a/src/main/kotlin/util/data/ProfileSpecificDataHolder.kt +++ b/src/main/kotlin/util/data/ProfileSpecificDataHolder.kt @@ -22,10 +22,10 @@ abstract class ProfileSpecificDataHolder( private val configDefault: () -> S ) : IDataHolder { - var allConfigs: MutableMap + var allConfigs: MutableMap override val data: S? - get() = SBData.profileId?.let { + get() = SBData.genericProfileId?.let { allConfigs.computeIfAbsent(it) { configDefault() } } @@ -36,7 +36,7 @@ abstract class ProfileSpecificDataHolder( private val configDirectory: Path get() = Firmament.CONFIG_DIR.resolve("profiles").resolve(configName) - private fun readValues(): MutableMap { + private fun readValues(): MutableMap { if (!configDirectory.exists()) { configDirectory.createDirectories() } @@ -45,7 +45,7 @@ abstract class ProfileSpecificDataHolder( .filter { it.extension == "json" } .mapNotNull { try { - UUID.fromString(it.nameWithoutExtension) to Firmament.json.decodeFromString(dataSerializer, it.readText()) + (it.nameWithoutExtension) to Firmament.json.decodeFromString(dataSerializer, it.readText()) } catch (e: Exception) { /* Expecting IOException and SerializationException, but Kotlin doesn't allow multi catches*/ IDataHolder.badLoads.add(configName) Firmament.logger.error( diff --git a/src/main/resources/assets/firmament/lang/en_us.json b/src/main/resources/assets/firmament/lang/en_us.json index bc2838b..68c30f9 100644 --- a/src/main/resources/assets/firmament/lang/en_us.json +++ b/src/main/resources/assets/firmament/lang/en_us.json @@ -194,6 +194,7 @@ "firmament.tooltip.copied.nbt": "Copied NBT data", "firmament.config.compatibility": "Intermod Features", "firmament.config.compatibility.explosion-enabled": "Redirect Enhanced Explosions", + "firmament.config.compatibility.tapcube": "Add TapCube features", "firmament.config.compatibility.explosion-power": "Enhanced Explosion Power", "firmament.quick-commands.join.unknown": "Could not find instance for %s", "firmament.quick-commands.join.success": "Joining: %s", -- cgit