Add Nearby Burrow Highlighter
This commit is contained in:
@@ -13,6 +13,7 @@ import moe.nea.firmament.events.ParticleSpawnEvent;
|
||||
import net.minecraft.client.network.ClientPlayNetworkHandler;
|
||||
import net.minecraft.network.packet.s2c.play.ParticleS2CPacket;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import org.joml.Vector3f;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
@@ -33,9 +34,10 @@ public abstract class IncomingPacketListenerPatches {
|
||||
var event = new ParticleSpawnEvent(
|
||||
packet.getParameters(),
|
||||
new Vec3d(packet.getX(), packet.getY(), packet.getZ()),
|
||||
new Vec3d(packet.getOffsetX(), packet.getOffsetY(), packet.getOffsetZ()),
|
||||
new Vector3f(packet.getOffsetX(), packet.getOffsetY(), packet.getOffsetZ()),
|
||||
packet.isLongDistance(),
|
||||
packet.getCount()
|
||||
packet.getCount(),
|
||||
packet.getSpeed()
|
||||
);
|
||||
ParticleSpawnEvent.Companion.publish(event);
|
||||
if (event.getCancelled())
|
||||
|
||||
@@ -45,7 +45,7 @@ import moe.nea.firmament.events.CommandEvent
|
||||
import moe.nea.firmament.events.ItemTooltipEvent
|
||||
import moe.nea.firmament.events.ScreenRenderPostEvent
|
||||
import moe.nea.firmament.events.TickEvent
|
||||
import moe.nea.firmament.events.registration.registerFirmamentChatEvents
|
||||
import moe.nea.firmament.events.registration.registerFirmamentEvents
|
||||
import moe.nea.firmament.features.FeatureManager
|
||||
import moe.nea.firmament.repo.HypixelStaticData
|
||||
import moe.nea.firmament.repo.RepoManager
|
||||
@@ -139,7 +139,7 @@ object Firmament {
|
||||
globalJob.cancel()
|
||||
}
|
||||
})
|
||||
registerFirmamentChatEvents()
|
||||
registerFirmamentEvents()
|
||||
ItemTooltipCallback.EVENT.register { a, b, c ->
|
||||
ItemTooltipEvent.publish(ItemTooltipEvent(a, b, c))
|
||||
}
|
||||
|
||||
23
src/main/kotlin/moe/nea/firmament/events/AttackBlockEvent.kt
Normal file
23
src/main/kotlin/moe/nea/firmament/events/AttackBlockEvent.kt
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Linnea Gräf <nea@nea.moe>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
package moe.nea.firmament.events
|
||||
|
||||
import net.minecraft.entity.player.PlayerEntity
|
||||
import net.minecraft.util.Hand
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.util.math.Direction
|
||||
import net.minecraft.world.World
|
||||
|
||||
data class AttackBlockEvent(
|
||||
val player: PlayerEntity,
|
||||
val world: World,
|
||||
val hand: Hand,
|
||||
val blockPos: BlockPos,
|
||||
val direction: Direction
|
||||
) : FirmamentEvent.Cancellable() {
|
||||
companion object : FirmamentEventBus<AttackBlockEvent>()
|
||||
}
|
||||
@@ -6,15 +6,17 @@
|
||||
|
||||
package moe.nea.firmament.events
|
||||
|
||||
import org.joml.Vector3f
|
||||
import net.minecraft.particle.ParticleEffect
|
||||
import net.minecraft.util.math.Vec3d
|
||||
|
||||
data class ParticleSpawnEvent(
|
||||
val particleEffect: ParticleEffect,
|
||||
val position: Vec3d,
|
||||
val offset: Vec3d,
|
||||
val offset: Vector3f,
|
||||
val longDistance: Boolean,
|
||||
val count: Int,
|
||||
val speed: Float,
|
||||
) : FirmamentEvent.Cancellable() {
|
||||
companion object : FirmamentEventBus<ParticleSpawnEvent>()
|
||||
}
|
||||
|
||||
16
src/main/kotlin/moe/nea/firmament/events/UseBlockEvent.kt
Normal file
16
src/main/kotlin/moe/nea/firmament/events/UseBlockEvent.kt
Normal file
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Linnea Gräf <nea@nea.moe>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
package moe.nea.firmament.events
|
||||
|
||||
import net.minecraft.entity.player.PlayerEntity
|
||||
import net.minecraft.util.Hand
|
||||
import net.minecraft.util.hit.BlockHitResult
|
||||
import net.minecraft.world.World
|
||||
|
||||
data class UseBlockEvent(val player: PlayerEntity, val world: World, val hand: Hand, val hitResult: BlockHitResult) : FirmamentEvent.Cancellable() {
|
||||
companion object : FirmamentEventBus<UseBlockEvent>()
|
||||
}
|
||||
@@ -6,24 +6,29 @@
|
||||
|
||||
package moe.nea.firmament.events.registration
|
||||
|
||||
import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents
|
||||
import net.fabricmc.fabric.api.event.player.AttackBlockCallback
|
||||
import net.fabricmc.fabric.api.event.player.UseBlockCallback
|
||||
import net.minecraft.text.Text
|
||||
import net.minecraft.util.ActionResult
|
||||
import moe.nea.firmament.events.AllowChatEvent
|
||||
import moe.nea.firmament.events.AttackBlockEvent
|
||||
import moe.nea.firmament.events.ModifyChatEvent
|
||||
import moe.nea.firmament.events.ProcessChatEvent
|
||||
import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents
|
||||
import net.minecraft.text.Text
|
||||
import moe.nea.firmament.events.UseBlockEvent
|
||||
|
||||
private var lastReceivedMessage: Text? = null
|
||||
|
||||
fun registerFirmamentChatEvents() {
|
||||
fun registerFirmamentEvents() {
|
||||
ClientReceiveMessageEvents.ALLOW_CHAT.register(ClientReceiveMessageEvents.AllowChat { message, signedMessage, sender, params, receptionTimestamp ->
|
||||
lastReceivedMessage = message
|
||||
!ProcessChatEvent.publish(ProcessChatEvent(message, false)).cancelled
|
||||
&& !AllowChatEvent.publish(AllowChatEvent(message)).cancelled
|
||||
&& !AllowChatEvent.publish(AllowChatEvent(message)).cancelled
|
||||
})
|
||||
ClientReceiveMessageEvents.ALLOW_GAME.register(ClientReceiveMessageEvents.AllowGame { message, overlay ->
|
||||
lastReceivedMessage = message
|
||||
overlay || (!ProcessChatEvent.publish(ProcessChatEvent(message, false)).cancelled &&
|
||||
!AllowChatEvent.publish(AllowChatEvent(message)).cancelled)
|
||||
!AllowChatEvent.publish(AllowChatEvent(message)).cancelled)
|
||||
})
|
||||
ClientReceiveMessageEvents.MODIFY_GAME.register(ClientReceiveMessageEvents.ModifyGame { message, overlay ->
|
||||
if (overlay) message
|
||||
@@ -39,4 +44,15 @@ fun registerFirmamentChatEvents() {
|
||||
ProcessChatEvent.publish(ProcessChatEvent(message, true))
|
||||
}
|
||||
})
|
||||
|
||||
AttackBlockCallback.EVENT.register(AttackBlockCallback { player, world, hand, pos, direction ->
|
||||
if (AttackBlockEvent.publish(AttackBlockEvent(player, world, hand, pos, direction)).cancelled)
|
||||
ActionResult.CONSUME
|
||||
else ActionResult.PASS
|
||||
})
|
||||
UseBlockCallback.EVENT.register(UseBlockCallback { player, world, hand, hitResult ->
|
||||
if (UseBlockEvent.publish(UseBlockEvent(player, world, hand, hitResult)).cancelled)
|
||||
ActionResult.CONSUME
|
||||
else ActionResult.PASS
|
||||
})
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import net.minecraft.sound.SoundEvents
|
||||
import net.minecraft.util.math.Vec3d
|
||||
import moe.nea.firmament.events.ParticleSpawnEvent
|
||||
import moe.nea.firmament.events.SoundReceiveEvent
|
||||
import moe.nea.firmament.events.WorldReadyEvent
|
||||
import moe.nea.firmament.events.WorldRenderLastEvent
|
||||
import moe.nea.firmament.util.TimeMark
|
||||
import moe.nea.firmament.util.render.RenderInWorldContext
|
||||
@@ -28,6 +29,8 @@ object AncestralSpadeSolver {
|
||||
fun onParticleSpawn(event: ParticleSpawnEvent) {
|
||||
if (!DianaWaypoints.TConfig.ancestralSpadeSolver) 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()
|
||||
@@ -90,4 +93,11 @@ object AncestralSpadeSolver {
|
||||
}
|
||||
}
|
||||
|
||||
fun onSwapWorld(event: WorldReadyEvent) {
|
||||
nextGuess = null
|
||||
particlePositions.clear()
|
||||
pitches.clear()
|
||||
lastDing = TimeMark.farPast()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -6,26 +6,41 @@
|
||||
|
||||
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.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: String
|
||||
get() = "diana-waypoints"
|
||||
override val config: ManagedConfig?
|
||||
get() = TConfig
|
||||
override val identifier get() = "diana-waypoints"
|
||||
override val config get() = TConfig
|
||||
|
||||
object TConfig : ManagedConfig(identifier) {
|
||||
val ancestralSpadeSolver by toggle("ancestral-spade") { false }
|
||||
}
|
||||
|
||||
override fun onLoad() {
|
||||
ParticleSpawnEvent.subscribe(NearbyBurrowsSolver::onParticles)
|
||||
WorldReadyEvent.subscribe(NearbyBurrowsSolver::onSwapWorld)
|
||||
WorldRenderLastEvent.subscribe(NearbyBurrowsSolver::onRender)
|
||||
UseBlockEvent.subscribe {
|
||||
NearbyBurrowsSolver.onBlockClick(it.hitResult.blockPos)
|
||||
}
|
||||
AttackBlockEvent.subscribe {
|
||||
NearbyBurrowsSolver.onBlockClick(it.blockPos)
|
||||
}
|
||||
ProcessChatEvent.subscribe(NearbyBurrowsSolver::onChatEvent)
|
||||
|
||||
|
||||
ParticleSpawnEvent.subscribe(AncestralSpadeSolver::onParticleSpawn)
|
||||
SoundReceiveEvent.subscribe(AncestralSpadeSolver::onPlaySound)
|
||||
WorldRenderLastEvent.subscribe(AncestralSpadeSolver::onWorldRender)
|
||||
WorldReadyEvent.subscribe(AncestralSpadeSolver::onSwapWorld)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Linnea Gräf <nea@nea.moe>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
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.events.ParticleSpawnEvent
|
||||
import moe.nea.firmament.events.ProcessChatEvent
|
||||
import moe.nea.firmament.events.WorldReadyEvent
|
||||
import moe.nea.firmament.events.WorldRenderLastEvent
|
||||
import moe.nea.firmament.util.TimeMark
|
||||
import moe.nea.firmament.util.mutableMapWithMaxSize
|
||||
import moe.nea.firmament.util.render.RenderInWorldContext.Companion.renderInWorld
|
||||
|
||||
object NearbyBurrowsSolver {
|
||||
|
||||
|
||||
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>()
|
||||
|
||||
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()
|
||||
}
|
||||
|
||||
fun onParticles(event: ParticleSpawnEvent) {
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
fun onRender(event: WorldRenderLastEvent) {
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun onSwapWorld(worldReadyEvent: WorldReadyEvent) {
|
||||
burrows.clear()
|
||||
recentEnchantParticles.clear()
|
||||
recentlyDugBurrows.clear()
|
||||
lastBlockClick = null
|
||||
}
|
||||
|
||||
fun onBlockClick(blockPos: BlockPos) {
|
||||
lastBlockClick = blockPos
|
||||
}
|
||||
}
|
||||
|
||||
fun Position.toBlockPos(): BlockPos {
|
||||
return BlockPos(MathHelper.floor(x), MathHelper.floor(y), MathHelper.floor(z))
|
||||
}
|
||||
@@ -1,191 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Linnea Gräf <nea@nea.moe>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
package moe.nea.firmament.features.fishing
|
||||
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.absoluteValue
|
||||
import kotlin.math.atan2
|
||||
import kotlin.math.cos
|
||||
import kotlin.math.min
|
||||
import kotlin.math.sin
|
||||
import kotlin.math.sqrt
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
import net.minecraft.entity.projectile.FishingBobberEntity
|
||||
import net.minecraft.particle.ParticleTypes
|
||||
import net.minecraft.util.math.Vec3d
|
||||
import moe.nea.firmament.Firmament
|
||||
import moe.nea.firmament.events.ParticleSpawnEvent
|
||||
import moe.nea.firmament.events.WorldReadyEvent
|
||||
import moe.nea.firmament.events.WorldRenderLastEvent
|
||||
import moe.nea.firmament.features.FirmamentFeature
|
||||
import moe.nea.firmament.features.debug.DebugView
|
||||
import moe.nea.firmament.gui.config.ManagedConfig
|
||||
import moe.nea.firmament.util.MC
|
||||
import moe.nea.firmament.util.TimeMark
|
||||
import moe.nea.firmament.util.render.RenderInWorldContext.Companion.renderInWorld
|
||||
|
||||
object FishingWarning : FirmamentFeature {
|
||||
override val identifier: String
|
||||
get() = "fishing-warning"
|
||||
|
||||
object TConfig : ManagedConfig("fishing-warning") {
|
||||
// Display a warning when you are about to hook a fish
|
||||
val displayWarning by toggle("display-warning") { false }
|
||||
val highlightWakeChain by toggle("highlight-wake-chain") { false }
|
||||
}
|
||||
|
||||
override val config: ManagedConfig get() = TConfig
|
||||
|
||||
|
||||
data class WakeChain(
|
||||
val delta: Vec3d,
|
||||
val momentum: Vec3d,
|
||||
val lastContinued: TimeMark,
|
||||
)
|
||||
|
||||
|
||||
val chains = mutableListOf<WakeChain>()
|
||||
|
||||
private fun areAnglesClose(a: Double, b: Double, tolerance: Double): Boolean {
|
||||
var dist = (a - b).absoluteValue
|
||||
if (180 < dist) dist = 360 - dist;
|
||||
return dist <= tolerance
|
||||
}
|
||||
|
||||
private fun calculateAngleFromOffsets(xOffset: Double, zOffset: Double): Double {
|
||||
// See also: Vanilla 1.8.9 Fishing particle code.
|
||||
var angleX = Math.toDegrees(Math.acos(xOffset / 0.04))
|
||||
var angleZ = Math.toDegrees(Math.asin(zOffset / 0.04))
|
||||
if (xOffset < 0) {
|
||||
// Old: angleZ = 180 - angleZ;
|
||||
angleZ = 180 - angleZ
|
||||
}
|
||||
if (zOffset < 0) {
|
||||
angleX = 360 - angleX
|
||||
}
|
||||
angleX %= 360.0
|
||||
angleZ %= 360.0
|
||||
if (angleX < 0) angleX += 360.0
|
||||
if (angleZ < 0) angleZ += 360.0
|
||||
var dist = angleX - angleZ
|
||||
if (dist < -180) dist += 360.0
|
||||
if (dist > 180) dist -= 360.0
|
||||
return Math.toDegrees(Math.atan2(xOffset, zOffset))
|
||||
return angleZ + dist / 2 + 180
|
||||
}
|
||||
|
||||
val π = Math.PI
|
||||
val τ = Math.PI * 2
|
||||
|
||||
private fun toDegrees(d: Double) = Math.toDegrees(d).mod(360.0)
|
||||
private fun toRadians(d: Double) = Math.toRadians(d).mod(τ)
|
||||
|
||||
fun isHookPossible(hook: FishingBobberEntity, particlePos: Vec3d, angle1: Double, angle2: Double): Boolean {
|
||||
val dx = particlePos.x - hook.trackedPosition.withDelta(0, 0, 0).x
|
||||
val dz = particlePos.z - hook.trackedPosition.withDelta(0, 0, 0).z
|
||||
val dist = sqrt(dx * dx + dz * dz)
|
||||
|
||||
if (dist < 0.2) return true
|
||||
val tolerance = toDegrees(atan2(0.03125, dist)) * 1.5
|
||||
val angleToHook = toDegrees(atan2(dz, dx))
|
||||
return areAnglesClose(angle1, angleToHook, tolerance) || areAnglesClose(angle2, angleToHook, tolerance)
|
||||
}
|
||||
|
||||
val recentParticles = mutableListOf<Pair<Vec3d, TimeMark>>()
|
||||
|
||||
data class Candidate(
|
||||
val angle1: Double,
|
||||
val angle2: Double,
|
||||
val hookOrigin: Vec3d,
|
||||
val position: Vec3d,
|
||||
val timeMark: TimeMark = TimeMark.now()
|
||||
)
|
||||
|
||||
val recentCandidates = mutableListOf<Candidate>()
|
||||
|
||||
private fun onParticleSpawn(event: ParticleSpawnEvent) {
|
||||
if (event.particleEffect.type != ParticleTypes.FISHING) return
|
||||
if (!(abs(event.offset.y - 0.01f) < 0.001f)) return
|
||||
val hook = MC.player?.fishHook ?: return
|
||||
val actualOffset = event.offset
|
||||
val candidate1 = calculateAngleFromOffsets(-actualOffset.x, (-actualOffset.z))
|
||||
val candidate2 = calculateAngleFromOffsets(actualOffset.x, actualOffset.z)
|
||||
recentCandidates.add(Candidate(candidate1, candidate2, hook.trackedPosition.withDelta(0, 0, 0), event.position))
|
||||
|
||||
if (isHookPossible(hook, event.position, candidate1, candidate2)) {
|
||||
recentParticles.add(Pair(event.position, TimeMark.now()))
|
||||
}
|
||||
}
|
||||
|
||||
override fun onLoad() {
|
||||
ParticleSpawnEvent.subscribe(::onParticleSpawn)
|
||||
WorldReadyEvent.subscribe {
|
||||
recentParticles.clear()
|
||||
}
|
||||
WorldRenderLastEvent.subscribe {
|
||||
recentParticles.removeIf { it.second.passedTime() > 5.seconds }
|
||||
recentCandidates.removeIf { it.timeMark.passedTime() > 5.seconds }
|
||||
renderInWorld(it) {
|
||||
color(0f, 0f, 1f, 1f)
|
||||
recentParticles.forEach {
|
||||
tinyBlock(it.first, 0.1F)
|
||||
}
|
||||
|
||||
if (Firmament.DEBUG) {
|
||||
recentCandidates.forEach {
|
||||
color(1f, 1f, 0f, 1f)
|
||||
line(it.hookOrigin, it.position)
|
||||
color(1f, 0f, 0f, 1f)
|
||||
fun P(yaw: Double) = Vec3d(cos(yaw), 0.0, sin(yaw))
|
||||
line(
|
||||
it.position,
|
||||
P(π - toRadians(it.angle1)).multiply(5.0).add(it.position)
|
||||
)
|
||||
color(0f, 1f, 0f, 1f)
|
||||
line(
|
||||
it.position,
|
||||
P(π - toRadians(it.angle2)).multiply(5.0).add(it.position)
|
||||
)
|
||||
val tolerance = (atan2(0.03125, it.position.distanceTo(it.hookOrigin))).absoluteValue * 1.5
|
||||
val diff = it.hookOrigin.subtract(it.position)
|
||||
val rd = atan2(diff.z, diff.x).mod(τ)
|
||||
color(0.8f, 0f, 0.8f, 1f)
|
||||
DebugView.showVariable("tolerance", tolerance)
|
||||
DebugView.showVariable("angle1Rad", toRadians(180 - it.angle1))
|
||||
DebugView.showVariable("angle1Diff", (toRadians(it.angle1) - rd).mod(τ))
|
||||
DebugView.showVariable("angle1Deg", it.angle1.mod(360.0))
|
||||
DebugView.showVariable("angle2Rad", toRadians(180 - it.angle2))
|
||||
DebugView.showVariable("angle2Deg", it.angle2.mod(360.0))
|
||||
DebugView.showVariable("angle2Diff", (toRadians(it.angle2) - rd).mod(τ))
|
||||
DebugView.showVariable("rd", rd)
|
||||
DebugView.showVariable("minT", (rd + tolerance).mod(τ))
|
||||
DebugView.showVariable("maxT", (rd - tolerance).mod(τ))
|
||||
DebugView.showVariable(
|
||||
"passes",
|
||||
if (min(
|
||||
(rd - toRadians(180 - it.angle2)).mod(τ),
|
||||
(rd - toRadians(180 - it.angle1)).mod(τ)
|
||||
) < tolerance
|
||||
) {
|
||||
"§aPasses"
|
||||
} else {
|
||||
"§cNo Pass"
|
||||
}
|
||||
)
|
||||
|
||||
line(it.position, P(rd + tolerance).add(it.position))
|
||||
line(it.position, P(rd - tolerance).add(it.position))
|
||||
}
|
||||
color(0.8F, 0.8F, 0.8f, 1f)
|
||||
val fishHook = MC.player?.fishHook
|
||||
if (fishHook != null)
|
||||
tinyBlock(fishHook.trackedPosition.withDelta(0, 0, 0), 0.2f)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Linnea Gräf <nea@nea.moe>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
package moe.nea.firmament.util
|
||||
|
||||
fun <K, V> mutableMapWithMaxSize(maxSize: Int): MutableMap<K, V> = object : LinkedHashMap<K, V>() {
|
||||
override fun removeEldestEntry(eldest: MutableMap.MutableEntry<K, V>): Boolean {
|
||||
return size > maxSize
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user