/.gradle
*/.gradle
/minecraft
+*/minecraft
/out
*/run
+*/out
/run
/classes
plugins {
- id("fabric-loom") version "0.4.3"
+ id("fabric-loom") version "0.4-SNAPSHOT"
}
minecraft {
package me.shedaniel.lightoverlay.fabric;
+import io.github.prospector.modmenu.api.ConfigScreenFactory;
import io.github.prospector.modmenu.api.ModMenuApi;
import me.shedaniel.clothconfig2.api.ConfigBuilder;
import me.shedaniel.clothconfig2.api.ConfigCategory;
import me.shedaniel.clothconfig2.api.ConfigEntryBuilder;
+import me.shedaniel.clothconfig2.gui.entries.IntegerSliderEntry;
import net.minecraft.client.gui.screen.Screen;
+import net.minecraft.client.resource.language.I18n;
import net.minecraft.util.math.MathHelper;
-import java.util.function.Function;
+import java.util.Optional;
public class LOModMenuEntry implements ModMenuApi {
@Override
}
@Override
- public Function<Screen, ? extends Screen> getConfigScreenFactory() {
+ public ConfigScreenFactory<?> getModConfigScreenFactory() {
return this::getConfigScreenByCloth;
}
ConfigEntryBuilder eb = builder.entryBuilder();
ConfigCategory general = builder.getOrCreateCategory("config.lightoverlay.general");
+ general.addEntry(eb.startTextDescription("§7" + I18n.translate("description.lightoverlay.caching")).build());
+ general.addEntry(eb.startBooleanToggle("config.lightoverlay.caching", LightOverlay.caching).setDefaultValue(false).setSaveConsumer(bool -> LightOverlay.caching = bool).build());
general.addEntry(eb.startIntSlider("config.lightoverlay.reach", LightOverlay.reach, 1, 64).setDefaultValue(12).setTextGetter(integer -> "Reach: " + integer + " Blocks").setSaveConsumer(integer -> LightOverlay.reach = integer).build());
- general.addEntry(eb.startIntSlider("config.lightoverlay.crossLevel", LightOverlay.crossLevel, 0, 15).setDefaultValue(7).setTextGetter(integer -> "Cross Level: " + integer).setSaveConsumer(integer -> LightOverlay.crossLevel = integer).build());
+ IntegerSliderEntry crossLevel = eb.startIntSlider("config.lightoverlay.crossLevel", LightOverlay.crossLevel, 0, 15).setDefaultValue(7).setTextGetter(integer -> "Cross Level: " + integer).setSaveConsumer(integer -> LightOverlay.crossLevel = integer).build();
+ general.addEntry(crossLevel);
+ general.addEntry(eb.startIntSlider("config.lightoverlay.secondaryLevel", LightOverlay.secondaryLevel, -1, 15)
+ .setErrorSupplier(integer -> {
+ if (integer >= 0 && integer >= crossLevel.getValue()) return Optional.of("Secondary Level cannot be higher than Cross Level!");
+ return Optional.empty();
+ }).setDefaultValue(-1).setTextGetter(integer -> integer < 0 ? "Off" : "Level: " + integer).setSaveConsumer(integer -> LightOverlay.secondaryLevel = integer).build());
general.addEntry(eb.startBooleanToggle("config.lightoverlay.showNumber", LightOverlay.showNumber).setDefaultValue(false).setSaveConsumer(bool -> LightOverlay.showNumber = bool).build());
general.addEntry(eb.startBooleanToggle("config.lightoverlay.smoothLines", LightOverlay.smoothLines).setDefaultValue(true).setSaveConsumer(bool -> LightOverlay.smoothLines = bool).build());
general.addEntry(eb.startBooleanToggle("config.lightoverlay.underwater", LightOverlay.underwater).setDefaultValue(false).setSaveConsumer(bool -> LightOverlay.underwater = bool).build());
general.addEntry(eb.startIntSlider("config.lightoverlay.lineWidth", MathHelper.floor(LightOverlay.lineWidth * 100), 100, 700).setDefaultValue(100).setTextGetter(integer -> "Light Width: " + LightOverlay.FORMAT.format(integer / 100d)).setSaveConsumer(integer -> LightOverlay.lineWidth = integer / 100f).build());
general.addEntry(eb.startColorField("config.lightoverlay.yellowColor", LightOverlay.yellowColor).setDefaultValue(0xFFFF00).setSaveConsumer(color -> LightOverlay.yellowColor = color).build());
general.addEntry(eb.startColorField("config.lightoverlay.redColor", LightOverlay.redColor).setDefaultValue(0xFF0000).setSaveConsumer(color -> LightOverlay.redColor = color).build());
+ general.addEntry(eb.startColorField("config.lightoverlay.secondaryColor", LightOverlay.secondaryColor).setDefaultValue(0x0000FF).setSaveConsumer(color -> LightOverlay.secondaryColor = color).build());
return builder.setSavingRunnable(() -> {
try {
import com.mojang.blaze3d.systems.RenderSystem;
import me.shedaniel.cloth.hooks.ClothClientHooks;
import net.fabricmc.api.ClientModInitializer;
-import net.fabricmc.fabric.api.client.keybinding.FabricKeyBinding;
-import net.fabricmc.fabric.api.client.keybinding.KeyBindingRegistry;
+import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper;
import net.fabricmc.fabric.api.event.client.ClientTickCallback;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.block.Block;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.network.ClientPlayerEntity;
-import net.minecraft.client.render.*;
+import net.minecraft.client.options.KeyBinding;
+import net.minecraft.client.render.Camera;
+import net.minecraft.client.render.Tessellator;
+import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.util.InputUtil;
import net.minecraft.client.util.math.Rotation3;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.tag.BlockTags;
-import net.minecraft.text.TranslatableText;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.*;
import net.minecraft.util.shape.VoxelShape;
import java.io.IOException;
import java.text.DecimalFormat;
import java.util.*;
-import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadPoolExecutor;
public class LightOverlay implements ClientModInitializer {
+
static final DecimalFormat FORMAT = new DecimalFormat("#.#");
private static final String KEYBIND_CATEGORY = "key.lightoverlay.category";
private static final Identifier ENABLE_OVERLAY_KEYBIND = new Identifier("lightoverlay", "enable_overlay");
- private static final Identifier INCREASE_REACH_KEYBIND = new Identifier("lightoverlay", "increase_reach");
- private static final Identifier DECREASE_REACH_KEYBIND = new Identifier("lightoverlay", "decrease_reach");
- private static final Identifier INCREASE_LINE_WIDTH_KEYBIND = new Identifier("lightoverlay", "increase_line_width");
- private static final Identifier DECREASE_LINE_WIDTH_KEYBIND = new Identifier("lightoverlay", "decrease_line_width");
static int reach = 12;
static int crossLevel = 7;
+ static int secondaryLevel = -1;
+ static int lowerCrossLevel = -1;
+ static int higherCrossLevel = -1;
+ static boolean caching = false;
static boolean showNumber = false;
static boolean smoothLines = true;
static boolean underwater = false;
static float lineWidth = 1.0F;
- static int yellowColor = 0xFFFF00, redColor = 0xFF0000;
+ static int yellowColor = 0xFFFF00, redColor = 0xFF0000, secondaryColor = 0x0000FF;
static File configFile = new File(FabricLoader.getInstance().getConfigDirectory(), "lightoverlay.properties");
- private static FabricKeyBinding enableOverlay, increaseReach, decreaseReach, increaseLineWidth, decreaseLineWidth;
+ private static final KeyBinding ENABLE_OVERLAY = createKeyBinding(ENABLE_OVERLAY_KEYBIND, InputUtil.Type.KEYSYM, 296, KEYBIND_CATEGORY);
private static boolean enabled = false;
private static EntityType<Entity> testingEntityType;
private static int threadNumber = 0;
- private static final ExecutorService EXECUTOR = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors(), r -> {
+ private static final ThreadPoolExecutor EXECUTOR = (ThreadPoolExecutor) Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors(), r -> {
Thread thread = new Thread(r, "light-overlay-" + threadNumber++);
thread.setDaemon(true);
return thread;
});
private static final List<ChunkPos> POS = Lists.newCopyOnWriteArrayList();
private static final Map<ChunkPos, Map<Long, Object>> CHUNK_MAP = Maps.newConcurrentMap();
+ private static final MinecraftClient CLIENT = MinecraftClient.getInstance();
private static long ticks = 0;
static {
ClientTickCallback.EVENT.register(client -> {
try {
ticks++;
- if (MinecraftClient.getInstance().player == null || !enabled) {
+ if (CLIENT.player == null || !enabled) {
POS.clear();
CHUNK_MAP.clear();
} else {
- ClientPlayerEntity player = MinecraftClient.getInstance().player;
- ClientWorld world = MinecraftClient.getInstance().world;
- EntityContext entityContext = EntityContext.of(player);
- Vec3d[] playerPos = {null};
- int playerPosX = ((int) player.getX()) >> 4;
- int playerPosZ = ((int) player.getZ()) >> 4;
- if (ticks % 20 == 0) {
- for (int chunkX = playerPosX - getChunkRange(); chunkX <= playerPosX + getChunkRange(); chunkX++) {
- for (int chunkZ = playerPosZ - getChunkRange(); chunkZ <= playerPosZ + getChunkRange(); chunkZ++) {
- ChunkPos chunkPos = new ChunkPos(chunkX, chunkZ);
- if (!CHUNK_MAP.containsKey(chunkPos))
- queueChunk(chunkPos);
+ if (!caching) {
+ POS.clear();
+ CHUNK_MAP.clear();
+ ClientPlayerEntity player = CLIENT.player;
+ ClientWorld world = CLIENT.world;
+ BlockPos playerPos = player.getBlockPos();
+ EntityContext entityContext = EntityContext.of(player);
+ ChunkLightingView block = world.getLightingProvider().get(LightType.BLOCK);
+ ChunkLightingView sky = showNumber ? null : world.getLightingProvider().get(LightType.SKY);
+ BlockPos.Mutable downPos = new BlockPos.Mutable();
+ Iterable<BlockPos> iterate = BlockPos.iterate(playerPos.getX() - reach, playerPos.getY() - reach, playerPos.getZ() - reach,
+ playerPos.getX() + reach, playerPos.getY() + reach, playerPos.getZ() + reach);
+ HashMap<Long, Object> map = Maps.newHashMap();
+ CHUNK_MAP.put(new ChunkPos(0, 0), map);
+ for (BlockPos blockPos : iterate) {
+ downPos.set(blockPos.getX(), blockPos.getY() - 1, blockPos.getZ());
+ if (showNumber) {
+ int level = getCrossLevel(blockPos, downPos, world, block, entityContext);
+ if (level >= 0) {
+ map.put(blockPos.asLong(), level);
+ }
+ } else {
+ CrossType type = getCrossType(blockPos, downPos, world, block, sky, entityContext);
+ if (type != CrossType.NONE) {
+ map.put(blockPos.asLong(), type);
+ }
}
}
- }
- if (!POS.isEmpty()) {
- if (playerPos[0] == null) {
- playerPos[0] = player.getPos();
+ } else {
+ ClientPlayerEntity player = CLIENT.player;
+ ClientWorld world = CLIENT.world;
+ EntityContext entityContext = EntityContext.of(player);
+ Vec3d[] playerPos = {null};
+ int playerPosX = ((int) player.getX()) >> 4;
+ int playerPosZ = ((int) player.getZ()) >> 4;
+ if (ticks % 20 == 0) {
+ for (int chunkX = playerPosX - getChunkRange(); chunkX <= playerPosX + getChunkRange(); chunkX++) {
+ for (int chunkZ = playerPosZ - getChunkRange(); chunkZ <= playerPosZ + getChunkRange(); chunkZ++) {
+ ChunkPos chunkPos = new ChunkPos(chunkX, chunkZ);
+ if (!CHUNK_MAP.containsKey(chunkPos))
+ queueChunk(chunkPos);
+ }
+ }
}
- ChunkPos pos = POS.stream().min(Comparator.comparingDouble(value -> value.toBlockPos(8, 0, 8).getSquaredDistance(playerPos[0].x, 0, playerPos[0].z, false))).get();
- EXECUTOR.submit(() -> {
- if (MathHelper.abs(pos.x - playerPosX) <= getChunkRange() && MathHelper.abs(pos.z - playerPosZ) <= getChunkRange()) {
- calculateChunk(world.getChunkManager().getChunk(pos.x, pos.z, ChunkStatus.FULL, false), world, pos, entityContext);
- } else {
- CHUNK_MAP.remove(pos);
+ if (!POS.isEmpty()) {
+ if (playerPos[0] == null) {
+ playerPos[0] = player.getPos();
+ }
+ ChunkPos pos = POS.stream().min(Comparator.comparingDouble(value -> value.toBlockPos(8, 0, 8).getSquaredDistance(playerPos[0].x, 0, playerPos[0].z, false))).get();
+ POS.remove(pos);
+ EXECUTOR.submit(() -> {
+ if (MathHelper.abs(pos.x - playerPosX) <= getChunkRange() && MathHelper.abs(pos.z - playerPosZ) <= getChunkRange()) {
+ calculateChunk(world.getChunkManager().getChunk(pos.x, pos.z, ChunkStatus.FULL, false), world, pos, entityContext);
+ } else {
+ CHUNK_MAP.remove(pos);
+ }
+ });
+ }
+ if (ticks % 50 == 0) {
+ Iterator<Map.Entry<ChunkPos, Map<Long, Object>>> chunkMapIterator = CHUNK_MAP.entrySet().iterator();
+ while (chunkMapIterator.hasNext()) {
+ Map.Entry<ChunkPos, Map<Long, Object>> pos = chunkMapIterator.next();
+ if (MathHelper.abs(pos.getKey().x - playerPosX) > getChunkRange() * 2 || MathHelper.abs(pos.getKey().z - playerPosZ) > getChunkRange() * 2) {
+ chunkMapIterator.remove();
+ }
}
- });
- POS.remove(pos);
- }
- Iterator<Map.Entry<ChunkPos, Map<Long, Object>>> chunkMapIterator = CHUNK_MAP.entrySet().iterator();
- while (chunkMapIterator.hasNext()) {
- Map.Entry<ChunkPos, Map<Long, Object>> pos = chunkMapIterator.next();
- if (MathHelper.abs(pos.getKey().x - playerPosX) > getChunkRange() * 2 || MathHelper.abs(pos.getKey().z - playerPosZ) > getChunkRange() * 2) {
- chunkMapIterator.remove();
}
}
}
}
public static void queueChunk(ChunkPos pos) {
- if (!POS.contains(pos))
- POS.add(0, pos);
+ if (caching)
+ if (!POS.contains(pos))
+ POS.add(0, pos);
}
public static int getChunkRange() {
private static void calculateChunk(WorldChunk chunk, World world, ChunkPos chunkPos, EntityContext entityContext) {
Map<Long, Object> map = Maps.newHashMap();
- if (chunk != null) {
- ChunkLightingView block = chunk.getLightingProvider().get(LightType.BLOCK);
- ChunkLightingView sky = showNumber ? null : chunk.getLightingProvider().get(LightType.SKY);
+ if (world != null) {
+ ChunkLightingView block = world.getLightingProvider().get(LightType.BLOCK);
+ ChunkLightingView sky = showNumber ? null : world.getLightingProvider().get(LightType.SKY);
for (BlockPos pos : BlockPos.iterate(chunkPos.getStartX(), 0, chunkPos.getStartZ(), chunkPos.getEndX(), 256, chunkPos.getEndZ())) {
BlockPos down = pos.down();
if (showNumber) {
// Check block state allow spawning (excludes bedrock and barriers automatically)
if (!blockBelowState.allowsSpawning(world, down, testingEntityType))
return CrossType.NONE;
- if (block.getLightLevel(pos) > crossLevel)
+ int blockLightLevel = block.getLightLevel(pos);
+ int skyLightLevel = sky.getLightLevel(pos);
+ if (blockLightLevel > higherCrossLevel)
return CrossType.NONE;
- if (sky.getLightLevel(pos) > crossLevel)
+ if (skyLightLevel > higherCrossLevel)
return CrossType.YELLOW;
- return CrossType.RED;
+ return lowerCrossLevel >= 0 && blockLightLevel > lowerCrossLevel ? CrossType.SECONDARY : CrossType.RED;
}
public static int getCrossLevel(BlockPos pos, BlockPos down, BlockView world, ChunkLightingView view, EntityContext entityContext) {
return view.getLightLevel(pos);
}
- public static void renderCross(Tessellator tessellator, BufferBuilder buffer, Camera camera, World world, BlockPos pos, int color, EntityContext entityContext) {
+ public static void renderCross(Camera camera, World world, BlockPos pos, int color, EntityContext entityContext) {
double d0 = camera.getPos().x;
double d1 = camera.getPos().y - .005D;
VoxelShape upperOutlineShape = world.getBlockState(pos).getOutlineShape(world, pos, entityContext);
d1 -= upperOutlineShape.getMaximum(Direction.Axis.Y);
double d2 = camera.getPos().z;
- buffer.begin(1, VertexFormats.POSITION_COLOR);
int red = (color >> 16) & 255;
int green = (color >> 8) & 255;
int blue = color & 255;
- buffer.vertex(pos.getX() + .01 - d0, pos.getY() - d1, pos.getZ() + .01 - d2).color(red, green, blue, 255).next();
- buffer.vertex(pos.getX() - .01 + 1 - d0, pos.getY() - d1, pos.getZ() - .01 + 1 - d2).color(red, green, blue, 255).next();
- buffer.vertex(pos.getX() - .01 + 1 - d0, pos.getY() - d1, pos.getZ() + .01 - d2).color(red, green, blue, 255).next();
- buffer.vertex(pos.getX() + .01 - d0, pos.getY() - d1, pos.getZ() - .01 + 1 - d2).color(red, green, blue, 255).next();
- tessellator.draw();
+ int x = pos.getX();
+ int y = pos.getY();
+ int z = pos.getZ();
+ RenderSystem.color4f(red / 255f, green / 255f, blue / 255f, 1f);
+ GL11.glVertex3d(x + .01 - d0, y - d1, z + .01 - d2);
+ GL11.glVertex3d(x - .01 + 1 - d0, y - d1, z - .01 + 1 - d2);
+ GL11.glVertex3d(x - .01 + 1 - d0, y - d1, z + .01 - d2);
+ GL11.glVertex3d(x + .01 - d0, y - d1, z - .01 + 1 - d2);
}
+ @SuppressWarnings("deprecation")
public static void renderLevel(MinecraftClient client, Camera camera, World world, BlockPos pos, BlockPos down, int level, EntityContext entityContext) {
- String string_1 = String.valueOf(level);
+ String text = String.valueOf(level);
TextRenderer textRenderer_1 = client.textRenderer;
double double_4 = camera.getPos().x;
double double_5 = camera.getPos().y;
RenderSystem.normal3f(0.0F, 1.0F, 0.0F);
float size = 0.07F;
RenderSystem.scalef(-size, -size, size);
- float float_3 = (float) (-textRenderer_1.getStringWidth(string_1)) / 2.0F + 0.4f;
+ float float_3 = (float) (-textRenderer_1.getStringWidth(text)) / 2.0F + 0.4f;
RenderSystem.enableAlphaTest();
- VertexConsumerProvider.Immediate vertexConsumerProvider$Immediate_1 = VertexConsumerProvider.immediate(Tessellator.getInstance().getBuffer());
- textRenderer_1.draw(string_1, float_3, -3.5f, level > crossLevel ? 0xff042404 : 0xff731111, false, Rotation3.identity().getMatrix(), vertexConsumerProvider$Immediate_1, false, 0, 15728880);
- vertexConsumerProvider$Immediate_1.draw();
+ VertexConsumerProvider.Immediate immediate = VertexConsumerProvider.immediate(Tessellator.getInstance().getBuffer());
+ textRenderer_1.draw(text, float_3, -3.5f, level > higherCrossLevel ? 0xff042404 : (lowerCrossLevel >= 0 && level > lowerCrossLevel ? 0xff0066ff : 0xff731111), false, Rotation3.identity().getMatrix(), immediate, false, 0, 15728880);
+ immediate.draw();
RenderSystem.popMatrix();
}
try {
redColor = 0xFF0000;
yellowColor = 0xFFFF00;
+ secondaryColor = 0x0000FF;
if (!file.exists() || !file.canRead())
saveConfig(file);
FileInputStream fis = new FileInputStream(file);
fis.close();
reach = Integer.parseInt((String) properties.computeIfAbsent("reach", a -> "12"));
crossLevel = Integer.parseInt((String) properties.computeIfAbsent("crossLevel", a -> "7"));
+ secondaryLevel = Integer.parseInt((String) properties.computeIfAbsent("secondaryLevel", a -> "-1"));
+ caching = ((String) properties.computeIfAbsent("caching", a -> "false")).equalsIgnoreCase("true");
showNumber = ((String) properties.computeIfAbsent("showNumber", a -> "false")).equalsIgnoreCase("true");
smoothLines = ((String) properties.computeIfAbsent("smoothLines", a -> "true")).equalsIgnoreCase("true");
underwater = ((String) properties.computeIfAbsent("underwater", a -> "false")).equalsIgnoreCase("true");
b = Integer.parseInt((String) properties.computeIfAbsent("redColorBlue", a -> "0"));
redColor = (r << 16) + (g << 8) + b;
}
+ {
+ int r, g, b;
+ r = Integer.parseInt((String) properties.computeIfAbsent("secondaryColorRed", a -> "0"));
+ g = Integer.parseInt((String) properties.computeIfAbsent("secondaryColorGreen", a -> "0"));
+ b = Integer.parseInt((String) properties.computeIfAbsent("secondaryColorBlue", a -> "255"));
+ secondaryColor = (r << 16) + (g << 8) + b;
+ }
saveConfig(file);
} catch (Exception e) {
e.printStackTrace();
reach = 12;
crossLevel = 7;
+ secondaryLevel = -1;
lineWidth = 1.0F;
redColor = 0xFF0000;
yellowColor = 0xFFFF00;
+ secondaryColor = 0x0000FF;
+ caching = false;
showNumber = false;
smoothLines = true;
underwater = false;
ex.printStackTrace();
}
}
+ if (secondaryLevel >= crossLevel) System.err.println("[Light Overlay] Secondary Level is higher than Cross Level");
+ lowerCrossLevel = Math.min(crossLevel, secondaryLevel);
+ higherCrossLevel = Math.max(crossLevel, secondaryLevel);
CHUNK_MAP.clear();
POS.clear();
}
fos.write("\n".getBytes());
fos.write(("crossLevel=" + crossLevel).getBytes());
fos.write("\n".getBytes());
+ fos.write(("secondaryLevel=" + secondaryLevel).getBytes());
+ fos.write("\n".getBytes());
+ fos.write(("caching=" + caching).getBytes());
+ fos.write("\n".getBytes());
fos.write(("showNumber=" + showNumber).getBytes());
fos.write("\n".getBytes());
fos.write(("smoothLines=" + smoothLines).getBytes());
fos.write(("redColorGreen=" + ((redColor >> 8) & 255)).getBytes());
fos.write("\n".getBytes());
fos.write(("redColorBlue=" + (redColor & 255)).getBytes());
+ fos.write("\n".getBytes());
+ fos.write(("secondaryColorRed=" + ((secondaryColor >> 16) & 255)).getBytes());
+ fos.write("\n".getBytes());
+ fos.write(("secondaryColorGreen=" + ((secondaryColor >> 8) & 255)).getBytes());
+ fos.write("\n".getBytes());
+ fos.write(("secondaryColorBlue=" + (secondaryColor & 255)).getBytes());
fos.close();
}
+ private static KeyBinding createKeyBinding(Identifier id, InputUtil.Type type, int code, String category) {
+ return KeyBindingHelper.registerKeyBinding(new KeyBinding("key." + id.getNamespace() + "." + id.getPath(), type, code, category));
+ }
+
@Override
public void onInitializeClient() {
// Load Config
// Setup
testingEntityType = EntityType.Builder.create(EntityCategory.MONSTER).setDimensions(0f, 0f).disableSaving().build(null);
- MinecraftClient client = MinecraftClient.getInstance();
- KeyBindingRegistry.INSTANCE.addCategory(KEYBIND_CATEGORY);
- KeyBindingRegistry.INSTANCE.register(enableOverlay = FabricKeyBinding.Builder.create(ENABLE_OVERLAY_KEYBIND, InputUtil.Type.KEYSYM, 296, KEYBIND_CATEGORY).build());
- KeyBindingRegistry.INSTANCE.register(increaseReach = FabricKeyBinding.Builder.create(INCREASE_REACH_KEYBIND, InputUtil.Type.KEYSYM, -1, KEYBIND_CATEGORY).build());
- KeyBindingRegistry.INSTANCE.register(decreaseReach = FabricKeyBinding.Builder.create(DECREASE_REACH_KEYBIND, InputUtil.Type.KEYSYM, -1, KEYBIND_CATEGORY).build());
- KeyBindingRegistry.INSTANCE.register(increaseLineWidth = FabricKeyBinding.Builder.create(INCREASE_LINE_WIDTH_KEYBIND, InputUtil.Type.KEYSYM, -1, KEYBIND_CATEGORY).build());
- KeyBindingRegistry.INSTANCE.register(decreaseLineWidth = FabricKeyBinding.Builder.create(DECREASE_LINE_WIDTH_KEYBIND, InputUtil.Type.KEYSYM, -1, KEYBIND_CATEGORY).build());
- ClothClientHooks.HANDLE_INPUT.register(minecraftClient -> {
- while (enableOverlay.wasPressed())
+ ClientTickCallback.EVENT.register(minecraftClient -> {
+ while (ENABLE_OVERLAY.wasPressed())
enabled = !enabled;
- while (increaseReach.wasPressed()) {
- if (reach < 64)
- reach++;
- try {
- saveConfig(configFile);
- } catch (IOException e) {
- e.printStackTrace();
- }
- client.player.addChatMessage(new TranslatableText("text.lightoverlay.current_reach", reach), false);
- }
- while (decreaseReach.wasPressed()) {
- if (reach > 1)
- reach--;
- try {
- saveConfig(configFile);
- } catch (IOException e) {
- e.printStackTrace();
- }
- client.player.addChatMessage(new TranslatableText("text.lightoverlay.current_reach", reach), false);
- }
- while (increaseLineWidth.wasPressed()) {
- if (lineWidth < 7)
- lineWidth += 0.1f;
- try {
- saveConfig(configFile);
- } catch (IOException e) {
- e.printStackTrace();
- }
- client.player.addChatMessage(new TranslatableText("text.lightoverlay.current_line_width", FORMAT.format(lineWidth)), false);
- }
- while (decreaseLineWidth.wasPressed()) {
- if (lineWidth > 1)
- lineWidth -= 0.1F;
- try {
- saveConfig(configFile);
- } catch (IOException e) {
- e.printStackTrace();
- }
- client.player.addChatMessage(new TranslatableText("text.lightoverlay.current_line_width", FORMAT.format(lineWidth)), false);
- }
});
ClothClientHooks.DEBUG_RENDER_PRE.register(() -> {
if (LightOverlay.enabled) {
- PlayerEntity playerEntity = client.player;
+ PlayerEntity playerEntity = CLIENT.player;
int playerPosX = ((int) playerEntity.getX()) >> 4;
int playerPosZ = ((int) playerEntity.getZ()) >> 4;
EntityContext entityContext = EntityContext.of(playerEntity);
- World world = client.world;
+ World world = CLIENT.world;
BlockPos playerPos = new BlockPos(playerEntity.getX(), playerEntity.getY(), playerEntity.getZ());
- Camera camera = MinecraftClient.getInstance().gameRenderer.getCamera();
+ Camera camera = CLIENT.gameRenderer.getCamera();
if (showNumber) {
RenderSystem.enableTexture();
RenderSystem.depthMask(true);
BlockPos.Mutable mutable = new BlockPos.Mutable();
for (Map.Entry<ChunkPos, Map<Long, Object>> entry : CHUNK_MAP.entrySet()) {
- if (MathHelper.abs(entry.getKey().x - playerPosX) > getChunkRange() || MathHelper.abs(entry.getKey().z - playerPosZ) > getChunkRange()) {
+ if (caching && (MathHelper.abs(entry.getKey().x - playerPosX) > getChunkRange() || MathHelper.abs(entry.getKey().z - playerPosZ) > getChunkRange())) {
continue;
}
for (Map.Entry<Long, Object> objectEntry : entry.getValue().entrySet()) {
mutable.set(BlockPos.unpackLongX(objectEntry.getKey()), BlockPos.unpackLongY(objectEntry.getKey()), BlockPos.unpackLongZ(objectEntry.getKey()));
if (mutable.isWithinDistance(playerPos, reach)) {
BlockPos down = mutable.down();
- LightOverlay.renderLevel(client, camera, world, mutable, down, (Integer) objectEntry.getValue(), entityContext);
+ LightOverlay.renderLevel(CLIENT, camera, world, mutable, down, (Integer) objectEntry.getValue(), entityContext);
}
}
}
}
- RenderSystem.color4f(1.0F, 1.0F, 1.0F, 1.0F);
RenderSystem.enableDepthTest();
} else {
RenderSystem.enableDepthTest();
RenderSystem.disableTexture();
RenderSystem.enableBlend();
RenderSystem.blendFunc(GlStateManager.SrcFactor.SRC_ALPHA, GlStateManager.DstFactor.ONE_MINUS_SRC_ALPHA);
- RenderSystem.disableLighting();
if (smoothLines) GL11.glEnable(GL11.GL_LINE_SMOOTH);
- RenderSystem.lineWidth(lineWidth);
- Tessellator tessellator = Tessellator.getInstance();
- BufferBuilder buffer = tessellator.getBuffer();
+ GL11.glLineWidth(lineWidth);
+ GL11.glBegin(GL11.GL_LINES);
BlockPos.Mutable mutable = new BlockPos.Mutable();
for (Map.Entry<ChunkPos, Map<Long, Object>> entry : CHUNK_MAP.entrySet()) {
- if (MathHelper.abs(entry.getKey().x - playerPosX) > getChunkRange() || MathHelper.abs(entry.getKey().z - playerPosZ) > getChunkRange()) {
+ if (caching && (MathHelper.abs(entry.getKey().x - playerPosX) > getChunkRange() || MathHelper.abs(entry.getKey().z - playerPosZ) > getChunkRange())) {
continue;
}
for (Map.Entry<Long, Object> objectEntry : entry.getValue().entrySet()) {
mutable.set(BlockPos.unpackLongX(objectEntry.getKey()), BlockPos.unpackLongY(objectEntry.getKey()), BlockPos.unpackLongZ(objectEntry.getKey()));
if (mutable.isWithinDistance(playerPos, reach)) {
BlockPos down = mutable.down();
- int color = objectEntry.getValue() == CrossType.RED ? redColor : yellowColor;
- LightOverlay.renderCross(tessellator, buffer, camera, world, mutable, color, entityContext);
+ int color = objectEntry.getValue() == CrossType.RED ? redColor : objectEntry.getValue() == CrossType.YELLOW ? yellowColor : secondaryColor;
+ LightOverlay.renderCross(camera, world, mutable, color, entityContext);
}
}
}
}
+ GL11.glEnd();
RenderSystem.disableBlend();
RenderSystem.enableTexture();
if (smoothLines) GL11.glDisable(GL11.GL_LINE_SMOOTH);
private enum CrossType {
YELLOW,
RED,
+ SECONDARY,
NONE
}
}
import net.minecraft.network.packet.s2c.play.BlockUpdateS2CPacket;
import net.minecraft.network.packet.s2c.play.ChunkDataS2CPacket;
import net.minecraft.network.packet.s2c.play.ChunkDeltaUpdateS2CPacket;
+import net.minecraft.network.packet.s2c.play.LightUpdateS2CPacket;
import net.minecraft.util.math.ChunkPos;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
LightOverlay.queueChunkAndNear(new ChunkPos(((ChunkDataS2CPacket) packet).getX(), ((ChunkDataS2CPacket) packet).getZ()));
} else if (packet instanceof ChunkDeltaUpdateS2CPacket) {
LightOverlay.queueChunkAndNear(new ChunkPos(((ChunkDeltaUpdateS2CPacket) packet).chunkPos.x, ((ChunkDeltaUpdateS2CPacket) packet).chunkPos.z));
+ } else if (packet instanceof LightUpdateS2CPacket) {
+ LightOverlay.queueChunk(new ChunkPos(((LightUpdateS2CPacket) packet).getChunkX(), ((LightUpdateS2CPacket) packet).getChunkZ()));
}
}
}
{
"key.lightoverlay.category": "Light Overlay",
"key.lightoverlay.enable_overlay": "Toggle Light Overlay",
- "key.lightoverlay.decrease_reach": "Decrease Light Overlay's Reach",
- "key.lightoverlay.increase_reach": "Increase Light Overlay's Reach",
- "key.lightoverlay.increase_line_width": "Increase Light Overlay's Line Width",
- "key.lightoverlay.decrease_line_width": "Decrease Light Overlay's Line Width",
- "text.lightoverlay.current_reach": "The current reach is %d!",
- "text.lightoverlay.current_line_width": "The current line width is %s!",
+ "description.lightoverlay.caching": "Caching is recommended if the reach is above 16 or if you are running on a potato.",
"config.lightoverlay.general": "General",
"config.lightoverlay.reach": "Reach:",
+ "config.lightoverlay.caching": "Caching:",
"config.lightoverlay.crossLevel": "Light Level:",
+ "config.lightoverlay.secondaryLevel": "Secondary Light Level:",
"config.lightoverlay.showNumber": "Show Number Instead:",
"config.lightoverlay.smoothLines": "Smooth Lines:",
"config.lightoverlay.underwater": "Display Underwater:",
"config.lightoverlay.lineWidth": "Line Width:",
"config.lightoverlay.yellowColor": "Yellow Color:",
+ "config.lightoverlay.secondaryColor": "Secondary Color:",
"config.lightoverlay.redColor": "Red Color:",
"config.lightoverlay.invalidColor": "Invalid Color"
}
\ No newline at end of file
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
+import com.mojang.blaze3d.platform.GlStateManager;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.player.ClientPlayerEntity;
import net.minecraft.client.gui.FontRenderer;
-import net.minecraft.client.renderer.*;
-import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
+import net.minecraft.client.renderer.ActiveRenderInfo;
+import net.minecraft.client.renderer.IRenderTypeBuffer;
+import net.minecraft.client.renderer.Tessellator;
+import net.minecraft.client.renderer.TransformationMatrix;
import net.minecraft.client.settings.KeyBinding;
import net.minecraft.client.util.InputMappings;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.network.play.server.SChangeBlockPacket;
import net.minecraft.network.play.server.SChunkDataPacket;
import net.minecraft.network.play.server.SMultiBlockChangePacket;
+import net.minecraft.network.play.server.SUpdateLightPacket;
import net.minecraft.tags.BlockTags;
import net.minecraft.util.Direction;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.shapes.ISelectionContext;
import net.minecraft.util.math.shapes.VoxelShape;
-import net.minecraft.util.text.TranslationTextComponent;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.LightType;
import net.minecraft.world.World;
public class LightOverlayClient {
static final DecimalFormat FORMAT = new DecimalFormat("#.#");
- private static final String KEYBIND_CATEGORY = "key.lightoverlay-forge.category";
- private static final ResourceLocation ENABLE_OVERLAY_KEYBIND = new ResourceLocation("lightoverlay-forge", "enable_overlay");
- private static final ResourceLocation INCREASE_REACH_KEYBIND = new ResourceLocation("lightoverlay-forge", "increase_reach");
- private static final ResourceLocation DECREASE_REACH_KEYBIND = new ResourceLocation("lightoverlay-forge", "decrease_reach");
- private static final ResourceLocation INCREASE_LINE_WIDTH_KEYBIND = new ResourceLocation("lightoverlay-forge", "increase_line_width");
- private static final ResourceLocation DECREASE_LINE_WIDTH_KEYBIND = new ResourceLocation("lightoverlay-forge", "decrease_line_width");
+ private static final String KEYBIND_CATEGORY = "key.lightoverlay.category";
+ private static final ResourceLocation ENABLE_OVERLAY_KEYBIND = new ResourceLocation("lightoverlay", "enable_overlay");
static int reach = 12;
static int crossLevel = 7;
+ static int secondaryLevel = -1;
+ static int lowerCrossLevel = -1;
+ static int higherCrossLevel = -1;
+ static boolean caching = false;
static boolean showNumber = false;
static boolean smoothLines = true;
static boolean underwater = false;
- static EntityType<Entity> testingEntityType;
static float lineWidth = 1.0F;
- static int yellowColor = 0xFFFF00, redColor = 0xFF0000;
+ static int yellowColor = 0xFFFF00, redColor = 0xFF0000, secondaryColor = 0x0000FF;
static File configFile = new File(new File(Minecraft.getInstance().gameDir, "config"), "lightoverlay.properties");
- private static KeyBinding enableOverlay, increaseReach, decreaseReach, increaseLineWidth, decreaseLineWidth;
+ private static final KeyBinding ENABLE_OVERLAY;
private static boolean enabled = false;
+ private static EntityType<Entity> testingEntityType;
private static int threadNumber = 0;
private static final ExecutorService EXECUTOR = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors(), r -> {
Thread thread = new Thread(r, "light-overlay-" + threadNumber++);
private static final Map<ChunkPos, Map<Long, Object>> CHUNK_MAP = Maps.newConcurrentMap();
private static long ticks = 0;
+ static {
+ ENABLE_OVERLAY = registerKeybind(ENABLE_OVERLAY_KEYBIND, InputMappings.Type.KEYSYM, 296, KEYBIND_CATEGORY);
+ }
+
public static void register() {
// Load Config
loadConfig(configFile);
// Setup
testingEntityType = EntityType.Builder.create(EntityClassification.MONSTER).size(0f, 0f).disableSerialization().build(null);
- enableOverlay = registerKeybind(ENABLE_OVERLAY_KEYBIND, InputMappings.Type.KEYSYM, 296, KEYBIND_CATEGORY);
- increaseReach = registerKeybind(INCREASE_REACH_KEYBIND, InputMappings.Type.KEYSYM, -1, KEYBIND_CATEGORY);
- decreaseReach = registerKeybind(DECREASE_REACH_KEYBIND, InputMappings.Type.KEYSYM, -1, KEYBIND_CATEGORY);
- increaseLineWidth = registerKeybind(INCREASE_LINE_WIDTH_KEYBIND, InputMappings.Type.KEYSYM, -1, KEYBIND_CATEGORY);
- decreaseLineWidth = registerKeybind(DECREASE_LINE_WIDTH_KEYBIND, InputMappings.Type.KEYSYM, -1, KEYBIND_CATEGORY);
MinecraftForge.EVENT_BUS.register(LightOverlayClient.class);
try {
VoxelShape upperCollisionShape = blockUpperState.getCollisionShape(reader, pos, selectionContext);
if (!underwater && !blockUpperState.getFluidState().isEmpty())
return CrossType.NONE;
- /* WorldEntitySpawner.func_222266_a */
// Check if the outline is full
if (Block.doesSideFillSquare(upperCollisionShape, Direction.UP))
return CrossType.NONE;
// Check block state allow spawning (excludes bedrock and barriers automatically)
if (!blockBelowState.canEntitySpawn(reader, down, testingEntityType))
return CrossType.NONE;
- if (block.getLightFor(pos) > crossLevel)
+ int blockLightLevel = block.getLightFor(pos);
+ int skyLightLevel = sky.getLightFor(pos);
+ if (blockLightLevel > higherCrossLevel)
return CrossType.NONE;
- if (sky.getLightFor(pos) > crossLevel)
+ if (skyLightLevel > higherCrossLevel)
return CrossType.YELLOW;
- return CrossType.RED;
+ return lowerCrossLevel >= 0 && blockLightLevel > lowerCrossLevel ? CrossType.SECONDARY : CrossType.RED;
}
public static int getCrossLevel(BlockPos pos, BlockPos down, IBlockReader reader, IWorldLightListener light, ISelectionContext context) {
return light.getLightFor(pos);
}
- public static void renderCross(ActiveRenderInfo info, Tessellator tessellator, BufferBuilder buffer, World world, BlockPos pos, int color, ISelectionContext context) {
+ public static void renderCross(ActiveRenderInfo info, World world, BlockPos pos, int color, ISelectionContext context) {
double d0 = info.getProjectedView().x;
double d1 = info.getProjectedView().y - .005D;
VoxelShape upperOutlineShape = world.getBlockState(pos).getShape(world, pos, context);
if (!upperOutlineShape.isEmpty())
d1 -= upperOutlineShape.getEnd(Direction.Axis.Y);
double d2 = info.getProjectedView().z;
- buffer.begin(1, DefaultVertexFormats.POSITION_COLOR);
int red = (color >> 16) & 255;
int green = (color >> 8) & 255;
int blue = color & 255;
- buffer.pos(pos.getX() + .01 - d0, pos.getY() - d1, pos.getZ() + .01 - d2).color(red, green, blue, 255).endVertex();
- buffer.pos(pos.getX() - .01 + 1 - d0, pos.getY() - d1, pos.getZ() - .01 + 1 - d2).color(red, green, blue, 255).endVertex();
- buffer.pos(pos.getX() - .01 + 1 - d0, pos.getY() - d1, pos.getZ() + .01 - d2).color(red, green, blue, 255).endVertex();
- buffer.pos(pos.getX() + .01 - d0, pos.getY() - d1, pos.getZ() - .01 + 1 - d2).color(red, green, blue, 255).endVertex();
- tessellator.draw();
+ int x = pos.getX();
+ int y = pos.getY();
+ int z = pos.getZ();
+ RenderSystem.color4f(red / 255f, green / 255f, blue / 255f, 1f);
+ GL11.glVertex3d(x + .01 - d0, y - d1, z + .01 - d2);
+ GL11.glVertex3d(x - .01 + 1 - d0, y - d1, z - .01 + 1 - d2);
+ GL11.glVertex3d(x - .01 + 1 - d0, y - d1, z + .01 - d2);
+ GL11.glVertex3d(x + .01 - d0, y - d1, z - .01 + 1 - d2);
}
public static void renderLevel(Minecraft minecraft, ActiveRenderInfo info, World world, BlockPos pos, BlockPos down, int level, ISelectionContext context) {
float float_3 = (float) (-fontRenderer.getStringWidth(string_1)) / 2.0F + 0.4f;
RenderSystem.enableAlphaTest();
IRenderTypeBuffer.Impl vertexConsumerProvider$Immediate_1 = IRenderTypeBuffer.getImpl(Tessellator.getInstance().getBuffer());
- fontRenderer.renderString(string_1, float_3, -3.5f, level > crossLevel ? 0xff042404 : 0xff731111, false, TransformationMatrix.identity().getMatrix(), vertexConsumerProvider$Immediate_1, false, 0, 15728880);
+ fontRenderer.renderString(string_1, float_3, -3.5f, level > higherCrossLevel ? 0xff042404 : (lowerCrossLevel >= 0 && level > lowerCrossLevel ? 0xff0066ff : 0xff731111), false, TransformationMatrix.identity().getMatrix(), vertexConsumerProvider$Immediate_1, false, 0, 15728880);
vertexConsumerProvider$Immediate_1.finish();
RenderSystem.popMatrix();
}
@SubscribeEvent(receiveCanceled = true)
public static void handleInput(InputEvent.KeyInputEvent event) {
- if (enableOverlay.isPressed())
+ if (ENABLE_OVERLAY.isPressed())
enabled = !enabled;
- if (increaseReach.isPressed()) {
- if (reach < 64)
- reach++;
- try {
- saveConfig(configFile);
- } catch (IOException e) {
- e.printStackTrace();
- }
- Minecraft.getInstance().player.sendStatusMessage(new TranslationTextComponent("text.lightoverlay-forge.current_reach", reach), false);
- }
- if (decreaseReach.isPressed()) {
- if (reach > 1)
- reach--;
- try {
- saveConfig(configFile);
- } catch (IOException e) {
- e.printStackTrace();
- }
- Minecraft.getInstance().player.sendStatusMessage(new TranslationTextComponent("text.lightoverlay-forge.current_reach", reach), false);
- }
- if (increaseLineWidth.isPressed()) {
- if (lineWidth < 7)
- lineWidth += 0.1f;
- try {
- saveConfig(configFile);
- } catch (IOException e) {
- e.printStackTrace();
- }
- Minecraft.getInstance().player.sendStatusMessage(new TranslationTextComponent("text.lightoverlay-forge.current_line_width", FORMAT.format(lineWidth)), false);
- }
- if (decreaseLineWidth.isPressed()) {
- if (lineWidth > 1)
- lineWidth -= 0.1F;
- try {
- saveConfig(configFile);
- } catch (IOException e) {
- e.printStackTrace();
- }
- Minecraft.getInstance().player.sendStatusMessage(new TranslationTextComponent("text.lightoverlay-forge.current_line_width", FORMAT.format(lineWidth)), false);
- }
}
public static void queueChunkAndNear(ChunkPos pos) {
}
public static void queueChunk(ChunkPos pos) {
- if (!POS.contains(pos))
- POS.add(0, pos);
+ if (caching)
+ if (!POS.contains(pos))
+ POS.add(0, pos);
}
public static int getChunkRange() {
POS.clear();
CHUNK_MAP.clear();
} else {
- ClientPlayerEntity player = minecraft.player;
- ClientWorld world = minecraft.world;
- ISelectionContext selectionContext = ISelectionContext.forEntity(player);
- Vec3d[] playerPos = {null};
- int playerPosX = ((int) player.getPosX()) >> 4;
- int playerPosZ = ((int) player.getPosZ()) >> 4;
- if (ticks % 20 == 0) {
- for (int chunkX = playerPosX - getChunkRange(); chunkX <= playerPosX + getChunkRange(); chunkX++) {
- for (int chunkZ = playerPosZ - getChunkRange(); chunkZ <= playerPosZ + getChunkRange(); chunkZ++) {
- ChunkPos chunkPos = new ChunkPos(chunkX, chunkZ);
- if (!CHUNK_MAP.containsKey(chunkPos))
- queueChunk(chunkPos);
+ if (!caching) {
+ POS.clear();
+ CHUNK_MAP.clear();
+ ClientPlayerEntity player = minecraft.player;
+ ClientWorld world = minecraft.world;
+ BlockPos playerPos = player.getPosition();
+ ISelectionContext entityContext = ISelectionContext.forEntity(player);
+ IWorldLightListener block = world.getLightManager().getLightEngine(LightType.BLOCK);
+ IWorldLightListener sky = showNumber ? null : world.getLightManager().getLightEngine(LightType.SKY);
+ BlockPos.Mutable downPos = new BlockPos.Mutable();
+ Iterable<BlockPos> iterate = BlockPos.getAllInBoxMutable(playerPos.getX() - reach, playerPos.getY() - reach, playerPos.getZ() - reach,
+ playerPos.getX() + reach, playerPos.getY() + reach, playerPos.getZ() + reach);
+ HashMap<Long, Object> map = Maps.newHashMap();
+ CHUNK_MAP.put(new ChunkPos(0, 0), map);
+ for (BlockPos blockPos : iterate) {
+ downPos.setPos(blockPos.getX(), blockPos.getY() - 1, blockPos.getZ());
+ if (showNumber) {
+ int level = getCrossLevel(blockPos, downPos, world, block, entityContext);
+ if (level >= 0) {
+ map.put(blockPos.toLong(), level);
+ }
+ } else {
+ CrossType type = getCrossType(blockPos, downPos, world, block, sky, entityContext);
+ if (type != CrossType.NONE) {
+ map.put(blockPos.toLong(), type);
+ }
}
}
- }
- if (!POS.isEmpty()) {
- if (playerPos[0] == null) {
- playerPos[0] = player.getPositionVec();
+ } else {
+ ClientPlayerEntity player = minecraft.player;
+ ClientWorld world = minecraft.world;
+ ISelectionContext selectionContext = ISelectionContext.forEntity(player);
+ Vec3d[] playerPos = {null};
+ int playerPosX = ((int) player.getPosX()) >> 4;
+ int playerPosZ = ((int) player.getPosZ()) >> 4;
+ if (ticks % 20 == 0) {
+ for (int chunkX = playerPosX - getChunkRange(); chunkX <= playerPosX + getChunkRange(); chunkX++) {
+ for (int chunkZ = playerPosZ - getChunkRange(); chunkZ <= playerPosZ + getChunkRange(); chunkZ++) {
+ ChunkPos chunkPos = new ChunkPos(chunkX, chunkZ);
+ if (!CHUNK_MAP.containsKey(chunkPos))
+ queueChunk(chunkPos);
+ }
+ }
}
- ChunkPos pos = POS.stream().min(Comparator.comparingDouble(value -> value.getBlock(8, 0, 8).distanceSq(playerPos[0].x, 0, playerPos[0].z, false))).get();
- EXECUTOR.submit(() -> {
- if (MathHelper.abs(pos.x - playerPosX) <= getChunkRange() && MathHelper.abs(pos.z - playerPosZ) <= getChunkRange()) {
- calculateChunk(world.getChunkProvider().getChunk(pos.x, pos.z, ChunkStatus.FULL, false), world, pos, selectionContext);
- } else {
- CHUNK_MAP.remove(pos);
+ if (!POS.isEmpty()) {
+ if (playerPos[0] == null) {
+ playerPos[0] = player.getPositionVec();
+ }
+ ChunkPos pos = POS.stream().min(Comparator.comparingDouble(value -> value.getBlock(8, 0, 8).distanceSq(playerPos[0].x, 0, playerPos[0].z, false))).get();
+ EXECUTOR.submit(() -> {
+ if (MathHelper.abs(pos.x - playerPosX) <= getChunkRange() && MathHelper.abs(pos.z - playerPosZ) <= getChunkRange()) {
+ calculateChunk(world.getChunkProvider().getChunk(pos.x, pos.z, ChunkStatus.FULL, false), world, pos, selectionContext);
+ } else {
+ CHUNK_MAP.remove(pos);
+ }
+ });
+ POS.remove(pos);
+ }
+ if (ticks % 50 == 0) {
+ Iterator<Map.Entry<ChunkPos, Map<Long, Object>>> chunkMapIterator = CHUNK_MAP.entrySet().iterator();
+ while (chunkMapIterator.hasNext()) {
+ Map.Entry<ChunkPos, Map<Long, Object>> pos = chunkMapIterator.next();
+ if (MathHelper.abs(pos.getKey().x - playerPosX) > getChunkRange() * 2 || MathHelper.abs(pos.getKey().z - playerPosZ) > getChunkRange() * 2) {
+ chunkMapIterator.remove();
+ }
}
- });
- POS.remove(pos);
- }
- Iterator<Map.Entry<ChunkPos, Map<Long, Object>>> chunkMapIterator = CHUNK_MAP.entrySet().iterator();
- while (chunkMapIterator.hasNext()) {
- Map.Entry<ChunkPos, Map<Long, Object>> pos = chunkMapIterator.next();
- if (MathHelper.abs(pos.getKey().x - playerPosX) > getChunkRange() * 2 || MathHelper.abs(pos.getKey().z - playerPosZ) > getChunkRange() * 2) {
- chunkMapIterator.remove();
}
}
}
RenderSystem.depthMask(true);
BlockPos.Mutable mutable = new BlockPos.Mutable();
for (Map.Entry<ChunkPos, Map<Long, Object>> entry : CHUNK_MAP.entrySet()) {
- if (MathHelper.abs(entry.getKey().x - playerPosX) > getChunkRange() || MathHelper.abs(entry.getKey().z - playerPosZ) > getChunkRange()) {
+ if (caching && (MathHelper.abs(entry.getKey().x - playerPosX) > getChunkRange() || MathHelper.abs(entry.getKey().z - playerPosZ) > getChunkRange())) {
continue;
}
for (Map.Entry<Long, Object> objectEntry : entry.getValue().entrySet()) {
RenderSystem.enableDepthTest();
} else {
RenderSystem.enableDepthTest();
- RenderSystem.shadeModel(7425);
- RenderSystem.enableAlphaTest();
- RenderSystem.defaultAlphaFunc();
RenderSystem.disableTexture();
- RenderSystem.disableBlend();
+ RenderSystem.enableBlend();
+ RenderSystem.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA);
if (smoothLines) GL11.glEnable(GL11.GL_LINE_SMOOTH);
- RenderSystem.lineWidth(lineWidth);
- Tessellator tessellator = Tessellator.getInstance();
- BufferBuilder buffer = tessellator.getBuffer();
+ GL11.glLineWidth(lineWidth);
+ GL11.glBegin(GL11.GL_LINES);
BlockPos.Mutable mutable = new BlockPos.Mutable();
for (Map.Entry<ChunkPos, Map<Long, Object>> entry : CHUNK_MAP.entrySet()) {
- if (MathHelper.abs(entry.getKey().x - playerPosX) > getChunkRange() || MathHelper.abs(entry.getKey().z - playerPosZ) > getChunkRange()) {
+ if (caching && (MathHelper.abs(entry.getKey().x - playerPosX) > getChunkRange() || MathHelper.abs(entry.getKey().z - playerPosZ) > getChunkRange())) {
continue;
}
for (Map.Entry<Long, Object> objectEntry : entry.getValue().entrySet()) {
mutable.setPos(BlockPos.unpackX(objectEntry.getKey()), BlockPos.unpackY(objectEntry.getKey()), BlockPos.unpackZ(objectEntry.getKey()));
if (mutable.withinDistance(playerPos, reach)) {
BlockPos down = mutable.down();
- int color = objectEntry.getValue() == CrossType.RED ? redColor : yellowColor;
- LightOverlayClient.renderCross(info, tessellator, buffer, world, mutable, color, selectionContext);
+ int color = objectEntry.getValue() == CrossType.RED ? redColor : objectEntry.getValue() == CrossType.YELLOW ? yellowColor : secondaryColor;
+ renderCross(info, world, mutable, color, selectionContext);
}
}
}
}
- RenderSystem.enableBlend();
+ GL11.glEnd();
+ RenderSystem.disableBlend();
RenderSystem.enableTexture();
- RenderSystem.shadeModel(7424);
if (smoothLines) GL11.glDisable(GL11.GL_LINE_SMOOTH);
}
RenderSystem.popMatrix();
try {
redColor = 0xFF0000;
yellowColor = 0xFFFF00;
+ secondaryColor = 0x0000FF;
if (!file.exists() || !file.canRead())
saveConfig(file);
FileInputStream fis = new FileInputStream(file);
fis.close();
reach = Integer.parseInt((String) properties.computeIfAbsent("reach", a -> "12"));
crossLevel = Integer.parseInt((String) properties.computeIfAbsent("crossLevel", a -> "7"));
+ secondaryLevel = Integer.parseInt((String) properties.computeIfAbsent("secondaryLevel", a -> "-1"));
+ caching = ((String) properties.computeIfAbsent("caching", a -> "false")).equalsIgnoreCase("true");
showNumber = ((String) properties.computeIfAbsent("showNumber", a -> "false")).equalsIgnoreCase("true");
smoothLines = ((String) properties.computeIfAbsent("smoothLines", a -> "true")).equalsIgnoreCase("true");
underwater = ((String) properties.computeIfAbsent("underwater", a -> "false")).equalsIgnoreCase("true");
b = Integer.parseInt((String) properties.computeIfAbsent("redColorBlue", a -> "0"));
redColor = (r << 16) + (g << 8) + b;
}
+ {
+ int r, g, b;
+ r = Integer.parseInt((String) properties.computeIfAbsent("secondaryColorRed", a -> "0"));
+ g = Integer.parseInt((String) properties.computeIfAbsent("secondaryColorGreen", a -> "0"));
+ b = Integer.parseInt((String) properties.computeIfAbsent("secondaryColorBlue", a -> "255"));
+ secondaryColor = (r << 16) + (g << 8) + b;
+ }
saveConfig(file);
} catch (Exception e) {
e.printStackTrace();
reach = 12;
+ crossLevel = 7;
+ secondaryLevel = -1;
lineWidth = 1.0F;
redColor = 0xFF0000;
yellowColor = 0xFFFF00;
+ secondaryColor = 0x0000FF;
+ caching = false;
showNumber = false;
smoothLines = true;
underwater = false;
ex.printStackTrace();
}
}
+ if (secondaryLevel >= crossLevel) System.err.println("[Light Overlay] Secondary Level is higher than Cross Level");
+ lowerCrossLevel = Math.min(crossLevel, secondaryLevel);
+ higherCrossLevel = Math.max(crossLevel, secondaryLevel);
+ CHUNK_MAP.clear();
+ POS.clear();
}
static void saveConfig(File file) throws IOException {
fos.write("\n".getBytes());
fos.write(("crossLevel=" + crossLevel).getBytes());
fos.write("\n".getBytes());
+ fos.write(("secondaryLevel=" + secondaryLevel).getBytes());
+ fos.write("\n".getBytes());
+ fos.write(("caching=" + caching).getBytes());
+ fos.write("\n".getBytes());
fos.write(("showNumber=" + showNumber).getBytes());
fos.write("\n".getBytes());
fos.write(("smoothLines=" + smoothLines).getBytes());
fos.write(("redColorGreen=" + ((redColor >> 8) & 255)).getBytes());
fos.write("\n".getBytes());
fos.write(("redColorBlue=" + (redColor & 255)).getBytes());
+ fos.write("\n".getBytes());
+ fos.write(("secondaryColorRed=" + ((secondaryColor >> 16) & 255)).getBytes());
+ fos.write("\n".getBytes());
+ fos.write(("secondaryColorGreen=" + ((secondaryColor >> 8) & 255)).getBytes());
+ fos.write("\n".getBytes());
+ fos.write(("secondaryColorBlue=" + (secondaryColor & 255)).getBytes());
fos.close();
}
} else if (packet instanceof SMultiBlockChangePacket) {
ChunkPos chunkPos = ObfuscationReflectionHelper.getPrivateValue(SMultiBlockChangePacket.class, (SMultiBlockChangePacket) packet, "field_148925_b");
LightOverlayClient.queueChunkAndNear(new ChunkPos(chunkPos.x, chunkPos.z));
+ } else if (packet instanceof SUpdateLightPacket) {
+ LightOverlayClient.queueChunkAndNear(new ChunkPos(((SUpdateLightPacket) packet).getChunkX(), ((SUpdateLightPacket) packet).getChunkZ()));
}
}
private enum CrossType {
YELLOW,
RED,
+ SECONDARY,
NONE
}
}
import me.shedaniel.forge.clothconfig2.api.ConfigBuilder;
import me.shedaniel.forge.clothconfig2.api.ConfigCategory;
import me.shedaniel.forge.clothconfig2.api.ConfigEntryBuilder;
+import me.shedaniel.forge.clothconfig2.gui.entries.IntegerSliderEntry;
+import net.minecraft.client.resources.I18n;
import net.minecraft.util.math.MathHelper;
import net.minecraftforge.fml.ExtensionPoint;
import net.minecraftforge.fml.ModLoadingContext;
+import java.util.Optional;
+
public class LightOverlayCloth {
public static void register() {
ModLoadingContext.get().registerExtensionPoint(ExtensionPoint.CONFIGGUIFACTORY, () -> (client, parent) -> {
ConfigBuilder builder = ConfigBuilder.create().setParentScreen(parent).setTitle("key.lightoverlay.category");
ConfigEntryBuilder eb = builder.getEntryBuilder();
- ConfigCategory general = builder.getOrCreateCategory("config.lightoverlay-forge.general");
- general.addEntry(eb.startIntSlider("config.lightoverlay-forge.reach", LightOverlayClient.reach, 1, 64).setDefaultValue(12).setTextGetter(integer -> "Reach: " + integer + " Blocks").setSaveConsumer(integer -> LightOverlayClient.reach = integer).build());
- general.addEntry(eb.startIntSlider("config.lightoverlay-forge.crossLevel", LightOverlayClient.crossLevel, 0, 15).setDefaultValue(7).setTextGetter(integer -> "Cross Level: " + integer).setSaveConsumer(integer -> LightOverlayClient.crossLevel = integer).build());
- general.addEntry(eb.startBooleanToggle("config.lightoverlay-forge.showNumber", LightOverlayClient.showNumber).setDefaultValue(false).setSaveConsumer(bool -> LightOverlayClient.showNumber = bool).build());
- general.addEntry(eb.startBooleanToggle("config.lightoverlay-forge.smoothLines", LightOverlayClient.smoothLines).setDefaultValue(true).setSaveConsumer(bool -> LightOverlayClient.smoothLines = bool).build());
- general.addEntry(eb.startBooleanToggle("config.lightoverlay-forge.underwater", LightOverlayClient.underwater).setDefaultValue(false).setSaveConsumer(bool -> LightOverlayClient.underwater = bool).build());
- general.addEntry(eb.startIntSlider("config.lightoverlay-forge.lineWidth", MathHelper.floor(LightOverlayClient.lineWidth * 100), 100, 700).setDefaultValue(100).setTextGetter(integer -> "Light Width: " + LightOverlayClient.FORMAT.format(integer / 100d)).setSaveConsumer(integer -> LightOverlayClient.lineWidth = integer / 100f).build());
- general.addEntry(eb.startColorField("config.lightoverlay-forge.yellowColor", LightOverlayClient.yellowColor).setDefaultValue(0xFFFF00).setSaveConsumer(color -> LightOverlayClient.yellowColor = color).build());
- general.addEntry(eb.startColorField("config.lightoverlay-forge.redColor", LightOverlayClient.redColor).setDefaultValue(0xFF0000).setSaveConsumer(color -> LightOverlayClient.redColor = color).build());
+ ConfigCategory general = builder.getOrCreateCategory("config.lightoverlay.general");
+ general.addEntry(eb.startTextDescription("§7" + I18n.format("description.lightoverlay.caching")).build());
+ general.addEntry(eb.startBooleanToggle("config.lightoverlay.caching", LightOverlayClient.caching).setDefaultValue(false).setSaveConsumer(bool -> LightOverlayClient.caching = bool).build());
+ general.addEntry(eb.startIntSlider("config.lightoverlay.reach", LightOverlayClient.reach, 1, 64).setDefaultValue(12).setTextGetter(integer -> "Reach: " + integer + " Blocks").setSaveConsumer(integer -> LightOverlayClient.reach = integer).build());
+ IntegerSliderEntry crossLevel = eb.startIntSlider("config.lightoverlay.crossLevel", LightOverlayClient.crossLevel, 0, 15).setDefaultValue(7).setTextGetter(integer -> "Cross Level: " + integer).setSaveConsumer(integer -> LightOverlayClient.crossLevel = integer).build();
+ general.addEntry(crossLevel);
+ general.addEntry(eb.startIntSlider("config.lightoverlay.secondaryLevel", LightOverlayClient.secondaryLevel, -1, 15)
+ .setErrorSupplier(integer -> {
+ if (integer >= 0 && integer >= crossLevel.getValue()) return Optional.of("Secondary Level cannot be higher than Cross Level!");
+ return Optional.empty();
+ }).setDefaultValue(-1).setTextGetter(integer -> integer < 0 ? "Off" : "Level: " + integer).setSaveConsumer(integer -> LightOverlayClient.secondaryLevel = integer).build());
+ general.addEntry(eb.startBooleanToggle("config.lightoverlay.showNumber", LightOverlayClient.showNumber).setDefaultValue(false).setSaveConsumer(bool -> LightOverlayClient.showNumber = bool).build());
+ general.addEntry(eb.startBooleanToggle("config.lightoverlay.smoothLines", LightOverlayClient.smoothLines).setDefaultValue(true).setSaveConsumer(bool -> LightOverlayClient.smoothLines = bool).build());
+ general.addEntry(eb.startBooleanToggle("config.lightoverlay.underwater", LightOverlayClient.underwater).setDefaultValue(false).setSaveConsumer(bool -> LightOverlayClient.underwater = bool).build());
+ general.addEntry(eb.startIntSlider("config.lightoverlay.lineWidth", MathHelper.floor(LightOverlayClient.lineWidth * 100), 100, 700).setDefaultValue(100).setTextGetter(integer -> "Light Width: " + LightOverlayClient.FORMAT.format(integer / 100d)).setSaveConsumer(integer -> LightOverlayClient.lineWidth = integer / 100f).build());
+ general.addEntry(eb.startColorField("config.lightoverlay.yellowColor", LightOverlayClient.yellowColor).setDefaultValue(0xFFFF00).setSaveConsumer(color -> LightOverlayClient.yellowColor = color).build());
+ general.addEntry(eb.startColorField("config.lightoverlay.redColor", LightOverlayClient.redColor).setDefaultValue(0xFF0000).setSaveConsumer(color -> LightOverlayClient.redColor = color).build());
+ general.addEntry(eb.startColorField("config.lightoverlay.secondaryColor", LightOverlayClient.secondaryColor).setDefaultValue(0x0000FF).setSaveConsumer(color -> LightOverlayClient.secondaryColor = color).build());
return builder.setSavingRunnable(() -> {
try {
if (instruction instanceof LabelNode) {
instructions.insertBefore(instruction, new LabelNode());
instructions.insertBefore(instruction, new VarInsnNode(Opcodes.ALOAD, 0));
- instructions.insertBefore(instruction, new MethodInsnNode(Opcodes.INVOKESTATIC, "me/shedaniel/lightoverlay/LightOverlay", "processPacket", "(Lnet/minecraft/network/IPacket;)V", false));
+ instructions.insertBefore(instruction, new MethodInsnNode(Opcodes.INVOKESTATIC, "me/shedaniel/lightoverlay/forge/LightOverlay", "processPacket", "(Lnet/minecraft/network/IPacket;)V", false));
break;
}
}
if (instruction instanceof LabelNode) {
instructions.insertBefore(instruction, new LabelNode());
instructions.insertBefore(instruction, new VarInsnNode(Opcodes.ALOAD, 0));
- instructions.insertBefore(instruction, new MethodInsnNode(Opcodes.INVOKESTATIC, "me/shedaniel/lightoverlay/LightOverlayClient", "renderWorldLast", "()V", false));
+ instructions.insertBefore(instruction, new MethodInsnNode(Opcodes.INVOKESTATIC, "me/shedaniel/lightoverlay/forge/LightOverlayClient", "renderWorldLast", "()V", false));
break;
}
}
{
"key.lightoverlay.category": "Light Overlay",
"key.lightoverlay.enable_overlay": "Toggle Light Overlay",
- "key.lightoverlay.decrease_reach": "Decrease Light Overlay's Reach",
- "key.lightoverlay.increase_reach": "Increase Light Overlay's Reach",
- "key.lightoverlay.increase_line_width": "Increase Light Overlay's Line Width",
- "key.lightoverlay.decrease_line_width": "Decrease Light Overlay's Line Width",
- "text.lightoverlay.current_reach": "The current reach is %d!",
- "text.lightoverlay.current_line_width": "The current line width is %s!",
+ "description.lightoverlay.caching": "Caching is recommended if the reach is above 16 or if you are running on a potato.",
"config.lightoverlay.general": "General",
"config.lightoverlay.reach": "Reach:",
+ "config.lightoverlay.caching": "Caching:",
"config.lightoverlay.crossLevel": "Light Level:",
+ "config.lightoverlay.secondaryLevel": "Secondary Light Level:",
"config.lightoverlay.showNumber": "Show Number Instead:",
"config.lightoverlay.smoothLines": "Smooth Lines:",
"config.lightoverlay.underwater": "Display Underwater:",
"config.lightoverlay.lineWidth": "Line Width:",
"config.lightoverlay.yellowColor": "Yellow Color:",
+ "config.lightoverlay.secondaryColor": "Secondary Color:",
"config.lightoverlay.redColor": "Red Color:",
"config.lightoverlay.invalidColor": "Invalid Color"
}
\ No newline at end of file
org.gradle.jvmargs=-Xmx3G
org.gradle.daemon=false
-mod_version=4.6.2
+mod_version=4.7.0
# fabric
fabric_minecraft_version=1.15.2
yarn_build=15
-fabric_loader_version=0.8.2+build.194
-fabric_api_version=0.5.1+build.294-1.15
+fabric_loader_version=0.8.8+build.202
+fabric_api_version=0.13.0+build.315-1.15
cloth_events_version=1.2.0
-cloth_config_version=2.14.0
+cloth_config_version=2.14.2
modmenu_version=1.10.2+build.32
# forge