BlastingCrisis/src/main/kotlin/cc/maxmc/blastingcrisis/packet/BEntity.kt

123 lines
3.9 KiB
Kotlin

package cc.maxmc.blastingcrisis.packet
import cc.maxmc.blastingcrisis.listener.BEntityInteract
import gnu.trove.TDecorators
import gnu.trove.map.hash.TIntObjectHashMap
import net.minecraft.server.v1_8_R3.*
import org.bukkit.Location
import org.bukkit.entity.Player
import taboolib.common.util.random
import taboolib.library.reflex.Reflex.Companion.getProperty
import taboolib.library.reflex.Reflex.Companion.setProperty
import taboolib.library.reflex.Reflex.Companion.unsafeInstance
import taboolib.module.nms.sendPacket
import java.util.concurrent.atomic.AtomicInteger
import java.util.concurrent.locks.ReentrantReadWriteLock
abstract class BEntity(var loc: Location, val entityType: Int) {
private val dataWatcher = (DataWatcher::class.java.unsafeInstance() as DataWatcher).apply {
setProperty("b", true)
setProperty("dataValues", TIntObjectHashMap<Any?>(10, 0.5f, -1))
setProperty("d", TDecorators.wrap(getProperty<TIntObjectHashMap<Any>>("dataValues")!!))
setProperty("f", ReentrantReadWriteLock())
}.apply {
/*
0x01 On Fire
0x02 Crouched
0x08 Sprinting
0x10 Eating/Drinking/Blocking
0x20 Invisible
*/
a(0, 0.toByte())
a(1, 300.toShort()) // Air
a(2, "") // Name Tag
a(3, 0.toByte()) // Always Show Name Tag
a(4, 0.toByte()) // Silent
initEntity()
}
val entityID: Int = getEID()
val viewers = ArrayList<Player>()
val interactHandlers = ArrayList<(BEntityInteract) -> Unit>()
abstract fun DataWatcher.initEntity()
open fun spawnForPlayer(player: Player) {
val packet = PacketPlayOutSpawnEntityLiving()
packet.apply {
setProperty("a", entityID)
setProperty("b", entityType)
setProperty("c", MathHelper.floor(loc.x * 32.0))
setProperty("d", MathHelper.floor(loc.y * 32.0))
setProperty("e", MathHelper.floor(loc.z * 32.0))
setProperty("f", 0.toShort())
setProperty("g", 0.toShort())
setProperty("h", 0.toShort())
setProperty("i", (loc.yaw * 256.0f / 360.0f).toInt().toByte())
setProperty("j", (loc.pitch * 256.0f / 360.0f).toInt().toByte())
setProperty("k", (loc.yaw * 256.0f / 360.0f).toInt().toByte())
}
packet.setProperty("l", dataWatcher)
viewers.forEach { it.sendPacket(packet) }
}
open fun addViewer(viewer: Player) {
viewers.add(viewer)
spawnForPlayer(viewer)
}
open fun removeViewer(viewer: Player) {
viewer.sendPacket(PacketPlayOutEntityDestroy(entityID))
viewers.remove(viewer)
}
fun destroy() {
ArrayList(viewers).forEach { removeViewer(it) }
}
fun update() {
viewers.forEach {
updateFor(it)
}
}
fun updateFor(player: Player) {
val packet = PacketPlayOutEntityMetadata(entityID, dataWatcher, true)
player.sendPacket(packet)
}
fun updateData(toDo: DataWatcher.(Player) -> Unit) {
viewers.forEach {
toDo(dataWatcher, it)
updateFor(it)
}
}
fun hurtAnimate() {
PacketPlayOutEntityStatus().apply {
setProperty("a", entityID)
setProperty("b", 2.toByte())
}.let { viewers.forEach { p -> p.sendPacket(it) } }
}
fun dieAnimate() {
PacketPlayOutEntityStatus().apply {
setProperty("a", entityID)
setProperty("b", 3.toByte())
}.let { viewers.forEach { p -> p.sendPacket(it) } }
}
fun handleInteract(handler: (BEntityInteract) -> Unit) {
interactHandlers.add(handler)
}
fun onInteract(interact: BEntityInteract) {
interactHandlers.forEach { it(interact) }
}
companion object {
private val incrementEntityID = AtomicInteger(197827 + random(0, 549))
fun getEID() = incrementEntityID.addAndGet(1)
}
}