@@ -6,11 +6,16 @@ import com.lambda.client.module.Category
6
6
import com.lambda.client.module.Module
7
7
import com.lambda.client.util.threads.runSafe
8
8
import com.lambda.client.util.threads.safeListener
9
+ import net.minecraft.entity.Entity
10
+ import net.minecraft.entity.EntityLiving
9
11
import net.minecraft.entity.passive.AbstractHorse
10
12
import net.minecraft.entity.passive.EntityTameable
11
13
import net.minecraftforge.fml.common.gameevent.TickEvent
14
+ import java.util.*
12
15
import kotlin.math.pow
13
16
17
+ private data class EntityData (var originalCustomNameTag : String , var previous : String? = null )
18
+
14
19
object MobOwner : Module(
15
20
name = " MobOwner" ,
16
21
description = " Displays the owner of tamed mobs" ,
@@ -22,58 +27,77 @@ object MobOwner : Module(
22
27
23
28
private const val invalidText = " Offline or invalid UUID!"
24
29
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
+
25
39
init {
26
40
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)
36
47
}
48
+ }
37
49
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)
45
55
}
46
56
}
47
57
}
48
58
49
59
onDisable {
50
60
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
53
65
54
- try {
55
- entity.alwaysRenderNameTag = false
56
- } catch (_: Exception ) {
57
- // Ignored
58
- }
66
+ it.alwaysRenderNameTag = false
59
67
}
68
+
69
+ originalCustomNameTags.clear()
70
+ nullUUIDs.clear()
60
71
}
61
72
}
62
73
}
63
74
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
66
90
}
67
91
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
+ }
71
98
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 )
75
100
76
- private fun getHealth (tameable : EntityTameable ): String {
77
- return if (! hp) " " else " HP: " + round(tameable.health, 2 )
101
+ return data
78
102
}
79
103
}
0 commit comments