From: shedaniel Date: Fri, 2 Oct 2020 10:06:41 +0000 (+0800) Subject: Multi-loader common module build X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=32288c278963de69cc628aaaa2f10fbde4f3c99c;p=LightOverlay.git Multi-loader common module build Signed-off-by: shedaniel --- diff --git a/.gitignore b/.gitignore index e787a1c..d74b152 100644 --- a/.gitignore +++ b/.gitignore @@ -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 index 0000000..7db7ebe --- /dev/null +++ b/architectPlugin/build.gradle @@ -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 index 0000000..9c68a5a --- /dev/null +++ b/architectPlugin/settings.gradle @@ -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 index 0000000..21638f8 --- /dev/null +++ b/architectPlugin/src/main/kotlin/me/shedaniel/plugin/architect/ArchitectPlugin.kt @@ -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 { + 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 index 0000000..260bdfa --- /dev/null +++ b/architectPlugin/src/main/kotlin/me/shedaniel/plugin/architect/ArchitectPluginExtension.kt @@ -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 index 0000000..e6a62b0 --- /dev/null +++ b/architectPlugin/src/main/kotlin/me/shedaniel/plugin/architect/RemapMCPTask.kt @@ -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): 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 { + val mcpMappings = readMCPMappings(getRootExtension().minecraft) + val mutableMap = mutableMapOf() + 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 { + 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().also { readMappings(it, file.inputStream()) } + } + + private fun readMappings(mutableMap: MutableMap, 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 diff --git a/build.gradle b/build.gradle index a87cca4..228b6bd 100644 --- a/build.gradle +++ b/build.gradle @@ -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 index 0000000..79e9531 --- /dev/null +++ b/common/build.gradle @@ -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 index 0000000..a237060 --- /dev/null +++ b/common/src/main/java/me/shedaniel/lightoverlay/common/AbstractPlatform.java @@ -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 index 0000000..2c40c2d --- /dev/null +++ b/common/src/main/java/me/shedaniel/lightoverlay/common/LightOverlayCore.java @@ -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> 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 POS = Lists.newCopyOnWriteArrayList(); + private static final Map> 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> entry : CHUNK_MAP.entrySet()) { + if (caching && (Mth.abs(entry.getKey().x - playerPosX) > getChunkRange() || Mth.abs(entry.getKey().z - playerPosZ) > getChunkRange())) { + continue; + } + for (Long2ReferenceMap.Entry 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> entry : CHUNK_MAP.entrySet()) { + if (caching && (Mth.abs(entry.getKey().x - playerPosX) > getChunkRange() || Mth.abs(entry.getKey().z - playerPosZ) > getChunkRange())) { + continue; + } + for (Long2ReferenceMap.Entry 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 iterate = BlockPos.betweenClosed(playerPos.getX() - reach, playerPos.getY() - reach, playerPos.getZ() - reach, + playerPos.getX() + reach, playerPos.getY() + reach, playerPos.getZ() + reach); + Long2ReferenceMap 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 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 index 0000000..5346550 --- /dev/null +++ b/common/src/main/resources/assets/lightoverlay/lang/en_us.json @@ -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 index 0000000..4fed948 --- /dev/null +++ b/common/src/main/resources/fabric.mod.json @@ -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 index 0000000..8bfd85a Binary files /dev/null and b/common/src/main/resources/icon.png differ diff --git a/fabric/build.gradle b/fabric/build.gradle index 6cd73c2..9b8058d 100755 --- a/fabric/build.gradle +++ b/fabric/build.gradle @@ -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 diff --git a/fabric/src/main/java/me/shedaniel/lightoverlay/fabric/FrustumHelper.java b/fabric/src/main/java/me/shedaniel/lightoverlay/fabric/FrustumHelper.java index 278ff84..ee36fdc 100644 --- a/fabric/src/main/java/me/shedaniel/lightoverlay/fabric/FrustumHelper.java +++ b/fabric/src/main/java/me/shedaniel/lightoverlay/fabric/FrustumHelper.java @@ -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; } } diff --git a/fabric/src/main/java/me/shedaniel/lightoverlay/fabric/LOModMenuEntry.java b/fabric/src/main/java/me/shedaniel/lightoverlay/fabric/LOModMenuEntry.java index c7f4c85..741e3a2 100644 --- a/fabric/src/main/java/me/shedaniel/lightoverlay/fabric/LOModMenuEntry.java +++ b/fabric/src/main/java/me/shedaniel/lightoverlay/fabric/LOModMenuEntry.java @@ -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(); } } diff --git a/fabric/src/main/java/me/shedaniel/lightoverlay/fabric/LightOverlay.java b/fabric/src/main/java/me/shedaniel/lightoverlay/fabric/LightOverlay.java index 23303ba..da0f190 100644 --- a/fabric/src/main/java/me/shedaniel/lightoverlay/fabric/LightOverlay.java +++ b/fabric/src/main/java/me/shedaniel/lightoverlay/fabric/LightOverlay.java @@ -1,499 +1,45 @@ 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 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 POS = Lists.newCopyOnWriteArrayList(); - private static final Map> 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 iterate = BlockPos.iterate(playerPos.getX() - reach, playerPos.getY() - reach, playerPos.getZ() - reach, - playerPos.getX() + reach, playerPos.getY() + reach, playerPos.getZ() + reach); - Long2ReferenceMap 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 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> entry : CHUNK_MAP.entrySet()) { - if (caching && (MathHelper.abs(entry.getKey().x - playerPosX) > getChunkRange() || MathHelper.abs(entry.getKey().z - playerPosZ) > getChunkRange())) { - continue; - } - for (Long2ReferenceMap.Entry 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> entry : CHUNK_MAP.entrySet()) { - if (caching && (MathHelper.abs(entry.getKey().x - playerPosX) > getChunkRange() || MathHelper.abs(entry.getKey().z - playerPosZ) > getChunkRange())) { - continue; - } - for (Long2ReferenceMap.Entry 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); } } diff --git a/fabric/src/main/java/me/shedaniel/lightoverlay/fabric/mixin/MixinClientConnection.java b/fabric/src/main/java/me/shedaniel/lightoverlay/fabric/mixin/MixinClientConnection.java index 4fed3aa..bdb88d7 100644 --- a/fabric/src/main/java/me/shedaniel/lightoverlay/fabric/mixin/MixinClientConnection.java +++ b/fabric/src/main/java/me/shedaniel/lightoverlay/fabric/mixin/MixinClientConnection.java @@ -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())); } } } diff --git a/fabric/src/main/java/me/shedaniel/lightoverlay/fabric/mixin/MixinWorldRenderer.java b/fabric/src/main/java/me/shedaniel/lightoverlay/fabric/mixin/MixinWorldRenderer.java index 4c0b271..8183969 100644 --- a/fabric/src/main/java/me/shedaniel/lightoverlay/fabric/mixin/MixinWorldRenderer.java +++ b/fabric/src/main/java/me/shedaniel/lightoverlay/fabric/mixin/MixinWorldRenderer.java @@ -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 index 5346550..0000000 --- a/fabric/src/main/resources/assets/lightoverlay/lang/en_us.json +++ /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 index 8bfd85a..0000000 Binary files a/fabric/src/main/resources/icon.png and /dev/null differ diff --git a/fabric/src/main/resources/lightoverlay.accesswidener b/fabric/src/main/resources/lightoverlay.accesswidener index 5339db9..ee2fe74 100644 --- a/fabric/src/main/resources/lightoverlay.accesswidener +++ b/fabric/src/main/resources/lightoverlay.accesswidener @@ -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 diff --git a/forge/build.gradle b/forge/build.gradle index 655e587..7c65caf 100644 --- a/forge/build.gradle +++ b/forge/build.gradle @@ -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 diff --git a/forge/src/main/java/me/shedaniel/lightoverlay/forge/FrustumHelper.java b/forge/src/main/java/me/shedaniel/lightoverlay/forge/FrustumHelper.java index 918b4b2..b02448d 100644 --- a/forge/src/main/java/me/shedaniel/lightoverlay/forge/FrustumHelper.java +++ b/forge/src/main/java/me/shedaniel/lightoverlay/forge/FrustumHelper.java @@ -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; } } diff --git a/forge/src/main/java/me/shedaniel/lightoverlay/forge/LightOverlayClient.java b/forge/src/main/java/me/shedaniel/lightoverlay/forge/LightOverlayClient.java index b9f3740..30ab28a 100644 --- a/forge/src/main/java/me/shedaniel/lightoverlay/forge/LightOverlayClient.java +++ b/forge/src/main/java/me/shedaniel/lightoverlay/forge/LightOverlayClient.java @@ -1,545 +1,77 @@ 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 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 POS = Lists.newCopyOnWriteArrayList(); - private static final Map> 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 iterate = BlockPos.getAllInBoxMutable(playerPos.getX() - reach, playerPos.getY() - reach, playerPos.getZ() - reach, - playerPos.getX() + reach, playerPos.getY() + reach, playerPos.getZ() + reach); - Long2ReferenceMap 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 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.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> entry : CHUNK_MAP.entrySet()) { - if (caching && (MathHelper.abs(entry.getKey().x - playerPosX) > getChunkRange() || MathHelper.abs(entry.getKey().z - playerPosZ) > getChunkRange())) { - continue; - } - for (Long2ReferenceMap.Entry 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> entry : CHUNK_MAP.entrySet()) { - if (caching && (MathHelper.abs(entry.getKey().x - playerPosX) > getChunkRange() || MathHelper.abs(entry.getKey().z - playerPosZ) > getChunkRange())) { - continue; - } - for (Long2ReferenceMap.Entry 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 - } } diff --git a/forge/src/main/java/me/shedaniel/lightoverlay/forge/LightOverlayCloth.java b/forge/src/main/java/me/shedaniel/lightoverlay/forge/LightOverlayCloth.java index 2eaff45..42b3118 100644 --- a/forge/src/main/java/me/shedaniel/lightoverlay/forge/LightOverlayCloth.java +++ b/forge/src/main/java/me/shedaniel/lightoverlay/forge/LightOverlayCloth.java @@ -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 index 5346550..0000000 --- a/forge/src/main/resources/assets/lightoverlay/lang/en_us.json +++ /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 index 8bfd85a..0000000 Binary files a/forge/src/main/resources/icon.png and /dev/null differ diff --git a/gradle.properties b/gradle.properties index 9f911f9..9eacd85 100755 --- a/gradle.properties +++ b/gradle.properties @@ -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 diff --git a/settings.gradle b/settings.gradle index baec76a..9772f17 100644 --- a/settings.gradle +++ b/settings.gradle @@ -9,7 +9,11 @@ pluginManagement { } } +includeBuild("architectPlugin") + rootProject.name="light-overlay" +include("common") include("fabric") include("forge") +