Commits
DerFrZocker authored and md_5 committed 06c0ce78cce
4 4 | import java.awt.Color; |
5 5 | import java.io.File; |
6 6 | import java.io.FileInputStream; |
7 7 | import java.io.FileOutputStream; |
8 8 | import java.io.IOException; |
9 9 | import java.io.InputStream; |
10 10 | import java.io.OutputStream; |
11 11 | import java.security.MessageDigest; |
12 12 | import java.security.NoSuchAlgorithmException; |
13 13 | import java.util.concurrent.CompletableFuture; |
14 + | import java.util.concurrent.atomic.AtomicBoolean; |
14 15 | import java.util.logging.Logger; |
15 16 | import java.util.zip.DeflaterOutputStream; |
16 17 | import java.util.zip.InflaterInputStream; |
17 18 | import net.minecraft.SystemUtils; |
18 19 | import org.bukkit.map.MapPalette; |
19 20 | |
20 21 | public class CraftMapColorCache implements MapPalette.MapColorCache { |
21 22 | |
22 23 | private static final String MD5_CACHE_HASH = "E88EDD068D12D39934B40E8B6B124C83"; |
23 24 | private static final File CACHE_FILE = new File("map-color-cache.dat"); |
24 25 | private byte[] cache; |
25 26 | private final Logger logger; |
26 27 | private boolean cached = false; |
27 - | private boolean running = false; |
28 + | private final AtomicBoolean running = new AtomicBoolean(false); |
28 29 | |
29 30 | public CraftMapColorCache(Logger logger) { |
30 31 | this.logger = logger; |
31 32 | } |
32 33 | |
33 34 | // Builds and prints the md5 hash of the cache, this should be run when new map colors are added to update the MD5_CACHE_HASH string |
34 35 | public static void main(String[] args) { |
35 36 | CraftMapColorCache craftMapColorCache = new CraftMapColorCache(Logger.getGlobal()); |
36 37 | craftMapColorCache.buildCache(); |
37 38 | try { |
50 51 | int first = (value & 0xF0) >> 4; |
51 52 | int second = value & 0x0F; |
52 53 | builder.append(chars[first]); |
53 54 | builder.append(chars[second]); |
54 55 | } |
55 56 | |
56 57 | return builder.toString(); |
57 58 | } |
58 59 | |
59 60 | public CompletableFuture<Void> initCache() { |
60 - | Preconditions.checkState(!cached && !running, "Cache is already build or is currently being build"); |
61 + | Preconditions.checkState(!cached && !running.getAndSet(true), "Cache is already build or is currently being build"); |
61 62 | |
62 63 | cache = new byte[256 * 256 * 256]; // Red, Green and Blue have each a range from 0 to 255 each mean we need space for 256 * 256 * 256 values |
63 64 | if (CACHE_FILE.exists()) { |
64 65 | byte[] fileContent; |
65 66 | |
66 67 | try (InputStream inputStream = new InflaterInputStream(new FileInputStream(CACHE_FILE))) { |
67 68 | fileContent = inputStream.readAllBytes(); |
68 69 | } catch (IOException e) { |
69 70 | logger.warning("Error while reading map color cache"); |
70 71 | e.printStackTrace(); |
101 102 | for (int g = 0; g < 256; g++) { |
102 103 | for (int b = 0; b < 256; b++) { |
103 104 | Color color = new Color(r, g, b); |
104 105 | cache[toInt(color)] = MapPalette.matchColor(color); |
105 106 | } |
106 107 | } |
107 108 | } |
108 109 | } |
109 110 | |
110 111 | private CompletableFuture<Void> buildAndSaveCache() { |
111 - | running = true; |
112 112 | return CompletableFuture.runAsync(() -> { |
113 113 | buildCache(); |
114 114 | |
115 115 | if (!CACHE_FILE.exists()) { |
116 116 | try { |
117 117 | if (!CACHE_FILE.createNewFile()) { |
118 - | running = false; |
119 118 | cached = true; |
120 119 | return; |
121 120 | } |
122 121 | } catch (IOException e) { |
123 122 | logger.warning("Error while building map color cache"); |
124 123 | e.printStackTrace(); |
125 - | running = false; |
126 124 | cached = true; |
127 125 | return; |
128 126 | } |
129 127 | } |
130 128 | |
131 129 | try (OutputStream outputStream = new DeflaterOutputStream(new FileOutputStream(CACHE_FILE))) { |
132 130 | outputStream.write(cache); |
133 131 | } catch (IOException e) { |
134 132 | logger.warning("Error while building map color cache"); |
135 133 | e.printStackTrace(); |
136 - | running = false; |
137 134 | cached = true; |
138 135 | return; |
139 136 | } |
140 137 | |
141 - | running = false; |
142 138 | cached = true; |
143 139 | logger.info("Map color cache build successfully"); |
144 140 | }, SystemUtils.backgroundExecutor()); |
145 141 | } |
146 142 | |
147 143 | private int toInt(Color color) { |
148 144 | return color.getRGB() & 0xFFFFFF; |
149 145 | } |
150 146 | |
151 147 | |
152 148 | public boolean isCached() { |
153 - | return cached || (!running && initCache().isDone()); |
149 + | return cached || (!running.get() && initCache().isDone()); |
154 150 | } |
155 151 | |
156 152 | |
157 153 | public byte matchColor(Color color) { |
158 154 | Preconditions.checkState(isCached(), "Cache not build jet"); |
159 155 | |
160 156 | return cache[toInt(color)]; |
161 157 | } |
162 158 | } |