]> git.lizzy.rs Git - LightOverlay.git/commitdiff
Multi-loader common module build
authorshedaniel <daniel@shedaniel.me>
Fri, 2 Oct 2020 10:06:41 +0000 (18:06 +0800)
committershedaniel <daniel@shedaniel.me>
Fri, 2 Oct 2020 10:06:41 +0000 (18:06 +0800)
Signed-off-by: shedaniel <daniel@shedaniel.me>
30 files changed:
.gitignore
architectPlugin/build.gradle [new file with mode: 0644]
architectPlugin/settings.gradle [new file with mode: 0644]
architectPlugin/src/main/kotlin/me/shedaniel/plugin/architect/ArchitectPlugin.kt [new file with mode: 0644]
architectPlugin/src/main/kotlin/me/shedaniel/plugin/architect/ArchitectPluginExtension.kt [new file with mode: 0644]
architectPlugin/src/main/kotlin/me/shedaniel/plugin/architect/RemapMCPTask.kt [new file with mode: 0644]
build.gradle
common/build.gradle [new file with mode: 0644]
common/src/main/java/me/shedaniel/lightoverlay/common/AbstractPlatform.java [new file with mode: 0644]
common/src/main/java/me/shedaniel/lightoverlay/common/LightOverlayCore.java [new file with mode: 0644]
common/src/main/resources/assets/lightoverlay/lang/en_us.json [new file with mode: 0755]
common/src/main/resources/fabric.mod.json [new file with mode: 0755]
common/src/main/resources/icon.png [new file with mode: 0644]
fabric/build.gradle
fabric/src/main/java/me/shedaniel/lightoverlay/fabric/FrustumHelper.java
fabric/src/main/java/me/shedaniel/lightoverlay/fabric/LOModMenuEntry.java
fabric/src/main/java/me/shedaniel/lightoverlay/fabric/LightOverlay.java
fabric/src/main/java/me/shedaniel/lightoverlay/fabric/mixin/MixinClientConnection.java
fabric/src/main/java/me/shedaniel/lightoverlay/fabric/mixin/MixinWorldRenderer.java
fabric/src/main/resources/assets/lightoverlay/lang/en_us.json [deleted file]
fabric/src/main/resources/icon.png [deleted file]
fabric/src/main/resources/lightoverlay.accesswidener
forge/build.gradle
forge/src/main/java/me/shedaniel/lightoverlay/forge/FrustumHelper.java
forge/src/main/java/me/shedaniel/lightoverlay/forge/LightOverlayClient.java
forge/src/main/java/me/shedaniel/lightoverlay/forge/LightOverlayCloth.java
forge/src/main/resources/assets/lightoverlay/lang/en_us.json [deleted file]
forge/src/main/resources/icon.png [deleted file]
gradle.properties
settings.gradle

index e787a1c7011cc5e99bd218544ff6fb07ac24a089..d74b1524af30ce6671d2e341244e8446890c6e37 100644 (file)
@@ -12,6 +12,7 @@
 */out
 /run
 /classes
+logs/
 
 # IDE nonsense that could go in source control but really shouldn't
 .classpath
diff --git a/architectPlugin/build.gradle b/architectPlugin/build.gradle
new file mode 100644 (file)
index 0000000..7db7ebe
--- /dev/null
@@ -0,0 +1,35 @@
+plugins {
+    id "org.jetbrains.kotlin.jvm" version "1.3.72"
+}
+
+repositories {
+    jcenter()
+    maven { url "https://maven.fabricmc.net/" }
+}
+
+apply plugin: 'java-gradle-plugin'
+
+dependencies {
+    implementation gradleApi()
+    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.3.72"
+    implementation "org.jetbrains.kotlin:kotlin-reflect:1.3.72"
+    implementation "net.fabricmc:fabric-loom:0.5-SNAPSHOT"
+    runtime "net.fabricmc:fabric-loom:0.5-SNAPSHOT"
+    implementation "net.fabricmc:tiny-remapper:0.3.0.70"
+    implementation "net.fabricmc:tiny-mappings-parser:0.2.2.14"
+}
+
+compileKotlin {
+    kotlinOptions {
+        jvmTarget = "1.8"
+    }
+}
+
+gradlePlugin {
+    plugins {
+        architect {
+            id = 'me.shedaniel.plugin.architect'
+            implementationClass = 'me.shedaniel.plugin.architect.ArchitectPlugin'
+        }
+    }
+}
\ No newline at end of file
diff --git a/architectPlugin/settings.gradle b/architectPlugin/settings.gradle
new file mode 100644 (file)
index 0000000..9c68a5a
--- /dev/null
@@ -0,0 +1,6 @@
+pluginManagement {
+    repositories {
+        jcenter()
+        gradlePluginPortal()
+    }
+}
diff --git a/architectPlugin/src/main/kotlin/me/shedaniel/plugin/architect/ArchitectPlugin.kt b/architectPlugin/src/main/kotlin/me/shedaniel/plugin/architect/ArchitectPlugin.kt
new file mode 100644 (file)
index 0000000..21638f8
--- /dev/null
@@ -0,0 +1,28 @@
+package me.shedaniel.plugin.architect
+
+import org.gradle.api.JavaVersion
+import org.gradle.api.Plugin
+import org.gradle.api.Project
+import org.gradle.api.plugins.JavaPluginExtension
+
+class ArchitectPlugin : Plugin<Project> {
+    override fun apply(project: Project) {
+        project.apply(mapOf(
+                "plugin" to "java",
+                "plugin" to "eclipse",
+                "plugin" to "idea"
+        ))
+        project.extensions.create("architect", ArchitectPluginExtension::class.java, project)
+        
+        project.afterEvaluate {
+            project.extensions.getByType(JavaPluginExtension::class.java).apply {
+                sourceCompatibility = JavaVersion.VERSION_1_8
+                targetCompatibility = JavaVersion.VERSION_1_8
+            }
+        }
+        
+        project.tasks.register("remapMcp", RemapMCPTask::class.java) {
+            
+        }
+    }
+}
\ No newline at end of file
diff --git a/architectPlugin/src/main/kotlin/me/shedaniel/plugin/architect/ArchitectPluginExtension.kt b/architectPlugin/src/main/kotlin/me/shedaniel/plugin/architect/ArchitectPluginExtension.kt
new file mode 100644 (file)
index 0000000..260bdfa
--- /dev/null
@@ -0,0 +1,7 @@
+package me.shedaniel.plugin.architect
+
+import org.gradle.api.Project
+
+open class ArchitectPluginExtension(val project: Project) {
+    var minecraft = ""
+}
\ No newline at end of file
diff --git a/architectPlugin/src/main/kotlin/me/shedaniel/plugin/architect/RemapMCPTask.kt b/architectPlugin/src/main/kotlin/me/shedaniel/plugin/architect/RemapMCPTask.kt
new file mode 100644 (file)
index 0000000..e6a62b0
--- /dev/null
@@ -0,0 +1,147 @@
+@file:Suppress("UnstableApiUsage")
+
+package me.shedaniel.plugin.architect
+
+import net.fabricmc.loom.LoomGradleExtension
+import net.fabricmc.loom.util.GradleSupport
+import net.fabricmc.loom.util.TinyRemapperMappingsHelper
+import net.fabricmc.mapping.tree.TinyTree
+import net.fabricmc.tinyremapper.IMappingProvider
+import net.fabricmc.tinyremapper.NonClassCopyMode
+import net.fabricmc.tinyremapper.OutputConsumerPath
+import net.fabricmc.tinyremapper.TinyRemapper
+import org.gradle.api.file.RegularFileProperty
+import org.gradle.api.tasks.TaskAction
+import org.gradle.jvm.tasks.Jar
+import java.io.FileNotFoundException
+import java.io.InputStream
+import java.net.URL
+import java.nio.file.Files
+import java.nio.file.Path
+
+
+open class RemapMCPTask : Jar() {
+    private val fromM: String = "named"
+    private val toM: String = "official"
+    val input: RegularFileProperty = GradleSupport.getfileProperty(project)
+
+    @TaskAction
+    fun doTask() {
+        val input: Path = this.input.asFile.get().toPath()
+        val output: Path = this.archiveFile.get().asFile.toPath()
+
+        output.toFile().delete()
+
+        if (!Files.exists(input)) {
+            throw FileNotFoundException(input.toString())
+        }
+
+        val remapperBuilder: TinyRemapper.Builder = TinyRemapper.newRemapper()
+        val mappings = getMappings()
+        val mojmapToMcpClass = createMojmapToMcpClass(mappings)
+        remapperBuilder.withMappings(remapToMcp(TinyRemapperMappingsHelper.create(mappings, fromM, toM, false), mojmapToMcpClass))
+
+        project.logger.lifecycle(":remapping " + input.fileName)
+
+        val architectFolder = project.rootProject.buildDir.resolve("tmp/architect")
+        architectFolder.deleteRecursively()
+        architectFolder.mkdirs()
+        val manifestFile = architectFolder.resolve("META-INF/MANIFEST.MF")
+        manifestFile.parentFile.mkdirs()
+        manifestFile.writeText("""
+Manifest-Version: 1.0
+FMLModType: LIBRARY
+        """.trimIndent())
+
+        val remapper = remapperBuilder.build()
+
+        try {
+            OutputConsumerPath.Builder(output).build().use { outputConsumer ->
+                outputConsumer.addNonClassFiles(input, NonClassCopyMode.SKIP_META_INF, null)
+                outputConsumer.addNonClassFiles(architectFolder.toPath(), NonClassCopyMode.UNCHANGED, null)
+                remapper.readInputs(input)
+                remapper.apply(outputConsumer)
+            }
+        } catch (e: Exception) {
+            remapper.finish()
+            throw RuntimeException("Failed to remap $input to $output", e)
+        }
+
+        architectFolder.deleteRecursively()
+        remapper.finish()
+
+        if (!Files.exists(output)) {
+            throw RuntimeException("Failed to remap $input to $output - file missing!")
+        }
+    }
+
+    private fun remapToMcp(parent: IMappingProvider, mojmapToMcpClass: Map<String, String>): IMappingProvider = IMappingProvider {
+        it.acceptClass("net/fabricmc/api/Environment","net/minecraftforge/api/distmarker/OnlyIn") 
+        it.acceptClass("net/fabricmc/api/EnvType","net/minecraftforge/api/distmarker/Dist") 
+        it.acceptField(IMappingProvider.Member("net/fabricmc/api/EnvType", "SERVER", "Lnet/fabricmc/api/EnvType;"),"DEDICATED_SERVER") 
+        
+        parent.load(object : IMappingProvider.MappingAcceptor {
+            override fun acceptClass(srcName: String?, dstName: String?) {
+                it.acceptClass(srcName, mojmapToMcpClass[srcName] ?: srcName)
+            }
+
+            override fun acceptMethod(method: IMappingProvider.Member?, dstName: String?) {
+                it.acceptMethod(method, dstName)
+            }
+
+            override fun acceptMethodArg(method: IMappingProvider.Member?, lvIndex: Int, dstName: String?) {
+                it.acceptMethodArg(method, lvIndex, dstName)
+            }
+
+            override fun acceptMethodVar(method: IMappingProvider.Member?, lvIndex: Int, startOpIdx: Int, asmIndex: Int, dstName: String?) {
+                it.acceptMethodVar(method, lvIndex, startOpIdx, asmIndex, dstName)
+            }
+
+            override fun acceptField(field: IMappingProvider.Member?, dstName: String?) {
+                it.acceptField(field, dstName)
+            }
+        })
+    }
+
+    private fun getMappings(): TinyTree {
+        val loomExtension = project.extensions.getByType(LoomGradleExtension::class.java)
+        return loomExtension.mappingsProvider.mappings
+    }
+
+    private fun getRootExtension(): ArchitectPluginExtension =
+            project.rootProject.extensions.getByType(ArchitectPluginExtension::class.java)
+
+    private fun createMojmapToMcpClass(mappings: TinyTree): Map<String, String> {
+        val mcpMappings = readMCPMappings(getRootExtension().minecraft)
+        val mutableMap = mutableMapOf<String, String>()
+        mappings.classes.forEach { clazz ->
+            val official = clazz.getName("official")
+            val named = clazz.getName("named")
+            val mcp = mcpMappings[official]
+            if (mcp != null) {
+                mutableMap[named] = mcp
+            }
+        }
+        return mutableMap
+    }
+
+    private fun readMCPMappings(version: String): Map<String, String> {
+        val file = project.rootProject.file(".gradle/mappings/mcp-$version.tsrg")
+        if (file.exists().not()) {
+            file.parentFile.mkdirs()
+            file.writeText(URL("https://raw.githubusercontent.com/MinecraftForge/MCPConfig/master/versions/release/$version/joined.tsrg").readText())
+        }
+        return mutableMapOf<String, String>().also { readMappings(it, file.inputStream()) }
+    }
+
+    private fun readMappings(mutableMap: MutableMap<String, String>, inputStream: InputStream) {
+        inputStream.bufferedReader().forEachLine {
+            if (!it.startsWith("\t")) {
+                val split = it.split(" ")
+                val obf = split[0]
+                val className = split[1]
+                mutableMap[obf] = className
+            }
+        }
+    }
+}
\ No newline at end of file
index a87cca45e3bab40838335babfec0afd6b4e77789..228b6bdf8aaae23586c9c5a7862d753201b1c4e8 100644 (file)
@@ -20,17 +20,21 @@ import java.util.zip.ZipInputStream
 import java.util.zip.ZipOutputStream
 
 plugins {
+    id "me.shedaniel.plugin.architect"
     id "org.jetbrains.gradle.plugin.idea-ext" version "0.7"
 }
 
+architect {
+    minecraft = minecraft_version
+}
+
 allprojects {
     apply plugin: "java"
+    apply plugin: "me.shedaniel.plugin.architect"
 
     group "me.shedaniel"
     archivesBaseName = rootProject.name
     version = rootProject.mod_version
-
-    sourceCompatibility = targetCompatibility = compileJava.sourceCompatibility = compileJava.targetCompatibility = JavaVersion.VERSION_1_8
 }
 
 idea.project.settings {
diff --git a/common/build.gradle b/common/build.gradle
new file mode 100644 (file)
index 0000000..79e9531
--- /dev/null
@@ -0,0 +1,26 @@
+plugins {
+    id "fabric-loom"
+}
+
+dependencies {
+    minecraft "com.mojang:minecraft:${rootProject.architect.minecraft}"
+    mappings minecraft.officialMojangMappings()
+    modCompile "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}"
+}
+
+configurations {
+    mcp
+}
+
+remapMcp {
+    input.set(file("${project.buildDir}/libs/$archivesBaseName-${project.version}-dev.jar"))
+    classifier("mcp")
+}
+
+remapJar.dependsOn(jar)
+
+artifacts {
+    mcp file: file("${project.buildDir}/libs/$archivesBaseName-${version}-mcp.jar"), type: "jar", builtBy: remapMcp
+}
+
+build.dependsOn(remapMcp)
\ No newline at end of file
diff --git a/common/src/main/java/me/shedaniel/lightoverlay/common/AbstractPlatform.java b/common/src/main/java/me/shedaniel/lightoverlay/common/AbstractPlatform.java
new file mode 100644 (file)
index 0000000..a237060
--- /dev/null
@@ -0,0 +1,18 @@
+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/LightOverlayCore.java b/common/src/main/java/me/shedaniel/lightoverlay/common/LightOverlayCore.java
new file mode 100644 (file)
index 0000000..2c40c2d
--- /dev/null
@@ -0,0 +1,489 @@
+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
+    }
+}
diff --git a/common/src/main/resources/assets/lightoverlay/lang/en_us.json b/common/src/main/resources/assets/lightoverlay/lang/en_us.json
new file mode 100755 (executable)
index 0000000..5346550
--- /dev/null
@@ -0,0 +1,18 @@
+{
+  "key.lightoverlay.category": "Light Overlay",
+  "key.lightoverlay.enable_overlay": "Toggle Light Overlay",
+  "description.lightoverlay.caching": "Caching is recommended if the reach is above 16 or if you are running on a potato.",
+  "config.lightoverlay.general": "General",
+  "config.lightoverlay.reach": "Reach:",
+  "config.lightoverlay.caching": "Caching:",
+  "config.lightoverlay.crossLevel": "Light Level:",
+  "config.lightoverlay.secondaryLevel": "Secondary Light Level:",
+  "config.lightoverlay.showNumber": "Show Number Instead:",
+  "config.lightoverlay.smoothLines": "Smooth Lines:",
+  "config.lightoverlay.underwater": "Display Underwater:",
+  "config.lightoverlay.lineWidth": "Line Width:",
+  "config.lightoverlay.yellowColor": "Yellow Color:",
+  "config.lightoverlay.secondaryColor": "Secondary Color:",
+  "config.lightoverlay.redColor": "Red Color:",
+  "config.lightoverlay.invalidColor": "Invalid Color"
+}
\ No newline at end of file
diff --git a/common/src/main/resources/fabric.mod.json b/common/src/main/resources/fabric.mod.json
new file mode 100755 (executable)
index 0000000..4fed948
--- /dev/null
@@ -0,0 +1,7 @@
+{
+  "_comment": "This file is here to make fabric load this on Knot classloader.",
+  "schemaVersion": 1,
+  "id": "lightoverlay-core",
+  "name": "Light Overlay Core",
+  "version": "0.0.1"
+}
diff --git a/common/src/main/resources/icon.png b/common/src/main/resources/icon.png
new file mode 100644 (file)
index 0000000..8bfd85a
Binary files /dev/null and b/common/src/main/resources/icon.png differ
index 6cd73c20de7617dc0800015279cce0a3c8ecbe82..9b8058da031f18d2f18f37aa6d96e6f7dae00419 100755 (executable)
@@ -1,5 +1,6 @@
 plugins {
-    id("fabric-loom") version "0.4-SNAPSHOT"
+    id "fabric-loom"
+    id "com.github.johnrengelman.shadow" version "5.0.0"
 }
 
 minecraft {
@@ -13,14 +14,13 @@ processResources {
     inputs.property "version", project.version
 }
 
-repositories {
-    jcenter()
-    maven { url "https://dl.bintray.com/shedaniel/legacy-yarn-updated" }
+configurations {
+    shadow
 }
 
 dependencies {
-    minecraft "com.mojang:minecraft:${rootProject.fabric_minecraft_version}"
-    mappings "me.shedaniel:legacy-yarn:${rootProject.yarn_build}:v2"
+    minecraft "com.mojang:minecraft:${rootProject.architect.minecraft}"
+    mappings minecraft.officialMojangMappings()
     modCompile "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}"
 
     modCompile "net.fabricmc.fabric-api:fabric-api:${rootProject.fabric_api_version}"
@@ -39,4 +39,23 @@ dependencies {
     include("me.shedaniel.cloth:config-2:${rootProject.cloth_config_version}") {
         transitive = false
     }
+
+    compile(project(":common")) {
+        transitive = false
+    }
+    shadow(project(":common")) {
+        transitive = false
+    }
 }
+
+shadowJar {
+    relocate "me.shedaniel.lightoverlay.common", "me.shedaniel.lightoverlay.common.fabric"
+
+    configurations = [project.configurations.shadow]
+    classifier "shadow"
+}
+
+remapJar {
+    dependsOn(shadowJar)
+    input.set(shadowJar.archivePath)
+}
\ No newline at end of file
index 278ff84af8ca37ad836553c0360db96780f9d959..ee36fdc4b8772d9a5d57917656882aae75e8966c 100644 (file)
@@ -1,21 +1,21 @@
 package me.shedaniel.lightoverlay.fabric;
 
-import net.minecraft.client.render.Frustum;
-import net.minecraft.client.util.math.Vector4f;
+import com.mojang.math.Vector4f;
+import net.minecraft.client.renderer.culling.Frustum;
 
 public class FrustumHelper {
     public static boolean isVisible(Frustum frustum, double minX, double minY, double minZ, double maxX, double maxY, double maxZ) {
-        float x1 = (float) (minX - frustum.x);
-        float y1 = (float) (minY - frustum.y);
-        float z1 = (float) (minZ - frustum.z);
-        float x2 = (float) (maxX - frustum.x);
-        float y2 = (float) (maxY - frustum.y);
-        float z2 = (float) (maxZ - frustum.z);
+        float x1 = (float) (minX - frustum.camX);
+        float y1 = (float) (minY - frustum.camY);
+        float z1 = (float) (minZ - frustum.camZ);
+        float x2 = (float) (maxX - frustum.camX);
+        float y2 = (float) (maxY - frustum.camY);
+        float z2 = (float) (maxZ - frustum.camZ);
         return isAnyCornerVisible(frustum, x1, y1, z1, x2, y2, z2);
     }
     
     private static boolean isAnyCornerVisible(Frustum frustum, float x1, float y1, float z1, float x2, float y2, float z2) {
-        Vector4f[] homogeneousCoordinates = frustum.homogeneousCoordinates;
+        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) {
                 return false;
@@ -26,6 +26,6 @@ public class FrustumHelper {
     }
     
     private static float dotProduct(Vector4f self, float x, float y, float z, float w) {
-        return self.getX() * x + self.getY() * y + self.getZ() * z + self.getW() * w;
+        return self.x() * x + self.y() * y + self.z() * z + self.w() * w;
     }
 }
index c7f4c852f9a3b7c82a40c8ba5bbf6b1570e7eb8f..741e3a2559c5c877c98cd15f8b5e7dc8de5f551d 100644 (file)
@@ -6,12 +6,13 @@ import me.shedaniel.clothconfig2.api.ConfigBuilder;
 import me.shedaniel.clothconfig2.api.ConfigCategory;
 import me.shedaniel.clothconfig2.api.ConfigEntryBuilder;
 import me.shedaniel.clothconfig2.gui.entries.IntegerSliderEntry;
-import net.minecraft.client.gui.screen.Screen;
-import net.minecraft.client.resource.language.I18n;
-import net.minecraft.text.LiteralText;
-import net.minecraft.text.Text;
-import net.minecraft.text.TranslatableText;
-import net.minecraft.util.math.MathHelper;
+import me.shedaniel.lightoverlay.common.LightOverlayCore;
+import net.minecraft.client.gui.screens.Screen;
+import net.minecraft.client.resources.language.I18n;
+import net.minecraft.network.chat.Component;
+import net.minecraft.network.chat.TextComponent;
+import net.minecraft.network.chat.TranslatableComponent;
+import net.minecraft.util.Mth;
 
 import java.util.Optional;
 
@@ -22,35 +23,36 @@ public class LOModMenuEntry implements ModMenuApi {
     }
     
     public Screen getConfigScreenByCloth(Screen parent) {
-        ConfigBuilder builder = ConfigBuilder.create().setParentScreen(parent).setTitle(new TranslatableText("key.lightoverlay.category"));
+        ConfigBuilder builder = ConfigBuilder.create().setParentScreen(parent).setTitle(new TranslatableComponent("key.lightoverlay.category"));
         
         ConfigEntryBuilder eb = builder.entryBuilder();
-        ConfigCategory general = builder.getOrCreateCategory(new TranslatableText("config.lightoverlay.general"));
-        general.addEntry(eb.startTextDescription(Text.of("§7" + I18n.translate("description.lightoverlay.caching"))).build());
-        general.addEntry(eb.startBooleanToggle(new TranslatableText("config.lightoverlay.caching"), LightOverlay.caching).setDefaultValue(false).setSaveConsumer(bool -> LightOverlay.caching = bool).build());
-        general.addEntry(eb.startIntSlider(new TranslatableText("config.lightoverlay.reach"), LightOverlay.reach, 1, 64).setDefaultValue(12).setTextGetter(integer -> Text.of("Reach: " + integer + " Blocks")).setSaveConsumer(integer -> LightOverlay.reach = integer).build());
-        IntegerSliderEntry crossLevel = eb.startIntSlider(new TranslatableText("config.lightoverlay.crossLevel"), LightOverlay.crossLevel, 0, 15).setDefaultValue(7).setTextGetter(integer -> Text.of("Cross Level: " + integer)).setSaveConsumer(integer -> LightOverlay.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"), 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(crossLevel);
-        general.addEntry(eb.startIntSlider(new TranslatableText("config.lightoverlay.secondaryLevel"), LightOverlay.secondaryLevel, -1, 15)
+        general.addEntry(eb.startIntSlider(new TranslatableComponent("config.lightoverlay.secondaryLevel"), LightOverlayCore.secondaryLevel, -1, 15)
                 .setErrorSupplier(integer -> {
-                    if (integer >= 0 && integer >= crossLevel.getValue()) return Optional.of(new LiteralText("Secondary Level cannot be higher than Cross Level!"));
+                    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 LiteralText(integer < 0 ? "Off" : "Level: " + integer)).setSaveConsumer(integer -> LightOverlay.secondaryLevel = integer).build());
-        general.addEntry(eb.startBooleanToggle(new TranslatableText("config.lightoverlay.showNumber"), LightOverlay.showNumber).setDefaultValue(false).setSaveConsumer(bool -> LightOverlay.showNumber = bool).build());
-        general.addEntry(eb.startBooleanToggle(new TranslatableText("config.lightoverlay.smoothLines"), LightOverlay.smoothLines).setDefaultValue(true).setSaveConsumer(bool -> LightOverlay.smoothLines = bool).build());
-        general.addEntry(eb.startBooleanToggle(new TranslatableText("config.lightoverlay.underwater"), LightOverlay.underwater).setDefaultValue(false).setSaveConsumer(bool -> LightOverlay.underwater = bool).build());
-        general.addEntry(eb.startIntSlider(new TranslatableText("config.lightoverlay.lineWidth"), MathHelper.floor(LightOverlay.lineWidth * 100), 100, 700).setDefaultValue(100).setTextGetter(integer -> new LiteralText("Light Width: " + LightOverlay.FORMAT.format(integer / 100d))).setSaveConsumer(integer -> LightOverlay.lineWidth = integer / 100f).build());
-        general.addEntry(eb.startColorField(new TranslatableText("config.lightoverlay.yellowColor"), LightOverlay.yellowColor).setDefaultValue(0xFFFF00).setSaveConsumer(color -> LightOverlay.yellowColor = color).build());
-        general.addEntry(eb.startColorField(new TranslatableText("config.lightoverlay.redColor"), LightOverlay.redColor).setDefaultValue(0xFF0000).setSaveConsumer(color -> LightOverlay.redColor = color).build());
-        general.addEntry(eb.startColorField(new TranslatableText("config.lightoverlay.secondaryColor"), LightOverlay.secondaryColor).setDefaultValue(0x0000FF).setSaveConsumer(color -> LightOverlay.secondaryColor = color).build());
+                }).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());
         
         return builder.setSavingRunnable(() -> {
             try {
-                LightOverlay.saveConfig(LightOverlay.configFile);
+                LightOverlayCore.saveConfig(LightOverlayCore.configFile);
             } catch (Exception e) {
                 e.printStackTrace();
             }
-            LightOverlay.loadConfig(LightOverlay.configFile);
+            LightOverlayCore.loadConfig(LightOverlayCore.configFile);
         }).build();
     }
 }
index 23303baae4cb44c12a9fa4b593192c994dbb8c1e..da0f19077c6f6f3957508cb2eae680a5b293fd68 100644 (file)
 package me.shedaniel.lightoverlay.fabric;
 
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.mojang.blaze3d.platform.GlStateManager;
-import com.mojang.blaze3d.systems.RenderSystem;
-import it.unimi.dsi.fastutil.longs.Long2ReferenceMap;
-import it.unimi.dsi.fastutil.longs.Long2ReferenceOpenHashMap;
 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.block.Block;
-import net.minecraft.block.BlockState;
-import net.minecraft.client.MinecraftClient;
-import net.minecraft.client.font.TextRenderer;
-import net.minecraft.client.network.ClientPlayerEntity;
-import net.minecraft.client.options.KeyBinding;
-import net.minecraft.client.render.Camera;
-import net.minecraft.client.render.Frustum;
-import net.minecraft.client.render.Tessellator;
-import net.minecraft.client.render.VertexConsumerProvider;
-import net.minecraft.client.util.InputUtil;
-import net.minecraft.client.util.math.Rotation3;
-import net.minecraft.client.world.ClientWorld;
-import net.minecraft.entity.Entity;
-import net.minecraft.entity.EntityCategory;
-import net.minecraft.entity.EntityContext;
-import net.minecraft.entity.EntityType;
-import net.minecraft.entity.player.PlayerEntity;
-import net.minecraft.tag.BlockTags;
-import net.minecraft.util.Identifier;
-import net.minecraft.util.math.*;
-import net.minecraft.util.shape.VoxelShape;
-import net.minecraft.world.BlockView;
-import net.minecraft.world.LightType;
-import net.minecraft.world.World;
-import net.minecraft.world.chunk.ChunkStatus;
-import net.minecraft.world.chunk.WorldChunk;
-import net.minecraft.world.chunk.light.ChunkLightingView;
-import org.apache.logging.log4j.LogManager;
-import org.lwjgl.opengl.GL11;
+import net.minecraft.client.KeyMapping;
+import net.minecraft.client.renderer.culling.Frustum;
 
-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;
+import java.nio.file.Path;
 
-public class LightOverlay implements ClientModInitializer {
-    
-    static final DecimalFormat FORMAT = new DecimalFormat("#.#");
-    private static final String KEYBIND_CATEGORY = "key.lightoverlay.category";
-    private static final Identifier ENABLE_OVERLAY_KEYBIND = new Identifier("lightoverlay", "enable_overlay");
-    static int reach = 12;
-    static int crossLevel = 7;
-    static int secondaryLevel = -1;
-    static int lowerCrossLevel = -1;
-    static int higherCrossLevel = -1;
-    static boolean caching = false;
-    static boolean showNumber = false;
-    static boolean smoothLines = true;
-    static boolean underwater = false;
-    static float lineWidth = 1.0F;
-    static int yellowColor = 0xFFFF00, redColor = 0xFF0000, secondaryColor = 0x0000FF;
-    static File configFile = new File(FabricLoader.getInstance().getConfigDir().toFile(), "lightoverlay.properties");
-    private static final KeyBinding ENABLE_OVERLAY = createKeyBinding(ENABLE_OVERLAY_KEYBIND, InputUtil.Type.KEYSYM, 296, KEYBIND_CATEGORY);
-    private static boolean enabled = false;
-    private static EntityType<Entity> testingEntityType;
-    private static int threadNumber = 0;
-    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 MinecraftClient CLIENT = MinecraftClient.getInstance();
-    private static long ticks = 0;
-    
-    static {
-        ClientTickEvents.END_CLIENT_TICK.register(client -> {
-            try {
-                ticks++;
-                if (CLIENT.player == null || !enabled) {
-                    POS.clear();
-                    CHUNK_MAP.clear();
-                } else {
-                    if (!caching) {
-                        POS.clear();
-                        CHUNK_MAP.clear();
-                        ClientPlayerEntity player = CLIENT.player;
-                        ClientWorld world = CLIENT.world;
-                        BlockPos playerPos = player.getSenseCenterPos();
-                        EntityContext entityContext = EntityContext.of(player);
-                        ChunkLightingView block = world.getLightingProvider().get(LightType.BLOCK);
-                        ChunkLightingView sky = showNumber ? null : world.getLightingProvider().get(LightType.SKY);
-                        BlockPos.Mutable downPos = new BlockPos.Mutable();
-                        Iterable<BlockPos> iterate = BlockPos.iterate(playerPos.getX() - reach, playerPos.getY() - reach, playerPos.getZ() - reach,
-                                playerPos.getX() + reach, playerPos.getY() + reach, playerPos.getZ() + reach);
-                        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, entityContext);
-                                if (level >= 0) {
-                                    map.put(blockPos.asLong(), Integer.valueOf(level));
-                                }
-                            } else {
-                                CrossType type = getCrossType(blockPos, downPos, world, block, sky, entityContext);
-                                if (type != CrossType.NONE) {
-                                    map.put(blockPos.asLong(), type);
-                                }
-                            }
-                        }
-                    } else {
-                        ClientPlayerEntity player = CLIENT.player;
-                        ClientWorld world = CLIENT.world;
-                        EntityContext entityContext = EntityContext.of(player);
-                        Vec3d[] playerPos = {null};
-                        int playerPosX = ((int) player.getX()) >> 4;
-                        int playerPosZ = ((int) player.getZ()) >> 4;
-                        if (ticks % 20 == 0) {
-                            for (int chunkX = playerPosX - getChunkRange(); chunkX <= playerPosX + getChunkRange(); chunkX++) {
-                                for (int chunkZ = playerPosZ - getChunkRange(); chunkZ <= playerPosZ + getChunkRange(); chunkZ++) {
-                                    ChunkPos chunkPos = new ChunkPos(chunkX, chunkZ);
-                                    if (!CHUNK_MAP.containsKey(chunkPos))
-                                        queueChunk(chunkPos);
-                                }
-                            }
-                        }
-                        POS.removeIf(pos -> MathHelper.abs(pos.x - playerPosX) > getChunkRange() || MathHelper.abs(pos.z - playerPosZ) > getChunkRange());
-                        for (int k = 0; k < 2; k++) {
-                            if (!POS.isEmpty()) {
-                                if (playerPos[0] == null) {
-                                    playerPos[0] = player.getPos();
-                                }
-                                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.getChunkManager().getChunk(pos.x, pos.z, ChunkStatus.FULL, false), world, pos, entityContext);
-                                    } catch (Throwable throwable) {
-                                        LogManager.getLogger().throwing(throwable);
-                                    }
-                                });
-                            }
-                        }
-                        if (ticks % 50 == 0) {
-                            CHUNK_MAP.entrySet().removeIf(pos -> MathHelper.abs(pos.getKey().x - playerPosX) > getChunkRange() * 2 || MathHelper.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(MathHelper.ceil(reach / 16f), 1);
-    }
-    
-    private static void calculateChunk(WorldChunk chunk, World world, ChunkPos chunkPos, EntityContext entityContext) {
-        if (world != null && chunk != null) {
-            Long2ReferenceMap<Object> map = new Long2ReferenceOpenHashMap<>();
-            ChunkLightingView block = world.getLightingProvider().get(LightType.BLOCK);
-            ChunkLightingView sky = showNumber ? null : world.getLightingProvider().get(LightType.SKY);
-            for (BlockPos pos : BlockPos.iterate(chunkPos.getStartX(), 0, chunkPos.getStartZ(), chunkPos.getEndX(), 256, chunkPos.getEndZ())) {
-                BlockPos down = pos.down();
-                if (showNumber) {
-                    int level = LightOverlay.getCrossLevel(pos, down, chunk, block, entityContext);
-                    if (level >= 0) {
-                        map.put(pos.asLong(), Integer.valueOf(level));
-                    }
-                } else {
-                    CrossType type = LightOverlay.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, BlockView world, ChunkLightingView block, ChunkLightingView sky, EntityContext 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.isFaceFullSquare(upperCollisionShape, Direction.UP))
-            return CrossType.NONE;
-        // TODO: Not to hard code no redstone
-        if (blockUpperState.emitsRedstonePower())
-            return CrossType.NONE;
-        // Check if the collision has a bump
-        if (upperCollisionShape.getMaximum(Direction.Axis.Y) > 0)
-            return CrossType.NONE;
-        if (blockUpperState.getBlock().isIn(BlockTags.RAILS))
-            return CrossType.NONE;
-        // Check block state allow spawning (excludes bedrock and barriers automatically)
-        if (!blockBelowState.allowsSpawning(world, down, testingEntityType))
-            return CrossType.NONE;
-        int blockLightLevel = block.getLightLevel(pos);
-        int skyLightLevel = sky.getLightLevel(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, BlockView world, ChunkLightingView view, EntityContext entityContext) {
-        BlockState blockBelowState = world.getBlockState(down);
-        BlockState blockUpperState = world.getBlockState(pos);
-        VoxelShape collisionShape = blockBelowState.getCollisionShape(world, down, entityContext);
-        VoxelShape upperCollisionShape = blockUpperState.getCollisionShape(world, pos, entityContext);
-        if (!underwater && !blockUpperState.getFluidState().isEmpty())
-            return -1;
-        if (!blockBelowState.getFluidState().isEmpty())
-            return -1;
-        if (blockBelowState.isAir())
-            return -1;
-        if (Block.isFaceFullSquare(upperCollisionShape, Direction.DOWN))
-            return -1;
-        return view.getLightLevel(pos);
-    }
-    
-    public static void renderCross(Camera camera, World world, BlockPos pos, int color, EntityContext entityContext) {
-        double d0 = camera.getPos().x;
-        double d1 = camera.getPos().y - .005D;
-        VoxelShape upperOutlineShape = world.getBlockState(pos).getOutlineShape(world, pos, entityContext);
-        if (!upperOutlineShape.isEmpty())
-            d1 -= upperOutlineShape.getMaximum(Direction.Axis.Y);
-        double d2 = camera.getPos().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(MinecraftClient client, Camera camera, World world, BlockPos pos, BlockPos down, int level, EntityContext entityContext) {
-        String text = String.valueOf(level);
-        TextRenderer textRenderer_1 = client.textRenderer;
-        double double_4 = camera.getPos().x;
-        double double_5 = camera.getPos().y;
-        VoxelShape upperOutlineShape = world.getBlockState(down).getOutlineShape(world, down, entityContext);
-        if (!upperOutlineShape.isEmpty())
-            double_5 += 1 - upperOutlineShape.getMaximum(Direction.Axis.Y);
-        double double_6 = camera.getPos().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.getStringWidth(text)) / 2.0F + 0.4f;
-        RenderSystem.enableAlphaTest();
-        VertexConsumerProvider.Immediate immediate = VertexConsumerProvider.immediate(Tessellator.getInstance().getBuffer());
-        textRenderer_1.draw(text, float_3, -3.5f, level > higherCrossLevel ? 0xff042404 : (lowerCrossLevel >= 0 && level > lowerCrossLevel ? 0xff0066ff : 0xff731111), false, Rotation3.identity().getMatrix(), immediate, false, 0, 15728880);
-        immediate.draw();
-        RenderSystem.popMatrix();
+public class LightOverlay implements ClientModInitializer, AbstractPlatform {
+    @Override
+    public void onInitializeClient() {
+        LightOverlayCore.register(this);
     }
     
-    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();
+    @Override
+    public Path getConfigDir() {
+        return FabricLoader.getInstance().getConfigDir();
     }
     
-    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();
+    @Override
+    public void registerClientTick(Runnable runnable) {
+        ClientTickEvents.END_CLIENT_TICK.register(minecraft -> runnable.run());
     }
     
-    private static KeyBinding createKeyBinding(Identifier id, InputUtil.Type type, int code, String category) {
-        return KeyBindingHelper.registerKeyBinding(new KeyBinding("key." + id.getNamespace() + "." + id.getPath(), type, code, category));
+    @Override
+    public void registerDebugRenderer(Runnable runnable) {
+        ClothClientHooks.DEBUG_RENDER_PRE.register(runnable);
     }
     
     @Override
-    public void onInitializeClient() {
-        // Load Config
-        loadConfig(configFile);
-        
-        // Setup
-        testingEntityType = EntityType.Builder.create(EntityCategory.MONSTER).setDimensions(0f, 0f).disableSaving().build(null);
-        ClientTickEvents.END_CLIENT_TICK.register(minecraftClient -> {
-            while (ENABLE_OVERLAY.wasPressed())
-                enabled = !enabled;
-        });
-        ClothClientHooks.DEBUG_RENDER_PRE.register(() -> {
-            if (LightOverlay.enabled) {
-                PlayerEntity playerEntity = CLIENT.player;
-                int playerPosX = ((int) playerEntity.getX()) >> 4;
-                int playerPosZ = ((int) playerEntity.getZ()) >> 4;
-                EntityContext entityContext = EntityContext.of(playerEntity);
-                World world = CLIENT.world;
-                BlockPos playerPos = new BlockPos(playerEntity.getX(), playerEntity.getY(), playerEntity.getZ());
-                Camera camera = CLIENT.gameRenderer.getCamera();
-                if (showNumber) {
-                    RenderSystem.enableTexture();
-                    RenderSystem.depthMask(true);
-                    BlockPos.Mutable mutable = new BlockPos.Mutable();
-                    BlockPos.Mutable downMutable = new BlockPos.Mutable();
-                    for (Map.Entry<ChunkPos, Long2ReferenceMap<Object>> entry : CHUNK_MAP.entrySet()) {
-                        if (caching && (MathHelper.abs(entry.getKey().x - playerPosX) > getChunkRange() || MathHelper.abs(entry.getKey().z - playerPosZ) > getChunkRange())) {
-                            continue;
-                        }
-                        for (Long2ReferenceMap.Entry<Object> objectEntry : entry.getValue().long2ReferenceEntrySet()) {
-                            if (objectEntry.getValue() instanceof Integer) {
-                                mutable.set(BlockPos.unpackLongX(objectEntry.getLongKey()), BlockPos.unpackLongY(objectEntry.getLongKey()), BlockPos.unpackLongZ(objectEntry.getLongKey()));
-                                if (mutable.isWithinDistance(playerPos, reach)) {
-                                    if (frustum == null || FrustumHelper.isVisible(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());
-                                        LightOverlay.renderLevel(CLIENT, camera, world, mutable, downMutable, (Integer) objectEntry.getValue(), entityContext);
-                                    }
-                                }
-                            }
-                        }
-                    }
-                    RenderSystem.enableDepthTest();
-                } else {
-                    RenderSystem.enableDepthTest();
-                    RenderSystem.disableTexture();
-                    RenderSystem.enableBlend();
-                    RenderSystem.blendFunc(GlStateManager.SrcFactor.SRC_ALPHA, GlStateManager.DstFactor.ONE_MINUS_SRC_ALPHA);
-                    if (smoothLines) GL11.glEnable(GL11.GL_LINE_SMOOTH);
-                    GL11.glLineWidth(lineWidth);
-                    GL11.glBegin(GL11.GL_LINES);
-                    BlockPos.Mutable mutable = new BlockPos.Mutable();
-                    for (Map.Entry<ChunkPos, Long2ReferenceMap<Object>> entry : CHUNK_MAP.entrySet()) {
-                        if (caching && (MathHelper.abs(entry.getKey().x - playerPosX) > getChunkRange() || MathHelper.abs(entry.getKey().z - playerPosZ) > getChunkRange())) {
-                            continue;
-                        }
-                        for (Long2ReferenceMap.Entry<Object> objectEntry : entry.getValue().long2ReferenceEntrySet()) {
-                            if (objectEntry.getValue() instanceof CrossType) {
-                                mutable.set(BlockPos.unpackLongX(objectEntry.getLongKey()), BlockPos.unpackLongY(objectEntry.getLongKey()), BlockPos.unpackLongZ(objectEntry.getLongKey()));
-                                if (mutable.isWithinDistance(playerPos, reach)) {
-                                    if (frustum == null || FrustumHelper.isVisible(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;
-                                        LightOverlay.renderCross(camera, world, mutable, color, entityContext);
-                                    }
-                                }
-                            }
-                        }
-                    }
-                    GL11.glEnd();
-                    RenderSystem.disableBlend();
-                    RenderSystem.enableTexture();
-                    if (smoothLines) GL11.glDisable(GL11.GL_LINE_SMOOTH);
-                }
-            }
-        });
+    public KeyMapping registerKeyBinding(KeyMapping keyMapping) {
+        return KeyBindingHelper.registerKeyBinding(keyMapping);
     }
     
-    private enum CrossType {
-        YELLOW,
-        RED,
-        SECONDARY,
-        NONE
+    @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);
     }
 }
index 4fed3aa0fdc52d6f7a8e339356ec5abde25a49d2..bdb88d7daf345c0d10528b63d6fbe1cad4b23fc7 100644 (file)
@@ -1,31 +1,31 @@
 package me.shedaniel.lightoverlay.fabric.mixin;
 
-import me.shedaniel.lightoverlay.fabric.LightOverlay;
-import net.minecraft.network.ClientConnection;
-import net.minecraft.network.Packet;
-import net.minecraft.network.listener.PacketListener;
-import net.minecraft.network.packet.s2c.play.BlockUpdateS2CPacket;
-import net.minecraft.network.packet.s2c.play.ChunkDataS2CPacket;
-import net.minecraft.network.packet.s2c.play.ChunkDeltaUpdateS2CPacket;
-import net.minecraft.network.packet.s2c.play.LightUpdateS2CPacket;
-import net.minecraft.util.math.ChunkPos;
+import me.shedaniel.lightoverlay.common.LightOverlayCore;
+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(ClientConnection.class)
+@Mixin(Connection.class)
 public class MixinClientConnection {
-    @Inject(method = "handlePacket", at = @At("HEAD"))
+    @Inject(method = "genericsFtw", at = @At("HEAD"))
     private static void handlePacket(Packet packet, PacketListener listener, CallbackInfo ci) {
-        if (packet instanceof BlockUpdateS2CPacket) {
-            LightOverlay.queueChunkAndNear(new ChunkPos(((BlockUpdateS2CPacket) packet).getPos()));
-        } else if (packet instanceof ChunkDataS2CPacket) {
-            LightOverlay.queueChunkAndNear(new ChunkPos(((ChunkDataS2CPacket) packet).getX(), ((ChunkDataS2CPacket) packet).getZ()));
-        } else if (packet instanceof ChunkDeltaUpdateS2CPacket) {
-            LightOverlay.queueChunkAndNear(new ChunkPos(((ChunkDeltaUpdateS2CPacket) packet).sectionPos.getSectionX(), ((ChunkDeltaUpdateS2CPacket) packet).sectionPos.getSectionZ()));
-        } else if (packet instanceof LightUpdateS2CPacket) {
-            LightOverlay.queueChunk(new ChunkPos(((LightUpdateS2CPacket) packet).getChunkX(), ((LightUpdateS2CPacket) packet).getChunkZ()));
+        if (packet instanceof ClientboundBlockUpdatePacket) {
+            LightOverlayCore.queueChunkAndNear(new ChunkPos(((ClientboundBlockUpdatePacket) packet).getPos()));
+        } else if (packet instanceof ClientboundSetChunkCacheCenterPacket) {
+            LightOverlayCore.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()));
+        } else if (packet instanceof ClientboundLightUpdatePacket) {
+            LightOverlayCore.queueChunk(new ChunkPos(((ClientboundLightUpdatePacket) packet).getX(), ((ClientboundLightUpdatePacket) packet).getZ()));
         }
     }
 }
index 4c0b2719aa7afc3f5d9e9572c2d05e87b2cee72a..8183969fc185c02e845cdf7a5f2e9f6ec6ee90c0 100644 (file)
@@ -1,18 +1,18 @@
 package me.shedaniel.lightoverlay.fabric.mixin;
 
-import me.shedaniel.lightoverlay.fabric.LightOverlay;
-import net.minecraft.client.render.Camera;
-import net.minecraft.client.render.Frustum;
-import net.minecraft.client.render.WorldRenderer;
+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(WorldRenderer.class)
+@Mixin(LevelRenderer.class)
 public class MixinWorldRenderer {
-    @Inject(method = "setupTerrain", at = @At("HEAD"))
-    private void setupTerrain(Camera camera, Frustum frustum, boolean hasForcedFrustum, int frame, boolean spectator, CallbackInfo ci) {
-        LightOverlay.frustum = frustum;
+    @Inject(method = "setupRender", at = @At("HEAD"))
+    private void setupTerrain(Camera camera, Frustum frustum, boolean bl, int i, boolean bl2, CallbackInfo ci) {
+        LightOverlayCore.frustum = frustum;
     }
 }
diff --git a/fabric/src/main/resources/assets/lightoverlay/lang/en_us.json b/fabric/src/main/resources/assets/lightoverlay/lang/en_us.json
deleted file mode 100755 (executable)
index 5346550..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-  "key.lightoverlay.category": "Light Overlay",
-  "key.lightoverlay.enable_overlay": "Toggle Light Overlay",
-  "description.lightoverlay.caching": "Caching is recommended if the reach is above 16 or if you are running on a potato.",
-  "config.lightoverlay.general": "General",
-  "config.lightoverlay.reach": "Reach:",
-  "config.lightoverlay.caching": "Caching:",
-  "config.lightoverlay.crossLevel": "Light Level:",
-  "config.lightoverlay.secondaryLevel": "Secondary Light Level:",
-  "config.lightoverlay.showNumber": "Show Number Instead:",
-  "config.lightoverlay.smoothLines": "Smooth Lines:",
-  "config.lightoverlay.underwater": "Display Underwater:",
-  "config.lightoverlay.lineWidth": "Line Width:",
-  "config.lightoverlay.yellowColor": "Yellow Color:",
-  "config.lightoverlay.secondaryColor": "Secondary Color:",
-  "config.lightoverlay.redColor": "Red Color:",
-  "config.lightoverlay.invalidColor": "Invalid Color"
-}
\ No newline at end of file
diff --git a/fabric/src/main/resources/icon.png b/fabric/src/main/resources/icon.png
deleted file mode 100644 (file)
index 8bfd85a..0000000
Binary files a/fabric/src/main/resources/icon.png and /dev/null differ
index 5339db9f2abbdece5807f534f377a8ee3a0c850d..ee2fe740e06eaabb7a2c072bc9cfb46310ca726c 100644 (file)
@@ -1,6 +1,6 @@
 accessWidener  v1  named
-accessible field net/minecraft/network/packet/s2c/play/ChunkDeltaUpdateS2CPacket sectionPos Lnet/minecraft/util/math/ChunkSectionPos;
-accessible field net/minecraft/client/render/Frustum x D
-accessible field net/minecraft/client/render/Frustum y D
-accessible field net/minecraft/client/render/Frustum z D
-accessible field net/minecraft/client/render/Frustum homogeneousCoordinates [Lnet/minecraft/client/util/math/Vector4f;
\ No newline at end of file
+accessible field net/minecraft/network/protocol/game/ClientboundSectionBlocksUpdatePacket sectionPos Lnet/minecraft/core/SectionPos;
+accessible field net/minecraft/client/renderer/culling/Frustum camX D
+accessible field net/minecraft/client/renderer/culling/Frustum camY D
+accessible field net/minecraft/client/renderer/culling/Frustum camZ D
+accessible field net/minecraft/client/renderer/culling/Frustum frustumData [Lcom/mojang/math/Vector4f;
\ No newline at end of file
index 655e58715ee6fad47fbe041e447893571876cdaa..7c65caf8218bfab1d4ac02f0e04e558c47b100c3 100644 (file)
@@ -9,11 +9,15 @@ buildscript {
     }
 }
 
+plugins {
+    id "com.github.johnrengelman.shadow" version "5.0.0"
+    id "eclipse"
+}
+
 apply plugin: "net.minecraftforge.gradle"
-apply plugin: "eclipse"
 
 minecraft {
-    mappings(channel: "snapshot", version: rootProject.mcp_snapshot)
+    mappings(channel: "official", version: rootProject.architect.minecraft)
     accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg')
     runs {
         client {
@@ -36,11 +40,35 @@ minecraft {
 }
 
 repositories {
+    jcenter()
     maven { url "https://files.minecraftforge.net/maven" }
     maven { url "https://dl.bintray.com/shedaniel/cloth-config-2" }
 }
 
+configurations {
+    shadow
+}
+
 dependencies {
-    minecraft("net.minecraftforge:forge:${rootProject.forge_minecraft_version}-${project.forge_version}")
+    minecraft("net.minecraftforge:forge:${rootProject.architect.minecraft}-${project.forge_version}")
     implementation(fg.deobf("me.shedaniel.cloth:cloth-config-forge:${rootProject.cloth_config_forge}"))
+
+    compile(project(path: ":common", configuration: "mcp")) {
+        transitive = false
+    }
+    shadow(project(path: ":common", configuration: "mcp")) {
+        transitive = false
+    }
+}
+
+shadowJar {
+    relocate "me.shedaniel.lightoverlay.common", "me.shedaniel.lightoverlay.common.forge"
+    exclude "fabric.mod.json"
+
+    configurations = [project.configurations.shadow]
+    classifier null
+}
+
+reobf {
+    shadowJar {}
 }
\ No newline at end of file
index 918b4b295e56ee6b55f50571c91c08ab14dbaa4d..b02448d75fe61cd6ab63ce93ffa91e3f6103ebf1 100644 (file)
@@ -5,17 +5,17 @@ import net.minecraft.util.math.vector.Vector4f;
 
 public class FrustumHelper {
     public static boolean isVisible(ClippingHelper frustum, double minX, double minY, double minZ, double maxX, double maxY, double maxZ) {
-        float x1 = (float) (minX - frustum.cameraX);
-        float y1 = (float) (minY - frustum.cameraY);
-        float z1 = (float) (minZ - frustum.cameraZ);
-        float x2 = (float) (maxX - frustum.cameraX);
-        float y2 = (float) (maxY - frustum.cameraY);
-        float z2 = (float) (maxZ - frustum.cameraZ);
+        float x1 = (float) (minX - frustum.camX);
+        float y1 = (float) (minY - frustum.camY);
+        float z1 = (float) (minZ - frustum.camZ);
+        float x2 = (float) (maxX - frustum.camX);
+        float y2 = (float) (maxY - frustum.camY);
+        float z2 = (float) (maxZ - frustum.camZ);
         return isAnyCornerVisible(frustum, x1, y1, z1, x2, y2, z2);
     }
     
     private static boolean isAnyCornerVisible(ClippingHelper frustum, float x1, float y1, float z1, float x2, float y2, float z2) {
-        Vector4f[] homogeneousCoordinates = frustum.frustum;
+        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) {
                 return false;
@@ -26,6 +26,6 @@ public class FrustumHelper {
     }
     
     private static float dotProduct(Vector4f self, float x, float y, float z, float w) {
-        return self.getX() * x + self.getY() * y + self.getZ() * z + self.getW() * w;
+        return self.x() * x + self.y() * y + self.z() * z + self.w() * w;
     }
 }
index b9f374092d1685181b4d3e993907444d2deb8812..30ab28aea0ffa5aaefd685638c7984eda2ae131a 100644 (file)
 package me.shedaniel.lightoverlay.forge;
 
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.mojang.blaze3d.platform.GlStateManager;
-import com.mojang.blaze3d.systems.RenderSystem;
-import it.unimi.dsi.fastutil.longs.Long2ReferenceMap;
-import it.unimi.dsi.fastutil.longs.Long2ReferenceOpenHashMap;
-import net.minecraft.block.Block;
-import net.minecraft.block.BlockState;
-import net.minecraft.client.Minecraft;
-import net.minecraft.client.entity.player.ClientPlayerEntity;
-import net.minecraft.client.gui.FontRenderer;
-import net.minecraft.client.renderer.ActiveRenderInfo;
-import net.minecraft.client.renderer.IRenderTypeBuffer;
-import net.minecraft.client.renderer.Tessellator;
+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.client.util.InputMappings;
-import net.minecraft.client.world.ClientWorld;
-import net.minecraft.entity.Entity;
-import net.minecraft.entity.EntityClassification;
-import net.minecraft.entity.EntityType;
 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.tags.BlockTags;
-import net.minecraft.util.Direction;
-import net.minecraft.util.ResourceLocation;
-import net.minecraft.util.math.BlockPos;
 import net.minecraft.util.math.ChunkPos;
-import net.minecraft.util.math.MathHelper;
-import net.minecraft.util.math.shapes.ISelectionContext;
-import net.minecraft.util.math.shapes.VoxelShape;
-import net.minecraft.util.math.vector.TransformationMatrix;
-import net.minecraft.util.math.vector.Vector3d;
-import net.minecraft.world.IBlockReader;
-import net.minecraft.world.LightType;
-import net.minecraft.world.World;
-import net.minecraft.world.chunk.Chunk;
-import net.minecraft.world.chunk.ChunkStatus;
-import net.minecraft.world.lighting.IWorldLightListener;
 import net.minecraftforge.api.distmarker.Dist;
-import net.minecraftforge.client.event.InputEvent;
-import net.minecraftforge.client.settings.KeyConflictContext;
-import net.minecraftforge.client.settings.KeyModifier;
 import net.minecraftforge.common.MinecraftForge;
 import net.minecraftforge.event.TickEvent;
-import net.minecraftforge.eventbus.api.SubscribeEvent;
 import net.minecraftforge.fml.DistExecutor;
 import net.minecraftforge.fml.client.registry.ClientRegistry;
-import org.apache.logging.log4j.LogManager;
-import org.lwjgl.opengl.GL11;
+import net.minecraftforge.fml.loading.FMLPaths;
 
-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.ExecutorService;
-import java.util.concurrent.Executors;
+import java.nio.file.Path;
 
 public class LightOverlayClient {
-    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");
-    static int reach = 12;
-    static int crossLevel = 7;
-    static int secondaryLevel = -1;
-    static int lowerCrossLevel = -1;
-    static int higherCrossLevel = -1;
-    static boolean caching = false;
-    static boolean showNumber = false;
-    static boolean smoothLines = true;
-    static boolean underwater = false;
-    static float lineWidth = 1.0F;
-    static int yellowColor = 0xFFFF00, redColor = 0xFF0000, secondaryColor = 0x0000FF;
-    static File configFile = new File(new File(Minecraft.getInstance().gameDir, "config"), "lightoverlay.properties");
-    private static final KeyBinding ENABLE_OVERLAY;
-    private static boolean enabled = false;
-    private static EntityType<Entity> testingEntityType;
-    private static int threadNumber = 0;
-    public static ClippingHelper frustum;
-    private static final ExecutorService EXECUTOR = 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 long ticks = 0;
-    
-    static {
-        ENABLE_OVERLAY = registerKeybind(ENABLE_OVERLAY_KEYBIND, InputMappings.Type.KEYSYM, 296, KEYBIND_CATEGORY);
-    }
+    private static Runnable debugRenderer = () -> {};
     
     public static void register() {
-        // Load Config
-        loadConfig(configFile);
-        
-        // Setup
-        testingEntityType = EntityType.Builder.create(EntityClassification.MONSTER).size(0f, 0f).disableSerialization().build(null);
-        MinecraftForge.EVENT_BUS.register(LightOverlayClient.class);
-        
-        try {
-            //noinspection Convert2MethodRef
-            DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> LightOverlayCloth.register());
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
-    }
-    
-    public static CrossType getCrossType(BlockPos pos, BlockPos down, IBlockReader reader, IWorldLightListener block, IWorldLightListener sky, ISelectionContext selectionContext) {
-        BlockState blockBelowState = reader.getBlockState(down);
-        BlockState blockUpperState = reader.getBlockState(pos);
-        VoxelShape upperCollisionShape = blockUpperState.getCollisionShape(reader, pos, selectionContext);
-        if (!underwater && !blockUpperState.getFluidState().isEmpty())
-            return CrossType.NONE;
-        // Check if the outline is full
-        if (Block.doesSideFillSquare(upperCollisionShape, Direction.UP))
-            return CrossType.NONE;
-        // Check if there is power
-        if (blockUpperState.canProvidePower())
-            return CrossType.NONE;
-        // Check if the collision has a bump
-        if (upperCollisionShape.getEnd(Direction.Axis.Y) > 0)
-            return CrossType.NONE;
-        if (blockUpperState.getBlock().isIn(BlockTags.RAILS))
-            return CrossType.NONE;
-        // Check block state allow spawning (excludes bedrock and barriers automatically)
-        if (!blockBelowState.canEntitySpawn(reader, down, testingEntityType))
-            return CrossType.NONE;
-        int blockLightLevel = block.getLightFor(pos);
-        int skyLightLevel = sky.getLightFor(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, IBlockReader reader, IWorldLightListener light, ISelectionContext context) {
-        BlockState blockBelowState = reader.getBlockState(down);
-        BlockState blockUpperState = reader.getBlockState(pos);
-        VoxelShape collisionShape = blockBelowState.getCollisionShape(reader, down, context);
-        VoxelShape upperCollisionShape = blockUpperState.getCollisionShape(reader, pos, context);
-        if (!underwater && !blockUpperState.getFluidState().isEmpty())
-            return -1;
-        if (!blockBelowState.getFluidState().isEmpty())
-            return -1;
-        if (blockBelowState.isAir(reader, down))
-            return -1;
-        if (Block.doesSideFillSquare(upperCollisionShape, Direction.DOWN))
-            return -1;
-        return light.getLightFor(pos);
-    }
-    
-    public static void renderCross(ActiveRenderInfo info, World world, BlockPos pos, int color, ISelectionContext context) {
-        double d0 = info.getProjectedView().x;
-        double d1 = info.getProjectedView().y - .005D;
-        VoxelShape upperOutlineShape = world.getBlockState(pos).getShape(world, pos, context);
-        if (!upperOutlineShape.isEmpty())
-            d1 -= upperOutlineShape.getEnd(Direction.Axis.Y);
-        double d2 = info.getProjectedView().z;
-        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);
-    }
-    
-    public static void renderLevel(Minecraft minecraft, ActiveRenderInfo info, World world, BlockPos pos, BlockPos down, int level, ISelectionContext context) {
-        String string_1 = String.valueOf(level);
-        FontRenderer fontRenderer = minecraft.fontRenderer;
-        double double_4 = info.getProjectedView().x;
-        double double_5 = info.getProjectedView().y;
-        VoxelShape upperOutlineShape = world.getBlockState(down).getShape(world, down, context);
-        if (!upperOutlineShape.isEmpty())
-            double_5 += 1 - upperOutlineShape.getEnd(Direction.Axis.Y);
-        double double_6 = info.getProjectedView().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) (-fontRenderer.getStringWidth(string_1)) / 2.0F + 0.4f;
-        RenderSystem.enableAlphaTest();
-        IRenderTypeBuffer.Impl vertexConsumerProvider$Immediate_1 = IRenderTypeBuffer.getImpl(Tessellator.getInstance().getBuffer());
-        fontRenderer.renderString(string_1, float_3, -3.5f, level > higherCrossLevel ? 0xff042404 : (lowerCrossLevel >= 0 && level > lowerCrossLevel ? 0xff0066ff : 0xff731111), false, TransformationMatrix.identity().getMatrix(), vertexConsumerProvider$Immediate_1, false, 0, 15728880);
-        vertexConsumerProvider$Immediate_1.finish();
-        RenderSystem.popMatrix();
-    }
-    
-    @SubscribeEvent(receiveCanceled = true)
-    public static void handleInput(InputEvent.KeyInputEvent event) {
-        if (ENABLE_OVERLAY.isPressed())
-            enabled = !enabled;
-    }
-    
-    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(MathHelper.ceil(reach / 16f), 1);
-    }
-    
-    @SubscribeEvent
-    public static void tick(TickEvent.ClientTickEvent event) {
-        if (event.phase == TickEvent.Phase.END) {
-            try {
-                Minecraft minecraft = Minecraft.getInstance();
-                ticks++;
-                if (minecraft.player == null || !enabled) {
-                    POS.clear();
-                    CHUNK_MAP.clear();
-                } else {
-                    if (!caching) {
-                        POS.clear();
-                        CHUNK_MAP.clear();
-                        ClientPlayerEntity player = minecraft.player;
-                        ClientWorld world = minecraft.world;
-                        BlockPos playerPos = player.getPosition();
-                        ISelectionContext entityContext = ISelectionContext.forEntity(player);
-                        IWorldLightListener block = world.getLightManager().getLightEngine(LightType.BLOCK);
-                        IWorldLightListener sky = showNumber ? null : world.getLightManager().getLightEngine(LightType.SKY);
-                        BlockPos.Mutable downPos = new BlockPos.Mutable();
-                        Iterable<BlockPos> iterate = BlockPos.getAllInBoxMutable(playerPos.getX() - reach, playerPos.getY() - reach, playerPos.getZ() - reach,
-                                playerPos.getX() + reach, playerPos.getY() + reach, playerPos.getZ() + reach);
-                        Long2ReferenceMap<Object> map = new Long2ReferenceOpenHashMap<>();
-                        CHUNK_MAP.put(new ChunkPos(0, 0), map);
-                        for (BlockPos blockPos : iterate) {
-                            downPos.setPos(blockPos.getX(), blockPos.getY() - 1, blockPos.getZ());
-                            if (showNumber) {
-                                int level = getCrossLevel(blockPos, downPos, world, block, entityContext);
-                                if (level >= 0) {
-                                    map.put(blockPos.toLong(), Integer.valueOf(level));
-                                }
-                            } else {
-                                CrossType type = getCrossType(blockPos, downPos, world, block, sky, entityContext);
-                                if (type != CrossType.NONE) {
-                                    map.put(blockPos.toLong(), type);
-                                }
-                            }
-                        }
-                    } else {
-                        ClientPlayerEntity player = minecraft.player;
-                        ClientWorld world = minecraft.world;
-                        ISelectionContext selectionContext = ISelectionContext.forEntity(player);
-                        Vector3d[] playerPos = {null};
-                        int playerPosX = ((int) player.getPosX()) >> 4;
-                        int playerPosZ = ((int) player.getPosZ()) >> 4;
-                        if (ticks % 20 == 0) {
-                            for (int chunkX = playerPosX - getChunkRange(); chunkX <= playerPosX + getChunkRange(); chunkX++) {
-                                for (int chunkZ = playerPosZ - getChunkRange(); chunkZ <= playerPosZ + getChunkRange(); chunkZ++) {
-                                    ChunkPos chunkPos = new ChunkPos(chunkX, chunkZ);
-                                    if (!CHUNK_MAP.containsKey(chunkPos))
-                                        queueChunk(chunkPos);
-                                }
-                            }
-                        }
-                        POS.removeIf(pos -> MathHelper.abs(pos.x - playerPosX) > getChunkRange() || MathHelper.abs(pos.z - playerPosZ) > getChunkRange());
-                        for (int k = 0; k < 2; k++) {
-                            if (!POS.isEmpty()) {
-                                if (playerPos[0] == null) {
-                                    playerPos[0] = player.getPositionVec();
-                                }
-                                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.getChunkProvider().getChunk(pos.x, pos.z, ChunkStatus.FULL, false), world, pos, selectionContext);
-                                    } catch (Throwable throwable) {
-                                        LogManager.getLogger().throwing(throwable);
-                                    }
-                                });
-                            }
-                        }
-                        if (ticks % 50 == 0) {
-                            CHUNK_MAP.entrySet().removeIf(pos -> MathHelper.abs(pos.getKey().x - playerPosX) > getChunkRange() * 2 || MathHelper.abs(pos.getKey().z - playerPosZ) > getChunkRange() * 2);
-                        }
-                    }
-                }
-            } catch (Exception e) {
-                LogManager.getLogger().throwing(e);
+        LightOverlayCore.register(new AbstractPlatform() {
+            @Override
+            public Path getConfigDir() {
+                return FMLPaths.CONFIGDIR.get();
             }
-        }
-    }
-    
-    public static void updateFrustum(ClippingHelper helper) {
-        frustum = helper;
-    }
-    
-    private static void calculateChunk(Chunk chunk, World world, ChunkPos chunkPos, ISelectionContext selectionContext) {
-        if (world != null && chunk != null) {
-            Long2ReferenceMap<Object> map = new Long2ReferenceOpenHashMap<>();
-            IWorldLightListener block = chunk.getWorldLightManager().getLightEngine(LightType.BLOCK);
-            IWorldLightListener sky = showNumber ? null : chunk.getWorldLightManager().getLightEngine(LightType.SKY);
-            for (BlockPos pos : BlockPos.getAllInBoxMutable(chunkPos.getXStart(), 0, chunkPos.getZStart(), chunkPos.getXEnd(), 256, chunkPos.getZEnd())) {
-                BlockPos down = pos.down();
-                if (showNumber) {
-                    int level = LightOverlayClient.getCrossLevel(pos, down, chunk, block, selectionContext);
-                    if (level >= 0) {
-                        map.put(pos.toLong(), Integer.valueOf(level));
-                    }
-                } else {
-                    CrossType type = LightOverlayClient.getCrossType(pos, down, chunk, block, sky, selectionContext);
-                    if (type != CrossType.NONE) {
-                        map.put(pos.toLong(), type);
-                    }
-                }
+            
+            @Override
+            public void registerClientTick(Runnable runnable) {
+                MinecraftForge.EVENT_BUS.<TickEvent.ClientTickEvent>addListener(event -> runnable.run());
             }
-            CHUNK_MAP.put(chunkPos, map);
-        } else {
-            CHUNK_MAP.remove(chunkPos);
-        }
-    }
-    
-    public static void renderWorldLast() {
-        if (LightOverlayClient.enabled) {
-            RenderSystem.pushMatrix();
-            Minecraft client = Minecraft.getInstance();
-            ClientPlayerEntity playerEntity = client.player;
-            int playerPosX = ((int) playerEntity.getPosX()) >> 4;
-            int playerPosZ = ((int) playerEntity.getPosZ()) >> 4;
-            ISelectionContext selectionContext = ISelectionContext.forEntity(playerEntity);
-            World world = client.world;
-            BlockPos playerPos = playerEntity.getPosition();
-            ActiveRenderInfo info = client.gameRenderer.getActiveRenderInfo();
-            if (showNumber) {
-                RenderSystem.enableTexture();
-                RenderSystem.depthMask(true);
-                BlockPos.Mutable mutable = new BlockPos.Mutable();
-                BlockPos.Mutable downMutable = new BlockPos.Mutable();
-                for (Map.Entry<ChunkPos, Long2ReferenceMap<Object>> entry : CHUNK_MAP.entrySet()) {
-                    if (caching && (MathHelper.abs(entry.getKey().x - playerPosX) > getChunkRange() || MathHelper.abs(entry.getKey().z - playerPosZ) > getChunkRange())) {
-                        continue;
-                    }
-                    for (Long2ReferenceMap.Entry<Object> objectEntry : entry.getValue().long2ReferenceEntrySet()) {
-                        if (objectEntry.getValue() instanceof Integer) {
-                            mutable.setPos(BlockPos.unpackX(objectEntry.getLongKey()), BlockPos.unpackY(objectEntry.getLongKey()), BlockPos.unpackZ(objectEntry.getLongKey()));
-                            if (mutable.withinDistance(playerPos, reach)) {
-                                if (frustum == null || FrustumHelper.isVisible(frustum, mutable.getX(), mutable.getY(), mutable.getZ(), mutable.getX() + 1, mutable.getX() + 1, mutable.getX() + 1)) {
-                                    downMutable.setPos(mutable.getX(), mutable.getY() - 1, mutable.getZ());
-                                    LightOverlayClient.renderLevel(client, info, world, mutable, downMutable, (Integer) objectEntry.getValue(), selectionContext);
-                                }
-                            }
-                        }
-                    }
-                }
-                RenderSystem.color4f(1.0F, 1.0F, 1.0F, 1.0F);
-                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.Mutable mutable = new BlockPos.Mutable();
-                for (Map.Entry<ChunkPos, Long2ReferenceMap<Object>> entry : CHUNK_MAP.entrySet()) {
-                    if (caching && (MathHelper.abs(entry.getKey().x - playerPosX) > getChunkRange() || MathHelper.abs(entry.getKey().z - playerPosZ) > getChunkRange())) {
-                        continue;
-                    }
-                    for (Long2ReferenceMap.Entry<Object> objectEntry : entry.getValue().long2ReferenceEntrySet()) {
-                        if (objectEntry.getValue() instanceof CrossType) {
-                            mutable.setPos(BlockPos.unpackX(objectEntry.getLongKey()), BlockPos.unpackY(objectEntry.getLongKey()), BlockPos.unpackZ(objectEntry.getLongKey()));
-                            if (mutable.withinDistance(playerPos, reach)) {
-                                if (frustum == null || FrustumHelper.isVisible(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(info, world, mutable, color, selectionContext);
-                                }
-                            }
-                        }
-                    }
-                }
-                GL11.glEnd();
-                RenderSystem.disableBlend();
-                RenderSystem.enableTexture();
-                if (smoothLines) GL11.glDisable(GL11.GL_LINE_SMOOTH);
+            
+            @Override
+            public void registerDebugRenderer(Runnable runnable) {
+                debugRenderer = runnable;
             }
-            RenderSystem.popMatrix();
-        }
-    }
-    
-    private static KeyBinding registerKeybind(ResourceLocation resourceLocation, InputMappings.Type type, int keyCode, String category) {
-        KeyBinding keyBinding = new KeyBinding("key." + resourceLocation.getNamespace() + "." + resourceLocation.getPath(), KeyConflictContext.IN_GAME, KeyModifier.NONE, type, keyCode, category);
-        ClientRegistry.registerKeyBinding(keyBinding);
-        return keyBinding;
-    }
-    
-    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;
+            
+            @Override
+            public KeyBinding registerKeyBinding(KeyBinding keyBinding) {
+                ClientRegistry.registerKeyBinding(keyBinding);
+                return keyBinding;
             }
-            {
-                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;
+            
+            @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);
             }
-            {
-                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);
+        });
+        
+        try {
+            //noinspection Convert2MethodRef
+            DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> LightOverlayCloth.register());
         } 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();
     }
     
-    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();
+    public static void renderWorldLast() {
+        debugRenderer.run();
     }
     
     public static void processPacket(IPacket<?> packet) {
         if (packet instanceof SChangeBlockPacket) {
-            LightOverlayClient.queueChunkAndNear(new ChunkPos(((SChangeBlockPacket) packet).getPos()));
+            LightOverlayCore.queueChunkAndNear(new ChunkPos(((SChangeBlockPacket) packet).getPos()));
         } else if (packet instanceof SChunkDataPacket) {
-            LightOverlayClient.queueChunkAndNear(new ChunkPos(((SChunkDataPacket) packet).getChunkX(), ((SChunkDataPacket) packet).getChunkZ()));
+            LightOverlayCore.queueChunkAndNear(new ChunkPos(((SChunkDataPacket) packet).getX(), ((SChunkDataPacket) packet).getZ()));
         } else if (packet instanceof SMultiBlockChangePacket) {
-            LightOverlayClient.queueChunkAndNear(new ChunkPos(((SMultiBlockChangePacket) packet).field_244305_a.getSectionX(), ((SMultiBlockChangePacket) packet).field_244305_a.getSectionZ()));
+            LightOverlayCore.queueChunkAndNear(new ChunkPos(((SMultiBlockChangePacket) packet).sectionPos.getX(), ((SMultiBlockChangePacket) packet).sectionPos.getZ()));
         } else if (packet instanceof SUpdateLightPacket) {
-            LightOverlayClient.queueChunkAndNear(new ChunkPos(((SUpdateLightPacket) packet).getChunkX(), ((SUpdateLightPacket) packet).getChunkZ()));
+            LightOverlayCore.queueChunkAndNear(new ChunkPos(((SUpdateLightPacket) packet).getX(), ((SUpdateLightPacket) packet).getZ()));
         }
     }
-    
-    private enum CrossType {
-        YELLOW,
-        RED,
-        SECONDARY,
-        NONE
-    }
 }
index 2eaff45bb489baaf2baaaae53cea0261c495ba43..42b3118c5211d542662864be7411cef956022963 100644 (file)
@@ -4,6 +4,7 @@ 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;
@@ -20,31 +21,32 @@ public class LightOverlayCloth {
             
             ConfigEntryBuilder eb = builder.entryBuilder();
             ConfigCategory general = builder.getOrCreateCategory(new TranslationTextComponent("config.lightoverlay.general"));
-            general.addEntry(eb.startTextDescription(ITextComponent.func_244388_a("§7" + I18n.format("description.lightoverlay.caching"))).build());
-            general.addEntry(eb.startBooleanToggle(new TranslationTextComponent("config.lightoverlay.caching"), LightOverlayClient.caching).setDefaultValue(false).setSaveConsumer(bool -> LightOverlayClient.caching = bool).build());
-            general.addEntry(eb.startIntSlider(new TranslationTextComponent("config.lightoverlay.reach"), LightOverlayClient.reach, 1, 64).setDefaultValue(12).setTextGetter(integer -> ITextComponent.func_244388_a("Reach: " + integer + " Blocks")).setSaveConsumer(integer -> LightOverlayClient.reach = integer).build());
-            IntegerSliderEntry crossLevel = eb.startIntSlider(new TranslationTextComponent("config.lightoverlay.crossLevel"), LightOverlayClient.crossLevel, 0, 15).setDefaultValue(7).setTextGetter(integer -> ITextComponent.func_244388_a("Cross Level: " + integer)).setSaveConsumer(integer -> LightOverlayClient.crossLevel = integer).build();
+            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();
             general.addEntry(crossLevel);
-            general.addEntry(eb.startIntSlider(new TranslationTextComponent("config.lightoverlay.secondaryLevel"), LightOverlayClient.secondaryLevel, -1, 15)
+            general.addEntry(eb.startIntSlider(new TranslationTextComponent("config.lightoverlay.secondaryLevel"), LightOverlayCore.secondaryLevel, -1, 15)
                     .setErrorSupplier(integer -> {
-                        if (integer >= 0 && integer >= crossLevel.getValue()) return Optional.of(ITextComponent.func_244388_a("Secondary Level cannot be higher than Cross Level!"));
+                        if (integer >= 0 && integer >= crossLevel.getValue())
+                            return Optional.of(ITextComponent.nullToEmpty("Secondary Level cannot be higher than Cross Level!"));
                         return Optional.empty();
-                    }).setDefaultValue(-1).setTextGetter(integer -> ITextComponent.func_244388_a(integer < 0 ? "Off" : "Level: " + integer)).setSaveConsumer(integer -> LightOverlayClient.secondaryLevel = integer).build());
-            general.addEntry(eb.startBooleanToggle(new TranslationTextComponent("config.lightoverlay.showNumber"), LightOverlayClient.showNumber).setDefaultValue(false).setSaveConsumer(bool -> LightOverlayClient.showNumber = bool).build());
-            general.addEntry(eb.startBooleanToggle(new TranslationTextComponent("config.lightoverlay.smoothLines"), LightOverlayClient.smoothLines).setDefaultValue(true).setSaveConsumer(bool -> LightOverlayClient.smoothLines = bool).build());
-            general.addEntry(eb.startBooleanToggle(new TranslationTextComponent("config.lightoverlay.underwater"), LightOverlayClient.underwater).setDefaultValue(false).setSaveConsumer(bool -> LightOverlayClient.underwater = bool).build());
-            general.addEntry(eb.startIntSlider(new TranslationTextComponent("config.lightoverlay.lineWidth"), MathHelper.floor(LightOverlayClient.lineWidth * 100), 100, 700).setDefaultValue(100).setTextGetter(integer -> ITextComponent.func_244388_a("Light Width: " + LightOverlayClient.FORMAT.format(integer / 100d))).setSaveConsumer(integer -> LightOverlayClient.lineWidth = integer / 100f).build());
-            general.addEntry(eb.startColorField(new TranslationTextComponent("config.lightoverlay.yellowColor"), LightOverlayClient.yellowColor).setDefaultValue(0xFFFF00).setSaveConsumer(color -> LightOverlayClient.yellowColor = color).build());
-            general.addEntry(eb.startColorField(new TranslationTextComponent("config.lightoverlay.redColor"), LightOverlayClient.redColor).setDefaultValue(0xFF0000).setSaveConsumer(color -> LightOverlayClient.redColor = color).build());
-            general.addEntry(eb.startColorField(new TranslationTextComponent("config.lightoverlay.secondaryColor"), LightOverlayClient.secondaryColor).setDefaultValue(0x0000FF).setSaveConsumer(color -> LightOverlayClient.secondaryColor = color).build());
+                    }).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());
             
             return builder.setSavingRunnable(() -> {
                 try {
-                    LightOverlayClient.saveConfig(LightOverlayClient.configFile);
+                    LightOverlayCore.saveConfig(LightOverlayCore.configFile);
                 } catch (Exception e) {
                     e.printStackTrace();
                 }
-                LightOverlayClient.loadConfig(LightOverlayClient.configFile);
+                LightOverlayCore.loadConfig(LightOverlayCore.configFile);
             }).build();
         });
     }
diff --git a/forge/src/main/resources/assets/lightoverlay/lang/en_us.json b/forge/src/main/resources/assets/lightoverlay/lang/en_us.json
deleted file mode 100755 (executable)
index 5346550..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-  "key.lightoverlay.category": "Light Overlay",
-  "key.lightoverlay.enable_overlay": "Toggle Light Overlay",
-  "description.lightoverlay.caching": "Caching is recommended if the reach is above 16 or if you are running on a potato.",
-  "config.lightoverlay.general": "General",
-  "config.lightoverlay.reach": "Reach:",
-  "config.lightoverlay.caching": "Caching:",
-  "config.lightoverlay.crossLevel": "Light Level:",
-  "config.lightoverlay.secondaryLevel": "Secondary Light Level:",
-  "config.lightoverlay.showNumber": "Show Number Instead:",
-  "config.lightoverlay.smoothLines": "Smooth Lines:",
-  "config.lightoverlay.underwater": "Display Underwater:",
-  "config.lightoverlay.lineWidth": "Line Width:",
-  "config.lightoverlay.yellowColor": "Yellow Color:",
-  "config.lightoverlay.secondaryColor": "Secondary Color:",
-  "config.lightoverlay.redColor": "Red Color:",
-  "config.lightoverlay.invalidColor": "Invalid Color"
-}
\ No newline at end of file
diff --git a/forge/src/main/resources/icon.png b/forge/src/main/resources/icon.png
deleted file mode 100644 (file)
index 8bfd85a..0000000
Binary files a/forge/src/main/resources/icon.png and /dev/null differ
index 9f911f9a3e365626740d3ce314e500dfd565680e..9eacd85b0a88be0d06063844fb21ced5282d7b2c 100755 (executable)
@@ -2,10 +2,9 @@ org.gradle.jvmargs=-Xmx3G
 org.gradle.daemon=false
 
 mod_version=5.5.3
+minecraft_version=1.16.2
 
 # fabric
-fabric_minecraft_version=1.16.2
-yarn_build=1.16.2+build.1+legacy.20w09a+build.8
 fabric_loader_version=0.9.1+build.205
 fabric_api_version=0.17.2+build.396-1.16
 cloth_version=1.0.8
@@ -13,7 +12,5 @@ cloth_config_version=4.7.0-unstable
 modmenu_version=1.14.6+build.31
 
 # forge
-mcp_snapshot=20200723-1.16.1
-forge_minecraft_version=1.16.2
 forge_version=33.0.57
 cloth_config_forge=4.1.0
\ No newline at end of file
index baec76af7dc178ca51b90dc33cf034739cc9ca8d..9772f1796af177a274188524e136b13f1056e42a 100644 (file)
@@ -9,7 +9,11 @@ pluginManagement {
     }
 }
 
+includeBuild("architectPlugin")
+
 rootProject.name="light-overlay"
 
+include("common")
 include("fabric")
 include("forge")
+