}
}
-import org.jetbrains.gradle.ext.ActionDelegationConfig
-
import java.nio.file.FileVisitResult
import java.nio.file.Files
import java.nio.file.Path
import java.util.zip.ZipOutputStream
plugins {
- id "architect-plugin" version "1.0.10"
- id "org.jetbrains.gradle.plugin.idea-ext" version "0.7"
+ id "architectury-plugin" version "1.3.39"
+ id "forgified-fabric-loom" version "0.5.16" apply false
}
architect {
minecraft = minecraft_version
}
+subprojects {
+ apply plugin: "forgified-fabric-loom"
+
+ loom {
+ silentMojangMappingsLicense()
+ }
+}
+
allprojects {
apply plugin: "java"
- apply plugin: "architect-plugin"
+ apply plugin: "architectury-plugin"
group "me.shedaniel"
archivesBaseName = rootProject.name
version = rootProject.mod_version
-}
-idea.project.settings {
- delegateActions {
- delegateBuildRunToGradle = false
- testRunner = ActionDelegationConfig.TestRunner.PLATFORM
- }
- runConfigurations {
- "Fabric: Minecraft Client"(org.jetbrains.gradle.ext.Gradle) {
- project = rootProject.project(":fabric")
- taskNames = Collections.singletonList("runClient")
- }
- "Fabric: Minecraft Server"(org.jetbrains.gradle.ext.Gradle) {
- project = rootProject.project(":fabric")
- taskNames = Collections.singletonList("runServer")
- }
- "Forge: Minecraft Client"(org.jetbrains.gradle.ext.Gradle) {
- project = rootProject.project(":forge")
- taskNames = Collections.singletonList("runClient")
- }
- "Forge: Minecraft Server"(org.jetbrains.gradle.ext.Gradle) {
- project = rootProject.project(":forge")
- taskNames = Collections.singletonList("runServer")
- }
+ tasks.withType(JavaCompile) {
+ options.encoding = "UTF-8"
}
}
task buildMerged {
+ allprojects {
+ dependsOn it.tasks.getByName("build")
+ }
doLast {
def folder = file(".gradle/.mergemods")
folder.mkdirs()
- def fabricJar = file("fabric/build/libs/${rootProject.name}-${rootProject.mod_version}.jar")
- def forgeJar = file("forge/build/libs/${rootProject.name}-${rootProject.mod_version}.jar")
+ def fabricJar = file("fabric/build/libs/${rootProject.name}-${rootProject.mod_version}-fabric.jar")
+ def forgeJar = file("forge/build/libs/${rootProject.name}-${rootProject.mod_version}-forge.jar")
def fabricFolder = new File(folder, ".tempFabric")
def forgeFolder = new File(folder, ".tempForge")
def mergeFolder = new File(folder, ".tempMerge")
if (outFile.exists()) {
def env = useFolder.getName().substring(5)
def fileName = outFile.getAbsolutePath().replace(mergeFolder.getAbsolutePath(), "")
- def policyEnv = policyMap.get(fileName)
- if (policyEnv == null) {
- throw new IllegalStateException("Unhandled duplicate file: $fileName")
+ if (!ogFile.isFile() || !outFile.isFile() || !Arrays.equals(ogFile.readBytes(), outFile.readBytes())) {
+ def policyEnv = policyMap.get(fileName)
+ if (policyEnv == null) {
+ throw new IllegalStateException("Unhandled duplicate file: $fileName")
+ }
+ println "Chose env ${policyEnv.toUpperCase(Locale.ROOT)} for duplicate file: $fileName"
+ if (policyEnv != env)
+ return FileVisitResult.CONTINUE
}
- println "Chose env ${policyEnv.toUpperCase(Locale.ROOT)} for duplicate file: $fileName"
- if (policyEnv != env)
- return FileVisitResult.CONTINUE
}
if (!ogFile.isDirectory()) {
org.apache.commons.io.FileUtils.copyFile(ogFile, outFile)
-plugins {
- id "fabric-loom"
-}
-
dependencies {
minecraft "com.mojang:minecraft:${rootProject.architect.minecraft}"
mappings minecraft.officialMojangMappings()
+ modCompile "me.shedaniel:architectury:${rootProject.architectury_version}"
modCompile "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}"
}
+++ /dev/null
-package me.shedaniel.lightoverlay.common;
-
-import net.minecraft.client.KeyMapping;
-import net.minecraft.client.renderer.culling.Frustum;
-
-import java.nio.file.Path;
-
-public interface AbstractPlatform {
- Path getConfigDir();
-
- void registerClientTick(Runnable runnable);
-
- void registerDebugRenderer(Runnable runnable);
-
- KeyMapping registerKeyBinding(KeyMapping keyMapping);
-
- boolean isFrustumVisible(Frustum frustum, double minX, double minY, double minZ, double maxX, double maxY, double maxZ);
-}
--- /dev/null
+package me.shedaniel.lightoverlay.common;
+
+import com.google.common.collect.Maps;
+import com.mojang.blaze3d.platform.GlStateManager;
+import com.mojang.blaze3d.platform.InputConstants;
+import com.mojang.blaze3d.systems.RenderSystem;
+import com.mojang.blaze3d.vertex.Tesselator;
+import com.mojang.math.Transformation;
+import it.unimi.dsi.fastutil.longs.Long2ReferenceMap;
+import it.unimi.dsi.fastutil.longs.Long2ReferenceOpenHashMap;
+import me.shedaniel.architectury.event.events.GuiEvent;
+import me.shedaniel.architectury.event.events.client.ClientTickEvent;
+import me.shedaniel.architectury.platform.Platform;
+import me.shedaniel.architectury.registry.KeyBindings;
+import net.minecraft.client.Camera;
+import net.minecraft.client.KeyMapping;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.Font;
+import net.minecraft.client.multiplayer.ClientLevel;
+import net.minecraft.client.player.LocalPlayer;
+import net.minecraft.client.renderer.MultiBufferSource;
+import net.minecraft.client.renderer.culling.Frustum;
+import net.minecraft.core.BlockPos;
+import net.minecraft.core.Direction;
+import net.minecraft.resources.ResourceLocation;
+import net.minecraft.tags.BlockTags;
+import net.minecraft.util.LazyLoadedValue;
+import net.minecraft.util.Mth;
+import net.minecraft.world.entity.Entity;
+import net.minecraft.world.entity.EntityType;
+import net.minecraft.world.entity.MobCategory;
+import net.minecraft.world.level.BlockGetter;
+import net.minecraft.world.level.ChunkPos;
+import net.minecraft.world.level.Level;
+import net.minecraft.world.level.LightLayer;
+import net.minecraft.world.level.block.Block;
+import net.minecraft.world.level.block.state.BlockState;
+import net.minecraft.world.level.chunk.ChunkStatus;
+import net.minecraft.world.level.chunk.LevelChunk;
+import net.minecraft.world.level.lighting.LayerLightEventListener;
+import net.minecraft.world.phys.shapes.CollisionContext;
+import net.minecraft.world.phys.shapes.VoxelShape;
+import org.apache.logging.log4j.LogManager;
+import org.lwjgl.opengl.GL11;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.text.DecimalFormat;
+import java.util.*;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadPoolExecutor;
+
+public class LightOverlay {
+ public static final DecimalFormat FORMAT = new DecimalFormat("#.#");
+ private static final String KEYBIND_CATEGORY = "key.lightoverlay.category";
+ private static final ResourceLocation ENABLE_OVERLAY_KEYBIND = new ResourceLocation("lightoverlay", "enable_overlay");
+ public static int reach = 12;
+ public static int crossLevel = 7;
+ public static int secondaryLevel = -1;
+ public static int lowerCrossLevel = -1;
+ public static int higherCrossLevel = -1;
+ public static boolean caching = false;
+ public static boolean showNumber = false;
+ public static boolean smoothLines = true;
+ public static boolean underwater = false;
+ public static float lineWidth = 1.0F;
+ public static int yellowColor = 0xFFFF00, redColor = 0xFF0000, secondaryColor = 0x0000FF;
+ public static File configFile;
+ private static KeyMapping enableOverlay;
+ private static boolean enabled = false;
+ private static final LazyLoadedValue<EntityType<Entity>> TESTING_ENTITY_TYPE = new LazyLoadedValue<>(() ->
+ EntityType.Builder.createNothing(MobCategory.MONSTER).sized(0f, 0f).noSave().build(null));
+ private static int threadNumber = 0;
+ public static Frustum frustum;
+ 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 Set<ChunkPos> POS = Collections.synchronizedSet(new HashSet<>());
+ private static final Set<ChunkPos> CALCULATING_POS = Collections.synchronizedSet(new HashSet<>());
+ private static final Map<ChunkPos, Long2ReferenceMap<Object>> CHUNK_MAP = Maps.newConcurrentMap();
+ private static final Minecraft CLIENT = Minecraft.getInstance();
+ private static long ticks = 0;
+
+ public static void register() {
+ // Load Config
+ configFile = new File(Platform.getConfigFolder().toFile(), "lightoverlay.properties");
+ loadConfig(configFile);
+
+ enableOverlay = createKeyBinding(ENABLE_OVERLAY_KEYBIND, InputConstants.Type.KEYSYM, 296, KEYBIND_CATEGORY);
+ KeyBindings.registerKeyBinding(enableOverlay);
+
+ registerDebugRenderer(() -> {
+ if (enabled) {
+ LocalPlayer playerEntity = CLIENT.player;
+ int playerPosX = ((int) playerEntity.getX()) >> 4;
+ int playerPosZ = ((int) playerEntity.getZ()) >> 4;
+ CollisionContext collisionContext = CollisionContext.of(playerEntity);
+ Level world = CLIENT.level;
+ BlockPos playerPos = new BlockPos(playerEntity.getX(), playerEntity.getY(), playerEntity.getZ());
+ Camera camera = CLIENT.gameRenderer.getMainCamera();
+
+ if (showNumber) {
+ RenderSystem.enableTexture();
+ RenderSystem.depthMask(true);
+ BlockPos.MutableBlockPos mutable = new BlockPos.MutableBlockPos();
+ BlockPos.MutableBlockPos downMutable = new BlockPos.MutableBlockPos();
+ for (Map.Entry<ChunkPos, Long2ReferenceMap<Object>> entry : CHUNK_MAP.entrySet()) {
+ if (caching && (Mth.abs(entry.getKey().x - playerPosX) > getChunkRange() || Mth.abs(entry.getKey().z - playerPosZ) > getChunkRange())) {
+ continue;
+ }
+ for (Long2ReferenceMap.Entry<Object> objectEntry : entry.getValue().long2ReferenceEntrySet()) {
+ if (objectEntry.getValue() instanceof Byte) {
+ mutable.set(BlockPos.getX(objectEntry.getLongKey()), BlockPos.getY(objectEntry.getLongKey()), BlockPos.getZ(objectEntry.getLongKey()));
+ if (mutable.closerThan(playerPos, reach)) {
+ if (frustum == null || isFrustumVisible(frustum, mutable.getX(), mutable.getY(), mutable.getZ(), mutable.getX() + 1, mutable.getX() + 1, mutable.getX() + 1)) {
+ downMutable.set(mutable.getX(), mutable.getY() - 1, mutable.getZ());
+ renderLevel(CLIENT, camera, world, mutable, downMutable, (Byte) objectEntry.getValue(), collisionContext);
+ }
+ }
+ }
+ }
+ }
+ RenderSystem.enableDepthTest();
+ } else {
+ RenderSystem.enableDepthTest();
+ RenderSystem.disableTexture();
+ RenderSystem.enableBlend();
+ RenderSystem.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA);
+ if (smoothLines) GL11.glEnable(GL11.GL_LINE_SMOOTH);
+ GL11.glLineWidth(lineWidth);
+ GL11.glBegin(GL11.GL_LINES);
+ BlockPos.MutableBlockPos mutable = new BlockPos.MutableBlockPos();
+ for (Map.Entry<ChunkPos, Long2ReferenceMap<Object>> entry : CHUNK_MAP.entrySet()) {
+ if (caching && (Mth.abs(entry.getKey().x - playerPosX) > getChunkRange() || Mth.abs(entry.getKey().z - playerPosZ) > getChunkRange())) {
+ continue;
+ }
+ for (Long2ReferenceMap.Entry<Object> objectEntry : entry.getValue().long2ReferenceEntrySet()) {
+ if (objectEntry.getValue() instanceof CrossType) {
+ mutable.set(BlockPos.getX(objectEntry.getLongKey()), BlockPos.getY(objectEntry.getLongKey()), BlockPos.getZ(objectEntry.getLongKey()));
+ if (mutable.closerThan(playerPos, reach)) {
+ if (frustum == null || isFrustumVisible(frustum, mutable.getX(), mutable.getY(), mutable.getZ(), mutable.getX() + 1, mutable.getX() + 1, mutable.getX() + 1)) {
+ int color = objectEntry.getValue() == CrossType.RED ? redColor : objectEntry.getValue() == CrossType.YELLOW ? yellowColor : secondaryColor;
+ renderCross(camera, world, mutable, color, collisionContext);
+ }
+ }
+ }
+ }
+ }
+ GL11.glEnd();
+ RenderSystem.disableBlend();
+ RenderSystem.enableTexture();
+ if (smoothLines) GL11.glDisable(GL11.GL_LINE_SMOOTH);
+ }
+ }
+ });
+
+ GuiEvent.DEBUG_TEXT_LEFT.register(list -> {
+ if (enabled) {
+ if (caching) {
+ list.add(String.format("[Light Overlay] Chunks to queue: %02d", POS.size()));
+ } else {
+ list.add("[Light Overlay] Enabled");
+ }
+ }else {
+ list.add("[Light Overlay] Disabled");
+ }
+ });
+ ClientTickEvent.CLIENT_POST.register(LightOverlay::tick);
+ }
+
+ private static void processChunk(ChunkPos pos, int playerPosX, int playerPosZ, CollisionContext context) {
+ CALCULATING_POS.remove(pos);
+ if (Mth.abs(pos.x - playerPosX) > getChunkRange() || Mth.abs(pos.z - playerPosZ) > getChunkRange() || POS.contains(pos)) {
+ return;
+ }
+ try {
+ calculateChunk(CLIENT.level.getChunkSource().getChunk(pos.x, pos.z, ChunkStatus.FULL, false), CLIENT.level, pos, context);
+ } catch (Throwable throwable) {
+ LogManager.getLogger().throwing(throwable);
+ }
+ }
+
+ public static void queueChunkAndNear(ChunkPos pos) {
+ for (int xOffset = -1; xOffset <= 1; xOffset++) {
+ for (int zOffset = -1; zOffset <= 1; zOffset++) {
+ queueChunk(new ChunkPos(pos.x + xOffset, pos.z + zOffset));
+ }
+ }
+ }
+
+ public static void queueChunk(ChunkPos pos) {
+ if (enabled && caching && !CALCULATING_POS.contains(pos)) {
+ POS.add(pos);
+ }
+ }
+
+ public static int getChunkRange() {
+ return Math.max(Mth.ceil(reach / 16f), 1);
+ }
+
+ private static void calculateChunk(LevelChunk chunk, Level world, ChunkPos chunkPos, CollisionContext entityContext) {
+ if (world != null && chunk != null) {
+ Long2ReferenceMap<Object> map = new Long2ReferenceOpenHashMap<>();
+ LayerLightEventListener block = world.getLightEngine().getLayerListener(LightLayer.BLOCK);
+ LayerLightEventListener sky = showNumber ? null : world.getLightEngine().getLayerListener(LightLayer.SKY);
+ for (BlockPos pos : BlockPos.betweenClosed(chunkPos.getMinBlockX(), 0, chunkPos.getMinBlockZ(), chunkPos.getMaxBlockX(), 256, chunkPos.getMaxBlockZ())) {
+ BlockPos down = pos.below();
+ if (showNumber) {
+ int level = getCrossLevel(pos, down, chunk, block, entityContext);
+ if (level >= 0) {
+ map.put(pos.asLong(), Byte.valueOf((byte) level));
+ }
+ } else {
+ CrossType type = getCrossType(pos, down, chunk, block, sky, entityContext);
+ if (type != CrossType.NONE) {
+ map.put(pos.asLong(), type);
+ }
+ }
+ }
+ CHUNK_MAP.put(chunkPos, map);
+ } else {
+ CHUNK_MAP.remove(chunkPos);
+ }
+ }
+
+ public static CrossType getCrossType(BlockPos pos, BlockPos down, BlockGetter world, LayerLightEventListener block, LayerLightEventListener sky, CollisionContext entityContext) {
+ BlockState blockBelowState = world.getBlockState(down);
+ BlockState blockUpperState = world.getBlockState(pos);
+ VoxelShape upperCollisionShape = blockUpperState.getCollisionShape(world, pos, entityContext);
+ if (!underwater && !blockUpperState.getFluidState().isEmpty())
+ return CrossType.NONE;
+ // Check if the outline is full
+ if (Block.isFaceFull(upperCollisionShape, Direction.UP))
+ return CrossType.NONE;
+ // TODO: Not to hard code no redstone
+ if (blockUpperState.isSignalSource())
+ return CrossType.NONE;
+ // Check if the collision has a bump
+ if (upperCollisionShape.max(Direction.Axis.Y) > 0)
+ return CrossType.NONE;
+ if (blockUpperState.getBlock().is(BlockTags.RAILS))
+ return CrossType.NONE;
+ // Check block state allow spawning (excludes bedrock and barriers automatically)
+ if (!blockBelowState.isValidSpawn(world, down, TESTING_ENTITY_TYPE.get()))
+ return CrossType.NONE;
+ int blockLightLevel = block.getLightValue(pos);
+ int skyLightLevel = sky.getLightValue(pos);
+ if (blockLightLevel > higherCrossLevel)
+ return CrossType.NONE;
+ if (skyLightLevel > higherCrossLevel)
+ return CrossType.YELLOW;
+ return lowerCrossLevel >= 0 && blockLightLevel > lowerCrossLevel ? CrossType.SECONDARY : CrossType.RED;
+ }
+
+ public static int getCrossLevel(BlockPos pos, BlockPos down, BlockGetter world, LayerLightEventListener view, CollisionContext collisionContext) {
+ BlockState blockBelowState = world.getBlockState(down);
+ BlockState blockUpperState = world.getBlockState(pos);
+ VoxelShape collisionShape = blockBelowState.getCollisionShape(world, down, collisionContext);
+ VoxelShape upperCollisionShape = blockUpperState.getCollisionShape(world, pos, collisionContext);
+ if (!underwater && !blockUpperState.getFluidState().isEmpty())
+ return -1;
+ if (!blockBelowState.getFluidState().isEmpty())
+ return -1;
+ if (blockBelowState.isAir())
+ return -1;
+ if (Block.isFaceFull(upperCollisionShape, Direction.DOWN))
+ return -1;
+ return view.getLightValue(pos);
+ }
+
+ public static void renderCross(Camera camera, Level world, BlockPos pos, int color, CollisionContext collisionContext) {
+ double d0 = camera.getPosition().x;
+ double d1 = camera.getPosition().y - .005D;
+ VoxelShape upperOutlineShape = world.getBlockState(pos).getShape(world, pos, collisionContext);
+ if (!upperOutlineShape.isEmpty())
+ d1 -= upperOutlineShape.max(Direction.Axis.Y);
+ double d2 = camera.getPosition().z;
+
+ int red = (color >> 16) & 255;
+ int green = (color >> 8) & 255;
+ int blue = color & 255;
+ 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(Minecraft client, Camera camera, Level world, BlockPos pos, BlockPos down, int level, CollisionContext collisionContext) {
+ String text = String.valueOf(level);
+ Font textRenderer_1 = client.font;
+ double double_4 = camera.getPosition().x;
+ double double_5 = camera.getPosition().y;
+ VoxelShape upperOutlineShape = world.getBlockState(down).getShape(world, down, collisionContext);
+ if (!upperOutlineShape.isEmpty())
+ double_5 += 1 - upperOutlineShape.max(Direction.Axis.Y);
+ double double_6 = camera.getPosition().z;
+ RenderSystem.pushMatrix();
+ RenderSystem.translatef((float) (pos.getX() + 0.5f - double_4), (float) (pos.getY() - double_5) + 0.005f, (float) (pos.getZ() + 0.5f - double_6));
+ RenderSystem.rotatef(90, 1, 0, 0);
+ RenderSystem.normal3f(0.0F, 1.0F, 0.0F);
+ float size = 0.07F;
+ RenderSystem.scalef(-size, -size, size);
+ float float_3 = (float) (-textRenderer_1.width(text)) / 2.0F + 0.4f;
+ RenderSystem.enableAlphaTest();
+ MultiBufferSource.BufferSource immediate = MultiBufferSource.immediate(Tesselator.getInstance().getBuilder());
+ textRenderer_1.drawInBatch(text, float_3, -3.5f, level > higherCrossLevel ? 0xff042404 : (lowerCrossLevel >= 0 && level > lowerCrossLevel ? 0xff0066ff : 0xff731111), false, Transformation.identity().getMatrix(), immediate, false, 0, 15728880);
+ immediate.endBatch();
+ RenderSystem.popMatrix();
+ }
+
+ public static void loadConfig(File file) {
+ try {
+ redColor = 0xFF0000;
+ yellowColor = 0xFFFF00;
+ secondaryColor = 0x0000FF;
+ if (!file.exists() || !file.canRead())
+ saveConfig(file);
+ FileInputStream fis = new FileInputStream(file);
+ Properties properties = new Properties();
+ properties.load(fis);
+ 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");
+ lineWidth = Float.parseFloat((String) properties.computeIfAbsent("lineWidth", a -> "1"));
+ {
+ int r, g, b;
+ r = Integer.parseInt((String) properties.computeIfAbsent("yellowColorRed", a -> "255"));
+ g = Integer.parseInt((String) properties.computeIfAbsent("yellowColorGreen", a -> "255"));
+ b = Integer.parseInt((String) properties.computeIfAbsent("yellowColorBlue", a -> "0"));
+ yellowColor = (r << 16) + (g << 8) + b;
+ }
+ {
+ int r, g, b;
+ r = Integer.parseInt((String) properties.computeIfAbsent("redColorRed", a -> "255"));
+ g = Integer.parseInt((String) properties.computeIfAbsent("redColorGreen", a -> "0"));
+ 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;
+ try {
+ saveConfig(file);
+ } catch (IOException ex) {
+ 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();
+ }
+
+ public static void saveConfig(File file) throws IOException {
+ FileOutputStream fos = new FileOutputStream(file, false);
+ fos.write("# Light Overlay Config".getBytes());
+ fos.write("\n".getBytes());
+ fos.write(("reach=" + reach).getBytes());
+ 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("\n".getBytes());
+ fos.write(("underwater=" + underwater).getBytes());
+ fos.write("\n".getBytes());
+ fos.write(("lineWidth=" + FORMAT.format(lineWidth)).getBytes());
+ fos.write("\n".getBytes());
+ fos.write(("yellowColorRed=" + ((yellowColor >> 16) & 255)).getBytes());
+ fos.write("\n".getBytes());
+ fos.write(("yellowColorGreen=" + ((yellowColor >> 8) & 255)).getBytes());
+ fos.write("\n".getBytes());
+ fos.write(("yellowColorBlue=" + (yellowColor & 255)).getBytes());
+ fos.write("\n".getBytes());
+ fos.write(("redColorRed=" + ((redColor >> 16) & 255)).getBytes());
+ fos.write("\n".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 KeyMapping createKeyBinding(ResourceLocation id, InputConstants.Type type, int code, String category) {
+ return new KeyMapping("key." + id.getNamespace() + "." + id.getPath(), type, code, category);
+ }
+
+ private static final LazyLoadedValue<MethodHandle> IS_FRUSTUM_VISIBLE = new LazyLoadedValue<>(() -> {
+ try {
+ return MethodHandles.lookup().findStatic(Class.forName("me.shedaniel.lightoverlay." + Platform.getModLoader() + ".LightOverlayImpl"), "isFrustumVisible",
+ MethodType.methodType(boolean.class, Frustum.class, double.class, double.class, double.class, double.class, double.class, double.class));
+ } catch (NoSuchMethodException | IllegalAccessException | ClassNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+ });
+
+ private static boolean isFrustumVisible(Frustum frustum, double minX, double minY, double minZ, double maxX, double maxY, double maxZ) {
+ try {
+ return (boolean) IS_FRUSTUM_VISIBLE.get().invokeExact(frustum, minX, minY, minZ, maxX, maxY, maxZ);
+ } catch (Throwable throwable) {
+ throw new RuntimeException(throwable);
+ }
+ }
+
+ private static void registerDebugRenderer(Runnable runnable) {
+ try {
+ Class.forName("me.shedaniel.lightoverlay." + Platform.getModLoader() + ".LightOverlayImpl").getDeclaredField("debugRenderer").set(null, runnable);
+ } catch (Throwable throwable) {
+ throw new RuntimeException(throwable);
+ }
+ }
+
+ private static void tick(Minecraft minecraft) {
+ while (enableOverlay.consumeClick())
+ enabled = !enabled;
+
+ try {
+ ticks++;
+ if (CLIENT.player == null || !enabled) {
+ POS.clear();
+ CALCULATING_POS.clear();
+ EXECUTOR.getQueue().clear();
+ CHUNK_MAP.clear();
+ } else {
+ LocalPlayer player = CLIENT.player;
+ ClientLevel world = CLIENT.level;
+ CollisionContext collisionContext = CollisionContext.of(player);
+
+ if (!caching) {
+ CALCULATING_POS.clear();
+ POS.clear();
+ CHUNK_MAP.clear();
+ BlockPos playerPos = player.blockPosition();
+ LayerLightEventListener block = world.getLightEngine().getLayerListener(LightLayer.BLOCK);
+ LayerLightEventListener sky = showNumber ? null : world.getLightEngine().getLayerListener(LightLayer.SKY);
+ BlockPos.MutableBlockPos downPos = new BlockPos.MutableBlockPos();
+ Iterable<BlockPos> iterate = BlockPos.betweenClosed(playerPos.getX() - reach, playerPos.getY() - reach, playerPos.getZ() - reach,
+ playerPos.getX() + reach, playerPos.getY() + reach, playerPos.getZ() + reach);
+ Long2ReferenceMap<Object> map = new Long2ReferenceOpenHashMap<>();
+ 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, collisionContext);
+ if (level >= 0) {
+ map.put(blockPos.asLong(), Byte.valueOf((byte) level));
+ }
+ } else {
+ CrossType type = getCrossType(blockPos, downPos, world, block, sky, collisionContext);
+ if (type != CrossType.NONE) {
+ map.put(blockPos.asLong(), type);
+ }
+ }
+ }
+ } else {
+ int playerPosX = ((int) player.getX()) >> 4;
+ int playerPosZ = ((int) player.getZ()) >> 4;
+ for (int chunkX = playerPosX - getChunkRange(); chunkX <= playerPosX + getChunkRange(); chunkX++) {
+ for (int chunkZ = playerPosZ - getChunkRange(); chunkZ <= playerPosZ + getChunkRange(); chunkZ++) {
+ if (Mth.abs(chunkX - playerPosX) > getChunkRange() || Mth.abs(chunkZ - playerPosZ) > getChunkRange())
+ continue;
+ ChunkPos chunkPos = new ChunkPos(chunkX, chunkZ);
+ if (!CHUNK_MAP.containsKey(chunkPos))
+ queueChunk(chunkPos);
+ }
+ }
+ for (int p = 0; p < 3; p++) {
+ if (EXECUTOR.getQueue().size() >= Runtime.getRuntime().availableProcessors()) break;
+ double d1 = Double.MAX_VALUE, d2 = Double.MAX_VALUE, d3 = Double.MAX_VALUE;
+ ChunkPos c1 = null, c2 = null, c3 = null;
+ synchronized (POS) {
+ Iterator<ChunkPos> iterator = POS.iterator();
+ while (iterator.hasNext()) {
+ ChunkPos pos = iterator.next();
+ if (Mth.abs(pos.x - playerPosX) > getChunkRange() || Mth.abs(pos.z - playerPosZ) > getChunkRange() || CALCULATING_POS.contains(pos)) {
+ iterator.remove();
+ } else {
+ if (isFrustumVisible(frustum, pos.getMinBlockX(), 0, pos.getMinBlockZ(), pos.getMaxBlockX(), 256, pos.getMaxBlockZ())) {
+ int i = Math.abs(pos.x - playerPosX);
+ int j = Math.abs(pos.z - playerPosZ);
+ double distance = Math.sqrt(i * i + j * j);
+ if (distance < d1) {
+ d3 = d2;
+ d2 = d1;
+ d1 = distance;
+ c3 = c2;
+ c2 = c1;
+ c1 = pos;
+ iterator.remove();
+ } else if (distance < d2) {
+ d3 = d2;
+ d2 = distance;
+ c3 = c2;
+ c2 = pos;
+ iterator.remove();
+ } else if (distance < d3) {
+ d3 = distance;
+ c3 = pos;
+ iterator.remove();
+ }
+ }
+ }
+ }
+ }
+ ChunkPos finalC1 = c1;
+ ChunkPos finalC2 = c2;
+ ChunkPos finalC3 = c3;
+ if (finalC1 != null) {
+ CALCULATING_POS.add(finalC1);
+ if (finalC2 != null) {
+ CALCULATING_POS.add(finalC2);
+ if (finalC3 != null) {
+ CALCULATING_POS.add(finalC3);
+ }
+ }
+ EXECUTOR.submit(() -> {
+ int playerPosX1 = ((int) CLIENT.player.getX()) >> 4;
+ int playerPosZ1 = ((int) CLIENT.player.getZ()) >> 4;
+ if (finalC1 != null) processChunk(finalC1, playerPosX1, playerPosZ1, collisionContext);
+ if (finalC2 != null) processChunk(finalC2, playerPosX1, playerPosZ1, collisionContext);
+ if (finalC3 != null) processChunk(finalC3, playerPosX1, playerPosZ1, collisionContext);
+ });
+ }
+ }
+ if (ticks % 50 == 0) {
+ CHUNK_MAP.entrySet().removeIf(pos -> Mth.abs(pos.getKey().x - playerPosX) > getChunkRange() * 2 || Mth.abs(pos.getKey().z - playerPosZ) > getChunkRange() * 2);
+ }
+ }
+ }
+ } catch (Throwable throwable) {
+ LogManager.getLogger().throwing(throwable);
+ }
+ }
+
+ private enum CrossType {
+ YELLOW,
+ RED,
+ SECONDARY,
+ NONE
+ }
+}
+++ /dev/null
-package me.shedaniel.lightoverlay.common;
-
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.mojang.blaze3d.platform.GlStateManager;
-import com.mojang.blaze3d.platform.InputConstants;
-import com.mojang.blaze3d.systems.RenderSystem;
-import com.mojang.blaze3d.vertex.Tesselator;
-import com.mojang.math.Transformation;
-import it.unimi.dsi.fastutil.longs.Long2ReferenceMap;
-import it.unimi.dsi.fastutil.longs.Long2ReferenceOpenHashMap;
-import net.minecraft.client.Camera;
-import net.minecraft.client.KeyMapping;
-import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.Font;
-import net.minecraft.client.multiplayer.ClientLevel;
-import net.minecraft.client.player.LocalPlayer;
-import net.minecraft.client.renderer.MultiBufferSource;
-import net.minecraft.client.renderer.culling.Frustum;
-import net.minecraft.core.BlockPos;
-import net.minecraft.core.Direction;
-import net.minecraft.resources.ResourceLocation;
-import net.minecraft.tags.BlockTags;
-import net.minecraft.util.LazyLoadedValue;
-import net.minecraft.util.Mth;
-import net.minecraft.world.entity.Entity;
-import net.minecraft.world.entity.EntityType;
-import net.minecraft.world.entity.MobCategory;
-import net.minecraft.world.level.BlockGetter;
-import net.minecraft.world.level.ChunkPos;
-import net.minecraft.world.level.Level;
-import net.minecraft.world.level.LightLayer;
-import net.minecraft.world.level.block.Block;
-import net.minecraft.world.level.block.state.BlockState;
-import net.minecraft.world.level.chunk.ChunkStatus;
-import net.minecraft.world.level.chunk.LevelChunk;
-import net.minecraft.world.level.lighting.LayerLightEventListener;
-import net.minecraft.world.phys.shapes.CollisionContext;
-import net.minecraft.world.phys.shapes.VoxelShape;
-import org.apache.logging.log4j.LogManager;
-import org.lwjgl.opengl.GL11;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.text.DecimalFormat;
-import java.util.Comparator;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ThreadPoolExecutor;
-
-public class LightOverlayCore {
- public static final DecimalFormat FORMAT = new DecimalFormat("#.#");
- private static final String KEYBIND_CATEGORY = "key.lightoverlay.category";
- private static final ResourceLocation ENABLE_OVERLAY_KEYBIND = new ResourceLocation("lightoverlay", "enable_overlay");
- public static int reach = 12;
- public static int crossLevel = 7;
- public static int secondaryLevel = -1;
- public static int lowerCrossLevel = -1;
- public static int higherCrossLevel = -1;
- public static boolean caching = false;
- public static boolean showNumber = false;
- public static boolean smoothLines = true;
- public static boolean underwater = false;
- public static float lineWidth = 1.0F;
- public static int yellowColor = 0xFFFF00, redColor = 0xFF0000, secondaryColor = 0x0000FF;
- public static File configFile;
- private static KeyMapping enableOverlay;
- private static boolean enabled = false;
- private static final LazyLoadedValue<EntityType<Entity>> TESTING_ENTITY_TYPE = new LazyLoadedValue<>(() ->
- EntityType.Builder.createNothing(MobCategory.MONSTER).sized(0f, 0f).noSave().build(null));
- private static int threadNumber = 0;
- public static Frustum frustum;
- 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, Long2ReferenceMap<Object>> CHUNK_MAP = Maps.newConcurrentMap();
- private static final Minecraft CLIENT = Minecraft.getInstance();
- private static long ticks = 0;
-
- public static void register(AbstractPlatform platform) {
- // Load Config
- configFile = new File(platform.getConfigDir().toFile(), "lightoverlay.properties");
- loadConfig(configFile);
-
- enableOverlay = platform.registerKeyBinding(createKeyBinding(ENABLE_OVERLAY_KEYBIND, InputConstants.Type.KEYSYM, 296, KEYBIND_CATEGORY));
-
- platform.registerDebugRenderer(() -> {
- if (enabled) {
- LocalPlayer playerEntity = CLIENT.player;
- int playerPosX = ((int) playerEntity.getX()) >> 4;
- int playerPosZ = ((int) playerEntity.getZ()) >> 4;
- CollisionContext collisionContext = CollisionContext.of(playerEntity);
- Level world = CLIENT.level;
- BlockPos playerPos = new BlockPos(playerEntity.getX(), playerEntity.getY(), playerEntity.getZ());
- Camera camera = CLIENT.gameRenderer.getMainCamera();
-
- if (showNumber) {
- RenderSystem.enableTexture();
- RenderSystem.depthMask(true);
- BlockPos.MutableBlockPos mutable = new BlockPos.MutableBlockPos();
- BlockPos.MutableBlockPos downMutable = new BlockPos.MutableBlockPos();
- for (Map.Entry<ChunkPos, Long2ReferenceMap<Object>> entry : CHUNK_MAP.entrySet()) {
- if (caching && (Mth.abs(entry.getKey().x - playerPosX) > getChunkRange() || Mth.abs(entry.getKey().z - playerPosZ) > getChunkRange())) {
- continue;
- }
- for (Long2ReferenceMap.Entry<Object> objectEntry : entry.getValue().long2ReferenceEntrySet()) {
- if (objectEntry.getValue() instanceof Byte) {
- mutable.set(BlockPos.getX(objectEntry.getLongKey()), BlockPos.getY(objectEntry.getLongKey()), BlockPos.getZ(objectEntry.getLongKey()));
- if (mutable.closerThan(playerPos, reach)) {
- if (frustum == null || platform.isFrustumVisible(frustum, mutable.getX(), mutable.getY(), mutable.getZ(), mutable.getX() + 1, mutable.getX() + 1, mutable.getX() + 1)) {
- downMutable.set(mutable.getX(), mutable.getY() - 1, mutable.getZ());
- renderLevel(CLIENT, camera, world, mutable, downMutable, (Byte) objectEntry.getValue(), collisionContext);
- }
- }
- }
- }
- }
- RenderSystem.enableDepthTest();
- } else {
- RenderSystem.enableDepthTest();
- RenderSystem.disableTexture();
- RenderSystem.enableBlend();
- RenderSystem.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA);
- if (smoothLines) GL11.glEnable(GL11.GL_LINE_SMOOTH);
- GL11.glLineWidth(lineWidth);
- GL11.glBegin(GL11.GL_LINES);
- BlockPos.MutableBlockPos mutable = new BlockPos.MutableBlockPos();
- for (Map.Entry<ChunkPos, Long2ReferenceMap<Object>> entry : CHUNK_MAP.entrySet()) {
- if (caching && (Mth.abs(entry.getKey().x - playerPosX) > getChunkRange() || Mth.abs(entry.getKey().z - playerPosZ) > getChunkRange())) {
- continue;
- }
- for (Long2ReferenceMap.Entry<Object> objectEntry : entry.getValue().long2ReferenceEntrySet()) {
- if (objectEntry.getValue() instanceof CrossType) {
- mutable.set(BlockPos.getX(objectEntry.getLongKey()), BlockPos.getY(objectEntry.getLongKey()), BlockPos.getZ(objectEntry.getLongKey()));
- if (mutable.closerThan(playerPos, reach)) {
- if (frustum == null || platform.isFrustumVisible(frustum, mutable.getX(), mutable.getY(), mutable.getZ(), mutable.getX() + 1, mutable.getX() + 1, mutable.getX() + 1)) {
- int color = objectEntry.getValue() == CrossType.RED ? redColor : objectEntry.getValue() == CrossType.YELLOW ? yellowColor : secondaryColor;
- renderCross(camera, world, mutable, color, collisionContext);
- }
- }
- }
- }
- }
- GL11.glEnd();
- RenderSystem.disableBlend();
- RenderSystem.enableTexture();
- if (smoothLines) GL11.glDisable(GL11.GL_LINE_SMOOTH);
- }
- }
- });
-
- platform.registerClientTick(() -> {
- while (enableOverlay.consumeClick())
- enabled = !enabled;
-
- try {
- ticks++;
- if (CLIENT.player == null || !enabled) {
- POS.clear();
- CHUNK_MAP.clear();
- } else {
- LocalPlayer player = CLIENT.player;
- ClientLevel world = CLIENT.level;
- CollisionContext collisionContext = CollisionContext.of(player);
-
- if (!caching) {
- POS.clear();
- CHUNK_MAP.clear();
- BlockPos playerPos = player.blockPosition();
- LayerLightEventListener block = world.getLightEngine().getLayerListener(LightLayer.BLOCK);
- LayerLightEventListener sky = showNumber ? null : world.getLightEngine().getLayerListener(LightLayer.SKY);
- BlockPos.MutableBlockPos downPos = new BlockPos.MutableBlockPos();
- Iterable<BlockPos> iterate = BlockPos.betweenClosed(playerPos.getX() - reach, playerPos.getY() - reach, playerPos.getZ() - reach,
- playerPos.getX() + reach, playerPos.getY() + reach, playerPos.getZ() + reach);
- Long2ReferenceMap<Object> map = new Long2ReferenceOpenHashMap<>();
- 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, collisionContext);
- if (level >= 0) {
- map.put(blockPos.asLong(), Byte.valueOf((byte) level));
- }
- } else {
- CrossType type = getCrossType(blockPos, downPos, world, block, sky, collisionContext);
- if (type != CrossType.NONE) {
- map.put(blockPos.asLong(), type);
- }
- }
- }
- } else {
- 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);
- }
- }
- }
- POS.removeIf(pos -> Mth.abs(pos.x - playerPosX) > getChunkRange() || Mth.abs(pos.z - playerPosZ) > getChunkRange());
- for (int k = 0; k < 2; k++) {
- if (!POS.isEmpty()) {
- ChunkPos pos = POS.stream().min(Comparator.comparingDouble(value -> {
- int i = Math.abs(value.x - playerPosX);
- int j = Math.abs(value.z - playerPosZ);
- return i * i + j * j;
- })).get();
- POS.remove(pos);
- EXECUTOR.submit(() -> {
- try {
- calculateChunk(world.getChunkSource().getChunk(pos.x, pos.z, ChunkStatus.FULL, false), world, pos, collisionContext);
- } catch (Throwable throwable) {
- LogManager.getLogger().throwing(throwable);
- }
- });
- }
- }
- if (ticks % 50 == 0) {
- CHUNK_MAP.entrySet().removeIf(pos -> Mth.abs(pos.getKey().x - playerPosX) > getChunkRange() * 2 || Mth.abs(pos.getKey().z - playerPosZ) > getChunkRange() * 2);
- }
- }
- }
- } catch (Throwable throwable) {
- LogManager.getLogger().throwing(throwable);
- }
- });
- }
-
- public static void queueChunkAndNear(ChunkPos pos) {
- for (int xOffset = -1; xOffset <= 1; xOffset++) {
- for (int zOffset = -1; zOffset <= 1; zOffset++) {
- queueChunk(new ChunkPos(pos.x + xOffset, pos.z + zOffset));
- }
- }
- }
-
- public static void queueChunk(ChunkPos pos) {
- if (caching)
- if (!POS.contains(pos))
- POS.add(0, pos);
- }
-
- public static int getChunkRange() {
- return Math.max(Mth.ceil(reach / 16f), 1);
- }
-
- private static void calculateChunk(LevelChunk chunk, Level world, ChunkPos chunkPos, CollisionContext entityContext) {
- if (world != null && chunk != null) {
- Long2ReferenceMap<Object> map = new Long2ReferenceOpenHashMap<>();
- LayerLightEventListener block = world.getLightEngine().getLayerListener(LightLayer.BLOCK);
- LayerLightEventListener sky = showNumber ? null : world.getLightEngine().getLayerListener(LightLayer.SKY);
- for (BlockPos pos : BlockPos.betweenClosed(chunkPos.getMinBlockX(), 0, chunkPos.getMinBlockZ(), chunkPos.getMaxBlockX(), 256, chunkPos.getMaxBlockZ())) {
- BlockPos down = pos.below();
- if (showNumber) {
- int level = getCrossLevel(pos, down, chunk, block, entityContext);
- if (level >= 0) {
- map.put(pos.asLong(), Byte.valueOf((byte) level));
- }
- } else {
- CrossType type = getCrossType(pos, down, chunk, block, sky, entityContext);
- if (type != CrossType.NONE) {
- map.put(pos.asLong(), type);
- }
- }
- }
- CHUNK_MAP.put(chunkPos, map);
- } else {
- CHUNK_MAP.remove(chunkPos);
- }
- }
-
- public static CrossType getCrossType(BlockPos pos, BlockPos down, BlockGetter world, LayerLightEventListener block, LayerLightEventListener sky, CollisionContext entityContext) {
- BlockState blockBelowState = world.getBlockState(down);
- BlockState blockUpperState = world.getBlockState(pos);
- VoxelShape upperCollisionShape = blockUpperState.getCollisionShape(world, pos, entityContext);
- if (!underwater && !blockUpperState.getFluidState().isEmpty())
- return CrossType.NONE;
- // Check if the outline is full
- if (Block.isFaceFull(upperCollisionShape, Direction.UP))
- return CrossType.NONE;
- // TODO: Not to hard code no redstone
- if (blockUpperState.isSignalSource())
- return CrossType.NONE;
- // Check if the collision has a bump
- if (upperCollisionShape.max(Direction.Axis.Y) > 0)
- return CrossType.NONE;
- if (blockUpperState.getBlock().is(BlockTags.RAILS))
- return CrossType.NONE;
- // Check block state allow spawning (excludes bedrock and barriers automatically)
- if (!blockBelowState.isValidSpawn(world, down, TESTING_ENTITY_TYPE.get()))
- return CrossType.NONE;
- int blockLightLevel = block.getLightValue(pos);
- int skyLightLevel = sky.getLightValue(pos);
- if (blockLightLevel > higherCrossLevel)
- return CrossType.NONE;
- if (skyLightLevel > higherCrossLevel)
- return CrossType.YELLOW;
- return lowerCrossLevel >= 0 && blockLightLevel > lowerCrossLevel ? CrossType.SECONDARY : CrossType.RED;
- }
-
- public static int getCrossLevel(BlockPos pos, BlockPos down, BlockGetter world, LayerLightEventListener view, CollisionContext collisionContext) {
- BlockState blockBelowState = world.getBlockState(down);
- BlockState blockUpperState = world.getBlockState(pos);
- VoxelShape collisionShape = blockBelowState.getCollisionShape(world, down, collisionContext);
- VoxelShape upperCollisionShape = blockUpperState.getCollisionShape(world, pos, collisionContext);
- if (!underwater && !blockUpperState.getFluidState().isEmpty())
- return -1;
- if (!blockBelowState.getFluidState().isEmpty())
- return -1;
- if (blockBelowState.isAir())
- return -1;
- if (Block.isFaceFull(upperCollisionShape, Direction.DOWN))
- return -1;
- return view.getLightValue(pos);
- }
-
- public static void renderCross(Camera camera, Level world, BlockPos pos, int color, CollisionContext collisionContext) {
- double d0 = camera.getPosition().x;
- double d1 = camera.getPosition().y - .005D;
- VoxelShape upperOutlineShape = world.getBlockState(pos).getShape(world, pos, collisionContext);
- if (!upperOutlineShape.isEmpty())
- d1 -= upperOutlineShape.max(Direction.Axis.Y);
- double d2 = camera.getPosition().z;
-
- int red = (color >> 16) & 255;
- int green = (color >> 8) & 255;
- int blue = color & 255;
- 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(Minecraft client, Camera camera, Level world, BlockPos pos, BlockPos down, int level, CollisionContext collisionContext) {
- String text = String.valueOf(level);
- Font textRenderer_1 = client.font;
- double double_4 = camera.getPosition().x;
- double double_5 = camera.getPosition().y;
- VoxelShape upperOutlineShape = world.getBlockState(down).getShape(world, down, collisionContext);
- if (!upperOutlineShape.isEmpty())
- double_5 += 1 - upperOutlineShape.max(Direction.Axis.Y);
- double double_6 = camera.getPosition().z;
- RenderSystem.pushMatrix();
- RenderSystem.translatef((float) (pos.getX() + 0.5f - double_4), (float) (pos.getY() - double_5) + 0.005f, (float) (pos.getZ() + 0.5f - double_6));
- RenderSystem.rotatef(90, 1, 0, 0);
- RenderSystem.normal3f(0.0F, 1.0F, 0.0F);
- float size = 0.07F;
- RenderSystem.scalef(-size, -size, size);
- float float_3 = (float) (-textRenderer_1.width(text)) / 2.0F + 0.4f;
- RenderSystem.enableAlphaTest();
- MultiBufferSource.BufferSource immediate = MultiBufferSource.immediate(Tesselator.getInstance().getBuilder());
- textRenderer_1.drawInBatch(text, float_3, -3.5f, level > higherCrossLevel ? 0xff042404 : (lowerCrossLevel >= 0 && level > lowerCrossLevel ? 0xff0066ff : 0xff731111), false, Transformation.identity().getMatrix(), immediate, false, 0, 15728880);
- immediate.endBatch();
- RenderSystem.popMatrix();
- }
-
- public static void loadConfig(File file) {
- try {
- redColor = 0xFF0000;
- yellowColor = 0xFFFF00;
- secondaryColor = 0x0000FF;
- if (!file.exists() || !file.canRead())
- saveConfig(file);
- FileInputStream fis = new FileInputStream(file);
- Properties properties = new Properties();
- properties.load(fis);
- 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");
- lineWidth = Float.parseFloat((String) properties.computeIfAbsent("lineWidth", a -> "1"));
- {
- int r, g, b;
- r = Integer.parseInt((String) properties.computeIfAbsent("yellowColorRed", a -> "255"));
- g = Integer.parseInt((String) properties.computeIfAbsent("yellowColorGreen", a -> "255"));
- b = Integer.parseInt((String) properties.computeIfAbsent("yellowColorBlue", a -> "0"));
- yellowColor = (r << 16) + (g << 8) + b;
- }
- {
- int r, g, b;
- r = Integer.parseInt((String) properties.computeIfAbsent("redColorRed", a -> "255"));
- g = Integer.parseInt((String) properties.computeIfAbsent("redColorGreen", a -> "0"));
- 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;
- try {
- saveConfig(file);
- } catch (IOException ex) {
- 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();
- }
-
- public static void saveConfig(File file) throws IOException {
- FileOutputStream fos = new FileOutputStream(file, false);
- fos.write("# Light Overlay Config".getBytes());
- fos.write("\n".getBytes());
- fos.write(("reach=" + reach).getBytes());
- 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("\n".getBytes());
- fos.write(("underwater=" + underwater).getBytes());
- fos.write("\n".getBytes());
- fos.write(("lineWidth=" + FORMAT.format(lineWidth)).getBytes());
- fos.write("\n".getBytes());
- fos.write(("yellowColorRed=" + ((yellowColor >> 16) & 255)).getBytes());
- fos.write("\n".getBytes());
- fos.write(("yellowColorGreen=" + ((yellowColor >> 8) & 255)).getBytes());
- fos.write("\n".getBytes());
- fos.write(("yellowColorBlue=" + (yellowColor & 255)).getBytes());
- fos.write("\n".getBytes());
- fos.write(("redColorRed=" + ((redColor >> 16) & 255)).getBytes());
- fos.write("\n".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 KeyMapping createKeyBinding(ResourceLocation id, InputConstants.Type type, int code, String category) {
- return new KeyMapping("key." + id.getNamespace() + "." + id.getPath(), type, code, category);
- }
-
- private enum CrossType {
- YELLOW,
- RED,
- SECONDARY,
- NONE
- }
-}
plugins {
- id "fabric-loom"
id "com.github.johnrengelman.shadow" version "5.0.0"
}
accessWidener = file("src/main/resources/lightoverlay.accesswidener")
}
+architectury {
+ platformSetupLoomIde()
+}
+
processResources {
filesMatching("fabric.mod.json") {
expand "version": project.version
modCompile "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}"
modCompile "net.fabricmc.fabric-api:fabric-api:${rootProject.fabric_api_version}"
- modCompile("me.shedaniel.cloth.api:cloth-client-events-v0:${rootProject.cloth_version}") {
- transitive = false
- }
modImplementation("me.shedaniel.cloth:config-2:${rootProject.cloth_config_version}") {
exclude(group: "net.fabricmc.fabric-api")
}
modImplementation("io.github.prospector:modmenu:${rootProject.modmenu_version}") {
transitive = false
}
- include("me.shedaniel.cloth.api:cloth-client-events-v0:${rootProject.cloth_version}") {
- transitive = false
- }
include("me.shedaniel.cloth:config-2:${rootProject.cloth_config_version}") {
transitive = false
}
+ modCompile("me.shedaniel:architectury:${rootProject.architectury_version}:fabric")
- compile(project(":common")) {
+ compileOnly(project(path: ":common")) {
+ transitive = false
+ }
+ runtimeOnly(project(path: ":common", configuration: "transformedRuntime")) {
transitive = false
}
- shadow(project(":common")) {
+ shadow(project(path: ":common", configuration: "transformed")) {
transitive = false
}
}
remapJar {
dependsOn(shadowJar)
input.set(shadowJar.archivePath)
+ archiveClassifier = "fabric"
}
\ No newline at end of file
import me.shedaniel.clothconfig2.api.ConfigCategory;
import me.shedaniel.clothconfig2.api.ConfigEntryBuilder;
import me.shedaniel.clothconfig2.gui.entries.IntegerSliderEntry;
-import me.shedaniel.lightoverlay.common.LightOverlayCore;
+import me.shedaniel.lightoverlay.common.LightOverlay;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.resources.language.I18n;
import net.minecraft.network.chat.Component;
ConfigEntryBuilder eb = builder.entryBuilder();
ConfigCategory general = builder.getOrCreateCategory(new TranslatableComponent("config.lightoverlay.general"));
general.addEntry(eb.startTextDescription(Component.nullToEmpty("§7" + I18n.get("description.lightoverlay.caching"))).build());
- general.addEntry(eb.startBooleanToggle(new TranslatableComponent("config.lightoverlay.caching"), LightOverlayCore.caching).setDefaultValue(false).setSaveConsumer(bool -> LightOverlayCore.caching = bool).build());
- general.addEntry(eb.startIntSlider(new TranslatableComponent("config.lightoverlay.reach"), LightOverlayCore.reach, 1, 64).setDefaultValue(12).setTextGetter(integer -> Component.nullToEmpty("Reach: " + integer + " Blocks")).setSaveConsumer(integer -> LightOverlayCore.reach = integer).build());
- IntegerSliderEntry crossLevel = eb.startIntSlider(new TranslatableComponent("config.lightoverlay.crossLevel"), LightOverlayCore.crossLevel, 0, 15).setDefaultValue(7).setTextGetter(integer -> Component.nullToEmpty("Cross Level: " + integer)).setSaveConsumer(integer -> LightOverlayCore.crossLevel = integer).build();
+ general.addEntry(eb.startBooleanToggle(new TranslatableComponent("config.lightoverlay.caching"), LightOverlay.caching).setDefaultValue(false).setSaveConsumer(bool -> LightOverlay.caching = bool).build());
+ general.addEntry(eb.startIntSlider(new TranslatableComponent("config.lightoverlay.reach"), LightOverlay.reach, 1, 64).setDefaultValue(12).setTextGetter(integer -> Component.nullToEmpty("Reach: " + integer + " Blocks")).setSaveConsumer(integer -> LightOverlay.reach = integer).build());
+ IntegerSliderEntry crossLevel = eb.startIntSlider(new TranslatableComponent("config.lightoverlay.crossLevel"), LightOverlay.crossLevel, 0, 15).setDefaultValue(7).setTextGetter(integer -> Component.nullToEmpty("Cross Level: " + integer)).setSaveConsumer(integer -> LightOverlay.crossLevel = integer).build();
general.addEntry(crossLevel);
- general.addEntry(eb.startIntSlider(new TranslatableComponent("config.lightoverlay.secondaryLevel"), LightOverlayCore.secondaryLevel, -1, 15)
+ general.addEntry(eb.startIntSlider(new TranslatableComponent("config.lightoverlay.secondaryLevel"), LightOverlay.secondaryLevel, -1, 15)
.setErrorSupplier(integer -> {
if (integer >= 0 && integer >= crossLevel.getValue())
return Optional.of(new TextComponent("Secondary Level cannot be higher than Cross Level!"));
return Optional.empty();
- }).setDefaultValue(-1).setTextGetter(integer -> new TextComponent(integer < 0 ? "Off" : "Level: " + integer)).setSaveConsumer(integer -> LightOverlayCore.secondaryLevel = integer).build());
- general.addEntry(eb.startBooleanToggle(new TranslatableComponent("config.lightoverlay.showNumber"), LightOverlayCore.showNumber).setDefaultValue(false).setSaveConsumer(bool -> LightOverlayCore.showNumber = bool).build());
- general.addEntry(eb.startBooleanToggle(new TranslatableComponent("config.lightoverlay.smoothLines"), LightOverlayCore.smoothLines).setDefaultValue(true).setSaveConsumer(bool -> LightOverlayCore.smoothLines = bool).build());
- general.addEntry(eb.startBooleanToggle(new TranslatableComponent("config.lightoverlay.underwater"), LightOverlayCore.underwater).setDefaultValue(false).setSaveConsumer(bool -> LightOverlayCore.underwater = bool).build());
- general.addEntry(eb.startIntSlider(new TranslatableComponent("config.lightoverlay.lineWidth"), Mth.floor(LightOverlayCore.lineWidth * 100), 100, 700).setDefaultValue(100).setTextGetter(integer -> new TextComponent("Light Width: " + LightOverlayCore.FORMAT.format(integer / 100d))).setSaveConsumer(integer -> LightOverlayCore.lineWidth = integer / 100f).build());
- general.addEntry(eb.startColorField(new TranslatableComponent("config.lightoverlay.yellowColor"), LightOverlayCore.yellowColor).setDefaultValue(0xFFFF00).setSaveConsumer(color -> LightOverlayCore.yellowColor = color).build());
- general.addEntry(eb.startColorField(new TranslatableComponent("config.lightoverlay.redColor"), LightOverlayCore.redColor).setDefaultValue(0xFF0000).setSaveConsumer(color -> LightOverlayCore.redColor = color).build());
- general.addEntry(eb.startColorField(new TranslatableComponent("config.lightoverlay.secondaryColor"), LightOverlayCore.secondaryColor).setDefaultValue(0x0000FF).setSaveConsumer(color -> LightOverlayCore.secondaryColor = color).build());
+ }).setDefaultValue(-1).setTextGetter(integer -> new TextComponent(integer < 0 ? "Off" : "Level: " + integer)).setSaveConsumer(integer -> LightOverlay.secondaryLevel = integer).build());
+ general.addEntry(eb.startBooleanToggle(new TranslatableComponent("config.lightoverlay.showNumber"), LightOverlay.showNumber).setDefaultValue(false).setSaveConsumer(bool -> LightOverlay.showNumber = bool).build());
+ general.addEntry(eb.startBooleanToggle(new TranslatableComponent("config.lightoverlay.smoothLines"), LightOverlay.smoothLines).setDefaultValue(true).setSaveConsumer(bool -> LightOverlay.smoothLines = bool).build());
+ general.addEntry(eb.startBooleanToggle(new TranslatableComponent("config.lightoverlay.underwater"), LightOverlay.underwater).setDefaultValue(false).setSaveConsumer(bool -> LightOverlay.underwater = bool).build());
+ general.addEntry(eb.startIntSlider(new TranslatableComponent("config.lightoverlay.lineWidth"), Mth.floor(LightOverlay.lineWidth * 100), 100, 700).setDefaultValue(100).setTextGetter(integer -> new TextComponent("Light Width: " + LightOverlay.FORMAT.format(integer / 100d))).setSaveConsumer(integer -> LightOverlay.lineWidth = integer / 100f).build());
+ general.addEntry(eb.startColorField(new TranslatableComponent("config.lightoverlay.yellowColor"), LightOverlay.yellowColor).setDefaultValue(0xFFFF00).setSaveConsumer(color -> LightOverlay.yellowColor = color).build());
+ general.addEntry(eb.startColorField(new TranslatableComponent("config.lightoverlay.redColor"), LightOverlay.redColor).setDefaultValue(0xFF0000).setSaveConsumer(color -> LightOverlay.redColor = color).build());
+ general.addEntry(eb.startColorField(new TranslatableComponent("config.lightoverlay.secondaryColor"), LightOverlay.secondaryColor).setDefaultValue(0x0000FF).setSaveConsumer(color -> LightOverlay.secondaryColor = color).build());
return builder.setSavingRunnable(() -> {
try {
- LightOverlayCore.saveConfig(LightOverlayCore.configFile);
+ LightOverlay.saveConfig(LightOverlay.configFile);
} catch (Exception e) {
e.printStackTrace();
}
- LightOverlayCore.loadConfig(LightOverlayCore.configFile);
+ LightOverlay.loadConfig(LightOverlay.configFile);
}).build();
}
}
+++ /dev/null
-package me.shedaniel.lightoverlay.fabric;
-
-import me.shedaniel.cloth.api.client.events.v0.ClothClientHooks;
-import me.shedaniel.lightoverlay.common.AbstractPlatform;
-import me.shedaniel.lightoverlay.common.LightOverlayCore;
-import net.fabricmc.api.ClientModInitializer;
-import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
-import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper;
-import net.fabricmc.loader.api.FabricLoader;
-import net.minecraft.client.KeyMapping;
-import net.minecraft.client.renderer.culling.Frustum;
-
-import java.nio.file.Path;
-
-public class LightOverlay implements ClientModInitializer, AbstractPlatform {
- @Override
- public void onInitializeClient() {
- LightOverlayCore.register(this);
- }
-
- @Override
- public Path getConfigDir() {
- return FabricLoader.getInstance().getConfigDir();
- }
-
- @Override
- public void registerClientTick(Runnable runnable) {
- ClientTickEvents.END_CLIENT_TICK.register(minecraft -> runnable.run());
- }
-
- @Override
- public void registerDebugRenderer(Runnable runnable) {
- ClothClientHooks.DEBUG_RENDER_PRE.register(runnable);
- }
-
- @Override
- public KeyMapping registerKeyBinding(KeyMapping keyMapping) {
- return KeyBindingHelper.registerKeyBinding(keyMapping);
- }
-
- @Override
- public boolean isFrustumVisible(Frustum frustum, double minX, double minY, double minZ, double maxX, double maxY, double maxZ) {
- return FrustumHelper.isVisible(frustum, minX, minY, minZ, maxX, maxY, maxZ);
- }
-}
--- /dev/null
+package me.shedaniel.lightoverlay.fabric;
+
+import me.shedaniel.lightoverlay.common.LightOverlay;
+import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents;
+import net.minecraft.client.renderer.culling.Frustum;
+
+public class LightOverlayImpl {
+ public static Runnable debugRenderer = () -> {};
+
+ public static void init() {
+ LightOverlay.register();
+ WorldRenderEvents.AFTER_SETUP.register(context -> LightOverlay.frustum = context.frustum());
+ WorldRenderEvents.BEFORE_DEBUG_RENDER.register(context -> debugRenderer.run());
+ }
+
+ public static boolean isFrustumVisible(Frustum frustum, double minX, double minY, double minZ, double maxX, double maxY, double maxZ) {
+ return FrustumHelper.isVisible(frustum, minX, minY, minZ, maxX, maxY, maxZ);
+ }
+}
package me.shedaniel.lightoverlay.fabric.mixin;
-import me.shedaniel.lightoverlay.common.LightOverlayCore;
+import me.shedaniel.lightoverlay.common.LightOverlay;
import net.minecraft.network.Connection;
import net.minecraft.network.PacketListener;
import net.minecraft.network.protocol.Packet;
@Inject(method = "genericsFtw", at = @At("HEAD"))
private static void handlePacket(Packet packet, PacketListener listener, CallbackInfo ci) {
if (packet instanceof ClientboundBlockUpdatePacket) {
- LightOverlayCore.queueChunkAndNear(new ChunkPos(((ClientboundBlockUpdatePacket) packet).getPos()));
+ LightOverlay.queueChunkAndNear(new ChunkPos(((ClientboundBlockUpdatePacket) packet).getPos()));
} else if (packet instanceof ClientboundSetChunkCacheCenterPacket) {
- LightOverlayCore.queueChunkAndNear(new ChunkPos(((ClientboundSetChunkCacheCenterPacket) packet).getX(), ((ClientboundSetChunkCacheCenterPacket) packet).getZ()));
+ LightOverlay.queueChunkAndNear(new ChunkPos(((ClientboundSetChunkCacheCenterPacket) packet).getX(), ((ClientboundSetChunkCacheCenterPacket) packet).getZ()));
} else if (packet instanceof ClientboundSectionBlocksUpdatePacket) {
- LightOverlayCore.queueChunkAndNear(new ChunkPos(((ClientboundSectionBlocksUpdatePacket) packet).sectionPos.getX(), ((ClientboundSectionBlocksUpdatePacket) packet).sectionPos.getZ()));
+ LightOverlay.queueChunkAndNear(new ChunkPos(((ClientboundSectionBlocksUpdatePacket) packet).sectionPos.getX(), ((ClientboundSectionBlocksUpdatePacket) packet).sectionPos.getZ()));
} else if (packet instanceof ClientboundLightUpdatePacket) {
- LightOverlayCore.queueChunk(new ChunkPos(((ClientboundLightUpdatePacket) packet).getX(), ((ClientboundLightUpdatePacket) packet).getZ()));
+ LightOverlay.queueChunk(new ChunkPos(((ClientboundLightUpdatePacket) packet).getX(), ((ClientboundLightUpdatePacket) packet).getZ()));
}
}
}
+++ /dev/null
-package me.shedaniel.lightoverlay.fabric.mixin;
-
-import me.shedaniel.lightoverlay.common.LightOverlayCore;
-import net.minecraft.client.Camera;
-import net.minecraft.client.renderer.LevelRenderer;
-import net.minecraft.client.renderer.culling.Frustum;
-import org.spongepowered.asm.mixin.Mixin;
-import org.spongepowered.asm.mixin.injection.At;
-import org.spongepowered.asm.mixin.injection.Inject;
-import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
-
-@Mixin(LevelRenderer.class)
-public class MixinWorldRenderer {
- @Inject(method = "setupRender", at = @At("HEAD"))
- private void setupTerrain(Camera camera, Frustum frustum, boolean bl, int i, boolean bl2, CallbackInfo ci) {
- LightOverlayCore.frustum = frustum;
- }
-}
},
"entrypoints": {
"client": [
- "me.shedaniel.lightoverlay.fabric.LightOverlay"
+ "me.shedaniel.lightoverlay.fabric.LightOverlayImpl::init"
],
"modmenu": [
"me.shedaniel.lightoverlay.fabric.LOModMenuEntry"
"accessWidener": "lightoverlay.accesswidener",
"custom": {
"modmenu:clientsideOnly": true
+ },
+ "depends": {
+ "fabric-api": ">=0.29.1",
+ "architectury": ">=1.2.67"
}
}
"compatibilityLevel": "JAVA_8",
"mixins": [],
"client": [
- "MixinClientConnection",
- "MixinWorldRenderer"
+ "MixinClientConnection"
],
"injectors": {
"defaultRequire": 1
-buildscript {
- repositories {
- maven { url "https://files.minecraftforge.net/maven" }
- jcenter()
- mavenCentral()
- }
- dependencies {
- classpath(group: "net.minecraftforge.gradle", name: "ForgeGradle", version: "3.+", changing: true)
- }
-}
-
plugins {
id "com.github.johnrengelman.shadow" version "5.0.0"
- id "eclipse"
}
-apply plugin: "net.minecraftforge.gradle"
+configurations {
+ shadow
+}
-minecraft {
- mappings(channel: "official", version: rootProject.architect.minecraft)
- accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg')
- runs {
- client {
- workingDirectory project.file("run")
- mods {
- examplemod {
- source sourceSets.main
- }
- }
- }
- server {
- workingDirectory project.file("run")
- mods {
- examplemod {
- source sourceSets.main
- }
- }
- }
- }
+architectury {
+ platformSetupLoomIde()
+}
+
+loom {
+ mixinConfig = "lightoverlay-forge.mixins.json"
}
repositories {
jcenter()
- maven { url "https://files.minecraftforge.net/maven" }
maven { url "https://dl.bintray.com/shedaniel/cloth-config-2" }
}
-configurations {
- shadow
+processResources {
+ filesMatching("META-INF/mods.toml") {
+ expand "version": project.version
+ }
+ inputs.property "META-INF/mods.toml", project.version
}
dependencies {
- minecraft("net.minecraftforge:forge:${rootProject.architect.minecraft}-${project.forge_version}")
- implementation(fg.deobf("me.shedaniel.cloth:cloth-config-forge:${rootProject.cloth_config_forge}"))
+ minecraft("com.mojang:minecraft:${rootProject.architect.minecraft}")
+ mappings(minecraft.officialMojangMappings())
+ forge("net.minecraftforge:forge:${rootProject.architect.minecraft}-${project.forge_version}")
+ modCompile("me.shedaniel.cloth:cloth-config-forge:${rootProject.cloth_config_forge}")
+ modCompile("me.shedaniel:architectury:${rootProject.architectury_version}:forge")
- compile(project(path: ":common", configuration: "mcpGenerateMod")) {
+ compileOnly(project(path: ":common")) {
+ transitive = false
+ }
+ runtimeOnly(project(path: ":common", configuration: "transformForgeFakeMod")) {
transitive = false
}
- shadow(project(path: ":common", configuration: "mcp")) {
+ shadow(project(path: ":common", configuration: "transformForge")) {
transitive = false
}
}
exclude "fabric.mod.json"
configurations = [project.configurations.shadow]
- classifier null
+ classifier "shadow"
}
-reobf {
- shadowJar {}
+remapJar {
+ dependsOn(shadowJar)
+ input.set(shadowJar.archivePath)
+ archiveClassifier = "forge"
}
\ No newline at end of file
--- /dev/null
+loom.forge=true
\ No newline at end of file
package me.shedaniel.lightoverlay.forge;
-import net.minecraft.client.renderer.culling.ClippingHelper;
-import net.minecraft.util.math.vector.Vector4f;
+import com.mojang.math.Vector4f;
+import net.minecraft.client.renderer.culling.Frustum;
public class FrustumHelper {
- public static boolean isVisible(ClippingHelper frustum, double minX, double minY, double minZ, double maxX, double maxY, double maxZ) {
+ public static boolean isVisible(Frustum frustum, double minX, double minY, double minZ, double maxX, double maxY, double maxZ) {
float x1 = (float) (minX - frustum.camX);
float y1 = (float) (minY - frustum.camY);
float z1 = (float) (minZ - frustum.camZ);
return isAnyCornerVisible(frustum, x1, y1, z1, x2, y2, z2);
}
- private static boolean isAnyCornerVisible(ClippingHelper frustum, float x1, float y1, float z1, float x2, float y2, float z2) {
+ private static boolean isAnyCornerVisible(Frustum frustum, float x1, float y1, float z1, float x2, float y2, float z2) {
Vector4f[] homogeneousCoordinates = frustum.frustumData;
for (Vector4f vector4f : homogeneousCoordinates) {
if (dotProduct(vector4f, x1, y1, z1, 1.0F) <= 0.0F && dotProduct(vector4f, x2, y1, z1, 1.0F) <= 0.0F && dotProduct(vector4f, x1, y2, z1, 1.0F) <= 0.0F && dotProduct(vector4f, x2, y2, z1, 1.0F) <= 0.0F && dotProduct(vector4f, x1, y1, z2, 1.0F) <= 0.0F && dotProduct(vector4f, x2, y1, z2, 1.0F) <= 0.0F && dotProduct(vector4f, x1, y2, z2, 1.0F) <= 0.0F && dotProduct(vector4f, x2, y2, z2, 1.0F) <= 0.0F) {
package me.shedaniel.lightoverlay.forge;
-import net.minecraft.network.IPacket;
import net.minecraftforge.api.distmarker.Dist;
-import net.minecraftforge.fml.ExtensionPoint;
import net.minecraftforge.fml.DistExecutor;
+import net.minecraftforge.fml.ExtensionPoint;
import net.minecraftforge.fml.ModLoadingContext;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.network.FMLNetworkConstants;
import org.apache.commons.lang3.tuple.Pair;
-@Mod("lightoverlay-forge")
+@Mod("lightoverlay")
public class LightOverlay {
public LightOverlay() {
ModLoadingContext.get().registerExtensionPoint(ExtensionPoint.DISPLAYTEST, () -> Pair.of(() -> FMLNetworkConstants.IGNORESERVERONLY, (a, b) -> true));
- DistExecutor.safeRunWhenOn(Dist.CLIENT, () -> LightOverlayClient::register);
- }
-
- public static void processPacket(IPacket<?> packet) {
- DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> LightOverlayClient.processPacket(packet));
+ DistExecutor.safeRunWhenOn(Dist.CLIENT, () -> LightOverlayImpl::register);
}
}
+++ /dev/null
-package me.shedaniel.lightoverlay.forge;
-
-import me.shedaniel.lightoverlay.common.AbstractPlatform;
-import me.shedaniel.lightoverlay.common.LightOverlayCore;
-import net.minecraft.client.renderer.culling.ClippingHelper;
-import net.minecraft.client.settings.KeyBinding;
-import net.minecraft.network.IPacket;
-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.util.math.ChunkPos;
-import net.minecraftforge.api.distmarker.Dist;
-import net.minecraftforge.common.MinecraftForge;
-import net.minecraftforge.event.TickEvent;
-import net.minecraftforge.fml.DistExecutor;
-import net.minecraftforge.fml.client.registry.ClientRegistry;
-import net.minecraftforge.fml.loading.FMLPaths;
-
-import java.nio.file.Path;
-
-public class LightOverlayClient {
- private static Runnable debugRenderer = () -> {};
-
- public static void register() {
- LightOverlayCore.register(new AbstractPlatform() {
- @Override
- public Path getConfigDir() {
- return FMLPaths.CONFIGDIR.get();
- }
-
- @Override
- public void registerClientTick(Runnable runnable) {
- MinecraftForge.EVENT_BUS.<TickEvent.ClientTickEvent>addListener(event -> runnable.run());
- }
-
- @Override
- public void registerDebugRenderer(Runnable runnable) {
- debugRenderer = runnable;
- }
-
- @Override
- public KeyBinding registerKeyBinding(KeyBinding keyBinding) {
- ClientRegistry.registerKeyBinding(keyBinding);
- return keyBinding;
- }
-
- @Override
- public boolean isFrustumVisible(ClippingHelper clippingHelper, double v, double v1, double v2, double v3, double v4, double v5) {
- return FrustumHelper.isVisible(clippingHelper, v, v1, v2, v3, v4, v5);
- }
- });
-
- try {
- //noinspection Convert2MethodRef
- DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> LightOverlayCloth.register());
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- public static void renderWorldLast() {
- debugRenderer.run();
- }
-
- public static void processPacket(IPacket<?> packet) {
- if (packet instanceof SChangeBlockPacket) {
- LightOverlayCore.queueChunkAndNear(new ChunkPos(((SChangeBlockPacket) packet).getPos()));
- } else if (packet instanceof SChunkDataPacket) {
- LightOverlayCore.queueChunkAndNear(new ChunkPos(((SChunkDataPacket) packet).getX(), ((SChunkDataPacket) packet).getZ()));
- } else if (packet instanceof SMultiBlockChangePacket) {
- LightOverlayCore.queueChunkAndNear(new ChunkPos(((SMultiBlockChangePacket) packet).sectionPos.getX(), ((SMultiBlockChangePacket) packet).sectionPos.getZ()));
- } else if (packet instanceof SUpdateLightPacket) {
- LightOverlayCore.queueChunkAndNear(new ChunkPos(((SUpdateLightPacket) packet).getX(), ((SUpdateLightPacket) packet).getZ()));
- }
- }
-}
import me.shedaniel.clothconfig2.forge.api.ConfigCategory;
import me.shedaniel.clothconfig2.forge.api.ConfigEntryBuilder;
import me.shedaniel.clothconfig2.forge.gui.entries.IntegerSliderEntry;
-import me.shedaniel.lightoverlay.common.LightOverlayCore;
-import net.minecraft.client.resources.I18n;
-import net.minecraft.util.math.MathHelper;
-import net.minecraft.util.text.ITextComponent;
-import net.minecraft.util.text.TranslationTextComponent;
+import me.shedaniel.lightoverlay.common.LightOverlay;
+import net.minecraft.client.resources.language.I18n;
+import net.minecraft.network.chat.Component;
+import net.minecraft.network.chat.TranslatableComponent;
+import net.minecraft.util.Mth;
import net.minecraftforge.fml.ExtensionPoint;
import net.minecraftforge.fml.ModLoadingContext;
public class LightOverlayCloth {
public static void register() {
ModLoadingContext.get().registerExtensionPoint(ExtensionPoint.CONFIGGUIFACTORY, () -> (client, parent) -> {
- ConfigBuilder builder = ConfigBuilder.create().setParentScreen(parent).setTitle(new TranslationTextComponent("key.lightoverlay.category"));
+ ConfigBuilder builder = ConfigBuilder.create().setParentScreen(parent).setTitle(new TranslatableComponent("key.lightoverlay.category"));
ConfigEntryBuilder eb = builder.entryBuilder();
- ConfigCategory general = builder.getOrCreateCategory(new TranslationTextComponent("config.lightoverlay.general"));
- general.addEntry(eb.startTextDescription(ITextComponent.nullToEmpty("§7" + I18n.get("description.lightoverlay.caching"))).build());
- general.addEntry(eb.startBooleanToggle(new TranslationTextComponent("config.lightoverlay.caching"), LightOverlayCore.caching).setDefaultValue(false).setSaveConsumer(bool -> LightOverlayCore.caching = bool).build());
- general.addEntry(eb.startIntSlider(new TranslationTextComponent("config.lightoverlay.reach"), LightOverlayCore.reach, 1, 64).setDefaultValue(12).setTextGetter(integer -> ITextComponent.nullToEmpty("Reach: " + integer + " Blocks")).setSaveConsumer(integer -> LightOverlayCore.reach = integer).build());
- IntegerSliderEntry crossLevel = eb.startIntSlider(new TranslationTextComponent("config.lightoverlay.crossLevel"), LightOverlayCore.crossLevel, 0, 15).setDefaultValue(7).setTextGetter(integer -> ITextComponent.nullToEmpty("Cross Level: " + integer)).setSaveConsumer(integer -> LightOverlayCore.crossLevel = integer).build();
+ ConfigCategory general = builder.getOrCreateCategory(new TranslatableComponent("config.lightoverlay.general"));
+ general.addEntry(eb.startTextDescription(Component.nullToEmpty("§7" + I18n.get("description.lightoverlay.caching"))).build());
+ general.addEntry(eb.startBooleanToggle(new TranslatableComponent("config.lightoverlay.caching"), LightOverlay.caching).setDefaultValue(false).setSaveConsumer(bool -> LightOverlay.caching = bool).build());
+ general.addEntry(eb.startIntSlider(new TranslatableComponent("config.lightoverlay.reach"), LightOverlay.reach, 1, 64).setDefaultValue(12).setTextGetter(integer -> Component.nullToEmpty("Reach: " + integer + " Blocks")).setSaveConsumer(integer -> LightOverlay.reach = integer).build());
+ IntegerSliderEntry crossLevel = eb.startIntSlider(new TranslatableComponent("config.lightoverlay.crossLevel"), LightOverlay.crossLevel, 0, 15).setDefaultValue(7).setTextGetter(integer -> Component.nullToEmpty("Cross Level: " + integer)).setSaveConsumer(integer -> LightOverlay.crossLevel = integer).build();
general.addEntry(crossLevel);
- general.addEntry(eb.startIntSlider(new TranslationTextComponent("config.lightoverlay.secondaryLevel"), LightOverlayCore.secondaryLevel, -1, 15)
+ general.addEntry(eb.startIntSlider(new TranslatableComponent("config.lightoverlay.secondaryLevel"), LightOverlay.secondaryLevel, -1, 15)
.setErrorSupplier(integer -> {
if (integer >= 0 && integer >= crossLevel.getValue())
- return Optional.of(ITextComponent.nullToEmpty("Secondary Level cannot be higher than Cross Level!"));
+ return Optional.of(Component.nullToEmpty("Secondary Level cannot be higher than Cross Level!"));
return Optional.empty();
- }).setDefaultValue(-1).setTextGetter(integer -> ITextComponent.nullToEmpty(integer < 0 ? "Off" : "Level: " + integer)).setSaveConsumer(integer -> LightOverlayCore.secondaryLevel = integer).build());
- general.addEntry(eb.startBooleanToggle(new TranslationTextComponent("config.lightoverlay.showNumber"), LightOverlayCore.showNumber).setDefaultValue(false).setSaveConsumer(bool -> LightOverlayCore.showNumber = bool).build());
- general.addEntry(eb.startBooleanToggle(new TranslationTextComponent("config.lightoverlay.smoothLines"), LightOverlayCore.smoothLines).setDefaultValue(true).setSaveConsumer(bool -> LightOverlayCore.smoothLines = bool).build());
- general.addEntry(eb.startBooleanToggle(new TranslationTextComponent("config.lightoverlay.underwater"), LightOverlayCore.underwater).setDefaultValue(false).setSaveConsumer(bool -> LightOverlayCore.underwater = bool).build());
- general.addEntry(eb.startIntSlider(new TranslationTextComponent("config.lightoverlay.lineWidth"), MathHelper.floor(LightOverlayCore.lineWidth * 100), 100, 700).setDefaultValue(100).setTextGetter(integer -> ITextComponent.nullToEmpty("Light Width: " + LightOverlayCore.FORMAT.format(integer / 100d))).setSaveConsumer(integer -> LightOverlayCore.lineWidth = integer / 100f).build());
- general.addEntry(eb.startColorField(new TranslationTextComponent("config.lightoverlay.yellowColor"), LightOverlayCore.yellowColor).setDefaultValue(0xFFFF00).setSaveConsumer(color -> LightOverlayCore.yellowColor = color).build());
- general.addEntry(eb.startColorField(new TranslationTextComponent("config.lightoverlay.redColor"), LightOverlayCore.redColor).setDefaultValue(0xFF0000).setSaveConsumer(color -> LightOverlayCore.redColor = color).build());
- general.addEntry(eb.startColorField(new TranslationTextComponent("config.lightoverlay.secondaryColor"), LightOverlayCore.secondaryColor).setDefaultValue(0x0000FF).setSaveConsumer(color -> LightOverlayCore.secondaryColor = color).build());
+ }).setDefaultValue(-1).setTextGetter(integer -> Component.nullToEmpty(integer < 0 ? "Off" : "Level: " + integer)).setSaveConsumer(integer -> LightOverlay.secondaryLevel = integer).build());
+ general.addEntry(eb.startBooleanToggle(new TranslatableComponent("config.lightoverlay.showNumber"), LightOverlay.showNumber).setDefaultValue(false).setSaveConsumer(bool -> LightOverlay.showNumber = bool).build());
+ general.addEntry(eb.startBooleanToggle(new TranslatableComponent("config.lightoverlay.smoothLines"), LightOverlay.smoothLines).setDefaultValue(true).setSaveConsumer(bool -> LightOverlay.smoothLines = bool).build());
+ general.addEntry(eb.startBooleanToggle(new TranslatableComponent("config.lightoverlay.underwater"), LightOverlay.underwater).setDefaultValue(false).setSaveConsumer(bool -> LightOverlay.underwater = bool).build());
+ general.addEntry(eb.startIntSlider(new TranslatableComponent("config.lightoverlay.lineWidth"), Mth.floor(LightOverlay.lineWidth * 100), 100, 700).setDefaultValue(100).setTextGetter(integer -> Component.nullToEmpty("Light Width: " + LightOverlay.FORMAT.format(integer / 100d))).setSaveConsumer(integer -> LightOverlay.lineWidth = integer / 100f).build());
+ general.addEntry(eb.startColorField(new TranslatableComponent("config.lightoverlay.yellowColor"), LightOverlay.yellowColor).setDefaultValue(0xFFFF00).setSaveConsumer(color -> LightOverlay.yellowColor = color).build());
+ general.addEntry(eb.startColorField(new TranslatableComponent("config.lightoverlay.redColor"), LightOverlay.redColor).setDefaultValue(0xFF0000).setSaveConsumer(color -> LightOverlay.redColor = color).build());
+ general.addEntry(eb.startColorField(new TranslatableComponent("config.lightoverlay.secondaryColor"), LightOverlay.secondaryColor).setDefaultValue(0x0000FF).setSaveConsumer(color -> LightOverlay.secondaryColor = color).build());
return builder.setSavingRunnable(() -> {
try {
- LightOverlayCore.saveConfig(LightOverlayCore.configFile);
+ LightOverlay.saveConfig(LightOverlay.configFile);
} catch (Exception e) {
e.printStackTrace();
}
- LightOverlayCore.loadConfig(LightOverlayCore.configFile);
+ LightOverlay.loadConfig(LightOverlay.configFile);
}).build();
});
}
--- /dev/null
+package me.shedaniel.lightoverlay.forge;
+
+import me.shedaniel.lightoverlay.common.LightOverlay;
+import net.minecraft.client.renderer.culling.Frustum;
+import net.minecraftforge.api.distmarker.Dist;
+import net.minecraftforge.fml.DistExecutor;
+
+public class LightOverlayImpl {
+ public static Runnable debugRenderer = () -> {};
+
+ public static void register() {
+ LightOverlay.register();
+
+ try {
+ //noinspection Convert2MethodRef
+ DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> LightOverlayCloth.register());
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public static boolean isFrustumVisible(Frustum clippingHelper, double v, double v1, double v2, double v3, double v4, double v5) {
+ return FrustumHelper.isVisible(clippingHelper, v, v1, v2, v3, v4, v5);
+ }
+
+ public static void renderWorldLast() {
+ debugRenderer.run();
+ }
+}
--- /dev/null
+package me.shedaniel.lightoverlay.forge.mixin;
+
+import me.shedaniel.lightoverlay.common.LightOverlay;
+import net.minecraft.network.Connection;
+import net.minecraft.network.PacketListener;
+import net.minecraft.network.protocol.Packet;
+import net.minecraft.network.protocol.game.ClientboundBlockUpdatePacket;
+import net.minecraft.network.protocol.game.ClientboundLightUpdatePacket;
+import net.minecraft.network.protocol.game.ClientboundSectionBlocksUpdatePacket;
+import net.minecraft.network.protocol.game.ClientboundSetChunkCacheCenterPacket;
+import net.minecraft.world.level.ChunkPos;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Inject;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+
+@Mixin(Connection.class)
+public class MixinClientConnection {
+ @Inject(method = "genericsFtw", at = @At("HEAD"))
+ private static void handlePacket(Packet packet, PacketListener listener, CallbackInfo ci) {
+ if (packet instanceof ClientboundBlockUpdatePacket) {
+ LightOverlay.queueChunkAndNear(new ChunkPos(((ClientboundBlockUpdatePacket) packet).getPos()));
+ } else if (packet instanceof ClientboundSetChunkCacheCenterPacket) {
+ LightOverlay.queueChunkAndNear(new ChunkPos(((ClientboundSetChunkCacheCenterPacket) packet).getX(), ((ClientboundSetChunkCacheCenterPacket) packet).getZ()));
+ } else if (packet instanceof ClientboundSectionBlocksUpdatePacket) {
+ LightOverlay.queueChunkAndNear(new ChunkPos(((ClientboundSectionBlocksUpdatePacket) packet).sectionPos.getX(), ((ClientboundSectionBlocksUpdatePacket) packet).sectionPos.getZ()));
+ } else if (packet instanceof ClientboundLightUpdatePacket) {
+ LightOverlay.queueChunk(new ChunkPos(((ClientboundLightUpdatePacket) packet).getX(), ((ClientboundLightUpdatePacket) packet).getZ()));
+ }
+ }
+}
--- /dev/null
+package me.shedaniel.lightoverlay.forge.mixin;
+
+import com.mojang.blaze3d.vertex.PoseStack;
+import me.shedaniel.lightoverlay.forge.LightOverlayImpl;
+import net.minecraft.client.renderer.MultiBufferSource;
+import net.minecraft.client.renderer.debug.DebugRenderer;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Inject;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+
+@Mixin(DebugRenderer.class)
+public class MixinDebugRenderer {
+ @Inject(method = "render", at = @At("HEAD"))
+ private void render(PoseStack arg, MultiBufferSource.BufferSource arg2, double d, double e, double f, CallbackInfo ci) {
+ LightOverlayImpl.renderWorldLast();
+ }
+}
--- /dev/null
+package me.shedaniel.lightoverlay.forge.mixin;
+
+import me.shedaniel.lightoverlay.common.LightOverlay;
+import net.minecraft.client.Camera;
+import net.minecraft.client.renderer.LevelRenderer;
+import net.minecraft.client.renderer.culling.Frustum;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Inject;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+
+@Mixin(LevelRenderer.class)
+public class MixinLevelRenderer {
+ @Inject(method = "setupRender", at = @At("HEAD"))
+ private void setupTerrain(Camera camera, Frustum frustum, boolean bl, int i, boolean bl2, CallbackInfo ci) {
+ LightOverlay.frustum = frustum;
+ }
+}
+++ /dev/null
-var Opcodes = Java.type("org.objectweb.asm.Opcodes");
-var LabelNode = Java.type("org.objectweb.asm.tree.LabelNode");
-var VarInsnNode = Java.type("org.objectweb.asm.tree.VarInsnNode");
-var MethodInsnNode = Java.type("org.objectweb.asm.tree.MethodInsnNode");
-var ASMAPI = Java.type("net.minecraftforge.coremod.api.ASMAPI");
-
-function initializeCoreMod() {
- return {
- "light-overlay-forge": {
- 'target': {
- 'type': 'CLASS',
- 'name': 'net.minecraft.network.NetworkManager'
- },
- 'transformer': function (classNode) {
- var processPacket = ASMAPI.mapMethod("func_197664_a");
- for (i in classNode.methods) {
- var method = classNode.methods[i];
- if (method.name === processPacket) {
- var instructions = method.instructions;
- var insnArray = instructions.toArray();
- for (j in insnArray) {
- var instruction = insnArray[j];
- 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/forge/LightOverlay", "processPacket", "(Lnet/minecraft/network/IPacket;)V", false));
- break;
- }
- }
- break;
- }
- }
- return classNode;
- }
- }
- }
-}
\ No newline at end of file
+++ /dev/null
-var Opcodes = Java.type("org.objectweb.asm.Opcodes");
-var LabelNode = Java.type("org.objectweb.asm.tree.LabelNode");
-var VarInsnNode = Java.type("org.objectweb.asm.tree.VarInsnNode");
-var MethodInsnNode = Java.type("org.objectweb.asm.tree.MethodInsnNode");
-var ASMAPI = Java.type("net.minecraftforge.coremod.api.ASMAPI");
-
-function initializeCoreMod() {
- return {
- "light-overlay-forge": {
- 'target': {
- 'type': 'CLASS',
- 'name': 'net.minecraft.client.renderer.debug.DebugRenderer'
- },
- 'transformer': function (classNode) {
- var render = ASMAPI.mapMethod("func_229019_a_");
- var setupTerrain = ASMAPI.mapMethod("func_228437_a_");
- for (var i in classNode.methods) {
- var method = classNode.methods[i];
- if (method.name === render) {
- var instructions = method.instructions;
- var insnArray = instructions.toArray();
- for (j in insnArray) {
- var instruction = insnArray[j];
- 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/forge/LightOverlayClient", "renderWorldLast", "()V", false));
- break;
- }
- }
- break;
- } else if (method.name === setupTerrain) {
- var instructions = method.instructions;
- instructions.insertBefore(new LabelNode());
- instructions.insertBefore(new VarInsnNode(Opcodes.ALOAD, 2));
- instructions.insertBefore(new MethodInsnNode(Opcodes.INVOKESTATIC, "me/shedaniel/lightoverlay/forge/LightOverlayClient", "updateFrustum", "(Lnet/minecraft/client/renderer/culling/ClippingHelper;)V", false));
- }
- }
- return classNode;
- }
- }
- }
-}
\ No newline at end of file
+++ /dev/null
-{
- "NetworkManager": "META-INF/NetworkManager.js",
- "WorldRenderer": "META-INF/WorldRenderer.js"
-}
\ No newline at end of file
-modLoader="javafml"
-loaderVersion="[33,)"
-issueTrackerURL="https://github.com/shedaniel/LightOverlay/issues/" #optional
-logoFile="icon.png"
-authors="shedaniel"
-license="Apache-2.0"
+modLoader = "javafml"
+loaderVersion = "[33,)"
+issueTrackerURL = "https://github.com/shedaniel/LightOverlay/issues/" #optional
+logoFile = "icon.png"
+authors = "shedaniel"
+license = "Apache-2.0"
[[mods]]
- modId="lightoverlay-forge"
- version="${file.jarVersion}"
- displayName="Light Overlay Forge"
- description='''
+modId = "lightoverlay"
+version = "${version}"
+displayName = "Light Overlay"
+description = '''
To provide users with NEI-like light overlay.
'''
-[[dependencies.lightoverlay-forge]]
- modId="cloth-config"
- mandatory=true
- versionRange="[4.0,)"
- ordering="NONE"
- side="CLIENT"
+[[dependencies.lightoverlay]]
+modId = "cloth-config"
+mandatory = true
+versionRange = "[4.1.3,)"
+ordering = "NONE"
+side = "CLIENT"
+
+[[dependencies.lightoverlay]]
+modId = "architectury"
+mandatory = true
+versionRange = "[1.2.67,)"
+ordering = "NONE"
+side = "CLIENT"
\ No newline at end of file
--- /dev/null
+{
+ "required": true,
+ "package": "me.shedaniel.lightoverlay.forge.mixin",
+ "minVersion": "0.7.11",
+ "compatibilityLevel": "JAVA_8",
+ "mixins": [],
+ "client": [
+ "MixinClientConnection",
+ "MixinDebugRenderer",
+ "MixinLevelRenderer"
+ ],
+ "injectors": {
+ "defaultRequire": 1
+ }
+}
\ No newline at end of file
org.gradle.jvmargs=-Xmx3G
org.gradle.daemon=false
-mod_version=5.5.4
-minecraft_version=1.16.2
+mod_version=5.6.0
+minecraft_version=1.16.4
+
+architectury_version=1.2.67
# fabric
-fabric_loader_version=0.9.1+build.205
-fabric_api_version=0.17.2+build.396-1.16
-cloth_version=1.0.8
-cloth_config_version=4.7.0-unstable
+fabric_loader_version=0.10.8
+fabric_api_version=0.29.1+1.16
+cloth_config_version=4.8.3
modmenu_version=1.14.6+build.31
# forge
-forge_version=33.0.57
-cloth_config_forge=4.1.0
\ No newline at end of file
+forge_version=35.1.7
+cloth_config_forge=4.1.3
\ No newline at end of file
-FABRIC /assets/lightoverlay/lang/en_us.json
-FORGE /META-INF/MANIFEST.MF
-FABRIC /icon.png
\ No newline at end of file
+FORGE /META-INF/MANIFEST.MF
\ No newline at end of file
pluginManagement {
repositories {
jcenter()
- maven {
- name = 'Fabric'
- url = 'https://maven.fabricmc.net/'
- }
+ maven { url "https://maven.fabricmc.net/" }
maven { url "https://dl.bintray.com/shedaniel/cloth" }
+ maven { url "https://files.minecraftforge.net/maven/" }
gradlePluginPortal()
}
}