aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/gregtech/api/util/GT_BlockMap.java
blob: 9ffe273cac9b4c6de29762c8f251548b0f05e76c (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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
package gregtech.api.util;

import java.util.concurrent.ConcurrentHashMap;
import java.util.function.BiFunction;

import net.minecraft.block.Block;

import gnu.trove.map.TByteObjectMap;
import gnu.trove.map.hash.TByteObjectHashMap;

public class GT_BlockMap<V> {

    public static final byte WILDCARD = -1;
    private final ConcurrentHashMap<Block, TByteObjectMap<V>> backing = new ConcurrentHashMap<>();
    private int size = 0;

    private TByteObjectMap<V> getSubmap(Block block) {
        return backing.computeIfAbsent(block, b -> new TByteObjectHashMap<>());
    }

    /**
     * Associate a value with that union key
     *
     * @param block block
     * @param meta  meta
     * @return old mapping, or null if that doesn't exist
     */
    public V put(Block block, byte meta, V value) {
        V v = getSubmap(block).put(meta, value);
        if (v == null) size++;
        return v;
    }

    /**
     * Associate a value with that union key ONLY IF there isn't a prior EXACT mapping
     *
     * @param block block
     * @param meta  meta
     * @return old mapping, or null if that doesn't exist
     */
    public V putIfAbsent(Block block, byte meta, V value) {
        V v = getSubmap(block).putIfAbsent(meta, value);
        if (v == null) size++;
        return v;
    }

    /**
     * Associate a value with that union key ONLY IF there isn't a prior EXACT mapping
     *
     * @param block block
     * @param meta  meta
     * @return old mapping, or null if that doesn't exist
     */
    public V computeIfAbsent(Block block, byte meta, BiFunction<Block, Byte, V> function) {
        TByteObjectMap<V> submap = getSubmap(block);
        V v = submap.get(meta);
        if (v == null) {
            v = function.apply(block, meta);
            submap.put(meta, v);
            size++;
        }
        return v;
    }

    /**
     * Contains an associated value
     *
     * @param block block
     * @param meta  meta
     * @return current mapping OR wildcard of that mapping exists
     */
    public boolean containsKey(Block block, byte meta) {
        TByteObjectMap<V> submap = backing.get(block);
        if (submap == null) return false;
        return submap.containsKey(meta) || submap.containsKey(WILDCARD);
    }

    /**
     * Get the associated value
     *
     * @param block block
     * @param meta  meta
     * @return current mapping OR wildcard of that block. null if neither exists
     */
    public V get(Block block, byte meta) {
        TByteObjectMap<V> submap = backing.get(block);
        if (submap == null) return null;
        V v = submap.get(meta);
        if (v != null) return v;
        return submap.get(WILDCARD);
    }

    /**
     * Remove a mapping
     *
     * @param block block
     * @param meta  meta
     * @return old value, or null if none
     */
    public V remove(Block block, byte meta) {
        TByteObjectMap<V> submap = backing.get(block);
        if (submap == null) return null;
        V v = submap.remove(meta);
        if (v != null) {
            size--;
            if (submap.isEmpty()) backing.remove(block);
        }
        return v;
    }

    /**
     * Size of all mappings
     *
     * @return size
     */
    public int size() {
        return size;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        GT_BlockMap<?> that = (GT_BlockMap<?>) o;

        return backing.equals(that.backing);
    }

    @Override
    public int hashCode() {
        return backing.hashCode();
    }
}