Refactor source layout
Introduce compat source sets and move all kotlin sources to the main directory [no changelog]
This commit is contained in:
131
src/main/kotlin/features/diana/AncestralSpadeSolver.kt
Normal file
131
src/main/kotlin/features/diana/AncestralSpadeSolver.kt
Normal file
@@ -0,0 +1,131 @@
|
||||
|
||||
package moe.nea.firmament.features.diana
|
||||
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
import net.minecraft.particle.ParticleTypes
|
||||
import net.minecraft.sound.SoundEvents
|
||||
import net.minecraft.util.math.Vec3d
|
||||
import moe.nea.firmament.annotations.Subscribe
|
||||
import moe.nea.firmament.events.ParticleSpawnEvent
|
||||
import moe.nea.firmament.events.SoundReceiveEvent
|
||||
import moe.nea.firmament.events.WorldKeyboardEvent
|
||||
import moe.nea.firmament.events.WorldReadyEvent
|
||||
import moe.nea.firmament.events.WorldRenderLastEvent
|
||||
import moe.nea.firmament.events.subscription.SubscriptionOwner
|
||||
import moe.nea.firmament.features.FirmamentFeature
|
||||
import moe.nea.firmament.util.MC
|
||||
import moe.nea.firmament.util.SBData
|
||||
import moe.nea.firmament.util.SkyBlockIsland
|
||||
import moe.nea.firmament.util.SkyblockId
|
||||
import moe.nea.firmament.util.TimeMark
|
||||
import moe.nea.firmament.util.WarpUtil
|
||||
import moe.nea.firmament.util.render.RenderInWorldContext
|
||||
import moe.nea.firmament.util.skyBlockId
|
||||
|
||||
object AncestralSpadeSolver : SubscriptionOwner {
|
||||
var lastDing = TimeMark.farPast()
|
||||
private set
|
||||
private val pitches = mutableListOf<Float>()
|
||||
val particlePositions = mutableListOf<Vec3d>()
|
||||
var nextGuess: Vec3d? = null
|
||||
private set
|
||||
|
||||
val ancestralSpadeId = SkyblockId("ANCESTRAL_SPADE")
|
||||
private var lastTeleportAttempt = TimeMark.farPast()
|
||||
|
||||
fun isEnabled() =
|
||||
DianaWaypoints.TConfig.ancestralSpadeSolver
|
||||
&& SBData.skyblockLocation == SkyBlockIsland.HUB
|
||||
&& MC.player?.inventory?.containsAny { it.skyBlockId == ancestralSpadeId } == true // TODO: add a reactive property here
|
||||
|
||||
@Subscribe
|
||||
fun onKeyBind(event: WorldKeyboardEvent) {
|
||||
if (!isEnabled()) return
|
||||
if (!event.matches(DianaWaypoints.TConfig.ancestralSpadeTeleport)) return
|
||||
|
||||
if (lastTeleportAttempt.passedTime() < 3.seconds) return
|
||||
WarpUtil.teleportToNearestWarp(SkyBlockIsland.HUB, nextGuess ?: return)
|
||||
lastTeleportAttempt = TimeMark.now()
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
fun onParticleSpawn(event: ParticleSpawnEvent) {
|
||||
if (!isEnabled()) return
|
||||
if (event.particleEffect != ParticleTypes.DRIPPING_LAVA) return
|
||||
if (event.offset.x != 0.0F || event.offset.y != 0F || event.offset.z != 0F)
|
||||
return
|
||||
particlePositions.add(event.position)
|
||||
if (particlePositions.size > 20) {
|
||||
particlePositions.removeFirst()
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
fun onPlaySound(event: SoundReceiveEvent) {
|
||||
if (!isEnabled()) return
|
||||
if (!SoundEvents.BLOCK_NOTE_BLOCK_HARP.matchesId(event.sound.value().id)) return
|
||||
|
||||
if (lastDing.passedTime() > 1.seconds) {
|
||||
particlePositions.clear()
|
||||
pitches.clear()
|
||||
}
|
||||
lastDing = TimeMark.now()
|
||||
|
||||
pitches.add(event.pitch)
|
||||
if (pitches.size > 20) {
|
||||
pitches.removeFirst()
|
||||
}
|
||||
|
||||
if (particlePositions.size < 3) {
|
||||
return
|
||||
}
|
||||
|
||||
val averagePitchDelta =
|
||||
if (pitches.isEmpty()) return
|
||||
else pitches
|
||||
.zipWithNext { a, b -> b - a }
|
||||
.average()
|
||||
|
||||
val soundDistanceEstimate = (Math.E / averagePitchDelta) - particlePositions.first().distanceTo(event.position)
|
||||
|
||||
if (soundDistanceEstimate > 1000) {
|
||||
return
|
||||
}
|
||||
|
||||
val lastParticleDirection = particlePositions
|
||||
.takeLast(3)
|
||||
.let { (a, _, b) -> b.subtract(a) }
|
||||
.normalize()
|
||||
|
||||
nextGuess = event.position.add(lastParticleDirection.multiply(soundDistanceEstimate))
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
fun onWorldRender(event: WorldRenderLastEvent) {
|
||||
if (!isEnabled()) return
|
||||
RenderInWorldContext.renderInWorld(event) {
|
||||
nextGuess?.let {
|
||||
color(1f, 1f, 0f, 0.5f)
|
||||
tinyBlock(it, 1f)
|
||||
color(1f, 1f, 0f, 1f)
|
||||
tracer(it, lineWidth = 3f)
|
||||
}
|
||||
if (particlePositions.size > 2 && lastDing.passedTime() < 10.seconds && nextGuess != null) {
|
||||
color(0f, 1f, 0f, 0.7f)
|
||||
line(particlePositions)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
fun onSwapWorld(event: WorldReadyEvent) {
|
||||
nextGuess = null
|
||||
particlePositions.clear()
|
||||
pitches.clear()
|
||||
lastDing = TimeMark.farPast()
|
||||
}
|
||||
|
||||
override val delegateFeature: FirmamentFeature
|
||||
get() = DianaWaypoints
|
||||
|
||||
}
|
||||
35
src/main/kotlin/features/diana/DianaWaypoints.kt
Normal file
35
src/main/kotlin/features/diana/DianaWaypoints.kt
Normal file
@@ -0,0 +1,35 @@
|
||||
|
||||
package moe.nea.firmament.features.diana
|
||||
|
||||
import moe.nea.firmament.events.AttackBlockEvent
|
||||
import moe.nea.firmament.events.ParticleSpawnEvent
|
||||
import moe.nea.firmament.events.ProcessChatEvent
|
||||
import moe.nea.firmament.events.SoundReceiveEvent
|
||||
import moe.nea.firmament.events.UseBlockEvent
|
||||
import moe.nea.firmament.events.WorldKeyboardEvent
|
||||
import moe.nea.firmament.events.WorldReadyEvent
|
||||
import moe.nea.firmament.events.WorldRenderLastEvent
|
||||
import moe.nea.firmament.features.FirmamentFeature
|
||||
import moe.nea.firmament.gui.config.ManagedConfig
|
||||
|
||||
object DianaWaypoints : FirmamentFeature {
|
||||
override val identifier get() = "diana"
|
||||
override val config get() = TConfig
|
||||
|
||||
object TConfig : ManagedConfig(identifier) {
|
||||
val ancestralSpadeSolver by toggle("ancestral-spade") { true }
|
||||
val ancestralSpadeTeleport by keyBindingWithDefaultUnbound("ancestral-teleport")
|
||||
val nearbyWaypoints by toggle("nearby-waypoints") { true }
|
||||
}
|
||||
|
||||
override fun onLoad() {
|
||||
UseBlockEvent.subscribe {
|
||||
NearbyBurrowsSolver.onBlockClick(it.hitResult.blockPos)
|
||||
}
|
||||
AttackBlockEvent.subscribe {
|
||||
NearbyBurrowsSolver.onBlockClick(it.blockPos)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
144
src/main/kotlin/features/diana/NearbyBurrowsSolver.kt
Normal file
144
src/main/kotlin/features/diana/NearbyBurrowsSolver.kt
Normal file
@@ -0,0 +1,144 @@
|
||||
|
||||
package moe.nea.firmament.features.diana
|
||||
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
import net.minecraft.particle.ParticleTypes
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.util.math.MathHelper
|
||||
import net.minecraft.util.math.Position
|
||||
import moe.nea.firmament.annotations.Subscribe
|
||||
import moe.nea.firmament.events.ParticleSpawnEvent
|
||||
import moe.nea.firmament.events.ProcessChatEvent
|
||||
import moe.nea.firmament.events.WorldReadyEvent
|
||||
import moe.nea.firmament.events.WorldRenderLastEvent
|
||||
import moe.nea.firmament.events.subscription.SubscriptionOwner
|
||||
import moe.nea.firmament.features.FirmamentFeature
|
||||
import moe.nea.firmament.util.TimeMark
|
||||
import moe.nea.firmament.util.mutableMapWithMaxSize
|
||||
import moe.nea.firmament.util.render.RenderInWorldContext.Companion.renderInWorld
|
||||
|
||||
object NearbyBurrowsSolver : SubscriptionOwner {
|
||||
|
||||
|
||||
private val recentlyDugBurrows: MutableMap<BlockPos, TimeMark> = mutableMapWithMaxSize(20)
|
||||
private val recentEnchantParticles: MutableMap<BlockPos, TimeMark> = mutableMapWithMaxSize(500)
|
||||
private var lastBlockClick: BlockPos? = null
|
||||
|
||||
enum class BurrowType {
|
||||
START, MOB, TREASURE
|
||||
}
|
||||
|
||||
val burrows = mutableMapOf<BlockPos, BurrowType>()
|
||||
|
||||
@Subscribe
|
||||
fun onChatEvent(event: ProcessChatEvent) {
|
||||
val lastClickedBurrow = lastBlockClick ?: return
|
||||
if (event.unformattedString.startsWith("You dug out a Griffin Burrow!") ||
|
||||
event.unformattedString.startsWith(" ☠ You were killed by") ||
|
||||
event.unformattedString.startsWith("You finished the Griffin burrow chain!")
|
||||
) {
|
||||
markAsDug(lastClickedBurrow)
|
||||
burrows.remove(lastClickedBurrow)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun wasRecentlyDug(blockPos: BlockPos): Boolean {
|
||||
val lastDigTime = recentlyDugBurrows[blockPos] ?: TimeMark.farPast()
|
||||
return lastDigTime.passedTime() < 10.seconds
|
||||
}
|
||||
|
||||
fun markAsDug(blockPos: BlockPos) {
|
||||
recentlyDugBurrows[blockPos] = TimeMark.now()
|
||||
}
|
||||
|
||||
fun wasRecentlyEnchanted(blockPos: BlockPos): Boolean {
|
||||
val lastEnchantTime = recentEnchantParticles[blockPos] ?: TimeMark.farPast()
|
||||
return lastEnchantTime.passedTime() < 4.seconds
|
||||
}
|
||||
|
||||
fun markAsEnchanted(blockPos: BlockPos) {
|
||||
recentEnchantParticles[blockPos] = TimeMark.now()
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
fun onParticles(event: ParticleSpawnEvent) {
|
||||
if (!DianaWaypoints.TConfig.nearbyWaypoints) return
|
||||
|
||||
val position: BlockPos = event.position.toBlockPos().down()
|
||||
|
||||
if (wasRecentlyDug(position)) return
|
||||
|
||||
val isEven50Spread = (event.offset.x == 0.5f && event.offset.z == 0.5f)
|
||||
|
||||
if (event.particleEffect.type == ParticleTypes.ENCHANT) {
|
||||
if (event.count == 5 && event.speed == 0.05F && event.offset.y == 0.4F && isEven50Spread) {
|
||||
markAsEnchanted(position)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if (!wasRecentlyEnchanted(position)) return
|
||||
|
||||
if (event.particleEffect.type == ParticleTypes.ENCHANTED_HIT
|
||||
&& event.count == 4
|
||||
&& event.speed == 0.01F
|
||||
&& event.offset.y == 0.1f
|
||||
&& isEven50Spread
|
||||
) {
|
||||
burrows[position] = BurrowType.START
|
||||
}
|
||||
if (event.particleEffect.type == ParticleTypes.CRIT
|
||||
&& event.count == 3
|
||||
&& event.speed == 0.01F
|
||||
&& event.offset.y == 0.1F
|
||||
&& isEven50Spread
|
||||
) {
|
||||
burrows[position] = BurrowType.MOB
|
||||
}
|
||||
if (event.particleEffect.type == ParticleTypes.DRIPPING_LAVA
|
||||
&& event.count == 2
|
||||
&& event.speed == 0.01F
|
||||
&& event.offset.y == 0.1F
|
||||
&& event.offset.x == 0.35F && event.offset.z == 0.35f
|
||||
) {
|
||||
burrows[position] = BurrowType.TREASURE
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
fun onRender(event: WorldRenderLastEvent) {
|
||||
if (!DianaWaypoints.TConfig.nearbyWaypoints) return
|
||||
renderInWorld(event) {
|
||||
for ((location, burrow) in burrows) {
|
||||
when (burrow) {
|
||||
BurrowType.START -> color(.2f, .8f, .2f, 0.4f)
|
||||
BurrowType.MOB -> color(0.3f, 0.4f, 0.9f, 0.4f)
|
||||
BurrowType.TREASURE -> color(1f, 0.7f, 0.2f, 0.4f)
|
||||
}
|
||||
block(location)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
fun onSwapWorld(worldReadyEvent: WorldReadyEvent) {
|
||||
burrows.clear()
|
||||
recentEnchantParticles.clear()
|
||||
recentlyDugBurrows.clear()
|
||||
lastBlockClick = null
|
||||
}
|
||||
|
||||
fun onBlockClick(blockPos: BlockPos) {
|
||||
if (!DianaWaypoints.TConfig.nearbyWaypoints) return
|
||||
burrows.remove(blockPos)
|
||||
lastBlockClick = blockPos
|
||||
}
|
||||
|
||||
override val delegateFeature: FirmamentFeature
|
||||
get() = DianaWaypoints
|
||||
}
|
||||
|
||||
fun Position.toBlockPos(): BlockPos {
|
||||
return BlockPos(MathHelper.floor(x), MathHelper.floor(y), MathHelper.floor(z))
|
||||
}
|
||||
Reference in New Issue
Block a user