diff options
Diffstat (limited to 'src/main/kotlin/moe/nea/notenoughupdates/features')
-rw-r--r-- | src/main/kotlin/moe/nea/notenoughupdates/features/FeatureManager.kt | 27 | ||||
-rw-r--r-- | src/main/kotlin/moe/nea/notenoughupdates/features/world/FairySouls.kt | 93 |
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) + } + } + } } } |