@@ -19,20 +19,27 @@ package gg.skytils.skytilsmod.features.impl.events
1919
2020import com.google.common.collect.EvictingQueue
2121import gg.essential.universal.UMatrixStack
22+ import gg.essential.universal.UMinecraft
23+ import gg.essential.universal.wrappers.UPlayer
2224import gg.skytils.skytilsmod.Skytils
2325import gg.skytils.skytilsmod.Skytils.Companion.mc
2426import gg.skytils.skytilsmod.events.impl.MainReceivePacketEvent
2527import gg.skytils.skytilsmod.events.impl.PacketEvent
2628import gg.skytils.skytilsmod.utils.*
2729import net.minecraft.client.renderer.GlStateManager
30+ import net.minecraft.entity.item.EntityArmorStand
2831import net.minecraft.init.Blocks
32+ import net.minecraft.init.Items
2933import net.minecraft.item.ItemStack
3034import net.minecraft.network.play.client.C07PacketPlayerDigging
3135import net.minecraft.network.play.client.C08PacketPlayerBlockPlacement
36+ import net.minecraft.network.play.server.S04PacketEntityEquipment
37+ import net.minecraft.network.play.server.S29PacketSoundEffect
3238import net.minecraft.network.play.server.S2APacketParticles
3339import net.minecraft.util.AxisAlignedBB
3440import net.minecraft.util.BlockPos
3541import net.minecraft.util.EnumParticleTypes
42+ import net.minecraft.util.Vec3
3643import net.minecraft.util.Vec3i
3744import net.minecraftforge.client.event.ClientChatReceivedEvent
3845import net.minecraftforge.client.event.RenderWorldLastEvent
@@ -42,6 +49,11 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
4249import net.minecraftforge.fml.common.gameevent.TickEvent
4350import net.minecraftforge.fml.common.gameevent.TickEvent.ClientTickEvent
4451import java.awt.Color
52+ import java.time.Duration
53+ import java.time.Instant
54+ import kotlin.math.PI
55+ import kotlin.math.cos
56+ import kotlin.math.sin
4557
4658object GriffinBurrows {
4759 val particleBurrows = hashMapOf<BlockPos , ParticleBurrow >()
@@ -50,13 +62,32 @@ object GriffinBurrows {
5062
5163 var hasSpadeInHotbar = false
5264
65+ object BurrowEstimation {
66+ val arrows = mutableMapOf<Arrow , Instant >()
67+ val guesses = mutableMapOf<BurrowGuess , Instant >()
68+ fun getDistanceFromPitch (pitch : Double ) =
69+ 2805 * pitch + 1375
70+
71+ val grassData by lazy {
72+ this ::class .java.getResource(" /assets/skytils/grassdata.txt" )!! .readBytes()
73+ }
74+
75+ class Arrow (val directionVector : Vec3 , val pos : Vec3 )
76+ }
77+
5378
5479 @SubscribeEvent
5580 fun onTick (event : ClientTickEvent ) {
5681 if (event.phase != TickEvent .Phase .START ) return
5782 hasSpadeInHotbar = mc.thePlayer != null && Utils .inSkyblock && (0 .. 7 ).any {
5883 mc.thePlayer.inventory.getStackInSlot(it).isSpade
5984 }
85+ BurrowEstimation .guesses.entries.removeIf { (_, instant) ->
86+ Duration .between(instant, Instant .now()).toMinutes() > 30
87+ }
88+ BurrowEstimation .arrows.entries.removeIf { (_, instant) ->
89+ Duration .between(instant, Instant .now()).toMinutes() > 5
90+ }
6091 }
6192
6293 @SubscribeEvent(receiveCanceled = true , priority = EventPriority .HIGHEST )
@@ -106,6 +137,23 @@ object GriffinBurrows {
106137 pb.drawWaypoint(event.partialTicks, matrixStack)
107138 }
108139 }
140+ for (bg in BurrowEstimation .guesses.keys) {
141+ bg.drawWaypoint(event.partialTicks, matrixStack)
142+ }
143+ for (arrow in BurrowEstimation .arrows.keys) {
144+ RenderUtil .drawCircle(
145+ matrixStack,
146+ arrow.pos.x,
147+ arrow.pos.y + 0.2 ,
148+ arrow.pos.z,
149+ event.partialTicks,
150+ 5.0 ,
151+ 100 ,
152+ 255 ,
153+ 128 ,
154+ 0 ,
155+ )
156+ }
109157 }
110158 }
111159
@@ -118,23 +166,81 @@ object GriffinBurrows {
118166 @SubscribeEvent
119167 fun onReceivePacket (event : MainReceivePacketEvent <* , * >) {
120168 if (! Utils .inSkyblock) return
121- if (Skytils .config.showGriffinBurrows && hasSpadeInHotbar && event.packet is S2APacketParticles ) {
122- if (SBInfo .mode != SkyblockIsland .Hub .mode) return
123- event.packet.apply {
124- val type = ParticleType .getParticleType(this ) ? : return
125- val pos = BlockPos (x, y, z).down()
126- if (recentlyDugParticleBurrows.contains(pos)) return
127- val burrow = particleBurrows.getOrPut(pos) {
128- ParticleBurrow (pos, hasFootstep = false , hasEnchant = false , type = - 1 )
169+ when (event.packet) {
170+ is S2APacketParticles -> {
171+ if (Skytils .config.showGriffinBurrows && hasSpadeInHotbar) {
172+ if (SBInfo .mode != SkyblockIsland .Hub .mode) return
173+ event.packet.apply {
174+ val type = ParticleType .getParticleType(this ) ? : return
175+ val pos = BlockPos (x, y, z).down()
176+ if (recentlyDugParticleBurrows.contains(pos)) return
177+ BurrowEstimation .guesses.keys.associateWith { guess ->
178+ pos.distanceSq(
179+ guess.x.toDouble(),
180+ guess.y.toDouble(),
181+ guess.z.toDouble()
182+ )
183+ }.minByOrNull { it.value }?.let { (guess, distance) ->
184+ printDevMessage(" Nearest guess is $distance blocks away" , " griffin" , " griffinguess" )
185+ if (distance <= 625 ) {
186+ BurrowEstimation .guesses.remove(guess)
187+ }
188+ }
189+ val burrow = particleBurrows.getOrPut(pos) {
190+ ParticleBurrow (pos, hasFootstep = false , hasEnchant = false , type = - 1 )
191+ }
192+ when (type) {
193+ ParticleType .FOOTSTEP -> burrow.hasFootstep = true
194+ ParticleType .ENCHANT -> burrow.hasEnchant = true
195+ ParticleType .EMPTY -> burrow.type = 0
196+ ParticleType .MOB -> burrow.type = 1
197+ ParticleType .TREASURE -> burrow.type = 2
198+ }
199+ }
129200 }
130- when (type) {
131- ParticleType .FOOTSTEP -> burrow.hasFootstep = true
132- ParticleType .ENCHANT -> burrow.hasEnchant = true
133- ParticleType .EMPTY -> burrow.type = 0
134- ParticleType .MOB -> burrow.type = 1
135- ParticleType .TREASURE -> burrow.type = 2
201+ }
202+ is S04PacketEntityEquipment -> {
203+ val entity = UMinecraft .getMinecraft().theWorld.getEntityByID(event.packet.entityID)
204+ (entity as ? EntityArmorStand )?.let { armorStand ->
205+ if (event.packet.itemStack.item != Items .arrow) return
206+ if (armorStand.getDistanceSq(UPlayer .getPlayer()?.position) >= 27 ) return
207+ printDevMessage(" Found armor stand with arrow" , " griffin" , " griffinguess" )
208+ val yaw = Math .toRadians(armorStand.rotationYaw.toDouble())
209+ val lookVec = Vec3 (
210+ - sin(yaw),
211+ 0.0 ,
212+ cos(yaw)
213+ )
214+ val offset = Vec3 (- sin(yaw + PI / 2 ), 0.0 , cos(yaw + PI / 2 )) * 0.9
215+ val origin = armorStand.positionVector.add(offset)
216+ BurrowEstimation .arrows.put(BurrowEstimation .Arrow (lookVec, origin), Instant .now())
136217 }
137218 }
219+ is S29PacketSoundEffect -> {
220+ if (event.packet.soundName != " note.harp" ) return
221+ val (arrow, distance) = BurrowEstimation .arrows.keys
222+ .associateWith { arrow ->
223+ arrow.pos.squareDistanceTo(event.packet.x, event.packet.y, event.packet.z)
224+ }.minByOrNull { it.value } ? : return
225+ printDevMessage(" Nearest arrow is $distance blocks away ${arrow.pos} " , " griffin" , " griffinguess" )
226+ if (distance > 25 ) return
227+ val guessPos = arrow.pos.add(
228+ arrow.directionVector * BurrowEstimation .getDistanceFromPitch(event.packet.pitch.toDouble())
229+ )
230+
231+ var y: Int
232+ var x = guessPos.x.toInt()
233+ var z = guessPos.z.toInt()
234+ // offset of 300 blocks for both x and z
235+ // x ranges from 195 to -281
236+ // z ranges from 207 to -233
237+ do {
238+ y = BurrowEstimation .grassData.get((x++ % 507 ) * 507 + (z++ % 495 )).toInt()
239+ } while (y < 2 )
240+ val guess = BurrowGuess (guessPos.x.toInt(), y, guessPos.z.toInt())
241+ BurrowEstimation .arrows.remove(arrow)
242+ BurrowEstimation .guesses[guess] = Instant .now()
243+ }
138244 }
139245 }
140246
@@ -181,6 +287,16 @@ object GriffinBurrows {
181287 }
182288 }
183289
290+ data class BurrowGuess (
291+ override val x : Int ,
292+ override val y : Int ,
293+ override val z : Int
294+ ) : Diggable() {
295+ override var type = 0
296+ override val waypointText = " §aBurrow §6(Guess)"
297+ override val color = Color .ORANGE
298+ }
299+
184300 data class ParticleBurrow (
185301 override val x : Int ,
186302 override val y : Int ,
0 commit comments