aboutsummaryrefslogtreecommitdiff
path: root/src/main/kotlin/moe/nea/notenoughupdates/features
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/kotlin/moe/nea/notenoughupdates/features')
-rw-r--r--src/main/kotlin/moe/nea/notenoughupdates/features/FeatureManager.kt27
-rw-r--r--src/main/kotlin/moe/nea/notenoughupdates/features/world/FairySouls.kt93
2 files changed, 113 insertions, 7 deletions
diff --git a/src/main/kotlin/moe/nea/notenoughupdates/features/FeatureManager.kt b/src/main/kotlin/moe/nea/notenoughupdates/features/FeatureManager.kt
index 766cf1f..0ffaad5 100644
--- a/src/main/kotlin/moe/nea/notenoughupdates/features/FeatureManager.kt
+++ b/src/main/kotlin/moe/nea/notenoughupdates/features/FeatureManager.kt
@@ -1,27 +1,42 @@
package moe.nea.notenoughupdates.features
+import kotlinx.serialization.Serializable
import kotlinx.serialization.serializer
import moe.nea.notenoughupdates.NotEnoughUpdates
import moe.nea.notenoughupdates.features.world.FairySouls
-import moe.nea.notenoughupdates.util.ConfigHolder
+import moe.nea.notenoughupdates.util.config.ConfigHolder
object FeatureManager : ConfigHolder<FeatureManager.Config>(serializer(), "features", ::Config) {
+ @Serializable
data class Config(
val enabledFeatures: MutableMap<String, Boolean> = mutableMapOf()
)
private val features = mutableMapOf<String, NEUFeature>()
+ private var hasAutoloaded = false
+
+ init {
+ autoload()
+ }
+
fun autoload() {
- loadFeature(FairySouls)
+ synchronized(this) {
+ if (hasAutoloaded) return
+ loadFeature(FairySouls)
+ hasAutoloaded = true
+ }
}
fun loadFeature(feature: NEUFeature) {
- if (feature.identifier in features) {
- NotEnoughUpdates.logger.error("Double registering feature ${feature.identifier}. Ignoring second instance $feature")
- return
+ synchronized(features) {
+ if (feature.identifier in features) {
+ NotEnoughUpdates.logger.error("Double registering feature ${feature.identifier}. Ignoring second instance $feature")
+ return
+ }
+ features[feature.identifier] = feature
+ feature.onLoad()
}
- features[feature.identifier] = feature
}
fun isEnabled(identifier: String): Boolean? =
diff --git a/src/main/kotlin/moe/nea/notenoughupdates/features/world/FairySouls.kt b/src/main/kotlin/moe/nea/notenoughupdates/features/world/FairySouls.kt
index b928f3d..9bd1a1f 100644
--- a/src/main/kotlin/moe/nea/notenoughupdates/features/world/FairySouls.kt
+++ b/src/main/kotlin/moe/nea/notenoughupdates/features/world/FairySouls.kt
@@ -1,12 +1,103 @@
package moe.nea.notenoughupdates.features.world
+import io.github.moulberry.repo.data.Coordinate
+import kotlinx.serialization.Serializable
+import kotlinx.serialization.serializer
+import net.minecraft.util.math.BlockPos
+import moe.nea.notenoughupdates.events.ServerChatLineReceivedEvent
+import moe.nea.notenoughupdates.events.SkyblockServerUpdateEvent
+import moe.nea.notenoughupdates.events.WorldRenderLastEvent
import moe.nea.notenoughupdates.features.NEUFeature
+import moe.nea.notenoughupdates.repo.RepoManager
+import moe.nea.notenoughupdates.util.MC
+import moe.nea.notenoughupdates.util.SBData
+import moe.nea.notenoughupdates.util.config.ProfileSpecificConfigHolder
+import moe.nea.notenoughupdates.util.render.RenderBlockContext.Companion.renderBlocks
+import moe.nea.notenoughupdates.util.unformattedString
+
+val Coordinate.blockPos: BlockPos
+ get() = BlockPos(x, y, z)
+
+object FairySouls : NEUFeature,
+ ProfileSpecificConfigHolder<FairySouls.Config>(serializer(), "fairy-souls.json", ::Config) {
+ @Serializable
+ data class Config(
+ val foundSouls: MutableMap<String, MutableSet<Int>> = mutableMapOf()
+ )
-object FairySouls : NEUFeature {
override val name: String get() = "Fairy Souls"
override val identifier: String get() = "fairy-souls"
+ val playerReach = 5
+ val playerReachSquared = playerReach * playerReach
+
+ var currentLocationName: String? = null
+ var currentLocationSouls: List<Coordinate> = emptyList()
+ var currentMissingSouls: List<Coordinate> = emptyList()
+
+ fun updateMissingSouls() {
+ currentMissingSouls = emptyList()
+ val c = config ?: return
+ val fi = c.foundSouls[currentLocationName] ?: setOf()
+ val cms = currentLocationSouls.toMutableList()
+ fi.asSequence().sortedDescending().filter { it in cms.indices }.forEach { cms.removeAt(it) }
+ currentMissingSouls = cms
+ }
+
+ fun updateWorldSouls() {
+ currentLocationSouls = emptyList()
+ val loc = currentLocationName ?: return
+ currentLocationSouls = RepoManager.neuRepo.constants.fairySouls.soulLocations[loc] ?: return
+ }
+
+ fun findNearestClickableSoul(): Coordinate? {
+ val player = MC.player ?: return null
+ val pos = player.pos
+ val location = SBData.skyblockLocation ?: return null
+ val soulLocations: List<Coordinate> =
+ RepoManager.neuRepo.constants.fairySouls.soulLocations[location] ?: return null
+ return soulLocations
+ .map { it to it.blockPos.getSquaredDistance(pos) }
+ .filter { it.second < playerReachSquared }
+ .minByOrNull { it.second }
+ ?.first
+ }
+
+ private fun markNearestSoul() {
+ val nearestSoul = findNearestClickableSoul() ?: return
+ val c = config ?: return
+ val loc = currentLocationName ?: return
+ val idx = currentLocationSouls.indexOf(nearestSoul)
+ c.foundSouls.computeIfAbsent(loc) { mutableSetOf() }.add(idx)
+ markDirty()
+ updateMissingSouls()
+ }
+
+
override fun onLoad() {
+ SkyblockServerUpdateEvent.subscribe {
+ currentLocationName = it.newLocraw?.skyblockLocation
+ updateWorldSouls()
+ updateMissingSouls()
+ }
+ ServerChatLineReceivedEvent.subscribe {
+ when (it.text.unformattedString) {
+ "You have already found that Fairy Soul!" -> {
+ markNearestSoul()
+ }
+ "SOUL! You found a Fairy Soul!" -> {
+ markNearestSoul()
+ }
+ }
+ }
+ WorldRenderLastEvent.subscribe {
+ renderBlocks(it.camera) {
+ color(1F, 1F, 0F, 0.8F)
+ currentMissingSouls.forEach {
+ block(it.blockPos)
+ }
+ }
+ }
}
}