diff --git a/.gitignore b/.gitignore index 7a4d0f0..8dfb399 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .idea/ +.vscode/ *.iml *.ipr *.iws @@ -11,4 +12,3 @@ build/ classes/ lombok.config extra.properties -swear_words.csv \ No newline at end of file diff --git a/build.gradle b/build.gradle index a08696f..8378fed 100644 --- a/build.gradle +++ b/build.gradle @@ -1,13 +1,19 @@ plugins { - id 'fabric-loom' version '1.0-SNAPSHOT' - id 'maven-publish' - id "io.freefair.lombok" version "6.0.0-m2" + id "fabric-loom" version "1.11-SNAPSHOT" + id "maven-publish" + id "io.freefair.lombok" version "8.10" } -apply from: 'https://raw.githubusercontent.com/DarkKronicle/GradleScripts/main/gradle/publish.gradle' +java { + toolchain { + languageVersion = JavaLanguageVersion.of(21) + } +} -sourceCompatibility = JavaVersion.VERSION_17 -targetCompatibility = JavaVersion.VERSION_17 +// apply from: 'https://raw.githubusercontent.com/DarkKronicle/GradleScripts/main/gradle/publish.gradle' + +sourceCompatibility = JavaVersion.VERSION_21 +targetCompatibility = JavaVersion.VERSION_21 archivesBaseName = project.archives_base_name version = "${project.minecraft_version}-${project.mod_version}" @@ -30,8 +36,8 @@ dependencies { minecraft "com.mojang:minecraft:${project.minecraft_version}" mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2" modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" - modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_api_version}" - modImplementation "fi.dy.masa.malilib:malilib-fabric-1.20.2:${project.malilib_version}" + modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" + modImplementation "com.github.sakura-ryoko:malilib:${project.malilib_version}" modCompileOnly "com.terraformersmc:modmenu:${project.modmenu_version}" implementation "com.github.DarkKronicle.Konstruct:addons:${project.konstruct_version}" @@ -52,9 +58,8 @@ dependencies { implementation "io.github.maowimpl:owo:${project.owo_version}" include "io.github.maowimpl:owo:${project.owo_version}" - implementation 'org.apache.commons:commons-csv:1.8' - include 'org.apache.commons:commons-csv:1.8' - + implementation 'org.apache.commons:commons-csv:1.11.0' + include 'org.apache.commons:commons-csv:1.11.0' } processResources { @@ -67,27 +72,20 @@ processResources { tasks.withType(JavaCompile).configureEach { it.options.encoding = "UTF-8" - it.options.release = 17 + it.options.release = 21 } -task sourcesJar(type: Jar, dependsOn: classes) { - classifier = "sources" +tasks.register("sourcesJar", Jar) { + dependsOn classes + archiveClassifier.set("sources") from sourceSets.main.allSource } - jar { from "LICENSE.txt" } -tasks.register('downloadExtra') { - def f = new File('./src/main/resources/swear_words.csv') - if (!f.exists()) { - new URL('https://raw.githubusercontent.com/surge-ai/profanity/main/profanity_en.csv').withInputStream{ i -> f.withOutputStream{ it << i }} - } -} - assemble { - dependsOn 'downloadExtra' + // dependsOn 'downloadExtra' } // configure the maven publication @@ -107,6 +105,6 @@ publishing { // select the repositories you want to publish to repositories { // uncomment to publish to the local maven - // mavenLocal() + mavenLocal() } } diff --git a/gradle.properties b/gradle.properties index ab07351..46394b2 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,19 +1,22 @@ org.gradle.jvmargs=-Xmx1G +org.gradle.parallel=true -minecraft_version=1.20.4 -yarn_mappings=1.20.4+build.3 -loader_version=0.15.3 -fabric_api_version=0.92.0+1.20.4 +minecraft_version=1.21.8 +yarn_mappings=1.21.8+build.1 +loader_version=0.17.2 +loom_version=1.11-SNAPSHOT -mod_version=1.5.10 +fabric_version=0.132.0+1.21.8 + +mod_version=1.8.0 maven_group=io.github.darkkronicle archives_base_name=AdvancedChatCore -malilib_version=0.17.0 +malilib_version=1.21.8-0.25.5-sakura.4 konstruct_version=2.0.3-build1 mxparser_version=4.4.2 owo_version=2.0.0 -modmenu_version=7.1.0 +modmenu_version=12.0.0 # Uploading data curseforge_slug=advancedchatcore @@ -30,4 +33,4 @@ project_logo=https://raw.githubusercontent.com/DarkKronicle/AdvancedChatCore/mai project_color=0x134bff changelog_hide_unimportant_commits=true changelog_max_commit_search=200 -discord_webhook_changelog_line_limit=10 \ No newline at end of file +discord_webhook_changelog_line_limit=10 diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 7454180..e644113 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index ffed3a2..d4081da 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip +networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index df3a6fe..b740cf1 100755 --- a/gradlew +++ b/gradlew @@ -1,7 +1,7 @@ -#!/usr/bin/env sh +#!/bin/sh # -# Copyright 2015 the original author or authors. +# Copyright © 2015-2021 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -17,67 +17,99 @@ # ############################################################################## -## -## Gradle start up script for UN*X -## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# ############################################################################## # Attempt to set APP_HOME + # Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -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"' +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +MAX_FD=maximum warn () { echo "$*" -} +} >&2 die () { echo echo "$*" echo exit 1 -} +} >&2 # 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 - ;; +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar @@ -87,97 +119,131 @@ CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACMD=$JAVA_HOME/jre/sh/java else - JAVACMD="$JAVA_HOME/bin/java" + JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. -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 - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac fi -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. # 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="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) fi - i=`expr $i + 1` + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg 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" ;; - esac fi -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=`save "$@"` -# 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" +# 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"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' -exec "$JAVACMD" "$@" \ No newline at end of file +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index 28690fe..7101f8e 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -14,7 +14,7 @@ @rem limitations under the License. @rem -@if "%DEBUG%" == "" @echo off +@if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @@ -25,7 +25,8 @@ if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @@ -40,13 +41,13 @@ if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute +if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -56,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -75,15 +76,17 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar :end @rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd +if %ERRORLEVEL% equ 0 goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% :mainEnd if "%OS%"=="Windows_NT" endlocal -:omega \ No newline at end of file +:omega diff --git a/src/main/java/io/github/darkkronicle/advancedchatcore/AdvancedChatCore.java b/src/main/java/io/github/darkkronicle/advancedchatcore/AdvancedChatCore.java index 6f42dd4..559041a 100644 --- a/src/main/java/io/github/darkkronicle/advancedchatcore/AdvancedChatCore.java +++ b/src/main/java/io/github/darkkronicle/advancedchatcore/AdvancedChatCore.java @@ -10,6 +10,8 @@ import fi.dy.masa.malilib.event.InitializationHandler; import fi.dy.masa.malilib.gui.GuiBase; import io.github.darkkronicle.advancedchatcore.chat.AdvancedSleepingChatScreen; +import io.github.darkkronicle.advancedchatcore.chat.ChatHistory; +import io.github.darkkronicle.advancedchatcore.config.ConfigStorage; import io.github.darkkronicle.advancedchatcore.util.Colors; import io.github.darkkronicle.advancedchatcore.util.SyncTaskQueue; import java.io.FileInputStream; @@ -23,6 +25,7 @@ import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; +import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents; import net.minecraft.client.MinecraftClient; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -74,6 +77,12 @@ public void onInitializeClient() { GuiBase.openGui(null); } }); + ClientPlayConnectionEvents.DISCONNECT.register((handler, c) -> { + if (ConfigStorage.General.CLEAR_ON_DISCONNECT.config.getBooleanValue()) { + ChatHistory.getInstance().clearAll(); + LOGGER.debug("Cleared chat successfully"); + } + }); } /** diff --git a/src/main/java/io/github/darkkronicle/advancedchatcore/chat/AdvancedChatScreen.java b/src/main/java/io/github/darkkronicle/advancedchatcore/chat/AdvancedChatScreen.java index cd5ae9f..d9c3abb 100644 --- a/src/main/java/io/github/darkkronicle/advancedchatcore/chat/AdvancedChatScreen.java +++ b/src/main/java/io/github/darkkronicle/advancedchatcore/chat/AdvancedChatScreen.java @@ -18,6 +18,7 @@ import io.github.darkkronicle.advancedchatcore.util.Color; import io.github.darkkronicle.advancedchatcore.util.RowList; import lombok.Getter; +import net.fabricmc.loader.impl.util.log.Log; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.hud.ChatHud; @@ -117,37 +118,57 @@ public boolean charTyped(char charIn, int modifiers) { public void initGui() { super.initGui(); + this.rightSideButtons.clear(); this.leftSideButtons.clear(); + resetCurrentMessage(); + this.chatField = - new AdvancedTextField( - this.textRenderer, - 4, - this.height - 12, - this.width - 10, - 12, - Text.translatable("chat.editBox")) { - protected MutableText getNarrationMessage() { - return null; - } - }; + new AdvancedTextField( + super.textRenderer, + 4, + super.height - 12, + super.width - 10, + 12, + Text.translatable("chat.editBox") + ) { + protected MutableText getNarrationMessage() { + return null; + } + }; + if (ConfigStorage.ChatScreen.MORE_TEXT.config.getBooleanValue()) { this.chatField.setMaxLength(64000); } else { this.chatField.setMaxLength(256); } + this.chatField.setDrawsBackground(false); - if (!this.originalChatText.equals("")) { + + if (!this.originalChatText.isEmpty()) { this.chatField.setText(this.originalChatText); - } else if (ConfigStorage.ChatScreen.PERSISTENT_TEXT.config.getBooleanValue() - && !last.equals("")) { + } else if ( + ConfigStorage.ChatScreen.PERSISTENT_TEXT.config.getBooleanValue() && + !last.isEmpty() + ) { this.chatField.setText(last); } + this.chatField.setChangedListener(this::onChatFieldUpdate); // Add settings button - rightSideButtons.add("settings", new IconButton(0, 0, 14, 64, new Identifier(AdvancedChatCore.MOD_ID, "textures/gui/settings.png"), (button) -> GuiBase.openGui(GuiConfigHandler.getInstance().getDefaultScreen()))); + rightSideButtons.add( + "settings", + new IconButton( + 0, + 0, + 14, + 64, + Identifier.of(AdvancedChatCore.MOD_ID, "textures/gui/settings.png"), + (button) -> GuiBase.openGui(GuiConfigHandler.getInstance().getDefaultScreen()) + ) + ); this.addSelectableChild(this.chatField); @@ -157,22 +178,40 @@ protected MutableText getNarrationMessage() { section.initGui(); } + this.renderButtons(); + + if (startHistory >= 0) { + setChatFromHistory(-startHistory - 1); + } + } + + private void renderButtons() { + super.clearButtons(); + int originalX = client.getWindow().getScaledWidth() - 1; - int y = client.getWindow().getScaledHeight() - 30; + + // int y = client.getWindow().getScaledHeight() - 30; + int y = client.getWindow().getScaledHeight() - 30 - (chatField.getHeight() * (chatField.getRenderLines().size() - 1) + 1); + for (int i = 0; i < rightSideButtons.rowSize(); i++) { List buttonList = rightSideButtons.get(i); int maxHeight = 0; int x = originalX; for (ButtonBase button : buttonList) { maxHeight = Math.max(maxHeight, button.getHeight()); - x -= button.getWidth() + 1; + x -= button.getWidth() + 2; button.setPosition(x, y); - addButton(button, null); + super.addButton(button, null); + // AdvancedChatCore.LOGGER.info("Adding right-side button at x: %s; y: %s; button: %s".formatted(x, y, button)); } - y -= maxHeight + 1; + y -= maxHeight + 2; } + originalX = 1; - y = client.getWindow().getScaledHeight() - 30; + + // y = client.getWindow().getScaledHeight() - 30; + y = client.getWindow().getScaledHeight() - 30 - (chatField.getHeight() * (chatField.getRenderLines().size() - 1) + 1); + for (int i = 0; i < leftSideButtons.rowSize(); i++) { List buttonList = leftSideButtons.get(i); int maxHeight = 0; @@ -180,15 +219,12 @@ protected MutableText getNarrationMessage() { for (ButtonBase button : buttonList) { maxHeight = Math.max(maxHeight, button.getHeight()); button.setPosition(x, y); - addButton(button, null); - x += button.getWidth() + 1; + super.addButton(button, null); + // AdvancedChatCore.LOGGER.info("Adding left-side button at x: %s; y: %s; button: %s".formatted(x, y, button)); + x += button.getWidth() + 2; } - y -= maxHeight + 1; - } - if (startHistory >= 0) { - setChatFromHistory(-startHistory - 1); + y -= maxHeight + 2; } - } public void resize(MinecraftClient client, int width, int height) { @@ -216,6 +252,8 @@ private void onChatFieldUpdate(String chatText) { for (AdvancedChatScreenSection section : sections) { section.onChatFieldUpdate(chatText, string); } + + this.renderButtons(); } @Override @@ -387,6 +425,7 @@ public void setChatFromHistory(int i) { @Override public void render(DrawContext context, int mouseX, int mouseY, float partialTicks) { + this.client.inGameHud.getChatHud().render(context, this.client.inGameHud.getTicks(), mouseX, mouseY, true); ChatHud hud = client.inGameHud.getChatHud(); this.setFocused(this.chatField); this.chatField.setFocused(true); @@ -402,9 +441,15 @@ public void render(DrawContext context, int mouseX, int mouseY, float partialTic } } - @Override - protected void drawScreenBackground(int mouseX, int mouseY) { + // TODO: See if this is needed + // @Override + // protected void drawScreenBackground(int mouseX, int mouseY) { + + // } + @Override + protected void drawScreenBackground(DrawContext drawContext, int mouseX, int mouseY) { + // Don't. } private void setText(String text) { diff --git a/src/main/java/io/github/darkkronicle/advancedchatcore/chat/AdvancedTextField.java b/src/main/java/io/github/darkkronicle/advancedchatcore/chat/AdvancedTextField.java index a5bdcae..f04bca8 100644 --- a/src/main/java/io/github/darkkronicle/advancedchatcore/chat/AdvancedTextField.java +++ b/src/main/java/io/github/darkkronicle/advancedchatcore/chat/AdvancedTextField.java @@ -7,21 +7,17 @@ */ package io.github.darkkronicle.advancedchatcore.chat; -import com.mojang.blaze3d.platform.GlStateManager; -import com.mojang.blaze3d.systems.RenderSystem; import fi.dy.masa.malilib.util.KeyCodes; import io.github.darkkronicle.advancedchatcore.config.ConfigStorage; -import io.github.darkkronicle.advancedchatcore.util.StringMatch; import io.github.darkkronicle.advancedchatcore.util.StyleFormatter; import io.github.darkkronicle.advancedchatcore.util.TextBuilder; import io.github.darkkronicle.advancedchatcore.util.TextUtil; +import lombok.Getter; import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder; import net.minecraft.client.gui.widget.TextFieldWidget; -import net.minecraft.client.render.*; -import net.minecraft.client.util.math.MatrixStack; import net.minecraft.text.OrderedText; import net.minecraft.text.Style; import net.minecraft.text.Text; @@ -46,14 +42,19 @@ public class AdvancedTextField extends TextFieldWidget { private final List history = new ArrayList<>(); private int focusedTicks = 0; + + @Getter private List renderLines = new ArrayList<>(); + private TextRenderer textRenderer; private String suggestion = null; private int maxLength = 32; private int selectionEnd; private int selectionStart; + // TODO Split? - private BiFunction renderTextProvider = (string, firstCharacterIndex) -> OrderedText.styledForwardsVisitedString(string, Style.EMPTY); + private BiFunction renderTextProvider = + (string, firstCharacterIndex) -> OrderedText.styledForwardsVisitedString(string, Style.EMPTY); private int historyIndex = -1; @@ -62,16 +63,20 @@ public AdvancedTextField(TextRenderer textRenderer, int x, int y, int width, int } public AdvancedTextField( - TextRenderer textRenderer, - int x, - int y, - int width, - int height, - @Nullable TextFieldWidget copyFrom, - Text text) { + TextRenderer textRenderer, + int x, + int y, + int width, + int height, + @Nullable TextFieldWidget copyFrom, + Text text + ) { super(textRenderer, x, y, width, height, copyFrom, text); + history.add(""); + this.textRenderer = textRenderer; + updateRender(); } @@ -155,80 +160,92 @@ public boolean mouseClicked(double mouseX, double mouseY, int button) { @Override public void renderWidget(DrawContext context, int mouseX, int mouseY, float delta) { - int color = 0xE0E0E0; + int color = 0xFFE0E0E0; int cursor = getCursor(); int cursorRow = renderLines.size() - 1; boolean renderCursor = this.isFocused() && focusedTicks / 6 % 2 == 0; int renderY = getY() - (renderLines.size() - 1) * (textRenderer.fontHeight + 2); int endX = 0; int charCount = 0; - int cursorX = -1; + int cursorX = 0; boolean selection = selectionStart != selectionEnd; boolean started = false; boolean ended = false; - int selStart; - int selEnd; - if (this.selectionStart < this.selectionEnd) { - selStart = this.selectionStart; - selEnd = this.selectionEnd; - } else { - selStart = this.selectionEnd; - selEnd = this.selectionStart; - } + + int selStart = Math.min(selectionStart, selectionEnd); + int selEnd = Math.max(selectionStart, selectionEnd); + int x = getX(); - int y = getY() ; - context.fill(getX() - 2, renderY - 2, getX() + width + 4, getY() + height + 4, ConfigStorage.ChatScreen.COLOR.config.get().color()); + int y = getY(); + + // Background + context.fill(x - 2, renderY - 2, x + width + 4, y + height + 4, ConfigStorage.ChatScreen.COLOR.config.get().color()); + for (int line = 0; line < renderLines.size(); line++) { Text text = renderLines.get(line); - if (cursor >= charCount && cursor < text.getString().length() + charCount) { - cursorX = textRenderer.getWidth(text.getString().substring(0, cursor - charCount)); + + // Strip leading spaces from wrapped lines + String raw = text.getString().stripLeading(); + int lineLength = raw.length(); + + // Compute cursor position for this line + if (cursor >= charCount && cursor <= charCount + lineLength) { + cursorX = textRenderer.getWidth(raw.substring(0, cursor - charCount)); cursorRow = line; } - endX = context.drawTextWithShadow(textRenderer, text, x, renderY, color); + + // Draw text + context.drawTextWithShadow(textRenderer, Text.literal(raw).setStyle(text.getStyle()), x, renderY, color); + + // Selection highlight if (selection) { - if (!started && selStart >= charCount && selStart <= text.getString().length() + charCount) { + if (!started && selStart >= charCount && selStart <= charCount + lineLength) { started = true; - int startX = textRenderer.getWidth(TextUtil.truncate(text, new StringMatch("", 0, selStart - charCount))); - if (selEnd > charCount && selEnd <= text.getString().length() + charCount) { - ended = true; - int sEndX = textRenderer.getWidth(TextUtil.truncate(text, new StringMatch("", 0, selEnd - charCount))); - drawSelectionHighlight(x + startX, renderY - 1, x + sEndX, renderY + textRenderer.fontHeight); - } else { - int sEndX = textRenderer.getWidth(text); - drawSelectionHighlight(x + startX, renderY - 1, x + sEndX, renderY + textRenderer.fontHeight); - } + + int startX = textRenderer.getWidth(raw.substring(0, selStart - charCount)); + + int sEndX = + selEnd <= charCount + lineLength + ? textRenderer.getWidth(raw.substring(0, selEnd - charCount)) + : textRenderer.getWidth(raw); + + drawSelectionHighlight(context, x + startX, renderY - 1, x + sEndX, renderY + textRenderer.fontHeight); + + if (selEnd <= charCount + lineLength) ended = true; } else if (started && !ended) { - if (selEnd >= charCount && selEnd <= text.getString().length() + charCount) { - ended = true; - int sEndX = textRenderer.getWidth(TextUtil.truncate(text, new StringMatch("", 0, selEnd - charCount))); - drawSelectionHighlight(x, renderY - 1, x + sEndX, renderY + textRenderer.fontHeight); - } else { - int sEndX = textRenderer.getWidth(text); - drawSelectionHighlight(x, renderY - 1, x + sEndX, renderY + textRenderer.fontHeight); - } + int sEndX = + selEnd <= charCount + lineLength + ? textRenderer.getWidth(raw.substring(0, selEnd - charCount)) + : textRenderer.getWidth(raw); + + drawSelectionHighlight(context, x, renderY - 1, x + sEndX, renderY + textRenderer.fontHeight); + + if (selEnd <= charCount + lineLength) ended = true; } } + + endX += textRenderer.getWidth(raw); renderY += textRenderer.fontHeight + 2; - charCount += text.getString().length(); - } - if (cursorX < 0) { - cursorX = endX; + charCount += lineLength; } - boolean cursorAtEnd = getCursor() == getText().length(); + + boolean cursorAtEnd = cursor == getText().length(); + + // Suggestion if (!cursorAtEnd && this.suggestion != null) { - context.drawTextWithShadow(textRenderer, this.suggestion, endX - 1, y, -8355712); + context.drawTextWithShadow(textRenderer, this.suggestion, endX - 1, y, 0xFF7F7F7F); } + + // Draw vertical caret if (renderCursor) { int cursorY = y - (renderLines.size() - 1 - cursorRow) * (textRenderer.fontHeight + 2); - if (cursorAtEnd) { - context.fill(cursorX, cursorY - 1, cursorX + 1, cursorY + 1 + this.textRenderer.fontHeight, -3092272); - } else { - context.drawTextWithShadow(textRenderer, "_", x + cursorX, cursorY, color); - } + int caretX = x + cursorX; + + context.fill(caretX, cursorY - 1, caretX + 1, cursorY + textRenderer.fontHeight + 1, 0xFFE0E0E0); } } - private void drawSelectionHighlight(int x1, int y1, int x2, int y2) { + private void drawSelectionHighlight(DrawContext context, int x1, int y1, int x2, int y2) { int x = getX(); int y = getY(); int i; @@ -248,22 +265,7 @@ private void drawSelectionHighlight(int x1, int y1, int x2, int y2) { if (x1 > x + this.width) { x1 = x + this.width; } - Tessellator tessellator = Tessellator.getInstance(); - BufferBuilder bufferBuilder = tessellator.getBuffer(); - RenderSystem.setShader(GameRenderer::getPositionProgram); - RenderSystem.setShaderColor(0.0f, 0.0f, 1.0f, 1.0f); -// RenderSystem.disableTexture(); - RenderSystem.enableColorLogicOp(); - RenderSystem.logicOp(GlStateManager.LogicOp.OR_REVERSE); - bufferBuilder.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION); - bufferBuilder.vertex(x1, y2, 0.0).next(); - bufferBuilder.vertex(x2, y2, 0.0).next(); - bufferBuilder.vertex(x2, y1, 0.0).next(); - bufferBuilder.vertex(x1, y1, 0.0).next(); - tessellator.draw(); - RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f); - RenderSystem.disableColorLogicOp(); -// RenderSystem.enableTexture(); + context.fill(x1, y1, x2, y2, 0x96FF5500); } @Override @@ -306,7 +308,24 @@ public void setText(String text) { private void updateRender() { OrderedText formatted = renderTextProvider.apply(getText(), 0); - renderLines = StyleFormatter.wrapText(textRenderer, getWidth(), new TextBuilder().append(formatted).build()); + + List wrappedLines = StyleFormatter.wrapText( + textRenderer, + getWidth(), + new TextBuilder().append(formatted).build() + ); + + // Remove leading spaces from each line to prevent indentation after wrapping + List lines = new ArrayList<>(); + for (Text t : wrappedLines) { + String stripped = t.getString().stripLeading(); + + Text line = Text.literal(stripped).setStyle(t.getStyle()); + + lines.add(line); + } + + renderLines = lines; } private void updateHistory() { @@ -328,7 +347,7 @@ private void addToHistory(String text) { this.lastSaved = text; this.history.add(text); while (this.history.size() > MAX_HISTORY) { - this.history.remove(0); + this.history.removeFirst(); } } @@ -343,7 +362,7 @@ private void pruneHistory(int index) { return; } while (history.size() > index) { - history.remove(history.size() - 1); + history.removeLast(); } } @@ -367,4 +386,15 @@ public boolean keyPressed(int keyCode, int scanCode, int modifiers) { public void appendClickableNarrations(NarrationMessageBuilder builder) { // Crashes here because Text is null } + + @Override + public void eraseWords(int wordOffset) { + if (!this.getText().isEmpty()) { + if (this.selectionEnd != this.selectionStart) { + this.setText(""); + } else { + this.eraseCharacters(this.getWordSkipPosition(wordOffset) - this.selectionStart); + } + } + } } diff --git a/src/main/java/io/github/darkkronicle/advancedchatcore/chat/ChatHistory.java b/src/main/java/io/github/darkkronicle/advancedchatcore/chat/ChatHistory.java index a0d1d05..09e7da8 100644 --- a/src/main/java/io/github/darkkronicle/advancedchatcore/chat/ChatHistory.java +++ b/src/main/java/io/github/darkkronicle/advancedchatcore/chat/ChatHistory.java @@ -99,10 +99,10 @@ public boolean add(ChatMessage message) { } } sendUpdate(message, IChatMessageProcessor.UpdateType.ADDED); - messages.add(0, message); + messages.addFirst(message); while (this.messages.size() > maxLines) { sendUpdate( - this.messages.remove(this.messages.size() - 1), + this.messages.removeLast(), IChatMessageProcessor.UpdateType.REMOVE); } return true; diff --git a/src/main/java/io/github/darkkronicle/advancedchatcore/chat/ChatHistoryProcessor.java b/src/main/java/io/github/darkkronicle/advancedchatcore/chat/ChatHistoryProcessor.java index 175d848..5e4252b 100644 --- a/src/main/java/io/github/darkkronicle/advancedchatcore/chat/ChatHistoryProcessor.java +++ b/src/main/java/io/github/darkkronicle/advancedchatcore/chat/ChatHistoryProcessor.java @@ -18,6 +18,8 @@ import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.hud.ChatHud; +import net.minecraft.client.gui.hud.ChatHudLine; import net.minecraft.client.gui.hud.MessageIndicator; import net.minecraft.network.message.MessageSignatureData; import net.minecraft.text.Style; @@ -30,8 +32,12 @@ public class ChatHistoryProcessor implements IMessageProcessor { private static boolean sendToHud(Text text, @Nullable MessageSignatureData signature, MessageIndicator indicator) { if (AdvancedChatCore.FORWARD_TO_HUD) { - ((MixinChatHudInvoker) MinecraftClient.getInstance().inGameHud.getChatHud()).invokeAddMessage( - text, signature, MinecraftClient.getInstance().inGameHud.getTicks(), indicator, false); + ChatHud chatHud = MinecraftClient.getInstance().inGameHud.getChatHud(); + ChatHudLine chatHudLine = new ChatHudLine(MinecraftClient.getInstance().inGameHud.getTicks(), text, signature, indicator); + + ((MixinChatHudInvoker) chatHud).invokeAddVisibleMessage(chatHudLine); + ((MixinChatHudInvoker) chatHud).invokeAddMessage(chatHudLine); + return true; } return false; @@ -63,7 +69,7 @@ public boolean process(Text text, @Nullable Text unfiltered, @Nullable MessageSi Style style = Style.EMPTY; TextColor textColor = TextColor.fromRgb(color.color()); style = style.withColor(textColor); - text.getSiblings().add(0, Text.literal(replaceFormat.replaceAll("%TIME%", time.format(format))).fillStyle(style)); + text.getSiblings().addFirst(Text.literal(replaceFormat.replaceAll("%TIME%", time.format(format))).fillStyle(style)); } int width = 0; diff --git a/src/main/java/io/github/darkkronicle/advancedchatcore/chat/MessageDispatcher.java b/src/main/java/io/github/darkkronicle/advancedchatcore/chat/MessageDispatcher.java index ef98c3e..6c6d19f 100644 --- a/src/main/java/io/github/darkkronicle/advancedchatcore/chat/MessageDispatcher.java +++ b/src/main/java/io/github/darkkronicle/advancedchatcore/chat/MessageDispatcher.java @@ -16,6 +16,8 @@ import io.github.darkkronicle.advancedchatcore.util.StringMatch; import io.github.darkkronicle.advancedchatcore.util.StyleFormatter; import io.github.darkkronicle.advancedchatcore.util.TextUtil; + +import java.net.URI; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; @@ -76,7 +78,13 @@ private MessageDispatcher() { url = "https://" + url; } if (current.getStyle().getClickEvent() == null) { - return Text.literal(match1.match).fillStyle(current.getStyle().withClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, url))); + return Text.literal(match1.match).fillStyle( + current.getStyle().withClickEvent( + new ClickEvent.OpenUrl( + URI.create(url) + ) + ) + ); } return MutableText.of(current.getContent()).fillStyle(current.getStyle()); }); @@ -109,9 +117,9 @@ private MessageDispatcher() { * @param text Text that is received */ public void handleText(Text text, @Nullable MessageSignatureData signature, @Nullable MessageIndicator indicator) { - boolean previouslyBlank = text.getString().length() == 0; + boolean previouslyBlank = text.getString().isEmpty(); text = preFilter(text, signature, indicator); - if (text.getString().length() == 0 && !previouslyBlank) { + if (text.getString().isEmpty() && !previouslyBlank) { // No more return; } diff --git a/src/main/java/io/github/darkkronicle/advancedchatcore/chat/MessageSender.java b/src/main/java/io/github/darkkronicle/advancedchatcore/chat/MessageSender.java index 468493e..c1a2ffd 100644 --- a/src/main/java/io/github/darkkronicle/advancedchatcore/chat/MessageSender.java +++ b/src/main/java/io/github/darkkronicle/advancedchatcore/chat/MessageSender.java @@ -50,7 +50,7 @@ public void sendMessage(String string) { } this.client.inGameHud.getChatHud().addToMessageHistory(unfiltered); - if (string.length() == 0) { + if (string.isEmpty()) { AdvancedChatCore.LOGGER.log(Level.WARN, "Blank message was attempted to be sent. " + unfiltered); return; } diff --git a/src/main/java/io/github/darkkronicle/advancedchatcore/config/ConfigStorage.java b/src/main/java/io/github/darkkronicle/advancedchatcore/config/ConfigStorage.java index 6d80393..6ef980b 100644 --- a/src/main/java/io/github/darkkronicle/advancedchatcore/config/ConfigStorage.java +++ b/src/main/java/io/github/darkkronicle/advancedchatcore/config/ConfigStorage.java @@ -375,11 +375,13 @@ public static JsonElement parseJsonFile(File file) { element = parser.parse(reader); } catch (Exception e) { reader.close(); - MaLiLib.logger.error( - "Failed to parse the JSON file '{}'. Attempting different charset." - + " ", - fileName, - e); + + MaLiLib.LOGGER.error( + "Failed to parse the JSON file '{}'. Attempting different charset." + " ", + fileName, + e + ); + continue; } reader.close(); @@ -387,7 +389,7 @@ public static JsonElement parseJsonFile(File file) { return element; } } catch (Exception e) { - MaLiLib.logger.error("Failed to parse the JSON file '{}'", fileName, e); + MaLiLib.LOGGER.error("Failed to parse the JSON file '{}'", fileName, e); } } @@ -405,15 +407,14 @@ public static boolean writeJsonToFile(JsonObject root, File file) { return true; } catch (IOException e) { - MaLiLib.logger.warn( - "Failed to write JSON data to file '{}'", file.getAbsolutePath(), e); + MaLiLib.LOGGER.warn("Failed to write JSON data to file '{}'", file.getAbsolutePath(), e); } finally { try { if (writer != null) { writer.close(); } } catch (Exception e) { - MaLiLib.logger.warn("Failed to close JSON file", e); + MaLiLib.LOGGER.warn("Failed to close JSON file", e); } } diff --git a/src/main/java/io/github/darkkronicle/advancedchatcore/config/gui/GuiConfig.java b/src/main/java/io/github/darkkronicle/advancedchatcore/config/gui/GuiConfig.java index df94ffc..55fcc1a 100644 --- a/src/main/java/io/github/darkkronicle/advancedchatcore/config/gui/GuiConfig.java +++ b/src/main/java/io/github/darkkronicle/advancedchatcore/config/gui/GuiConfig.java @@ -13,7 +13,8 @@ import fi.dy.masa.malilib.gui.button.ButtonBase; import fi.dy.masa.malilib.gui.button.ButtonGeneric; import fi.dy.masa.malilib.gui.button.IButtonActionListener; -import fi.dy.masa.malilib.util.Color4f; +import fi.dy.masa.malilib.gui.widgets.WidgetListConfigOptions; +import fi.dy.masa.malilib.util.data.Color4f; import io.github.darkkronicle.advancedchatcore.AdvancedChatCore; import net.minecraft.client.gui.screen.Screen; @@ -68,11 +69,11 @@ public void initGui() { y += (addAllChildrenButtons(this, TAB, x, y) * 22); } setListPosition(getListX(), y + 10); - if (this.getListWidget() != null) { - this.getListWidget().setSize(this.getBrowserWidth(), this.getBrowserHeight()); - this.getListWidget().initGui(); + WidgetListConfigOptions listWidgetOptions = this.getListWidget(); + if (listWidgetOptions != null) { + listWidgetOptions.setSize(this.getBrowserWidth(), this.getBrowserHeight()); + listWidgetOptions.initGui(); } - } @Override diff --git a/src/main/java/io/github/darkkronicle/advancedchatcore/config/gui/widgets/WidgetLabelHoverable.java b/src/main/java/io/github/darkkronicle/advancedchatcore/config/gui/widgets/WidgetLabelHoverable.java index d472306..184de2f 100644 --- a/src/main/java/io/github/darkkronicle/advancedchatcore/config/gui/widgets/WidgetLabelHoverable.java +++ b/src/main/java/io/github/darkkronicle/advancedchatcore/config/gui/widgets/WidgetLabelHoverable.java @@ -34,19 +34,20 @@ public void setHoverLines(String... hoverLines) { } @Override - public void postRenderHovered( - int mouseX, int mouseY, boolean selected, DrawContext context) { - super.postRenderHovered(mouseX, mouseY, selected, context); + public void postRenderHovered(DrawContext context, int mouseX, int mouseY, boolean selected) { + super.postRenderHovered(context, mouseX, mouseY, selected); if (hoverLines == null) { return; } - if (mouseX >= this.x - && mouseX < this.x + this.width - && mouseY >= this.y - && mouseY <= this.y + this.height) { - RenderUtils.drawHoverText(mouseX, mouseY, this.hoverLines, context); + if ( + mouseX >= this.x && + mouseX < this.x + this.width && + mouseY >= this.y && + mouseY <= this.y + this.height + ) { + RenderUtils.drawHoverText(context, mouseX, mouseY, this.hoverLines); } } } diff --git a/src/main/java/io/github/darkkronicle/advancedchatcore/config/gui/widgets/WidgetRegistryOptionEntry.java b/src/main/java/io/github/darkkronicle/advancedchatcore/config/gui/widgets/WidgetRegistryOptionEntry.java index 42128ec..50c7e57 100644 --- a/src/main/java/io/github/darkkronicle/advancedchatcore/config/gui/widgets/WidgetRegistryOptionEntry.java +++ b/src/main/java/io/github/darkkronicle/advancedchatcore/config/gui/widgets/WidgetRegistryOptionEntry.java @@ -76,61 +76,69 @@ private int addOnOffButton(int xRight, int y, ButtonListener.Type type, boolean } @Override - public void render(int mouseX, int mouseY, boolean selected, DrawContext context) { - RenderUtils.color(1f, 1f, 1f, 1f); + public void render(DrawContext context, int mouseX, int mouseY, boolean selected) { + // RenderUtils.color(1f, 1f, 1f, 1f); // TODO: See if this is needed // Draw a lighter background for the hovered and the selected entry if (selected || this.isMouseOver(mouseX, mouseY)) { RenderUtils.drawRect( - this.x, - this.y, - this.width, - this.height, - Colors.getInstance().getColorOrWhite("white").withAlpha(150).color()); + context, // TODO: see if this is correct + this.x, + this.y, + this.width, + this.height, + Colors.getInstance().getColorOrWhite("white").withAlpha(150).color() + ); } else if (this.isOdd) { RenderUtils.drawRect( - this.x, - this.y, - this.width, - this.height, - Colors.getInstance().getColorOrWhite("white").withAlpha(70).color()); + context, // TODO: see if this is correct + this.x, + this.y, + this.width, + this.height, + Colors.getInstance().getColorOrWhite("white").withAlpha(70).color() + ); } else { RenderUtils.drawRect( - this.x, - this.y, - this.width, - this.height, - Colors.getInstance().getColorOrWhite("white").withAlpha(50).color()); + context, // TODO: see if this is correct + this.x, + this.y, + this.width, + this.height, + Colors.getInstance().getColorOrWhite("white").withAlpha(50).color() + ); } String name = this.option.getDisplayName(); this.drawString( - this.x + 4, - this.y + 7, - Colors.getInstance().getColorOrWhite("white").color(), - name, - context); + context, + this.x + 4, + this.y + 7, + Colors.getInstance().getColorOrWhite("white").color(), + name + ); - RenderUtils.color(1f, 1f, 1f, 1f); - RenderSystem.disableBlend(); + // RenderUtils.color(1f, 1f, 1f, 1f); // TODO: See if this is needed + // RenderSystem.disableBlend(); // TODO: See if this is needed - super.render(mouseX, mouseY, selected, context); + super.render(context, mouseX, mouseY, selected); - RenderUtils.disableDiffuseLighting(); + // RenderUtils.disableDiffuseLighting(); // TODO: See if this is needed } @Override - public void postRenderHovered( - int mouseX, int mouseY, boolean selected, DrawContext context) { - super.postRenderHovered(mouseX, mouseY, selected, context); + public void postRenderHovered(DrawContext context, int mouseX, int mouseY, boolean selected) { + super.postRenderHovered(context, mouseX, mouseY, selected); if (hoverLines == null) { return; } - if (mouseX >= this.x - && mouseX < this.buttonStartX - && mouseY >= this.y - && mouseY <= this.y + this.height) { - RenderUtils.drawHoverText(mouseX, mouseY, this.hoverLines, context); + if ( + mouseX >= this.x && + mouseX < this.buttonStartX && + mouseY >= this.y && + mouseY <= this.y + this.height + ) { + RenderUtils.drawHoverText(context, mouseX, mouseY, this.hoverLines); } } diff --git a/src/main/java/io/github/darkkronicle/advancedchatcore/config/options/ConfigColor.java b/src/main/java/io/github/darkkronicle/advancedchatcore/config/options/ConfigColor.java index 60c3e2c..757979b 100644 --- a/src/main/java/io/github/darkkronicle/advancedchatcore/config/options/ConfigColor.java +++ b/src/main/java/io/github/darkkronicle/advancedchatcore/config/options/ConfigColor.java @@ -40,7 +40,7 @@ public void resetToDefault() { if (defaultReference != null) { this.setValueFromString(defaultReference); } else { - this.setValueFromString(new Color(defaultValue).getString()); + this.setValueFromString(super.getDefaultStringValue()); } onValueChanged(); } @@ -91,21 +91,22 @@ public void setValueFromJsonElement(JsonElement element) { this.setColor(); return; } - this.value = this.getClampedValue(StringUtils.getColor(value, 0)); - this.setIntegerValue(this.value); + this.setIntegerValue(this.getClampedValue(StringUtils.getColor(value, 0))); this.setColor(); } else { - MaLiLib.logger.warn( - "Failed to set config value for '{}' from the JSON element '{}'", - this.getName(), - element); - } - } catch (Exception e) { - MaLiLib.logger.warn( + MaLiLib.LOGGER.warn( "Failed to set config value for '{}' from the JSON element '{}'", this.getName(), - element, - e); + element + ); + } + } catch (Exception e) { + MaLiLib.LOGGER.warn( + "Failed to set config value for '{}' from the JSON element '{}'", + this.getName(), + element, + e + ); } } diff --git a/src/main/java/io/github/darkkronicle/advancedchatcore/gui/CleanButton.java b/src/main/java/io/github/darkkronicle/advancedchatcore/gui/CleanButton.java index 5c2c5a8..9917ccd 100644 --- a/src/main/java/io/github/darkkronicle/advancedchatcore/gui/CleanButton.java +++ b/src/main/java/io/github/darkkronicle/advancedchatcore/gui/CleanButton.java @@ -47,7 +47,7 @@ public CleanButton(int x, int y, int width, int height, Color baseColor, String } @Override - public void render(int mouseX, int mouseY, boolean selected, DrawContext context) { + public void render(DrawContext context, int mouseX, int mouseY, boolean selected) { int relMX = mouseX - x; int relMY = mouseY - y; hovered = relMX >= 0 && relMX <= width && relMY >= 0 && relMY <= height; @@ -55,12 +55,13 @@ public void render(int mouseX, int mouseY, boolean selected, DrawContext context if (hovered) { color = Colors.getInstance().getColor("white").get().withAlpha(color.alpha()); } - RenderUtils.drawRect(x, y, width, height, color.color()); + RenderUtils.drawRect(context, x, y, width, height, color.color()); // TODO: See if this is correct drawCenteredString( - (x + (width / 2)), - (y + (height / 2) - 3), - Colors.getInstance().getColorOrWhite("white").color(), - displayString, - context); + context, + (x + (width / 2)), + (y + (height / 2) - 3), + Colors.getInstance().getColorOrWhite("white").color(), + displayString + ); } } diff --git a/src/main/java/io/github/darkkronicle/advancedchatcore/gui/ContextMenu.java b/src/main/java/io/github/darkkronicle/advancedchatcore/gui/ContextMenu.java index 947f10e..072b7fd 100644 --- a/src/main/java/io/github/darkkronicle/advancedchatcore/gui/ContextMenu.java +++ b/src/main/java/io/github/darkkronicle/advancedchatcore/gui/ContextMenu.java @@ -87,7 +87,7 @@ protected boolean onMouseClickedImpl(int mouseX, int mouseY, int mouseButton) { } @Override - public void render(int mouseX, int mouseY, boolean selected, DrawContext context) { + public void render(DrawContext context, int mouseX, int mouseY, boolean selected) { drawRect(context, x, y, width, height, background.color()); int rX = x + 2; int rY = y + 2; diff --git a/src/main/java/io/github/darkkronicle/advancedchatcore/gui/IconButton.java b/src/main/java/io/github/darkkronicle/advancedchatcore/gui/IconButton.java index 4c3d3f5..2e4f413 100644 --- a/src/main/java/io/github/darkkronicle/advancedchatcore/gui/IconButton.java +++ b/src/main/java/io/github/darkkronicle/advancedchatcore/gui/IconButton.java @@ -6,9 +6,9 @@ import lombok.Getter; import lombok.Setter; import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gl.RenderPipelines; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.sound.PositionedSoundInstance; -import net.minecraft.client.util.math.MatrixStack; import net.minecraft.sound.SoundEvents; import net.minecraft.util.Identifier; @@ -59,7 +59,7 @@ public IconButton(int x, int y, int width, int height, int padding, int iconWidt } @Override - public void render(int mouseX, int mouseY, boolean unused, DrawContext context) { + public void render(DrawContext context, int mouseX, int mouseY, boolean unused) { int relMX = mouseX - x; int relMY = mouseY - y; hovered = relMX >= 0 && relMX <= width && relMY >= 0 && relMY <= height; @@ -69,12 +69,24 @@ public void render(int mouseX, int mouseY, boolean unused, DrawContext context) plusBack = Colors.getInstance().getColorOrWhite("hover").withAlpha(plusBack.alpha()); } - RenderUtils.drawRect(x, y, width, height, plusBack.color()); - - RenderUtils.color(1, 1, 1, 1); - RenderUtils.bindTexture(icon); - context.drawTexture(icon, x + padding, y + padding, width - (padding * 2), height - (padding * 2), - 0, 0, iconWidth, iconHeight, iconWidth, iconHeight); + RenderUtils.drawRect(context, x, y, width, height, plusBack.color()); // TODO: See if this is correct + + // RenderUtils.color(1, 1, 1, 1); // TODO: May not be needed + RenderUtils.bindGpuTexture(icon); // TODO: May be `bindGpuTextureView` + context.drawTexture( + RenderPipelines.GUI_TEXTURED, // TODO: See if this is correct + icon, + x + padding, + y + padding, + 0, + 0, + width - (padding * 2), + height - (padding * 2), + iconWidth, + iconHeight, + iconWidth, + iconHeight + ); if (hovered && onHover != null) { context.drawCenteredTextWithShadow( diff --git a/src/main/java/io/github/darkkronicle/advancedchatcore/gui/WidgetConfigListEntry.java b/src/main/java/io/github/darkkronicle/advancedchatcore/gui/WidgetConfigListEntry.java index ae67c9b..bd0dba0 100644 --- a/src/main/java/io/github/darkkronicle/advancedchatcore/gui/WidgetConfigListEntry.java +++ b/src/main/java/io/github/darkkronicle/advancedchatcore/gui/WidgetConfigListEntry.java @@ -7,7 +7,7 @@ */ package io.github.darkkronicle.advancedchatcore.gui; -import com.mojang.blaze3d.systems.RenderSystem; +// import com.mojang.blaze3d.systems.RenderSystem; import fi.dy.masa.malilib.gui.GuiTextFieldGeneric; import fi.dy.masa.malilib.gui.widgets.WidgetBase; import fi.dy.masa.malilib.gui.widgets.WidgetListEntryBase; @@ -20,7 +20,7 @@ import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.util.math.MatrixStack; +// import net.minecraft.client.util.math.MatrixStack; @Environment(EnvType.CLIENT) public abstract class WidgetConfigListEntry extends WidgetListEntryBase { @@ -60,43 +60,49 @@ public List> getTextFields() { } @Override - public void render(int mouseX, int mouseY, boolean selected, DrawContext context) { - RenderUtils.color(1f, 1f, 1f, 1f); + public void render(DrawContext context, int mouseX, int mouseY, boolean selected) { + // RenderUtils.color(1f, 1f, 1f, 1f); // TODO: See if this is needed // Draw a lighter background for the hovered and the selected entry if (selected || this.isMouseOver(mouseX, mouseY)) { RenderUtils.drawRect( - this.x, - this.y, - this.width, - this.height, - Colors.getInstance().getColorOrWhite("white").withAlpha(150).color()); + context, // TODO: See if this is correct + this.x, + this.y, + this.width, + this.height, + Colors.getInstance().getColorOrWhite("white").withAlpha(150).color() + ); } else if (this.odd) { RenderUtils.drawRect( - this.x, - this.y, - this.width, - this.height, - Colors.getInstance().getColorOrWhite("white").withAlpha(70).color()); + context, // TODO: See if this is correct + this.x, + this.y, + this.width, + this.height, + Colors.getInstance().getColorOrWhite("white").withAlpha(70).color() + ); } else { RenderUtils.drawRect( - this.x, - this.y, - this.width, - this.height, - Colors.getInstance().getColorOrWhite("white").withAlpha(50).color()); + context, // TODO: See if this is correct + this.x, + this.y, + this.width, + this.height, + Colors.getInstance().getColorOrWhite("white").withAlpha(50).color() + ); } renderEntry(mouseX, mouseY, selected, context); - RenderUtils.color(1f, 1f, 1f, 1f); - RenderSystem.disableBlend(); + // RenderUtils.color(1f, 1f, 1f, 1f); // TODO: See if this is needed + // RenderSystem.disableBlend(); // TODO: See if this is needed this.drawTextFields(mouseX, mouseY, context); - super.render(mouseX, mouseY, selected, context); + super.render(context, mouseX, mouseY, selected); - RenderUtils.disableDiffuseLighting(); + // RenderUtils.disableDiffuseLighting(); // TODO: See if this is needed } /** @@ -106,26 +112,29 @@ public void render(int mouseX, int mouseY, boolean selected, DrawContext context public void renderEntry(int mouseX, int mouseY, boolean selected, DrawContext context) { String name = getName(); this.drawString( - this.x + 4, - this.y + 7, - Colors.getInstance().getColorOrWhite("white").color(), - name, - context); + context, + this.x + 4, + this.y + 7, + Colors.getInstance().getColorOrWhite("white").color(), + name + ); } @Override - public void postRenderHovered( - int mouseX, int mouseY, boolean selected, DrawContext context) { - super.postRenderHovered(mouseX, mouseY, selected, context); + public void postRenderHovered(DrawContext context, int mouseX, int mouseY, boolean selected) { + super.postRenderHovered(context, mouseX, mouseY, selected); + if (hoverLines == null) { return; } - if (mouseX >= this.x - && mouseX < this.buttonStartX - && mouseY >= this.y - && mouseY <= this.y + this.height) { - RenderUtils.drawHoverText(mouseX, mouseY, this.hoverLines, context); + if ( + mouseX >= this.x && + mouseX < this.buttonStartX && + mouseY >= this.y && + mouseY <= this.y + this.height + ) { + RenderUtils.drawHoverText(context, mouseX, mouseY, this.hoverLines); } } @@ -173,9 +182,7 @@ protected boolean onMouseClickedImpl(int mouseX, int mouseY, int mouseButton) { if (!this.subWidgets.isEmpty()) { for (WidgetBase widget : this.subWidgets) { - ret |= - widget.isMouseOver(mouseX, mouseY) - && widget.onMouseClicked(mouseX, mouseY, mouseButton); + ret |= widget.isMouseOver(mouseX, mouseY) && widget.onMouseClicked(mouseX, mouseY, mouseButton); } } diff --git a/src/main/java/io/github/darkkronicle/advancedchatcore/mixin/MixinChatHudInvoker.java b/src/main/java/io/github/darkkronicle/advancedchatcore/mixin/MixinChatHudInvoker.java index a6702a1..f3d5283 100644 --- a/src/main/java/io/github/darkkronicle/advancedchatcore/mixin/MixinChatHudInvoker.java +++ b/src/main/java/io/github/darkkronicle/advancedchatcore/mixin/MixinChatHudInvoker.java @@ -8,15 +8,15 @@ package io.github.darkkronicle.advancedchatcore.mixin; import net.minecraft.client.gui.hud.ChatHud; -import net.minecraft.client.gui.hud.MessageIndicator; -import net.minecraft.network.message.MessageSignatureData; -import net.minecraft.text.Text; -import org.jetbrains.annotations.Nullable; +import net.minecraft.client.gui.hud.ChatHudLine; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Invoker; @Mixin(ChatHud.class) public interface MixinChatHudInvoker { - @Invoker - void invokeAddMessage(Text message, @Nullable MessageSignatureData signature, int ticks, @Nullable MessageIndicator indicator, boolean refresh); + @Invoker("addVisibleMessage") + void invokeAddVisibleMessage(ChatHudLine message); + + @Invoker("addMessage") + void invokeAddMessage(ChatHudLine message); } diff --git a/src/main/java/io/github/darkkronicle/advancedchatcore/mixin/MixinClientPlayerEntity.java b/src/main/java/io/github/darkkronicle/advancedchatcore/mixin/MixinClientPlayerEntity.java index 03b97aa..355db3d 100644 --- a/src/main/java/io/github/darkkronicle/advancedchatcore/mixin/MixinClientPlayerEntity.java +++ b/src/main/java/io/github/darkkronicle/advancedchatcore/mixin/MixinClientPlayerEntity.java @@ -25,18 +25,20 @@ public MixinClientPlayerEntity(EntityType type, World world) { } @Inject( - method="updateNausea", + method="tickNausea", at = @At(value="INVOKE", target="Lnet/minecraft/client/MinecraftClient;setScreen(Lnet/minecraft/client/gui/screen/Screen;)V"), cancellable = true ) - public void updateNauseaHook(CallbackInfo ci) { + public void tickNauseaHook(CallbackInfo ci) { if (client.currentScreen instanceof AdvancedChatScreen) { ci.cancel(); nauseaIntensity += 0.0125f; if (this.nauseaIntensity >= 1.0f) { this.nauseaIntensity = 1.0f; } - inNetherPortal = false; + if(this.portalManager != null){ + portalManager.setInPortal(false); + } } } diff --git a/src/main/java/io/github/darkkronicle/advancedchatcore/mixin/MixinMinecraftClient.java b/src/main/java/io/github/darkkronicle/advancedchatcore/mixin/MixinMinecraftClient.java index dc9c9b8..484a5cf 100644 --- a/src/main/java/io/github/darkkronicle/advancedchatcore/mixin/MixinMinecraftClient.java +++ b/src/main/java/io/github/darkkronicle/advancedchatcore/mixin/MixinMinecraftClient.java @@ -28,14 +28,6 @@ @Mixin(MinecraftClient.class) public class MixinMinecraftClient { - @Inject(method = "disconnect(Lnet/minecraft/client/gui/screen/Screen;)V", at = @At("RETURN")) - public void onDisconnect(Screen screen, CallbackInfo ci) { - // Clear data on disconnect - if (ConfigStorage.General.CLEAR_ON_DISCONNECT.config.getBooleanValue()) { - ChatHistory.getInstance().clearAll(); - } - } - @Inject(method = "openChatScreen(Ljava/lang/String;)V", at = @At(value = "HEAD"), cancellable = true) public void openChatScreen(String text, CallbackInfo ci) { diff --git a/src/main/java/io/github/darkkronicle/advancedchatcore/util/ColorUtil.java b/src/main/java/io/github/darkkronicle/advancedchatcore/util/ColorUtil.java index 3782321..7a017a7 100644 --- a/src/main/java/io/github/darkkronicle/advancedchatcore/util/ColorUtil.java +++ b/src/main/java/io/github/darkkronicle/advancedchatcore/util/ColorUtil.java @@ -43,7 +43,7 @@ public Color intToColor4f(int rgb) { * @param c The color to pack * @return The packed int */ - public int colorToInt4f(Color c) { + public static int colorToInt4f(Color c) { int rgb = c.alpha(); rgb = (rgb << 8) + c.red(); rgb = (rgb << 8) + c.green(); diff --git a/src/main/java/io/github/darkkronicle/advancedchatcore/util/ProfanityUtil.java b/src/main/java/io/github/darkkronicle/advancedchatcore/util/ProfanityUtil.java index 203898d..9026b4c 100644 --- a/src/main/java/io/github/darkkronicle/advancedchatcore/util/ProfanityUtil.java +++ b/src/main/java/io/github/darkkronicle/advancedchatcore/util/ProfanityUtil.java @@ -32,9 +32,11 @@ */ @Environment(EnvType.CLIENT) public class ProfanityUtil { - @Getter private final Map> words = new HashMap<>(); + @Getter + private final Map> words = new HashMap<>(); - @Getter private int largestWordLength = 0; + @Getter + private int largestWordLength = 0; private static final ProfanityUtil INSTANCE = new ProfanityUtil(); @@ -46,44 +48,66 @@ private ProfanityUtil() {} public void loadConfigs() { try { - List lines; - File file = FileUtils.getConfigDirectory() - .toPath() - .resolve("advancedchat") - .resolve("swear_words.csv") - .toFile(); + File file = + FileUtils.getConfigDirectory() + .toPath() + .resolve("advancedchat") + .resolve("swear_words.csv") + .toFile(); Reader fileReader; if (!file.exists()) { // Use built in - fileReader = new InputStreamReader(AdvancedChatCore.getResource("swear_words.csv"), StandardCharsets.UTF_8); + fileReader = new InputStreamReader( + AdvancedChatCore.getResource("swear_words.csv"), + StandardCharsets.UTF_8 + ); } else { fileReader = new FileReader(file); } - CSVParser csv = new CSVParser(fileReader, CSVFormat.DEFAULT.withFirstRecordAsHeader().withIgnoreHeaderCase()); - int counter = 0; - for (CSVRecord record : csv) { - counter++; - try { - String word = record.get("text"); - float severity = Float.parseFloat(record.get("severity_rating")); - - if (word.length() > largestWordLength) { - largestWordLength = word.length(); - } - if (!words.containsKey(severity)) { - words.put(severity, new ArrayList<>()); - } - words.get(severity).add(word); - } catch (Exception e) { - AdvancedChatCore.LOGGER.log( - Level.ERROR, "Error while initializing profanity words", e); + CSVFormat csvFormat = + CSVFormat.DEFAULT.builder() + .setHeader() + .setSkipHeaderRecord(true) + .setIgnoreHeaderCase(true) + .build(); + + try ( + CSVParser csvParser = new CSVParser(fileReader, csvFormat); + ) { + int counter = 0; + for (CSVRecord record : csvParser) { + counter++; + + try { + String word = record.get("text"); + + float severity = Float.parseFloat(record.get("severity_rating")); + + if (word.length() > largestWordLength) { + largestWordLength = word.length(); + } + if (!words.containsKey(severity)) { + words.put(severity, new ArrayList<>()); + } + + words.get(severity).add(word); + } catch (Exception e) { + AdvancedChatCore.LOGGER.log( + Level.ERROR, + "Error while initializing profanity words", + e + ); + } } + + AdvancedChatCore.LOGGER.log( + Level.INFO, + "Loaded " + counter + " words to profanity filter." + ); } - AdvancedChatCore.LOGGER.log( - Level.INFO, "Loaded " + counter + " words to profanity filter."); - } catch (URISyntaxException | IOException e) { + } catch (URISyntaxException | IOException e) { AdvancedChatCore.LOGGER.log(Level.ERROR, "Error loading swear_words.csv", e); } } @@ -92,7 +116,11 @@ public void loadConfigs() { * Iterates over a String input and checks whether a cuss word was found in a list, then checks * if the word should be ignored (e.g. bass contains the word *ss). */ - public List getBadWords(String input, float severity, boolean onlyWordBoundaries) { + public List getBadWords( + String input, + float severity, + boolean onlyWordBoundaries + ) { if (input == null) { return new ArrayList<>(); } @@ -102,9 +130,11 @@ public List getBadWords(String input, float severity, boolean onlyW List wordBoundaries; if (onlyWordBoundaries) { - wordBoundaries = SearchUtils.findMatches(input, "\\b", FindType.REGEX) - .map(matches -> matches.stream().map(m -> m.start).toList()) - .orElseGet(ArrayList::new); + wordBoundaries = + SearchUtils.findMatches(input, "\\b", FindType.REGEX) + .map(matches -> matches.stream().map(m -> m.start).toList()) + .orElseGet(ArrayList::new); + if (wordBoundaries.size() == 0) { return new ArrayList<>(); } @@ -121,33 +151,50 @@ public List getBadWords(String input, float severity, boolean onlyW while (index < input.length()) { // from each letter, keep going to find bad words until either the end of the sentence // is reached, or the max word length is reached. - for (int offset = 1; offset < (input.length() + 1 - index) && offset < largestWordLength; offset++) { + for ( + int offset = 1; + ( + offset < (input.length() + 1 - index) && + offset < largestWordLength + ); + offset++ + ) { String wordToCheck = input.substring(index, index + offset); - if (wordsToFind.contains(wordToCheck) && (!onlyWordBoundaries || (wordBoundaries.contains(index + offset)))) { + if ( + wordsToFind.contains(wordToCheck) && + ( + !onlyWordBoundaries || + wordBoundaries.contains(index + offset) + ) + ) { // for example, if you want to say the word bass, that should be possible. badWords.add(new StringMatch(wordToCheck, index, index + offset)); } } + if (onlyWordBoundaries) { boundaryIndex++; - if (boundaryIndex >= wordBoundaries.size()) { - break; - } + + if (boundaryIndex >= wordBoundaries.size()) break; + index = wordBoundaries.get(boundaryIndex); } else { index++; } } + return badWords; } public List getAboveSeverity(float severity) { List list = new ArrayList<>(); + for (Map.Entry> entry : words.entrySet()) { if (entry.getKey() >= severity) { list.addAll(entry.getValue()); } } + return list; } } diff --git a/src/main/java/io/github/darkkronicle/advancedchatcore/util/StyleFormatter.java b/src/main/java/io/github/darkkronicle/advancedchatcore/util/StyleFormatter.java index 70760ab..af61b4a 100644 --- a/src/main/java/io/github/darkkronicle/advancedchatcore/util/StyleFormatter.java +++ b/src/main/java/io/github/darkkronicle/advancedchatcore/util/StyleFormatter.java @@ -236,9 +236,11 @@ public static MutableText flattenText(Text text) { */ public static List wrapText(TextRenderer textRenderer, int scaledWidth, Text text) { ArrayList lines = new ArrayList<>(); + for (OrderedText breakRenderedChatMessageLine : ChatMessages.breakRenderedChatMessageLines(text, scaledWidth, textRenderer)) { lines.add(new TextBuilder().append(breakRenderedChatMessageLine).build()); } + return lines; } } diff --git a/src/main/java/io/github/darkkronicle/advancedchatcore/util/TextUtil.java b/src/main/java/io/github/darkkronicle/advancedchatcore/util/TextUtil.java index 95b3d22..9712d32 100644 --- a/src/main/java/io/github/darkkronicle/advancedchatcore/util/TextUtil.java +++ b/src/main/java/io/github/darkkronicle/advancedchatcore/util/TextUtil.java @@ -31,7 +31,7 @@ public class TextUtil { * *

https://stackoverflow.com/questions/955110/similarity-string-comparison-in-java */ - public double similarity(String s1, String s2) { + public static double similarity(String s1, String s2) { String longer = s1, shorter = s2; if (s1.length() < s2.length()) { // longer should always have greater length longer = s2; diff --git a/src/main/resources/advancedchatcore.mixins.json b/src/main/resources/advancedchatcore.mixins.json index b79d5f6..c244afb 100644 --- a/src/main/resources/advancedchatcore.mixins.json +++ b/src/main/resources/advancedchatcore.mixins.json @@ -1,7 +1,7 @@ { "required": true, "package": "io.github.darkkronicle.advancedchatcore.mixin", - "compatibilityLevel": "JAVA_8", + "compatibilityLevel": "JAVA_21", "mixins": [ "MixinClientPlayerEntity" ], diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index cb3ce31..8080a5c 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -28,10 +28,10 @@ "advancedchatcore.mixins.json" ], "depends": { - "fabricloader": ">=0.14.18", + "fabricloader": ">=0.16.3", "fabric": "*", - "minecraft": ">=1.20", - "malilib": ">=0.16.0" + "minecraft": ">=1.21.4", + "malilib": ">=0.21.0" }, "custom": { "modmenu": { diff --git a/src/main/resources/swear_words.csv b/src/main/resources/swear_words.csv new file mode 100644 index 0000000..e00cb72 --- /dev/null +++ b/src/main/resources/swear_words.csv @@ -0,0 +1 @@ +"text","severity_rating"