1 package me.shedaniel.lightoverlay.common;
3 import com.mojang.blaze3d.platform.InputConstants;
4 import com.mojang.blaze3d.vertex.PoseStack;
5 import dev.architectury.event.events.client.ClientGuiEvent;
6 import dev.architectury.event.events.client.ClientTickEvent;
7 import dev.architectury.injectables.targets.ArchitecturyTarget;
8 import dev.architectury.platform.Platform;
9 import dev.architectury.registry.client.keymappings.KeyMappingRegistry;
10 import net.minecraft.client.KeyMapping;
11 import net.minecraft.resources.ResourceLocation;
12 import net.minecraft.util.Mth;
15 import java.io.FileInputStream;
16 import java.io.FileOutputStream;
17 import java.io.IOException;
18 import java.text.DecimalFormat;
19 import java.util.Properties;
20 import java.util.function.Consumer;
22 public class LightOverlay {
23 public static final DecimalFormat FORMAT = new DecimalFormat("#.#");
24 public static int reach = 12;
25 public static int crossLevel = 0;
26 public static int secondaryLevel = 7;
27 public static int lowerCrossLevel = -1;
28 public static int higherCrossLevel = -1;
29 public static boolean caching = false;
30 public static boolean showNumber = false;
31 public static boolean underwater = false;
32 public static boolean mushroom = false;
33 public static float lineWidth = 1.0F;
34 public static int yellowColor = 0xFFFF00, redColor = 0xFF0000, secondaryColor = 0x0000FF;
35 public static File configFile;
37 public static KeyMapping enableOverlay;
38 public static boolean enabled = false;
40 public static LightOverlayTicker ticker = new LightOverlayTicker();
41 public static LightOverlayRenderer renderer = new LightOverlayRenderer(ticker);
43 public static void register() {
45 configFile = new File(Platform.getConfigFolder().toFile(), "lightoverlay.properties");
46 loadConfig(configFile);
48 enableOverlay = createKeyBinding(new ResourceLocation("lightoverlay", "enable_overlay"), InputConstants.Type.KEYSYM, 296, "key.lightoverlay.category");
49 KeyMappingRegistry.register(enableOverlay);
51 registerDebugRenderer(renderer);
53 ClientGuiEvent.DEBUG_TEXT_LEFT.register(list -> {
56 list.add(String.format("[Light Overlay] Chunks to queue: %02d", ticker.POS.size()));
58 list.add("[Light Overlay] Enabled");
61 list.add("[Light Overlay] Disabled");
64 ClientTickEvent.CLIENT_POST.register(ticker::tick);
68 public static void queueChunkAndNear(CubicChunkPos pos) {
69 for (int xOffset = -1; xOffset <= 1; xOffset++) {
70 for (int yOffset = -1; yOffset <= 1; yOffset++) {
71 for (int zOffset = -1; zOffset <= 1; zOffset++) {
72 queueChunk(new CubicChunkPos(pos.x + xOffset, pos.y + yOffset, pos.z + zOffset));
78 public static void queueChunk(CubicChunkPos pos) {
79 ticker.queueChunk(pos);
82 public static int getChunkRange() {
83 return Math.max(Mth.ceil(reach / 16f), 1);
87 public static void loadConfig(File file) {
90 yellowColor = 0xFFFF00;
91 secondaryColor = 0x0000FF;
92 if (!file.exists() || !file.canRead())
94 FileInputStream fis = new FileInputStream(file);
95 Properties properties = new Properties();
98 reach = Integer.parseInt((String) properties.computeIfAbsent("reach", a -> "12"));
99 crossLevel = Integer.parseInt((String) properties.computeIfAbsent("crossLevel", a -> "0"));
100 secondaryLevel = Integer.parseInt((String) properties.computeIfAbsent("secondaryLevel", a -> "7"));
101 caching = ((String) properties.computeIfAbsent("caching", a -> "false")).equalsIgnoreCase("true");
102 showNumber = ((String) properties.computeIfAbsent("showNumber", a -> "false")).equalsIgnoreCase("true");
103 underwater = ((String) properties.computeIfAbsent("underwater", a -> "false")).equalsIgnoreCase("true");
104 mushroom = ((String) properties.computeIfAbsent("mushroom", a -> "false")).equalsIgnoreCase("true");
105 lineWidth = Float.parseFloat((String) properties.computeIfAbsent("lineWidth", a -> "1"));
108 r = Integer.parseInt((String) properties.computeIfAbsent("yellowColorRed", a -> "255"));
109 g = Integer.parseInt((String) properties.computeIfAbsent("yellowColorGreen", a -> "255"));
110 b = Integer.parseInt((String) properties.computeIfAbsent("yellowColorBlue", a -> "0"));
111 yellowColor = (r << 16) + (g << 8) + b;
115 r = Integer.parseInt((String) properties.computeIfAbsent("redColorRed", a -> "255"));
116 g = Integer.parseInt((String) properties.computeIfAbsent("redColorGreen", a -> "0"));
117 b = Integer.parseInt((String) properties.computeIfAbsent("redColorBlue", a -> "0"));
118 redColor = (r << 16) + (g << 8) + b;
122 r = Integer.parseInt((String) properties.computeIfAbsent("secondaryColorRed", a -> "0"));
123 g = Integer.parseInt((String) properties.computeIfAbsent("secondaryColorGreen", a -> "0"));
124 b = Integer.parseInt((String) properties.computeIfAbsent("secondaryColorBlue", a -> "255"));
125 secondaryColor = (r << 16) + (g << 8) + b;
128 } catch (Exception e) {
135 yellowColor = 0xFFFF00;
136 secondaryColor = 0x0000FF;
143 } catch (IOException ex) {
144 ex.printStackTrace();
147 if (secondaryLevel >= crossLevel) {
148 higherCross = CROSS_SECONDARY;
149 lowerCross = CROSS_YELLOW;
151 higherCross = CROSS_YELLOW;
152 lowerCross = CROSS_SECONDARY;
154 lowerCrossLevel = Math.min(crossLevel, secondaryLevel);
155 higherCrossLevel = Math.max(crossLevel, secondaryLevel);
156 ticker.CHUNK_MAP.clear();
160 public static void saveConfig(File file) throws IOException {
161 FileOutputStream fos = new FileOutputStream(file, false);
162 fos.write("# Light Overlay Config".getBytes());
163 fos.write("\n".getBytes());
164 fos.write(("reach=" + reach).getBytes());
165 fos.write("\n".getBytes());
166 fos.write(("crossLevel=" + crossLevel).getBytes());
167 fos.write("\n".getBytes());
168 fos.write(("secondaryLevel=" + secondaryLevel).getBytes());
169 fos.write("\n".getBytes());
170 fos.write(("caching=" + caching).getBytes());
171 fos.write("\n".getBytes());
172 fos.write(("showNumber=" + showNumber).getBytes());
173 fos.write("\n".getBytes());
174 fos.write(("underwater=" + underwater).getBytes());
175 fos.write("\n".getBytes());
176 fos.write(("mushroom=" + mushroom).getBytes());
177 fos.write("\n".getBytes());
178 fos.write(("lineWidth=" + FORMAT.format(lineWidth)).getBytes());
179 fos.write("\n".getBytes());
180 fos.write(("yellowColorRed=" + ((yellowColor >> 16) & 255)).getBytes());
181 fos.write("\n".getBytes());
182 fos.write(("yellowColorGreen=" + ((yellowColor >> 8) & 255)).getBytes());
183 fos.write("\n".getBytes());
184 fos.write(("yellowColorBlue=" + (yellowColor & 255)).getBytes());
185 fos.write("\n".getBytes());
186 fos.write(("redColorRed=" + ((redColor >> 16) & 255)).getBytes());
187 fos.write("\n".getBytes());
188 fos.write(("redColorGreen=" + ((redColor >> 8) & 255)).getBytes());
189 fos.write("\n".getBytes());
190 fos.write(("redColorBlue=" + (redColor & 255)).getBytes());
191 fos.write("\n".getBytes());
192 fos.write(("secondaryColorRed=" + ((secondaryColor >> 16) & 255)).getBytes());
193 fos.write("\n".getBytes());
194 fos.write(("secondaryColorGreen=" + ((secondaryColor >> 8) & 255)).getBytes());
195 fos.write("\n".getBytes());
196 fos.write(("secondaryColorBlue=" + (secondaryColor & 255)).getBytes());
200 private static KeyMapping createKeyBinding(ResourceLocation id, InputConstants.Type type, int code, String category) {
201 return new KeyMapping("key." + id.getNamespace() + "." + id.getPath(), type, code, category);
205 private static void registerDebugRenderer(Consumer<PoseStack> runnable) {
207 Class.forName("me.shedaniel.lightoverlay." + ArchitecturyTarget.getCurrentTarget() + ".LightOverlayImpl").getDeclaredField("debugRenderer").set(null, runnable);
208 } catch (Throwable throwable) {
209 throw new RuntimeException(throwable);
213 public static final byte CROSS_YELLOW = 0;
214 public static final byte CROSS_RED = 1;
215 public static final byte CROSS_SECONDARY = 2;
216 public static final byte CROSS_NONE = 3;
217 public static byte higherCross = CROSS_YELLOW;
218 public static byte lowerCross = CROSS_SECONDARY;