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(10, 0.5f, -1)) setProperty("d", TDecorators.wrap(getProperty>("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() 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) } }