Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: Add Timite tracker and helpers #3102

Open
wants to merge 2 commits into
base: beta
Choose a base branch
from
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 @@ -4,6 +4,7 @@
import at.hannibal2.skyhanni.config.features.rift.area.dreadfarm.DreadfarmConfig;
import at.hannibal2.skyhanni.config.features.rift.area.livingcave.LivingCaveConfig;
import at.hannibal2.skyhanni.config.features.rift.area.mirrorverse.MirrorVerseConfig;
import at.hannibal2.skyhanni.config.features.rift.area.mountaintop.MountaintopConfig;
import at.hannibal2.skyhanni.config.features.rift.area.stillgorechateau.StillgoreChateauConfig;
import at.hannibal2.skyhanni.config.features.rift.area.westvillage.WestVillageConfig;
import at.hannibal2.skyhanni.config.features.rift.area.wyldwoods.WyldWoodsConfig;
Expand Down Expand Up @@ -53,8 +54,8 @@ public class RiftAreasConfig {
@Accordion
public StillgoreChateauConfig stillgoreChateau = new StillgoreChateauConfig();

// @Expose
// @ConfigOption(name = "Mountaintop", desc = "")
// @Accordion
// public MountaintopConfig mountaintop = new MountaintopConfig();
@Expose
@ConfigOption(name = "Mountaintop", desc = "")
@Accordion
public MountaintopConfig mountaintop = new MountaintopConfig();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package at.hannibal2.skyhanni.config.features.rift.area.mountaintop;

import com.google.gson.annotations.Expose;
import io.github.notenoughupdates.moulconfig.annotations.Accordion;
import io.github.notenoughupdates.moulconfig.annotations.ConfigOption;

public class MountaintopConfig {

@Expose
@ConfigOption(name = "Timite", desc = "")
@Accordion
public TimiteConfig timite = new TimiteConfig();

}

Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package at.hannibal2.skyhanni.config.features.rift.area.mountaintop;

import at.hannibal2.skyhanni.config.core.config.Position;
import com.google.gson.annotations.Expose;
import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorBoolean;
import io.github.notenoughupdates.moulconfig.annotations.ConfigLink;
import io.github.notenoughupdates.moulconfig.annotations.ConfigOption;

public class TimiteConfig {

@Expose
@ConfigOption(name = "Timite Timer", desc = "Count down the time until Timite evolves with the time gun.")
@ConfigEditorBoolean
public boolean timiteTimer = true;

@Expose
@ConfigOption(name = "Timite Expiry Timer", desc = "Count down the time until Timite/Obsolite expires.")
@ConfigEditorBoolean
public boolean timiteExpiryTimer = true;

@Expose
@ConfigOption(name = "Timite Tracker", desc = "Tracks collected Timite ores and shows mote profit")
@ConfigEditorBoolean
public boolean timiteTracker = false;

@Expose
@ConfigLink(owner = TimiteConfig.class, field = "timiteTimer")
public Position timerPos = new Position(421, -220, false, true);

@Expose
@ConfigLink(owner = TimiteConfig.class, field = "timiteTracker")
public Position trackerPos = new Position(-201, -220, false, true);
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@
import at.hannibal2.skyhanni.features.mining.powdertracker.PowderTracker;
import at.hannibal2.skyhanni.features.misc.DraconicSacrificeTracker;
import at.hannibal2.skyhanni.features.misc.trevor.TrevorTracker;
import at.hannibal2.skyhanni.features.rift.area.mountaintop.TimiteHelper;
import at.hannibal2.skyhanni.features.rift.area.mountaintop.TimiteTracker;
import at.hannibal2.skyhanni.features.rift.area.westvillage.VerminTracker;
import at.hannibal2.skyhanni.features.rift.area.westvillage.kloon.KloonTerminal;
import at.hannibal2.skyhanni.features.skillprogress.SkillType;
Expand Down Expand Up @@ -885,4 +887,7 @@ public int hashCode() {
);
}
}

@Expose
public TimiteTracker.Data timiteHelperTracker = new TimiteTracker.Data();
}
5 changes: 5 additions & 0 deletions src/main/java/at/hannibal2/skyhanni/features/rift/RiftAPI.kt
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,9 @@ object RiftAPI {
fun inStillgoreChateau() = LorenzUtils.skyBlockArea.let { it == "Stillgore Château" || it == "Oubliette" }
fun inDreadfarm() = LorenzUtils.skyBlockArea == "Dreadfarm"
fun inWestVillage() = LorenzUtils.skyBlockArea.let { it == "West Village" || it == "Infested House" }
fun inMountainTop() = when (LorenzUtils.skyBlockArea) {
"Continuum", "The Mountaintop", "Trial Grounds", "Time-Torn Isles",
"Wizardman Bureau", "Wizard Brawl", "Walk of Fame", "Time Chamber" -> true
else -> false
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
package at.hannibal2.skyhanni.features.rift.area.mountaintop

import at.hannibal2.skyhanni.SkyHanniMod
import at.hannibal2.skyhanni.api.event.HandleEvent
import at.hannibal2.skyhanni.data.ClickType
import at.hannibal2.skyhanni.events.BlockClickEvent
import at.hannibal2.skyhanni.events.GuiRenderEvent
import at.hannibal2.skyhanni.events.LorenzRenderWorldEvent
import at.hannibal2.skyhanni.events.LorenzWorldChangeEvent
import at.hannibal2.skyhanni.events.SecondPassedEvent
import at.hannibal2.skyhanni.features.rift.RiftAPI
import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule
import at.hannibal2.skyhanni.utils.BlockUtils.getBlockAt
import at.hannibal2.skyhanni.utils.BlockUtils.getBlockStateAt
import at.hannibal2.skyhanni.utils.InventoryUtils
import at.hannibal2.skyhanni.utils.LocationUtils
import at.hannibal2.skyhanni.utils.LocationUtils.distanceToPlayer
import at.hannibal2.skyhanni.utils.LorenzVec
import at.hannibal2.skyhanni.utils.NEUInternalName.Companion.toInternalName
import at.hannibal2.skyhanni.utils.RenderUtils.drawDynamicText
import at.hannibal2.skyhanni.utils.RenderUtils.renderString
import at.hannibal2.skyhanni.utils.SimpleTimeMark
import at.hannibal2.skyhanni.utils.TimeUtils.format
import at.hannibal2.skyhanni.utils.toLorenzVec
import net.minecraft.block.BlockStainedGlassPane
import net.minecraft.block.state.IBlockState
import net.minecraft.init.Blocks
import net.minecraft.item.EnumDyeColor
import net.minecraft.util.BlockPos
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.Duration.Companion.seconds

@SkyHanniModule
object TimiteHelper {

private val TIME_GUN = "TIME_GUN".toInternalName()
private var holdingClick = SimpleTimeMark.farPast()
private var lastClick = SimpleTimeMark.farPast()
private val config get() = SkyHanniMod.feature.rift.area.mountaintop.timite
private var currentPos: LorenzVec? = null
private var currentBlockState: IBlockState? = null
private var doubleTimeShooting = false

@HandleEvent
fun onBlockHit(event: BlockClickEvent) {
if (!isEnabled()) return
if (InventoryUtils.itemInHandId != TIME_GUN) return
if (event.clickType != ClickType.RIGHT_CLICK) return
if (event.position != currentPos || currentBlockState != event.getBlockState) {
lastClick = SimpleTimeMark.farPast()

if (event.position == currentPos && currentBlockState != event.getBlockState) {
timiteLocations[event.position] = SimpleTimeMark.now()
doubleTimeShooting = true
} else {
doubleTimeShooting = false
}
}
currentPos = event.position
currentBlockState = event.getBlockState
if (event.getBlockState.block != Blocks.stained_glass_pane) return
val color = event.getBlockState.getValue(BlockStainedGlassPane.COLOR)
if (color != EnumDyeColor.BLUE && color != EnumDyeColor.LIGHT_BLUE) return
if (lastClick + 300.milliseconds > SimpleTimeMark.now()) {
lastClick = SimpleTimeMark.now()
return
}
lastClick = SimpleTimeMark.now()
holdingClick = SimpleTimeMark.now()
}

@SubscribeEvent
fun onGuiRender(event: GuiRenderEvent.GuiOverlayRenderEvent) {
if (!isEnabled()) return
if (InventoryUtils.itemInHandId != TIME_GUN) return
if (lastClick + 400.milliseconds < SimpleTimeMark.now()) {
holdingClick = SimpleTimeMark.farPast()
doubleTimeShooting = false
}
if (holdingClick.isFarPast()) return

if ((currentBlockState?.block ?: return) != Blocks.stained_glass_pane) return
// this works for me but idk if ive just tuned it for my ping only
val time = if (doubleTimeShooting) 1800 else 2000
val timeLeft = holdingClick + time.milliseconds
if (!timeLeft.isInPast()) {
val formattedTime = timeLeft.timeUntil().format(showMilliSeconds = true)
config.timerPos.renderString("§b$formattedTime", 0, 0, "Timite Helper")
}
}

private val timiteLocations = mutableMapOf<LorenzVec, SimpleTimeMark>()

@SubscribeEvent
fun onSecondPassed(event: SecondPassedEvent) {
val location = LocationUtils.playerLocation()
val from = location.add(-15, -15, -15).toBlockPos()
val to = location.add(15, 15, 15).toBlockPos()

for (pos in BlockPos.getAllInBox(from, to)) {
val loc = pos.toLorenzVec()
if (loc.getBlockAt() == Blocks.stained_glass_pane && loc.distanceToPlayer() <= 15) {
val color = loc.getBlockStateAt().getValue(BlockStainedGlassPane.COLOR)
if (color != EnumDyeColor.BLUE && color != EnumDyeColor.LIGHT_BLUE) continue
if (timiteLocations[loc] == null) timiteLocations[loc] = SimpleTimeMark.now()
}
}
val iterator = timiteLocations.entries.iterator()
while (iterator.hasNext()) {
val entry = iterator.next()
if (entry.key.getBlockAt() == Blocks.air) {
iterator.remove()
} else if (entry.key.getBlockAt() == Blocks.stained_glass_pane) {
val color = entry.key.getBlockStateAt().getValue(BlockStainedGlassPane.COLOR)
if (color == EnumDyeColor.LIGHT_BLUE) {
iterator.remove()
}
}
}


}

@SubscribeEvent
fun onBlockRender(event: LorenzRenderWorldEvent) {
if (!RiftAPI.inMountainTop() || !config.timiteExpiryTimer) return

for (timiteLocation in timiteLocations.entries) {
val timeLeft = timiteLocation.value + 31.seconds
if (timeLeft.timeUntil() < 6.seconds) {
event.drawDynamicText(timiteLocation.key, "§c${timeLeft.timeUntil().format()}", 1.5)
}
}
}

@SubscribeEvent
fun onWorldChange(event: LorenzWorldChangeEvent) = timiteLocations.clear()


private fun isEnabled() = RiftAPI.inMountainTop() && config.timiteTimer

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
package at.hannibal2.skyhanni.features.rift.area.mountaintop

import at.hannibal2.skyhanni.SkyHanniMod
import at.hannibal2.skyhanni.api.event.HandleEvent
import at.hannibal2.skyhanni.config.commands.CommandCategory
import at.hannibal2.skyhanni.config.commands.CommandRegistrationEvent
import at.hannibal2.skyhanni.data.ItemAddManager
import at.hannibal2.skyhanni.events.GuiRenderEvent
import at.hannibal2.skyhanni.events.ItemAddEvent
import at.hannibal2.skyhanni.features.rift.RiftAPI
import at.hannibal2.skyhanni.features.rift.RiftAPI.motesNpcPrice
import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule
import at.hannibal2.skyhanni.utils.CollectionUtils.addSearchString
import at.hannibal2.skyhanni.utils.ItemUtils
import at.hannibal2.skyhanni.utils.NEUInternalName
import at.hannibal2.skyhanni.utils.NEUInternalName.Companion.toInternalName
import at.hannibal2.skyhanni.utils.NEUItems
import at.hannibal2.skyhanni.utils.NEUItems.getItemStack
import at.hannibal2.skyhanni.utils.NumberUtil.shortFormat
import at.hannibal2.skyhanni.utils.TimeUtils.format
import at.hannibal2.skyhanni.utils.renderables.Renderable
import at.hannibal2.skyhanni.utils.renderables.Searchable
import at.hannibal2.skyhanni.utils.renderables.toSearchable
import at.hannibal2.skyhanni.utils.tracker.ItemTrackerData
import at.hannibal2.skyhanni.utils.tracker.SkyHanniItemTracker
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
import kotlin.time.Duration.Companion.seconds

@SkyHanniModule
object TimiteTracker {

private val config get() = SkyHanniMod.feature.rift.area.mountaintop.timite
private val HIGHLITE = "HIGHLITE".toInternalName()


class Data : ItemTrackerData() {
override fun resetItems() {
"detekt ur a stupid fucker"
}

override fun getDescription(timesGained: Long): List<String> {
return emptyList()
}

override fun getCoinName(item: TrackedItem): String {
return "§5Motes"
}

override fun getCoinDescription(item: TrackedItem): List<String> {
return emptyList()
}

override fun getCustomPricePer(internalName: NEUInternalName): Double {
return internalName.getItemStack().motesNpcPrice() ?: 0.0
}

fun getTime(): Int {
this.items["TIMITE".toInternalName()]?.let {
return it.totalAmount.toInt() * 2
}
return 0
}

}

private fun drawDisplay(data: Data): List<Searchable> = buildList {
addSearchString("§9§lTimite Tracker")
val profit = tracker.drawItems(data, { true }, this)


val highliteRecipe = NEUItems.getRecipes(HIGHLITE).singleOrNull()
if (highliteRecipe != null) {
var craftableAmount = 0

for (neededItem in ItemUtils.neededItems(highliteRecipe)) {
if (neededItem.key in validItems) {
data.items[neededItem.key]?.let {
val amountCanCraft = it.totalAmount.toInt() / neededItem.value
if (craftableAmount == 0 || amountCanCraft < craftableAmount) {
craftableAmount = amountCanCraft
}
}
}
}
val stack = HIGHLITE.getItemStack()
val motes = stack.motesNpcPrice()?.times(craftableAmount)?.shortFormat() ?: "0"
if (craftableAmount > 0) {
add(
Renderable.string(
" §7${craftableAmount.shortFormat()}x ${stack.displayName} Craftable§7: §5$motes motes"
).toSearchable()
)
}
}

add(Renderable.string("§aTime§7: §a${data.getTime().seconds.format()}ф").toSearchable())


add(
Renderable.string(
"§dTotal Profit§7: §5${profit.toInt().shortFormat()} Motes"
).toSearchable()
)

}

private val tracker =
SkyHanniItemTracker("Timite Tracker", { Data() }, { it.timiteHelperTracker }) {
drawDisplay(it)
}

private val validItems = listOf(
"TIMITE".toInternalName(),
"YOUNGITE".toInternalName(),
"OBSOLITE".toInternalName(),
)

@HandleEvent
fun onItem(event: ItemAddEvent) {

if (validItems.contains(event.internalName)) {
tracker.addItem(event.internalName, event.amount, event.source == ItemAddManager.Source.COMMAND)
}
}

@SubscribeEvent
fun onRender(event: GuiRenderEvent) {
if (!isEnabled()) return

tracker.renderDisplay(config.trackerPos)
}

@HandleEvent
fun onCommandRegistration(event: CommandRegistrationEvent) {
event.register("shresettimitetracker") {
description = "Resets the Timite Tracker."
category = CommandCategory.USERS_RESET
callback { tracker.resetCommand() }
}
}

private fun isEnabled() = RiftAPI.inMountainTop() && config.timiteTracker

}
Loading