@@ -6,11 +6,16 @@ import com.lambda.client.module.Category
66import com.lambda.client.module.Module
77import com.lambda.client.util.threads.runSafe
88import com.lambda.client.util.threads.safeListener
9+ import net.minecraft.entity.Entity
10+ import net.minecraft.entity.EntityLiving
911import net.minecraft.entity.passive.AbstractHorse
1012import net.minecraft.entity.passive.EntityTameable
1113import net.minecraftforge.fml.common.gameevent.TickEvent
14+ import java.util.*
1215import kotlin.math.pow
1316
17+ private data class EntityData (var originalCustomNameTag : String , var previous : String? = null )
18+
1419object MobOwner : Module(
1520 name = " MobOwner" ,
1621 description = " Displays the owner of tamed mobs" ,
@@ -22,58 +27,77 @@ object MobOwner : Module(
2227
2328 private const val invalidText = " Offline or invalid UUID!"
2429
30+ // nullUUIDs caches all UUID's that returned an empty response from the Mojang API, effectively removing the endless
31+ // HTTP requests and subsequent rate-limit.
32+ private val nullUUIDs = mutableSetOf<UUID >()
33+
34+ // originalCustomNameTags does two things. It stores an EntityData data class for every tamable entity.
35+ // In EntityData the original customNameTag is stored that someone might have applied to the entity, a stateful
36+ // previous variable holds the last customNameTag to keep track when a new customNameTag is applied by a player.
37+ private val originalCustomNameTags = mutableMapOf<UUID , EntityData >()
38+
2539 init {
2640 safeListener<TickEvent .ClientTickEvent > {
27- for (entity in world.loadedEntityList) {
28- /* Non Horse types, such as wolves */
29- if (entity is EntityTameable ) {
30- val ownerUUID = entity.ownerId
31- if (! entity.isTamed || ownerUUID == null ) continue
32-
33- val ownerName = UUIDManager .getByUUID(ownerUUID)?.name ? : invalidText
34- entity.alwaysRenderNameTag = true
35- entity.customNameTag = " Owner: " + ownerName + getHealth(entity)
41+ /* Non Horse types, such as wolves */
42+ world.loadedEntityList.filterIsInstance<EntityTameable >().filter {
43+ it.isTamed
44+ }.forEach { entity ->
45+ entity.ownerId?.let {
46+ changeEntityData(it, entity)
3647 }
48+ }
3749
38- if (entity is AbstractHorse ) {
39- val ownerUUID = entity.ownerUniqueId
40- if (! entity.isTame || ownerUUID == null ) continue
41-
42- val ownerName = UUIDManager .getByUUID(ownerUUID)?.name ? : invalidText
43- entity.alwaysRenderNameTag = true
44- entity.customNameTag = " Owner: " + ownerName + getSpeed(entity) + getJump(entity) + getHealth(entity)
50+ world.loadedEntityList.filterIsInstance<AbstractHorse >().filter {
51+ it.isTame
52+ }.forEach { entity ->
53+ entity.ownerUniqueId?.let {
54+ changeEntityData(it, entity)
4555 }
4656 }
4757 }
4858
4959 onDisable {
5060 runSafe {
51- for (entity in world.loadedEntityList) {
52- if (entity !is AbstractHorse ) continue
61+ // Revert customNameTag back to original.
62+ world.loadedEntityList.filterNotNull().forEach {
63+ val entityData = originalCustomNameTags[it.uniqueID]
64+ it.customNameTag = entityData?.originalCustomNameTag ? : it.customNameTag
5365
54- try {
55- entity.alwaysRenderNameTag = false
56- } catch (_: Exception ) {
57- // Ignored
58- }
66+ it.alwaysRenderNameTag = false
5967 }
68+
69+ originalCustomNameTags.clear()
70+ nullUUIDs.clear()
6071 }
6172 }
6273 }
6374
64- private fun getSpeed (horse : AbstractHorse ): String {
65- return if (! speed) " " else " S: " + round(43.17 * horse.aiMoveSpeed, 2 )
75+ private fun changeEntityData (ownerUUID : UUID , entity : Entity ) {
76+ val owner = if (nullUUIDs.contains(ownerUUID)) null else UUIDManager .getByUUID(ownerUUID)
77+ val ownerName = if (owner == null ) {
78+ nullUUIDs.add(ownerUUID)
79+ invalidText
80+ } else {
81+ owner.name
82+ }
83+ val entityData = originalCustomNameTags.getOrPut(entity.uniqueID) { EntityData (originalCustomNameTag = entity.customNameTag) }
84+ if (entityData.previous != null && entity.customNameTag != entityData.previous) {
85+ entityData.originalCustomNameTag = entity.customNameTag
86+ }
87+ entity.alwaysRenderNameTag = true
88+ entity.customNameTag = " ${if (entityData.originalCustomNameTag != " " ) " ${entityData.originalCustomNameTag} | " else " " } Owner: " + ownerName + getData(entity as EntityLiving )
89+ entityData.previous = entity.customNameTag
6690 }
6791
68- private fun getJump (horse : AbstractHorse ): String {
69- return if (! jump) " " else " J: " + round(- 0.1817584952 * horse.horseJumpStrength.pow(3.0 ) + 3.689713992 * horse.horseJumpStrength.pow(2.0 ) + 2.128599134 * horse.horseJumpStrength - 0.343930367 , 2 )
70- }
92+ private fun getData (entity : EntityLiving ): String {
93+ var data = " "
94+ if (entity is AbstractHorse ) {
95+ if (speed) data + = " S: " + round(43.17 * entity.aiMoveSpeed, 2 )
96+ if (jump) data + = " J: " + round(- 0.1817584952 * entity.horseJumpStrength.pow(3.0 ) + 3.689713992 * entity.horseJumpStrength.pow(2.0 ) + 2.128599134 * entity.horseJumpStrength - 0.343930367 , 2 )
97+ }
7198
72- private fun getHealth (horse : AbstractHorse ): String {
73- return if (! hp) " " else " HP: " + round(horse.health, 2 )
74- }
99+ if (hp) data + = " HP: " + round(entity.health, 2 )
75100
76- private fun getHealth (tameable : EntityTameable ): String {
77- return if (! hp) " " else " HP: " + round(tameable.health, 2 )
101+ return data
78102 }
79103}
0 commit comments