aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/at/hannibal2/skyhanni/events/RenderEntityOutlineEvent.kt
blob: f64dfa27edf60d226ad6c0f013a7504d5a671156 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package at.hannibal2.skyhanni.events

import net.minecraft.client.Minecraft
import net.minecraft.entity.Entity
import net.minecraft.entity.item.EntityArmorStand
import net.minecraft.entity.item.EntityItemFrame

class RenderEntityOutlineEvent(theType: Type?, potentialEntities: HashSet<Entity>?) :
    LorenzEvent() {

    /**
     * The phase of the event (see [Type]
     */
    var type: Type? = null

    /**
     * The entities to outline. This is progressively cumulated from [.entitiesToChooseFrom]
     */
    var entitiesToOutline: HashMap<Entity, Int>? = null

    /**
     * The entities we can outline. Note that this set and [.entitiesToOutline] are disjoint at all times.
     */
    var entitiesToChooseFrom: HashSet<Entity>? = null

    /**
     * Constructs the event, given the type and optional entities to outline.
     *
     *
     * This will modify {@param potentialEntities} internally, so make a copy before passing it if necessary.
     *
     * @param theType of the event (see [Type]
     */
    init {
        type = theType
        entitiesToChooseFrom = potentialEntities
        if (potentialEntities != null) {
            entitiesToOutline = HashMap(potentialEntities.size)
        }
    }

    /**
     * Conditionally queue entities around which to render entities
     * Selects from the pool of [.entitiesToChooseFrom] to speed up the predicate testing on subsequent calls.
     * Is more efficient (theoretically) than calling [.queueEntityToOutline] for each entity because lists are handled internally.
     *
     *
     * This function loops through all entities and so is not very efficient.
     * It's advisable to encapsulate calls to this function with global checks (those not dependent on an individual entity) for efficiency purposes.
     *
     * @param outlineColor a function to test
     */
    fun queueEntitiesToOutline(outlineColor: ((entity: Entity) -> Int?)? = null) {
        if (outlineColor == null) {
            return
        }
        if (entitiesToChooseFrom == null) {
            computeAndCacheEntitiesToChooseFrom()
        }
        val itr: MutableIterator<Entity> = entitiesToChooseFrom!!.iterator()
        while (itr.hasNext()) {
            val e: Entity = itr.next()
            val i: Int? = outlineColor(e)
            if (i != null) {
                entitiesToOutline!![e] = i
                itr.remove()
            }
        }
    }

    /**
     * Adds a single entity to the list of the entities to outline
     *
     * @param entity       the entity to add
     * @param outlineColor the color with which to outline
     */
    fun queueEntityToOutline(entity: Entity?, outlineColor: Int) {
        if (entity == null) {
            return
        }
        if (entitiesToChooseFrom == null) {
            computeAndCacheEntitiesToChooseFrom()
        }
        if (!entitiesToChooseFrom!!.contains(entity)) {
            return
        }
        entitiesToOutline!![entity] = outlineColor
        entitiesToChooseFrom!!.remove(entity)
    }

    /**
     * Used for on-the-fly generation of entities. Driven by event handlers in a decentralized fashion
     */
    private fun computeAndCacheEntitiesToChooseFrom() {
        val entities: List<Entity> = Minecraft.getMinecraft().theWorld.getLoadedEntityList()
        // Only render outlines around non-null entities within the camera frustum
        entitiesToChooseFrom = HashSet(entities.size)
        // Only consider entities that aren't invisible armorstands to increase FPS significantly
        for (entity in entities) {
            if (!(entity is EntityArmorStand && entity.isInvisible()) && entity !is EntityItemFrame) {
                entitiesToChooseFrom!!.add(entity)
            }
        }
        entitiesToOutline = HashMap(entitiesToChooseFrom!!.size)
    }

    /**
     * The phase of the event.
     * [.XRAY] means that this directly precedes entities whose outlines are rendered through walls (Vanilla 1.9+)
     * [.NO_XRAY] means that this directly precedes entities whose outlines are rendered only when visible to the client
     */
    enum class Type {

        XRAY,
        NO_XRAY
    }
}