19 Commits

Author SHA1 Message Date
Motschen
0eb076fb40 Blur 2.3.0 - Update to MidnightLib v0.2.5
Add live config preview
Russian translations by @Felix14-v2
Brazilian translations by @Percario
2021-09-24 18:34:00 +02:00
Motschen
79814b4395 Merge pull request #24 from Felix14-v2/fabric-1.17
Added translations into russian (1.17)
2021-09-24 15:19:02 +00:00
Felix14-v2
3800b44eb3 Add files via upload 2021-09-20 22:10:34 +03:00
Motschen
b6e54fddfa Merge pull request #22 from maneschy-d/patch-1
add pt_br.json
2021-09-02 17:46:47 +02:00
Maneschy
9feb8a42bd add pt_br.json 2021-08-31 14:53:51 -03:00
Motschen
3b9fa30b11 Merge pull request #20 from backryun/fabric-1.17
update minecraft version and gradle
2021-08-20 10:34:48 +02:00
backryun
6667f7564f update minecraft version and gradle 2021-08-19 14:12:11 +09:00
Motschen
b77190c602 Blur 2.2.1 - 1.17
Update to MidnightConfig v1.0.4
2021-06-21 18:24:25 +02:00
Motschen
994a975c6c Merge pull request #15 from Pyrofab/fabric-1.17
Update to 1.17-pre3
2021-06-21 17:12:23 +02:00
Pyrofab
e1346d2516 Update to 1.17-pre3 2021-06-02 14:33:24 +02:00
Motschen
a520948fff Blur 2.1.0 - MidnightConfig
Switch to MidnightConfig:
- Much smaller file size
- Live preview
- Fixed #4

Chinise translation by @Enaium
Update to 21w08b
2021-03-05 17:52:48 +01:00
Motschen
40d63109f3 Merge pull request #8 from Enaium/fabric
Create zh_cn.json
2021-03-05 09:55:49 +01:00
Enaium
a6b70f1c6a Create zh_cn.json 2021-03-05 13:06:49 +08:00
Motschen
d42905746b Use official Satin build, Gradle cleanup, Remove unneeded dependencies 2020-12-20 15:05:55 +01:00
Motschen
432934b056 2.0.0 - AutoConfig and Fade Fix 2020-11-08 18:09:57 +01:00
Motschen
f8a4dd71fd Merge pull request #1 from Pyrofab/fabric
Update to 1.16.2
2020-08-17 15:31:34 +02:00
Pyrofab
d117c98de2 Bump version to 1.0.7 2020-08-17 09:56:47 +02:00
Pyrofab
fd84d68897 Update to 1.16.2 2020-08-17 09:49:13 +02:00
Motschen
7e8194a529 Port to 1.16-rc1 2020-06-21 12:33:45 +02:00
30 changed files with 709 additions and 359 deletions

147
build.gradle Normal file → Executable file
View File

@@ -1,116 +1,83 @@
plugins {
id 'java'
id 'fabric-loom' version '0.8-SNAPSHOT'
id 'maven-publish'
id 'idea'
id 'eclipse'
id 'com.matthewprenger.cursegradle' version '1.0.9'
id 'fabric-loom' version '0.2.5-SNAPSHOT'
}
boolean dev = System.getenv('RELEASE') == null || System.getenv('RELEASE').equals('false');
ext.buildnumber = System.getenv().BUILD_NUMBER ?: 'custom';
sourceCompatibility = JavaVersion.VERSION_16
targetCompatibility = JavaVersion.VERSION_16
group = 'com.tterrag.blur'
archivesBaseName = "Blur"
version = "${mod_version}-${minecraft_version}[fabric]"
sourceCompatibility = '1.8'
targetCompatibility = '1.8'
minecraft {
}
archivesBaseName = project.archives_base_name
version = project.mod_version
group = project.maven_group
repositories {
maven { url 'https://jitpack.io' }
maven {
name = 'Ladysnake Mods'
url = 'https://ladysnake.jfrog.io/artifactory/mods'
content {
includeGroup 'io.github.ladysnake'
includeGroupByRegex 'io\\.github\\.onyxstudios.*'
}
}
flatDir {
dirs 'local_maven'
}
}
dependencies {
minecraft "com.mojang:minecraft:${minecraft_version}"
mappings "net.fabricmc:yarn:${mappings_version}"
modCompile "net.fabricmc:fabric-loader:${fabric_loader_version}"
modCompile "net.fabricmc.fabric-api:fabric-api:${fabric_version}"
modCompile "com.github.Ladysnake:Satin:${satin_version}"
include "com.github.Ladysnake:Satin:${satin_version}"
mappings "net.fabricmc:yarn:${yarn_mappings}"
modImplementation "net.fabricmc:fabric-loader:${loader_version}"
modImplementation "net.fabricmc.fabric-api:fabric-api:${fabric_version}"
modImplementation "io.github.ladysnake:satin:${satin_version}"
include "io.github.ladysnake:satin:${satin_version}"
implementation 'com.google.code.findbugs:jsr305:3.0.2'
modImplementation "eu.midnightdust:midnightlib:${midnightlib_version}"
include "eu.midnightdust:midnightlib:${midnightlib_version}"
}
processResources {
inputs.property "version", mod_version
inputs.property "version", project.version
from(sourceSets.main.resources.srcDirs) {
include "fabric.mod.json"
expand "version": mod_version
}
from(sourceSets.main.resources.srcDirs) {
exclude "fabric.mod.json"
filesMatching("fabric.mod.json") {
expand "version": project.version
}
}
import org.apache.tools.ant.filters.ReplaceTokens
import groovy.json.JsonSlurper
// ensure that the encoding is set to UTF-8, no matter what the system default is
// this fixes some edge cases with special characters not displaying correctly
// see http://yodaconditions.net/blog/fix-for-java-file-encoding-problems-with-gradle.html
tasks.withType(JavaCompile) {
options.encoding = "UTF-8"
}
task createResourcePacks {
def inputFile = new File("resource_packs.json")
def json = new JsonSlurper().parseText(inputFile.text)
json.each {
def pack_id = it.key
def pack_name = it.value.name
def pack_desc = it.value.description
def pack_radius = it.value.radius
def taskName = "createPack" + pack_id.capitalize();
task "${taskName}" (type: Zip) {
from ('pack_template') {
filter(ReplaceTokens, tokens: [
mod_version: project.version.toString(),
pack_version: '3',
description: pack_desc.toString(),
radius: pack_radius.toString()
])
rename(/(.+)\.template/, '$1')
java {
withSourcesJar()
}
jar {
from "LICENSE"
}
// configure the maven publication
publishing {
publications {
mavenJava(MavenPublication) {
// add all the jars that should be included when publishing to maven
artifact(remapJar) {
builtBy remapJar
}
from ('pack_icons') {
include "${pack_id}.png"
rename '.+', 'icon.png'
artifact(sourcesJar) {
builtBy remapSourcesJar
}
baseName = "Blur " + pack_name
}
createResourcePacks.finalizedBy taskName
}
// select the repositories you want to publish to
repositories {
// uncomment to publish to the local maven
// mavenLocal()
}
}
// Not necessary atm
// tasks.build.dependsOn createResourcePacks
tasks.curseforge.enabled = !dev && project.hasProperty('curseforge_key')
curseforge {
if (project.hasProperty('curseforge_key')) {
apiKey = project.curseforge_key
}
project {
id = project.project_id
changelogType = 'html'
changelog = System.getenv('CHANGELOG')
if (changelog == null || 'none'.equals(changelog)) {
changelog = getChangelog() ?: ''
changelogType = 'text'
}
releaseType = project.release_type
addGameVersion '1.9.4'
addGameVersion '1.11.2'
addGameVersion '1.12'
addGameVersion '1.12.1'
mainArtifact(jar) {
displayName = "Blur ${mod_version}"
}
}
}

28
gradle.properties Normal file → Executable file
View File

@@ -1,13 +1,19 @@
minecraft_version=19w34a
# Done to increase the memory available to gradle.
org.gradle.jvmargs=-Xmx1G
mod_version=1.0.5
# Fabric Properties
# check these on https://fabricmc.net/use
minecraft_version=1.17.1
yarn_mappings=1.17.1+build.61
loader_version=0.11.7
# Mod Properties
mod_version = 2.3.0-1.17+fabric
maven_group = com.tterrag.blur
archives_base_name = Blur
fabric_loader_version=0.5.0+build.162
fabric_version=0.3.1+build.208
mappings_version=19w34a+build.10
# Satin library
satin_version = 1.15-SNAPSHOT
project_id=268324
release_type=release
# Dependencies
# currently not on the main fabric site, check on the maven: https://maven.fabricmc.net/net/fabricmc/fabric-api/fabric-api
fabric_version=0.40.1+1.17
satin_version = 1.6.4
midnightlib_version=0.2.5

Binary file not shown.

View File

@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.5.1-all.zip

149
gradlew vendored
View File

@@ -1,4 +1,20 @@
#!/usr/bin/env bash
#!/usr/bin/env sh
#
# Copyright 2015 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
##
@@ -6,47 +22,6 @@
##
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
echo "$*"
}
die ( ) {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
esac
# For Cygwin, ensure paths are in UNIX format before anything is touched.
if $cygwin ; then
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
fi
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
@@ -61,12 +36,53 @@ while [ -h "$PRG" ] ; do
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >&-
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >&-
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
@@ -90,7 +106,7 @@ location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
@@ -110,11 +126,13 @@ if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
@@ -138,27 +156,30 @@ if $cygwin ; then
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
i=`expr $i + 1`
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
0) set -- ;;
1) set -- "$args0" ;;
2) set -- "$args0" "$args1" ;;
3) set -- "$args0" "$args1" "$args2" ;;
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
APP_ARGS=`save "$@"`
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
exec "$JAVACMD" "$@"

53
gradlew.bat vendored
View File

@@ -1,3 +1,19 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@@ -8,20 +24,23 @@
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
@@ -35,7 +54,7 @@ goto fail
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
@@ -45,34 +64,14 @@ echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windowz variants
if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell

BIN
local_maven/midnightlib-0.2.5.jar Executable file

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

View File

@@ -1,67 +0,0 @@
{
"targets": [
"swap"
],
"passes": [
{
"name": "fade_in_blur",
"intarget": "minecraft:main",
"outtarget": "swap",
"uniforms": [
{
"name": "BlurDir",
"values": [ 1.0, 0.0 ]
},
{
"name": "Radius",
"values": [ @radius@.0 ]
}
]
},
{
"name": "fade_in_blur",
"intarget": "swap",
"outtarget": "minecraft:main",
"uniforms": [
{
"name": "BlurDir",
"values": [ 0.0, 1.0 ]
},
{
"name": "Radius",
"values": [ @radius@.0 ]
}
]
},
{
"name": "fade_in_blur",
"intarget": "minecraft:main",
"outtarget": "swap",
"uniforms": [
{
"name": "BlurDir",
"values": [ 1.0, 0.0 ]
},
{
"name": "Radius",
"values": [ @radius@.0 ]
}
]
},
{
"name": "fade_in_blur",
"intarget": "swap",
"outtarget": "minecraft:main",
"uniforms": [
{
"name": "BlurDir",
"values": [ 0.0, 1.0 ]
},
{
"name": "Radius",
"values": [ @radius@.0 ]
}
]
}
]
}

View File

@@ -1,7 +0,0 @@
{
"pack": {
"_comment": "This pack was made for Blur version @mod_version@",
"pack_format": @pack_version@,
"description": "@description@"
}
}

View File

@@ -1,22 +0,0 @@
{
"ultra_lite": {
"name": "Ultra Lite",
"radius": 2,
"description": "Least passes, weakest effect, greatest performance. It's like having a smudge on your glasses."
},
"lite": {
"name": "Lite",
"radius": 8,
"description": "Less passes, weaker effect, greater performance."
},
"strong": {
"name": "Strong",
"radius": 32,
"description" : "More passes, stronger effect, lesser performance."
},
"ultra_strong": {
"name": "Ultra Strong",
"radius": 64,
"description": "Too many passes, strongest effect, worst performance. It's like having Vaseline in your eyes."
}
}

View File

@@ -1,65 +1,33 @@
package com.tterrag.blur;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.tterrag.blur.config.BlurConfig;
import ladysnake.satin.api.event.ShaderEffectRenderCallback;
import ladysnake.satin.api.experimental.managed.Uniform1f;
import ladysnake.satin.api.managed.ManagedShaderEffect;
import ladysnake.satin.api.managed.ShaderEffectManager;
import ladysnake.satin.api.managed.uniform.Uniform1f;
import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.ChatScreen;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.util.Identifier;
import org.apache.commons.lang3.ArrayUtils;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.StandardOpenOption;
public class Blur implements ClientModInitializer {
public static final String MODID = "blur";
public static final String MOD_NAME = "Blur";
public static final String VERSION = "@VERSION@";
static class ConfigJson {
String[] blurExclusions = new String[]{ ChatScreen.class.getName() };
int fadeTimeMillis = 200;
int radius = 8;
String gradientStartColor = "75000000";
String gradientEndColor = "75000000";
}
private long start;
public ConfigJson configs = new ConfigJson();
public int colorFirst, colorSecond;
private final ManagedShaderEffect blur = ShaderEffectManager.getInstance().manage(new Identifier(MODID, "shaders/post/fade_in_blur.json"),
shader -> shader.setUniformValue("Radius", (float) getRadius()));
shader -> shader.setUniformValue("Radius", (float) BlurConfig.radius));
private final Uniform1f blurProgress = blur.findUniform1f("Progress");
public static final Blur INSTANCE = new Blur();
@Override
public void onInitializeClient() {
File configFile = new File(FabricLoader.getInstance().getConfigDirectory(), Blur.MODID + ".json");
try {
if (!configFile.exists()) {
configFile.getParentFile().mkdirs();
Files.write(configFile.toPath(), new GsonBuilder().setPrettyPrinting().create().toJson(configs).getBytes(), StandardOpenOption.CREATE_NEW);
} else {
configs = new Gson().fromJson(new FileReader(configFile), ConfigJson.class);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
colorFirst = Integer.parseUnsignedInt(configs.gradientStartColor, 16);
colorSecond = Integer.parseUnsignedInt(configs.gradientEndColor, 16);
BlurConfig.init("blur", BlurConfig.class);
ShaderEffectRenderCallback.EVENT.register((deltaTick) -> {
if (start > 0) {
blurProgress.set(getProgress());
@@ -68,23 +36,27 @@ public class Blur implements ClientModInitializer {
});
}
private boolean doFade = false;
public void onScreenChange(Screen newGui) {
if (MinecraftClient.getInstance().world != null) {
boolean excluded = newGui == null || ArrayUtils.contains(configs.blurExclusions, newGui.getClass().getName());
boolean excluded = newGui == null || ArrayUtils.contains(BlurConfig.blurExclusions, newGui.getClass().getName());
if (!excluded) {
start = System.currentTimeMillis();
blur.setUniformValue("Radius", (float) BlurConfig.radius);
colorFirst = Integer.parseUnsignedInt(String.valueOf(BlurConfig.gradientStartColor), 16);
colorSecond = Integer.parseUnsignedInt(String.valueOf(BlurConfig.gradientEndColor), 16);
if (doFade) {
start = System.currentTimeMillis();
doFade = false;
}
} else {
start = -1;
doFade = true;
}
}
}
public int getRadius() {
return configs.radius;
}
private float getProgress() {
return Math.min((System.currentTimeMillis() - start) / (float) configs.fadeTimeMillis, 1);
return Math.min((System.currentTimeMillis() - start) / (float) BlurConfig.fadeTimeMillis, 1);
}
public int getBackgroundColor(boolean second) {

View File

@@ -0,0 +1,17 @@
package com.tterrag.blur.config;
import eu.midnightdust.lib.config.MidnightConfig;
import net.minecraft.client.gui.screen.ChatScreen;
public class BlurConfig extends MidnightConfig {
@Entry
public static String[] blurExclusions = new String[]{ ChatScreen.class.getName() };
@Entry(min = 0, max = 5000, width = 4)
public static int fadeTimeMillis = 200;
@Entry(min = 0, max = 500, width = 3)
public static int radius = 8;
@Entry(min = 0, max = 99999999, width = 8)
public static int gradientStartColor = 75000000;
@Entry(min = 0, max = 99999999, width = 8)
public static int gradientEndColor = 75000000;
}

View File

@@ -0,0 +1,15 @@
package com.tterrag.blur.config;
import com.terraformersmc.modmenu.api.ConfigScreenFactory;
import com.terraformersmc.modmenu.api.ModMenuApi;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
@Environment(EnvType.CLIENT)
public class ModMenuIntegration implements ModMenuApi {
@Override
public ConfigScreenFactory<?> getModConfigScreenFactory() {
return parent -> BlurConfig.getScreen(parent,"blur");
}
}

View File

@@ -4,23 +4,21 @@ import org.objectweb.asm.Opcodes;
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.At.Shift;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import com.tterrag.blur.Blur;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.resource.ReloadableResourceManager;
@Mixin(MinecraftClient.class)
public class MixinMinecraftClient {
@Inject(method = "openScreen",
@Inject(method = "setScreen",
at = @At(value = "FIELD",
target = "Lnet/minecraft/client/MinecraftClient;currentScreen:Lnet/minecraft/client/gui/screen/Screen;",
opcode = Opcodes.PUTFIELD))
public void onScreenOpen(Screen newScreen, CallbackInfo info) {
private void onScreenOpen(Screen newScreen, CallbackInfo info) {
Blur.INSTANCE.onScreenChange(newScreen);
}
}

28
src/main/java/com/tterrag/blur/mixin/MixinScreen.java Normal file → Executable file
View File

@@ -1,27 +1,45 @@
package com.tterrag.blur.mixin;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.util.math.MatrixStack;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Constant;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.ModifyConstant;
import com.tterrag.blur.Blur;
import net.minecraft.client.gui.screen.Screen;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.Locale;
@Mixin(Screen.class)
public class MixinScreen {
public abstract class MixinScreen {
@Shadow @Nullable protected MinecraftClient client;
@Inject(at = @At("HEAD"), method = "render")
private void reloadShader(MatrixStack matrixStack, int i, int j, float f, CallbackInfo ci) {
if (this.getClass().toString().toLowerCase(Locale.ROOT).contains("midnight") && this.client != null) {
Blur.INSTANCE.onScreenChange(this.client.currentScreen);
}
}
@ModifyConstant(
method = "renderBackground(I)V",
method = "renderBackground(Lnet/minecraft/client/util/math/MatrixStack;I)V",
constant = @Constant(intValue = -1072689136))
public int getFirstBackgroundColor(int color) {
private int getFirstBackgroundColor(int color) {
return Blur.INSTANCE.getBackgroundColor(false);
}
@ModifyConstant(
method = "renderBackground(I)V",
method = "renderBackground(Lnet/minecraft/client/util/math/MatrixStack;I)V",
constant = @Constant(intValue = -804253680))
public int getSecondBackgroundColor(int color) {
private int getSecondBackgroundColor(int color) {
return Blur.INSTANCE.getBackgroundColor(true);
}
}

View File

@@ -0,0 +1,390 @@
package eu.midnightdust.lib.config;
import com.google.gson.ExclusionStrategy;
import com.google.gson.FieldAttributes;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gui.DrawableHelper;
import net.minecraft.client.gui.Element;
import net.minecraft.client.gui.Selectable;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.screen.ScreenTexts;
import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.client.gui.widget.ClickableWidget;
import net.minecraft.client.gui.widget.ElementListWidget;
import net.minecraft.client.gui.widget.TextFieldWidget;
import net.minecraft.client.resource.language.I18n;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.text.LiteralText;
import net.minecraft.text.Text;
import net.minecraft.text.TranslatableText;
import net.minecraft.util.Formatting;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.regex.Pattern;
// MidnightConfig v1.0.4
// Single class config library - feel free to copy!
// Changelog:
// - 1.0.4:
// - Number field length is now configurable
// - Fixed number fields being empty
// - 1.0.3:
// - Text field length is now configurable
// - Better separation of client and server
// - 1.0.2:
// - Update to 21w20a
// - 1.0.1:
// - Fixed buttons not working in fullscreen
// - 1.0.0:
// - The config screen no longer shows the entries of all instances of MidnightConfig
// - Compatible with servers!
// - Scrollable!
// - Comment support!
// - Fresh New Design
/** Based on https://github.com/Minenash/TinyConfig
* Credits to Minenash */
@SuppressWarnings("unchecked")
public class MidnightConfig {
public static boolean useTooltipForTitle = true; // Render title as tooltip or as simple text
private static final Pattern INTEGER_ONLY = Pattern.compile("(-?[0-9]*)");
private static final Pattern DECIMAL_ONLY = Pattern.compile("-?([\\d]+\\.?[\\d]*|[\\d]*\\.?[\\d]+|\\.)");
private static final List<EntryInfo> entries = new ArrayList<>();
protected static class EntryInfo {
Field field;
Object widget;
int width;
int max;
Map.Entry<TextFieldWidget,Text> error;
Object defaultValue;
Object value;
String tempValue;
boolean inLimits = true;
String id;
}
public static final Map<String,Class<?>> configClass = new HashMap<>();
private static Path path;
private static final Gson gson = new GsonBuilder().excludeFieldsWithModifiers(Modifier.TRANSIENT).excludeFieldsWithModifiers(Modifier.PRIVATE).addSerializationExclusionStrategy(new HiddenAnnotationExclusionStrategy()).setPrettyPrinting().create();
public static void init(String modid, Class<?> config) {
path = FabricLoader.getInstance().getConfigDir().resolve(modid + ".json");
configClass.put(modid, config);
for (Field field : config.getFields()) {
EntryInfo info = new EntryInfo();
if (field.isAnnotationPresent(Entry.class) || field.isAnnotationPresent(Comment.class))
if (FabricLoader.getInstance().getEnvironmentType() == EnvType.CLIENT) initClient(modid, field, info);
if (field.isAnnotationPresent(Entry.class))
try {
info.defaultValue = field.get(null);
} catch (IllegalAccessException ignored) {}
}
try { gson.fromJson(Files.newBufferedReader(path), config); }
catch (Exception e) { write(modid); }
for (EntryInfo info : entries) {
if (info.field.isAnnotationPresent(Entry.class))
try {
info.value = info.field.get(null);
info.tempValue = info.value.toString();
} catch (IllegalAccessException ignored) {
}
}
}
@Environment(EnvType.CLIENT)
private static void initClient(String modid, Field field, EntryInfo info) {
Class<?> type = field.getType();
Entry e = field.getAnnotation(Entry.class);
info.width = e != null ? e.width() : 0;
info.field = field;
info.id = modid;
if (e != null) {
if (type == int.class) textField(info, Integer::parseInt, INTEGER_ONLY, e.min(), e.max(), true);
else if (type == double.class) textField(info, Double::parseDouble, DECIMAL_ONLY, e.min(), e.max(), false);
else if (type == String.class) {
info.max = e.max() == Double.MAX_VALUE ? Integer.MAX_VALUE : (int) e.max();
textField(info, String::length, null, Math.min(e.min(), 0), Math.max(e.max(), 1), true);
} else if (type == boolean.class) {
Function<Object, Text> func = value -> new LiteralText((Boolean) value ? "True" : "False").formatted((Boolean) value ? Formatting.GREEN : Formatting.RED);
info.widget = new AbstractMap.SimpleEntry<ButtonWidget.PressAction, Function<Object, Text>>(button -> {
info.value = !(Boolean) info.value;
button.setMessage(func.apply(info.value));
}, func);
} else if (type.isEnum()) {
List<?> values = Arrays.asList(field.getType().getEnumConstants());
Function<Object, Text> func = value -> new TranslatableText(modid + ".midnightconfig." + "enum." + type.getSimpleName() + "." + info.value.toString());
info.widget = new AbstractMap.SimpleEntry<ButtonWidget.PressAction, Function<Object, Text>>(button -> {
int index = values.indexOf(info.value) + 1;
info.value = values.get(index >= values.size() ? 0 : index);
button.setMessage(func.apply(info.value));
}, func);
}
}
entries.add(info);
}
private static void textField(EntryInfo info, Function<String,Number> f, Pattern pattern, double min, double max, boolean cast) {
boolean isNumber = pattern != null;
info.widget = (BiFunction<TextFieldWidget, ButtonWidget, Predicate<String>>) (t, b) -> s -> {
s = s.trim();
if (!(s.isEmpty() || !isNumber || pattern.matcher(s).matches())) return false;
Number value = 0;
boolean inLimits = false;
System.out.println(((isNumber ^ s.isEmpty())));
System.out.println(!s.equals("-") && !s.equals("."));
info.error = null;
if (!(isNumber && s.isEmpty()) && !s.equals("-") && !s.equals(".")) {
value = f.apply(s);
inLimits = value.doubleValue() >= min && value.doubleValue() <= max;
info.error = inLimits? null : new AbstractMap.SimpleEntry<>(t, new LiteralText(value.doubleValue() < min ?
"§cMinimum " + (isNumber? "value" : "length") + (cast? " is " + (int)min : " is " + min) :
"§cMaximum " + (isNumber? "value" : "length") + (cast? " is " + (int)max : " is " + max)));
}
info.tempValue = s;
t.setEditableColor(inLimits? 0xFFFFFFFF : 0xFFFF7777);
info.inLimits = inLimits;
b.active = entries.stream().allMatch(e -> e.inLimits);
if (inLimits)
info.value = isNumber? value : s;
return true;
};
}
public static void write(String modid) {
path = FabricLoader.getInstance().getConfigDir().resolve(modid + ".json");
try {
if (!Files.exists(path)) Files.createFile(path);
Files.write(path, gson.toJson(configClass.get(modid).getDeclaredConstructor().newInstance()).getBytes());
} catch (Exception e) {
e.printStackTrace();
}
}
@Environment(EnvType.CLIENT)
public static Screen getScreen(Screen parent, String modid) {
return new MidnightConfigScreen(parent, modid);
}
@Environment(EnvType.CLIENT)
private static class MidnightConfigScreen extends Screen {
protected MidnightConfigScreen(Screen parent, String modid) {
super(new TranslatableText(modid + ".midnightconfig." + "title"));
this.parent = parent;
this.modid = modid;
this.translationPrefix = modid + ".midnightconfig.";
}
private final String translationPrefix;
private final Screen parent;
private final String modid;
private MidnightConfigListWidget list;
// Real Time config update //
@Override
public void tick() {
for (EntryInfo info : entries)
try { info.field.set(null, info.value); }
catch (IllegalAccessException ignored) {}
}
@Override
protected void init() {
super.init();
this.addDrawableChild(new ButtonWidget(this.width / 2 - 154, this.height - 28, 150, 20, ScreenTexts.CANCEL, button -> {
try { gson.fromJson(Files.newBufferedReader(path), configClass.get(modid)); }
catch (Exception e) { write(modid); }
for (EntryInfo info : entries) {
if (info.field.isAnnotationPresent(Entry.class)) {
try {
info.value = info.field.get(null);
info.tempValue = info.value.toString();
} catch (IllegalAccessException ignored) {
}
}
}
Objects.requireNonNull(client).openScreen(parent);
}));
ButtonWidget done = this.addDrawableChild(new ButtonWidget(this.width / 2 + 4, this.height - 28, 150, 20, ScreenTexts.DONE, (button) -> {
for (EntryInfo info : entries)
if (info.id.equals(modid)) {
try {
info.field.set(null, info.value);
} catch (IllegalAccessException ignored) {}
}
write(modid);
Objects.requireNonNull(client).openScreen(parent);
}));
this.list = new MidnightConfigListWidget(this.client, this.width, this.height, 32, this.height - 32, 25);
this.addSelectableChild(this.list);
for (EntryInfo info : entries) {
if (info.id.equals(modid)) {
TranslatableText name = new TranslatableText(translationPrefix + info.field.getName());
ButtonWidget resetButton = new ButtonWidget(width - 155, 0, 40, 20, new LiteralText("Reset").formatted(Formatting.RED), (button -> {
info.value = info.defaultValue;
info.tempValue = info.value.toString();
double scrollAmount = list.getScrollAmount();
Objects.requireNonNull(client).openScreen(this);
list.setScrollAmount(scrollAmount);
}));
if (info.widget instanceof Map.Entry) {
Map.Entry<ButtonWidget.PressAction, Function<Object, Text>> widget = (Map.Entry<ButtonWidget.PressAction, Function<Object, Text>>) info.widget;
if (info.field.getType().isEnum()) widget.setValue(value -> new TranslatableText(translationPrefix + "enum." + info.field.getType().getSimpleName() + "." + info.value.toString()));
this.list.addButton(new ButtonWidget(width - 110, 0,100, 20, widget.getValue().apply(info.value), widget.getKey()),resetButton,name);
} else if (info.widget != null) {
TextFieldWidget widget = new TextFieldWidget(textRenderer, width - 110, 0, 100, 20, null);
widget.setMaxLength(info.width);
widget.setText(info.tempValue);
Predicate<String> processor = ((BiFunction<TextFieldWidget, ButtonWidget, Predicate<String>>) info.widget).apply(widget, done);
widget.setTextPredicate(processor);
this.list.addButton(widget, resetButton, name);
} else {
ButtonWidget dummy = new ButtonWidget(-10, 0, 0, 0, Text.of(""), null);
this.list.addButton(dummy,dummy,name);
}
}
}
}
@Override
public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) {
this.renderBackground(matrices);
this.list.render(matrices, mouseX, mouseY, delta);
int stringWidth = (int) (title.getString().length() * 2.75f);
if (useTooltipForTitle) renderTooltip(matrices, title, width/2 - stringWidth, 27);
else drawCenteredText(matrices, textRenderer, title, width / 2, 15, 0xFFFFFF);
for (EntryInfo info : entries) {
if (info.id.equals(modid)) {
if (list.getHoveredButton(mouseX,mouseY).isPresent()) {
ClickableWidget buttonWidget = list.getHoveredButton(mouseX,mouseY).get();
Text text = ButtonEntry.buttonsWithText.get(buttonWidget);
TranslatableText name = new TranslatableText(this.translationPrefix + info.field.getName());
String key = translationPrefix + info.field.getName() + ".tooltip";
if (info.error != null && text.equals(name)) renderTooltip(matrices, info.error.getValue(), mouseX, mouseY);
else if (I18n.hasTranslation(key) && text.equals(name)) {
List<Text> list = new ArrayList<>();
for (String str : I18n.translate(key).split("\n"))
list.add(new LiteralText(str));
renderTooltip(matrices, list, mouseX, mouseY);
}
}
}
}
super.render(matrices,mouseX,mouseY,delta);
}
}
@Environment(EnvType.CLIENT)
public static class MidnightConfigListWidget extends ElementListWidget<ButtonEntry> {
TextRenderer textRenderer;
public MidnightConfigListWidget(MinecraftClient minecraftClient, int i, int j, int k, int l, int m) {
super(minecraftClient, i, j, k, l, m);
this.centerListVertically = false;
textRenderer = minecraftClient.textRenderer;
}
@Override
public int getScrollbarPositionX() { return this.width -7; }
public void addButton(ClickableWidget button, ClickableWidget resetButton, Text text) {
this.addEntry(ButtonEntry.create(button, text, resetButton));
}
@Override
public int getRowWidth() { return 10000; }
public Optional<ClickableWidget> getHoveredButton(double mouseX, double mouseY) {
for (ButtonEntry buttonEntry : this.children()) {
for (ClickableWidget ClickableWidget : buttonEntry.buttons) {
if (ClickableWidget.isMouseOver(mouseX, mouseY)) {
return Optional.of(ClickableWidget);
}
}
}
return Optional.empty();
}
}
public static class ButtonEntry extends ElementListWidget.Entry<ButtonEntry> {
private static final TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer;
private final List<ClickableWidget> buttons = new ArrayList<>();
private final List<ClickableWidget> resetButtons = new ArrayList<>();
private final List<Text> texts = new ArrayList<>();
private final List<ClickableWidget> buttonsWithResetButtons = new ArrayList<>();
public static final Map<ClickableWidget, Text> buttonsWithText = new HashMap<>();
private ButtonEntry(ClickableWidget button, Text text, ClickableWidget resetButton) {
buttonsWithText.put(button,text);
this.buttons.add(button);
this.resetButtons.add(resetButton);
this.texts.add(text);
this.buttonsWithResetButtons.add(button);
this.buttonsWithResetButtons.add(resetButton);
}
public static ButtonEntry create(ClickableWidget button, Text text, ClickableWidget resetButton) {
return new ButtonEntry(button, text, resetButton);
}
public void render(MatrixStack matrices, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta) {
this.buttons.forEach(button -> {
button.y = y;
button.render(matrices, mouseX, mouseY, tickDelta);
});
this.texts.forEach(text -> DrawableHelper.drawTextWithShadow(matrices,textRenderer, text,12,y+5,0xFFFFFF));
this.resetButtons.forEach((button) -> {
button.y = y;
button.render(matrices, mouseX, mouseY, tickDelta);
});
}
public List<? extends Element> children() {
return buttonsWithResetButtons;
}
public List<? extends Selectable> method_37025() {
return buttonsWithResetButtons;
}
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Entry {
int width() default 100;
double min() default Double.MIN_NORMAL;
double max() default Double.MAX_VALUE;
}
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface Comment {}
public static class HiddenAnnotationExclusionStrategy implements ExclusionStrategy {
public boolean shouldSkipClass(Class<?> clazz) { return false; }
public boolean shouldSkipField(FieldAttributes fieldAttributes) {
return fieldAttributes.getAnnotation(Entry.class) == null;
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 182 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

@@ -0,0 +1,7 @@
{
"blur.midnightconfig.title": "Blur Konfiguration",
"blur.midnightconfig.fadeTimeMillis": "Überblendzeit (in Millisekunden)",
"blur.midnightconfig.radius": "Radius",
"blur.midnightconfig.gradientStartColor": "Farbverlauf-Anfangsfarbe",
"blur.midnightconfig.gradientEndColor": "Farbverlauf-Endfarbe"
}

View File

@@ -0,0 +1,7 @@
{
"blur.midnightconfig.title": "Blur Config",
"blur.midnightconfig.fadeTimeMillis": "Fade Time (in milliseconds)",
"blur.midnightconfig.radius": "Radius",
"blur.midnightconfig.gradientStartColor": "Gradient Start Colour",
"blur.midnightconfig.gradientEndColor": "Gradient End Colour"
}

7
src/main/resources/assets/blur/lang/en_us.json Normal file → Executable file
View File

@@ -1,3 +1,8 @@
{
"blur.config.title": "Blur Config"
"blur.midnightconfig.title": "Blur Config",
"blur.midnightconfig.blurExclusions": "§cBlur Exclusions are currently not configurable in-game!",
"blur.midnightconfig.fadeTimeMillis": "Fade Time (in milliseconds)",
"blur.midnightconfig.radius": "Radius",
"blur.midnightconfig.gradientStartColor": "Gradient Start Color",
"blur.midnightconfig.gradientEndColor": "Gradient End Color"
}

View File

@@ -0,0 +1,8 @@
{
"blur.midnightconfig.title": "Definições de desfoque",
"blur.midnightconfig.blurExclusions": "Exclusões de desfoque não são configuráveis em jogo no momento.",
"blur.midnightconfig.fadeTimeMillis": "Esmaecimento (em milissegundos)",
"blur.midnightconfig.radius": "Raio",
"blur.midnightconfig.gradientStartColor": "Cor de início do gradiente",
"blur.midnightconfig.gradientEndColor": "Cor de término do gradiente"
}

View File

@@ -0,0 +1,8 @@
{
"blur.midnightconfig.title": "Настройки Blur",
"blur.midnightconfig.blurExclusions": "В настоящее время исключения для размытия не настраиваются в игре.",
"blur.midnightconfig.fadeTimeMillis": "Время размытия (в милисекундах)",
"blur.midnightconfig.radius": "Радиус размытия",
"blur.midnightconfig.gradientStartColor": "Верхний цвет градиента",
"blur.midnightconfig.gradientEndColor": "Нижний цвет градиента"
}

View File

@@ -0,0 +1,7 @@
{
"blur.midnightconfig.title": "模糊配置",
"blur.midnightconfig.fadeTimeMillis": "淡入时间(毫秒)",
"blur.midnightconfig.radius": "半径",
"blur.midnightconfig.gradientStartColor": "渐变起始色",
"blur.midnightconfig.gradientEndColor": "渐变结束色"
}

View File

@@ -1,9 +1,9 @@
#version 120
#version 150
uniform sampler2D DiffuseSampler;
varying vec2 texCoord;
varying vec2 oneTexel;
in vec2 texCoord;
in vec2 oneTexel;
uniform vec2 InSize;
@@ -11,6 +11,8 @@ uniform vec2 BlurDir;
uniform float Radius;
uniform float Progress;
out vec4 fragColor;
void main() {
vec4 blurred = vec4(0.0);
float totalStrength = 0.0;
@@ -18,7 +20,7 @@ void main() {
float totalSamples = 0.0;
float progRadius = floor(Radius * Progress);
for(float r = -progRadius; r <= progRadius; r += 1.0) {
vec4 sample = texture2D(DiffuseSampler, texCoord + oneTexel * r * BlurDir);
vec4 sample = texture(DiffuseSampler, texCoord + oneTexel * r * BlurDir);
// Accumulate average alpha
totalAlpha = totalAlpha + sample.a;
@@ -29,5 +31,5 @@ void main() {
totalStrength = totalStrength + strength;
blurred = blurred + sample;
}
gl_FragColor = vec4(blurred.rgb / (progRadius * 2.0 + 1.0), totalAlpha);
fragColor = vec4(blurred.rgb / (progRadius * 2.0 + 1.0), totalAlpha);
}

View File

@@ -1,8 +1,8 @@
{
"blend": {
"func": "add",
"srcrgb": "one",
"dstrgb": "zero"
"srcrgb": "srcalpha",
"dstrgb": "1-srcalpha"
},
"vertex": "sobel",
"fragment": "blur:fade_in_blur",

17
src/main/resources/fabric.mod.json Normal file → Executable file
View File

@@ -1,8 +1,8 @@
{
"schemaVersion": 1,
"id": "blur",
"name": "Blur",
"version": "$version",
"name": "Blur (Fabric)",
"version": "2.1.0",
"environment": "client",
"license": "MIT",
"icon": "assets/blur/icon.png",
@@ -12,17 +12,16 @@
]
},
"contact": {
"homepage": "https://minecraft.curseforge.com/projects/blur",
"issues": "https://github.com/tterrag1098/Blur/issues"
"homepage": "https://www.curseforge.com/minecraft/mc-mods/blur-fabric",
"issues": "https://github.com/Motschen/Blur/issues"
},
"authors": [
"tterrag1098"
"tterrag1098",
"Pyrofab",
"Motschen"
],
"description": "Modifies the background behind Minecraft GUIs to have a blur effect",
"mixins": [
"mixins.blur.json"
],
"custom": {
"modmenu:clientsideOnly": true
}
]
}