]> git.lizzy.rs Git - LightOverlay.git/commitdiff
Migrate to architectury fully
authorshedaniel <daniel@shedaniel.me>
Fri, 1 Jan 2021 17:34:15 +0000 (01:34 +0800)
committershedaniel <daniel@shedaniel.me>
Fri, 1 Jan 2021 17:34:15 +0000 (01:34 +0800)
Signed-off-by: shedaniel <daniel@shedaniel.me>
31 files changed:
build.gradle
common/build.gradle
common/src/main/java/me/shedaniel/lightoverlay/common/AbstractPlatform.java [deleted file]
common/src/main/java/me/shedaniel/lightoverlay/common/LightOverlay.java [new file with mode: 0644]
common/src/main/java/me/shedaniel/lightoverlay/common/LightOverlayCore.java [deleted file]
fabric/build.gradle
fabric/src/main/java/me/shedaniel/lightoverlay/fabric/LOModMenuEntry.java
fabric/src/main/java/me/shedaniel/lightoverlay/fabric/LightOverlay.java [deleted file]
fabric/src/main/java/me/shedaniel/lightoverlay/fabric/LightOverlayImpl.java [new file with mode: 0644]
fabric/src/main/java/me/shedaniel/lightoverlay/fabric/mixin/MixinClientConnection.java
fabric/src/main/java/me/shedaniel/lightoverlay/fabric/mixin/MixinWorldRenderer.java [deleted file]
fabric/src/main/resources/fabric.mod.json
fabric/src/main/resources/lightoverlay.mixins.json
forge/build.gradle
forge/gradle.properties [new file with mode: 0644]
forge/src/main/java/me/shedaniel/lightoverlay/forge/FrustumHelper.java
forge/src/main/java/me/shedaniel/lightoverlay/forge/LightOverlay.java
forge/src/main/java/me/shedaniel/lightoverlay/forge/LightOverlayClient.java [deleted file]
forge/src/main/java/me/shedaniel/lightoverlay/forge/LightOverlayCloth.java
forge/src/main/java/me/shedaniel/lightoverlay/forge/LightOverlayImpl.java [new file with mode: 0644]
forge/src/main/java/me/shedaniel/lightoverlay/forge/mixin/MixinClientConnection.java [new file with mode: 0644]
forge/src/main/java/me/shedaniel/lightoverlay/forge/mixin/MixinDebugRenderer.java [new file with mode: 0644]
forge/src/main/java/me/shedaniel/lightoverlay/forge/mixin/MixinLevelRenderer.java [new file with mode: 0644]
forge/src/main/resources/META-INF/NetworkManager.js [deleted file]
forge/src/main/resources/META-INF/WorldRenderer.js [deleted file]
forge/src/main/resources/META-INF/coremods.json [deleted file]
forge/src/main/resources/META-INF/mods.toml
forge/src/main/resources/lightoverlay-forge.mixins.json [new file with mode: 0644]
gradle.properties
merging.policy
settings.gradle

index 7a18195b347d4889b1afe2964c6c91dac24003fc..861026fe60fe499ae386c7de3fb7c9322ac98e36 100644 (file)
@@ -7,8 +7,6 @@ buildscript {
     }
 }
 
-import org.jetbrains.gradle.ext.ActionDelegationConfig
-
 import java.nio.file.FileVisitResult
 import java.nio.file.Files
 import java.nio.file.Path
@@ -20,54 +18,44 @@ import java.util.zip.ZipInputStream
 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")
@@ -99,13 +87,15 @@ task buildMerged {
                             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)
index 6c6aadb968ef080f869e4e233adbd852471ba9b2..8c3d1b66b700dbca4773bb2971388eea83f0d049 100644 (file)
@@ -1,10 +1,7 @@
-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}"
 }
 
diff --git a/common/src/main/java/me/shedaniel/lightoverlay/common/AbstractPlatform.java b/common/src/main/java/me/shedaniel/lightoverlay/common/AbstractPlatform.java
deleted file mode 100644 (file)
index a237060..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-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);
-}
diff --git a/common/src/main/java/me/shedaniel/lightoverlay/common/LightOverlay.java b/common/src/main/java/me/shedaniel/lightoverlay/common/LightOverlay.java
new file mode 100644 (file)
index 0000000..ec86af8
--- /dev/null
@@ -0,0 +1,587 @@
+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
+    }
+}
diff --git a/common/src/main/java/me/shedaniel/lightoverlay/common/LightOverlayCore.java b/common/src/main/java/me/shedaniel/lightoverlay/common/LightOverlayCore.java
deleted file mode 100644 (file)
index 2c40c2d..0000000
+++ /dev/null
@@ -1,489 +0,0 @@
-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
-    }
-}
index 9b8058da031f18d2f18f37aa6d96e6f7dae00419..5f297e7bc0670280dce9b13c1abfd7d2c00e6a2a 100755 (executable)
@@ -1,5 +1,4 @@
 plugins {
-    id "fabric-loom"
     id "com.github.johnrengelman.shadow" version "5.0.0"
 }
 
@@ -7,6 +6,10 @@ minecraft {
     accessWidener = file("src/main/resources/lightoverlay.accesswidener")
 }
 
+architectury {
+    platformSetupLoomIde()
+}
+
 processResources {
     filesMatching("fabric.mod.json") {
         expand "version": project.version
@@ -24,26 +27,24 @@ dependencies {
     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
     }
 }
@@ -58,4 +59,5 @@ shadowJar {
 remapJar {
     dependsOn(shadowJar)
     input.set(shadowJar.archivePath)
+    archiveClassifier = "fabric"
 }
\ No newline at end of file
index 741e3a2559c5c877c98cd15f8b5e7dc8de5f551d..ee3cc509c97a6cc17eb3652d551d5d0d87a0c35b 100644 (file)
@@ -6,7 +6,7 @@ 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 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;
@@ -28,31 +28,31 @@ public class LOModMenuEntry implements ModMenuApi {
         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();
     }
 }
diff --git a/fabric/src/main/java/me/shedaniel/lightoverlay/fabric/LightOverlay.java b/fabric/src/main/java/me/shedaniel/lightoverlay/fabric/LightOverlay.java
deleted file mode 100644 (file)
index da0f190..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-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);
-    }
-}
diff --git a/fabric/src/main/java/me/shedaniel/lightoverlay/fabric/LightOverlayImpl.java b/fabric/src/main/java/me/shedaniel/lightoverlay/fabric/LightOverlayImpl.java
new file mode 100644 (file)
index 0000000..56ba706
--- /dev/null
@@ -0,0 +1,19 @@
+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);
+    }
+}
index bdb88d7daf345c0d10528b63d6fbe1cad4b23fc7..5320e78ae4471d73073a289cf16e0a7202cd5594 100644 (file)
@@ -1,6 +1,6 @@
 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;
@@ -19,13 +19,13 @@ public class MixinClientConnection {
     @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()));
         }
     }
 }
diff --git a/fabric/src/main/java/me/shedaniel/lightoverlay/fabric/mixin/MixinWorldRenderer.java b/fabric/src/main/java/me/shedaniel/lightoverlay/fabric/mixin/MixinWorldRenderer.java
deleted file mode 100644 (file)
index 8183969..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-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;
-    }
-}
index a8f12bdf3f66dfd9a5ffa71110b3add375ede0db..ee934035bd1607a9182fe111e38574424c92317f 100755 (executable)
@@ -15,7 +15,7 @@
   },
   "entrypoints": {
     "client": [
-      "me.shedaniel.lightoverlay.fabric.LightOverlay"
+      "me.shedaniel.lightoverlay.fabric.LightOverlayImpl::init"
     ],
     "modmenu": [
       "me.shedaniel.lightoverlay.fabric.LOModMenuEntry"
@@ -29,5 +29,9 @@
   "accessWidener": "lightoverlay.accesswidener",
   "custom": {
     "modmenu:clientsideOnly": true
+  },
+  "depends": {
+    "fabric-api": ">=0.29.1",
+    "architectury": ">=1.2.67"
   }
 }
index 7b63a7bd750ad216a625907435d5ecfc7dbff33d..cb0c3f1f58b90e87e9476f4f0d1a3d6d2bf7b86e 100644 (file)
@@ -5,8 +5,7 @@
   "compatibilityLevel": "JAVA_8",
   "mixins": [],
   "client": [
-    "MixinClientConnection",
-    "MixinWorldRenderer"
+    "MixinClientConnection"
   ],
   "injectors": {
     "defaultRequire": 1
index c8f2722f9f9832aebf8fff1a7ff96a3f32b68dd3..c90d7b3985330eec962ead514bd0f9661004552c 100644 (file)
@@ -1,62 +1,45 @@
-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
     }
 }
@@ -66,9 +49,11 @@ shadowJar {
     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
diff --git a/forge/gradle.properties b/forge/gradle.properties
new file mode 100644 (file)
index 0000000..01c185b
--- /dev/null
@@ -0,0 +1 @@
+loom.forge=true
\ No newline at end of file
index b02448d75fe61cd6ab63ce93ffa91e3f6103ebf1..46acc0bea33b2aac29cfac8d75e438e7ee6d9a88 100644 (file)
@@ -1,10 +1,10 @@
 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);
@@ -14,7 +14,7 @@ public class FrustumHelper {
         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) {
index cd2c6e6277ba9b5e240c5e2a64ec8a5395ae9995..4c840aa9cf4fac07ef9fae3ff70b97ccc94c784f 100644 (file)
@@ -1,22 +1,17 @@
 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);
     }
 }
diff --git a/forge/src/main/java/me/shedaniel/lightoverlay/forge/LightOverlayClient.java b/forge/src/main/java/me/shedaniel/lightoverlay/forge/LightOverlayClient.java
deleted file mode 100644 (file)
index 30ab28a..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-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()));
-        }
-    }
-}
index 42b3118c5211d542662864be7411cef956022963..2efb4c1affdff569560eef0917352ea74fbaafe5 100644 (file)
@@ -4,11 +4,11 @@ import me.shedaniel.clothconfig2.forge.api.ConfigBuilder;
 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;
 
@@ -17,36 +17,36 @@ 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(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();
         });
     }
diff --git a/forge/src/main/java/me/shedaniel/lightoverlay/forge/LightOverlayImpl.java b/forge/src/main/java/me/shedaniel/lightoverlay/forge/LightOverlayImpl.java
new file mode 100644 (file)
index 0000000..624b9be
--- /dev/null
@@ -0,0 +1,29 @@
+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();
+    }
+}
diff --git a/forge/src/main/java/me/shedaniel/lightoverlay/forge/mixin/MixinClientConnection.java b/forge/src/main/java/me/shedaniel/lightoverlay/forge/mixin/MixinClientConnection.java
new file mode 100644 (file)
index 0000000..b6c8274
--- /dev/null
@@ -0,0 +1,31 @@
+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()));
+        }
+    }
+}
diff --git a/forge/src/main/java/me/shedaniel/lightoverlay/forge/mixin/MixinDebugRenderer.java b/forge/src/main/java/me/shedaniel/lightoverlay/forge/mixin/MixinDebugRenderer.java
new file mode 100644 (file)
index 0000000..dd29fd9
--- /dev/null
@@ -0,0 +1,18 @@
+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();
+    }
+}
diff --git a/forge/src/main/java/me/shedaniel/lightoverlay/forge/mixin/MixinLevelRenderer.java b/forge/src/main/java/me/shedaniel/lightoverlay/forge/mixin/MixinLevelRenderer.java
new file mode 100644 (file)
index 0000000..e77d2d6
--- /dev/null
@@ -0,0 +1,18 @@
+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;
+    }
+}
diff --git a/forge/src/main/resources/META-INF/NetworkManager.js b/forge/src/main/resources/META-INF/NetworkManager.js
deleted file mode 100644 (file)
index 6f586f1..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-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
diff --git a/forge/src/main/resources/META-INF/WorldRenderer.js b/forge/src/main/resources/META-INF/WorldRenderer.js
deleted file mode 100644 (file)
index 5f29014..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-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
diff --git a/forge/src/main/resources/META-INF/coremods.json b/forge/src/main/resources/META-INF/coremods.json
deleted file mode 100644 (file)
index ed2abed..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-{
-  "NetworkManager": "META-INF/NetworkManager.js",
-  "WorldRenderer": "META-INF/WorldRenderer.js"
-}
\ No newline at end of file
index 418c41a2269c49c13c1faf69351c21a47fdfd995..5f7f7da56ad4e22b02cc7a0139bafda79abb777e 100755 (executable)
@@ -1,20 +1,27 @@
-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
diff --git a/forge/src/main/resources/lightoverlay-forge.mixins.json b/forge/src/main/resources/lightoverlay-forge.mixins.json
new file mode 100644 (file)
index 0000000..798efb5
--- /dev/null
@@ -0,0 +1,15 @@
+{
+  "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
index 04356396d7230c22a7289538ed643c00567185c9..cd3f4daf206eb88ebb491a6a31cc73936e72a604 100755 (executable)
@@ -1,16 +1,17 @@
 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
index f956d760df5c017b026085872312c2a83c522dd7..6192e0b275a1f66299f5777d564f089cfadfa584 100644 (file)
@@ -1,3 +1 @@
-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
index 5cfc93160143489b8ce5a38a580ad5a97a388aee..a28885afcb1debe4e6ff7de0d82935527fce3bff 100644 (file)
@@ -1,11 +1,9 @@
 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()
     }
 }